protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single deltaPitch = this.RotationRate.X * deltaSeconds; Single deltaYaw = this.RotationRate.Y * deltaSeconds; Single deltaRoll = this.RotationRate.Z * deltaSeconds; var particle = iterator.First; do { #if UNSAFE particle->Rotation.X += deltaPitch; particle->Rotation.Y += deltaYaw; particle->Rotation.Z += deltaRoll; #else particle.Rotation.X += deltaPitch; particle.Rotation.Y += deltaYaw; particle.Rotation.Z += deltaRoll; #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single initialForceDeltaX = this.InitialForce.X * deltaSeconds; Single initialForceDeltaY = this.InitialForce.Y * deltaSeconds; Single initialForceDeltaZ = this.InitialForce.Z * deltaSeconds; Single finalForceDeltaX = this.FinalForce.X * deltaSeconds; Single finalForceDeltaY = this.FinalForce.Y * deltaSeconds; Single finalForceDeltaZ = this.FinalForce.Z * deltaSeconds; var particle = iterator.First; do { #if UNSAFE particle->Velocity.X += initialForceDeltaX + ((finalForceDeltaX - initialForceDeltaX) * particle->Age); particle->Velocity.Y += initialForceDeltaY + ((finalForceDeltaY - initialForceDeltaY) * particle->Age); particle->Velocity.Z += initialForceDeltaZ + ((finalForceDeltaZ - initialForceDeltaZ) * particle->Age); #else particle.Velocity.X += initialForceDeltaX + ((finalForceDeltaX - initialForceDeltaX) * particle.Age); particle.Velocity.Y += initialForceDeltaY + ((finalForceDeltaY - initialForceDeltaY) * particle.Age); particle.Velocity.Z += initialForceDeltaZ + ((finalForceDeltaZ - initialForceDeltaZ) * particle.Age); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single inverseCoefficientDelta = -(this.DampingCoefficient * deltaSeconds); var particle = iterator.First; do { #if UNSAFE particle->Velocity.X += particle->Velocity.X * inverseCoefficientDelta; particle->Velocity.Y += particle->Velocity.Y * inverseCoefficientDelta; particle->Velocity.Z += particle->Velocity.Z * inverseCoefficientDelta; #else particle.Velocity.X += particle.Velocity.X * inverseCoefficientDelta; particle.Velocity.Y += particle.Velocity.Y * inverseCoefficientDelta; particle.Velocity.Z += particle.Velocity.Z * inverseCoefficientDelta; #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Vector3 initialColour = this.InitialColour; Vector3 delta = this.FinalColour - initialColour; var particle = iterator.First; do { #if UNSAFE particle->Colour.X = (initialColour.X + (delta.X * particle->Age)); particle->Colour.Y = (initialColour.Y + (delta.Y * particle->Age)); particle->Colour.Z = (initialColour.Z + (delta.Z * particle->Age)); #else particle.Colour.X = (initialColour.X + (delta.X * particle.Age)); particle.Colour.Y = (initialColour.Y + (delta.Y * particle.Age)); particle.Colour.Z = (initialColour.Z + (delta.Z * particle.Age)); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single deltaStrength = this.Strength * deltaSeconds; Single deltaGravityX = this.GravityVector.X * deltaStrength; Single deltaGravityY = this.GravityVector.Y * deltaStrength; Single deltaGravityZ = this.GravityVector.Z * deltaStrength; var particle = iterator.First; do { #if UNSAFE particle->Velocity.X += deltaGravityX; particle->Velocity.Y += deltaGravityY; particle->Velocity.Z += deltaGravityZ; #else particle.Velocity.X += deltaGravityX; particle.Velocity.Y += deltaGravityY; particle.Velocity.Z += deltaGravityZ; #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { var particle = iterator.First; do { #if UNSAFE Single age = particle->Age; #else Single age = particle.Age; #endif if (age < this.Median) #if UNSAFE particle->Colour.W = this.InitialOpacity + ((this.MedianOpacity - this.InitialOpacity) * (age / this.Median)); #else particle.Colour.W = this.InitialOpacity + ((this.MedianOpacity - this.InitialOpacity) * (age / this.Median)); #endif else #if UNSAFE particle->Colour.W = this.MedianOpacity + ((this.FinalOpacity - this.MedianOpacity) * ((age - this.Median) / (1f - this.Median))); #else particle.Colour.W = this.MedianOpacity + ((this.FinalOpacity - this.MedianOpacity) * ((age - this.Median) / (1f - this.Median))); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
public unsafe ParticleBuffer(int size) { Size = size; // add one extra spot in memory for margin between head and tail // so the iterator can see that it's at the end _nativePointer = Marshal.AllocHGlobal(SizeInBytes); BufferEnd = (Particle*)(_nativePointer + SizeInBytes); Head = (Particle*)_nativePointer; Tail = (Particle*)_nativePointer; _iterator = new ParticleIterator(this); GC.AddMemoryPressure(SizeInBytes); }
/// <summary> /// Performs rendering of particles. /// </summary> /// <param name="iterator">The particle iterator object.</param> /// <param name="context">The render context containing rendering information.</param> protected override void Render(ref RenderContext context, ref ParticleIterator iterator) { Vector2 origin = new Vector2(context.Texture.Width / 2f, context.Texture.Height / 2f); this.SpriteBatch.Begin(SpriteSortMode.Deferred, context.BlendState, SamplerState.PointClamp, DepthStencilState.None, RasterizerState.CullNone, null, this.Transformation); { #if UNSAFE unsafe { Particle* particle = iterator.First; #else Particle particle = iterator.First; #endif do { #if UNSAFE Single scale = particle->Scale / context.Texture.Width; Vector2 position = new Vector2 { X = particle->Position.X, Y = particle->Position.Y }; this.SpriteBatch.Draw(context.Texture, position, null, new Color(particle->Colour), particle->Rotation.Z, origin, scale, SpriteEffects.None, 0f); #else Single scale = particle.Scale / context.Texture.Width; Vector2 position = new Vector2 { X = particle.Position.X, Y = particle.Position.Y }; this.SpriteBatch.Draw(context.Texture, position, null, new Color(particle.Colour), particle.Rotation.Z, origin, scale, SpriteEffects.None, 0f); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif #if UNSAFE } #endif this.SpriteBatch.End(); } }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single squareRadius = (this.Radius * this.Radius); Single deltaStrength = this.Strength * deltaSeconds; Single deltaForceX = this.ForceVector.X * deltaStrength; Single deltaForceY = this.ForceVector.Y * deltaStrength; Single deltaForceZ = this.ForceVector.Z * deltaStrength; Vector3 forcePosition = this.Position; var particle = iterator.First; do { #if UNSAFE Vector3 position = particle->Position; #else Vector3 position = particle.Position; #endif Single distanceX = forcePosition.X - position.X; Single distanceY = forcePosition.Y - position.Y; Single distanceZ = forcePosition.Z - position.Z; Single squareDistance = ((distanceX * distanceX) + (distanceY * distanceY) + (distanceZ * distanceZ)); if (squareDistance < squareRadius) { #if UNSAFE particle->Velocity.X += deltaForceX; particle->Velocity.Y += deltaForceY; particle->Velocity.Z += deltaForceZ; #else particle.Velocity.X += deltaForceX; particle.Velocity.Y += deltaForceY; particle.Velocity.Z += deltaForceZ; #endif } } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single h = ((this.HueShift * deltaSeconds) * Calculator.Pi) / 180f; Single u = Calculator.Cos(h); Single w = Calculator.Sin(h); Matrix hueTransform = new Matrix(1f, 0f, 0f, 0f, 0f, u, -w, 0f, 0f, w, u, 0f, 0f, 0f, 0f, 1f); var particle = iterator.First; #if UNSAFE Vector4 colour = particle->Colour; #else Vector4 colour = particle.Colour; #endif do { // Convert the current colour of the particle to YIQ colour space... Vector4.Transform(ref colour, ref HueShiftModifier.YiqTransform, out colour); // Transform the colour in YIQ space... Vector4.Transform(ref colour, ref hueTransform, out colour); // Convert the colour back to RGB space... Vector4.Transform(ref colour, ref HueShiftModifier.RgbTransform, out colour); #if UNSAFE particle->Colour.X = colour.X; particle->Colour.Y = colour.Y; particle->Colour.Z = colour.Z; #else particle.Colour.X = colour.X; particle.Colour.Y = colour.Y; particle.Colour.Z = colour.Z; #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { var particle = iterator.First; do { #if UNSAFE particle->Scale = this.InitialScale + ((this.FinalScale - this.InitialScale) * particle->Age); #else particle.Scale = this.InitialScale + ((this.FinalScale - this.InitialScale) * particle.Age); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single w; Vector3 x, y; var particle = iterator.First; do { #if UNSAFE Single age = particle->Age; #else Single age = particle.Age; #endif if (age < this.Median) { x = this.InitialColour; y = this.MedianColour; w = age / this.Median; } else { x = this.MedianColour; y = this.FinalColour; w = (age - this.Median) / (1f - this.Median); } #if UNSAFE particle->Colour.X = x.X + ((y.X - x.X) * w); particle->Colour.Y = x.Y + ((y.Y - x.Y) * w); particle->Colour.Z = x.Z + ((y.Z - x.Z) * w); #else particle.Colour.X = x.X + ((y.X - x.X) * w); particle.Colour.Y = x.Y + ((y.Y - x.Y) * w); particle.Colour.Z = x.Z + ((y.Z - x.Z) * w); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { var particle = iterator.First; do { #if UNSAFE particle->Colour.W = this.InitialOpacity - (this.InitialOpacity * particle->Age); #else particle.Colour.W = this.InitialOpacity - (this.InitialOpacity * particle.Age); #endif } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single squareMaximumVelocity = (this.MaximumVelocity * this.MaximumVelocity); var particle = iterator.First; do { #if UNSAFE Vector3 velocity = particle->Velocity; #else Vector3 velocity = particle.Velocity; #endif Single squareVelocity = ((velocity.X * velocity.X) + (velocity.Y * velocity.Y) + (velocity.Z * velocity.Z)); if (squareVelocity > squareMaximumVelocity) { Single actualVelocity = Calculator.Sqrt(squareVelocity); #if UNSAFE particle->Velocity.X = (particle->Velocity.X / actualVelocity) * this.MaximumVelocity; particle->Velocity.Y = (particle->Velocity.Y / actualVelocity) * this.MaximumVelocity; particle->Velocity.Z = (particle->Velocity.Z / actualVelocity) * this.MaximumVelocity; #else particle.Velocity.X = (particle.Velocity.X / actualVelocity) * this.MaximumVelocity; particle.Velocity.Y = (particle.Velocity.Y / actualVelocity) * this.MaximumVelocity; particle.Velocity.Z = (particle.Velocity.Z / actualVelocity) * this.MaximumVelocity; #endif } } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
/// <summary> /// Performs rendering of particles. /// </summary> /// <param name="iterator">The particle iterator object.</param> /// <param name="context">The render context containing rendering information.</param> protected override void Render(ref RenderContext context, ref ParticleIterator iterator) { Int32 vertexCount = 0; Vector3 cameraPos = context.CameraPosition; Vector3 rotationAxis = context.BillboardRotationalAxis; bool squareTexture = (context.Texture.Height == context.Texture.Width); float aspectRatio = context.Texture.Height / (float)context.Texture.Width ; SetDataOptions setDataOptions = SetDataOptions.NoOverwrite; //Use the SpriteBatch style of filling buffers //http://blogs.msdn.com/b/shawnhar/archive/2010/07/07/setdataoptions-nooverwrite-versus-discard.aspx if (_vertexBufferPosition + context.Count * VerticesPerParticle > NumVertices) { //Too much to fit in the remaining space - start at the beginning and discard _vertexBufferPosition = 0; setDataOptions = SetDataOptions.Discard; } #if UNSAFE unsafe { fixed (ParticleVertex* vertexArray = Vertices) { ParticleVertex* verts = vertexArray +_vertexBufferPosition; #else int vertexIndex = _vertexBufferPosition; #endif var particle = iterator.First; do { #if UNSAFE Single scale = particle->Scale; Vector3 position = particle->Position; Vector3 rotation = particle->Rotation; Vector4 colour = particle->Colour; //Work out our world transform - and set a flag to avoid some multiplies if world ends up as zero bool worldIsNotIdentity = true; Matrix effectWorld; if (context.WorldIsIdentity) { if (particle->EffectProxyIndex > 0) { effectWorld = ParticleEffectProxy.Proxies[particle->EffectProxyIndex].World; } else { worldIsNotIdentity = false; effectWorld = Matrix.Identity; //Makes the compiler happy though we will never actually use it. } } else { effectWorld = particle->EffectProxyIndex > 0 ? ParticleEffectProxy.Proxies[particle->EffectProxyIndex].FinalWorld : context.World; } #else Single scale = particle.Scale; Vector3 position = particle.Position; Vector3 rotation = particle.Rotation; Vector4 colour = particle.Colour; //If we have a proxy then multiply in the proxy world matrix bool worldIsNotIdentity = true; Matrix effectWorld; if (context.WorldIsIdentity) { if (particle.EffectProxyIndex > 0) { effectWorld = ParticleEffectProxy.Proxies[particle.EffectProxyIndex].World; } else { worldIsNotIdentity = false; effectWorld = Matrix.Identity; //Makes the compiler happy though we will never actually use it. } } else { effectWorld = particle.EffectProxyIndex > 0 ? ParticleEffectProxy.Proxies[particle.EffectProxyIndex].FinalWorld : context.World; } #endif //Individual particle transformations - scale and rotation //The Rotation setup will fill in the top 3x3 so we just need to initialise 44 var transform = new Matrix {M44 = 1}; float scaleX = scale; float scaleY = squareTexture ? scale : scale * aspectRatio; //ScaleZ is always 1 so no need multiple into M_3 //Inline the rotation and scale calculations and do each element in one go //Fast rotation matrix - see http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations //This set matches //Matrix temp2 = Matrix.CreateRotationX(rotation.X) * Matrix.CreateRotationY(rotation.Y) * Matrix.CreateRotationZ(rotation.Z); //Matches math od Rotx*RotY*RotZ //var cosX = (float) Math.Cos(rotation.X); //var cosY = (float) Math.Cos(rotation.Y); //var cosZ = (float) Math.Cos(rotation.Z); //var sinX = (float) Math.Sin(rotation.X); //var sinY = (float) Math.Sin(rotation.Y); //var sinZ = (float) Math.Sin(rotation.Z); //transform.M11 = cosY*cosZ; //transform.M12 = cosY * sinZ; //transform.M13 = -sinY; //transform.M21 = sinX*sinY*cosZ - cosX * sinZ; //transform.M22 = sinX*sinY*sinZ + cosX*cosZ; //transform.M23 = sinX*cosY; //transform.M31 = cosX*sinY*cosZ + sinX * sinZ; //transform.M32 = cosX*sinY*sinZ - sinX * cosZ; //transform.M33 = cosX * cosY; //This set matches //Matrix temp2 = Matrix.CreateScale(new VEctor3(scaleX, scaleY,1) * Matrix.CreateRotationZ(rotation.Z) * Matrix.CreateRotationX(rotation.Y) * Matrix.CreateRotationY(rotation.X) ; //Matches YawPitchRoll order //Matrix temp = Matrix.CreateScale(new VEctor3(scaleX, scaleY,1) * Matrix.CreateFromYawPitchRoll(rotation.X, rotation.Y, rotation.Z); //TODO - can we optimise out a rotation e.g.fast path if rotation.Y=0 etc //TODO - can we optimise out rotation(s) if we know its a billboard? That overwrites much of the transform var cosX = (float)Math.Cos(rotation.Y); var cosY = (float)Math.Cos(rotation.X); var cosZ = (float)Math.Cos(rotation.Z); var sinX = (float)Math.Sin(rotation.Y); var sinY = (float)Math.Sin(rotation.X); var sinZ = (float)Math.Sin(rotation.Z); var cosYcosZ = cosY*cosZ; var cosYsinZ = cosY*sinZ; var sinXsinY = sinX*sinY; transform.M11 = (cosYcosZ + sinXsinY * sinZ) * scaleX; transform.M12 = (cosX * sinZ) * scaleX; transform.M13 = (sinX * cosYsinZ - sinY * cosZ) * scaleX; transform.M21 = (sinXsinY * cosZ - cosYsinZ) * scaleY; transform.M22 = (cosX * cosZ) *scaleY; transform.M23 = (sinY * sinZ + sinX * cosYcosZ) * scaleY; transform.M31 = cosX * sinY; transform.M32 = -sinX; transform.M33 = cosX * cosY; switch (context.BillboardStyle) { case BillboardStyle.None: //Position the particle without a multiplication! transform.M41 = position.X; transform.M42 = position.Y; transform.M43 = position.Z; //Just apply the world //TODO - we can just do this in Basic effect instead of per vertex - only if there is no proxy, sort of a fast path! if (worldIsNotIdentity) { Matrix.Multiply(ref transform, ref effectWorld, out transform); } break; default: //Its billboarded Vector3 worldPos; if (worldIsNotIdentity) { Vector3.Transform(ref position, ref effectWorld, out worldPos); } else { worldPos = position; } //Apply the billboard (which includes the world translation) Matrix billboardMatrix; if (context.BillboardStyle == BillboardStyle.Spherical) { //Spherical billboards (always face the camera) Matrix.CreateBillboard(ref worldPos, ref cameraPos, ref Up, Forward, out billboardMatrix); } else { //HACK: For progenitor DBP use the velocity as the axis for a per particle axis if (context.UseVelocityAsBillboardAxis) { #if UNSAFE Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref particle->Velocity, Forward, null, out billboardMatrix); #else Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref particle.Velocity, Forward, null, out billboardMatrix); #endif } else { //Cylindrical billboards have a vector they are allowed to rotate around Matrix.CreateConstrainedBillboard(ref worldPos, ref cameraPos, ref rotationAxis, Forward, null, out billboardMatrix); } } Matrix.Multiply(ref transform, ref billboardMatrix, out transform); break; } Vector3 v1; Vector3 v2; Vector3 v3; Vector3 v4; Vector3.Transform(ref inv1, ref transform, out v1); Vector3.Transform(ref inv2, ref transform, out v2); Vector3.Transform(ref inv3, ref transform, out v3); Vector3.Transform(ref inv4, ref transform, out v4); #if UNSAFE //inline particle value assignments - removes 4 calls with their parameters and its a struct anyway verts->Position.X = v1.X; verts->Position.Y = v1.Y; verts->Position.Z = v1.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v2.X; verts->Position.Y = v2.Y; verts->Position.Z = v2.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v3.X; verts->Position.Y = v3.Y; verts->Position.Z = v3.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; verts->Position.X = v4.X; verts->Position.Y = v4.Y; verts->Position.Z = v4.Z; verts->Colour.X = colour.X; verts->Colour.Y = colour.Y; verts->Colour.Z = colour.Z; verts->Colour.W = colour.W; verts++; #else //inline particle value assignments - removes 4 calls with their parameters and its a struct anyway this.Vertices[vertexIndex].Position = v1; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv1; this.Vertices[vertexIndex].Position = v2; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv2; this.Vertices[vertexIndex].Position = v3; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv3; this.Vertices[vertexIndex].Position = v4; this.Vertices[vertexIndex].Colour = colour; this.Vertices[vertexIndex++].TextureCoordinate = uv4; #endif vertexCount += 4; } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif base.GraphicsDeviceService.GraphicsDevice.BlendState = context.BlendState; this.BasicEffect.Texture = context.Texture; //Xbox need the vertex buffer to be set to null before SetData is called //Windows does not //TODO: Is this a bug? see http://forums.create.msdn.com/forums/p/61885/399495.aspx#399495 #if XBOX if (setDataOptions == SetDataOptions.Discard) { base.GraphicsDeviceService.GraphicsDevice.SetVertexBuffer(null); } #endif _vertexBuffer.SetData(_vertexBufferPosition * ParticleVertex.Size, Vertices, _vertexBufferPosition, vertexCount, ParticleVertex.Size, setDataOptions); Debug.WriteLine(String.Format("position: {0} Count: {1} Hint: {2}", _vertexBufferPosition, vertexCount, setDataOptions)); base.GraphicsDeviceService.GraphicsDevice.SetVertexBuffer(_vertexBuffer); foreach (EffectPass pass in this.BasicEffect.CurrentTechnique.Passes) { pass.Apply(); base.GraphicsDeviceService.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, _vertexBufferPosition, vertexCount, _vertexBufferPosition/4*6, vertexCount/2); } //Move to the next free part of the array _vertexBufferPosition += vertexCount; #if UNSAFE } } #endif }
/// <summary> /// Renders the specified particle effect. /// </summary> /// <param name="effect">The particle effect to render.</param> /// <param name="worldMatrix">The world transformation matrix.</param> /// <param name="viewMatrix">The view matrix.</param> /// <param name="projectionMatrix">The projection matrix.</param> /// <param name="cameraPosition">The camera matrix.</param> public void RenderEffect(ParticleEffect effect, ref Matrix worldMatrix, ref Matrix viewMatrix, ref Matrix projectionMatrix, ref Vector3 cameraPosition) { #if UNSAFE unsafe #endif { this.PreRender(ref worldMatrix, ref viewMatrix, ref projectionMatrix); //Pre-multiply any proxies world matrices with the passed in world matrix if (effect.Proxies != null && worldMatrix != Matrix.Identity) { effect.SetFinalWorld(ref worldMatrix); } for (Int32 i = 0; i < effect.Emitters.Count; i++) { AbstractEmitter emitter = effect.Emitters[i]; // Skip if the emitter does not have a texture... if (emitter.ParticleTexture == null) continue; // Skip if the emitter blend mode is set to 'None'... if (emitter.BlendMode == EmitterBlendMode.None) continue; // Skip if the emitter has no active particles... if (emitter.ActiveParticlesCount == 0) continue; BlendState blendState = BlendStateFactory.GetBlendState(emitter.BlendMode); RenderContext context = new RenderContext(emitter.BillboardStyle, emitter.BillboardRotationalAxis, blendState, emitter.ParticleTexture, ref worldMatrix, ref viewMatrix, ref projectionMatrix, ref cameraPosition, emitter.ActiveParticlesCount, emitter.UseVelocityAsBillboardAxis); Counters.ParticlesDrawn += emitter.ActiveParticlesCount; #if UNSAFE fixed (Particle* buffer = emitter.Particles) #else Particle[] buffer = emitter.Particles; #endif { ParticleIterator iterator = new ParticleIterator(buffer, emitter.Budget, emitter.ActiveIndex, emitter.ActiveParticlesCount); this.Render(ref context, ref iterator); } } } }
/// <summary> /// Performs rendering of particles. /// </summary> /// <param name="context">The render context containing rendering information.</param> /// <param name="iterator">The particle iterator object.</param> protected abstract void Render(ref RenderContext context, ref ParticleIterator iterator);
/// <summary> /// Processes active particles. /// </summary> /// <param name="deltaSeconds">Elapsed time in whole and fractional seconds.</param> /// <param name="iterator">A particle iterator object.</param> #if UNSAFE protected internal override unsafe void Process(Single deltaSeconds, ref ParticleIterator iterator)
/// <summary> /// Updates the particle emitter. /// </summary> /// <param name="deltaSeconds">Elapsed time in whole and fractional seconds.</param> public void Update(Single deltaSeconds) { Check.True(this.Initialised, "Emitter has not yet been initialised!"); this.TotalSeconds += deltaSeconds; this.Controllers.Update(deltaSeconds); if (this.ActiveParticlesCount < 1) { return; } #if UNSAFE unsafe #endif { #if UNSAFE fixed(Particle *particleArray = this.Particles) #endif { // Copy the state of the ring buffer as we will modify it as particles die... var currentIndex = this.ActiveIndex; var currentParticleCount = this.ActiveParticlesCount; for (var i = 0; i < currentParticleCount; i++) { #if UNSAFE // Get a pointer to the particle in the buffer... Particle *particle = particleArray + currentIndex; // Calculate the age of the particle in seconds... var actualAge = this.TotalSeconds - particle->Inception; #else // Extract the particle from the buffer... Particle particle = this.Particles[currentIndex]; // Calculate the age of the particle in seconds... var actualAge = this.TotalSeconds - particle.Inception; #endif // Check to see if the particle has expired... if (actualAge > this.Term) { // Increment the index of the first active particle... this.ActiveIndex = (this.ActiveIndex + 1) % this.Budget; // Decrement the active particles count... this.ActiveParticlesCount = (this.ActiveParticlesCount - 1); } else { #if UNSAFE // Calculate the normalized age of the particle... particle->Age = actualAge / this.Term; //HACK: For progenitor DBP use the velocity as the axis for a per particle axis if (!UseVelocityAsBillboardAxis) { // Apply particle movement... particle->Position.X += (particle->Velocity.X * deltaSeconds); particle->Position.Y += (particle->Velocity.Y * deltaSeconds); particle->Position.Z += (particle->Velocity.Z * deltaSeconds); } else { particle->Velocity.Normalize(); } #else // Calculate the normalized age of the particle... particle.Age = actualAge / this.Term; // Apply particle movement... particle.Position.X += (particle.Velocity.X * deltaSeconds); particle.Position.Y += (particle.Velocity.Y * deltaSeconds); particle.Position.Z += (particle.Velocity.Z * deltaSeconds); // Put the mutated particle back in the buffer... this.Particles[currentIndex] = particle; #endif } currentIndex = (currentIndex + 1) % this.Budget; } if (this.ActiveParticlesCount > 0) { #if UNSAFE var buffer = particleArray; #else var buffer = this.Particles; #endif var iterator = new ParticleIterator(buffer, this.Budget, this.ActiveIndex, this.ActiveParticlesCount); this.Modifiers.RunProcessors(deltaSeconds, ref iterator); } } } }
protected internal override void Process(Single deltaSeconds, ref ParticleIterator iterator) #endif { Single deltaStrength = this.Strength * deltaSeconds; Single deltaForceX = this.Force.X * deltaStrength; Single deltaForceY = this.Force.Y * deltaStrength; Single deltaForceZ = this.Force.Z * deltaStrength; var particle = iterator.First; do { #if UNSAFE Vector3 position = particle->Position; #else Vector3 position = particle.Position; #endif if (position.X > (this.Position.X - this.HalfWidth)) if (position.X < (this.Position.X + this.HalfWidth)) if (position.Y > (this.Position.Y - this.HalfHeight)) if (position.Y < (this.Position.Y + this.HalfHeight)) if (position.Z > (this.Position.Z - this.HalfDepth)) if (position.Z < (this.Position.Z + this.HalfDepth)) { #if UNSAFE particle->Velocity.X += deltaForceX; particle->Velocity.Y += deltaForceY; particle->Velocity.Z += deltaForceZ; #else particle.Velocity.X += deltaForceX; particle.Velocity.Y += deltaForceY; particle.Velocity.Z += deltaForceZ; #endif } } #if UNSAFE while (iterator.MoveNext(&particle)); #else while (iterator.MoveNext(ref particle)); #endif }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ParticleIterator obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
protected internal abstract void Process(Single deltaSeconds, ref ParticleIterator iterator);
public BaseObject Create() { ParticleIterator emptyInstance = new ParticleIterator(CreatedWhenConstruct.CWC_NotToCreate); return(emptyInstance); }