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