1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_ParticleCollection.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: 26419 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/gfx/gfx_ParticleCollection.h>
19 #include <nw/gfx/gfx_ISceneVisitor.h>
20
21 #include <nw/ut/ut_ResUtil.h>
22 #include <nw/ut/ut_ResDictionary.h>
23
24 namespace nw
25 {
26 namespace gfx
27 {
28
29 NW_UT_RUNTIME_TYPEINFO_DEFINITION(ParticleCollection, SceneObject);
30
31 //----------------------------------------
32 template <typename T>
33 static int
ParticleStreamCreateSize(int capacity,int prevSize)34 ParticleStreamCreateSize(
35 int capacity,
36 int prevSize
37 )
38 {
39 NW_ASSERT(capacity > 0);
40
41 prevSize = ut::RoundUp(prevSize, 8);
42
43 // サイズをショートベクタ演算の処理単位に切り上げる
44 const int size =
45 ut::RoundUp(capacity, internal::PARTICLE_SIMD_WIDTH_MAX) * sizeof(T) +
46 internal::PARTICLE_SIMD_WIDTH_MAX;
47
48 return prevSize + size;
49 }
50
51 template <typename T>
52 static bool
ParticleStreamCreate(ParticleCollection::ParticleAttribute * storage,ParticleUsage usage,int capacity,u8 ** buffer)53 ParticleStreamCreate(
54 ParticleCollection::ParticleAttribute* storage,
55 ParticleUsage usage,
56 int capacity,
57 u8** buffer
58 )
59 {
60 NW_ASSERT(capacity > 0);
61 NW_NULL_ASSERT(buffer);
62
63 // サイズをショートベクタ演算の処理単位に切り上げる
64 const int size =
65 ut::RoundUp(capacity, internal::PARTICLE_SIMD_WIDTH_MAX) * sizeof(T) +
66 internal::PARTICLE_SIMD_WIDTH_MAX;
67
68 // VFPは64bitバスを持つので、8byteアラインメントしたほうが高速
69 *buffer = reinterpret_cast<u8*>(ut::RoundUp(*buffer, 8));
70 void* memory = *buffer;
71 *buffer += size;
72
73 std::memset(memory, 0, size);
74
75 storage->m_Usage = static_cast<s32>(usage);
76 storage->m_IsStream = true;
77 storage->m_Stream = reinterpret_cast<f32*>(memory);
78
79 return memory != NULL;
80 }
81
82 //----------------------------------------
83 template <typename T>
84 static int
ParticleParameterAttributeCreateSize(int prevSize)85 ParticleParameterAttributeCreateSize(
86 int prevSize
87 )
88 {
89 prevSize = ut::RoundUp(prevSize, 4);
90
91 const int size = sizeof(T);
92
93 return prevSize + size;
94 }
95
96 template <typename T>
97 static bool
ParticleParameterAttributeCreate(ParticleCollection::ParticleAttribute * storage,ParticleUsage usage,const ResParticleParameterAttribute & resource,u8 ** buffer)98 ParticleParameterAttributeCreate(
99 ParticleCollection::ParticleAttribute* storage,
100 ParticleUsage usage,
101 const ResParticleParameterAttribute& resource,
102 u8** buffer
103 )
104 {
105 NW_NULL_ASSERT(buffer);
106
107 const int size = sizeof(T);
108
109 *buffer = reinterpret_cast<u8*>(ut::RoundUp(*buffer, 4));
110 void* memory = *buffer;
111 *buffer += size;
112
113 nw::os::MemCpy(memory, resource.GetData(), size);
114
115 storage->m_Usage = static_cast<s32>(usage);
116 storage->m_IsStream = false;
117 storage->m_Stream = reinterpret_cast<f32*>(memory);
118
119 return memory != NULL;
120 }
121
122 //----------------------------------------
123 void
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResParticleCollection resNode)124 ParticleCollection::GetMemorySizeInternal(
125 os::MemorySizeCalculator* pSize,
126 ResParticleCollection resNode)
127 {
128 os::MemorySizeCalculator& size = *pSize;
129
130 const int capacity = resNode.GetCapacity();
131
132 int collectionMemorySize = sizeof(ParticleCollection);
133 collectionMemorySize = ut::RoundUp(collectionMemorySize, 4);
134
135 bool hasAttribute[PARTICLEUSAGE_COUNT];
136 for (int i = 0; i < PARTICLEUSAGE_COUNT; ++i)
137 {
138 hasAttribute[i] = false;
139 }
140
141 // 使用するメモリの総量の確認
142 {
143 // 生まれた順でアクティブなインデックスが格納されている
144 // ここではメモリ確保しない
145 {
146 ParticleUsage usage = PARTICLEUSAGE_ACTIVEINDEX;
147 hasAttribute[usage] = true;
148 }
149
150 // 使用可能なインデックスが前詰めで格納されている
151 {
152 ParticleUsage usage = PARTICLEUSAGE_FREEINDEX;
153
154 collectionMemorySize =
155 ParticleStreamCreateSize<u16>(capacity, collectionMemorySize);
156 collectionMemorySize = ut::RoundUp(collectionMemorySize, 4);
157
158 hasAttribute[usage] = true;
159 }
160
161 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
162 // 消滅する時刻(高速化のため)
163 {
164 ParticleUsage usage = PARTICLEUSAGE_NEG_TIMELIMIT;
165
166 collectionMemorySize =
167 ParticleStreamCreateSize<f32>(capacity, collectionMemorySize);
168
169 hasAttribute[usage] = true;
170 }
171 #endif
172
173 ResParticleAttributeArray attributes = resNode.GetAttributes();
174 ResParticleAttributeArray::iterator attributeEnd = attributes.end();
175 for (ResParticleAttributeArray::iterator it = attributes.begin();
176 it != attributeEnd;
177 ++it)
178 {
179 ParticleUsage usage = (ParticleUsage)(*it).GetUsage();
180
181 if ((*it).GetTypeInfo() == ResParticleParameterAttribute::TYPE_INFO)
182 {
183 ResParticleParameterAttribute resParam((*it).ptr());
184
185 switch (usage)
186 {
187 case PARTICLEUSAGE_BIRTH:
188 case PARTICLEUSAGE_LIFE:
189 collectionMemorySize =
190 ParticleParameterAttributeCreateSize<f32>(collectionMemorySize);
191 break;
192 case PARTICLEUSAGE_VELOCITY:
193 NW_FATAL_ERROR("PARTICLEUSAGE_VELOCITY must not be ParameterAttribute");
194 break;
195 case PARTICLEUSAGE_ALPHA:
196 case PARTICLEUSAGE_TEXTUREROTATE0:
197 collectionMemorySize =
198 ParticleShape::AddVertexParamSize(GL_FLOAT, 1, collectionMemorySize);
199 break;
200 case PARTICLEUSAGE_TRANSLATE:
201 case PARTICLEUSAGE_SCALE:
202 case PARTICLEUSAGE_ROTATE:
203 case PARTICLEUSAGE_COLOR:
204 case PARTICLEUSAGE_SCALE_EXT:
205 collectionMemorySize =
206 ParticleShape::AddVertexParamSize(GL_FLOAT, 3, collectionMemorySize);
207 break;
208 case PARTICLEUSAGE_TEXTURETRANSLATE0:
209 case PARTICLEUSAGE_TEXTURESCALE0:
210 collectionMemorySize =
211 ParticleShape::AddVertexParamSize(GL_FLOAT, 2, collectionMemorySize);
212 break;
213 }
214
215 hasAttribute[usage] = true;
216 }
217 else
218 {
219 switch (usage)
220 {
221 case PARTICLEUSAGE_BIRTH:
222 case PARTICLEUSAGE_LIFE:
223 collectionMemorySize =
224 ParticleStreamCreateSize<f32>(capacity, collectionMemorySize);
225 break;
226 case PARTICLEUSAGE_VELOCITY:
227 collectionMemorySize =
228 ParticleStreamCreateSize<nw::math::VEC3>(capacity, collectionMemorySize);
229 break;
230 case PARTICLEUSAGE_ALPHA:
231 case PARTICLEUSAGE_TEXTUREROTATE0:
232 case PARTICLEUSAGE_TRANSLATE:
233 case PARTICLEUSAGE_SCALE:
234 case PARTICLEUSAGE_ROTATE:
235 case PARTICLEUSAGE_COLOR:
236 case PARTICLEUSAGE_SCALE_EXT:
237 case PARTICLEUSAGE_TEXTURETRANSLATE0:
238 case PARTICLEUSAGE_TEXTURESCALE0:
239 break;
240 }
241
242 hasAttribute[usage] = true;
243 }
244 }
245
246 for (int usage = 0; usage < PARTICLEUSAGE_COUNT; ++usage)
247 {
248 if (!hasAttribute[usage])
249 {
250 switch (usage)
251 {
252 case PARTICLEUSAGE_BIRTH:
253 case PARTICLEUSAGE_LIFE:
254 case PARTICLEUSAGE_VELOCITY:
255 NW_FATAL_ERROR("PARTICLEUSAGE_BIRTH/LIFE/VELOCITY must not be ParameterAttribute");
256 break;
257 case PARTICLEUSAGE_ALPHA:
258 collectionMemorySize =
259 ParticleShape::AddVertexParamSize(GL_FLOAT, 1, collectionMemorySize);
260 break;
261 case PARTICLEUSAGE_TEXTUREROTATE0:
262 collectionMemorySize =
263 ParticleShape::AddVertexParamSize(GL_FLOAT, 1, collectionMemorySize);
264 break;
265 case PARTICLEUSAGE_TRANSLATE:
266 case PARTICLEUSAGE_ROTATE:
267 collectionMemorySize =
268 ParticleShape::AddVertexParamSize(GL_FLOAT, 3, collectionMemorySize);
269 break;
270 case PARTICLEUSAGE_COLOR:
271 case PARTICLEUSAGE_SCALE:
272 case PARTICLEUSAGE_SCALE_EXT:
273 collectionMemorySize =
274 ParticleShape::AddVertexParamSize(GL_FLOAT, 3, collectionMemorySize);
275 break;
276 case PARTICLEUSAGE_TEXTURETRANSLATE0:
277 collectionMemorySize =
278 ParticleShape::AddVertexParamSize(GL_FLOAT, 2, collectionMemorySize);
279 break;
280 case PARTICLEUSAGE_TEXTURESCALE0:
281 collectionMemorySize =
282 ParticleShape::AddVertexParamSize(GL_FLOAT, 2, collectionMemorySize);
283 break;
284 }
285
286 // 実際の確保のために初期化
287 hasAttribute[usage] = false;
288 }
289 }
290 }
291
292 size.Add(collectionMemorySize, 32);
293 }
294
295 //----------------------------------------
296 void
GetDeviceMemorySizeInternal(os::MemorySizeCalculator * pSize,ResParticleCollection resNode)297 ParticleCollection::GetDeviceMemorySizeInternal(
298 os::MemorySizeCalculator* pSize,
299 ResParticleCollection resNode)
300 {
301 os::MemorySizeCalculator& size = *pSize;
302
303 const int capacity = resNode.GetCapacity();
304
305 int deviceMemorySize = 0;
306
307 // 使用するメモリの総量の確認
308 {
309 ResParticleAttributeArray attributes = resNode.GetAttributes();
310 ResParticleAttributeArray::iterator attributeEnd = attributes.end();
311 for (ResParticleAttributeArray::iterator it = attributes.begin();
312 it != attributeEnd;
313 ++it)
314 {
315 ParticleUsage usage = (ParticleUsage)(*it).GetUsage();
316
317 if ((*it).GetTypeInfo() != ResParticleParameterAttribute::TYPE_INFO)
318 {
319 switch (usage)
320 {
321 case PARTICLEUSAGE_BIRTH:
322 case PARTICLEUSAGE_LIFE:
323 case PARTICLEUSAGE_VELOCITY:
324 break;
325 case PARTICLEUSAGE_ALPHA:
326 case PARTICLEUSAGE_TEXTUREROTATE0:
327 deviceMemorySize =
328 ParticleShape::AddVertexStreamSize(GL_FLOAT, 1, capacity, deviceMemorySize);
329 break;
330 case PARTICLEUSAGE_TRANSLATE:
331 case PARTICLEUSAGE_SCALE:
332 case PARTICLEUSAGE_ROTATE:
333 case PARTICLEUSAGE_COLOR:
334 case PARTICLEUSAGE_SCALE_EXT:
335 deviceMemorySize =
336 ParticleShape::AddVertexStreamSize(GL_FLOAT, 3, capacity, deviceMemorySize);
337 break;
338 case PARTICLEUSAGE_TEXTURETRANSLATE0:
339 case PARTICLEUSAGE_TEXTURESCALE0:
340 deviceMemorySize =
341 ParticleShape::AddVertexStreamSize(GL_FLOAT, 2, capacity, deviceMemorySize);
342 break;
343 }
344 }
345 }
346 }
347
348 size.Add(deviceMemorySize, 32);
349 }
350
351 //----------------------------------------
352 ParticleCollection*
Create(ParticleSet * parent,ResParticleCollection resNode,os::IAllocator * mainAllocator,os::IAllocator * deviceAllocator,ParticleShape * shape)353 ParticleCollection::Create(
354 ParticleSet* parent,
355 ResParticleCollection resNode,
356 os::IAllocator* mainAllocator,
357 os::IAllocator* deviceAllocator,
358 ParticleShape* shape
359 )
360 {
361 NW_NULL_ASSERT(mainAllocator);
362 NW_NULL_ASSERT(deviceAllocator);
363 NW_NULL_ASSERT(shape);
364
365 NW_ASSERT(resNode.IsValid());
366
367 const int capacity = resNode.GetCapacity();
368
369 int collectionMemorySize = sizeof(ParticleCollection);
370 collectionMemorySize = ut::RoundUp(collectionMemorySize, 4);
371
372 int deviceMemorySize = 0;
373
374 bool hasAttribute[PARTICLEUSAGE_COUNT];
375 for (int i = 0; i < PARTICLEUSAGE_COUNT; ++i)
376 {
377 hasAttribute[i] = false;
378 }
379
380 // 使用するメモリの総量の確認
381 {
382 // 生まれた順でアクティブなインデックスが格納されている
383 // ここではメモリ確保しない
384 {
385 ParticleUsage usage = PARTICLEUSAGE_ACTIVEINDEX;
386 hasAttribute[usage] = true;
387 }
388
389 // 使用可能なインデックスが前詰めで格納されている
390 {
391 ParticleUsage usage = PARTICLEUSAGE_FREEINDEX;
392
393 collectionMemorySize =
394 ParticleStreamCreateSize<u16>(capacity, collectionMemorySize);
395 collectionMemorySize = ut::RoundUp(collectionMemorySize, 4);
396
397 hasAttribute[usage] = true;
398 }
399
400 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
401 // 消滅する時刻(高速化のため)
402 {
403 ParticleUsage usage = PARTICLEUSAGE_NEG_TIMELIMIT;
404
405 collectionMemorySize =
406 ParticleStreamCreateSize<f32>(capacity, collectionMemorySize);
407
408 hasAttribute[usage] = true;
409 }
410 #endif
411
412 ResParticleAttributeArray attributes = resNode.GetAttributes();
413 ResParticleAttributeArray::iterator attributeEnd = attributes.end();
414 for (ResParticleAttributeArray::iterator it = attributes.begin();
415 it != attributeEnd;
416 ++it)
417 {
418 ParticleUsage usage = (ParticleUsage)(*it).GetUsage();
419
420 if ((*it).GetTypeInfo() == ResParticleParameterAttribute::TYPE_INFO)
421 {
422 ResParticleParameterAttribute resParam((*it).ptr());
423
424 switch (usage)
425 {
426 case PARTICLEUSAGE_BIRTH:
427 case PARTICLEUSAGE_LIFE:
428 collectionMemorySize =
429 ParticleParameterAttributeCreateSize<f32>(collectionMemorySize);
430 break;
431 case PARTICLEUSAGE_VELOCITY:
432 NW_FATAL_ERROR("PARTICLEUSAGE_VELOCITY must not be ParameterAttribute");
433 break;
434 case PARTICLEUSAGE_ALPHA:
435 case PARTICLEUSAGE_TEXTUREROTATE0:
436 collectionMemorySize =
437 shape->AddVertexParamSize(GL_FLOAT, 1, collectionMemorySize);
438 break;
439 case PARTICLEUSAGE_TRANSLATE:
440 case PARTICLEUSAGE_SCALE:
441 case PARTICLEUSAGE_ROTATE:
442 case PARTICLEUSAGE_COLOR:
443 case PARTICLEUSAGE_SCALE_EXT:
444 collectionMemorySize =
445 shape->AddVertexParamSize(GL_FLOAT, 3, collectionMemorySize);
446 break;
447 case PARTICLEUSAGE_TEXTURETRANSLATE0:
448 case PARTICLEUSAGE_TEXTURESCALE0:
449 collectionMemorySize =
450 shape->AddVertexParamSize(GL_FLOAT, 2, collectionMemorySize);
451 break;
452 }
453
454 hasAttribute[usage] = true;
455 }
456 else
457 {
458 switch (usage)
459 {
460 case PARTICLEUSAGE_BIRTH:
461 case PARTICLEUSAGE_LIFE:
462 collectionMemorySize =
463 ParticleStreamCreateSize<f32>(capacity, collectionMemorySize);
464 break;
465 case PARTICLEUSAGE_VELOCITY:
466 collectionMemorySize =
467 ParticleStreamCreateSize<nw::math::VEC3>(capacity, collectionMemorySize);
468 break;
469 case PARTICLEUSAGE_ALPHA:
470 case PARTICLEUSAGE_TEXTUREROTATE0:
471 deviceMemorySize =
472 shape->AddVertexStreamSize(GL_FLOAT, 1, capacity, deviceMemorySize);
473 break;
474 case PARTICLEUSAGE_TRANSLATE:
475 case PARTICLEUSAGE_SCALE:
476 case PARTICLEUSAGE_ROTATE:
477 case PARTICLEUSAGE_COLOR:
478 case PARTICLEUSAGE_SCALE_EXT:
479 deviceMemorySize =
480 shape->AddVertexStreamSize(GL_FLOAT, 3, capacity, deviceMemorySize);
481 break;
482 case PARTICLEUSAGE_TEXTURETRANSLATE0:
483 case PARTICLEUSAGE_TEXTURESCALE0:
484 deviceMemorySize =
485 shape->AddVertexStreamSize(GL_FLOAT, 2, capacity, deviceMemorySize);
486 break;
487 }
488
489 hasAttribute[usage] = true;
490 }
491 }
492
493 for (int usage = 0; usage < PARTICLEUSAGE_COUNT; ++usage)
494 {
495 if (!hasAttribute[usage])
496 {
497 switch (usage)
498 {
499 case PARTICLEUSAGE_BIRTH:
500 case PARTICLEUSAGE_LIFE:
501 case PARTICLEUSAGE_VELOCITY:
502 NW_FATAL_ERROR("PARTICLEUSAGE_BIRTH/LIFE/VELOCITY must not be ParameterAttribute");
503 break;
504 case PARTICLEUSAGE_ALPHA:
505 collectionMemorySize =
506 shape->AddVertexParamSize(GL_FLOAT, 1, collectionMemorySize);
507 break;
508 case PARTICLEUSAGE_TEXTUREROTATE0:
509 collectionMemorySize =
510 shape->AddVertexParamSize(GL_FLOAT, 1, collectionMemorySize);
511 break;
512 case PARTICLEUSAGE_TRANSLATE:
513 case PARTICLEUSAGE_ROTATE:
514 collectionMemorySize =
515 shape->AddVertexParamSize(GL_FLOAT, 3, collectionMemorySize);
516 break;
517 case PARTICLEUSAGE_COLOR:
518 case PARTICLEUSAGE_SCALE:
519 case PARTICLEUSAGE_SCALE_EXT:
520 collectionMemorySize =
521 shape->AddVertexParamSize(GL_FLOAT, 3, collectionMemorySize);
522 break;
523 case PARTICLEUSAGE_TEXTURETRANSLATE0:
524 collectionMemorySize =
525 shape->AddVertexParamSize(GL_FLOAT, 2, collectionMemorySize);
526 break;
527 case PARTICLEUSAGE_TEXTURESCALE0:
528 collectionMemorySize =
529 shape->AddVertexParamSize(GL_FLOAT, 2, collectionMemorySize);
530 break;
531 }
532
533 // 実際の確保のために初期化
534 hasAttribute[usage] = false;
535 }
536 }
537 }
538
539 u8* deviceMemory = NULL;
540 if (deviceMemorySize > 0)
541 {
542 deviceMemory = reinterpret_cast<u8*>(deviceAllocator->Alloc(deviceMemorySize, 32));
543 if (deviceMemory == NULL)
544 {
545 return NULL;
546 }
547 }
548
549 u8* nodeMemory = reinterpret_cast<u8*>(mainAllocator->Alloc(collectionMemorySize, 32));
550 if (nodeMemory == NULL)
551 {
552 if (deviceMemory != NULL)
553 {
554 deviceAllocator->Free(deviceMemory);
555 }
556
557 return NULL;
558 }
559
560 ParticleCollection* node = new(nodeMemory) ParticleCollection(
561 mainAllocator,
562 deviceAllocator,
563 deviceMemory,
564 resNode);
565 nodeMemory += sizeof(ParticleCollection);
566 nodeMemory = reinterpret_cast<u8*>(ut::RoundUp(nodeMemory, 4));
567
568 node->m_Capacity = capacity;
569
570 node->m_ParticleShape = shape;
571
572 {
573 // 生まれた順でアクティブなインデックスが格納されている
574 {
575 ParticleUsage usage = PARTICLEUSAGE_ACTIVEINDEX;
576
577 node->m_IsStream[usage] = true;
578 for (int i = 0; i < 2; ++i)
579 {
580 node->m_StreamPtr[usage][i] = shape->GetPrimitiveStreamPtr((ParticleBuffer)i);
581 node->m_StreamStride[usage] = 2;
582 }
583
584 hasAttribute[usage] = true;
585 }
586
587 // 使用可能なインデックスが前詰めで格納されている
588 {
589 ParticleUsage usage = PARTICLEUSAGE_FREEINDEX;
590
591 ParticleStreamCreate<u16>(
592 &node->m_ParticleAttribute[usage], static_cast<ParticleUsage>(usage), capacity, &nodeMemory);
593
594 node->m_IsStream[usage] = true;
595 for (int i = 0; i < 2; ++i)
596 {
597 node->m_StreamPtr[usage][i] = node->m_ParticleAttribute[usage].m_Stream;
598 node->m_StreamStride[usage] = 2;
599 }
600
601 hasAttribute[usage] = true;
602 }
603
604 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
605 // 消滅する時刻(高速化のため)
606 {
607 ParticleUsage usage = PARTICLEUSAGE_NEG_TIMELIMIT;
608
609 ParticleStreamCreate<f32>(
610 &node->m_ParticleAttribute[usage], static_cast<ParticleUsage>(usage), capacity, &nodeMemory);
611
612 node->m_IsStream[usage] = true;
613 for (int i = 0; i < 2; ++i)
614 {
615 node->m_StreamPtr[usage][i] = node->m_ParticleAttribute[usage].m_Stream;
616 node->m_StreamStride[usage] = 2;
617 }
618
619 hasAttribute[usage] = true;
620 }
621 #endif
622
623 ResParticleAttributeArray attributes = resNode.GetAttributes();
624 ResParticleAttributeArray::iterator attributeEnd = attributes.end();
625 for (ResParticleAttributeArray::iterator it = attributes.begin();
626 it != attributeEnd;
627 ++it)
628 {
629 ParticleUsage usage = (ParticleUsage)(*it).GetUsage();
630
631 void* ptr0 = NULL;
632 void* ptr1 = NULL;
633
634 if ((*it).GetTypeInfo() == ResParticleParameterAttribute::TYPE_INFO)
635 {
636 ResParticleParameterAttribute resParam((*it).ptr());
637
638 void* ptr = NULL;
639
640 switch (usage)
641 {
642 case PARTICLEUSAGE_BIRTH:
643 case PARTICLEUSAGE_LIFE:
644 ParticleParameterAttributeCreate<ParticleTime>(
645 &node->m_ParticleAttribute[usage], usage, resParam, &nodeMemory);
646 ptr = node->m_ParticleAttribute[usage].m_Stream;
647 {
648 *(ParticleTime*)ptr = *resParam.GetData();
649 }
650 break;
651 case PARTICLEUSAGE_VELOCITY:
652 NW_FATAL_ERROR("PARTICLEUSAGE_VELOCITY must not be ParameterAttribute");
653 break;
654 case PARTICLEUSAGE_ALPHA:
655 case PARTICLEUSAGE_TEXTUREROTATE0:
656 {
657 ParticleShape::VertexAttribute* data =
658 shape->AddVertexParam(usage, GL_FLOAT, 1, resParam.GetData(), &nodeMemory);
659 ptr = data->m_Stream[0];
660 }
661 break;
662 case PARTICLEUSAGE_TRANSLATE:
663 case PARTICLEUSAGE_SCALE:
664 case PARTICLEUSAGE_ROTATE:
665 case PARTICLEUSAGE_COLOR:
666 case PARTICLEUSAGE_SCALE_EXT:
667 {
668 ParticleShape::VertexAttribute* data =
669 shape->AddVertexParam(usage, GL_FLOAT, 3, resParam.GetData(), &nodeMemory);
670 ptr = data->m_Stream[0];
671 }
672 break;
673 case PARTICLEUSAGE_TEXTURETRANSLATE0:
674 case PARTICLEUSAGE_TEXTURESCALE0:
675 {
676 ParticleShape::VertexAttribute* data =
677 shape->AddVertexParam(usage, GL_FLOAT, 2, resParam.GetData(), &nodeMemory);
678 ptr = data->m_Stream[0];
679 }
680 break;
681 }
682
683 hasAttribute[usage] = true;
684 node->m_IsStream[usage] = false;
685 node->m_StreamPtr[usage][0] = ptr;
686 node->m_StreamPtr[usage][1] = ptr;
687 node->m_StreamStride[usage] = 0;
688 }
689 else
690 {
691 switch (usage)
692 {
693 case PARTICLEUSAGE_BIRTH:
694 case PARTICLEUSAGE_LIFE:
695 ParticleStreamCreate<ParticleTime>(
696 &node->m_ParticleAttribute[usage], static_cast<ParticleUsage>(usage), capacity, &nodeMemory);
697 node->m_StreamPtr[usage][0] = node->m_ParticleAttribute[usage].m_Stream;
698 node->m_StreamPtr[usage][1] = node->m_ParticleAttribute[usage].m_Stream;
699 node->m_StreamStride[usage] = 4;
700 break;
701 case PARTICLEUSAGE_VELOCITY:
702 ParticleStreamCreate<nw::math::VEC3>(
703 &node->m_ParticleAttribute[usage], static_cast<ParticleUsage>(usage), capacity, &nodeMemory);
704 node->m_StreamPtr[usage][0] = node->m_ParticleAttribute[usage].m_Stream;
705 node->m_StreamPtr[usage][1] = node->m_ParticleAttribute[usage].m_Stream;
706 node->m_StreamStride[usage] = 12;
707 break;
708 case PARTICLEUSAGE_ALPHA:
709 case PARTICLEUSAGE_TEXTUREROTATE0:
710 {
711 ParticleShape::VertexAttribute* datas = shape->AddVertexStream(usage, GL_FLOAT, 1, capacity, &deviceMemory);
712 node->m_StreamPtr[usage][0] = datas->m_Stream[0];
713 node->m_StreamPtr[usage][1] = datas->m_Stream[1];
714 node->m_StreamStride[usage] = 4;
715 }
716 break;
717 case PARTICLEUSAGE_TRANSLATE:
718 case PARTICLEUSAGE_SCALE:
719 case PARTICLEUSAGE_ROTATE:
720 case PARTICLEUSAGE_COLOR:
721 case PARTICLEUSAGE_SCALE_EXT:
722 {
723 ParticleShape::VertexAttribute* datas = shape->AddVertexStream(usage, GL_FLOAT, 3, capacity, &deviceMemory);
724 node->m_StreamPtr[usage][0] = datas->m_Stream[0];
725 node->m_StreamPtr[usage][1] = datas->m_Stream[1];
726 node->m_StreamStride[usage] = 12;
727 }
728 break;
729 case PARTICLEUSAGE_TEXTURETRANSLATE0:
730 case PARTICLEUSAGE_TEXTURESCALE0:
731 {
732 ParticleShape::VertexAttribute* datas = shape->AddVertexStream(usage, GL_FLOAT, 2, capacity, &deviceMemory);
733 node->m_StreamPtr[usage][0] = datas->m_Stream[0];
734 node->m_StreamPtr[usage][1] = datas->m_Stream[1];
735 node->m_StreamStride[usage] = 8;
736 }
737 break;
738 }
739
740 node->m_IsStream[usage] = true;
741 hasAttribute[usage] = true;
742 }
743 }
744
745 for (int usage = 0; usage < PARTICLEUSAGE_COUNT; ++usage)
746 {
747 if (!hasAttribute[usage])
748 {
749 float paramZero[] = {0.0f, 0.0f, 0.0f, 0.0f};
750 float paramOne[] = {1.0f, 1.0f, 1.0f, 1.0f};
751
752 void* ptr = NULL;
753
754 switch (usage)
755 {
756 case PARTICLEUSAGE_BIRTH:
757 case PARTICLEUSAGE_LIFE:
758 case PARTICLEUSAGE_VELOCITY:
759 NW_FATAL_ERROR("PARTICLEUSAGE_BIRTH/LIFE/VELOCITY must not be ParameterAttribute");
760 break;
761 case PARTICLEUSAGE_ALPHA:
762 {
763 ParticleShape::VertexAttribute* data =
764 shape->AddVertexParam(usage, GL_FLOAT, 1, paramOne, &nodeMemory);
765 ptr = data->m_Stream[0];
766 }
767 break;
768 case PARTICLEUSAGE_TEXTUREROTATE0:
769 {
770 ParticleShape::VertexAttribute* data =
771 shape->AddVertexParam(usage, GL_FLOAT, 1, paramZero, &nodeMemory);
772 ptr = data->m_Stream[0];
773 }
774 break;
775 case PARTICLEUSAGE_TRANSLATE:
776 case PARTICLEUSAGE_ROTATE:
777 {
778 ParticleShape::VertexAttribute* data =
779 shape->AddVertexParam(usage, GL_FLOAT, 3, paramZero, &nodeMemory);
780 ptr = data->m_Stream[0];
781 }
782 break;
783 case PARTICLEUSAGE_COLOR:
784 case PARTICLEUSAGE_SCALE:
785 case PARTICLEUSAGE_SCALE_EXT:
786 {
787 ParticleShape::VertexAttribute* data =
788 shape->AddVertexParam(usage, GL_FLOAT, 3, paramOne, &nodeMemory);
789 ptr = data->m_Stream[0];
790 }
791 break;
792 case PARTICLEUSAGE_TEXTURETRANSLATE0:
793 {
794 ParticleShape::VertexAttribute* data =
795 shape->AddVertexParam(usage, GL_FLOAT, 2, paramZero, &nodeMemory);
796 ptr = data->m_Stream[0];
797 }
798 break;
799 case PARTICLEUSAGE_TEXTURESCALE0:
800 {
801 ParticleShape::VertexAttribute* data =
802 shape->AddVertexParam(usage, GL_FLOAT, 2, paramOne, &nodeMemory);
803 ptr = data->m_Stream[0];
804 }
805 break;
806 }
807
808 hasAttribute[usage] = true;
809 node->m_IsStream[usage] = false;
810 node->m_StreamPtr[usage][0] = ptr;
811 node->m_StreamPtr[usage][1] = ptr;
812 node->m_StreamStride[usage] = 0;
813 }
814 }
815 }
816
817 node->Clear();
818
819 if (parent)
820 {
821 bool result = parent->AttachParticleCollection(node);
822 NW_ASSERT(result);
823
824 node->m_ParticleSet = parent;
825 }
826
827 return node;
828 }
829
830 //----------------------------------------
ParticleCollection(os::IAllocator * allocator,os::IAllocator * deviceAllocator,void * deviceMemory,ResParticleCollection resObj)831 ParticleCollection::ParticleCollection(
832 os::IAllocator* allocator,
833 os::IAllocator* deviceAllocator,
834 void* deviceMemory,
835 ResParticleCollection resObj
836 )
837 : GfxObject(allocator),
838 m_BufferSide(false),
839 m_MinActiveIndex(0),
840 m_MaxActiveIndex(0),
841 m_ResParticleCollection(resObj),
842 m_ParticleShape(NULL),
843 m_ParticleSet(NULL),
844 m_DeviceAllocator(deviceAllocator),
845 m_DeviceMemory(deviceMemory)
846 {
847 NW_UNUSED_VARIABLE(resObj)
848
849 for (int i = 0; i < PARTICLEUSAGE_COUNT; ++i)
850 {
851 this->m_ParticleAttribute[i].m_Stream = NULL;
852 this->m_StreamStride[i] = 0;
853
854 this->m_IsStream[i] = false;
855 for (int j = 0; j < 2; ++j)
856 {
857 this->m_StreamPtr[i][j] = NULL;
858 }
859 }
860 }
861
862 //----------------------------------------
~ParticleCollection()863 ParticleCollection::~ParticleCollection()
864 {
865 if (m_DeviceMemory != NULL)
866 {
867 m_DeviceAllocator->Free(m_DeviceMemory);
868 }
869
870 for (int i = 0; i < PARTICLEUSAGE_COUNT; ++i)
871 {
872 if (this->m_ParticleAttribute[i].m_Stream != NULL)
873 {
874 this->m_ParticleAttribute[i].m_Stream = NULL;
875 }
876
877 for (int j = 0; j < 2; ++j)
878 {
879 this->m_StreamPtr[i][j] = NULL;
880 }
881 }
882 }
883
884 //----------------------------------------
885 void
Clear()886 ParticleCollection::Clear()
887 {
888 const int capacity = this->GetCapacity();
889
890 this->SetCount(0);
891 this->SetMinActiveIndex(0xffff);
892 this->SetMaxActiveIndex(0);
893
894 // 生まれた順でアクティブなインデックスが格納されている
895 for (int j = 0; j < 2; ++j)
896 {
897 u16* ptr = (u16*)this->GetStreamPtr(PARTICLEUSAGE_ACTIVEINDEX, (ParticleBuffer)j);
898 std::memset(ptr, 0xff, sizeof(u16) * capacity);
899 }
900
901 // 使用可能なインデックスが前詰めで格納されている
902 {
903 u16* ptr = (u16*)this->GetStreamPtr(PARTICLEUSAGE_FREEINDEX, PARTICLE_BUFFER_FRONT);
904 for (int i = capacity - 1; i >= 0; --i)
905 {
906 *ptr++ = i;
907 }
908 }
909
910 #if 0
911 // 消滅する時刻(高速化のため)
912 {
913 f32* ptr = (f32*)this->GetStreamPtr(PARTICLEUSAGE_NEG_TIMELIMIT, PARTICLE_BUFFER_FRONT);
914 std::memset(ptr, 0xff, sizeof(f32) * capacity);
915 }
916 #endif
917 }
918
919 //----------------------------------------
920 void
SetParameter(ParticleUsage usage,ParticleBuffer side,const f32 * ptr)921 ParticleCollection::SetParameter(
922 ParticleUsage usage,
923 ParticleBuffer side,
924 const f32* ptr
925 )
926 {
927 NW_ASSERT(usage >= 0 && usage < PARTICLEUSAGE_COUNT);
928
929 if (this->m_IsStream[usage])
930 {
931 return;
932 }
933
934 // 非VBOから検索
935 for (int i = 0; i < PARTICLEUSAGE_COUNT; ++i)
936 {
937 if (this->m_ParticleAttribute[i].m_Usage == usage)
938 {
939 nw::os::MemCpy(
940 this->m_ParticleAttribute[i].m_Stream,
941 ptr,
942 sizeof(ParticleTime)); // TBD:LIFEしかないはずなので固定
943 return; // 見つかったので終了する
944 }
945 }
946
947 // VBO
948 for (int i = 0; i < this->m_ParticleShape->GetVertexAttributesCount(); ++i)
949 {
950 if (this->m_ParticleShape->GetVertexAttributeUsage(i) == usage)
951 {
952 this->m_ParticleShape->SetVertexParameter(i, side, ptr);
953 return;
954 }
955 }
956 }
957
958 } // namespace gfx
959 } // namespace nw
960