1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ParticleModel.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: 25777 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/gfx/gfx_ParticleModel.h>
19 #include <nw/gfx/gfx_ParticleSet.h>
20 #include <nw/gfx/gfx_ParticleShape.h>
21 #include <nw/gfx/gfx_ISceneVisitor.h>
22 
23 #include <nw/ut/ut_ResUtil.h>
24 #include <nw/ut/ut_ResDictionary.h>
25 #include <nw/ut/ut_Foreach.h>
26 
27 namespace nw
28 {
29 namespace gfx
30 {
31 
32 NW_UT_RUNTIME_TYPEINFO_DEFINITION( ParticleModel, Model );
33 
34 //----------------------------------------
35 void
operator ()(const ParticleSet * particleSet)36 ParticleSetsAreEmpty::operator()(const ParticleSet* particleSet)
37 {
38     if (particleSet->GetParticleCollection()->GetCount() > 0)
39     {
40         *this->m_Result = false;
41     }
42 }
43 
44 //----------------------------------------
45 void
operator ()(ParticleSet * particleSet)46 ParticleSetsClear::operator()(ParticleSet* particleSet)
47 {
48     particleSet->ClearParticleCollection();
49 }
50 
51 //----------------------------------------
52 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResParticleModel resNode,const ParticleModel::Description & description)53 ParticleModel::GetMemorySizeInternal(
54     os::MemorySizeCalculator* pSize,
55     ResParticleModel resNode,
56     const ParticleModel::Description& description)
57 {
58     os::MemorySizeCalculator& size = *pSize;
59 
60     size += sizeof(ParticleModel);
61 
62     ParticleModel::GetMemorySizeForInitialize(
63         &size,
64         resNode,
65         description);
66 
67     int setCount = resNode.GetParticleSetsCount();
68     NW_ASSERT(setCount == resNode.GetShapesCount());
69     for (int i = 0; i < setCount; ++i)
70     {
71         nw::gfx::ResParticleSet resParticleSet = resNode.GetParticleSets(i);
72 
73         nw::gfx::ResParticleShape resParticleShape =
74             ResDynamicCast<ResParticleShape>(resNode.GetShapes(i));
75         NW_ASSERT(resParticleShape.IsValid());
76 
77         ParticleShape::GetMemorySizeInternal(
78             &size,
79             resParticleSet.GetParticleCollection().GetCapacity());
80 
81         ParticleSet::Description particleSetDescription;
82         particleSetDescription.maxCallbacks = 0;
83         particleSetDescription.maxChildren = 0;
84         particleSetDescription.isFixedSizeMemory = true;
85 
86         ParticleSet::GetMemorySizeInternal(
87             &size,
88             resParticleSet,
89             particleSetDescription);
90     }
91 }
92 
93 //----------------------------------------
94 void
GetDeviceMemorySizeInternal(os::MemorySizeCalculator * pSize,ResParticleModel resNode)95 ParticleModel::GetDeviceMemorySizeInternal(
96     os::MemorySizeCalculator* pSize,
97     ResParticleModel resNode)
98 {
99     os::MemorySizeCalculator& size = *pSize;
100 
101     int setCount = resNode.GetParticleSetsCount();
102     NW_ASSERT(setCount == resNode.GetShapesCount());
103     for (int i = 0; i < setCount; ++i)
104     {
105         nw::gfx::ResParticleSet resParticleSet = resNode.GetParticleSets(i);
106 
107         nw::gfx::ResParticleShape resParticleShape =
108             ResDynamicCast<ResParticleShape>(resNode.GetShapes(i));
109         NW_ASSERT(resParticleShape.IsValid());
110 
111         ParticleShape::GetDeviceMemorySizeInternal(
112             pSize, resParticleSet.GetParticleCollection().GetCapacity());
113 
114         ParticleSet::GetDeviceMemorySizeInternal(pSize, resParticleSet);
115     }
116 }
117 
118 //----------------------------------------
119 ParticleModel*
Create(SceneNode * parent,ResSceneObject resource,const ParticleModel::Description & modelDescription,os::IAllocator * mainAllocator,os::IAllocator * deviceAllocator)120 ParticleModel::Create(
121     SceneNode* parent,
122     ResSceneObject resource,
123     const ParticleModel::Description& modelDescription,
124     os::IAllocator* mainAllocator,
125     os::IAllocator* deviceAllocator
126 )
127 {
128     NW_NULL_ASSERT(mainAllocator);
129     NW_NULL_ASSERT(deviceAllocator);
130 
131     ResParticleModel resNode = ResDynamicCast<ResParticleModel>(resource);
132     NW_ASSERT(resNode.IsValid());
133 
134     void* memory = mainAllocator->Alloc(sizeof(ParticleModel));
135     if (memory == NULL)
136     {
137         return NULL;
138     }
139 
140     ParticleModel* node = new(memory) ParticleModel(
141         mainAllocator,
142         resNode,
143         modelDescription);
144 
145     {
146         Result result = node->Initialize(mainAllocator);
147         if (!result.IsSuccess())
148         {
149             SafeDestroy(node);
150             return NULL;
151         }
152     }
153 
154     bool isSuccess = true;
155 
156     int setCount = resNode.GetParticleSetsCount();
157     NW_ASSERT(setCount == resNode.GetShapesCount());
158     for (int i = 0; i < setCount; ++i)
159     {
160         nw::gfx::ResParticleSet resParticleSet = resNode.GetParticleSets(i);
161 
162         nw::gfx::ResParticleShape resParticleShape =
163             ResDynamicCast<ResParticleShape>(resNode.GetShapes(i));
164         NW_ASSERT(resParticleShape.IsValid());
165 
166         ParticleShape* shapeNode = ParticleShape::Create(
167             resParticleShape,
168             resParticleSet.GetParticleCollection().GetCapacity(),
169             mainAllocator,
170             deviceAllocator);
171 
172         if (shapeNode == NULL)
173         {
174             isSuccess = false;
175             break;
176         }
177 
178         node->AttachParticleShape(shapeNode);
179 
180         ParticleSet::Description description;
181         description.maxCallbacks = 0;
182         description.maxChildren = 0;
183         description.isFixedSizeMemory = true;
184 
185         ParticleSet* setNode = ParticleSet::Create(
186             node,
187             resParticleSet,
188             description,
189             mainAllocator,
190             deviceAllocator,
191             shapeNode);
192 
193         if (setNode == NULL)
194         {
195             isSuccess = false;
196             break;
197         }
198 
199         node->AttachParticleSet(setNode);
200     }
201 
202     if (isSuccess == false)
203     {
204         for (int i = 0; i < node->m_MaximumParticleSet; ++i) // TBD
205         {
206             if (node->m_ParticleSets[i] != NULL)
207             {
208                 SafeDestroy(node->m_ParticleSets[i]);
209                 node->m_ParticleSets[i] = NULL;
210             }
211         }
212 
213         SafeDestroy(node);
214         return NULL;
215     }
216 
217     if (parent)
218     {
219         bool result = parent->AttachChild(node);
220         NW_ASSERT(result);
221     }
222 
223     return node;
224 }
225 
226 //----------------------------------------
227 void
Accept(ISceneVisitor * visitor)228 ParticleModel::Accept(
229     ISceneVisitor* visitor
230 )
231 {
232     visitor->VisitParticleModel(this);
233     AcceptChildren(visitor);
234 }
235 
236 void
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,ResParticleModel resource,const ParticleModel::Description & description)237 ParticleModel::GetMemorySizeForInitialize(
238     os::MemorySizeCalculator* pSize,
239     ResParticleModel resource,
240     const ParticleModel::Description& description)
241 {
242     os::MemorySizeCalculator& size = *pSize;
243 
244     Model::GetMemorySizeForInitialize(pSize, resource, description);
245 
246     size += sizeof(ParticleSet*) * description.particleSetCount;
247     size += sizeof(ParticleShape*) * description.particleSetCount;
248 }
249 
250 //----------------------------------------
251 Result
Initialize(os::IAllocator * allocator)252 ParticleModel::Initialize(os::IAllocator* allocator)
253 {
254     Result result = INITIALIZE_RESULT_OK;
255 
256     result |= Model::Initialize(allocator);
257     NW_ENSURE_AND_RETURN(result);
258 
259     if (m_MaximumParticleSet != 0)
260     {
261         void* memory = allocator->Alloc(sizeof(ParticleSet*) * m_MaximumParticleSet);
262         if (!memory)
263         {
264             result |= Result::MASK_FAIL_BIT;
265         }
266         NW_ENSURE_AND_RETURN(result);
267 
268         m_ParticleSets = ut::MoveArray<ParticleSet*>(memory, m_MaximumParticleSet, allocator);
269         m_ParticleSets.Resize(m_MaximumParticleSet);
270         for (int i = 0; i < m_ParticleSets.size(); ++i)
271         {
272             m_ParticleSets[i] = NULL;
273         }
274     }
275 
276     if (m_MaximumParticleSet != 0)
277     {
278         void* memory = allocator->Alloc(sizeof(ParticleShape*) * m_MaximumParticleSet);
279         if (!memory)
280         {
281             result |= Result::MASK_FAIL_BIT;
282         }
283         NW_ENSURE_AND_RETURN(result);
284 
285         m_ParticleShapes = ut::MoveArray<ParticleShape*>(memory, m_MaximumParticleSet, allocator);
286         m_ParticleShapes.Resize(m_MaximumParticleSet);
287         for (int i = 0; i < m_ParticleShapes.size(); ++i)
288         {
289             m_ParticleShapes[i] = NULL;
290         }
291     }
292 
293     return result;
294 
295 }
296 
297 } // namespace gfx
298 } // namespace nw
299