1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_Particle.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: 26050 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nw/ut.h>
17 #include <nw/gfx.h>
18 #include <nw/demo/demo_Particle.h>
19 
20 namespace nw
21 {
22 namespace demo
23 {
24 
25 NW_UT_RUNTIME_TYPEINFO_DEFINITION(ParticleNode, gfx::TransformNode);
26 
27 //----------------------------------------
ParticleNode(os::IAllocator * allocator,gfx::ResTransformNode resObj,const gfx::TransformNode::Description & description)28 ParticleNode::ParticleNode(
29     os::IAllocator* allocator,
30     gfx::ResTransformNode resObj,
31     const gfx::TransformNode::Description& description)
32 : gfx::TransformNode(allocator, resObj, description),
33   m_ModelInstances(allocator),
34   m_EmitterInstances(allocator)
35 {
36 
37 }
38 
39 //----------------------------------------
40 ParticleNode*
Create(os::IAllocator * allocator)41 ParticleNode::DynamicBuilder::Create(
42     os::IAllocator* allocator
43 )
44 {
45     NW_NULL_ASSERT(allocator);
46 
47     void* memory = allocator->Alloc(sizeof(ParticleNode));
48 
49     if (memory == NULL)
50     {
51         return NULL;
52     }
53 
54     ParticleNode* node = new(memory) ParticleNode(
55         allocator,
56         nw::gfx::ResTransformNode(),
57         m_Description);
58 
59     {
60         gfx::Result result = node->Initialize(allocator);
61         if (!result.IsSuccess())
62         {
63             SafeDestroy(node);
64             return NULL;
65         }
66     }
67 
68     return node;
69 }
70 
71 
72 //--------------------------------------------------------------------------
73 ParticleEffect*
Create(os::IAllocator * mainAllocator,os::IAllocator * deviceAllocator,bool autoAlocate,gfx::ParticleContext * particleContext)74 ParticleEffect::Create(os::IAllocator* mainAllocator,
75                        os::IAllocator* deviceAllocator,
76                        bool autoAlocate,
77                        gfx::ParticleContext* particleContext)
78 {
79     NW_NULL_ASSERT( mainAllocator );
80 
81     void* memory = mainAllocator->Alloc( sizeof(ParticleEffect) );
82     NW_ASSERT( memory != NULL );
83     ParticleEffect* particleEffect = new(memory) ParticleEffect(mainAllocator,
84                                                                 deviceAllocator,
85                                                                 autoAlocate,
86                                                                 particleContext);
87 
88     return particleEffect;
89 }
90 
91 
92 //--------------------------------------------------------------------------
93 void
Destroy()94 ParticleEffect::Destroy()
95 {
96     os::IAllocator* allocator = this->m_MainAllocator;
97 
98     NW_ASSERT( allocator != NULL );
99 
100     this->~ParticleEffect();
101     allocator->Free(this);
102 }
103 
104 
105 //----------------------------------------
106 void
Setup(gfx::ResGraphicsFile resource,bool useParticleMaterial)107 ParticleEffect::Setup(gfx::ResGraphicsFile resource, bool useParticleMaterial)
108 {
109     resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
110 
111     // TODO:パーティクルマテリアルをコミットしたら復帰する。
112     NW_UNUSED_VARIABLE(useParticleMaterial);
113 
114     // パーティクルマテリアルを使用します。
115     if (useParticleMaterial)
116     {
117         resource.ForeachModelMaterial(nw::gfx::ParticleMaterialFlagSetter());
118     }
119 
120     nw::gfx::Result result = resource.Setup(m_DeviceAllocator);
121 
122     if (result.IsFailure())
123     {
124         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
125     }
126 }
127 
128 //----------------------------------------
129 void
Register(gfx::ResGraphicsFile resource,const char ** nodeNames)130 ParticleEffect::Register(gfx::ResGraphicsFile resource, const char** nodeNames)
131 {
132     nw::gfx::ResModelArray models = resource.GetModels();
133     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
134     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
135         modelResource != modelsEnd; ++modelResource)
136     {
137         const char *resourceName = (*modelResource).GetName();
138 
139         const char** name = nodeNames;
140         bool find = false;
141         while (!find && *name != NULL)
142         {
143             if (strcmp(resourceName, *name) == 0)
144             {
145                 find = true;
146             }
147 
148             ++name;
149         }
150 
151         if (find)
152         {
153             m_ResModels.PushBack(nw::gfx::ResDynamicCast<nw::gfx::ResParticleModel>(*modelResource));
154         }
155     }
156 
157     nw::gfx::ResEmitterArray emitters = resource.GetEmitters();
158     for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
159         emitterResource != emitters.end(); ++emitterResource)
160     {
161         const char *resourceName = (*emitterResource).GetName();
162 
163         const char** name = nodeNames;
164         bool find = false;
165         while (!find && *name != NULL)
166         {
167             if (strcmp(resourceName, *name) == 0)
168             {
169                 find = true;
170             }
171 
172             ++name;
173         }
174 
175         if (find)
176         {
177             m_ResEmitters.PushBack(*emitterResource);
178         }
179     }
180 }
181 
182 
183 //----------------------------------------
184 void
Register(gfx::ResGraphicsFile resource)185 ParticleEffect::Register(gfx::ResGraphicsFile resource)
186 {
187     nw::gfx::ResModelArray models = resource.GetModels();
188     nw::gfx::ResModelArray::iterator modelsEnd = models.end();
189     for (nw::gfx::ResModelArray::iterator modelResource = models.begin();
190         modelResource != modelsEnd; ++modelResource)
191     {
192         nw::ut::ResTypeInfo resTypeInfo = (*modelResource).GetTypeInfo();
193         if ( resTypeInfo == nw::gfx::ResParticleModel::TYPE_INFO)
194         {
195             m_ResModels.PushBack(nw::gfx::ResDynamicCast<nw::gfx::ResParticleModel>(*modelResource));
196         }
197     }
198 
199     nw::gfx::ResEmitterArray emitters = resource.GetEmitters();
200     for (nw::gfx::ResEmitterArray::iterator emitterResource = emitters.begin();
201         emitterResource != emitters.end(); ++emitterResource)
202     {
203         m_ResEmitters.PushBack(*emitterResource);
204     }
205 }
206 
207 
208 ParticleNode*
Allocate()209 ParticleEffect::Allocate()
210 {
211     // トップノード生成
212     ParticleNode* top = ParticleNode::DynamicBuilder()
213         .MaxCallbacks(0)
214         .MaxChildren(this->m_ResModels.Size() + this->m_ResEmitters.Size())
215         .Create(this->m_MainAllocator);
216 
217     top->SetID(this->m_NextId++);
218 
219     nw::ut::MoveArray<nw::gfx::SceneNode*> sceneNodeArray(this->m_MainAllocator);
220 
221     // モデル生成
222     NW_FOREACH(const nw::gfx::ResParticleModel resModel, this->m_ResModels)
223     {
224         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
225             .Resource(resModel)
226             .CreateObject(this->m_MainAllocator, this->m_DeviceAllocator);
227 
228         nw::gfx::SceneNode* node = nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
229         sceneNodeArray.PushBack(node);
230 
231         nw::gfx::ParticleModel* model = nw::ut::DynamicCast<nw::gfx::ParticleModel*>(node);
232         top->RegisterParticleModel(model);
233     }
234 
235     // エミッタ生成
236     NW_FOREACH(const nw::gfx::ResParticleEmitter resEmitter, this->m_ResEmitters)
237     {
238         nw::gfx::SceneObject* sceneObject = nw::gfx::SceneBuilder()
239             .Resource(resEmitter)
240             .CreateObject(this->m_MainAllocator, this->m_DeviceAllocator);
241 
242         nw::gfx::SceneNode* node = nw::ut::DynamicCast<nw::gfx::SceneNode*>(sceneObject);
243         sceneNodeArray.PushBack(node);
244 
245         nw::gfx::ParticleEmitter* emitter = nw::ut::DynamicCast<nw::gfx::ParticleEmitter*>(node);
246         top->RegisterParticleEmitter(emitter);
247     }
248 
249     // 階層再構築
250     nw::gfx::SceneHelper::ResolveReference(sceneNodeArray);
251 
252     // パーティクルの参照解決・初期化
253     nw::gfx::ParticleUtil::SetupParticleObject(&sceneNodeArray, this->m_ParticleContext);
254 
255     // トップノードにアタッチ
256     NW_FOREACH(nw::gfx::SceneNode* node, sceneNodeArray)
257     {
258         if (node->GetParent() == NULL)
259         {
260             top->AttachChild(node);
261         }
262     }
263 
264     return top;
265 }
266 
267 void
DestroyParticleNode(ParticleNode * node)268 ParticleEffect::DestroyParticleNode(ParticleNode* node)
269 {
270     NW_NULL_ASSERT(node);
271 
272     nw::gfx::SafeDestroyBranch(node);
273 }
274 
275 } // namespace demo
276 } // namespace nw
277