public bool Update() { m_elapsedTime += MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; if (m_elapsedTime >= Life) { return(false); } m_normalizedTime += m_elapsedTimeDivider; m_velocity.Y += m_generation.Gravity * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_actualPosition.X += Velocity.X * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_actualPosition.Y += Velocity.Y * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; m_actualPosition.Z += Velocity.Z * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; if (PivotRotation != null && PivotDistance != null) { MyTransparentGeometry.StartParticleProfilingBlock("Pivot calculation"); Vector3 rotation; float distance; PivotRotation.GetInterpolatedValue <Vector3>(m_normalizedTime, out rotation); PivotDistance.GetInterpolatedValue <float>(m_normalizedTime, out distance); Quaternion rotationQ = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(rotation.Y), MathHelper.ToRadians(rotation.X), MathHelper.ToRadians(rotation.Z)); m_actualPivot = Vector3.Transform(Vector3.Forward, rotationQ) * distance; MyTransparentGeometry.EndParticleProfilingBlock(); } if (Acceleration != null) { MyTransparentGeometry.StartParticleProfilingBlock("Acceleration calculation"); Acceleration.GetInterpolatedValue <Vector3>(m_normalizedTime, out m_actualAcceleration); Velocity += m_actualAcceleration * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; MyTransparentGeometry.EndParticleProfilingBlock(); } m_actualAngle += RotationSpeed * MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS; MyUtils.AssertIsValid(m_actualPosition); MyUtils.AssertIsValid(m_actualAngle); return(true); }
public void PrepareForDraw(ref VRageRender.MyBillboard effectBillboard) { m_billboards.Clear(); if (m_particles.Count == 0) { return; } if (UseLayerSorting && effectBillboard == null) { effectBillboard = MyTransparentGeometry.AddBillboardEffect(m_effect); if (effectBillboard != null) { m_billboards.Add(effectBillboard); } } using (ParticlesLock.AcquireSharedUsing()) { foreach (MyAnimatedParticle particle in m_particles) { MyTransparentGeometry.StartParticleProfilingBlock("m_preallocatedBillboards.Allocate()"); VRageRender.MyBillboard billboard = MyTransparentGeometry.AddBillboardParticle(particle, effectBillboard, !UseLayerSorting); if (billboard != null) { if (!UseLayerSorting) { billboard.Position0.AssertIsValid(); billboard.Position1.AssertIsValid(); billboard.Position2.AssertIsValid(); billboard.Position3.AssertIsValid(); m_billboards.Add(billboard); } } MyTransparentGeometry.EndParticleProfilingBlock(); if (billboard == null) { break; } } } }
// 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) { 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, m_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(); 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; float alpha = 1; if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); GetBillboardQuadRotated(billboard, ref m_actualPosition, actualRadius, m_actualAngle); 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 (m_actualAngle > 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(MathHelper.ToRadians(m_actualAngle))); } polyLine.Point0 = m_actualPosition; polyLine.Point1.X = m_actualPosition.X + polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = m_actualPosition.Y + polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = m_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; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }