Document SPLEmitter_EmitChildren

This commit is contained in:
Fexty12573 2024-08-02 16:09:08 +02:00
parent 616005990d
commit d79dad4c74
8 changed files with 96 additions and 97 deletions

View File

@ -37,7 +37,7 @@ void sub_020A1A48(SPLParticle *ptcl, SPLResource *res, int lifeRate); // spl_chl
void sub_020A19F0(SPLParticle *ptcl, SPLResource *res, int lifeRate); // spl_chld_alp_out
void SPLEmitter_EmitParticles(SPLEmitter *emtr, SPLParticleList *list);
void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list);
void SPLEmitter_EmitChildren(SPLParticle *ptcl, SPLEmitter *emtr, SPLParticleList *list);
void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr);
void SPLManager_DoDraw(SPLManager *mgr);

View File

@ -35,7 +35,7 @@ typedef struct SPLParticle {
u16 currentPolygonID : 6;
} visibility;
fx32 baseScale;
fx16 unk_34;
fx16 animScale;
GXRgb color;
VecFx32 emitterPos;
} SPLParticle; // size=0x44

View File

@ -27,6 +27,12 @@ enum SPLEmissionType {
SPL_EMISSION_TYPE_HEMISPHERE, // Any point inside a hemisphere (direction specified by flags)
};
enum SPLChildRotationType {
SPL_CHILD_ROT_NONE = 0,
SPL_CHILD_ROT_INHERIT_ANGLE = 1,
SPL_CHILD_ROT_INHERIT_ANGLE_AND_VELOCITY = 2,
};
typedef struct SPLArcHdr {
u32 magic;
u32 version;
@ -80,9 +86,9 @@ typedef union SPLChildResourceFlags {
u16 usesBehaviors : 1;
u16 hasScaleAnim : 1;
u16 hasAlphaAnim : 1;
u16 unk_02_3 : 2;
u16 rotationType : 2;
u16 followEmitter : 1;
u16 unk_02_6 : 1;
u16 useChildColor : 1;
u16 drawType : 2;
u16 unk_03_1 : 2;
u16 unk_03_3 : 1;
@ -219,16 +225,14 @@ typedef struct SPLTexAnim {
typedef struct SPLChildResource {
SPLChildResourceFlags flags;
fx16 unk_02;
fx16 randomInitVelMag; // Randomization factor for the initial velocity magnitude (0 = no randomization)
fx16 unk_04;
u16 unk_06;
u16 lifeTime;
u8 velocityRatio; // Ratio of the parent particle's velocity to inherit (255 = 100%)
u8 scaleRatio; // Ratio of the parent particle's scale to inherit (255 = 100%)
GXRgb color;
struct {
u16 unk_00_0 : 8;
u16 unk_01_0 : 8;
} unk_08;
GXRgb unk_0A;
struct {
u32 unk_00_0 : 8;
u32 emissionCount : 8; // Number of particles to emit per emission interval
u32 emissionDelay : 8; // Delay, as a fraction of the particle's lifetime, before the particle starts emitting
u32 emissionInterval : 8;
u32 textureIndex : 8;

View File

@ -18,7 +18,7 @@ libspl_srcs = files(
'src/spl_manager.c',
'src/spl_emitter.c',
'src/unk_0209DD54.c',
'src/unk_020A05BC.c',
'src/spl_emit.c',
'src/unk_020A19F0.c',
'src/spl_behavior.c',
'src/spl_list.c',

View File

@ -235,7 +235,7 @@ void SPLEmitter_EmitParticles(SPLEmitter *emtr, SPLParticleList *list)
ptcl->emitterPos = emtr->position;
ptcl->baseScale = SPLRandom_DoubleScaledRangeFX32(emtr->baseScale, header->randomAttenuation.baseScale);
ptcl->unk_34 = FX32_ONE;
ptcl->animScale = FX32_ONE;
if (header->flags.hasColorAnim && res->colorAnim->unk_08.unk_00_0) {
u16 clr[3];
@ -285,76 +285,71 @@ void SPLEmitter_EmitParticles(SPLEmitter *emtr, SPLParticleList *list)
}
}
void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list)
void SPLEmitter_EmitChildren(SPLParticle *ptcl, SPLEmitter *emtr, SPLParticleList *list)
{
SPLParticle *chld;
fx32 velBase, velRand;
u32 rng;
int i;
SPLChildResource *chldRes = emtr->resource->childResource;
fx32 vel = FX_MUL((fx32)(chldRes->unk_08.unk_00_0 << FX32_SHIFT), FX32_CONST(1 / 256.0f));
SPLParticle *child;
for (i = 0; i < chldRes->misc.unk_00_0; i++) {
chld = (SPLParticle *)SPLList_PopFront(list);
if (chld == NULL) {
SPLChildResource *childRes = emtr->resource->childResource;
fx32 velRatio = FX_MUL(childRes->velocityRatio * FX32_ONE, FX32_CONST(1 / 256.0f));
for (int i = 0; i < childRes->misc.emissionCount; i++) {
child = (SPLParticle *)SPLList_PopFront((SPLList *)list); // SPLParticleList_PopFront doesn't match here for some reason
if (child == NULL) {
return;
}
SPLList_PushFront((SPLList *)&emtr->childParticles, (SPLNode *)chld);
chld->position = ptcl->position;
SPLParticleList_PushFront(&emtr->childParticles, child);
velBase = FX_MUL(ptcl->velocity.x, vel);
velRand = SPLRandom_RangeFX32(chldRes->unk_02);
chld->velocity.x = velBase + velRand;
child->position = ptcl->position;
velBase = FX_MUL(ptcl->velocity.y, vel);
velRand = SPLRandom_RangeFX32(chldRes->unk_02);
chld->velocity.y = velBase + velRand;
fx32 velBase = FX_MUL(ptcl->velocity.x, velRatio);
fx32 velRand = SPLRandom_RangeFX32(childRes->randomInitVelMag);
child->velocity.x = velBase + velRand;
velBase = FX_MUL(ptcl->velocity.z, vel);
velRand = SPLRandom_RangeFX32(chldRes->unk_02);
chld->velocity.z = velBase + velRand;
velBase = FX_MUL(ptcl->velocity.y, velRatio);
velRand = SPLRandom_RangeFX32(childRes->randomInitVelMag);
child->velocity.y = velBase + velRand;
chld->emitterPos = ptcl->emitterPos;
velBase = FX_MUL(ptcl->velocity.z, velRatio);
velRand = SPLRandom_RangeFX32(childRes->randomInitVelMag);
child->velocity.z = velBase + velRand;
// `unk_08.unk_00_0` and `unk_08.unk_01_0` in `UnkSPLStruct14`
// could just be `u8 unk_08;` and `u8 unk_09;`
// instead of an inner struct
int idk = ptcl->baseScale * ptcl->unk_34 >> FX32_SHIFT;
chld->baseScale = idk * (chldRes->unk_08.unk_01_0 + 1) >> 6;
child->emitterPos = ptcl->emitterPos;
chld->unk_34 = FX32_ONE;
fx32 parentScale = ptcl->baseScale * ptcl->animScale >> FX32_SHIFT;
child->baseScale = parentScale * (childRes->scaleRatio + 1) >> 6;
child->animScale = FX32_ONE;
if (chldRes->flags.unk_02_6) {
chld->color = chldRes->unk_0A;
if (childRes->flags.useChildColor) {
child->color = childRes->color;
} else {
chld->color = ptcl->color;
child->color = ptcl->color;
}
chld->visibility.baseAlpha = (ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
chld->visibility.animAlpha = 31;
child->visibility.baseAlpha = (ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
child->visibility.animAlpha = 31;
switch (chldRes->flags.unk_02_3) {
case 0:
chld->rotation = 0;
chld->angularVelocity = 0;
switch (childRes->flags.rotationType) {
case SPL_CHILD_ROT_NONE:
child->rotation = 0;
child->angularVelocity = 0;
break;
case 1:
chld->rotation = ptcl->rotation;
chld->angularVelocity = 0;
case SPL_CHILD_ROT_INHERIT_ANGLE:
child->rotation = ptcl->rotation;
child->angularVelocity = 0;
break;
case 2:
chld->rotation = ptcl->rotation;
chld->angularVelocity = ptcl->angularVelocity;
case SPL_CHILD_ROT_INHERIT_ANGLE_AND_VELOCITY:
child->rotation = ptcl->rotation;
child->angularVelocity = ptcl->angularVelocity;
break;
}
chld->lifeTime = chldRes->unk_06;
chld->age = 0;
chld->misc.texture = chldRes->misc.textureIndex;
child->lifeTime = childRes->lifeTime;
child->age = 0;
child->misc.texture = childRes->misc.textureIndex;
chld->loopTimeFactor = 0xFFFF / (ptcl->lifeTime / 2);
chld->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
chld->misc.lifeRateOffset = 0;
child->loopTimeFactor = 0xFFFF / (ptcl->lifeTime / 2);
child->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
child->misc.lifeRateOffset = 0;
}
}

View File

@ -225,7 +225,7 @@ void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr)
if (diff >= 0) {
if ((diff >> FX32_SHIFT) % child->misc.emissionInterval == 0) {
sub_020A05BC(ptcl, emtr, (SPLList *)&mgr->inactiveParticles);
SPLEmitter_EmitChildren(ptcl, emtr, &mgr->inactiveParticles);
}
}
}

View File

@ -133,7 +133,7 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
cmr = mgr->renderState.viewMatrix;
aspect = mgr->renderState.emitter->resource->header->unk_30;
animScale = ptcl->unk_34;
animScale = ptcl->animScale;
ptclCol = ptcl->color;
emtrCol = emtr->color;
@ -261,16 +261,16 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
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);
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case 1:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case 2:
sclY = FX_MUL(sclY, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
}
@ -372,16 +372,16 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
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);
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case 1:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case 2:
sclY = FX_MUL(sclY, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
}
@ -527,16 +527,16 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
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);
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case 1:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case 2:
sclY = FX_MUL(sclY, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
}
@ -680,16 +680,16 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
switch (resBase->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case 1:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case 2:
sclY = FX_MUL(sclY, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
}
@ -763,16 +763,16 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
switch (resBase->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case 1:
sclX = FX_MUL(sclX, ptcl->unk_34);
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case 2:
sclY = FX_MUL(sclY, ptcl->unk_34);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
}
@ -881,16 +881,16 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
switch (resBase->misc.unk_07_4) {
case 0:
scaleX = FX_MUL(scaleX, ptcl->unk_34);
scaleY = FX_MUL(scaleY, ptcl->unk_34);
scaleX = FX_MUL(scaleX, ptcl->animScale);
scaleY = FX_MUL(scaleY, ptcl->animScale);
break;
case 1:
scaleX = FX_MUL(scaleX, ptcl->unk_34);
scaleX = FX_MUL(scaleX, ptcl->animScale);
break;
case 2:
scaleY = FX_MUL(scaleY, ptcl->unk_34);
scaleY = FX_MUL(scaleY, ptcl->animScale);
break;
}
@ -999,16 +999,16 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
switch (resBase->misc.unk_07_4) {
case 0:
scaleX = FX_MUL(scaleX, ptcl->unk_34);
scaleY = FX_MUL(scaleY, ptcl->unk_34);
scaleX = FX_MUL(scaleX, ptcl->animScale);
scaleY = FX_MUL(scaleY, ptcl->animScale);
break;
case 1:
scaleX = FX_MUL(scaleX, ptcl->unk_34);
scaleX = FX_MUL(scaleX, ptcl->animScale);
break;
case 2:
scaleY = FX_MUL(scaleY, ptcl->unk_34);
scaleY = FX_MUL(scaleY, ptcl->animScale);
break;
}

View File

@ -18,13 +18,13 @@ void sub_020A1DA0(SPLParticle *ptcl, SPLResource *res, int lifeRate)
if (lifeRate < in) {
start = scaleAnim->unk_00;
n = scaleAnim->unk_02;
ptcl->unk_34 = start + ((lifeRate * (n - start)) / in);
ptcl->animScale = start + ((lifeRate * (n - start)) / in);
} else if (lifeRate >= out) {
end = scaleAnim->unk_04;
n = scaleAnim->unk_02;
ptcl->unk_34 = end + (((lifeRate - 255) * (end - n)) / (255 - out));
ptcl->animScale = end + (((lifeRate - 255) * (end - n)) / (255 - out));
} else {
ptcl->unk_34 = scaleAnim->unk_02;
ptcl->animScale = scaleAnim->unk_02;
}
}
@ -124,7 +124,7 @@ void sub_020A1A94(SPLParticle *ptcl, SPLResource *res, int lifeRate)
void sub_020A1A48(SPLParticle *ptcl, SPLResource *res, int lifeRate)
{
ptcl->unk_34 = res->childResource->unk_04 + ((res->childResource->unk_04 - FX16_ONE) * (lifeRate - 255)) / 255;
ptcl->animScale = res->childResource->unk_04 + ((res->childResource->unk_04 - FX16_ONE) * (lifeRate - 255)) / 255;
}
void sub_020A19F0(SPLParticle *ptcl, SPLResource *res, int lifeRate)