/*---------------------------------------------------------------------------* Project: NintendoWare File: AnimationBlendDemo.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: 22362 $ *---------------------------------------------------------------------------*/ #define NW_DEBUG_CHECK_MEMORY_LEAK #include #include #include #include #include #include #include #include namespace { //---------------------------------------- // メモリ関係 // デバイスメモリを確保するためのアロケータです。 nw::demo::DemoAllocator s_DeviceAllocator; //---------------------------------------- // ファイル名の定義です。 const wchar_t* FONT_SHADER_FILE_NAME = NW_DEMO_FILE_PATH(L"nwfont_RectDrawerShader.shbin"); const wchar_t* FONT_FILE_NAME = NW_DEMO_FILE_PATH(L"Font.bcfnt"); 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"), NW_DEMO_FILE_PATH(L"Run.bcskla") }; const wchar_t* MATERIAL_ANIM_RESOURCE_FILES[] = { NW_DEMO_FILE_PATH(L"RedFading.bcmata"), NW_DEMO_FILE_PATH(L"GreenFading.bcmata") }; //---------------------------------------- // プロファイル関係 const int NW_LOAD_METER_INTERVAL = 60; //---------------------------------------- // 描画関係 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; //---------------------------------------- // アニメーション関係 nw::gfx::SkeletalModel* s_AnimModel = NULL; const int MAX_ANIM_OBJECTS = 6; nw::ut::FixedSizeArray s_AnimObjects; float s_SkeletalAnimWeight0 = 0.5f; float s_SkeletalAnimWeight1 = 0.5f; float s_MaterialAnimWeight0 = 0.5f; float s_MaterialAnimWeight1 = 0.5f; /*!--------------------------------------------------------------------------* @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 ); bool result = s_GraphicsDrawing.InitializeFont(&s_DeviceAllocator, FONT_SHADER_FILE_NAME, FONT_FILE_NAME); NN_ASSERTMSG(result, "Fail to load Font."); s_RenderTargets.push_back( nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription) ); NW_ASSERT(!s_RenderTargets.empty()); s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front()); // sceneDescriptionへの標準的な設定はコンストラクタで行われています。 nw::demo::SceneSystem::Description sceneDescription; sceneDescription.isFixedSizeMemory = true; 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 ファイルから TransformAnimEvaluator を生成します。 リソースからアニメーションを計算するための AnimEvaluator(アニメーション評価)を生成します。 @param[in] maxBones 最大メンバ数です。 @param[in] translateAnimEnabled 移動アニメーションが有効かどうかです。 @param[in] filePath トランスフォームアニメーションファイルのフルパスです。 @return トランスフォームアニメーション評価です。 *---------------------------------------------------------------------------*/ nw::gfx::TransformAnimEvaluator* CreateTransformAnimEvaluator( const int maxMembers, const bool translateAnimEnabled, const wchar_t* filePath ) { // ファイルからアニメーションデータのインスタンスを生成します。 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator); if (resourceSet->resource.GetSkeletalAnimsCount() == 0) { // スケルタルアニメーション用のアニメーションデータがありません。 return NULL; } nw::anim::ResAnim resAnim = resourceSet->resource.GetSkeletalAnims(0); if (!resAnim.IsValid()) { return NULL; } // resAnim から、AnimEvaluator::Builder を用いて AnimEvaluator を生成します。 // スケルタルアニメーションの場合は、TransformAnimEvaluator::Builder を使用します。 // // アニメーションを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 ファイルからマテリアルアニメーション評価を生成します。 @param[in] maxBones 最大メンバ数です。 @param[in] filePath マテリアルアニメーションファイルのフルパスです。 @return マテリアルアニメーション評価です。 *---------------------------------------------------------------------------*/ nw::gfx::AnimEvaluator* CreateMaterialAnimEvaluator( const int maxMembers, const wchar_t* filePath ) { //---------------------------------------- // アニメーションリソースを生成します。 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, filePath, &s_DeviceAllocator); if (resourceSet->resource.GetMaterialAnimsCount() == 0) { return NULL; } nw::anim::ResAnim resAnim = resourceSet->resource.GetMaterialAnims(0); if (!resAnim.IsValid()) { return NULL; } //---------------------------------------- // マテリアルアニメーション評価を生成します。 nw::gfx::AnimEvaluator* evaluator = nw::gfx::AnimEvaluator::Builder() .AnimData(resAnim) .MaxMembers(maxMembers) .MaxAnimMembers(resAnim.GetMemberAnimSetCount()) .AllocCache(true) .Create(&s_DeviceAllocator); return evaluator; } /*!--------------------------------------------------------------------------* @brief スケルタルアニメーションを初期化します。 アニメーション補間を生成し、2 つのアニメーション評価の結果をブレンドします。 @param[in] model スケルタルモデルです。 *---------------------------------------------------------------------------*/ void InitializeSkeletalAnim(nw::gfx::SkeletalModel* model) { nw::gfx::AnimGroup* animGroup = model->GetSkeletalAnimGroup(); if (animGroup == NULL) // スケルタルアニメーション用のアニメーショングループがありません。 { return; } 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* evaluator0 = CreateTransformAnimEvaluator( maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILES[0]); if (evaluator0 == NULL) { return; } // アニメーションをバインドします。 evaluator0->Bind(animGroup); s_AnimObjects.PushBack(evaluator0); //---------------------------------------- // 2 つめのアニメーション評価を生成します。 nw::gfx::TransformAnimEvaluator* evaluator1 = CreateTransformAnimEvaluator( maxBones, translateAnimEnabled, SKELETAL_ANIM_RESOURCE_FILES[1]); if (evaluator1 == NULL) { return; } evaluator1->Bind(animGroup); s_AnimObjects.PushBack(evaluator1); // 自然な絵になるように、2つのアニメーションの再生時間を合わせます。 float frameSize0 = evaluator0->AnimFrameController().GetEndFrame(); float frameSize1 = evaluator1->AnimFrameController().GetEndFrame(); evaluator1->SetStepFrame(frameSize1 / frameSize0); //---------------------------------------- // スケルタルアニメーション補間を生成します。 nw::gfx::TransformAnimInterpolator* blender = nw::gfx::TransformAnimInterpolator::Builder() .MaxAnimObjects(2) .Create(&s_DeviceAllocator); blender->Bind(animGroup); blender->AddAnimObject(evaluator0); blender->AddAnimObject(evaluator1); blender->SetWeight(0, s_SkeletalAnimWeight0); blender->SetWeight(1, s_SkeletalAnimWeight1); // 設定する重みは常に合計が 1 になり正規化は不要なので、正規化を無効にします。 // 合計が 1 にならないような重みを設定する場合は true を指定します。 blender->SetNormalizationEnabled(false); model->SetSkeletalAnimObject(blender); s_AnimObjects.PushBack(blender); } /*!--------------------------------------------------------------------------* @brief マテリアルアニメーションを初期化します。 アニメーション補間を生成し、2 つのアニメーション評価の結果をブレンドします。 @param[in] model モデルです。 *---------------------------------------------------------------------------*/ void InitializeMaterialAnim(nw::gfx::Model* model) { nw::gfx::AnimGroup* animGroup = model->GetMaterialAnimGroup(); if (animGroup == NULL) // アニメーション用のアニメーショングループがありません。 { return; } int maxMembers = animGroup->GetMemberCount(); //---------------------------------------- // アニメーション評価を生成します。 nw::gfx::AnimEvaluator* evaluator0 = CreateMaterialAnimEvaluator( maxMembers, MATERIAL_ANIM_RESOURCE_FILES[0]); if (evaluator0 == NULL) { return; } // アニメーションをバインドします。 evaluator0->Bind(animGroup); s_AnimObjects.PushBack(evaluator0); //---------------------------------------- // 2 つめのアニメーション評価を生成します。 nw::gfx::AnimEvaluator* evaluator1 = CreateMaterialAnimEvaluator( maxMembers, MATERIAL_ANIM_RESOURCE_FILES[1]); if (evaluator1 == NULL) { return; } evaluator1->Bind(animGroup); s_AnimObjects.PushBack(evaluator1); //---------------------------------------- // アニメーション補間を生成します。 nw::gfx::AnimInterpolator* blender = nw::gfx::AnimInterpolator::Builder() .MaxAnimObjects(2) .Create(&s_DeviceAllocator); blender->Bind(animGroup); blender->AddAnimObject(evaluator0); blender->AddAnimObject(evaluator1); blender->SetWeight(0, s_MaterialAnimWeight0); blender->SetWeight(1, s_MaterialAnimWeight0); // 設定する重みは常に合計が 1 になり正規化は不要なので、正規化を無効にします。 // 合計が 1 にならないような重みを設定する場合は true を指定します。 blender->SetNormalizationEnabled(false); model->SetMaterialAnimObject(blender); s_AnimObjects.PushBack(blender); } /*!--------------------------------------------------------------------------* @brief ブレンダーを更新します。 @param[in] model モデルです。 *---------------------------------------------------------------------------*/ void UpdateBlender(nw::gfx::SkeletalModel* model) { NW_PROFILE("UpdateBlender"); if (model == NULL) { return; } // ブレンドのウェイト値を設定します。 nw::gfx::AnimObject* skeletalAnimObject = model->GetSkeletalAnimObject(); nw::gfx::TransformAnimInterpolator* skeletalInterpolator = nw::ut::DynamicCast(skeletalAnimObject); if (skeletalInterpolator != NULL) { bool weightChanged = false; nw::demo::Pad* pad = nw::demo::PadFactory::GetPad(); if (pad->IsButtonPress(nw::demo::Pad::BUTTON_LEFT)) { s_SkeletalAnimWeight1 -= 0.02f; weightChanged = true; } if (pad->IsButtonPress(nw::demo::Pad::BUTTON_RIGHT)) { s_SkeletalAnimWeight1 += 0.02f; weightChanged = true; } if (weightChanged) { s_SkeletalAnimWeight1 = nw::ut::Clamp(s_SkeletalAnimWeight1, 0.0f, 1.0f); s_SkeletalAnimWeight0 = 1.0f - s_SkeletalAnimWeight1; skeletalInterpolator->SetWeight(0, s_SkeletalAnimWeight0); skeletalInterpolator->SetWeight(1, s_SkeletalAnimWeight1); } } nw::gfx::AnimObject* materialAnimObject = model->GetMaterialAnimObject(); nw::gfx::AnimInterpolator* materialInterpolator = nw::ut::DynamicCast(materialAnimObject); if (materialInterpolator != NULL) { bool weightChanged = false; nw::demo::Pad* pad = nw::demo::PadFactory::GetPad(); if (pad->IsButtonPress(nw::demo::Pad::BUTTON_UP)) { s_MaterialAnimWeight1 -= 0.02f; weightChanged = true; } if (pad->IsButtonPress(nw::demo::Pad::BUTTON_DOWN)) { s_MaterialAnimWeight1 += 0.02f; weightChanged = true; } if (weightChanged) { s_MaterialAnimWeight1 = nw::ut::Clamp(s_MaterialAnimWeight1, 0.0f, 1.0f); s_MaterialAnimWeight0 = 1.0f - s_MaterialAnimWeight1; materialInterpolator->SetWeight(0, s_MaterialAnimWeight1); materialInterpolator->SetWeight(1, s_MaterialAnimWeight0); } } } /*!--------------------------------------------------------------------------* @brief アニメーションの後始末をします。 *---------------------------------------------------------------------------*/ void TerminateAnim(void) { for (int animIdx = 0; animIdx < s_AnimObjects.Size(); ++animIdx) { nw::gfx::SafeDestroy(s_AnimObjects[animIdx]); } s_AnimObjects.clear(); } /*!--------------------------------------------------------------------------* @brief ルートノード関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildRootNodes() { NW_ASSERT(s_SceneRoot == NULL); s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder() .Create(&s_DeviceAllocator); NW_NULL_ASSERT(s_SceneRoot); NW_ASSERT(s_ModelRoot == NULL); s_ModelRoot = nw::gfx::TransformNode::DynamicBuilder() .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(20.0f, 15.0f, 20.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::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP)); resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP)); resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(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(SCENE_NODE_COUNT, &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_AnimModel = 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 InitializeScenes() { s_SkeletalAnimWeight0 = 0.5f; s_SkeletalAnimWeight1 = 0.5f; s_MaterialAnimWeight0 = 0.5f; s_MaterialAnimWeight1 = 0.5f; BuildRootNodes(); BuildCameras(); NW_FOREACH(const wchar_t* name, MODEL_RESOURCE_FILES) { BuildResources(nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator)); } if (s_AnimModel != NULL) { InitializeSkeletalAnim(s_AnimModel); InitializeMaterialAnim(s_AnimModel); } // シーンツリーを巡回して初期化を行います。 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; } /*!--------------------------------------------------------------------------* @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 UpdateScene() { UpdateBlender(s_AnimModel); 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(); s_GraphicsDrawing.BeginDrawingString(); nw::demo::DebugUtility::DrawLoadMeter( s_RenderSystem, &s_GraphicsDrawing, (s_FrameCount % NW_LOAD_METER_INTERVAL == 0) ); const int dumpPositionX = 10; const int dumpPositionY = 10; s_GraphicsDrawing.DrawString( dumpPositionX, dumpPositionY, "weight: %0.2f %0.2f", s_SkeletalAnimWeight1, s_MaterialAnimWeight1 ); s_GraphicsDrawing.FlushDrawing(); s_RenderSystem->ResumeLoadMeter(); } /*!--------------------------------------------------------------------------* @brief シーンをデモンストレーションします。 *---------------------------------------------------------------------------*/ void DemoScene() { NW_ASSERT(!s_RenderTargets.empty()); nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext(); InitializeScenes(); NW_LOG("[Animation Blend Demo usage]\n"); NW_LOG("up/down : change material animation blender weight\n"); NW_LOG("left/right: change skeletal animation blender weight\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; } } 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(); }