Document SPLEmitter Init and Update

This commit is contained in:
Fexty12573 2024-08-01 12:19:53 +02:00
parent d0190d81e6
commit 0b9f3ec2ca
11 changed files with 308 additions and 282 deletions

View File

@ -6,24 +6,24 @@
static inline void SPL_UnkInline1 (SPLEmitter * param0, const VecFx32 * param1)
{
param0->unk_98.x = param1->x + param0->resource->header->unk_04.x;
param0->unk_98.y = param1->y + param0->resource->header->unk_04.y;
param0->unk_98.z = param1->z + param0->resource->header->unk_04.z;
param0->position.x = param1->x + param0->resource->header->emitterBasePos.x;
param0->position.y = param1->y + param0->resource->header->emitterBasePos.y;
param0->position.z = param1->z + param0->resource->header->emitterBasePos.z;
}
static inline void SPL_UnkInline2 (SPLEmitter * param0, fx32 param1)
{
param0->unk_98.x = param1 + param0->resource->header->unk_04.x;
param0->position.x = param1 + param0->resource->header->emitterBasePos.x;
}
static inline void SPL_UnkInline3 (SPLEmitter * param0, fx32 param1)
{
param0->unk_98.y = param1 + param0->resource->header->unk_04.y;
param0->position.y = param1 + param0->resource->header->emitterBasePos.y;
}
static inline void SPL_UnkInline4 (SPLEmitter * param0, fx32 param1)
{
param0->unk_98.z = param1 + param0->resource->header->unk_04.z;
param0->position.z = param1 + param0->resource->header->emitterBasePos.z;
}
static inline void SPL_UnkInline5 (SPLEmitter * param0, const VecFx16 * param1)

View File

