1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     main.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: 23867 $
14  *---------------------------------------------------------------------------*/
15 
16 //------------------------------------------------------------------
17 // デモ: perspective
18 //
19 // 概要
20 //   3D風に表示するレイアウトのデモです。
21 //
22 // 操作
23 //   Aボタンで、射影行列を透視射影、正射影と切り替わります。
24 //   透視射影のときが3D風の表示なります。
25 //   正射影のときは通常の2D表示になります。
26 //
27 //------------------------------------------------------------------
28 
29 #include <nw/lyt.h>
30 #include <nw/demo.h>
31 
32 namespace
33 {
34 
35 typedef nw::ut::MoveArray<u8> File;
36 
37 /*---------------------------------------------------------------------------*
38   @brief 描画の初期設定を行います。
39 
40   @param width  画面の幅。
41   @param height  画面の高さ。
42  *---------------------------------------------------------------------------*/
43 void
InitDraw(int width,int height)44 InitDraw(int width, int height)
45 {
46     // カラーバッファ情報
47     // LCDの向きに合わせて、幅と高さを入れ替えています。
48     const nw::font::ColorBufferInfo colBufInfo =
49     {
50         height, width, PICA_DATA_DEPTH24_STENCIL8_EXT
51     };
52 
53     const u32 commands[] =
54     {
55         // ビューポートの設定
56         NW_FONT_CMD_SET_VIEWPORT(0, 0, colBufInfo.width, colBufInfo.height),
57 
58         // シザー処理を無効
59         NW_FONT_CMD_SET_DISABLE_SCISSOR(colBufInfo),
60 
61         // wバッファの無効化
62         // デプスレンジの設定
63         // ポリゴンオフセットの無効化
64         NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
65             0.0f,           // wScale : 0.0 でWバッファが無効
66             0.0f,           // depth range near
67             1.0f,           // depth range far
68             0,              // polygon offset units : 0.0 で ポリゴンオフセットが無効
69             colBufInfo),
70     };
71 
72     nngxAdd3DCommand(commands, sizeof(commands), true);
73 
74     static const u32 constCommands[] =
75     {
76         // カリングを無効
77         NW_FONT_CMD_SET_CULL_FACE(NW_FONT_CMD_CULL_FACE_DISABLE),
78 
79         // ステンシルテストを無効
80         NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
81 
82         // デプステストを無効
83         // カラーバッファの全ての成分を書き込み可
84         NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
85             false,  // isDepthTestEnabled
86             0,      // depthFunc
87             true,   // depthMask
88             true,   // red
89             true,   // green
90             true,   // blue
91             true),  // alpha
92 
93         // アーリーデプステストを無効
94         NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST(false),
95 
96         // フレームバッファアクセス制御
97         NW_FONT_CMD_SET_FBACCESS(
98             true,   // colorRead
99             true,   // colorWrite
100             false,  // depthRead
101             false,  // depthWrite
102             false,  // stencilRead
103             false), // stencilWrite
104     };
105 
106     nngxAdd3DCommand(constCommands, sizeof(constCommands), true);
107 }
108 
109 /*---------------------------------------------------------------------------*
110   @brief Zバッファによる比較を有効にするか無効にするかを切り替えます。
111 
112   @param bEnable  真のとき、Zバッファによる比較を有効にします。
113  *---------------------------------------------------------------------------*/
114 void
EnableZCompare(bool bEnable)115 EnableZCompare(bool bEnable)
116 {
117     if (bEnable)
118     {
119         // Z比較を行います。
120         glEnable(GL_DEPTH_TEST);
121     }
122     else
123     {
124         // Z比較を行いません。常に、レイアウトの階層の下に行くほど手前に表示されます。
125         glDisable(GL_DEPTH_TEST);
126     }
127 }
128 
129 /*---------------------------------------------------------------------------*
130   @brief モデルビュー行列と射影行列を設定します。
131 
132   @param drawInfo  描画情報です。
133   @param layout  レイアウトです。
134   @param bPerspective  射影の種類を指定します。
135                        真のときは、射影行列を透視射影にします。
136                        偽のときは、正射影にします。
137  *---------------------------------------------------------------------------*/
138 void
SetupCamera(nw::lyt::DrawInfo & drawInfo,const nw::lyt::Layout & layout,bool bPerspective)139 SetupCamera(
140     nw::lyt::DrawInfo& drawInfo,
141     const nw::lyt::Layout& layout,
142     bool bPerspective
143 )
144 {
145     nw::ut::Rect layoutRect = layout.GetLayoutRect();
146 
147     if (bPerspective)
148     {
149         const f32 fovy = 45.f;
150         const f32 znear = 0.05f;
151         const f32 zfar = 10000.f;
152         const f32 width = layoutRect.top - layoutRect.bottom;
153         const f32 height = layoutRect.right - layoutRect.left;
154 
155         // 射影行列を透視射影に設定します。
156         nw::math::MTX44 projMtx;
157         nw::math::MTX44Perspective(
158             &projMtx,
159             fovy,
160             width / height,
161             znear,
162             zfar);
163         drawInfo.SetProjectionMtx(projMtx);
164 
165         //  ビュー行列
166         //      注視点を(0, 0, 0)とし、Zの位置が0であるペインの見た目が正射影のときと同じになるように、
167         //      カメラの位置を手前にセットします。
168         const f32 dist = height * 0.5f / nw::math::TanDeg(fovy * 0.5f);
169 
170         nw::math::VEC3 pos(0.f, 0.f, dist);
171         nw::math::VEC3 up(-1, 0, 0);
172         nw::math::VEC3 target(0.f, 0.f, 0.f);
173 
174         nw::math::MTX34 viewMtx;  // ビュー行列
175         nw::math::MTX34LookAt(
176             &viewMtx,
177             &pos,                 // カメラの位置
178             &up,                  // カメラの上方向
179             &target);             // 注視点
180         drawInfo.SetViewMtx(viewMtx);
181     }
182     else
183     {
184         const f32 znear   =  -1000.f;
185         const f32 zfar    =   1000.f;
186 
187         // 射影行列を正射影に設定
188         // (Layoutデータは横向きなので向きを変換する)
189         nw::math::MTX44 projMtx;
190         nw::math::MTX44Ortho(
191             &projMtx,
192             layoutRect.bottom,  // left
193             layoutRect.top,     // right
194             -layoutRect.right,  // bottom
195             -layoutRect.left,   // top
196             znear,
197             zfar);
198         drawInfo.SetProjectionMtx(projMtx);
199 
200         // モデルビュー行列を設定
201         // (Layoutデータは横向きなので画面の上方向はレイアウトの-X方向)
202         nw::math::VEC3 pos(0, 0, 1);
203         nw::math::VEC3 up(-1, 0, 0);
204         nw::math::VEC3 target(0, 0, 0);
205 
206         nw::math::MTX34 viewMtx;
207         nw::math::MTX34LookAt(&viewMtx, &pos, &up, &target);
208         drawInfo.SetViewMtx(viewMtx);
209     }
210 }
211 
212 }   // namespace
213 
214 /*---------------------------------------------------------------------------*
215   @brief サンプルのメイン関数です。
216  *---------------------------------------------------------------------------*/
217 void
nnMain()218 nnMain()
219 {
220     nw::demo::SimpleApp& demoApp = nw::demo::SimpleApp::GetInstance();
221     demoApp.Initialize();
222 
223     nw::lyt::Initialize(&demoApp.GetAllocator(), &demoApp.GetDeviceAllocator());
224 
225     // レイアウトのバイナリリソース(アーカイブ)を読み込み。
226     File fileLayout = nw::demo::Utility::LoadFile(
227         &demoApp.GetDeviceAllocator(), NW_DEMO_FILE_PATH(L"layout.arc"), 128);
228 
229     if (fileLayout.empty())
230     {
231         NW_FATAL_ERROR("can not open layout archive.\n");
232     }
233 
234     // バイナリリソースのルートディレクトリを指定してリソースアクセサを生成。
235     nw::lyt::ArcResourceAccessor* pResAccessor = new nw::lyt::ArcResourceAccessor;
236     if (!pResAccessor->Attach(fileLayout.begin(), "."))
237     {
238         NW_FATAL_ERROR("can not attach layout archive.\n");
239     }
240 
241     nw::lyt::Layout* pLayout = new nw::lyt::Layout();
242 
243     // レイアウトリソースの読み込み
244     {
245         const void* lytRes = pResAccessor->GetResource(0, "perspective.bclyt");
246         NW_NULL_ASSERT(lytRes);
247         pLayout->Build(lytRes, pResAccessor);
248     }
249 
250     nw::lyt::AnimTransform* pAnimTrans = 0;
251     // アニメーションリソースの読み込み
252     {
253         const void* lpaRes = pResAccessor->GetResource(0, "perspective.bclan");
254         NW_NULL_ASSERT(lpaRes);
255         pAnimTrans = pLayout->CreateAnimTransform(lpaRes, pResAccessor);
256         pLayout->BindAnimation(pAnimTrans);
257     }
258 
259     f32 animFrame = 0;
260     bool bPerspective = true;
261 
262     nw::lyt::GraphicsResource graphicsResource;
263     // グローバルなリソースファイルを読み込みます。
264     {
265         graphicsResource.StartSetup();
266         const wchar_t* resourcePath = 0;
267         for (int i = 0;
268              (resourcePath = graphicsResource.GetResourcePath(i)) != NULL;
269              ++i)
270         {
271             File file = nw::demo::Utility::LoadFile(&demoApp.GetAllocator(), resourcePath);
272 
273             if (file.empty())
274             {
275                 NW_FATAL_ERROR("can not read lyt resource file.");
276             }
277 
278             graphicsResource.SetResource(i, file.begin(), file.size(), false);
279         }
280 
281         graphicsResource.FinishSetup();
282     }
283 
284     nw::lyt::DrawInfo drawInfo;
285     drawInfo.SetGraphicsResource(&graphicsResource);
286 
287     nw::lyt::Drawer drawer;
288     drawer.Initialize(graphicsResource);
289 
290     nw::demo::Pad& pad = *nw::demo::PadFactory::GetPad();
291 
292     const nw::ut::FloatColor clearColor(0.3f, 0.3f, 0.3f, 1.0f);
293     const f32 clearDepth = 0.0f;
294 
295     bool loop = true;
296     while (loop)
297     {
298         pad.Update();
299 
300         if (pad.IsButtonDown(pad.BUTTON_A))
301         {
302             // 透視射影か正射影かを切り替えます。
303             bPerspective = ! bPerspective;
304         }
305 
306         demoApp.SetRenderingTarget(demoApp.DISPLAY0);
307         {
308             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
309 
310             InitDraw(demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT);
311 
312             EnableZCompare(bPerspective);
313             SetupCamera(drawInfo, *pLayout, bPerspective);
314 
315             pLayout->Animate();
316             pLayout->CalculateMtx(drawInfo);
317 
318             drawer.DrawBegin(drawInfo);
319             drawer.Draw(pLayout, drawInfo);
320             drawer.DrawEnd(drawInfo);
321 
322             // フレームの更新
323             animFrame += 1.0f;
324             while (animFrame >= pAnimTrans->GetFrameSize())
325             {
326                 animFrame -= pAnimTrans->GetFrameSize();
327             }
328             pAnimTrans->SetFrame(animFrame);
329         }
330 
331         demoApp.SetRenderingTarget(demoApp.DISPLAY1);
332         {
333             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
334         }
335 
336         demoApp.SwapBuffer(demoApp.DISPLAY_BOTH);
337     }
338 
339     delete pLayout;
340     delete pResAccessor;
341 }
342 
343