// // ParticleSystemUtils.cpp // cocos2d_libs // // Created by 徐俊杰 on 2020/4/24. // #include "rparticle/ParticleSystemUtils.h" #include "rparticle/Modules/ParticleSystemModule.h" #include "rparticle/ParticleSystemParticle.h" #include "rparticle/Modules/ColorModule.h" #include "rparticle/Modules/ColorByVelocityModule.h" #include "rparticle/Modules/SizeModule.h" #include "rparticle/Modules/SizeByVelocityModule.h" #include "rparticle/Modules/SubEmitterModule.h" NS_RRP_BEGIN UInt32 randomSeed = 0x1337; UInt32 GetGlobalRandomSeed () { return ++randomSeed; } void ResetGlobalRandomSeed () { randomSeed = 0x1337; } Vector2f CalculateInverseLerpOffsetScale (const Vector2f& range) { Assert (range.x < range.y); float scale = 1.0F / (range.y - range.x); return Vector2f (scale, -range.x * scale); } void CalculatePositionAndVelocity(Vector3f& initialPosition, Vector3f& initialVelocity, const ParticleSystemReadOnlyState& roState, const ParticleSystemState& state, const ParticleSystemParticles& ps, const size_t index) { initialPosition = ps.position[index]; initialVelocity = ps.velocity[index] + ps.animatedVelocity[index]; if(roState.useLocalSpace) { // If we are in local space, transform to world space to make independent of this emitters transform // initialPosition = state.localToWorld.MultiplyPoint3(initialPosition); // initialVelocity = state.localToWorld.MultiplyVector3(initialVelocity); state.localToWorld.transformPoint(&initialPosition); state.localToWorld.transformVector(&initialVelocity); } } static void CalculateInheritedProperties(const ParticleSystemReadOnlyState& roState, SubEmitterInheritValues& initialProperties, int properties, const ParticleSystemParticle& particle, RParticleSystem* srcSystem, float normalizedT) { if (properties & SubEmitterModule::kInheritColor) { initialProperties.color = particle.color; if (srcSystem->GetColorModule()->GetEnabled()) srcSystem->GetColorModule()->UpdateSingle(particle, initialProperties.color); if (srcSystem->GetColorBySpeedModule()->GetEnabled()) srcSystem->GetColorBySpeedModule()->UpdateSingle(roState, particle, initialProperties.color); } if (properties & SubEmitterModule::kInheritSize) { initialProperties.size = particle.size; if (srcSystem->GetSizeModule()->GetEnabled()) srcSystem->GetSizeModule()->UpdateSingle(particle, true, initialProperties.size); if (srcSystem->GetSizeBySpeedModule()->GetEnabled()) srcSystem->GetSizeBySpeedModule()->UpdateSingle(roState, particle, true, initialProperties.size); } if (properties & SubEmitterModule::kInheritRotation) { initialProperties.rotation = particle.rotation; initialProperties.axisOfRotation = particle.axisOfRotation; } if (properties & SubEmitterModule::kInheritLifetime) { initialProperties.lifetimeMultiplier = particle.lifetime; } if (properties & SubEmitterModule::kInheritDuration) { initialProperties.normalizedT = normalizedT; } } void KillParticle(const ParticleSystemReadOnlyState& roState, ParticleSystemState& state, ParticleSystemParticles& ps, size_t index, size_t& particleCount) { Assert(particleCount > 0); for(int i = 0; i < state.numCachedSubDataDeath; i++) { ParticleSystemEmissionState emissionState; RecordEmit(emissionState, state.cachedSubDataDeath[i], roState, state, ps, kParticleSystemSubTypeDeath, i, index, 0.0f, 0.0001f, 1.0f); } ps.element_assign (index, particleCount - 1); --particleCount; } void RecordEmit(ParticleSystemEmissionState& emissionState, const ParticleSystemSubEmitterData& subEmitterData, const ParticleSystemReadOnlyState& roState, ParticleSystemState& state, ParticleSystemParticles& ps, ParticleSystemSubType type, int subEmitterIndex, size_t particleIndex, float t, float dt, float length) { size_t numContinuous = 0; Vector3f initialPosition; Vector3f initialVelocity; CalculatePositionAndVelocity(initialPosition, initialVelocity, roState, state, ps, particleIndex); int amountOfParticlesToEmit = RParticleSystem::EmitFromData (roState, emissionState, numContinuous, subEmitterData.emissionData, initialVelocity, t, std::min(t + dt, length), dt, length); if(amountOfParticlesToEmit) { SubEmitterInheritValues inheritValues; auto subEmitterProperties = subEmitterData.properties; if (subEmitterProperties) { ParticleSystemParticle particle; //particle.position = ps.position[particleIndex]; //particle.velocity = ps.velocity[particleIndex]; //particle.animatedVelocity = ps.animatedVelocity[particleIndex]; particle.color = ps.color[particleIndex]; particle.size = ps.size[particleIndex] / roState.GetRenderScale(); particle.startLifetime = ps.startLifetime[particleIndex]; particle.lifetime = ps.lifetime[particleIndex]; particle.rotation = ps.rotation[particleIndex]; particle.axisOfRotation = ps.usesAxisOfRotation ? ps.axisOfRotation[particleIndex] : Vector3f::UNIT_Z; CalculateInheritedProperties(roState, inheritValues, subEmitterProperties, particle, state.system, t); } if(!state.recordSubEmits) RParticleSystem::Emit(*subEmitterData.emitter, SubEmitterEmitCommand(emissionState, initialPosition, initialVelocity, inheritValues, type, subEmitterIndex, amountOfParticlesToEmit, numContinuous, t, dt), kParticleSystemEMStaging); else if(!state.subEmitterCommandBuffer.IsFull()) state.subEmitterCommandBuffer.AddCommand(emissionState, initialPosition, initialVelocity, inheritValues, type, subEmitterIndex, amountOfParticlesToEmit, numContinuous, t, dt); } } bool GetTransformationMatrix(Matrix4x4f& output, const bool isSystemInWorld, const bool isCurveInWorld, const Matrix4x4f& localToWorld) { if(isCurveInWorld != isSystemInWorld) { if(isSystemInWorld) output = localToWorld; else // Matrix4x4f::Invert_General3D(localToWorld, output); output = localToWorld.getInversed(); return true; } else { // output = Matrix4x4f::identity; output.setIdentity(); return false; } } bool GetTransformationMatrices(Matrix4x4f& output, Matrix4x4f& outputInverse, const bool isSystemInWorld, const bool isCurveInWorld, const Matrix4x4f& localToWorld) { if(isCurveInWorld != isSystemInWorld) { if(isSystemInWorld) { output = localToWorld; // Matrix4x4f::Invert_General3D(localToWorld, outputInverse); outputInverse = localToWorld.getInversed(); } else { // Matrix4x4f::Invert_General3D(localToWorld, output); output = localToWorld.getInversed(); outputInverse = localToWorld; } return true; } else { // output = Matrix4x4f::identity; // outputInverse = Matrix4x4f::identity; output.setIdentity(); outputInverse.setIdentity(); return false; } } NS_RRP_END