summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2024-04-14 09:05:44 -0700
committerJasper St. Pierre <jstpierre@mecheye.net>2024-04-14 09:05:54 -0700
commit4ce4072fef3c296dc2e7fcd18ae949c464c6a71e (patch)
tree1d27e9233fe2c8bb2aec3d14df560f778e06c55d
parent5b3b66015a8da8b4c038ccab9bb0786b200eec6f (diff)
JPA work
-rw-r--r--include/JSystem/JGeometry.h70
-rw-r--r--include/JSystem/JParticle/JPAEmitter.h20
-rw-r--r--src/JSystem/JParticle/JPAEmitter.cpp61
-rw-r--r--src/JSystem/JParticle/JPAField.cpp62
4 files changed, 116 insertions, 97 deletions
diff --git a/include/JSystem/JGeometry.h b/include/JSystem/JGeometry.h
index 212334cd..56268aea 100644
--- a/include/JSystem/JGeometry.h
+++ b/include/JSystem/JGeometry.h
@@ -144,34 +144,13 @@ struct TVec3<f32> : public Vec {
return C_VECSquareMag((Vec*)&x);
}
- f32 normalize_broken() {
- f32 sq = squared();
- if (sq <= TUtil<f32>::epsilon()) {
- return 0.0f;
- }
- f32 norm = TUtil<f32>::inv_sqrt(sq);
- scale(norm);
- return norm;
- }
-
f32 normalize() {
f32 sq = squared();
if (sq <= TUtil<f32>::epsilon()) {
return 0.0f;
}
f32 norm = TUtil<f32>::inv_sqrt(sq);
- scale(1.0f / norm);
- return norm;
- }
-
- f32 normalize(const TVec3<f32>& other) {
- f32 sq = other.squared();
- if (sq <= TUtil<f32>::epsilon()) {
- zero();
- return 0.0f;
- }
- f32 norm = TUtil<f32>::inv_sqrt(sq);
- scale(1.0f / norm, other);
+ scale(norm);
return norm;
}
@@ -180,26 +159,16 @@ struct TVec3<f32> : public Vec {
return TUtil<f32>::sqrt(sqr);
}
- void scale(register f32 sc) {
+ void scale(f32 sc) {
x *= sc;
y *= sc;
z *= sc;
}
- void scale(register f32 sc, const TVec3<f32>& 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<f32>& b) {
+ x = b.x * sc;
+ y = b.y * sc;
+ z = b.z * sc;
}
void negate() {
@@ -209,11 +178,15 @@ struct TVec3<f32> : public Vec {
}
void sub(const TVec3<f32>& b) {
- C_VECSubtract((Vec*)&x, (Vec*)&b.x, (Vec*)&x);
+ x -= b.x;
+ y -= b.y;
+ z -= b.z;
}
void sub(const TVec3<f32>& a, const TVec3<f32>& 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<f32> : public Vec {
scale(norm * len);
}
- f32 dot(const TVec3<f32>& 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<f32>& b) const {
+ return x*b.x + y*b.y * z*b.z;
}
template<typename S>
diff --git a/include/JSystem/JParticle/JPAEmitter.h b/include/JSystem/JParticle/JPAEmitter.h
index ddf815f3..77b25b49 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<f32>&) {}
- void checkEmDataFlag(u32) {}
void drawCB() {}
void drawEmitterCallBack() {}
void getAxisYVec(JGeometry::TVec3<f32>&) const {}
@@ -283,7 +283,6 @@ public:
void getFrame() {}
void getGlobalParticleScale(JGeometry::TVec3<f32>&) const {}
void getParticleList() {}
- void getRate() const {}
void getgReRDirection(JGeometry::TVec3<f32>&) {}
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<f32> mEmitterScale;
/* 0x018 */ JGeometry::TVec3<f32> mEmitterTranslation;
diff --git a/src/JSystem/JParticle/JPAEmitter.cpp b/src/JSystem/JParticle/JPAEmitter.cpp
index a74b6139..a52934a5 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 eb08d747..fa3b5a60 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<f32> 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<f32> 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<f32> 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);
}