1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: main.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: 31311 $
16 *---------------------------------------------------------------------------*/
17
18 //------------------------------------------------------------------
19 // デモ: orthoStereo
20 //
21 // 概要
22 // レイアウトを正射影で立体視するサンプルです。
23 //
24 //------------------------------------------------------------------
25
26 #include <nn/os.h>
27 #include <nn/fs.h>
28
29 #include <nw/types.h>
30 #include <nw/sdk.h>
31 #include <nw/demo.h>
32 #include <nw/dev.h>
33 #include <nw/gfx.h>
34 #include <nw/lyt.h>
35 #include <nw/ut.h>
36
37 namespace
38 {
39
40 nw::demo::RenderSystem* s_pRenderSystem = NULL;
41 nw::gfx::IRenderTarget* s_pRenderTarget = NULL;
42 nw::gfx::IRenderTarget* s_pRenderTargetLower = NULL;
43
44 //----------------------------------------
45 // メモリ関係
46
47 // デバイスメモリを確保するためのアロケータです。
48 nw::demo::DemoAllocator s_DeviceAllocator;
49
50 //----------------------------------------
51 typedef nw::ut::MoveArray<u8> File;
52
53 nn::ulcd::CTR::StereoCamera s_StereoCamera;
54
55 f32 s_DepthLevel = 10.0f; // LCD 上に配置したい場所(基準面)までのカメラからの距離
56 f32 s_StereoFactor = 1.0f; // 立体具合の調整係数(0で視差が無くなり、1で標準となります。)
57
58 /*---------------------------------------------------------------------------*
59 @brief グラフィックス関連の初期化を行います。
60 *---------------------------------------------------------------------------*/
61 void
InitializeGraphics()62 InitializeGraphics()
63 {
64 nw::demo::RenderSystem::Description renderDesc;
65
66 nw::demo::DisplayBufferSwapper::Description& upperScreenDesc =
67 renderDesc.upperScreenDescription;
68
69 nw::demo::DisplayBufferSwapper::Description& lowerScreenDesc =
70 renderDesc.lowerScreenDescription;
71
72 renderDesc.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
73
74 s_pRenderSystem = nw::demo::RenderSystem::Create(
75 &s_DeviceAllocator,
76 renderDesc);
77
78 NW_ASSERT(s_pRenderSystem != NULL);
79
80 s_pRenderTarget = nw::gfx::IRenderTarget::Builder()
81 .BufferSize(upperScreenDesc.height, upperScreenDesc.width)
82 .ColorFormat(renderDesc.renderColorFormat)
83 .Create(&s_DeviceAllocator);
84
85 NW_ASSERT(s_pRenderTarget != NULL);
86
87 s_pRenderTargetLower = nw::gfx::IRenderTarget::Builder()
88 .BufferSize(lowerScreenDesc.height, lowerScreenDesc.width)
89 .ColorFormat(renderDesc.renderColorFormat)
90 .Create(&s_DeviceAllocator);
91
92 NW_ASSERT(s_pRenderTargetLower != NULL);
93
94 NW_GL_ASSERT();
95 }
96
97 //---------------------------------------------------------------------------
98 //! @brief グラフィックス関連の後始末を行います。
99 //---------------------------------------------------------------------------
100 void
TerminateGraphics()101 TerminateGraphics()
102 {
103 nw::gfx::SafeDestroy(s_pRenderSystem);
104 nw::gfx::SafeDestroy(s_pRenderTarget);
105 nw::gfx::SafeDestroy(s_pRenderTargetLower);
106 }
107
108 /*---------------------------------------------------------------------------*
109 @brief 描画の初期設定を行います。
110
111 @param width 画面の幅。
112 @param height 画面の高さ。
113 *---------------------------------------------------------------------------*/
114 void
InitDraw(int width,int height)115 InitDraw(int width, int height)
116 {
117 // カラーバッファ情報
118 // LCDの向きに合わせて、幅と高さを入れ替えています。
119 const nw::font::ColorBufferInfo colBufInfo =
120 {
121 height, width, PICA_DATA_DEPTH24_STENCIL8_EXT
122 };
123
124 const u32 commands[] =
125 {
126 // ビューポートの設定
127 NW_FONT_CMD_SET_VIEWPORT(0, 0, colBufInfo.width, colBufInfo.height),
128
129 // シザー処理を無効
130 NW_FONT_CMD_SET_DISABLE_SCISSOR(colBufInfo),
131
132 // wバッファの無効化
133 // デプスレンジの設定
134 // ポリゴンオフセットの無効化
135 NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
136 0.0f, // wScale : 0.0 でWバッファが無効
137 0.0f, // depth range near
138 1.0f, // depth range far
139 0, // polygon offset units : 0.0 で ポリゴンオフセットが無効
140 colBufInfo),
141 };
142
143 nngxAdd3DCommand(commands, sizeof(commands), true);
144
145 static const u32 constCommands[] =
146 {
147 // カリングを無効
148 NW_FONT_CMD_SET_CULL_FACE(NW_FONT_CMD_CULL_FACE_DISABLE),
149
150 // ステンシルテストを無効
151 NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
152
153 // デプステストを無効
154 // カラーバッファの全ての成分を書き込み可
155 NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
156 false, // isDepthTestEnabled
157 0, // depthFunc
158 true, // depthMask
159 true, // red
160 true, // green
161 true, // blue
162 true), // alpha
163
164 // アーリーデプステストを無効
165 NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST(false),
166
167 // フレームバッファアクセス制御
168 NW_FONT_CMD_SET_FBACCESS(
169 true, // colorRead
170 true, // colorWrite
171 false, // depthRead
172 false, // depthWrite
173 false, // stencilRead
174 false), // stencilWrite
175 };
176
177 nngxAdd3DCommand(constCommands, sizeof(constCommands), true);
178 }
179
180 //---------------------------------------------------------------------------
181 //! @brief モデルビュー行列と射影行列を設定します。
182 //!
183 //! @param[in] drawInfo 描画情報です。
184 //! @param[in] layout レイアウトです。
185 //!
186 //! @return 視差の半分の値を返します(液晶のドット単位)。
187 //---------------------------------------------------------------------------
188 void
SetupCamera(nw::lyt::DrawInfo & drawInfo,const nw::lyt::Layout & layout)189 SetupCamera(
190 nw::lyt::DrawInfo& drawInfo,
191 const nw::lyt::Layout& layout
192 )
193 {
194 nw::ut::Rect layoutRect = layout.GetLayoutRect();
195
196 f32 znear = 0.f;
197 f32 zfar = 500.f;
198
199 // 射影行列を正射影に設定
200 // (Layoutデータは横向きなので向きを変換する)
201 nw::math::MTX44 projMtx;
202 nw::math::MTX44OrthoPivot(
203 &projMtx,
204 layoutRect.left, // left
205 layoutRect.right, // right
206 layoutRect.bottom, // bottom
207 layoutRect.top, // top
208 znear,
209 zfar,
210 nw::math::PIVOT_UPSIDE_TO_TOP);
211 drawInfo.SetProjectionMtx(projMtx);
212
213 // モデルビュー行列を設定
214 nw::math::VEC3 pos(0, 0, s_DepthLevel);
215 nw::math::VEC3 up(0, 1, 0);
216 nw::math::VEC3 target(0, 0, 0);
217
218 nw::math::MTX34 viewMtx;
219 nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target);
220 drawInfo.SetViewMtx(viewMtx);
221 }
222
223 //---------------------------------------------------------------------------
224 //! @brief 視差の半分の値を液晶のドット単位で求めます。
225 //!
226 //! @param[in] drawInfo 描画情報です。
227 //!
228 //! @return 視差の半分の値を返します(液晶のドット単位)。
229 //---------------------------------------------------------------------------
230 f32
CalcParallaxDot(nw::lyt::DrawInfo & drawInfo)231 CalcParallaxDot(nw::lyt::DrawInfo& drawInfo)
232 {
233 // 左右の視差に対応した絵を描画するための射影行列、ビュー行列を計算する
234 nn::math::MTX34 view = drawInfo.GetViewMtx();
235 s_StereoCamera.SetBaseCamera(&view);
236
237 nn::math::MTX44 projL, projR;
238 nn::math::MTX34 viewL, viewR;
239 s_StereoCamera.CalculateMatrices(
240 &projL,
241 &viewL,
242 &projR,
243 &viewR,
244 s_DepthLevel,
245 s_StereoFactor,
246 nn::math::PIVOT_UPSIDE_TO_TOP);
247
248 // 視差の半分の値を液晶のドット単位で求める。
249 f32 wkParallax = s_StereoCamera.GetCoefficientForParallax();
250 return wkParallax * nw::demo::SimpleApp::DISPLAY0_WIDTH;
251 }
252
253 //---------------------------------------------------------------------------
254 //! @brief コマンドリストを作成します。
255 //!
256 //! @param[in] bufSize 3Dコマンドバッファのサイズです。
257 //! @param[in] requestCount コマンドリクエストの個数です。
258 //!
259 //! @return コマンドリストIDを返します。
260 //---------------------------------------------------------------------------
261 GLuint
CreateCmdList(GLsizei bufSize,GLsizei requestCount)262 CreateCmdList(
263 GLsizei bufSize,
264 GLsizei requestCount
265 )
266 {
267 // カレントを退避
268 GLuint crntCmdListId;
269 nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, reinterpret_cast<GLint*>(&crntCmdListId));
270
271 // 生成
272 GLuint lytCmdListId;
273 nngxGenCmdlists(1, &lytCmdListId);
274 nngxBindCmdlist(lytCmdListId);
275 nngxCmdlistStorage(bufSize, requestCount);
276
277 // カレントを復帰
278 nngxBindCmdlist(crntCmdListId);
279
280 return lytCmdListId;
281 }
282
283 //---------------------------------------------------------------------------
284 //! @brief コマンドリストの保存を開始します。
285 //!
286 //! @param[in] cmdListId 保存するコマンドリストのID。
287 //!
288 //! @return 現在のコマンドリストIDを返します。
289 //---------------------------------------------------------------------------
290 GLuint
StartCmdListSave(GLuint cmdListId)291 StartCmdListSave(GLuint cmdListId)
292 {
293 // カレントを退避
294 GLuint crntCmdListId;
295 nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, reinterpret_cast<GLint*>(&crntCmdListId));
296
297 nngxBindCmdlist(cmdListId); // バインド
298 nngxClearCmdlist(); // クリア
299 nngxStartCmdlistSave(); // セーブ開始
300
301 return crntCmdListId;
302 }
303
304 //---------------------------------------------------------------------------
305 //! @brief 保存したコマンドリストの情報を保存する構造体。
306 //---------------------------------------------------------------------------
307 struct CmdListInfo
308 {
309 GLuint bufferOffset;
310 GLsizei bufferSize;
311 GLuint requestId;
312 GLsizei requestSize;
313 };
314
315 //---------------------------------------------------------------------------
316 //! @brief コマンドリストの保存を終了します。
317 //!
318 //! @param[out] pCmdListInfo コマンドリストの情報を保存する構造体へのポインタ。
319 //! @param[in] cmdListId 元に戻すコマンドリストのID。
320 //---------------------------------------------------------------------------
321 void
StopCmdListSave(CmdListInfo * pCmdListInfo,GLuint cmdListId)322 StopCmdListSave(
323 CmdListInfo* pCmdListInfo,
324 GLuint cmdListId
325 )
326 {
327 nngxStopCmdlistSave(
328 &pCmdListInfo->bufferOffset,
329 &pCmdListInfo->bufferSize,
330 &pCmdListInfo->requestId,
331 &pCmdListInfo->requestSize);
332 NW_GL_ASSERT();
333
334 // カレントを復帰
335 nngxBindCmdlist(cmdListId);
336 }
337
338 //---------------------------------------------------------------------------
339 //! @brief 保存されたコマンドリストを使用します。
340 //!
341 //! @param[in] cmdListId コマンドリストのID。
342 //! @param[in] cmdListInfo コマンドリストの情報を保存する構造体。
343 //---------------------------------------------------------------------------
344 void
UseSavedCmdlist(GLuint cmdListId,const CmdListInfo & cmdListInfo)345 UseSavedCmdlist(
346 GLuint cmdListId,
347 const CmdListInfo& cmdListInfo
348 )
349 {
350 nngxUseSavedCmdlist(
351 cmdListId,
352 cmdListInfo.bufferOffset,
353 cmdListInfo.bufferSize,
354 cmdListInfo.requestId,
355 cmdListInfo.requestSize,
356 0,
357 GL_TRUE);
358 }
359
360 } // namespace {anonymous}
361
362 //---------------------------------------------------------------------------
363 //! @brief サンプルのメイン関数です。
364 //---------------------------------------------------------------------------
365 void
nnMain()366 nnMain()
367 {
368 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
369
370 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
371
372 InitializeGraphics();
373
374 // レイアウトライブラリの初期化。
375 // デモでは全てのメモリをデバイスメモリから確保していますので、
376 // 同じアロケータを渡しています。
377 // ヒープメモリと区別して扱う場合は第2引数は必ずデバイスメモリを指定してください。
378 nw::lyt::Initialize(&s_DeviceAllocator, &s_DeviceAllocator);
379
380 // レイアウトのバイナリリソース(アーカイブ)を読み込み。
381 File resLayout = nw::demo::Utility::LoadFile(
382 &s_DeviceAllocator, NW_DEMO_FILE_PATH(L"layout.arc"), 128);
383
384 if (resLayout.empty())
385 {
386 NW_FATAL_ERROR("can not open layout archive.\n");
387 }
388
389 // バイナリリソースのルートディレクトリを指定してリソースアクセサを生成。
390 nw::lyt::ArcResourceAccessor* pResAccessor = new nw::lyt::ArcResourceAccessor;
391 if (!pResAccessor->Attach(resLayout.begin(), "."))
392 {
393 NW_FATAL_ERROR("can not attach layout archive.\n");
394 }
395
396 nw::lyt::Layout* pLayout = new nw::lyt::Layout();
397
398 // レイアウトリソースの読み込み
399 {
400 const void* lytRes = pResAccessor->GetResource(0, "orthoStereo.bclyt");
401 NW_NULL_ASSERT(lytRes);
402 pLayout->Build(lytRes, pResAccessor);
403 }
404
405 nw::lyt::GraphicsResource graphicsResource;
406
407 // グローバルなリソースファイルを読み込みます。
408 {
409 graphicsResource.StartSetup();
410 const wchar_t* resourcePath = 0;
411 for (int i = 0;
412 (resourcePath = graphicsResource.GetResourcePath(i)) != NULL;
413 ++i)
414 {
415 File resource = nw::demo::Utility::LoadFile(&s_DeviceAllocator, resourcePath);
416
417 if (resource.empty())
418 {
419 NW_FATAL_ERROR("can not read lyt resource file.");
420 }
421
422 graphicsResource.SetResource(i, resource.begin(), resource.size(), false);
423 }
424
425 graphicsResource.FinishSetup();
426 }
427
428 nw::lyt::DrawInfo drawInfo;
429 drawInfo.SetGraphicsResource(&graphicsResource);
430
431 nw::lyt::Drawer drawer;
432 drawer.Initialize(graphicsResource);
433
434 // 立体視のためのカメラの初期化
435 s_StereoCamera.Initialize();
436 s_StereoCamera.SetBaseFrustum(
437 -0.04f,
438 0.04f,
439 -0.04f * nw::demo::SimpleApp::DISPLAY0_HEIGHT / nw::demo::SimpleApp::DISPLAY0_WIDTH,
440 0.04f * nw::demo::SimpleApp::DISPLAY0_HEIGHT / nw::demo::SimpleApp::DISPLAY0_WIDTH,
441 0.2f,
442 30.f);
443
444 // レイアウト描画用のコマンドリストの作成
445 const GLuint lytCmdListId = CreateCmdList(2048, 1);
446
447 bool loop = true;
448 while (loop)
449 {
450 SetupCamera(drawInfo, *pLayout);
451 NW_GL_ASSERT();
452
453 pLayout->Animate();
454 pLayout->CalculateMtx(drawInfo);
455 NW_GL_ASSERT();
456
457 // レイアウトの描画コマンドを生成
458 CmdListInfo lytCmdListInfo;
459 const GLuint crntCmdListId = StartCmdListSave(lytCmdListId);
460 drawer.DrawBegin(nw::lyt::Drawer::DONT_USE_SETUP_COMMAND);
461 drawer.Draw(pLayout, drawInfo);
462 drawer.DrawEnd(nw::lyt::Drawer::DONT_USE_SETUP_COMMAND);
463 StopCmdListSave(&lytCmdListInfo, crntCmdListId);
464
465 s_pRenderSystem->SetRenderTarget(s_pRenderTarget);
466 NW_GL_ASSERT();
467
468 // 視差の半分の値を液晶のドット単位で求めます。
469 const f32 halfParallaxDot = CalcParallaxDot(drawInfo);
470
471 // 上画面(左目用)
472 {
473 s_pRenderSystem->ClearBuffer(
474 nw::ut::FloatColor(0.2f, 0.2f, 0.2f, 0.0f));
475
476 InitDraw(
477 nw::demo::SimpleApp::DISPLAY0_WIDTH,
478 nw::demo::SimpleApp::DISPLAY0_HEIGHT);
479
480 // Drawerを使ってレイアウトを描画します。
481 drawer.SetParallax(-halfParallaxDot, s_StereoCamera.GetDistanceToLevel());
482 drawer.DrawBegin(drawInfo);
483 UseSavedCmdlist(lytCmdListId, lytCmdListInfo);
484 drawer.DrawEnd();
485
486 s_pRenderSystem->TransferBuffer(nw::demo::UPPER_SCREEN);
487 }
488
489 // 上画面(右目用)
490 {
491 s_pRenderSystem->ClearBuffer(
492 nw::ut::FloatColor(0.2f, 0.2f, 0.2f, 0.0f));
493
494 InitDraw(
495 nw::demo::SimpleApp::DISPLAY0_WIDTH,
496 nw::demo::SimpleApp::DISPLAY0_HEIGHT);
497
498 // Drawerを使ってレイアウトを描画します。
499 drawer.SetParallax( halfParallaxDot, s_StereoCamera.GetDistanceToLevel());
500 drawer.DrawBegin(drawInfo);
501 UseSavedCmdlist(lytCmdListId, lytCmdListInfo);
502 drawer.DrawEnd();
503
504 s_pRenderSystem->TransferBuffer(nw::demo::EXTENSION_SCREEN);
505 }
506
507 s_pRenderSystem->SetRenderTarget(s_pRenderTargetLower);
508
509 // 下画面
510 {
511 s_pRenderSystem->ClearBuffer(
512 nw::ut::FloatColor(0.1f, 0.1f, 0.1f, 0.0f));
513
514 s_pRenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
515 }
516
517 s_pRenderSystem->PresentBuffer(nw::demo::BOTH_SCREENS);
518 NW_GL_ASSERT();
519 }
520
521 drawer.Finalize();
522
523 delete pLayout;
524 delete pResAccessor;
525
526 TerminateGraphics();
527
528 nw::demo::PadFactory::Finalize();
529 }
530
531