public int AddParticles(ref ISystemData particlesToAdd) { // Copy particles in to our structure int numAdded = _systemData.CopyFrom (_systemData.NumParticles, ref particlesToAdd, 0, particlesToAdd.NumParticles); // Return number added return numAdded; }
public UnmanagedSimulation(int maxNumParticles) { SoAData soaData =new SoAData(maxNumParticles); _systemData = soaData; _systemDataStreams = soaData; _worldBounds = new object(); _is2D = false; }
public int CopyFrom(int offset, ref ISystemData src, int srcOffset, int count) { int capacityLeft = MaxNumParticles - NumParticles; int numToCopy = count < capacityLeft ? count : capacityLeft; // Position Marshal.Copy(src.PositionX, srcOffset, _positionStreamX + offset, numToCopy); Marshal.Copy(src.PositionY, srcOffset, _positionStreamY + offset, numToCopy); Marshal.Copy(src.PositionZ, srcOffset, _positionStreamZ + offset, numToCopy); // Time if (_lifespanStream != null) Marshal.Copy(src.Lifespan, srcOffset, _lifespanStream + offset, numToCopy); if (_timeRemainingStream != null) Marshal.Copy(src.TimeRemaining, srcOffset, _timeRemainingStream + offset, numToCopy); // Velocity if (_velocityStreamX != null) Marshal.Copy(src.VelocityX, srcOffset, _velocityStreamX + offset, numToCopy); if (_velocityStreamY != null) Marshal.Copy(src.VelocityY, srcOffset, _velocityStreamY + offset, numToCopy); if (_velocityStreamZ != null) Marshal.Copy(src.VelocityZ, srcOffset, _velocityStreamZ + offset, numToCopy); // Mass if (_massStream != null) Marshal.Copy(src.Mass, srcOffset, _massStream + offset, numToCopy); // UserData if (_userDataStream != null) Marshal.Copy(src.UserData, srcOffset, (System.IntPtr)(_userDataStream + offset), numToCopy); // Update number of particles _numParticles += numToCopy; // Return number copied return numToCopy; }
public int CopyFrom(int offset, ref ISystemData src, int srcOffset, int count) { int capacityLeft = MaxNumParticles - NumParticles; int numToCopy = count < capacityLeft ? count : capacityLeft; for (int i = offset, j = srcOffset; i < numToCopy; i++, j++) { _systemData[i].px = src.PositionX[j]; _systemData[i].py = src.PositionY[j]; _systemData[i].pz = src.PositionZ[j]; _systemData[i].vx = src.VelocityX[j]; _systemData[i].vy = src.VelocityY[j]; _systemData[i].vz = src.VelocityZ[j]; _systemData[i].lifespan = src.Lifespan[i]; _systemData[i].timeRemaining = src.TimeRemaining[i]; _systemData[i].mass = src.Mass[i]; } // Update number of particles _numParticles += numToCopy; // Return number copied return numToCopy; }
protected override void _EmitParticles(int numParticlesToEmit, float oneOverPPS, float dt, float pt, out ISystemData particlesToEmit) { // TODO: Pool this stuff if (_particlesToEmit.MaxNumParticles < numParticlesToEmit) _particlesToEmit = new SoAData(numParticlesToEmit); const int numBatches = 0; int numRemainder = numParticlesToEmit; float initialMass = _InitialMass(pt); float initialSpeed = _InitialSpeed(pt); float initialLifespan = _InitialLifespan(pt); bool emitOnSurfaceOnly = _EmitOnSurfaceOnly(pt); bool emitRingOnly = _EmitRingOnly(pt); float radius = _Radius(pt); // Emit remaining particles individually int numBatchesTimesFour = numBatches * 4; for (int i = 0; i < numRemainder; i++) { // Calculate pos on circle with a random angle float angle = (float)(RandomSource.NextDouble()) * MathF.TwoPI; float posX = MathF.Cos(angle) * radius; float posY = MathF.Sin(angle) * radius; float posZ = emitRingOnly ? 0.0f : MathF.Sin((float)(RandomSource.NextDouble()) * MathF.TwoPI) * radius; // If this emitter is supposed to emit only on the surface // don't need to get a random distance if (!emitOnSurfaceOnly) { float distance = (float)RandomSource.NextDouble(); posX *= distance; posY *= distance; posZ *= distance; } // Transform position // TODO: Matrix and transform stuff // Length float len = MathF.Sqrt((posX * posX) + (posY * posY) + (posZ * posZ)); // Normalize float velX = posX / len; float velY = posY / len; float velZ = posZ / len; // Scale by speed velX *= initialSpeed; velY *= initialSpeed; velZ *= initialSpeed; // Avoid clumping by doing some pre-simulation float preSimTime = (i + 1) * oneOverPPS; if (oneOverPPS > 0) { posX += velX * preSimTime; posY += velY * preSimTime; posZ += velZ * preSimTime; } // Store out position _particlesToEmit._positionStreamX[numBatchesTimesFour + i] = posX; _particlesToEmit._positionStreamY[numBatchesTimesFour + i] = posY; _particlesToEmit._positionStreamZ[numBatchesTimesFour + i] = posZ; // Store out velocity _particlesToEmit._velocityStreamX[numBatchesTimesFour + i] = velX; _particlesToEmit._velocityStreamY[numBatchesTimesFour + i] = velY; _particlesToEmit._velocityStreamZ[numBatchesTimesFour + i] = velZ; // Store out lifespan and mass float lifespan = initialLifespan - preSimTime; _particlesToEmit._lifespanStream[numBatchesTimesFour + i] = lifespan; _particlesToEmit._timeRemainingStream[numBatchesTimesFour + i] = lifespan; _particlesToEmit._massStream[numBatchesTimesFour + i] = initialMass; } // Assign number of particles _particlesToEmit._numParticles = numParticlesToEmit; // Assign the output variable particlesToEmit = _particlesToEmit; }
/// <summary> /// This method is a request to emit a number of particles. The implementor should assign, and populate /// the <see cref="ISystemData"/> passed as a parameter with the particles it does emit. /// </summary> /// /// <remarks> /// If the value of <see cref="particlesToEmit"/> is not <see cref="null"/>, <see cref="ISimulation.AddParticles"/> /// will be called following the return of this method. /// </remarks> /// /// <param name="numParticlesToEmit"> The number of particles requested for emission </param> /// <param name="oneOverPPS"> A value which does not need to be recomputed, and is needed in most emitters (1.0 / ParticlesPerSecond) </param> /// <param name="dt"> The time, in seconds, since the last call to AdvanceTime(). </param> /// <param name="pt"> A normalized value which is to used by the Emitter as an interpolation parameter. </param> /// <param name="particlesToEmit"> A <see cref="ISystemData"/> full of particles to add to the <see cref="ISimulation"/>. </param> protected abstract void _EmitParticles(int numParticlesToEmit, float oneOverPPS, float dt, float pt, out ISystemData particlesToEmit);
public int CopyFrom(int offset, ref ISystemData src, int srcOffset, int count) { int capacityLeft = MaxNumParticles - NumParticles; int numToCopy = count < capacityLeft ? count : capacityLeft; // Position System.Array.Copy(src.PositionX, srcOffset, _positionStreamX, offset, numToCopy); System.Array.Copy(src.PositionY, srcOffset, _positionStreamY, offset, numToCopy); System.Array.Copy(src.PositionZ, srcOffset, _positionStreamZ, offset, numToCopy); // Time System.Array.Copy(src.Lifespan, srcOffset, _lifespanStream, offset, numToCopy); System.Array.Copy(src.TimeRemaining, srcOffset, _timeRemainingStream, offset, numToCopy); // Velocity System.Array.Copy(src.VelocityX, srcOffset, _velocityStreamX, offset, numToCopy); System.Array.Copy(src.VelocityY, srcOffset, _velocityStreamY, offset, numToCopy); System.Array.Copy(src.VelocityZ, srcOffset, _velocityStreamZ, offset, numToCopy); // Mass System.Array.Copy(src.Mass, srcOffset, _massStream, offset, numToCopy); // UserData System.Array.Copy(src.UserData, srcOffset, _userDataStream, offset, numToCopy); // Update number of particles _numParticles += numToCopy; // Return number copied return numToCopy; }