/// <summary> /// Draws the model. /// </summary> /// <param name="gameTime">The elapsed game time.</param> public override void Draw(TimeSpan gameTime) { if (this.meshes == null) { return; } float zOrder = Vector3.DistanceSquared(this.RenderManager.CurrentDrawingCamera3D.Position, this.rootJointTransform.Position); this.shouldSkinMeshes |= this.RefreshSkinMatrices(); this.shouldSkinMeshes |= this.ShouldRefreshMorph(); var worldTransform = this.rootJointTransform.WorldTransform; for (int i = 0; i < this.meshes.Length; i++) { var currentMesh = this.meshes[i] as SkinnedMesh; if (this.shouldSkinMeshes) { Timers.BeginAveragedTimer("Skin_" + this.Owner.Name); currentMesh.SetBones(this.skinMatrices, this.Quality, this.morphTargetWeights, true, true); Timers.EndAveragedTimer("Skin_" + this.Owner.Name); this.GraphicsDevice.BindVertexBuffer(currentMesh.VertexBuffer); } Material currentMaterial = null; if (this.Materials?.Length > 0 && this.ModelMesh?.InternalModel?.Materials?.Count > currentMesh.MaterialIndex) { string fileMaterialName = this.ModelMesh.InternalModel.Materials[currentMesh.MaterialIndex]; var materialComponent = (from m in this.Materials where m.AsignedTo == fileMaterialName select m).FirstOrDefault(); if (materialComponent != null) { currentMaterial = materialComponent.Material; } else { currentMaterial = this.Materials[0].Material; } } if (currentMaterial != null) { currentMesh.ZOrder = zOrder; // Draw mesh this.RenderManager.DrawMesh(currentMesh, currentMaterial, worldTransform, this.Owner.IsFinalStatic); } } this.shouldSkinMeshes = false; this.rootJointChanged = false; }
private void UpdateParticles(TimeSpan gameTime) { if (this.ParticleSystem.ZOrdering) { Vector3 cameraPosition = this.RenderManager.CurrentDrawingCamera3D.Position; Vector3.Transform(ref cameraPosition, ref this.inverseWorld, out vertexComparer.Camera); } var pS = this.ParticleSystem; bool hasForces = false; ////if (pS.ApplyForces) ////{ //// if (this.forcesManager != null) //// { //// this.forcesManager.GetForces(pS.ForcesCategory, ref this.forces); //// hasForces = this.forces.Count > 0; //// if (hasForces) //// { //// for (int i = 0; i < this.forces.Count; i++) //// { //// this.forces[i].Prepare(this); //// } //// } //// } ////} pS.material.VelocityTrailFactor = (pS.ScreenAlign == NewParticleSystem.ScreenAlignType.Velocity) ? pS.VelocityTrailFactor : 0; // The amount of time this.timeFactor = (float)gameTime.TotalSeconds * this.ParticleSystem.TimeFactor; // Gets the number of new particles in this frame var newParticles = this.LaunchNewParticles(); this.aliveParticles = 0; float correctedTime = this.timeFactor * this.ParticleSystem.LifeFactor; Timers.BeginAveragedTimer("Particles"); ////this.ParticleSystem.Shape?.Prepare(); Parallel.For(0, this.numParticles, (i) => { ////for (var i = 0; i < this.numParticles; i++) ////{ ref Particle p = ref this.particles[i]; // We check the life cycle of the particle if (p.Alive) { p.LifeLerp += correctedTime / p.LifeTime; if (p.LifeLerp > 1) { p.Alive = false; p.Size = 0; } } else { // If the particle is not alive we create a new one (if there are new particles to create) if (Interlocked.Decrement(ref newParticles) >= 0) { this.ParticleSystem.ResetParticle(ref p); var startTime = (float)(this.timeFactor * this.random.NextDouble()); p.LifeLerp = startTime * (this.ParticleSystem.LifeFactor) / p.LifeTime; p.Position += startTime * p.Velocity; } } if (p.Alive) { // If the particle is alive after all, we update it p.Forces.X -= this.timeFactor * pS.Gravity.X; p.Forces.Y -= this.timeFactor * pS.Gravity.Y; p.Forces.Z -= this.timeFactor * pS.Gravity.Z; if (hasForces) { for (int fIdx = 0; fIdx < this.forces.Count; fIdx++) { this.forces[fIdx].ApplyForce(this, this.timeFactor, ref p); } } if (pS.ColorAnimated && (pS.ColorOverLife != null)) { p.Color = p.InitColor * pS.ColorOverLife.GetValue(p.LifeLerp); if (pS.PremultiplyAlpha) { var alpha = p.Color.A / 255f; p.Color.R = (byte)(p.Color.R * alpha); p.Color.G = (byte)(p.Color.G * alpha); p.Color.B = (byte)(p.Color.B * alpha); } } if (pS.SizeAnimated && (pS.SizeOverLife != null)) { p.Size = p.InitSize * pS.SizeOverLife.GetValue(p.LifeLerp); } if ((pS.VelocityAnimated) && (pS.VelocityOverLifeX != null) && (pS.VelocityOverLifeY != null) && (pS.VelocityOverLifeZ != null)) { p.Velocity.X = p.InitVelocity.X * pS.VelocityOverLifeX.GetValue(p.LifeLerp); p.Velocity.Y = p.InitVelocity.Y * pS.VelocityOverLifeY.GetValue(p.LifeLerp); p.Velocity.Z = p.InitVelocity.Z * pS.VelocityOverLifeZ.GetValue(p.LifeLerp); } if ((pS.CollideWithFloor) && (p.Position.Y < pS.FloorLevel)) { switch (pS.CollisionType) { case NewParticleSystem.ParticleCollisionType.Die: p.Alive = false; p.Size = 0; break; case NewParticleSystem.ParticleCollisionType.Bounce: p.Position.Y = pS.FloorLevel; p.Velocity.X = p.Velocity.X * pS.FloorBounciness; p.Velocity.Y = (p.Velocity.Y + p.Forces.Y) * -pS.FloorBounciness; p.Velocity.Z = p.Velocity.Z * pS.FloorBounciness; p.Forces.Y = 0; break; case NewParticleSystem.ParticleCollisionType.Stop: default: p.Position.Y = pS.FloorLevel; p.Velocity.X = 0; p.Velocity.Y = 0; p.Velocity.Z = 0; break; } } p.Angle += timeFactor * p.AngularVelocity; p.Position.X += (p.Velocity.X + p.Forces.X) * timeFactor; p.Position.Y += (p.Velocity.Y + p.Forces.Y) * timeFactor; p.Position.Z += (p.Velocity.Z + p.Forces.Z) * timeFactor; int particleIndex = (Interlocked.Increment(ref this.aliveParticles) - 1) * 4; PointSpriteVertexFormat pointVertex = default(PointSpriteVertexFormat); pointVertex.Position = p.Position; pointVertex.Size.X = p.Size; pointVertex.Size.Y = p.Size; pointVertex.Color = p.Color; pointVertex.VelocityAndRotation.X = p.Velocity.X; pointVertex.VelocityAndRotation.Y = p.Velocity.Y; pointVertex.VelocityAndRotation.Z = p.Velocity.Z; pointVertex.VelocityAndRotation.W = p.Angle; // Copy to Vertex Buffer pointVertex.VertexTexCoords = VertexUVs[0]; this.vertices[particleIndex++] = pointVertex; // 0 pointVertex.VertexTexCoords = VertexUVs[1]; this.vertices[particleIndex++] = pointVertex; // 1 pointVertex.VertexTexCoords = VertexUVs[2]; this.vertices[particleIndex++] = pointVertex; // 2 pointVertex.VertexTexCoords = VertexUVs[3]; this.vertices[particleIndex++] = pointVertex; // 3 } }