/// <inheritdoc/> public override unsafe void Update(float dt, ParticlePool pool) { if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity)) { return; } var posField = pool.GetField(ParticleFields.Position); var velField = pool.GetField(ParticleFields.Velocity); var lifeField = pool.GetField(ParticleFields.Life); foreach (var particle in pool) { var surfacePoint = new Vector3(0, 0, 0); var surfaceNormal = new Vector3(0, 1, 0); var particlePos = (*((Vector3 *)particle[posField])); var particleVel = (*((Vector3 *)particle[velField])); var isInside = false; if (FieldShape != null) { FieldShape.PreUpdateField(WorldPosition, WorldRotation, WorldScale); isInside = FieldShape.IsPointInside(particlePos, out surfacePoint, out surfaceNormal); } if (IsHollow != isInside) { if (IsHollow) { surfaceNormal *= -1; } // The particle is on the wrong side of the collision shape and must collide (*((Vector3 *)particle[posField])) = surfacePoint; var verIncidentCoef = Vector3.Dot(surfaceNormal, particleVel); var verticalIncidentVelocity = verIncidentCoef * surfaceNormal; var horizontalIncidentVelocity = particleVel - verticalIncidentVelocity; particleVel = horizontalIncidentVelocity * (1 - Friction) + verticalIncidentVelocity * ((verIncidentCoef > 0) ? Restitution : -Restitution); (*((Vector3 *)particle[velField])) = particleVel; // TODO Maybe set some collision flags if other calculations depend on them // Possibly kill the particle if (KillParticles) { // Don't set the particle's life directly to 0 just yet - it might need to spawn other particles on impact (*((float *)particle[lifeField])) = MathUtil.ZeroTolerance; } } } }
/// <inheritdoc /> public override unsafe void Update(float dt, ParticlePool pool) { // The force field operates over position and velocity. If the particles don't have such fields we can't run this update if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity)) { return; } var posField = pool.GetField(ParticleFields.Position); var velField = pool.GetField(ParticleFields.Velocity); // Depending on our settings some of the energy will be lost (it directly translates to changes in position) // and some of the energy will be preserved (it translates to changes in velocity) var directToPosition = 1f - EnergyConservation; foreach (var particle in pool) { var alongAxis = new Vector3(0, 1, 0); var awayAxis = new Vector3(0, 0, 1); var aroundAxis = new Vector3(1, 0, 0); var particlePos = (*((Vector3 *)particle[posField])); var particleVel = (*((Vector3 *)particle[velField])); var forceMagnitude = 1f; if (FieldShape != null) { FieldShape.PreUpdateField(WorldPosition, WorldRotation, WorldScale); forceMagnitude = FieldShape.GetDistanceToCenter(particlePos, particleVel, out alongAxis, out aroundAxis, out awayAxis); forceMagnitude = FieldFalloff.GetStrength(forceMagnitude); } forceMagnitude *= dt * parentScale; var totalForceVector = ForceFixed + alongAxis * ForceDirected + aroundAxis * ForceVortex + awayAxis * ForceRepulsive; totalForceVector *= forceMagnitude; // Force contribution to velocity - conserved energy var vectorContribution = totalForceVector * EnergyConservation; (*((Vector3 *)particle[velField])) += vectorContribution; // Force contribution to position - lost energy vectorContribution = (vectorContribution * (dt * 0.5f)) + (totalForceVector * directToPosition); (*((Vector3 *)particle[posField])) += vectorContribution; } }
public override unsafe void Update(float dt, ParticlePool pool) { if (!pool.FieldExists(ParticleFields.Position) || !pool.FieldExists(ParticleFields.Velocity)) { return; } var posField = pool.GetField(ParticleFields.Position); var velField = pool.GetField(ParticleFields.Velocity); // var colField = pool.GetField(ParticleFields.Color); var directToPosition = 1f - EnergyConservation; foreach (var particle in pool) { var alongAxis = new Vector3(0, 1, 0); var awayAxis = new Vector3(0, 0, 1); var aroundAxis = new Vector3(1, 0, 0); var particlePos = (*((Vector3 *)particle[posField])); var particleVel = (*((Vector3 *)particle[velField])); var forceMagnitude = 1f; if (FieldShape != null) { FieldShape.PreUpdateField(WorldPosition, WorldRotation, WorldScale); forceMagnitude = FieldShape.GetDistanceToCenter(particlePos, particleVel, out alongAxis, out aroundAxis, out awayAxis); forceMagnitude = FieldFalloff.GetStrength(forceMagnitude); } forceMagnitude *= dt * parentScale; var totalForceVector = ForceFixed + alongAxis * ForceDirected + aroundAxis * ForceVortex + awayAxis * ForceRepulsive; totalForceVector *= forceMagnitude; // Force contribution to velocity - conserved energy var vectorContribution = totalForceVector * EnergyConservation; (*((Vector3 *)particle[velField])) += vectorContribution; // Force contribution to position - lost energy vectorContribution = (vectorContribution * (dt * 0.5f)) + (totalForceVector * directToPosition); (*((Vector3 *)particle[posField])) += vectorContribution; } }
private void ExportFieldMapData() { // Reading Palette FDPalette palette = new FDPalette(@".\color"); ShapeDataFile shapeData = new ShapeDataFile(@".\FDSHAP.DAT"); shapeData.LoadData(); FieldDataFile fieldData = new FieldDataFile(@".\FDFIELD.DAT"); fieldData.LoadData(); for (int m = 0; m < 33; m++) { FieldMap map = fieldData.GetField(m); HashSet <int> shapes = new HashSet <int>(); for (int i = 0; i < map.Width; i++) { for (int j = 0; j < map.Height; j++) { var shapeIndex = map.GetShapeIndexAt(i, j); shapes.Add(shapeIndex); } } var shapePanel = shapeData.GetPanel(m); foreach (int shapeIndex in shapes) { ShapeInfo shapeInfo = shapePanel.Shapes[shapeIndex]; FieldShape shape = new FieldShape(); shape.Type = shapeInfo.Type; shape.BattleGroundId = shapeInfo.BattleGroundId; map.Shapes[shapeIndex] = shape; } string mapString = JsonConvert.SerializeObject(map, Formatting.Indented); int mm = m + 1; File.WriteAllText(string.Format(@"D:\Temp\FDII\Chapter_{0}.txt", (mm < 10 ? "0" + mm.ToString() : mm.ToString())), mapString); } }
private void DoEmissionSettings() { if (gameObject.GetComponent <SphereCollider>() != null) { fieldShape = FieldShape.Sphere; } else if (gameObject.GetComponent <CapsuleCollider>() != null) { fieldShape = FieldShape.Cylinder; } else { fieldShape = FieldShape.Box; } if (emitterObject) { emitterObject.GetComponent <ParticleSystem>().emissionRate = Mathf.Clamp(particleMultiplier * volume * 0.033f, 20.0f, 5000.0f); } }
/// <inheritdoc /> public override bool TryGetDebugDrawShape(out DebugDrawShape debugDrawShape, out Vector3 translation, out Quaternion rotation, out Vector3 scale) { if (!DebugDraw) { return(base.TryGetDebugDrawShape(out debugDrawShape, out translation, out rotation, out scale)); } rotation = Quaternion.Identity; scale = new Vector3(1, 1, 1); translation = new Vector3(0, 0, 0); debugDrawShape = FieldShape?.GetDebugDrawShape(out translation, out rotation, out scale) ?? DebugDrawShape.None; rotation *= WorldRotation; scale *= WorldScale; translation *= WorldScale; rotation.Rotate(ref translation); translation += WorldPosition; return(true); }