@ -6,6 +6,13 @@
#include "spl_particle.h"
#include "spl_resource.h"
enum SPLUpdateCallbackType {
SPL_CALLBACK_PRE_UPDATE = 0,
SPL_CALLBACK_POST_UPDATE = 1,
};
typedef void(* SPLEmitterUpdateCallback)(struct SPLEmitter *emitter, enum SPLUpdateCallbackType type);
typedef struct UnkSPLStruct7 {
union
{
@ -13,12 +20,12 @@ typedef struct UnkSPLStruct7 {
u8 padding_00[4];
struct
{
u32 terminate:1;
u32 stop_generate:1;
u32 paused:1;
u32 renderingDisabled:1;
u32 terminate : 1;
u32 emissionPaused : 1;
u32 paused : 1;
u32 renderingDisabled : 1;
u32 started: 1 ;
u32 reserved0:27;
u32 : 27;
};
};
} UnkSPLStruct7;
@ -30,8 +37,8 @@ typedef struct SPLEmitter {
SPLParticleList childParticles;
SPLResource *resource;
UnkSPLStruct7 state;
VecFx32 unk_98;
VecFx32 unk_A4;
VecFx32 position;
VecFx32 velocity;
VecFx32 unk_B0;
u16 age;
fx16 unk_BE;
@ -43,22 +50,22 @@ typedef struct SPLEmitter {
fx32 unk_D4;
fx32 unk_D8;
fx32 unk_DC;
u16 unk_E0;
GXRgb unk_E2;
u16 particleLifeTime;
GXRgb color;
fx32 collisionPlaneHeight;
fx16 unk_E8;
fx16 unk_EA;
fx16 unk_EC;
fx16 unk_EE;
struct {
u32 unk_00_0 : 8;
u32 emissionInterval : 8; // number of frames between particle emissions
u32 unk_01_0 : 8;
u32 updateCycle : 3; // 0 = every frame, 1 = cycle A, 2 = cycle B, cycles A and B alternate
u32 unk_02_3 : 13;
} misc;
VecFx16 unk_F4;
VecFx16 unk_FA;
void (* unk_100)(struct SPLEmitter *, unsigned int);
SPLEmitterUpdateCallback updateCallback;
void * unk_104;
union {
u32 unk_108_val1;

View File

@ -39,9 +39,9 @@ void sub_020A19F0(SPLParticle *ptcl, SPLResource *res, int lifeRate); // spl_chl
void sub_020A08DC(SPLEmitter *emtr, SPLList *list);
void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list);
void sub_0209D150(SPLManager *mgr, SPLEmitter *emtr);
void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr);
void sub_0209CF00(SPLManager *mgr);
void sub_0209D998(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos);
void SPLEmitter_Init(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos);
void spl_generate(SPLEmitter *emtr, SPLList *list);
static inline void SPLParticleList_PushFront(SPLParticleList *list, SPLParticle *ptcl)

View File

@ -10,20 +10,29 @@ typedef struct SPLParticle {
struct SPLParticle *prev;
VecFx32 position;
VecFx32 velocity;
u16 unk_20;
s16 unk_22;
u16 rotation;
s16 angularVelocity;
u16 lifeTime;
u16 age;
u16 unk_28;
u16 unk_2A;
// These two values are essentially 1.0f / lifeTime (or 1.0f / loopTime), represented as an integer
// They are used to map between age/lifeTime and a [0, 255] range
// Mainly just to lower the amount of divisions needed in the update functions
u16 loopTimeFactor;
u16 lifeTimeFactor;
struct {
u16 unk_00 : 8;
u16 unk_01 : 8;
} unk_2C;
// A value between 0 and 255 that is added to the life rate of the particle.
// This is used only for looping particles, so particles spawned at the same time
// don't have aren't all in sync (animation-wise)
u16 lifeRateOffset : 8;
} misc;
struct {
u16 unk_00_0 : 5;
u16 unk_00_5 : 5;
u16 unk_01_2 : 6;
u16 currentPolygonID : 6;
} unk_2E;
fx32 unk_30;
fx16 unk_34;

View File

@ -34,7 +34,7 @@ typedef union {
// If set, the emitter will automatically terminate when it reaches the end of its life
// and all of its particles have died
u32 selfMaintaining : 1;
u32 unk_05_7 : 1;
u32 followEmitter : 1;
u32 hasChildResource : 1;
u32 unk_06_1 : 2;
u32 unk_06_3 : 1;
@ -48,26 +48,26 @@ typedef union {
u32 hasSpinBehavior : 1;
u32 hasCollisionPlaneBehavior : 1;
u32 hasConvergenceBehavior : 1;
u32 unk_07_6 : 1;
u32 unk_07_7 : 1;
u32 hasFixedPolygonID : 1;
u32 childHasFixedPolygonID : 1;
};
} SPLResourceFlags; // size=0x4
typedef union {
u16 unk_00;
u16 all;
struct {
u16 unk_02_0 : 1;
u16 unk_02_1 : 1;
u16 unk_02_2 : 1;
u16 usesBehaviors : 1;
u16 hasScaleAnim : 1;
u16 hasAlphaAnim : 1;
u16 unk_02_3 : 2;
u16 unk_02_5 : 1;
u16 followEmitter : 1;
u16 unk_02_6 : 1;
u16 unk_02_7 : 2;
u16 unk_03_1 : 2;
u16 unk_03_3 : 1;
u16 reserved_03_4 : 4;
};
} UnkSPLUnion2; // size=0x2
} SPLChildResourceFlags; // size=0x2
typedef union {
u16 val1;
@ -87,9 +87,9 @@ typedef union {
};
} UnkSPLUnion4; // size=0x4
typedef struct UnkSPLStruct9_t {
typedef struct SPLResourceHeader {
SPLResourceFlags flags;
VecFx32 unk_04;
VecFx32 emitterBasePos;
fx32 unk_10;
fx32 unk_14;
fx32 unk_18;
@ -116,7 +116,7 @@ typedef struct UnkSPLStruct9_t {
struct {
u32 unk_00_0 : 8;
u32 unk_01_0 : 8;
u32 unk_02_0 : 8;
u32 airResistance : 8;
u32 unk_03_0 : 8;
u32 unk_04_0 : 8;
u32 unk_05_0 : 16;
@ -128,7 +128,7 @@ typedef struct UnkSPLStruct9_t {
u32 unk_08_1 : 1;
u32 unk_08_2 : 3;
u32 unk_08_5 : 27;
} unk_48;
} misc;
fx16 unk_54;
fx16 unk_56;
struct {
@ -137,7 +137,7 @@ typedef struct UnkSPLStruct9_t {
} unk_58;
} SPLResourceHeader; // size=0x5C
typedef struct UnkSPLStruct10_t {
typedef struct SPLScaleAnim {
fx16 unk_00;
fx16 unk_02;
fx16 unk_04;
@ -149,7 +149,7 @@ typedef struct UnkSPLStruct10_t {
u16 reserved_0A;
} SPLScaleAnim; // size=0xc
typedef struct UnkSPLStruct11_t {
typedef struct SPLColorAnim {
GXRgb unk_00;
GXRgb unk_02;
UnkSPLUnion4 unk_04;
@ -162,7 +162,7 @@ typedef struct UnkSPLStruct11_t {
u16 reserved_0A;
} SPLColorAnim;
typedef struct UnkSPLStruct12_t {
typedef struct SPLAlphaAnim {
union {
u16 val1;
struct {
@ -181,7 +181,7 @@ typedef struct UnkSPLStruct12_t {
u16 reserved_06;
} SPLAlphaAnim; // size=0x8
typedef struct UnkSPLStruct13_t {
typedef struct SPLTexAnim {
u8 unk_00[8];
struct {
u32 unk_00_0 : 8;
@ -192,8 +192,8 @@ typedef struct UnkSPLStruct13_t {
} unk_08;
} SPLTexAnim;
typedef struct UnkSPLStruct14_t {
UnkSPLUnion2 unk_00;
typedef struct SPLChildResource {
SPLChildResourceFlags flags;
fx16 unk_02;
fx16 unk_04;
u16 unk_06;
@ -204,8 +204,8 @@ typedef struct UnkSPLStruct14_t {
GXRgb unk_0A;
struct {
u32 unk_00_0 : 8;
u32 unk_01_0 : 8;
u32 unk_02_0 : 8;
u32 emissionDelay : 8; // Delay, as a fraction of the particle's lifetime, before the particle starts emitting
u32 emissionInterval : 8;
u32 unk_03_0 : 8;
u32 unk_04_0 : 2;
u32 unk_04_2 : 2;
@ -213,7 +213,7 @@ typedef struct UnkSPLStruct14_t {
u32 unk_04_5 : 1;
u32 unk_04_6 : 1;
u32 reserved_04_7 : 25;
} unk_0C;
} misc;
} SPLChildResource;
typedef struct SPLResource {

View File

@ -8,11 +8,11 @@ typedef union SPLTextureParam {
u32 all;
struct {
u32 format : 4; // Maps to GXTexFmt
u32 s : 4;
u32 t : 4;
u32 val2_01_4 : 2;
u32 val2_01_6 : 2;
u32 val2_02_0 : 1;
u32 s : 4; // Maps to GXTexSizeS
u32 t : 4; // Maps to GXTexSizeT
u32 repeat : 2; // Maps to GXTexRepeat
u32 flip : 2; // Maps to GXTexFlip
u32 palColor0 : 1; // Maps to GXTexPlttColor0
u32 val2_02_1 : 1;
u32 sharedTexID : 8;
u32 val2_03_2 : 6;

View File

@ -288,7 +288,7 @@ void SPLManager_Update(SPLManager *mgr)
if (!emtr->state.paused) {
if (emtr->misc.updateCycle == 0 || mgr->currentCycle == emtr->misc.updateCycle - 1) {
sub_0209D150(mgr, emtr);
SPLEmitter_Update(mgr, emtr);
}
}
@ -342,7 +342,7 @@ SPLEmitter *SPLManager_CreateEmitter(SPLManager *mgr, int resourceID, const VecF
if (mgr->inactiveEmitters.first != NULL) {
emtr = SPLEmitterList_PopFront(&mgr->inactiveEmitters);
sub_0209D998(emtr, mgr->resources + resourceID, pos);
SPLEmitter_Init(emtr, mgr->resources + resourceID, pos);
SPLEmitterList_PushFront(&mgr->activeEmitters, emtr);
if (emtr->resource->header->flags.selfMaintaining) { // Self-maintaining emitters are not returned to the user
@ -359,7 +359,7 @@ SPLEmitter *SPLManager_CreateEmitterWithCallback(SPLManager *mgr, int resourceID
if (mgr->inactiveEmitters.first != NULL) {
VecFx32 pos = { 0, 0, 0 };
emtr = SPLEmitterList_PopFront(&mgr->inactiveEmitters);
sub_0209D998(emtr, mgr->resources + resourceID, &pos);
SPLEmitter_Init(emtr, mgr->resources + resourceID, &pos);
if (initCallback != NULL) {
initCallback(emtr);
@ -380,7 +380,7 @@ SPLEmitter *SPLManager_CreateEmitterWithCallbackEx(SPLManager *mgr, int resource
SPLEmitter *emtr = NULL;
if (mgr->inactiveEmitters.first != NULL) {
emtr = SPLEmitterList_PopFront(&mgr->inactiveEmitters);
sub_0209D998(emtr, mgr->resources + resourceID, pos);
SPLEmitter_Init(emtr, mgr->resources + resourceID, pos);
if (initCallback != NULL) {
initCallback(emtr, param);
@ -431,8 +431,8 @@ void SPL_Emit(SPLManager *mgr, SPLEmitter *emtr)
void SPL_EmitAt(SPLManager *mgr, SPLEmitter *emtr, VecFx32 *pos)
{
emtr->unk_98.x = pos->x + emtr->resource->header->unk_04.x;
emtr->unk_98.y = pos->y + emtr->resource->header->unk_04.y;
emtr->unk_98.z = pos->z + emtr->resource->header->unk_04.z;
emtr->position.x = pos->x + emtr->resource->header->emitterBasePos.x;
emtr->position.y = pos->y + emtr->resource->header->emitterBasePos.y;
emtr->position.z = pos->z + emtr->resource->header->emitterBasePos.z;
spl_generate(emtr, (SPLList *)&mgr->inactiveParticles);
}

View File

@ -10,6 +10,8 @@
#include "spl_internal.h"
#include "spl_list.h"
#define ANIM_FUNC_NO_LOOP 0
#define ANIM_FUNC_LOOP 1
typedef void(*DrawFunc)(SPLManager *mgr, SPLParticle *ptcl);
typedef void(*SetTexFunc)(SPLTexture *tex);
@ -17,22 +19,22 @@ typedef void(*SetTexFunc)(SPLTexture *tex);
typedef struct FieldFunc {
void (*func)(SPLParticle *, SPLResource *, int);
BOOL loop;
} FieldFunc;
} AnimFunc;
typedef struct FieldFunc8 {
void (*func)(SPLParticle *, SPLResource *, u8);
BOOL loop;
} FieldFunc8;
static void sub_0209DC68(SPLTexture *tex); // spl_set_tex
static void sub_0209DC64(SPLTexture *tex); // spl_set_tex_dummy
static void SPLUtil_SetTexture(SPLTexture *tex); // spl_set_tex
static void SPLUtil_SetTexture_Stub(SPLTexture *tex); // spl_set_tex_dummy
static void sub_0209D064(SPLManager *mgr);
static void sub_0209CF7C(SPLManager *mgr);
void sub_0209D998(SPLEmitter *emtr, SPLResource *res, const VecFx32 *param2);
void SPLEmitter_Init(SPLEmitter *emtr, SPLResource *res, const VecFx32 *param2);
void sub_0209CF00(SPLManager *mgr);
void sub_0209D150(SPLManager *mgr, SPLEmitter *emtr);
void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr);
static void sub_0209DC68(SPLTexture *tex)
static void SPLUtil_SetTexture(SPLTexture *tex)
{
SPLTextureParam param = tex->param;
@ -41,9 +43,9 @@ static void sub_0209DC68(SPLTexture *tex)
GX_TEXGEN_TEXCOORD,
param.s,
param.t,
param.val2_01_4,
param.val2_01_6,
param.val2_02_0,
param.repeat,
param.flip,
param.palColor0,
tex->texAddr);
G3_TexPlttBase(tex->palAddr, param.format);
@ -53,23 +55,23 @@ static void sub_0209DC68(SPLTexture *tex)
G3_MtxMode(GX_MTXMODE_POSITION);
}
static void sub_0209DC64(SPLTexture *tex)
static void SPLUtil_SetTexture_Stub(SPLTexture *tex)
{
}
void sub_0209D998(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos)
void SPLEmitter_Init(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos)
{
emtr->resource = res;
emtr->state.all = 0;
emtr->unk_98.x = pos->x + emtr->resource->header->unk_04.x;
emtr->unk_98.y = pos->y + emtr->resource->header->unk_04.y;
emtr->unk_98.z = pos->z + emtr->resource->header->unk_04.z;
emtr->position.x = pos->x + emtr->resource->header->emitterBasePos.x;
emtr->position.y = pos->y + emtr->resource->header->emitterBasePos.y;
emtr->position.z = pos->z + emtr->resource->header->emitterBasePos.z;
emtr->unk_B0.x = 0;
emtr->unk_B0.y = 0;
emtr->unk_B0.z = 0;
emtr->unk_A4.x = emtr->unk_A4.y = emtr->unk_A4.z = 0;
emtr->velocity.x = emtr->velocity.y = emtr->velocity.z = 0;
emtr->age = 0;
emtr->unk_BE = 0;
@ -82,34 +84,34 @@ void sub_0209D998(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos)
emtr->unk_D4 = emtr->resource->header->unk_24;
emtr->unk_D8 = emtr->resource->header->unk_28;
emtr->unk_DC = emtr->resource->header->unk_2C;
emtr->unk_E0 = emtr->resource->header->particleLifeTime;
emtr->particleLifeTime = emtr->resource->header->particleLifeTime;
emtr->unk_E2 = GX_RGB(31, 31, 31);
emtr->misc.unk_00_0 = emtr->resource->header->unk_48.unk_00_0;
emtr->misc.unk_01_0 = emtr->resource->header->unk_48.unk_01_0;
emtr->color = GX_RGB(31, 31, 31);
emtr->misc.emissionInterval = emtr->resource->header->misc.unk_00_0;
emtr->misc.unk_01_0 = emtr->resource->header->misc.unk_01_0;
emtr->misc.updateCycle = 0;
emtr->misc.unk_02_3 = 0;
emtr->collisionPlaneHeight = FX32_MIN;
emtr->unk_E8 = FX32_ONE << emtr->resource->header->unk_48.unk_07_0;
emtr->unk_EA = FX32_ONE << emtr->resource->header->unk_48.unk_07_2;
emtr->unk_E8 = FX32_ONE << emtr->resource->header->misc.unk_07_0;
emtr->unk_EA = FX32_ONE << emtr->resource->header->misc.unk_07_2;
if (emtr->resource->header->unk_48.unk_08_0) {
if (emtr->resource->header->misc.unk_08_0) {
emtr->unk_E8 *= -1;
}
if (emtr->resource->header->unk_48.unk_08_1) {
if (emtr->resource->header->misc.unk_08_1) {
emtr->unk_EA *= -1;
}
if (emtr->resource->header->flags.hasChildResource) {
emtr->unk_EC = FX32_ONE << emtr->resource->childResource->unk_0C.unk_04_0;
emtr->unk_EE = FX32_ONE << emtr->resource->childResource->unk_0C.unk_04_2;
emtr->unk_EC = FX32_ONE << emtr->resource->childResource->misc.unk_04_0;
emtr->unk_EE = FX32_ONE << emtr->resource->childResource->misc.unk_04_2;
if (emtr->resource->childResource->unk_0C.unk_04_4) {
if (emtr->resource->childResource->misc.unk_04_4) {
emtr->unk_EC *= -1;
}
if (emtr->resource->childResource->unk_0C.unk_04_5) {
if (emtr->resource->childResource->misc.unk_04_5) {
emtr->unk_EE *= -1;
}
}
@ -117,116 +119,121 @@ void sub_0209D998(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos)
emtr->next = emtr->prev = NULL;
emtr->particles.first = emtr->childParticles.first = NULL;
emtr->particles.count = emtr->childParticles.count = 0;
emtr->unk_100 = NULL;
emtr->updateCallback = NULL;
emtr->unk_104 = NULL;
emtr->unk_108.unk_108_val1 = 0;
}
void sub_0209D150(SPLManager *mgr, SPLEmitter *emtr)
void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr)
{
SPLParticle *ptcl;
SPLParticle *next;
SPLResource *res;
SPLResourceHeader *resBase;
SPLResourceHeader *header;
SPLChildResource *child;
SPLResourceFlags resFlags;
FieldFunc fieldFuncs[4];
FieldFunc fieldFuncs2[4];
int i, fieldIndex, fldNum;
AnimFunc animFuncs[4];
AnimFunc childAnimFuncs[4];
int i, animCount, behaviorCount;
int airResistance;
u8 lifeRates[2];
VecFx32 vec;
int idx;
VecFx32 acc;
res = emtr->resource;
child = res->childResource;
fieldIndex = 0;
resBase = res->header;
resFlags = resBase->flags;
fldNum = res->behaviorCount;
airResistance = resBase->unk_48.unk_02_0 + 0x180;
animCount = 0;
header = res->header;
resFlags = header->flags;
behaviorCount = res->behaviorCount;
airResistance = header->misc.airResistance + FX32_CONST(0.09375);
if (emtr->unk_100) {
emtr->unk_100(emtr, FALSE);
if (emtr->updateCallback) {
emtr->updateCallback(emtr, SPL_CALLBACK_PRE_UPDATE);
}
if (resBase->emitterLifeTime == 0 || emtr->age < resBase->emitterLifeTime) {
if (emtr->age % emtr->misc.unk_00_0 == 0) {
if (!emtr->state.terminate && !emtr->state.stop_generate && emtr->state.started) {
if (header->emitterLifeTime == 0 || emtr->age < header->emitterLifeTime) {
if (emtr->age % emtr->misc.emissionInterval == 0) {
if (!emtr->state.terminate && !emtr->state.emissionPaused && emtr->state.started) {
sub_020A08DC(emtr, (SPLList *)(&mgr->inactiveParticles));
}
}
}
if (resFlags.hasScaleAnim) { // ScaleAnim
fieldFuncs[fieldIndex].func = sub_020A1DA0;
fieldFuncs[fieldIndex++].loop = res->scaleAnim->unk_08.unk_00_0;
animFuncs[animCount].func = sub_020A1DA0;
animFuncs[animCount++].loop = res->scaleAnim->unk_08.unk_00_0;
}
if (resFlags.hasColorAnim && !res->colorAnim->unk_08.unk_00_0) { // ColorAnim
fieldFuncs[fieldIndex].func = sub_020A1BD4;
fieldFuncs[fieldIndex++].loop = res->colorAnim->unk_08.unk_00_1;
animFuncs[animCount].func = sub_020A1BD4;
animFuncs[animCount++].loop = res->colorAnim->unk_08.unk_00_1;
}
if (resFlags.hasAlphaAnim) { // AlphaAnim
fieldFuncs[fieldIndex].func = sub_020A1AF8;
fieldFuncs[fieldIndex++].loop = res->alphaAnim->unk_02.unk_01_0;
animFuncs[animCount].func = sub_020A1AF8;
animFuncs[animCount++].loop = res->alphaAnim->unk_02.unk_01_0;
}
if (resFlags.hasTexAnim && !res->texAnim->unk_08.unk_02_0) { // TexAnim
fieldFuncs[fieldIndex].func = sub_020A1A94;
fieldFuncs[fieldIndex++].loop = res->texAnim->unk_08.unk_02_1;
animFuncs[animCount].func = sub_020A1A94;
animFuncs[animCount++].loop = res->texAnim->unk_08.unk_02_1;
}
for (ptcl = emtr->particles.first; ptcl != NULL; ptcl = next) {
next = ptcl->next;
lifeRates[0] = ptcl->unk_2A * ptcl->age >> 8;
lifeRates[1] = ptcl->unk_2C.unk_01 + (ptcl->unk_28 * ptcl->age >> 8);
for (i = 0; i < fieldIndex; i++) {
fieldFuncs[i].func(ptcl, res, lifeRates[fieldFuncs[i].loop]);
// For non-looping particles, "life rate" is a fraction of the particle's lifetime, represented as a u8.
// where 0 is the start of the particle's life and 255 is the end
// For looping particles, it's a fraction of the number of frames in the loop
// See the SPLParticle struct for more info
lifeRates[ANIM_FUNC_NO_LOOP] = (ptcl->lifeTimeFactor * ptcl->age) >> 8;
lifeRates[ANIM_FUNC_LOOP] = ptcl->misc.lifeRateOffset + ((ptcl->loopTimeFactor * ptcl->age) >> 8);
for (i = 0; i < animCount; i++) {
animFuncs[i].func(ptcl, res, lifeRates[animFuncs[i].loop]);
}
vec.x = vec.y = vec.z = 0;
acc.x = acc.y = acc.z = 0;
if (resFlags.unk_05_7) {
ptcl->emitterPos = emtr->unk_98;
if (resFlags.followEmitter) {
ptcl->emitterPos = emtr->position;
}
for (i = 0; i < fldNum; i++) {
res->behaviors[i].apply(res->behaviors[i].object, ptcl, &vec, emtr);
for (i = 0; i < behaviorCount; i++) {
res->behaviors[i].apply(res->behaviors[i].object, ptcl, &acc, emtr);
}
ptcl->unk_20 += ptcl->unk_22;
ptcl->rotation += ptcl->angularVelocity;
ptcl->velocity.x = (ptcl->velocity.x * airResistance >> 9);
ptcl->velocity.y = (ptcl->velocity.y * airResistance >> 9);
ptcl->velocity.z = (ptcl->velocity.z * airResistance >> 9);
ptcl->velocity.x = ptcl->velocity.x * airResistance >> 9;
ptcl->velocity.y = ptcl->velocity.y * airResistance >> 9;
ptcl->velocity.z = ptcl->velocity.z * airResistance >> 9;
ptcl->velocity.x += vec.x;
ptcl->velocity.y += vec.y;
ptcl->velocity.z += vec.z;
ptcl->velocity.x += acc.x;
ptcl->velocity.y += acc.y;
ptcl->velocity.z += acc.z;
ptcl->position.x += ptcl->velocity.x + emtr->unk_A4.x;
ptcl->position.y += ptcl->velocity.y + emtr->unk_A4.y;
ptcl->position.z += ptcl->velocity.z + emtr->unk_A4.z;
ptcl->position.x += ptcl->velocity.x + emtr->velocity.x;
ptcl->position.y += ptcl->velocity.y + emtr->velocity.y;
ptcl->position.z += ptcl->velocity.z + emtr->velocity.z;
if (resFlags.hasChildResource) {
fx32 x = FX_MUL((fx32)ptcl->lifeTime << FX32_SHIFT, (fx32)child->unk_0C.unk_01_0 << FX32_SHIFT);
fx32 a = (fx32)ptcl->age * FX32_ONE;
fx32 diff = a - (x >> 8);
fx32 emissionDelay = FX_MUL((fx32)ptcl->lifeTime << FX32_SHIFT, (fx32)child->misc.emissionDelay << FX32_SHIFT);
// The >> 8 here is a division by 256 because emissionDelay is a fraction of the particle's lifetime represented as a u8
fx32 diff = ((fx32)ptcl->age * FX32_ONE) - (emissionDelay >> 8);
if (diff >= 0) {
if ((diff >> FX32_SHIFT) % child->unk_0C.unk_02_0 == 0) {
if ((diff >> FX32_SHIFT) % child->misc.emissionInterval == 0) {
sub_020A05BC(ptcl, emtr, (SPLList *)&mgr->inactiveParticles);
}
}
}
if (emtr->resource->header->flags.unk_07_6) {
ptcl->unk_2E.unk_01_2 = mgr->polygonID.fix;
if (emtr->resource->header->flags.hasFixedPolygonID) {
ptcl->unk_2E.currentPolygonID = mgr->polygonID.fix;
} else {
ptcl->unk_2E.unk_01_2 = mgr->polygonID.current;
ptcl->unk_2E.currentPolygonID = mgr->polygonID.current;
mgr->polygonID.current += 1;
if (mgr->polygonID.current > mgr->polygonID.max) {
@ -237,63 +244,65 @@ void sub_0209D150(SPLManager *mgr, SPLEmitter *emtr)
ptcl->age += 1;
if (ptcl->age > ptcl->lifeTime) {
SPLNode *node = SPLList_Erase((SPLList *)(&emtr->particles), (SPLNode *)ptcl);
SPLList_PushFront((SPLList *)&mgr->inactiveParticles, node);
SPLParticle *erased = SPLParticleList_Erase(&emtr->particles, ptcl);
SPLParticleList_PushFront(&mgr->inactiveParticles, erased);
}
}
if (resFlags.hasChildResource) {
fieldIndex = 0;
if (child->unk_00.unk_02_1) {
fieldFuncs2[fieldIndex].func = sub_020A1A48;
fieldFuncs2[fieldIndex++].loop = FALSE;
animCount = 0;
if (child->flags.hasScaleAnim) {
childAnimFuncs[animCount].func = sub_020A1A48;
childAnimFuncs[animCount++].loop = FALSE;
}
if (child->unk_00.unk_02_2) {
fieldFuncs2[fieldIndex].func = sub_020A19F0;
fieldFuncs2[fieldIndex++].loop = FALSE;
if (child->flags.hasAlphaAnim) {
childAnimFuncs[animCount].func = sub_020A19F0;
childAnimFuncs[animCount++].loop = FALSE;
}
if (!child->unk_00.unk_02_0) {
fldNum = 0;
if (!child->flags.usesBehaviors) {
behaviorCount = 0;
}
for (ptcl = emtr->childParticles.first; ptcl != NULL; ptcl = next) {
next = ptcl->next;
// "life rate" is a fraction of the particle's lifetime, represented as a u8
// where 0 is the start of the particle's life and 255 is the end
lifeRates[0] = (ptcl->age << 8) / ptcl->lifeTime;
for (i = 0; i < fieldIndex; i++) {
u8 lifeRate = lifeRates[0];
fieldFuncs2[i].func(ptcl, res, lifeRate);
for (i = 0; i < animCount; i++) {
childAnimFuncs[i].func(ptcl, res, lifeRates[0]);
}
vec.x = vec.y = vec.z = 0;
acc.x = acc.y = acc.z = 0;
if (child->unk_00.unk_02_5) {
ptcl->emitterPos = emtr->unk_98;
if (child->flags.followEmitter) {
ptcl->emitterPos = emtr->position;
}
for (i = 0; i < fldNum; i++) {
res->behaviors[i].apply(res->behaviors[i].object, ptcl, &vec, emtr);
for (i = 0; i < behaviorCount; i++) {
res->behaviors[i].apply(res->behaviors[i].object, ptcl, &acc, emtr);
}
ptcl->unk_20 += ptcl->unk_22;
ptcl->rotation += ptcl->angularVelocity;
ptcl->velocity.x = ptcl->velocity.x * airResistance >> 9;
ptcl->velocity.y = ptcl->velocity.y * airResistance >> 9;
ptcl->velocity.z = ptcl->velocity.z * airResistance >> 9;
ptcl->velocity.x += vec.x;
ptcl->velocity.y += vec.y;
ptcl->velocity.z += vec.z;
ptcl->velocity.x += acc.x;
ptcl->velocity.y += acc.y;
ptcl->velocity.z += acc.z;
ptcl->position.x += ptcl->velocity.x + emtr->unk_A4.x;
ptcl->position.y += ptcl->velocity.y + emtr->unk_A4.y;
ptcl->position.z += ptcl->velocity.z + emtr->unk_A4.z;
ptcl->position.x += ptcl->velocity.x + emtr->velocity.x;
ptcl->position.y += ptcl->velocity.y + emtr->velocity.y;
ptcl->position.z += ptcl->velocity.z + emtr->velocity.z;
if (emtr->resource->header->flags.unk_07_7) {
ptcl->unk_2E.unk_01_2 = mgr->polygonID.fix;
if (emtr->resource->header->flags.childHasFixedPolygonID) {
ptcl->unk_2E.currentPolygonID = mgr->polygonID.fix;
} else {
ptcl->unk_2E.unk_01_2 = mgr->polygonID.current;
ptcl->unk_2E.currentPolygonID = mgr->polygonID.current;
mgr->polygonID.current += 1;
if (mgr->polygonID.current > mgr->polygonID.max) {
@ -304,15 +313,16 @@ void sub_0209D150(SPLManager *mgr, SPLEmitter *emtr)
ptcl->age += 1;
if (ptcl->age > ptcl->lifeTime) {
SPLList_PushFront((SPLList *)&mgr->inactiveParticles, SPLList_Erase((SPLList *)(&emtr->childParticles), (SPLNode *)ptcl));
SPLParticle *erased = SPLParticleList_Erase(&emtr->childParticles, ptcl);
SPLParticleList_PushFront(&mgr->inactiveParticles, erased);
}
}
}
emtr->age += 1;
if (emtr->unk_100) {
emtr->unk_100(emtr, TRUE);
if (emtr->updateCallback) {
emtr->updateCallback(emtr, SPL_CALLBACK_POST_UPDATE);
}
}
@ -328,7 +338,7 @@ static void sub_0209D064(SPLManager *mgr)
resBase = emtr->resource->header;
drawFunc = NULL;
sub_0209DC68(mgr->textures + resBase->unk_48.unk_03_0);
SPLUtil_SetTexture(mgr->textures + resBase->misc.unk_03_0);
switch (resBase->flags.unk_04_4) {
case 0:
@ -348,11 +358,11 @@ static void sub_0209D064(SPLManager *mgr)
break;
}
setTexFunc = resBase->flags.hasTexAnim ? sub_0209DC68 : sub_0209DC64;
setTexFunc = resBase->flags.hasTexAnim ? SPLUtil_SetTexture : SPLUtil_SetTexture_Stub;
ptcl = emtr->particles.first;
while (ptcl != NULL) {
setTexFunc(mgr->textures + ptcl->unk_2C.unk_00);
setTexFunc(mgr->textures + ptcl->misc.unk_00);
drawFunc(mgr, ptcl);
ptcl = ptcl->next;
}
@ -373,9 +383,9 @@ static void sub_0209CF7C(SPLManager *mgr)
return;
}
sub_0209DC68(mgr->textures + res->childResource->unk_0C.unk_03_0);
SPLUtil_SetTexture(mgr->textures + res->childResource->misc.unk_03_0);
switch (res->childResource->unk_00.unk_02_7) {
switch (res->childResource->flags.unk_02_7) {
case 0:
drawFunc = sub_0209FAB8;
break;
@ -430,9 +440,9 @@ void SPL_Util_SetCylinderEmiterDirection(SPLEmitter *emtr, VecFx32 *p1, VecFx32
VecFx32 vex;
if (emtr->resource->header->flags.unk_04_0 == 6 || emtr->resource->header->flags.unk_04_0 == 7) {
emtr->unk_98.x = (p2->x + p1->x) / 2;
emtr->unk_98.y = (p2->y + p1->y) / 2;
emtr->unk_98.z = (p2->z + p1->z) / 2;
emtr->position.x = (p2->x + p1->x) / 2;
emtr->position.y = (p2->y + p1->y) / 2;
emtr->position.z = (p2->z + p1->z) / 2;
emtr->unk_D0 = VEC_Distance(p1, p2) / 2;
vex.x = p2->x - p1->x;

View File

@ -136,9 +136,9 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
animScale = ptcl->unk_34;
ptclCol = ptcl->unk_36;
emtrCol = emtr->unk_E2;
emtrCol = emtr->color;
scaleAnimDirect = resBase->unk_48.unk_07_4;
scaleAnimDirect = resBase->misc.unk_07_4;
fx32 alpha = ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1) >> 5;
@ -146,7 +146,7 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -174,8 +174,8 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
trs.z = ptcl->position.z + ptcl->emitterPos.z;
MTX_MultVec43(&trs, cmr, &trs);
sin = FX_SinIdx(ptcl->unk_20);
fx32 cos = FX_CosIdx(ptcl->unk_20);
sin = FX_SinIdx(ptcl->rotation);
fx32 cos = FX_CosIdx(ptcl->rotation);
load.m[0][0] = FX_MUL(cos, sclX);
load.m[0][1] = FX_MUL(sin, sclX);
load.m[0][2] = 0;
@ -192,13 +192,13 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
G3_MultMtx43(&load);
} else {
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->unk_04.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->emitterBasePos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
MTX_MultVec43(&trs, cmr, &trs);
sin = FX_SinIdx(ptcl->unk_20);
fx32 cos = FX_CosIdx(ptcl->unk_20);
sin = FX_SinIdx(ptcl->rotation);
fx32 cos = FX_CosIdx(ptcl->rotation);
load.m[0][0] = FX_MUL(cos, sclX);
load.m[0][1] = FX_MUL(sin, sclX);
load.m[0][2] = 0;
@ -215,7 +215,7 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
SPLResourceHeader *resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(&load);
}
@ -246,7 +246,7 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -259,7 +259,7 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
sclY = ptcl->unk_30;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->unk_48.unk_07_4) {
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
@ -280,8 +280,8 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
trs.z = ptcl->position.z + ptcl->emitterPos.z;
MTX_MultVec43(&trs, cmr, &trs);
sin = FX_SinIdx(ptcl->unk_20);
fx32 cos = FX_CosIdx(ptcl->unk_20);
sin = FX_SinIdx(ptcl->rotation);
fx32 cos = FX_CosIdx(ptcl->rotation);
load.m[0][0] = FX_MUL(cos, sclX);
load.m[0][1] = FX_MUL(sin, sclX);
load.m[0][2] = 0;
@ -298,13 +298,13 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
G3_MultMtx43(&load);
} else {
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->unk_04.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->emitterBasePos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
MTX_MultVec43(&trs, cmr, &trs);
sin = FX_SinIdx(ptcl->unk_20);
fx32 cos = FX_CosIdx(ptcl->unk_20);
sin = FX_SinIdx(ptcl->rotation);
fx32 cos = FX_CosIdx(ptcl->rotation);
load.m[0][0] = FX_MUL(cos, sclX);
load.m[0][1] = FX_MUL(sin, sclX);
load.m[0][2] = 0;
@ -321,12 +321,12 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
SPLResourceHeader *resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(&load);
}
GXRgb colA = ptcl->unk_36;
GXRgb colB = mgr->renderState.emitter->unk_E2;
GXRgb colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
@ -357,7 +357,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -370,7 +370,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
sclY = ptcl->unk_30;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->unk_48.unk_07_4) {
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
@ -414,7 +414,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
dot = -dot;
}
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->unk_48.unk_05_0) + FX32_ONE);
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->misc.unk_05_0) + FX32_ONE);
load.m[0][0] = FX_MUL(dir.x, sclX);
load.m[1][0] = FX_MUL(-dir.y, dot);
load.m[3][0] = trs.x;
@ -431,9 +431,9 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
G3_MultMtx43(&load);
} else {
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->unk_04.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->emitterBasePos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
dir = ptcl->velocity;
@ -459,7 +459,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
dot = -dot;
}
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->unk_48.unk_05_0) + FX32_ONE);
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->misc.unk_05_0) + FX32_ONE);
load.m[0][0] = FX_MUL(dir.x, sclX);
load.m[1][0] = FX_MUL(-dir.y, dot);
load.m[2][0] = 0;
@ -476,12 +476,12 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
SPLResourceHeader *resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(&load);
}
GXRgb colA = ptcl->unk_36;
GXRgb colB = mgr->renderState.emitter->unk_E2;
GXRgb colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
@ -512,7 +512,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -525,7 +525,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
sclY = ptcl->unk_30;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->unk_48.unk_07_4) {
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
@ -569,7 +569,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
dot = -dot;
}
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->unk_48.unk_05_0) + FX32_ONE);
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->misc.unk_05_0) + FX32_ONE);
load.m[0][0] = FX_MUL(dir.x, sclX);
load.m[1][0] = FX_MUL(-dir.y, dot);
load.m[3][0] = trs.x;
@ -586,9 +586,9 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
G3_MultMtx43(&load);
} else {
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->unk_04.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
trs.x = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->emitterBasePos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
dir = ptcl->velocity;
@ -614,7 +614,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
dot = -dot;
}
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->unk_48.unk_05_0) + FX32_ONE);
dot = FX_MUL(sclY, FX_MUL(FX32_ONE - dot, (fx32)mgr->renderState.emitter->resource->header->misc.unk_05_0) + FX32_ONE);
load.m[0][0] = FX_MUL(dir.x, sclX);
load.m[1][0] = FX_MUL(-dir.y, dot);
load.m[2][0] = 0;
@ -631,12 +631,12 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
G3_Identity();
SPLResourceHeader *resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(&load);
}
GXRgb colA = ptcl->unk_36;
GXRgb colB = mgr->renderState.emitter->unk_E2;
GXRgb colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
@ -662,7 +662,7 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -672,13 +672,13 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->unk_20), FX_CosIdx(ptcl->unk_20), &rotMtx);
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sclY = ptcl->unk_30;
resBase = mgr->renderState.emitter->resource->header;
sclX = FX_MUL(sclY, resBase->unk_30);
switch (resBase->unk_48.unk_07_4) {
switch (resBase->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
@ -704,21 +704,21 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
G3_LoadMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&load);
} else {
load.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->unk_04.x;
load.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
load.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
load.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->emitterBasePos.x;
load.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
load.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
G3_Identity();
resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&load);
}
GXRgb colA = ptcl->unk_36;
GXRgb colB = mgr->renderState.emitter->unk_E2;
GXRgb colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
@ -745,7 +745,7 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -755,13 +755,13 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->unk_00.unk_03_1](FX_SinIdx(ptcl->unk_20), FX_CosIdx(ptcl->unk_20), &rotMtx);
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sclY = ptcl->unk_30;
resBase = mgr->renderState.emitter->resource->header;
sclX = FX_MUL(sclY, resBase->unk_30);
switch (resBase->unk_48.unk_07_4) {
switch (resBase->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
@ -786,27 +786,27 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
G3_LoadMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&load);
} else {
load.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->unk_04.x;
load.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
load.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
load.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - mgr->renderState.emitter->resource->header->emitterBasePos.x;
load.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
load.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
G3_Identity();
resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&load);
}
GXRgb colA = ptcl->unk_36;
GXRgb colB = mgr->renderState.emitter->unk_E2;
GXRgb colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
GX_RGB_B_(colA) * GX_RGB_B_(colB) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
Unk_02100DA0[emtr->resource->childResource->unk_00.unk_03_3](emtr->unk_EC, emtr->unk_EE, 0, 0);
Unk_02100DA0[emtr->resource->childResource->flags.unk_03_3](emtr->unk_EC, emtr->unk_EE, 0, 0);
}
void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
@ -827,7 +827,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -837,11 +837,11 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->unk_20), FX_CosIdx(ptcl->unk_20), &rotMat);
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMat);
MTX_Identity43(&mat);
if (!mgr->renderState.emitter->resource->header->unk_48.unk_07_7) {
if (!mgr->renderState.emitter->resource->header->misc.unk_07_7) {
VEC_Normalize(&ptcl->velocity, &vec1);
} else {
VEC_Normalize(&ptcl->position, &vec1);
@ -879,7 +879,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
scaleY = ptcl->unk_30;
scaleX = FX_MUL(scaleY, resBase->unk_30);
switch (resBase->unk_48.unk_07_4) {
switch (resBase->misc.unk_07_4) {
case 0:
scaleX = FX_MUL(scaleX, ptcl->unk_34);
scaleY = FX_MUL(scaleY, ptcl->unk_34);
@ -905,20 +905,20 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
G3_LoadMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&transform);
} else {
transform.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - resBase->unk_04.x;
transform.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
transform.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
transform.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - resBase->emitterBasePos.x;
transform.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
transform.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
G3_Identity();
resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&transform);
}
colA = ptcl->unk_36;
colB = mgr->renderState.emitter->unk_E2;
colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
@ -945,7 +945,7 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->unk_2E.unk_01_2,
ptcl->unk_2E.currentPolygonID,
alpha,
mgr->unk_3C);
@ -955,11 +955,11 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->unk_00.unk_03_1](FX_SinIdx(ptcl->unk_20), FX_CosIdx(ptcl->unk_20), &rotMtx);
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
MTX_Identity43(&mat);
if (!mgr->renderState.emitter->resource->childResource->unk_0C.unk_04_6) {
if (!mgr->renderState.emitter->resource->childResource->misc.unk_04_6) {
VEC_Normalize(&ptcl->velocity, &vec1);
} else {
VEC_Normalize(&ptcl->position, &vec1);
@ -997,7 +997,7 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
scaleY = ptcl->unk_30;
scaleX = FX_MUL(scaleY, resBase->unk_30);
switch (resBase->unk_48.unk_07_4) {
switch (resBase->misc.unk_07_4) {
case 0:
scaleX = FX_MUL(scaleX, ptcl->unk_34);
scaleY = FX_MUL(scaleY, ptcl->unk_34);
@ -1023,25 +1023,25 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
G3_LoadMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&transform);
} else {
transform.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - resBase->unk_04.x;
transform.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->unk_04.y;
transform.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->unk_04.z;
transform.m[3][0] = ptcl->position.x + ptcl->emitterPos.x - resBase->emitterBasePos.x;
transform.m[3][1] = ptcl->position.y + ptcl->emitterPos.y - mgr->renderState.emitter->resource->header->emitterBasePos.y;
transform.m[3][2] = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
G3_Identity();
resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->unk_04.x, resBase->unk_04.y, resBase->unk_04.z);
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(mgr->renderState.viewMatrix);
G3_MultMtx43(&transform);
}
GXRgb colA = ptcl->unk_36;
GXRgb colB = mgr->renderState.emitter->unk_E2;
GXRgb colB = mgr->renderState.emitter->color;
G3_Color(GX_RGB(
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
GX_RGB_G_(colA) * GX_RGB_G_(colB) >> 15,
GX_RGB_B_(colA) * GX_RGB_B_(colB) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
Unk_02100DA0[emtr->resource->childResource->unk_00.unk_03_3](emtr->unk_EC, emtr->unk_EE, 0, 0);
Unk_02100DA0[emtr->resource->childResource->flags.unk_03_3](emtr->unk_EC, emtr->unk_EE, 0, 0);
}

View File

@ -232,7 +232,7 @@ void sub_020A08DC(SPLEmitter *emtr, SPLList *list)
ptcl->velocity.y = FX_MUL(posNorm.y, magPos) + FX_MUL(emtr->unk_C0.y, magAxis) + emtr->unk_B0.y;
ptcl->velocity.z = FX_MUL(posNorm.z, magPos) + FX_MUL(emtr->unk_C0.z, magAxis) + emtr->unk_B0.z;
ptcl->emitterPos = emtr->unk_98;
ptcl->emitterPos = emtr->position;
ptcl->unk_30 = SPLRandom_DoubleScaledRangeFX32(emtr->unk_DC, resBase->unk_44.unk_00_0);
ptcl->unk_34 = FX32_ONE;
@ -252,35 +252,35 @@ void sub_020A08DC(SPLEmitter *emtr, SPLList *list)
ptcl->unk_2E.unk_00_5 = 31;
if (resBase->flags.unk_05_5) {
ptcl->unk_20 = SPLRandom_S32(32);
ptcl->rotation = SPLRandom_S32(32);
} else {
ptcl->unk_20 = emtr->unk_C6;
ptcl->rotation = emtr->unk_C6;
}
if (resBase->flags.unk_05_4) {
ptcl->unk_22 = (u32)SPLRandom_BetweenFX32(resBase->unk_34, resBase->unk_36) >> FX32_SHIFT;
ptcl->angularVelocity = (u32)SPLRandom_BetweenFX32(resBase->unk_34, resBase->unk_36) >> FX32_SHIFT;
} else {
ptcl->unk_22 = 0;
ptcl->angularVelocity = 0;
}
ptcl->lifeTime = SPLRandom_ScaledRangeFX32(emtr->unk_E0, resBase->unk_44.unk_01_0) + 1;
ptcl->lifeTime = SPLRandom_ScaledRangeFX32(emtr->particleLifeTime, resBase->unk_44.unk_01_0) + 1;
ptcl->age = 0;
if (resBase->flags.hasTexAnim && res->texAnim->unk_08.unk_02_0) {
ptcl->unk_2C.unk_00 = res->texAnim->unk_00[SPLRandom_U32(12) % res->texAnim->unk_08.unk_00_0];
ptcl->misc.unk_00 = res->texAnim->unk_00[SPLRandom_U32(12) % res->texAnim->unk_08.unk_00_0];
} else if (resBase->flags.hasTexAnim && !res->texAnim->unk_08.unk_02_0) {
ptcl->unk_2C.unk_00 = res->texAnim->unk_00[0];
ptcl->misc.unk_00 = res->texAnim->unk_00[0];
} else {
ptcl->unk_2C.unk_00 = resBase->unk_48.unk_03_0;
ptcl->misc.unk_00 = resBase->misc.unk_03_0;
}
ptcl->unk_28 = 0xFFFF / res->header->unk_48.unk_04_0;
ptcl->unk_2A = 0xFFFF / ptcl->lifeTime;
ptcl->loopTimeFactor = 0xFFFF / res->header->misc.unk_04_0;
ptcl->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
ptcl->unk_2C.unk_01 = 0;
ptcl->misc.lifeRateOffset = 0;
if (resBase->flags.unk_06_4) {
ptcl->unk_2C.unk_01 = (u8)SPLRandom_S32(8);
ptcl->misc.lifeRateOffset = (u8)SPLRandom_S32(8);
}
i++;
} while (i < curGenNum);
@ -296,7 +296,7 @@ void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list)
SPLChildResource *chldRes = emtr->resource->childResource;
fx32 vel = FX_MUL((fx32)(chldRes->unk_08.unk_00_0 << FX32_SHIFT), FX32_CONST(1 / 256.0f));
for (i = 0; i < chldRes->unk_0C.unk_00_0; i++) {
for (i = 0; i < chldRes->misc.unk_00_0; i++) {
chld = (SPLParticle *)SPLList_PopFront(list);
if (chld == NULL) {
return;
@ -327,7 +327,7 @@ void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list)
chld->unk_34 = FX32_ONE;
if (chldRes->unk_00.unk_02_6) {
if (chldRes->flags.unk_02_6) {
chld->unk_36 = chldRes->unk_0A;
} else {
chld->unk_36 = ptcl->unk_36;
@ -336,27 +336,27 @@ void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list)
chld->unk_2E.unk_00_0 = (ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1)) >> 5;
chld->unk_2E.unk_00_5 = 31;
switch (chldRes->unk_00.unk_02_3) {
switch (chldRes->flags.unk_02_3) {
case 0:
chld->unk_20 = 0;
chld->unk_22 = 0;
chld->rotation = 0;
chld->angularVelocity = 0;
break;
case 1:
chld->unk_20 = ptcl->unk_20;
chld->unk_22 = 0;
chld->rotation = ptcl->rotation;
chld->angularVelocity = 0;
break;
case 2:
chld->unk_20 = ptcl->unk_20;
chld->unk_22 = ptcl->unk_22;
chld->rotation = ptcl->rotation;
chld->angularVelocity = ptcl->angularVelocity;
break;
}
chld->lifeTime = chldRes->unk_06;
chld->age = 0;
chld->unk_2C.unk_00 = chldRes->unk_0C.unk_03_0;
chld->misc.unk_00 = chldRes->misc.unk_03_0;
chld->unk_28 = 0xFFFF / (ptcl->lifeTime / 2);
chld->unk_2A = 0xFFFF / ptcl->lifeTime;
chld->unk_2C.unk_01 = 0;
chld->loopTimeFactor = 0xFFFF / (ptcl->lifeTime / 2);
chld->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
chld->misc.lifeRateOffset = 0;
}
}

View File

@ -116,7 +116,7 @@ void sub_020A1A94(SPLParticle *ptcl, SPLResource *res, int lifeRate)
SPLTexAnim *texAnim = res->texAnim;
for (int i = 0; i < texAnim->unk_08.unk_00_0; i++) {
if (lifeRate < texAnim->unk_08.unk_01_0 * (i + 1)) {
ptcl->unk_2C.unk_00 = texAnim->unk_00[i];
ptcl->misc.unk_00 = texAnim->unk_00[i];
return;
}
}