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