1 // Copyright (C) 2002-2012 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 "IrrCompileConfig.h"
6 #include "CParticleSphereEmitter.h"
7 #include "os.h"
8 #include "IAttributes.h"
9 
10 namespace irr
11 {
12 namespace scene
13 {
14 
15 //! constructor
CParticleSphereEmitter(const core::vector3df & center,f32 radius,const core::vector3df & direction,u32 minParticlesPerSecond,u32 maxParticlesPerSecond,const video::SColor & minStartColor,const video::SColor & maxStartColor,u32 lifeTimeMin,u32 lifeTimeMax,s32 maxAngleDegrees,const core::dimension2df & minStartSize,const core::dimension2df & maxStartSize)16 CParticleSphereEmitter::CParticleSphereEmitter(
17 	const core::vector3df& center, f32 radius,
18 	const core::vector3df& direction, u32 minParticlesPerSecond,
19 	u32 maxParticlesPerSecond, const video::SColor& minStartColor,
20 	const video::SColor& maxStartColor, u32 lifeTimeMin, u32 lifeTimeMax,
21 	s32 maxAngleDegrees,
22 	const core::dimension2df& minStartSize,
23 	const core::dimension2df& maxStartSize )
24 	: Center(center), Radius(radius), Direction(direction),
25 	MinStartSize(minStartSize), MaxStartSize(maxStartSize),
26 	MinParticlesPerSecond(minParticlesPerSecond),
27 	MaxParticlesPerSecond(maxParticlesPerSecond),
28 	MinStartColor(minStartColor), MaxStartColor(maxStartColor),
29 	MinLifeTime(lifeTimeMin), MaxLifeTime(lifeTimeMax),
30 	Time(0), Emitted(0), MaxAngleDegrees(maxAngleDegrees)
31 {
32 	#ifdef _DEBUG
33 	setDebugName("CParticleSphereEmitter");
34 	#endif
35 
36 }
37 
38 
39 //! Prepares an array with new particles to emitt into the system
40 //! and returns how much new particles there are.
emitt(u32 now,u32 timeSinceLastCall,SParticle * & outArray)41 s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outArray)
42 {
43 	Time += timeSinceLastCall;
44 
45 	const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
46 	const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
47 	const f32 everyWhatMillisecond = 1000.0f / perSecond;
48 
49 	if(Time > everyWhatMillisecond)
50 	{
51 		Particles.set_used(0);
52 		u32 amount = (u32)((Time / everyWhatMillisecond) + 0.5f);
53 		Time = 0;
54 		SParticle p;
55 
56 		if(amount > MaxParticlesPerSecond*2)
57 			amount = MaxParticlesPerSecond * 2;
58 
59 		for(u32 i=0; i<amount; ++i)
60 		{
61 			// Random distance from center
62 			const f32 distance = os::Randomizer::frand() * Radius;
63 
64 			// Random direction from center
65 			p.pos.set(Center + distance);
66 			p.pos.rotateXYBy(os::Randomizer::frand() * 360.f, Center );
67 			p.pos.rotateYZBy(os::Randomizer::frand() * 360.f, Center );
68 			p.pos.rotateXZBy(os::Randomizer::frand() * 360.f, Center );
69 
70 			p.startTime = now;
71 			p.vector = Direction;
72 
73 			if(MaxAngleDegrees)
74 			{
75 				core::vector3df tgt = Direction;
76 				tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
77 				tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
78 				tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
79 				p.vector = tgt;
80 			}
81 
82 			p.endTime = now + MinLifeTime;
83 			if (MaxLifeTime != MinLifeTime)
84 				p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
85 
86 			if (MinStartColor==MaxStartColor)
87 				p.color=MinStartColor;
88 			else
89 				p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
90 
91 			p.startColor = p.color;
92 			p.startVector = p.vector;
93 
94 			if (MinStartSize==MaxStartSize)
95 				p.startSize = MinStartSize;
96 			else
97 				p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
98 			p.size = p.startSize;
99 
100 			Particles.push_back(p);
101 		}
102 
103 		outArray = Particles.pointer();
104 
105 		return Particles.size();
106 	}
107 
108 	return 0;
109 }
110 
111 //! Writes attributes of the object.
serializeAttributes(io::IAttributes * out,io::SAttributeReadWriteOptions * options) const112 void CParticleSphereEmitter::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
113 {
114 	out->addVector3d("Center", Direction);
115 	out->addFloat("Radius", Radius);
116 
117 	out->addVector3d("Direction", Direction);
118 	out->addFloat("MinStartSizeWidth", MinStartSize.Width);
119 	out->addFloat("MinStartSizeHeight", MinStartSize.Height);
120 	out->addFloat("MaxStartSizeWidth", MaxStartSize.Width);
121 	out->addFloat("MaxStartSizeHeight", MaxStartSize.Height);
122 	out->addInt("MinParticlesPerSecond", MinParticlesPerSecond);
123 	out->addInt("MaxParticlesPerSecond", MaxParticlesPerSecond);
124 	out->addColor("MinStartColor", MinStartColor);
125 	out->addColor("MaxStartColor", MaxStartColor);
126 	out->addInt("MinLifeTime", MinLifeTime);
127 	out->addInt("MaxLifeTime", MaxLifeTime);
128 	out->addInt("MaxAngleDegrees", MaxAngleDegrees);
129 }
130 
131 //! Reads attributes of the object.
deserializeAttributes(io::IAttributes * in,io::SAttributeReadWriteOptions * options)132 void CParticleSphereEmitter::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
133 {
134 	Center = in->getAttributeAsVector3d("Center");
135 	Radius = in->getAttributeAsFloat("Radius");
136 
137 	Direction = in->getAttributeAsVector3d("Direction");
138 	if (Direction.getLength() == 0)
139 		Direction.set(0,0.01f,0);
140 
141 	int idx = -1;
142 	idx = in->findAttribute("MinStartSizeWidth");
143 	if ( idx >= 0 )
144 		MinStartSize.Width = in->getAttributeAsFloat(idx);
145 	idx = in->findAttribute("MinStartSizeHeight");
146 	if ( idx >= 0 )
147 		MinStartSize.Height = in->getAttributeAsFloat(idx);
148 	idx = in->findAttribute("MaxStartSizeWidth");
149 	if ( idx >= 0 )
150 		MaxStartSize.Width = in->getAttributeAsFloat(idx);
151 	idx = in->findAttribute("MaxStartSizeHeight");
152 	if ( idx >= 0 )
153 		MaxStartSize.Height = in->getAttributeAsFloat(idx);
154 	MinParticlesPerSecond = in->getAttributeAsInt("MinParticlesPerSecond");
155 	MaxParticlesPerSecond = in->getAttributeAsInt("MaxParticlesPerSecond");
156 
157 	MinParticlesPerSecond = core::max_(1u, MinParticlesPerSecond);
158 	MaxParticlesPerSecond = core::max_(MaxParticlesPerSecond, 1u);
159 	MaxParticlesPerSecond = core::min_(MaxParticlesPerSecond, 200u);
160 	MinParticlesPerSecond = core::min_(MinParticlesPerSecond, MaxParticlesPerSecond);
161 
162 	MinStartColor = in->getAttributeAsColor("MinStartColor");
163 	MaxStartColor = in->getAttributeAsColor("MaxStartColor");
164 	MinLifeTime = in->getAttributeAsInt("MinLifeTime");
165 	MaxLifeTime = in->getAttributeAsInt("MaxLifeTime");
166 	MinLifeTime = core::max_(0u, MinLifeTime);
167 	MaxLifeTime = core::max_(MaxLifeTime, MinLifeTime);
168 	MinLifeTime = core::min_(MinLifeTime, MaxLifeTime);
169 
170 	MaxAngleDegrees = in->getAttributeAsInt("MaxAngleDegrees");
171 }
172 
173 } // end namespace scene
174 } // end namespace irr
175 
176