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             touchPanelStaus = static_cast<SmTouchPanelStatus*>(object);
344             NW_NULL_ASSERT( touchPanelStaus );
345 
346             if ( m_Collision.CheckInner( touchPanelStaus->GetX(), touchPanelStaus->GetY() ) )
347             {
348                 // 他処理で使用中でなければ
349                 if ( !touchPanelStaus->IsGrab() )
350                 {
351                     // 掴む
352                     touchPanelStaus->Grab();
353                     m_IsGrab    = true;
354                 }
355             }
356         }
357         break;
358 
359     case SM_MESSAGE_TUCHPANEL_MOTION:
360         {
361             touchPanelStaus = static_cast<SmTouchPanelStatus*>(object);
362             NW_NULL_ASSERT( touchPanelStaus );
363 
364             MoveCamera3D( NULL, touchPanelStaus );
365         }
366         break;
367 
368     case SM_MESSAGE_TUCHPANEL_RELEASE:
369         {
370             touchPanelStaus = static_cast<SmTouchPanelStatus*>(object);
371             NW_NULL_ASSERT( touchPanelStaus );
372 
373             // 放す
374             if ( m_IsGrab )
375             {
376                 touchPanelStaus->UnGrab();
377                 m_IsGrab = false;
378 
379                 mTouchPanelX = -1;
380                 mTouchPanelY = -1;
381             }
382         }
383         break;
384 
385 
386     default:
387         break;
388     }
389 
390     return false;
391 }
392 
393 //----------------------------------------
394 // カメラマトリクスを更新する
395 void
UpdateMatrix()396 SmCamera::UpdateMatrix()
397 {
398     m_Camera->UpdateCameraMatrix();
399     m_PadCamera->UpdateCameraMatrix();
400 }
401 
402 
403 
404 //----------------------------------------
405 // Viewerと同カメラ操作
406 void
MoveCamera3D(SmPadStatus * padStatus,SmTouchPanelStatus * panelStatus)407 SmCamera::MoveCamera3D( SmPadStatus* padStatus, SmTouchPanelStatus* panelStatus )
408 {
409     nw::gfx::Camera* camera = m_PadCamera;
410 
411     f32 stickX = 0.0f;
412     f32 stickY = 0.0f;
413     f32 lookatX = 0.0f;
414     f32 lookatY = 0.0f;
415     f32 expansion = 0.0f;
416     f32 translationX = 0.0f;
417     f32 translationY = 0.0f;
418     f32 tiltX = 0.0f;
419     f32 tiltY = 0.0f;
420 
421     if (padStatus)
422     {
423         stickX = padStatus->GetStickX();
424         stickY = padStatus->GetStickY();
425 
426         if (stickX != 0.0f || stickY != 0.0f)
427         {
428             lookatX =mRotation * stickX;
429             lookatY =mRotation * stickY;
430             mRotation += mCameraInfo.RotationStep;
431             if (mRotation > mCameraInfo.RotationMax)
432             {
433                 mRotation = mCameraInfo.RotationMax;
434             }
435         }
436         else
437         {
438             mRotation = mCameraInfo.RotationInit;
439             mTranslation = mCameraInfo.TranslationInit;
440         }
441     }
442 
443     // タッチパッドでの前後移動処理
444     if (m_IsGrab && panelStatus)
445     {
446         u16 x = panelStatus->GetX();
447         u16 y = panelStatus->GetY();
448         const u16 width = 320 / 5;  // 下液晶幅320の1/5を使用 64pixel
449         if (x < width)
450         {
451             if (-1 != mTouchPanelY)
452             {
453                 int trans = y-mTouchPanelY;
454                 expansion -= trans;
455             }
456 
457         }else{
458             if (-1 != mTouchPanelX && -1 != mTouchPanelY)
459             {
460                 int rotX = x-mTouchPanelX;
461                 int rotY = y-mTouchPanelY;
462                 tiltX = rotX * mCameraInfo.TiltInit;
463                 tiltY = rotY * mCameraInfo.TiltInit;
464             }
465         }
466         mTouchPanelX = x;
467         mTouchPanelY = y;
468     }
469 
470     // 操作系の反転処理
471     if (mCameraInfo.TumbleXInverse)
472     {
473         lookatX = -lookatX;
474     }
475     if (mCameraInfo.TumbleYInverse)
476     {
477         lookatY = -lookatY;
478     }
479     if (mCameraInfo.TrackXInverse)
480     {
481         translationX = -translationX;
482     }
483     if (mCameraInfo.TrackYInverse)
484     {
485         translationY = -translationY;
486     }
487     if (mCameraInfo.TiltXInverse)
488     {
489         tiltX = -tiltX;
490     }
491     if (mCameraInfo.TiltYInverse)
492     {
493         tiltY = -tiltY;
494     }
495 
496     nw::gfx::LookAtTargetViewUpdater* viewUpdater =
497         nw::ut::DynamicCast<nw::gfx::LookAtTargetViewUpdater*>(camera->GetViewUpdater());
498     nw::gfx::ResLookAtTargetViewUpdater resViewUpdater =
499         nw::gfx::ResStaticCast<nw::gfx::ResLookAtTargetViewUpdater>(viewUpdater->GetResource());
500 
501     nw::math::VEC3 position;
502     camera->Transform().GetTranslate(&position);
503     nw::math::VEC3 direction = resViewUpdater.GetTargetPosition() - position;
504     nw::math::VEC3Normalize(&direction, &direction);
505 
506     nw::math::VEC3 right;
507     nw::math::VEC3Cross(&right, &resViewUpdater.GetUpwardVector(), &direction);
508     nw::math::VEC3Normalize(&right, &right);
509 
510     // 回転
511     if (lookatX != 0.0f || lookatY != 0.0f)
512     {
513         nw::math::VEC3 translate;
514         camera->Transform().GetTranslate(&translate);
515         translate -= resViewUpdater.GetTargetPosition();
516 
517         nw::math::MTX34 rotateV;
518         nw::math::MTX34 rotateH;
519         MTX34RotAxisRad(&rotateV, &right, lookatY);
520         MTX34RotXYZRad(&rotateH, 0.0f, lookatX, 0.0f);
521 
522         VEC3Transform(&translate, &rotateH, &translate);
523         VEC3Transform(&translate, &rotateV, &translate);
524 
525         translate += resViewUpdater.GetTargetPosition();
526         camera->Transform().SetTranslate(translate);
527 
528         nw::math::VEC3 upVector;
529 
530         VEC3Transform(
531             &upVector,
532             &rotateH,
533             &resViewUpdater.GetUpwardVector());
534 
535         VEC3Transform(
536             &upVector,
537             &rotateV,
538             &upVector);
539 
540         // 回転後のY軸とZ軸からX軸を算出
541         VEC3Cross(&right,&upVector,&direction);
542         // X軸ベクトルのy成分を0にし、正規化することでカメラを水平に保つ
543         right.y = 0.0f;
544         nw::math::VEC3Normalize(&right, &right);
545         // 新しいZ軸とX軸からY軸を算出
546         VEC3Cross(&upVector,&direction,&right);
547 
548         resViewUpdater.SetUpwardVector(upVector);
549     }
550 
551     if (expansion != 0.0f)
552     {
553         // 注視点とともに前後移動
554 /*
555         if (padStatus.hold & nn::hid::CTR::BUTTON_L)
556         {
557             if (mCameraInfo.DollyTargetInverse)
558             {
559                 expansion = -expansion;
560             }
561 
562             nw::math::VEC3 translate = expansion * direction *
563                 VEC3Len(resViewUpdater.GetTargetPosition() - position) * mCameraInfo.DollyInit;
564             resViewUpdater.SetTargetPosition(
565                 resViewUpdater.GetTargetPosition() + translate);
566             nw::math::VEC3 pos;
567             camera->Transform().GetTranslate(&pos);
568             pos += translate;
569             camera->Transform().SetTranslate(pos);
570         }
571         else
572 */
573         {
574             if (mCameraInfo.DollyInverse)
575             {
576                 expansion = -expansion;
577             }
578 
579             // ドリー(前後移動)
580             nw::math::VEC3 translate;
581             camera->Transform().GetTranslate(&translate);
582             translate += expansion * direction * VEC3Len(resViewUpdater.GetTargetPosition() - translate) * mCameraInfo.DollyInit;
583             camera->Transform().SetTranslate(translate);
584         }
585     }
586 
587     // 首ふり回転(tilt)
588     if (tiltX != 0.0f || tiltY != 0.0f)
589     {
590         nw::math::VEC3 translate;
591         camera->Transform().GetTranslate(&translate);
592         translate = resViewUpdater.GetTargetPosition() - translate;
593 
594         nw::math::MTX34 rotateV;
595         nw::math::MTX34 rotateH;
596         MTX34RotAxisRad(&rotateV, &right, tiltY);
597         MTX34RotXYZRad(&rotateH, 0.0f, -tiltX, 0.0f);
598 
599         VEC3Transform(&translate, &rotateH, &translate);
600         VEC3Transform(&translate, &rotateV, &translate);
601 
602         nw::math::VEC3 upVector, targetPos;
603 
604         VEC3Transform(
605             &upVector,
606             &rotateH,
607             &resViewUpdater.GetUpwardVector());
608 
609         VEC3Transform(
610             &upVector,
611             &rotateV,
612             &upVector);
613 
614         VEC3Cross(&right,&upVector,&direction);
615         right.y = 0.0f;
616         nw::math::VEC3Normalize(&right, &right);
617         VEC3Cross(&upVector,&direction,&right);
618 
619         resViewUpdater.SetUpwardVector(upVector);
620 
621         nw::math::VEC3 pos;
622         camera->Transform().GetTranslate(&pos);
623         targetPos = translate + pos;
624 
625         resViewUpdater.SetTargetPosition(targetPos);
626     }
627 
628     // トラック(平行移動)
629     if (translationX != 0.0f || translationY != 0.0f)
630     {
631         resViewUpdater.SetTargetPosition(
632             resViewUpdater.GetTargetPosition() + right * translationX +
633             resViewUpdater.GetUpwardVector() * translationY);
634         nw::math::VEC3 translate;
635         camera->Transform().GetTranslate(&translate);
636         translate += right * translationX + resViewUpdater.GetUpwardVector() * translationY;
637         camera->Transform().SetTranslate(translate);
638     }
639 }
640 
641 
642 } // namespace
643 
644