// // ParticleSystemModule.cpp // libcocos2d Mac // // Created by 徐俊杰 on 2020/4/24. // #include "rparticle/Modules/ParticleSystemModule.h" #include "rparticle/Serialize/TransferFunctions/SerializeTransfer.h" #include "base/CCDirector.h" #include "rparticle/Utilities/Transform.h" #include "renderer/CCTexture2D.h" #define zero ZERO #define one ONE #define SetIdentity setIdentity NS_RRP_BEGIN RRP_PARTICLEQUAD_VERTEX_INFO RRP_PARTICLEQUAD_VERTEX_INFO::Create(cocos2d::Texture2D *texture, const cocos2d::Rect& pointRect, bool isRotaed, const cocos2d::Vec2& offset, const cocos2d::Vec2& originalSize) { // convert to Tex coords RRP_PARTICLEQUAD_VERTEX_INFO _vertexInfo; const auto& rect = pointRect; GLfloat wide = (GLfloat) pointRect.size.width; GLfloat high = (GLfloat) pointRect.size.height; float rw = rect.size.width; float rh = rect.size.height; if (isRotaed) std::swap(rw, rh); if (texture) { wide = (GLfloat)texture->getPixelsWide(); high = (GLfloat)texture->getPixelsHigh(); } #if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL GLfloat left = (rect.origin.x*2+1) / (wide*2); GLfloat bottom = (rect.origin.y*2+1) / (high*2); GLfloat right = left + (rw*2-2) / (wide*2); GLfloat top = bottom + (rh*2-2) / (high*2); #else GLfloat left = rect.origin.x / wide; GLfloat bottom = rect.origin.y / high; GLfloat right = left + rw / wide; GLfloat top = bottom + rh / high; #endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL // Important. Texture in cocos2d are inverted, so the Y component should be inverted std::swap(top, bottom); // CCASSERT(_texNumber < 100, "纹理数量超过上限"); // if (isRotaed) { _vertexInfo.bl.u = left; _vertexInfo.bl.v = top; _vertexInfo.br.u = left; _vertexInfo.br.v = bottom; _vertexInfo.tl.u = right; _vertexInfo.tl.v = top; _vertexInfo.tr.u = right; _vertexInfo.tr.v = bottom; } else { _vertexInfo.bl.u = left; _vertexInfo.bl.v = bottom; _vertexInfo.br.u = right; _vertexInfo.br.v = bottom; _vertexInfo.tl.u = left; _vertexInfo.tl.v = top; _vertexInfo.tr.u = right; _vertexInfo.tr.v = top; } // if (!offset.isZero()){ // // CCLOG(""); // } float originalSizeX_2 = 2 / originalSize.x; // 宽的一半的倒数 float originalSizeY_2 = 2 / originalSize.y; float x1 = (pointRect.size.width * 0.5 - offset.x) * originalSizeX_2; float x2 = (pointRect.size.width * 0.5 + offset.x) * originalSizeX_2; float aspectRatio = originalSize.y / originalSize.x; float y1 = (pointRect.size.height * 0.5 - offset.y) * originalSizeY_2 * aspectRatio; float y2 = (pointRect.size.height * 0.5 + offset.y) * originalSizeY_2 * aspectRatio; _vertexInfo.centerPercentage.set(x1, x2, y1, y2); // auto halfScale = Vec2(pointRect.size.width / originalSize.x, pointRect.size.height / originalSize.y) * 0.5f; // auto offsetScale = Vec2(offset.x / originalSize.x, offset.y / originalSize.y); // // _vertexInfo.border.set(halfScale.x - offsetScale.x, halfScale.x + offsetScale.x, halfScale.y - offsetScale.y, halfScale.y + offsetScale.y); return _vertexInfo; } ParticleSystemReadOnlyState::ParticleSystemReadOnlyState() : lengthInSec (5.0f) , startDelay (0.0f) , speed (1.0f) , randomSeed (0) , looping (true) , prewarm (false) , scalingMode(0) , playOnAwake (true) , useLocalSpace (true) { } void ParticleSystemReadOnlyState::CheckConsistency() { lengthInSec = std::max(lengthInSec, 0.1f); lengthInSec = std::min(lengthInSec, 100000.0f); // Very large values can lead to editor locking up due to numerical instability. startDelay = std::max(startDelay, 0.0f); speed = std::max(speed, 0.0f); } float ParticleSystemReadOnlyState::GetRenderScale() const { return scale * CC_CONTENT_SCALE_FACTOR(); } template void ParticleSystemReadOnlyState::Transfer (TransferFunction& transfer) { TRANSFER (lengthInSec); TRANSFER (startDelay); TRANSFER (speed); TRANSFER (randomSeed); TRANSFER (looping); TRANSFER (prewarm); TRANSFER (playOnAwake); transfer.Transfer (useLocalSpace, "moveWithTransform"); } INSTANTIATE_TEMPLATE_TRANSFER(ParticleSystemReadOnlyState) ParticleSystemState::ParticleSystemState (RParticleSystem* system_) : system(system_) , playing (false) , needRestart (true) , stopEmitting (false) , accumulatedDt (0.0f) , delayT (0.0f) , t (0.0f) , maxSize (0.0f) , isSubEmitter (false) , recordSubEmits(false) , cullTime(0.0) , culled(false) , numLoops(0) , invalidateProcedural(false) , supportsProcedural(true) , cachedForces(0) , numCachedForces(0) , cachedSubDataBirth(0) , numCachedSubDataBirth(0) , cachedSubDataCollision(0) , numCachedSubDataCollision(0) , cachedSubDataDeath(0) , numCachedSubDataDeath(0) , cachedCollisionPlanes(0) , numCachedCollisionPlanes(0) , rayBudget(0) , nextParticleToTrace(0) { ClearSubEmitterCommandBuffer(); localToWorld.SetIdentity (); emitterVelocity = Vector3f::zero; emitterScale = Vector3f::one; minMaxAABB = MinMaxAABB (Vector3f::zero, Vector3f::zero); } void ParticleSystemState::Tick (const ParticleSystemReadOnlyState& constState, float dt) { t += dt; for(int i = 0; i < subEmitterCommandBuffer.commandCount; i++) subEmitterCommandBuffer.commands[i].timeAlive += dt; if (!constState.looping) t = std::min (t, constState.lengthInSec); else if(t > constState.lengthInSec) { t -= constState.lengthInSec; numLoops++; } } void ParticleSystemState::ClearSubEmitterCommandBuffer() { if(cachedSubDataBirth) { for (int i = 0; i < numCachedSubDataBirth; ++i) { (cachedSubDataBirth+i)->~ParticleSystemSubEmitterData(); } FREE_TEMP_MANUAL(cachedSubDataBirth); } if(cachedSubDataCollision) { for (int i = 0; i < numCachedSubDataCollision; ++i) { (cachedSubDataCollision+i)->~ParticleSystemSubEmitterData(); } FREE_TEMP_MANUAL(cachedSubDataCollision); } if(cachedSubDataDeath) { for (int i = 0; i < numCachedSubDataDeath; ++i) { (cachedSubDataDeath+i)->~ParticleSystemSubEmitterData(); } FREE_TEMP_MANUAL(cachedSubDataDeath); } if(subEmitterCommandBuffer.commands) FREE_TEMP_MANUAL(subEmitterCommandBuffer.commands); cachedSubDataBirth = cachedSubDataCollision = cachedSubDataDeath = 0; numCachedSubDataBirth = numCachedSubDataCollision = numCachedSubDataDeath = 0; subEmitterCommandBuffer.commands = 0; subEmitterCommandBuffer.commandCount = subEmitterCommandBuffer.maxCommandCount = 0; } template void ParticleSystemState::Transfer (TransferFunction& transfer) { // TRANSFER_DEBUG (t); } INSTANTIATE_TEMPLATE_TRANSFER(ParticleSystemState) template void ParticleSystemModule::Transfer (TransferFunction& transfer) { transfer.Transfer (m_Enabled, "enabled"); transfer.Align (); } INSTANTIATE_TEMPLATE_TRANSFER(ParticleSystemModule) NS_RRP_END