/*---------------------------------------------------------------------------* Project: NintendoWare File: ParticleCtrlEmissionDemo.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: 25967 $ *---------------------------------------------------------------------------*/ /* 放出量と初速を変えるデモです。 */ #define NW_DEBUG_CHECK_MEMORY_LEAK #include #include #include #include #include #include #include namespace { //---------------------------------------- // メモリ関係 // デバイスメモリを確保するためのアロケータです。 nw::demo::DemoAllocator s_DeviceAllocator; nw::demo::DemoAllocator s_ParticleAllocator; //---------------------------------------- // ファイル名の定義です。 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 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::gfx::ParticleContext* s_ParticleContext = NULL; nw::demo::GraphicsDrawing s_GraphicsDrawing; //---------------------------------------- // リソース関係 nw::demo::ResourceArray s_Resources; //---------------------------------------- // シーン関係 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 s32 s_BaseCameraIndex = 0; //---------------------------------------- // パーティクル関係 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL; nw::demo::FlushCache* s_FlushCache; /*!--------------------------------------------------------------------------* @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; s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription); s_ParticleContext = nw::gfx::ParticleContext::Builder() .Create(&s_DeviceAllocator); s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder() .Create(&s_DeviceAllocator); // デモ用の最遠景モデルをレンダリングシステムに設定します。 // 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_ParticleSceneUpdater); nw::gfx::SafeDestroy(s_ParticleContext); 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() .IsFixedSizeMemory(false) .Create(&s_DeviceAllocator); NW_NULL_ASSERT(s_SceneRoot); } /*!--------------------------------------------------------------------------* @brief カメラ関連の構築をします。 *---------------------------------------------------------------------------*/ void BuildCameras() { nw::demo::Utility::CreateStereoCameras( &s_BaseCamera, &s_LeftCamera, &s_RightCamera, &s_DeviceAllocator, nw::math::VEC3(28.0f, 22.0f, 28.0f), nw::math::VEC3(0.0f, 0.0f, 0.0f), s_fNearPlane ); s_SceneRoot->AttachChild(s_BaseCamera); s_SceneSystem->GetCameraController()->Register(s_BaseCamera); } /*!--------------------------------------------------------------------------* @brief シーンを初期化します。 *---------------------------------------------------------------------------*/ void InitializeScenes() { BuildRootNodes(); BuildCameras(); // シーンツリーを巡回して初期化を行います。 s_SceneSystem->InitializeScene(s_SceneRoot); s_SceneSystem->UpdateScene(); // カメラを設定します。 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_GL_ASSERT(); s_Resources.clear(); } /*!--------------------------------------------------------------------------* @brief シーンを更新します。 *---------------------------------------------------------------------------*/ void UpdateScene() { NW_ASSERT(0 < s_RenderTargets.size()); s_SceneSystem->GetCameraController()->Update(); s_SceneSystem->UpdateScene(); s_BaseCamera->UpdateCameraMatrix(); NW_NULL_ASSERT(s_ParticleSceneUpdater); s_ParticleSceneUpdater->UpdateNode( s_SceneSystem->GetSceneContext(), s_ParticleContext); s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f); s_FrameCount++; s_FlushCache->Execute(); } /*!--------------------------------------------------------------------------* @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) ); s_GraphicsDrawing.FlushDrawing(); s_RenderSystem->ResumeLoadMeter(); } //---------------------------------------- // デモ固有の変数 // パーティクルエフェクトクラス nw::demo::ParticleEffect* s_ParticleEffect = NULL; // パーティクルノードクラス nw::demo::ParticleNode* s_particleNode = NULL; // 放出量 f32 s_EmissionRatio = 1.0f; // ロードするエフェクトファイル名 const wchar_t* EFFECT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"fountain_particle_all.bcptl"); /*!--------------------------------------------------------------------------* @brief ParticleCtrlEmissionDemoの初期化を行います。 *---------------------------------------------------------------------------*/ void InitializeParticleCtrlEmissionDemo() { // このデモは、パッドのLRを用いて、 // パーティクルの放出量の調整を行うデモです。 // 放出量の調整は、ParticleNode::SetEmissionRatioメソッドを用いて行います。 // パーティクルエフェクトクラスを生成します。 s_ParticleEffect = nw::demo::ParticleEffect::Create(&s_DeviceAllocator, &s_DeviceAllocator, false, s_ParticleContext); // エフェクトデータをロードしてセットアップします。 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, EFFECT_RESOURCE_FILE, &s_DeviceAllocator); // リソースをセットアップを行います。 // fountain_particle_allはコンスタントカラーを使用しているので、ParticleMaterialは使用できません。 s_ParticleEffect->Setup(resourceSet->resource, false); // ParticleEffectにリソースをセットします。 s_ParticleEffect->Register(resourceSet->resource); s_ParticleEffect->AddPool(1); // パーティクルノードクラスのインスタンスをリースします。 s_particleNode = s_ParticleEffect->LeaseInstance(); // シーンに追加します。 s_SceneRoot->AttachChild(s_particleNode); s_SceneSystem->InitializeScene(s_SceneRoot); s_SceneSystem->UpdateScene(); // 操作説明をログ出力します。 NW_DEV_LOG("[ParticleCtrlEmissionDemo Ctrl]\n"); NW_DEV_LOG("l : Decrement Emission Ratio\n"); NW_DEV_LOG("r : Additive Emission Ratio\n"); } /*!--------------------------------------------------------------------------* @brief ParticleCtrlEmissionDemoの定期処理です。 *---------------------------------------------------------------------------*/ void UpdateParticleCtrlEmissionDemo() { bool isEmissionRatioUpdate = false; // パッドで放出量を操作します。 if (nw::demo::PadFactory::GetPad()->IsButtonDown(nw::demo::Pad::BUTTON_L)) { s_EmissionRatio -= 0.1f; if (s_EmissionRatio < 0.f) { s_EmissionRatio = 0.f; } isEmissionRatioUpdate = true; } if (nw::demo::PadFactory::GetPad()->IsButtonDown(nw::demo::Pad::BUTTON_R)) { s_EmissionRatio += 0.1f; if (s_EmissionRatio > 2.f) { s_EmissionRatio = 2.f; } isEmissionRatioUpdate = true; } // 放出量を設定します。 if (isEmissionRatioUpdate) { // SetEmissionRatioメソッド内では、 // ResParticleEmitterParameter内、SetEmissionRatioメソッドを操作しています。 // ResParticleEmitterParameter自体は、 // ParticleEmitter::GetResParticleEmitterParameterCopy()にて取得できます。 s_particleNode->SetEmissionRatio(s_EmissionRatio); } } /*!--------------------------------------------------------------------------* @brief ParticleCtrlEmissionDemoのスクリーンデバッグ表示です。 *---------------------------------------------------------------------------*/ void ReportParticleCtrlEmissionDemo() { s_GraphicsDrawing.DrawString(10, 10, "Particle Num :%d\n", s_particleNode->GetParticleSize() ); s_GraphicsDrawing.DrawString(10, 22, "Emission Ratio:%2.1f/2.0\n", s_EmissionRatio ); } /*!--------------------------------------------------------------------------* @brief ParticleCtrlEmissionDemoの終了処理を行います。 *---------------------------------------------------------------------------*/ void TerminateParticleCtrlEmissionDemo() { nw::demo::ParticleNode* prevTarget = s_ParticleEffect->GetActiveEffect(0); while (prevTarget != NULL) { s_ParticleEffect->ReleaseInstance(prevTarget); prevTarget = s_ParticleEffect->GetActiveEffect(0); } s_ParticleEffect->FreePool(); nw::gfx::SafeDestroy(s_ParticleEffect); } /*!--------------------------------------------------------------------------* @brief シーンをデモンストレーションします。 *---------------------------------------------------------------------------*/ void DemoScene() { NW_ASSERT(!s_RenderTargets.empty()); nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext(); InitializeScenes(); // ParticleCtrlEmissionDemoの初期化処理です。 InitializeParticleCtrlEmissionDemo(); bool isContinuing = true; while ( isContinuing ) { nw::demo::DebugUtility::AdvanceAutoTestFrame(); nw::demo::PadFactory::GetPad()->Update(); // ParticleCtrlEmissionDemoの定期処理です。 UpdateParticleCtrlEmissionDemo(); 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(); // ParticleCtrlEmissionDemoのレポートを表示します。 ReportParticleCtrlEmissionDemo(); 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; } } // ParticleCtrlEmissionDemoの終了処理です。 TerminateParticleCtrlEmissionDemo(); TerminateScenes(); } } // namespace /*!--------------------------------------------------------------------------* @brief メイン関数です。 *---------------------------------------------------------------------------*/ void nnMain() { nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator); nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE); nw::demo::PadFactory::Initialize(&s_DeviceAllocator); NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem) { InitializeGraphics(); s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator); DemoScene(); nw::ut::SafeDestroy(s_FlushCache); TerminateGraphics(); } nw::demo::PadFactory::Finalize(); nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator); nw::demo::FinalizeGraphicsSystem(); }