// Update position, check collisions, etc. and draw if particle still lives. // Return false if particle dies/timeouts in this tick. public bool Draw(VRageRender.MyBillboard billboard) { var actualPosition = m_actualPosition + m_actualPivot; MyTransparentGeometry.StartParticleProfilingBlock("Distance calculation"); // This time is scaled according to planned lifespan of the particle // Distance for sorting billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyTransparentGeometry.Camera.Translation, actualPosition); MyTransparentGeometry.EndParticleProfilingBlock(); // If distance to camera is really small don't draw it. if (billboard.DistanceSquared <= 0.1f) { return(false); } MyTransparentGeometry.StartParticleProfilingBlock("Quad calculation"); MyTransparentGeometry.StartParticleProfilingBlock("actualRadius"); float actualRadius = 1; Radius.GetInterpolatedValue <float>(m_normalizedTime, out actualRadius); MyTransparentGeometry.EndParticleProfilingBlock(); float actualAlphaCutout = 0; if (AlphaCutout != null) { MyTransparentGeometry.StartParticleProfilingBlock("AlphaCutout calculation"); AlphaCutout.GetInterpolatedValue <float>(m_normalizedTime, out actualAlphaCutout); MyTransparentGeometry.EndParticleProfilingBlock(); } billboard.ContainedBillboards.Clear(); billboard.Near = m_generation.GetEffect().Near; billboard.Lowres = m_generation.GetEffect().LowRes || VRageRender.MyRenderConstants.RenderQualityProfile.LowResParticles; billboard.CustomViewProjection = -1; billboard.ParentID = -1; billboard.AlphaCutout = actualAlphaCutout; float alpha = 1; if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadius, m_actualAngle); MyTransparentGeometry.EndParticleProfilingBlock(); } else if (Type == MyParticleTypeEnum.Line) { if (MyUtils.IsZero(Velocity.LengthSquared())) { Velocity = MyUtils.GetRandomVector3Normalized(); } MyQuadD quad = new MyQuadD(); Vector3 actualVelocity = (Vector3)(m_actualPosition - m_previousPosition); MyPolyLineD polyLine = new MyPolyLineD(); //polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); if (actualVelocity.LengthSquared() > 0) { polyLine.LineDirectionNormalized = MyUtils.Normalize(actualVelocity); } else { polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); } if (m_actualAngle > 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(MathHelper.ToRadians(m_actualAngle))); } float radiusBySpeed = m_generation.RadiusBySpeed; if (radiusBySpeed > 0) { float actualSpeed = actualVelocity.Length(); actualRadius = Math.Max(actualRadius, actualRadius * m_generation.RadiusBySpeed * actualSpeed); } polyLine.Point0 = actualPosition; polyLine.Point1.X = actualPosition.X - polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = actualPosition.Y - polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = actualPosition.Z - polyLine.LineDirectionNormalized.Z * actualRadius; if (m_actualAngle > 0) { //centerize polyLine.Point0.X = polyLine.Point0.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point0.Y = polyLine.Point0.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point0.Z = polyLine.Point0.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; polyLine.Point1.X = polyLine.Point1.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point1.Y = polyLine.Point1.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point1.Z = polyLine.Point1.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; } polyLine.Thickness = Thickness; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out quad, ref polyLine, camPos); if (this.m_generation.AlphaAnisotropic) { float angle = 1 - Math.Abs(Vector3.Dot(MyUtils.Normalize(MyTransparentGeometry.Camera.Forward), polyLine.LineDirectionNormalized)); float alphaCone = (float)Math.Pow(angle, 0.5f); alpha = alphaCone; } billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; } else if (Type == MyParticleTypeEnum.Trail) { if (Quad.Point0 == Quad.Point2) //not moving particle { return(false); } if (Quad.Point1 == Quad.Point3) //not moving particle was previous one { return(false); } if (Quad.Point0 == Quad.Point3) //not moving particle was previous one { return(false); } billboard.Position0 = Quad.Point0; billboard.Position1 = Quad.Point1; billboard.Position2 = Quad.Point2; billboard.Position3 = Quad.Point3; //if (this.m_generation.AlphaAnisotropic) /* { //Trails are anisotropic by default (nobody wants them to see ugly) * Vector3 lineDir = Vector3.Normalize(Quad.Point1 - Quad.Point0); * float angle = 1 - Math.Abs(Vector3.Dot(MyMwcUtils.Normalize(MyCamera.ForwardVector), lineDir)); * float alphaCone = (float)Math.Pow(angle, 0.3f); * alpha = alphaCone; * }*/ } else { throw new NotSupportedException(Type + " is not supported particle type"); } MyTransparentGeometry.EndParticleProfilingBlock(); MyTransparentGeometry.StartParticleProfilingBlock("Material calculation"); Vector4 color; Color.GetInterpolatedValue <Vector4>(m_normalizedTime, out color); var material1 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); var material2 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); float textureBlendRatio = 0; if ((Flags & ParticleFlags.BlendTextures) != 0) { float prevTime, nextTime, difference; Material.GetPreviousValue(m_normalizedTime, out material1, out prevTime); Material.GetNextValue(m_normalizedTime, out material2, out nextTime, out difference); if (prevTime != nextTime) { textureBlendRatio = (m_normalizedTime - prevTime) * difference; } } else { Material.GetInterpolatedValue(m_normalizedTime, out material1); } MyTransparentGeometry.EndParticleProfilingBlock(); //This gets 0.44ms for 2000 particles MyTransparentGeometry.StartParticleProfilingBlock("billboard.Start"); billboard.Material = material1.Name; billboard.BlendMaterial = material2.Name; billboard.BlendTextureRatio = textureBlendRatio; billboard.EnableColorize = false; billboard.Color = color * alpha * m_generation.GetEffect().UserColorMultiplier; billboard.ColorIntensity = ColorIntensity; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }
private void CreateParticle(Vector3D interpolatedEffectPosition) { MyAnimatedParticle particle = MyTransparentGeometry.AddAnimatedParticle(); if (particle == null) { return; } particle.Type = (MyParticleTypeEnum)ParticleType.GetValue <int>(); MyUtils.AssertIsValid(m_effect.WorldMatrix); Vector3D startOffset; m_emitter.CalculateStartPosition(m_effect.GetElapsedTime(), MatrixD.CreateWorld(interpolatedEffectPosition, m_effect.WorldMatrix.Forward, m_effect.WorldMatrix.Up), m_effect.UserEmitterScale * m_effect.UserAxisScale, m_effect.UserEmitterScale * m_effect.UserScale, out startOffset, out particle.StartPosition); Vector3D particlePosition = particle.StartPosition; m_AABB = m_AABB.Include(ref particlePosition); Life.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Life); float lifeVar = LifeVar; if (lifeVar > 0) { particle.Life = MathHelper.Max(MyUtils.GetRandomFloat(particle.Life - lifeVar, particle.Life + lifeVar), 0.1f); } Vector3 vel; Velocity.GetInterpolatedValue <Vector3>(m_effect.GetElapsedTime(), out vel); vel.X *= m_effect.UserScale; vel.Y *= m_effect.UserScale; vel.Z *= m_effect.UserScale; particle.Velocity = vel; if (VelocityDir == MyVelocityDirEnum.FromEmitterCenter) { if (!MyUtils.IsZero(startOffset - particle.StartPosition)) { float length = particle.Velocity.Length(); particle.Velocity = MyUtils.Normalize(particle.StartPosition - (Vector3D)startOffset) * length; } } particle.Velocity = Vector3D.TransformNormal(particle.Velocity, GetEffect().WorldMatrix); Angle.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Angle); float angleVar = AngleVar; if (angleVar > 0) { particle.Angle = MyUtils.GetRandomFloat(particle.Angle - AngleVar, particle.Angle + AngleVar); } RotationSpeed.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.RotationSpeed); float rotationSpeedVar = RotationSpeedVar; if (rotationSpeedVar > 0) { particle.RotationSpeed = MyUtils.GetRandomFloat(particle.RotationSpeed - RotationSpeedVar, particle.RotationSpeed + RotationSpeedVar); } float radiusVar; RadiusVar.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out radiusVar); float lodRadius = 1.0f; if (GetEffect().EnableLods) { LODRadius.GetInterpolatedValue <float>(GetEffect().Distance, out lodRadius); } Radius.GetInterpolatedKeys(m_effect.GetElapsedTime(), radiusVar, (EnableCustomRadius.GetValue <bool>() ? m_effect.UserRadiusMultiplier : 1.0f) * lodRadius * GetEffect().UserScale, particle.Radius); if (particle.Type != MyParticleTypeEnum.Point) { Thickness.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.Thickness); } particle.Thickness *= lodRadius; float colorVar; ColorVar.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out colorVar); Color.GetInterpolatedKeys(m_effect.GetElapsedTime(), colorVar, 1.0f, particle.Color); ColorIntensity.GetInterpolatedValue <float>(m_effect.GetElapsedTime(), out particle.ColorIntensity); Material.GetInterpolatedKeys(m_effect.GetElapsedTime(), 0, 1.0f, particle.Material); particle.Flags = 0; particle.Flags |= BlendTextures.GetValue <bool>() ? MyAnimatedParticle.ParticleFlags.BlendTextures : 0; if (PivotRotation.GetKeysCount() > 0 && PivotDistance.GetKeysCount() > 0) { particle.PivotDistance = new MyAnimatedPropertyFloat(PivotDistance.Name); particle.PivotRotation = new MyAnimatedPropertyVector3(PivotRotation.Name); PivotDistance.GetInterpolatedKeys(m_effect.GetElapsedTime(), PivotDistVar, 1.0f, particle.PivotDistance); PivotRotation.GetInterpolatedKeys(m_effect.GetElapsedTime(), 1.0f, particle.PivotRotation); } if (Acceleration.GetKeysCount() > 0) { particle.Acceleration = new MyAnimatedPropertyVector3(Acceleration.Name); float multiplier = MyUtils.GetRandomFloat(1 - AccelerationVar, 1 + AccelerationVar); Acceleration.GetInterpolatedKeys(m_effect.GetElapsedTime(), multiplier, particle.Acceleration); } if (AlphaCutout.GetKeysCount() > 0) { particle.AlphaCutout = new MyAnimatedPropertyFloat(AlphaCutout.Name); AlphaCutout.GetInterpolatedKeys(m_effect.GetElapsedTime(), 0, 1, particle.AlphaCutout); } particle.Start(this); m_particles.Add(particle); }
// Update position, check collisions, etc. and draw if particle still lives. // Return false if particle dies/timeouts in this tick. public bool Draw(VRageRender.MyBillboard billboard) { if (Pivot != null && !MyParticlesManager.Paused) { if (PivotRotation != null) { Matrix pivotRotationTransform = Matrix.CreateRotationX(MathHelper.ToRadians(m_actualPivotRotation.X) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) * Matrix.CreateRotationY(MathHelper.ToRadians(m_actualPivotRotation.Y) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) * Matrix.CreateRotationZ(MathHelper.ToRadians(m_actualPivotRotation.Z) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS); m_actualPivot = Vector3.TransformNormal(m_actualPivot, pivotRotationTransform); } m_actualPivot = Vector3D.TransformNormal(m_actualPivot, m_generation.GetEffect().WorldMatrix); } var actualPosition = m_actualPosition + m_actualPivot; MyTransparentGeometry.StartParticleProfilingBlock("Distance calculation"); // This time is scaled according to planned lifespan of the particle // Distance for sorting billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyTransparentGeometry.Camera.Translation, actualPosition); MyTransparentGeometry.EndParticleProfilingBlock(); // If distance to camera is really small don't draw it. if (billboard.DistanceSquared <= 0.1f) { return(false); } MyTransparentGeometry.StartParticleProfilingBlock("Quad calculation"); MyTransparentGeometry.StartParticleProfilingBlock("actualRadius"); float actualRadius = 1; Radius.GetInterpolatedValue <float>(m_normalizedTime, out actualRadius); MyTransparentGeometry.EndParticleProfilingBlock(); float actualAlphaCutout = 0; if (AlphaCutout != null) { MyTransparentGeometry.StartParticleProfilingBlock("AlphaCutout calculation"); AlphaCutout.GetInterpolatedValue <float>(m_normalizedTime, out actualAlphaCutout); MyTransparentGeometry.EndParticleProfilingBlock(); } billboard.ContainedBillboards.Clear(); billboard.Near = m_generation.GetEffect().Near; billboard.Lowres = VRageRender.MyRenderConstants.RenderQualityProfile.LowResParticles; billboard.CustomViewProjection = -1; billboard.ParentID = -1; billboard.AlphaCutout = actualAlphaCutout; billboard.UVOffset = Vector2.Zero; billboard.UVSize = Vector2.One; float alpha = 1; Matrix transform = Matrix.Identity; Vector3 normal = Vector3.Forward; Vector3 actualVelocity = (Vector3)(m_actualPosition - m_previousPosition); float radiusBySpeed = m_generation.RadiusBySpeed; if (radiusBySpeed > 0) { float actualSpeed = actualVelocity.Length(); actualRadius = Math.Max(actualRadius, actualRadius * m_generation.RadiusBySpeed * actualSpeed); } if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); Vector2 actualRadiusV2 = new Vector2(actualRadius, actualRadius); if (Thickness > 0) { actualRadiusV2.Y = Thickness; } if (m_generation.RotationReference == MyRotationReference.Camera) { transform = Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, MyTransparentGeometry.Camera.Left, MyTransparentGeometry.Camera.Up); } else if (m_generation.RotationReference == MyRotationReference.Local) { transform = Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, m_generation.GetEffect().WorldMatrix.Left, m_generation.GetEffect().WorldMatrix.Up); } else if (m_generation.RotationReference == MyRotationReference.Velocity) { if (actualVelocity.LengthSquared() < 0.00001f) { return(false); } Matrix velocityRef = Matrix.CreateFromDir(Vector3.Normalize(actualVelocity)); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else if (m_generation.RotationReference == MyRotationReference.VelocityAndCamera) { if (actualVelocity.LengthSquared() < 0.0001f) { return(false); } Vector3 cameraToPoint = Vector3.Normalize(m_actualPosition - MyTransparentGeometry.Camera.Translation); Vector3 velocityDir = Vector3.Normalize(actualVelocity); Vector3 sideVector = Vector3.Cross(cameraToPoint, velocityDir); Vector3 upVector = Vector3.Cross(sideVector, velocityDir); Matrix velocityRef = Matrix.CreateWorld(m_actualPosition, velocityDir, upVector); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else if (m_generation.RotationReference == MyRotationReference.LocalAndCamera) { Vector3 cameraToPoint = Vector3.Normalize(m_actualPosition - MyTransparentGeometry.Camera.Translation); Vector3 localDir = m_generation.GetEffect().WorldMatrix.Forward; float dot = cameraToPoint.Dot(localDir); Matrix velocityRef; if (dot >= 0.9999f) { // TODO Petr: probably not correct, at least it does not produce NaN positions velocityRef = Matrix.CreateTranslation(m_actualPosition); } else { Vector3 sideVector = Vector3.Cross(cameraToPoint, localDir); Vector3 upVector = Vector3.Cross(sideVector, localDir); velocityRef = Matrix.CreateWorld(m_actualPosition, localDir, upVector); } transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else { System.Diagnostics.Debug.Fail("Unknown RotationReference enum"); } MyTransparentGeometry.EndParticleProfilingBlock(); } else if (Type == MyParticleTypeEnum.Line) { if (MyUtils.IsZero(Velocity.LengthSquared())) { Velocity = MyUtils.GetRandomVector3Normalized(); } MyQuadD quad = new MyQuadD(); MyPolyLineD polyLine = new MyPolyLineD(); //polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); if (actualVelocity.LengthSquared() > 0) { polyLine.LineDirectionNormalized = MyUtils.Normalize(actualVelocity); } else { polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); } if (m_actualAngle.Z != 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(m_actualAngle.Z)); } polyLine.Point0 = actualPosition; polyLine.Point1.X = actualPosition.X - polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = actualPosition.Y - polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = actualPosition.Z - polyLine.LineDirectionNormalized.Z * actualRadius; if (m_actualAngle.LengthSquared() > 0) { //centerize polyLine.Point0.X = polyLine.Point0.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point0.Y = polyLine.Point0.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point0.Z = polyLine.Point0.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; polyLine.Point1.X = polyLine.Point1.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point1.Y = polyLine.Point1.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point1.Z = polyLine.Point1.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; } polyLine.Thickness = Thickness; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out quad, ref polyLine, camPos); transform.Forward = polyLine.LineDirectionNormalized; billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; } else if (Type == MyParticleTypeEnum.Trail) { if (Quad.Point0 == Quad.Point2) //not moving particle { return(false); } if (Quad.Point1 == Quad.Point3) //not moving particle was previous one { return(false); } if (Quad.Point0 == Quad.Point3) //not moving particle was previous one { return(false); } billboard.Position0 = Quad.Point0; billboard.Position1 = Quad.Point1; billboard.Position2 = Quad.Point2; billboard.Position3 = Quad.Point3; } else { throw new NotSupportedException(Type + " is not supported particle type"); } if (this.m_generation.AlphaAnisotropic) { normal = Vector3.Normalize(Vector3.Cross(billboard.Position0 - billboard.Position1, billboard.Position0 - billboard.Position2)); Vector3 forward = (billboard.Position0 + billboard.Position1 + billboard.Position2 + billboard.Position3) / 4 - MyTransparentGeometry.Camera.Translation; //Vector3 forward = MyTransparentGeometry.Camera.Forward; float angle = Math.Abs(Vector3.Dot(MyUtils.Normalize(forward), normal)); float alphaCone = 1 - (float)Math.Pow(1 - angle, 4); alpha = alphaCone; } MyTransparentGeometry.EndParticleProfilingBlock(); MyTransparentGeometry.StartParticleProfilingBlock("Material calculation"); Vector4 color = Vector4.One; if (Color.GetKeysCount() > 0) { Color.GetInterpolatedValue <Vector4>(m_normalizedTime, out color); } if (m_arrayIndex != -1) { Vector3 arraySize = m_generation.ArraySize; if (arraySize.X > 0 && arraySize.Y > 0) { int arrayOffset = m_generation.ArrayOffset; int arrayModulo = m_generation.ArrayModulo == 0 ? (int)arraySize.X * (int)arraySize.Y : m_generation.ArrayModulo; m_arrayIndex = m_arrayIndex % arrayModulo + arrayOffset; float xDiv = 1.0f / arraySize.X; float yDiv = 1.0f / arraySize.Y; int xIndex = m_arrayIndex % (int)arraySize.X; int yIndex = m_arrayIndex / (int)arraySize.X; billboard.UVOffset = new Vector2(xDiv * xIndex, yDiv * yIndex); billboard.UVSize = new Vector2(xDiv, yDiv); } } var material1 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); var material2 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); float textureBlendRatio = 0; if ((Flags & ParticleFlags.BlendTextures) != 0) { float prevTime, nextTime, difference; Material.GetPreviousValue(m_normalizedTime, out material1, out prevTime); Material.GetNextValue(m_normalizedTime, out material2, out nextTime, out difference); if (prevTime != nextTime) { textureBlendRatio = (m_normalizedTime - prevTime) * difference; } } else { Material.GetInterpolatedValue(m_normalizedTime, out material1); } MyTransparentGeometry.EndParticleProfilingBlock(); //This gets 0.44ms for 2000 particles MyTransparentGeometry.StartParticleProfilingBlock("billboard.Start"); if (material1 != null) { billboard.Material = material1.Name; } billboard.BlendMaterial = material2.Name; billboard.BlendTextureRatio = textureBlendRatio; billboard.EnableColorize = false; billboard.Color = color * alpha * m_generation.GetEffect().UserColorMultiplier; billboard.ColorIntensity = ColorIntensity; billboard.SoftParticleDistanceScale = SoftParticleDistanceScale; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }
private void UpdateParticlesLife() { int counter = 0; VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleGeneration-UpdateParticlesLife"); MyParticleGeneration inheritedGeneration = null; Vector3D previousParticlePosition = m_effect.WorldMatrix.Translation; float particlesToCreate = 0; m_AABB = BoundingBoxD.CreateInvalid(); m_AABB = m_AABB.Include(ref previousParticlePosition); if (OnDie.GetValue <int>() != -1) { inheritedGeneration = GetInheritedGeneration(OnDie.GetValue <int>()); if (inheritedGeneration == null) { OnDie.SetValue(-1); } else { inheritedGeneration.IsInherited = true; particlesToCreate = inheritedGeneration.m_particlesToCreate; } } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("ParticleGeneration-Update01"); Vector3D previousTrail0 = previousParticlePosition; Vector3D previousTrail1 = previousParticlePosition; using (ParticlesLock.AcquireExclusiveUsing()) { while (counter < m_particles.Count) { float motionInheritance; MotionInheritance.GetInterpolatedValue(m_effect.GetElapsedTime(), out motionInheritance); MyAnimatedParticle particle = m_particles[counter]; if (motionInheritance > 0) { m_effect.CalculateDeltaMatrix = true; } if (particle.Update()) { if (motionInheritance > 0) { var delta = m_effect.GetDeltaMatrix(); particle.AddMotionInheritance(ref motionInheritance, ref delta); } if (counter == 0) { previousParticlePosition = particle.ActualPosition; previousTrail0 = particle.Quad.Point1; previousTrail1 = particle.Quad.Point2; particle.Quad.Point0 = particle.ActualPosition; particle.Quad.Point2 = particle.ActualPosition; } counter++; if (particle.Type == MyParticleTypeEnum.Trail) { if (particle.ActualPosition == previousParticlePosition) { particle.Quad.Point0 = particle.ActualPosition; particle.Quad.Point1 = particle.ActualPosition; particle.Quad.Point2 = particle.ActualPosition; particle.Quad.Point3 = particle.ActualPosition; } else { MyPolyLineD polyLine = new MyPolyLineD(); polyLine.Thickness = particle.Thickness; polyLine.Point0 = particle.ActualPosition; polyLine.Point1 = previousParticlePosition; Vector3D direction = polyLine.Point1 - polyLine.Point0; Vector3D normalizedDirection = MyUtils.Normalize(polyLine.Point1 - polyLine.Point0); polyLine.LineDirectionNormalized = normalizedDirection; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out particle.Quad, ref polyLine, camPos); particle.Quad.Point0 = previousTrail0 + direction * 0.15f; particle.Quad.Point3 = previousTrail1 + direction * 0.15f; previousTrail0 = particle.Quad.Point1; previousTrail1 = particle.Quad.Point2; } } previousParticlePosition = particle.ActualPosition; m_AABB = m_AABB.Include(ref previousParticlePosition); continue; } if (inheritedGeneration != null) { inheritedGeneration.m_particlesToCreate = particlesToCreate; inheritedGeneration.EffectMatrix = MatrixD.CreateWorld(particle.ActualPosition, Vector3D.Normalize(particle.Velocity), Vector3D.Cross(Vector3D.Left, particle.Velocity)); inheritedGeneration.UpdateParticlesCreation(); } m_particles.Remove(particle); MyTransparentGeometry.DeallocateAnimatedParticle(particle); } } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); }
public bool Update() { m_elapsedTime += VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; if (m_elapsedTime >= Life) { return(false); } m_normalizedTime += m_elapsedTimeDivider; m_velocity += m_generation.GetEffect().Gravity *m_generation.Gravity *VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_previousPosition = m_actualPosition; m_actualPosition.X += Velocity.X * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_actualPosition.Y += Velocity.Y * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_actualPosition.Z += Velocity.Z * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; if (Pivot != null) { MyTransparentGeometry.StartParticleProfilingBlock("Pivot calculation"); Pivot.GetInterpolatedValue <Vector3>(m_normalizedTime, out m_actualPivot); MyTransparentGeometry.EndParticleProfilingBlock(); } if (Acceleration != null) { MyTransparentGeometry.StartParticleProfilingBlock("Acceleration calculation"); Acceleration.GetInterpolatedValue <Vector3>(m_normalizedTime, out m_actualAcceleration); Matrix transform = Matrix.Identity; if (m_generation.AccelerationReference == MyAccelerationReference.Camera) { transform = MyTransparentGeometry.Camera; } else if (m_generation.AccelerationReference == MyAccelerationReference.Local) { } else if ((m_generation.AccelerationReference == MyAccelerationReference.Velocity)) { Vector3 actualVelocity = (Vector3)(m_actualPosition - m_previousPosition); if (actualVelocity.LengthSquared() < 0.00001f) { m_actualAcceleration = Vector3.Zero; } else { transform = Matrix.CreateFromDir(Vector3.Normalize(actualVelocity)); } } else if ((m_generation.AccelerationReference == MyAccelerationReference.Gravity)) { if (m_generation.GetEffect().Gravity.LengthSquared() < 0.00001f) { m_actualAcceleration = Vector3.Zero; } else { transform = Matrix.CreateFromDir(Vector3.Normalize(m_generation.GetEffect().Gravity)); } } else { System.Diagnostics.Debug.Fail("Unknown RotationReference enum"); } m_actualAcceleration = Vector3.TransformNormal(m_actualAcceleration, transform); Velocity += m_actualAcceleration * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; MyTransparentGeometry.EndParticleProfilingBlock(); } if (RotationSpeed != null) { Vector3 rotationSpeed; RotationSpeed.GetInterpolatedValue <Vector3>(m_normalizedTime, out rotationSpeed); m_actualAngle += new Vector3(MathHelper.ToRadians(rotationSpeed.X), MathHelper.ToRadians(rotationSpeed.Y), MathHelper.ToRadians(rotationSpeed.Z)) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; } if (PivotRotation != null) { Vector3 pivotRotation; PivotRotation.GetInterpolatedValue <Vector3>(m_normalizedTime, out pivotRotation); m_actualPivotRotation += pivotRotation; } if (ArrayIndex != null) { ArrayIndex.GetInterpolatedValue <int>(m_normalizedTime, out m_arrayIndex); } MyUtils.AssertIsValid(m_actualPosition); MyUtils.AssertIsValid(m_actualAngle); return(true); }