diff options
| author | robojumper <robojumper@gmail.com> | 2025-03-22 12:34:18 +0100 |
|---|---|---|
| committer | robojumper <robojumper@gmail.com> | 2025-03-22 12:34:18 +0100 |
| commit | 510df58ea4d587d3aeff295b4d05708fffd52d00 (patch) | |
| tree | 2d7dd0c643b233e1bcc5d5dd678e06c9d0e85031 /src/egg/gfx/eggLightObject.cpp | |
| parent | 818e818b56af7584c2f9b8274f68a2ff664605e3 (diff) | |
eggLightObject good enough
Diffstat (limited to 'src/egg/gfx/eggLightObject.cpp')
| -rw-r--r-- | src/egg/gfx/eggLightObject.cpp | 270 |
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 {} |
