Document SPLDraw billboard functions

This commit is contained in:
Fexty12573 2024-08-02 20:11:53 +02:00
parent 86b9e9f2a4
commit 327e781f54
7 changed files with 271 additions and 300 deletions

View File

@ -53,10 +53,10 @@ typedef struct SPLEmitter {
u16 particleLifeTime;
GXRgb color;
fx32 collisionPlaneHeight;
fx16 unk_E8;
fx16 unk_EA;
fx16 unk_EC;
fx16 unk_EE;
fx16 textureS;
fx16 textureT;
fx16 childTextureS;
fx16 childTextureT;
struct {
u32 emissionInterval : 8; // number of frames between particle emissions
u32 baseAlpha : 8;

View File

@ -20,11 +20,11 @@
#define GX_RGB_B_(rgb) (rgb & GX_RGB_B_MASK)
void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl);
void SPLDraw_Child_Billboard(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl);
void SPLDraw_Billboard(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl);
void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl);

View File

@ -33,6 +33,12 @@ enum SPLChildRotationType {
SPL_CHILD_ROT_INHERIT_ANGLE_AND_VELOCITY = 2,
};
enum SPLScaleAnimDir {
SPL_SCALE_ANIM_DIR_XY = 0,
SPL_SCALE_ANIM_DIR_X = 1,
SPL_SCALE_ANIM_DIR_Y = 2,
};
typedef struct SPLArcHdr {
u32 magic;
u32 version;
@ -68,7 +74,7 @@ typedef union SPLResourceFlags {
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;
u32 useViewSpace : 1; // If set, the rendering calculations will be done in view space
u32 hasGravityBehavior : 1;
u32 hasRandomBehavior : 1;
u32 hasMagnetBehavior : 1;
@ -125,7 +131,7 @@ typedef struct SPLResourceHeader {
fx32 unk_24;
fx32 unk_28;
fx32 unk_2C;
fx16 unk_30;
fx16 aspectRatio;
u16 startDelay; // Delay, in frames, before the emitter starts emitting particles
s16 minRotation;
s16 maxRotation;
@ -153,15 +159,15 @@ typedef struct SPLResourceHeader {
u32 unk_05_0 : 16;
u32 unk_07_0 : 2;
u32 unk_07_2 : 2;
u32 unk_07_4 : 3;
u32 scaleAnimDir : 3; // Maps to SPLScaleAnimDir
u32 unk_07_7 : 1;
u32 unk_08_0 : 1;
u32 unk_08_1 : 1;
u32 unk_08_2 : 3;
u32 unk_08_5 : 27;
} misc;
fx16 unk_54;
fx16 unk_56;
fx16 polygonX;
fx16 polygonY;
struct {
u32 unk_00_0 : 8;
u32 reserved_01_0 : 24;

View File

@ -13,9 +13,9 @@ typedef union SPLTextureParam {
u32 repeat : 2; // Maps to GXTexRepeat
u32 flip : 2; // Maps to GXTexFlip
u32 palColor0 : 1; // Maps to GXTexPlttColor0
u32 val2_02_1 : 1;
u32 useSharedTexture : 1;
u32 sharedTexID : 8;
u32 val2_03_2 : 6;
u32 : 6;
};
} SPLTextureParam;

View File

@ -91,27 +91,27 @@ void SPLEmitter_Init(SPLEmitter *emtr, SPLResource *res, const VecFx32 *pos)
emtr->misc.updateCycle = 0;
emtr->misc.unk_02_3 = 0;
emtr->collisionPlaneHeight = FX32_MIN;
emtr->unk_E8 = FX32_ONE << emtr->resource->header->misc.unk_07_0;
emtr->unk_EA = FX32_ONE << emtr->resource->header->misc.unk_07_2;
emtr->textureS = FX32_ONE << emtr->resource->header->misc.unk_07_0;
emtr->textureT = FX32_ONE << emtr->resource->header->misc.unk_07_2;
if (emtr->resource->header->misc.unk_08_0) {
emtr->unk_E8 *= -1;
emtr->textureS *= -1;
}
if (emtr->resource->header->misc.unk_08_1) {
emtr->unk_EA *= -1;
emtr->textureT *= -1;
}
if (emtr->resource->header->flags.hasChildResource) {
emtr->unk_EC = FX32_ONE << emtr->resource->childResource->misc.unk_04_0;
emtr->unk_EE = FX32_ONE << emtr->resource->childResource->misc.unk_04_2;
emtr->childTextureS = FX32_ONE << emtr->resource->childResource->misc.unk_04_0;
emtr->childTextureT = FX32_ONE << emtr->resource->childResource->misc.unk_04_2;
if (emtr->resource->childResource->misc.unk_04_4) {
emtr->unk_EC *= -1;
emtr->childTextureS *= -1;
}
if (emtr->resource->childResource->misc.unk_04_5) {
emtr->unk_EE *= -1;
emtr->childTextureT *= -1;
}
}
@ -335,7 +335,7 @@ static void SPLManager_DrawParticles(SPLManager *mgr)
switch (header->flags.drawType) {
case 0:
drawFunc = sub_0209FF0C;
drawFunc = SPLDraw_Billboard;
break;
case 1:
drawFunc = sub_0209F3D0;
@ -373,7 +373,7 @@ static void SPLManager_DrawChildParticles(SPLManager *mgr)
switch (res->childResource->flags.drawType) {
case 0:
drawFunc = sub_0209FAB8;
drawFunc = SPLDraw_Child_Billboard;
break;
case 1:
drawFunc = sub_0209ECF0;

View File

@ -220,7 +220,7 @@ BOOL SPLManager_UploadTexturesEx(SPLManager *mgr, SPLTexVRAMAllocFunc vramAlloc)
SPLTexture *tex = &textures[i];
SPLTextureResource *texRes = (SPLTextureResource *)tex->resource;
if (texRes->param.val2_02_1) {
if (texRes->param.useSharedTexture) {
tex->texAddr = textures[texRes->param.sharedTexID].texAddr;
} else {
u32 addr = vramAlloc(texRes->textureSize, texRes->param.format == GX_TEXFMT_COMP4x4);

View File

@ -1,4 +1,5 @@
#include "nitro/types.h"
#include <nitro/fx/fx.h>
#include <nitro/fx/fx_const.h>
#include <nitro/fx/fx_mtx43.h>
@ -13,233 +14,35 @@
typedef void (*RotFunc)(fx32 sin, fx32 cos, MtxFx43 *rot);
typedef void (*DrawPlaneFunc)(fx16 s, fx16 t, fx16 offsetX, fx16 offsetY);
void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_chld_bb
void SPLDraw_Child_Billboard(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_chld_bb
void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_chld_dbb
void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_chld_pol
void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_chld_dpl
void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_bb
void SPLDraw_Billboard(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_bb
void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_dbb
void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_pol
void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl); // spl_draw_dpl
static void sub_020A0500(fx16 s, fx16 t, fx16 offsetX, fx16 offsetY);
static void sub_020A0444(fx16 s, fx16 t, fx16 offsetX, fx16 offsetZ);
static void SPLUtil_DrawXYPlane(fx16 s, fx16 t, fx16 offsetX, fx16 offsetY);
static void SPLUtil_DrawXZPlane(fx16 s, fx16 t, fx16 offsetX, fx16 offsetZ);
static void sub_020A0398(fx32 sin, fx32 cos, MtxFx43 *mat);
static void sub_020A0358(fx32 sin, fx32 cos, MtxFx43 *mat);
static void SPLUtil_RotateXYZ(fx32 sin, fx32 cos, MtxFx43 *mat);
static void SPLUtil_RotateY(fx32 sin, fx32 cos, MtxFx43 *mat);
static DrawPlaneFunc Unk_02100DA0[2] = {
sub_020A0500,
sub_020A0444,
static DrawPlaneFunc sPlaneDrawingFunctions[2] = {
SPLUtil_DrawXYPlane,
SPLUtil_DrawXZPlane,
};
static RotFunc Unk_02100DA8[2] = {
sub_020A0358,
sub_020A0398,
static RotFunc sRotationFunctions[2] = {
SPLUtil_RotateY,
SPLUtil_RotateXYZ,
};
static void sub_020A0500(fx16 s, fx16 t, fx16 offsetX, fx16 offsetY)
// Returns `TRUE` if the particle should not be drawn
static inline BOOL SPLDraw_Setup(const SPLParticle *ptcl, const SPLManager *mgr)
{
G3_Begin(GX_BEGIN_QUADS);
G3_TexCoord(0, 0);
G3_Vtx10(offsetX - FX32_ONE, offsetY + FX32_ONE, 0);
G3_TexCoord(s, 0);
G3_Vtx10(offsetX + FX32_ONE, offsetY + FX32_ONE, 0);
G3_TexCoord(s, t);
G3_Vtx10(offsetX + FX32_ONE, offsetY - FX32_ONE, 0);
G3_TexCoord(0, t);
G3_Vtx10(offsetX - FX32_ONE, offsetY - FX32_ONE, 0);
G3_End();
}
static void sub_020A0444(fx16 s, fx16 t, fx16 offsetX, fx16 offsetZ)
{
G3_Begin(GX_BEGIN_QUADS);
G3_TexCoord(0, 0);
G3_Vtx10(offsetX - FX32_ONE, 0, offsetZ + FX32_ONE);
G3_TexCoord(s, 0);
G3_Vtx10(offsetX + FX32_ONE, 0, offsetZ + FX32_ONE);
G3_TexCoord(s, t);
G3_Vtx10(offsetX + FX32_ONE, 0, offsetZ - FX32_ONE);
G3_TexCoord(0, t);
G3_Vtx10(offsetX - FX32_ONE, 0, offsetZ - FX32_ONE);
G3_End();
}
static void sub_020A0398(fx32 sin, fx32 cos, MtxFx43 *mat)
{
fx32 C, Sm, Sp;
C = FX_MUL(FX32_ONE - cos, FX32_CONST(1 / 3.0));
Sm = C + FX_MUL(sin, FX32_SQRT1_3);
Sp = C - FX_MUL(sin, FX32_SQRT1_3);
C += cos;
mat->m[0][0] = C;
mat->m[1][0] = Sm;
mat->m[2][0] = Sp;
mat->m[3][0] = 0;
mat->m[0][1] = Sp;
mat->m[1][1] = C;
mat->m[2][1] = Sm;
mat->m[3][1] = 0;
mat->m[0][2] = Sm;
mat->m[1][2] = Sp;
mat->m[2][2] = C;
mat->m[3][2] = 0;
}
static void sub_020A0358(fx32 sin, fx32 cos, MtxFx43 *mat)
{
mat->m[0][0] = cos;
mat->m[1][0] = 0;
mat->m[2][0] = sin;
mat->m[3][0] = 0;
mat->m[0][1] = 0;
mat->m[1][1] = FX32_ONE;
mat->m[2][1] = 0;
mat->m[3][1] = 0;
mat->m[0][2] = -sin;
mat->m[1][2] = 0;
mat->m[2][2] = cos;
mat->m[3][2] = 0;
}
void sub_0209FF0C(SPLManager *mgr, SPLParticle *ptcl)
{
fx32 aspect;
const MtxFx43 *cmr;
VecFx32 trs;
fx32 sclX, sclY;
MtxFx43 load;
fx32 sin;
fx16 animScale;
GXRgb ptclCol, emtrCol;
u8 scaleAnimDirect;
SPLEmitter *emtr = mgr->renderState.emitter;
SPLResourceHeader *resBase = emtr->resource->header;
cmr = mgr->renderState.viewMatrix;
aspect = mgr->renderState.emitter->resource->header->unk_30;
animScale = ptcl->animScale;
ptclCol = ptcl->color;
emtrCol = emtr->color;
scaleAnimDirect = resBase->misc.unk_07_4;
fx32 alpha = ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1) >> 5;
G3_PolygonAttr(
GX_LIGHTMASK_NONE,
GX_POLYGONMODE_MODULATE,
GX_CULL_NONE,
ptcl->visibility.currentPolygonID,
alpha,
mgr->unk_3C);
reg_G3_POLYGON_ATTR;
if (alpha == 0) {
return;
}
sclY = ptcl->baseScale;
sclX = FX_MUL(sclY, aspect);
if (scaleAnimDirect == 0) {
sclX = FX_MUL(sclX, animScale);
sclY = FX_MUL(sclY, animScale);
} else if (scaleAnimDirect == 1) {
sclX = FX_MUL(sclX, animScale);
} else {
sclY = FX_MUL(sclY, animScale);
}
if (!mgr->renderState.emitter->resource->header->flags.unk_06_7) {
trs.x = ptcl->position.x + ptcl->emitterPos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z;
MTX_MultVec43(&trs, cmr, &trs);
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;
load.m[1][0] = FX_MUL(-sin, sclY);
load.m[1][1] = FX_MUL(cos, sclY);
load.m[1][2] = 0;
load.m[2][0] = 0;
load.m[2][1] = 0;
load.m[2][2] = FX32_ONE;
load.m[3][0] = trs.x;
load.m[3][1] = trs.y;
load.m[3][2] = trs.z;
G3_Identity();
G3_MultMtx43(&load);
} else {
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->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;
load.m[1][0] = FX_MUL(-sin, sclY);
load.m[1][1] = FX_MUL(cos, sclY);
load.m[1][2] = 0;
load.m[2][0] = 0;
load.m[2][1] = 0;
load.m[2][2] = FX32_ONE;
load.m[3][0] = trs.x;
load.m[3][1] = trs.y;
load.m[3][2] = trs.z;
G3_Identity();
SPLResourceHeader *resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_MultMtx43(&load);
}
G3_Color(GX_RGB(
GX_RGB_R_(ptclCol) * GX_RGB_R_(emtrCol) >> 5,
GX_RGB_G_(ptclCol) * GX_RGB_G_(emtrCol) >> 15,
GX_RGB_B_(ptclCol) * GX_RGB_B_(emtrCol) >> 25));
emtr = mgr->renderState.emitter;
sub_020A0500(emtr->unk_E8, emtr->unk_EA, emtr->resource->header->unk_54, emtr->resource->header->unk_56);
}
void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
{
fx32 aspect;
const MtxFx43 *cmr;
VecFx32 trs;
fx32 sclX, sclY;
MtxFx43 load;
fx32 sin;
cmr = mgr->renderState.viewMatrix;
aspect = mgr->renderState.emitter->resource->header->unk_30;
fx32 alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
G3_PolygonAttr(
@ -250,37 +53,106 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
alpha,
mgr->unk_3C);
reg_G3_POLYGON_ATTR;
reg_G3_POLYGON_ATTR; // No idea why but this is needed to match
if (alpha == 0) {
return alpha == 0;
}
static void SPLUtil_DrawXYPlane(fx16 s, fx16 t, fx16 x, fx16 y)
{
G3_Begin(GX_BEGIN_QUADS);
G3_TexCoord(0, 0);
G3_Vtx10(x - FX32_ONE, y + FX32_ONE, 0);
G3_TexCoord(s, 0);
G3_Vtx10(x + FX32_ONE, y + FX32_ONE, 0);
G3_TexCoord(s, t);
G3_Vtx10(x + FX32_ONE, y - FX32_ONE, 0);
G3_TexCoord(0, t);
G3_Vtx10(x - FX32_ONE, y - FX32_ONE, 0);
G3_End();
}
static void SPLUtil_DrawXZPlane(fx16 s, fx16 t, fx16 x, fx16 z)
{
G3_Begin(GX_BEGIN_QUADS);
G3_TexCoord(0, 0);
G3_Vtx10(x - FX32_ONE, 0, z + FX32_ONE);
G3_TexCoord(s, 0);
G3_Vtx10(x + FX32_ONE, 0, z + FX32_ONE);
G3_TexCoord(s, t);
G3_Vtx10(x + FX32_ONE, 0, z - FX32_ONE);
G3_TexCoord(0, t);
G3_Vtx10(x - FX32_ONE, 0, z - FX32_ONE);
G3_End();
}
static void SPLUtil_RotateXYZ(fx32 sin, fx32 cos, MtxFx43 *mat)
{
fx32 C, Sm, Sp;
C = FX_MUL(FX32_ONE - cos, FX32_CONST(1 / 3.0));
Sm = C + FX_MUL(sin, FX32_SQRT1_3);
Sp = C - FX_MUL(sin, FX32_SQRT1_3);
C += cos;
mat->m[0][0] = C; mat->m[1][0] = Sm; mat->m[2][0] = Sp; mat->m[3][0] = 0;
mat->m[0][1] = Sp; mat->m[1][1] = C; mat->m[2][1] = Sm; mat->m[3][1] = 0;
mat->m[0][2] = Sm; mat->m[1][2] = Sp; mat->m[2][2] = C; mat->m[3][2] = 0;
}
static void SPLUtil_RotateY(fx32 sin, fx32 cos, MtxFx43 *mat)
{
mat->m[0][0] = cos; mat->m[1][0] = 0; mat->m[2][0] = sin; mat->m[3][0] = 0;
mat->m[0][1] = 0; mat->m[1][1] = FX32_ONE; mat->m[2][1] = 0; mat->m[3][1] = 0;
mat->m[0][2] = -sin; mat->m[1][2] = 0; mat->m[2][2] = cos; mat->m[3][2] = 0;
}
void SPLDraw_Billboard(SPLManager *mgr, SPLParticle *ptcl)
{
VecFx32 trs;
fx32 sclX, sclY;
MtxFx43 load;
const MtxFx43 *cmr = mgr->renderState.viewMatrix;
fx32 aspect = mgr->renderState.emitter->resource->header->aspectRatio;
fx16 animScale = ptcl->animScale;
GXRgb ptclCol = ptcl->color;
GXRgb emtrCol = mgr->renderState.emitter->color;
u8 scaleAnimDir = mgr->renderState.emitter->resource->header->misc.scaleAnimDir;
if (SPLDraw_Setup(ptcl, mgr)) {
return;
}
sclY = ptcl->baseScale;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
case 0:
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case 1:
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case 2:
sclY = FX_MUL(sclY, ptcl->animScale);
break;
if (scaleAnimDir == SPL_SCALE_ANIM_DIR_XY) {
sclX = FX_MUL(sclX, animScale);
sclY = FX_MUL(sclY, animScale);
} else if (scaleAnimDir == SPL_SCALE_ANIM_DIR_X) {
sclX = FX_MUL(sclX, animScale);
} else { // SPL_SCALE_ANIM_DIR_Y
sclY = FX_MUL(sclY, animScale);
}
if (!mgr->renderState.emitter->resource->header->flags.unk_06_7) {
if (!mgr->renderState.emitter->resource->header->flags.useViewSpace) {
trs.x = ptcl->position.x + ptcl->emitterPos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z;
MTX_MultVec43(&trs, cmr, &trs);
sin = FX_SinIdx(ptcl->rotation);
fx32 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);
@ -303,7 +175,7 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
trs.z = ptcl->position.z + ptcl->emitterPos.z - mgr->renderState.emitter->resource->header->emitterBasePos.z;
MTX_MultVec43(&trs, cmr, &trs);
sin = FX_SinIdx(ptcl->rotation);
fx32 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);
@ -319,21 +191,114 @@ void sub_0209FAB8(SPLManager *mgr, SPLParticle *ptcl)
load.m[3][2] = trs.z;
G3_Identity();
SPLResourceHeader *resBase = mgr->renderState.emitter->resource->header;
G3_Translate(resBase->emitterBasePos.x, resBase->emitterBasePos.y, resBase->emitterBasePos.z);
G3_Translate(
mgr->renderState.emitter->resource->header->emitterBasePos.x,
mgr->renderState.emitter->resource->header->emitterBasePos.y,
mgr->renderState.emitter->resource->header->emitterBasePos.z);
G3_MultMtx43(&load);
}
GXRgb colA = ptcl->color;
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));
GX_RGB_R_(ptclCol) * GX_RGB_R_(emtrCol) >> 5,
GX_RGB_G_(ptclCol) * GX_RGB_G_(emtrCol) >> 15,
GX_RGB_B_(ptclCol) * GX_RGB_B_(emtrCol) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
sub_020A0500(emtr->unk_EC, emtr->unk_EE, 0, 0);
SPLUtil_DrawXYPlane(
mgr->renderState.emitter->textureS,
mgr->renderState.emitter->textureT,
mgr->renderState.emitter->resource->header->polygonX,
mgr->renderState.emitter->resource->header->polygonY);
}
void SPLDraw_Child_Billboard(SPLManager *mgr, SPLParticle *ptcl)
{
VecFx32 trs;
fx32 sclX, sclY;
MtxFx43 load;
const MtxFx43 *cmr = mgr->renderState.viewMatrix;
fx32 aspect = mgr->renderState.emitter->resource->header->aspectRatio;
if (SPLDraw_Setup(ptcl, mgr)) {
return;
}
sclY = ptcl->baseScale;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->misc.scaleAnimDir) {
case SPL_SCALE_ANIM_DIR_XY:
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
break;
case SPL_SCALE_ANIM_DIR_X:
sclX = FX_MUL(sclX, ptcl->animScale);
break;
case SPL_SCALE_ANIM_DIR_Y:
sclY = FX_MUL(sclY, ptcl->animScale);
break;
}
if (!mgr->renderState.emitter->resource->header->flags.useViewSpace) {
trs.x = ptcl->position.x + ptcl->emitterPos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z;
MTX_MultVec43(&trs, cmr, &trs);
fx32 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;
load.m[1][0] = FX_MUL(-sin, sclY);
load.m[1][1] = FX_MUL(cos, sclY);
load.m[1][2] = 0;
load.m[2][0] = 0;
load.m[2][1] = 0;
load.m[2][2] = FX32_ONE;
load.m[3][0] = trs.x;
load.m[3][1] = trs.y;
load.m[3][2] = trs.z;
G3_Identity();
G3_MultMtx43(&load);
} else {
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);
fx32 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;
load.m[1][0] = FX_MUL(-sin, sclY);
load.m[1][1] = FX_MUL(cos, sclY);
load.m[1][2] = 0;
load.m[2][0] = 0;
load.m[2][1] = 0;
load.m[2][2] = FX32_ONE;
load.m[3][0] = trs.x;
load.m[3][1] = trs.y;
load.m[3][2] = trs.z;
G3_Identity();
G3_Translate(
mgr->renderState.emitter->resource->header->emitterBasePos.x,
mgr->renderState.emitter->resource->header->emitterBasePos.y,
mgr->renderState.emitter->resource->header->emitterBasePos.z);
G3_MultMtx43(&load);
}
G3_Color(GX_RGB(
GX_RGB_R_(ptcl->color) * GX_RGB_R_(mgr->renderState.emitter->color) >> 5,
GX_RGB_G_(ptcl->color) * GX_RGB_G_(mgr->renderState.emitter->color) >> 15,
GX_RGB_B_(ptcl->color) * GX_RGB_B_(mgr->renderState.emitter->color) >> 25));
SPLUtil_DrawXYPlane(mgr->renderState.emitter->childTextureS, mgr->renderState.emitter->childTextureT, 0, 0);
}
void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
@ -349,7 +314,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
MtxFx43 load;
cmr = mgr->renderState.viewMatrix;
aspect = mgr->renderState.emitter->resource->header->unk_30;
aspect = mgr->renderState.emitter->resource->header->aspectRatio;
fx32 alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
@ -370,7 +335,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
sclY = ptcl->baseScale;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
switch (mgr->renderState.emitter->resource->header->misc.scaleAnimDir) {
case 0:
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
@ -385,7 +350,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
break;
}
if (!mgr->renderState.emitter->resource->header->flags.unk_06_7) {
if (!mgr->renderState.emitter->resource->header->flags.useViewSpace) {
trs.x = ptcl->position.x + ptcl->emitterPos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z;
@ -402,7 +367,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
}
VEC_Normalize(&dir, &dir);
MI_Copy36B(cmr, &mtx);
MTX_Copy43To33(cmr, &mtx);
MTX_MultVec33(&dir, &mtx, &dir);
MTX_MultVec43(&trs, cmr, &trs);
@ -417,12 +382,12 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
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;
load.m[3][0] = trs.x;
load.m[3][1] = trs.y;
load.m[0][1] = FX_MUL(dir.y, sclX);
load.m[1][1] = FX_MUL(dir.x, dot);
load.m[2][0] = 0;
load.m[2][1] = 0;
load.m[3][1] = trs.y;
load.m[0][2] = 0;
load.m[1][2] = 0;
load.m[2][2] = FX32_ONE;
@ -447,7 +412,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
}
VEC_Normalize(&dir, &dir);
MI_Copy36B(cmr, &mtx);
MTX_Copy43To33(cmr, &mtx);
MTX_MultVec33(&dir, &mtx, &dir);
MTX_MultVec43(&trs, cmr, &trs);
@ -488,7 +453,7 @@ void sub_0209F3D0(SPLManager *mgr, SPLParticle *ptcl)
GX_RGB_B_(colA) * GX_RGB_B_(colB) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
sub_020A0500(emtr->unk_E8, emtr->unk_EA, emtr->resource->header->unk_54, emtr->resource->header->unk_56);
SPLUtil_DrawXYPlane(emtr->textureS, emtr->textureT, emtr->resource->header->polygonX, emtr->resource->header->polygonY);
}
void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
@ -504,7 +469,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
MtxFx43 load;
cmr = mgr->renderState.viewMatrix;
aspect = mgr->renderState.emitter->resource->header->unk_30;
aspect = mgr->renderState.emitter->resource->header->aspectRatio;
fx32 alpha = (fx32)(ptcl->visibility.baseAlpha * (ptcl->visibility.animAlpha + 1)) >> 5;
@ -525,7 +490,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
sclY = ptcl->baseScale;
sclX = FX_MUL(sclY, aspect);
switch (mgr->renderState.emitter->resource->header->misc.unk_07_4) {
switch (mgr->renderState.emitter->resource->header->misc.scaleAnimDir) {
case 0:
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
@ -540,7 +505,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
break;
}
if (!mgr->renderState.emitter->resource->header->flags.unk_06_7) {
if (!mgr->renderState.emitter->resource->header->flags.useViewSpace) {
trs.x = ptcl->position.x + ptcl->emitterPos.x;
trs.y = ptcl->position.y + ptcl->emitterPos.y;
trs.z = ptcl->position.z + ptcl->emitterPos.z;
@ -557,7 +522,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
}
VEC_Normalize(&dir, &dir);
MI_Copy36B(cmr, &mtx);
MTX_Copy43To33(cmr, &mtx);
MTX_MultVec33(&dir, &mtx, &dir);
MTX_MultVec43(&trs, cmr, &trs);
@ -572,12 +537,12 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
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;
load.m[3][0] = trs.x;
load.m[3][1] = trs.y;
load.m[0][1] = FX_MUL(dir.y, sclX);
load.m[1][1] = FX_MUL(dir.x, dot);
load.m[2][0] = 0;
load.m[2][1] = 0;
load.m[3][1] = trs.y;
load.m[0][2] = 0;
load.m[1][2] = 0;
load.m[2][2] = FX32_ONE;
@ -602,7 +567,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
}
VEC_Normalize(&dir, &dir);
MI_Copy36B(cmr, &mtx);
MTX_Copy43To33(cmr, &mtx);
MTX_MultVec33(&dir, &mtx, &dir);
MTX_MultVec43(&trs, cmr, &trs);
@ -643,7 +608,7 @@ void sub_0209ECF0(SPLManager *mgr, SPLParticle *ptcl)
GX_RGB_B_(colA) * GX_RGB_B_(colB) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
sub_020A0500(emtr->unk_EC, emtr->unk_EE, 0, 0);
SPLUtil_DrawXYPlane(emtr->childTextureS, emtr->childTextureT, 0, 0);
}
void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
@ -672,13 +637,13 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sRotationFunctions[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sclY = ptcl->baseScale;
resBase = mgr->renderState.emitter->resource->header;
sclX = FX_MUL(sclY, resBase->unk_30);
sclX = FX_MUL(sclY, resBase->aspectRatio);
switch (resBase->misc.unk_07_4) {
switch (resBase->misc.scaleAnimDir) {
case 0:
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
@ -697,7 +662,7 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
MTX_Concat43(&sclMtx, &rotMtx, &load);
// resBase = mgr->unk_40.unk_00->p_res->header;
if (!mgr->renderState.emitter->resource->header->flags.unk_06_7) {
if (!mgr->renderState.emitter->resource->header->flags.useViewSpace) {
load.m[3][0] = ptcl->position.x + ptcl->emitterPos.x;
load.m[3][1] = ptcl->position.y + ptcl->emitterPos.y;
load.m[3][2] = ptcl->position.z + ptcl->emitterPos.z;
@ -726,7 +691,7 @@ void sub_0209E9A0(SPLManager *mgr, SPLParticle *ptcl)
SPLEmitter *emtr = mgr->renderState.emitter;
resBase = emtr->resource->header;
Unk_02100DA0[resBase->flags.unk_06_3](emtr->unk_E8, emtr->unk_EA, resBase->unk_54, resBase->unk_56);
sPlaneDrawingFunctions[resBase->flags.unk_06_3](emtr->textureS, emtr->textureT, resBase->polygonX, resBase->polygonY);
}
void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
@ -755,13 +720,13 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sRotationFunctions[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sclY = ptcl->baseScale;
resBase = mgr->renderState.emitter->resource->header;
sclX = FX_MUL(sclY, resBase->unk_30);
sclX = FX_MUL(sclY, resBase->aspectRatio);
switch (resBase->misc.unk_07_4) {
switch (resBase->misc.scaleAnimDir) {
case 0:
sclX = FX_MUL(sclX, ptcl->animScale);
sclY = FX_MUL(sclY, ptcl->animScale);
@ -779,7 +744,7 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
MTX_Scale43(&sclMtx, sclX, sclY, sclY);
MTX_Concat43(&rotMtx, &sclMtx, &load);
if (!mgr->renderState.emitter->resource->header->flags.unk_06_7) {
if (!mgr->renderState.emitter->resource->header->flags.useViewSpace) {
load.m[3][0] = ptcl->position.x + ptcl->emitterPos.x;
load.m[3][1] = ptcl->position.y + ptcl->emitterPos.y;
load.m[3][2] = ptcl->position.z + ptcl->emitterPos.z;
@ -806,7 +771,7 @@ void sub_0209E650(SPLManager *mgr, SPLParticle *ptcl)
GX_RGB_B_(colA) * GX_RGB_B_(colB) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
Unk_02100DA0[emtr->resource->childResource->flags.unk_03_3](emtr->unk_EC, emtr->unk_EE, 0, 0);
sPlaneDrawingFunctions[emtr->resource->childResource->flags.unk_03_3](emtr->childTextureS, emtr->childTextureT, 0, 0);
}
void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
@ -837,7 +802,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMat);
sRotationFunctions[mgr->renderState.emitter->resource->header->flags.unk_06_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMat);
MTX_Identity43(&mat);
@ -877,9 +842,9 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
resBase = mgr->renderState.emitter->resource->header;
scaleY = ptcl->baseScale;
scaleX = FX_MUL(scaleY, resBase->unk_30);
scaleX = FX_MUL(scaleY, resBase->aspectRatio);
switch (resBase->misc.unk_07_4) {
switch (resBase->misc.scaleAnimDir) {
case 0:
scaleX = FX_MUL(scaleX, ptcl->animScale);
scaleY = FX_MUL(scaleY, ptcl->animScale);
@ -898,7 +863,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
MTX_Concat43(&sclMat, &rotMat, &transform);
resBase = mgr->renderState.emitter->resource->header;
if (!resBase->flags.unk_06_7) {
if (!resBase->flags.useViewSpace) {
transform.m[3][0] = ptcl->position.x + ptcl->emitterPos.x;
transform.m[3][1] = ptcl->position.y + ptcl->emitterPos.y;
transform.m[3][2] = ptcl->position.z + ptcl->emitterPos.z;
@ -926,7 +891,7 @@ void sub_0209E1D4(SPLManager *mgr, SPLParticle *ptcl)
emtr = mgr->renderState.emitter;
resBase = emtr->resource->header;
Unk_02100DA0[resBase->flags.unk_06_3](emtr->unk_E8, emtr->unk_EA, resBase->unk_54, resBase->unk_56);
sPlaneDrawingFunctions[resBase->flags.unk_06_3](emtr->textureS, emtr->textureT, resBase->polygonX, resBase->polygonY);
}
void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
@ -955,7 +920,7 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
return;
}
Unk_02100DA8[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
sRotationFunctions[mgr->renderState.emitter->resource->childResource->flags.unk_03_1](FX_SinIdx(ptcl->rotation), FX_CosIdx(ptcl->rotation), &rotMtx);
MTX_Identity43(&mat);
@ -995,9 +960,9 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
resBase = mgr->renderState.emitter->resource->header;
scaleY = ptcl->baseScale;
scaleX = FX_MUL(scaleY, resBase->unk_30);
scaleX = FX_MUL(scaleY, resBase->aspectRatio);
switch (resBase->misc.unk_07_4) {
switch (resBase->misc.scaleAnimDir) {
case 0:
scaleX = FX_MUL(scaleX, ptcl->animScale);
scaleY = FX_MUL(scaleY, ptcl->animScale);
@ -1016,7 +981,7 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
MTX_Concat43(&rotMtx, &sclMat, &transform);
resBase = mgr->renderState.emitter->resource->header;
if (!resBase->flags.unk_06_7) {
if (!resBase->flags.useViewSpace) {
transform.m[3][0] = ptcl->position.x + ptcl->emitterPos.x;
transform.m[3][1] = ptcl->position.y + ptcl->emitterPos.y;
transform.m[3][2] = ptcl->position.z + ptcl->emitterPos.z;
@ -1043,5 +1008,5 @@ void sub_0209DD54(SPLManager *mgr, SPLParticle *ptcl)
GX_RGB_B_(colA) * GX_RGB_B_(colB) >> 25));
SPLEmitter *emtr = mgr->renderState.emitter;
Unk_02100DA0[emtr->resource->childResource->flags.unk_03_3](emtr->unk_EC, emtr->unk_EE, 0, 0);
sPlaneDrawingFunctions[emtr->resource->childResource->flags.unk_03_3](emtr->childTextureS, emtr->childTextureT, 0, 0);
}