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