1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ParticleUtil.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_ParticleUtil.h>
19 
20 namespace nw
21 {
22 namespace gfx
23 {
24 
25 // パーティクルセットを探します。
26 ParticleSet*
FindParticleSet(const char * name,ut::MoveArray<SceneNode * > * sceneNodeArray)27 FindParticleSet(
28     const char* name,
29     ut::MoveArray<SceneNode*>* sceneNodeArray
30 )
31 {
32     for (ut::MoveArray<SceneNode*>::iterator i = sceneNodeArray->Begin();
33         i != sceneNodeArray->End();
34         ++i)
35     {
36         ParticleModel* particleModel = ut::DynamicCast<ParticleModel*>(*i);
37         if (!particleModel) { continue; }
38 
39         for (int j = 0; j < (int)particleModel->GetParticleSetsCount(); ++j)
40         {
41             ParticleSet* itParticleSet = particleModel->GetParticleSets(j);
42             NW_NULL_ASSERT(itParticleSet);
43 
44             const char* itParticleSetName= itParticleSet->GetResParticleSet().GetName();
45 
46             if (std::strcmp(itParticleSetName, name) == 0)
47             {
48                 return itParticleSet;
49             }
50         }
51     }
52 
53     return NULL;
54 }
55 
56 void
SetupParticleObject(ut::MoveArray<SceneNode * > * sceneNodeArray,ParticleContext * particleContext)57 ParticleUtil::SetupParticleObject(
58     ut::MoveArray<SceneNode*>* sceneNodeArray,
59     ParticleContext* particleContext
60 )
61 {
62     NW_NULL_ASSERT(sceneNodeArray);
63     NW_NULL_ASSERT(particleContext);
64 
65     ResolveParticleObject(sceneNodeArray);
66 
67     NW_FOREACH(SceneNode* node, *sceneNodeArray)
68     {
69         ResSceneNode resSceneNode = node->GetResSceneNode();
70         NW_ASSERT(resSceneNode.IsValid());
71 
72         switch (resSceneNode.ptr()->typeInfo)
73         {
74         case ResParticleModel::TYPE_INFO:
75             {
76                 ParticleModel* model = static_cast<ParticleModel*>(node);
77                 NW_NULL_ASSERT(model);
78 
79                 for (u32 i = 0; i < model->GetParticleSetsCount(); ++i)
80                 {
81                     ParticleSet* particleSet = model->GetParticleSets(i);
82                     NW_NULL_ASSERT(particleSet);
83 
84                     particleSet->Srand(particleContext->GetRandom());
85                 }
86             }
87             break;
88         case ResParticleEmitter::TYPE_INFO:
89             {
90                 ParticleEmitter* emitter = static_cast<ParticleEmitter*>(node);
91                 NW_NULL_ASSERT(emitter);
92 
93                 emitter->Srand(particleContext->GetRandom());
94             }
95         }
96     }
97 }
98 
99 void
ResolveParticleObject(ut::MoveArray<SceneNode * > * sceneNodeArray)100 ParticleUtil::ResolveParticleObject(
101     ut::MoveArray<SceneNode*>* sceneNodeArray
102 )
103 {
104     NW_NULL_ASSERT(sceneNodeArray);
105 
106     NW_FOREACH(SceneNode* node, *sceneNodeArray)
107     {
108         ResSceneNode resSceneNode = node->GetResSceneNode();
109         NW_ASSERT(resSceneNode.IsValid());
110 
111         switch (resSceneNode.ptr()->typeInfo)
112         {
113         case ResParticleModel::TYPE_INFO:
114             {
115                 ParticleModel* model = static_cast<ParticleModel*>(node);
116                 NW_NULL_ASSERT(model);
117 
118                 for (u32 i = 0; i < model->GetParticleSetsCount(); ++i)
119                 {
120                     ParticleSet* particleSet = model->GetParticleSets(i);
121                     NW_NULL_ASSERT(particleSet);
122 
123                     ut::MoveArray<ParticleSet::Updater>* updaters =
124                         particleSet->GetUpdaters();
125                     NW_NULL_ASSERT(updaters);
126 
127                     ut::MoveArray<ParticleSet::Updater>::iterator endIter = updaters->end();
128                     for (ut::MoveArray<ParticleSet::Updater>::iterator iter = updaters->begin();
129                         iter != endIter;)
130                     {
131                         ParticleSet::Updater& updater = *iter++;
132 
133                         ResParticleUpdater resUpdater(updater.resource);
134                         NW_ASSERT(resUpdater.IsValid());
135 
136                         if (resUpdater.GetTypeInfo() == ResParticleChildUpdater::TYPE_INFO)
137                         {
138                             ResParticleChildUpdater childUpdater =
139                                 ResDynamicCast<ResParticleChildUpdater>(resUpdater);
140 
141                             const char* particleSetPath = childUpdater.GetParticleSetPath();
142 
143                             ParticleSet* childParticleSet =
144                                 FindParticleSet(particleSetPath, sceneNodeArray);
145                             if (childParticleSet != NULL)
146                             {
147                                 updater.work = (u32)childParticleSet;
148                             }
149                         }
150                     }
151                 }
152             }
153             break;
154         case ResParticleEmitter::TYPE_INFO:
155             {
156                 ParticleEmitter* emitter = static_cast<ParticleEmitter*>(node);
157                 NW_NULL_ASSERT(emitter);
158 
159                 ResParticleEmitter resource = emitter->GetResParticleEmitter();
160                 if (resource.IsValid())
161                 {
162                     ParticleSet* particleSet =
163                         FindParticleSet(resource.GetParticleSetPath(), sceneNodeArray);
164 
165                     emitter->SetParticleSet(particleSet);
166                 }
167             }
168             break;
169         }
170     }
171 }
172 
173 bool
operator ()(const ParticleSet * lhs,const ParticleSet * rhs)174 ParticleSetCompare::operator() (
175         const ParticleSet* lhs,
176         const ParticleSet* rhs)
177 {
178     if (rhs == NULL)
179     {
180         return true;
181     }
182 
183     if (lhs == NULL)
184     {
185         return false;
186     }
187 
188     const ResParticleSet& lhsResource = lhs->GetResParticleSet();
189     const ResParticleSet& rhsResource = rhs->GetResParticleSet();
190     return lhsResource.GetParticleSetPriority() < rhsResource.GetParticleSetPriority();
191 }
192 
193 void
GetMemorySizeForDuplicateResParticleInitializerInternal(os::MemorySizeCalculator * pSize,const ResParticleInitializer * src)194 ParticleUtil::GetMemorySizeForDuplicateResParticleInitializerInternal(
195     os::MemorySizeCalculator* pSize,
196     const ResParticleInitializer* src)
197 {
198     os::MemorySizeCalculator& size = *pSize;
199 
200     int baseSize = 0;
201 
202     switch (src->GetTypeInfo())
203     {
204     case ResParticleInitializer::TYPE_INFO:
205         baseSize += sizeof(ResParticleInitializerData);
206         break;
207     case ResParticleDirectionalVelocityInitializer::TYPE_INFO:
208         baseSize += sizeof(ResParticleDirectionalVelocityInitializerData);
209         break;
210     case ResParticleRandomDirectionalVelocityInitializer::TYPE_INFO:
211         baseSize += sizeof(ResParticleRandomDirectionalVelocityInitializerData);
212         break;
213     case ResParticleOriginVelocityInitializer::TYPE_INFO:
214         baseSize += sizeof(ResParticleOriginVelocityInitializerData);
215         break;
216     case ResParticleRandomVelocityInitializer::TYPE_INFO:
217         baseSize += sizeof(ResParticleRandomVelocityInitializerData);
218         break;
219     case ResParticleYAxisVelocityInitializer::TYPE_INFO:
220         baseSize += sizeof(ResParticleYAxisVelocityInitializerData);
221         break;
222     case ResParticleVector3ImmediateInitializer::TYPE_INFO:
223         baseSize += sizeof(ResParticleVector3ImmediateInitializerData);
224         break;
225     case ResParticleFloatRandomInitializer::TYPE_INFO:
226         baseSize += sizeof(ResParticleFloatRandomInitializerData);
227         break;
228     case ResParticleFloatRangeRandomInitializer::TYPE_INFO:
229         baseSize += sizeof(ResParticleFloatRangeRandomInitializerData);
230         break;
231     case ResParticleFloatImmediateInitializer::TYPE_INFO:
232         baseSize += sizeof(ResParticleFloatImmediateInitializerData);
233         break;
234     case ResParticleVector2ImmediateInitializer::TYPE_INFO:
235         baseSize += sizeof(ResParticleVector2ImmediateInitializerData);
236         break;
237     case ResParticleVector3Random1Initializer::TYPE_INFO:
238         baseSize += sizeof(ResParticleVector3Random1InitializerData);
239         break;
240     case ResParticleVector3Random3Initializer::TYPE_INFO:
241         baseSize += sizeof(ResParticleVector3Random3InitializerData);
242         break;
243     case ResParticleVector3MultRandomInitializer::TYPE_INFO:
244         baseSize += sizeof(ResParticleVector3MultRandomInitializerData);
245         break;
246     default:
247         NW_FATAL_ERROR("unknown initializer type");
248     }
249 
250     size.Add(baseSize, 4);
251 }
252 
253 ResParticleInitializerData*
DuplicateResParticleInitializer(const ResParticleInitializer * src,os::IAllocator * allocator)254 ParticleUtil::DuplicateResParticleInitializer(
255     const ResParticleInitializer* src,
256     os::IAllocator* allocator
257 )
258 {
259     NW_NULL_ASSERT(src);
260     NW_NULL_ASSERT(allocator);
261 
262     int baseSize = 0;
263     int size = 0;
264 
265     switch (src->GetTypeInfo())
266     {
267     case ResParticleInitializer::TYPE_INFO:
268         baseSize += sizeof(ResParticleInitializerData);
269         break;
270     case ResParticleDirectionalVelocityInitializer::TYPE_INFO:
271         baseSize += sizeof(ResParticleDirectionalVelocityInitializerData);
272         break;
273     case ResParticleRandomDirectionalVelocityInitializer::TYPE_INFO:
274         baseSize += sizeof(ResParticleRandomDirectionalVelocityInitializerData);
275         break;
276     case ResParticleOriginVelocityInitializer::TYPE_INFO:
277         baseSize += sizeof(ResParticleOriginVelocityInitializerData);
278         break;
279     case ResParticleRandomVelocityInitializer::TYPE_INFO:
280         baseSize += sizeof(ResParticleRandomVelocityInitializerData);
281         break;
282     case ResParticleYAxisVelocityInitializer::TYPE_INFO:
283         baseSize += sizeof(ResParticleYAxisVelocityInitializerData);
284         break;
285     case ResParticleVector3ImmediateInitializer::TYPE_INFO:
286         baseSize += sizeof(ResParticleVector3ImmediateInitializerData);
287         break;
288     case ResParticleFloatRandomInitializer::TYPE_INFO:
289         baseSize += sizeof(ResParticleFloatRandomInitializerData);
290         break;
291     case ResParticleFloatRangeRandomInitializer::TYPE_INFO:
292         baseSize += sizeof(ResParticleFloatRangeRandomInitializerData);
293         break;
294     case ResParticleFloatImmediateInitializer::TYPE_INFO:
295         baseSize += sizeof(ResParticleFloatImmediateInitializerData);
296         break;
297     case ResParticleVector2ImmediateInitializer::TYPE_INFO:
298         baseSize += sizeof(ResParticleVector2ImmediateInitializerData);
299         break;
300     case ResParticleVector3Random1Initializer::TYPE_INFO:
301         baseSize += sizeof(ResParticleVector3Random1InitializerData);
302         break;
303     case ResParticleVector3Random3Initializer::TYPE_INFO:
304         baseSize += sizeof(ResParticleVector3Random3InitializerData);
305         break;
306     case ResParticleVector3MultRandomInitializer::TYPE_INFO:
307         baseSize += sizeof(ResParticleVector3MultRandomInitializerData);
308         break;
309     default:
310         NW_FATAL_ERROR("unknown initializer type");
311     }
312 
313     size += ut::RoundUp(baseSize, 4);
314 
315     void* memory = allocator->Alloc(size, 4);
316     if (memory == NULL)
317     {
318         return NULL;
319     }
320 
321     {
322         u8* dstPtr = (u8*)memory;
323 
324         ResParticleInitializerData* dstData =
325             reinterpret_cast<ResParticleInitializerData*>(dstPtr);
326         const ResParticleInitializerData* srcData = src->ptr();
327 
328         ::std::memcpy(dstPtr, srcData, baseSize);
329         dstPtr += ut::RoundUp(baseSize, 4);
330     }
331 
332     switch (src->GetTypeInfo())
333     {
334     case ResParticleInitializer::TYPE_INFO:
335     case ResParticleDirectionalVelocityInitializer::TYPE_INFO:
336     case ResParticleRandomDirectionalVelocityInitializer::TYPE_INFO:
337     case ResParticleOriginVelocityInitializer::TYPE_INFO:
338     case ResParticleRandomVelocityInitializer::TYPE_INFO:
339     case ResParticleYAxisVelocityInitializer::TYPE_INFO:
340     case ResParticleVector3ImmediateInitializer::TYPE_INFO:
341     case ResParticleFloatRandomInitializer::TYPE_INFO:
342     case ResParticleFloatRangeRandomInitializer::TYPE_INFO:
343     case ResParticleFloatImmediateInitializer::TYPE_INFO:
344     case ResParticleVector2ImmediateInitializer::TYPE_INFO:
345     case ResParticleVector3Random1Initializer::TYPE_INFO:
346     case ResParticleVector3Random3Initializer::TYPE_INFO:
347     case ResParticleVector3MultRandomInitializer::TYPE_INFO:
348         // PRIMITIVEしかないので何もしなくてよい
349         break;
350     default:
351         NW_FATAL_ERROR("unknown initializer type");
352     }
353 
354     return reinterpret_cast<ResParticleInitializerData*>(memory);
355 }
356 
357 void
GetMemorySizeForDuplicateResParticleUpdaterInternal(os::MemorySizeCalculator * pSize,const ResParticleUpdater * src)358 ParticleUtil::GetMemorySizeForDuplicateResParticleUpdaterInternal(
359     os::MemorySizeCalculator* pSize,
360     const ResParticleUpdater* src)
361 {
362     int baseSize = 0;
363     os::MemorySizeCalculator& size = *pSize;
364     int childStrSize = 0;
365     int childFormSize = 0;
366     int childOptionSize  = 0;
367 
368     switch (src->GetTypeInfo())
369     {
370     case ResParticleUpdater::TYPE_INFO:
371         baseSize = sizeof(ResParticleUpdaterData);
372         break;
373     case ResParticleAccelarationUpdater::TYPE_INFO:
374         baseSize = sizeof(ResParticleAccelarationUpdaterData);
375         break;
376     case ResParticleGeneralUpdater::TYPE_INFO:
377         baseSize = sizeof(ResParticleGeneralUpdaterData);
378         break;
379     case ResParticleGravityUpdater::TYPE_INFO:
380         baseSize = sizeof(ResParticleGravityUpdaterData);
381         break;
382     case ResParticleSpinUpdater::TYPE_INFO:
383         baseSize = sizeof(ResParticleSpinUpdaterData);
384         break;
385     case ResParticleRandomUpdater::TYPE_INFO:
386         baseSize = sizeof(ResParticleRandomUpdaterData);
387         break;
388     case ResParticleChildUpdater::TYPE_INFO:
389         baseSize = sizeof(ResParticleChildUpdaterData);
390         {
391             const ResParticleChildUpdater& child = ResDynamicCast<ResParticleChildUpdater>(*src);
392             NW_ASSERT(child.IsValid());
393 
394             childStrSize = strlen(child.GetParticleSetPath()) + 1;
395 
396             const ResParticleForm& form = child.GetParticleForm();
397             const ResParticleChildUpdaterOption& option = child.GetTiming();
398 
399             if (form.IsValid())
400             {
401                 switch (form.GetTypeInfo())
402                 {
403                 case ResParticleForm::TYPE_INFO:
404                     childFormSize = sizeof(ResParticleFormData);
405                     break;
406                 case ResParticleCubeForm::TYPE_INFO:
407                     childFormSize = sizeof(ResParticleCubeFormData);
408                     break;
409                 case ResParticleCylinderForm::TYPE_INFO:
410                     childFormSize = sizeof(ResParticleCylinderFormData);
411                     break;
412                 case ResParticleDiscForm::TYPE_INFO:
413                     childFormSize = sizeof(ResParticleDiscFormData);
414                     break;
415                 case ResParticlePointForm::TYPE_INFO:
416                     childFormSize = sizeof(ResParticlePointFormData);
417                     break;
418                 case ResParticleRectangleForm::TYPE_INFO:
419                     childFormSize = sizeof(ResParticleRectangleFormData);
420                     break;
421                 case ResParticleSphereForm::TYPE_INFO:
422                     childFormSize = sizeof(ResParticleSphereFormData);
423                     break;
424                 default:
425                     NW_FATAL_ERROR("unknown form type");
426                 }
427             }
428 
429             if (option.IsValid())
430             {
431                 switch (option.GetTypeInfo())
432                 {
433                 case ResParticleChildUpdaterFinalUpdateOption::TYPE_INFO:
434                     childOptionSize = sizeof(ResParticleChildUpdaterFinalUpdateOptionData);
435                     break;
436                 case ResParticleChildUpdaterFirstUpdateOption::TYPE_INFO:
437                     childOptionSize = sizeof(ResParticleChildUpdaterFirstUpdateOptionData);
438                     break;
439                 case ResParticleChildUpdaterIntervalOption::TYPE_INFO:
440                     childOptionSize = sizeof(ResParticleChildUpdaterIntervalOptionData);
441                     break;
442                 default:
443                     NW_FATAL_ERROR("unknown updateOption type");
444                 }
445             }
446         }
447         break;
448     case ResParticleUserUpdater::TYPE_INFO:
449         baseSize = sizeof(ResParticleUserUpdaterData);
450         break;
451     case ResParticleVector2ImmediateUpdater::TYPE_INFO:
452         baseSize = sizeof(ResParticleVector2ImmediateUpdaterData);
453         break;
454     case ResParticleVector3Updater::TYPE_INFO:
455         baseSize = sizeof(ResParticleVector3UpdaterData);
456         break;
457     case ResParticleFloatUpdater::TYPE_INFO:
458         baseSize = sizeof(ResParticleFloatUpdaterData);
459         break;
460     case ResParticleRotateUpVectorUpdater::TYPE_INFO:
461         baseSize = sizeof(ResParticleRotateUpVectorUpdaterData);
462         break;
463     case ResParticleTexturePatternUpdater::TYPE_INFO:
464         baseSize = sizeof(ResParticleTexturePatternUpdaterData);
465         break;
466     case ResParticleVector3ImmediateUpdater::TYPE_INFO:
467         baseSize = sizeof(ResParticleVector3ImmediateUpdaterData);
468         break;
469     case ResParticleVector3AdditiveUpdater::TYPE_INFO:
470         baseSize = sizeof(ResParticleVector3AdditiveUpdaterData);
471         break;
472     case ResParticleVector3RandomAdditiveUpdater::TYPE_INFO:
473         baseSize = sizeof(ResParticleVector3RandomAdditiveUpdaterData);
474         break;
475     case ResParticleFloatImmediateUpdater::TYPE_INFO:
476         baseSize = sizeof(ResParticleFloatImmediateUpdaterData);
477         break;
478     default:
479         NW_FATAL_ERROR("unknown updater type");
480         break;
481     }
482 
483     // アニメーションのサイズ計算
484     int animationSize = 0;
485     int enabledSize = 0;
486     int dataSize = 0;
487     int animationOptionSize = 0;
488     {
489         const ResParticleAnimation& resAnimation = src->GetParticleAnimation();
490         if (resAnimation.IsValid())
491         {
492             animationSize += sizeof(ResParticleAnimationData);
493 
494             enabledSize = resAnimation.GetAnimationEnabledCount() * sizeof(bool);
495             dataSize = resAnimation.GetAnimationDataCount() * sizeof(s32);
496 
497             const ResParticleAnimationOption& option =
498                 resAnimation.GetParticleAnimationOption();
499             if (option.IsValid())
500             {
501                 switch (option.GetTypeInfo())
502                 {
503                 case ResParticleAnimationOption::TYPE_INFO:
504                     animationOptionSize = sizeof(ResParticleAnimationOptionData);
505                     break;
506                 case ResParticleFittingAnimationOption::TYPE_INFO:
507                     animationOptionSize = sizeof(ResParticleFittingAnimationOptionData);
508                     break;
509                 case ResParticleFrameLoopAnimationOption::TYPE_INFO:
510                     animationOptionSize = sizeof(ResParticleFrameLoopAnimationOptionData);
511                     break;
512                 case ResParticleRandomAnimationOption::TYPE_INFO:
513                     animationOptionSize = sizeof(ResParticleRandomAnimationOptionData);
514                     break;
515                 default:
516                     NW_FATAL_ERROR("unknown animationOption type");
517                 }
518             }
519 
520             animationSize +=
521                 resAnimation.GetAnimationEnabledCount() * sizeof(u32);
522             animationSize +=
523                 resAnimation.GetAnimationDataCount() * sizeof(u32);
524         }
525     }
526 
527     size.Add(baseSize, 4);
528     size.Add(animationSize, 4);
529     size.Add(enabledSize, 4);
530     size.Add(dataSize, 4);
531     size.Add(animationOptionSize, 4);
532     size.Add(childStrSize, 4);
533     size.Add(childFormSize, 4);
534     size.Add(childOptionSize, 4);
535 }
536 
537 ResParticleUpdaterData*
DuplicateResParticleUpdater(const ResParticleUpdater * src,os::IAllocator * allocator)538 ParticleUtil::DuplicateResParticleUpdater(
539     const ResParticleUpdater* src,
540     os::IAllocator* allocator
541 )
542 {
543     NW_NULL_ASSERT(src);
544     NW_NULL_ASSERT(allocator);
545 
546     int baseSize = 0;
547     int size = 0;
548     int childStrSize = 0;
549     int childFormSize = 0;
550     int childOptionSize  = 0;
551 
552     switch (src->GetTypeInfo())
553     {
554     case ResParticleUpdater::TYPE_INFO:
555         baseSize = sizeof(ResParticleUpdaterData);
556         break;
557     case ResParticleAccelarationUpdater::TYPE_INFO:
558         baseSize = sizeof(ResParticleAccelarationUpdaterData);
559         break;
560     case ResParticleGeneralUpdater::TYPE_INFO:
561         baseSize = sizeof(ResParticleGeneralUpdaterData);
562         break;
563     case ResParticleGravityUpdater::TYPE_INFO:
564         baseSize = sizeof(ResParticleGravityUpdaterData);
565         break;
566     case ResParticleSpinUpdater::TYPE_INFO:
567         baseSize = sizeof(ResParticleSpinUpdaterData);
568         break;
569     case ResParticleRandomUpdater::TYPE_INFO:
570         baseSize = sizeof(ResParticleRandomUpdaterData);
571         break;
572     case ResParticleChildUpdater::TYPE_INFO:
573         baseSize = sizeof(ResParticleChildUpdaterData);
574         {
575             const ResParticleChildUpdater& child = ResDynamicCast<ResParticleChildUpdater>(*src);
576             NW_ASSERT(child.IsValid());
577 
578             childStrSize = strlen(child.GetParticleSetPath()) + 1;
579 
580             const ResParticleForm& form = child.GetParticleForm();
581             const ResParticleChildUpdaterOption& option = child.GetTiming();
582 
583             if (form.IsValid())
584             {
585                 switch (form.GetTypeInfo())
586                 {
587                 case ResParticleForm::TYPE_INFO:
588                     childFormSize = sizeof(ResParticleFormData);
589                     break;
590                 case ResParticleCubeForm::TYPE_INFO:
591                     childFormSize = sizeof(ResParticleCubeFormData);
592                     break;
593                 case ResParticleCylinderForm::TYPE_INFO:
594                     childFormSize = sizeof(ResParticleCylinderFormData);
595                     break;
596                 case ResParticleDiscForm::TYPE_INFO:
597                     childFormSize = sizeof(ResParticleDiscFormData);
598                     break;
599                 case ResParticlePointForm::TYPE_INFO:
600                     childFormSize = sizeof(ResParticlePointFormData);
601                     break;
602                 case ResParticleRectangleForm::TYPE_INFO:
603                     childFormSize = sizeof(ResParticleRectangleFormData);
604                     break;
605                 case ResParticleSphereForm::TYPE_INFO:
606                     childFormSize = sizeof(ResParticleSphereFormData);
607                     break;
608                 default:
609                     NW_FATAL_ERROR("unknown form type");
610                 }
611             }
612 
613             if (option.IsValid())
614             {
615                 switch (option.GetTypeInfo())
616                 {
617                 case ResParticleChildUpdaterFinalUpdateOption::TYPE_INFO:
618                     childOptionSize = sizeof(ResParticleChildUpdaterFinalUpdateOptionData);
619                     break;
620                 case ResParticleChildUpdaterFirstUpdateOption::TYPE_INFO:
621                     childOptionSize = sizeof(ResParticleChildUpdaterFirstUpdateOptionData);
622                     break;
623                 case ResParticleChildUpdaterIntervalOption::TYPE_INFO:
624                     childOptionSize = sizeof(ResParticleChildUpdaterIntervalOptionData);
625                     break;
626                 default:
627                     NW_FATAL_ERROR("unknown updateOption type");
628                 }
629             }
630         }
631         break;
632     case ResParticleUserUpdater::TYPE_INFO:
633         baseSize = sizeof(ResParticleUserUpdaterData);
634         break;
635     case ResParticleVector2ImmediateUpdater::TYPE_INFO:
636         baseSize = sizeof(ResParticleVector2ImmediateUpdaterData);
637         break;
638     case ResParticleVector3Updater::TYPE_INFO:
639         baseSize = sizeof(ResParticleVector3UpdaterData);
640         break;
641     case ResParticleFloatUpdater::TYPE_INFO:
642         baseSize = sizeof(ResParticleFloatUpdaterData);
643         break;
644     case ResParticleRotateUpVectorUpdater::TYPE_INFO:
645         baseSize = sizeof(ResParticleRotateUpVectorUpdaterData);
646         break;
647     case ResParticleTexturePatternUpdater::TYPE_INFO:
648         baseSize = sizeof(ResParticleTexturePatternUpdaterData);
649         break;
650     case ResParticleVector3ImmediateUpdater::TYPE_INFO:
651         baseSize = sizeof(ResParticleVector3ImmediateUpdaterData);
652         break;
653     case ResParticleVector3AdditiveUpdater::TYPE_INFO:
654         baseSize = sizeof(ResParticleVector3AdditiveUpdaterData);
655         break;
656     case ResParticleVector3RandomAdditiveUpdater::TYPE_INFO:
657         baseSize = sizeof(ResParticleVector3RandomAdditiveUpdaterData);
658         break;
659     case ResParticleFloatImmediateUpdater::TYPE_INFO:
660         baseSize = sizeof(ResParticleFloatImmediateUpdaterData);
661         break;
662     default:
663         NW_FATAL_ERROR("unknown updater type");
664         break;
665     }
666 
667     // アニメーションのサイズ計算
668     int animationSize = 0;
669     int enabledSize = 0;
670     int dataSize = 0;
671     int animationOptionSize = 0;
672     {
673         const ResParticleAnimation& resAnimation = src->GetParticleAnimation();
674         if (resAnimation.IsValid())
675         {
676             animationSize += sizeof(ResParticleAnimationData);
677 
678             enabledSize = resAnimation.GetAnimationEnabledCount() * sizeof(bool);
679             dataSize = resAnimation.GetAnimationDataCount() * sizeof(s32);
680 
681             const ResParticleAnimationOption& option =
682                 resAnimation.GetParticleAnimationOption();
683             if (option.IsValid())
684             {
685                 switch (option.GetTypeInfo())
686                 {
687                 case ResParticleAnimationOption::TYPE_INFO:
688                     animationOptionSize = sizeof(ResParticleAnimationOptionData);
689                     break;
690                 case ResParticleFittingAnimationOption::TYPE_INFO:
691                     animationOptionSize = sizeof(ResParticleFittingAnimationOptionData);
692                     break;
693                 case ResParticleFrameLoopAnimationOption::TYPE_INFO:
694                     animationOptionSize = sizeof(ResParticleFrameLoopAnimationOptionData);
695                     break;
696                 case ResParticleRandomAnimationOption::TYPE_INFO:
697                     animationOptionSize = sizeof(ResParticleRandomAnimationOptionData);
698                     break;
699                 default:
700                     NW_FATAL_ERROR("unknown animationOption type");
701                 }
702             }
703 
704             animationSize +=
705                 resAnimation.GetAnimationEnabledCount() * sizeof(u32);
706             animationSize +=
707                 resAnimation.GetAnimationDataCount() * sizeof(u32);
708         }
709     }
710 
711     size += ut::RoundUp(baseSize, 4);
712     size += ut::RoundUp(animationSize, 4);
713     size += ut::RoundUp(enabledSize, 4);
714     size += ut::RoundUp(dataSize, 4);
715     size += ut::RoundUp(animationOptionSize, 4);
716     size += ut::RoundUp(childStrSize, 4);
717     size += ut::RoundUp(childFormSize, 4);
718     size += ut::RoundUp(childOptionSize, 4);
719 
720     void* memory = allocator->Alloc(size, 4);
721     if (memory == NULL)
722     {
723         return NULL;
724     }
725 
726     u8* dstPtr = (u8*)memory;
727 
728     ResParticleUpdaterData* dstData =
729         reinterpret_cast<ResParticleUpdaterData*>(dstPtr);
730 
731     {
732         const ResParticleUpdaterData* srcData = src->ptr();
733         ::std::memcpy(dstPtr, srcData, baseSize);
734         dstPtr += ut::RoundUp(baseSize, 4);
735     }
736 
737     if (animationSize != 0)
738     {
739         const ResParticleAnimation& animation = src->GetParticleAnimation();
740 
741         ResParticleAnimationData* dstAnimation =
742             reinterpret_cast<ResParticleAnimationData*>(dstPtr);
743 
744         ::std::memcpy(
745             dstPtr,
746             animation.ptr(),
747             animationSize);
748         dstData->toParticleAnimation.set_ptr(dstPtr);
749         dstPtr += ut::RoundUp(animationSize, 4);
750 
751         if (enabledSize > 0)
752         {
753             ::std::memcpy(
754                 dstPtr,
755                 animation.GetAnimationEnabled(),
756                 enabledSize);
757             dstAnimation->toAnimationEnabledTable.set_ptr(dstPtr);
758             dstPtr += ut::RoundUp(enabledSize, 4);
759         }
760 
761         if (dataSize > 0)
762         {
763             ::std::memcpy(
764                 dstPtr,
765                 animation.GetAnimationData(),
766                 dataSize);
767             dstAnimation->toAnimationDataTable.set_ptr(dstPtr);
768             dstPtr += ut::RoundUp(dataSize, 4);
769         }
770 
771         if (animationOptionSize != 0)
772         {
773             const ResParticleAnimationOption& option = animation.GetParticleAnimationOption();
774 
775             ::std::memcpy(
776                 dstPtr,
777                 option.ptr(),
778                 animationOptionSize);
779             dstAnimation->toParticleAnimationOption.set_ptr(dstPtr);
780             dstPtr += ut::RoundUp(animationOptionSize, 4);
781         }
782     }
783 
784     switch (src->GetTypeInfo())
785     {
786     case ResParticleChildUpdater::TYPE_INFO:
787         {
788             ResParticleChildUpdaterData* childData =
789                 reinterpret_cast<ResParticleChildUpdaterData*>(memory);
790 
791             const ResParticleChildUpdater& child = ResDynamicCast<ResParticleChildUpdater>(*src);
792 
793             if (childStrSize > 0)
794             {
795                 const char* str = child.GetParticleSetPath();
796 
797                 ::std::memcpy(
798                     dstPtr,
799                     str,
800                     childStrSize);
801                 childData->toParticleSetPath.set_ptr((const char*)dstPtr);
802                 dstPtr += ut::RoundUp(childStrSize, 4);
803             }
804 
805             if (childFormSize > 0)
806             {
807                 const ResParticleForm& form = child.GetParticleForm();
808 
809                 ::std::memcpy(
810                     dstPtr,
811                     form.ptr(),
812                     childFormSize);
813                 childData->toParticleForm.set_ptr(dstPtr);
814                 dstPtr += ut::RoundUp(childFormSize, 4);
815             }
816 
817             if (childOptionSize > 0)
818             {
819                 const ResParticleChildUpdaterOption& option = child.GetTiming();
820 
821                 ::std::memcpy(
822                     dstPtr,
823                     option.ptr(),
824                     childOptionSize);
825                 childData->toTiming.set_ptr(dstPtr);
826                 dstPtr += ut::RoundUp(childOptionSize, 4);
827             }
828         }
829         break;
830     }
831 
832     return reinterpret_cast<ResParticleUpdaterData*>(memory);
833 }
834 
835 } // namespace gfx
836 } // namespace nw
837