Commit 28dd2521 authored by hybrid's avatar hybrid

Add random number generator frand() for interval [0..1] which fixes many...

Add random number generator frand() for interval [0..1] which fixes many issues with current usage of rand() in the particle emitters. Thanks to vitek for the initial ideas, CuteAlien for the new method suggestions, and Auria for bringing this up again.
TODO: Test cases, which would need a public interface to this class first...

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3538 dfc29bdd-3216-0410-991c-e03cc46cb475
parent a8f35e0d
...@@ -44,7 +44,7 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, ...@@ -44,7 +44,7 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall,
Time += timeSinceLastCall; Time += timeSinceLastCall;
const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
const f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
const f32 everyWhatMillisecond = 1000.0f / perSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond;
if(Time > everyWhatMillisecond) if(Time > everyWhatMillisecond)
...@@ -80,19 +80,20 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, ...@@ -80,19 +80,20 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall,
if( MaxAngleDegrees ) if( MaxAngleDegrees )
{ {
core::vector3df tgt = p.vector; core::vector3df tgt = p.vector;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -100,8 +101,7 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, ...@@ -100,8 +101,7 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall,
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
...@@ -133,19 +133,20 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, ...@@ -133,19 +133,20 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall,
if( MaxAngleDegrees ) if( MaxAngleDegrees )
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -153,8 +154,7 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall, ...@@ -153,8 +154,7 @@ s32 CParticleAnimatedMeshSceneNodeEmitter::emitt(u32 now, u32 timeSinceLastCall,
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
......
...@@ -40,7 +40,7 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr ...@@ -40,7 +40,7 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr
Time += timeSinceLastCall; Time += timeSinceLastCall;
const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
const f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
const f32 everyWhatMillisecond = 1000.0f / perSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond;
if (Time > everyWhatMillisecond) if (Time > everyWhatMillisecond)
...@@ -56,9 +56,9 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr ...@@ -56,9 +56,9 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr
for (u32 i=0; i<amount; ++i) for (u32 i=0; i<amount; ++i)
{ {
p.pos.X = Box.MinEdge.X + fmodf((f32)os::Randomizer::rand(), extent.X); p.pos.X = Box.MinEdge.X + os::Randomizer::frand() * extent.X;
p.pos.Y = Box.MinEdge.Y + fmodf((f32)os::Randomizer::rand(), extent.Y); p.pos.Y = Box.MinEdge.Y + os::Randomizer::frand() * extent.Y;
p.pos.Z = Box.MinEdge.Z + fmodf((f32)os::Randomizer::rand(), extent.Z); p.pos.Z = Box.MinEdge.Z + os::Randomizer::frand() * extent.Z;
p.startTime = now; p.startTime = now;
p.vector = Direction; p.vector = Direction;
...@@ -66,19 +66,20 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr ...@@ -66,19 +66,20 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr
if (MaxAngleDegrees) if (MaxAngleDegrees)
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if (MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -86,8 +87,7 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr ...@@ -86,8 +87,7 @@ s32 CParticleBoxEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outAr
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
......
...@@ -43,7 +43,7 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ...@@ -43,7 +43,7 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*&
Time += timeSinceLastCall; Time += timeSinceLastCall;
const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
const f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
const f32 everyWhatMillisecond = 1000.0f / perSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond;
if(Time > everyWhatMillisecond) if(Time > everyWhatMillisecond)
...@@ -59,18 +59,14 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ...@@ -59,18 +59,14 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*&
for(u32 i=0; i<amount; ++i) for(u32 i=0; i<amount; ++i)
{ {
// Random distance from center if outline only is not true // Random distance from center if outline only is not true
f32 distance; const f32 distance = (!OutlineOnly) ? (os::Randomizer::frand() * Radius) : Radius;
if( !OutlineOnly )
distance = fmodf( (f32)os::Randomizer::rand(), Radius * 1000.0f ) * 0.001f;
else
distance = Radius;
// Random direction from center // Random direction from center
p.pos.set(Center.X + distance, Center.Y, Center.Z + distance); p.pos.set(Center.X + distance, Center.Y, Center.Z + distance);
p.pos.rotateXZBy( os::Randomizer::rand() % 360, Center ); p.pos.rotateXZBy(os::Randomizer::frand() * 360, Center);
// Random length // Random length
const f32 length = fmodf( (f32)os::Randomizer::rand(), Length * 1000.0f ) * 0.001f; const f32 length = os::Randomizer::frand() * Length;
// Random point along the cylinders length // Random point along the cylinders length
p.pos += Normal * length; p.pos += Normal * length;
...@@ -81,19 +77,20 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ...@@ -81,19 +77,20 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*&
if( MaxAngleDegrees ) if( MaxAngleDegrees )
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df()); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df()); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df()); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -101,8 +98,7 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ...@@ -101,8 +98,7 @@ s32 CParticleCylinderEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*&
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
......
...@@ -44,7 +44,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -44,7 +44,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
Time += timeSinceLastCall; Time += timeSinceLastCall;
const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
const f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
const f32 everyWhatMillisecond = 1000.0f / perSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond;
if(Time > everyWhatMillisecond) if(Time > everyWhatMillisecond)
...@@ -77,19 +77,20 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -77,19 +77,20 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
if( MaxAngleDegrees ) if( MaxAngleDegrees )
{ {
core::vector3df tgt = p.vector; core::vector3df tgt = p.vector;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df(0,0,0)); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df(0,0,0)); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df(0,0,0)); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -97,8 +98,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -97,8 +98,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
...@@ -107,16 +107,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -107,16 +107,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
} }
else else
{ {
s32 randomMB = 0; const s32 randomMB = (MBNumber < 0) ? (os::Randomizer::rand() % MBCount) : MBNumber;
if( MBNumber < 0 )
{
randomMB = os::Randomizer::rand() % MBCount;
}
else
{
randomMB = MBNumber;
}
u32 vertexNumber = Mesh->getMeshBuffer(randomMB)->getVertexCount(); u32 vertexNumber = Mesh->getMeshBuffer(randomMB)->getVertexCount();
if (!vertexNumber) if (!vertexNumber)
...@@ -135,19 +126,20 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -135,19 +126,20 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
if( MaxAngleDegrees ) if( MaxAngleDegrees )
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df(0,0,0)); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df(0,0,0)); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, core::vector3df(0,0,0)); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -155,8 +147,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -155,8 +147,7 @@ s32 CParticleMeshEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
......
...@@ -40,7 +40,7 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out ...@@ -40,7 +40,7 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out
Time += timeSinceLastCall; Time += timeSinceLastCall;
const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
const f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
const f32 everyWhatMillisecond = 1000.0f / perSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond;
if (Time > everyWhatMillisecond) if (Time > everyWhatMillisecond)
...@@ -52,19 +52,20 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out ...@@ -52,19 +52,20 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out
if (MaxAngleDegrees) if (MaxAngleDegrees)
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
Particle.vector = tgt; Particle.vector = tgt;
} }
if (MaxLifeTime - MinLifeTime == 0)
Particle.endTime = now + MinLifeTime; Particle.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
Particle.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); Particle.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
Particle.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); Particle.color=MinStartColor;
else
Particle.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
Particle.startColor = Particle.color; Particle.startColor = Particle.color;
Particle.startVector = Particle.vector; Particle.startVector = Particle.vector;
...@@ -72,8 +73,7 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out ...@@ -72,8 +73,7 @@ s32 CParticlePointEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& out
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
Particle.startSize = MinStartSize; Particle.startSize = MinStartSize;
else else
Particle.startSize = MinStartSize.getInterpolated( Particle.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
Particle.size = Particle.startSize; Particle.size = Particle.startSize;
outArray = &Particle; outArray = &Particle;
......
...@@ -42,7 +42,7 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -42,7 +42,7 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
Time += timeSinceLastCall; Time += timeSinceLastCall;
u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
f32 everyWhatMillisecond = 1000.0f / perSecond; f32 everyWhatMillisecond = 1000.0f / perSecond;
if(Time > everyWhatMillisecond) if(Time > everyWhatMillisecond)
...@@ -57,14 +57,14 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -57,14 +57,14 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
for(u32 i=0; i<amount; ++i) for(u32 i=0; i<amount; ++i)
{ {
f32 distance = fmodf( (f32)os::Randomizer::rand(), RingThickness * 0.5f * 1000.0f ) * 0.001f; f32 distance = os::Randomizer::frand() * RingThickness * 0.5f;
s32 plusMinus = os::Randomizer::rand() % 2; if (os::Randomizer::rand() % 2)
if( plusMinus ) distance -= Radius;
distance *= -1.0f; else
distance += Radius; distance += Radius;
p.pos.set(Center.X + distance, Center.Y, Center.Z + distance); p.pos.set(Center.X + distance, Center.Y, Center.Z + distance);
p.pos.rotateXZBy( ( os::Randomizer::rand() % 3600 ) * 0.1f, Center ); p.pos.rotateXZBy(os::Randomizer::frand() * 360, Center );
p.startTime = now; p.startTime = now;
p.vector = Direction; p.vector = Direction;
...@@ -72,19 +72,20 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -72,19 +72,20 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
if(MaxAngleDegrees) if(MaxAngleDegrees)
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, Center ); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees, Center );
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, Center ); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees, Center );
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees, Center ); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees, Center );
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -92,8 +93,7 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA ...@@ -92,8 +93,7 @@ s32 CParticleRingEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& outA
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
......
...@@ -43,7 +43,7 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou ...@@ -43,7 +43,7 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou
Time += timeSinceLastCall; Time += timeSinceLastCall;
const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond); const u32 pps = (MaxParticlesPerSecond - MinParticlesPerSecond);
const f32 perSecond = pps ? (f32)MinParticlesPerSecond + (os::Randomizer::rand() % pps) : MinParticlesPerSecond; const f32 perSecond = pps ? ((f32)MinParticlesPerSecond + os::Randomizer::frand() * pps) : MinParticlesPerSecond;
const f32 everyWhatMillisecond = 1000.0f / perSecond; const f32 everyWhatMillisecond = 1000.0f / perSecond;
if(Time > everyWhatMillisecond) if(Time > everyWhatMillisecond)
...@@ -59,13 +59,13 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou ...@@ -59,13 +59,13 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou
for(u32 i=0; i<amount; ++i) for(u32 i=0; i<amount; ++i)
{ {
// Random distance from center // Random distance from center
f32 distance = fmodf( (f32)os::Randomizer::rand(), Radius * 1000.0f ) * 0.001f; const f32 distance = os::Randomizer::rand() * Radius;
// Random direction from center // Random direction from center
p.pos.set(Center + distance); p.pos.set(Center + distance);
p.pos.rotateXYBy( os::Randomizer::rand() % 360, Center ); p.pos.rotateXYBy(os::Randomizer::frand() * 360.f, Center );
p.pos.rotateYZBy( os::Randomizer::rand() % 360, Center ); p.pos.rotateYZBy(os::Randomizer::frand() * 360.f, Center );
p.pos.rotateXZBy( os::Randomizer::rand() % 360, Center ); p.pos.rotateXZBy(os::Randomizer::frand() * 360.f, Center );
p.startTime = now; p.startTime = now;
p.vector = Direction; p.vector = Direction;
...@@ -73,19 +73,20 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou ...@@ -73,19 +73,20 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou
if(MaxAngleDegrees) if(MaxAngleDegrees)
{ {
core::vector3df tgt = Direction; core::vector3df tgt = Direction;
tgt.rotateXYBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXYBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateYZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateYZBy(os::Randomizer::frand() * MaxAngleDegrees);
tgt.rotateXZBy((os::Randomizer::rand()%(MaxAngleDegrees*2)) - MaxAngleDegrees); tgt.rotateXZBy(os::Randomizer::frand() * MaxAngleDegrees);
p.vector = tgt; p.vector = tgt;
} }
if(MaxLifeTime - MinLifeTime == 0)
p.endTime = now + MinLifeTime; p.endTime = now + MinLifeTime;
else if (MaxLifeTime != MinLifeTime)
p.endTime = now + MinLifeTime + (os::Randomizer::rand() % (MaxLifeTime - MinLifeTime)); p.endTime += os::Randomizer::rand() % (MaxLifeTime - MinLifeTime);
p.color = MinStartColor.getInterpolated( if (MinStartColor==MaxStartColor)
MaxStartColor, (os::Randomizer::rand() % 100) / 100.0f); p.color=MinStartColor;
else
p.color = MinStartColor.getInterpolated(MaxStartColor, os::Randomizer::frand());
p.startColor = p.color; p.startColor = p.color;
p.startVector = p.vector; p.startVector = p.vector;
...@@ -93,8 +94,7 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou ...@@ -93,8 +94,7 @@ s32 CParticleSphereEmitter::emitt(u32 now, u32 timeSinceLastCall, SParticle*& ou
if (MinStartSize==MaxStartSize) if (MinStartSize==MaxStartSize)
p.startSize = MinStartSize; p.startSize = MinStartSize;
else else
p.startSize = MinStartSize.getInterpolated( p.startSize = MinStartSize.getInterpolated(MaxStartSize, os::Randomizer::frand());
MaxStartSize, (os::Randomizer::rand() % 100) / 100.0f);
p.size = p.startSize; p.size = p.startSize;
Particles.push_back(p); Particles.push_back(p);
......
...@@ -202,17 +202,25 @@ namespace os ...@@ -202,17 +202,25 @@ namespace os
//! generates a pseudo random number //! generates a pseudo random number
s32 Randomizer::rand() s32 Randomizer::rand()
{ {
const s32 m = 2147483399; // a non-Mersenne prime // (a*seed)%m with Schrage's method
const s32 a = 40692; // another spectral success story
const s32 q = m/a;
const s32 r = m%a; // again less than q
seed = a * (seed%q) - r* (seed/q); seed = a * (seed%q) - r* (seed/q);
if (seed<0) seed += m; if (seed<0)
seed += m;
return seed; return seed;
} }
//! generates a pseudo random number
f32 Randomizer::frand()
{
return rand()*(1.f/rMax);
}
s32 Randomizer::randMax()
{
return rMax;
}
//! resets the randomizer //! resets the randomizer
void Randomizer::reset() void Randomizer::reset()
{ {
......
...@@ -43,6 +43,9 @@ namespace os ...@@ -43,6 +43,9 @@ namespace os
}; };
// mixed linear congruential generator (MLCG)
// numbers chosen according to L'Ecuyer, Commun. ACM 31 (1988) 742
// period is somewhere around m-1
class Randomizer class Randomizer
{ {
public: public:
...@@ -50,12 +53,23 @@ namespace os ...@@ -50,12 +53,23 @@ namespace os
//! resets the randomizer //! resets the randomizer
static void reset(); static void reset();
//! generates a pseudo random number //! generates a pseudo random number in the range 0..randMax()
static s32 rand(); static s32 rand();
//! generates a pseudo random number in the range 0..1
static f32 frand();
//! get maxmimum number generated by rand()
static s32 randMax();
private: private:
static s32 seed; static s32 seed;
static const s32 m = 2147483399; // a non-Mersenne prime
static const s32 a = 40692; // another spectral success story
static const s32 q = m/a;
static const s32 r = m%a; // again less than q
static const s32 rMax = m-1;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment