~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CParticleSystemSceneNode.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#include "CParticleSystemSceneNode.h"
 
6
#include "os.h"
 
7
#include "ISceneManager.h"
 
8
#include "ICameraSceneNode.h"
 
9
#include "IVideoDriver.h"
 
10
 
 
11
#include "CParticleAnimatedMeshSceneNodeEmitter.h"
 
12
#include "CParticleBoxEmitter.h"
 
13
#include "CParticleCylinderEmitter.h"
 
14
#include "CParticleMeshEmitter.h"
 
15
#include "CParticlePointEmitter.h"
 
16
#include "CParticleRingEmitter.h"
 
17
#include "CParticleSphereEmitter.h"
 
18
#include "CParticleAttractionAffector.h"
 
19
#include "CParticleFadeOutAffector.h"
 
20
#include "CParticleGravityAffector.h"
 
21
#include "CParticleRotationAffector.h"
 
22
#include "CParticleScaleAffector.h"
 
23
#include "SViewFrustum.h"
 
24
 
 
25
namespace irr
 
26
{
 
27
namespace scene
 
28
{
 
29
 
 
30
//! constructor
 
31
CParticleSystemSceneNode::CParticleSystemSceneNode(bool createDefaultEmitter,
 
32
        ISceneNode* parent, ISceneManager* mgr, s32 id,
 
33
        const core::vector3df& position, const core::vector3df& rotation,
 
34
        const core::vector3df& scale)
 
35
        : IParticleSystemSceneNode(parent, mgr, id, position, rotation, scale),
 
36
        Emitter(0), ParticleSize(core::dimension2d<f32>(5.0f, 5.0f)), LastEmitTime(0),
 
37
        MaxParticles(0xffff), Buffer(0), ParticlesAreGlobal(true)
 
38
{
 
39
        #ifdef _DEBUG
 
40
        setDebugName("CParticleSystemSceneNode");
 
41
        #endif
 
42
 
 
43
        Buffer = new SMeshBuffer();
 
44
        if (createDefaultEmitter)
 
45
        {
 
46
                IParticleEmitter* e = createBoxEmitter();
 
47
                setEmitter(e);
 
48
                e->drop();
 
49
        }
 
50
}
 
51
 
 
52
 
 
53
//! destructor
 
54
CParticleSystemSceneNode::~CParticleSystemSceneNode()
 
55
{
 
56
        if (Emitter)
 
57
                Emitter->drop();
 
58
        if (Buffer)
 
59
                Buffer->drop();
 
60
 
 
61
        removeAllAffectors();
 
62
}
 
63
 
 
64
 
 
65
//! Gets the particle emitter, which creates the particles.
 
66
IParticleEmitter* CParticleSystemSceneNode::getEmitter()
 
67
{
 
68
        return Emitter;
 
69
}
 
70
 
 
71
 
 
72
//! Sets the particle emitter, which creates the particles.
 
73
void CParticleSystemSceneNode::setEmitter(IParticleEmitter* emitter)
 
74
{
 
75
    if (emitter == Emitter)
 
76
        return;
 
77
        if (Emitter)
 
78
                Emitter->drop();
 
79
 
 
80
        Emitter = emitter;
 
81
 
 
82
        if (Emitter)
 
83
                Emitter->grab();
 
84
}
 
85
 
 
86
 
 
87
//! Adds new particle effector to the particle system.
 
88
void CParticleSystemSceneNode::addAffector(IParticleAffector* affector)
 
89
{
 
90
        affector->grab();
 
91
        AffectorList.push_back(affector);
 
92
}
 
93
 
 
94
//! Get a list of all particle affectors.
 
95
const core::list<IParticleAffector*>& CParticleSystemSceneNode::getAffectors() const
 
96
{
 
97
        return AffectorList;
 
98
}
 
99
 
 
100
//! Removes all particle affectors in the particle system.
 
101
void CParticleSystemSceneNode::removeAllAffectors()
 
102
{
 
103
        core::list<IParticleAffector*>::Iterator it = AffectorList.begin();
 
104
        while (it != AffectorList.end())
 
105
        {
 
106
                (*it)->drop();
 
107
                it = AffectorList.erase(it);
 
108
        }
 
109
}
 
110
 
 
111
 
 
112
//! Returns the material based on the zero based index i.
 
113
video::SMaterial& CParticleSystemSceneNode::getMaterial(u32 i)
 
114
{
 
115
        return Buffer->Material;
 
116
}
 
117
 
 
118
 
 
119
//! Returns amount of materials used by this scene node.
 
120
u32 CParticleSystemSceneNode::getMaterialCount() const
 
121
{
 
122
        return 1;
 
123
}
 
124
 
 
125
 
 
126
//! Creates a particle emitter for an animated mesh scene node
 
127
IParticleAnimatedMeshSceneNodeEmitter*
 
128
CParticleSystemSceneNode::createAnimatedMeshSceneNodeEmitter(
 
129
        scene::IAnimatedMeshSceneNode* node, bool useNormalDirection,
 
130
        const core::vector3df& direction, f32 normalDirectionModifier,
 
131
        s32 mbNumber, bool everyMeshVertex,
 
132
        u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
 
133
        const video::SColor& minStartColor, const video::SColor& maxStartColor,
 
134
        u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
 
135
        const core::dimension2df& minStartSize,
 
136
        const core::dimension2df& maxStartSize )
 
137
{
 
138
        return new CParticleAnimatedMeshSceneNodeEmitter( node,
 
139
                        useNormalDirection, direction, normalDirectionModifier,
 
140
                        mbNumber, everyMeshVertex,
 
141
                        minParticlesPerSecond, maxParticlesPerSecond,
 
142
                        minStartColor, maxStartColor,
 
143
                        lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
144
                        minStartSize, maxStartSize );
 
145
}
 
146
 
 
147
 
 
148
//! Creates a box particle emitter.
 
149
IParticleBoxEmitter* CParticleSystemSceneNode::createBoxEmitter(
 
150
        const core::aabbox3df& box, const core::vector3df& direction,
 
151
        u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
 
152
        const video::SColor& minStartColor, const video::SColor& maxStartColor,
 
153
        u32 lifeTimeMin, u32 lifeTimeMax,
 
154
        s32 maxAngleDegrees, const core::dimension2df& minStartSize,
 
155
        const core::dimension2df& maxStartSize )
 
156
{
 
157
        return new CParticleBoxEmitter(box, direction, minParticlesPerSecond,
 
158
                maxParticlesPerSecond, minStartColor, maxStartColor,
 
159
                lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
160
                        minStartSize, maxStartSize );
 
161
}
 
162
 
 
163
 
 
164
//! Creates a particle emitter for emitting from a cylinder
 
165
IParticleCylinderEmitter* CParticleSystemSceneNode::createCylinderEmitter(
 
166
        const core::vector3df& center, f32 radius,
 
167
        const core::vector3df& normal, f32 length,
 
168
        bool outlineOnly, const core::vector3df& direction,
 
169
        u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
 
170
        const video::SColor& minStartColor, const video::SColor& maxStartColor,
 
171
        u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
 
172
        const core::dimension2df& minStartSize,
 
173
        const core::dimension2df& maxStartSize )
 
174
{
 
175
        return new CParticleCylinderEmitter( center, radius, normal, length,
 
176
                        outlineOnly, direction,
 
177
                        minParticlesPerSecond, maxParticlesPerSecond,
 
178
                        minStartColor, maxStartColor,
 
179
                        lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
180
                        minStartSize, maxStartSize );
 
181
}
 
182
 
 
183
 
 
184
//! Creates a mesh particle emitter.
 
185
IParticleMeshEmitter* CParticleSystemSceneNode::createMeshEmitter(
 
186
        scene::IMesh* mesh, bool useNormalDirection,
 
187
        const core::vector3df& direction, f32 normalDirectionModifier,
 
188
        s32 mbNumber, bool everyMeshVertex,
 
189
        u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
 
190
        const video::SColor& minStartColor, const video::SColor& maxStartColor,
 
191
        u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
 
192
        const core::dimension2df& minStartSize,
 
193
        const core::dimension2df& maxStartSize)
 
194
{
 
195
        return new CParticleMeshEmitter( mesh, useNormalDirection, direction,
 
196
                        normalDirectionModifier, mbNumber, everyMeshVertex,
 
197
                        minParticlesPerSecond, maxParticlesPerSecond,
 
198
                        minStartColor, maxStartColor,
 
199
                        lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
200
                        minStartSize, maxStartSize );
 
201
}
 
202
 
 
203
 
 
204
//! Creates a point particle emitter.
 
205
IParticlePointEmitter* CParticleSystemSceneNode::createPointEmitter(
 
206
        const core::vector3df& direction, u32 minParticlesPerSecond,
 
207
        u32 maxParticlesPerSecond, const video::SColor& minStartColor,
 
208
        const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax,
 
209
        s32 maxAngleDegrees, const core::dimension2df& minStartSize,
 
210
        const core::dimension2df& maxStartSize )
 
211
{
 
212
        return new CParticlePointEmitter(direction, minParticlesPerSecond,
 
213
                maxParticlesPerSecond, minStartColor, maxStartColor,
 
214
                lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
215
                        minStartSize, maxStartSize );
 
216
}
 
217
 
 
218
 
 
219
//! Creates a ring particle emitter.
 
220
IParticleRingEmitter* CParticleSystemSceneNode::createRingEmitter(
 
221
        const core::vector3df& center, f32 radius, f32 ringThickness,
 
222
        const core::vector3df& direction,
 
223
        u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
 
224
        const video::SColor& minStartColor, const video::SColor& maxStartColor,
 
225
        u32 lifeTimeMin, u32 lifeTimeMax, s32 maxAngleDegrees,
 
226
        const core::dimension2df& minStartSize, const core::dimension2df& maxStartSize )
 
227
{
 
228
        return new CParticleRingEmitter( center, radius, ringThickness, direction,
 
229
                minParticlesPerSecond, maxParticlesPerSecond, minStartColor,
 
230
                maxStartColor, lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
231
                        minStartSize, maxStartSize );
 
232
}
 
233
 
 
234
 
 
235
//! Creates a sphere particle emitter.
 
236
IParticleSphereEmitter* CParticleSystemSceneNode::createSphereEmitter(
 
237
        const core::vector3df& center, f32 radius, const core::vector3df& direction,
 
238
        u32 minParticlesPerSecond, u32 maxParticlesPerSecond,
 
239
        const video::SColor& minStartColor, const video::SColor& maxStartColor,
 
240
        u32 lifeTimeMin, u32 lifeTimeMax,
 
241
        s32 maxAngleDegrees, const core::dimension2df& minStartSize,
 
242
        const core::dimension2df& maxStartSize )
 
243
{
 
244
        return new CParticleSphereEmitter(center, radius, direction,
 
245
                        minParticlesPerSecond, maxParticlesPerSecond,
 
246
                        minStartColor, maxStartColor,
 
247
                        lifeTimeMin, lifeTimeMax, maxAngleDegrees,
 
248
                        minStartSize, maxStartSize );
 
249
}
 
250
 
 
251
 
 
252
//! Creates a point attraction affector. This affector modifies the positions of the
 
253
//! particles and attracts them to a specified point at a specified speed per second.
 
254
IParticleAttractionAffector* CParticleSystemSceneNode::createAttractionAffector(
 
255
        const core::vector3df& point, f32 speed, bool attract,
 
256
        bool affectX, bool affectY, bool affectZ )
 
257
{
 
258
        return new CParticleAttractionAffector( point, speed, attract, affectX, affectY, affectZ );
 
259
}
 
260
 
 
261
//! Creates a scale particle affector.
 
262
IParticleAffector* CParticleSystemSceneNode::createScaleParticleAffector(const core::dimension2df& scaleTo)
 
263
{
 
264
        return new CParticleScaleAffector(scaleTo);
 
265
}
 
266
 
 
267
 
 
268
//! Creates a fade out particle affector.
 
269
IParticleFadeOutAffector* CParticleSystemSceneNode::createFadeOutParticleAffector(
 
270
                const video::SColor& targetColor, u32 timeNeededToFadeOut)
 
271
{
 
272
        return new CParticleFadeOutAffector(targetColor, timeNeededToFadeOut);
 
273
}
 
274
 
 
275
 
 
276
//! Creates a gravity affector.
 
277
IParticleGravityAffector* CParticleSystemSceneNode::createGravityAffector(
 
278
                const core::vector3df& gravity, u32 timeForceLost)
 
279
{
 
280
        return new CParticleGravityAffector(gravity, timeForceLost);
 
281
}
 
282
 
 
283
 
 
284
//! Creates a rotation affector. This affector rotates the particles around a specified pivot
 
285
//! point.  The speed represents Degrees of rotation per second.
 
286
IParticleRotationAffector* CParticleSystemSceneNode::createRotationAffector(
 
287
        const core::vector3df& speed, const core::vector3df& pivotPoint )
 
288
{
 
289
        return new CParticleRotationAffector( speed, pivotPoint );
 
290
}
 
291
 
 
292
 
 
293
//! pre render event
 
294
void CParticleSystemSceneNode::OnRegisterSceneNode()
 
295
{
 
296
        doParticleSystem(os::Timer::getTime());
 
297
 
 
298
        if (IsVisible && (Particles.size() != 0))
 
299
        {
 
300
                SceneManager->registerNodeForRendering(this);
 
301
                ISceneNode::OnRegisterSceneNode();
 
302
        }
 
303
}
 
304
 
 
305
 
 
306
//! render
 
307
void CParticleSystemSceneNode::render()
 
308
{
 
309
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
 
310
        ICameraSceneNode* camera = SceneManager->getActiveCamera();
 
311
 
 
312
        if (!camera || !driver)
 
313
                return;
 
314
 
 
315
 
 
316
#if 0
 
317
        // calculate vectors for letting particles look to camera
 
318
        core::vector3df view(camera->getTarget() - camera->getAbsolutePosition());
 
319
        view.normalize();
 
320
 
 
321
        view *= -1.0f;
 
322
 
 
323
#else
 
324
 
 
325
        const core::matrix4 &m = camera->getViewFrustum()->getTransform( video::ETS_VIEW );
 
326
 
 
327
        const core::vector3df view ( -m[2], -m[6] , -m[10] );
 
328
 
 
329
#endif
 
330
 
 
331
        // reallocate arrays, if they are too small
 
332
        reallocateBuffers();
 
333
 
 
334
        // create particle vertex data
 
335
        s32 idx = 0;
 
336
        for (u32 i=0; i<Particles.size(); ++i)
 
337
        {
 
338
                const SParticle& particle = Particles[i];
 
339
 
 
340
                #if 0
 
341
                        core::vector3df horizontal = camera->getUpVector().crossProduct(view);
 
342
                        horizontal.normalize();
 
343
                        horizontal *= 0.5f * particle.size.Width;
 
344
 
 
345
                        core::vector3df vertical = horizontal.crossProduct(view);
 
346
                        vertical.normalize();
 
347
                        vertical *= 0.5f * particle.size.Height;
 
348
 
 
349
                #else
 
350
                        f32 f;
 
351
 
 
352
                        f = 0.5f * particle.size.Width;
 
353
                        const core::vector3df horizontal ( m[0] * f, m[4] * f, m[8] * f );
 
354
 
 
355
                        f = -0.5f * particle.size.Height;
 
356
                        const core::vector3df vertical ( m[1] * f, m[5] * f, m[9] * f );
 
357
                #endif
 
358
 
 
359
                Buffer->Vertices[0+idx].Pos = particle.pos + horizontal + vertical;
 
360
                Buffer->Vertices[0+idx].Color = particle.color;
 
361
                Buffer->Vertices[0+idx].Normal = view;
 
362
 
 
363
                Buffer->Vertices[1+idx].Pos = particle.pos + horizontal - vertical;
 
364
                Buffer->Vertices[1+idx].Color = particle.color;
 
365
                Buffer->Vertices[1+idx].Normal = view;
 
366
 
 
367
                Buffer->Vertices[2+idx].Pos = particle.pos - horizontal - vertical;
 
368
                Buffer->Vertices[2+idx].Color = particle.color;
 
369
                Buffer->Vertices[2+idx].Normal = view;
 
370
 
 
371
                Buffer->Vertices[3+idx].Pos = particle.pos - horizontal + vertical;
 
372
                Buffer->Vertices[3+idx].Color = particle.color;
 
373
                Buffer->Vertices[3+idx].Normal = view;
 
374
 
 
375
                idx +=4;
 
376
        }
 
377
 
 
378
        // render all
 
379
        core::matrix4 mat;
 
380
        if (!ParticlesAreGlobal)
 
381
                mat.setTranslation(AbsoluteTransformation.getTranslation());
 
382
        driver->setTransform(video::ETS_WORLD, mat);
 
383
 
 
384
        driver->setMaterial(Buffer->Material);
 
385
 
 
386
        driver->drawVertexPrimitiveList(Buffer->getVertices(), Particles.size()*4,
 
387
                Buffer->getIndices(), Particles.size()*2, video::EVT_STANDARD, EPT_TRIANGLES,Buffer->getIndexType());
 
388
 
 
389
        // for debug purposes only:
 
390
        if ( DebugDataVisible & scene::EDS_BBOX )
 
391
        {
 
392
                driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
 
393
                video::SMaterial deb_m;
 
394
                deb_m.Lighting = false;
 
395
                driver->setMaterial(deb_m);
 
396
                driver->draw3DBox(Buffer->BoundingBox, video::SColor(0,255,255,255));
 
397
        }
 
398
}
 
399
 
 
400
 
 
401
//! returns the axis aligned bounding box of this node
 
402
const core::aabbox3d<f32>& CParticleSystemSceneNode::getBoundingBox() const
 
403
{
 
404
        return Buffer->getBoundingBox();
 
405
}
 
406
 
 
407
 
 
408
void CParticleSystemSceneNode::doParticleSystem(u32 time)
 
409
{
 
410
        if (LastEmitTime==0)
 
411
        {
 
412
                LastEmitTime = time;
 
413
                return;
 
414
        }
 
415
 
 
416
        u32 now = time;
 
417
        u32 timediff = time - LastEmitTime;
 
418
        LastEmitTime = time;
 
419
 
 
420
        // run emitter
 
421
 
 
422
        if (Emitter && IsVisible)
 
423
        {
 
424
                SParticle* array = 0;
 
425
                s32 newParticles = Emitter->emitt(now, timediff, array);
 
426
 
 
427
                if (newParticles && array)
 
428
                {
 
429
                        s32 j=Particles.size();
 
430
                        if (newParticles > 16250-j)
 
431
                                newParticles=16250-j;
 
432
                        Particles.set_used(j+newParticles);
 
433
                        for (s32 i=j; i<j+newParticles; ++i)
 
434
                        {
 
435
                                Particles[i]=array[i-j];
 
436
                                AbsoluteTransformation.rotateVect(Particles[i].startVector);
 
437
                                if (ParticlesAreGlobal)
 
438
                                        AbsoluteTransformation.transformVect(Particles[i].pos);
 
439
                        }
 
440
                }
 
441
        }
 
442
 
 
443
        // run affectors
 
444
        core::list<IParticleAffector*>::Iterator ait = AffectorList.begin();
 
445
        for (; ait != AffectorList.end(); ++ait)
 
446
                (*ait)->affect(now, Particles.pointer(), Particles.size());
 
447
 
 
448
        if (ParticlesAreGlobal)
 
449
                Buffer->BoundingBox.reset(AbsoluteTransformation.getTranslation());
 
450
        else
 
451
                Buffer->BoundingBox.reset(core::vector3df(0,0,0));
 
452
 
 
453
        // animate all particles
 
454
        f32 scale = (f32)timediff;
 
455
 
 
456
        for (u32 i=0; i<Particles.size();)
 
457
        {
 
458
                // erase is pretty expensive!
 
459
                if (now > Particles[i].endTime)
 
460
                {
 
461
                        // Particle order does not seem to matter.
 
462
                        // So we can delete by switching with last particle and deleting that one.
 
463
                        // This is a lot faster and speed is very important here as the erase otherwise
 
464
                        // can cause noticable freezes.
 
465
                        Particles[i] = Particles[Particles.size()-1];
 
466
                        Particles.erase( Particles.size()-1 );
 
467
                }
 
468
                else
 
469
                {
 
470
                        Particles[i].pos += (Particles[i].vector * scale);
 
471
                        Buffer->BoundingBox.addInternalPoint(Particles[i].pos);
 
472
                        ++i;
 
473
                }
 
474
        }
 
475
 
 
476
        const f32 m = (ParticleSize.Width > ParticleSize.Height ? ParticleSize.Width : ParticleSize.Height) * 0.5f;
 
477
        Buffer->BoundingBox.MaxEdge.X += m;
 
478
        Buffer->BoundingBox.MaxEdge.Y += m;
 
479
        Buffer->BoundingBox.MaxEdge.Z += m;
 
480
 
 
481
        Buffer->BoundingBox.MinEdge.X -= m;
 
482
        Buffer->BoundingBox.MinEdge.Y -= m;
 
483
        Buffer->BoundingBox.MinEdge.Z -= m;
 
484
 
 
485
        if (ParticlesAreGlobal)
 
486
        {
 
487
                core::matrix4 absinv( AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE );
 
488
                absinv.transformBoxEx(Buffer->BoundingBox);
 
489
        }
 
490
}
 
491
 
 
492
 
 
493
//! Sets if the particles should be global. If it is, the particles are affected by
 
494
//! the movement of the particle system scene node too, otherwise they completely
 
495
//! ignore it. Default is true.
 
496
void CParticleSystemSceneNode::setParticlesAreGlobal(bool global)
 
497
{
 
498
        ParticlesAreGlobal = global;
 
499
}
 
500
 
 
501
//! Remove all currently visible particles
 
502
void CParticleSystemSceneNode::clearParticles()
 
503
{
 
504
        Particles.set_used(0);
 
505
}
 
506
 
 
507
//! Sets the size of all particles.
 
508
void CParticleSystemSceneNode::setParticleSize(const core::dimension2d<f32> &size)
 
509
{
 
510
        os::Printer::log("setParticleSize is deprecated, use setMinStartSize/setMaxStartSize in emitter.", irr::ELL_WARNING);
 
511
        //A bit of a hack, but better here than in the particle code
 
512
        if (Emitter)
 
513
        {
 
514
                Emitter->setMinStartSize(size);
 
515
                Emitter->setMaxStartSize(size);
 
516
        }
 
517
        ParticleSize = size;
 
518
}
 
519
 
 
520
 
 
521
void CParticleSystemSceneNode::reallocateBuffers()
 
522
{
 
523
        if (Particles.size() * 4 > Buffer->getVertexCount() ||
 
524
                        Particles.size() * 6 > Buffer->getIndexCount())
 
525
        {
 
526
                u32 oldSize = Buffer->getVertexCount();
 
527
                Buffer->Vertices.set_used(Particles.size() * 4);
 
528
 
 
529
                u32 i;
 
530
 
 
531
                // fill remaining vertices
 
532
                for (i=oldSize; i<Buffer->Vertices.size(); i+=4)
 
533
                {
 
534
                        Buffer->Vertices[0+i].TCoords.set(0.0f, 0.0f);
 
535
                        Buffer->Vertices[1+i].TCoords.set(0.0f, 1.0f);
 
536
                        Buffer->Vertices[2+i].TCoords.set(1.0f, 1.0f);
 
537
                        Buffer->Vertices[3+i].TCoords.set(1.0f, 0.0f);
 
538
                }
 
539
 
 
540
                // fill remaining indices
 
541
                u32 oldIdxSize = Buffer->getIndexCount();
 
542
                u32 oldvertices = oldSize;
 
543
                Buffer->Indices.set_used(Particles.size() * 6);
 
544
 
 
545
                for (i=oldIdxSize; i<Buffer->Indices.size(); i+=6)
 
546
                {
 
547
                        Buffer->Indices[0+i] = (u16)0+oldvertices;
 
548
                        Buffer->Indices[1+i] = (u16)2+oldvertices;
 
549
                        Buffer->Indices[2+i] = (u16)1+oldvertices;
 
550
                        Buffer->Indices[3+i] = (u16)0+oldvertices;
 
551
                        Buffer->Indices[4+i] = (u16)3+oldvertices;
 
552
                        Buffer->Indices[5+i] = (u16)2+oldvertices;
 
553
                        oldvertices += 4;
 
554
                }
 
555
        }
 
556
}
 
557
 
 
558
 
 
559
//! Writes attributes of the scene node.
 
560
void CParticleSystemSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
 
561
{
 
562
        IParticleSystemSceneNode::serializeAttributes(out, options);
 
563
 
 
564
        out->addBool("GlobalParticles", ParticlesAreGlobal);
 
565
        out->addFloat("ParticleWidth", ParticleSize.Width);
 
566
        out->addFloat("ParticleHeight", ParticleSize.Height);
 
567
 
 
568
        // write emitter
 
569
 
 
570
        E_PARTICLE_EMITTER_TYPE type = EPET_COUNT;
 
571
        if (Emitter)
 
572
                type = Emitter->getType();
 
573
 
 
574
        out->addEnum("Emitter", (s32)type, ParticleEmitterTypeNames);
 
575
 
 
576
        if (Emitter)
 
577
                Emitter->serializeAttributes(out, options);
 
578
 
 
579
        // write affectors
 
580
 
 
581
        E_PARTICLE_AFFECTOR_TYPE atype = EPAT_NONE;
 
582
 
 
583
        for (core::list<IParticleAffector*>::ConstIterator it = AffectorList.begin();
 
584
                it != AffectorList.end(); ++it)
 
585
        {
 
586
                atype = (*it)->getType();
 
587
 
 
588
                out->addEnum("Affector", (s32)atype, ParticleAffectorTypeNames);
 
589
 
 
590
                (*it)->serializeAttributes(out);
 
591
        }
 
592
 
 
593
        // add empty affector to make it possible to add further affectors
 
594
 
 
595
        if (options && options->Flags & io::EARWF_FOR_EDITOR)
 
596
                out->addEnum("Affector", EPAT_NONE, ParticleAffectorTypeNames);
 
597
}
 
598
 
 
599
 
 
600
//! Reads attributes of the scene node.
 
601
void CParticleSystemSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
 
602
{
 
603
        IParticleSystemSceneNode::deserializeAttributes(in, options);
 
604
 
 
605
        ParticlesAreGlobal = in->getAttributeAsBool("GlobalParticles");
 
606
        ParticleSize.Width = in->getAttributeAsFloat("ParticleWidth");
 
607
        ParticleSize.Height = in->getAttributeAsFloat("ParticleHeight");
 
608
 
 
609
        // read emitter
 
610
 
 
611
        int emitterIdx = in->findAttribute("Emitter");
 
612
        if (emitterIdx == -1)
 
613
                return;
 
614
 
 
615
        if (Emitter)
 
616
                Emitter->drop();
 
617
        Emitter = 0;
 
618
 
 
619
        E_PARTICLE_EMITTER_TYPE type = (E_PARTICLE_EMITTER_TYPE)
 
620
                in->getAttributeAsEnumeration("Emitter", ParticleEmitterTypeNames);
 
621
 
 
622
        switch(type)
 
623
        {
 
624
        case EPET_POINT:
 
625
                Emitter = createPointEmitter();
 
626
                break;
 
627
        case EPET_ANIMATED_MESH:
 
628
                Emitter = createAnimatedMeshSceneNodeEmitter(NULL); // we can't set the node - the user will have to do this
 
629
                break;
 
630
        case EPET_BOX:
 
631
                Emitter = createBoxEmitter();
 
632
                break;
 
633
        case EPET_CYLINDER:
 
634
                Emitter = createCylinderEmitter(core::vector3df(0,0,0), 10.f, core::vector3df(0,1,0), 10.f);    // (values here don't matter)
 
635
                break;
 
636
        case EPET_MESH:
 
637
                Emitter = createMeshEmitter(NULL);      // we can't set the mesh - the user will have to do this
 
638
                break;
 
639
        case EPET_RING:
 
640
                Emitter = createRingEmitter(core::vector3df(0,0,0), 10.f, 10.f);        // (values here don't matter)
 
641
                break;
 
642
        case EPET_SPHERE:
 
643
                Emitter = createSphereEmitter(core::vector3df(0,0,0), 10.f);    // (values here don't matter)
 
644
                break;
 
645
        default:
 
646
                break;
 
647
        }
 
648
 
 
649
        u32 idx = 0;
 
650
 
 
651
#if 0
 
652
        if (Emitter)
 
653
                idx = Emitter->deserializeAttributes(idx, in);
 
654
 
 
655
        ++idx;
 
656
#else
 
657
        if (Emitter)
 
658
                Emitter->deserializeAttributes(in);
 
659
#endif
 
660
 
 
661
        // read affectors
 
662
 
 
663
        removeAllAffectors();
 
664
        u32 cnt = in->getAttributeCount();
 
665
 
 
666
        while(idx < cnt)
 
667
        {
 
668
                const char* name = in->getAttributeName(idx);
 
669
 
 
670
                if (!name || strcmp("Affector", name))
 
671
                        return;
 
672
 
 
673
                E_PARTICLE_AFFECTOR_TYPE atype =
 
674
                        (E_PARTICLE_AFFECTOR_TYPE)in->getAttributeAsEnumeration(idx, ParticleAffectorTypeNames);
 
675
 
 
676
                IParticleAffector* aff = 0;
 
677
 
 
678
                switch(atype)
 
679
                {
 
680
                case EPAT_ATTRACT:
 
681
                        aff = createAttractionAffector(core::vector3df(0,0,0));
 
682
                        break;
 
683
                case EPAT_FADE_OUT:
 
684
                        aff = createFadeOutParticleAffector();
 
685
                        break;
 
686
                case EPAT_GRAVITY:
 
687
                        aff = createGravityAffector();
 
688
                        break;
 
689
                case EPAT_ROTATE:
 
690
                        aff = createRotationAffector();
 
691
                        break;
 
692
                case EPAT_SCALE:
 
693
                        aff = createScaleParticleAffector();
 
694
                        break;
 
695
                case EPAT_NONE:
 
696
                default:
 
697
                        break;
 
698
                }
 
699
 
 
700
                ++idx;
 
701
 
 
702
                if (aff)
 
703
                {
 
704
#if 0
 
705
                        idx = aff->deserializeAttributes(idx, in, options);
 
706
                        ++idx;
 
707
#else
 
708
                        aff->deserializeAttributes(in, options);
 
709
#endif
 
710
 
 
711
                        addAffector(aff);
 
712
                        aff->drop();
 
713
                }
 
714
        }
 
715
}
 
716
 
 
717
 
 
718
} // end namespace scene
 
719
} // end namespace irr
 
720
 
 
721