From a9c6b0fca242830a45892785cc202a32c4df5a75 Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sat, 18 Nov 2023 16:44:42 -0800 Subject: [PATCH] JPAEmitter work --- include/JSystem/JGeometry.h | 22 +---- include/JSystem/JMath/random.h | 1 + include/JSystem/JParticle/JPAEmitter.h | 9 +- include/JSystem/JParticle/JPAField.h | 4 +- src/JSystem/JParticle/JPAEmitter.cpp | 68 ++++++++++---- src/JSystem/JParticle/JPAField.cpp | 118 ++++++++++++++++++++----- 6 files changed, 158 insertions(+), 64 deletions(-) diff --git a/include/JSystem/JGeometry.h b/include/JSystem/JGeometry.h index c17cb3ff4..945b4d6c5 100644 --- a/include/JSystem/JGeometry.h +++ b/include/JSystem/JGeometry.h @@ -107,25 +107,9 @@ struct TVec3 { void zero() { x = y = z = 0.0f; } void mul(const TVec3& a, const TVec3& b) { - register f32* dst = &x; - const register f32* srca = &a.x; - const register f32* srcb = &b.x; - register f32 a_x_y; - register f32 b_x_y; - register f32 x_y; - register f32 za; - register f32 zb; - register f32 z; - asm { - psq_l a_x_y, 0(srca), 0, 0 - psq_l b_x_y, 0(srcb), 0, 0 - ps_mul x_y, a_x_y, b_x_y - psq_st x_y, 0(dst), 0, 0 - lfs za, 8(srca) - lfs zb, 8(srcb) - fmuls z, za, zb - stfs z, 8(dst) - }; + x = a.x * b.x; + y = a.y * b.y; + z = a.z * b.z; } inline TVec3& operator+=(const TVec3& b) { diff --git a/include/JSystem/JMath/random.h b/include/JSystem/JMath/random.h index 3c24e7caf..ccae23a0f 100644 --- a/include/JSystem/JMath/random.h +++ b/include/JSystem/JMath/random.h @@ -14,6 +14,7 @@ struct TRandom_fast_ { } u32 get_bit32(void) { return this->get(); } + u16 get_bit16(void) { return this->get() >> 16; } // due to the float constant, having this function inlined adds that float to data, // making it not match diff --git a/include/JSystem/JParticle/JPAEmitter.h b/include/JSystem/JParticle/JPAEmitter.h index 2dddd5c34..ecb5dbf97 100644 --- a/include/JSystem/JParticle/JPAEmitter.h +++ b/include/JSystem/JParticle/JPAEmitter.h @@ -121,8 +121,8 @@ public: /* 0x118 */ JGeometry::TVec3 mVelOmni; /* 0x124 */ JGeometry::TVec3 mVelAxis; /* 0x130 */ f32 mVolumeSize; - /* 0x134 */ u32 mVolumeEmitCount; - /* 0x138 */ u32 mVolumeEmitIdx; + /* 0x134 */ s32 mVolumeEmitCount; + /* 0x138 */ s32 mVolumeEmitIdx; /* 0x13C */ u32 mVolumeEmitAngleCount; /* 0x140 */ u32 mVolumeEmitXCount; /* 0x144 */ u32 mVolumeEmitAngleMax; @@ -240,6 +240,11 @@ public: void initDrawMgr(JPATextureResource* texRes) { mDraw.initialize(this, texRes); } void draw(MtxP cameraMtxP) { mDraw.draw(cameraMtxP); } + f32 getRandomF() { return mRandomSeed.get_ufloat_1(); } + f32 getRandomRF() { f32 x = mRandomSeed.get_ufloat_1(); return x + x - 1.0f; } + f32 getRandomSF() { return mRandomSeed.get_ufloat_1() - 0.5f; } + s16 getRandomSS() { return mRandomSeed.get_bit16(); } + static JPAEmitterInfo emtrInfo; /* 0x000 */ VolumeFunc mVolumeFunc; diff --git a/include/JSystem/JParticle/JPAField.h b/include/JSystem/JParticle/JPAField.h index a3ea0faba..1731f9b5a 100644 --- a/include/JSystem/JParticle/JPAField.h +++ b/include/JSystem/JParticle/JPAField.h @@ -37,11 +37,11 @@ public: /* 0x04 */ JPABaseField * mpBaseField; /* 0x08 */ JSULink mLink; /* 0x18 */ JGeometry::TVec3 mVel; - /* 0x24 */ JGeometry::TVec3 mAirPos; + /* 0x24 */ JGeometry::TVec3 mLocalPos; /* 0x30 */ f32 mAirMinDist; /* 0x34 */ u32 field_0x34; /* 0x38 */ u32 field_0x38; - /* 0x3C */ JGeometry::TVec3 mAirDir; + /* 0x3C */ JGeometry::TVec3 mLocalDir; /* 0x48 */ f32 mMaxDistSq; /* 0x4C */ f32 mFadeOutRate; /* 0x50 */ f32 mFadeInRate; diff --git a/src/JSystem/JParticle/JPAEmitter.cpp b/src/JSystem/JParticle/JPAEmitter.cpp index 73c18ebb4..0718ca578 100644 --- a/src/JSystem/JParticle/JPAEmitter.cpp +++ b/src/JSystem/JParticle/JPAEmitter.cpp @@ -8,6 +8,7 @@ #include "JSystem/JParticle/JPAExtraShape.h" #include "JSystem/JParticle/JPASweepShape.h" #include "JSystem/JParticle/JPAKeyBlock.h" +#include "JSystem/JMath/JMATrigonometric.h" #include "dolphin/mtx/mtx.h" #include "dolphin/mtx/mtxvec.h" @@ -15,33 +16,50 @@ JPAEmitterInfo JPABaseEmitter::emtrInfo; /* 8025C128-8025C254 .text calcVolumePoint__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumePoint() { - /* Nonmatching */ - emtrInfo.mVolumePos.z = 0.0f; - emtrInfo.mVolumePos.y = 0.0f; - emtrInfo.mVolumePos.x = 0.0f; - - emtrInfo.mVelOmni.z = mRandomSeed.get_ufloat_1() - 0.5f; - emtrInfo.mVelOmni.y = mRandomSeed.get_ufloat_1() - 0.5f; - emtrInfo.mVelOmni.x = mRandomSeed.get_ufloat_1() - 0.5f; - - emtrInfo.mVelAxis.x = mRandomSeed.get_ufloat_1() - 0.5f; - emtrInfo.mVelAxis.y = 0.0f; - emtrInfo.mVelAxis.z = mRandomSeed.get_ufloat_1() - 0.5f; + emtrInfo.mVolumePos.zero(); + emtrInfo.mVelOmni.set(getRandomSF(), getRandomSF(), getRandomSF()); + emtrInfo.mVelAxis.set(getRandomSF(), 0.0f, getRandomSF()); } /* 8025C254-8025C394 .text calcVolumeLine__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeLine() { - /* Nonmatching */ + if (mDataFlag & 2) { + emtrInfo.mVolumePos.set(0.0f, 0.0f, emtrInfo.mVolumeSize * ((f32)emtrInfo.mVolumeEmitIdx / ((f32)emtrInfo.mVolumeEmitCount - 1.0f) - 0.5f)); + emtrInfo.mVolumeEmitIdx++; + } else { + emtrInfo.mVolumePos.set(0.0f, 0.0f, emtrInfo.mVolumeSize * getRandomSF()); + } + + emtrInfo.mVelOmni.mul(emtrInfo.mVolumePos, emtrInfo.mEmitterGlobalScale); + emtrInfo.mVelAxis.set(emtrInfo.mVolumePos.x, 0.0f, emtrInfo.mVolumePos.z); } /* 8025C394-8025C538 .text calcVolumeCircle__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeCircle() { - /* Nonmatching */ + s16 angle; + if (mDataFlag & 0x02) { + s16 idx = (0x10000 * emtrInfo.mVolumeEmitIdx / emtrInfo.mVolumeEmitCount); + angle = idx * mVolumeSweep; + emtrInfo.mVolumeEmitIdx++; + } else { + angle = mVolumeSweep * getRandomSS(); + } + + f32 rad = getRandomF(); + if (mDataFlag & 0x01) + rad = 1.0f - rad * rad; + rad = emtrInfo.mVolumeSize * (mVolumeMinRad + rad * (1.0f - mVolumeMinRad)); + + emtrInfo.mVolumePos.set(rad * JMASSin(angle), 0.0f, rad * JMASCos(angle)); + emtrInfo.mVelOmni.mul(emtrInfo.mVolumePos, emtrInfo.mEmitterGlobalScale); + emtrInfo.mVelAxis.set(emtrInfo.mVolumePos.x, 0.0f, emtrInfo.mVolumePos.z); } /* 8025C538-8025C63C .text calcVolumeCube__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeCube() { - /* Nonmatching */ + emtrInfo.mVolumePos.set(emtrInfo.mVolumeSize * getRandomSF(), emtrInfo.mVolumeSize * getRandomSF(), emtrInfo.mVolumeSize * getRandomSF()); + emtrInfo.mVelOmni.mul(emtrInfo.mVolumePos, emtrInfo.mEmitterGlobalScale); + emtrInfo.mVelAxis.set(emtrInfo.mVolumePos.x, 0.0f, emtrInfo.mVolumePos.z); } /* 8025C63C-8025C8A4 .text calcVolumeSphere__14JPABaseEmitterFv */ @@ -52,11 +70,27 @@ void JPABaseEmitter::calcVolumeSphere() { /* 8025C8A4-8025CA28 .text calcVolumeCylinder__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeCylinder() { /* Nonmatching */ + s16 angle = mVolumeSweep * getRandomSS(); + + f32 rad = getRandomF(); + if (mDataFlag & 0x01) + rad = 1.0f - rad * rad; + rad = emtrInfo.mVolumeSize * (mVolumeMinRad + rad * (1.0f - mVolumeMinRad)); + + emtrInfo.mVolumePos.set(rad * JMASSin(angle), emtrInfo.mVolumeSize * getRandomRF(), rad * JMASCos(angle)); + emtrInfo.mVelOmni.mul(emtrInfo.mVolumePos, emtrInfo.mEmitterGlobalScale); + emtrInfo.mVelAxis.set(emtrInfo.mVolumePos.x, 0.0f, emtrInfo.mVolumePos.z); } /* 8025CA28-8025CB54 .text calcVolumeTorus__14JPABaseEmitterFv */ void JPABaseEmitter::calcVolumeTorus() { - /* Nonmatching */ + s16 angle1 = mVolumeSweep * getRandomSS(); + s16 angle2 = getRandomSS(); + f32 rad = mVolumeMinRad * emtrInfo.mVolumeSize; + + emtrInfo.mVelAxis.set(rad * JMASSin(angle1) * JMASCos(angle2), rad * JMASSin(angle2), rad * JMASCos(angle1) * JMASCos(angle2)); + emtrInfo.mVolumePos.set(emtrInfo.mVelAxis.x + emtrInfo.mVolumeSize * JMASSin(angle1), emtrInfo.mVelAxis.y, emtrInfo.mVelAxis.z + emtrInfo.mVolumeSize * JMASCos(angle1)); + emtrInfo.mVelOmni.mul(emtrInfo.mVolumePos, emtrInfo.mEmitterGlobalScale); } /* 8025CB54-8025D0B0 .text create__14JPABaseEmitterFP20JPADataBlockLinkInfo */ @@ -275,7 +309,7 @@ void JPABaseEmitter::calcChild() { /* 8025D8CC-8025DA90 .text calcKey__14JPABaseEmitterFv */ void JPABaseEmitter::calcKey() { /* Nonmatching */ - for (u32 i = 0; i < getEmitterDataBlockInfoPtr()->getKeyNum(); i++) { + for (s32 i = 0; i < getEmitterDataBlockInfoPtr()->getKeyNum(); i++) { JPAKeyBlock* key = getEmitterDataBlockInfoPtr()->getKey()[i]; f32 tick = mTick; const f32* dataPtr = key->getKeyDataPtr(); diff --git a/src/JSystem/JParticle/JPAField.cpp b/src/JSystem/JParticle/JPAField.cpp index 47fb46230..d99efe391 100644 --- a/src/JSystem/JParticle/JPAField.cpp +++ b/src/JSystem/JParticle/JPAField.cpp @@ -8,6 +8,8 @@ #include "JSystem/JParticle/JPAParticle.h" #include "JSystem/JParticle/JPAFieldBlock.h" #include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JMath/JMATrigonometric.h" +#include "dolphin/mtx/mtxvec.h" JPAFieldContainer fc; JPAEmitterInfo * JPAFieldData::pEmtrInfo; @@ -82,93 +84,153 @@ bool JPABaseField::isItinRange(JPAFieldData* data, f32 v) { } /* 8025A344-8025A3E4 .text preCalc__15JPAGravityFieldFP12JPAFieldData */ -void JPAGravityField::preCalc(JPAFieldData*) { - /* Nonmatching */ +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; + } 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; + } } /* 8025A3E4-8025A404 .text calc__15JPAGravityFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPAGravityField::calc(JPAFieldData*, JPABaseParticle*) { - /* Nonmatching */ +void JPAGravityField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { + calcVel(data, ptcl); } /* 8025A404-8025A510 .text preCalc__11JPAAirFieldFP12JPAFieldData */ -void JPAAirField::preCalc(JPAFieldData*) { - /* Nonmatching */ +void JPAAirField::preCalc(JPAFieldData* data) { + JPABaseField::preCalc(data); + if (data->mSttFlag & 0x02) { + data->mLocalDir.set(data->mDir); + } else { + 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; + if (data->mSttFlag & 0x01) { + data->mAirMinDist = JMASCos(data->mVal1 * 0xFFFF); + if (data->mSttFlag & 0x02) { + data->mLocalPos.set(data->mPos); + } else { + MTXMultVec(JPAFieldData::pEmtrInfo->mGlobalRot, data->mLocalPos, data->mPos); + } + } } /* 8025A510-8025A6EC .text calc__11JPAAirFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPAAirField::calc(JPAFieldData*, JPABaseParticle*) { +void JPAAirField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025A6EC-8025A788 .text preCalc__14JPAMagnetFieldFP12JPAFieldData */ -void JPAMagnetField::preCalc(JPAFieldData*) { - /* Nonmatching */ +void JPAMagnetField::preCalc(JPAFieldData* data) { + JPABaseField::preCalc(data); + if (data->mSttFlag & 0x02) { + data->mLocalPos.set(data->mPos); + } else { + const JGeometry::TVec3& emtrTrans = JPAFieldData::pEmtrInfo->mEmitterTranslation; + data->mLocalPos.x = data->mPos.x - emtrTrans.x; + data->mLocalPos.y = data->mPos.y - emtrTrans.y; + data->mLocalPos.z = data->mPos.z - emtrTrans.z; + MTXMultVec(JPAFieldData::pEmtrInfo->mGlobalRot, data->mLocalPos, data->mLocalPos); + } } /* 8025A788-8025A8AC .text calc__14JPAMagnetFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPAMagnetField::calc(JPAFieldData*, JPABaseParticle*) { +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; + } 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.normalize(); + calcVel(data, ptcl); } /* 8025A8AC-8025A954 .text preCalc__14JPANewtonFieldFP12JPAFieldData */ -void JPANewtonField::preCalc(JPAFieldData*) { - /* Nonmatching */ +void JPANewtonField::preCalc(JPAFieldData* data) { + JPABaseField::preCalc(data); + if (data->mSttFlag & 0x02) { + data->mLocalPos.set(data->mPos); + } else { + const JGeometry::TVec3& emtrTrans = JPAFieldData::pEmtrInfo->mEmitterTranslation; + data->mLocalPos.x = data->mPos.x - emtrTrans.x; + data->mLocalPos.y = data->mPos.y - emtrTrans.y; + data->mLocalPos.z = data->mPos.z - emtrTrans.z; + MTXMultVec(JPAFieldData::pEmtrInfo->mGlobalRot, data->mLocalPos, data->mLocalPos); + } + data->mVal2 = data->mVal1 * data->mVal1; } /* 8025A954-8025ABB8 .text calc__14JPANewtonFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPANewtonField::calc(JPAFieldData*, JPABaseParticle*) { +void JPANewtonField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025ABB8-8025ACA0 .text preCalc__14JPAVortexFieldFP12JPAFieldData */ -void JPAVortexField::preCalc(JPAFieldData*) { +void JPAVortexField::preCalc(JPAFieldData* data) { /* Nonmatching */ } /* 8025ACA0-8025AE04 .text calc__14JPAVortexFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPAVortexField::calc(JPAFieldData*, JPABaseParticle*) { +void JPAVortexField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025AE04-8025B114 .text preCalc__18JPAConvectionFieldFP12JPAFieldData */ -void JPAConvectionField::preCalc(JPAFieldData*) { +void JPAConvectionField::preCalc(JPAFieldData* data) { /* Nonmatching */ } /* 8025B114-8025B3CC .text calc__18JPAConvectionFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPAConvectionField::calc(JPAFieldData*, JPABaseParticle*) { +void JPAConvectionField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025B3CC-8025B50C .text calc__14JPARandomFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPARandomField::calc(JPAFieldData*, JPABaseParticle*) { +void JPARandomField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025B50C-8025B584 .text init__12JPADragFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPADragField::init(JPAFieldData*, JPABaseParticle*) { +void JPADragField::init(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025B584-8025B5F4 .text calc__12JPADragFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPADragField::calc(JPAFieldData*, JPABaseParticle*) { +void JPADragField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025B5F4-8025B718 .text preCalc__12JPASpinFieldFP12JPAFieldData */ -void JPASpinField::preCalc(JPAFieldData*) { +void JPASpinField::preCalc(JPAFieldData* data) { /* Nonmatching */ } /* 8025B718-8025B7F8 .text calc__12JPASpinFieldFP12JPAFieldDataP15JPABaseParticle */ -void JPASpinField::calc(JPAFieldData*, JPABaseParticle*) { +void JPASpinField::calc(JPAFieldData* data, JPABaseParticle* ptcl) { /* Nonmatching */ } /* 8025B7F8-8025B960 .text initField__15JPAFieldManagerFP20JPADataBlockLinkInfoP14JPAEmitterInfo */ void JPAFieldManager::initField(JPADataBlockLinkInfo* dataInfo, JPAEmitterInfo* emtrInfo) { - /* Nonmatching */ u8 fieldNum = dataInfo->getFieldNum(); JPAFieldBlock** fieldBlock = dataInfo->getField(); for (u8 i = 0; i < fieldNum; i++) { @@ -219,8 +281,16 @@ void JPAFieldManager::calc(JPABaseParticle* ptcl) { /* Nonmatching */ for (JSULink* link = mList.getFirst(); link != NULL; link = link->getNext()) { JPAFieldData* data = link->getObject(); + if (data->mSttFlag & 0x80) { + // This isn't quite right, probably a TVec3 inline? + f32 z = ptcl->mPosition.z - data->mPos.z; z *= z; + f32 x = ptcl->mPosition.x - data->mPos.x; x *= x; + f32 y = ptcl->mPosition.y - data->mPos.y; y *= y; + f32 dist = z + y + x; + if (!data->mpBaseField->isItinRange(data, dist)) + continue; + } data->mpBaseField->calc(data, ptcl); - // more to do here } }