/*---------------------------------------------------------------------------* Project: NintendoWare File: ResourceDemo.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: 28152 $ *---------------------------------------------------------------------------*/ #define NW_DEBUG_CHECK_MEMORY_LEAK #include #include #include #include #include #include #include namespace { //---------------------------------------- // メモリ関係 // デバイスメモリを確保するためのアロケータです。 nw::demo::DemoAllocator s_DeviceAllocator; //---------------------------------------- // リソース関係 nw::demo::ResourceSet* s_ShaderResource; nw::demo::ResourceArray s_LutResources; nw::demo::ResourceArray s_Resources; struct ResourceData { ResourceData( wchar_t* modelName, s32 lutIndex, nw::math::VEC3 position) : modelName(modelName), lutIndex(lutIndex), position(position) {} const wchar_t* modelName; const s32 lutIndex; const nw::math::VEC3 position; }; enum LutResource { //! @brief 共通のLUTセットです。 DemoLutSet, //! @brief マテリアルサンプルのLUTセットです。 MaterialSampleLutSet }; static const wchar_t* LUT_RESOURCE_FILES[] = { NW_DEMO_FILE_PATH(L"Lutset.bclts"), NW_DEMO_FILE_PATH(L"SampleLutset.bclts"), }; static const ResourceData MODEL_RESOURCE_DATA[] = { ResourceData(NW_DEMO_FILE_PATH(L"Phong.bcmdl"), DemoLutSet, nw::math::VEC3(0.0f, 0.0f, 0.0f)), ResourceData(NW_DEMO_FILE_PATH(L"Blinn.bcmdl"), DemoLutSet, nw::math::VEC3(2.5f, 0.0f, 0.0f)), ResourceData(NW_DEMO_FILE_PATH(L"VertexLight.bcmdl"), DemoLutSet, nw::math::VEC3(5.0f, 0.0f, 0.0f)), ResourceData(NW_DEMO_FILE_PATH(L"CarPaint.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(7.5f, 0.0f, 0.0f)), ResourceData(NW_DEMO_FILE_PATH(L"Sss.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(10.0f, 0.0f, 0.0f)), ResourceData(NW_DEMO_FILE_PATH(L"ThinFilm.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(12.5f, 0.0f, 0.0f)), ResourceData(NW_DEMO_FILE_PATH(L"Toon.bcmdl"), MaterialSampleLutSet, nw::math::VEC3(15.0f, 0.0f, 0.0f)), }; const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl"); static const wchar_t* RESOURCE_FILES[] = { NW_DEMO_FILE_PATH(L"SceneEnvironmentSetting.bcenv"), NW_DEMO_FILE_PATH(L"Camera.bcenv"), NW_DEMO_FILE_PATH(L"FragmentLight.bcenv"), NW_DEMO_FILE_PATH(L"HemisphereLight.bcenv"), NW_DEMO_FILE_PATH(L"VertexLight.bcenv"), NW_DEMO_FILE_PATH(L"Fog.bcenv"), }; static const wchar_t* SHADER_RESOURCE_FILE_NAME = NW_DEMO_FILE_PATH(L"nwgfx_DefaultShader.bcsdr"); //---------------------------------------- // 描画関係 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; //---------------------------------------- // シーン関係 const int SCENE_NODE_COUNT = 16; nw::gfx::SceneNode* s_SceneRoot = 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 int ENVIRONMENT_SETTINGS_COUNT = 1; typedef nw::ut::FixedSizeArray SceneEnvironmentSettingArray; SceneEnvironmentSettingArray s_SceneEnvironmentSettings; const s32 s_BaseCameraIndex = 0; /*!--------------------------------------------------------------------------* @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()); // sceneDescriptionへの標準的な設定はコンストラクタで行われています。 nw::demo::SceneSystem::Description sceneDescription; sceneDescription.isFixedSizeMemory = true; s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription); // ファイルからシェーダリソースを読み込みます。 // シェーダの作り方は CreativeStudio の シェーダクリエーションパネルの説明を参照してください。 s_ShaderResource = s_DeviceAllocator.AllocAndConstruct(1); s_ShaderResource->buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , SHADER_RESOURCE_FILE_NAME); NW_NULL_ASSERT(s_ShaderResource->buffer); s_ShaderResource->resource = nw::gfx::ResGraphicsFile(&(s_ShaderResource->buffer.front())); // デモ用の最遠景モデルをレンダリングシステムに設定します。 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME); NW_GL_ASSERT(); } /*!--------------------------------------------------------------------------* @brief グラフィックス関連の後始末をします。 *---------------------------------------------------------------------------*/ void TerminateGraphics() { s_DeviceAllocator.DestructAndFree(s_ShaderResource, 1); 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 ルートノード関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildRootNodes() { NW_ASSERT(s_SceneRoot == NULL); s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder() .MaxChildren(16) .Create(&s_DeviceAllocator); NW_NULL_ASSERT(s_SceneRoot); } /*!--------------------------------------------------------------------------* @brief カメラ関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildCameras() { s_LeftCamera = nw::gfx::Camera::DynamicBuilder() .MaxChildren(0) .MaxCallbacks(0) .Create(&s_DeviceAllocator); NW_POINTER_ASSERT(s_LeftCamera); s_RightCamera = nw::gfx::Camera::DynamicBuilder() .MaxChildren(0) .MaxCallbacks(0) .Create(&s_DeviceAllocator); NW_POINTER_ASSERT(s_RightCamera); s_BaseCamera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin()); s_SceneRoot->AttachChild(s_BaseCamera); s_SceneSystem->GetCameraController()->Register(s_BaseCamera); } /*!--------------------------------------------------------------------------* @brief シーンを初期化します。 *---------------------------------------------------------------------------*/ void InitializeScenes() { BuildRootNodes(); // ファイルから LUT Set を読み込みます。 NW_FOREACH(const wchar_t* name, LUT_RESOURCE_FILES) { nw::demo::ResourceSet resourceSet; resourceSet.buffer = nw::demo::Utility::LoadFile(&s_DeviceAllocator , name); NW_NULL_ASSERT(resourceSet.buffer); resourceSet.resource = nw::gfx::ResGraphicsFile(&(resourceSet.buffer.front())); s_LutResources.push_back(resourceSet); } nw::ut::MoveArray sceneNodeArray(SCENE_NODE_COUNT, &s_DeviceAllocator); // モデルリソースを読み込みます。 NW_FOREACH(const ResourceData resourceData, MODEL_RESOURCE_DATA) { nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, resourceData.modelName, &s_DeviceAllocator); 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()) { if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_SHADER) { // シェーダーが見つからなかったときは、外部ファイルを指定して再びセットアップします。 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_ShaderResource->resource); } if (result.GetDescription() & nw::gfx::RESOURCE_RESULT_NOT_FOUND_LUT) { // 参照テーブルが見つからなかったときは、外部ファイルを指定して再びセットアップします。 result = resourceSet->resource.Setup(&s_DeviceAllocator, s_LutResources[resourceData.lutIndex].resource); } if (result.IsFailure()) { NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode()); } } 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::math::VEC3& translate = (*modelResource).GetTransform().translate; translate += resourceData.position; nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode( &s_DeviceAllocator, (*modelResource), false ); NW_NULL_ASSERT(node); sceneNodeArray.push_back(node); } } // モデル以外のリソースを読み込みます。 NW_FOREACH(const wchar_t* name, RESOURCE_FILES) { nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, name, &s_DeviceAllocator); 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::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::ResCameraArray cameras = resourceSet->resource.GetCameras(); nw::gfx::ResCameraArray::iterator camerasEnd = cameras.end(); for (nw::gfx::ResCameraArray::iterator cameraResource = cameras.begin(); cameraResource != camerasEnd; ++cameraResource) { nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode( &s_DeviceAllocator, (*cameraResource) ); NW_NULL_ASSERT(node); sceneNodeArray.push_back(node); } nw::gfx::ResFogArray fogs = resourceSet->resource.GetFogs(); nw::gfx::ResFogArray::iterator fogsEnd = fogs.end(); for (nw::gfx::ResFogArray::iterator fogResource = fogs.begin(); fogResource != fogsEnd; ++fogResource) { nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode( &s_DeviceAllocator, (*fogResource) ); NW_NULL_ASSERT(node); sceneNodeArray.push_back(node); } 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); } } // 親子付け参照関係を解決 nw::gfx::SceneHelper::ResolveReference(sceneNodeArray); // モデルをシーンに追加 nw::gfx::SceneHelper::ForeachRootNodes( sceneNodeArray.Begin(), sceneNodeArray.End(), nw::gfx::AttachNode(s_SceneRoot) ); // シーンツリーを巡回して初期化を行います。 s_SceneSystem->InitializeScene(s_SceneRoot); BuildCameras(); // シーン環境の参照解決を行い設定します。 s_RenderSystem->SetSceneEnvironmentSettings( s_SceneSystem, &s_SceneEnvironmentSettings); s_SceneSystem->UpdateScene(); NW_GL_ASSERT(); //----------------------------------------------------------------------------- s_FrameCount = 0; } /*!--------------------------------------------------------------------------* @brief シーン関連の後始末をします。 *---------------------------------------------------------------------------*/ void TerminateScenes() { nw::gfx::SafeDestroyBranch(s_SceneRoot); nw::demo::SafeCleanupResources(s_Resources); nw::demo::SafeCleanupResources(s_LutResources); nw::ut::SafeCleanup(s_ShaderResource->resource); nw::ut::SafeDestroyAll(s_SceneEnvironmentSettings); NW_GL_ASSERT(); s_Resources.clear(); s_LutResources.clear(); s_SceneEnvironmentSettings.clear(); } /*!--------------------------------------------------------------------------* @brief シーンを更新します。 *---------------------------------------------------------------------------*/ void UpdateScene() { s_SceneSystem->GetCameraController()->Update(); s_SceneSystem->UpdateScene(); s_BaseCamera->UpdateCameraMatrix(); s_RenderSystem->CalcStereoCamera( s_LeftCamera, s_RightCamera, *(s_SceneSystem->GetSceneContext()->GetCameraBegin()), 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 ); 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::gfx::Camera* camera = *(s_SceneSystem->GetSceneContext()->GetCameraBegin()); nw::demo::Utility::SetCameraAspectRatio(camera, s_RenderTargets[0]); 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(); }