public static void SimulateParticleAging(PartSysEmitter emitter, float timeToSimulateSec)
    {
        var it   = emitter.NewIterator();
        var ages = emitter.GetParticles();

        while (it.HasNext())
        {
            var particleIdx = it.Next();
            ages[particleIdx] += timeToSimulateSec;
        }

        emitter.PruneExpiredParticles();
    }
    private void RenderParticles(PartSysEmitter emitter)
    {
        var it         = emitter.NewIterator();
        var totalCount = emitter.GetActiveCount();

        if (totalCount == 0)
        {
            return;
        }

        // Lazily initialize render state
        if (!emitter.HasRenderState())
        {
            emitter.SetRenderState(
                new QuadEmitterRenderState(_device, emitter));
        }

        var renderState = (QuadEmitterRenderState)emitter.GetRenderState();

        using var spriteMemory = MemoryPool.Rent(4 * totalCount);
        var sUpdateBuffer = spriteMemory.Memory.Span.Slice(0, 4 * totalCount);

        var i = 0;

        while (it.HasNext())
        {
            var particleIdx = it.Next();
            FillVertex(emitter, particleIdx, sUpdateBuffer, i);
            i += 4;
        }

        renderState.vertexBuffer.Resource.Update <SpriteVertex>(sUpdateBuffer);

        _device.SetMaterial(renderState.material);
        renderState.bufferBinding.Resource.Bind();

        // Draw the batch
        _device.DrawIndexed(PrimitiveType.TriangleList, 4 * totalCount, 6 * totalCount);
    }
Example #3
0
    public override void Render(IGameViewport viewport, PartSysEmitter emitter)
    {
        var it = emitter.NewIterator();

        var animParams = AnimatedModelParams.Default;

        animParams.rotation3d = true;

        // Lazily initialize render state
        if (!emitter.HasRenderState())
        {
            // Resolve the mesh filename
            var baseName = ResolveBasename(emitter.GetSpec().GetMeshName());
            var skmName  = baseName + ".skm";
            var skaName  = baseName + ".ska";

            try
            {
                var animId = new EncodedAnimId(NormalAnimType.ItemIdle); // This seems to be item_idle
                var model  = _modelFactory.FromFilenames(skmName, skaName, animId, animParams);

                emitter.SetRenderState(
                    new ModelEmitterRenderState(model)
                    );
            }
            catch (Exception e)
            {
                Logger.Error("Unable to load model {0} for particle system {1}: {2}",
                             baseName, emitter.GetSpec().GetParent().GetName(), e);

                emitter.SetRenderState(new ModelEmitterRenderState(null));
            }
        }

        var renderState = (ModelEmitterRenderState)emitter.GetRenderState();

        if (renderState.Model == null)
        {
            return; // The loader above was unable to load the model for this emitter
        }

        var overrides = new MdfRenderOverrides
        {
            ignoreLighting  = true,
            overrideDiffuse = true
        };

        var yaw   = emitter.GetParamState(PartSysParamId.part_yaw);
        var pitch = emitter.GetParamState(PartSysParamId.part_pitch);
        var roll  = emitter.GetParamState(PartSysParamId.part_roll);

        while (it.HasNext())
        {
            var particleIdx = it.Next();
            var age         = emitter.GetParticleAge(particleIdx);

            overrides.overrideColor = GeneralEmitterRenderState.GetParticleColor(emitter, particleIdx);

            // Yes, this is *actually* swapped for Y / Z
            var particleState = emitter.GetParticleState();
            animParams.offsetX = particleState.GetState(ParticleStateField.PSF_POS_VAR_X, particleIdx);
            animParams.offsetY = particleState.GetState(ParticleStateField.PSF_POS_VAR_Z, particleIdx);
            animParams.offsetZ = particleState.GetState(ParticleStateField.PSF_POS_VAR_Y, particleIdx);

            if (yaw != null)
            {
                animParams.rotationYaw = Angles.ToRadians(yaw.GetValue(emitter, particleIdx, age));
            }

            if (pitch != null)
            {
                animParams.rotationPitch = Angles.ToRadians(pitch.GetValue(emitter, particleIdx, age));
            }

            if (roll != null)
            {
                animParams.rotationRoll = Angles.ToRadians(roll.GetValue(emitter, particleIdx, age));
            }

            renderState.Model.SetTime(animParams, age);

            _modelRenderer.Render(viewport, renderState.Model, animParams, new List <Light3d>(), overrides);
        }
    }
    public static void SimulateParticleMovement(PartSysEmitter emitter, float timeToSimulateSecs)
    {
        var spec = emitter.GetSpec();

        // Used as a factor in integrating the acceleration to retroactively calculate
        // its influence on the particle position
        var accelIntegrationFactor = timeToSimulateSecs * timeToSimulateSecs * 0.5f;

        var state = emitter.GetParticleState();
        var it    = emitter.NewIterator();

        while (it.HasNext())
        {
            var particleIdx = it.Next();
            var particleAge = emitter.GetParticleAge(particleIdx);

            var valueSource = new ParticleValueSource(emitter, particleIdx, particleAge);

            var x = state.GetState(ParticleStateField.PSF_X, particleIdx);
            var y = state.GetState(ParticleStateField.PSF_Y, particleIdx);
            var z = state.GetState(ParticleStateField.PSF_Z, particleIdx);

            var velX = state.GetState(ParticleStateField.PSF_VEL_X, particleIdx);
            var velY = state.GetState(ParticleStateField.PSF_VEL_Y, particleIdx);
            var velZ = state.GetState(ParticleStateField.PSF_VEL_Z, particleIdx);

            // Calculate new position of particle based on velocity
            x += timeToSimulateSecs * velX;
            y += timeToSimulateSecs * velY;
            z += timeToSimulateSecs * velZ;

            // Apply acceleration to velocity (retroactively to position as well)
            float value;
            if (valueSource.GetValue(PartSysParamId.part_accel_X, out value))
            {
                x    += accelIntegrationFactor * value;
                velX += timeToSimulateSecs * value;
            }

            if (valueSource.GetValue(PartSysParamId.part_accel_Y, out value))
            {
                y    += accelIntegrationFactor * value;
                velY += timeToSimulateSecs * value;
            }

            if (valueSource.GetValue(PartSysParamId.part_accel_Z, out value))
            {
                z    += accelIntegrationFactor * value;
                velZ += timeToSimulateSecs * value;
            }

            /*
             *  Apply Velocity Var
             */
            if (spec.GetParticleVelocityCoordSys() == PartSysCoordSys.Polar)
            {
                if (spec.GetParticlePosCoordSys() != PartSysCoordSys.Polar)
                {
                    // Velocity is polar, positions are not . convert velocity
                    var azimuth = emitter.GetParamValue(PartSysParamId.part_velVariation_X, particleIdx,
                                                        particleAge);
                    var inclination = emitter.GetParamValue(PartSysParamId.part_velVariation_Y, particleIdx,
                                                            particleAge);
                    var radius = emitter.GetParamValue(PartSysParamId.part_velVariation_Z, particleIdx,
                                                       particleAge);

                    var cartesianVel = SphericalDegToCartesian(azimuth, inclination, radius);
                    x += cartesianVel.X * timeToSimulateSecs;
                    y += cartesianVel.Y * timeToSimulateSecs;
                    z += cartesianVel.Z * timeToSimulateSecs;
                }
                else
                {
                    // Modify the spherical coordinates of the particle directly
                    if (valueSource.GetValue(PartSysParamId.part_velVariation_X, out value))
                    {
                        ref var azimuth = ref state.GetStatePtr(ParticleStateField.PSF_POS_AZIMUTH, particleIdx);
                        azimuth += value * timeToSimulateSecs;
                    }

                    if (valueSource.GetValue(PartSysParamId.part_velVariation_Y, out value))
                    {
                        ref var inclination =
                            ref state.GetStatePtr(ParticleStateField.PSF_POS_INCLINATION, particleIdx);
                        inclination += value * timeToSimulateSecs;
                    }

                    if (valueSource.GetValue(PartSysParamId.part_velVariation_Z, out value))
                    {
                        ref var radius = ref state.GetStatePtr(ParticleStateField.PSF_POS_RADIUS, particleIdx);
                        radius += value * timeToSimulateSecs;
                    }
                }