From 4ce4072fef3c296dc2e7fcd18ae949c464c6a71e Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 14 Apr 2024 09:05:44 -0700 Subject: [PATCH] JPA work --- include/JSystem/JGeometry.h | 70 ++++++-------------------- include/JSystem/JParticle/JPAEmitter.h | 20 ++++++-- src/JSystem/JParticle/JPAEmitter.cpp | 61 ++++++++++++++++------ src/JSystem/JParticle/JPAField.cpp | 62 +++++++++++++++-------- 4 files changed, 116 insertions(+), 97 deletions(-) diff --git a/include/JSystem/JGeometry.h b/include/JSystem/JGeometry.h index 212334cda..56268aeaf 100644 --- a/include/JSystem/JGeometry.h +++ b/include/JSystem/JGeometry.h @@ -144,7 +144,7 @@ struct TVec3 : public Vec { return C_VECSquareMag((Vec*)&x); } - f32 normalize_broken() { + f32 normalize() { f32 sq = squared(); if (sq <= TUtil::epsilon()) { return 0.0f; @@ -154,52 +154,21 @@ struct TVec3 : public Vec { return norm; } - f32 normalize() { - f32 sq = squared(); - if (sq <= TUtil::epsilon()) { - return 0.0f; - } - f32 norm = TUtil::inv_sqrt(sq); - scale(1.0f / norm); - return norm; - } - - f32 normalize(const TVec3& other) { - f32 sq = other.squared(); - if (sq <= TUtil::epsilon()) { - zero(); - return 0.0f; - } - f32 norm = TUtil::inv_sqrt(sq); - scale(1.0f / norm, other); - return norm; - } - f32 length() const { f32 sqr = squared(); return TUtil::sqrt(sqr); } - void scale(register f32 sc) { + void scale(f32 sc) { x *= sc; y *= sc; z *= sc; } - void scale(register f32 sc, const TVec3& other) { - register const f32* src = &other.x; - register f32 z; - register f32 x_y; - register f32* dst = &x; - register f32 zres; - asm { - psq_l x_y, 0(src), 0, 0 - psq_l z, 8(src), 1, 0 - ps_muls0 x_y, x_y, sc - psq_st x_y, 0(dst), 0, 0 - ps_muls0 zres, z, sc - psq_st zres, 8(dst), 1, 0 - }; + void scale(f32 sc, const TVec3& b) { + x = b.x * sc; + y = b.y * sc; + z = b.z * sc; } void negate() { @@ -209,11 +178,15 @@ struct TVec3 : public Vec { } void sub(const TVec3& b) { - C_VECSubtract((Vec*)&x, (Vec*)&b.x, (Vec*)&x); + x -= b.x; + y -= b.y; + z -= b.z; } void sub(const TVec3& a, const TVec3& b) { - C_VECSubtract((Vec*)&a.x, (Vec*)&b.x, (Vec*)&x); + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; } bool isZero() const { @@ -233,23 +206,8 @@ struct TVec3 : public Vec { scale(norm * len); } - f32 dot(const TVec3& other) const { - register const f32* pThis = &x; - register const f32* pOther = &other.x; - register f32 otherReg; - register f32 thisyz; - register f32 res; - register f32 thisxy; - asm { - psq_l thisyz, 4(pThis), 0, 0 - psq_l otherReg, 4(pOther), 0, 0 - ps_mul thisyz, thisyz, otherReg - psq_l thisxy, 0(pThis), 0, 0 - psq_l otherReg, 0(pOther), 0, 0 - ps_madd res, thisxy, otherReg, thisyz - ps_sum0 res, res, thisyz, thisyz - }; - return res; + f32 dot(const TVec3& b) const { + return x*b.x + y*b.y * z*b.z; } template diff --git a/include/JSystem/JParticle/JPAEmitter.h b/include/JSystem/JParticle/JPAEmitter.h index ddf815f37..77b25b495 100644 --- a/include/JSystem/JParticle/JPAEmitter.h +++ b/include/JSystem/JParticle/JPAEmitter.h @@ -168,6 +168,8 @@ public: bool checkStatus(u32 status) { return mFlags & status; } void initStatus(u32 status) { mFlags = status; } + bool checkEmDataFlag(u32 mask) { return mDataFlag & mask; } + int getParticleNumber() { return mActiveParticles.getNumLinks() + mChildParticles.getNumLinks(); } @@ -226,6 +228,7 @@ public: void setVolumeSweep(f32 i_volSweep) { mVolumeSweep = i_volSweep; } void setVolumeSize(u16 size) { mVolumeSize = size; } void setLifeTime(s16 i_lifeTime) { mLifeTime = i_lifeTime; } + f32 getRate() const { return mRate; } void setRate(f32 i_rate) { mRate = i_rate; } void setRandomDirectionSpeed(f32 i_speed) { mInitialVelRndm = i_speed; } void setDirectionalSpeed(f32 i_speed) { mInitialVelDir = i_speed; } @@ -241,6 +244,7 @@ public: void becomeImmortalEmitter() { setStatus(JPAEmtrStts_Immortal); } void quitImmortalEmitter() { clearStatus(JPAEmtrStts_Immortal); } + void becomeContinuousParticle() { mMaxFrame = 0; } void becomeInvalidEmitter() { mMaxFrame = -1; stopCreateParticle(); @@ -267,11 +271,7 @@ public: void setUserWork(u32 work) { mUserData = work; } // TODO - void becomeContinuousParticle() {} - void calcAfterCB() {} - void calcBeforeCB() {} void calcEmitterGlobalTranslation(JGeometry::TVec3&) {} - void checkEmDataFlag(u32) {} void drawCB() {} void drawEmitterCallBack() {} void getAxisYVec(JGeometry::TVec3&) const {} @@ -283,7 +283,6 @@ public: void getFrame() {} void getGlobalParticleScale(JGeometry::TVec3&) const {} void getParticleList() {} - void getRate() const {} void getgReRDirection(JGeometry::TVec3&) {} void isChildDraw() {} void isContinuousParticle() {} @@ -308,6 +307,17 @@ public: static f32 getAspect() { return emtrInfo.mAspect; } static f32 getFovy() { return emtrInfo.mFovy; } +private: + void calcAfterCB() { + if (mpEmitterCallBack != NULL) + mpEmitterCallBack->executeAfter(this); + } + void calcBeforeCB() { + if (mpEmitterCallBack != NULL) + mpEmitterCallBack->execute(this); + } + +public: /* 0x000 */ VolumeFunc mVolumeFunc; /* 0x00C */ JGeometry::TVec3 mEmitterScale; /* 0x018 */ JGeometry::TVec3 mEmitterTranslation; diff --git a/src/JSystem/JParticle/JPAEmitter.cpp b/src/JSystem/JParticle/JPAEmitter.cpp index a74b6139e..a52934a54 100644 --- a/src/JSystem/JParticle/JPAEmitter.cpp +++ b/src/JSystem/JParticle/JPAEmitter.cpp @@ -23,7 +23,7 @@ void JPABaseEmitter::calcVolumePoint() { /* 8025C254-8025C394 .text calcVolumeLine__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeLine() { - if (mDataFlag & 2) { + if (checkEmDataFlag(0x02)) { emtrInfo.mVolumePos.set(0.0f, 0.0f, emtrInfo.mVolumeSize * ((f32)emtrInfo.mVolumeEmitIdx / ((f32)emtrInfo.mVolumeEmitCount - 1.0f) - 0.5f)); emtrInfo.mVolumeEmitIdx++; } else { @@ -37,7 +37,7 @@ void JPABaseEmitter::calcVolumeLine() { /* 8025C394-8025C538 .text calcVolumeCircle__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeCircle() { s16 angle; - if (mDataFlag & 0x02) { + if (checkEmDataFlag(0x02)) { s16 idx = (0x10000 * emtrInfo.mVolumeEmitIdx / emtrInfo.mVolumeEmitCount); angle = idx * mVolumeSweep; emtrInfo.mVolumeEmitIdx++; @@ -46,7 +46,7 @@ void JPABaseEmitter::calcVolumeCircle() { } f32 rad = getRandomF(); - if (mDataFlag & 0x01) + if (checkEmDataFlag(0x01)) rad = 1.0f - rad * rad; rad = emtrInfo.mVolumeSize * (mVolumeMinRad + rad * (1.0f - mVolumeMinRad)); @@ -73,7 +73,7 @@ void JPABaseEmitter::calcVolumeCylinder() { s16 angle = mVolumeSweep * getRandomSS(); f32 rad = getRandomF(); - if (mDataFlag & 0x01) + if (checkEmDataFlag(0x01)) rad = 1.0f - rad * rad; rad = emtrInfo.mVolumeSize * (mVolumeMinRad + rad * (1.0f - mVolumeMinRad)); @@ -125,8 +125,7 @@ void JPABaseEmitter::create(JPADataBlockLinkInfo* info) { mInitialVelDir = dyn->getInitVelDir(); mAccel = dyn->getAccel(); dyn->getEmitterDir(mEmitterDir); - // This appears to be an attempt at a normalize, but it scales by the length instead (???) - mEmitterDir.normalize_broken(); + mEmitterDir.normalize(); mSpread = dyn->getSpread(); mDataFlag = dyn->getDataFlag(); mUseKeyFlag = dyn->getUseKeyFlag(); @@ -197,31 +196,65 @@ void JPABaseEmitter::calc() { emtrInfo.mVolumeEmitCount = 0; if (!checkStatus(JPAEmtrStts_StopCalc)) { calcKey(); - if (mpEmitterCallBack != NULL) - mpEmitterCallBack->execute(this); + calcBeforeCB(); calcEmitterInfo(); mDraw.calc(); mFieldManager.preCalc(); if (!checkStatus(JPAEmtrStts_EnableDeleteEmitter)) calcCreatePtcls(); - if (mpEmitterCallBack != NULL) - mpEmitterCallBack->executeAfter(this); + calcAfterCB(); calcParticle(); calcChild(); mTick += 1.0f; if (mTick < 0.0f) mTick = 0.0f; } else { - if (mpEmitterCallBack != NULL) - mpEmitterCallBack->execute(this); - if (mpEmitterCallBack != NULL) - mpEmitterCallBack->executeAfter(this); + calcBeforeCB(); + calcAfterCB(); } } /* 8025D3C0-8025D5D4 .text calcCreatePtcls__14JPABaseEmitterFv */ void JPABaseEmitter::calcCreatePtcls() { /* Nonmatching */ + if (checkStatus(JPAEmtrStts_RateStepEmit)) { + s32 emitCount = 0; + if (checkEmDataFlag(0x02)) { // Fixed interval + emitCount = (mVolumeType == 1) ? + (mDivNumber + 1) * (mDivNumber - 1) * 4 + 6 : // Sphere + mDivNumber; + emtrInfo.mVolumeEmitIdx = 0; + } else { + f32 incr = mRate * (1.0f + mRateRndm * getRandomRF()); + mEmitCount += incr; + + if (mEmitCount >= 1) { + emitCount = mEmitCount; + mEmitCount -= emitCount; + } else if (mEmitCount > 0 && checkStatus(JPAEmtrStts_FirstEmit)) { + emitCount = 1; + } + } + + emtrInfo.mVolumeEmitCount = emitCount; + + if (checkStatus(JPAEmtrStts_StopEmit)) + emitCount = 0; + + for (s32 i = 0; i < emitCount; i++) { + JPABaseParticle* ptcl = createParticle(); + if (ptcl == NULL) + break; + } + } + + if (mRateStepTimer++ >= mRateStep + 1) { + mRateStepTimer -= mRateStep + 1; + setStatus(JPAEmtrStts_RateStepEmit); + } else { + clearStatus(JPAEmtrStts_RateStepEmit); + } + clearStatus(JPAEmtrStts_FirstEmit); } /* 8025D5D4-8025D670 .text createChildren__14JPABaseEmitterFP15JPABaseParticle */ diff --git a/src/JSystem/JParticle/JPAField.cpp b/src/JSystem/JParticle/JPAField.cpp index eb08d747e..fa3b5a601 100644 --- a/src/JSystem/JParticle/JPAField.cpp +++ b/src/JSystem/JParticle/JPAField.cpp @@ -40,7 +40,6 @@ void JPABaseField::loadFieldData(JPAFieldData* data, JPAFieldBlock* block) { /* 8025A0D8-8025A21C .text calcVel__12JPABaseFieldFP12JPAFieldDataP15JPABaseParticle */ void JPABaseField::calcVel(JPAFieldData* data, JPABaseParticle* ptcl) { - /* Nonmatching - copy of vel shouldn't be using PS */ JGeometry::TVec3 vel = data->mVel; if (!(ptcl->mStatus & 0x04)) { @@ -56,8 +55,17 @@ void JPABaseField::calcVel(JPAFieldData* data, JPABaseParticle* ptcl) { } /* 8025A21C-8025A2B0 .text calcFadeAffect__12JPABaseFieldFP12JPAFieldDataf */ -f32 JPABaseField::calcFadeAffect(JPAFieldData* data, f32 t) { - /* Nonmatching */ +f32 JPABaseField::calcFadeAffect(JPAFieldData* data, f32 time) { + f32 affect = 1.0f; + if (((data->mSttFlag & 0x08) && time < data->mEnTime) || ((data->mSttFlag & 0x10) && time >= data->mDisTime)) { + affect = 0.0f; + } else { + if ((data->mSttFlag & 0x40) && time >= data->mFadeOut) + affect = data->mFadeOutRate * (data->mDisTime - time); + else if ((data->mSttFlag & 0x20) && time < data->mFadeIn) + affect = data->mFadeInRate * (time - data->mEnTime); + } + return affect; } /* 8025A2B0-8025A330 .text preCalc__12JPABaseFieldFP12JPAFieldData */ @@ -87,17 +95,11 @@ bool JPABaseField::isItinRange(JPAFieldData* data, f32 v) { void JPAGravityField::preCalc(JPAFieldData* data) { JPABaseField::preCalc(data); if (data->mSttFlag & 0x02) { - f32 mag = data->mMag; - data->mVel.x = data->mDir.x * mag; - data->mVel.y = data->mDir.y * mag; - data->mVel.z = data->mDir.z * mag; + data->mVel.scale(data->mMag, data->mDir); } else { JGeometry::TVec3 rotDir; MTXMultVec(JPAFieldData::pEmtrInfo->mGlobalRot, data->mDir, rotDir); - f32 mag = data->mMag; - data->mVel.x = rotDir.x * mag; - data->mVel.y = rotDir.y * mag; - data->mVel.z = rotDir.z * mag; + data->mVel.scale(data->mMag, rotDir); } } @@ -115,10 +117,7 @@ void JPAAirField::preCalc(JPAFieldData* data) { MTXMultVec(JPAFieldData::pEmtrInfo->mGlobalRot, data->mDir, data->mLocalDir); } - f32 mag = data->mMag; - data->mVel.x = data->mLocalDir.x * mag; - data->mVel.y = data->mLocalDir.y * mag; - data->mVel.z = data->mLocalDir.z * mag; + data->mVel.scale(data->mMag, data->mLocalDir); if (data->mSttFlag & 0x01) { data->mAirMinDist = JMASCos(data->mVal1 * 0xFFFF); if (data->mSttFlag & 0x02) { @@ -132,6 +131,29 @@ void JPAAirField::preCalc(JPAFieldData* data) { /* 8025A510-8025A6EC .text calc__11JPAAirFieldFP12JPAFieldDataP15JPABaseParticle */ void JPAAirField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ + if (data->mSttFlag & 0x01) { + JGeometry::TVec3 vel; + if (data->mSttFlag & 0x02) { + vel.sub(ptcl->mPosition, data->mLocalPos); + } else { + vel.sub(ptcl->mLocalPosition, data->mLocalPos); + } + + vel.normalize(); + + if (data->mAirMinDist <= data->mLocalDir.dot(vel)) { + JPABaseField::calcVel(data, ptcl); + } + } else { + JPABaseField::calcVel(data, ptcl); + } + + if (data->mSttFlag & 0x04) { + f32 len = ptcl->mBaseVel.length(); + if (len > data->mMagRndm) { + ptcl->mBaseVel.scale(data->mMagRndm / len); + } + } } /* 8025A6EC-8025A788 .text preCalc__14JPAMagnetFieldFP12JPAFieldData */ @@ -152,15 +174,11 @@ void JPAMagnetField::preCalc(JPAFieldData* data) { void JPAMagnetField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ if (data->mSttFlag & 0x02) { - data->mVel.x = data->mLocalPos.x - ptcl->mPosition.x; - data->mVel.y = data->mLocalPos.y - ptcl->mPosition.y; - data->mVel.z = data->mLocalPos.z - ptcl->mPosition.z; + data->mVel.sub(data->mLocalPos, ptcl->mPosition); } else { - data->mVel.x = data->mLocalPos.x - ptcl->mLocalPosition.x; - data->mVel.y = data->mLocalPos.y - ptcl->mLocalPosition.y; - data->mVel.z = data->mLocalPos.z - ptcl->mLocalPosition.z; + data->mVel.sub(data->mLocalPos, ptcl->mLocalPosition); } - data->mVel.normalize(); + data->mVel.setLength(data->mMag); calcVel(data, ptcl); }