1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: SmCamera.cpp
4
5 Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain proprietary
8 information of Nintendo and/or its licensed developers and are protected by
9 national and international copyright laws. They may not be disclosed to third
10 parties or copied or duplicated in any form, in whole or in part, without the
11 prior written consent of Nintendo.
12
13 The content herein is highly confidential and should be handled accordingly.
14
15 $Revision: $
16 *---------------------------------------------------------------------------*/
17
18 #include "../include/SmCamera.h"
19
20
21
22 namespace
23 {
24
25
26
27 // Viewerから拝借したカメラ情報構造体
CameraInfo()28 CameraInfo::CameraInfo()
29 {
30 Fovy = 37.8f;
31 Near = 0.05f;
32 Far = 10000.0f;
33
34 RotationInit = 0.05f;
35 RotationStep = 0.0f;
36 RotationMax = 0.1f;
37 TranslationInit = 0.004f;
38 TranslationStep = 0.001f;
39 TranslationMax = 0.01f;
40 TiltInit = 0.005f;
41 DollyInit = 0.01f;
42
43 TumbleXInverse = false;
44 TumbleYInverse = false;
45 TrackXInverse = false;
46 TrackYInverse = false;
47 DollyInverse = false;
48 DollyTargetInverse = false;
49 TiltXInverse = false;
50 TiltYInverse = false;
51 }
52
53
54 //----------------------------------------
55 // コンストラクタ
SmCamera(nw::gfx::SceneNode * parent,nw::gfx::Camera * camera)56 SmCamera::SmCamera( nw::gfx::SceneNode* parent, nw::gfx::Camera* camera )
57 : SmMessage(NULL),
58 m_Parent(parent),
59 m_Camera(camera),
60 m_PadCamera(NULL),
61 m_PadCameraAttached(false),
62 m_IsAnimPlaying(true),
63 m_AnimationFrame(0.f),
64 m_CurrentAnimEvNo(0),
65 mRotation(0.0f),
66 mTranslation(0.0f),
67 mTouchPanelX(0),
68 mTouchPanelY(0),
69 m_IsGrab(false)
70 {
71 NW_NULL_ASSERT( parent );
72
73 // 初期値
74 m_Position.x = 30.f;
75 m_Position.y = 25.f;
76 m_Position.z = 120.f;
77
78 m_Target.x = 0.f;
79 m_Target.y = 0.f;
80 m_Target.z = 20.f;
81
82 // カメラズームインアウト用のコリジョン
83 m_Collision.SetRect( 0, 40, 100, 280 );
84
85 // カメラをセット
86 if ( m_Camera )
87 {
88 this->SetGxCamera( m_Camera );
89 }
90
91 // パッド用カメラを生成します。
92 {
93 nw::math::VEC3 mCameraPos;
94 nw::math::VEC3 mCameraTarget;
95 nw::math::VEC3 mCameraUp;
96
97 mCameraPos.Set( 0.0f, 0.0f, 50.f );
98 mCameraTarget.Set( 0.0f, 0.0f, 0.f );
99 mCameraUp.Set( 0.0f, 1.0f, 0.f );
100
101 // カメラの生成
102 nw::os::IAllocator* pAllocator = m_Allocator;
103
104 nw::gfx::LookAtTargetViewUpdater* viewUpdater
105 = nw::gfx::LookAtTargetViewUpdater::Create(pAllocator);
106
107 nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
108 nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(viewUpdater->GetResource());
109
110 resViewUpdater.SetTargetPosition(mCameraTarget);
111 resViewUpdater.SetUpwardVector(mCameraUp);
112
113 nw::gfx::PerspectiveProjectionUpdater* projectionUpdater
114 = nw::gfx::PerspectiveProjectionUpdater::Create(pAllocator);
115
116 nw::gfx::ResPerspectiveProjectionUpdater resProjectionUpdater =
117 nw::gfx::ResStaticCast<nw::gfx::ResPerspectiveProjectionUpdater>(
118 projectionUpdater->GetResource());
119 resProjectionUpdater.SetNear(0.1f);
120 resProjectionUpdater.SetFar(1000.0f);
121 resProjectionUpdater.SetFovy(0.821342f);//NW_MATH_DEG_TO_RAD(60.0f));
122
123 m_PadCamera =
124 nw::gfx::Camera::DynamicBuilder()
125 .MaxChildren(0)
126 .MaxCallbacks(0)
127 .ViewUpdater(viewUpdater)
128 .ProjectionUpdater(projectionUpdater)
129 .Create(pAllocator);
130
131 m_PadCamera->Transform().SetTranslate(mCameraPos);
132
133 m_PadCamera->SetWScale(1.f/1000.0f);
134
135 // パッドカメラをアタッチする。
136 m_Parent->AttachChild(m_PadCamera);
137 m_PadCameraAttached = true;
138 }
139
140 m_CameraAnimEvaluatorArray.clear();
141 }
142
143
144 //----------------------------------------
145 // デストラクタ
~SmCamera()146 SmCamera::~SmCamera()
147 {
148
149 }
150
151
152 //----------------------------------------
153 // カメラセット
154 void
SetGxCamera(nw::gfx::Camera * camera)155 SmCamera::SetGxCamera( nw::gfx::Camera* camera )
156 {
157 NW_NULL_ASSERT( camera );
158 NW_ASSERT( !m_Camera );
159
160 // パッドカメラをデタッチする
161 m_PadCameraAttached = false;
162
163 // アサインされたカメラをアタッチする
164 m_Camera = camera;
165 m_Parent->AttachChild( camera );
166
167 // パッドカメラにwScaleと画角を継承させる
168 // f32 wScale = camera->GetWScale();
169 // m_PadCamera->SetWScale( wScale );
170 }
171
172
173 //----------------------------------------
174 // カメラを取得します。
175 nw::gfx::Camera*
GetGxCamera()176 SmCamera::GetGxCamera()
177 {
178 if (m_PadCameraAttached)
179 {
180 return m_PadCamera;
181 }
182 else
183 {
184 return m_Camera;
185 }
186 }
187
188
189 //----------------------------------------
190 // アニメーション設定解除する
DetachAnimEvaluator()191 bool SmCamera::DetachAnimEvaluator()
192 {
193 if ( m_CurrentAnimEvNo >= GetAnimEvaluatorNum() ) return false;
194 if ( !m_Camera ) return false;
195
196 m_CameraAnimEvaluatorArray[m_CurrentAnimEvNo]->Release();
197 m_Camera->SetAnimObject( NULL );
198
199 m_CurrentAnimEvNo = -1;
200
201 return true;
202 }
203
204
205 //----------------------------------------
206 // アニメーションを追加する
207 void
AddAnimEvaluator(nw::gfx::AnimEvaluator * animEvaluator)208 SmCamera::AddAnimEvaluator( nw::gfx::AnimEvaluator* animEvaluator )
209 {
210 m_CameraAnimEvaluatorArray.push_back( animEvaluator );
211 }
212
213
214 //----------------------------------------
215 // アニメーション数を取得する
216 uint
GetAnimEvaluatorNum() const217 SmCamera::GetAnimEvaluatorNum() const
218 {
219 return m_CameraAnimEvaluatorArray.size();
220 }
221
222
223 //----------------------------------------
224 // アニメーションを設定する
225 bool
SetAnimEvaluatorNo(uint animEvaluatorNo)226 SmCamera::SetAnimEvaluatorNo( uint animEvaluatorNo )
227 {
228 if ( animEvaluatorNo >= GetAnimEvaluatorNum() ) return false;
229 if ( !m_Camera ) return false;
230
231 nw::gfx::AnimGroup* animGroup = m_Camera->GetAnimGroup();
232 // if (animGroup == NULL){ NW_FATAL_ERROR("Dont have AnimGroup");; }
233 if (animGroup == NULL){ NW_DEV_LOG("SmCamera:Dont have AnimGroup"); }
234
235 // アニメーションをバインドします。
236 m_CameraAnimEvaluatorArray[animEvaluatorNo]->Release();
237 bool bindResult = m_CameraAnimEvaluatorArray[animEvaluatorNo]->Bind(animGroup);
238
239 // アニメーションをカメラに登録します。
240 m_Camera->SetAnimObject(m_CameraAnimEvaluatorArray[animEvaluatorNo]);
241
242 // 番号を保持
243 m_CurrentAnimEvNo = animEvaluatorNo;
244
245 return true;
246 }
247
248
249 //----------------------------------------
250 // アニメーションフレームを設定する
251 void
SetAnimationFrame(f32 setFrame)252 SmCamera::SetAnimationFrame( f32 setFrame )
253 {
254 if ( m_CurrentAnimEvNo >= GetAnimEvaluatorNum() ) return;
255 if ( !m_Camera ) return;
256
257 m_AnimationFrame = setFrame;
258 if ( m_CurrentAnimEvNo == -1 ) return;
259
260 // フレーム数をセット
261 m_CameraAnimEvaluatorArray[m_CurrentAnimEvNo]->SetFrame(m_AnimationFrame);
262 }
263
264
265 //----------------------------------------
266 // アニメーションフレームを進める
267 // 最終フレームに到達した場合は、trueを返す
268 bool
AddAnimationFrame(f32 addFrame,bool loop)269 SmCamera::AddAnimationFrame( f32 addFrame, bool loop )
270 {
271 if ( m_CurrentAnimEvNo >= GetAnimEvaluatorNum() ) return false;
272 if ( !m_Camera ) return false;
273
274 bool ret = false;
275
276 m_AnimationFrame += addFrame;
277
278 // 最終フレームで固定
279 f32 endFrame = m_CameraAnimEvaluatorArray[m_CurrentAnimEvNo]->AnimFrameController().GetEndFrame();
280 if ( m_AnimationFrame > endFrame )
281 {
282 if ( loop )
283 {
284 m_AnimationFrame = 0.f;
285 }
286 else
287 {
288 m_AnimationFrame = endFrame;
289 }
290
291 ret = true;
292 }
293
294 // フレーム数をセット
295 m_CameraAnimEvaluatorArray[m_CurrentAnimEvNo]->SetFrame(m_AnimationFrame);
296
297 return ret;
298 }
299
300
301 //----------------------------------------
302 // アニメーションフレームを取得する
303 f32
GetAnimationFrame() const304 SmCamera::GetAnimationFrame() const
305 {
306 return m_AnimationFrame;
307 }
308
309 //----------------------------------------
310 // メッセージ受信
ReceveMessage(SmMessageType type,void * object,uint targetId)311 bool SmCamera::ReceveMessage( SmMessageType type, void* object, uint targetId )
312 {
313 NW_UNUSED_VARIABLE(targetId);
314
315 SmTouchPanelStatus* touchPanelStaus = NULL;
316
317 switch( type )
318 {
319 case SM_MESSAGE_PAD_UPDATE:
320 {
321 SmPadStatus* padStaus = static_cast<SmPadStatus*>(object);
322
323 // スタートボタンでカメラアニメーションのオンオフ
324 if ( padStaus->IsTrigger( SmPadStatus::SM_BUTTON_START ) )
325 {
326 if (m_PadCameraAttached)
327 {
328 m_PadCameraAttached = false;
329 }
330 else
331 {
332 m_PadCameraAttached = true;
333 }
334 }
335
336 if (m_PadCameraAttached)
337 {
338 MoveCamera3D( padStaus, NULL );
339 }
340 }
341 break;
342
343 case SM_MESSAGE_TUCHPANEL_PRESS:
344 {
345 if (!m_PadCameraAttached) break;
346
347 touchPanelStaus = static_cast<SmTouchPanelStatus*>(object);
348 NW_NULL_ASSERT( touchPanelStaus );
349
350 if ( m_Collision.CheckInner( touchPanelStaus->GetX(), touchPanelStaus->GetY() ) )
351 {
352 // 他処理で使用中でなければ
353 if ( !touchPanelStaus->IsGrab() )
354 {
355 // 掴む
356 touchPanelStaus->Grab();
357 m_IsGrab = true;
358 }
359 }
360 }
361 break;
362
363 case SM_MESSAGE_TUCHPANEL_MOTION:
364 {
365 if (!m_PadCameraAttached) break;
366
367 touchPanelStaus = static_cast<SmTouchPanelStatus*>(object);
368 NW_NULL_ASSERT( touchPanelStaus );
369
370 MoveCamera3D( NULL, touchPanelStaus );
371 }
372 break;
373
374 case SM_MESSAGE_TUCHPANEL_RELEASE:
375 {
376 touchPanelStaus = static_cast<SmTouchPanelStatus*>(object);
377 NW_NULL_ASSERT( touchPanelStaus );
378
379 // 放す
380 if ( m_IsGrab )
381 {
382 touchPanelStaus->UnGrab();
383 m_IsGrab = false;
384
385 mTouchPanelX = -1;
386 mTouchPanelY = -1;
387 }
388 }
389 break;
390
391
392 default:
393 break;
394 }
395
396 return false;
397 }
398
399 //----------------------------------------
400 // カメラマトリクスを更新する
401 void
UpdateMatrix()402 SmCamera::UpdateMatrix()
403 {
404 m_Camera->UpdateCameraMatrix();
405 m_PadCamera->UpdateCameraMatrix();
406 }
407
408
409
410 //----------------------------------------
411 // Viewerと同カメラ操作
412 void
MoveCamera3D(SmPadStatus * padStatus,SmTouchPanelStatus * panelStatus)413 SmCamera::MoveCamera3D( SmPadStatus* padStatus, SmTouchPanelStatus* panelStatus )
414 {
415 nw::gfx::Camera* camera = m_PadCamera;
416
417 f32 stickX = 0.0f;
418 f32 stickY = 0.0f;
419 f32 lookatX = 0.0f;
420 f32 lookatY = 0.0f;
421 f32 expansion = 0.0f;
422 f32 translationX = 0.0f;
423 f32 translationY = 0.0f;
424 f32 tiltX = 0.0f;
425 f32 tiltY = 0.0f;
426
427 if (padStatus)
428 {
429 stickX = padStatus->GetStickX();
430 stickY = padStatus->GetStickY();
431
432 if (stickX != 0.0f || stickY != 0.0f)
433 {
434 lookatX =mRotation * stickX;
435 lookatY =mRotation * stickY;
436 mRotation += mCameraInfo.RotationStep;
437 if (mRotation > mCameraInfo.RotationMax)
438 {
439 mRotation = mCameraInfo.RotationMax;
440 }
441 }
442 else
443 {
444 mRotation = mCameraInfo.RotationInit;
445 mTranslation = mCameraInfo.TranslationInit;
446 }
447 }
448
449 // タッチパッドでの前後移動処理
450 if (m_IsGrab && panelStatus)
451 {
452 u16 x = panelStatus->GetX();
453 u16 y = panelStatus->GetY();
454 const u16 width = 320 / 5; // 下液晶幅320の1/5を使用 64pixel
455 if (x < width)
456 {
457 if (-1 != mTouchPanelY)
458 {
459 int trans = y-mTouchPanelY;
460 expansion -= trans;
461 }
462
463 }else{
464 if (-1 != mTouchPanelX && -1 != mTouchPanelY)
465 {
466 int rotX = x-mTouchPanelX;
467 int rotY = y-mTouchPanelY;
468 tiltX = rotX * mCameraInfo.TiltInit;
469 tiltY = rotY * mCameraInfo.TiltInit;
470 }
471 }
472 mTouchPanelX = x;
473 mTouchPanelY = y;
474 }
475
476 // 操作系の反転処理
477 if (mCameraInfo.TumbleXInverse)
478 {
479 lookatX = -lookatX;
480 }
481 if (mCameraInfo.TumbleYInverse)
482 {
483 lookatY = -lookatY;
484 }
485 if (mCameraInfo.TrackXInverse)
486 {
487 translationX = -translationX;
488 }
489 if (mCameraInfo.TrackYInverse)
490 {
491 translationY = -translationY;
492 }
493 if (mCameraInfo.TiltXInverse)
494 {
495 tiltX = -tiltX;
496 }
497 if (mCameraInfo.TiltYInverse)
498 {
499 tiltY = -tiltY;
500 }
501
502 nw::gfx::LookAtTargetViewUpdater* viewUpdater =
503 nw::ut::DynamicCast<nw::gfx::LookAtTargetViewUpdater*>(camera->GetViewUpdater());
504 nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
505 nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(viewUpdater->GetResource());
506
507 nw::math::VEC3 position;
508 camera->Transform().GetTranslate(&position);
509 nw::math::VEC3 direction = resViewUpdater.GetTargetPosition() - position;
510 nw::math::VEC3Normalize(&direction, &direction);
511
512 nw::math::VEC3 right;
513 nw::math::VEC3Cross(&right, &resViewUpdater.GetUpwardVector(), &direction);
514 nw::math::VEC3Normalize(&right, &right);
515
516 // 回転
517 if (lookatX != 0.0f || lookatY != 0.0f)
518 {
519 nw::math::VEC3 translate;
520 camera->Transform().GetTranslate(&translate);
521 translate -= resViewUpdater.GetTargetPosition();
522
523 nw::math::MTX34 rotateV;
524 nw::math::MTX34 rotateH;
525 MTX34RotAxisRad(&rotateV, &right, lookatY);
526 MTX34RotXYZRad(&rotateH, 0.0f, lookatX, 0.0f);
527
528 VEC3Transform(&translate, &rotateH, &translate);
529 VEC3Transform(&translate, &rotateV, &translate);
530
531 translate += resViewUpdater.GetTargetPosition();
532 camera->Transform().SetTranslate(translate);
533
534 nw::math::VEC3 upVector;
535
536 VEC3Transform(
537 &upVector,
538 &rotateH,
539 &resViewUpdater.GetUpwardVector());
540
541 VEC3Transform(
542 &upVector,
543 &rotateV,
544 &upVector);
545
546 // 回転後のY軸とZ軸からX軸を算出
547 VEC3Cross(&right,&upVector,&direction);
548 // X軸ベクトルのy成分を0にし、正規化することでカメラを水平に保つ
549 right.y = 0.0f;
550 nw::math::VEC3Normalize(&right, &right);
551 // 新しいZ軸とX軸からY軸を算出
552 VEC3Cross(&upVector,&direction,&right);
553
554 resViewUpdater.SetUpwardVector(upVector);
555 }
556
557 if (expansion != 0.0f)
558 {
559 // 注視点とともに前後移動
560 /*
561 if (padStatus.hold & nn::hid::CTR::BUTTON_L)
562 {
563 if (mCameraInfo.DollyTargetInverse)
564 {
565 expansion = -expansion;
566 }
567
568 nw::math::VEC3 translate = expansion * direction *
569 VEC3Len(resViewUpdater.GetTargetPosition() - position) * mCameraInfo.DollyInit;
570 resViewUpdater.SetTargetPosition(
571 resViewUpdater.GetTargetPosition() + translate);
572 nw::math::VEC3 pos;
573 camera->Transform().GetTranslate(&pos);
574 pos += translate;
575 camera->Transform().SetTranslate(pos);
576 }
577 else
578 */
579 {
580 if (mCameraInfo.DollyInverse)
581 {
582 expansion = -expansion;
583 }
584
585 // ドリー(前後移動)
586 nw::math::VEC3 translate;
587 camera->Transform().GetTranslate(&translate);
588 translate += expansion * direction * VEC3Len(resViewUpdater.GetTargetPosition() - translate) * mCameraInfo.DollyInit;
589 camera->Transform().SetTranslate(translate);
590 }
591 }
592
593 // 首ふり回転(tilt)
594 if (tiltX != 0.0f || tiltY != 0.0f)
595 {
596 nw::math::VEC3 translate;
597 camera->Transform().GetTranslate(&translate);
598 translate = resViewUpdater.GetTargetPosition() - translate;
599
600 nw::math::MTX34 rotateV;
601 nw::math::MTX34 rotateH;
602 MTX34RotAxisRad(&rotateV, &right, tiltY);
603 MTX34RotXYZRad(&rotateH, 0.0f, -tiltX, 0.0f);
604
605 VEC3Transform(&translate, &rotateH, &translate);
606 VEC3Transform(&translate, &rotateV, &translate);
607
608 nw::math::VEC3 upVector, targetPos;
609
610 VEC3Transform(
611 &upVector,
612 &rotateH,
613 &resViewUpdater.GetUpwardVector());
614
615 VEC3Transform(
616 &upVector,
617 &rotateV,
618 &upVector);
619
620 VEC3Cross(&right,&upVector,&direction);
621 right.y = 0.0f;
622 nw::math::VEC3Normalize(&right, &right);
623 VEC3Cross(&upVector,&direction,&right);
624
625 resViewUpdater.SetUpwardVector(upVector);
626
627 nw::math::VEC3 pos;
628 camera->Transform().GetTranslate(&pos);
629 targetPos = translate + pos;
630
631 resViewUpdater.SetTargetPosition(targetPos);
632 }
633
634 // トラック(平行移動)
635 if (translationX != 0.0f || translationY != 0.0f)
636 {
637 resViewUpdater.SetTargetPosition(
638 resViewUpdater.GetTargetPosition() + right * translationX +
639 resViewUpdater.GetUpwardVector() * translationY);
640 nw::math::VEC3 translate;
641 camera->Transform().GetTranslate(&translate);
642 translate += right * translationX + resViewUpdater.GetUpwardVector() * translationY;
643 camera->Transform().SetTranslate(translate);
644 }
645 }
646
647
648 } // namespace
649
650