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