summaryrefslogtreecommitdiff
path: root/src/egg/gfx/eggLightObject.cpp
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2025-03-22 12:34:18 +0100
committerrobojumper <robojumper@gmail.com>2025-03-22 12:34:18 +0100
commit510df58ea4d587d3aeff295b4d05708fffd52d00 (patch)
tree2d7dd0c643b233e1bcc5d5dd678e06c9d0e85031 /src/egg/gfx/eggLightObject.cpp
parent818e818b56af7584c2f9b8274f68a2ff664605e3 (diff)
eggLightObject good enough
Diffstat (limited to 'src/egg/gfx/eggLightObject.cpp')
-rw-r--r--src/egg/gfx/eggLightObject.cpp270
1 files changed, 233 insertions, 37 deletions
diff --git a/src/egg/gfx/eggLightObject.cpp b/src/egg/gfx/eggLightObject.cpp
index 9eb4db95..1c5703c7 100644
--- a/src/egg/gfx/eggLightObject.cpp
+++ b/src/egg/gfx/eggLightObject.cpp
@@ -1,6 +1,10 @@
#include "egg/gfx/eggLightObject.h"
+#include "common.h"
#include "egg/gfx/eggDrawGX.h"
+#include "egg/gfx/eggLightTexture.h"
+#include "nw4r/g3d/g3d_light.h"
+#include "nw4r/g3d/res/g3d_resanmlight.h"
#include "nw4r/math/math_arithmetic.h"
#include "nw4r/math/math_types.h"
#include "rvl/GX/GXLight.h"
@@ -8,6 +12,12 @@
#include "rvl/MTX/mtxvec.h"
#include "rvl/MTX/vec.h"
+// TODO: This whole file does weird things with vectors!
+// NSMBW symbol names indicate that functions use nw4r::math::VEC3
+// arguments and we have some nw4r PS inlines, but
+// a fair number of vector assignments happen in a weird order
+// which might indicate EGG::Vector3f?
+
namespace EGG {
template <>
@@ -35,17 +45,17 @@ LightObject::LightObject()
mBlack(DrawGX::BLACK),
field_0x3C(0),
field_0x3D(1),
- mSpotFn(0),
- mDistAttnFn(0),
+ mSpotFn(GX_SP_OFF),
+ mDistAttnFn(GX_DA_OFF),
field_0x40(90.0f),
field_0x44(0.5f),
field_0x48(0.5f),
- field_0x64(16.0f),
- field_0x68(0x661) {}
+ mShininess(16.0f),
+ mFlags(0x661) {}
void LightObject::Reset() {
SetPosAt(nw4r::math::VEC3(-10000.0f, 10000.0f, 10000.0f), zeroVec);
- field_0x68 = 0x661;
+ mFlags = 0x661;
mWhite = DrawGX::WHITE;
mBlack = DrawGX::BLACK;
field_0x30 = 1.0;
@@ -54,24 +64,24 @@ void LightObject::Reset() {
field_0x40 = 90.0;
field_0x44 = 0.5;
field_0x48 = 0.5;
- mSpotFn = 0;
- mDistAttnFn = 0;
- field_0x64 = 16.0;
+ mSpotFn = GX_SP_OFF;
+ mDistAttnFn = GX_DA_OFF;
+ mShininess = 16.0;
field_0x58.x = 1.0;
field_0x4C.x = 1.0;
field_0x58.z = 0.0;
- field_0x4C.y = 0.0;
- field_0x58.y = 0.0;
field_0x4C.z = 0.0;
+ field_0x58.y = 0.0;
+ field_0x4C.y = 0.0;
}
void LightObject::Calc() {
field_0x6C = mDir;
- field_0x78 = mWhite;
+ mLightColor = mWhite;
}
void LightObject::CalcView(nw4r::math::MTX34 const &viewMtx) {
- if ((field_0x68 & 1) == 0) {
+ if ((mFlags & 1) == 0) {
return;
}
@@ -80,35 +90,35 @@ void LightObject::CalcView(nw4r::math::MTX34 const &viewMtx) {
case 3: {
// Halp
f32 scale = -1.0f;
- field_0x88.x = 0.0f;
+ mViewAt.x = 0.0f;
field_0x94.x = 0.0f;
- field_0x88.y = 0.0f;
+ mViewAt.y = 0.0f;
field_0x94.y = 0.0f;
field_0x94.z = -1.0f;
- field_0x88.z = scale * mDist;
- field_0x7C.z = 0.0f;
- field_0x7C.y = 0.0f;
- field_0x7C.x = 0.0f;
+ mViewAt.z = scale * mDist;
+ mViewPos.z = 0.0f;
+ mViewPos.y = 0.0f;
+ mViewPos.x = 0.0f;
break;
}
case 4: {
// Halp
f32 scale = 1.0f;
- field_0x7C.x = 0.0f;
+ mViewPos.x = 0.0f;
field_0x94.x = 0.0f;
- field_0x7C.y = 0.0f;
+ mViewPos.y = 0.0f;
field_0x94.y = 0.0f;
field_0x94.z = 1.0f;
- field_0x7C.z = scale * mDist;
- field_0x88.z = 0.0f;
- field_0x88.y = 0.0f;
- field_0x88.x = 0.0f;
+ mViewPos.z = scale * mDist;
+ mViewAt.z = 0.0f;
+ mViewAt.y = 0.0f;
+ mViewAt.x = 0.0f;
break;
}
case 2:
field_0x94 = mDir;
- field_0x88 = mAt;
- field_0x7C = mPos;
+ mViewAt = mAt;
+ mViewPos = mPos;
break;
}
@@ -126,15 +136,30 @@ void LightObject::CalcView(nw4r::math::MTX34 const &viewMtx) {
field_0x6C.z = 1.0f;
}
}
- PSMTXMultVec(viewMtx, mPos, field_0x7C);
- PSMTXMultVec(viewMtx, mAt, field_0x88);
+ PSMTXMultVec(viewMtx, mPos, mViewPos);
+ PSMTXMultVec(viewMtx, mAt, mViewAt);
nw4r::math::VEC3TransformNormal(&field_0x94, &viewMtx, &field_0x6C);
}
}
+void LightObject::fn_804A9C30(const LightTexture *tex, nw4r::math::VEC3 *pVec, GXColor *color) const {
+ *pVec = field_0x94;
+ *color = mLightColor;
+ f32 f = tex->getFloat(mIndex);
+ if (f < 1.0f) {
+ color->r = color->r * f;
+ color->g = color->g * f;
+ color->b = color->b * f;
+ color->a = color->a * f;
+ } else {
+ // Yes
+ *color = *color;
+ }
+}
+
void LightObject::InitGX(GXLightObj *obj) const {
- if ((field_0x68 & 1) != 0 && ((field_0x68 >> 6) & 1) != 0) {
- GXInitLightColor(obj, field_0x78);
+ if ((mFlags & 1) != 0 && ((mFlags >> 6) & 1) != 0) {
+ GXInitLightColor(obj, mLightColor);
switch (field_0x3D) {
case 1: {
nw4r::math::VEC3 tmp = field_0x94 * -1e10f;
@@ -143,31 +168,31 @@ void LightObject::InitGX(GXLightObj *obj) const {
break;
}
case 0: {
- GXInitLightPos(obj, field_0x7C.x, field_0x7C.y, field_0x7C.z);
+ GXInitLightPos(obj, mViewPos.x, mViewPos.y, mViewPos.z);
GXInitLightDir(obj, zeroVec[0], zeroVec[1], zeroVec[2]);
break;
}
case 2: {
- GXInitLightPos(obj, field_0x7C.x, field_0x7C.y, field_0x7C.z);
+ GXInitLightPos(obj, mViewPos.x, mViewPos.y, mViewPos.z);
GXInitLightDir(obj, field_0x94.x, field_0x94.y, field_0x94.z);
break;
}
}
- if ((field_0x68 & 0x80) != 0) {
+ if ((mFlags & 0x80) != 0) {
GXInitLightAttnA(obj, field_0x4C.x, field_0x4C.y, field_0x4C.z);
} else {
GXInitLightSpot(obj, field_0x40 > 0.0f ? field_0x40 : 0.0001f, getSpotFn());
}
- if ((field_0x68 & 0x100) != 0) {
+ if ((mFlags & 0x100) != 0) {
GXInitLightAttnK(obj, field_0x58.x, field_0x58.y, field_0x58.z);
} else {
GXInitLightDistAttn(obj, field_0x44 * getDistance(), field_0x48, getDistAttnFn());
}
- if ((field_0x68 & 0x800) != 0) {
- f32 ka = field_0x64 / 2.0f;
+ if ((mFlags & 0x800) != 0) {
+ f32 ka = mShininess / 2.0f;
GXInitLightAttn(obj, 0.0f, 0.0f, 1.0f, ka, 0.0f, 1.0f - ka);
}
@@ -176,6 +201,178 @@ void LightObject::InitGX(GXLightObj *obj) const {
}
}
+void LightObject::CopyToG3D_World(nw4r::g3d::LightObj &g3dObj) const {
+ if ((mFlags & 1) != 0 && (mFlags & 0x40) != 0) {
+ g3dObj.Clear();
+ if ((mFlags & 0x200) == 0) {
+ g3dObj.DisableColor();
+ }
+ if ((mFlags & 0x400) == 0) {
+ g3dObj.DisableAlpha();
+ }
+
+ g3dObj.Enable();
+ g3dObj.InitLightColor(mLightColor);
+
+ if ((mFlags & 0x80) != 0) {
+ g3dObj.InitLightAttnA(field_0x4C.x, field_0x4C.y, field_0x4C.z);
+ } else {
+ g3dObj.InitLightSpot(field_0x40 > 0.0f ? field_0x40 : 0.0001f, getSpotFn());
+ }
+
+ if ((mFlags & 0x100) != 0) {
+ g3dObj.InitLightAttnK(field_0x58.x, field_0x58.y, field_0x58.z);
+ } else {
+ g3dObj.InitLightDistAttn(field_0x44 * getDistance(), field_0x48, getDistAttnFn());
+ }
+
+ if ((mFlags & 0x800) != 0) {
+ g3dObj.InitLightShininess(mShininess);
+ }
+ } else {
+ g3dObj.Disable();
+ }
+}
+
+void LightObject::CopyToG3D_View(nw4r::g3d::LightObj &g3dObj, const nw4r::math::MTX34 &viewMtx) const {
+ if (!g3dObj.IsEnable()) {
+ return;
+ }
+
+ // TODO
+ if (!(mFlags & 0x800)) {
+ nw4r::math::VEC3 dir;
+ nw4r::math::VEC3 pos;
+ switch (field_0x3D) {
+ case 1: {
+ nw4r::math::VEC3TransformNormal(&dir, &viewMtx, &field_0x94);
+ nw4r::math::VEC3Scale(&pos, &dir, -1e10f);
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ dir.x = 0.0f;
+ break;
+ }
+ case 0: {
+ PSMTXMultVec(viewMtx, mViewPos, pos);
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ dir.x = 0.0f;
+ break;
+ }
+ case 2: {
+ PSMTXMultVec(viewMtx, mViewPos, pos);
+ nw4r::math::VEC3TransformNormal(&dir, &viewMtx, &field_0x94);
+ break;
+ }
+ }
+ g3dObj.InitLightPos(pos.x, pos.y, pos.z);
+ g3dObj.InitLightDir(dir.x, dir.y, dir.z);
+ } else {
+ g3dObj.InitSpecularDir(mDir.x, mDir.y, mDir.z);
+ }
+}
+
+void LightObject::CopyFromG3D(
+ const nw4r::g3d::ResAnmLight &g3dLight, f32 frame, EGG::LightObject *optObj, bool skipDoingSomething
+) {
+ nw4r::g3d::LightAnmResult result;
+ g3dLight.GetAnmResult(&result, frame);
+ if (!skipDoingSomething || (result.flags & nw4r::g3d::LightAnmResult::FLAG_LIGHT_ENABLE) != 0) {
+ if ((result.flags & nw4r::g3d::LightAnmResult::FLAG_LIGHT_ENABLE) != 0) {
+ ApplyAnmResultA(result);
+ if (optObj != nullptr && optObj->ApplyAnmResultB(result)) {
+ optObj->field_0x06 = mIndex;
+ optObj->mFlags |= 2;
+ }
+ } else {
+ // TODO
+ mFlags = mFlags & 0xFFFE;
+ if (optObj != nullptr) {
+ optObj->mFlags = optObj->mFlags & 0xFFFE;
+ }
+ }
+ }
+}
+
+void LightObject::ApplyAnmResultInner(const nw4r::g3d::LightAnmResult &res) {
+ // TODO
+ mFlags = mFlags & 0xF07E;
+ field_0x40 = 90.0f;
+ field_0x44 = 0.5f;
+ field_0x48 = 0.5f;
+ mSpotFn = GX_SP_OFF;
+ mDistAttnFn = GX_DA_OFF;
+ mShininess = 16.0f;
+ // ...
+ field_0x58.x = 1.0f;
+ field_0x4C.x = 1.0f;
+ field_0x58.z = 0.0f;
+ field_0x4C.z = 0.0f;
+ field_0x58.y = 0.0f;
+ field_0x4C.y = 0.0f;
+ if ((res.flags & nw4r::g3d::LightAnmResult::FLAG_COLOR_ENABLE) != 0) {
+ mFlags |= 0x200;
+ }
+ if ((res.flags & nw4r::g3d::LightAnmResult::FLAG_ALPHA_ENABLE) != 0) {
+ mFlags |= 0x400;
+ }
+ if ((res.flags & nw4r::g3d::LightAnmResult::FLAG_LIGHT_ENABLE) != 0) {
+ mFlags |= 1;
+ }
+}
+
+void LightObject::ApplyAnmResultA(const nw4r::g3d::LightAnmResult &res) {
+ ApplyAnmResultInner(res);
+ switch ((int)(res.flags & nw4r::g3d::LightAnmResult::FLAG_LIGHT_TYPE_MASK)) {
+ case 0: {
+ field_0x3D = 0;
+ mWhite = res.color;
+ SetPosAt(res.pos, res.pos);
+ field_0x40 = 0.0f;
+ mSpotFn = GX_SP_OFF;
+ field_0x44 = res.refDistance;
+ field_0x48 = res.refBrightness;
+ mDistAttnFn = res.distFunc;
+ break;
+ }
+ case 1: {
+ field_0x3D = 1;
+ mWhite = res.color;
+ SetPosAt(res.pos, res.aim);
+ mSpotFn = GX_SP_OFF;
+ mDistAttnFn = GX_AF_SPEC;
+ break;
+ }
+ case 2: {
+ field_0x3D = 2;
+ mWhite = res.color;
+ SetPosAt(res.pos, res.aim);
+ mSpotFn = res.spotFunc;
+ field_0x40 = res.cutoff;
+ mDistAttnFn = res.distFunc;
+ field_0x44 = res.refDistance;
+ field_0x48 = res.refBrightness;
+ break;
+ }
+ }
+}
+
+bool LightObject::ApplyAnmResultB(const nw4r::g3d::LightAnmResult &res) {
+ if ((res.flags & nw4r::g3d::LightAnmResult::FLAG_SPECULAR_ENABLE) != 0) {
+ ApplyAnmResultInner(res);
+ field_0x3D = 1;
+ mWhite = res.specColor;
+ SetPosAt(res.pos, res.aim);
+ mFlags |= 0x800;
+ mShininess = res.shininess;
+ return true;
+ } else {
+ // TODO
+ mFlags = mFlags & 0xFFFE;
+ return false;
+ }
+}
+
void LightObject::CalcDirDist() {
mDir.x = mAt.x - mPos.x;
mDir.y = mAt.y - mPos.y;
@@ -217,7 +414,6 @@ void LightObject::SetPosAt(nw4r::math::VEC3 const &pos, nw4r::math::VEC3 const &
CalcDirDist();
}
-
void LightObject::SetBinaryInner(const Bin &bin) {}
void LightObject::GetBinaryInner(Bin *bin) const {}