protected override Vector3 NewPosition(System3 system, int bundleFirstItem, int i) { var dir = (Vector3) MathHelper2.RandomVector3(1); var l = dir.Length; var k = (float) MathHelper2.GetThreadLocalRandom().NextDouble(); return dir * BoxOuterSize * k + dir * BoxInnerSize * (1 - k); }
void ISimulationScheme.Simulate(System3 system, DateTime simulationTime, long simulationStep) { m_MapModeComputed &= simulationStep == m_PrevSimulStep + 1; m_PrevSimulStep = simulationStep; var position = system.Position; var dimension = system.Dimension; var meta = system.Meta; var color = system.Color; var dt = (float)system.DT; var fun = system.ChaoticMap.Map; m_SpeedUpperBound = Math.Max(m_SpeedUpperBound * 0.75f, 1); var step = 150; var meta0 = meta[0]; var ld = (meta0.Leader + 1) % step; meta0.Leader = ld; meta[0] = meta0; //prepare seed points if (!m_MapModeComputed) { for (int i = 0; i < step; i++) { position[i] = new Vector4 ((float)(MathHelper2.GetThreadLocalRandom().NextDouble () * 0.01), 0, 0, 1); dimension[i] = Vector4.Zero; } m_MapModeComputed = true; } //iterate the seed values ld += step; for (int i = ld; i < position.Length; i += step) { var posi = position[i]; var posis = position[i - step]; fun (ref posis, ref posi ); posi.W = 1; position[i] = posi; dimension[i] = new Vector4(meta[i].Size); switch (ColorScheme) { case ColorSchemeType.Distance: var speed = (position[i] - position[i - step]).LengthFast / dt; var A = MathHelper2.Clamp (2 * speed / m_SpeedUpperBound, 0, 1); m_SpeedUpperBound = m_SpeedUpperBound < speed? speed: m_SpeedUpperBound; color[i] = (new Vector4 (1, 0.2f, 0.2f, 1) * A + new Vector4 (0.2f, 1, 0.2f, 1) * (1 - A)); break; case ColorSchemeType.Color: color[i] = new Vector4 (0.2f, 1, 0.2f, 1); break; default: break; } } }
protected override Vector3 NewPosition(System3 system, int bundleFirstItem, int i) { var pcount = system.PARTICLES_COUNT; var amount = Math.Max (AmountX * AmountY * AmountZ, float.Epsilon); var gridCount = (int)Math.Floor (Math.Pow (pcount / amount, 1 / 3.0)); var gcx = (int)Math.Max(gridCount * AmountY * gridCount * AmountZ, 1); var gcy = (int)Math.Max(gridCount * AmountZ, 1); int ix = i / gcx; int iy = (i - gcx * ix) / gcy; int iz = i - gcx * ix - gcy * iy; return Vector3.Multiply (new Vector3 (ix, iy, iz), new Vector3 (StepX, StepY, StepZ)) - Vector3.Multiply (new Vector3 (gridCount * StepX, gridCount * StepY, gridCount * StepZ), new Vector3 (AmountX, AmountY, AmountZ)) / 2; }
void IGenerationScheme.Generate(System3 system, DateTime simulationTime, long simulationStep) { var trailSize = Math.Max (system.TrailSize, 1); var trailCount = (system.Position.Length + trailSize - 1) / trailSize; var trailBundleSize = Math.Max (system.SimulationScheme is ParticlesWithTrails ? ((ParticlesWithTrails)system.SimulationScheme).TrailBundleSize : 1, 1); var trailBundleCount = (trailCount + trailBundleSize - 1) / trailBundleSize; var fun = system.ChaoticMap.Map; var position = system.Position; var dimension = system.Dimension; var meta = system.Meta; var rotation = system.Rotation; var attribute1 = system.Color; var particleCount = position.Length; var particleScale = system.ParticleScaleFactor; var dt = (float)system.DT; for (int bundleIndex = 0; bundleIndex < trailBundleCount; bundleIndex++) { var firsttrail = bundleIndex * trailBundleSize * trailSize; var lasttrail = Math.Min (firsttrail + trailBundleSize, particleCount); for (int j = 0; j < trailSize; j++) { for (int i = firsttrail; i < lasttrail; i++) { //i is the trail's first element var ii = i + j * trailBundleSize; if (ii >= particleCount) { break; } if(j != 0 || trailSize == 1) meta[ii].Size = Math.Max (system.ParticleGenerator.UpdateSize (system, i, ii), float.Epsilon); if (j == trailSize - 1) { if (meta [i].LifeLen <= 0) { system.ParticleGenerator.NewBundle (system, i); } else meta [i].LifeLen--; } } } } }
void IGenerationScheme.Generate(System3 system, DateTime simulationTime, long simulationStep) { m_MapModeComputed &= simulationStep == m_PrevSimulStep + 1; m_PrevSimulStep = simulationStep; var Position = system.Position; var Meta = system.Meta; var Color = system.Color; var dt = (float)system.DT; //prepare seed points if (!m_MapModeComputed) { for (int i = 0; i < Meta.Length; i++) { system.ParticleGenerator.MakeBubble (system, 0, i); } m_MapModeComputed = true; } }
protected virtual Vector3 NewPosition(System3 system, int bundleFirstItem, int i) { return (Vector3)MathHelper2.RandomVector3(12); }
public float UpdateSize(System3 system, int bundleFirstItem, int i) { var Meta = system.Meta; var r = (float)MathHelper2.GetThreadLocalRandom().NextDouble(); return Math.Max((1 - SizeRandomness * r) * Meta [bundleFirstItem].Size, ScaleRatioMaxDifference * SizeScaleRatio); }
public void NewBundle(System3 system, int bundleFirstItem) { var Meta = system.Meta; Meta [bundleFirstItem] = new MetaInformation { Size = (float)Math.Pow (MathHelper2.GetThreadLocalRandom().NextDouble (), SizeScalePower) * SizeScaleRatio, LifeLen = MathHelper2.GetThreadLocalRandom().Next (LifeLengthMin, LifeLengthMax), Leader = Meta[bundleFirstItem].Leader }; MakeBubble(system, bundleFirstItem, Meta [bundleFirstItem].Leader + bundleFirstItem); return; }
public void MakeBubble(System3 system, int bundleFirstItem, int i) { var Position = system.Position; var Dimension = system.Dimension; var Rotation = system.Rotation; var Color = system.Color; if (PreferStableOrbits) { var map = system.ChaoticMap; var lp = map.LyapunovExponent(Position [i], StableOrbitsCount); if (lp.Item1 > StableOrbitsLMin && lp.Item1 < StableOrbitsLMax) return; if (lp.Item2.Length < StableOrbitsMaxDist) return; } var size = UpdateSize(system, bundleFirstItem, i); var newpos = NewPosition(system, bundleFirstItem, i); Dimension [i] = new Vector4(size, size, size, size); Position [i] = new Vector4(newpos.X, newpos.Y, newpos.Z, 1); Color [i] = new Vector4(0, 1, 0, 1); Rotation [i] = Matrix4.Identity; }
void IGenerationScheme.Generate(System3 system, DateTime simulationTime, long simulationStep) { var trailBundleSize = Math.Max (system.SimulationScheme is ParticlesWithTrails ? ((ParticlesWithTrails)system.SimulationScheme).TrailBundleSize : 1, 1); var dt = (float)system.DT; m_GIndices = m_GIndices ?? GenerationIndices(system).GetEnumerator(); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); while(m_GIndices.MoveNext()) { var pack = m_GIndices.Current; var i = (int)(pack >> 32); var j = (int)(pack); var ii = i + j * trailBundleSize; if (ii >= system.Position.Length) { break; } var _i = i; var metai = system.Meta.MapReadWrite(ref _i); if(j == 0) { if (m_Length != system.Position.Length) { system.ParticleGenerator.NewBundle (system, i); } else if (metai[_i].LifeLen <= 0) { system.ParticleGenerator.NewBundle (system, i); } else { metai[_i].LifeLen--; metai[_i].Size = Math.Max (system.ParticleGenerator.UpdateSize (system, i, i), float.Epsilon); } } else { var _ii = ii; system.Meta.MapReadWrite(ref _ii)[_ii].Size = Math.Max (system.ParticleGenerator.UpdateSize (system, i, ii), float.Epsilon); } if(m_Length == system.Position.Length) if(sw.Elapsed > TimeSpan.FromMilliseconds(50)) return; } m_GIndices.Dispose (); m_GIndices = null; m_Length = system.Position.Length; }
IEnumerable<long> GenerationIndices(System3 system) { var trailSize = Math.Max (system.TrailSize, 1); var trailCount = (system.Position.Length + trailSize - 1) / trailSize; var trailBundleSize = Math.Max (system.SimulationScheme is ParticlesWithTrails ? ((ParticlesWithTrails)system.SimulationScheme).TrailBundleSize : 1, 1); var trailBundleCount = (trailCount + trailBundleSize - 1) / trailBundleSize; var position = system.Position; for (int bundleIndex = 0; bundleIndex < trailBundleCount; bundleIndex++) { var firsttrail = bundleIndex * trailBundleSize * trailSize; var lasttrail = Math.Min (firsttrail + trailBundleSize, system.Position.Length); for (int j = 0; j < trailSize; j++) { for (int i = firsttrail; i < lasttrail; i++) { //i is the trail's first element var ii = i + j * trailBundleSize; if (ii >= system.Position.Length) { yield break; } yield return (long)i << 32 | (uint)j; } } } }
void ISimulationScheme.Simulate(System3 system, DateTime simulationTime, long simulationStep) { var trailBundleSize = Math.Max(TrailBundleSize, 1); if (m_State == null) { //create program from resources filtered by namespace and name var program = new Program ("SimulationScheme") { RenderPass.GetShaders ("System3", "ParticlesWithTrails"), RenderPass.GetShaders ("System3", "PWTSub") }; m_Parameters = new BufferObjectCompact<float>(sizeof(float), 0) { Name = "map_parameters_buffer", Usage = BufferUsageHint.DynamicDraw }; m_State = new State (null) { program, new ShaderStorageSet { {"Position", system.PositionBuffer}, {"Rotation", system.RotationBuffer}, {"MapParameters", m_Parameters}, {"Dimension", system.DimensionBuffer}, {"Attribute1", system.ColorBuffer}, {"Meta", system.MetaBuffer}, }, new UniformState { {"u_Dt", () => (float)system.DT }, {"u_TrailSize", () => system.TrailSize }, {"u_TrailBundleSize", () => TrailBundleSize }, {"u_StepsPerFrame", () => system.StepsPerFrame }, {"u_ParticleScale", () => (float)system.ParticleScaleFactor }, {"u_Map", (ShaderType)ShaderTypeExt.ComputeShader, () => system.ChaoticMap.Name }, } }; } system.MetaBuffer.Publish(); system.PositionBuffer.Publish(); system.DimensionBuffer.Publish(); system.RotationBuffer.Publish(); system.ColorBuffer.Publish(); system.RotationLocalBuffer.Publish(); m_Parameters.Length = system.ChaoticMap.a.Length; m_Parameters.CopyFrom(system.ChaoticMap.a, 0); m_Parameters.Publish(); m_State.Activate (); GLExtensions.DispatchCompute (system.PARTICLES_COUNT/(8 * trailBundleSize) + 1, 1, 1); //system.MetaBuffer.Readout(); //system.PositionBuffer.Readout(); //system.RotationBuffer.Readout(); //system.DimensionBuffer.Readout(); //system.ColorBuffer.Readout(); }
void ISimulationScheme.Simulate(System3 system, DateTime simulationTime, long simulationStep) { m_MapModeComputed &= simulationStep == m_PrevSimulStep + 1; m_PrevSimulStep = simulationStep; var position = system.Position; var fun = system.ChaoticMap.Map; m_SpeedUpperBound = Math.Max(m_SpeedUpperBound * 0.75f, 1); //prepare seed points if (!m_MapModeComputed) { for (int i = 0; i < position.Length; i++) { system.ParticleGenerator.MakeBubble(system, i, i); fun (ref position[i], ref position[i]); position[i].W = 1; } m_MapModeComputed = true; } }
void ISimulationScheme.Simulate(System3 system, DateTime simulationTime, long simulationStep) { m_SpeedUpperBound = Math.Max(m_SpeedUpperBound * 0.75f, 0.01f); var trailSize = Math.Max(system.TrailSize, 1); var trailCount = (system.Position.Length + trailSize - 1) / trailSize; var trailBundleSize = Math.Max(TrailBundleSize, 1); var trailBundleCount = (trailCount + trailBundleSize - 1) / trailBundleSize; var stepsPerFrame = Math.Max(system.StepsPerFrame, 1); var fun = system.ChaoticMap.Map; var position = system.Position; var dimension = system.Dimension; var meta = system.Meta; var rotation = system.Rotation; var attribute1 = system.Color; var particleCount = position.Length; var particleScale = system.ParticleScaleFactor; var dt = (float)system.DT; Parallel.For (0, trailBundleCount, bundleIndex => { var firsttrail = bundleIndex * trailBundleSize * trailSize; var lasttrail = Math.Min(firsttrail + trailBundleSize , particleCount); var speedBound = m_SpeedUpperBound; var dp = Vector4.Zero; var dpA = Vector4.Zero; var dpB = Vector4.Zero; var delta2 = Vector4.Zero; var size = 0f; var middlepoint = Vector4.Zero; var endpoint = Vector4.Zero; for (int j = 0; j < stepsPerFrame; j++) { for (int i = firsttrail ; i < lasttrail ; i += 1) { //i is the trail's first element var pi = i + meta[i].Leader; var K = dt; size = Math.Max(meta[pi].Size, float.Epsilon); if(MapMode == MapModeType.ForceField) { dp = new Vector4 (meta[i].Velocity, 0); fun (ref position[pi], ref delta2); meta[i].Velocity += delta2.Xyz * dt; } else { fun (ref position[pi], ref dp); } // var b0 = new Vector4( dp.Xyz, 0); var b2 = new Vector4( Vector3.Cross( b0.Xyz, rotation[pi].Row1.Xyz), 0); var b1 = new Vector4( Vector3.Cross( b2.Xyz, b0.Xyz), 0); b0.Normalize(); b1.Normalize(); b2.Normalize(); // if(IntegrationStep == IntegrationStepType.LimitDelta) { K *= Math.Min(1, 10 * (size * particleScale)/ (dp.Length * dt)); } if(Interpolation == InterpolationType.Cubic) K *= 0.5f; dp *= K; // var localCount = (float)Math.Ceiling(dp.Length / (size * particleScale)); localCount = Math.Min(localCount, trailSize); if(Interpolation == InterpolationType.Cubic) { dpA = 2 * dp; middlepoint = position[pi] + dp; fun (ref middlepoint, ref dpB); dpB *= K; endpoint = middlepoint + dpB; fun (ref endpoint, ref dpB); dpB *= 2 * K; } for(int li = 0; li < localCount; li++) { meta[i].Leader = (meta[i].Leader + trailBundleSize) % (trailSize * trailBundleSize); var ii = i + meta[i].Leader; if (ii >= particleCount) { ii = i; meta[i].Leader = 0; } if(Interpolation == InterpolationType.Cubic) { var t = (1 + li) / localCount; var p1 = 2*t*t*t - 3*t*t + 1; var p2 = t*t*t - 2*t*t + t; var p3 = -p1 + 1; var p4 = p2 + t*t - t; position[ii] = p1 * position[pi] + p2 * dpA + p3 * endpoint + p4 * dpB; dimension[ii] = new Vector4 (size, size, size, size); rotation[ii] = new Matrix4(b0, b1, b2, new Vector4(0,0,0,1)); } else { position[ii] = position[pi] + ((1 + li) / localCount) * dp; dimension[ii] = new Vector4 (size, size, size, size); rotation[ii] = new Matrix4(b0, b1, b2, new Vector4(0,0,0,1)); } switch (ComputeMetadataMode) { case ComputeMetadata.Speed: attribute1[ii] = dp; break; case ComputeMetadata.Tangent: attribute1[ii] = b0; break; default: break; } } } } var orig = m_SpeedUpperBound; var help = orig; while( speedBound > orig && (help = Interlocked.CompareExchange(ref m_SpeedUpperBound, speedBound, orig)) != orig) orig = help; }); }
protected override ParticleSystem GetInstanceInternal(GameWindow win) { var result = new System3 { PARTICLES_COUNT = 260000, VIEWPORT_WIDTH = 324, NEAR = 1, FAR = 10240, DT = 1, Fov = 0.9, PublishMethod = PublishMethod.Never, ParticleScaleFactor = 600, SimulationScheme = new ParticlesWithTrailsGpuSimulationScheme(), GenerationScheme = new ParticlesWithTrailsGenerationScheme(), ParticleGenerator = new GridGenerator { AmountX = 1, AmountY = 1, AmountZ = 0.001f, StepX = 0.1f, StepY = 0.1f }, ChaoticMap = new Swirl2DMap() }; return result; }