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