/*---------------------------------------------------------------------------* Project: NintendoWare File: MultiInstanceDemo.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 19393 $ *---------------------------------------------------------------------------*/ #define NW_DEBUG_CHECK_MEMORY_LEAK #include #include #include #include #include #include #include #include namespace { //---------------------------------------- // メモリ関係 // デバイスメモリを確保するためのアロケータです。 nw::demo::DemoAllocator s_DeviceAllocator; //---------------------------------------- // ファイル名の定義です。 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl"); const wchar_t* MODEL_RESOURCE_FILES[] = { NW_DEMO_FILE_PATH(L"Male.bcmdl"), NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"), NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"), }; const wchar_t* SKELETAL_ANIM_RESOURCE_FILES[] = { NW_DEMO_FILE_PATH(L"Walk.bcskla"), }; //---------------------------------------- // 描画関係 const int RENDER_TARGET_COUNT = 1; typedef nw::ut::FixedSizeArray RenderTargetArray; RenderTargetArray s_RenderTargets; nw::demo::SceneSystem* s_SceneSystem = NULL; nw::demo::RenderSystem* s_RenderSystem = NULL; nw::demo::GraphicsDrawing s_GraphicsDrawing; //---------------------------------------- // リソース関係 nw::demo::ResourceArray s_Resources; //---------------------------------------- // シーン関係 const int SCENE_NODE_COUNT = 4; nw::gfx::SceneNode* s_SceneRoot = NULL; nw::gfx::SceneNode* s_ModelRoot = NULL; s32 s_FrameCount = 0; nw::gfx::Camera* s_BaseCamera = NULL; nw::gfx::Camera* s_LeftCamera = NULL; nw::gfx::Camera* s_RightCamera = NULL; const f32 s_fNearPlane = 0.1f; //---------------------------------------- // シーン環境関係 const s32 ENVIRONMENT_SETTINGS_COUNT = 1; typedef nw::ut::FixedSizeArray SceneEnvironmentSettingArray; SceneEnvironmentSettingArray s_SceneEnvironmentSettings; const s32 s_BaseCameraIndex = 0; //---------------------------------------- // アニメーション関係 float s_AnimWeight0 = 0.5f; float s_AnimWeight1 = 0.5f; const int MAX_ANIM_MODELS = 80; struct AnimModelSet { nw::gfx::SkeletalModel* skeletalModel; nw::anim::ResAnim resAnim; nw::gfx::TransformAnimEvaluator* evaluator; bool isSkeletonShared; }; typedef nw::ut::FixedSizeArray AnimModelSetArray; AnimModelSetArray s_AnimModelSets; AnimModelSet s_AnimModelSetTemplate; u32 s_NumCopy = 0; u32 s_NumSkeletonSharedCopy = 0; //---------------------------------------- // 操作関係 s32 s_WhirlDepth; s32 s_WhirlPos; /*!--------------------------------------------------------------------------* @brief モデル複製の方法です。 *---------------------------------------------------------------------------*/ enum DuplicationMode { DUPLICATION, //!< 新しくスケルタルモデルを生成します。 SKELETON_SHARED //!< スケルトンを共有したモデルを生成します。 }; /*!--------------------------------------------------------------------------* @brief グラフィックス関連の初期化を行います。 *---------------------------------------------------------------------------*/ void InitializeGraphics() { nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator ); // renderDescriptionへステレオの設定を行います。 nw::demo::RenderSystem::Description renderDescription; renderDescription.reusableCommandBufferSize = 0x100000; renderDescription.reusableCommandRequestCount = 512; renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO; s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription); s_GraphicsDrawing.SetScreenSize( renderDescription.lowerScreenDescription.width, renderDescription.lowerScreenDescription.height ); nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing); s_RenderTargets.push_back( nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription) ); NW_ASSERT(!s_RenderTargets.empty()); s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front()); nw::demo::SceneSystem::Description sceneDescription; sceneDescription.maxSceneNodes = MAX_ANIM_MODELS + 10; sceneDescription.maxSkeletalModels = MAX_ANIM_MODELS + 1; sceneDescription.maxModels = MAX_ANIM_MODELS + 1; sceneDescription.isFixedSizeMemory = false; s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription); // デモ用の最遠景モデルをレンダリングシステムに設定します。 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME); NW_GL_ASSERT(); } /*!--------------------------------------------------------------------------* @brief グラフィックス関連の後始末をします。 *---------------------------------------------------------------------------*/ void TerminateGraphics() { nw::gfx::SafeDestroy(s_LeftCamera); nw::gfx::SafeDestroy(s_RightCamera); nw::gfx::SafeDestroy(s_SceneSystem); nw::gfx::SafeDestroyAll(s_RenderTargets); s_GraphicsDrawing.Finalize(); nw::gfx::SafeDestroy(s_RenderSystem); NW_GL_ASSERT(); } /*!--------------------------------------------------------------------------* @brief ファイルからトランスフォームアニメーション評価を生成します。 @param[in] maxBones 最大メンバ数です。 @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。 @param[in] resAnim トランスフォームアニメーションのリソースです。 @return トランスフォームアニメーション評価です。 *---------------------------------------------------------------------------*/ nw::gfx::TransformAnimEvaluator* CreateTransformAnimEvaluator( const int maxMembers, const bool translateAnimEnabled, nw::anim::ResAnim resAnim ) { if (!resAnim.IsValid()) { return NULL; } //---------------------------------------- // トランスフォームアニメーション評価を生成します。 // // アニメーションを1つのモデルにのみ適用する場合や、 // コマ形式データの場合は、 AllocCache を false にすると処理負荷が下がります。 nw::gfx::TransformAnimEvaluator* evaluator = nw::gfx::TransformAnimEvaluator::Builder() .AnimData(resAnim) .MaxMembers(maxMembers) .MaxAnimMembers(resAnim.GetMemberAnimSetCount()) .AllocCache(false) .Create(&s_DeviceAllocator); // 移動アニメーションの無効化フラグを設定します。 evaluator->SetIsTranslateDisabled(!translateAnimEnabled); return evaluator; } /*!--------------------------------------------------------------------------* @brief スケルタルアニメーションにアニメーション評価をバインドし、そのアニメーション評価を返します。 *---------------------------------------------------------------------------*/ nw::gfx::TransformAnimEvaluator* InitializeSkeletalAnim( nw::gfx::SkeletalModel* model, nw::anim::ResAnim resAnim ) { nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup(); NW_NULL_ASSERT(animGroup); nw::gfx::ResSkeletalModel resModel = model->GetResSkeletalModel(); nw::gfx::ResSkeleton resSkeleton = resModel.GetSkeleton(); const int maxBones = resSkeleton.GetBonesCount(); const bool translateAnimEnabled = nw::ut::CheckFlag(resSkeleton.GetFlags(), nw::gfx::ResSkeletonData::FLAG_TRANSLATE_ANIMATION_ENABLED); nw::gfx::TransformAnimEvaluator* evaluator = CreateTransformAnimEvaluator( maxBones, translateAnimEnabled, resAnim); NW_NULL_ASSERT(evaluator); // アニメーションをバインドします。 bool bindResult = evaluator->Bind(animGroup); // アニメーションをモデルに登録します。 model->SetSkeletalAnimObject(evaluator); return evaluator; } /*!--------------------------------------------------------------------------* @brief アニメーションの後始末をします。 *---------------------------------------------------------------------------*/ void TerminateAnim(void) { for (int animIdx = 0; animIdx < s_AnimModelSets.Size(); ++animIdx) { nw::gfx::SafeDestroy(s_AnimModelSets[animIdx].evaluator); } s_AnimModelSets.clear(); nw::gfx::SafeDestroy(s_AnimModelSetTemplate.evaluator); } /*!--------------------------------------------------------------------------* @brief ルートノード関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildRootNodes() { NW_ASSERT(s_SceneRoot == NULL); s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder() .IsFixedSizeMemory(false) .Create(&s_DeviceAllocator); NW_NULL_ASSERT(s_SceneRoot); NW_ASSERT(s_ModelRoot == NULL); s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder() .IsFixedSizeMemory(false) .Create(&s_DeviceAllocator); s_SceneRoot->AttachChild(s_ModelRoot); NW_NULL_ASSERT(s_ModelRoot); } /*!--------------------------------------------------------------------------* @brief カメラ関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildCameras() { nw::demo::Utility::CreateStereoCameras( &s_BaseCamera, &s_LeftCamera, &s_RightCamera, &s_DeviceAllocator, nw::math::VEC3(50.0f, 40.0f, 50.0f), nw::math::VEC3(0.0f, 10.0f, 0.0f), s_fNearPlane ); s_SceneRoot->AttachChild(s_BaseCamera); s_SceneSystem->GetCameraController()->Register(s_BaseCamera); } /*!--------------------------------------------------------------------------* @brief リソース関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildResources(nw::demo::ResourceSet* resourceSet) { resourceSet->resource.ForeachTexture(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP)); resourceSet->resource.ForeachIndexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP)); resourceSet->resource.ForeachVertexStream(nw::gfx::LocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP)); nw::gfx::Result result = resourceSet->resource.Setup(&s_DeviceAllocator); if (result.IsFailure()) { NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode()); } nw::ut::MoveArray sceneNodeArray(&s_DeviceAllocator); nw::gfx::ResModelArray models = resourceSet->resource.GetModels(); nw::gfx::ResModelArray::iterator modelsEnd = models.end(); for (nw::gfx::ResModelArray::iterator modelResource = models.begin(); modelResource != modelsEnd; ++modelResource) { nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode( &s_DeviceAllocator, (*modelResource) ); NW_NULL_ASSERT(node); sceneNodeArray.push_back(node); s_AnimModelSetTemplate.skeletalModel = nw::ut::DynamicCast(node); } nw::gfx::ResLightArray lights = resourceSet->resource.GetLights(); nw::gfx::ResLightArray::iterator lightsEnd = lights.end(); for (nw::gfx::ResLightArray::iterator lightResource = lights.begin(); lightResource != lightsEnd; ++lightResource) { nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode( &s_DeviceAllocator, (*lightResource) ); NW_NULL_ASSERT(node); sceneNodeArray.push_back(node); } // 親子付け参照関係を解決 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray); // モデルをシーンに追加 nw::gfx::SceneHelper::ForeachRootNodes( sceneNodeArray.Begin(), sceneNodeArray.End(), nw::gfx::AttachNode(s_ModelRoot) ); nw::gfx::ResSceneEnvironmentSettingArray settings = resourceSet->resource.GetSceneEnvironmentSettings(); nw::gfx::ResSceneEnvironmentSettingArray::iterator settingsEnd = settings.end(); for (nw::gfx::ResSceneEnvironmentSettingArray::iterator settingResource = settings.begin(); settingResource != settingsEnd; ++settingResource) { nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder() .Resource(*settingResource) .CreateObject(&s_DeviceAllocator, &s_DeviceAllocator); nw::gfx::SceneEnvironmentSetting* sceneEnvironmentSetting = nw::ut::DynamicCast(sceneObject); NW_NULL_ASSERT(sceneEnvironmentSetting); s_SceneEnvironmentSettings.push_back(sceneEnvironmentSetting); } } /*!--------------------------------------------------------------------------* @brief テンプレートとなるスケルタルモデルとアニメーションを作成します。 *---------------------------------------------------------------------------*/ void BuildAnimModelTemplate() { NW_NULL_ASSERT(s_AnimModelSetTemplate.skeletalModel); nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, SKELETAL_ANIM_RESOURCE_FILES[0], &s_DeviceAllocator); NW_ASSERT (resourceSet->resource.GetSkeletalAnimsCount() != 0); s_AnimModelSetTemplate.skeletalModel->GetSkeleton()->GetResSkeleton().EnableFlags(nw::gfx::ResSkeletonData::FLAG_MODEL_COORDINATE); s_AnimModelSetTemplate.resAnim = resourceSet->resource.GetSkeletalAnims(0); s_AnimModelSetTemplate.evaluator = InitializeSkeletalAnim(s_AnimModelSetTemplate.skeletalModel, s_AnimModelSetTemplate.resAnim); } /*!--------------------------------------------------------------------------* @brief 新しくモデルの生成する位置を求めます。 *---------------------------------------------------------------------------*/ void GetNewDisplayPosition(f32* pPosX, f32* pPosZ) { // モデルを渦巻状に配置していきます int whirlSideLength = (s_WhirlDepth * 2 + 2); int posX; int posZ; // 新しい位置が矩形のどの辺になるかを求めます switch (s_WhirlPos / whirlSideLength) { case 0: // 右辺 posX = s_WhirlDepth + 1; posZ = s_WhirlPos % whirlSideLength - s_WhirlDepth; break; case 1: // 上辺 posX = -(s_WhirlPos % whirlSideLength) + s_WhirlDepth; posZ = s_WhirlDepth + 1; break; case 2: // 左辺 posX = -s_WhirlDepth - 1; posZ = -(s_WhirlPos % whirlSideLength) + s_WhirlDepth; break; case 3: // 下辺 posX = s_WhirlPos % whirlSideLength - s_WhirlDepth; posZ = -s_WhirlDepth - 1; break; default: NW_ASSERT(false); } *pPosX = posX * 10.0f; *pPosZ = posZ * 10.0f; s_WhirlPos++; if (s_WhirlPos >= whirlSideLength * 4) { s_WhirlDepth++; s_WhirlPos = 0; } return; } /*!--------------------------------------------------------------------------* @brief 次にモデルの生成する位置をひとつ戻します。 *---------------------------------------------------------------------------*/ void ReleaseLastDisplayPosition() { s_WhirlPos--; if (s_WhirlPos < 0) { s_WhirlDepth--; s_WhirlPos = (s_WhirlDepth * 2 + 2) * 4 - 1; } NW_ASSERT(s_WhirlDepth >= 0); } /*!--------------------------------------------------------------------------* @brief モデルを複製します。 *---------------------------------------------------------------------------*/ void DuplicateModel(DuplicationMode duplicationMode) { if (s_AnimModelSets.size() >= MAX_ANIM_MODELS) { return; } nw::gfx::SkeletalModel* skeletalModel; AnimModelSet animModelSet; switch (duplicationMode) { case SKELETON_SHARED: // スケルトンを共有するスケルタルモデルのインスタンスを生成します。 // スケルトンを共有する場合、 FLAG_MODEL_COORDINATE フラグを ResSkelton に設定しておく必要があります。 // また、最初に生成されたスケルトンが所有権を持つので、スケルトンの破棄には注意が必要です。 // このデモでは s_AnimModelSetTemplate.skeletalModel がスケルトンの所有権を持ちます。 skeletalModel = nw::gfx::SkeletalModel::Builder() .SharedSkeleton( s_AnimModelSetTemplate.skeletalModel->GetSkeleton() ) .SharedMaterialModel( s_AnimModelSetTemplate.skeletalModel ) .Create(NULL, nw::gfx::ResSceneObject(s_AnimModelSetTemplate.skeletalModel->GetResModel()), &s_DeviceAllocator); NW_NULL_ASSERT(skeletalModel); animModelSet.isSkeletonShared = true; s_NumSkeletonSharedCopy++; break; case DUPLICATION: // スケルタルモデルのインスタンスを生成します。 skeletalModel = nw::gfx::SkeletalModel::Builder() .SharedMaterialModel( s_AnimModelSetTemplate.skeletalModel ) .Create(NULL, nw::gfx::ResSceneObject(s_AnimModelSetTemplate.skeletalModel->GetResModel()), &s_DeviceAllocator); NW_NULL_ASSERT(skeletalModel); animModelSet.isSkeletonShared = false; s_NumCopy++; break; default: NW_ASSERT(false); } if (s_ModelRoot->AttachChild(skeletalModel)) { f32 posX; f32 posZ; animModelSet.skeletalModel = skeletalModel; animModelSet.resAnim = s_AnimModelSetTemplate.resAnim; switch (duplicationMode) { case SKELETON_SHARED: // スケルトンを共有する場合、共有スケルトンの1つにアニメーション評価をすればよいので、 // 複製のスケルトンにはアニメーション評価の作成やバインドを行いません。 animModelSet.evaluator = NULL; break; case DUPLICATION: animModelSet.evaluator = InitializeSkeletalAnim(animModelSet.skeletalModel, animModelSet.resAnim); NW_NULL_ASSERT(animModelSet.evaluator); break; } s_AnimModelSets.push_back( animModelSet ); GetNewDisplayPosition(&posX, &posZ); skeletalModel->Transform().SetTranslate(posX, 0.0f, posZ); // シーン構造が変化したので初期化を行います。 s_SceneSystem->InitializeScene(s_SceneRoot); } else { nw::ut::SafeDestroy(skeletalModel); } } /*!--------------------------------------------------------------------------* @brief 最後に複製したモデルを破棄します。 *---------------------------------------------------------------------------*/ void DestroyLastDuplicatedModel() { if (s_AnimModelSets.empty()) { return; } AnimModelSet destroyModelSet = s_AnimModelSets.back(); s_AnimModelSets.pop_back(); s_ModelRoot->DetachChild(destroyModelSet.skeletalModel); nw::ut::SafeDestroy(destroyModelSet.skeletalModel); nw::ut::SafeDestroy(destroyModelSet.evaluator); s_SceneSystem->InitializeScene(s_SceneRoot); ReleaseLastDisplayPosition(); if (destroyModelSet.isSkeletonShared) { s_NumSkeletonSharedCopy--; } else { s_NumCopy--; } } /*!--------------------------------------------------------------------------* @brief シーンを初期化します。 *---------------------------------------------------------------------------*/ void InitializeScenes() { s_AnimModelSetTemplate.skeletalModel = NULL; BuildRootNodes(); BuildCameras(); NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES) { BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator)); } BuildAnimModelTemplate(); s_NumCopy = 0; s_NumSkeletonSharedCopy = 0; // シーンツリーを巡回して初期化を行います。 s_SceneSystem->InitializeScene(s_SceneRoot); s_SceneSystem->UpdateScene(); // シーン環境の参照解決を行い設定します。 s_RenderSystem->SetSceneEnvironmentSettings(s_SceneSystem, &s_SceneEnvironmentSettings); // カメラを設定します。 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment(); sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera); nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]); NW_GL_ASSERT(); s_FrameCount = 0; s_WhirlDepth = 0; s_WhirlPos = 0; // あらかじめ何体か配置しておきます。 DuplicateModel(SKELETON_SHARED); DuplicateModel(SKELETON_SHARED); DuplicateModel(DUPLICATION); DuplicateModel(DUPLICATION); DuplicateModel(DUPLICATION); } /*!--------------------------------------------------------------------------* @brief シーン関連の後始末をします。 *---------------------------------------------------------------------------*/ void TerminateScenes() { nw::gfx::SafeDestroyBranch(s_SceneRoot); nw::demo::SafeCleanupResources(s_Resources); nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings); TerminateAnim(); NW_GL_ASSERT(); s_Resources.clear(); s_SceneEnvironmentSettings.clear(); s_ModelRoot = NULL; } /*!--------------------------------------------------------------------------* @brief モデルの生成・破棄や操作を行います。 *---------------------------------------------------------------------------*/ void ControlModels() { if (nw::demo::PadFactory::GetPad()->IsButtonRepeatFast(nw::demo::Pad::BUTTON_L)) { // Lボタンでモデルを生成します。 // 十字キーの上を押しながらLボタンを押すとスケルトンを共有するモデルを生成します。 if (nw::demo::PadFactory::GetPad()->IsButtonPress(nw::demo::Pad::BUTTON_UP)) { DuplicateModel(SKELETON_SHARED); } else { DuplicateModel(DUPLICATION); } } else if (nw::demo::PadFactory::GetPad()->IsButtonRepeatFast(nw::demo::Pad::BUTTON_R)) { // 最後に生成したモデルを破棄します。 DestroyLastDuplicatedModel(); } } /*!--------------------------------------------------------------------------* @brief シーンを更新します。 *---------------------------------------------------------------------------*/ void UpdateScene() { ControlModels(); s_SceneSystem->GetCameraController()->Update(); s_SceneSystem->UpdateScene(); s_BaseCamera->UpdateCameraMatrix(); s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f); ++s_FrameCount; } /*!--------------------------------------------------------------------------* @brief 負荷表示やテスト機能の処理をおこないます。 *---------------------------------------------------------------------------*/ void ReportDemo() { NW_PROFILE("ReportDemo"); // 負荷表示からはこれらの負荷は除きます。 s_RenderSystem->SuspendLoadMeter(); nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem); s_GraphicsDrawing.BeginDrawingShape(); nw::demo::DebugUtility::DrawLoadMeter( s_RenderSystem, &s_GraphicsDrawing ); s_GraphicsDrawing.EndDrawingShape(); s_GraphicsDrawing.BeginDrawingString(); nw::demo::DebugUtility::DrawLoadMeterText( s_RenderSystem, &s_GraphicsDrawing ); const int dumpPositionX = 10; const int dumpPositionY = 10; s_GraphicsDrawing.DrawString( dumpPositionX, dumpPositionY, " original: 1\n" " copy: %d\n" "skeleton shared: %d", s_NumCopy, s_NumSkeletonSharedCopy ); s_GraphicsDrawing.EndDrawingString(); s_RenderSystem->ResumeLoadMeter(); } /*!--------------------------------------------------------------------------* @brief シーンをデモンストレーションします。 *---------------------------------------------------------------------------*/ void DemoScene() { NW_ASSERT(!s_RenderTargets.empty()); nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext(); InitializeScenes(); nw::demo::DebugUtility::PostInitializeScenes(); NW_LOG("[Multi Instance Demo usage]\n"); NW_LOG("r : delete\n"); NW_LOG("l : add copy\n"); NW_LOG("up + l : add skeleton shared copy\n"); bool isContinuing = true; while ( isContinuing ) { nw::demo::DebugUtility::AdvanceAutoTestFrame(); nw::demo::PadFactory::GetPad()->Update(); UpdateScene(); renderContext->SetActiveCamera(s_BaseCameraIndex); s_RenderSystem->SubmitView(s_SceneSystem); s_RenderSystem->SetRenderTarget(s_RenderTargets[0]); s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera); s_RenderSystem->ClearBySkyModel(s_BaseCamera); ReportDemo(); s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN); s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN); renderContext->ResetState(); if (nw::demo::Utility::IsTerminating()) { isContinuing = false; } } nw::demo::DebugUtility::PreTerminateScenes(); TerminateScenes(); } } // namespace /*!--------------------------------------------------------------------------* @brief メイン関数です。 *---------------------------------------------------------------------------*/ void nnMain() { nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator); nw::demo::PadFactory::Initialize(&s_DeviceAllocator); NW_DEMO_TEST_LOOP(&s_DeviceAllocator, NULL, &s_RenderSystem) { InitializeGraphics(); DemoScene(); TerminateGraphics(); } nw::demo::PadFactory::Finalize(); nw::demo::FinalizeGraphicsSystem(); }