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