mirror of
https://github.com/pret/pokeplatinum.git
synced 2024-11-23 05:49:44 +00:00
Document SPLEmitter_EmitParticles
This commit is contained in:
parent
98ca0c745a
commit
616005990d
@ -39,17 +39,17 @@ typedef struct SPLEmitter {
|
||||
UnkSPLStruct7 state;
|
||||
VecFx32 position;
|
||||
VecFx32 velocity;
|
||||
VecFx32 unk_B0;
|
||||
VecFx32 particleInitVelocity;
|
||||
u16 age;
|
||||
fx16 unk_BE;
|
||||
fx16 emissionCountFractional; // fractional part of the number of particles to emit (doesn't seem to be used)
|
||||
VecFx16 axis;
|
||||
u16 unk_C6;
|
||||
fx32 unk_C8;
|
||||
fx32 unk_CC;
|
||||
fx32 emissionCount;
|
||||
fx32 radius;
|
||||
fx32 length;
|
||||
fx32 unk_D4;
|
||||
fx32 unk_D8;
|
||||
fx32 unk_DC;
|
||||
fx32 initVelPositionAmplifier; // amplifies the initial velocity of the particles based on their position
|
||||
fx32 initVelAxisAmplifier; // amplifies the initial velocity of the particles based on the emitter's axis
|
||||
fx32 baseScale; // base scale of the particles
|
||||
u16 particleLifeTime;
|
||||
GXRgb color;
|
||||
fx32 collisionPlaneHeight;
|
||||
@ -59,12 +59,12 @@ typedef struct SPLEmitter {
|
||||
fx16 unk_EE;
|
||||
struct {
|
||||
u32 emissionInterval : 8; // number of frames between particle emissions
|
||||
u32 unk_01_0 : 8;
|
||||
u32 baseAlpha : 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;
|
||||
VecFx16 crossAxis1;
|
||||
VecFx16 crossAxis2;
|
||||
SPLEmitterUpdateCallback updateCallback;
|
||||
void * unk_104;
|
||||
union {
|
||||
|
@ -36,13 +36,13 @@ void sub_020A1A94(SPLParticle *ptcl, SPLResource *res, int lifeRate); // spl_tex
|
||||
void sub_020A1A48(SPLParticle *ptcl, SPLResource *res, int lifeRate); // spl_chld_scl_out
|
||||
void sub_020A19F0(SPLParticle *ptcl, SPLResource *res, int lifeRate); // spl_chld_alp_out
|
||||
|
||||
void sub_020A08DC(SPLEmitter *emtr, SPLList *list);
|
||||
void SPLEmitter_EmitParticles(SPLEmitter *emtr, SPLParticleList *list);
|
||||
void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list);
|
||||
|
||||
void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr);
|
||||
void SPLManager_DoDraw(SPLManager *mgr);
|
||||
void SPLEmitter_Init(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos);
|
||||
void SPLEmitter_Emit(SPLEmitter *emtr, SPLList *list);
|
||||
void SPLEmitter_Emit(SPLEmitter *emtr, SPLParticleList *list);
|
||||
|
||||
static inline void SPLParticleList_PushFront(SPLParticleList *list, SPLParticle *ptcl)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
typedef struct SPLParticle {
|
||||
struct SPLParticle *next;
|
||||
struct SPLParticle *prev;
|
||||
VecFx32 position;
|
||||
VecFx32 position; // position of the particle, relative to the emitter
|
||||
VecFx32 velocity;
|
||||
u16 rotation;
|
||||
s16 angularVelocity;
|
||||
@ -22,7 +22,7 @@ typedef struct SPLParticle {
|
||||
u16 lifeTimeFactor;
|
||||
|
||||
struct {
|
||||
u16 unk_00 : 8;
|
||||
u16 texture : 8; // Index of the current texture in the resource
|
||||
|
||||
// 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
|
||||
@ -30,13 +30,13 @@ typedef struct SPLParticle {
|
||||
u16 lifeRateOffset : 8;
|
||||
} misc;
|
||||
struct {
|
||||
u16 unk_00_0 : 5;
|
||||
u16 unk_00_5 : 5;
|
||||
u16 baseAlpha : 5;
|
||||
u16 animAlpha : 5;
|
||||
u16 currentPolygonID : 6;
|
||||
} unk_2E;
|
||||
fx32 unk_30;
|
||||
} visibility;
|
||||
fx32 baseScale;
|
||||
fx16 unk_34;
|
||||
GXRgb unk_36;
|
||||
GXRgb color;
|
||||
VecFx32 emitterPos;
|
||||
} SPLParticle; // size=0x44
|
||||
|
||||
|
@ -5,6 +5,27 @@
|
||||
|
||||
#include "struct_defs/struct_020147B8.h"
|
||||
|
||||
#define SPL_TEX_ANIM_MAX_FRAMES 8
|
||||
|
||||
enum SPLCircleAxis {
|
||||
SPL_CIRCLE_AXIS_Z = 0,
|
||||
SPL_CIRCLE_AXIS_Y = 1,
|
||||
SPL_CIRCLE_AXIS_X = 2,
|
||||
SPL_CIRCLE_AXIS_EMITTER = 3, // The emitter's axis
|
||||
};
|
||||
|
||||
enum SPLEmissionType {
|
||||
SPL_EMISSION_TYPE_POINT = 0, // A single point
|
||||
SPL_EMISSION_TYPE_SPHERE_SURFACE, // Any point on the surface of a sphere
|
||||
SPL_EMISSION_TYPE_CIRCLE_BORDER, // Any point on a circle around an axis (specified by flags)
|
||||
SPL_EMISSION_TYPE_CIRCLE_BORDER_UNIFORM, // Uniform distribution of points on a circle around an axis (specified by flags)
|
||||
SPL_EMISSION_TYPE_SPHERE, // Any point inside a sphere
|
||||
SPL_EMISSION_TYPE_CIRCLE, // Any point inside a circle around an axis (specified by flags)
|
||||
SPL_EMISSION_TYPE_CYLINDER_SURFACE, // Any point on the surface of a cylinder
|
||||
SPL_EMISSION_TYPE_CYLINDER, // Any point inside a cylinder
|
||||
SPL_EMISSION_TYPE_HEMISPHERE_SURFACE, // Any point on the surface of a hemisphere (direction specified by flags)
|
||||
SPL_EMISSION_TYPE_HEMISPHERE, // Any point inside a hemisphere (direction specified by flags)
|
||||
};
|
||||
|
||||
typedef struct SPLArcHdr {
|
||||
u32 magic;
|
||||
@ -21,14 +42,14 @@ typedef struct SPLArcHdr {
|
||||
typedef union SPLResourceFlags {
|
||||
u32 all;
|
||||
struct {
|
||||
u32 unk_04_0 : 4;
|
||||
u32 emissionType : 4; // Maps to SPLEmissionType
|
||||
u32 drawType : 2;
|
||||
u32 unk_04_6 : 2;
|
||||
u32 circleAxis : 2; // Maps to SPLCircleAxis
|
||||
u32 hasScaleAnim : 1;
|
||||
u32 hasColorAnim : 1;
|
||||
u32 hasAlphaAnim : 1;
|
||||
u32 hasTexAnim : 1;
|
||||
u32 unk_05_4 : 1;
|
||||
u32 hasRotation : 1;
|
||||
u32 unk_05_5 : 1;
|
||||
// Whether the emitter manages itself or not.
|
||||
// If set, the emitter will automatically terminate when it reaches the end of its life
|
||||
@ -38,7 +59,7 @@ typedef union SPLResourceFlags {
|
||||
u32 hasChildResource : 1;
|
||||
u32 unk_06_1 : 2;
|
||||
u32 unk_06_3 : 1;
|
||||
u32 unk_06_4 : 1;
|
||||
u32 randomizeLoopedAnim : 1;
|
||||
u32 drawChildrenFirst : 1; // If set, child particles will be rendered before parent particles
|
||||
u32 hideParent : 1; // If set, only child particles will be rendered
|
||||
u32 unk_06_7 : 1;
|
||||
@ -90,35 +111,39 @@ typedef union {
|
||||
typedef struct SPLResourceHeader {
|
||||
SPLResourceFlags flags;
|
||||
VecFx32 emitterBasePos;
|
||||
fx32 unk_10;
|
||||
fx32 emissionCount; // Number of particles to emit per emission interval
|
||||
fx32 unk_14;
|
||||
fx32 unk_18;
|
||||
VecFx16 unk_1C;
|
||||
GXRgb unk_22;
|
||||
GXRgb color;
|
||||
fx32 unk_24;
|
||||
fx32 unk_28;
|
||||
fx32 unk_2C;
|
||||
fx16 unk_30;
|
||||
u16 startDelay; // Delay, in frames, before the emitter starts emitting particles
|
||||
s16 unk_34;
|
||||
s16 unk_36;
|
||||
s16 minRotation;
|
||||
s16 maxRotation;
|
||||
u16 unk_38;
|
||||
u16 reserved_3A;
|
||||
u16 emitterLifeTime;
|
||||
u16 particleLifeTime;
|
||||
|
||||
// All of these values are mapped to the range [0, 1]
|
||||
// They are used to attenuate the particle's properties at initialization,
|
||||
// acting as a sort of randomization factor which scales down the initial values
|
||||
struct {
|
||||
u32 unk_00_0 : 8;
|
||||
u32 unk_01_0 : 8;
|
||||
u32 unk_02_0 : 8;
|
||||
u32 reserved_03_0 : 8;
|
||||
} unk_44;
|
||||
u32 baseScale : 8; // Damping factor for the base scale of the particles (0 = no damping)
|
||||
u32 lifeTime : 8;
|
||||
u32 initVel : 8; // Attenuation factor for the initial velocity of the particles (0 = no attenuation)
|
||||
u32 : 8;
|
||||
} randomAttenuation;
|
||||
|
||||
struct {
|
||||
u32 unk_00_0 : 8;
|
||||
u32 unk_01_0 : 8;
|
||||
u32 airResistance : 8;
|
||||
u32 textureIndex : 8;
|
||||
u32 unk_04_0 : 8;
|
||||
u32 loopFrames : 8;
|
||||
u32 unk_05_0 : 16;
|
||||
u32 unk_07_0 : 2;
|
||||
u32 unk_07_2 : 2;
|
||||
@ -150,8 +175,8 @@ typedef struct SPLScaleAnim {
|
||||
} SPLScaleAnim; // size=0xc
|
||||
|
||||
typedef struct SPLColorAnim {
|
||||
GXRgb unk_00;
|
||||
GXRgb unk_02;
|
||||
GXRgb startColor;
|
||||
GXRgb endColor;
|
||||
UnkSPLUnion4 unk_04;
|
||||
struct {
|
||||
u16 unk_00_0 : 1;
|
||||
@ -182,14 +207,14 @@ typedef struct SPLAlphaAnim {
|
||||
} SPLAlphaAnim; // size=0x8
|
||||
|
||||
typedef struct SPLTexAnim {
|
||||
u8 unk_00[8];
|
||||
u8 textures[SPL_TEX_ANIM_MAX_FRAMES];
|
||||
struct {
|
||||
u32 unk_00_0 : 8;
|
||||
u32 frameCount : 8;
|
||||
u32 unk_01_0 : 8;
|
||||
u32 unk_02_0 : 1;
|
||||
u32 randomizeInit : 1; // Randomize the initial texture frame
|
||||
u32 unk_02_1 : 1;
|
||||
u32 reserved_02_2 : 14;
|
||||
} unk_08;
|
||||
} param;
|
||||
} SPLTexAnim;
|
||||
|
||||
typedef struct SPLChildResource {
|
||||
|
@ -68,27 +68,27 @@ void SPLEmitter_Init(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos)
|
||||
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->particleInitVelocity.x = 0;
|
||||
emtr->particleInitVelocity.y = 0;
|
||||
emtr->particleInitVelocity.z = 0;
|
||||
emtr->velocity.x = emtr->velocity.y = emtr->velocity.z = 0;
|
||||
|
||||
emtr->age = 0;
|
||||
emtr->unk_BE = 0;
|
||||
emtr->emissionCountFractional = 0;
|
||||
|
||||
emtr->axis = emtr->resource->header->unk_1C;
|
||||
emtr->unk_C6 = emtr->resource->header->unk_38;
|
||||
emtr->unk_C8 = emtr->resource->header->unk_10;
|
||||
emtr->unk_CC = emtr->resource->header->unk_14;
|
||||
emtr->emissionCount = emtr->resource->header->emissionCount;
|
||||
emtr->radius = emtr->resource->header->unk_14;
|
||||
emtr->length = emtr->resource->header->unk_18;
|
||||
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->initVelPositionAmplifier = emtr->resource->header->unk_24;
|
||||
emtr->initVelAxisAmplifier = emtr->resource->header->unk_28;
|
||||
emtr->baseScale = emtr->resource->header->unk_2C;
|
||||
emtr->particleLifeTime = emtr->resource->header->particleLifeTime;
|
||||
|
||||
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.baseAlpha = emtr->resource->header->misc.unk_01_0;
|
||||
emtr->misc.updateCycle = 0;
|
||||
emtr->misc.unk_02_3 = 0;
|
||||
emtr->collisionPlaneHeight = FX32_MIN;
|
||||
@ -154,7 +154,7 @@ void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr)
|
||||
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));
|
||||
SPLEmitter_EmitParticles(emtr, &mgr->inactiveParticles);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,9 +174,9 @@ void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr)
|
||||
animFuncs[animCount++].loop = res->alphaAnim->unk_02.unk_01_0;
|
||||
}
|
||||
|
||||
if (resFlags.hasTexAnim && !res->texAnim->unk_08.unk_02_0) { // TexAnim
|
||||
if (resFlags.hasTexAnim && !res->texAnim->param.randomizeInit) { // TexAnim
|
||||
animFuncs[animCount].func = sub_020A1A94;
|
||||
animFuncs[animCount++].loop = res->texAnim->unk_08.unk_02_1;
|
||||
animFuncs[animCount++].loop = res->texAnim->param.unk_02_1;
|
||||
}
|
||||
|
||||
for (ptcl = emtr->particles.first; ptcl != NULL; ptcl = next) {
|
||||
@ -231,9 +231,9 @@ void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr)
|
||||
}
|
||||
|
||||
if (emtr->resource->header->flags.hasFixedPolygonID) {
|
||||
ptcl->unk_2E.currentPolygonID = mgr->polygonID.fix;
|
||||
ptcl->visibility.currentPolygonID = mgr->polygonID.fix;
|
||||
} else {
|
||||
ptcl->unk_2E.currentPolygonID = mgr->polygonID.current;
|
||||
ptcl->visibility.currentPolygonID = mgr->polygonID.current;
|
||||
mgr->polygonID.current += 1;
|
||||
|
||||
if (mgr->polygonID.current > mgr->polygonID.max) {
|
||||
@ -300,9 +300,9 @@ void SPLEmitter_Update(SPLManager *mgr, SPLEmitter *emtr)
|
||||
ptcl->position.z += ptcl->velocity.z + emtr->velocity.z;
|
||||
|
||||
if (emtr->resource->header->flags.childHasFixedPolygonID) {
|
||||
ptcl->unk_2E.currentPolygonID = mgr->polygonID.fix;
|
||||
ptcl->visibility.currentPolygonID = mgr->polygonID.fix;
|
||||
} else {
|
||||
ptcl->unk_2E.currentPolygonID = mgr->polygonID.current;
|
||||
ptcl->visibility.currentPolygonID = mgr->polygonID.current;
|
||||
mgr->polygonID.current += 1;
|
||||
|
||||
if (mgr->polygonID.current > mgr->polygonID.max) {
|
||||
@ -355,7 +355,7 @@ static void SPLManager_DrawParticles(SPLManager *mgr)
|
||||
SetTexFunc setTexFunc = header->flags.hasTexAnim ? SPLUtil_SetTexture : SPLUtil_SetTexture_Stub;
|
||||
|
||||
for (SPLParticle *ptcl = emtr->particles.first; ptcl != NULL; ptcl = ptcl->next) {
|
||||
setTexFunc(mgr->textures + ptcl->misc.unk_00);
|
||||
setTexFunc(mgr->textures + ptcl->misc.texture);
|
||||
drawFunc(mgr, ptcl);
|
||||
}
|
||||
}
|
||||
@ -414,16 +414,16 @@ void SPLManager_DoDraw(SPLManager *mgr)
|
||||
}
|
||||
}
|
||||
|
||||
void SPLEmitter_Emit(SPLEmitter *emtr, SPLList *list)
|
||||
void SPLEmitter_Emit(SPLEmitter *emtr, SPLParticleList *list)
|
||||
{
|
||||
sub_020A08DC(emtr, list);
|
||||
SPLEmitter_EmitParticles(emtr, list);
|
||||
}
|
||||
|
||||
void SPLUtil_SetCylinderEmitterDir(SPLEmitter *emtr, VecFx32 *p1, VecFx32 *p2)
|
||||
{
|
||||
VecFx32 vex;
|
||||
|
||||
if (emtr->resource->header->flags.unk_04_0 == 6 || emtr->resource->header->flags.unk_04_0 == 7) {
|
||||
if (emtr->resource->header->flags.emissionType == 6 || emtr->resource->header->flags.emissionType == 7) {
|
||||
emtr->position.x = (p2->x + p1->x) / 2;
|
||||
emtr->position.y = (p2->y + p1->y) / 2;
|
||||
emtr->position.z = (p2->z + p1->z) / 2;
|
||||
|
@ -426,7 +426,7 @@ void SPLManager_DeleteAllEmitters(SPLManager *mgr)
|
||||
|
||||
void SPL_Emit(SPLManager *mgr, SPLEmitter *emtr)
|
||||
{
|
||||
SPLEmitter_Emit(emtr, (SPLList *)&mgr->inactiveParticles);
|
||||
SPLEmitter_Emit(emtr, &mgr->inactiveParticles);
|
||||
}
|
||||
|
||||
void SPL_EmitAt(SPLManager *mgr, SPLEmitter *emtr, VecFx32 *pos)
|
||||
@ -434,5 +434,5 @@ void SPL_EmitAt(SPLManager *mgr, SPLEmitter *emtr, VecFx32 *pos)
|
||||
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;
|
||||
SPLEmitter_Emit(emtr, (SPLList *)&mgr->inactiveParticles);
|
||||
SPLEmitter_Emit(emtr, &mgr->inactiveParticles);
|
||||
}
|
||||
|
@ -135,18 +135,18 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
|
||||
aspect = mgr->renderState.emitter->resource->header->unk_30;
|
||||
animScale = ptcl->unk_34;
|
||||
|
||||
ptclCol = ptcl->unk_36;
|
||||
ptclCol = ptcl->color;
|
||||
emtrCol = emtr->color;
|
||||
|
||||
scaleAnimDirect = resBase->misc.unk_07_4;
|
||||
|
||||
fx32 alpha = ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1) >> 5;
|
||||
fx32 alpha = ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -156,7 +156,7 @@ void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
|
||||
return;
|
||||
}
|
||||
|
||||
sclY = ptcl->unk_30;
|
||||
sclY = ptcl->baseScale;
|
||||
sclX = FX_MUL(sclY, aspect);
|
||||
|
||||
if (scaleAnimDirect == 0) {
|
||||
@ -240,13 +240,13 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
|
||||
cmr = mgr->renderState.viewMatrix;
|
||||
aspect = mgr->renderState.emitter->resource->header->unk_30;
|
||||
|
||||
fx32 alpha = (fx32)(ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1)) >> 5;
|
||||
fx32 alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -256,7 +256,7 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
|
||||
return;
|
||||
}
|
||||
|
||||
sclY = ptcl->unk_30;
|
||||
sclY = ptcl->baseScale;
|
||||
sclX = FX_MUL(sclY, aspect);
|
||||
|
||||
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
|
||||
@ -325,7 +325,7 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&load);
|
||||
}
|
||||
|
||||
GXRgb colA = ptcl->unk_36;
|
||||
GXRgb colA = ptcl->color;
|
||||
GXRgb colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
@ -351,13 +351,13 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
cmr = mgr->renderState.viewMatrix;
|
||||
aspect = mgr->renderState.emitter->resource->header->unk_30;
|
||||
|
||||
fx32 alpha = (fx32)(ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1)) >> 5;
|
||||
fx32 alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -367,7 +367,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
return;
|
||||
}
|
||||
|
||||
sclY = ptcl->unk_30;
|
||||
sclY = ptcl->baseScale;
|
||||
sclX = FX_MUL(sclY, aspect);
|
||||
|
||||
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
|
||||
@ -480,7 +480,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&load);
|
||||
}
|
||||
|
||||
GXRgb colA = ptcl->unk_36;
|
||||
GXRgb colA = ptcl->color;
|
||||
GXRgb colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
@ -506,13 +506,13 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
cmr = mgr->renderState.viewMatrix;
|
||||
aspect = mgr->renderState.emitter->resource->header->unk_30;
|
||||
|
||||
fx32 alpha = (fx32)(ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1)) >> 5;
|
||||
fx32 alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -522,7 +522,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
return;
|
||||
}
|
||||
|
||||
sclY = ptcl->unk_30;
|
||||
sclY = ptcl->baseScale;
|
||||
sclX = FX_MUL(sclY, aspect);
|
||||
|
||||
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
|
||||
@ -635,7 +635,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&load);
|
||||
}
|
||||
|
||||
GXRgb colA = ptcl->unk_36;
|
||||
GXRgb colA = ptcl->color;
|
||||
GXRgb colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
@ -656,13 +656,13 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
fx32 alpha;
|
||||
SPLResourceHeader *resBase;
|
||||
|
||||
alpha = (fx32)(ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1)) >> 5;
|
||||
alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -674,7 +674,7 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
|
||||
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
|
||||
|
||||
sclY = ptcl->unk_30;
|
||||
sclY = ptcl->baseScale;
|
||||
resBase = mgr->renderState.emitter->resource->header;
|
||||
sclX = FX_MUL(sclY, resBase->unk_30);
|
||||
|
||||
@ -717,7 +717,7 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&load);
|
||||
}
|
||||
|
||||
GXRgb colA = ptcl->unk_36;
|
||||
GXRgb colA = ptcl->color;
|
||||
GXRgb colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
@ -739,13 +739,13 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
|
||||
fx32 alpha;
|
||||
SPLResourceHeader *resBase;
|
||||
|
||||
alpha = ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1) >> 5;
|
||||
alpha = ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -757,7 +757,7 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
|
||||
|
||||
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
|
||||
|
||||
sclY = ptcl->unk_30;
|
||||
sclY = ptcl->baseScale;
|
||||
resBase = mgr->renderState.emitter->resource->header;
|
||||
sclX = FX_MUL(sclY, resBase->unk_30);
|
||||
|
||||
@ -798,7 +798,7 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&load);
|
||||
}
|
||||
|
||||
GXRgb colA = ptcl->unk_36;
|
||||
GXRgb colA = ptcl->color;
|
||||
GXRgb colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
@ -821,13 +821,13 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
|
||||
SPLEmitter *emtr;
|
||||
GXRgb colA, colB;
|
||||
|
||||
alpha = ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1) >> 5;
|
||||
alpha = ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -876,7 +876,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
|
||||
MTX_Concat43(&rotMat, &mat, &rotMat);
|
||||
|
||||
resBase = mgr->renderState.emitter->resource->header;
|
||||
scaleY = ptcl->unk_30;
|
||||
scaleY = ptcl->baseScale;
|
||||
scaleX = FX_MUL(scaleY, resBase->unk_30);
|
||||
|
||||
switch (resBase->misc.unk_07_4) {
|
||||
@ -917,7 +917,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&transform);
|
||||
}
|
||||
|
||||
colA = ptcl->unk_36;
|
||||
colA = ptcl->color;
|
||||
colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
@ -939,13 +939,13 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
|
||||
fx32 dot, scaleX, scaleY, scaleZ, alpha, tmp;
|
||||
SPLResourceHeader *resBase;
|
||||
|
||||
alpha = ptcl->unk_2E.unk_00_0 * (ptcl->unk_2E.unk_00_5 + 1) >> 5;
|
||||
alpha = ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1) >> 5;
|
||||
|
||||
G3_PolygonAttr(
|
||||
GX_LIGHTMASK_NONE,
|
||||
GX_POLYGONMODE_MODULATE,
|
||||
GX_CULL_NONE,
|
||||
ptcl->unk_2E.currentPolygonID,
|
||||
ptcl->visibility.currentPolygonID,
|
||||
alpha,
|
||||
mgr->unk_3C);
|
||||
|
||||
@ -994,7 +994,7 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
|
||||
MTX_Concat43(&rotMtx, &mat, &rotMtx);
|
||||
|
||||
resBase = mgr->renderState.emitter->resource->header;
|
||||
scaleY = ptcl->unk_30;
|
||||
scaleY = ptcl->baseScale;
|
||||
scaleX = FX_MUL(scaleY, resBase->unk_30);
|
||||
|
||||
switch (resBase->misc.unk_07_4) {
|
||||
@ -1035,7 +1035,7 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
|
||||
G3_MultMtx43(&transform);
|
||||
}
|
||||
|
||||
GXRgb colA = ptcl->unk_36;
|
||||
GXRgb colA = ptcl->color;
|
||||
GXRgb colB = mgr->renderState.emitter->color;
|
||||
G3_Color(GX_RGB(
|
||||
GX_RGB_R_(colA) * GX_RGB_R_(colB) >> 5,
|
||||
|
@ -1,44 +1,45 @@
|
||||
#include "nitro/types.h"
|
||||
#include <nitro/fx/fx.h>
|
||||
#include <nitro/fx/fx_const.h>
|
||||
#include <nitro/fx/fx_trig.h>
|
||||
|
||||
#include "spl_emitter.h"
|
||||
#include "spl_internal.h"
|
||||
#include "spl_list.h"
|
||||
#include "spl_particle.h"
|
||||
#include "spl_random.h"
|
||||
#include "spl_resource.h"
|
||||
|
||||
|
||||
#define IS_IN_RANGE(x, min, max) (((x) - (min)) <= ((max) - (min)))
|
||||
static void SPLEmitter_ComputeOrthogonalAxes(SPLEmitter *emtr);
|
||||
static void SPLUtil_TiltCoordinates(VecFx32 *ptclPos, VecFx32 *pos, SPLEmitter *emtr);
|
||||
|
||||
static VecFx16 sUpVector = { 0, FX16_ONE, 0 };
|
||||
|
||||
|
||||
static void sub_020A1768(SPLEmitter *emtr);
|
||||
static void sub_020A1608(VecFx32 *ptclPos, VecFx32 *pos, SPLEmitter *emtr);
|
||||
|
||||
VecFx16 Unk_02100DB0 = { 0, FX16_ONE, 0 };
|
||||
|
||||
|
||||
static void sub_020A1768(SPLEmitter *emtr)
|
||||
static void SPLEmitter_ComputeOrthogonalAxes(SPLEmitter *emtr)
|
||||
{
|
||||
VecFx16 vec, axis;
|
||||
|
||||
vec = Unk_02100DB0;
|
||||
vec = sUpVector;
|
||||
|
||||
switch (emtr->resource->header->flags.unk_04_6) {
|
||||
case 2:
|
||||
switch (emtr->resource->header->flags.circleAxis) {
|
||||
case SPL_CIRCLE_AXIS_X:
|
||||
axis.x = FX32_ONE;
|
||||
axis.y = 0;
|
||||
axis.z = 0;
|
||||
break;
|
||||
case 1:
|
||||
case SPL_CIRCLE_AXIS_Y:
|
||||
axis.x = 0;
|
||||
axis.y = FX32_ONE;
|
||||
axis.z = 0;
|
||||
break;
|
||||
case 0:
|
||||
case SPL_CIRCLE_AXIS_Z:
|
||||
axis.x = 0;
|
||||
axis.y = 0;
|
||||
axis.z = FX32_ONE;
|
||||
break;
|
||||
default:
|
||||
default: // SPL_CIRCLE_AXIS_EMITTER
|
||||
VEC_Fx16Normalize(&emtr->axis, &axis);
|
||||
break;
|
||||
}
|
||||
@ -50,240 +51,237 @@ static void sub_020A1768(SPLEmitter *emtr)
|
||||
vec.z = 0;
|
||||
}
|
||||
|
||||
emtr->unk_F4.x = FX_MUL(axis.y, vec.z) - FX_MUL(axis.z, vec.y);
|
||||
emtr->unk_F4.y = FX_MUL(axis.z, vec.x) - FX_MUL(axis.x, vec.z);
|
||||
emtr->unk_F4.z = FX_MUL(axis.x, vec.y) - FX_MUL(axis.y, vec.x);
|
||||
emtr->crossAxis1.x = FX_MUL(axis.y, vec.z) - FX_MUL(axis.z, vec.y);
|
||||
emtr->crossAxis1.y = FX_MUL(axis.z, vec.x) - FX_MUL(axis.x, vec.z);
|
||||
emtr->crossAxis1.z = FX_MUL(axis.x, vec.y) - FX_MUL(axis.y, vec.x);
|
||||
|
||||
emtr->unk_FA.x = FX_MUL(axis.y, emtr->unk_F4.z) - FX_MUL(axis.z, emtr->unk_F4.y);
|
||||
emtr->unk_FA.y = FX_MUL(axis.z, emtr->unk_F4.x) - FX_MUL(axis.x, emtr->unk_F4.z);
|
||||
emtr->unk_FA.z = FX_MUL(axis.x, emtr->unk_F4.y) - FX_MUL(axis.y, emtr->unk_F4.x);
|
||||
emtr->crossAxis2.x = FX_MUL(axis.y, emtr->crossAxis1.z) - FX_MUL(axis.z, emtr->crossAxis1.y);
|
||||
emtr->crossAxis2.y = FX_MUL(axis.z, emtr->crossAxis1.x) - FX_MUL(axis.x, emtr->crossAxis1.z);
|
||||
emtr->crossAxis2.z = FX_MUL(axis.x, emtr->crossAxis1.y) - FX_MUL(axis.y, emtr->crossAxis1.x);
|
||||
|
||||
VEC_Fx16Normalize(&emtr->unk_F4, &emtr->unk_F4);
|
||||
VEC_Fx16Normalize(&emtr->unk_FA, &emtr->unk_FA);
|
||||
VEC_Fx16Normalize(&emtr->crossAxis1, &emtr->crossAxis1);
|
||||
VEC_Fx16Normalize(&emtr->crossAxis2, &emtr->crossAxis2);
|
||||
}
|
||||
|
||||
static void sub_020A1608(VecFx32 *ptclPos, VecFx32 *pos, SPLEmitter *emtr)
|
||||
// Tilt the coordinates of a particle based on the emitter's axis
|
||||
static void SPLUtil_TiltCoordinates(VecFx32 *ptclPos, VecFx32 *pos, SPLEmitter *emtr)
|
||||
{
|
||||
VecFx16 vec;
|
||||
VEC_Fx16CrossProduct(&emtr->unk_F4, &emtr->unk_FA, &vec);
|
||||
VEC_Fx16CrossProduct(&emtr->crossAxis1, &emtr->crossAxis2, &vec);
|
||||
VEC_Fx16Normalize(&vec, &vec);
|
||||
|
||||
ptclPos->x = FX_MUL(pos->x, emtr->unk_F4.x) + FX_MUL(pos->y, emtr->unk_FA.x) + FX_MUL(pos->z, vec.x);
|
||||
ptclPos->y = FX_MUL(pos->x, emtr->unk_F4.y) + FX_MUL(pos->y, emtr->unk_FA.y) + FX_MUL(pos->z, vec.y);
|
||||
ptclPos->z = FX_MUL(pos->x, emtr->unk_F4.z) + FX_MUL(pos->y, emtr->unk_FA.z) + FX_MUL(pos->z, vec.z);
|
||||
ptclPos->x = FX_MUL(pos->x, emtr->crossAxis1.x) + FX_MUL(pos->y, emtr->crossAxis2.x) + FX_MUL(pos->z, vec.x);
|
||||
ptclPos->y = FX_MUL(pos->x, emtr->crossAxis1.y) + FX_MUL(pos->y, emtr->crossAxis2.y) + FX_MUL(pos->z, vec.y);
|
||||
ptclPos->z = FX_MUL(pos->x, emtr->crossAxis1.z) + FX_MUL(pos->y, emtr->crossAxis2.z) + FX_MUL(pos->z, vec.z);
|
||||
}
|
||||
|
||||
void sub_020A08DC(SPLEmitter *emtr, SPLList *list)
|
||||
void SPLEmitter_EmitParticles(SPLEmitter *emtr, SPLParticleList *list)
|
||||
{
|
||||
SPLResource *res;
|
||||
SPLResourceHeader *resBase;
|
||||
int i, curGenNum;
|
||||
SPLParticle *ptcl;
|
||||
fx32 magPos;
|
||||
fx32 magAxis;
|
||||
SPLResource *res = emtr->resource;
|
||||
SPLResourceHeader *header = res->header;
|
||||
|
||||
res = emtr->resource;
|
||||
resBase = res->header;
|
||||
int i = 0;
|
||||
int emitCountDec = emtr->emissionCount + FX32_CAST(emtr->emissionCountFractional);
|
||||
int totalEmissions = emitCountDec >> FX32_SHIFT;
|
||||
int emission = 0;
|
||||
emtr->emissionCountFractional = emitCountDec & FX32_DEC_MASK;
|
||||
|
||||
int temp = emtr->unk_C8 + FX32_CAST(emtr->unk_BE);
|
||||
curGenNum = temp >> FX32_SHIFT;
|
||||
emtr->unk_BE = temp & FX32_DEC_MASK;
|
||||
|
||||
u32 initType = resBase->flags.unk_04_0;
|
||||
if (initType == 2 || initType == 3 || IS_IN_RANGE(initType, 5, 9)) {
|
||||
sub_020A1768(emtr);
|
||||
enum SPLEmissionType emitType = header->flags.emissionType;
|
||||
if (emitType == SPL_EMISSION_TYPE_CIRCLE_BORDER ||
|
||||
emitType == SPL_EMISSION_TYPE_CIRCLE_BORDER_UNIFORM ||
|
||||
emitType == SPL_EMISSION_TYPE_CIRCLE ||
|
||||
emitType == SPL_EMISSION_TYPE_CYLINDER_SURFACE ||
|
||||
emitType == SPL_EMISSION_TYPE_CYLINDER ||
|
||||
emitType == SPL_EMISSION_TYPE_HEMISPHERE_SURFACE ||
|
||||
emitType == SPL_EMISSION_TYPE_HEMISPHERE) {
|
||||
SPLEmitter_ComputeOrthogonalAxes(emtr);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (i < curGenNum) {
|
||||
fx32 genNum = 0;
|
||||
do {
|
||||
ptcl = (SPLParticle *)SPLList_PopFront(list);
|
||||
for (i = 0; i < totalEmissions; i++) {
|
||||
SPLParticle *ptcl = SPLParticleList_PopFront(list);
|
||||
if (ptcl == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptcl == NULL) {
|
||||
return;
|
||||
SPLParticleList_PushFront(&emtr->particles, ptcl);
|
||||
|
||||
switch (header->flags.emissionType) {
|
||||
case SPL_EMISSION_TYPE_POINT:
|
||||
ptcl->position.x = ptcl->position.y = ptcl->position.z = 0;
|
||||
break;
|
||||
|
||||
case SPL_EMISSION_TYPE_SPHERE_SURFACE:
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
ptcl->position.x = FX_MUL(ptcl->position.x, emtr->radius);
|
||||
ptcl->position.y = FX_MUL(ptcl->position.y, emtr->radius);
|
||||
ptcl->position.z = FX_MUL(ptcl->position.z, emtr->radius);
|
||||
break;
|
||||
|
||||
case SPL_EMISSION_TYPE_CIRCLE_BORDER: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&pos);
|
||||
pos.x = FX_MUL(pos.x, emtr->radius);
|
||||
pos.y = FX_MUL(pos.y, emtr->radius);
|
||||
pos.z = 0;
|
||||
SPLUtil_TiltCoordinates(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case SPL_EMISSION_TYPE_CIRCLE_BORDER_UNIFORM: {
|
||||
VecFx32 pos;
|
||||
int idx = (emission * FX32_CONST(16)) / totalEmissions;
|
||||
emission += 1;
|
||||
|
||||
fx32 sin = FX_SinIdx(idx);
|
||||
fx32 cos = FX_CosIdx(idx);
|
||||
pos.x = FX_MUL(sin, emtr->radius);
|
||||
pos.y = FX_MUL(cos, emtr->radius);
|
||||
pos.z = 0;
|
||||
SPLUtil_TiltCoordinates(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case SPL_EMISSION_TYPE_SPHERE:
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
ptcl->position.x = FX_MUL(FX_MUL(ptcl->position.x, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
ptcl->position.y = FX_MUL(FX_MUL(ptcl->position.y, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
ptcl->position.z = FX_MUL(FX_MUL(ptcl->position.z, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
break;
|
||||
|
||||
case SPL_EMISSION_TYPE_CIRCLE: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&pos);
|
||||
pos.x = FX_MUL(FX_MUL(pos.x, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
pos.y = FX_MUL(FX_MUL(pos.y, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
SPLUtil_TiltCoordinates(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case SPL_EMISSION_TYPE_HEMISPHERE_SURFACE: {
|
||||
VecFx32 pos;
|
||||
VecFx16 emitterUp;
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
VEC_Fx16CrossProduct(&emtr->crossAxis1, &emtr->crossAxis2, &emitterUp);
|
||||
pos.x = emitterUp.x;
|
||||
pos.y = emitterUp.y;
|
||||
pos.z = emitterUp.z;
|
||||
if (VEC_DotProduct(&pos, &ptcl->position) <= 0) {
|
||||
ptcl->position.x = -ptcl->position.x;
|
||||
ptcl->position.y = -ptcl->position.y;
|
||||
ptcl->position.z = -ptcl->position.z;
|
||||
}
|
||||
|
||||
SPLList_PushFront((SPLList *)&emtr->particles, (SPLNode *)ptcl);
|
||||
ptcl->position.x = FX_MUL(ptcl->position.x, emtr->radius);
|
||||
ptcl->position.y = FX_MUL(ptcl->position.y, emtr->radius);
|
||||
ptcl->position.z = FX_MUL(ptcl->position.z, emtr->radius);
|
||||
} break;
|
||||
|
||||
switch (resBase->flags.unk_04_0) {
|
||||
case 0:
|
||||
ptcl->position.x = ptcl->position.y = ptcl->position.z = 0;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
ptcl->position.x = FX_MUL(ptcl->position.x, emtr->unk_CC);
|
||||
ptcl->position.y = FX_MUL(ptcl->position.y, emtr->unk_CC);
|
||||
ptcl->position.z = FX_MUL(ptcl->position.z, emtr->unk_CC);
|
||||
break;
|
||||
|
||||
case 2: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&pos);
|
||||
pos.x = FX_MUL(pos.x, emtr->unk_CC);
|
||||
pos.y = FX_MUL(pos.y, emtr->unk_CC);
|
||||
pos.z = 0;
|
||||
sub_020A1608(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case 3: {
|
||||
VecFx32 pos;
|
||||
int idx = genNum / curGenNum;
|
||||
genNum += 0x10000;
|
||||
fx32 sin = FX_SinIdx(idx);
|
||||
fx32 cos = FX_CosIdx(idx);
|
||||
pos.x = FX_MUL(sin, emtr->unk_CC);
|
||||
pos.y = FX_MUL(cos, emtr->unk_CC);
|
||||
pos.z = 0;
|
||||
sub_020A1608(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case 4:
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
ptcl->position.x = FX_MUL(FX_MUL(ptcl->position.x, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
ptcl->position.y = FX_MUL(FX_MUL(ptcl->position.y, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
ptcl->position.z = FX_MUL(FX_MUL(ptcl->position.z, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
break;
|
||||
|
||||
case 5: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&pos);
|
||||
pos.x = FX_MUL(FX_MUL(pos.x, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
pos.y = FX_MUL(FX_MUL(pos.y, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
sub_020A1608(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case 8: {
|
||||
VecFx32 pos;
|
||||
VecFx16 tmpUnitVec;
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
VEC_Fx16CrossProduct(&emtr->unk_F4, &emtr->unk_FA, &tmpUnitVec);
|
||||
pos.x = tmpUnitVec.x;
|
||||
pos.y = tmpUnitVec.y;
|
||||
pos.z = tmpUnitVec.z;
|
||||
if (VEC_DotProduct(&pos, &ptcl->position) <= 0) {
|
||||
ptcl->position.x = -ptcl->position.x;
|
||||
ptcl->position.y = -ptcl->position.y;
|
||||
ptcl->position.z = -ptcl->position.z;
|
||||
}
|
||||
|
||||
ptcl->position.x = FX_MUL(ptcl->position.x, emtr->unk_CC);
|
||||
ptcl->position.y = FX_MUL(ptcl->position.y, emtr->unk_CC);
|
||||
ptcl->position.z = FX_MUL(ptcl->position.z, emtr->unk_CC);
|
||||
} break;
|
||||
|
||||
case 9: {
|
||||
VecFx32 pos;
|
||||
VecFx16 tmpUnitVec;
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
VEC_Fx16CrossProduct(&emtr->unk_F4, &emtr->unk_FA, &tmpUnitVec);
|
||||
pos.x = tmpUnitVec.x;
|
||||
pos.y = tmpUnitVec.y;
|
||||
pos.z = tmpUnitVec.z;
|
||||
if (VEC_DotProduct(&pos, &ptcl->position) < 0) {
|
||||
ptcl->position.x = -ptcl->position.x;
|
||||
ptcl->position.y = -ptcl->position.y;
|
||||
ptcl->position.z = -ptcl->position.z;
|
||||
}
|
||||
|
||||
ptcl->position.x = FX_MUL(FX_MUL(ptcl->position.x, emtr->unk_CC), (SPLRandom_RangeFX32(FX32_ONE) >> 1) + FX32_HALF);
|
||||
ptcl->position.y = FX_MUL(FX_MUL(ptcl->position.y, emtr->unk_CC), (SPLRandom_RangeFX32(FX32_ONE) >> 1) + FX32_HALF);
|
||||
ptcl->position.z = FX_MUL(FX_MUL(ptcl->position.z, emtr->unk_CC), (SPLRandom_RangeFX32(FX32_ONE) >> 1) + FX32_HALF);
|
||||
} break;
|
||||
|
||||
case 6: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&ptcl->velocity);
|
||||
pos.x = FX_MUL(ptcl->velocity.x, emtr->unk_CC);
|
||||
pos.y = FX_MUL(ptcl->velocity.y, emtr->unk_CC);
|
||||
pos.z = SPLRandom_RangeFX32(emtr->length);
|
||||
sub_020A1608(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
case 7: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&ptcl->velocity);
|
||||
pos.x = FX_MUL(FX_MUL(ptcl->velocity.x, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
pos.y = FX_MUL(FX_MUL(ptcl->velocity.y, emtr->unk_CC), SPLRandom_RangeFX32(FX32_ONE));
|
||||
pos.z = SPLRandom_RangeFX32(emtr->length);
|
||||
sub_020A1608(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
case SPL_EMISSION_TYPE_HEMISPHERE: {
|
||||
VecFx32 pos;
|
||||
VecFx16 tmpUnitVec;
|
||||
SPLRandom_VecFx32(&ptcl->position);
|
||||
VEC_Fx16CrossProduct(&emtr->crossAxis1, &emtr->crossAxis2, &tmpUnitVec);
|
||||
pos.x = tmpUnitVec.x;
|
||||
pos.y = tmpUnitVec.y;
|
||||
pos.z = tmpUnitVec.z;
|
||||
if (VEC_DotProduct(&pos, &ptcl->position) < 0) {
|
||||
ptcl->position.x = -ptcl->position.x;
|
||||
ptcl->position.y = -ptcl->position.y;
|
||||
ptcl->position.z = -ptcl->position.z;
|
||||
}
|
||||
|
||||
magPos = SPLRandom_DoubleScaledRangeFX32(emtr->unk_D4, resBase->unk_44.unk_02_0);
|
||||
magAxis = SPLRandom_DoubleScaledRangeFX32(emtr->unk_D8, resBase->unk_44.unk_02_0);
|
||||
ptcl->position.x = FX_MUL(FX_MUL(ptcl->position.x, emtr->radius), (SPLRandom_RangeFX32(FX32_ONE) >> 1) + FX32_HALF);
|
||||
ptcl->position.y = FX_MUL(FX_MUL(ptcl->position.y, emtr->radius), (SPLRandom_RangeFX32(FX32_ONE) >> 1) + FX32_HALF);
|
||||
ptcl->position.z = FX_MUL(FX_MUL(ptcl->position.z, emtr->radius), (SPLRandom_RangeFX32(FX32_ONE) >> 1) + FX32_HALF);
|
||||
} break;
|
||||
|
||||
VecFx32 posNorm;
|
||||
if (resBase->flags.unk_04_0 == 6) {
|
||||
VecFx32 tmp;
|
||||
tmp.x = FX_MUL(ptcl->velocity.x, emtr->unk_F4.x) + FX_MUL(ptcl->velocity.y, emtr->unk_FA.x);
|
||||
tmp.y = FX_MUL(ptcl->velocity.x, emtr->unk_F4.y) + FX_MUL(ptcl->velocity.y, emtr->unk_FA.y);
|
||||
tmp.z = FX_MUL(ptcl->velocity.x, emtr->unk_F4.z) + FX_MUL(ptcl->velocity.y, emtr->unk_FA.z);
|
||||
case SPL_EMISSION_TYPE_CYLINDER_SURFACE: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&ptcl->velocity);
|
||||
pos.x = FX_MUL(ptcl->velocity.x, emtr->radius);
|
||||
pos.y = FX_MUL(ptcl->velocity.y, emtr->radius);
|
||||
pos.z = SPLRandom_RangeFX32(emtr->length);
|
||||
SPLUtil_TiltCoordinates(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
|
||||
VEC_Normalize(&tmp, &posNorm);
|
||||
} else if (ptcl->position.x == 0 && ptcl->position.y == 0 && ptcl->position.z == 0) {
|
||||
SPLRandom_VecFx32(&posNorm);
|
||||
} else {
|
||||
VEC_Normalize(&ptcl->position, &posNorm);
|
||||
}
|
||||
case SPL_EMISSION_TYPE_CYLINDER: {
|
||||
VecFx32 pos;
|
||||
SPLRandom_VecFx32_XY(&ptcl->velocity);
|
||||
pos.x = FX_MUL(FX_MUL(ptcl->velocity.x, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
pos.y = FX_MUL(FX_MUL(ptcl->velocity.y, emtr->radius), SPLRandom_RangeFX32(FX32_ONE));
|
||||
pos.z = SPLRandom_RangeFX32(emtr->length);
|
||||
SPLUtil_TiltCoordinates(&ptcl->position, &pos, emtr);
|
||||
} break;
|
||||
}
|
||||
|
||||
ptcl->velocity.x = FX_MUL(posNorm.x, magPos) + FX_MUL(emtr->axis.x, magAxis) + emtr->unk_B0.x;
|
||||
ptcl->velocity.y = FX_MUL(posNorm.y, magPos) + FX_MUL(emtr->axis.y, magAxis) + emtr->unk_B0.y;
|
||||
ptcl->velocity.z = FX_MUL(posNorm.z, magPos) + FX_MUL(emtr->axis.z, magAxis) + emtr->unk_B0.z;
|
||||
fx32 magPos = SPLRandom_DoubleScaledRangeFX32(emtr->initVelPositionAmplifier, header->randomAttenuation.initVel);
|
||||
fx32 magAxis = SPLRandom_DoubleScaledRangeFX32(emtr->initVelAxisAmplifier, header->randomAttenuation.initVel);
|
||||
|
||||
ptcl->emitterPos = emtr->position;
|
||||
VecFx32 posNorm;
|
||||
if (header->flags.emissionType == SPL_EMISSION_TYPE_CYLINDER_SURFACE) {
|
||||
VecFx32 tmp;
|
||||
tmp.x = FX_MUL(ptcl->velocity.x, emtr->crossAxis1.x) + FX_MUL(ptcl->velocity.y, emtr->crossAxis2.x);
|
||||
tmp.y = FX_MUL(ptcl->velocity.x, emtr->crossAxis1.y) + FX_MUL(ptcl->velocity.y, emtr->crossAxis2.y);
|
||||
tmp.z = FX_MUL(ptcl->velocity.x, emtr->crossAxis1.z) + FX_MUL(ptcl->velocity.y, emtr->crossAxis2.z);
|
||||
|
||||
ptcl->unk_30 = SPLRandom_DoubleScaledRangeFX32(emtr->unk_DC, resBase->unk_44.unk_00_0);
|
||||
ptcl->unk_34 = FX32_ONE;
|
||||
VEC_Normalize(&tmp, &posNorm);
|
||||
} else if (ptcl->position.x == 0 && ptcl->position.y == 0 && ptcl->position.z == 0) {
|
||||
SPLRandom_VecFx32(&posNorm);
|
||||
} else {
|
||||
VEC_Normalize(&ptcl->position, &posNorm);
|
||||
}
|
||||
|
||||
if (resBase->flags.hasColorAnim && res->colorAnim->unk_08.unk_00_0) {
|
||||
u16 clr[3];
|
||||
u32 index = SPLRandom_S32(12);
|
||||
clr[0] = res->colorAnim->unk_00;
|
||||
clr[1] = resBase->unk_22;
|
||||
clr[2] = res->colorAnim->unk_02;
|
||||
ptcl->unk_36 = clr[index % 3];
|
||||
} else {
|
||||
ptcl->unk_36 = resBase->unk_22;
|
||||
}
|
||||
ptcl->velocity.x = FX_MUL(posNorm.x, magPos) + FX_MUL(emtr->axis.x, magAxis) + emtr->particleInitVelocity.x;
|
||||
ptcl->velocity.y = FX_MUL(posNorm.y, magPos) + FX_MUL(emtr->axis.y, magAxis) + emtr->particleInitVelocity.y;
|
||||
ptcl->velocity.z = FX_MUL(posNorm.z, magPos) + FX_MUL(emtr->axis.z, magAxis) + emtr->particleInitVelocity.z;
|
||||
|
||||
ptcl->unk_2E.unk_00_0 = emtr->misc.unk_01_0;
|
||||
ptcl->unk_2E.unk_00_5 = 31;
|
||||
ptcl->emitterPos = emtr->position;
|
||||
|
||||
if (resBase->flags.unk_05_5) {
|
||||
ptcl->rotation = SPLRandom_S32(32);
|
||||
} else {
|
||||
ptcl->rotation = emtr->unk_C6;
|
||||
}
|
||||
ptcl->baseScale = SPLRandom_DoubleScaledRangeFX32(emtr->baseScale, header->randomAttenuation.baseScale);
|
||||
ptcl->unk_34 = FX32_ONE;
|
||||
|
||||
if (resBase->flags.unk_05_4) {
|
||||
ptcl->angularVelocity = (u32)SPLRandom_BetweenFX32(resBase->unk_34, resBase->unk_36) >> FX32_SHIFT;
|
||||
} else {
|
||||
ptcl->angularVelocity = 0;
|
||||
}
|
||||
if (header->flags.hasColorAnim && res->colorAnim->unk_08.unk_00_0) {
|
||||
u16 clr[3];
|
||||
u32 index = SPLRandom_S32(12);
|
||||
clr[0] = res->colorAnim->startColor;
|
||||
clr[1] = header->color;
|
||||
clr[2] = res->colorAnim->endColor;
|
||||
ptcl->color = clr[index % 3];
|
||||
} else {
|
||||
ptcl->color = header->color;
|
||||
}
|
||||
|
||||
ptcl->lifeTime = SPLRandom_ScaledRangeFX32(emtr->particleLifeTime, resBase->unk_44.unk_01_0) + 1;
|
||||
ptcl->age = 0;
|
||||
ptcl->visibility.baseAlpha = emtr->misc.baseAlpha;
|
||||
ptcl->visibility.animAlpha = 31;
|
||||
|
||||
if (resBase->flags.hasTexAnim && res->texAnim->unk_08.unk_02_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->misc.unk_00 = res->texAnim->unk_00[0];
|
||||
} else {
|
||||
ptcl->misc.unk_00 = resBase->misc.textureIndex;
|
||||
}
|
||||
if (header->flags.unk_05_5) {
|
||||
ptcl->rotation = SPLRandom_S32(32);
|
||||
} else {
|
||||
ptcl->rotation = emtr->unk_C6;
|
||||
}
|
||||
|
||||
ptcl->loopTimeFactor = 0xFFFF / res->header->misc.unk_04_0;
|
||||
ptcl->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
|
||||
if (header->flags.hasRotation) {
|
||||
ptcl->angularVelocity = (u32)SPLRandom_BetweenFX32(header->minRotation, header->maxRotation) >> FX32_SHIFT;
|
||||
} else {
|
||||
ptcl->angularVelocity = 0;
|
||||
}
|
||||
|
||||
ptcl->misc.lifeRateOffset = 0;
|
||||
ptcl->lifeTime = SPLRandom_ScaledRangeFX32(emtr->particleLifeTime, header->randomAttenuation.lifeTime) + 1; // Life is always at least 1 frame
|
||||
ptcl->age = 0;
|
||||
|
||||
if (resBase->flags.unk_06_4) {
|
||||
ptcl->misc.lifeRateOffset = (u8)SPLRandom_S32(8);
|
||||
}
|
||||
i++;
|
||||
} while (i < curGenNum);
|
||||
if (header->flags.hasTexAnim && res->texAnim->param.randomizeInit) {
|
||||
ptcl->misc.texture = res->texAnim->textures[SPLRandom_U32(12) % res->texAnim->param.frameCount];
|
||||
} else if (header->flags.hasTexAnim && !res->texAnim->param.randomizeInit) {
|
||||
ptcl->misc.texture = res->texAnim->textures[0];
|
||||
} else {
|
||||
ptcl->misc.texture = header->misc.textureIndex;
|
||||
}
|
||||
|
||||
ptcl->loopTimeFactor = 0xFFFF / res->header->misc.loopFrames;
|
||||
ptcl->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
|
||||
|
||||
ptcl->misc.lifeRateOffset = 0;
|
||||
|
||||
if (header->flags.randomizeLoopedAnim) {
|
||||
ptcl->misc.lifeRateOffset = (u8)SPLRandom_S32(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,19 +320,19 @@ void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list)
|
||||
// `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->unk_30 * ptcl->unk_34 >> FX32_SHIFT;
|
||||
chld->unk_30 = idk * (chldRes->unk_08.unk_01_0 + 1) >> 6;
|
||||
int idk = ptcl->baseScale * ptcl->unk_34 >> FX32_SHIFT;
|
||||
chld->baseScale = idk * (chldRes->unk_08.unk_01_0 + 1) >> 6;
|
||||
|
||||
chld->unk_34 = FX32_ONE;
|
||||
|
||||
if (chldRes->flags.unk_02_6) {
|
||||
chld->unk_36 = chldRes->unk_0A;
|
||||
chld->color = chldRes->unk_0A;
|
||||
} else {
|
||||
chld->unk_36 = ptcl->unk_36;
|
||||
chld->color = ptcl->color;
|
||||
}
|
||||
|
||||
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;
|
||||
chld->visibility.baseAlpha = (ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
|
||||
chld->visibility.animAlpha = 31;
|
||||
|
||||
switch (chldRes->flags.unk_02_3) {
|
||||
case 0:
|
||||
@ -353,7 +351,7 @@ void sub_020A05BC(SPLParticle *ptcl, SPLEmitter *emtr, SPLList *list)
|
||||
|
||||
chld->lifeTime = chldRes->unk_06;
|
||||
chld->age = 0;
|
||||
chld->misc.unk_00 = chldRes->misc.textureIndex;
|
||||
chld->misc.texture = chldRes->misc.textureIndex;
|
||||
|
||||
chld->loopTimeFactor = 0xFFFF / (ptcl->lifeTime / 2);
|
||||
chld->lifeTimeFactor = 0xFFFF / ptcl->lifeTime;
|
||||
|
@ -41,53 +41,53 @@ void sub_020A1BD4(SPLParticle *ptcl, SPLResource *res, int lifeRate)
|
||||
in = colorAnim->unk_04.unk_04_0;
|
||||
|
||||
if (lifeRate < in) {
|
||||
ptcl->unk_36 = colorAnim->unk_00;
|
||||
ptcl->color = colorAnim->startColor;
|
||||
} else if (lifeRate < peak) {
|
||||
int peakR = GX_RGB_R(resBase->unk_22);
|
||||
int startR = GX_RGB_R(colorAnim->unk_00);
|
||||
int peakR = GX_RGB_R(resBase->color);
|
||||
int startR = GX_RGB_R(colorAnim->startColor);
|
||||
|
||||
int peakG = GX_RGB_G(resBase->unk_22);
|
||||
int startG = GX_RGB_G(colorAnim->unk_00);
|
||||
int peakG = GX_RGB_G(resBase->color);
|
||||
int startG = GX_RGB_G(colorAnim->startColor);
|
||||
|
||||
int peakB = GX_RGB_B(resBase->unk_22);
|
||||
int startB = GX_RGB_B(colorAnim->unk_00);
|
||||
int peakB = GX_RGB_B(resBase->color);
|
||||
int startB = GX_RGB_B(colorAnim->startColor);
|
||||
|
||||
if (colorAnim->unk_08.unk_00_2) { // interpolate
|
||||
int a = lifeRate - in;
|
||||
int b = peak - in;
|
||||
|
||||
ptcl->unk_36 = GX_RGB(
|
||||
ptcl->color = GX_RGB(
|
||||
startR + (a * (int)(peakR - startR)) / b,
|
||||
startG + (a * (int)(peakG - startG)) / b,
|
||||
startB + (a * (int)(peakB - startB)) / b
|
||||
);
|
||||
} else {
|
||||
ptcl->unk_36 = GX_RGB(peakR, peakG, peakB);
|
||||
ptcl->color = GX_RGB(peakR, peakG, peakB);
|
||||
}
|
||||
} else if (lifeRate < out) {
|
||||
int peakR = GX_RGB_R(resBase->unk_22);
|
||||
int endR = GX_RGB_R(colorAnim->unk_02);
|
||||
int peakR = GX_RGB_R(resBase->color);
|
||||
int endR = GX_RGB_R(colorAnim->endColor);
|
||||
|
||||
int peakG = GX_RGB_G(resBase->unk_22);
|
||||
int endG = GX_RGB_G(colorAnim->unk_02);
|
||||
int peakG = GX_RGB_G(resBase->color);
|
||||
int endG = GX_RGB_G(colorAnim->endColor);
|
||||
|
||||
int peakB = GX_RGB_B(resBase->unk_22);
|
||||
int endB = GX_RGB_B(colorAnim->unk_02);
|
||||
int peakB = GX_RGB_B(resBase->color);
|
||||
int endB = GX_RGB_B(colorAnim->endColor);
|
||||
|
||||
if (colorAnim->unk_08.unk_00_2) { // interpolate
|
||||
int a = lifeRate - peak;
|
||||
int b = out - peak;
|
||||
|
||||
ptcl->unk_36 = GX_RGB(
|
||||
ptcl->color = GX_RGB(
|
||||
peakR + (a * (int)(endR - peakR)) / b,
|
||||
peakG + (a * (int)(endG - peakG)) / b,
|
||||
peakB + (a * (int)(endB - peakB)) / b
|
||||
);
|
||||
} else {
|
||||
ptcl->unk_36 = GX_RGB(endR, endG, endB);
|
||||
ptcl->color = GX_RGB(endR, endG, endB);
|
||||
}
|
||||
} else {
|
||||
ptcl->unk_36 = colorAnim->unk_02;
|
||||
ptcl->color = colorAnim->endColor;
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,15 +108,15 @@ void sub_020A1AF8(SPLParticle *ptcl, SPLResource *res, int lifeRate)
|
||||
x += alphaAnim->unk_00.val2_01_2;
|
||||
}
|
||||
|
||||
ptcl->unk_2E.unk_00_5 = SPLRandom_ScaledRangeFX32(x, alphaAnim->unk_02.unk_00_0);
|
||||
ptcl->visibility.animAlpha = SPLRandom_ScaledRangeFX32(x, alphaAnim->unk_02.unk_00_0);
|
||||
}
|
||||
|
||||
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->misc.unk_00 = texAnim->unk_00[i];
|
||||
for (int i = 0; i < texAnim->param.frameCount; i++) {
|
||||
if (lifeRate < texAnim->param.unk_01_0 * (i + 1)) {
|
||||
ptcl->misc.texture = texAnim->textures[i];
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -129,5 +129,5 @@ void sub_020A1A48(SPLParticle *ptcl, SPLResource *res, int lifeRate)
|
||||
|
||||
void sub_020A19F0(SPLParticle *ptcl, SPLResource *res, int lifeRate)
|
||||
{
|
||||
ptcl->unk_2E.unk_00_5 = ((255 - lifeRate) * 31) / 255;
|
||||
ptcl->visibility.animAlpha = ((255 - lifeRate) * 31) / 255;
|
||||
}
|
||||
|
@ -652,7 +652,7 @@ void sub_02014798(SPLEmitter *param0, VecFx16 *param1)
|
||||
|
||||
void sub_020147B0(SPLEmitter *param0, fx32 param1)
|
||||
{
|
||||
param0->resource->header->unk_10 = param1;
|
||||
param0->resource->header->emissionCount = param1;
|
||||
}
|
||||
|
||||
enum {
|
||||
|
Loading…
Reference in New Issue
Block a user