g3d initial pullover (#115)

* g3d Headers

* initial g3d source files -- NOT YET FIXED

* change ResFile static_cast to explicit ctor
This commit is contained in:
Elijah Thomas
2025-02-09 12:40:41 -05:00
committed by GitHub
parent 85bef3afb9
commit cec09ad023
269 changed files with 30456 additions and 4825 deletions
@@ -0,0 +1,220 @@
#ifndef MSL_CPP_ALGORITHM_H
#define MSL_CPP_ALGORITHM_H
#include <iterator>
namespace std {
template <typename T> inline const T& max(const T& a, const T& b) {
return (a < b) ? b : a;
}
template <typename T> inline const T& min(const T& a, const T& b) {
return (b < a) ? b : a;
}
template <typename TPtr, typename T>
inline TPtr find(TPtr first, TPtr last, const T& value) {
while (first != last && *first != value) {
++first;
}
return first;
}
template <typename TPtr> inline long distance(TPtr first, TPtr last) {
random_access_iterator_tag tag;
return __distance(first, last, tag);
}
template <typename TPtr>
inline long __distance(TPtr first, TPtr last,
random_access_iterator_tag /* tag */) {
return static_cast<long>(last - first);
}
template <typename T> inline T& move(T& x) {
return x;
}
template <typename T> inline void swap(T& a, T& b) {
T tmp = move(a);
a = move(b);
b = move(tmp);
}
template <typename TIt, typename TCompare>
inline TIt min_element(TIt first, TIt last, TCompare compare) {
TIt it = first;
if (first != last) {
for (++first; first != last; ++first) {
if (compare(*first, *it)) {
it = first;
}
}
}
return it;
}
template <typename TCompare, typename TIt>
inline void __selection_sort(TIt first, TIt last, TCompare compare) {
if (first == last) {
return;
}
TIt j = last;
for (--j; first != j; ++first) {
TIt i = min_element<TIt, TCompare&>(first, last, compare);
if (i != first) {
swap(*i, *first);
}
}
}
template <typename TCompare, typename TIt>
void __sort132(TIt a1, TIt a2, TIt a3, TCompare compare)
__attribute__((never_inline)) {
bool b1 = !compare(*a3, *a1);
bool b2 = !compare(*a2, *a3);
if (!b1 || !b2) {
if (!b1 && !b2) {
swap(*a1, *a2);
return;
}
if (compare(*a2, *a1)) {
swap(*a1, *a2);
}
if (b1) {
swap(*a2, *a3);
return;
}
swap(*a1, *a3);
}
}
template <typename TIt, typename TCompare>
void sort(TIt first, TIt last, TCompare compare) {
static const int SHUFFLE_MIN = -4;
static const int SHUFFLE_MAX = 5;
static const int SELECTION_SORT_MIN = 20;
while (true) {
long len = static_cast<long>(last - first);
if (len <= 1) {
return;
}
if (len <= SELECTION_SORT_MIN) {
__selection_sort<TCompare&, TIt>(first, last, compare);
return;
}
static int shuffle = -4;
TIt m = first +
(len / static_cast<long>(sizeof(TIt)) + shuffle % SHUFFLE_MAX);
if (++shuffle >= SHUFFLE_MAX) {
shuffle = SHUFFLE_MIN;
}
TIt i1 = first + (len * static_cast<long>(sizeof(TIt) - 1) /
static_cast<long>(sizeof(TIt)) +
shuffle % SHUFFLE_MAX);
if (++shuffle >= SHUFFLE_MAX) {
shuffle = SHUFFLE_MIN;
}
TIt j = last - 1;
__sort132<TCompare&, TIt>(m, i1, j, compare);
m = first;
i1 = j;
while (compare(*m, *j)) {
m++;
}
do {
i1--;
if (m == i1) {
break;
}
} while (!compare(*i1, *j));
if (m < i1) {
swap(*m, *i1);
m++;
while (true) {
while (compare(*m, *j)) {
m++;
}
while (!compare(*--i1, *j)) {
;
}
if (m < i1) {
swap(*m, *i1);
m++;
} else {
break;
}
}
}
if (m == first) {
swap(*m, *j);
m++;
i1 = last;
if (!compare(*first, *--i1)) {
while (m != last && !compare(*first, *m)) {
m++;
}
if (m < i1) {
swap(*m, *i1);
}
}
if (m < i1) {
while (true) {
while (!compare(*first, *m)) {
m++;
}
while (compare(*first, *--i1)) {
;
}
if (m < i1) {
swap(*m, *i1);
m++;
} else {
break;
}
}
}
first = m;
} else if (m - first < last - m) {
sort<TIt, TCompare&>(first, m, compare);
first = m;
} else {
sort<TIt, TCompare&>(m, last, compare);
last = m;
}
}
}
} // namespace std
#endif
@@ -0,0 +1,12 @@
#ifndef MSL_CPP_CCTYPE_H
#define MSL_CPP_CCTYPE_H
#include <ctype.h>
#ifdef __cplusplus
namespace std {
using ::tolower;
using ::toupper;
} // namespace std
#endif
#endif
@@ -0,0 +1,4 @@
#ifndef MSL_CPP_CERRNO_H
#define MSL_CPP_CERRNO_H
#include <errno.h>
#endif
@@ -0,0 +1,4 @@
#ifndef MSL_CPP_CLIMITS_H
#define MSL_CPP_CLIMITS_H
#include <limits.h>
#endif
@@ -0,0 +1,58 @@
#ifndef MSL_CPP_CMATH_H
#define MSL_CPP_CMATH_H
#include <math.h>
#ifdef __cplusplus
// Remove C macro
#undef fabs
namespace std {
using ::acos;
using ::acosf;
using ::asin;
// using ::asinf;
using ::atan;
using ::atan2;
using ::atan2f;
using ::ceil;
using ::ceilf;
using ::copysign;
using ::cos;
using ::cosf;
using ::fabsf;
using ::floor;
using ::floorf;
using ::fmod;
using ::fmodf;
using ::frexp;
using ::ldexp;
// using ::ldexpf;
using ::modf;
using ::modff;
// using ::nan;
using ::pow;
using ::scalbn;
using ::sin;
using ::sinf;
using ::sqrt;
using ::sqrtf;
using ::tan;
using ::tanf;
inline float sqrt(float x) {
return ::sqrtf(x);
}
// TODO: Very fake!
// inline double fabs_wrapper(double x) {
// return __fabs(x);
// }
// inline float fabs(float x) {
// return fabs_wrapper(x);
// }
} // namespace std
#endif
#endif
@@ -0,0 +1,14 @@
#ifndef MSL_CPP_CSTDDEF_H
#define MSL_CPP_CSTDDEF_H
#include <stddef.h>
#ifdef __cplusplus
namespace std {
using ::intptr_t;
using ::ptrdiff_t;
using ::size_t;
using ::uintptr_t;
} // namespace std
#endif
#endif
@@ -0,0 +1,21 @@
#ifndef MSL_CPP_CSTDIO_H
#define MSL_CPP_CSTDIO_H
#include <stdio.h>
#ifdef __cplusplus
namespace std {
using ::fclose;
using ::fflush;
using ::FILE;
// using ::ftell;
// using ::fwide;
using ::snprintf;
using ::sprintf;
// using ::sscanf;
using ::vprintf;
using ::vsnprintf;
// using ::vsprintf;
} // namespace std
#endif
#endif
@@ -0,0 +1,17 @@
#ifndef MSL_CPP_CSTDLIB_H
#define MSL_CPP_CSTDLIB_H
#include <stdlib.h>
#ifdef __cplusplus
// TODO: Fillout impls
namespace std {
// using ::abs;
// using ::atof;
// using ::mbstowcs;
// using ::mbtowc;
// using ::rand;
// using ::wcstombs;
} // namespace std
#endif
#endif
@@ -0,0 +1,26 @@
#ifndef MSL_CPP_CSTRING_H
#define MSL_CPP_CSTRING_H
#include <string.h>
#ifdef __cplusplus
namespace std {
using ::__memrchr;
using ::memchr;
using ::memcmp;
using ::memcpy;
using ::memmove;
using ::memset;
using ::strcat;
using ::strchr;
using ::strcmp;
using ::strcpy;
// using ::stricmp;
using ::strlen;
using ::strncat;
using ::strncmp;
using ::strncpy;
// using ::strstr;
} // namespace std
#endif
#endif
@@ -4,13 +4,13 @@
#include "string.h"
namespace std {
inline size_t strlen(const char* str) {
inline size_t strlen(const char *str) {
return ::strlen(str);
}
inline char* strcpy(char* dest, const char* src) {
inline char *strcpy(char *dest, const char *src) {
return ::strcpy(dest, src);
}
} // namespace std
} // namespace std
#endif
#endif
@@ -0,0 +1,21 @@
#ifndef MSL_CPP_CWCHAR_H
#define MSL_CPP_CWCHAR_H
#include <wchar.h>
#ifdef __cplusplus
namespace std {
using ::mbstowcs;
using ::mbtowc;
using ::swprintf;
using ::vswprintf;
using ::wcscat;
using ::wcschr;
using ::wcscmp;
using ::wcscpy;
using ::wcslen;
using ::wcsncpy;
using ::wcstombs;
} // namespace std
#endif
#endif
@@ -0,0 +1,10 @@
#ifndef MSL_CPP_ITERATOR_H
#define MSL_CPP_ITERATOR_H
namespace std {
struct random_access_iterator_tag {};
} // namespace std
#endif
@@ -0,0 +1,17 @@
#ifndef MSL_CPP_NEW_H
#define MSL_CPP_NEW_H
#include <stddef.h>
#ifdef __cplusplus
inline void* operator new(size_t size, void* ptr) {
#pragma unused(size)
return ptr;
}
inline void* operator new[](size_t size, void* ptr) {
#pragma unused(size)
return ptr;
}
#endif
#endif
@@ -13,6 +13,9 @@ typedef unsigned long size_t;
typedef long ptrdiff_t;
#endif
typedef signed long intptr_t;
typedef unsigned long uintptr_t;
#ifdef __MWERKS__
#define offsetof(type, member) ((size_t) & (((type *)0)->member))
#else
@@ -17,6 +17,7 @@ char *strrchr(const char *str, int c);
char *strchr(const char *str, int c);
int strncmp(const char *str1, const char *str2, size_t n);
int strcmp(const char *str1, const char *str2);
char *strncat(char *dst, const char *src, size_t n);
char *strcat(char *dst, const char *src);
char *strncpy(char *dst, const char *src, size_t n);
char *strcpy(char *dst, const char *src);
+1 -1
View File
@@ -14,7 +14,7 @@ SPECIAL_ACTOR_PROFILE(BOMBF, dAcBombf_c, fProfile::BOMBF, 0x129, 0, 4099);
STATE_DEFINE(dAcBombf_c, Wait);
bool dAcBombf_c::createHeap() {
nw4r::g3d::ResFile resFile = getOarcResFile("FlowerBomb");
nw4r::g3d::ResFile resFile(getOarcResFile("FlowerBomb"));
nw4r::g3d::ResMdl resMdl = resFile.GetResMdl("LeafBomb");
return mModel.create(resMdl, &heap_allocator, 0x120, 1, nullptr);
}
+1 -1
View File
@@ -10,7 +10,7 @@ bool dAcEhb_leaf_c::createHeap() {
// but only ever a single pointer.
void *fp = getOarcResFile("Degubaba");
TRY_CREATE(mModel.create(fp, "degubaba_leaf", "shake2", &heap_allocator, 0x123));
nw4r::g3d::ResFile f = fp;
nw4r::g3d::ResFile f(fp);
nw4r::g3d::ResMdl mdl = f.GetResMdl("degubaba_leaf");
nw4r::g3d::ResAnmTexPat anm = f.GetResAnmTexPat("degubaba_leaf");
TRY_CREATE(mAnm.create(mdl, anm, &heap_allocator, nullptr, 1));
+2 -1
View File
@@ -2,6 +2,7 @@
#include "d/a/d_a_player.h"
#include "d/col/bg/d_bg_s.h"
#include "nw4r/types_nw4r.h"
#include "toBeSorted/area_utils.h"
#include "toBeSorted/room_manager.h"
@@ -16,7 +17,7 @@ STATE_DEFINE(dAcOappearBridge_c, Appear);
STATE_DEFINE(dAcOappearBridge_c, Disappear);
bool dAcOappearBridge_c::createHeap() {
mResFile = getOarcResFile("TongueStage");
mResFile = nw4r::g3d::ResFile(getOarcResFile("TongueStage"));
RoomManager::bindStageResToFile(&mResFile);
nw4r::g3d::ResMdl mdl = mResFile.GetResMdl("TongueStage");
TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x128));
+2 -1
View File
@@ -2,6 +2,7 @@
#include "d/col/bg/d_bg_s.h"
#include "d/flag/storyflag_manager.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "toBeSorted/room_manager.h"
const f32 dAcObambooIsland_c::unusedFloat1 = 100000.0f;
@@ -21,7 +22,7 @@ void dAcObambooIsland_c::rideCallback(dBgW *unknown, dAcObjBase_c *actor, dAcObj
}
bool dAcObambooIsland_c::createHeap() {
mBrres = getOarcResFile("IslBamb");
mBrres = nw4r::g3d::ResFile(getOarcResFile("IslBamb"));
RoomManager::bindStageResToFile(&mBrres);
RoomManager::bindSkyCmnToResFile(&mBrres);
for (int i = 0; i < 2; i++) {
@@ -10,8 +10,8 @@
#include "m/m_mtx.h"
#include "m/m_quat.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "rvl/MTX/mtxvec.h"
SPECIAL_ACTOR_PROFILE(
@@ -25,8 +25,8 @@ bool dAcOFlyingClawshotTarget_c::createHeap() {
return false;
}
nw4r::g3d::ResFile file = data;
if (!file.mFile.IsValid()) {
nw4r::g3d::ResFile file(data);
if (!file.IsValid()) {
return false;
}
nw4r::g3d::ResMdl mdl = file.GetResMdl("BirdObjD3_S");
+5 -5
View File
@@ -4,8 +4,8 @@
#include "d/a/obj/d_a_obj_base.h"
#include "f/f_base.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "s/s_Math.h"
#include "toBeSorted/time_area_mgr.h"
@@ -22,14 +22,14 @@ bool dAcOFruitGutsLeaf_c::createHeap() {
if (data == nullptr) {
return false;
}
nw4r::g3d::ResFile f = data;
if (!f.mFile.IsValid()) {
nw4r::g3d::ResFile f(data);
if (!f.IsValid()) {
return false;
}
nw4r::g3d::ResMdl m = f.GetResMdl(mdlName);
if (!m.mMdl.IsValid()) {
if (!m.IsValid()) {
return false;
}
+5 -4
View File
@@ -2,13 +2,14 @@
#include "d/a/obj/d_a_obj_base.h"
#include "d/col/bg/d_bg_s.h"
#include "d/flag/storyflag_manager.h"
#include "f/f_base.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/g3d_resnode.h"
#include "nw4r/g3d/g3d_scnmdl.h"
#include "nw4r/g3d/g3d_scnobj.h"
#include "d/flag/storyflag_manager.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resnode.h"
#include "toBeSorted/room_manager.h"
const f32 dAcOislandNusi_c::someFloat = 100000.0f;
@@ -24,7 +25,7 @@ STATE_DEFINE(dAcOislandNusi_c, Wait);
STATE_DEFINE(dAcOislandNusi_c, NusiFight);
bool dAcOislandNusi_c::createHeap() {
mRes = getOarcResFile("IslNusi");
mRes = nw4r::g3d::ResFile(getOarcResFile("IslNusi"));
RoomManager::bindStageResToFile(&mRes);
RoomManager::bindSkyCmnToResFile(&mRes);
for (int i = 0; i < 2; i++) {
+2 -2
View File
@@ -1,7 +1,7 @@
#include "d/a/obj/d_a_obj_junk_repairing.h"
#include "d/flag/storyflag_manager.h"
#include "nw4r/g3d/res/g3d_resfile.h"
SPECIAL_ACTOR_PROFILE(OBJ_JUNK_REPAIR, dAcOJunkRep_c, fProfile::OBJ_JUNK_REPAIR, 0x027B, 0, 3);
@@ -19,7 +19,7 @@ bool dAcOJunkRep_c::getState() {
}
bool dAcOJunkRep_c::createHeap() {
mResFile = getOarcResFile("Junk");
mResFile = nw4r::g3d::ResFile(getOarcResFile("Junk"));
if (!loadMdl(mModel1, getMdlName1())) {
return false;
}
+2 -2
View File
@@ -1,12 +1,12 @@
#include "d/a/obj/d_a_obj_lava_F200.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "toBeSorted/room_manager.h"
SPECIAL_ACTOR_PROFILE(OBJ_LAVA_F200, dAcOlavaF200_c, fProfile::OBJ_LAVA_F200, 0x0214, 0, 0);
bool dAcOlavaF200_c::createHeap() {
mBrres = getOarcResFile("LavaF200");
mBrres = nw4r::g3d::ResFile(getOarcResFile("LavaF200"));
RoomManager::bindStageResToFile(&mBrres);
nw4r::g3d::ResMdl mdl0 = mBrres.GetResMdl("LavaF200");
+3 -3
View File
@@ -6,8 +6,8 @@
#include "d/flag/storyflag_manager.h"
#include "f/f_base.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resanmtexsrt.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resanmtexsrt.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "toBeSorted/room_manager.h"
static const char *const sResFiles[] = {
@@ -45,7 +45,7 @@ SPECIAL_ACTOR_PROFILE(OBJ_MEGAMI_ISLAND, dAcOmegamiIsland_c, fProfile::OBJ_MEGAM
bool dAcOmegamiIsland_c::createHeap() {
mVariant = getVariant();
mRes = getOarcResFile(sResFiles[mVariant]);
mRes = nw4r::g3d::ResFile(getOarcResFile(sResFiles[mVariant]));
RoomManager::bindStageResToFile(&mRes);
RoomManager::bindSkyCmnToResFile(&mRes);
+2 -2
View File
@@ -12,8 +12,8 @@ const f32 dAcOmoleSoil_c::sHalfScale = 0.5f;
const f32 dAcOmoleSoil_c::sFullScale = 1.0f;
bool dAcOmoleSoil_c::createHeap() {
nw4r::g3d::ResFile file = getOarcResFile("MogumaMud");
if (!file.mFile.IsValid()) {
nw4r::g3d::ResFile file(getOarcResFile("MogumaMud"));
if (!file.IsValid()) {
return false;
}
mBrres = file;
+2 -2
View File
@@ -1,16 +1,16 @@
#include "d/a/obj/d_a_obj_pool_cock.h"
#include "d/a/obj/d_a_obj_vortex.h"
#include "d/flag/sceneflag_manager.h"
#include "s/s_Math.h"
#include "toBeSorted/room_manager.h"
#include "d/flag/sceneflag_manager.h"
SPECIAL_ACTOR_PROFILE(OBJ_POOL_COCK, dAcOPoolCock_c, fProfile::OBJ_POOL_COCK, 0x024D, 0, 7);
STATE_DEFINE(dAcOPoolCock_c, Wait);
bool dAcOPoolCock_c::createHeap() {
mBrres = getOarcResFile("WaterD101");
mBrres = nw4r::g3d::ResFile(getOarcResFile("WaterD101"));
RoomManager::bindStageResToFile(&mBrres);
nw4r::g3d::ResMdl mdl = mBrres.GetResMdl("PoolCockD101");
for (int i = 0; i < 2; i++) {
+2 -2
View File
@@ -1,14 +1,14 @@
#include "d/a/obj/d_a_obj_pumpkin_leaf.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "s/s_Math.h"
SPECIAL_ACTOR_PROFILE(OBJ_PUMPKIN_LEAF, dAcOPumpkinLeaf_c, fProfile::OBJ_PUMPKIN_LEAF, 0x0135, 0, 3);
STATE_DEFINE(dAcOPumpkinLeaf_c, Wait);
bool dAcOPumpkinLeaf_c::createHeap() {
mBrres = getOarcResFile("Pumpkin");
mBrres = nw4r::g3d::ResFile(getOarcResFile("Pumpkin"));
nw4r::g3d::ResMdl mdl = mBrres.GetResMdl("Leaf");
TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x120, 1, nullptr));
return true;
+2 -2
View File
@@ -1,14 +1,14 @@
#include "d/a/obj/d_a_obj_ring.h"
#include "d/a/d_a_player.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resfile.h"
SPECIAL_ACTOR_PROFILE(OBJ_RING, dAcOring_c, fProfile::OBJ_RING, 0x00f2, 0, 0x103);
STATE_DEFINE(dAcOring_c, Move);
bool dAcOring_c::createHeap() {
nw4r::g3d::ResFile f = getOarcResFile("PRing");
nw4r::g3d::ResFile f(getOarcResFile("PRing"));
nw4r::g3d::ResMdl mdl = f.GetResMdl("PeehatRing");
// This matches but in a really weird way. Maybe an inline function?
TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x20, 1, nullptr));
+2 -2
View File
@@ -11,7 +11,7 @@
#include "m/m_angle.h"
#include "m/m_mtx.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "rvl/MTX/mtx.h"
#include "s/s_Math.h"
#include "toBeSorted/attention.h"
@@ -55,7 +55,7 @@ bool dAcOSeatSword_c::createHeap() {
TRY_CREATE(mSwordMdl.create(mRes.GetResMdl(sword_name), &heap_allocator, 0x120, 1, nullptr));
}
nw4r::g3d::ResFile mPedRes = getOarcResFile(SwordSeatNames[mSubtype]);
nw4r::g3d::ResFile mPedRes(getOarcResFile(SwordSeatNames[mSubtype]));
TRY_CREATE(mPedestalMdl.create(mPedRes.GetResMdl(SwordSeatNames[mSubtype]), &heap_allocator, 0x120, 1, nullptr));
void *dzb = getOarcDZB(SwordSeatNames[mSubtype], SwordSeatNames[mSubtype]);
void *plc = getOarcPLC(SwordSeatNames[mSubtype], SwordSeatNames[mSubtype]);
+1 -1
View File
@@ -16,7 +16,7 @@ STATE_DEFINE(dAcOsmoke_c, Wait);
bool dAcOsmoke_c::createHeap() {
mType = params & 3;
mBrres = getOarcResFile(sSmokeNames1[mType]);
mBrres = nw4r::g3d::ResFile(getOarcResFile(sSmokeNames1[mType]));
nw4r::g3d::ResMdl mdl = mBrres.GetResMdl(sSmokeNames2[mType]);
TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x324));
nw4r::g3d::ResAnmTexSrt srt = mBrres.GetResAnmTexSrt(sSmokeNames1[mType]);
+1 -1
View File
@@ -18,7 +18,7 @@ const mVec3_c dAcOspike_c::sVec2 = mVec3_c(73.0f, 255.0f, 482.0f);
STATE_DEFINE(dAcOspike_c, Wait);
bool dAcOspike_c::createHeap() {
mResFile = getOarcResFile("SpikeD101");
mResFile = nw4r::g3d::ResFile(getOarcResFile("SpikeD101"));
nw4r::g3d::ResMdl mdl = mResFile.GetResMdl("SpikeD101");
TRY_CREATE(mMdl.create(mdl, &heap_allocator, 0x120));
return true;
+2 -2
View File
@@ -1,14 +1,14 @@
#include "d/a/obj/d_a_obj_stage_cover.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "toBeSorted/arc_managers/current_stage_arc_manager.h"
SPECIAL_ACTOR_PROFILE(OBJ_STAGE_COVER, dAcOstageCover_c, fProfile::OBJ_STAGE_COVER, 0x01E1, 0, 0);
STATE_DEFINE(dAcOstageCover_c, Wait);
bool dAcOstageCover_c::createHeap() {
mBrres = CurrentStageArcManager::sInstance->getData("g3d/stage.brres");
mBrres = nw4r::g3d::ResFile(CurrentStageArcManager::sInstance->getData("g3d/stage.brres"));
nw4r::g3d::ResMdl mdl = mBrres.GetResMdl("StageCover");
TRY_CREATE(mModel.create(mdl, &heap_allocator, 0x120));
return true;
+2 -2
View File
@@ -1,16 +1,16 @@
#include "d/a/obj/d_a_obj_sun_light.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "toBeSorted/arc_managers/current_stage_arc_manager.h"
#include "toBeSorted/room_manager.h"
#include "toBeSorted/scgame.h"
SPECIAL_ACTOR_PROFILE(OBJ_SUN_LIGHT, dAcOsunLight_c, fProfile::OBJ_SUN_LIGHT, 0x0219, 0, 3);
STATE_DEFINE(dAcOsunLight_c, Wait);
bool dAcOsunLight_c::createHeap() {
mBrres = CurrentStageArcManager::sInstance->getData("g3d/stage.brres");
mBrres = nw4r::g3d::ResFile(CurrentStageArcManager::sInstance->getData("g3d/stage.brres"));
RoomManager::bindStageResToFile(&mBrres);
RoomManager::bindSkyCmnToResFile(&mBrres);
nw4r::g3d::ResMdl mdl = mBrres.GetResMdl("StageF000Light");
+6 -5
View File
@@ -4,9 +4,10 @@
#include "d/a/obj/d_a_obj_base.h"
#include "m/m_color.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resanmclr.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/g3d_resnode.h"
#include "nw4r/g3d/res/g3d_resanmclr.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resnode.h"
#include "nw4r/math/math_types.h"
#include "rvl/GX/GXTypes.h"
#include "s/s_Math.h"
@@ -26,12 +27,12 @@ static const char *sMdl2Names[] = {
STATE_DEFINE(dAcOTimeStageBg_c, Wait);
bool dAcOTimeStageBg_c::createHeap() {
mRes = CurrentStageArcManager::sInstance->getData("g3d/stage.brres");
mRes = nw4r::g3d::ResFile(CurrentStageArcManager::sInstance->getData("g3d/stage.brres"));
nw4r::g3d::ResMdl mdl = mRes.GetResMdl(sMdlNames[mSubType]);
TRY_CREATE(mMdl1.create(mdl, &heap_allocator, 0x128));
nw4r::g3d::ResNode nd = mdl.GetResNode(sMdlNames[mSubType]);
field_0x3EC.copyFrom((nd.mNode.ref().VEC3_0x44 + nd.mNode.ref().VEC3_0x50) * 0.5f);
field_0x3EC.copyFrom((nd.ref().volume_min + nd.ref().volume_max) * 0.5f);
if (mSubType == 4) {
nw4r::g3d::ResAnmClr a = mRes.GetResAnmClr("Teniobj_0");
TRY_CREATE(mAnm.create(mdl, a, &heap_allocator, nullptr, 1));
@@ -57,7 +57,7 @@ dCcD_SrcCyl dAcOtoD3StoneFigure_c::sCcSrc = {
bool dAcOtoD3StoneFigure_c::createHeap() {
const char *modelName = getModelName();
mResFile = getOarcResFile("BirdObjD3");
mResFile = nw4r::g3d::ResFile(getOarcResFile("BirdObjD3"));
nw4r::g3d::ResMdl mdl = mResFile.GetResMdl(modelName);
TRY_CREATE(mMdl.create(mdl, &heap_allocator, 0x120));
return true;
+2 -2
View File
@@ -8,7 +8,7 @@
#include "f/f_manager.h"
#include "f/f_profile_name.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "toBeSorted/room_manager.h"
SPECIAL_ACTOR_PROFILE(OBJ_TOWER_GEAR_D101, dAcOTowerGearD101_c, fProfile::OBJ_TOWER_GEAR_D101, 0x17E, 0, 7);
@@ -19,7 +19,7 @@ extern "C" void fn_80067340(mVec3_c &, nw4r::g3d::ResMdl *, const char *);
bool dAcOTowerGearD101_c::createHeap() {
const char *name = "TowerGearD101";
mRes = getOarcResFile(name);
mRes = nw4r::g3d::ResFile(getOarcResFile(name));
RoomManager::bindStageResToFile(&mRes);
nw4r::g3d::ResMdl mdl = mRes.GetResMdl(name);
if (!mMdl.create(mdl, &heap_allocator, 0x120, 1, nullptr)) {
+3 -3
View File
@@ -11,7 +11,7 @@
#include "m/m_angle.h"
#include "m/m_mtx.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "rvl/MTX/mtx.h"
#include "rvl/MTX/vec.h"
#include "s/s_Math.h"
@@ -104,8 +104,8 @@ bool dAcOTowerHandD101_c::createHeap() {
if (!isValidDirectionParam(direction)) {
return false;
}
nw4r::g3d::ResFile res = resP;
if (!res.mFile.IsValid()) {
nw4r::g3d::ResFile res(resP);
if (!res.IsValid()) {
return false;
}
RoomManager::bindStageResToFile(&res);
+2 -3
View File
@@ -13,7 +13,7 @@ STATE_DEFINE(dAcOtrapRock1_c, TrapAction);
STATE_DEFINE(dAcOtrapRock1_c, TrapReturn);
bool dAcOtrapRock1_c::createHeap() {
mResFile = getOarcResFile("TrapRockRoll");
mResFile = nw4r::g3d::ResFile(getOarcResFile("TrapRockRoll"));
nw4r::g3d::ResMdl m = mResFile.GetResMdl("TrapRockRoll");
TRY_CREATE(mMdl.create(m, &heap_allocator, 0x120));
@@ -97,8 +97,7 @@ void dAcOtrapRock1_c::executeState_TrapAction() {
}
if (ratio > 1.0f) {
ratio = 1.0f;
}
else if (ratio < 0.1f) {
} else if (ratio < 0.1f) {
ratio = 0.1f;
}
s16 newAng = field_0x5A5 * (1.0f - ratio) * field_0x5A2;
+2 -1
View File
@@ -3,6 +3,7 @@
#include "c/c_math.h"
#include "d/col/cc/d_cc_s.h"
#include "m/m_vec.h"
#include "nw4r/g3d/res/g3d_resfile.h"
SPECIAL_ACTOR_PROFILE(OBJ_TRIFORCE, dAcOtriforce_c, fProfile::OBJ_TRIFORCE, 0x15D, 0, 4);
@@ -21,7 +22,7 @@ const u32 dAcOtriforce_c::sStartingOffsetRange = 0x10000;
// const f32 dAcOtriforce_c::sAmpPos = 23.0f;
bool dAcOtriforce_c::createHeap() {
mResFile = getOarcResFile("TriForce");
mResFile = nw4r::g3d::ResFile(getOarcResFile("TriForce"));
nw4r::g3d::ResMdl mdl = mResFile.GetResMdl("TriForce");
TRY_CREATE(mMdl.create(mdl, &heap_allocator, 0x324));
nw4r::g3d::ResAnmTexSrt anm = mResFile.GetResAnmTexSrt("TriForce");
+1 -1
View File
@@ -60,7 +60,7 @@ dCcD_SrcSph dAcOtubo_c::sSphSrc = {
};
bool dAcOtubo_c::createHeap() {
mRes = getOarcResFile("Tubo");
mRes = nw4r::g3d::ResFile(getOarcResFile("Tubo"));
const char *subtype = getSubtype() == 0 ? "Tubo00" : "Tubo01";
TRY_CREATE(mMdl.create(mRes.GetResMdl(subtype), &heap_allocator, 0x120, 1, nullptr));
return true;
+1 -2
View File
@@ -40,7 +40,7 @@ dCcD_SrcSph dAcOTumbleWeed_c::sSphSrc = {
};
bool dAcOTumbleWeed_c::createHeap() {
mResFile = getOarcResFile("GrassRollDry");
mResFile = nw4r::g3d::ResFile(getOarcResFile("GrassRollDry"));
TRY_CREATE(mMdl.create(mResFile.GetResMdl("GrassRollDry"), &heap_allocator, 0x120, 1, nullptr));
return true;
}
@@ -92,7 +92,6 @@ int dAcOTumbleWeed_c::doDelete() {
return SUCCEEDED;
}
int dAcOTumbleWeed_c::actorExecute() {
if (!mField_0x98C && !isStopped()) {
mField_0x968 = velocity;
@@ -5,8 +5,8 @@
#include "d/a/obj/d_a_obj_base.h"
#include "d/flag/sceneflag_manager.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resanmclr.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resanmclr.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "toBeSorted/event_manager.h"
SPECIAL_ACTOR_PROFILE(OBJ_UG_SWITCH, dAcOUgSwitch_c, fProfile::OBJ_UG_SWITCH, 0x15A, 0, 3);
@@ -22,11 +22,11 @@ bool dAcOUgSwitch_c::createHeap() {
// Why. Regswap...
void *data = getOarcResFile("SwitchPass");
mRes = data;
mRes = nw4r::g3d::ResFile(data);
nw4r::g3d::ResMdl mdl = mRes.GetResMdl("SwitchPass");
TRY_CREATE(mMdl.create(mdl, &heap_allocator, 0x120));
mRes = data;
mRes = nw4r::g3d::ResFile(data);
mdl = mRes.GetResMdl("SwitchPass");
nw4r::g3d::ResAnmClr clr = mRes.GetResAnmClr("SwitchPass_Light");
TRY_CREATE(mAnmClr.create(mdl, clr, &heap_allocator, nullptr, 1));
+3 -2
View File
@@ -3,7 +3,8 @@
#include "d/a/obj/d_a_obj_base.h"
#include "f/f_base.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "toBeSorted/arc_managers/current_stage_arc_manager.h"
#include "toBeSorted/room_manager.h"
@@ -23,7 +24,7 @@ bool dAcOutaDemoPedest_c::createHeap() {
mModelType = 0;
}
mRes = CurrentStageArcManager::sInstance->getData("g3d/stage.brres");
mRes = nw4r::g3d::ResFile(CurrentStageArcManager::sInstance->getData("g3d/stage.brres"));
RoomManager::bindStageResToFile(&mRes);
RoomManager::bindSkyCmnToResFile(&mRes);
nw4r::g3d::ResMdl mdl = mRes.GetResMdl(sMdlNames[mModelType]);
+2 -2
View File
@@ -23,11 +23,11 @@ void dAcOutajima_c::rideCallback(dBgW *bg, dAcObjBase_c *o1, dAcObjBase_c *o2) {
}
bool dAcOutajima_c::createHeap() {
mRes = getOarcResFile("IslSon");
mRes = nw4r::g3d::ResFile(getOarcResFile("IslSon"));
RoomManager::bindStageResToFile(&mRes);
RoomManager::bindSkyCmnToResFile(&mRes);
nw4r::g3d::ResMdl m = nullptr;
nw4r::g3d::ResMdl m(nullptr);
for (int i = 0; i < 2; i++) {
m = mRes.GetResMdl(mMdlNames[i]);
+2 -2
View File
@@ -8,7 +8,7 @@
#include "f/f_manager.h"
#include "f/f_profile_name.h"
#include "m/m_angle.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "s/s_Math.h"
#include "toBeSorted/room_manager.h"
@@ -24,7 +24,7 @@ const f32 dAcOutajimaIsland_c::floats[] = {
};
bool dAcOutajimaIsland_c::createHeap() {
mRes = getOarcResFile("IslPuzIslet00");
mRes = nw4r::g3d::ResFile(getOarcResFile("IslPuzIslet00"));
RoomManager::bindStageResToFile(&mRes);
RoomManager::bindSkyCmnToResFile(&mRes);
nw4r::g3d::ResMdl m = mRes.GetResMdl("IslPuzIslet00");
+1 -1
View File
@@ -10,7 +10,7 @@ SPECIAL_ACTOR_PROFILE(OBJ_UTAJIMA_LV2, dAcOutajimaLv2_c, fProfile::OBJ_UTAJIMA_L
const f32 dAcOutajimaLv2_c::someFloat = 100000.0f;
bool dAcOutajimaLv2_c::createHeap() {
mRes = getOarcResFile("IslCave");
mRes = nw4r::g3d::ResFile(getOarcResFile("IslCave"));
RoomManager::bindStageResToFile(&mRes);
RoomManager::bindSkyCmnToResFile(&mRes);
nw4r::g3d::ResMdl mdl = mRes.GetResMdl("IslCave");
+2 -1
View File
@@ -1,11 +1,12 @@
#include "d/a/obj/d_a_obj_water_shield.h"
#include "d/col/bg/d_bg_s.h"
#include "nw4r/types_nw4r.h"
SPECIAL_ACTOR_PROFILE(OBJ_WATER_SHIELD, dAcOwaterShield_c, fProfile::OBJ_WATER_SHIELD, 0x218, 0, 0);
bool dAcOwaterShield_c::createHeap() {
mRes = getOarcResFile("WaterWallF103");
mRes = nw4r::g3d::ResFile(getOarcResFile("WaterWallF103"));
nw4r::g3d::ResMdl mdl = mRes.GetResMdl("WaterWallF103");
TRY_CREATE(mMdl.create(mdl, &heap_allocator, 0x32C));
nw4r::g3d::ResAnmClr clr = mRes.GetResAnmClr("WaterWallF103");
+2 -1
View File
@@ -3,6 +3,7 @@
#include "c/c_math.h"
#include "d/a/d_a_player.h"
#include "d/col/c/c_cc_d.h"
#include "nw4r/types_nw4r.h"
SPECIAL_ACTOR_PROFILE(ARROW, dAcArrow_c, fProfile::ARROW, 0x126, 0, 0x80);
@@ -44,7 +45,7 @@ bool hitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjBase_c *i_ac
}
bool dAcArrow_c::createHeap() {
mResFile = getOarcResFile("Alink");
mResFile = nw4r::g3d::ResFile(getOarcResFile("Alink"));
nw4r::g3d::ResMdl mdl(nullptr);
if ((mSubType & 0x10) != 0) {
mdl = mResFile.GetResMdl("EquipPachinkoBullet");
+5 -5
View File
@@ -4,7 +4,7 @@
#include "d/col/bg/d_bg_s.h"
#include "d/col/bg/d_bg_w.h"
#include "d/flag/sceneflag_manager.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "s/s_Math.h"
SPECIAL_ACTOR_PROFILE(OBJ_SW, dAcOsw_c, fProfile::OBJ_SW, 0x12B, 0, 0x1002);
@@ -63,12 +63,12 @@ void dAcOsw_c::rideCallback(dBgW *unknown, dAcObjBase_c *actor, dAcObjBase_c *in
}
bool dAcOsw_c::createHeap() {
nw4r::g3d::ResFile resFile = getOarcResFile(SWITCH_TYPES[mSwitchType]);
nw4r::g3d::ResMdl resMdl = resFile.GetResMdl(SWITCH_TYPES[mSwitchType]);
nw4r::g3d::ResFile resFile(getOarcResFile(SWITCH_TYPES[mSwitchType]));
nw4r::g3d::ResMdl resMdl(resFile.GetResMdl(SWITCH_TYPES[mSwitchType]));
TRY_CREATE(mModel.create(resMdl, &heap_allocator, 0x20, 1, nullptr));
field_0x5E8 = mScale.x * (resMdl.GetResNode("base").mNode.ref().VEC3_0x50.x -
resMdl.GetResNode("base").mNode.ref().VEC3_0x44.x);
field_0x5E8 =
mScale.x * (resMdl.GetResNode("base").ref().volume_max.x - resMdl.GetResNode("base").ref().volume_min.x);
cBgD_t *dbzData = (cBgD_t *)getOarcDZB(SWITCH_TYPES[mSwitchType], SWITCH_TYPES[mSwitchType]);
PLC *plcData = (PLC *)getOarcPLC(SWITCH_TYPES[mSwitchType], SWITCH_TYPES[mSwitchType]);
mScale.set(1.0f, 0.8f, 1.0f);
+23 -19
View File
@@ -18,11 +18,11 @@
#include "m/m3d/m_scnleaf.h"
#include "m/m_mtx.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resanmchr.h"
#include "nw4r/g3d/g3d_resanmtexpat.h"
#include "nw4r/g3d/g3d_resanmtexsrt.h"
#include "nw4r/g3d/g3d_resfile.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resanmchr.h"
#include "nw4r/g3d/res/g3d_resanmtexpat.h"
#include "nw4r/g3d/res/g3d_resanmtexsrt.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "rvl/MTX/mtxvec.h"
#include "s/s_Math.h"
#include "toBeSorted/arc_managers/oarc_manager.h"
@@ -811,8 +811,12 @@ bool dAcTbox_c::isBelowGroundAtPos(f32 height, const mVec3_c &pos) {
}
dAcTbox_c::dAcTbox_c()
: mStateMgr(*this, sStateID::null), mScnCallback(this), mEvent(*this, nullptr), mTboxListNode(this),
mDowsingTarget(this, DowsingTarget::SLOT_NONE), mGoddessDowsingTarget(this, DowsingTarget::SLOT_NONE) {
: mStateMgr(*this, sStateID::null),
mScnCallback(this),
mEvent(*this, nullptr),
mTboxListNode(this),
mDowsingTarget(this, DowsingTarget::SLOT_NONE),
mGoddessDowsingTarget(this, DowsingTarget::SLOT_NONE) {
field_0x120B = 0;
field_0x120E = 0;
mDoObstructedCheck = false;
@@ -842,8 +846,8 @@ bool dAcTbox_c::createHeap() {
}
if (mVariant == GODDESS) {
nw4r::g3d::ResFile res = data;
if (!res.mFile.IsValid()) {
nw4r::g3d::ResFile res(data);
if (!res.IsValid()) {
return false;
}
nw4r::g3d::ResMdl mdl = mMdl1.getModel().getResMdl();
@@ -851,7 +855,7 @@ bool dAcTbox_c::createHeap() {
return false;
}
nw4r::g3d::ResAnmTexPat anmTexPat = res.GetResAnmTexPat("GoddessTBox");
if (!anmTexPat.mAnmTexPat.IsValid()) {
if (!anmTexPat.IsValid()) {
return false;
}
if (!mAnmGoddessPat.create(mdl, anmTexPat, &heap_allocator, nullptr, 1)) {
@@ -861,7 +865,7 @@ bool dAcTbox_c::createHeap() {
u16 goddessTBoxActive = getParams2Lower();
if (StoryflagManager::sInstance->getCounterOrFlag(goddessTBoxActive) && !mHasBeenOpened) {
nw4r::g3d::ResAnmTexSrt anmTexSrt = res.GetResAnmTexSrt("GoddessTBox");
if (!anmTexSrt.mAnmTexSrt.IsValid()) {
if (!anmTexSrt.IsValid()) {
return false;
}
if (!mAnmGoddessTexSrt.create(mdl, anmTexSrt, &heap_allocator, nullptr, 1)) {
@@ -870,12 +874,12 @@ bool dAcTbox_c::createHeap() {
mMdl1.getModel().setAnm(mAnmGoddessTexSrt);
}
} else if (mVariant == NORMAL) {
nw4r::g3d::ResFile res = data;
if (!res.mFile.IsValid()) {
nw4r::g3d::ResFile res(data);
if (!res.IsValid()) {
return false;
}
nw4r::g3d::ResAnmClr anmClr = res.GetResAnmClr("TBoxNormalTAppear");
if (!anmClr.mAnmClr.IsValid()) {
if (!anmClr.IsValid()) {
return false;
}
nw4r::g3d::ResMdl mdl = mMdl1.getModel().getResMdl();
@@ -894,8 +898,8 @@ bool dAcTbox_c::createHeap() {
if (fxData == nullptr) {
return false;
}
nw4r::g3d::ResFile fxRes = fxData;
if (!fxRes.mFile.IsValid()) {
nw4r::g3d::ResFile fxRes(fxData);
if (!fxRes.IsValid()) {
return false;
}
@@ -909,7 +913,7 @@ bool dAcTbox_c::createHeap() {
mOpenFxMdl.setPriorityDraw(0x7F, 0x86);
nw4r::g3d::ResAnmChr openAnm = fxRes.GetResAnmChr(sOpenAnmChrName);
if (!openAnm.mAnmChr.IsValid()) {
if (!openAnm.IsValid()) {
return false;
}
if (!mAnmChr.create(openMdl, openAnm, &heap_allocator, nullptr)) {
@@ -918,7 +922,7 @@ bool dAcTbox_c::createHeap() {
mOpenFxMdl.setAnm(mAnmChr);
nw4r::g3d::ResAnmTexSrt anmTexSrt = fxRes.GetResAnmTexSrt(sOpenAnmTexSrtName);
if (!anmTexSrt.mAnmTexSrt.IsValid()) {
if (!anmTexSrt.IsValid()) {
return false;
}
if (!mAnmTexSrt1.create(openMdl, anmTexSrt, &heap_allocator, nullptr, 1)) {
@@ -927,7 +931,7 @@ bool dAcTbox_c::createHeap() {
mOpenFxMdl.setAnm(mAnmTexSrt1);
nw4r::g3d::ResAnmClr anmClr = fxRes.GetResAnmClr(sOpenAnmClrName);
if (!anmClr.mAnmClr.IsValid()) {
if (!anmClr.IsValid()) {
return false;
}
if (!mAnmMatClr2.create(openMdl, anmClr, &heap_allocator, nullptr, 1)) {
+5 -5
View File
@@ -4,19 +4,19 @@
#include "d/a/obj/d_a_obj_base.h"
#include "m/m3d/m_fanm.h"
#include "m/m_vec.h"
#include "nw4r/g3d/g3d_resanmclr.h"
#include "nw4r/g3d/g3d_resanmtexsrt.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resanmclr.h"
#include "nw4r/g3d/res/g3d_resanmtexsrt.h"
#include "nw4r/g3d/res/g3d_resfile.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "s/s_State.hpp"
SPECIAL_ACTOR_PROFILE(OBJ_WATER_SPOUT, dAcOwaterSpout_c, fProfile::OBJ_WATER_SPOUT, 0x1DA, 0, 6);
STATE_DEFINE(dAcOwaterSpout_c, Wait);
bool dAcOwaterSpout_c::createHeap() {
void *data = getOarcResFile("FX_WaterColumn");
mResFile = data;
mResFile = nw4r::g3d::ResFile(data);
nw4r::g3d::ResMdl mdl = mResFile.GetResMdl("FX_WaterColumn");
TRY_CREATE(mMdl.create(data, "FX_WaterColumn", "FX_WaterColumn", &heap_allocator, 0x32C));
nw4r::g3d::ResAnmTexSrt anmSrt = mResFile.GetResAnmTexSrt("FX_WaterColumn");
+3 -3
View File
@@ -8,9 +8,9 @@
#include "m/m_video.h"
#include "nw4r/g3d/g3d_camera.h"
#include "nw4r/g3d/g3d_init.h"
#include "nw4r/g3d/g3d_resmat.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/g3d_state.h"
#include "nw4r/g3d/res/g3d_resmat.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "rvl/GX.h" // IWYU pragma: export
namespace m3d {
@@ -164,7 +164,7 @@ void setCurrentCamera(int id) {
}
nw4r::g3d::LightSetting *getLightSettingP() {
return internal::l_scnRoot_p->getLightSetting();
return &internal::l_scnRoot_p->GetLightSetting();
}
EGG::LightManager *getLightMgr(int idx) {
+1 -2
View File
@@ -2,8 +2,7 @@
#include "m/m3d/m3d.h"
#include "nw4r/g3d/g3d_anmchr.h"
#include "nw4r/g3d/g3d_resanmchr.h"
#include "nw4r/g3d/res/g3d_resanmchr.h"
namespace m3d {
+1 -2
View File
@@ -2,8 +2,7 @@
#include "m/m3d/m3d.h"
#include "nw4r/g3d/g3d_anmchr.h"
#include "nw4r/g3d/g3d_resanmchr.h"
#include "nw4r/g3d/res/g3d_resanmchr.h"
namespace m3d {
-1
View File
@@ -4,7 +4,6 @@
#include "m/m3d/m3d.h"
#include "m/m_heap.h"
namespace m3d {
anmMatClr_c::child_c::~child_c() {}
+6 -4
View File
@@ -1,5 +1,7 @@
#include "m/m3d/m_anmmdl.h"
#include "nw4r/g3d/res/g3d_resfile.h"
namespace m3d {
mdlAnmChr::~mdlAnmChr() {}
@@ -38,8 +40,8 @@ bool mdlAnmChr::create(
void *mdlFile, void *anmFile, const char *mdlName, const char *anmName, mdl_c::mdlCallback_c *callback,
mAllocator_c *alloc, u32 bufferOption, int nView, u32 *pSize
) {
mMdlFile = mdlFile;
mAnmFile = anmFile;
mMdlFile = nw4r::g3d::ResFile(mdlFile);
mAnmFile = nw4r::g3d::ResFile(anmFile);
nw4r::g3d::ResMdl resMdl = mMdlFile.GetResMdl(mdlName);
if (!mMdl.create(resMdl, callback, alloc, bufferOption, nView, pSize)) {
@@ -47,7 +49,7 @@ bool mdlAnmChr::create(
}
nw4r::g3d::ResAnmChr resAnm = mAnmFile.GetResAnmChr(anmName);
if (!resAnm.mAnmChr.IsValid()) {
if (!resAnm.IsValid()) {
resAnm = mMdlFile.GetResAnmChr(anmName);
}
u32 oldSize;
@@ -75,7 +77,7 @@ bool mdlAnmChr::create(
void mdlAnmChr::setAnm(const char *name, playMode_e mode, f32 blend) {
nw4r::g3d::ResAnmChr anm = mAnmFile.GetResAnmChr(name);
if (!anm.mAnmChr.IsValid()) {
if (!anm.IsValid()) {
anm = mMdlFile.GetResAnmChr(name);
}
mAnm.setAnm(mMdl, anm, mode);
-1
View File
@@ -4,7 +4,6 @@
#include "m/m3d/m3d.h"
#include "m/m_heap.h"
namespace m3d {
int anmTexPat_c::child_c::getType() const {
+2 -3
View File
@@ -2,9 +2,8 @@
#include "m/m3d/m3d.h"
#include "nw4r/g3d/g3d_anmvis.h"
#include "nw4r/g3d/g3d_resanmvis.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resanmvis.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
namespace m3d {
+1 -2
View File
@@ -3,7 +3,6 @@
#include "m/m3d/m3d.h"
#include "m/m_heap.h"
namespace m3d {
banm_c::~banm_c() {
banm_c::remove();
@@ -40,7 +39,7 @@ bool banm_c::IsBound() const {
if (mpAnmObj == nullptr) {
return false;
}
return mpAnmObj->TestAnmFlag(nw4r::g3d::AnmObj::ANMFLAG_ISBOUND);
return mpAnmObj->TestAnmFlag(nw4r::g3d::AnmObj::FLAG_ANM_BOUND);
}
void banm_c::play() {}
+1 -2
View File
@@ -3,7 +3,6 @@
#include "m/m3d/m3d.h"
#include "nw4r/g3d/g3d_scnmdl.h"
namespace m3d {
bmdl_c::~bmdl_c() {
@@ -24,7 +23,7 @@ int bmdl_c::getNodeID(const char *name) const {
bool bmdl_c::getNodeWorldMtx(u32 p1, nw4r::math::MTX34 *out) const {
return nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf)->GetScnMtxPos(
out, nw4r::g3d::ScnObj::MTX_TYPE_WORLD, p1
out, nw4r::g3d::ScnObj::MTX_WORLD, p1
);
}
+33 -33
View File
@@ -2,7 +2,7 @@
#include "m/m3d/m3d.h"
#include "nw4r/g3d/g3d_scnmdlsmpl.h"
#include "nw4r/g3d/g3d_scnobj.h"
namespace m3d {
@@ -17,34 +17,34 @@ mdl_c::mdlCallback_c::~mdlCallback_c() {}
void mdl_c::mdlCallback_c::ExecCallbackA(
nw4r::g3d::ChrAnmResult *result, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *o
) {
u16 nodeId = o->GetNodeId();
u16 nodeId = o->GetCallbackNodeID();
nw4r::g3d::ChrAnmResult *resPtr = &mpNodes[nodeId];
if (mCalcRatio.is0x18() && !mCalcRatio.isEnd()) {
if (!mCalcRatio.is0x19()) {
*result = *resPtr;
} else {
u32 flags = result->mFlags;
u32 flags = result->flags;
f32 f2 = mCalcRatio.get0x10();
f32 f1 = mCalcRatio.get0x14();
// TODO clean up this code, what does it even do, why do operators
// break
if ((flags & 8) == 0) {
result->VEC3_0x4.x = (result->VEC3_0x4.x * f1 + resPtr->VEC3_0x4.x * f2);
result->VEC3_0x4.y = (result->VEC3_0x4.y * f1 + resPtr->VEC3_0x4.y * f2);
result->VEC3_0x4.z = (result->VEC3_0x4.z * f1 + resPtr->VEC3_0x4.z * f2);
result->s.x = (result->s.x * f1 + resPtr->s.x * f2);
result->s.y = (result->s.y * f1 + resPtr->s.y * f2);
result->s.z = (result->s.z * f1 + resPtr->s.z * f2);
} else {
result->VEC3_0x4.x = (f1 + resPtr->VEC3_0x4.x * f2);
result->VEC3_0x4.y = (f1 + resPtr->VEC3_0x4.y * f2);
result->VEC3_0x4.z = (f1 + resPtr->VEC3_0x4.z * f2);
result->s.x = (f1 + resPtr->s.x * f2);
result->s.y = (f1 + resPtr->s.y * f2);
result->s.z = (f1 + resPtr->s.z * f2);
}
nw4r::math::QUAT q1;
nw4r::math::QUAT q2;
C_QUATMtx(q1, resPtr->mMtx);
C_QUATMtx(q1, resPtr->rt);
if ((flags & 0x20) == 0) {
C_QUATMtx(q2, result->mMtx);
C_QUATMtx(q2, result->rt);
} else {
q2.x = 0.0f;
q2.y = 0.0f;
@@ -54,22 +54,22 @@ void mdl_c::mdlCallback_c::ExecCallbackA(
C_QUATSlerp(q1, q2, q1, f1);
nw4r::math::VEC3 tmp;
tmp.x = result->mMtx._03;
tmp.y = result->mMtx._13;
tmp.z = result->mMtx._23;
PSMTXQuat(result->mMtx, q1);
result->mMtx._03 = tmp.x;
result->mMtx._13 = tmp.y;
result->mMtx._23 = tmp.z;
tmp.x = result->rt._03;
tmp.y = result->rt._13;
tmp.z = result->rt._23;
PSMTXQuat(result->rt, q1);
result->rt._03 = tmp.x;
result->rt._13 = tmp.y;
result->rt._23 = tmp.z;
if ((flags & 0x40) == 0) {
result->mMtx._03 = tmp.x * f1;
result->mMtx._13 = tmp.y * f1;
result->mMtx._23 = tmp.z * f1;
result->rt._03 = tmp.x * f1;
result->rt._13 = tmp.y * f1;
result->rt._23 = tmp.z * f1;
}
result->mMtx._03 += resPtr->mMtx._03 * f2;
result->mMtx._13 += resPtr->mMtx._13 * f2;
result->mMtx._23 += resPtr->mMtx._23 * f2;
result->mFlags = result->mFlags & ~(0x80000000 | 0x00000040 | 0x00000020 | 0x00000008);
result->rt._03 += resPtr->rt._03 * f2;
result->rt._13 += resPtr->rt._13 * f2;
result->rt._23 += resPtr->rt._23 * f2;
result->flags = result->flags & ~(0x80000000 | 0x00000040 | 0x00000020 | 0x00000008);
*resPtr = *result;
}
} else {
@@ -84,11 +84,11 @@ void mdl_c::mdlCallback_c::ExecCallbackA(
void mdl_c::mdlCallback_c::ExecCallbackB(
nw4r::g3d::WorldMtxManip *m, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *o
) {
u16 nodeId = o->GetNodeId();
u16 nodeId = o->GetCallbackNodeID();
if (mpBaseCallback != nullptr) {
mpBaseCallback->timingB(nodeId, m, mdl);
}
o->SetNodeId((nodeId + 1) % mdl.GetResNodeNumEntries());
o->SetCallbackNodeID((nodeId + 1) % mdl.GetResNodeNumEntries());
}
void mdl_c::mdlCallback_c::ExecCallbackC(nw4r::math::MTX34 *mat, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *) {
@@ -118,10 +118,10 @@ bool mdl_c::mdlCallback_c::create(nw4r::g3d::ResMdl mdl, mAllocator_c *alloc, u3
*pSize = ROUND_UP(bufSize + ROUND_UP(*pSize, 0x04), 0x04);
nw4r::g3d::ChrAnmResult *node = mpNodes;
for (int i = 0; i < mNumNode; i++) {
node->VEC3_0x4.x = 1.0f;
node->VEC3_0x4.y = 1.0f;
node->VEC3_0x4.z = 1.0f;
PSMTXIdentity(node->mMtx);
node->s.x = 1.0f;
node->s.y = 1.0f;
node->s.z = 1.0f;
PSMTXIdentity(node->rt);
node++;
}
@@ -199,8 +199,8 @@ bool mdl_c::create(
}
nw4r::g3d::ScnMdlSimple *sMdl;
sMdl = nw4r::g3d::G3dObj::DynamicCast<nw4r::g3d::ScnMdlSimple>(mpScnLeaf);
sMdl->SetCalcWorldCallback(mpCallback);
sMdl->EnableScnMdlCallbackTiming(nw4r::g3d::ScnObj::TIMING_ALL);
sMdl->SetScnMdlCallback(mpCallback);
sMdl->EnableScnMdlCallbackTiming(nw4r::g3d::ScnObj::Timing(0x7));
setCallback(nullptr);
return true;
}
+5 -6
View File
@@ -2,7 +2,6 @@
#include "m/m3d/m3d.h"
namespace m3d {
scnLeaf_c::scnLeaf_c() : mpScnLeaf(nullptr) {}
@@ -39,23 +38,23 @@ void scnLeaf_c::getScale(nw4r::math::VEC3 *vec) const {
}
void scnLeaf_c::setLocalMtx(const nw4r::math::MTX34 *mtx) {
mpScnLeaf->SetMtx(nw4r::g3d::ScnObj::MTX_TYPE_LOCAL, mtx);
mpScnLeaf->SetMtx(nw4r::g3d::ScnObj::MTX_LOCAL, mtx);
}
void scnLeaf_c::getLocalMtx(nw4r::math::MTX34 *mtx) const {
mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_TYPE_LOCAL, mtx);
mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_LOCAL, mtx);
}
const nw4r::math::MTX34 *scnLeaf_c::getLocalMtx() const {
return mpScnLeaf->GetMtxPtr(nw4r::g3d::ScnObj::MTX_TYPE_LOCAL);
return mpScnLeaf->GetMtxPtr(nw4r::g3d::ScnObj::MTX_LOCAL);
}
void scnLeaf_c::getWorldMtx(nw4r::math::MTX34 *mtx) const {
mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_TYPE_WORLD, mtx);
mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_WORLD, mtx);
}
void scnLeaf_c::getViewMtx(nw4r::math::MTX34 *mtx) const {
mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_TYPE_VIEW, mtx);
mpScnLeaf->GetMtx(nw4r::g3d::ScnObj::MTX_VIEW, mtx);
}
// unofficial
+4 -4
View File
@@ -3,12 +3,12 @@
#include "nw4r/g3d/g3d_calcview.h"
#include "nw4r/g3d/g3d_draw.h"
#include "nw4r/g3d/g3d_draw1mat1shp.h"
#include "nw4r/g3d/g3d_resmat.h"
#include "nw4r/g3d/g3d_resmdl.h"
#include "nw4r/g3d/g3d_resshp.h"
#include "nw4r/g3d/g3d_scnmdl.h"
#include "nw4r/g3d/g3d_scnmdlsmpl.h"
#include "nw4r/g3d/g3d_state.h"
#include "nw4r/g3d/res/g3d_resmat.h"
#include "nw4r/g3d/res/g3d_resmdl.h"
#include "nw4r/g3d/res/g3d_resshp.h"
// All of this is completely made up, as we don't have symbols for this TU
// (contrary to the rest of m3d and most of nw4r::g3d)
@@ -548,7 +548,7 @@ void mShadowChild_c::drawMdl() {
g3d::ScnMdl *mdl2 = g3d::G3dObj::DynamicCast<g3d::ScnMdl>(lf->getG3dObject());
g3d::DrawResMdlReplacement *pRep = mdl2 ? mdl2->GetDrawResMdlReplacement() : nullptr;
g3d::DrawResMdlReplacement *pRep = mdl2 ? &mdl2->GetDrawResMdlReplacement() : nullptr;
g3d::DrawResMdlDirectly(
mdl->GetResMdl(), viewPosArray, nullptr, nullptr,
+313
View File
@@ -0,0 +1,313 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace detail {
namespace dcc {
namespace {
void MakeTexSrtMtx_S(math::MTX34 *pMtx, const TexSrt &rSrt) {
pMtx->_00 = rSrt.Su;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = 0.5f * (1.0f - rSrt.Su);
pMtx->_10 = 0.0f;
pMtx->_11 = rSrt.Sv;
pMtx->_12 = 0.0f;
pMtx->_13 = 0.5f * (1.0f - rSrt.Sv);
}
void MakeTexSrtMtx_R(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
pMtx->_00 = cosR;
pMtx->_01 = sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = -0.5f * (cosR + sinR - 1.0f);
pMtx->_10 = -sinR;
pMtx->_11 = cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = -0.5f * (-sinR + cosR - 1.0f);
}
void MakeTexSrtMtx_T(math::MTX34 *pMtx, const TexSrt &rSrt) {
pMtx->_00 = 1.0f;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = -rSrt.Tu;
pMtx->_10 = 0.0f;
pMtx->_11 = 1.0f;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Tv;
}
void MakeTexSrtMtx_SR(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
pMtx->_00 = sucr;
pMtx->_01 = susr;
pMtx->_02 = 0.0f;
pMtx->_03 = -0.5f * (sucr + susr - 1.0f);
pMtx->_10 = -svsr;
pMtx->_11 = svcr;
pMtx->_12 = 0.0f;
pMtx->_13 = -0.5f * (-svsr + svcr - 1.0f);
}
void MakeTexSrtMtx_RT(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
pMtx->_00 = cosR;
pMtx->_01 = sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = -cosR * (0.5f + rSrt.Tu) + sinR * (rSrt.Tv - 0.5f) + 0.5f;
pMtx->_10 = -sinR;
pMtx->_11 = cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = sinR * (0.5f + rSrt.Tu) + cosR * (rSrt.Tv - 0.5f) + 0.5f;
}
void MakeTexSrtMtx_ST(math::MTX34 *pMtx, const TexSrt &rSrt) {
pMtx->_00 = rSrt.Su;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = -rSrt.Su * (0.5f + rSrt.Tu) + 0.5f;
pMtx->_10 = 0.0f;
pMtx->_11 = rSrt.Sv;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Sv * (rSrt.Tv - 0.5f) + 0.5f;
}
void MakeTexSrtMtx_SRT(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
pMtx->_00 = sucr;
pMtx->_01 = susr;
pMtx->_02 = 0.0f;
pMtx->_03 = -sucr * (0.5f + rSrt.Tu) + susr * (rSrt.Tv - 0.5f) + 0.5f;
pMtx->_10 = -svsr;
pMtx->_11 = svcr;
pMtx->_12 = 0.0f;
pMtx->_13 = svsr * (0.5f + rSrt.Tu) + svcr * (rSrt.Tv - 0.5f) + 0.5f;
}
void ProductTexSrtMtx_S(math::MTX34 *pMtx, const TexSrt &rSrt) {
pMtx->_00 *= rSrt.Su;
pMtx->_01 *= rSrt.Su;
pMtx->_02 *= rSrt.Su;
pMtx->_03 = rSrt.Su * (pMtx->_03 - 0.5f) + 0.5f;
pMtx->_10 *= rSrt.Sv;
pMtx->_11 *= rSrt.Sv;
pMtx->_12 *= rSrt.Sv;
pMtx->_13 = rSrt.Sv * (pMtx->_13 - 0.5f) + 0.5f;
}
void ProductTexSrtMtx_R(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
_0x = cosR * pMtx->_00 + sinR * pMtx->_10;
_1x = -sinR * pMtx->_00 + cosR * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = cosR * pMtx->_01 + sinR * pMtx->_11;
_1x = -sinR * pMtx->_01 + cosR * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = cosR * pMtx->_02 + sinR * pMtx->_12;
_1x = -sinR * pMtx->_02 + cosR * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = cosR * (pMtx->_03 - 0.5f) + sinR * (pMtx->_13 - 0.5f) + 0.5f;
_1x = -sinR * (pMtx->_03 - 0.5f) + cosR * (pMtx->_13 - 0.5f) + 0.5f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_T(math::MTX34 *pMtx, const TexSrt &rSrt) {
pMtx->_03 -= rSrt.Tu;
pMtx->_13 += rSrt.Tv;
}
void ProductTexSrtMtx_SR(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
_0x = sucr * pMtx->_00 + susr * pMtx->_10;
_1x = -svsr * pMtx->_00 + svcr * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = sucr * pMtx->_01 + susr * pMtx->_11;
_1x = -svsr * pMtx->_01 + svcr * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = sucr * pMtx->_02 + susr * pMtx->_12;
_1x = -svsr * pMtx->_02 + svcr * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = sucr * (pMtx->_03 - 0.5f) + susr * (pMtx->_13 - 0.5f) + 0.5f;
_1x = -svsr * (pMtx->_03 - 0.5f) + svcr * (pMtx->_13 - 0.5f) + 0.5f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_RT(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
_0x = cosR * pMtx->_00 + sinR * pMtx->_10;
_1x = -sinR * pMtx->_00 + cosR * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = cosR * pMtx->_01 + sinR * pMtx->_11;
_1x = -sinR * pMtx->_01 + cosR * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = cosR * pMtx->_02 + sinR * pMtx->_12;
_1x = -sinR * pMtx->_02 + cosR * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = cosR * (pMtx->_03 - rSrt.Tu - 0.5f) + sinR * (pMtx->_13 + rSrt.Tv - 0.5f) + 0.5f;
_1x = -sinR * (pMtx->_03 - rSrt.Tu - 0.5f) + cosR * (pMtx->_13 + rSrt.Tv - 0.5f) + 0.5f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_ST(math::MTX34 *pMtx, const TexSrt &rSrt) {
pMtx->_00 *= rSrt.Su;
pMtx->_01 *= rSrt.Su;
pMtx->_02 *= rSrt.Su;
pMtx->_03 = rSrt.Su * (pMtx->_03 - rSrt.Tu - 0.5f) + 0.5f;
pMtx->_10 *= rSrt.Sv;
pMtx->_11 *= rSrt.Sv;
pMtx->_12 *= rSrt.Sv;
pMtx->_13 *= rSrt.Sv * (pMtx->_13 + rSrt.Tv - 0.5f) + 0.5f;
}
void ProductTexSrtMtx_SRT(math::MTX34 *pMtx, const TexSrt &rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
_0x = sucr * pMtx->_00 + susr * pMtx->_10;
_1x = -svsr * pMtx->_00 + svcr * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = sucr * pMtx->_01 + susr * pMtx->_11;
_1x = -svsr * pMtx->_01 + svcr * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = sucr * pMtx->_02 + susr * pMtx->_12;
_1x = -svsr * pMtx->_02 + svcr * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = sucr * (pMtx->_03 - rSrt.Tu - 0.5f) + susr * (pMtx->_13 + rSrt.Tv - 0.5f) + 0.5f;
_1x = -svsr * (pMtx->_03 - rSrt.Tu - 0.5f) + svcr * (pMtx->_13 + rSrt.Tv - 0.5f) + 0.5f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
} // namespace
typedef void (*CalcTexMtxFunc)(math::MTX34 *pMtx, const TexSrt &rSrt);
bool CalcTexMtx_3dsmax(math::MTX34 *pMtx, bool set, const TexSrt &rSrt, TexSrt::Flag flag) {
// Extract S/R/T flags
u32 index = flag >> 1 & 0b111;
// Scale-one, no rotate/trans
if (index == 0b111) {
return false;
}
if (set) {
static const CalcTexMtxFunc funcTable[] = {
MakeTexSrtMtx_SRT, // 0 0 0
MakeTexSrtMtx_RT, // 0 0 1
MakeTexSrtMtx_ST, // 0 1 0
MakeTexSrtMtx_T, // 0 1 1
MakeTexSrtMtx_SR, // 1 0 0
MakeTexSrtMtx_R, // 1 0 1
MakeTexSrtMtx_S // 1 1 0
};
funcTable[index](pMtx, rSrt);
} else {
static const CalcTexMtxFunc funcTable[] = {
ProductTexSrtMtx_SRT, // 0 0 0
ProductTexSrtMtx_RT, // 0 0 1
ProductTexSrtMtx_ST, // 0 1 0
ProductTexSrtMtx_T, // 0 1 1
ProductTexSrtMtx_SR, // 1 0 0
ProductTexSrtMtx_R, // 1 0 1
ProductTexSrtMtx_S // 1 1 0
};
funcTable[index](pMtx, rSrt);
}
pMtx->_20 = 0.0f;
pMtx->_21 = 0.0f;
pMtx->_22 = 1.0f;
pMtx->_23 = 0.0f;
return true;
}
} // namespace dcc
} // namespace detail
} // namespace g3d
} // namespace nw4r
+764
View File
@@ -0,0 +1,764 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
#include <rvl/GX.h>
#include <cmath.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObjChr);
NW4R_G3D_RTTI_DEF(AnmObjChrNode);
NW4R_G3D_RTTI_DEF(AnmObjChrBlend);
NW4R_G3D_RTTI_DEF(AnmObjChrRes);
namespace {
u32 GetPartialNodeEndId(const ResMdl mdl, u32 target) {
ResNode targetNode = mdl.GetResNode(target);
ResNode node = targetNode;
ResNode endNode = node.GetNextSibling();
while (!endNode.IsValid()) {
node = node.GetParentNode();
if (!node.IsValid()) {
break;
}
endNode = node.GetNextSibling();
}
if (endNode.IsValid()) {
return endNode.GetID();
}
return mdl.GetResNodeNumEntries();
}
} // namespace
/******************************************************************************
*
* AnmObjChr
*
******************************************************************************/
AnmObjChr::AnmObjChr(MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding)
: AnmObj(pAllocator, NULL), mNumBinding(numBinding), mpBinding(pBindingBuf) {
Release();
}
bool AnmObjChr::TestExistence(u32 idx) const {
return !(mpBinding[idx] & (BINDING_UNDEFINED | BINDING_INVALID));
}
bool AnmObjChr::TestDefined(u32 idx) const {
return !(mpBinding[idx] & BINDING_UNDEFINED);
}
void AnmObjChr::Release() {
for (int i = 0; i < mNumBinding; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
SetAnmFlag(FLAG_ANM_BOUND, false);
}
AnmObjChrRes *AnmObjChr::Attach(int idx, AnmObjChrRes *pRes) {
#pragma unused(idx)
#pragma unused(pRes)
return NULL;
}
AnmObjChrRes *AnmObjChr::Detach(int idx) {
#pragma unused(idx)
return NULL;
}
void AnmObjChr::SetWeight(int idx, f32 weight){
#pragma unused(idx)
#pragma unused(weight)
}
f32 AnmObjChr::GetWeight(int idx) const {
#pragma unused(idx)
return 0.0f;
}
void AnmObjChr::DetachAll() {}
/******************************************************************************
*
* AnmObjChrNode
*
******************************************************************************/
AnmObjChrNode::AnmObjChrNode(
MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding, AnmObjChrRes **ppChildrenBuf, int numChildren
)
: AnmObjChr(pAllocator, pBindingBuf, numBinding), mChildrenArraySize(numChildren), mpChildrenArray(ppChildrenBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpChildrenArray[i] = NULL;
}
}
AnmObjChrNode::~AnmObjChrNode() {
DetachAll();
}
AnmObjChrRes *AnmObjChrNode::Attach(int idx, AnmObjChrRes *pRes) {
AnmObjChrRes *pOld = Detach(idx);
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
if (!pRes->TestDefined(i)) {
continue;
}
hasAnm = true;
mpBinding[i] = 0;
}
if (hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, true);
}
mpChildrenArray[idx] = pRes;
pRes->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return pOld;
}
AnmObjChrRes *AnmObjChrNode::Detach(int idx) {
AnmObjChrRes *pOld = mpChildrenArray[idx];
if (pOld != NULL) {
pOld->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpChildrenArray[idx] = NULL;
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
u16 binding = BINDING_UNDEFINED;
for (int j = 0; j < mChildrenArraySize; j++) {
AnmObjChrRes *pChild = mpChildrenArray[j];
if (pChild == NULL || !pChild->TestDefined(i)) {
continue;
}
hasAnm = true;
binding = 0;
break;
}
mpBinding[i] = binding;
}
if (!hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, false);
}
}
return pOld;
}
void AnmObjChrNode::DetachAll() {
for (int i = 0; i < mChildrenArraySize; i++) {
Detach(i);
}
}
void AnmObjChrNode::UpdateFrame() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->UpdateFrame();
}
}
}
void AnmObjChrNode::SetFrame(f32 frame) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetFrame(frame);
}
}
}
f32 AnmObjChrNode::GetFrame() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetFrame();
}
}
return 0.0f;
}
void AnmObjChrNode::SetUpdateRate(f32 rate) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetUpdateRate(rate);
}
}
}
f32 AnmObjChrNode::GetUpdateRate() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetUpdateRate();
}
}
return 1.0f;
}
bool AnmObjChrNode::Bind(const ResMdl mdl) {
bool success = false;
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjChrRes *pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
bool AnmObjChrNode::Bind(const ResMdl mdl, u32 target, BindOption option) {
bool success = false;
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjChrRes *pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl, target, option);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjChrNode::Release() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->Release();
}
}
AnmObjChr::Release();
}
void AnmObjChrNode::Release(const ResMdl mdl, u32 target, BindOption option) {
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjChrRes *pChild = mpChildrenArray[i];
if (pChild != NULL) {
pChild->Release(mdl, target, option);
}
}
AnmObjChr::Release();
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjChrRes *pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
}
void AnmObjChrNode::G3dProc(u32 task, u32 param, void *pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_CHILD_DETACHED: {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] == pInfo) {
Detach(i);
return;
}
}
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj *>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjChrBlend
*
******************************************************************************/
AnmObjChrBlend *AnmObjChrBlend::Construct(MEMAllocator *pAllocator, u32 *pSize, ResMdl mdl, int numChildren) {
if (!mdl.IsValid()) {
return NULL;
}
int bindNum = mdl.GetResNodeNumEntries();
u32 bindSize = bindNum * sizeof(u16);
u32 childrenSize = numChildren * sizeof(AnmObjChrRes *);
u32 weightSize = numChildren * sizeof(f32);
u32 bindOfs = ut::RoundUp(sizeof(AnmObjChrBlend), 4);
u32 childrenOfs = ut::RoundUp(bindOfs + bindSize, 4);
u32 weightOfs = ut::RoundUp(childrenOfs + childrenSize, 4);
u32 size = ut::RoundUp(weightOfs + weightSize, 4);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
return new (pBuffer) AnmObjChrBlend(
pAllocator,
reinterpret_cast<u16*>(pBuffer + bindOfs),
bindNum,
reinterpret_cast<AnmObjChrRes**>(pBuffer + childrenOfs),
numChildren,
reinterpret_cast<f32*>(pBuffer + weightOfs));
// clang-format on
}
AnmObjChrBlend::AnmObjChrBlend(
MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding, AnmObjChrRes **ppChildrenBuf, int numChildren,
f32 *pWeightBuf
)
: AnmObjChrNode(pAllocator, pBindingBuf, numBinding, ppChildrenBuf, numChildren), mpWeightArray(pWeightBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpWeightArray[i] = 1.0f;
}
}
const ChrAnmResult *AnmObjChrBlend::GetResult(ChrAnmResult *pResult, u32 idx) {
AnmObjChrRes *pFirstChild = NULL;
int blendNum = 0;
f32 weightSum = 0.0f;
for (u32 i = 0; static_cast<int>(i) < mChildrenArraySize; i++) {
f32 weight = mpWeightArray[i];
AnmObjChrRes *pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
if (weight == 0.0f || !pChild->TestExistence(idx)) {
continue;
}
blendNum++;
weightSum += weight;
if (pFirstChild == NULL) {
pFirstChild = pChild;
}
}
if (blendNum == 0) {
pResult->flags = 0;
return pResult;
}
if (blendNum == 1) {
return pFirstChild->GetResult(pResult, idx);
}
bool useQuat = TestAnmFlag(FLAG_USE_QUATERNION_ROTATION_BLEND);
bool useAccScale = TestAnmFlag(FLAG_USE_ACCURATE_SCALE_BLEND);
f32 esx = 0.0f;
f32 esy = 0.0f;
f32 esz = 0.0f;
math::QUAT rot(0.0f, 0.0f, 0.0f, 1.0f);
f32 addedWeight = 0.0f;
math::MTX33 firstRot;
f32 invWeightSum = math::FInv(weightSum);
pResult->flags = 0xFFFFFFFF;
pResult->s.x = 0.0f;
pResult->s.y = 0.0f;
pResult->s.z = 0.0f;
math::MTX34Zero(&pResult->rt);
for (int i = 0; i < mChildrenArraySize; i++) {
ChrAnmResult resultBuf;
AnmObjChrRes *pChild = mpChildrenArray[i];
f32 weight = mpWeightArray[i];
if (pChild == NULL || weight == 0.0f || !pChild->TestExistence(idx)) {
continue;
}
const ChrAnmResult *pMyResult = pChild->GetResult(&resultBuf, idx);
f32 ratio = weight * invWeightSum;
u32 flags = pMyResult->flags;
if (useAccScale) {
if (!(flags & ChrAnmResult::FLAG_SCALE_ONE)) {
esx += ratio * math::FLog(pMyResult->s.x);
esy += ratio * math::FLog(pMyResult->s.y);
esz += ratio * math::FLog(pMyResult->s.z);
}
} else if (!(flags & ChrAnmResult::FLAG_SCALE_ONE)) {
pResult->s.x += pMyResult->s.x * ratio;
pResult->s.y += pMyResult->s.y * ratio;
pResult->s.z += pMyResult->s.z * ratio;
} else {
pResult->s.x += ratio;
pResult->s.y += ratio;
pResult->s.z += ratio;
}
if (useQuat) {
math::QUAT q;
if (!(flags & ChrAnmResult::FLAG_ROT_ZERO)) {
math::MTX34ToQUAT(&q, &pMyResult->rt);
} else {
q.x = 0.0f;
q.y = 0.0f;
q.z = 0.0f;
q.w = 1.0f;
}
addedWeight += weight;
f32 invAddedWeight = math::FInv(addedWeight);
f32 t = weight * invAddedWeight;
math::C_QUATSlerp(&rot, &rot, &q, t);
} else if (!(flags & ChrAnmResult::FLAG_ROT_ZERO)) {
pResult->rt._00 += pMyResult->rt._00 * ratio;
pResult->rt._01 += pMyResult->rt._01 * ratio;
pResult->rt._02 += pMyResult->rt._02 * ratio;
pResult->rt._10 += pMyResult->rt._10 * ratio;
pResult->rt._11 += pMyResult->rt._11 * ratio;
pResult->rt._12 += pMyResult->rt._12 * ratio;
} else {
pResult->rt._00 += ratio;
pResult->rt._11 += ratio;
}
if (!(flags & ChrAnmResult::FLAG_TRANS_ZERO)) {
pResult->rt._03 += pMyResult->rt._03 * ratio;
pResult->rt._13 += pMyResult->rt._13 * ratio;
pResult->rt._23 += pMyResult->rt._23 * ratio;
}
pResult->flags &= flags;
}
if (useAccScale) {
pResult->s.x = math::FExp(esx);
pResult->s.y = math::FExp(esy);
pResult->s.z = math::FExp(esz);
}
if (useQuat) {
Vec t;
t.x = pResult->rt._03;
t.y = pResult->rt._13;
t.z = pResult->rt._23;
math::QUATToMTX34(&pResult->rt, &rot);
pResult->rt._03 = t.x;
pResult->rt._13 = t.y;
pResult->rt._23 = t.z;
} else {
math::VEC3 *pV0 = reinterpret_cast<math::VEC3 *>(&pResult->rt._00);
math::VEC3 *pV1 = reinterpret_cast<math::VEC3 *>(&pResult->rt._10);
math::VEC3 *pV2 = reinterpret_cast<math::VEC3 *>(&pResult->rt._20);
math::VEC3Cross(pV2, pV0, pV1);
math::VEC3Normalize(pV0, pV0);
math::VEC3Normalize(pV2, pV2);
math::VEC3Cross(pV1, pV2, pV0);
}
pResult->flags &= ~ChrAnmResult::FLAG_ROT_RAW_FMT;
return pResult;
}
void AnmObjChrBlend::SetWeight(int idx, f32 weight) {
mpWeightArray[idx] = weight;
}
f32 AnmObjChrBlend::GetWeight(int idx) const {
return mpWeightArray[idx];
}
/******************************************************************************
*
* AnmObjChrRes
*
******************************************************************************/
AnmObjChrRes *AnmObjChrRes::Construct(MEMAllocator *pAllocator, u32 *pSize, ResAnmChr chr, ResMdl mdl, bool cache) {
if (!chr.IsValid() || !mdl.IsValid()) {
return NULL;
}
int numAnim = chr.GetNumNode();
int numMat = mdl.GetResNodeNumEntries();
int bindNum = numMat;
int cacheNum = cache ? numAnim : 0;
u32 bindSize = bindNum * sizeof(u16);
u32 cacheSize = cacheNum * sizeof(ChrAnmResult);
u32 size = bindSize + cacheSize + sizeof(AnmObjChrRes);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
ChrAnmResult *pCacheBuf = cache ? reinterpret_cast<ChrAnmResult *>(pBuffer + sizeof(AnmObjChrRes)) : NULL;
u16 *pBindingBuf = reinterpret_cast<u16 *>(cacheSize + (pBuffer + sizeof(AnmObjChrRes)));
return new (pBuffer) AnmObjChrRes(pAllocator, chr, pBindingBuf, bindNum, pCacheBuf);
}
AnmObjChrRes::AnmObjChrRes(
MEMAllocator *pAllocator, ResAnmChr chr, u16 *pBindingBuf, int numBinding, ChrAnmResult *pCacheBuf
)
: AnmObjChr(pAllocator, pBindingBuf, numBinding),
FrameCtrl(0.0f, chr.GetNumFrame(), GetAnmPlayPolicy(chr.GetAnmPolicy())),
mRes(chr),
mpResultCache(pCacheBuf) {
if (mpResultCache != NULL) {
UpdateCache();
}
}
void AnmObjChrRes::SetFrame(f32 frame) {
SetFrm(frame);
if (mpResultCache != NULL) {
UpdateCache();
}
}
f32 AnmObjChrRes::GetFrame() const {
return GetFrm();
}
void AnmObjChrRes::SetUpdateRate(f32 rate) {
SetRate(rate);
}
f32 AnmObjChrRes::GetUpdateRate() const {
return GetRate();
}
void AnmObjChrRes::UpdateFrame() {
UpdateFrm();
if (mpResultCache != NULL) {
UpdateCache();
}
}
bool AnmObjChrRes::Bind(const ResMdl mdl) {
int numAnim = mRes.GetNumNode();
bool success = false;
for (u16 i = 0; i < numAnim; i++) {
const ResAnmChrNodeData *pData = mRes.GetNodeAnm(i);
// Seek back from name string to start of ResName
ResName name(ut::AddOffsetToPtr(pData, pData->name - 4));
ResNode node = mdl.GetResNode(name);
if (!node.IsValid()) {
continue;
}
mpBinding[node.GetID()] = i;
success = true;
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
bool AnmObjChrRes::Bind(const ResMdl mdl, u32 target, BindOption option) {
bool success = false;
switch (option) {
case BIND_PARTIAL: {
u32 bindBegin = target;
u32 bindEnd = GetPartialNodeEndId(mdl, bindBegin);
for (u32 i = bindBegin; i < bindEnd; i++) {
ResNode node = mdl.GetResNode(i);
ResName name = node.GetResName();
int id = mRes.GetNodeAnmIndex(name);
if (id != ResDic::NOT_FOUND) {
mpBinding[i] = static_cast<u16>(id);
success = true;
}
}
break;
}
case BIND_ONE: {
ResNode node = mdl.GetResNode(target);
ResName name = node.GetResName();
int id = mRes.GetNodeAnmIndex(name);
if (id != ResDic::NOT_FOUND) {
mpBinding[target] = static_cast<u16>(id);
success = true;
}
break;
}
default: {
break;
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjChrRes::Release(const ResMdl mdl, u32 target, BindOption option) {
switch (option) {
case BIND_PARTIAL: {
u32 bindBegin = target;
u32 bindEnd = GetPartialNodeEndId(mdl, bindBegin);
for (u32 i = bindBegin; i < bindEnd; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
break;
}
case BIND_ONE: {
mpBinding[target] = BINDING_UNDEFINED;
break;
}
default: {
break;
}
}
}
const ChrAnmResult *AnmObjChrRes::GetResult(ChrAnmResult *pResult, u32 idx) {
u32 id = mpBinding[idx];
if (id & (BINDING_UNDEFINED | BINDING_INVALID)) {
pResult->flags = 0;
return pResult;
}
if (mpResultCache != NULL) {
return &mpResultCache[id];
}
mRes.GetAnmResult(pResult, id, GetFrm());
return pResult;
}
void AnmObjChrRes::UpdateCache() {
f32 frame = GetFrm();
for (u32 i = 0; i < mNumBinding; i++) {
u16 bind = mpBinding[i];
if (!(bind & BINDING_UNDEFINED)) {
u32 id = bind & BINDING_ID_MASK;
mRes.GetAnmResult(&mpResultCache[id], id, frame);
}
}
}
void AnmObjChrRes::G3dProc(u32 task, u32 param, void *pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_UPDATEFRAME: {
UpdateFrame();
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj *>(pInfo));
break;
}
}
}
} // namespace g3d
} // namespace nw4r
+600
View File
@@ -0,0 +1,600 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObjMatClr);
NW4R_G3D_RTTI_DEF(AnmObjMatClrNode);
NW4R_G3D_RTTI_DEF(AnmObjMatClrOverride);
NW4R_G3D_RTTI_DEF(AnmObjMatClrRes);
/******************************************************************************
*
* AnmObjMatClr
*
******************************************************************************/
AnmObjMatClr::AnmObjMatClr(MEMAllocator* pAllocator, u16* pBindingBuf,
int numBinding)
: AnmObj(pAllocator, NULL),
mNumBinding(numBinding),
mpBinding(pBindingBuf) {
Release();
}
bool AnmObjMatClr::TestExistence(u32 idx) const {
return !(mpBinding[idx] & (BINDING_UNDEFINED | BINDING_INVALID));
}
bool AnmObjMatClr::TestDefined(u32 idx) const {
return !(mpBinding[idx] & BINDING_UNDEFINED);
}
void AnmObjMatClr::Release() {
for (int i = 0; i < mNumBinding; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
SetAnmFlag(FLAG_ANM_BOUND, false);
}
AnmObjMatClrRes* AnmObjMatClr::Attach(int idx, AnmObjMatClrRes* pRes) {
#pragma unused(idx)
#pragma unused(pRes)
return NULL;
}
AnmObjMatClrRes* AnmObjMatClr::Detach(int idx) {
#pragma unused(idx)
return NULL;
}
void AnmObjMatClr::DetachAll() {}
/******************************************************************************
*
* AnmObjMatClrNode
*
******************************************************************************/
AnmObjMatClrNode::AnmObjMatClrNode(MEMAllocator* pAllocator, u16* pBindingBuf,
int numBinding,
AnmObjMatClrRes** ppChildrenBuf,
int numChildren)
: AnmObjMatClr(pAllocator, pBindingBuf, numBinding),
mChildrenArraySize(numChildren),
mpChildrenArray(ppChildrenBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpChildrenArray[i] = NULL;
}
}
AnmObjMatClrNode::~AnmObjMatClrNode() {
DetachAll();
}
AnmObjMatClrRes* AnmObjMatClrNode::Attach(int idx, AnmObjMatClrRes* pRes) {
AnmObjMatClrRes* pOld = Detach(idx);
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
if (!pRes->TestDefined(i)) {
continue;
}
hasAnm = true;
mpBinding[i] = 0;
}
if (hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, true);
}
mpChildrenArray[idx] = pRes;
pRes->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return pOld;
}
AnmObjMatClrRes* AnmObjMatClrNode::Detach(int idx) {
AnmObjMatClrRes* pOld = mpChildrenArray[idx];
if (pOld != NULL) {
pOld->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpChildrenArray[idx] = NULL;
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
u16 binding = BINDING_UNDEFINED;
for (int j = 0; j < mChildrenArraySize; j++) {
AnmObjMatClrRes* pChild = mpChildrenArray[j];
if (pChild == NULL || !pChild->TestDefined(i)) {
continue;
}
hasAnm = true;
binding = 0;
break;
}
mpBinding[i] = binding;
}
if (!hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, false);
}
}
return pOld;
}
void AnmObjMatClrNode::DetachAll() {
for (int i = 0; i < mChildrenArraySize; i++) {
Detach(i);
}
}
void AnmObjMatClrNode::UpdateFrame() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->UpdateFrame();
}
}
}
void AnmObjMatClrNode::SetFrame(f32 frame) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetFrame(frame);
}
}
}
f32 AnmObjMatClrNode::GetFrame() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetFrame();
}
}
return 0.0f;
}
void AnmObjMatClrNode::SetUpdateRate(f32 rate) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetUpdateRate(rate);
}
}
}
f32 AnmObjMatClrNode::GetUpdateRate() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetUpdateRate();
}
}
return 1.0f;
}
bool AnmObjMatClrNode::Bind(const ResMdl mdl) {
bool success = false;
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjMatClrRes* pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjMatClrNode::Release() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->Release();
}
}
AnmObjMatClr::Release();
}
void AnmObjMatClrNode::G3dProc(u32 task, u32 param, void* pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_CHILD_DETACHED: {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] == pInfo) {
Detach(i);
return;
}
}
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjMatClrOverride
*
******************************************************************************/
AnmObjMatClrOverride* AnmObjMatClrOverride::Construct(MEMAllocator* pAllocator,
u32* pSize, ResMdl mdl,
int numChildren) {
if (!mdl.IsValid()) {
return NULL;
}
int numAnim = mdl.GetResMatNumEntries();
int bindNum = numAnim;
u32 objSize = sizeof(AnmObjMatClrOverride);
u32 bindSize = bindNum * sizeof(u16);
u32 childrenSize = numChildren * sizeof(AnmObjMatClrRes*);
u32 bindOfs = align4(objSize);
u32 childrenOfs = align4(bindOfs + bindSize);
u32 size = align4(childrenOfs + childrenSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
return new (pBuffer) AnmObjMatClrOverride(
pAllocator,
reinterpret_cast<u16*>(pBuffer + bindOfs),
bindNum,
reinterpret_cast<AnmObjMatClrRes**>(pBuffer + childrenOfs),
numChildren);
// clang-format on
}
const ClrAnmResult* AnmObjMatClrOverride::GetResult(ClrAnmResult* pResult,
u32 idx) {
for (int i = mChildrenArraySize - 1; i >= 0; i--) {
AnmObjMatClrRes* pChild = mpChildrenArray[i];
if (pChild == NULL || !pChild->TestExistence(idx)) {
continue;
}
const ClrAnmResult* pChildResult = pChild->GetResult(pResult, idx);
if (pChildResult->bRgbaExist != 0) {
return pChildResult;
}
}
pResult->bRgbaExist = 0;
return pResult;
}
/******************************************************************************
*
* AnmObjMatClrRes
*
******************************************************************************/
AnmObjMatClrRes* AnmObjMatClrRes::Construct(MEMAllocator* pAllocator,
u32* pSize, ResAnmClr clr,
ResMdl mdl, bool cache) {
if (!clr.IsValid() || !mdl.IsValid()) {
return NULL;
}
int numAnim = clr.GetNumMaterial();
int numMat = mdl.GetResMatNumEntries();
int bindNum = numMat;
int cacheNum = cache ? numAnim : 0;
u32 bindSize = bindNum * sizeof(u16);
u32 cacheSize = cacheNum * sizeof(ClrAnmResult);
u32 size = bindSize + cacheSize + sizeof(AnmObjMatClrRes);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
ClrAnmResult* pCacheBuf =
cache
? reinterpret_cast<ClrAnmResult*>(pBuffer + sizeof(AnmObjMatClrRes))
: NULL;
u16* pBindingBuf =
reinterpret_cast<u16*>(cacheSize + (pBuffer + sizeof(AnmObjMatClrRes)));
return new (pBuffer)
AnmObjMatClrRes(pAllocator, clr, pBindingBuf, bindNum, pCacheBuf);
}
AnmObjMatClrRes::AnmObjMatClrRes(MEMAllocator* pAllocator, ResAnmClr clr,
u16* pBindingBuf, int numBinding,
ClrAnmResult* pCacheBuf)
: AnmObjMatClr(pAllocator, pBindingBuf, numBinding),
FrameCtrl(0.0f, clr.GetNumFrame(), GetAnmPlayPolicy(clr.GetAnmPolicy())),
mRes(clr),
mpResultCache(pCacheBuf) {
if (mpResultCache != NULL) {
UpdateCache();
}
}
void AnmObjMatClrRes::SetFrame(f32 frame) {
SetFrm(frame);
if (mpResultCache != NULL) {
UpdateCache();
}
}
f32 AnmObjMatClrRes::GetFrame() const {
return GetFrm();
}
void AnmObjMatClrRes::SetUpdateRate(f32 rate) {
SetRate(rate);
}
f32 AnmObjMatClrRes::GetUpdateRate() const {
return GetRate();
}
void AnmObjMatClrRes::UpdateFrame() {
UpdateFrm();
if (mpResultCache != NULL) {
UpdateCache();
}
}
bool AnmObjMatClrRes::Bind(const ResMdl mdl) {
int numAnim = mRes.GetNumMaterial();
bool success = false;
for (u16 i = 0; i < numAnim; i++) {
const ResAnmClrMatData* pData = mRes.GetMatAnm(i);
// Seek back from name string to start of ResName
ResName name(ut::AddOffsetToPtr(pData, pData->name - 4));
ResMat mat = mdl.GetResMat(name);
if (!mat.IsValid()) {
continue;
}
mpBinding[mat.GetID()] = i;
success = true;
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
const ClrAnmResult* AnmObjMatClrRes::GetResult(ClrAnmResult* pResult, u32 idx) {
u32 id = mpBinding[idx];
if (id & (BINDING_UNDEFINED | BINDING_INVALID)) {
pResult->bRgbaExist = 0;
return pResult;
}
if (mpResultCache != NULL) {
return &mpResultCache[id];
}
mRes.GetAnmResult(pResult, id, GetFrm());
return pResult;
}
void AnmObjMatClrRes::UpdateCache() {
f32 frame = GetFrm();
for (u32 i = 0; i < mNumBinding; i++) {
u16 bind = mpBinding[i];
if (!(bind & BINDING_UNDEFINED)) {
u32 id = bind & BINDING_ID_MASK;
mRes.GetAnmResult(&mpResultCache[id], id, frame);
}
}
}
void AnmObjMatClrRes::G3dProc(u32 task, u32 param, void* pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_UPDATEFRAME: {
UpdateFrame();
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
}
}
/******************************************************************************
*
* ApplyClrAnmResult
*
******************************************************************************/
void ApplyClrAnmResult(ResMatChan chan, ResMatTevColor tev,
const ClrAnmResult* pResult) {
ut::Color c;
if (pResult->bRgbaExist &
(1 << ClrAnmResult::CLA_CLR0 | 1 << ClrAnmResult::CLA_CLR1 |
1 << ClrAnmResult::CLA_AMB0 | 1 << ClrAnmResult::CLA_AMB1)) {
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_CLR0)) {
GXColor& rMatColor = chan.ref().chan[0].matColor;
c = rMatColor;
rMatColor = (c & pResult->rgbaMask[ClrAnmResult::CLA_CLR0]) |
pResult->rgba[ClrAnmResult::CLA_CLR0];
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_AMB0)) {
GXColor& rMatColor = chan.ref().chan[0].ambColor;
c = rMatColor;
rMatColor = (c & pResult->rgbaMask[ClrAnmResult::CLA_AMB0]) |
pResult->rgba[ClrAnmResult::CLA_AMB0];
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_CLR1)) {
GXColor& rMatColor = chan.ref().chan[1].matColor;
c = rMatColor;
rMatColor = (c & pResult->rgbaMask[ClrAnmResult::CLA_CLR1]) |
pResult->rgba[ClrAnmResult::CLA_CLR1];
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_AMB1)) {
GXColor& rMatColor = chan.ref().chan[1].ambColor;
c = rMatColor;
rMatColor = (c & pResult->rgbaMask[ClrAnmResult::CLA_AMB1]) |
pResult->rgba[ClrAnmResult::CLA_AMB1];
}
}
if (pResult->bRgbaExist &
(1 << ClrAnmResult::CLA_TEV0 | 1 << ClrAnmResult::CLA_TEV1 |
1 << ClrAnmResult::CLA_TEV2 | 1 << ClrAnmResult::CLA_TEVK0 |
1 << ClrAnmResult::CLA_TEVK1 | 1 << ClrAnmResult::CLA_TEVK2 |
1 << ClrAnmResult::CLA_TEVK3)) {
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEV0)) {
if (!tev.GXGetTevColor(GX_TEVREG0, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevColor(GX_TEVREG0,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEV0] |
pResult->rgba[ClrAnmResult::CLA_TEV0]);
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEV1)) {
if (!tev.GXGetTevColor(GX_TEVREG1, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevColor(GX_TEVREG1,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEV1] |
pResult->rgba[ClrAnmResult::CLA_TEV1]);
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEV2)) {
if (!tev.GXGetTevColor(GX_TEVREG2, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevColor(GX_TEVREG2,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEV2] |
pResult->rgba[ClrAnmResult::CLA_TEV2]);
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEVK0)) {
if (!tev.GXGetTevKColor(GX_KCOLOR0, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevKColor(GX_KCOLOR0,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEVK0] |
pResult->rgba[ClrAnmResult::CLA_TEVK0]);
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEVK1)) {
if (!tev.GXGetTevKColor(GX_KCOLOR1, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevKColor(GX_KCOLOR1,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEVK1] |
pResult->rgba[ClrAnmResult::CLA_TEVK1]);
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEVK2)) {
if (!tev.GXGetTevKColor(GX_KCOLOR2, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevKColor(GX_KCOLOR2,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEVK2] |
pResult->rgba[ClrAnmResult::CLA_TEVK2]);
}
if (pResult->bRgbaExist & (1 << ClrAnmResult::CLA_TEVK3)) {
if (!tev.GXGetTevKColor(GX_KCOLOR3, &c)) {
c = ut::Color::BLACK;
}
tev.GXSetTevKColor(GX_KCOLOR3,
c & pResult->rgbaMask[ClrAnmResult::CLA_TEVK3] |
pResult->rgba[ClrAnmResult::CLA_TEVK3]);
}
tev.DCStore(false);
}
}
} // namespace g3d
} // namespace nw4r
+43
View File
@@ -0,0 +1,43 @@
#include <nw4r/g3d.h>
#include <nw4r/math.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObj);
f32 FrameCtrl::smBaseUpdateRate = 1.0f;
f32 PlayPolicy_Onetime(f32 start, f32 end, f32 frame) {
#pragma unused(start)
#pragma unused(end)
return frame;
}
f32 PlayPolicy_Loop(f32 start, f32 end, f32 frame) {
f32 length = end - start;
if (frame >= 0.0f) {
return math::FMod(frame, length);
}
f32 offset = math::FMod(frame + length, length);
return offset + math::FSelect(offset, 0.0f, length);
}
void AnmObj::SetAnmFlag(AnmFlag flag, bool value) {
if (value) {
mFlags |= flag;
} else {
mFlags &= ~flag;
}
}
bool AnmObj::TestAnmFlag(AnmFlag flag) const {
return mFlags & flag;
}
} // namespace g3d
} // namespace nw4r
+69
View File
@@ -0,0 +1,69 @@
#include <nw4r/g3d.h>
#include <algorithm>
namespace nw4r {
namespace g3d {
void AnmScn::GetLightSetting(LightSetting* pSetting) {
const u32 numLightSet = GetLightSetMaxRefNumber();
const u32 numAmbLight = GetAmbLightMaxRefNumber();
const u32 numDiffLight = GetDiffuseLightMaxRefNumber();
if (numLightSet > 0) {
const u32 numLightSetObj = pSetting->GetNumLightSet();
const u32 numLoadableSet = std::min(numLightSet, numLightSetObj);
for (u32 i = 0; i < numLoadableSet; i++) {
LightSet set = pSetting->GetLightSet(i);
GetLightSet(set, i);
}
}
if (numAmbLight > 0) {
AmbLightObj* pAmbObjArray = pSetting->GetAmbLightObjArray();
const u32 numAmbObj = pSetting->GetNumLightObj();
const u32 numLoadableAmb = std::min(numAmbLight, numAmbObj);
for (u32 i = 0; i < numLoadableAmb; i++) {
AmbLightObj* pAmbObj = &pAmbObjArray[i];
*reinterpret_cast<u32*>(&pAmbObj->r) = GetAmbLightColor(i);
}
}
if (numDiffLight > 0) {
LightObj* pLightObjArray = pSetting->GetLightObjArray();
const u32 numLightObj = pSetting->GetNumLightObj();
const u32 numSpecLight = GetNumSpecularLight();
const u32 numLight = numDiffLight + numSpecLight;
const u32 numLoadableDiffLight = std::min(numDiffLight, numLightObj);
const u32 numLoadableLight = std::min(numLight, numLightObj);
for (u32 i = 0; i < numLoadableDiffLight; i++) {
LightObj* pObj = &pLightObjArray[i];
pObj->Disable();
}
for (u32 i = 0; i < numLoadableDiffLight; i++) {
LightObj* pDiffObj = &pLightObjArray[i];
LightObj* pSpecObj = NULL;
if (pDiffObj->IsEnable()) {
continue;
}
if (HasSpecularLight(i)) {
const u32 specId = GetSpecularLightID(i);
if (specId < numLoadableLight) {
pSpecObj = &pLightObjArray[specId];
}
}
GetLight(pDiffObj, pSpecObj, i);
}
}
}
} // namespace g3d
} // namespace nw4r
+591
View File
@@ -0,0 +1,591 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObjShp);
NW4R_G3D_RTTI_DEF(AnmObjShpNode);
NW4R_G3D_RTTI_DEF(AnmObjShpBlend);
NW4R_G3D_RTTI_DEF(AnmObjShpRes);
/******************************************************************************
*
* AnmObjShp
*
******************************************************************************/
AnmObjShp::AnmObjShp(MEMAllocator* pAllocator, u16* pBindingBuf, int numBinding)
: AnmObj(pAllocator, NULL),
mNumBinding(numBinding),
mpBinding(pBindingBuf) {
Release();
}
bool AnmObjShp::TestExistence(u32 idx) const {
return !(mpBinding[idx] & (BINDING_UNDEFINED | BINDING_INVALID));
}
bool AnmObjShp::TestDefined(u32 idx) const {
return !(mpBinding[idx] & BINDING_UNDEFINED);
}
void AnmObjShp::Release() {
for (int i = 0; i < mNumBinding; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
SetAnmFlag(FLAG_ANM_BOUND, false);
}
AnmObjShpRes* AnmObjShp::Attach(int idx, AnmObjShpRes* pRes) {
#pragma unused(idx)
#pragma unused(pRes)
return NULL;
}
AnmObjShpRes* AnmObjShp::Detach(int idx) {
#pragma unused(idx)
return NULL;
}
void AnmObjShp::SetWeight(int idx, f32 weight) {
#pragma unused(idx)
#pragma unused(weight)
}
f32 AnmObjShp::GetWeight(int idx) const {
#pragma unused(idx)
return 0.0f;
}
void AnmObjShp::DetachAll() {}
/******************************************************************************
*
* AnmObjShpNode
*
******************************************************************************/
AnmObjShpNode::AnmObjShpNode(MEMAllocator* pAllocator, u16* pBindingBuf,
int numBinding, AnmObjShpRes** ppChildrenBuf,
int numChildren)
: AnmObjShp(pAllocator, pBindingBuf, numBinding),
mChildrenArraySize(numChildren),
mpChildrenArray(ppChildrenBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpChildrenArray[i] = NULL;
}
}
AnmObjShpNode::~AnmObjShpNode() {
DetachAll();
}
AnmObjShpRes* AnmObjShpNode::Attach(int idx, AnmObjShpRes* pRes) {
AnmObjShpRes* pOld = Detach(idx);
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
if (!pRes->TestDefined(i)) {
continue;
}
hasAnm = true;
mpBinding[i] = 0;
}
if (hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, true);
}
mpChildrenArray[idx] = pRes;
pRes->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return pOld;
}
AnmObjShpRes* AnmObjShpNode::Detach(int idx) {
AnmObjShpRes* pOld = mpChildrenArray[idx];
if (pOld != NULL) {
pOld->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpChildrenArray[idx] = NULL;
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
u16 binding = BINDING_UNDEFINED;
for (int j = 0; j < mChildrenArraySize; j++) {
AnmObjShpRes* pChild = mpChildrenArray[j];
if (pChild == NULL || !pChild->TestDefined(i)) {
continue;
}
hasAnm = true;
binding = 0;
break;
}
mpBinding[i] = binding;
}
if (!hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, false);
}
}
return pOld;
}
void AnmObjShpNode::DetachAll() {
for (int i = 0; i < mChildrenArraySize; i++) {
Detach(i);
}
}
void AnmObjShpNode::UpdateFrame() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->UpdateFrame();
}
}
}
void AnmObjShpNode::SetFrame(f32 frame) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetFrame(frame);
}
}
}
f32 AnmObjShpNode::GetFrame() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetFrame();
}
}
return 0.0f;
}
void AnmObjShpNode::SetUpdateRate(f32 rate) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetUpdateRate(rate);
}
}
}
f32 AnmObjShpNode::GetUpdateRate() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetUpdateRate();
}
}
return 1.0f;
}
bool AnmObjShpNode::Bind(const ResMdl mdl) {
bool success = false;
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjShpRes* pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjShpNode::Release() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->Release();
}
}
AnmObjShp::Release();
}
void AnmObjShpNode::G3dProc(u32 task, u32 param, void* pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_CHILD_DETACHED: {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] == pInfo) {
Detach(i);
return;
}
}
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjShpBlend
*
******************************************************************************/
AnmObjShpBlend* AnmObjShpBlend::Construct(MEMAllocator* pAllocator, u32* pSize,
ResMdl mdl, int numChildren) {
if (!mdl.IsValid()) {
return NULL;
}
int bindNum = mdl.GetResVtxPosNumEntries();
u32 bindSize = bindNum * sizeof(u16);
u32 childrenSize = numChildren * sizeof(AnmObjShpRes*);
u32 weightSize = numChildren * sizeof(f32);
u32 bindOfs = ut::RoundUp(sizeof(AnmObjShpBlend), 4);
u32 childrenOfs = ut::RoundUp(bindOfs + bindSize, 4);
u32 weightOfs = ut::RoundUp(childrenOfs + childrenSize, 4);
u32 size = ut::RoundUp(weightOfs + weightSize, 4);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
return new (pBuffer) AnmObjShpBlend(
pAllocator,
reinterpret_cast<u16*>(pBuffer + bindOfs),
bindNum,
reinterpret_cast<AnmObjShpRes**>(pBuffer + childrenOfs),
numChildren,
reinterpret_cast<f32*>(pBuffer + weightOfs));
// clang-format on
}
AnmObjShpBlend::AnmObjShpBlend(MEMAllocator* pAllocator, u16* pBindingBuf,
int numBinding, AnmObjShpRes** ppChildrenBuf,
int numChildren, f32* pWeightBuf)
: AnmObjShpNode(pAllocator, pBindingBuf, numBinding, ppChildrenBuf,
numChildren),
mpWeightArray(pWeightBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpWeightArray[i] = 1.0f;
}
}
const ShpAnmResult* AnmObjShpBlend::GetResult(ShpAnmResult* pResult, u32 idx) {
detail::workmem::ShpAnmResultBuf* pWorkBuffer =
detail::workmem::GetShpAnmResultBufTemporary();
int blendNum = 0;
f32 weightSum = 0.0f;
for (int i = 0; i < mChildrenArraySize; i++) {
f32 weight = mpWeightArray[i];
AnmObjShpRes* pChild = mpChildrenArray[i];
// @note Bitwise AND
if (!(pChild != NULL & weight != 0.0f)) {
continue;
}
if (!pChild->TestExistence(idx)) {
continue;
}
detail::workmem::ShpAnmResultBuf& rAnmBuf = pWorkBuffer[blendNum];
const ShpAnmResult* pMyResult =
pChild->GetResult(&rAnmBuf.resultBuf, idx);
if (!(pMyResult->flags & 1)) {
continue;
}
rAnmBuf.pResult = pMyResult;
rAnmBuf.weight = weight;
blendNum++;
weightSum += weight;
}
if (blendNum == 0) {
pResult->flags = 0;
return pResult;
}
if (blendNum == 1) {
detail::workmem::ShpAnmResultBuf& rAnmBuf = *pWorkBuffer;
if (rAnmBuf.pResult == &rAnmBuf.resultBuf) {
*pResult = *rAnmBuf.pResult;
return pResult;
} else {
return rAnmBuf.pResult;
}
}
f32 invWeightSum = math::FInv(weightSum);
pResult->flags = pWorkBuffer->pResult->flags;
pResult->numKeyShape = 0;
pResult->baseShapeVtxSet = pWorkBuffer->pResult->baseShapeVtxSet;
pResult->baseShapeWeight = 0.0f;
for (int i = 0; i < blendNum; i++) {
const ShpAnmResult* pMyResult = pWorkBuffer[i].pResult;
f32 weight = pWorkBuffer[i].weight;
f32 ratio = weight * invWeightSum;
pResult->baseShapeWeight += pMyResult->baseShapeWeight * ratio;
for (u32 myKey = 0; myKey < pMyResult->numKeyShape; myKey++) {
const BlendVtx& rMyKeyShape = pMyResult->keyShape[myKey];
u32 otherKey;
for (otherKey = 0; otherKey < pResult->numKeyShape; otherKey++) {
if (rMyKeyShape.vtxSet == pResult->keyShape[otherKey].vtxSet) {
break;
}
}
if (otherKey == pResult->numKeyShape) {
pResult->keyShape[otherKey].vtxSet = rMyKeyShape.vtxSet;
pResult->keyShape[otherKey].weight = 0.0f;
pResult->numKeyShape++;
}
pResult->keyShape[otherKey].weight += rMyKeyShape.weight * ratio;
}
}
return pResult;
}
void AnmObjShpBlend::SetWeight(int idx, f32 weight) {
mpWeightArray[idx] = weight;
}
f32 AnmObjShpBlend::GetWeight(int idx) const {
return mpWeightArray[idx];
}
/******************************************************************************
*
* AnmObjShpRes
*
******************************************************************************/
AnmObjShpRes* AnmObjShpRes::Construct(MEMAllocator* pAllocator, u32* pSize,
ResAnmShp shp, ResMdl mdl, bool cache) {
if (!shp.IsValid() || !mdl.IsValid()) {
return NULL;
}
int animNum = shp.GetShapeAnmNumEntries();
int vtxNum = mdl.GetResVtxPosNumEntries();
int bindNum = vtxNum;
int vtxSetNum = shp.GetNumVtxNames();
int cacheNum = cache ? animNum : 0;
u32 bindSize = bindNum * sizeof(u16);
u32 vtxSetSize = vtxSetNum * sizeof(ShpAnmVtxSet);
u32 cacheSize = cacheNum * sizeof(ShpAnmResult);
u32 bindOfs = ut::RoundUp(sizeof(AnmObjShpRes), 2);
u32 vtxSetOfs = ut::RoundUp(bindOfs + bindSize, 4);
u32 cacheOfs = ut::RoundUp(vtxSetOfs + vtxSetSize, 4);
u32 size = ut::RoundUp(cacheOfs + cacheSize, 4);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
u16* const pBindingBuf = reinterpret_cast<u16*>(pBuffer + bindOfs);
ShpAnmVtxSet* const pVtxSetBuf =
reinterpret_cast<ShpAnmVtxSet*>(pBuffer + vtxSetOfs);
ShpAnmResult* const pCacheBuf =
reinterpret_cast<ShpAnmResult*>(pBuffer + cacheOfs);
return new (pBuffer)
AnmObjShpRes(pAllocator, shp, pBindingBuf, pVtxSetBuf, bindNum,
cacheSize != 0 ? pCacheBuf : NULL);
}
AnmObjShpRes::AnmObjShpRes(MEMAllocator* pAllocator, ResAnmShp shp,
u16* pBindingBuf, ShpAnmVtxSet* pVtxSetBuf,
int numBinding, ShpAnmResult* pCacheBuf)
: AnmObjShp(pAllocator, pBindingBuf, numBinding),
FrameCtrl(0.0f, shp.GetNumFrame(), GetAnmPlayPolicy(shp.GetAnmPolicy())),
mRes(shp),
mpVtxSetArray(pVtxSetBuf),
mpResultCache(pCacheBuf) {
if (mpResultCache != NULL) {
UpdateCache();
}
}
void AnmObjShpRes::SetFrame(f32 frame) {
SetFrm(frame);
if (mpResultCache != NULL) {
UpdateCache();
}
}
f32 AnmObjShpRes::GetFrame() const {
return GetFrm();
}
void AnmObjShpRes::SetUpdateRate(f32 rate) {
SetRate(rate);
}
f32 AnmObjShpRes::GetUpdateRate() const {
return GetRate();
}
void AnmObjShpRes::UpdateFrame() {
UpdateFrm();
if (mpResultCache != NULL) {
UpdateCache();
}
}
bool AnmObjShpRes::Bind(const ResMdl mdl) {
bool success = false;
u32 numAnim = mRes.GetShapeAnmNumEntries();
for (u16 i = 0; i < numAnim; i++) {
const ResAnmShpAnmData* pData = mRes.GetShapeAnm(i);
// Seek back from name string to start of ResName
ResName name(ut::AddOffsetToPtr(pData, pData->name - 4));
ResVtxPos pos = mdl.GetResVtxPos(name);
if (!pos.IsValid()) {
continue;
}
mpBinding[pos.GetID()] = i;
success = true;
}
int nameNum = mRes.GetNumVtxNames();
const s32* pVtxNameArray = mRes.GetVtxNameArray();
for (int i = 0; i < nameNum; i++) {
ShpAnmVtxSet& rSet = mpVtxSetArray[i];
s32 offset = pVtxNameArray[i];
// Seek back from name string to start of ResName
ResName name = NW4R_G3D_OFS_TO_RESNAME(pVtxNameArray, offset);
rSet.resVtxPos = mdl.GetResVtxPos(name);
rSet.resVtxNrm = mdl.GetResVtxNrm(name);
rSet.resVtxClr = mdl.GetResVtxClr(name);
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
const ShpAnmResult* AnmObjShpRes::GetResult(ShpAnmResult* pResult, u32 idx) {
u32 id = mpBinding[idx];
if (id & (BINDING_UNDEFINED | BINDING_INVALID)) {
pResult->flags = 0;
return pResult;
}
if (mpResultCache != NULL) {
return &mpResultCache[id];
}
mRes.GetAnmResult(pResult, id, GetFrm(), mpVtxSetArray);
return pResult;
}
void AnmObjShpRes::UpdateCache() {
f32 frame = GetFrm();
for (u32 i = 0; i < mNumBinding; i++) {
u16 bind = mpBinding[i];
if (!(bind & BINDING_UNDEFINED)) {
u32 id = bind & BINDING_ID_MASK;
mRes.GetAnmResult(&mpResultCache[id], id, frame, mpVtxSetArray);
}
}
}
void AnmObjShpRes::G3dProc(u32 task, u32 param, void* pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_UPDATEFRAME: {
UpdateFrame();
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
}
}
} // namespace g3d
} // namespace nw4r
+529
View File
@@ -0,0 +1,529 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
#include <rvl/GX.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObjTexPat);
NW4R_G3D_RTTI_DEF(AnmObjTexPatNode);
NW4R_G3D_RTTI_DEF(AnmObjTexPatOverride);
NW4R_G3D_RTTI_DEF(AnmObjTexPatRes);
/******************************************************************************
*
* AnmObjTexPat
*
******************************************************************************/
AnmObjTexPat::AnmObjTexPat(MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding)
: AnmObj(pAllocator, NULL), mNumBinding(numBinding), mpBinding(pBindingBuf) {
Release();
}
bool AnmObjTexPat::TestExistence(u32 idx) const {
return !(mpBinding[idx] & (BINDING_UNDEFINED | BINDING_INVALID));
}
bool AnmObjTexPat::TestDefined(u32 idx) const {
return !(mpBinding[idx] & BINDING_UNDEFINED);
}
void AnmObjTexPat::Release() {
for (int i = 0; i < mNumBinding; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
SetAnmFlag(FLAG_ANM_BOUND, false);
}
AnmObjTexPatRes *AnmObjTexPat::Attach(int idx, AnmObjTexPatRes *pRes) {
#pragma unused(idx)
#pragma unused(pRes)
return NULL;
}
AnmObjTexPatRes *AnmObjTexPat::Detach(int idx) {
#pragma unused(idx)
return NULL;
}
void AnmObjTexPat::DetachAll() {}
/******************************************************************************
*
* AnmObjTexPatNode
*
******************************************************************************/
AnmObjTexPatNode::AnmObjTexPatNode(
MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding, AnmObjTexPatRes **ppChildrenBuf, int numChildren
)
: AnmObjTexPat(pAllocator, pBindingBuf, numBinding),
mChildrenArraySize(numChildren),
mpChildrenArray(ppChildrenBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpChildrenArray[i] = NULL;
}
}
AnmObjTexPatNode::~AnmObjTexPatNode() {
DetachAll();
}
AnmObjTexPatRes *AnmObjTexPatNode::Attach(int idx, AnmObjTexPatRes *pRes) {
AnmObjTexPatRes *pOld = Detach(idx);
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
if (!pRes->TestDefined(i)) {
continue;
}
hasAnm = true;
mpBinding[i] = 0;
}
if (hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, true);
}
mpChildrenArray[idx] = pRes;
pRes->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return pOld;
}
AnmObjTexPatRes *AnmObjTexPatNode::Detach(int idx) {
AnmObjTexPatRes *pOld = mpChildrenArray[idx];
if (pOld != NULL) {
pOld->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpChildrenArray[idx] = NULL;
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
u16 binding = BINDING_UNDEFINED;
for (int j = 0; j < mChildrenArraySize; j++) {
AnmObjTexPatRes *pChild = mpChildrenArray[j];
if (pChild == NULL || !pChild->TestDefined(i)) {
continue;
}
hasAnm = true;
binding = 0;
break;
}
mpBinding[i] = binding;
}
if (!hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, false);
}
}
return pOld;
}
void AnmObjTexPatNode::DetachAll() {
for (int i = 0; i < mChildrenArraySize; i++) {
Detach(i);
}
}
void AnmObjTexPatNode::UpdateFrame() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->UpdateFrame();
}
}
}
void AnmObjTexPatNode::SetFrame(f32 frame) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetFrame(frame);
}
}
}
f32 AnmObjTexPatNode::GetFrame() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetFrame();
}
}
return 0.0f;
}
void AnmObjTexPatNode::SetUpdateRate(f32 rate) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetUpdateRate(rate);
}
}
}
f32 AnmObjTexPatNode::GetUpdateRate() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetUpdateRate();
}
}
return 1.0f;
}
bool AnmObjTexPatNode::Bind(const ResMdl mdl) {
bool success = false;
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjTexPatRes *pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjTexPatNode::Release() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->Release();
}
}
AnmObjTexPat::Release();
}
void AnmObjTexPatNode::G3dProc(u32 task, u32 param, void *pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_CHILD_DETACHED: {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] == pInfo) {
Detach(i);
return;
}
}
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj *>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjTexPatOverride
*
******************************************************************************/
AnmObjTexPatOverride *
AnmObjTexPatOverride::Construct(MEMAllocator *pAllocator, u32 *pSize, ResMdl mdl, int numChildren) {
if (!mdl.IsValid()) {
return NULL;
}
int numAnim = mdl.GetResMatNumEntries();
int bindNum = numAnim;
u32 objSize = sizeof(AnmObjTexPatOverride);
u32 bindSize = bindNum * sizeof(u16);
u32 childrenSize = numChildren * sizeof(AnmObjTexPatRes *);
u32 bindOfs = align4(objSize);
u32 childrenOfs = align4(bindOfs + bindSize);
u32 size = align4(childrenOfs + childrenSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
return new (pBuffer) AnmObjTexPatOverride(
pAllocator,
reinterpret_cast<u16*>(pBuffer + bindOfs),
bindNum,
reinterpret_cast<AnmObjTexPatRes**>(pBuffer + childrenOfs),
numChildren);
// clang-format on
}
const TexPatAnmResult *AnmObjTexPatOverride::GetResult(TexPatAnmResult *pResult, u32 idx) {
for (int i = mChildrenArraySize - 1; i >= 0; i--) {
AnmObjTexPatRes *pChild = mpChildrenArray[i];
if (pChild == NULL || !pChild->TestExistence(idx)) {
continue;
}
const TexPatAnmResult *pChildResult = pChild->GetResult(pResult, idx);
if (pChildResult->bTexExist != 0 || pChildResult->bPlttExist) {
return pChildResult;
}
}
pResult->bTexExist = 0;
pResult->bPlttExist = 0;
return pResult;
}
/******************************************************************************
*
* AnmObjTexPatRes
*
******************************************************************************/
AnmObjTexPatRes *
AnmObjTexPatRes::Construct(MEMAllocator *pAllocator, u32 *pSize, ResAnmTexPat pat, ResMdl mdl, bool cache) {
if (!pat.IsValid() || !mdl.IsValid()) {
return NULL;
}
int numAnim = pat.GetNumMaterial();
int numMat = mdl.GetResMatNumEntries();
int bindNum = numMat;
int cacheNum = cache ? numAnim : 0;
u32 bindSize = bindNum * sizeof(u16);
u32 cacheSize = cacheNum * sizeof(TexPatAnmResult);
u32 size = bindSize + cacheSize + sizeof(AnmObjTexPatRes);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
TexPatAnmResult *pCacheBuf = cache ? reinterpret_cast<TexPatAnmResult *>(pBuffer + sizeof(AnmObjTexPatRes)) : NULL;
u16 *pBindingBuf = reinterpret_cast<u16 *>(cacheSize + (pBuffer + sizeof(AnmObjTexPatRes)));
return new (pBuffer) AnmObjTexPatRes(pAllocator, pat, pBindingBuf, bindNum, pCacheBuf);
}
AnmObjTexPatRes::AnmObjTexPatRes(
MEMAllocator *pAllocator, ResAnmTexPat pat, u16 *pBindingBuf, int numBinding, TexPatAnmResult *pCacheBuf
)
: AnmObjTexPat(pAllocator, pBindingBuf, numBinding),
FrameCtrl(0.0f, pat.GetNumFrame(), GetAnmPlayPolicy(pat.GetAnmPolicy())),
mRes(pat),
mpResultCache(pCacheBuf) {
if (mpResultCache != NULL) {
UpdateCache();
}
}
void AnmObjTexPatRes::SetFrame(f32 frame) {
SetFrm(frame);
if (mpResultCache != NULL) {
UpdateCache();
}
}
f32 AnmObjTexPatRes::GetFrame() const {
return GetFrm();
}
void AnmObjTexPatRes::SetUpdateRate(f32 rate) {
SetRate(rate);
}
f32 AnmObjTexPatRes::GetUpdateRate() const {
return GetRate();
}
void AnmObjTexPatRes::UpdateFrame() {
UpdateFrm();
if (mpResultCache != NULL) {
UpdateCache();
}
}
bool AnmObjTexPatRes::Bind(const ResMdl mdl) {
int numAnim = mRes.GetNumMaterial();
bool success = false;
for (u16 i = 0; i < numAnim; i++) {
const ResAnmTexPatMatData *pData = mRes.GetMatAnm(i);
// Seek back from name string to start of ResName
ResName name(ut::AddOffsetToPtr(pData, pData->name - 4));
ResMat mat = mdl.GetResMat(name);
if (!mat.IsValid()) {
continue;
}
mpBinding[mat.GetID()] = i;
success = true;
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
const TexPatAnmResult *AnmObjTexPatRes::GetResult(TexPatAnmResult *pResult, u32 i) {
u32 id = mpBinding[i];
if (id & (BINDING_UNDEFINED | BINDING_INVALID)) {
pResult->bTexExist = 0;
pResult->bPlttExist = 0;
return pResult;
}
if (mpResultCache != NULL) {
return &mpResultCache[id];
}
mRes.GetAnmResult(pResult, id, GetFrm());
return pResult;
}
void AnmObjTexPatRes::UpdateCache() {
f32 frame = GetFrm();
for (u32 i = 0; i < mNumBinding; i++) {
u16 bind = mpBinding[i];
if (!(bind & BINDING_UNDEFINED)) {
u32 id = bind & BINDING_ID_MASK;
mRes.GetAnmResult(&mpResultCache[id], id, frame);
}
}
}
void AnmObjTexPatRes::G3dProc(u32 task, u32 param, void *pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_UPDATEFRAME: {
UpdateFrame();
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj *>(pInfo));
break;
}
}
}
/******************************************************************************
*
* ApplyTexPatAnmResult
*
******************************************************************************/
void ApplyTexPatAnmResult(ResTexObj texObj, ResTlutObj tlutObj, const TexPatAnmResult *pResult) {
u32 texExist = pResult->bTexExist;
u32 i;
for (i = 0; texExist != 0; texExist >>= 1, i++) {
if (!(texExist & 1)) {
continue;
}
ResTex tex = pResult->tex[i];
GXTexObj *pGXObj = texObj.GetTexObj(static_cast<GXTexMapID>(i));
GXTexFilter minFilt, magFilt;
f32 minLod, maxLod, lodBias;
GXBool biasClamp, edgeLod, mipmap;
GXAnisotropy maxAniso;
void *pTexData;
u16 width, height;
GXTexFmt fmt;
GXCITexFmt cifmt;
GXGetTexObjLODAll(pGXObj, &minFilt, &magFilt, &minLod, &maxLod, &lodBias, &biasClamp, &edgeLod, &maxAniso);
GXTexWrapMode wrapS = GXGetTexObjWrapS(pGXObj);
GXTexWrapMode wrapT = GXGetTexObjWrapT(pGXObj);
if (tex.IsCIFmt()) {
tex.GetTexObjCIParam(&pTexData, &width, &height, &cifmt, &minLod, &maxLod, &mipmap);
GXInitTexObjCI(
pGXObj, pTexData, width, height, static_cast<GXTexFmt>(cifmt), wrapS, wrapT, mipmap,
static_cast<GXTlut>(i)
);
} else {
tex.GetTexObjParam(&pTexData, &width, &height, &fmt, &minLod, &maxLod, &mipmap);
GXInitTexObj(pGXObj, pTexData, width, height, fmt, wrapS, wrapT, mipmap);
}
GXInitTexObjLOD(pGXObj, minFilt, magFilt, minLod, maxLod, lodBias, biasClamp, edgeLod, maxAniso);
}
u32 plttExist = pResult->bPlttExist;
for (i = 0; plttExist != 0; plttExist >>= 1, i++) {
if (!(plttExist & 1)) {
continue;
}
ResPltt pltt = pResult->pltt[i];
void *pLUT = pltt.GetPlttData();
GXTlutFmt fmt = pltt.GetFmt();
u16 numEntries = pltt.GetNumEntries();
GXTlutObj *pGXObj = tlutObj.GetTlut(static_cast<GXTlut>(i));
GXInitTlutObj(pGXObj, pLUT, fmt, numEntries);
}
}
} // namespace g3d
} // namespace nw4r
+528
View File
@@ -0,0 +1,528 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
#include <rvl/GX.h>
#include <cmath>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObjTexSrt);
NW4R_G3D_RTTI_DEF(AnmObjTexSrtNode);
NW4R_G3D_RTTI_DEF(AnmObjTexSrtOverride);
NW4R_G3D_RTTI_DEF(AnmObjTexSrtRes);
/******************************************************************************
*
* AnmObjTexSrt
*
******************************************************************************/
AnmObjTexSrt::AnmObjTexSrt(MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding)
: AnmObj(pAllocator, NULL), mNumBinding(numBinding), mpBinding(pBindingBuf) {
Release();
}
bool AnmObjTexSrt::TestExistence(u32 idx) const {
return !(mpBinding[idx] & (BINDING_UNDEFINED | BINDING_INVALID));
}
bool AnmObjTexSrt::TestDefined(u32 idx) const {
return !(mpBinding[idx] & BINDING_UNDEFINED);
}
void AnmObjTexSrt::Release() {
for (int i = 0; i < mNumBinding; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
SetAnmFlag(FLAG_ANM_BOUND, false);
}
AnmObjTexSrtRes *AnmObjTexSrt::Attach(int idx, AnmObjTexSrtRes *pRes) {
#pragma unused(idx)
#pragma unused(pRes)
return NULL;
}
AnmObjTexSrtRes *AnmObjTexSrt::Detach(int idx) {
#pragma unused(idx)
return NULL;
}
void AnmObjTexSrt::DetachAll() {}
/******************************************************************************
*
* AnmObjTexSrtNode
*
******************************************************************************/
AnmObjTexSrtNode::AnmObjTexSrtNode(
MEMAllocator *pAllocator, u16 *pBindingBuf, int numBinding, AnmObjTexSrtRes **ppChildrenBuf, int numChildren
)
: AnmObjTexSrt(pAllocator, pBindingBuf, numBinding),
mChildrenArraySize(numChildren),
mpChildrenArray(ppChildrenBuf) {
for (int i = 0; i < mChildrenArraySize; i++) {
mpChildrenArray[i] = NULL;
}
}
AnmObjTexSrtNode::~AnmObjTexSrtNode() {
DetachAll();
}
AnmObjTexSrtRes *AnmObjTexSrtNode::Attach(int idx, AnmObjTexSrtRes *pRes) {
AnmObjTexSrtRes *pOld = Detach(idx);
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
if (!pRes->TestDefined(i)) {
continue;
}
hasAnm = true;
mpBinding[i] = 0;
}
if (hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, true);
}
mpChildrenArray[idx] = pRes;
pRes->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return pOld;
}
AnmObjTexSrtRes *AnmObjTexSrtNode::Detach(int idx) {
AnmObjTexSrtRes *pOld = mpChildrenArray[idx];
if (pOld != NULL) {
pOld->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpChildrenArray[idx] = NULL;
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
u16 binding = BINDING_UNDEFINED;
for (int j = 0; j < mChildrenArraySize; j++) {
AnmObjTexSrtRes *pChild = mpChildrenArray[j];
if (pChild == NULL || !pChild->TestDefined(i)) {
continue;
}
hasAnm = true;
binding = 0;
break;
}
mpBinding[i] = binding;
}
if (!hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, false);
}
}
return pOld;
}
void AnmObjTexSrtNode::DetachAll() {
for (int i = 0; i < mChildrenArraySize; i++) {
Detach(i);
}
}
void AnmObjTexSrtNode::UpdateFrame() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->UpdateFrame();
}
}
}
void AnmObjTexSrtNode::SetFrame(f32 frame) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetFrame(frame);
}
}
}
f32 AnmObjTexSrtNode::GetFrame() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetFrame();
}
}
return 0.0f;
}
void AnmObjTexSrtNode::SetUpdateRate(f32 rate) {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->SetUpdateRate(rate);
}
}
}
f32 AnmObjTexSrtNode::GetUpdateRate() const {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
return mpChildrenArray[i]->GetUpdateRate();
}
}
return 1.0f;
}
bool AnmObjTexSrtNode::Bind(const ResMdl mdl) {
bool success = false;
for (int i = 0; i < mChildrenArraySize; i++) {
AnmObjTexSrtRes *pChild = mpChildrenArray[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjTexSrtNode::Release() {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] != NULL) {
mpChildrenArray[i]->Release();
}
}
AnmObjTexSrt::Release();
}
void AnmObjTexSrtNode::G3dProc(u32 task, u32 param, void *pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_CHILD_DETACHED: {
for (int i = 0; i < mChildrenArraySize; i++) {
if (mpChildrenArray[i] == pInfo) {
Detach(i);
return;
}
}
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj *>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjTexSrtOverride
*
******************************************************************************/
AnmObjTexSrtOverride *
AnmObjTexSrtOverride::Construct(MEMAllocator *pAllocator, u32 *pSize, ResMdl mdl, int numChildren) {
if (!mdl.IsValid()) {
return NULL;
}
int numAnim = mdl.GetResMatNumEntries();
int bindNum = numAnim;
u32 objSize = sizeof(AnmObjTexSrtOverride);
u32 bindSize = bindNum * sizeof(u16);
u32 childrenSize = numChildren * sizeof(AnmObjTexSrtRes *);
u32 bindOfs = align4(objSize);
u32 childrenOfs = align4(bindOfs + bindSize);
u32 size = align4(childrenOfs + childrenSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
return new (pBuffer) AnmObjTexSrtOverride(
pAllocator,
reinterpret_cast<u16*>(pBuffer + bindOfs),
bindNum,
reinterpret_cast<AnmObjTexSrtRes**>(pBuffer + childrenOfs),
numChildren);
// clang-format on
}
const TexSrtAnmResult *AnmObjTexSrtOverride::GetResult(TexSrtAnmResult *pResult, u32 idx) {
for (int i = mChildrenArraySize - 1; i >= 0; i--) {
AnmObjTexSrtRes *pChild = mpChildrenArray[i];
if (pChild == NULL || !pChild->TestExistence(idx)) {
continue;
}
const TexSrtAnmResult *pChildResult = pChild->GetResult(pResult, idx);
if (pChildResult->flags != 0) {
return pChildResult;
}
}
pResult->flags = 0;
return pResult;
}
/******************************************************************************
*
* AnmObjTexSrtRes
*
******************************************************************************/
AnmObjTexSrtRes *
AnmObjTexSrtRes::Construct(MEMAllocator *pAllocator, u32 *pSize, ResAnmTexSrt srt, ResMdl mdl, bool cache) {
if (!srt.IsValid() || !mdl.IsValid()) {
return NULL;
}
int numAnim = srt.GetNumMaterial();
int numMat = mdl.GetResMatNumEntries();
int bindNum = numMat;
int cacheNum = cache ? numAnim : 0;
u32 bindSize = bindNum * sizeof(u16);
u32 cacheSize = cacheNum * sizeof(TexSrtAnmResult);
u32 size = bindSize + cacheSize + sizeof(AnmObjTexSrtRes);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
TexSrtAnmResult *pCacheBuf = cache ? reinterpret_cast<TexSrtAnmResult *>(pBuffer + sizeof(AnmObjTexSrtRes)) : NULL;
u16 *pBindingBuf = reinterpret_cast<u16 *>(cacheSize + (pBuffer + sizeof(AnmObjTexSrtRes)));
return new (pBuffer) AnmObjTexSrtRes(pAllocator, srt, pBindingBuf, bindNum, pCacheBuf);
}
AnmObjTexSrtRes::AnmObjTexSrtRes(
MEMAllocator *pAllocator, ResAnmTexSrt srt, u16 *pBindingBuf, int numBinding, TexSrtAnmResult *pCacheBuf
)
: AnmObjTexSrt(pAllocator, pBindingBuf, numBinding),
FrameCtrl(0.0f, srt.GetNumFrame(), GetAnmPlayPolicy(srt.GetAnmPolicy())),
mRes(srt),
mpResultCache(pCacheBuf) {
if (mpResultCache != NULL) {
UpdateCache();
}
}
void AnmObjTexSrtRes::SetFrame(f32 frame) {
SetFrm(frame);
if (mpResultCache != NULL) {
UpdateCache();
}
}
f32 AnmObjTexSrtRes::GetFrame() const {
return GetFrm();
}
void AnmObjTexSrtRes::SetUpdateRate(f32 rate) {
SetRate(rate);
}
f32 AnmObjTexSrtRes::GetUpdateRate() const {
return GetRate();
}
void AnmObjTexSrtRes::UpdateFrame() {
UpdateFrm();
if (mpResultCache != NULL) {
UpdateCache();
}
}
bool AnmObjTexSrtRes::Bind(const ResMdl mdl) {
int numAnim = mRes.GetNumMaterial();
bool success = false;
for (u16 i = 0; i < numAnim; i++) {
const ResAnmTexSrtMatData *pData = mRes.GetMatAnm(i);
// Seek back from name string to start of ResName
ResName name(ut::AddOffsetToPtr(pData, pData->name - 4));
ResMat mat = mdl.GetResMat(name);
if (!mat.IsValid()) {
continue;
}
mpBinding[mat.GetID()] = i;
success = true;
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
const TexSrtAnmResult *AnmObjTexSrtRes::GetResult(TexSrtAnmResult *pResult, u32 idx) {
u32 id = mpBinding[idx];
if (id & (BINDING_UNDEFINED | BINDING_INVALID)) {
pResult->flags = 0;
return pResult;
}
if (mpResultCache != NULL) {
return &mpResultCache[id];
}
mRes.GetAnmResult(pResult, id, GetFrm());
return pResult;
}
void AnmObjTexSrtRes::UpdateCache() {
f32 frame = GetFrm();
for (u32 i = 0; i < mNumBinding; i++) {
u16 bind = mpBinding[i];
if (!(bind & BINDING_UNDEFINED)) {
u32 id = bind & BINDING_ID_MASK;
mRes.GetAnmResult(&mpResultCache[id], id, frame);
}
}
}
void AnmObjTexSrtRes::G3dProc(u32 task, u32 param, void *pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_UPDATEFRAME: {
UpdateFrame();
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj *>(pInfo));
break;
}
}
}
/******************************************************************************
*
* ApplyTexSrtAnmResult
*
******************************************************************************/
void ApplyTexSrtAnmResult(ResTexSrt srt, const TexSrtAnmResult *pResult) {
ResTexSrtData &r = srt.ref();
u32 flags = pResult->flags;
u32 mask = 0x0F;
for (int i = 0; flags != 0; flags >>= TexSrt::NUM_OF_FLAGS, mask <<= 4, i++) {
if (!(flags & 1)) {
continue;
}
r.texMtxMode = pResult->texMtxMode;
r.texSrt[i] = pResult->srt[i];
r.flag = (r.flag & ~mask) | (pResult->flags & mask);
}
}
void ApplyTexSrtAnmResult(ResTexSrt srt, ResMatIndMtxAndScale ind, const TexSrtAnmResult *pResult) {
ApplyTexSrtAnmResult(srt, pResult);
u32 flags = pResult->indFlags;
for (int i = TexSrtAnmResult::NUM_OF_MAT_TEX_MTX; flags != 0; i++, flags >>= TexSrt::NUM_OF_FLAGS) {
if (!(flags & 1)) {
continue;
}
math::MTX34 mtx;
CalcTexMtx(
&mtx, true, pResult->srt[i], static_cast<TexSrt::Flag>(flags & TexSrt::FLAGSET_IDENTITY),
TexSrtTypedef::TEXMATRIXMODE_MAYA
);
s8 scaleExp;
f32 maxElem = 0.000000000000000001f;
maxElem = ut::Max(maxElem, math::FAbs(mtx._00));
maxElem = ut::Max(maxElem, math::FAbs(mtx._01));
maxElem = ut::Max(maxElem, math::FAbs(mtx._03));
maxElem = ut::Max(maxElem, math::FAbs(mtx._10));
maxElem = ut::Max(maxElem, math::FAbs(mtx._11));
maxElem = ut::Max(maxElem, math::FAbs(mtx._13));
scaleExp = static_cast<s8>(math::FGetExpPart(maxElem) + 1);
f32 invScale = 0.f; // TODO: ldexpf(1.0f, -scaleExp);
mtx._00 *= invScale;
mtx._01 *= invScale;
mtx._02 = mtx._03 * invScale;
mtx._10 *= invScale;
mtx._11 *= invScale;
mtx._12 = mtx._13 * invScale;
GXIndTexMtxID id = static_cast<GXIndTexMtxID>(i - TexSrtAnmResult::NUM_OF_MAT_TEX_MTX + 1);
ind.GXSetIndTexMtx(id, mtx, scaleExp);
}
}
} // namespace g3d
} // namespace nw4r
+444
View File
@@ -0,0 +1,444 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(AnmObjVis);
NW4R_G3D_RTTI_DEF(AnmObjVisNode);
NW4R_G3D_RTTI_DEF(AnmObjVisOR);
NW4R_G3D_RTTI_DEF(AnmObjVisRes);
/******************************************************************************
*
* AnmObjVis
*
******************************************************************************/
AnmObjVis::AnmObjVis(MEMAllocator* pAllocator, u16* pBindingBuf, int numBinding)
: AnmObj(pAllocator, NULL),
mpBinding(pBindingBuf),
mNumBinding(numBinding) {
Release();
}
bool AnmObjVis::TestExistence(u32 idx) const {
return !(mpBinding[idx] & (BINDING_UNDEFINED | BINDING_INVALID));
}
bool AnmObjVis::TestDefined(u32 idx) const {
return !(mpBinding[idx] & BINDING_UNDEFINED);
}
void AnmObjVis::Release() {
for (int i = 0; i < mNumBinding; i++) {
mpBinding[i] = BINDING_UNDEFINED;
}
SetAnmFlag(FLAG_ANM_BOUND, false);
}
AnmObjVisRes* AnmObjVis::Attach(int idx, AnmObjVisRes* pRes) {
#pragma unused(idx)
#pragma unused(pRes)
return NULL;
}
AnmObjVisRes* AnmObjVis::Detach(int idx) {
#pragma unused(idx)
return NULL;
}
void AnmObjVis::DetachAll() {
for (int i = 0; i < MAX_CHILD; i++) {
Detach(i);
}
}
void AnmObjVis::G3dProc(u32 task, u32 param, void* pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_UPDATEFRAME: {
SetAnmFlag(FLAG_CACHE_OBSOLETE, true);
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjVisNode
*
******************************************************************************/
AnmObjVisNode::AnmObjVisNode(MEMAllocator* pAllocator, u16* pBindingBuf,
int numBinding)
: AnmObjVis(pAllocator, pBindingBuf, numBinding) {
for (int i = 0; i < MAX_CHILD; i++) {
mpChildren[i] = NULL;
}
}
AnmObjVisNode::~AnmObjVisNode() {
DetachAll();
}
AnmObjVisRes* AnmObjVisNode::Attach(int idx, AnmObjVisRes* pRes) {
AnmObjVisRes* pOld = Detach(idx);
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
if (!pRes->TestDefined(i)) {
continue;
}
hasAnm = true;
mpBinding[i] = 0;
}
if (hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, true);
}
mpChildren[idx] = pRes;
pRes->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return pOld;
}
AnmObjVisRes* AnmObjVisNode::Detach(int idx) {
AnmObjVisRes* pOld = mpChildren[idx];
if (pOld != NULL) {
pOld->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpChildren[idx] = NULL;
bool hasAnm = false;
for (u32 i = 0; i < mNumBinding; i++) {
u16 binding = BINDING_UNDEFINED;
for (int j = 0; j < MAX_CHILD; j++) {
AnmObjVisRes* pChild = mpChildren[j];
if (pChild == NULL || !pChild->TestDefined(i)) {
continue;
}
hasAnm = true;
binding = 0;
break;
}
mpBinding[i] = binding;
}
if (!hasAnm) {
SetAnmFlag(FLAG_ANM_BOUND, false);
}
}
return pOld;
}
void AnmObjVisNode::UpdateFrame() {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] != NULL) {
mpChildren[i]->UpdateFrame();
}
}
}
void AnmObjVisNode::SetFrame(f32 frame) {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] != NULL) {
mpChildren[i]->SetFrame(frame);
}
}
}
f32 AnmObjVisNode::GetFrame() const {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] != NULL) {
return mpChildren[i]->GetFrame();
}
}
return 0.0f;
}
void AnmObjVisNode::SetUpdateRate(f32 rate) {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] != NULL) {
mpChildren[i]->SetUpdateRate(rate);
}
}
}
f32 AnmObjVisNode::GetUpdateRate() const {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] != NULL) {
return mpChildren[i]->GetUpdateRate();
}
}
return 1.0f;
}
bool AnmObjVisNode::Bind(ResMdl mdl) {
bool success = false;
for (int i = 0; i < MAX_CHILD; i++) {
AnmObjVisRes* pChild = mpChildren[i];
if (pChild == NULL) {
continue;
}
bool childSuccess = pChild->Bind(mdl);
success = success || childSuccess;
for (u32 j = 0; j < mNumBinding; j++) {
if (pChild->TestDefined(j)) {
mpBinding[j] = 0;
}
}
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
void AnmObjVisNode::Release() {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] != NULL) {
mpChildren[i]->Release();
}
}
AnmObjVis::Release();
}
void AnmObjVisNode::G3dProc(u32 task, u32 param, void* pInfo) {
#pragma unused(param)
switch (task) {
case G3DPROC_CHILD_DETACHED: {
for (int i = 0; i < MAX_CHILD; i++) {
if (mpChildren[i] == pInfo) {
Detach(i);
return;
}
}
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
}
}
/******************************************************************************
*
* AnmObjVisOR
*
******************************************************************************/
AnmObjVisOR* AnmObjVisOR::Construct(MEMAllocator* pAllocator, u32* pSize,
ResMdl mdl) {
if (!mdl.IsValid()) {
return NULL;
}
u32 numAnim = mdl.GetResNodeNumEntries();
int bindNum = numAnim;
u32 bindSize = bindNum * sizeof(u16);
u32 size = bindSize + sizeof(AnmObjVisOR);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
u16* pBindingBuf = reinterpret_cast<u16*>(pBuffer + sizeof(AnmObjVisOR));
AnmObjVisOR* pObjVis =
new (pBuffer) AnmObjVisOR(pAllocator, pBindingBuf, bindNum);
return pObjVis;
}
bool AnmObjVisOR::GetResult(u32 idx) {
for (int i = 0; i < MAX_CHILD; i++) {
AnmObjVisRes* pChild = mpChildren[i];
if (pChild == NULL || !pChild->TestExistence(idx)) {
continue;
}
if (!pChild->GetResult(idx)) {
return false;
}
}
return true;
}
/******************************************************************************
*
* AnmObjVisRes
*
******************************************************************************/
AnmObjVisRes* AnmObjVisRes::Construct(MEMAllocator* pAllocator, u32* pSize,
ResAnmVis vis, ResMdl mdl) {
if (!vis.IsValid() || !mdl.IsValid()) {
return NULL;
}
u32 numAnim = mdl.GetResNodeNumEntries();
int bindNum = numAnim;
u32 bindSize = bindNum * sizeof(u16);
u32 size = bindSize + sizeof(AnmObjVisRes);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator == NULL) {
return NULL;
}
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
u16* pBindingBuf = reinterpret_cast<u16*>(pBuffer + sizeof(AnmObjVisRes));
AnmObjVisRes* pObjVis =
new (pBuffer) AnmObjVisRes(pAllocator, vis, pBindingBuf, bindNum);
return pObjVis;
}
AnmObjVisRes::AnmObjVisRes(MEMAllocator* pAllocator, ResAnmVis vis,
u16* pBindingBuf, int numBinding)
: AnmObjVis(pAllocator, pBindingBuf, numBinding),
FrameCtrl(0.0f, vis.GetNumFrame(), GetAnmPlayPolicy(vis.GetAnmPolicy())),
mRes(vis) {}
void AnmObjVisRes::SetFrame(f32 frame) {
SetFrm(frame);
G3dProc(G3DPROC_UPDATEFRAME, 0, NULL);
}
f32 AnmObjVisRes::GetFrame() const {
return GetFrm();
}
void AnmObjVisRes::SetUpdateRate(f32 rate) {
SetRate(rate);
}
f32 AnmObjVisRes::GetUpdateRate() const {
return GetRate();
}
void AnmObjVisRes::UpdateFrame() {
UpdateFrm();
G3dProc(G3DPROC_UPDATEFRAME, 0, NULL);
}
bool AnmObjVisRes::Bind(ResMdl mdl) {
int numAnim = mRes.GetNumNode();
bool success = false;
for (u16 i = 0; i < numAnim; i++) {
const ResAnmVisAnmData* pData = mRes.GetNodeAnm(i);
// Seek back from name string to start of ResName
ResName name(ut::AddOffsetToPtr(pData, pData->name - 4));
ResNode node = mdl.GetResNode(name);
if (!node.IsValid()) {
continue;
}
mpBinding[node.GetID()] = i;
success = true;
}
SetAnmFlag(FLAG_ANM_BOUND, true);
return success;
}
bool AnmObjVisRes::GetResult(u32 idx) {
u32 id = mpBinding[idx];
if ((id & BINDING_INVALID) || (id & BINDING_UNDEFINED)) {
return true;
}
return mRes.GetAnmResult(id, GetFrm());
}
/******************************************************************************
*
* ApplyVisAnmResult
*
******************************************************************************/
void ApplyVisAnmResult(ResMdl mdl, AnmObjVis* pObj) {
u32 numNode = mdl.GetResNodeNumEntries();
for (u32 i = 0; i < numNode; i++) {
if (!pObj->TestExistence(i)) {
continue;
}
ResNode node = mdl.GetResNode(i);
node.SetVisibility(pObj->GetResult(i));
}
}
void ApplyVisAnmResult(u8* byteVec, ResMdl mdl, AnmObjVis* pObj) {
u32 numNode = mdl.GetResNodeNumEntries();
for (u32 i = 0; i < numNode; i++) {
if (!pObj->TestExistence(i)) {
continue;
}
byteVec[i] = pObj->GetResult(i);
}
}
} // namespace g3d
} // namespace nw4r
+61
View File
@@ -0,0 +1,61 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace detail {
namespace dcc {
u32 CalcWorldMtx_Basic(math::MTX34* pW, math::VEC3* pS, const math::MTX34* pW1,
const math::VEC3* pS1, u32 attr,
const ChrAnmResult* pResult) {
u32 flag = pResult->flags;
u32 newAttr = attr;
if (flag & ChrAnmResult::FLAG_SCALE_ONE) {
newAttr = detail::WorldMtxAttr::AnmScaleOne(newAttr);
pS->x = pS->y = pS->z = 1.0f;
} else {
newAttr = detail::WorldMtxAttr::AnmNotScaleOne(newAttr);
*pS = pResult->s;
}
if ((flag & ChrAnmResult::FLAG_MTX_IDENT) ||
(flag & ChrAnmResult::FLAG_ROT_TRANS_ZERO)) {
if (detail::WorldMtxAttr::IsScaleOne(attr)) {
math::MTX34Copy(pW, pW1);
} else {
math::MTX34Scale(pW, pW1, pS1);
}
} else if (flag & ChrAnmResult::FLAG_ROT_ZERO) {
if (detail::WorldMtxAttr::IsScaleOne(attr)) {
math::VEC3 trans(pResult->rt._03, pResult->rt._13, pResult->rt._23);
math::MTX34Trans(pW, pW1, &trans);
} else {
math::MTX34 temp;
math::MTX34Scale(&temp, pS1, &pResult->rt);
math::MTX34Mult(pW, pW1, &temp);
}
} else if (detail::WorldMtxAttr::IsScaleOne(attr)) {
math::MTX34Mult(pW, pW1, &pResult->rt);
} else {
math::MTX34Scale(pW, pW1, pS1);
math::MTX34Mult(pW, pW, &pResult->rt);
}
if (flag & ChrAnmResult::FLAG_SCALE_UNIFORM) {
newAttr = detail::WorldMtxAttr::AnmScaleUniform(newAttr);
} else {
newAttr = detail::WorldMtxAttr::AnmNotScaleUniform(newAttr);
}
return newAttr;
}
} // namespace dcc
} // namespace detail
} // namespace g3d
} // namespace nw4r
+61
View File
@@ -0,0 +1,61 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
void CalcMaterialDirectly(ResMdl mdl, AnmObjTexPat* pAnmTexPat,
AnmObjTexSrt* pAnmTexSrt, AnmObjMatClr* pAnmMatClr) {
u32 i;
u32 numMatID = mdl.GetResMatNumEntries();
for (i = 0; i < numMatID; i++) {
ResMat mat = mdl.GetResMat(i);
if (pAnmTexPat != NULL && pAnmTexPat->TestExistence(i)) {
TexPatAnmResult result;
const TexPatAnmResult* pResult;
pResult = pAnmTexPat->GetResult(&result, i);
ApplyTexPatAnmResult(mat.GetResTexObj(), mat.GetResTlutObj(),
pResult);
mat.GetResTexObj().EndEdit();
mat.GetResTlutObj().EndEdit();
}
if (pAnmTexSrt != NULL && pAnmTexSrt->TestExistence(i)) {
TexSrtAnmResult result;
const TexSrtAnmResult* pResult;
ResTexSrt srt = mat.GetResTexSrt();
ResMatIndMtxAndScale ind = mat.GetResMatIndMtxAndScale();
pResult = pAnmTexSrt->GetResult(&result, i);
ApplyTexSrtAnmResult(srt, ind, pResult);
ind.EndEdit();
srt.EndEdit();
}
if (pAnmMatClr != NULL && pAnmMatClr->TestExistence(i)) {
ClrAnmResult result;
const ClrAnmResult* pResult;
ResMatTevColor tevColor = mat.GetResMatTevColor();
ResMatChan chan = mat.GetResMatChan();
pResult = pAnmMatClr->GetResult(&result, i);
ApplyClrAnmResult(chan, tevColor, pResult);
chan.EndEdit();
tevColor.EndEdit();
}
}
}
} // namespace g3d
} // namespace nw4r
+963
View File
@@ -0,0 +1,963 @@
#include <nw4r/g3d.h>
#include <algorithm>
namespace nw4r {
namespace g3d {
/******************************************************************************
*
* Paired-single math implementation
*
******************************************************************************/
namespace {
// Allows struct offsets inside assembly
using nw4r::math::MTX34;
using nw4r::math::VEC3;
asm void GetModelLocalAxisY2(register math::VEC3* pVec,
register const math::MTX34* pModelMtx,
register const math::MTX34* pParentModelMtx) {
// clang-format off
nofralloc
psq_l f2, MTX34._10(pParentModelMtx), 1, 0
psq_l f3, MTX34._11(pParentModelMtx), 0, 0
psq_l f0, MTX34._00(pParentModelMtx), 1, 0
psq_l f1, MTX34._01(pParentModelMtx), 0, 0
ps_merge10 f7, f3, f2
psq_l f5, MTX34._21(pParentModelMtx), 0, 0
psq_l f4, MTX34._20(pParentModelMtx), 1, 0
ps_merge10 f6, f1, f0
ps_mul f12, f5, f7
ps_merge10 f8, f5, f4
ps_mul f10, f3, f6
ps_mul f9, f0, f5
ps_mul f11, f1, f8
ps_msub f12, f3, f8, f12
ps_msub f10, f1, f7, f10
ps_msub f11, f5, f6, f11
ps_mul f7, f0, f12
ps_sub f6, f6, f6
ps_msub f9, f1, f4, f9
ps_madd f7, f2, f11, f7
stfs f6, VEC3.z(pVec)
ps_madd f7, f4, f10, f7
ps_cmpo0 cr0, f7, f6
bne _lbl_80068168
psq_st f6, VEC3.x(pVec), 0, 0
blr
_lbl_80068168:
fres f0, f7
psq_l f1, MTX34._10(pModelMtx), 0, 0
psq_l f2, MTX34._02(pModelMtx), 1, 0
psq_l f3, MTX34._12(pModelMtx), 1, 0
ps_add f6, f0, f0
ps_mul f5, f0, f0
ps_nmsub f0, f7, f5, f6
ps_merge00 f6, f2, f3
ps_muls0 f11, f11, f0
ps_muls0 f9, f9, f0
psq_l f0, MTX34._00(pModelMtx), 0, 0
ps_merge00 f4, f0, f1
ps_merge11 f5, f0, f1
ps_muls0 f0, f4, f11
ps_madds1 f0, f5, f11, f0
ps_madds0 f0, f6, f9, f0
psq_st f0, VEC3.x(pVec), 0, 0
blr
// clang-format on
}
asm void GetModelLocalAxisY3(register math::VEC3* pVec,
register const math::MTX34* pModelMtx,
register const math::MTX34* pParentModelMtx) {
// clang-format off
nofralloc
psq_l f2, MTX34._10(pParentModelMtx), 1, 0
psq_l f3, MTX34._11(pParentModelMtx), 0, 0
psq_l f0, MTX34._00(pParentModelMtx), 1, 0
psq_l f1, MTX34._01(pParentModelMtx), 0, 0
ps_merge10 f7, f3, f2
psq_l f5, MTX34._21(pParentModelMtx), 0, 0
psq_l f4, MTX34._20(pParentModelMtx), 1, 0
ps_merge10 f6, f1, f0
ps_mul f12, f5, f7
ps_merge10 f8, f5, f4
ps_mul f10, f3, f6
ps_mul f9, f0, f5
ps_mul f11, f1, f8
ps_msub f12, f3, f8, f12
ps_msub f10, f1, f7, f10
ps_msub f11, f5, f6, f11
ps_mul f7, f0, f12
ps_sub f6, f6, f6
ps_msub f9, f1, f4, f9
ps_madd f7, f2, f11, f7
ps_madd f7, f4, f10, f7
ps_cmpo0 cr0, f7, f6
bne _lbl_80068218
psq_st f6, VEC3.x(pVec), 0, 0
stfs f6, VEC3.z(pVec)
blr
_lbl_80068218:
fres f0, f7
psq_l f1, MTX34._10(pModelMtx), 0, 0
psq_l f2, MTX34._02(pModelMtx), 1, 0
psq_l f3, MTX34._12(pModelMtx), 1, 0
ps_add f6, f0, f0
ps_mul f5, f0, f0
ps_nmsub f0, f7, f5, f6
ps_merge00 f6, f2, f3
psq_l f2, MTX34._22(pModelMtx), 1, 0
ps_muls0 f11, f11, f0
ps_muls0 f9, f9, f0
psq_l f0, MTX34._00(pModelMtx), 0, 0
ps_merge00 f4, f0, f1
ps_merge11 f5, f0, f1
psq_l f1, MTX34._20(pModelMtx), 0, 0
ps_muls0 f0, f4, f11
ps_mul f1, f1, f9
ps_madds1 f0, f5, f11, f0
ps_sum0 f1, f1, f1, f1
ps_madds0 f0, f6, f9, f0
fmadds f1, f2, f9, f1
psq_st f0, VEC3.x(pVec), 0, 0
psq_st f1, VEC3.z(pVec), 1, 0
blr
// clang-format on
}
inline void SetMdlViewMtxSR(register math::MTX34* pViewPos,
register const math::VEC3& rRY, register f32 s) {
register f32 work0, work1;
register f32 c_zero = 0.0f;
// clang-format off
asm {
psq_l work0, VEC3.x(rRY), 0, 0
ps_muls0 work0, work0, s
ps_merge10 work1, work0, work0
psq_st work1, MTX34._00(pViewPos), 0, 0
ps_neg work1, work0
ps_merge01 work1, work1, work0
psq_st work1, MTX34._10(pViewPos), 0, 0
stfs c_zero, MTX34._02(pViewPos)
stfs c_zero, MTX34._12(pViewPos)
psq_st c_zero, MTX34._20(pViewPos), 0, 0
stfs s, MTX34._22(pViewPos)
}
// clang-format on
}
inline void SetMdlViewMtxSR(register math::MTX34* pViewPos,
register const math::VEC3& rRY, register f32 sx,
register f32 sy, register f32 sz) {
register f32 work0, work1, work2, work3;
register f32 c_zero = 0.0f;
// clang-format off
asm {
ps_merge00 work0, sx, sy
psq_l work1, VEC3.x(rRY), 0, 0
ps_merge10 work3, work1, work1
ps_mul work3, work3, work0
psq_st work3, MTX34._00(pViewPos), 0, 0
ps_neg work2, work1
ps_merge01 work3, work2, work1
ps_mul work3, work3, work0
psq_st work3, MTX34._10(pViewPos), 0, 0
stfs c_zero, MTX34._02(pViewPos)
stfs c_zero, MTX34._12(pViewPos)
psq_st c_zero, MTX34._20(pViewPos), 0, 0
stfs sz, MTX34._22(pViewPos)
}
// clang-format on
}
inline void SetMdlViewMtxSR(register math::MTX34* pViewPos,
register const math::VEC3& rRX,
register const math::VEC3& rRY,
register const math::VEC3& rRZ, register f32 sx,
register f32 sy, register f32 sz) {
register f32 work0, work1, work2, work3;
// clang-format off
asm {
psq_l work0, VEC3.x(rRX), 0, 0
psq_l work1, VEC3.x(rRY), 0, 0
ps_muls0 work0, work0, sx
ps_muls0 work1, work1, sy
ps_merge00 work2, work0, work1
ps_merge11 work3, work0, work1
psq_st work2, MTX34._00(pViewPos), 0, 0
psq_st work3, MTX34._10(pViewPos), 0, 0
psq_l work0, VEC3.x(rRZ), 0, 0
ps_muls0 work0, work0, sz
stfs work0, MTX34._02(pViewPos)
ps_merge11 work0, work0, work0
stfs work0, MTX34._12(pViewPos)
lfs work0, VEC3.z(rRX)
fmuls work0, work0, sx
stfs work0, MTX34._20(pViewPos)
lfs work0, VEC3.z(rRY)
fmuls work0, work0, sy
stfs work0, MTX34._21(pViewPos)
lfs work0, VEC3.z(rRZ)
fmuls work0, work0, sz
stfs work0, MTX34._22(pViewPos)
}
// clang-format on
}
} // namespace
/******************************************************************************
*
* Billboard implementation
*
******************************************************************************/
namespace {
inline f32 GetMtx34Scale(const math::MTX34& rMtx, int col) {
return math::FSqrt(rMtx.m[0][col] * rMtx.m[0][col] +
rMtx.m[1][col] * rMtx.m[1][col] +
rMtx.m[2][col] * rMtx.m[2][col]);
}
void Calc_BILLBOARD_STD(math::MTX34* pViewPos,
const math::MTX34* pModelMtxArray, bool uniformScale,
const math::MTX34* pViewMtx, const ResMdl mdl,
const u32 id) {
#pragma unused(pViewMtx)
#pragma unused(mdl)
math::VEC3 vy(pViewPos->_01, pViewPos->_11, 0.0f);
math::VEC3Normalize(&vy, &vy);
if (uniformScale) {
f32 s = GetMtx34Scale(pModelMtxArray[id], 0);
SetMdlViewMtxSR(pViewPos, vy, s);
} else {
f32 sx = GetMtx34Scale(pModelMtxArray[id], 0);
f32 sy = GetMtx34Scale(pModelMtxArray[id], 1);
f32 sz = GetMtx34Scale(pModelMtxArray[id], 2);
SetMdlViewMtxSR(pViewPos, vy, sx, sy, sz);
}
}
void Calc_BILLBOARD_PERSP_STD(math::MTX34* pViewPos,
const math::MTX34* pModelMtxArray,
bool uniformScale, const math::MTX34* pViewMtx,
const ResMdl mdl, const u32 id) {
#pragma unused(pViewMtx)
#pragma unused(mdl)
math::VEC3 vx;
math::VEC3 vy(pViewPos->_01, pViewPos->_11, pViewPos->_21);
math::VEC3 vz(-pViewPos->_03, -pViewPos->_13, -pViewPos->_23);
math::VEC3Normalize(&vz, &vz);
math::VEC3Cross(&vx, &vy, &vz);
math::VEC3Normalize(&vx, &vx);
math::VEC3Cross(&vy, &vz, &vx);
if (uniformScale) {
f32 s = GetMtx34Scale(pModelMtxArray[id], 0);
SetMdlViewMtxSR(pViewPos, vx, vy, vz, s, s, s);
} else {
f32 sx = GetMtx34Scale(pModelMtxArray[id], 0);
f32 sy = GetMtx34Scale(pModelMtxArray[id], 1);
f32 sz = GetMtx34Scale(pModelMtxArray[id], 2);
SetMdlViewMtxSR(pViewPos, vx, vy, vz, sx, sy, sz);
}
}
void Calc_BILLBOARD_ROT(math::MTX34* pViewPos,
const math::MTX34* pModelMtxArray, bool uniformScale,
const math::MTX34* pViewMtx, const ResMdl mdl,
const u32 id) {
#pragma unused(pViewMtx)
math::VEC3 vy;
int nodeID = mdl.GetResMdlInfo().GetNodeIDFromMtxID(id);
if (nodeID >= 0) {
ResNode node = mdl.GetResNode(nodeID);
ResNode parent = node.GetParentNode();
if (parent.IsValid()) {
u32 parentMtxID = parent.GetMtxID();
GetModelLocalAxisY2(&vy, &pModelMtxArray[id],
&pModelMtxArray[parentMtxID]);
} else {
vy.x = pModelMtxArray[id]._01;
vy.y = pModelMtxArray[id]._11;
vy.z = 0.0f;
}
} else {
vy.x = pModelMtxArray[id]._01;
vy.y = pModelMtxArray[id]._11;
vy.z = 0.0f;
}
math::VEC3Normalize(&vy, &vy);
if (uniformScale) {
f32 s = GetMtx34Scale(pModelMtxArray[id], 0);
SetMdlViewMtxSR(pViewPos, vy, s);
} else {
f32 sx = GetMtx34Scale(pModelMtxArray[id], 0);
f32 sy = GetMtx34Scale(pModelMtxArray[id], 1);
f32 sz = GetMtx34Scale(pModelMtxArray[id], 2);
SetMdlViewMtxSR(pViewPos, vy, sx, sy, sz);
}
}
void Calc_BILLBOARD_PERSP_ROT(math::MTX34* pViewPos,
const math::MTX34* pModelMtxArray,
bool uniformScale, const math::MTX34* pViewMtx,
const ResMdl mdl, const u32 id) {
#pragma unused(pViewMtx)
math::VEC3 vx;
math::VEC3 vy;
math::VEC3 vz(-pViewPos->_03, -pViewPos->_13, -pViewPos->_23);
int nodeID = mdl.GetResMdlInfo().GetNodeIDFromMtxID(id);
if (nodeID >= 0) {
ResNode node = mdl.GetResNode(nodeID);
ResNode parent = node.GetParentNode();
if (parent.IsValid()) {
u32 parentMtxID = parent.GetMtxID();
GetModelLocalAxisY3(&vy, &pModelMtxArray[id],
&pModelMtxArray[parentMtxID]);
} else {
vy.x = pModelMtxArray[id]._01;
vy.y = pModelMtxArray[id]._11;
vy.z = pModelMtxArray[id]._21;
}
} else {
vy.x = pModelMtxArray[id]._01;
vy.y = pModelMtxArray[id]._11;
vy.z = pModelMtxArray[id]._21;
}
math::VEC3Normalize(&vz, &vz);
math::VEC3Cross(&vx, &vy, &vz);
math::VEC3Normalize(&vx, &vx);
math::VEC3Cross(&vy, &vz, &vx);
if (uniformScale) {
f32 s = GetMtx34Scale(pModelMtxArray[id], 0);
SetMdlViewMtxSR(pViewPos, vx, vy, vz, s, s, s);
} else {
f32 sx = GetMtx34Scale(pModelMtxArray[id], 0);
f32 sy = GetMtx34Scale(pModelMtxArray[id], 1);
f32 sz = GetMtx34Scale(pModelMtxArray[id], 2);
SetMdlViewMtxSR(pViewPos, vx, vy, vz, sx, sy, sz);
}
}
void Calc_BILLBOARD_Y(math::MTX34* pViewPos, const math::MTX34* pModelMtxArray,
bool uniformScale, const math::MTX34* pViewMtx,
const ResMdl mdl, const u32 id) {
#pragma unused(pViewMtx)
#pragma unused(mdl)
math::VEC3 vz;
math::VEC3 vy(pViewPos->_01, pViewPos->_11, pViewPos->_21);
math::VEC3 vx(vy.y, -vy.x, 0.0f);
f32 sy = GetMtx34Scale(pModelMtxArray[id], 1);
f32 invSY = math::FInv(sy);
vy *= invSY;
math::VEC3Normalize(&vx, &vx);
math::VEC3Cross(&vz, &vx, &vy);
if (uniformScale) {
SetMdlViewMtxSR(pViewPos, vx, vy, vz, sy, sy, sy);
} else {
f32 sx = GetMtx34Scale(pModelMtxArray[id], 0);
f32 sz = GetMtx34Scale(pModelMtxArray[id], 2);
SetMdlViewMtxSR(pViewPos, vx, vy, vz, sx, sy, sz);
}
}
void Calc_BILLBOARD_PERSP_Y(math::MTX34* pViewPos,
const math::MTX34* pModelMtxArray,
bool uniformScale, const math::MTX34* pViewMtx,
const ResMdl mdl, const u32 id) {
#pragma unused(pViewMtx)
#pragma unused(mdl)
math::VEC3 vx;
math::VEC3 vy(pViewPos->_01, pViewPos->_11, pViewPos->_21);
math::VEC3 vz(-pViewPos->_03, -pViewPos->_13, -pViewPos->_23);
f32 sy = GetMtx34Scale(pModelMtxArray[id], 1);
f32 invSY = math::FInv(sy);
vy *= invSY;
math::VEC3Cross(&vx, &vy, &vz);
math::VEC3Normalize(&vx, &vx);
math::VEC3Cross(&vz, &vx, &vy);
if (uniformScale) {
SetMdlViewMtxSR(pViewPos, vx, vy, vz, sy, sy, sy);
} else {
f32 sx = GetMtx34Scale(pModelMtxArray[id], 0);
f32 sz = GetMtx34Scale(pModelMtxArray[id], 2);
SetMdlViewMtxSR(pViewPos, vx, vy, vz, sx, sy, sz);
}
}
typedef void (*BillBoardFunc)(math::MTX34* pViewPos,
const math::MTX34* pModelMtxArray,
bool uniformScale, const math::MTX34* pViewMtx,
const ResMdl mdl, const u32 id);
const BillBoardFunc bbFunc[ResNodeData::NUM_BILLBOARD] = {
NULL, // BILLBOARD_OFF is ignored
Calc_BILLBOARD_STD, //
Calc_BILLBOARD_PERSP_STD, //
Calc_BILLBOARD_ROT, //
Calc_BILLBOARD_PERSP_ROT, //
Calc_BILLBOARD_Y, //
Calc_BILLBOARD_PERSP_Y //
};
} // namespace
/******************************************************************************
*
* CalcView
*
******************************************************************************/
void CalcView(math::MTX34* pViewPosArray, math::MTX33* pViewNrmArray,
const math::MTX34* pModelMtxArray,
const u32* pModelMtxAttribArray, u32 numMtx,
const math::MTX34* pViewMtx, const ResMdl mdl,
math::MTX34* pViewTexMtxArray) {
if (numMtx <= 0) {
return;
}
math::MTX34* pVArray;
math::MTX33* pNArray;
math::MTX34* pCurTArray;
u32 sizeVArray = align32(numMtx * sizeof(math::MTX34));
u32 sizeNArray = align32(numMtx * sizeof(math::MTX33));
u32 sizeTArray = align32(numMtx * sizeof(math::MTX34));
pVArray = pViewPosArray;
if (numMtx > 1) {
math::MTX34MultArray(pVArray, pViewMtx, pModelMtxArray, numMtx);
} else {
math::MTX34Mult(pVArray, pViewMtx, pModelMtxArray);
}
math::MTX34* pBbMtxArray = detail::workmem::GetBillboardMtxTemporary();
for (u32 i = 0; i < numMtx; i++) {
u32 attr = pModelMtxAttribArray[i];
ResNodeData::Billboard bbType =
detail::WorldMtxAttr::GetBillboard(attr);
if (bbType != ResNodeData::BILLBOARD_OFF) {
math::MTX34& rVMtx = pVArray[i];
bbFunc[bbType](&rVMtx, pModelMtxArray,
detail::WorldMtxAttr::IsAllScaleUniform(attr),
pViewMtx, mdl, i);
s32 nodeID = mdl.GetResMdlInfo().GetNodeIDFromMtxID(i);
ResNode node = mdl.GetResNode(static_cast<u32>(nodeID));
if (node.IsValid() && node.GetChildNode().IsValid()) {
math::MTX34 invWorld;
u32 ret = math::MTX34Inv(&invWorld, &pModelMtxArray[i]);
if (ret == TRUE) {
math::MTX34Mult(&pBbMtxArray[i], &pVArray[i], &invWorld);
} else {
math::MTX34Identity(&pBbMtxArray[i]);
}
}
} else {
s32 nodeID = mdl.GetResMdlInfo().GetNodeIDFromMtxID(i);
if (nodeID < 0) {
continue;
}
ResNode node = mdl.GetResNode(static_cast<u32>(nodeID));
if (!node.IsValid()) {
continue;
}
if (!(node.ref().flags & ResNodeData::FLAG_BILLBOARD_PARENT)) {
continue;
}
u32 bbMtxID = mdl.GetResNode(node.ref().bbref_nodeid).GetMtxID();
math::MTX34Mult(&pVArray[i], &pBbMtxArray[bbMtxID],
&pModelMtxArray[i]);
}
}
pNArray = pViewNrmArray;
pCurTArray = pViewTexMtxArray;
if (pNArray != NULL) {
for (u32 i = 0; i < numMtx; i++) {
math::MTX34& rVMtx = pVArray[i];
math::MTX33& rNMtx = pNArray[i];
u32 attr = pModelMtxAttribArray[i];
if (detail::WorldMtxAttr::IsAllScaleUniform(attr)) {
if (pCurTArray != NULL) {
math::MTX34Copy(&pCurTArray[i], &rVMtx);
pCurTArray[i]._03 = pCurTArray[i]._13 = pCurTArray[i]._23 =
0.0f;
}
math::MTX34ToMTX33(&rNMtx, &rVMtx);
} else {
if (pCurTArray != NULL) {
math::MTX34InvTranspose(&pCurTArray[i], &rVMtx);
math::MTX34ToMTX33(&rNMtx, &pCurTArray[i]);
} else {
math::MTX34InvTranspose(&rNMtx, &rVMtx);
}
}
}
}
DC::FlushRangeNoSync(pVArray, sizeVArray);
if (pNArray != NULL) {
DC::FlushRangeNoSync(pViewNrmArray, sizeNArray);
if (pCurTArray != NULL) {
DC::FlushRangeNoSync(pViewTexMtxArray, sizeTArray);
}
}
}
void CalcView_LC(math::MTX34* pViewPosArray, math::MTX33* pViewNrmArray,
const math::MTX34* pModelMtxArray,
const u32* pModelMtxAttribArray, u32 numMtx,
const math::MTX34* pViewMtx, const ResMdl mdl,
math::MTX34* pViewTexMtxArray) {
if (numMtx <= 0) {
return;
}
detail::MtxCacheMap* pMtxCache =
static_cast<detail::MtxCacheMap*>(ut::LC::GetBase());
math::MTX34* pCurVArray =
reinterpret_cast<math::MTX34*>(pMtxCache->currViewArray);
math::MTX33* pCurNArray =
reinterpret_cast<math::MTX33*>(pMtxCache->currNrmArray);
math::MTX34* pCurTArray =
reinterpret_cast<math::MTX34*>(pMtxCache->currTexArray);
math::MTX34* pPrevVArray =
reinterpret_cast<math::MTX34*>(pMtxCache->prevViewArray);
math::MTX33* pPrevNArray =
reinterpret_cast<math::MTX33*>(pMtxCache->prevNrmArray);
math::MTX34* pPrevTArray =
reinterpret_cast<math::MTX34*>(pMtxCache->prevTexArray);
u32 sizeVArray = align32(numMtx * sizeof(math::MTX34));
DC::InvalidateRange(pViewPosArray, sizeVArray);
u32 queueLen = 1;
u32 sizeNArray, sizeTArray;
if (pViewNrmArray != NULL) {
queueLen++;
sizeNArray = align32(numMtx * sizeof(math::MTX33));
DC::InvalidateRange(pViewNrmArray, sizeNArray);
if (pViewTexMtxArray != NULL) {
queueLen++;
sizeTArray = align32(numMtx * sizeof(math::MTX34));
DC::InvalidateRange(pViewTexMtxArray, sizeTArray);
}
}
math::MTX34* pBbMtxArray = detail::workmem::GetBillboardMtxTemporary();
ut::LC::QueueWait(0);
u32 baseMtx;
for (baseMtx = 0; baseMtx < numMtx; baseMtx += 40) {
u32 remain = numMtx - baseMtx;
u32 numBlocks, numBlocksNrm;
if (remain > 40) {
remain = 40;
numBlocks = 60;
numBlocksNrm = 45;
} else {
numBlocks = align32(remain * sizeof(math::MTX34)) / 32;
numBlocksNrm = align32(remain * sizeof(math::MTX33)) / 32;
}
ut::LC::QueueWait(queueLen);
if (remain > 1) {
math::MTX34MultArray(pCurVArray, pViewMtx, &pModelMtxArray[baseMtx],
remain);
} else {
math::MTX34Mult(pCurVArray, pViewMtx, &pModelMtxArray[baseMtx]);
}
for (u32 i = 0; i < remain; i++) {
u32 attr = pModelMtxAttribArray[baseMtx + i];
ResNodeData::Billboard bbType =
detail::WorldMtxAttr::GetBillboard(attr);
if (bbType != ResNodeData::BILLBOARD_OFF) {
math::MTX34& rVMtx = pCurVArray[i];
bbFunc[bbType](&rVMtx, pModelMtxArray,
detail::WorldMtxAttr::IsAllScaleUniform(attr),
pViewMtx, mdl, baseMtx + i);
s32 nodeID =
mdl.GetResMdlInfo().GetNodeIDFromMtxID(baseMtx + i);
ResNode node = mdl.GetResNode(static_cast<u32>(nodeID));
if (node.IsValid() && node.GetChildNode().IsValid()) {
math::MTX34 invWorld;
u32 ret =
math::MTX34Inv(&invWorld, &pModelMtxArray[baseMtx + i]);
if (ret == TRUE) {
math::MTX34Mult(&pBbMtxArray[baseMtx + i],
&pCurVArray[i], &invWorld);
} else {
math::MTX34Identity(&pBbMtxArray[baseMtx + i]);
}
}
} else {
s32 nodeID =
mdl.GetResMdlInfo().GetNodeIDFromMtxID(baseMtx + i);
if (nodeID < 0) {
continue;
}
ResNode node = mdl.GetResNode(static_cast<u32>(nodeID));
if (!node.IsValid()) {
continue;
}
if (!(node.ref().flags & ResNodeData::FLAG_BILLBOARD_PARENT)) {
continue;
}
u32 bbMtxID =
mdl.GetResNode(node.ref().bbref_nodeid).GetMtxID();
math::MTX34Mult(&pCurVArray[i], &pBbMtxArray[bbMtxID],
&pModelMtxArray[baseMtx + i]);
}
}
ut::LC::StoreBlocks(&pViewPosArray[baseMtx], pCurVArray, numBlocks);
if (pViewNrmArray != NULL) {
for (u32 i = 0; i < remain; i++) {
math::MTX34& rVMtx = pCurVArray[i];
math::MTX33& rNMtx = pCurNArray[i];
u32 attr = pModelMtxAttribArray[baseMtx + i];
if (detail::WorldMtxAttr::IsAllScaleUniform(attr)) {
if (pViewTexMtxArray != NULL) {
math::MTX34Copy(&pCurTArray[i], &rVMtx);
pCurTArray[i]._03 = pCurTArray[i]._13 =
pCurTArray[i]._23 = 0.0f;
}
math::MTX34ToMTX33(&rNMtx, &rVMtx);
} else {
if (pViewTexMtxArray != NULL) {
math::MTX34InvTranspose(&pCurTArray[i], &rVMtx);
math::MTX34ToMTX33(&rNMtx, &pCurTArray[i]);
} else {
math::MTX34InvTranspose(&rNMtx, &rVMtx);
}
}
}
}
if (pViewNrmArray != NULL) {
ut::LC::StoreBlocks(&pViewNrmArray[baseMtx], pCurNArray,
numBlocksNrm);
if (pViewTexMtxArray != NULL) {
ut::LC::StoreBlocks(&pViewTexMtxArray[baseMtx], pCurTArray,
numBlocks);
}
}
std::swap(pCurVArray, pPrevVArray);
std::swap(pCurNArray, pPrevNArray);
std::swap(pCurTArray, pPrevTArray);
}
}
void CalcView_LC_DMA_ModelMtx(math::MTX34* pViewPosArray,
math::MTX33* pViewNrmArray,
const math::MTX34* pModelMtxArray,
const u32* pModelMtxAttribArray, u32 numMtx,
const math::MTX34* pViewMtx, const ResMdl mdl,
math::MTX34* pViewTexMtxArray) {
if (numMtx <= 0) {
return;
}
detail::MtxCacheMap* pMtxCache =
static_cast<detail::MtxCacheMap*>(ut::LC::GetBase());
math::MTX34* pCurMArray =
reinterpret_cast<math::MTX34*>(pMtxCache->currDmaArray);
math::MTX34* pCurVArray =
reinterpret_cast<math::MTX34*>(pMtxCache->currViewArray);
math::MTX33* pCurNArray =
reinterpret_cast<math::MTX33*>(pMtxCache->currNrmArray);
math::MTX34* pCurTArray =
reinterpret_cast<math::MTX34*>(pMtxCache->currTexArray);
math::MTX34* pPrevMArray =
reinterpret_cast<math::MTX34*>(pMtxCache->prevDmaArray);
math::MTX34* pPrevVArray =
reinterpret_cast<math::MTX34*>(pMtxCache->prevViewArray);
math::MTX33* pPrevNArray =
reinterpret_cast<math::MTX33*>(pMtxCache->prevNrmArray);
math::MTX34* pPrevTArray =
reinterpret_cast<math::MTX34*>(pMtxCache->prevTexArray);
u32 sizeVArray = align32(numMtx * sizeof(math::MTX34));
DC::InvalidateRange(pViewPosArray, sizeVArray);
u32 queueLen = 1;
u32 sizeNArray, sizeTArray;
if (pViewNrmArray != NULL) {
queueLen++;
sizeNArray = align32(numMtx * sizeof(math::MTX33));
DC::InvalidateRange(pViewNrmArray, sizeNArray);
if (pViewTexMtxArray != NULL) {
queueLen++;
sizeTArray = align32(numMtx * sizeof(math::MTX34));
DC::InvalidateRange(pViewTexMtxArray, sizeTArray);
}
}
math::MTX34* pBbMtxArray = detail::workmem::GetBillboardMtxTemporary();
ut::LC::QueueWait(0);
u32 numBlocks;
if (numMtx > 40) {
numBlocks = 60;
} else {
numBlocks = align32(numMtx * sizeof(math::MTX34)) / 32;
}
ut::LC::LoadBlocks(pCurMArray, const_cast<math::MTX34*>(pModelMtxArray),
numBlocks);
if (numMtx > 20) {
ut::LC::QueueWaitEx(0);
} else {
ut::LC::QueueWait(0);
}
u32 baseMtx;
for (baseMtx = 0; baseMtx < numMtx; baseMtx += 40) {
u32 remain = numMtx - baseMtx;
u32 numBlocks, numBlocksNrm;
if (remain > 40) {
remain = 40;
numBlocks = 60;
numBlocksNrm = 45;
} else {
numBlocks = align32(remain * sizeof(math::MTX34)) / 32;
numBlocksNrm = align32(remain * sizeof(math::MTX33)) / 32;
}
ut::LC::QueueWait(queueLen);
if (baseMtx + 40 < numMtx) {
u32 n = numMtx - baseMtx - 40;
u32 blocks;
if (n > 40) {
blocks = 60;
} else {
blocks = align32(n * sizeof(math::MTX34)) / 32;
}
ut::LC::LoadBlocks(
pPrevMArray,
const_cast<math::MTX34*>(&pModelMtxArray[baseMtx + 40]),
blocks);
}
if (remain > 1) {
math::MTX34MultArray(pCurVArray, pViewMtx, pCurMArray, remain);
} else {
math::MTX34Mult(pCurVArray, pViewMtx, pCurMArray);
}
for (u32 i = 0; i < remain; i++) {
u32 attr = pModelMtxAttribArray[baseMtx + i];
ResNodeData::Billboard bbType =
detail::WorldMtxAttr::GetBillboard(attr);
if (bbType != ResNodeData::BILLBOARD_OFF) {
math::MTX34& rVMtx = pCurVArray[i];
bbFunc[bbType](&rVMtx, pModelMtxArray,
detail::WorldMtxAttr::IsAllScaleUniform(attr),
pViewMtx, mdl, baseMtx + i);
s32 nodeID =
mdl.GetResMdlInfo().GetNodeIDFromMtxID(baseMtx + i);
ResNode node = mdl.GetResNode(static_cast<u32>(nodeID));
if (node.IsValid() && node.GetChildNode().IsValid()) {
math::MTX34 invWorld;
u32 ret =
math::MTX34Inv(&invWorld, &pModelMtxArray[baseMtx + i]);
if (ret == TRUE) {
math::MTX34Mult(&pBbMtxArray[baseMtx + i],
&pCurVArray[i], &invWorld);
} else {
math::MTX34Identity(&pBbMtxArray[baseMtx + i]);
}
}
} else {
s32 nodeID =
mdl.GetResMdlInfo().GetNodeIDFromMtxID(baseMtx + i);
if (nodeID < 0) {
continue;
}
ResNode node = mdl.GetResNode(static_cast<u32>(nodeID));
if (!node.IsValid()) {
continue;
}
if (!(node.ref().flags & ResNodeData::FLAG_BILLBOARD_PARENT)) {
continue;
}
u32 bbMtxID =
mdl.GetResNode(node.ref().bbref_nodeid).GetMtxID();
math::MTX34Mult(&pCurVArray[i], &pBbMtxArray[bbMtxID],
&pModelMtxArray[baseMtx + i]);
}
}
ut::LC::StoreBlocks(&pViewPosArray[baseMtx], pCurVArray, numBlocks);
if (pViewNrmArray != NULL) {
for (u32 i = 0; i < remain; i++) {
math::MTX34& rVMtx = pCurVArray[i];
math::MTX33& rNMtx = pCurNArray[i];
u32 attr = pModelMtxAttribArray[baseMtx + i];
if (detail::WorldMtxAttr::IsAllScaleUniform(attr)) {
if (pViewTexMtxArray != NULL) {
math::MTX34Copy(&pCurTArray[i], &rVMtx);
pCurTArray[i]._03 = pCurTArray[i]._13 =
pCurTArray[i]._23 = 0.0f;
}
math::MTX34ToMTX33(&rNMtx, &rVMtx);
} else {
if (pViewTexMtxArray != NULL) {
math::MTX34InvTranspose(&pCurTArray[i], &rVMtx);
math::MTX34ToMTX33(&rNMtx, &pCurTArray[i]);
} else {
math::MTX34InvTranspose(&rNMtx, &rVMtx);
}
}
}
}
if (pViewNrmArray != NULL) {
ut::LC::StoreBlocks(&pViewNrmArray[baseMtx], pCurNArray,
numBlocksNrm);
if (pViewTexMtxArray != NULL) {
ut::LC::StoreBlocks(&pViewTexMtxArray[baseMtx], pCurTArray,
numBlocks);
}
}
std::swap(pCurMArray, pPrevMArray);
std::swap(pCurVArray, pPrevVArray);
std::swap(pCurNArray, pPrevNArray);
std::swap(pCurTArray, pPrevTArray);
}
}
} // namespace g3d
} // namespace nw4r
+345
View File
@@ -0,0 +1,345 @@
#include <nw4r/g3d.h>
#include <nw4r/math.h>
namespace nw4r {
namespace g3d {
void CalcVtx(ResMdl mdl, AnmObjShp* pAnmShp, ResVtxPosData** ppVtxPosTable,
ResVtxNrmData** ppVtxNrmTable, ResVtxClrData** ppVtxClrTable) {
// Allows struct offsets inside assembly
using nw4r::math::VEC3;
using nw4r::ut::Color;
u32 numVtxPos = mdl.GetResVtxPosNumEntries();
for (u32 id = 0; id < numVtxPos; id++) {
if (!pAnmShp->TestExistence(id)) {
continue;
}
ShpAnmResult result;
const ShpAnmResult* pResult = pAnmShp->GetResult(&result, id);
if (!(pResult->flags & ShpAnmResult::FLAG_ANM_EXISTS)) {
continue;
}
if (pResult->flags & ShpAnmResult::FLAG_ANM_VTXPOS) {
struct KeyShape {
const math::VEC3* pVtx; // at 0x0
f32 weight; // at 0x4
};
ResVtxPos basePos = pResult->baseShapeVtxSet.resVtxPos;
KeyShape keyShape[ShpAnmResult::MAX_KEY_SHAPE + 1];
int numKeyShape = 0;
ResVtxPos vtxPos(ppVtxPosTable[id]);
math::VEC3* pVtxPosBuf = static_cast<math::VEC3*>(vtxPos.GetData());
if (pResult->baseShapeWeight != 0.0f) {
const math::VEC3* pBase;
u8 stride;
basePos.GetArray(reinterpret_cast<const void**>(&pBase),
&stride);
keyShape[numKeyShape].pVtx = pBase;
keyShape[numKeyShape].weight = pResult->baseShapeWeight;
numKeyShape++;
}
for (int i = 0; i < static_cast<int>(pResult->numKeyShape); i++) {
if (pResult->keyShape[i].weight == 0.0f) {
continue;
}
ResVtxPos key(pResult->keyShape[i].vtxSet.resVtxPos);
const void* pData = key.GetData();
keyShape[numKeyShape].pVtx =
static_cast<const math::VEC3*>(pData);
keyShape[numKeyShape].weight = pResult->keyShape[i].weight;
numKeyShape++;
}
u32 numVtx = basePos.GetNumVtxPos();
// clang-format off
const math::VEC3* const pVtxPosBufEnd = reinterpret_cast<const math::VEC3*>(
reinterpret_cast<const u8*>(pVtxPosBuf) + numVtx * sizeof(math::VEC3));
// clang-format on
const KeyShape* const pKeyEnd = keyShape + numKeyShape;
for (; pVtxPosBuf < pVtxPosBufEnd; pVtxPosBuf++) {
register f32 xy, z_;
KeyShape& rFirst = keyShape[0];
register f32 firstWeight = rFirst.weight;
register const void* pVtx = rFirst.pVtx;
// clang-format off
asm {
psq_l xy, VEC3.x(pVtx), 0, 0
psq_l z_, VEC3.z(pVtx), 1, 0
ps_mul xy, xy, firstWeight
ps_mul z_, z_, firstWeight
}
// clang-format on
// clang-format off
rFirst.pVtx = reinterpret_cast<const math::VEC3*>(
reinterpret_cast<const u8*>(rFirst.pVtx) + sizeof(math::VEC3));
// clang-format on
for (KeyShape* pKey = &keyShape[1]; pKey < pKeyEnd; pKey++) {
register f32 keyWeight = pKey->weight;
register const void* pKeyVtx = pKey->pVtx;
register f32 key_xy, key_z_;
// clang-format off
asm {
psq_l key_xy, VEC3.x(pKeyVtx), 0, 0
psq_l key_z_, VEC3.z(pKeyVtx), 1, 0
ps_madd xy, key_xy, keyWeight, xy
ps_madd z_, key_z_, keyWeight, z_
}
// clang-format on
// clang-format off
pKey->pVtx = reinterpret_cast<const math::VEC3*>(
reinterpret_cast<const u8*>(pKey->pVtx) + sizeof(math::VEC3));
// clang-format on
}
register void* pDst = pVtxPosBuf;
// clang-format off
asm {
psq_st xy, VEC3.x(pDst), 0, 0
psq_st z_, VEC3.z(pDst), 1, 0
}
// clang-format on
}
DC::StoreRange(vtxPos.GetData(), numVtx * sizeof(math::VEC3));
}
if ((pResult->flags & ShpAnmResult::FLAG_ANM_VTXNRM) &&
ppVtxNrmTable != NULL) {
struct KeyShape {
const math::VEC3* pVtx; // at 0x0
f32 weight; // at 0x4
};
ResVtxNrm baseNrm = pResult->baseShapeVtxSet.resVtxNrm;
KeyShape keyShape[ShpAnmResult::MAX_KEY_SHAPE + 1];
int numKeyShape = 0;
ResVtxNrm vtxNrm(ppVtxNrmTable[baseNrm.GetID()]);
math::VEC3* pVtxNrmBuf = static_cast<math::VEC3*>(vtxNrm.GetData());
if (pResult->baseShapeWeight != 0.0f) {
const math::VEC3* pBase;
u8 stride;
baseNrm.GetArray(reinterpret_cast<const void**>(&pBase),
&stride);
keyShape[numKeyShape].pVtx = pBase;
keyShape[numKeyShape].weight = pResult->baseShapeWeight;
numKeyShape++;
}
for (int i = 0; i < static_cast<int>(pResult->numKeyShape); i++) {
if (pResult->keyShape[i].weight == 0.0f) {
continue;
}
ResVtxNrm key(pResult->keyShape[i].vtxSet.resVtxNrm);
const void* pData = key.GetData();
keyShape[numKeyShape].pVtx =
static_cast<const math::VEC3*>(pData);
keyShape[numKeyShape].weight = pResult->keyShape[i].weight;
numKeyShape++;
}
u32 numVtx = baseNrm.GetNumVtxNrm();
// clang-format off
const math::VEC3* const pVtxNrmBufEnd = reinterpret_cast<const math::VEC3*>(
reinterpret_cast<const u8*>(pVtxNrmBuf) + numVtx * sizeof(math::VEC3));
// clang-format on
const KeyShape* const pKeyEnd = keyShape + numKeyShape;
for (; pVtxNrmBuf < pVtxNrmBufEnd; pVtxNrmBuf++) {
register f32 xy, z_;
KeyShape& rFirst = keyShape[0];
register f32 firstWeight = rFirst.weight;
register const void* pVtx = rFirst.pVtx;
// clang-format off
asm {
psq_l xy, VEC3.x(pVtx), 0, 0
psq_l z_, VEC3.z(pVtx), 1, 0
ps_mul xy, xy, firstWeight
ps_mul z_, z_, firstWeight
}
// clang-format on
// clang-format off
rFirst.pVtx = reinterpret_cast<const math::VEC3*>(
reinterpret_cast<const u8*>(rFirst.pVtx) + sizeof(math::VEC3));
// clang-format on
for (KeyShape* pKey = &keyShape[1]; pKey < pKeyEnd; pKey++) {
register f32 keyWeight = pKey->weight;
register const void* pKeyVtx = pKey->pVtx;
register f32 key_xy, key_z_;
// clang-format off
asm {
psq_l key_xy, VEC3.x(pKeyVtx), 0, 0
psq_l key_z_, VEC3.z(pKeyVtx), 1, 0
ps_madd xy, key_xy, keyWeight, xy
ps_madd z_, key_z_, keyWeight, z_
}
// clang-format on
// clang-format off
pKey->pVtx = reinterpret_cast<const math::VEC3*>(
reinterpret_cast<const u8*>(pKey->pVtx) + sizeof(math::VEC3));
// clang-format on
}
register void* pDst = pVtxNrmBuf;
// clang-format off
asm {
psq_st xy, VEC3.x(pDst), 0, 0
psq_st z_, VEC3.z(pDst), 1, 0
}
// clang-format on
}
DC::StoreRange(vtxNrm.GetData(), numVtx * sizeof(math::VEC3));
}
if ((pResult->flags & ShpAnmResult::FLAG_ANM_VTXCLR) &&
ppVtxClrTable != NULL) {
struct KeyShape {
const ut::Color* pVtx; // at 0x0
f32 weight; // at 0x4
};
ResVtxClr baseClr = pResult->baseShapeVtxSet.resVtxClr;
KeyShape keyShape[ShpAnmResult::MAX_KEY_SHAPE + 1];
int numKeyShape = 0;
ResVtxClr vtxClr(ppVtxClrTable[baseClr.GetID()]);
ut::Color* pVtxClrBuf = static_cast<ut::Color*>(vtxClr.GetData());
if (pResult->baseShapeWeight != 0.0f) {
const ut::Color* pBase;
u8 stride;
baseClr.GetArray(reinterpret_cast<const void**>(&pBase),
&stride);
keyShape[numKeyShape].pVtx = pBase;
keyShape[numKeyShape].weight = pResult->baseShapeWeight;
numKeyShape++;
}
for (int i = 0; i < static_cast<int>(pResult->numKeyShape); i++) {
if (pResult->keyShape[i].weight == 0.0f) {
continue;
}
ResVtxClr key(pResult->keyShape[i].vtxSet.resVtxClr);
const void* pData = key.GetData();
keyShape[numKeyShape].pVtx =
static_cast<const ut::Color*>(pData);
keyShape[numKeyShape].weight = pResult->keyShape[i].weight;
numKeyShape++;
}
u32 numVtx = baseClr.GetNumVtxClr();
// clang-format off
const ut::Color* const pVtxClrBufEnd = reinterpret_cast<const ut::Color*>(
reinterpret_cast<const u8*>(pVtxClrBuf) + numVtx * sizeof(ut::Color));
// clang-format on
const KeyShape* const pKeyEnd = keyShape + numKeyShape;
for (; pVtxClrBuf < pVtxClrBufEnd; pVtxClrBuf++) {
register f32 rg, ba;
KeyShape& rFirst = keyShape[0];
register f32 firstWeight = rFirst.weight;
register const void* pVtx = rFirst.pVtx;
// clang-format off
asm {
psq_l rg, Color.r(pVtx), 0, 2
psq_l ba, Color.b(pVtx), 0, 2
ps_mul rg, rg, firstWeight
ps_mul ba, ba, firstWeight
}
// clang-format on
// clang-format off
rFirst.pVtx = reinterpret_cast<const ut::Color*>(
reinterpret_cast<const u8*>(rFirst.pVtx) + sizeof(ut::Color));
// clang-format on
for (KeyShape* pKey = &keyShape[1]; pKey < pKeyEnd; pKey++) {
register f32 keyWeight = pKey->weight;
register const void* pKeyVtx = pKey->pVtx;
register f32 key_rg, key_ba;
// clang-format off
asm {
psq_l key_rg, Color.r(pKeyVtx), 0, 2
psq_l key_ba, Color.b(pKeyVtx), 0, 2
ps_madd rg, key_rg, keyWeight, rg
ps_madd ba, key_ba, keyWeight, ba
}
// clang-format on
// clang-format off
pKey->pVtx = reinterpret_cast<const ut::Color*>(
reinterpret_cast<const u8*>(pKey->pVtx) + sizeof(ut::Color));
// clang-format on
}
register void* pDst = pVtxClrBuf;
// clang-format off
asm {
psq_st rg, Color.r(pDst), 0, 2
psq_st ba, Color.b(pDst), 0, 2
}
// clang-format on
}
DC::StoreRange(vtxClr.GetData(), numVtx * sizeof(ut::Color));
}
}
}
} // namespace g3d
} // namespace nw4r
+284
View File
@@ -0,0 +1,284 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
void CalcWorld(math::MTX34* pModelMtxArray, u32* pModelMtxAttribArray,
const u8* pByteCode, const math::MTX34* pBaseMtx, ResMdl mdl,
AnmObjChr* pAnmChr, FuncObjCalcWorld* pFuncObj, u32 rootAttrib) {
#define pCalcCmd reinterpret_cast<const ResByteCodeData::CalcParams*>(pByteCode)
#define pMtxDupCmd \
reinterpret_cast<const ResByteCodeData::MtxDupParams*>(pByteCode)
u8 c;
ChrAnmResult result;
const ChrAnmResult* pResult = NULL;
if (pByteCode == NULL) {
pByteCode = mdl.GetResByteCode("NodeTree");
if (pByteCode == NULL) {
return;
}
}
bool xsi = mdl.GetResMdlInfo().GetScalingRule() == SCALINGRULE_SOFTIMAGE;
bool ignoreTrans = detail::WorldMtxAttr::IsIgnoreTrans(rootAttrib);
math::VEC3* pScaleArray = detail::workmem::GetScaleTemporary();
pScaleArray[0].x = pScaleArray[0].y = pScaleArray[0].z = 1.0f;
math::MTX34Copy(pModelMtxArray, pBaseMtx);
u32* pMtxIDArray = detail::workmem::GetMtxIDTemporary();
u32 numMtxID = 0;
pModelMtxAttribArray[0] = rootAttrib;
while ((c = *pByteCode) != ResByteCodeData::END) {
if (c == ResByteCodeData::CALC) {
u32 nodeID = (pCalcCmd->nodeIdHi << 8) + pCalcCmd->nodeIdLo;
u32 parentMtxID =
(pCalcCmd->parentMtxIdHi << 8) + pCalcCmd->parentMtxIdLo;
ResNode node = mdl.GetResNode(nodeID);
u32 mtxID = node.GetMtxID();
pMtxIDArray[numMtxID++] = mtxID;
math::MTX34* pModelMtx = &pModelMtxArray[mtxID];
math::VEC3* pScale = &pScaleArray[mtxID];
math::MTX34* pParentModelMtx = &pModelMtxArray[parentMtxID];
math::VEC3* pParentScale = &pScaleArray[parentMtxID];
u32 parentAttr = pModelMtxAttribArray[parentMtxID];
if (pAnmChr != NULL) {
pResult = pAnmChr->GetResult(&result, node.GetID());
}
if (pAnmChr == NULL || pResult->flags == 0) {
node.CalcChrAnmResult(&result);
pResult = &result;
}
if (nodeID != 0 && ignoreTrans) {
if (pResult != &result) {
result = *pResult;
pResult = &result;
}
result.flags |= ChrAnmResult::FLAG_PATCH_TRANS;
node.PatchChrAnmResult(&result);
}
if (pFuncObj != NULL) {
if (pResult != &result) {
result = *pResult;
pResult = &result;
}
pFuncObj->CheckCallbackA(nodeID, &result, mdl);
}
if (xsi) {
pModelMtxAttribArray[mtxID] = detail::dcc::CalcWorldMtx_Xsi(
pModelMtx, pScale, pParentModelMtx, pParentScale,
parentAttr, pResult);
} else if (pResult->flags & ChrAnmResult::FLAG_SSC_APPLY) {
pModelMtxAttribArray[mtxID] =
detail::dcc::CalcWorldMtx_Maya_SSC_Apply(
pModelMtx, pScale, pParentModelMtx, pParentScale,
parentAttr, pResult);
} else {
pModelMtxAttribArray[mtxID] = detail::dcc::CalcWorldMtx_Basic(
pModelMtx, pScale, pParentModelMtx, pParentScale,
parentAttr, pResult);
}
pModelMtxAttribArray[mtxID] = detail::WorldMtxAttr::SetBillboard(
pModelMtxAttribArray[mtxID], node.GetBillboardMode());
if (pFuncObj != NULL) {
pFuncObj->CheckCallbackB(nodeID, pModelMtx, pScale,
&pModelMtxAttribArray[mtxID], mdl);
}
pByteCode += sizeof(ResByteCodeData::CalcParams);
} else /* Assume MTXDUP */ {
u32 toMtxID = (pMtxDupCmd->toMtxIdHi << 8) + pMtxDupCmd->toMtxIdLo;
u32 fromMtxID =
(pMtxDupCmd->fromMtxIdHi << 8) + pMtxDupCmd->fromMtxIdLo;
pMtxIDArray[numMtxID++] = toMtxID;
pModelMtxAttribArray[toMtxID] = pModelMtxAttribArray[fromMtxID];
math::MTX34Copy(&pModelMtxArray[toMtxID],
&pModelMtxArray[fromMtxID]);
pScaleArray[toMtxID] = pScaleArray[fromMtxID];
pByteCode += sizeof(ResByteCodeData::MtxDupParams);
}
}
for (u32 i = 0; i < numMtxID; i++) {
u32 mtxID = pMtxIDArray[i];
if (pScaleArray[mtxID].x == 1.0f && pScaleArray[mtxID].y == 1.0f &&
pScaleArray[mtxID].z == 1.0f) {
continue;
}
math::MTX34Scale(&pModelMtxArray[mtxID], &pModelMtxArray[mtxID],
&pScaleArray[mtxID]);
}
if (pFuncObj != NULL) {
pFuncObj->CheckCallbackC(pModelMtxArray, mdl);
}
#undef pCalcCmd
#undef pMtxDupCmd
}
void CalcWorld(math::MTX34* pModelMtxArray, u32* pModelMtxAttribArray,
const u8* pByteCode, const math::MTX34* pBaseMtx, ResMdl mdl,
AnmObjChr* pAnmChr, FuncObjCalcWorld* pFuncObj) {
CalcWorld(pModelMtxArray, pModelMtxAttribArray, pByteCode, pBaseMtx, mdl,
pAnmChr, pFuncObj, detail::WorldMtxAttr::GetRootMtxAttr());
}
void CalcSkinning(math::MTX34* pModelMtxArray, u32* pModelMtxAttribArray,
const ResMdl mdl, const u8* pByteCode) {
// Allows struct offsets inside assembly
using nw4r::math::MTX34;
#define pWeightCmd \
reinterpret_cast<const ResByteCodeData::WeightParams*>(pByteCode)
#define pWeightEntry \
reinterpret_cast<const ResByteCodeData::WeightEntry*>(pByteCode)
#define pEvpMtxCmd \
reinterpret_cast<const ResByteCodeData::EvpMtxParams*>(pByteCode)
u8 c;
if (pByteCode == NULL) {
pByteCode = mdl.GetResByteCode("NodeMix");
if (pByteCode == NULL) {
return;
}
}
math::MTX34* pSkinMtxArray = detail::workmem::GetSkinningMtxTemporary();
while ((c = *pByteCode) != ResByteCodeData::END) {
if (c == ResByteCodeData::WEIGHT) {
u32 targetMtxID = (pWeightCmd->tgtIdHi << 8) + pWeightCmd->tgtIdLo;
u32 numBlendMtx = pWeightCmd->numBlendMtx;
pModelMtxAttribArray[targetMtxID] =
detail::WorldMtxAttr::GetRootMtxAttr();
pByteCode += sizeof(ResByteCodeData::WeightParams);
register f32 M00, M02;
register f32 M10, M12;
register f32 M20, M22;
M00 = 0.0f;
// clang-format off
asm {
ps_merge00 M00, M00, M00
ps_merge00 M02, M00, M00
ps_merge00 M10, M00, M00
ps_merge00 M12, M00, M00
ps_merge00 M20, M00, M00
ps_merge00 M22, M00, M00
}
// clang-format on
for (u32 i = 0; i < numBlendMtx; i++) {
u32 mtxID =
(pWeightEntry->mtxIdHi << 8) + pWeightEntry->mtxIdLo;
u32 iraito = pWeightEntry->fWeight0 << 24 |
pWeightEntry->fWeight1 << 16 |
pWeightEntry->fWeight2 << 8 |
pWeightEntry->fWeight3;
register f32 R = *reinterpret_cast<f32*>(&iraito);
register f32 T00, T02;
register f32 T10, T12;
register f32 T20, T22;
register math::MTX34* pT = &pSkinMtxArray[mtxID];
// clang-format off
asm {
psq_l T00, MTX34._00(pT), 0, 0
psq_l T02, MTX34._02(pT), 0, 0
psq_l T10, MTX34._10(pT), 0, 0
psq_l T12, MTX34._12(pT), 0, 0
psq_l T20, MTX34._20(pT), 0, 0
psq_l T22, MTX34._22(pT), 0, 0
ps_madds0 M00, T00, R, M00
ps_madds0 M02, T02, R, M02
ps_madds0 M10, T10, R, M10
ps_madds0 M12, T12, R, M12
ps_madds0 M20, T20, R, M20
ps_madds0 M22, T22, R, M22
}
// clang-format on
pModelMtxAttribArray[targetMtxID] &=
pModelMtxAttribArray[mtxID];
pByteCode += sizeof(ResByteCodeData::WeightEntry);
}
register math::MTX34* pTargetMtx = &pModelMtxArray[targetMtxID];
// clang-format off
asm {
psq_st M00, MTX34._00(pTargetMtx), 0, 0
psq_st M02, MTX34._02(pTargetMtx), 0, 0
psq_st M10, MTX34._10(pTargetMtx), 0, 0
psq_st M12, MTX34._12(pTargetMtx), 0, 0
psq_st M20, MTX34._20(pTargetMtx), 0, 0
psq_st M22, MTX34._22(pTargetMtx), 0, 0
}
// clang-format on
} else /* Assume EVPMTX */ {
u32 mtxID = (pEvpMtxCmd->mtxIdHi << 8) + pEvpMtxCmd->mtxIdLo;
u32 nodeID = (pEvpMtxCmd->nodeIdHi << 8) + pEvpMtxCmd->nodeIdLo;
math::MTX34Mult(&pSkinMtxArray[mtxID], &pModelMtxArray[mtxID],
static_cast<const math::MTX34*>(
&mdl.GetResNode(nodeID).ref().invModelMtx));
pByteCode += sizeof(ResByteCodeData::EvpMtxParams);
}
}
#undef pWeightCmd
#undef pWeightEntry
#undef pEvpMtxCmd
}
} // namespace g3d
} // namespace nw4r
+544
View File
@@ -0,0 +1,544 @@
#include <nw4r/g3d.h>
#include <nw4r/math.h>
#include <rvl/GX.h>
#include <rvl/MTX.h>
namespace nw4r {
namespace g3d {
Camera::Camera(CameraData *pData) : ResCommon(pData) {}
void Camera::Init() {
const GXRenderModeObj *pObj = G3DState::GetRenderModeObj();
Init(pObj->fbWidth, pObj->efbHeight, pObj->fbWidth, pObj->xfbHeight, pObj->viWidth, pObj->viHeight);
}
void Camera::Init(u16 efbWidth, u16 efbHeight, u16 xfbWidth, u16 xfbHeight, u16 viWidth, u16 viHeight) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.flags = CameraData::FLAG_CAM_LOOKAT | CameraData::FLAG_PROJ_PERSP;
r.cameraPos.x = 0.0f;
r.cameraPos.y = 0.0f;
r.cameraPos.z = 15.0f;
r.cameraUp.x = 0.0f;
r.cameraUp.y = 1.0f;
r.cameraUp.z = 0.0f;
r.cameraTarget.x = 0.0f;
r.cameraTarget.y = 0.0f;
r.cameraTarget.z = 0.0f;
r.cameraRotate.x = 0.0f;
r.cameraRotate.y = 0.0f;
r.cameraRotate.z = 0.0f;
r.cameraTwist = 0.0f;
r.projType = GX_PERSPECTIVE;
r.projFovy = 60.0f;
r.projAspect = 4.0f / 3.0f;
r.projNear = 0.1f;
r.projFar = 1000.f;
r.projTop = 0.0f;
r.projBottom = static_cast<f32>(viHeight);
r.projLeft = 0.0f;
r.projRight = static_cast<f32>(viWidth);
r.lightScaleS = 0.5f;
r.lightScaleT = 0.5f;
r.lightTransS = 0.5f;
r.lightTransT = 0.5f;
r.viewportOrigin.x = 0.0f;
r.viewportOrigin.y = 0.0f;
r.viewportSize.x = static_cast<f32>(xfbWidth);
r.viewportSize.y = static_cast<f32>(xfbHeight);
r.viewportNear = 0.0f;
r.viewportFar = 1.0f;
r.scissorX = 0;
r.scissorY = 0;
r.scissorWidth = efbWidth;
r.scissorHeight = efbHeight;
r.scissorOffsetX = 0;
r.scissorOffsetY = 0;
}
void Camera::SetPosition(f32 x, f32 y, f32 z) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.cameraPos.x = x;
r.cameraPos.y = y;
r.cameraPos.z = z;
r.flags &= ~CameraData::FLAG_CAM_MTX_READY;
}
void Camera::SetPosition(const math::VEC3 &rPos) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.cameraPos = rPos;
r.flags &= ~CameraData::FLAG_CAM_MTX_READY;
}
void Camera::SetPosture(const PostureInfo &rInfo) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
switch (rInfo.tp) {
case POSTURE_LOOKAT: {
if (r.flags & CameraData::FLAG_CAM_LOOKAT) {
if (!(rInfo.cameraUp != r.cameraUp) && !(rInfo.cameraTarget != r.cameraTarget)) {
return;
}
}
r.flags &= ~(CameraData::FLAG_CAM_LOOKAT | CameraData::FLAG_CAM_ROTATE | CameraData::FLAG_CAM_AIM);
r.flags |= CameraData::FLAG_CAM_LOOKAT;
r.cameraUp = rInfo.cameraUp;
r.cameraTarget = rInfo.cameraTarget;
r.flags &= ~CameraData::FLAG_CAM_MTX_READY;
break;
}
case POSTURE_ROTATE: {
if (r.flags & CameraData::FLAG_CAM_ROTATE) {
if (!(rInfo.cameraRotate != r.cameraRotate)) {
return;
}
}
r.flags &= ~(CameraData::FLAG_CAM_LOOKAT | CameraData::FLAG_CAM_ROTATE | CameraData::FLAG_CAM_AIM);
r.flags |= CameraData::FLAG_CAM_ROTATE;
r.cameraRotate = rInfo.cameraRotate;
r.flags &= ~CameraData::FLAG_CAM_MTX_READY;
break;
}
case POSTURE_AIM: {
if (r.flags & CameraData::FLAG_CAM_AIM) {
if (!(rInfo.cameraTarget != r.cameraTarget) && rInfo.cameraTwist == r.cameraTwist) {
return;
}
}
r.flags &= ~(CameraData::FLAG_CAM_LOOKAT | CameraData::FLAG_CAM_ROTATE | CameraData::FLAG_CAM_AIM);
r.flags |= CameraData::FLAG_CAM_AIM;
r.cameraTarget = rInfo.cameraTarget;
r.cameraTwist = rInfo.cameraTwist;
r.flags &= ~CameraData::FLAG_CAM_MTX_READY;
break;
}
default: {
break;
}
}
}
void Camera::SetCameraMtxDirectly(const math::MTX34 &rMtx) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
math::MTX34Copy(&r.cameraMtx, &rMtx);
r.flags |= CameraData::FLAG_CAM_MTX_READY;
}
void Camera::SetPerspective(f32 fovy, f32 aspect, f32 near, f32 far) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.projType = GX_PERSPECTIVE;
r.projFovy = fovy;
r.projAspect = aspect;
r.projNear = near;
r.projFar = far;
r.flags &=
~(CameraData::FLAG_PROJ_FRUSTUM | CameraData::FLAG_PROJ_PERSP | CameraData::FLAG_PROJ_ORTHO |
CameraData::FLAG_PROJ_MTX_READY);
r.flags |= CameraData::FLAG_PROJ_PERSP;
}
void Camera::SetOrtho(f32 top, f32 bottom, f32 left, f32 right, f32 near, f32 far) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.projType = GX_ORTHOGRAPHIC;
r.projTop = top;
r.projBottom = bottom;
r.projLeft = left;
r.projRight = right;
r.projNear = near;
r.projFar = far;
r.flags &=
~(CameraData::FLAG_PROJ_FRUSTUM | CameraData::FLAG_PROJ_PERSP | CameraData::FLAG_PROJ_ORTHO |
CameraData::FLAG_PROJ_MTX_READY);
r.flags |= CameraData::FLAG_PROJ_ORTHO;
}
void Camera::SetProjectionMtxDirectly(const math::MTX44 *pMtx) {
if (pMtx != NULL && IsValid()) {
CameraData &r = ref();
math::MTX44Copy(&r.projMtx, pMtx);
r.flags |= CameraData::FLAG_PROJ_MTX_READY;
}
}
void Camera::SetScissor(u32 x, u32 y, u32 width, u32 height) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.scissorX = x;
r.scissorY = y;
r.scissorWidth = width;
r.scissorHeight = height;
}
void Camera::SetScissorBoxOffset(s32 ox, s32 oy) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.scissorOffsetX = ox;
r.scissorOffsetY = oy;
}
void Camera::SetViewport(f32 x, f32 y, f32 width, f32 height) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.viewportOrigin.x = x;
r.viewportOrigin.y = y;
r.viewportSize.x = width;
r.viewportSize.y = height;
SetScissor(static_cast<u32>(x), static_cast<u32>(y), static_cast<u32>(width), static_cast<u32>(height));
}
void Camera::SetViewportZRange(f32 near, f32 far) {
if (!IsValid()) {
return;
}
CameraData &r = ref();
r.viewportNear = near;
r.viewportFar = far;
}
void Camera::GetViewport(f32 *pX, f32 *pY, f32 *pWidth, f32 *pHeight, f32 *pNear, f32 *pFar) const {
if (!IsValid()) {
return;
}
const CameraData &r = ref();
if (pX != NULL) {
*pX = r.viewportOrigin.x;
}
if (pY != NULL) {
*pY = r.viewportOrigin.y;
}
if (pWidth != NULL) {
*pWidth = r.viewportSize.x;
}
if (pHeight != NULL) {
*pHeight = r.viewportSize.y;
}
if (pNear != NULL) {
*pNear = r.viewportNear;
}
if (pFar != NULL) {
*pFar = r.viewportFar;
}
}
void Camera::GetCameraMtx(math::MTX34 *pMtx) const {
if (pMtx != NULL && IsValid()) {
const CameraData &r = ref();
if (!(r.flags & CameraData::FLAG_CAM_MTX_READY)) {
UpdateCameraMtx();
}
math::MTX34Copy(pMtx, &r.cameraMtx);
}
}
void Camera::GetProjectionMtx(math::MTX44 *pMtx) const {
if (pMtx != NULL && IsValid()) {
const CameraData &r = ref();
if (!(r.flags & CameraData::FLAG_PROJ_MTX_READY)) {
UpdateProjectionMtx();
}
math::MTX44Copy(pMtx, &r.projMtx);
}
}
void Camera::GetProjectionTexMtx(math::MTX34 *pMtx) const {
if (pMtx != NULL && IsValid()) {
const CameraData &r = ref();
if (r.flags & CameraData::FLAG_PROJ_ORTHO) {
C_MTXLightOrtho(
*pMtx, r.projTop, r.projBottom, r.projLeft, r.projRight, r.lightScaleS, -r.lightScaleT, r.lightTransS,
r.lightTransT
);
} else if (r.flags & CameraData::FLAG_PROJ_FRUSTUM) {
C_MTXLightFrustum(
*pMtx, r.projTop, r.projBottom, r.projLeft, r.projRight, r.projNear, r.lightScaleS, -r.lightScaleT,
r.lightTransS, r.lightTransT
);
} else /* FLAG_PROJ_PERSP */ {
C_MTXLightPerspective(
*pMtx, r.projFovy, r.projAspect, r.lightScaleS, -r.lightScaleT, r.lightTransS, r.lightTransT
);
}
}
}
void Camera::GetEnvironmentTexMtx(math::MTX34 *pMtx) const {
if (pMtx != NULL && IsValid()) {
const CameraData &r = ref();
math::MTX34Identity(pMtx);
pMtx->_00 = r.lightScaleS;
pMtx->_03 = r.lightTransS;
pMtx->_11 = -r.lightScaleT;
pMtx->_13 = r.lightTransT;
pMtx->_22 = 0.0f;
pMtx->_23 = 1.0f;
}
}
void Camera::GXSetViewport() const {
if (!IsValid()) {
return;
}
const CameraData &r = ref();
const GXRenderModeObj *pObj = G3DState::GetRenderModeObj();
if (pObj->field_rendering) {
::GXSetViewportJitter(
r.viewportOrigin.x, r.viewportOrigin.y, r.viewportSize.x, r.viewportSize.y, r.viewportNear, r.viewportFar,
r.flags & CameraData::FLAG_VI_ODD_FIELD ? GX_FIELD_ODD : GX_FIELD_EVEN
);
} else {
::GXSetViewport(
r.viewportOrigin.x, r.viewportOrigin.y, r.viewportSize.x, r.viewportSize.y, r.viewportNear, r.viewportFar
);
}
}
void Camera::GXSetProjection() const {
if (!IsValid()) {
return;
}
const CameraData &r = ref();
if (!(r.flags & CameraData::FLAG_PROJ_MTX_READY)) {
UpdateProjectionMtx();
}
::GXSetProjection(r.projMtx, r.projType);
}
void Camera::GXSetScissor() const {
if (!IsValid()) {
return;
}
const CameraData &r = ref();
::GXSetScissor(r.scissorX, r.scissorY, r.scissorWidth, r.scissorHeight);
}
void Camera::GXSetScissorBoxOffset() const {
if (!IsValid()) {
return;
}
const CameraData &r = ref();
::GXSetScissorBoxOffset(r.scissorOffsetX, r.scissorOffsetY);
}
void Camera::UpdateCameraMtx() const {
CameraData &r = const_cast<CameraData &>(ref());
if (r.flags & CameraData::FLAG_CAM_LOOKAT) {
C_MTXLookAt(r.cameraMtx, r.cameraPos, r.cameraUp, r.cameraTarget);
} else if (r.flags & CameraData::FLAG_CAM_AIM) {
math::MTX34 &rMtx = r.cameraMtx;
math::VEC3 &rPos = r.cameraPos;
math::VEC3 &rTarget = r.cameraTarget;
math::VEC3 back(rPos.x - rTarget.x, rPos.y - rTarget.y, rPos.z - rTarget.z);
if (back.x == 0.0f && back.z == 0.0f) {
rMtx._00 = 1.0f;
rMtx._01 = 0.0f;
rMtx._02 = 0.0f;
rMtx._03 = -rPos.x;
rMtx._10 = 0.0f;
rMtx._11 = 0.0f;
rMtx._20 = 0.0f;
rMtx._22 = 0.0f;
if (back.y <= 0.0f) {
rMtx._12 = 1.0f;
rMtx._13 = -rPos.z;
rMtx._21 = -1.0f;
rMtx._23 = rPos.y;
} else {
rMtx._12 = -1.0f;
rMtx._13 = rPos.z;
rMtx._21 = 1.0f;
rMtx._23 = -rPos.y;
}
} else {
math::VEC3 _r(back.z, 0.0f, -back.x);
math::VEC3 u;
math::VEC3Normalize(&back, &back);
math::VEC3Normalize(&_r, &_r);
math::VEC3Cross(&u, &back, &_r);
f32 st, ct;
math::SinCosDeg(&st, &ct, r.cameraTwist);
math::VEC3 right, up;
right.x = st * u.x + ct * _r.x;
right.y = st * u.y;
right.z = st * u.z + ct * _r.z;
up.x = ct * u.x - st * _r.x;
up.y = ct * u.y;
up.z = ct * u.z - st * _r.z;
rMtx._00 = right.x;
rMtx._01 = right.y;
rMtx._02 = right.z;
rMtx._03 = -math::VEC3Dot(&rPos, &right);
rMtx._10 = up.x;
rMtx._11 = up.y;
rMtx._12 = up.z;
rMtx._13 = -math::VEC3Dot(&rPos, &up);
rMtx._20 = back.x;
rMtx._21 = back.y;
rMtx._22 = back.z;
rMtx._23 = -math::VEC3Dot(&rPos, &back);
}
} else /* FLAG_CAM_ROTATE */ {
math::MTX34 &rMtx = r.cameraMtx;
math::VEC3 &rPos = r.cameraPos;
f32 sx, sy, sz, cx, cy, cz;
math::SinCosDeg(&sx, &cx, r.cameraRotate.x);
math::SinCosDeg(&sy, &cy, r.cameraRotate.y);
math::SinCosDeg(&sz, &cz, r.cameraRotate.z);
math::VEC3 right, up, back;
right.x = sx * sy * sz + cy * cz;
right.y = cx * sz;
right.z = sx * cy * sz - sy * cz;
up.x = sx * sy * cz - cy * sz;
up.y = cx * cz;
up.z = sx * cy * cz + sy * sz;
back.x = cx * sy;
back.y = -sx;
back.z = cx * cy;
rMtx._00 = right.x;
rMtx._01 = right.y;
rMtx._02 = right.z;
rMtx._03 = -math::VEC3Dot(&rPos, &right);
rMtx._10 = up.x;
rMtx._11 = up.y;
rMtx._12 = up.z;
rMtx._13 = -math::VEC3Dot(&rPos, &up);
rMtx._20 = back.x;
rMtx._21 = back.y;
rMtx._22 = back.z;
rMtx._23 = -math::VEC3Dot(&rPos, &back);
}
r.flags |= CameraData::FLAG_CAM_MTX_READY;
}
void Camera::UpdateProjectionMtx() const {
CameraData &r = const_cast<CameraData &>(ref());
if (r.flags & CameraData::FLAG_PROJ_ORTHO) {
C_MTXOrtho(r.projMtx, r.projTop, r.projBottom, r.projLeft, r.projRight, r.projNear, r.projFar);
} else if (r.flags & CameraData::FLAG_PROJ_FRUSTUM) {
C_MTXFrustum(r.projMtx, r.projTop, r.projBottom, r.projLeft, r.projRight, r.projNear, r.projFar);
} else /* FLAG_PROJ_PERSP */ {
C_MTXPerspective(r.projMtx, r.projFovy, r.projAspect, r.projNear, r.projFar);
}
r.flags |= CameraData::FLAG_PROJ_MTX_READY;
}
} // namespace g3d
} // namespace nw4r
+26
View File
@@ -0,0 +1,26 @@
#include <nw4r/g3d.h>
#include <nw4r/math.h>
namespace nw4r {
namespace g3d {
void CalcTexMtx(math::MTX34* pMtx, bool set, const TexSrt& rSrt,
TexSrt::Flag flag, TexSrtTypedef::TexMatrixMode mode) {
bool ident = true;
if (mode == TexSrtTypedef::TEXMATRIXMODE_MAYA) {
ident = !detail::dcc::CalcTexMtx_Maya(pMtx, set, rSrt, flag);
} else if (mode == TexSrtTypedef::TEXMATRIXMODE_XSI) {
ident = !detail::dcc::CalcTexMtx_Xsi(pMtx, set, rSrt, flag);
} else /* TEXMATRIXMODE_3DSMAX */ {
ident = !detail::dcc::CalcTexMtx_3dsmax(pMtx, set, rSrt, flag);
}
if (ident && set) {
math::MTX34Identity(pMtx);
}
}
} // namespace g3d
} // namespace nw4r
+531
View File
@@ -0,0 +1,531 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
#include <rvl/BASE.h>
#include <algorithm>
namespace nw4r {
namespace g3d {
namespace detail {
G3DState::IndMtxOp *GetIndMtxOp(ResMat mat, ResNode node, ResShp shp) {
if (!mat.IsValid() || !shp.IsValid()) {
return NULL;
}
ResMatMisc misc = mat.GetResMatMisc();
ResMatMiscData::IndirectMethod method[GX_ITM_2 - GX_ITM_0 + 1];
s8 lightRef[GX_ITM_2 - GX_ITM_0 + 1];
misc.GetIndirectTexMtxCalcMethod(GX_ITM_0, &method[GX_ITM_0 - 1], &lightRef[GX_ITM_0 - 1]);
misc.GetIndirectTexMtxCalcMethod(GX_ITM_1, &method[GX_ITM_1 - 1], &lightRef[GX_ITM_1 - 1]);
misc.GetIndirectTexMtxCalcMethod(GX_ITM_2, &method[GX_ITM_2 - 1], &lightRef[GX_ITM_2 - 1]);
if (method[GX_ITM_0 - 1] == ResMatMiscData::WARP && method[GX_ITM_1 - 1] == ResMatMiscData::WARP &&
method[GX_ITM_2 - 1] == ResMatMiscData::WARP) {
return NULL;
}
bool nrmMtxInit = false;
math::MTX34 nrmMtx;
u32 i;
G3DState::IndMtxOp &rOp = *G3DState::GetIndMtxOp();
rOp.Reset();
for (i = 0; i < GX_ITM_2 - GX_ITM_0 + 1; i++) {
GXIndTexMtxID id = static_cast<GXIndTexMtxID>(i + 1);
if (method[i] == ResMatMiscData::WARP) {
continue;
}
if (!nrmMtxInit) {
nrmMtxInit = true;
if (shp.ptr()->curMtxIdx >= 0) {
if (shp.ptr()->curMtxIdx == node.GetMtxID()) {
const math::MTX33 *pViewNrm = G3DState::GetViewNrmMtxPtr(shp.ptr()->curMtxIdx);
nrmMtx._00 = pViewNrm->_00;
nrmMtx._01 = pViewNrm->_01;
nrmMtx._02 = pViewNrm->_02;
nrmMtx._10 = pViewNrm->_10;
nrmMtx._11 = pViewNrm->_11;
nrmMtx._12 = pViewNrm->_12;
nrmMtx._20 = pViewNrm->_20;
nrmMtx._21 = pViewNrm->_21;
nrmMtx._22 = pViewNrm->_22;
} else {
ResMdl mdl = mat.GetParent();
int shpNodeID = mdl.GetResMdlInfo().GetNodeIDFromMtxID(shp.ptr()->curMtxIdx);
ResNode shpNode = mdl.GetResNode(shpNodeID);
math::MTX34Mult(
&nrmMtx, static_cast<math::MTX34 *>(&shpNode.ref().invModelMtx),
static_cast<math::MTX34 *>(&node.ref().modelMtx)
);
const math::MTX33 *pViewNrm = G3DState::GetViewNrmMtxPtr(shp.ptr()->curMtxIdx);
// clang-format off
math::MTX34 viewNrm34(
pViewNrm->_00, pViewNrm->_01, pViewNrm->_02, 0.0f,
pViewNrm->_10, pViewNrm->_11, pViewNrm->_12, 0.0f,
pViewNrm->_20, pViewNrm->_21, pViewNrm->_22, 0.0f);
// clang-format on
math::MTX34Mult(&nrmMtx, &viewNrm34, &nrmMtx);
}
nrmMtx._03 = nrmMtx._13 = nrmMtx._23 = 0.0f;
math::VEC3 col0(nrmMtx._00, nrmMtx._10, nrmMtx._20);
math::VEC3Normalize(&col0, &col0);
nrmMtx._00 = col0.x;
nrmMtx._10 = col0.y;
nrmMtx._20 = col0.z;
math::VEC3 col1(nrmMtx._01, nrmMtx._11, nrmMtx._21);
math::VEC3Normalize(&col1, &col1);
nrmMtx._01 = col1.x;
nrmMtx._11 = col1.y;
nrmMtx._21 = col1.z;
math::VEC3 col2(nrmMtx._02, nrmMtx._12, nrmMtx._22);
math::VEC3Normalize(&col2, &col2);
nrmMtx._02 = col2.x;
nrmMtx._12 = col2.y;
nrmMtx._22 = col2.z;
} else {
math::MTX34Copy(&nrmMtx, G3DState::GetCameraMtxPtr());
}
}
const LightObj *pLight = G3DState::GetLightObj(lightRef[i]);
if (pLight != NULL && pLight->IsEnable()) {
math::VEC3 lightVec;
if (pLight->IsSpotLight()) {
pLight->GetLightDir(&lightVec);
if (lightVec.x == 0.0f && lightVec.y == 0.0f && lightVec.z == 0.0f) {
pLight->GetLightPos(&lightVec);
lightVec = -lightVec;
math::VEC3Normalize(&lightVec, &lightVec);
}
} else if (pLight->IsDiffuseLight()) {
pLight->GetLightPos(&lightVec);
lightVec = -lightVec;
math::VEC3Normalize(&lightVec, &lightVec);
} else {
math::VEC3 H;
pLight->GetLightDir(&H);
lightVec.x = -2.0f * H.z * H.x;
lightVec.y = -2.0f * H.z * H.y;
lightVec.z = -2.0f * H.z * H.z + 1.0f;
math::VEC3Normalize(&lightVec, &lightVec);
}
rOp.SetNrmMapMtx(id, &lightVec, &nrmMtx, method[i]);
} else {
rOp.SetNrmMapMtx(id, NULL, &nrmMtx, method[i]);
}
}
return &rOp;
}
} // namespace detail
namespace {
void SetupDraw1Mat1ShpSwap(Draw1Mat1ShpSwap *pSwap, DrawResMdlReplacement *pReplacement, u32 id) {
if (pReplacement->texObjDataArray != NULL) {
pSwap->texObj = ResTexObj(&pReplacement->texObjDataArray[id]);
} else {
pSwap->texObj = ResTexObj(NULL);
}
if (pReplacement->tlutObjDataArray != NULL) {
pSwap->tlutObj = ResTlutObj(&pReplacement->tlutObjDataArray[id]);
} else {
pSwap->tlutObj = ResTlutObj(NULL);
}
if (pReplacement->texSrtDataArray != NULL) {
pSwap->texSrt = ResTexSrt(&pReplacement->texSrtDataArray[id]);
} else {
pSwap->texSrt = ResTexSrt(NULL);
}
if (pReplacement->chanDataArray != NULL) {
pSwap->chan = ResMatChan(&pReplacement->chanDataArray[id]);
} else {
pSwap->chan = ResMatChan(NULL);
}
if (pReplacement->genModeDataArray != NULL) {
pSwap->genMode = ResGenMode(&pReplacement->genModeDataArray[id]);
} else {
pSwap->genMode = ResGenMode(NULL);
}
if (pReplacement->matMiscDataArray != NULL) {
pSwap->misc = ResMatMisc(&pReplacement->matMiscDataArray[id]);
} else {
pSwap->misc = ResMatMisc(NULL);
}
if (pReplacement->pixDLArray != NULL) {
pSwap->pix = ResMatPix(&pReplacement->pixDLArray[id]);
} else {
pSwap->pix = ResMatPix(NULL);
}
if (pReplacement->tevColorDLArray != NULL) {
pSwap->tevColor = ResMatTevColor(&pReplacement->tevColorDLArray[id]);
} else {
pSwap->tevColor = ResMatTevColor(NULL);
}
if (pReplacement->indMtxAndScaleDLArray != NULL) {
pSwap->indMtxAndScale = ResMatIndMtxAndScale(&pReplacement->indMtxAndScaleDLArray[id]);
} else {
pSwap->indMtxAndScale = ResMatIndMtxAndScale(NULL);
}
if (pReplacement->texCoordGenDLArray != NULL) {
pSwap->texCoordGen = ResMatTexCoordGen(&pReplacement->texCoordGenDLArray[id]);
} else {
pSwap->texCoordGen = ResMatTexCoordGen(NULL);
}
if (pReplacement->tevDataArray != NULL) {
pSwap->tev = ResTev(&pReplacement->tevDataArray[id]);
} else {
pSwap->tev = ResTev(NULL);
}
pSwap->vtxPosTable = pReplacement->vtxPosTable;
pSwap->vtxNrmTable = pReplacement->vtxNrmTable;
pSwap->vtxClrTable = pReplacement->vtxClrTable;
}
inline bool FrontToBack(const detail::workmem::MdlZ &rLhs, const detail::workmem::MdlZ &rRhs) {
if (rLhs.priority < rRhs.priority) {
return true;
}
if (rLhs.priority > rRhs.priority) {
return false;
}
if (rLhs.Z > rRhs.Z) {
return true;
}
return false;
}
inline bool BackToFront(const detail::workmem::MdlZ &rLhs, const detail::workmem::MdlZ &rRhs) {
if (rLhs.priority < rRhs.priority) {
return true;
}
if (rLhs.priority > rRhs.priority) {
return false;
}
if (rLhs.Z < rRhs.Z) {
return true;
}
if (rLhs.Z == rRhs.Z && rLhs.matID < rRhs.matID) {
return true;
}
return false;
}
void DrawResMdlLoop(const ResMdl mdl, const u8 *pByteCode, u32 drawMode) {
#define pDrawCmd reinterpret_cast<const ResByteCodeData::DrawParams *>(pByteCode)
u8 c;
ResMat mat;
ResMat prevMat;
ResShp shp;
ResNode node;
bool ignoreMat = (drawMode & RESMDL_DRAWMODE_IGNORE_MATERIAL);
u32 ctrl = DRAW1MAT1SHP_CTRL_NOPPCSYNC;
if (drawMode & RESMDL_DRAWMODE_FORCE_LIGHTOFF) {
ctrl |= DRAW1MAT1SHP_CTRL_FORCE_LIGHTOFF;
}
for (; (c = *pByteCode) != ResByteCodeData::END; pByteCode += sizeof(ResByteCodeData::DrawParams)) {
node = mdl.GetResNode(pDrawCmd->nodeIdHi << 8 | pDrawCmd->nodeIdLo);
if (!node.IsVisible()) {
continue;
}
mat = mdl.GetResMat(pDrawCmd->matIdHi << 8 | pDrawCmd->matIdLo);
shp = mdl.GetResShp(pDrawCmd->shpIdHi << 8 | pDrawCmd->shpIdLo);
Draw1Mat1ShpDirectly(
ignoreMat || mat == prevMat ? ResMat(NULL) : mat, shp, NULL, NULL, ctrl, NULL,
detail::GetIndMtxOp(mat, node, shp)
);
prevMat = mat;
}
#undef pDrawCmd
}
void DrawResMdlLoop(const ResMdl mdl, const u8 *pByteCode, DrawResMdlReplacement *pReplacement, u32 drawMode) {
#define pDrawCmd reinterpret_cast<const ResByteCodeData::DrawParams *>(pByteCode)
u8 c;
ResMat mat;
ResMat prevMat;
ResShp shp;
ResNode node;
Draw1Mat1ShpSwap swap;
bool ignoreMat = (drawMode & RESMDL_DRAWMODE_IGNORE_MATERIAL);
u32 ctrl = DRAW1MAT1SHP_CTRL_NOPPCSYNC;
if (drawMode & RESMDL_DRAWMODE_FORCE_LIGHTOFF) {
ctrl |= DRAW1MAT1SHP_CTRL_FORCE_LIGHTOFF;
}
for (; (c = *pByteCode) != ResByteCodeData::END; pByteCode += sizeof(ResByteCodeData::DrawParams)) {
node = mdl.GetResNode(pDrawCmd->nodeIdHi << 8 | pDrawCmd->nodeIdLo);
bool visible;
// @bug Replacement pointer not validated
if (pReplacement->visArray != NULL) {
visible = pReplacement->visArray[node.GetID()] != 0;
} else {
visible = node.IsVisible();
}
if (!visible) {
continue;
}
mat = mdl.GetResMat(pDrawCmd->matIdHi << 8 | pDrawCmd->matIdLo);
shp = mdl.GetResShp(pDrawCmd->shpIdHi << 8 | pDrawCmd->shpIdLo);
SetupDraw1Mat1ShpSwap(&swap, pReplacement, mat.GetID());
Draw1Mat1ShpDirectly(
ignoreMat || mat == prevMat ? ResMat(NULL) : mat, shp, NULL, NULL, ctrl, &swap,
detail::GetIndMtxOp(mat, node, shp)
);
prevMat = mat;
}
#undef pDrawCmd
}
void DrawResMdlLoop(const ResMdl mdl, const detail::workmem::MdlZ *pMdlZArray, u32 numMdlZ, u32 drawMode) {
u32 i;
ResMat mat;
ResMat prevMat;
ResShp shp;
ResNode node;
bool ignoreMat = (drawMode & RESMDL_DRAWMODE_IGNORE_MATERIAL);
u32 ctrl = DRAW1MAT1SHP_CTRL_NOPPCSYNC;
if (drawMode & RESMDL_DRAWMODE_FORCE_LIGHTOFF) {
ctrl |= DRAW1MAT1SHP_CTRL_FORCE_LIGHTOFF;
}
for (i = 0; i < numMdlZ; i++) {
const detail::workmem::MdlZ &rMdlZ = pMdlZArray[i];
mat = mdl.GetResMat(rMdlZ.matID);
shp = mdl.GetResShp(rMdlZ.shpID);
node = mdl.GetResNode(rMdlZ.nodeID);
Draw1Mat1ShpDirectly(
ignoreMat || mat == prevMat ? ResMat(NULL) : mat, shp, NULL, NULL, ctrl, NULL,
detail::GetIndMtxOp(mat, node, shp)
);
prevMat = mat;
}
}
void DrawResMdlLoop(
const ResMdl mdl, const detail::workmem::MdlZ *pMdlZArray, u32 numMdlZ, DrawResMdlReplacement *pReplacement,
u32 drawMode
) {
u32 i;
ResMat mat;
ResMat prevMat;
ResShp shp;
ResNode node;
Draw1Mat1ShpSwap swap;
bool ignoreMat = (drawMode & RESMDL_DRAWMODE_IGNORE_MATERIAL);
u32 ctrl = DRAW1MAT1SHP_CTRL_NOPPCSYNC;
if (drawMode & RESMDL_DRAWMODE_FORCE_LIGHTOFF) {
ctrl |= DRAW1MAT1SHP_CTRL_FORCE_LIGHTOFF;
}
for (i = 0; i < numMdlZ; i++) {
const detail::workmem::MdlZ &rMdlZ = pMdlZArray[i];
mat = mdl.GetResMat(rMdlZ.matID);
shp = mdl.GetResShp(rMdlZ.shpID);
node = mdl.GetResNode(rMdlZ.nodeID);
SetupDraw1Mat1ShpSwap(&swap, pReplacement, mat.GetID());
Draw1Mat1ShpDirectly(
ignoreMat || mat == prevMat ? ResMat(NULL) : mat, shp, NULL, NULL, ctrl, &swap,
detail::GetIndMtxOp(mat, node, shp)
);
prevMat = mat;
}
}
detail::workmem::MdlZ *SetUpMdlZ(
u32 *pNumMdlZ, const ResMdl mdl, const math::MTX34 *pViewPosMtxArray, const u8 *pByteCode,
DrawResMdlReplacement *pReplacement
) {
#define pDrawCmd reinterpret_cast<const ResByteCodeData::DrawParams *>(pByteCode)
u16 nodeID;
u8 c;
u32 mdlZNum = 0;
ResNode node;
u32 mtxID;
u32 viewMtxNum = mdl.GetResMdlInfo().GetNumViewMtx();
detail::workmem::MdlZ *pMdlZArray = detail::workmem::GetMdlZTemporary();
for (; (c = *pByteCode) != ResByteCodeData::END; pByteCode += sizeof(ResByteCodeData::DrawParams)) {
nodeID = pDrawCmd->nodeIdHi << 8 | pDrawCmd->nodeIdLo;
node = mdl.GetResNode(nodeID);
bool visible;
if (pReplacement == NULL || pReplacement->visArray == NULL) {
visible = node.IsVisible();
} else {
visible = pReplacement->visArray[node.GetID()] != 0;
}
if (!visible) {
continue;
}
detail::workmem::MdlZ &rMdlZ = pMdlZArray[mdlZNum];
rMdlZ.nodeID = nodeID;
rMdlZ.matID = pDrawCmd->matIdHi << 8 | pDrawCmd->matIdLo;
rMdlZ.shpID = pDrawCmd->shpIdHi << 8 | pDrawCmd->shpIdLo;
// @bug Matrix ID not validated
mtxID = node.GetMtxID();
rMdlZ.Z = pViewPosMtxArray[mtxID]._23;
rMdlZ.priority = pDrawCmd->priority;
mdlZNum++;
}
*pNumMdlZ = mdlZNum;
return pMdlZArray;
#undef pDrawCmd
}
} // namespace
void DrawResMdlDirectly(
const ResMdl mdl, const math::MTX34 *pViewPosMtxArray, const math::MTX33 *pViewNrmMtxArray,
const math::MTX34 *pViewEnvMtxArray, const u8 *pByteCodeOpa, const u8 *pByteCodeXlu,
DrawResMdlReplacement *pReplacement, u32 drawMode
) {
G3DState::SetViewPosNrmMtxArray(pViewPosMtxArray, pViewNrmMtxArray, pViewEnvMtxArray);
if (!(drawMode & RESMDL_DRAWMODE_NOPPCSYNC)) {
ut::LC::QueueWait(0);
PPCSync();
}
if (pByteCodeOpa != NULL) {
if (drawMode & RESMDL_DRAWMODE_SORT_OPA_Z) {
u32 numMdlZ;
detail::workmem::MdlZ *pMdlZArray = SetUpMdlZ(&numMdlZ, mdl, pViewPosMtxArray, pByteCodeOpa, pReplacement);
std::sort(pMdlZArray, pMdlZArray + numMdlZ, FrontToBack);
if (pReplacement != NULL) {
DrawResMdlLoop(mdl, pMdlZArray, numMdlZ, pReplacement, drawMode);
} else {
DrawResMdlLoop(mdl, pMdlZArray, numMdlZ, drawMode);
}
} else if (pReplacement != NULL) {
DrawResMdlLoop(mdl, pByteCodeOpa, pReplacement, drawMode);
} else {
DrawResMdlLoop(mdl, pByteCodeOpa, drawMode);
}
}
if (pByteCodeXlu != NULL) {
if (drawMode & RESMDL_DRAWMODE_SORT_XLU_Z) {
u32 numMdlZ;
detail::workmem::MdlZ *pMdlZArray = SetUpMdlZ(&numMdlZ, mdl, pViewPosMtxArray, pByteCodeXlu, pReplacement);
std::sort(pMdlZArray, pMdlZArray + numMdlZ, BackToFront);
if (pReplacement != NULL) {
DrawResMdlLoop(mdl, pMdlZArray, numMdlZ, pReplacement, drawMode);
} else {
DrawResMdlLoop(mdl, pMdlZArray, numMdlZ, drawMode);
}
} else if (pReplacement != NULL) {
DrawResMdlLoop(mdl, pByteCodeXlu, pReplacement, drawMode);
} else {
DrawResMdlLoop(mdl, pByteCodeXlu, drawMode);
}
}
G3DState::SetViewPosNrmMtxArray(NULL, NULL, NULL);
}
} // namespace g3d
} // namespace nw4r
+175
View File
@@ -0,0 +1,175 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
#include <rvl/BASE.h>
#include <rvl/GX.h>
namespace nw4r {
namespace g3d {
void Draw1Mat1ShpDirectly(
ResMat mat, ResShp shp, const math::MTX34 *pViewPos, const math::MTX34 *pViewNrm, u32 ctrl, Draw1Mat1ShpSwap *pSwap,
G3DState::IndMtxOp *pIndMtxOp
) {
if (!(ctrl & DRAW1MAT1SHP_CTRL_NOPPCSYNC)) {
ut::LC::QueueWait(0);
PPCSync();
}
if (mat.IsValid()) {
ResMatMisc misc;
if (pSwap == NULL || !pSwap->misc.IsValid()) {
misc = mat.GetResMatMisc();
} else {
misc = pSwap->misc;
}
int fogID = misc.GetFogIdx();
G3DState::LoadFog(fogID);
G3DState::LoadResMatMisc(misc);
if (pSwap == NULL || !pSwap->tlutObj.IsValid()) {
G3DState::LoadResTlutObj(mat.GetResTlutObj());
} else {
G3DState::LoadResTlutObj(pSwap->tlutObj);
}
if (pSwap == NULL || !pSwap->texObj.IsValid()) {
G3DState::LoadResTexObj(mat.GetResTexObj());
} else {
G3DState::LoadResTexObj(pSwap->texObj);
}
if (pSwap == NULL || !pSwap->genMode.IsValid()) {
G3DState::LoadResGenMode(mat.GetResGenMode());
} else {
G3DState::LoadResGenMode(pSwap->genMode);
}
if (pSwap == NULL || !pSwap->tev.IsValid()) {
G3DState::LoadResTev(mat.GetResTev());
} else {
G3DState::LoadResTev(pSwap->tev);
}
if (pSwap == NULL || !pSwap->pix.IsValid()) {
G3DState::LoadResMatPix(mat.GetResMatPix());
} else {
G3DState::LoadResMatPix(pSwap->pix);
}
if (pSwap == NULL || !pSwap->tevColor.IsValid()) {
G3DState::LoadResMatTevColor(mat.GetResMatTevColor());
} else {
G3DState::LoadResMatTevColor(pSwap->tevColor);
}
if (pSwap == NULL || !pSwap->indMtxAndScale.IsValid()) {
if (pIndMtxOp != NULL) {
G3DState::LoadResMatIndMtxAndScale(mat.GetResMatIndMtxAndScale(), *pIndMtxOp);
} else {
G3DState::LoadResMatIndMtxAndScale(mat.GetResMatIndMtxAndScale());
}
} else {
if (pIndMtxOp != NULL) {
G3DState::LoadResMatIndMtxAndScale(pSwap->indMtxAndScale, *pIndMtxOp);
} else {
G3DState::LoadResMatIndMtxAndScale(pSwap->indMtxAndScale);
}
}
u32 diffColorMask, diffAlphaMask;
u32 specColorMask, specAlphaMask;
GXColor ambColor;
AmbLightObj ambLight;
G3DState::LoadLightSet(
misc.GetLightSetIdx(), &diffColorMask, &diffAlphaMask, &specColorMask, &specAlphaMask, &ambLight
);
ambColor.r = ambLight.r;
ambColor.g = ambLight.g;
ambColor.b = ambLight.b;
ambColor.a = ambLight.a;
if (pSwap == NULL || !pSwap->chan.IsValid()) {
G3DState::LoadResMatChan(
mat.GetResMatChan(), diffColorMask, diffAlphaMask, specColorMask, specAlphaMask, ambColor,
(ctrl & DRAW1MAT1SHP_CTRL_FORCE_LIGHTOFF) ? true : false
);
} else {
G3DState::LoadResMatChan(
pSwap->chan, diffColorMask, diffAlphaMask, specColorMask, specAlphaMask, ambColor,
(ctrl & DRAW1MAT1SHP_CTRL_FORCE_LIGHTOFF) ? true : false
);
}
if (pSwap == NULL || !pSwap->texCoordGen.IsValid()) {
G3DState::LoadResMatTexCoordGen(mat.GetResMatTexCoordGen());
} else {
G3DState::LoadResMatTexCoordGen(pSwap->texCoordGen);
}
if (pSwap == NULL || !pSwap->texSrt.IsValid()) {
G3DState::LoadResTexSrt(mat.GetResTexSrt());
} else {
G3DState::LoadResTexSrt(pSwap->texSrt);
}
} else if (pIndMtxOp != NULL) {
if (pSwap == NULL || !pSwap->indMtxAndScale.IsValid()) {
G3DState::IndTexMtxInfo info;
(*pIndMtxOp)(&info);
info.FifoSend();
} else {
G3DState::LoadResMatIndMtxAndScale(pSwap->indMtxAndScale, *pIndMtxOp);
}
}
if (shp.IsValid() && shp.IsVisible()) {
if (!(ctrl & DRAW1MAT1SHP_CTRL_NOSWAPSHP)) {
G3DState::LoadResShpPrePrimitive(shp);
if (pSwap != NULL) {
if (pSwap->vtxPosTable != NULL) {
ResVtxPos(pSwap->vtxPosTable[shp.ref().idVtxPosition]).SetArray();
}
if (pSwap->vtxNrmTable != NULL) {
int nrmID = shp.ref().idVtxNormal;
if (nrmID >= 0) {
ResVtxNrm(pSwap->vtxNrmTable[nrmID]).SetArray();
}
}
if (pSwap->vtxClrTable != NULL) {
int clrID = shp.ref().idVtxColor[0];
if (clrID >= 0) {
ResVtxClr(pSwap->vtxClrTable[clrID]).SetArray(GX_VA_CLR0);
}
clrID = shp.ref().idVtxColor[1];
if (clrID >= 0) {
ResVtxClr(pSwap->vtxClrTable[clrID]).SetArray(GX_VA_CLR1);
}
}
}
}
if (ctrl & DRAW1MAT1SHP_CTRL_CULL_FRONT) {
fifo::GDSetCullMode(GX_CULL_FRONT);
G3DState::Invalidate(G3DState::INVALIDATE_SHP);
}
G3DState::LoadResShpPrimitive(shp, pViewPos, pViewNrm);
}
}
} // namespace g3d
} // namespace nw4r
+94
View File
@@ -0,0 +1,94 @@
#include <nw4r/g3d.h>
#include <rvl/GX.h>
namespace nw4r {
namespace g3d {
Fog::Fog(FogData *pData) : ResCommon(pData) {}
void Fog::Init() {
if (!IsValid()) {
return;
}
FogData &r = ref();
r.type = GX_FOG_NONE;
r.startz = 0.0f;
r.endz = 0.0f;
r.nearz = 0.0f;
r.farz = 0.0f;
r.color.r = r.color.g = r.color.b = r.color.a = 0;
r.adjEnable = FALSE;
r.PADDING_0x19 = 0;
r.adjCenter = 0;
for (int i = 0; i < GX_FOG_ADJ_TABLE_SZ; i++) {
r.adjTable.r[i] = 0;
}
}
Fog Fog::CopyTo(register void *pDst) const {
if (pDst != NULL && IsValid()) {
register const FogData *pSrc = ptr();
register f64 work0, work1, work2, work3, work4, work5;
// clang-format off
asm {
lfd work0, 0(pSrc)
stfd work0, 0(pDst)
lfd work1, 8(pSrc)
stfd work1, 8(pDst)
lfd work2, 16(pSrc)
stfd work2, 16(pDst)
lfd work3, 24(pSrc)
stfd work3, 24(pDst)
lfd work4, 32(pSrc)
stfd work4, 32(pDst)
lfd work5, 40(pSrc)
stfd work5, 40(pDst)
}
// clang-format on
return Fog(static_cast<FogData *>(pDst));
}
return Fog(NULL);
}
void Fog::SetFogRangeAdjParam(u16 width, u16 center, const math::MTX44 &rProjMtx) {
if (!IsValid()) {
return;
}
FogData &r = ref();
r.adjCenter = center;
GXInitFogAdjTable(&r.adjTable, width, rProjMtx);
}
void Fog::SetGP() const {
if (!IsValid()) {
return;
}
const FogData &r = ref();
if (r.type != GX_FOG_NONE) {
GXSetFogRangeAdj(r.adjEnable, r.adjCenter, &r.adjTable);
}
GXSetFog(r.type, r.color, r.startz, r.endz, r.nearz, r.farz);
}
} // namespace g3d
} // namespace nw4r
+65
View File
@@ -0,0 +1,65 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
#include <rvl/GX.h>
#include <rvl/OS.h>
#include <rvl/VI.h>
namespace {
NW4R_LIB_VERSION(G3D, "Jun 8 2007", "11:16:25", "0x4199_60831");
} // namespace
namespace nw4r {
namespace g3d {
void G3dInit(bool enableLockedCache) {
OSRegisterVersion(NW4R_G3D_Version_);
if (enableLockedCache) {
ut::LC::Enable();
} else {
ut::LC::Disable();
}
InitFastCast();
GXRenderModeObj *pMode;
switch (VIGetTvFormat()) {
case VI_TV_FMT_NTSC: {
pMode = &GXNtsc480IntDf;
break;
}
case VI_TV_FMT_PAL: {
pMode = &GXPal528IntDf;
break;
}
case VI_TV_FMT_EURGB60: {
pMode = &GXEurgb60Hz480IntDf;
break;
}
case VI_TV_FMT_MPAL: {
pMode = &GXMpal480IntDf;
break;
}
default: {
pMode = &GXNtsc480IntDf;
break;
}
}
G3DState::SetRenderModeObj(*pMode);
}
void G3dReset() {
G3DState::Invalidate();
}
} // namespace g3d
} // namespace nw4r
+262
View File
@@ -0,0 +1,262 @@
#include <nw4r/g3d.h>
#include <nw4r/math.h>
#include <algorithm>
namespace nw4r {
namespace g3d {
/******************************************************************************
*
* LightObj
*
******************************************************************************/
LightObj& LightObj::operator=(const LightObj& rOther) {
if (this != &rOther) {
mFlag = rOther.mFlag;
detail::Copy32ByteBlocks(&mObj, &rOther.mObj, sizeof(GXLightObj));
}
return *this;
}
void LightObj::Clear() {
mFlag = 0;
detail::ZeroMemory32ByteBlocks(&mObj, sizeof(GXLightObj));
}
void LightObj::InitLightColor(GXColor color) {
GXInitLightColor(&mObj, color);
}
void LightObj::InitLightPos(f32 x, f32 y, f32 z) {
GXInitLightPos(&mObj, x, y, z);
mFlag &= ~FLAG_SPECULAR;
}
void LightObj::InitLightDir(f32 nx, f32 ny, f32 nz) {
GXInitLightDir(&mObj, nx, ny, nz);
mFlag &= ~FLAG_SPECULAR;
mFlag |= FLAG_SPOT;
}
void LightObj::InitSpecularDir(f32 nx, f32 ny, f32 nz) {
GXInitLightDir(&mObj, nx, ny, nz);
mFlag &= ~FLAG_SPOT;
mFlag |= FLAG_SPECULAR;
mFlag |= FLAG_SPECULAR_DIR;
}
void LightObj::InitLightSpot(f32 cutoff, GXSpotFn spotFn) {
GXInitLightSpot(&mObj, cutoff, spotFn);
mFlag &= ~FLAG_SPECULAR;
mFlag |= FLAG_SPOT;
}
void LightObj::InitLightAttnA(f32 aa, f32 ab, f32 ac) {
GXInitLightAttnA(&mObj, aa, ab, ac);
mFlag &= ~FLAG_SPECULAR;
mFlag |= FLAG_SPOT;
}
void LightObj::InitLightDistAttn(f32 distance, f32 brightness,
GXDistAttnFn distAttnFn) {
GXInitLightDistAttn(&mObj, distance, brightness, distAttnFn);
mFlag &= ~FLAG_SPECULAR;
mFlag |= FLAG_SPOT;
}
void LightObj::InitLightAttnK(f32 ka, f32 kb, f32 kc) {
GXInitLightAttnK(&mObj, ka, kb, kc);
mFlag &= ~FLAG_SPECULAR;
mFlag |= FLAG_SPOT;
}
void LightObj::InitLightShininess(f32 shininess) {
GXInitLightAttn(&mObj, 0.0f, 0.0f, 1.0f, shininess / 2.0f, 0.0f,
1.0f - shininess / 2.0f);
mFlag &= ~FLAG_SPOT;
mFlag |= FLAG_SPECULAR;
}
void LightObj::GetLightPos(math::VEC3* pPos) const {
if (!pPos) {
return;
}
GXGetLightPos(&mObj, &pPos->x, &pPos->y, &pPos->z);
}
void LightObj::GetLightDir(math::VEC3* pDir) const {
if (!pDir) {
return;
}
GXGetLightDir(&mObj, &pDir->x, &pDir->y, &pDir->z);
}
void LightObj::ApplyViewMtx(const math::MTX34& rCamera) {
math::VEC3 dir;
GetLightDir(&dir);
math::VEC3TransformNormal(&dir, &rCamera, &dir);
if (IsSpecularDir()) {
GXInitSpecularDir(&mObj, dir.x, dir.y, dir.z);
} else {
math::VEC3 pos;
GetLightPos(&pos);
math::VEC3Transform(&pos, &rCamera, &pos);
GXInitLightPos(&mObj, pos.x, pos.y, pos.z);
GXInitLightDir(&mObj, dir.x, dir.y, dir.z);
}
}
/******************************************************************************
*
* LightSetting
*
******************************************************************************/
LightSetting::LightSetting(LightObj* pLightObjArray,
AmbLightObj* pAmbLightObjArray, u32 numLight,
LightSetData* pLightSetDataArray, u32 numLightSet)
: mNumLight(numLight),
mNumLightSet(numLightSet),
mpLightObjArray(pLightObjArray),
mpAmbLightObjArray(pAmbLightObjArray),
mpLightSetDataArray(pLightSetDataArray) {
for (u32 i = 0; i < mNumLightSet; i++) {
LightSetData& rData = mpLightSetDataArray[i];
rData.idxAmbLight = -1;
for (u32 j = 0; j < G3DState::NUM_LIGHT_IN_LIGHT_SET; j++) {
rData.idxLight[j] = -1;
}
}
mpLightSetDataArray[0].idxLight[0] = 0;
mpLightSetDataArray[0].idxLight[1] = 2;
mpLightSetDataArray[0].idxAmbLight = -1;
GXColor white = {255, 255, 255, 255};
AmbLightObj ambWhite = {255, 255, 255, 255};
LightObj lobj0, lobj1, lobj2, lobj3;
lobj0.Clear();
lobj1.Clear();
lobj2.Clear();
lobj3.Clear();
lobj0.InitLightColor(white);
lobj0.InitLightPos(4000000.0f, 4000000.0f, 4000000.0f);
lobj0.InitLightDir(0.0f, -1.0f, 0.0f);
lobj0.InitLightSpot(90.0f, GX_SP_OFF);
lobj0.InitLightDistAttn(10.0f, 0.5f, GX_DA_OFF);
lobj0.Enable();
lobj1.InitLightColor(white);
lobj1.InitLightPos(4000000.0f, 4000000.0f, 4000000.0f);
lobj1.Enable();
lobj2.InitLightColor(white);
lobj2.InitLightPos(4000000.0f, 4000000.0f, 4000000.0f);
lobj2.InitSpecularDir(0.0f, -1.0f, 0.0f);
lobj2.InitLightShininess(16.0f);
lobj2.Enable();
lobj3.Disable();
if (mNumLight > 0) {
mpLightObjArray[0] = lobj0;
mpAmbLightObjArray[0] = ambWhite;
}
if (mNumLight > 1) {
mpLightObjArray[1] = lobj1;
mpAmbLightObjArray[1] = ambWhite;
}
if (mNumLight > 2) {
mpLightObjArray[2] = lobj2;
mpAmbLightObjArray[2] = ambWhite;
}
for (u32 i = 3; i < mNumLight; i++) {
mpLightObjArray[i] = lobj3;
mpAmbLightObjArray[i] = ambWhite;
}
}
bool LightSetting::Import(const LightSetting& rSetting) {
if (mNumLight < rSetting.mNumLight ||
mNumLightSet < rSetting.mNumLightSet) {
return false;
}
for (u32 i = 0; i < rSetting.mNumLight; i++) {
if (rSetting.mpLightObjArray[i].IsEnable()) {
mpLightObjArray[i] = rSetting.mpLightObjArray[i];
} else {
mpLightObjArray[i].Disable();
}
mpAmbLightObjArray[i] = rSetting.mpAmbLightObjArray[i];
}
for (u32 i = 0; i < rSetting.mNumLightSet; i++) {
mpLightSetDataArray[i] = rSetting.mpLightSetDataArray[i];
}
return true;
}
void LightSetting::ApplyViewMtx(const math::MTX34& rCamera, u32 numLight) {
numLight = std::max<u32>(numLight, mNumLight);
for (u32 i = 0; i < numLight; i++) {
if (mpLightObjArray[i].IsEnable()) {
mpLightObjArray[i].ApplyViewMtx(rCamera);
}
}
}
/******************************************************************************
*
* LightSet
*
******************************************************************************/
bool LightSet::SelectLightObj(u32 lightIdx, int lightObjIdx) {
if (IsValid() && lightIdx < G3DState::NUM_LIGHT_IN_LIGHT_SET) {
if (lightObjIdx < 0) {
mpLightSetData->idxLight[lightIdx] = -1;
return true;
}
if (lightObjIdx < static_cast<int>(mpSetting->GetNumLightObj())) {
mpLightSetData->idxLight[lightIdx] = lightObjIdx;
return true;
}
}
return false;
}
bool LightSet::SelectAmbLightObj(int lightObjIdx) {
if (IsValid()) {
if (lightObjIdx < 0) {
mpLightSetData->idxAmbLight = -1;
return true;
}
if (lightObjIdx < static_cast<int>(mpSetting->GetNumLightObj())) {
mpLightSetData->idxAmbLight = lightObjIdx;
return true;
}
}
return false;
}
} // namespace g3d
} // namespace nw4r
+382
View File
@@ -0,0 +1,382 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace detail {
namespace dcc {
namespace {
void MakeTexSrtMtx_S(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 = rSrt.Su;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = 0.0f;
pMtx->_10 = 0.0f;
pMtx->_11 = rSrt.Sv;
pMtx->_12 = 0.0f;
pMtx->_13 = 1.0f - rSrt.Sv;
}
void MakeTexSrtMtx_R(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sinPart = 0.5f * sinR;
f32 cosPart = 0.5f - 0.5f * cosR;
pMtx->_00 = cosR;
pMtx->_01 = sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = cosPart - sinPart;
pMtx->_10 = -sinR;
pMtx->_11 = cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = cosPart + sinPart;
}
void MakeTexSrtMtx_T(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 = 1.0f;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = -rSrt.Tu;
pMtx->_10 = 0.0f;
pMtx->_11 = 1.0f;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Tv;
}
void MakeTexSrtMtx_SR(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
pMtx->_00 = sucr;
pMtx->_01 = susr;
pMtx->_02 = 0.0f;
pMtx->_03 = -0.5f * (susr + sucr - rSrt.Su);
pMtx->_10 = -svsr;
pMtx->_11 = svcr;
pMtx->_12 = 0.0f;
pMtx->_13 = 0.5f * (svsr - svcr - rSrt.Sv) + 1.0f;
}
void MakeTexSrtMtx_RT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sinPart = 0.5f * sinR;
f32 cosPart = 0.5f - 0.5f * cosR;
pMtx->_00 = cosR;
pMtx->_01 = sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = cosPart - sinPart - rSrt.Tu;
pMtx->_10 = -sinR;
pMtx->_11 = cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = cosPart + sinPart + rSrt.Tv;
}
void MakeTexSrtMtx_ST(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 = rSrt.Su;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = -rSrt.Su * rSrt.Tu;
pMtx->_10 = 0.0f;
pMtx->_11 = rSrt.Sv;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Sv * (rSrt.Tv - 1.0f) + 1.0f;
}
void MakeTexSrtMtx_SRT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sinPart = 0.5f * sinR - 0.5f;
f32 cosPart = -0.5f * cosR;
pMtx->_00 = rSrt.Su * cosR;
pMtx->_01 = rSrt.Su * sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = rSrt.Su * (cosPart - sinPart - rSrt.Tu);
pMtx->_10 = -rSrt.Sv * sinR;
pMtx->_11 = rSrt.Sv * cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Sv * (cosPart + sinPart + rSrt.Tv) + 1.0f;
}
void ProductTexSrtMtx_S(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 *= rSrt.Su;
pMtx->_01 *= rSrt.Su;
pMtx->_02 *= rSrt.Su;
pMtx->_03 *= rSrt.Su;
pMtx->_10 *= rSrt.Sv;
pMtx->_11 *= rSrt.Sv;
pMtx->_12 *= rSrt.Sv;
pMtx->_13 = 1.0f + pMtx->_13 * rSrt.Sv - rSrt.Sv;
}
void ProductTexSrtMtx_R(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sinPart = 0.5f * sinR;
f32 cosPart = 0.5f - 0.5f * cosR;
_0x = cosR * pMtx->_00 + sinR * pMtx->_10;
_1x = -sinR * pMtx->_00 + cosR * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = cosR * pMtx->_01 + sinR * pMtx->_11;
_1x = -sinR * pMtx->_01 + cosR * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = cosR * pMtx->_02 + sinR * pMtx->_12;
_1x = -sinR * pMtx->_02 + cosR * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = cosR * pMtx->_03 + sinR * pMtx->_13 + cosPart - sinPart;
_1x = -sinR * pMtx->_03 + cosR * pMtx->_13 + cosPart + sinPart;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_T(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_03 += -rSrt.Tu;
pMtx->_13 += rSrt.Tv;
}
void ProductTexSrtMtx_SR(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
_0x = sucr * pMtx->_00 + susr * pMtx->_10;
_1x = -svsr * pMtx->_00 + svcr * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = sucr * pMtx->_01 + susr * pMtx->_11;
_1x = -svsr * pMtx->_01 + svcr * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = sucr * pMtx->_02 + susr * pMtx->_12;
_1x = -svsr * pMtx->_02 + svcr * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
// clang-format off
_0x = sucr * (pMtx->_03 - 0.5f)
+ susr * (pMtx->_13 - 0.5f)
+ 0.5f * rSrt.Su;
_1x = -svsr * (pMtx->_03 - 0.5f)
+ svcr * (pMtx->_13 - 0.5f)
- 0.5f * rSrt.Sv + 1.0f;
// clang-format on
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_RT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sinPart = 0.5f * sinR - 0.5f;
f32 cosPart = -0.5f * cosR;
_0x = cosR * pMtx->_00 + sinR * pMtx->_10;
_1x = -sinR * pMtx->_00 + cosR * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = cosR * pMtx->_01 + sinR * pMtx->_11;
_1x = -sinR * pMtx->_01 + cosR * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = cosR * pMtx->_02 + sinR * pMtx->_12;
_1x = -sinR * pMtx->_02 + cosR * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = cosR * pMtx->_03 + sinR * pMtx->_13 + cosPart - sinPart - rSrt.Tu;
_1x = -sinR * pMtx->_03 + cosR * pMtx->_13 + cosPart + sinPart + rSrt.Tv;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_ST(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 *= rSrt.Su;
pMtx->_01 *= rSrt.Su;
pMtx->_02 *= rSrt.Su;
pMtx->_03 = rSrt.Su * (pMtx->_03 - rSrt.Tu);
pMtx->_10 *= rSrt.Sv;
pMtx->_11 *= rSrt.Sv;
pMtx->_12 *= rSrt.Sv;
pMtx->_13 = rSrt.Sv * (pMtx->_13 + rSrt.Tv - 1.0f) + 1.0f;
}
void ProductTexSrtMtx_SRT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
_0x = sucr * pMtx->_00 + susr * pMtx->_10;
_1x = -svsr * pMtx->_00 + svcr * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = sucr * pMtx->_01 + susr * pMtx->_11;
_1x = -svsr * pMtx->_01 + svcr * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = sucr * pMtx->_02 + susr * pMtx->_12;
_1x = -svsr * pMtx->_02 + svcr * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = sucr * (pMtx->_03 - 0.5f) + susr * (pMtx->_13 - 0.5f) +
(0.5f - rSrt.Tu) * rSrt.Su;
_1x = -svsr * (0.5f + pMtx->_03) + svcr * (pMtx->_13 - 0.5f) -
(0.5f - rSrt.Tv) * rSrt.Sv + 1.0f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
} // namespace
typedef void (*CalcTexMtxFunc)(math::MTX34* pMtx, const TexSrt& rSrt);
bool CalcTexMtx_Maya(math::MTX34* pMtx, bool set, const TexSrt& rSrt,
TexSrt::Flag flag) {
// Extract S/R/T flags
u32 index = flag >> 1 & 0b111;
// Scale-one, no rotate/trans
if (index == 0b111) {
return false;
}
if (set) {
static const CalcTexMtxFunc funcTable[] = {
MakeTexSrtMtx_SRT, // 0 0 0
MakeTexSrtMtx_RT, // 0 0 1
MakeTexSrtMtx_ST, // 0 1 0
MakeTexSrtMtx_T, // 0 1 1
MakeTexSrtMtx_SR, // 1 0 0
MakeTexSrtMtx_R, // 1 0 1
MakeTexSrtMtx_S // 1 1 0
};
funcTable[index](pMtx, rSrt);
} else {
static const CalcTexMtxFunc funcTable[] = {
ProductTexSrtMtx_SRT, // 0 0 0
ProductTexSrtMtx_RT, // 0 0 1
ProductTexSrtMtx_ST, // 0 1 0
ProductTexSrtMtx_T, // 0 1 1
ProductTexSrtMtx_SR, // 1 0 0
ProductTexSrtMtx_R, // 1 0 1
ProductTexSrtMtx_S // 1 1 0
};
funcTable[index](pMtx, rSrt);
}
pMtx->_20 = 0.0f;
pMtx->_21 = 0.0f;
pMtx->_22 = 1.0f;
pMtx->_23 = 0.0f;
return true;
}
u32 CalcWorldMtx_Maya_SSC_Apply(math::MTX34* pW, math::VEC3* pS,
const math::MTX34* pW1, const math::VEC3* pS1,
u32 attr, const ChrAnmResult* pResult) {
u32 flag = pResult->flags;
u32 newAttr = attr;
if (flag & ChrAnmResult::FLAG_SCALE_ONE) {
newAttr = detail::WorldMtxAttr::AnmScaleOne(newAttr);
pS->x = pS->y = pS->z = 1.0f;
} else {
newAttr = detail::WorldMtxAttr::AnmNotScaleOne(newAttr);
*pS = pResult->s;
}
if ((flag & ChrAnmResult::FLAG_MTX_IDENT) ||
(flag & ChrAnmResult::FLAG_ROT_TRANS_ZERO)) {
math::MTX34Copy(pW, pW1);
} else if (flag & ChrAnmResult::FLAG_ROT_ZERO) {
if (detail::WorldMtxAttr::IsScaleOne(attr)) {
math::VEC3 trans(pResult->rt._03, pResult->rt._13, pResult->rt._23);
math::MTX34Trans(pW, pW1, &trans);
} else {
math::VEC3 trans(pS1->x * pResult->rt._03, pS1->y * pResult->rt._13,
pS1->z * pResult->rt._23);
math::MTX34Trans(pW, pW1, &trans);
}
} else if (detail::WorldMtxAttr::IsScaleOne(attr)) {
math::MTX34Mult(pW, pW1, &pResult->rt);
} else {
math::MTX34Copy(pW, &pResult->rt);
pW->_03 *= pS1->x;
pW->_13 *= pS1->y;
pW->_23 *= pS1->z;
math::MTX34Mult(pW, pW1, pW);
}
if (flag & ChrAnmResult::FLAG_SCALE_UNIFORM) {
newAttr = detail::WorldMtxAttr::AnmScaleUniform(newAttr);
} else {
newAttr = detail::WorldMtxAttr::AnmNotScaleUniform(newAttr);
}
return newAttr;
}
} // namespace dcc
} // namespace detail
} // namespace g3d
} // namespace nw4r
+28
View File
@@ -0,0 +1,28 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(G3dObj);
G3dObj::~G3dObj() {
Dealloc(mpHeap, this);
}
void G3dObj::Destroy() {
G3dObj* pParent = GetParent();
if (pParent != NULL) {
pParent->G3dProc(G3DPROC_CHILD_DETACHED, 0, this);
}
delete this;
}
// clang-format off
DECOMP_FORCEACTIVE(g3d_obj_cpp,
G3dObj::IsDerivedFrom);
// clang-format on
} // namespace g3d
} // namespace nw4r
File diff suppressed because it is too large Load Diff
+9
View File
@@ -0,0 +1,9 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(ScnMdl1Mat1Shp);
} // namespace g3d
} // namespace nw4r
+897
View File
@@ -0,0 +1,897 @@
#include <nw4r/g3d.h>
#include <nw4r/ut.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(ScnMdlSimple);
ScnMdlSimple* ScnMdlSimple::Construct(MEMAllocator* pAllocator, u32* pSize,
ResMdl mdl, int numView) {
if (!mdl.IsValid()) {
return NULL;
}
if (numView == 0) {
numView = 1;
} else if (numView > VIEW_MAX) {
numView = VIEW_MAX;
}
ScnMdlSimple* pSimple = NULL;
u32 simpleSize = sizeof(ScnMdlSimple);
u32 posNrmMtxNum = mdl.GetResMdlInfo().GetNumPosNrmMtx();
u32 viewMtxNum = mdl.GetResMdlInfo().GetNumViewMtx();
u32 worldMtxSize = posNrmMtxNum * sizeof(math::MTX34);
u32 worldAttrSize = posNrmMtxNum * sizeof(u32);
u32 viewPosTexMtxSizeUnit = viewMtxNum * (sizeof(math::MTX34));
u32 viewNrmMtxSizeUnit = viewMtxNum * (sizeof(math::MTX33));
u32 viewPosMtxSize = numView * align32(viewPosTexMtxSizeUnit);
u32 viewNrmMtxSize = mdl.GetResMdlInfo().ref().need_nrm_mtx_array
? numView * align32(viewNrmMtxSizeUnit)
: 0;
// TODO: Fakematch
u32 viewTexMtxSize = mdl.ref().info.need_tex_mtx_array
? numView * align32(viewPosTexMtxSizeUnit)
: 0;
u32 worldMtxOfs = align32(simpleSize);
u32 worldAttrOfs = align32(worldMtxOfs + worldMtxSize);
u32 viewPosMtxOfs = align32(worldAttrOfs + worldAttrSize);
u32 viewNrmMtxOfs = align32(viewPosMtxOfs + viewPosMtxSize);
u32 viewTexMtxOfs = align32(viewNrmMtxOfs + viewNrmMtxSize);
u32 size = align32(viewTexMtxOfs + viewTexMtxSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator != NULL) {
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
pSimple = new (pBuffer) ScnMdlSimple(
pAllocator,
mdl,
reinterpret_cast<math::MTX34*>(pBuffer + worldMtxOfs),
reinterpret_cast<u32*>(pBuffer + worldAttrOfs),
reinterpret_cast<math::MTX34*>(pBuffer + viewPosMtxOfs),
viewNrmMtxSize != 0 ? reinterpret_cast<math::MTX33*>(pBuffer + viewNrmMtxOfs) : NULL,
viewTexMtxSize != 0 ? reinterpret_cast<math::MTX34*>(pBuffer + viewTexMtxOfs) : NULL,
numView,
viewMtxNum);
// clang-format on
}
return pSimple;
}
void ScnMdlSimple::ScnMdlSmpl_CalcPosture(u32 param,
const math::MTX34* pParent) {
CheckCallback_CALC_WORLD(CALLBACK_TIMING_A, param,
const_cast<math::MTX34*>(pParent));
CalcWorldMtx(pParent, &param);
CheckCallback_CALC_WORLD(CALLBACK_TIMING_B, param,
const_cast<math::MTX34*>(pParent));
u32 mtxNum = GetResMdl().GetResMdlInfo().GetNumPosNrmMtx();
math::MTX34* pWorldMtxArray;
bool locked = false;
if (mtxNum > MTX_CACHE_MIN && mtxNum < MTX_CACHE_MAX &&
(locked = ut::LC::Lock()) == true) {
mFlagScnMdlSimple |= SCNMDLSMPLFLAG_LC_DMA;
DC::InvalidateRange(GetWldMtxArray(), mtxNum * sizeof(math::MTX34));
pWorldMtxArray = static_cast<math::MTX34*>(ut::LC::GetBase());
} else {
mFlagScnMdlSimple &= ~SCNMDLSMPLFLAG_LC_DMA;
pWorldMtxArray = GetWldMtxArray();
}
ScaleProperty property = GetScaleProperty();
u32 rootAttr = detail::WorldMtxAttr::GetRootMtxAttr();
u32 ignoreTrans;
GetScnObjOption(OPTION_IGNORE_ANMCHR_TRANS, &ignoreTrans);
if (property == UNIFORM_SCALED) {
rootAttr = detail::WorldMtxAttr::AnmNotScaleOne(rootAttr);
} else if (property == NONUNIFORM_SCALED) {
rootAttr = detail::WorldMtxAttr::AnmNotScaleUniform(rootAttr);
}
if (ignoreTrans) {
rootAttr = detail::WorldMtxAttr::AnmIgnoreTrans(rootAttr);
}
if (GetScnMdlCallback() != NULL) {
FuncObjCalcWorld funcObj(GetScnMdlCallback(), GetScnMdlCallbackTiming(),
GetScnMdlCallbackNodeID());
CalcWorld(pWorldMtxArray, GetWldMtxAttribArray(), GetByteCodeCalc(),
GetMtxPtr(MTX_WORLD), GetResMdl(), GetAnmObjChr(), &funcObj,
rootAttr);
} else {
CalcWorld(pWorldMtxArray, GetWldMtxAttribArray(), GetByteCodeCalc(),
GetMtxPtr(MTX_WORLD), GetResMdl(), GetAnmObjChr(), NULL,
rootAttr);
}
if (GetByteCodeMix() != NULL) {
CalcSkinning(pWorldMtxArray, GetWldMtxAttribArray(), GetResMdl(),
GetByteCodeMix());
}
if (locked) {
ut::LC::StoreData(GetWldMtxArray(), ut::LC::GetBase(),
mtxNum * sizeof(math::MTX34));
ut::LC::Unlock();
}
}
void ScnMdlSimple::ScnMdlSmpl_G3DPROC_GATHER_SCNOBJ(
u32 param, IScnObjGather* pCollection) {
#pragma unused(param)
pCollection->Add(this, !TestScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_OPA),
!TestScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_XLU));
}
void ScnMdlSimple::ScnMdlSmpl_G3DPROC_CALC_WORLD(u32 param,
const math::MTX34* pParent) {
ScnMdlSmpl_CalcPosture(param, pParent);
if (GetAnmObjVis() != NULL) {
ApplyVisAnmResult(GetResMdl(), GetAnmObjVis());
}
CheckCallback_CALC_WORLD(CALLBACK_TIMING_C, param,
const_cast<math::MTX34*>(pParent));
}
void ScnMdlSimple::ScnMdlSmpl_G3DPROC_CALC_MAT(u32 param, void* pInfo) {
CheckCallback_CALC_MAT(CALLBACK_TIMING_A, param, pInfo);
if (GetAnmObjTexPat() != NULL || GetAnmObjTexSrt() != NULL ||
GetAnmObjMatClr() != NULL) {
CalcMaterialDirectly(GetResMdl(), GetAnmObjTexPat(), GetAnmObjTexSrt(),
GetAnmObjMatClr());
}
CheckCallback_CALC_MAT(CALLBACK_TIMING_C, param, pInfo);
}
void ScnMdlSimple::ScnMdlSmpl_G3DPROC_CALC_VIEW(u32 param,
const math::MTX34* pCamera) {
mCurView = (mCurView + 1) % mNumView;
CheckCallback_CALC_VIEW(CALLBACK_TIMING_A, param,
const_cast<math::MTX34*>(pCamera));
CalcViewMtx(pCamera);
CheckCallback_CALC_VIEW(CALLBACK_TIMING_B, param,
const_cast<math::MTX34*>(pCamera));
if (ut::LC::Lock()) {
if (mFlagScnMdlSimple & SCNMDLSMPLFLAG_LC_DMA) {
DC::StoreRange(GetWldMtxArray(),
GetNumViewMtx() * sizeof(math::MTX34));
CalcView_LC_DMA_ModelMtx(GetViewPosMtxArray(), GetViewNrmMtxArray(),
GetWldMtxArray(), GetWldMtxAttribArray(),
GetNumViewMtx(), pCamera, GetResMdl(),
GetViewTexMtxArray());
} else {
CalcView_LC(GetViewPosMtxArray(), GetViewNrmMtxArray(),
GetWldMtxArray(), GetWldMtxAttribArray(),
GetNumViewMtx(), pCamera, GetResMdl(),
GetViewTexMtxArray());
}
ut::LC::Unlock();
} else {
CalcView(GetViewPosMtxArray(), GetViewNrmMtxArray(), GetWldMtxArray(),
GetWldMtxAttribArray(), GetNumViewMtx(), pCamera, GetResMdl(),
GetViewTexMtxArray());
}
CheckCallback_CALC_VIEW(CALLBACK_TIMING_C, param,
const_cast<math::MTX34*>(pCamera));
}
void ScnMdlSimple::ScnMdlSmpl_G3DPROC_DRAW_OPA(u32 param, void* pInfo) {
CheckCallback_DRAW_OPA(CALLBACK_TIMING_A, param, pInfo);
u32 drawMode = pInfo != NULL ? *static_cast<u32*>(pInfo) : GetDrawMode();
DrawResMdlDirectly(GetResMdl(), GetViewPosMtxArray(), GetViewNrmMtxArray(),
GetViewTexMtxArray(), GetByteCodeDrawOpa(), NULL, NULL,
drawMode);
CheckCallback_DRAW_OPA(CALLBACK_TIMING_C, param, pInfo);
}
void ScnMdlSimple::ScnMdlSmpl_G3DPROC_DRAW_XLU(u32 param, void* pInfo) {
CheckCallback_DRAW_XLU(CALLBACK_TIMING_A, param, pInfo);
u32 drawMode = pInfo != NULL ? *static_cast<u32*>(pInfo) : GetDrawMode();
DrawResMdlDirectly(GetResMdl(), GetViewPosMtxArray(), GetViewNrmMtxArray(),
GetViewTexMtxArray(), NULL, GetByteCodeDrawXlu(), NULL,
drawMode);
CheckCallback_DRAW_XLU(CALLBACK_TIMING_C, param, pInfo);
}
void ScnMdlSimple::G3dProc(u32 task, u32 param, void* pInfo) {
if (IsG3dProcDisabled(task)) {
return;
}
switch (task) {
case G3DPROC_GATHER_SCNOBJ: {
ScnMdlSmpl_G3DPROC_GATHER_SCNOBJ(param,
static_cast<IScnObjGather*>(pInfo));
break;
}
case G3DPROC_CALC_WORLD: {
ScnMdlSmpl_G3DPROC_CALC_WORLD(param, static_cast<math::MTX34*>(pInfo));
break;
}
case G3DPROC_CALC_MAT: {
ScnMdlSmpl_G3DPROC_CALC_MAT(param, pInfo);
break;
}
case G3DPROC_CALC_VIEW: {
ScnMdlSmpl_G3DPROC_CALC_VIEW(param, static_cast<math::MTX34*>(pInfo));
break;
}
case G3DPROC_DRAW_OPA: {
ScnMdlSmpl_G3DPROC_DRAW_OPA(param, pInfo);
break;
}
case G3DPROC_DRAW_XLU: {
ScnMdlSmpl_G3DPROC_DRAW_XLU(param, pInfo);
break;
}
case G3DPROC_UPDATEFRAME: {
ScnMdlSmpl_G3DPROC_UPDATEFRAME(param, pInfo);
break;
}
case G3DPROC_CHILD_DETACHED: {
RemoveAnmObj(static_cast<AnmObj*>(pInfo));
break;
}
default: {
DefG3dProcScnLeaf(task, param, pInfo);
break;
}
}
}
bool ScnMdlSimple::SetScnObjOption(u32 option, u32 value) {
switch (option) {
case OPTION_IGNORE_ANMCHR_TRANS: {
SetScnObjFlag(SCNOBJFLAG_IGNORE_ANMCHR_TRANS, value);
break;
}
default: {
return ScnLeaf::SetScnObjOption(option, value);
}
}
return true;
}
bool ScnMdlSimple::GetScnObjOption(u32 option, u32* pValue) const {
if (pValue == NULL) {
return false;
}
switch (option) {
case OPTION_IGNORE_ANMCHR_TRANS: {
*pValue = TestScnObjFlag(SCNOBJFLAG_IGNORE_ANMCHR_TRANS);
break;
}
default: {
return ScnLeaf::GetScnObjOption(option, pValue);
}
}
return true;
}
bool ScnMdlSimple::GetScnMtxPos(math::MTX34* pMtx, ScnObjMtxType type,
u32 idx) const {
if (pMtx != NULL) {
ResNode node = GetResMdl().GetResNode(idx);
if (node.IsValid()) {
s32 id = node.GetMtxID();
switch (type) {
case MTX_WORLD: {
math::MTX34Copy(pMtx, &mpWorldMtxArray[id]);
return true;
}
case MTX_VIEW: {
if (id < GetResMdl().GetResMdlInfo().GetNumViewMtx()) {
math::MTX34Copy(pMtx, &GetViewPosMtxArray()[id]);
return true;
}
const math::MTX34* pWorld = GetMtxPtr(MTX_WORLD);
const math::MTX34* pView = GetMtxPtr(MTX_VIEW);
math::MTX34 work0;
math::MTX34 work1;
if (math::MTX34Inv(&work0, pWorld) != FALSE) {
math::MTX34Mult(&work1, pView, &work0);
math::MTX34Mult(pMtx, &work1, &mpWorldMtxArray[id]);
return true;
}
}
default: {
break;
}
}
}
}
return false;
}
bool ScnMdlSimple::SetAnmObj(AnmObj* pObj, AnmObjType type) {
if (pObj == NULL || pObj->GetParent() != NULL) {
return false;
}
AnmObjChr* pChr = NULL;
AnmObjVis* pVis = NULL;
AnmObjMatClr* pClr = NULL;
AnmObjTexPat* pPat = NULL;
AnmObjTexSrt* pSrt = NULL;
switch (type) {
case ANMOBJTYPE_CHR: {
if ((pChr = DynamicCast<AnmObjChr>(pObj)) != NULL) {
goto _type_chr;
}
goto _bad_cast;
}
case ANMOBJTYPE_VIS: {
if ((pVis = DynamicCast<AnmObjVis>(pObj)) != NULL) {
goto _type_vis;
}
goto _bad_cast;
}
case ANMOBJTYPE_MATCLR: {
if ((pClr = DynamicCast<AnmObjMatClr>(pObj)) != NULL) {
goto _type_clr;
}
goto _bad_cast;
}
case ANMOBJTYPE_TEXPAT: {
if ((pPat = DynamicCast<AnmObjTexPat>(pObj)) != NULL) {
goto _type_pat;
}
goto _bad_cast;
}
case ANMOBJTYPE_TEXSRT: {
if ((pSrt = DynamicCast<AnmObjTexSrt>(pObj)) != NULL) {
goto _type_srt;
}
goto _bad_cast;
}
case ANMOBJTYPE_NOT_SPECIFIED: {
if ((pChr = DynamicCast<AnmObjChr>(pObj)) != NULL) {
goto _type_chr;
}
if ((pVis = DynamicCast<AnmObjVis>(pObj)) != NULL) {
goto _type_vis;
}
if ((pClr = DynamicCast<AnmObjMatClr>(pObj)) != NULL) {
goto _type_clr;
}
if ((pPat = DynamicCast<AnmObjTexPat>(pObj)) != NULL) {
goto _type_pat;
}
if ((pSrt = DynamicCast<AnmObjTexSrt>(pObj)) != NULL) {
goto _type_srt;
}
// FALLTHROUGH
}
_bad_cast:
case ANMOBJTYPE_SHP:
default: {
return false;
}
}
_type_chr:
if (!pChr->IsBound()) {
return false;
}
if (mpAnmObjChr != NULL) {
RemoveAnmObj(mpAnmObjChr);
}
mpAnmObjChr = pChr;
pChr->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return true;
_type_vis:
if (!pVis->IsBound()) {
return false;
}
if (mpAnmObjVis != NULL) {
RemoveAnmObj(mpAnmObjVis);
}
mpAnmObjVis = pVis;
pVis->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return true;
_type_clr:
if (!pClr->IsBound()) {
return false;
}
if (mpAnmObjMatClr != NULL) {
RemoveAnmObj(mpAnmObjMatClr);
}
mpAnmObjMatClr = pClr;
pClr->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return true;
_type_pat:
if (!pPat->IsBound()) {
return false;
}
if (mpAnmObjTexPat != NULL) {
RemoveAnmObj(mpAnmObjTexPat);
}
mpAnmObjTexPat = pPat;
pPat->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return true;
_type_srt:
if (!pSrt->IsBound()) {
return false;
}
if (mpAnmObjTexSrt != NULL) {
RemoveAnmObj(mpAnmObjTexSrt);
}
mpAnmObjTexSrt = pSrt;
pSrt->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
return true;
}
bool ScnMdlSimple::RemoveAnmObj(AnmObj* pObj) {
if (pObj == NULL) {
return false;
}
if (pObj == mpAnmObjChr) {
mpAnmObjChr->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpAnmObjChr = NULL;
return true;
}
if (pObj == mpAnmObjVis) {
mpAnmObjVis->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpAnmObjVis = NULL;
return true;
}
if (pObj == mpAnmObjMatClr) {
mpAnmObjMatClr->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpAnmObjMatClr = NULL;
return true;
}
if (pObj == mpAnmObjTexPat) {
mpAnmObjTexPat->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpAnmObjTexPat = NULL;
return true;
}
if (pObj == mpAnmObjTexSrt) {
mpAnmObjTexSrt->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpAnmObjTexSrt = NULL;
return true;
}
return false;
}
AnmObj* ScnMdlSimple::RemoveAnmObj(AnmObjType type) {
AnmObj* pObj = NULL;
switch (type) {
case ANMOBJTYPE_CHR: {
pObj = mpAnmObjChr;
RemoveAnmObj(mpAnmObjChr);
break;
}
case ANMOBJTYPE_VIS: {
pObj = mpAnmObjVis;
RemoveAnmObj(mpAnmObjVis);
break;
}
case ANMOBJTYPE_MATCLR: {
pObj = mpAnmObjMatClr;
RemoveAnmObj(mpAnmObjMatClr);
break;
}
case ANMOBJTYPE_TEXPAT: {
pObj = mpAnmObjTexPat;
RemoveAnmObj(mpAnmObjTexPat);
break;
}
case ANMOBJTYPE_TEXSRT: {
pObj = mpAnmObjTexSrt;
RemoveAnmObj(mpAnmObjTexSrt);
break;
}
case ANMOBJTYPE_SHP:
case ANMOBJTYPE_NOT_SPECIFIED:
default: {
break;
}
}
return pObj;
}
AnmObj* ScnMdlSimple::GetAnmObj(AnmObjType type) {
switch (type) {
case ANMOBJTYPE_CHR: {
return mpAnmObjChr;
}
case ANMOBJTYPE_VIS: {
return mpAnmObjVis;
}
case ANMOBJTYPE_MATCLR: {
return mpAnmObjMatClr;
}
case ANMOBJTYPE_TEXPAT: {
return mpAnmObjTexPat;
}
case ANMOBJTYPE_TEXSRT: {
return mpAnmObjTexSrt;
}
case ANMOBJTYPE_SHP:
case ANMOBJTYPE_NOT_SPECIFIED:
default: {
return NULL;
}
}
}
const AnmObj* ScnMdlSimple::GetAnmObj(AnmObjType type) const {
switch (type) {
case ANMOBJTYPE_CHR: {
return mpAnmObjChr;
}
case ANMOBJTYPE_VIS: {
return mpAnmObjVis;
}
case ANMOBJTYPE_MATCLR: {
return mpAnmObjMatClr;
}
case ANMOBJTYPE_TEXPAT: {
return mpAnmObjTexPat;
}
case ANMOBJTYPE_TEXSRT: {
return mpAnmObjTexSrt;
}
case ANMOBJTYPE_SHP:
case ANMOBJTYPE_NOT_SPECIFIED:
default: {
return NULL;
}
}
}
void ScnMdlSimple::UpdateFrame() {
if (mpAnmObjChr != NULL) {
mpAnmObjChr->UpdateFrame();
}
if (mpAnmObjVis != NULL) {
mpAnmObjVis->UpdateFrame();
}
if (mpAnmObjMatClr != NULL) {
mpAnmObjMatClr->UpdateFrame();
}
if (mpAnmObjTexPat != NULL) {
mpAnmObjTexPat->UpdateFrame();
}
if (mpAnmObjTexSrt != NULL) {
mpAnmObjTexSrt->UpdateFrame();
}
}
void ScnMdlSimple::EnableScnMdlCallbackTiming(Timing timing) {
if (timing & CALLBACK_TIMING_A) {
mCwcbTiming |= CALLBACK_TIMING_A;
}
if (timing & CALLBACK_TIMING_B) {
mCwcbTiming |= CALLBACK_TIMING_B;
}
if (timing & CALLBACK_TIMING_C) {
mCwcbTiming |= CALLBACK_TIMING_C;
}
}
void ScnMdlSimple::DisableScnMdlCallbackTiming(Timing timing) {
if (timing & CALLBACK_TIMING_A) {
mCwcbTiming &= ~CALLBACK_TIMING_A;
}
if (timing & CALLBACK_TIMING_B) {
mCwcbTiming &= ~CALLBACK_TIMING_B;
}
if (timing & CALLBACK_TIMING_C) {
mCwcbTiming &= ~CALLBACK_TIMING_C;
}
}
math::MTX34* ScnMdlSimple::GetViewPosMtxArray() {
u8* pBase = reinterpret_cast<u8*>(mpViewPosMtxArray);
return reinterpret_cast<math::MTX34*>(
pBase + mCurView * align32(mNumViewMtx * sizeof(math::MTX34)));
}
const math::MTX34* ScnMdlSimple::GetViewPosMtxArray() const {
u8* pBase = reinterpret_cast<u8*>(mpViewPosMtxArray);
return reinterpret_cast<math::MTX34*>(
pBase + mCurView * align32(mNumViewMtx * sizeof(math::MTX34)));
}
math::MTX33* ScnMdlSimple::GetViewNrmMtxArray() {
if (mpViewNrmMtxArray != NULL) {
u8* pBase = reinterpret_cast<u8*>(mpViewNrmMtxArray);
return reinterpret_cast<math::MTX33*>(
pBase + mCurView * align32(mNumViewMtx * sizeof(math::MTX33)));
}
return NULL;
}
const math::MTX33* ScnMdlSimple::GetViewNrmMtxArray() const {
if (mpViewNrmMtxArray != NULL) {
u8* pBase = reinterpret_cast<u8*>(mpViewNrmMtxArray);
return reinterpret_cast<math::MTX33*>(
pBase + mCurView * align32(mNumViewMtx * sizeof(math::MTX33)));
}
return NULL;
}
math::MTX34* ScnMdlSimple::GetViewTexMtxArray() {
if (mpViewTexMtxArray != NULL) {
u8* pBase = reinterpret_cast<u8*>(mpViewTexMtxArray);
return reinterpret_cast<math::MTX34*>(
pBase + mCurView * align32(mNumViewMtx * sizeof(math::MTX34)));
}
return NULL;
}
const math::MTX34* ScnMdlSimple::GetViewTexMtxArray() const {
if (mpViewTexMtxArray != NULL) {
u8* pBase = reinterpret_cast<u8*>(mpViewTexMtxArray);
return reinterpret_cast<math::MTX34*>(
pBase + mCurView * align32(mNumViewMtx * sizeof(math::MTX34)));
}
return NULL;
}
const u8* ScnMdlSimple::GetByteCode(ByteCodeType type) const {
switch (type) {
case BYTE_CODE_CALC: {
return mpByteCodeCalc;
}
case BYTE_CODE_MIX: {
return mpByteCodeMix;
}
case BYTE_CODE_DRAW_OPA: {
return mpByteCodeDrawOpa;
}
case BYTE_CODE_DRAW_XLU: {
return mpByteCodeDrawXlu;
}
default: {
return NULL;
}
}
}
ScnMdlSimple::ScnMdlSimple(MEMAllocator* pAllocator, ResMdl mdl,
math::MTX34* pWorldMtxArray,
u32* pWorldMtxAttribArray,
math::MTX34* pViewPosMtxArray,
math::MTX33* pViewNrmMtxArray,
math::MTX34* pViewTexMtxArray, int numView,
int numViewMtx)
: ScnLeaf(pAllocator),
mResMdl(mdl),
mpWorldMtxArray(pWorldMtxArray),
mpWorldMtxAttribArray(pWorldMtxAttribArray),
mpViewPosMtxArray(pViewPosMtxArray),
mpViewNrmMtxArray(pViewNrmMtxArray),
mpViewTexMtxArray(pViewTexMtxArray),
mNumView(numView),
mCurView(0),
mNumViewMtx(numViewMtx),
mFlagScnMdlSimple(0),
mpByteCodeCalc(mdl.GetResByteCode("NodeTree")),
mpByteCodeMix(mdl.GetResByteCode("NodeMix")),
mpByteCodeDrawOpa(mdl.GetResByteCode("DrawOpa")),
mpByteCodeDrawXlu(mdl.GetResByteCode("DrawXlu")),
mDrawMode(RESMDL_DRAWMODE_DEFAULT),
mpCalcWorldCallback(NULL),
mCwcbTiming(0),
mCwcbDeleteOption(FALSE),
mCwcbNodeID(0),
mpAnmObjChr(NULL),
mpAnmObjVis(NULL),
mpAnmObjMatClr(NULL),
mpAnmObjTexPat(NULL),
mpAnmObjTexSrt(NULL) {
if (mpByteCodeDrawOpa != NULL) {
SetScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_OPA, false);
} else {
SetScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_OPA, true);
}
if (mpByteCodeDrawXlu != NULL) {
SetScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_XLU, false);
} else {
SetScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_XLU, true);
}
if (mpViewPosMtxArray != NULL) {
DC::InvalidateRange(mpViewPosMtxArray,
numView *
align32(numViewMtx * sizeof(math::MTX34)));
}
if (mpViewNrmMtxArray != NULL) {
DC::InvalidateRange(mpViewNrmMtxArray,
numView *
align32(numViewMtx * sizeof(math::MTX33)));
}
if (mpViewTexMtxArray != NULL) {
DC::InvalidateRange(mpViewTexMtxArray,
numView *
align32(numViewMtx * sizeof(math::MTX34)));
}
if (mdl.GetResMdlInfo().ref().is_valid_volume) {
const math::_VEC3& rMin = mdl.GetResMdlInfo().ref().volume_min;
const math::_VEC3& rMax = mdl.GetResMdlInfo().ref().volume_max;
math::AABB box;
box.min = static_cast<const math::VEC3&>(rMin);
box.max = static_cast<const math::VEC3&>(rMax);
SetBoundingVolume(&box);
}
}
ScnMdlSimple::~ScnMdlSimple() {
switch (mCwcbDeleteOption) {
case TRUE: {
delete mpCalcWorldCallback;
break;
}
}
if (mpAnmObjChr != NULL) {
RemoveAnmObj(mpAnmObjChr);
}
if (mpAnmObjVis != NULL) {
RemoveAnmObj(mpAnmObjVis);
}
if (mpAnmObjMatClr != NULL) {
RemoveAnmObj(mpAnmObjMatClr);
}
if (mpAnmObjTexPat != NULL) {
RemoveAnmObj(mpAnmObjTexPat);
}
if (mpAnmObjTexSrt != NULL) {
RemoveAnmObj(mpAnmObjTexSrt);
}
}
} // namespace g3d
} // namespace nw4r
+666
View File
@@ -0,0 +1,666 @@
#include <nw4r/g3d.h>
#include <nw4r/math.h>
#include <algorithm>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(ScnObj);
NW4R_G3D_RTTI_DEF(ScnLeaf);
NW4R_G3D_RTTI_DEF(ScnGroup);
const math::FRUSTUM* gpCullingFrustum = NULL;
/******************************************************************************
*
* ScnObj
*
******************************************************************************/
void ScnObj::CalcWorldMtx(const math::MTX34* pParent, u32* pParam) {
if (pParam != NULL && (*pParam & SCNOBJFLAG_DISABLE_CALC_WORLD)) {
*pParam &= ~SCNOBJFLAG_DISABLE_CALC_WORLD;
return;
}
if (pParent != NULL) {
if (TestScnObjFlag(SCNOBJFLAG_MTX_LOCAL_IDENTITY)) {
math::MTX34Copy(&mMtxArray[MTX_WORLD], pParent);
} else {
math::MTX34Mult(&mMtxArray[MTX_WORLD], pParent,
&mMtxArray[MTX_LOCAL]);
}
} else {
math::MTX34Copy(&mMtxArray[MTX_WORLD], &mMtxArray[MTX_LOCAL]);
}
if (TestScnObjFlag(SCNOBJFLAG_ENABLE_CULLING)) {
mAABB[BOUNDINGVOLUME_AABB_WORLD].Set(&mAABB[BOUNDINGVOLUME_AABB_LOCAL],
&mMtxArray[MTX_WORLD]);
}
}
void ScnObj::CalcViewMtx(const math::MTX34* pCamera) {
math::MTX34Mult(&mMtxArray[MTX_VIEW], pCamera, &mMtxArray[MTX_WORLD]);
}
ScnObj::ScnObj(MEMAllocator* pAllocator)
: G3dObj(pAllocator, NULL),
mScnObjFlags(0),
mPriorityDrawOpa(128),
mPriorityDrawXlu(128),
PADDING_0xD2(0),
PADDING_0xD3(0),
mpFuncObjExec(NULL),
mCallbackTiming(0),
mCallbackDeleteOption(FALSE),
mCallbackExecOpMask(0) {
SetScnObjFlag(SCNOBJFLAG_MTX_LOCAL_IDENTITY, TRUE);
math::MTX34Identity(&mMtxArray[MTX_LOCAL]);
math::MTX34Identity(&mMtxArray[MTX_WORLD]);
math::MTX34Identity(&mMtxArray[MTX_VIEW]);
mAABB[BOUNDINGVOLUME_AABB_LOCAL].min = math::VEC3(0.0f, 0.0f, 0.0f);
mAABB[BOUNDINGVOLUME_AABB_LOCAL].max = math::VEC3(0.0f, 0.0f, 0.0f);
mAABB[BOUNDINGVOLUME_AABB_WORLD].min = math::VEC3(0.0f, 0.0f, 0.0f);
mAABB[BOUNDINGVOLUME_AABB_WORLD].max = math::VEC3(0.0f, 0.0f, 0.0f);
}
ScnObj::~ScnObj() {
if (mpFuncObjExec == NULL) {
return;
}
switch (mCallbackDeleteOption) {
case TRUE: {
delete mpFuncObjExec;
break;
}
}
}
bool ScnObj::SetScnObjOption(u32 option, u32 value) {
switch (option) {
case OPTION_DISABLE_GATHER_SCNOBJ: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_GATHER_SCNOBJ, value);
break;
}
case OPTION_DISABLE_CALC_WORLD: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_CALC_WORLD, value);
break;
}
case OPTION_DISABLE_CALC_MAT: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_CALC_MAT, value);
break;
}
case OPTION_DISABLE_CALC_VTX: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_CALC_VTX, value);
break;
}
case OPTION_DISABLE_CALC_VIEW: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_CALC_VIEW, value);
break;
}
case OPTION_DISABLE_DRAW_OPA: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_DRAW_OPA, value);
break;
}
case OPTION_DISABLE_DRAW_XLU: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_DRAW_XLU, value);
break;
}
case OPTION_DISABLE_UPDATEFRAME: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_UPDATEFRAME, value);
break;
}
case OPTION_ENABLE_CULLING: {
SetScnObjFlag(SCNOBJFLAG_ENABLE_CULLING, value);
break;
}
default: {
return false;
}
}
return true;
}
bool ScnObj::GetScnObjOption(u32 option, u32* pValue) const {
if (pValue == NULL) {
return false;
}
switch (option) {
case OPTION_DISABLE_GATHER_SCNOBJ: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_GATHER_SCNOBJ);
break;
}
case OPTION_DISABLE_CALC_WORLD: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_CALC_WORLD);
break;
}
case OPTION_DISABLE_CALC_MAT: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_CALC_MAT);
break;
}
case OPTION_DISABLE_CALC_VTX: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_CALC_VTX);
break;
}
case OPTION_DISABLE_CALC_VIEW: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_CALC_VIEW);
break;
}
case OPTION_DISABLE_DRAW_OPA: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_DRAW_OPA);
break;
}
case OPTION_DISABLE_DRAW_XLU: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_DRAW_XLU);
break;
}
case OPTION_DISABLE_UPDATEFRAME: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_UPDATEFRAME);
break;
}
case OPTION_ENABLE_CULLING: {
*pValue = TestScnObjFlag(SCNOBJFLAG_ENABLE_CULLING);
break;
}
default: {
return false;
}
}
return true;
}
bool ScnObj::SetMtx(ScnObjMtxType type, const math::MTX34* pMtx) {
if (static_cast<u32>(type) < MTX_TYPE_MAX) {
if (pMtx != NULL) {
if (type == MTX_LOCAL) {
SetScnObjFlag(SCNOBJFLAG_MTX_LOCAL_IDENTITY, FALSE);
}
math::MTX34Copy(&mMtxArray[type], pMtx);
} else {
if (type == MTX_LOCAL) {
SetScnObjFlag(SCNOBJFLAG_MTX_LOCAL_IDENTITY, TRUE);
}
math::MTX34Identity(&mMtxArray[type]);
}
return true;
}
return false;
}
bool ScnObj::GetMtx(ScnObjMtxType type, math::MTX34* pMtx) const {
if (pMtx != NULL && static_cast<u32>(type) < MTX_TYPE_MAX) {
math::MTX34Copy(pMtx, &mMtxArray[type]);
return true;
}
return false;
}
f32 ScnObj::GetValueForSortOpa() const {
return -mMtxArray[MTX_VIEW]._23;
}
f32 ScnObj::GetValueForSortXlu() const {
return mMtxArray[MTX_VIEW]._23;
}
void ScnObj::SetPriorityDrawOpa(int prio) {
if (prio < 0) {
prio = 0;
} else if (prio > 255) {
prio = 255;
}
mPriorityDrawOpa = prio;
}
void ScnObj::SetPriorityDrawXlu(int prio) {
if (prio < 0) {
prio = 0;
} else if (prio > 255) {
prio = 255;
}
mPriorityDrawXlu = prio;
}
void ScnObj::EnableScnObjCallbackTiming(Timing timing) {
if (timing & CALLBACK_TIMING_A) {
mCallbackTiming |= CALLBACK_TIMING_A;
}
if (timing & CALLBACK_TIMING_B) {
mCallbackTiming |= CALLBACK_TIMING_B;
}
if (timing & CALLBACK_TIMING_C) {
mCallbackTiming |= CALLBACK_TIMING_C;
}
}
void ScnObj::EnableScnObjCallbackExecOp(ExecOp op) {
mCallbackExecOpMask |= static_cast<u16>(op);
}
bool ScnObj::SetBoundingVolume(ScnObjBoundingVolumeType type,
const math::AABB* pAABB) {
if (pAABB != NULL) {
if (type < BOUNDINGVOLUME_MAX) {
mAABB[type] = *pAABB;
return SetScnObjOption(OPTION_ENABLE_CULLING, TRUE);
}
return false;
}
return SetScnObjOption(OPTION_ENABLE_CULLING, FALSE);
}
bool ScnObj::GetBoundingVolume(ScnObjBoundingVolumeType type,
math::AABB* pAABB) const {
if (pAABB != NULL) {
if (type < BOUNDINGVOLUME_MAX) {
*pAABB = mAABB[type];
return true;
}
return false;
}
return false;
}
/******************************************************************************
*
* ScnLeaf
*
******************************************************************************/
ScnObj::ForEachResult ScnLeaf::ForEach(ForEachFunc pFunc, void* pInfo,
bool postOrder) {
#pragma unused(postOrder)
return pFunc(this, pInfo) != FOREACHRESULT_CONTINUE
? FOREACHRESULT_OK
: FOREACHRESULT_CONTINUE;
}
bool ScnLeaf::SetScnObjOption(u32 option, u32 value) {
switch (option) {
case OPTION_DISABLE_DRAW_ALL: {
SetScnObjFlag(SCNOBJFLAG_DISABLE_DRAW, value);
break;
}
default: {
return ScnObj::SetScnObjOption(option, value);
}
}
return true;
}
bool ScnLeaf::GetScnObjOption(u32 option, u32* pValue) const {
if (pValue == NULL) {
return false;
}
switch (option) {
case OPTION_DISABLE_DRAW_ALL: {
*pValue = TestScnObjFlag(SCNOBJFLAG_DISABLE_DRAW);
break;
}
default: {
return ScnObj::GetScnObjOption(option, pValue);
}
}
return true;
}
void ScnLeaf::CalcWorldMtx(const math::MTX34* pParent, u32* pParam) {
if (pParam != NULL && (*pParam & SCNOBJFLAG_DISABLE_CALC_WORLD)) {
*pParam &= ~SCNOBJFLAG_DISABLE_CALC_WORLD;
return;
}
ScnObj::CalcWorldMtx(pParent, pParam);
math::MTX34Scale(&mMtxArray[MTX_WORLD], &mMtxArray[MTX_WORLD], &mScale);
if (TestScnObjFlag(SCNOBJFLAG_ENABLE_CULLING)) {
mAABB[BOUNDINGVOLUME_AABB_WORLD].Set(&mAABB[BOUNDINGVOLUME_AABB_LOCAL],
&mMtxArray[MTX_WORLD]);
}
}
ScnLeaf::ScaleProperty ScnLeaf::GetScaleProperty() const {
if (mScale.x == mScale.y) {
if (mScale.y == mScale.z) {
if (mScale.x == 1.0f) {
return NOT_SCALED;
}
return UNIFORM_SCALED;
}
}
return NONUNIFORM_SCALED;
}
void ScnLeaf::DefG3dProcScnLeaf(u32 task, u32 param, void* pInfo) {
switch (task) {
case G3DPROC_CALC_WORLD: {
CheckCallback_CALC_WORLD(CALLBACK_TIMING_A, param, pInfo);
CalcWorldMtx(static_cast<math::MTX34*>(pInfo), &param);
CheckCallback_CALC_WORLD(CALLBACK_TIMING_B, param, pInfo);
CheckCallback_CALC_WORLD(CALLBACK_TIMING_C, param, pInfo);
break;
}
case G3DPROC_CALC_MAT: {
CheckCallback_CALC_MAT(CALLBACK_TIMING_A, param, pInfo);
CheckCallback_CALC_MAT(CALLBACK_TIMING_C, param, pInfo);
break;
}
case G3DPROC_CALC_VIEW: {
CheckCallback_CALC_VIEW(CALLBACK_TIMING_A, param, pInfo);
CalcViewMtx(static_cast<math::MTX34*>(pInfo));
CheckCallback_CALC_VIEW(CALLBACK_TIMING_B, param, pInfo);
CheckCallback_CALC_VIEW(CALLBACK_TIMING_C, param, pInfo);
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<G3dObj*>(pInfo));
break;
}
case G3DPROC_GATHER_SCNOBJ:
case G3DPROC_DRAW_OPA:
case G3DPROC_DRAW_XLU:
case G3DPROC_UPDATEFRAME:
case G3DPROC_CHILD_DETACHED:
case G3DPROC_ZSORT: {
break;
}
}
}
/******************************************************************************
*
* ScnGroup
*
******************************************************************************/
ScnObj::ForEachResult ScnGroup::ForEach(ForEachFunc pFunc, void* pInfo,
bool postOrder) {
ForEachResult result;
if (postOrder) {
for (u32 i = 0; i < Size(); i++) {
result = mpScnObjArray[i]->ForEach(pFunc, pInfo, false);
if (result == FOREACHRESULT_CONTINUE) {
return FOREACHRESULT_CONTINUE;
}
}
result = pFunc(this, pInfo);
return result == FOREACHRESULT_CONTINUE ? FOREACHRESULT_CONTINUE
: FOREACHRESULT_OK;
} else {
result = pFunc(this, pInfo);
if (result == FOREACHRESULT_OK) {
for (u32 i = 0; i < Size(); i++) {
result = mpScnObjArray[i]->ForEach(pFunc, pInfo, false);
if (result == FOREACHRESULT_CONTINUE) {
return FOREACHRESULT_CONTINUE;
}
}
return FOREACHRESULT_OK;
}
return result == FOREACHRESULT_CONTINUE ? FOREACHRESULT_CONTINUE
: FOREACHRESULT_OK;
}
}
void ScnGroup::ScnGroup_G3DPROC_GATHER_SCNOBJ(u32 param,
IScnObjGather* pCollection) {
IScnObjGather::CullingStatus status =
pCollection->Add(this, !TestScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_OPA),
!TestScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_XLU));
if (status == IScnObjGather::CULLINGSTATUS_INTERSECT) {
for (u32 i = 0; i < mNumScnObj; i++) {
mpScnObjArray[i]->G3dProc(G3DPROC_GATHER_SCNOBJ, param,
pCollection);
}
} else if (status == IScnObjGather::CULLINGSTATUS_INSIDE) {
const math::FRUSTUM* pTemp = gpCullingFrustum;
gpCullingFrustum = NULL;
{
for (u32 i = 0; i < mNumScnObj; i++) {
mpScnObjArray[i]->G3dProc(G3DPROC_GATHER_SCNOBJ, param,
pCollection);
}
}
gpCullingFrustum = pTemp;
}
}
void ScnGroup::ScnGroup_G3DPROC_CALC_WORLD(u32 param,
const math::MTX34* pParent) {
CheckCallback_CALC_WORLD(CALLBACK_TIMING_A, param,
const_cast<math::MTX34*>(pParent));
CalcWorldMtx(pParent, &param);
CheckCallback_CALC_WORLD(CALLBACK_TIMING_B, param,
const_cast<math::MTX34*>(pParent));
math::MTX34* pWorldMtx = const_cast<math::MTX34*>(GetMtxPtr(MTX_WORLD));
for (u32 i = 0; i < mNumScnObj; i++) {
mpScnObjArray[i]->G3dProc(G3DPROC_CALC_WORLD, param, pWorldMtx);
}
CheckCallback_CALC_WORLD(CALLBACK_TIMING_C, param,
const_cast<math::MTX34*>(pParent));
}
void ScnGroup::ScnGroup_G3DPROC_CALC_MAT(u32 param, void* pInfo) {
CheckCallback_CALC_MAT(CALLBACK_TIMING_A, param, pInfo);
for (u32 i = 0; i < mNumScnObj; i++) {
mpScnObjArray[i]->G3dProc(G3DPROC_CALC_MAT, param, pInfo);
}
CheckCallback_CALC_MAT(CALLBACK_TIMING_C, param, pInfo);
}
void ScnGroup::ScnGroup_G3DPROC_CALC_VIEW(u32 param,
const math::MTX34* pCamera) {
CheckCallback_CALC_VIEW(CALLBACK_TIMING_A, param,
const_cast<math::MTX34*>(pCamera));
CalcViewMtx(pCamera);
CheckCallback_CALC_VIEW(CALLBACK_TIMING_B, param,
const_cast<math::MTX34*>(pCamera));
for (u32 i = 0; i < mNumScnObj; i++) {
mpScnObjArray[i]->G3dProc(G3DPROC_CALC_VIEW, param,
const_cast<math::MTX34*>(pCamera));
}
CheckCallback_CALC_VIEW(CALLBACK_TIMING_C, param,
const_cast<math::MTX34*>(pCamera));
}
void ScnGroup::G3dProc(u32 task, u32 param, void* pInfo) {
if (IsG3dProcDisabled(task)) {
return;
}
DefG3dProcScnGroup(task, param, pInfo);
}
void ScnGroup::DefG3dProcScnGroup(u32 task, u32 param, void* pInfo) {
switch (task) {
case G3DPROC_GATHER_SCNOBJ: {
ScnGroup_G3DPROC_GATHER_SCNOBJ(param,
static_cast<IScnObjGather*>(pInfo));
break;
}
case G3DPROC_CALC_WORLD: {
ScnGroup_G3DPROC_CALC_WORLD(param, static_cast<math::MTX34*>(pInfo));
break;
}
case G3DPROC_CALC_MAT: {
ScnGroup_G3DPROC_CALC_MAT(param, pInfo);
break;
}
case G3DPROC_CALC_VIEW: {
ScnGroup_G3DPROC_CALC_VIEW(param, static_cast<math::MTX34*>(pInfo));
break;
}
case G3DPROC_DRAW_OPA:
case G3DPROC_DRAW_XLU: {
return;
}
case G3DPROC_CHILD_DETACHED: {
Remove(static_cast<ScnObj*>(pInfo));
break;
}
case G3DPROC_DETACH_PARENT: {
SetParent(NULL);
break;
}
case G3DPROC_ATTACH_PARENT: {
SetParent(static_cast<ScnObj*>(pInfo));
break;
}
case G3DPROC_UPDATEFRAME:
case G3DPROC_ZSORT:
default: {
for (u32 i = 0; i < mNumScnObj; i++) {
mpScnObjArray[i]->G3dProc(task, param, pInfo);
}
break;
}
}
}
bool ScnGroup::Insert(u32 idx, ScnObj* pObj) {
if (idx <= mNumScnObj && mNumScnObj < mSizeScnObj && pObj != NULL &&
pObj->GetParent() == NULL) {
ScnObj** ppObj =
std::find(mpScnObjArray, mpScnObjArray + mNumScnObj, pObj);
if (ppObj == mpScnObjArray + mNumScnObj) {
for (u32 i = mNumScnObj; i > idx; i--) {
mpScnObjArray[i] = mpScnObjArray[i - 1];
}
mpScnObjArray[idx] = pObj;
pObj->G3dProc(G3DPROC_ATTACH_PARENT, 0, this);
mNumScnObj++;
return true;
}
}
return false;
}
ScnObj* ScnGroup::Remove(u32 idx) {
if (idx < mNumScnObj) {
ScnObj* pObj = mpScnObjArray[idx];
pObj->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
for (u32 i = idx; i < mNumScnObj - 1; i++) {
mpScnObjArray[i] = mpScnObjArray[i + 1];
}
mNumScnObj--;
return pObj;
}
return NULL;
}
bool ScnGroup::Remove(ScnObj* pObj) {
ScnObj** ppObj = std::find(mpScnObjArray, mpScnObjArray + mNumScnObj, pObj);
if (ppObj != mpScnObjArray + mNumScnObj) {
return Remove(std::distance(mpScnObjArray, ppObj)) != NULL;
}
return false;
}
ScnGroup::ScnGroup(MEMAllocator* pAllocator, ScnObj** ppObj, u32 capacity)
: ScnObj(pAllocator),
mpScnObjArray(ppObj),
mSizeScnObj(capacity),
mNumScnObj(0) {
SetScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_OPA, TRUE);
SetScnObjFlag(SCNOBJFLAG_NOT_GATHER_DRAW_XLU, TRUE);
}
ScnGroup::~ScnGroup() {
Clear();
}
} // namespace g3d
} // namespace nw4r
+72
View File
@@ -0,0 +1,72 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(ScnProc);
ScnProc* ScnProc::Construct(MEMAllocator* pAllocator, u32* pSize,
DrawProc pProc, bool opa, bool xlu,
u32 userDataSize) {
ScnProc* pScnProc = NULL;
u32 scnProcSize = sizeof(ScnProc);
userDataSize = align4(userDataSize);
u32 userDataOfs = align4(scnProcSize);
u32 size = align4(userDataOfs + userDataSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator != NULL) {
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer != NULL) {
void* pUserData = userDataSize != 0 ? pBuffer + userDataOfs : NULL;
pScnProc =
new (pBuffer) ScnProc(pAllocator, pProc, pUserData, opa, xlu);
}
}
return pScnProc;
}
void ScnProc::G3dProc(u32 task, u32 param, void* pInfo) {
if (IsG3dProcDisabled(task)) {
return;
}
switch (task) {
case G3DPROC_GATHER_SCNOBJ: {
IScnObjGather* pCollection = static_cast<IScnObjGather*>(pInfo);
pCollection->Add(this, (mFlag & SCNPROCFLAG_DRAW_OPA) ? true : false,
(mFlag & SCNPROCFLAG_DRAW_XLU) ? true : false);
break;
}
case G3DPROC_DRAW_OPA: {
if (mpDrawProc != NULL) {
G3DState::Invalidate();
mpDrawProc(this, true);
}
break;
}
case G3DPROC_DRAW_XLU: {
if (mpDrawProc != NULL) {
G3DState::Invalidate();
mpDrawProc(this, false);
}
break;
}
default: {
DefG3dProcScnLeaf(task, param, pInfo);
}
}
}
} // namespace g3d
} // namespace nw4r
+237
View File
@@ -0,0 +1,237 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(ScnRfl);
void ScnRfl::SetLightSetIdx(int idx) {
if (idx < 0 || idx > G3DState::NUM_LIGHT_SET - 1) {
mIdxLightSet = -1;
return;
}
mIdxLightSet = idx;
}
void ScnRfl::SetFogIdx(int idx) {
// @bug G3DState only allows 32 fog entries
if (idx < 0 || idx > 127) {
mIdxFog = -1;
return;
}
mIdxFog = idx;
}
bool ScnRfl::SetExpression(RFLExpression expression) {
if (IsCharModelReady()) {
RFLSetExpression(&mCharModel, expression);
return true;
}
return false;
}
bool ScnRfl::GetExpression(RFLExpression* pExpression) {
if (pExpression != NULL && IsCharModelReady()) {
*pExpression = RFLGetExpression(&mCharModel);
return true;
}
return false;
}
bool ScnRfl::SetupCharModel(RFLDataSource src, u16 index,
RFLMiddleDB* pMiddleDB) {
ReleaseCharModel();
mRFLErrCode = RFLInitCharModel(&mCharModel, src, pMiddleDB, index,
mpNglBuffer, mResolution, mExpressionFlag);
if (mRFLErrCode != RFLErrcode_Success) {
return false;
}
mCharModelReady = TRUE;
return true;
}
void ScnRfl::ReleaseCharModel() {
if (IsCharModelReady()) {
mCharModelReady = FALSE;
}
}
ScnRfl* ScnRfl::Construct(MEMAllocator* pAllocator, u32* pSize,
RFLResolution resolution, u32 exprFlags,
u32 userDataSize) {
ScnRfl* pScnRfl = NULL;
u32 scnRflSize = sizeof(ScnRfl);
u32 nglSize = RFLGetModelBufferSize(resolution, exprFlags);
u32 userOffset = align4(scnRflSize);
u32 nglOffset = align32(userOffset + userDataSize);
u32 size = align32(nglOffset + nglSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator != NULL) {
u8* pBuffer = reinterpret_cast<u8*>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
// clang-format off
pScnRfl = new (pBuffer) ScnRfl(
pAllocator,
pBuffer + nglOffset,
userDataSize != 0 ? pBuffer + userOffset : NULL,
resolution,
exprFlags);
// clang-format on
}
return pScnRfl;
}
void ScnRfl::G3dProc(u32 task, u32 param, void* pInfo) {
if (IsG3dProcDisabled(task)) {
return;
}
switch (task) {
case G3DPROC_GATHER_SCNOBJ: {
IScnObjGather* pCollection = static_cast<IScnObjGather*>(pInfo);
pCollection->Add(this, true, true);
break;
}
case G3DPROC_CALC_WORLD: {
CheckCallback_CALC_WORLD(CALLBACK_TIMING_A, param, pInfo);
CalcWorldMtx(static_cast<math::MTX34*>(pInfo), &param);
CheckCallback_CALC_WORLD(CALLBACK_TIMING_B, param, pInfo);
CheckCallback_CALC_WORLD(CALLBACK_TIMING_C, param, pInfo);
break;
}
case G3DPROC_CALC_VIEW: {
CheckCallback_CALC_VIEW(CALLBACK_TIMING_A, param, pInfo);
CalcViewMtx(static_cast<math::MTX34*>(pInfo));
CheckCallback_CALC_VIEW(CALLBACK_TIMING_B, param, pInfo);
math::MTX34 viewMtx;
GetMtx(MTX_VIEW, &viewMtx);
RFLSetMtx(&mCharModel, viewMtx);
CheckCallback_CALC_VIEW(CALLBACK_TIMING_C, param, pInfo);
break;
}
case G3DPROC_DRAW_OPA: {
if (!IsCharModelReady()) {
break;
}
if (mpDrawProc == NULL) {
LoadDrawSetting();
RFLDrawOpa(&mCharModel);
} else {
CallDrawProc(true);
}
break;
}
case G3DPROC_DRAW_XLU: {
if (!IsCharModelReady()) {
break;
}
if (mpDrawProc == NULL) {
LoadDrawSetting();
RFLDrawXlu(&mCharModel);
} else {
CallDrawProc(false);
}
break;
}
default: {
DefG3dProcScnLeaf(task, param, pInfo);
break;
}
}
}
void ScnRfl::CallDrawProc(bool opa) {
G3DState::LoadFog(GetFogIdx());
u32 diffMask, specMask;
AmbLightObj lobj;
G3DState::LoadLightSet(GetLightSetIdx(), &diffMask, &specMask, &lobj);
GXColor ambColor;
ambColor.r = 0.5f + (lobj.r * mAmbientColor.r) * (1.0f / 255.0f);
ambColor.g = 0.5f + (lobj.g * mAmbientColor.g) * (1.0f / 255.0f);
ambColor.b = 0.5f + (lobj.b * mAmbientColor.b) * (1.0f / 255.0f);
ambColor.a = 0.5f + (lobj.a * mAmbientColor.a) * (1.0f / 255.0f);
G3DState::Invalidate(
G3DState::INVALIDATE_ALL &
~(G3DState::INVALIDATE_FOG | G3DState::INVALIDATE_LIGHT));
mpDrawProc(this, &mCharModel, diffMask, specMask, ambColor, opa);
}
void ScnRfl::LoadDrawSetting() {
RFLDrawSetting setting;
G3DState::LoadFog(GetFogIdx());
u32 diffMask, specMask;
AmbLightObj lobj;
G3DState::LoadLightSet(GetLightSetIdx(), &diffMask, &specMask, &lobj);
setting.lightEnable = GetLightSetIdx() >= 0 ? TRUE : FALSE;
setting.lightMask = static_cast<GXLightID>(diffMask);
setting.diffuse = GetDiffuseFunc();
setting.attn = GetAttnFunc();
setting.compLoc = GXGetZCompLoc();
setting.ambColor.r = 0.5f + ((lobj.r * mAmbientColor.r) * (1.0f / 255.0f));
setting.ambColor.g = 0.5f + ((lobj.g * mAmbientColor.g) * (1.0f / 255.0f));
setting.ambColor.b = 0.5f + ((lobj.b * mAmbientColor.b) * (1.0f / 255.0f));
setting.ambColor.a = 0.5f + ((lobj.a * mAmbientColor.a) * (1.0f / 255.0f));
G3DState::Invalidate(
G3DState::INVALIDATE_ALL &
~(G3DState::INVALIDATE_FOG | G3DState::INVALIDATE_LIGHT));
RFLLoadDrawSetting(&setting);
}
ScnRfl::ScnRfl(MEMAllocator* pAllocator, void* pNglBuffer, void* pUserData,
RFLResolution resolution, u32 exprFlag)
: ScnLeaf(pAllocator),
mResolution(resolution),
mExpressionFlag(exprFlag),
mIdxLightSet(-1),
mIdxFog(-1),
mZCompLoc(TRUE),
mCharModelReady(FALSE),
mDiffuseFn(GX_DF_CLAMP),
mAttnFn(GX_AF_SPOT),
mpNglBuffer(pNglBuffer),
mRFLErrCode(RFLErrcode_Success),
mpDrawProc(NULL),
mpUserData(pUserData) {
mAmbientColor.r = mAmbientColor.g = mAmbientColor.b = 64;
mAmbientColor.a = 255;
}
} // namespace g3d
} // namespace nw4r
+453
View File
@@ -0,0 +1,453 @@
#include <nw4r/g3d.h>
#include <rvl/GX.h>
#include <algorithm>
#include <new>
namespace nw4r {
namespace g3d {
NW4R_G3D_RTTI_DEF(ScnRoot);
/******************************************************************************
*
* ScnRoot
*
******************************************************************************/
ScnRoot *ScnRoot::Construct(
MEMAllocator *pAllocator, u32 *pSize, u32 maxChildren, u32 maxScnObj, u32 numLightObj, u32 numLightSet
) {
ScnRoot *pScnRoot = NULL;
u32 scnRootSize = sizeof(ScnRoot);
u32 scnObjGatherSize = sizeof(ScnObjGather);
u32 childrenSize = maxChildren * sizeof(ScnObj *);
u32 scnObjBufSize = maxScnObj * sizeof(ScnObj *) + maxScnObj * sizeof(ScnObj *);
u32 lightObjSize = numLightObj * sizeof(LightObj);
u32 ambLightObjSize = numLightObj * sizeof(AmbLightObj);
u32 lightSetDataSize = numLightSet * sizeof(LightSetData);
u32 scnObjGatherOfs = align4(scnRootSize);
u32 childrenOfs = align4(scnObjGatherOfs + scnObjGatherSize);
u32 scnObjBufOfs = align4(childrenOfs + childrenSize);
u32 lightObjOfs = align4(scnObjBufOfs + scnObjBufSize);
u32 ambLightOfs = align4(lightObjOfs + lightObjSize);
u32 lightSetDataOfs = align4(ambLightOfs + ambLightObjSize);
u32 size = align4(lightSetDataOfs + lightSetDataSize);
if (pSize != NULL) {
*pSize = size;
}
if (pAllocator != NULL) {
u8 *pBuffer = reinterpret_cast<u8 *>(Alloc(pAllocator, size));
if (pBuffer == NULL) {
return NULL;
}
ScnObj **ppScnObjBuf = reinterpret_cast<ScnObj **>(pBuffer + scnObjBufOfs);
IScnObjGather *pGather =
new (pBuffer + scnObjGatherOfs) ScnObjGather(ppScnObjBuf, ppScnObjBuf + maxScnObj, maxScnObj);
LightObj *pLightObjBuf = reinterpret_cast<LightObj *>(pBuffer + lightObjOfs);
AmbLightObj *pAmbObjBuf = reinterpret_cast<AmbLightObj *>(pBuffer + ambLightOfs);
LightSetData *pLightSetBuf = reinterpret_cast<LightSetData *>(pBuffer + lightSetDataOfs);
// clang-format off
pScnRoot = new (pBuffer) ScnRoot(
pAllocator,
pGather,
reinterpret_cast<ScnObj**>(pBuffer + childrenOfs),
maxChildren,
numLightObj,
numLightSet,
pLightObjBuf,
pAmbObjBuf,
pLightSetBuf);
// clang-format on
}
return pScnRoot;
}
void ScnRoot::G3dProc(u32 task, u32 param, void *pInfo) {
if (IsG3dProcDisabled(task)) {
return;
}
switch (task) {
case G3DPROC_CHILD_DETACHED: {
if (mpAnmScn == pInfo) {
mpAnmScn->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
mpAnmScn = NULL;
break;
}
// FALLTHROUGH, detach may be for ScnGroup
}
default: {
DefG3dProcScnGroup(task, param, pInfo);
break;
}
}
}
Camera ScnRoot::GetCamera(int idx) {
if (idx >= 0 && idx < G3DState::NUM_CAMERA) {
return Camera(&mCamera[idx]);
}
return Camera(NULL);
}
Camera ScnRoot::GetCurrentCamera() {
return Camera(&mCamera[mCurrentCameraID]);
}
void ScnRoot::SetCurrentCamera(int idx) {
mCurrentCameraID = static_cast<u8>(idx);
}
Fog ScnRoot::GetFog(int idx) {
if (idx >= 0 && idx < G3DState::NUM_FOG) {
return Fog(&mFog[idx]);
}
return Fog(NULL);
}
LightSet ScnRoot::GetLightSet(int idx) {
return mLightSetting.GetLightSet(idx);
}
void ScnRoot::UpdateFrame() {
if (mpAnmScn != NULL) {
mpAnmScn->UpdateFrame();
}
G3dProc(G3DPROC_UPDATEFRAME, 0, NULL);
}
void ScnRoot::SetGlbSettings() {
int i;
Camera cam = GetCurrentCamera();
cam.GXSetViewport();
cam.GXSetProjection();
cam.GXSetScissor();
cam.GXSetScissorBoxOffset();
for (i = 0; i < G3DState::NUM_CAMERA; i++) {
G3DState::SetCameraProjMtx(Camera(&mCamera[i]), i, i == mCurrentCameraID);
}
bool persp = cam.GetProjectionType() != GX_ORTHOGRAPHIC;
u32 projOrthoBit = persp ? 0 : GX_ORTHOGRAPHIC << 3;
f32 near = cam.ref().projNear;
f32 far = cam.ref().projFar;
u16 width = 0;
u16 center = 0;
math::MTX44 proj;
bool fogRangeAdj = false;
for (i = 0; i < G3DState::NUM_FOG; i++) {
Fog fog(&mFog[i]);
fog.SetNearFar(near, far);
if (fog.ref().type != GX_PERSPECTIVE) {
fog.ref().type = static_cast<GXFogType>((fog.ref().type & ~(GX_ORTHOGRAPHIC << 3)) | projOrthoBit);
}
if (fog.IsFogRangeAdjEnable()) {
if (!fogRangeAdj) {
cam.GetProjectionMtx(&proj);
f32 f_width, x;
cam.GetViewport(&x, NULL, &f_width, NULL, NULL, NULL);
width = math::F32ToU16(f_width);
center = math::F32ToU16(x + f_width * 0.5f);
fogRangeAdj = true;
}
fog.SetFogRangeAdjParam(width, center, proj);
}
G3DState::SetFog(fog, i);
}
G3DState::SetLightSetting(mLightSetting);
}
void ScnRoot::CalcAnmScn() {
if (mpAnmScn == NULL) {
return;
}
const u32 numLightSet = mpAnmScn->GetLightSetMaxRefNumber();
const u32 numFog = mpAnmScn->GetFogMaxRefNumber();
const u32 numCamera = mpAnmScn->GetCameraMaxRefNumber();
if (numLightSet > 0) {
mpAnmScn->GetLightSetting(&mLightSetting);
}
if (numFog > 0) {
const u32 numLoadableFog = std::min<u32>(G3DState::NUM_FOG, numFog);
for (u32 i = 0; i < numLoadableFog; i++) {
Fog fog(&mFog[i]);
mpAnmScn->GetFog(fog, i);
}
}
if (numCamera > 0) {
const u32 numLoadableCamera = std::min<u32>(G3DState::NUM_CAMERA, numCamera);
for (u32 i = 0; i < numLoadableCamera; i++) {
Camera cam(&mCamera[i]);
mpAnmScn->GetCamera(cam, i);
}
}
}
void ScnRoot::CalcWorld() {
CalcAnmScn();
G3dProc(G3DPROC_CALC_WORLD, 0, NULL);
}
void ScnRoot::CalcMaterial() {
G3dProc(G3DPROC_CALC_MAT, 0, NULL);
}
void ScnRoot::CalcVtx() {
G3dProc(G3DPROC_CALC_VTX, 0, NULL);
}
void ScnRoot::CalcView() {
math::MTX34 cam;
GXInvalidateVtxCache();
GetCurrentCamera().GetCameraMtx(&cam);
G3dProc(G3DPROC_CALC_VIEW, 0, &cam);
}
void ScnRoot::GatherDrawScnObj() {
mpCollection->Clear();
math::FRUSTUM frustum;
Camera cam = GetCurrentCamera();
math::MTX34 mtx;
cam.GetCameraMtx(&mtx);
if (cam.ref().flags & CameraData::FLAG_PROJ_PERSP) {
frustum.Set(cam.ref().projFovy, cam.ref().projAspect, cam.ref().projNear, cam.ref().projFar, mtx);
} else {
frustum.Set(
cam.ref().projTop, cam.ref().projBottom, cam.ref().projLeft, cam.ref().projRight, cam.ref().projNear,
cam.ref().projFar, mtx
);
}
gpCullingFrustum = &frustum;
G3dProc(G3DPROC_GATHER_SCNOBJ, 0, mpCollection);
gpCullingFrustum = NULL;
}
void ScnRoot::ZSort() {
mpCollection->ZSort();
G3dProc(G3DPROC_ZSORT, 0, mpCollection);
}
void ScnRoot::DrawOpa() {
SetGlbSettings();
if (TestScnRootFlag(SCNROOTFLAG_FORCE_RESMDLDRAWMODE)) {
mpCollection->DrawOpa(&mDrawMode);
} else {
mpCollection->DrawOpa(NULL);
}
G3DState::Invalidate(G3DState::INVALIDATE_TEV);
}
void ScnRoot::DrawXlu() {
SetGlbSettings();
if (TestScnRootFlag(SCNROOTFLAG_FORCE_RESMDLDRAWMODE)) {
mpCollection->DrawXlu(&mDrawMode);
} else {
mpCollection->DrawXlu(NULL);
}
G3DState::Invalidate(G3DState::INVALIDATE_TEV);
}
ScnRoot::ScnRoot(
MEMAllocator *pAllocator, IScnObjGather *pGather, ScnObj **ppChildrenBuf, u32 maxChildren, u32 numLight,
u32 numLightSet, LightObj *pLightObjBuf, AmbLightObj *pAmbObjBuf, LightSetData *pLightSetBuf
)
: ScnGroup(pAllocator, ppChildrenBuf, maxChildren),
mpCollection(pGather),
mDrawMode(RESMDL_DRAWMODE_DEFAULT),
mScnRootFlags(0),
mCurrentCameraID(0),
mLightSetting(pLightObjBuf, pAmbObjBuf, numLight, pLightSetBuf, numLightSet),
mpAnmScn(NULL) {
for (u32 i = 0; i < G3DState::NUM_CAMERA; i++) {
Camera res(&mCamera[i]);
res.Init();
}
for (u32 i = 0; i < G3DState::NUM_FOG; i++) {
Fog res(&mFog[i]);
res.Init();
}
}
ScnRoot::~ScnRoot() {
if (mpAnmScn != NULL) {
mpAnmScn->G3dProc(G3DPROC_DETACH_PARENT, 0, this);
}
}
/******************************************************************************
*
* Sorting functions
*
******************************************************************************/
namespace {
inline bool LessZSortOpa(const ScnObj *pLhs, const ScnObj *pRhs) {
int lhsPrio = pLhs->GetPriorityDrawOpa();
int rhsPrio = pRhs->GetPriorityDrawOpa();
if (lhsPrio == rhsPrio) {
return pLhs->GetMtxPtr(ScnObj::MTX_VIEW)->_23 > pRhs->GetMtxPtr(ScnObj::MTX_VIEW)->_23;
}
return lhsPrio < rhsPrio;
}
inline bool LessZSortXlu(const ScnObj *pLhs, const ScnObj *pRhs) {
int lhsPrio = pLhs->GetPriorityDrawXlu();
int rhsPrio = pRhs->GetPriorityDrawXlu();
if (lhsPrio == rhsPrio) {
return pLhs->GetMtxPtr(ScnObj::MTX_VIEW)->_23 < pRhs->GetMtxPtr(ScnObj::MTX_VIEW)->_23;
}
return lhsPrio < rhsPrio;
}
inline bool LessByGetValueForSortOpa(const ScnObj *pLhs, const ScnObj *pRhs) {
int lhsPrio = pLhs->GetPriorityDrawOpa();
int rhsPrio = pRhs->GetPriorityDrawOpa();
if (lhsPrio == rhsPrio) {
return pLhs->GetValueForSortOpa() < pRhs->GetValueForSortOpa();
}
return lhsPrio < rhsPrio;
}
inline bool LessByGetValueForSortXlu(const ScnObj *pLhs, const ScnObj *pRhs) {
int lhsPrio = pLhs->GetPriorityDrawXlu();
int rhsPrio = pRhs->GetPriorityDrawXlu();
if (lhsPrio == rhsPrio) {
return pLhs->GetValueForSortXlu() < pRhs->GetValueForSortXlu();
}
return lhsPrio < rhsPrio;
}
} // namespace
/******************************************************************************
*
* ScnObjGather
*
******************************************************************************/
IScnObjGather::CullingStatus ScnObjGather::Add(ScnObj *pObj, bool opa, bool xlu) {
IScnObjGather::CullingStatus status = IScnObjGather::CULLINGSTATUS_INTERSECT;
math::IntersectionResult ixResult = math::INTERSECTION_INTERSECT;
if (gpCullingFrustum != NULL) {
u32 value;
pObj->GetScnObjOption(ScnObj::OPTION_ENABLE_CULLING, &value);
if (value) {
math::AABB aabb;
pObj->GetBoundingVolume(ScnObj::BOUNDINGVOLUME_AABB_WORLD, &aabb);
ixResult = gpCullingFrustum->IntersectAABB_Ex(&aabb);
if (ixResult == math::INTERSECTION_NONE) {
return IScnObjGather::CULLINGSTATUS_OUTSIDE;
} else if (ixResult == math::INTERSECTION_INSIDE) {
status = IScnObjGather::CULLINGSTATUS_INSIDE;
}
}
}
if (opa) {
if (mNumScnObjOpa < mSizeScnObj) {
mpArrayOpa[mNumScnObjOpa++] = pObj;
} else {
return status;
}
}
if (xlu) {
if (mNumScnObjXlu < mSizeScnObj) {
mpArrayXlu[mNumScnObjXlu++] = pObj;
} else {
return status;
}
}
return status;
}
void ScnObjGather::ZSort() {
std::sort(mpArrayOpa, mpArrayOpa + mNumScnObjOpa, LessZSortOpa);
std::sort(mpArrayXlu, mpArrayXlu + mNumScnObjXlu, LessZSortXlu);
}
void ScnObjGather::Sort() {
std::sort(mpArrayOpa, mpArrayOpa + mNumScnObjOpa, LessByGetValueForSortOpa);
std::sort(mpArrayXlu, mpArrayXlu + mNumScnObjXlu, LessByGetValueForSortXlu);
}
void ScnObjGather::Sort(LessThanFunc pOpaFunc, LessThanFunc pXluFunc) {
std::sort(mpArrayOpa, mpArrayOpa + mNumScnObjOpa, pOpaFunc);
std::sort(mpArrayXlu, mpArrayXlu + mNumScnObjXlu, pXluFunc);
}
void ScnObjGather::DrawOpa(ResMdlDrawMode *pForceMode) {
for (u32 i = 0; i != mNumScnObjOpa;) {
mpArrayOpa[i++]->G3dProc(G3dObj::G3DPROC_DRAW_OPA, 0, pForceMode);
}
}
void ScnObjGather::DrawXlu(ResMdlDrawMode *pForceMode) {
for (u32 i = 0; i != mNumScnObjXlu;) {
mpArrayXlu[i++]->G3dProc(G3dObj::G3DPROC_DRAW_XLU, 0, pForceMode);
}
}
ScnObjGather::ScnObjGather(ScnObj **ppBufOpa, ScnObj **ppBufXlu, u32 capacity)
: mpArrayOpa(ppBufOpa), mpArrayXlu(ppBufXlu), mSizeScnObj(capacity), mNumScnObjOpa(0), mNumScnObjXlu(0) {}
} // namespace g3d
} // namespace nw4r
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace detail {
namespace workmem {
namespace {
union {
u8 mem[WORKMEM_SIZE]; // at 0x0
struct {
math::_VEC3 tmpScale[WORKMEM_NUMTMPSCALE]; // at 0x0
u32 mtxID[WORKMEM_NUMMTXID]; // at 0x6000
};
u8 byteCode[WORKMEM_NUMBYTECODE]; // at 0x0
MdlZ mdlZ[WORKMEM_NUMMDLZ]; // at 0x0
math::_MTX34 skinningMtx[WORKMEM_NUMSKINNINGMTX]; // at 0x0
math::_MTX34 bbMtx[WORKMEM_NUMBBMTX]; // at 0x0
u8 shpAnmResultBuf[WORKMEM_NUMSHPANMRESULT]; // at 0x0
} sTemp ALIGN_DECL(128);
} // namespace
math::VEC3 *GetScaleTemporary() {
return static_cast<math::VEC3 *>(sTemp.tmpScale);
}
u32 *GetMtxIDTemporary() {
return sTemp.mtxID;
}
MdlZ *GetMdlZTemporary() {
return sTemp.mdlZ;
}
math::MTX34 *GetSkinningMtxTemporary() {
return static_cast<math::MTX34 *>(sTemp.skinningMtx);
}
math::MTX34 *GetBillboardMtxTemporary() {
return static_cast<math::MTX34 *>(sTemp.bbMtx);
}
ShpAnmResultBuf *GetShpAnmResultBufTemporary() {
return reinterpret_cast<ShpAnmResultBuf *>(sTemp.shpAnmResultBuf);
}
} // namespace workmem
} // namespace detail
} // namespace g3d
} // namespace nw4r
+379
View File
@@ -0,0 +1,379 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace detail {
namespace dcc {
namespace {
void MakeTexSrtMtx_S(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 = rSrt.Su;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = 0.0f;
pMtx->_10 = 0.0f;
pMtx->_11 = rSrt.Sv;
pMtx->_12 = 0.0f;
pMtx->_13 = 1.0f - rSrt.Sv;
}
void MakeTexSrtMtx_R(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
pMtx->_00 = cosR;
pMtx->_01 = -sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = sinR;
pMtx->_10 = sinR;
pMtx->_11 = cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = 1.0f - cosR;
}
void MakeTexSrtMtx_T(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 = 1.0f;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = -rSrt.Tu;
pMtx->_10 = 0.0f;
pMtx->_11 = 1.0f;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Tv;
}
void MakeTexSrtMtx_SR(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
pMtx->_00 = sucr;
pMtx->_01 = -susr;
pMtx->_02 = 0.0f;
pMtx->_03 = susr;
pMtx->_10 = svsr;
pMtx->_11 = svcr;
pMtx->_12 = 0.0f;
pMtx->_13 = -svcr + 1.0f;
}
void MakeTexSrtMtx_RT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
pMtx->_00 = cosR;
pMtx->_01 = -sinR;
pMtx->_02 = 0.0f;
pMtx->_03 = (sinR - cosR * rSrt.Tu) - sinR * rSrt.Tv;
pMtx->_10 = sinR;
pMtx->_11 = cosR;
pMtx->_12 = 0.0f;
pMtx->_13 = (-cosR - sinR * rSrt.Tu) + cosR * rSrt.Tv + 1.0f;
}
void MakeTexSrtMtx_ST(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 = rSrt.Su;
pMtx->_01 = 0.0f;
pMtx->_02 = 0.0f;
pMtx->_03 = -rSrt.Su * rSrt.Tu;
pMtx->_10 = 0.0f;
pMtx->_11 = rSrt.Sv;
pMtx->_12 = 0.0f;
pMtx->_13 = rSrt.Sv * (rSrt.Tv - 1.0f) + 1.0f;
}
void MakeTexSrtMtx_SRT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
pMtx->_00 = sucr;
pMtx->_01 = -susr;
pMtx->_02 = 0.0f;
pMtx->_03 = (susr - sucr * rSrt.Tu) - susr * rSrt.Tv;
pMtx->_10 = svsr;
pMtx->_11 = svcr;
pMtx->_12 = 0.0f;
pMtx->_13 = (-svcr - svsr * rSrt.Tu) + svcr * rSrt.Tv + 1.0f;
}
void ProductTexSrtMtx_S(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 *= rSrt.Su;
pMtx->_01 *= rSrt.Su;
pMtx->_02 *= rSrt.Su;
pMtx->_03 *= rSrt.Su;
pMtx->_10 *= rSrt.Sv;
pMtx->_11 *= rSrt.Sv;
pMtx->_12 *= rSrt.Sv;
pMtx->_13 = rSrt.Sv * (pMtx->_13 - 1.0f) + 1.0f;
}
void ProductTexSrtMtx_R(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
_0x = cosR * pMtx->_00 - sinR * pMtx->_10;
_1x = sinR * pMtx->_00 + cosR * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = cosR * pMtx->_01 - sinR * pMtx->_11;
_1x = sinR * pMtx->_01 + cosR * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = cosR * pMtx->_02 - sinR * pMtx->_12;
_1x = sinR * pMtx->_02 + cosR * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = cosR * pMtx->_03 - sinR * pMtx->_13 + sinR;
_1x = sinR * pMtx->_03 + cosR * pMtx->_13 - cosR + 1.0f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_T(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_03 -= rSrt.Tu;
pMtx->_13 += rSrt.Tv;
}
void ProductTexSrtMtx_SR(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
_0x = sucr * pMtx->_00 - susr * pMtx->_10;
_1x = svsr * pMtx->_00 + svcr * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = sucr * pMtx->_01 - susr * pMtx->_11;
_1x = svsr * pMtx->_01 + svcr * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = sucr * pMtx->_02 - susr * pMtx->_12;
_1x = svsr * pMtx->_02 + svcr * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
_0x = sucr * pMtx->_03 - susr * pMtx->_13 + susr;
_1x = svsr * pMtx->_03 + svcr * pMtx->_13 - svcr + 1.0f;
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_RT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
_0x = cosR * pMtx->_00 - sinR * pMtx->_10;
_1x = sinR * pMtx->_00 + cosR * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = cosR * pMtx->_01 - sinR * pMtx->_11;
_1x = sinR * pMtx->_01 + cosR * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = cosR * pMtx->_02 - sinR * pMtx->_12;
_1x = sinR * pMtx->_02 + cosR * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
// clang-format off
_0x = cosR * (pMtx->_03 - rSrt.Tu)
- sinR * (pMtx->_13 + rSrt.Tv)
+ sinR;
_1x = sinR * (pMtx->_03 - rSrt.Tu)
+ cosR * (pMtx->_13 + rSrt.Tv)
- cosR + 1.0f;
// clang-format on
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
void ProductTexSrtMtx_ST(math::MTX34* pMtx, const TexSrt& rSrt) {
pMtx->_00 *= rSrt.Su;
pMtx->_01 *= rSrt.Su;
pMtx->_02 *= rSrt.Su;
pMtx->_03 = (pMtx->_03 - rSrt.Tu) * rSrt.Su;
pMtx->_10 *= rSrt.Sv;
pMtx->_11 *= rSrt.Sv;
pMtx->_12 *= rSrt.Sv;
pMtx->_13 = (pMtx->_13 + rSrt.Tv - 1.0f) * rSrt.Sv + 1.0f;
}
void ProductTexSrtMtx_SRT(math::MTX34* pMtx, const TexSrt& rSrt) {
f32 sinR, cosR;
f32 _0x, _1x;
math::SinCosDeg(&sinR, &cosR, rSrt.R);
f32 sucr = rSrt.Su * cosR;
f32 susr = rSrt.Su * sinR;
f32 svcr = rSrt.Sv * cosR;
f32 svsr = rSrt.Sv * sinR;
_0x = sucr * pMtx->_00 - susr * pMtx->_10;
_1x = svsr * pMtx->_00 + svcr * pMtx->_10;
pMtx->_00 = _0x;
pMtx->_10 = _1x;
_0x = sucr * pMtx->_01 - susr * pMtx->_11;
_1x = svsr * pMtx->_01 + svcr * pMtx->_11;
pMtx->_01 = _0x;
pMtx->_11 = _1x;
_0x = sucr * pMtx->_02 - susr * pMtx->_12;
_1x = svsr * pMtx->_02 + svcr * pMtx->_12;
pMtx->_02 = _0x;
pMtx->_12 = _1x;
// clang-format off
_0x = sucr * (pMtx->_03 - rSrt.Tu)
- susr * (pMtx->_13 + rSrt.Tv)
+ susr;
_1x = svsr * (pMtx->_03 - rSrt.Tu)
+ svcr * (pMtx->_13 + rSrt.Tv)
- svcr + 1.0f;
// clang-format on
pMtx->_03 = _0x;
pMtx->_13 = _1x;
}
} // namespace
typedef void (*CalcTexMtxFunc)(math::MTX34* pMtx, const TexSrt& rSrt);
bool CalcTexMtx_Xsi(math::MTX34* pMtx, bool set, const TexSrt& rSrt,
TexSrt::Flag flag) {
// Extract S/R/T flags
u32 index = flag >> 1 & 0b111;
// Scale-one, no rotate/trans
if (index == 0b111) {
return false;
}
if (set) {
static const CalcTexMtxFunc funcTable[] = {
MakeTexSrtMtx_SRT, // 0 0 0
MakeTexSrtMtx_RT, // 0 0 1
MakeTexSrtMtx_ST, // 0 1 0
MakeTexSrtMtx_T, // 0 1 1
MakeTexSrtMtx_SR, // 1 0 0
MakeTexSrtMtx_R, // 1 0 1
MakeTexSrtMtx_S // 1 1 0
};
funcTable[index](pMtx, rSrt);
} else {
static const CalcTexMtxFunc funcTable[] = {
ProductTexSrtMtx_SRT, // 0 0 0
ProductTexSrtMtx_RT, // 0 0 1
ProductTexSrtMtx_ST, // 0 1 0
ProductTexSrtMtx_T, // 0 1 1
ProductTexSrtMtx_SR, // 1 0 0
ProductTexSrtMtx_R, // 1 0 1
ProductTexSrtMtx_S // 1 1 0
};
funcTable[index](pMtx, rSrt);
}
pMtx->_20 = 0.0f;
pMtx->_21 = 0.0f;
pMtx->_22 = 1.0f;
pMtx->_23 = 0.0f;
return true;
}
u32 CalcWorldMtx_Xsi(math::MTX34* pW, math::VEC3* pS, const math::MTX34* pW1,
const math::VEC3* pS1, u32 attr,
const ChrAnmResult* pResult) {
u32 flag = pResult->flags;
u32 newAttr = attr;
if (flag & ChrAnmResult::FLAG_SCALE_ONE) {
newAttr = detail::WorldMtxAttr::AnmScaleOne(newAttr);
*pS = *pS1;
} else {
newAttr = detail::WorldMtxAttr::AnmNotScaleOne(newAttr);
pS->x = pS1->x * pResult->s.x;
pS->y = pS1->y * pResult->s.y;
pS->z = pS1->z * pResult->s.z;
}
if ((flag & ChrAnmResult::FLAG_MTX_IDENT) ||
(flag & ChrAnmResult::FLAG_ROT_TRANS_ZERO)) {
math::MTX34Copy(pW, pW1);
} else if (flag & ChrAnmResult::FLAG_ROT_ZERO) {
if (detail::WorldMtxAttr::IsAllScaleOne(attr)) {
math::VEC3 trans(pResult->rt._03, pResult->rt._13, pResult->rt._23);
math::MTX34Trans(pW, pW1, &trans);
} else {
math::VEC3 trans(pS1->x * pResult->rt._03, pS1->y * pResult->rt._13,
pS1->z * pResult->rt._23);
math::MTX34Trans(pW, pW1, &trans);
}
} else if (detail::WorldMtxAttr::IsAllScaleOne(attr)) {
math::MTX34Mult(pW, pW1, &pResult->rt);
} else {
math::MTX34Copy(pW, &pResult->rt);
pW->_03 *= pS1->x;
pW->_13 *= pS1->y;
pW->_23 *= pS1->z;
math::MTX34Mult(pW, pW1, pW);
}
if (flag & ChrAnmResult::FLAG_SCALE_UNIFORM) {
newAttr = detail::WorldMtxAttr::AnmScaleUniform(newAttr);
} else {
newAttr = detail::WorldMtxAttr::AnmNotScaleUniform(newAttr);
}
return newAttr;
}
} // namespace dcc
} // namespace detail
} // namespace g3d
} // namespace nw4r
+51
View File
@@ -0,0 +1,51 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace detail {
void Copy32ByteBlocks(register void *pDst, register const void *pSrc, register u32 size) {
register f32 work0, work1, work2, work3;
for (size /= 32; size > 0; size--) {
// clang-format off
asm {
lfd work0, 0(pSrc)
stfd work0, 0(pDst)
lfd work1, 8(pSrc)
stfd work1, 8(pDst)
lfd work2, 16(pSrc)
stfd work2, 16(pDst)
lfd work3, 24(pSrc)
stfd work3, 24(pDst)
}
// clang-format on
pDst = static_cast<u8 *>(pDst) + 32;
pSrc = static_cast<const u8 *>(pSrc) + 32;
}
}
void ZeroMemory32ByteBlocks(register void *pDst, register u32 size) {
register f32 zero = 0.0f;
for (size /= 32; size > 0; size--) {
// clang-format off
asm {
psq_st zero, 0(pDst), 0, 0
psq_st zero, 8(pDst), 0, 0
psq_st zero, 16(pDst), 0, 0
psq_st zero, 24(pDst), 0, 0
}
// clang-format on
pDst = static_cast<u8 *>(pDst) + 32;
}
}
} // namespace detail
} // namespace g3d
} // namespace nw4r
+212
View File
@@ -0,0 +1,212 @@
#include <nw4r/g3d.h>
namespace nw4r {
namespace g3d {
namespace fifo {
void GDSetGenMode2(u8 numTexGens, u8 numChans, u8 numTevs, u8 numInds, GXCullMode cullMode) {
// clang-format off
// @note NUMCOLORS is actually three bits
LoadBPCmd(GX_BP_REG_SSMASK << GX_BP_OPCODE_SHIFT |
GX_BP_GENMODE_NUMTEX_MASK |
0b11 << GX_BP_GENMODE_NUMCOLORS_SHIFT |
GX_BP_GENMODE_NUMTEVSTAGES_MASK |
GX_BP_GENMODE_CULLMODE_MASK |
GX_BP_GENMODE_NUMINDSTAGES_MASK);
// clang-format on
// clang-format off
LoadBPCmd(
numTexGens << GX_BP_GENMODE_NUMTEX_SHIFT |
numChans << GX_BP_GENMODE_NUMCOLORS_SHIFT |
numTevs - 1 << GX_BP_GENMODE_NUMTEVSTAGES_SHIFT |
cm2hw[cullMode] << GX_BP_GENMODE_CULLMODE_SHIFT |
numInds << GX_BP_GENMODE_NUMINDSTAGES_SHIFT |
GX_BP_REG_GENMODE << GX_BP_OPCODE_SHIFT);
// clang-format on
LoadXFCmd(GX_XF_REG_NUMCOLORS, numChans);
LoadXFCmd(GX_XF_REG_NUMTEX, numTexGens);
}
void GDSetCullMode(GXCullMode cullMode) {
// clang-format off
LoadBPCmd(GX_BP_REG_SSMASK << GX_BP_OPCODE_SHIFT |
GX_BP_GENMODE_CULLMODE_MASK);
// clang-format on
LoadBPCmd(cm2hw[cullMode] << GX_BP_GENMODE_CULLMODE_SHIFT);
}
void GDSetTexCoordScale2(
GXTexCoordID coord, u16 scaleS, GXBool biasS, GXBool wrapS, u16 scaleT, GXBool biasT, GXBool wrapT
) {
// clang-format off
LoadBPCmd(GX_BP_REG_SSMASK << GX_BP_OPCODE_SHIFT |
GX_BP_SU_SIZE_SCALE_MASK |
GX_BP_SU_SIZE_RANGEBIAS_MASK |
GX_BP_SU_SIZE_CYLINDRICWRAP_MASK);
// clang-format on
// clang-format off
LoadBPCmd(
scaleS - 1 << GX_BP_SU_SIZE_SCALE_SHIFT |
biasS << GX_BP_SU_SIZE_RANGEBIAS_SHIFT |
wrapS << GX_BP_SU_SIZE_CYLINDRICWRAP_SHIFT |
GX_BP_REG_SU_SSIZE0 + coord * 2 << GX_BP_OPCODE_SHIFT);
// clang-format on
// clang-format off
LoadBPCmd(
scaleT - 1 << GX_BP_SU_SIZE_SCALE_SHIFT |
biasT << GX_BP_SU_SIZE_RANGEBIAS_SHIFT |
wrapT << GX_BP_SU_SIZE_CYLINDRICWRAP_SHIFT |
GX_BP_REG_SU_TSIZE0 + coord * 2 << GX_BP_OPCODE_SHIFT);
// clang-format on
}
void GDSetIndTexMtx(u32 id, const math::MTX34 &rMtx) {
f32 m00, m01, m02, m10, m11, m12;
f32 a00, a01, a02, a10, a11, a12;
s8 scaleExp = 0;
m00 = rMtx._00;
m01 = rMtx._01;
m02 = rMtx._02;
m10 = rMtx._10;
m11 = rMtx._11;
m12 = rMtx._12;
a00 = math::FAbs(m00);
a01 = math::FAbs(m01);
a02 = math::FAbs(m02);
a10 = math::FAbs(m10);
a11 = math::FAbs(m11);
a12 = math::FAbs(m12);
if (a00 >= 1.0f || a01 >= 1.0f || a02 >= 1.0f || a10 >= 1.0f || a11 >= 1.0f || a12 >= 1.0f) {
do {
if (scaleExp >= 46) {
break;
}
scaleExp++;
m00 /= 2.0f;
m01 /= 2.0f;
m02 /= 2.0f;
m10 /= 2.0f;
m11 /= 2.0f;
m12 /= 2.0f;
a00 /= 2.0f;
a01 /= 2.0f;
a02 /= 2.0f;
a10 /= 2.0f;
a11 /= 2.0f;
a12 /= 2.0f;
} while (a00 >= 1.0f || a01 >= 1.0f || a02 >= 1.0f || a10 >= 1.0f || a11 >= 1.0f || a12 >= 1.0f);
} else if (a00 < 0.5f && a01 < 0.5f && a02 < 0.5f && a10 < 0.5f && a11 < 0.5f && a12 < 0.5f) {
do {
scaleExp--;
m00 *= 2.0f;
m01 *= 2.0f;
m02 *= 2.0f;
m10 *= 2.0f;
m11 *= 2.0f;
m12 *= 2.0f;
a00 *= 2.0f;
a01 *= 2.0f;
a02 *= 2.0f;
a10 *= 2.0f;
a11 *= 2.0f;
a12 *= 2.0f;
if (!(a00 < 0.5f) || !(a01 < 0.5f) || !(a02 < 0.5f) || !(a10 < 0.5f) || !(a11 < 0.5f) || !(a12 < 0.5f)) {
break;
}
} while (scaleExp > -17);
}
// Hardware stores as -17
scaleExp += 17;
// clang-format off
LoadBPCmd(
static_cast<u32>((static_cast<int>(1024.0f * m00) & GX_BP_INDMTXA_M00_LMASK) << GX_BP_INDMTXA_M00_SHIFT) |
static_cast<u32>((static_cast<int>(1024.0f * m10) & GX_BP_INDMTXA_M10_LMASK) << GX_BP_INDMTXA_M10_SHIFT) |
static_cast<u32>((scaleExp >> 0 & GX_BP_INDMTXA_EXP_LMASK) << GX_BP_INDMTXA_EXP_SHIFT) |
static_cast<u32>(id + GX_BP_REG_INDMTX0A << GX_BP_OPCODE_SHIFT));
LoadBPCmd(
static_cast<u32>((static_cast<int>(1024.0f * m01) & GX_BP_INDMTXB_M01_LMASK) << GX_BP_INDMTXB_M01_SHIFT) |
static_cast<u32>((static_cast<int>(1024.0f * m11) & GX_BP_INDMTXB_M11_LMASK) << GX_BP_INDMTXB_M11_SHIFT) |
static_cast<u32>((scaleExp >> 2 & GX_BP_INDMTXB_EXP_LMASK) << GX_BP_INDMTXB_EXP_SHIFT) |
static_cast<u32>((id + GX_BP_REG_INDMTX0B << GX_BP_OPCODE_SHIFT)));
LoadBPCmd(
static_cast<u32>((static_cast<int>(1024.0f * m02) & GX_BP_INDMTXC_M02_LMASK) << GX_BP_INDMTXC_M02_SHIFT) |
static_cast<u32>((static_cast<int>(1024.0f * m12) & GX_BP_INDMTXC_M12_LMASK) << GX_BP_INDMTXC_M12_SHIFT) |
static_cast<u32>((scaleExp >> 4 & GX_BP_INDMTXC_EXP_LMASK) << GX_BP_INDMTXC_EXP_SHIFT) |
static_cast<u32>(id + GX_BP_REG_INDMTX0C << GX_BP_OPCODE_SHIFT));
// clang-format on
}
void GDResetCurrentMtx() {
u32 regA = GX_PNMTX0 << GX_CP_MATRIXINDEXA_POSNRM_SHIFT | GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXA_TEX0_SHIFT |
GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXA_TEX1_SHIFT | GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXA_TEX2_SHIFT |
GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXA_TEX3_SHIFT;
u32 regB = GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXB_TEX4_SHIFT | GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXB_TEX5_SHIFT |
GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXB_TEX6_SHIFT | GX_TEXMTX_IDENT << GX_CP_MATRIXINDEXB_TEX7_SHIFT;
LoadCPCmd(GX_CP_REG_MATRIXINDEXA, regA);
LoadCPCmd(GX_CP_REG_MATRIXINDEXB, regB);
LoadXFCmdHdr(GX_XF_REG_MATRIXINDEX0, 2);
GXCmd1u32(regA);
GXCmd1u32(regB);
}
void GDSetCurrentMtx(const u32 *pIdArray) {
u32 regA = pIdArray[0] << GX_CP_MATRIXINDEXA_TEX0_SHIFT | pIdArray[1] << GX_CP_MATRIXINDEXA_TEX1_SHIFT |
pIdArray[2] << GX_CP_MATRIXINDEXA_TEX2_SHIFT | pIdArray[3] << GX_CP_MATRIXINDEXA_TEX3_SHIFT;
u32 regB = pIdArray[4] << GX_CP_MATRIXINDEXB_TEX4_SHIFT | pIdArray[5] << GX_CP_MATRIXINDEXB_TEX5_SHIFT |
pIdArray[6] << GX_CP_MATRIXINDEXB_TEX6_SHIFT | pIdArray[7] << GX_CP_MATRIXINDEXB_TEX7_SHIFT;
LoadXFCmdHdr(GX_XF_REG_MATRIXINDEX0, 2);
GXCmd1u32(regA);
GXCmd1u32(regB);
}
void GDLoadTexMtxImm3x3(const math::MTX33 &rMtx, u32 id) {
math::MTX34 mtx;
const math::MTX33 *pMtx = &rMtx;
mtx._00 = pMtx->_00;
mtx._01 = pMtx->_01;
mtx._02 = pMtx->_02;
mtx._03 = 0.0f;
mtx._10 = pMtx->_10;
mtx._11 = pMtx->_11;
mtx._12 = pMtx->_12;
mtx._13 = 0.0f;
mtx._20 = pMtx->_20;
mtx._21 = pMtx->_21;
mtx._22 = pMtx->_22;
mtx._23 = 0.0f;
GXLoadTexMtxImm(mtx, id, GX_MTX_3x4);
}
} // namespace fifo
} // namespace g3d
} // namespace nw4r
+305
View File
@@ -0,0 +1,305 @@
#include <nw4r/g3d.h>
// TODO: Naming
enum TMemCachePlan {
TMEM_CACHE_NONE,
TMEM_CACHE_PLAN_0,
TMEM_CACHE_PLAN_1,
TMEM_CACHE_PLAN_2,
TMEM_CACHE_MAX
};
enum TexRegionID {
TEX_REGION_DEFAULT,
TEX_REGION_DEFAULT_MIPMAP,
TEX_REGION_CI,
TEX_REGION_CI_MIPMAP,
TEX_REGION_RGBA8,
TEX_REGION_RGBA8_MIPMAP,
TEX_REGION_MAX
};
struct TexRegionAddr {
u32 addrDefaultEven[GX_MAX_TEXMAP]; // at 0x0
u32 addrDefaultMipMapEven[GX_MAX_TEXMAP]; // at 0x20
u32 addrDefaultMipMapOdd[GX_MAX_TEXMAP]; // at 0x40
u32 addrCiEven[GX_MAX_TEXMAP]; // at 0x60
u32 addrCiMipMapEven[GX_MAX_TEXMAP]; // at 0x80
u32 addrCiMipMapOdd[GX_MAX_TEXMAP]; // at 0xA0
u32 addrRgba8Even[GX_MAX_TEXMAP]; // at 0xC0
u32 addrRgba8Odd[GX_MAX_TEXMAP]; // at 0xE0
u32 addrRgba8MipMapEven[GX_MAX_TEXMAP]; // at 0x100
u32 addrRgba8MipMapOdd[GX_MAX_TEXMAP]; // at 0x120
};
struct TexRegionSize {
u32 sizeDefaultEven[GX_MAX_TEXMAP]; // at 0x0
u32 sizeDefaultMipMapEven[GX_MAX_TEXMAP]; // at 0x20
u32 sizeDefaultMipMapOdd[GX_MAX_TEXMAP]; // at 0x40
u32 sizeCiEven[GX_MAX_TEXMAP]; // at 0x60
u32 sizeCiMipMapEven[GX_MAX_TEXMAP]; // at 0x80
u32 sizeCiMipMapOdd[GX_MAX_TEXMAP]; // at 0xA0
u32 sizeRgba8Even[GX_MAX_TEXMAP]; // at 0xC0
u32 sizeRgba8Odd[GX_MAX_TEXMAP]; // at 0xE0
u32 sizeRgba8MipMapEven[GX_MAX_TEXMAP]; // at 0x100
u32 sizeRgba8MipMapOdd[GX_MAX_TEXMAP]; // at 0x120
};
static GXTexRegion saaTexRegion[TEX_REGION_MAX][GX_MAX_TEXMAP];
static GXTlutRegion saaTlutRegion[GX_BIGTLUT3 + 1];
static TMemCachePlan sTMemCachePlan = TMEM_CACHE_NONE;
static u32 sTlutRegionNum = 0;
static GXTexRegionCallback sfpDefaultTexRegionCallback = NULL;
static GXTlutRegionCallback sfpDefaultTlutRegionCallback = NULL;
// clang-format off
static const TexRegionAddr scaaaTexRegionAddr[TMEM_CACHE_MAX - 1] = {
// TMEM_CACHE_PLAN_0
{
{0x00000, 0x40000, 0x50000, 0x60000, 0x70000, 0x30000, 0x20000, 0x10000}, // addrDefaultEven
{0x00000, 0xB0000, 0x50000, 0x90000, 0x70000, 0xB0000, 0x20000, 0x90000}, // addrDefaultMipMapEven
{0x80000, 0x40000, 0xA0000, 0x60000, 0x80000, 0x30000, 0xA0000, 0x10000}, // addrDefaultMipMapOdd
{0x00000, 0x40000, 0x50000, 0x60000, 0x70000, 0x30000, 0x20000, 0x10000}, // addrCiEven
{0x00000, 0x40000, 0x50000, 0x60000, 0x70000, 0x30000, 0x20000, 0x10000}, // addrCiMipMapEven
{0x20000, 0x48000, 0x58000, 0x68000, 0x78000, 0x38000, 0x28000, 0x18000}, // addrCiMipMapOdd
{0x00000, 0xB0000, 0x50000, 0x90000, 0x70000, 0xB0000, 0x20000, 0x90000}, // addrRgba8Even
{0x80000, 0x40000, 0xA0000, 0x60000, 0x80000, 0x30000, 0xA0000, 0x10000}, // addrRgba8Odd
{0x00000, 0xB0000, 0x50000, 0x90000, 0x70000, 0xB0000, 0x20000, 0x90000}, // addrRgba8MipMapEven
{0x80000, 0x40000, 0xA0000, 0x60000, 0x80000, 0x30000, 0xA0000, 0x10000}, // addrRgba8MipMapOdd
},
// TMEM_CACHE_PLAN_1
{
{0x00000, 0x40000, 0x50000, 0x60000, 0x70000, 0x78000, 0x68000, 0x58000}, // addrDefaultEven
{0x00000, 0xC0000, 0x50000, 0xE0000, 0x70000, 0xD8000, 0x68000, 0xB8000}, // addrDefaultMipMapEven
{0x80000, 0x40000, 0xA0000, 0x60000, 0x80000, 0x30000, 0xA0000, 0x10000}, // addrDefaultMipMapOdd
{0x00000, 0x40000, 0x50000, 0x60000, 0x70000, 0x78000, 0x68000, 0x58000}, // addrCiEven
{0x00000, 0x40000, 0x50000, 0x60000, 0x70000, 0x70000, 0x60000, 0x50000}, // addrCiMipMapEven
{0x20000, 0x48000, 0x58000, 0x68000, 0x78000, 0x78000, 0x68000, 0x58000}, // addrCiMipMapOdd
{0x00000, 0xC0000, 0x50000, 0xE0000, 0x70000, 0xD8000, 0x68000, 0xB8000}, // addrRgba8Even
{0x80000, 0x40000, 0xD0000, 0x60000, 0xE8000, 0x78000, 0xC8000, 0x58000}, // addrRgba8Odd
{0x00000, 0xC0000, 0x50000, 0xE0000, 0x70000, 0xD0000, 0x60000, 0xB0000}, // addrRgba8MipMapEven
{0x80000, 0x40000, 0xD0000, 0x60000, 0xE0000, 0x70000, 0xC0000, 0x50000}, // addrRgba8MipMapOdd
},
// TMEM_CACHE_PLAN_2
{
{0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000}, // addrDefaultEven
{0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000}, // addrDefaultMipMapEven
{0x80000, 0xC0000, 0xC8000, 0xD0000, 0xD0000, 0xC8000, 0xC0000, 0xB0000}, // addrDefaultMipMapOdd
{0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000}, // addrCiEven
{0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000}, // addrCiMipMapEven
{0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000}, // addrCiMipMapOdd
{0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000}, // addrRgba8Even
{0x80000, 0xC0000, 0xC8000, 0xD0000, 0xD0000, 0xC8000, 0xC0000, 0xB0000}, // addrRgba8Odd
{0x00000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x40000, 0x00000}, // addrRgba8MipMapEven
{0x80000, 0xC0000, 0xD0000, 0xE0000, 0xE0000, 0xD0000, 0xC0000, 0xB0000}, // addrRgba8MipMapOdd
},
};
// clang-format on
// clang-format off
static const TexRegionSize scaaaTexRegionSize[TMEM_CACHE_MAX - 1] = {
// TMEM_CACHE_PLAN_0
{
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeDefaultEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeDefaultMipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeDefaultMipMapOdd
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeCiEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeCiMipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeCiMipMapOdd
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8Even
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8Odd
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8MipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8MipMapOdd
},
// TMEM_CACHE_PLAN_1
{
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeDefaultEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeDefaultMipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeDefaultMipMapOdd
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeCiEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeCiMipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeCiMipMapOdd
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8Even
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8Odd
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8MipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8MipMapOdd
},
// TMEM_CACHE_PLAN_2
{
{2, 2, 2, 2, 2, 2, 2, 2}, // sizeDefaultEven
{2, 2, 2, 2, 2, 2, 2, 2}, // sizeDefaultMipMapEven
{1, 1, 1, 1, 1, 1, 0, 0}, // sizeDefaultMipMapOdd
{2, 2, 2, 2, 2, 2, 2, 2}, // sizeCiEven
{2, 2, 2, 2, 2, 2, 2, 2}, // sizeCiMipMapEven
{1, 1, 1, 1, 1, 1, 0, 0}, // sizeCiMipMapOdd
{2, 2, 2, 2, 2, 2, 2, 2}, // sizeRgba8Even
{1, 1, 1, 1, 1, 1, 0, 0}, // sizeRgba8Odd
{1, 1, 1, 1, 1, 1, 1, 1}, // sizeRgba8MipMapEven
{1, 0, 0, 0, 0, 0, 0, 0}, // sizeRgba8MipMapOdd
},
};
// clang-format on
// Forward declarations
static GXTexRegion *TexRegionCallback(const GXTexObj *pObj, GXTexMapID map);
static GXTlutRegion *TlutRegionCallback(u32 id);
static void setTexRegion_(TMemCachePlan plan) __attribute__((never_inline));
namespace nw4r {
namespace g3d {
namespace tmem {
void SetTMemLayout(TMemLayout layout) {
if (sfpDefaultTexRegionCallback == NULL) {
// clang-format off
sfpDefaultTexRegionCallback = GXSetTexRegionCallback(TexRegionCallback);
GXSetTexRegionCallback(sfpDefaultTexRegionCallback);
sfpDefaultTlutRegionCallback = GXSetTlutRegionCallback(TlutRegionCallback);
GXSetTlutRegionCallback(sfpDefaultTlutRegionCallback);
// clang-format on
}
if (sfpDefaultTexRegionCallback == NULL) {
return;
}
sTMemCachePlan = static_cast<TMemCachePlan>(layout);
setTexRegion_(sTMemCachePlan);
switch (layout) {
case TMEM_LAYOUT_NONE:
case TMEM_LAYOUT_1: {
GXSetTlutRegionCallback(sfpDefaultTlutRegionCallback);
break;
}
case TMEM_LAYOUT_2: {
int i;
u32 num = 0;
u32 addr;
GXTlutRegion *pRegion = saaTlutRegion;
for (i = 0, addr = 0xF0000; i < GX_MAX_TEXMAP; i++, pRegion++, num++, addr += 0x2000) {
GXInitTlutRegion(pRegion, addr, 16);
}
sTlutRegionNum = num;
GXSetTlutRegionCallback(TlutRegionCallback);
break;
}
// TODO: Seems to imply no TMEM_LAYOUT_3 exists. Then why the [plan - 1]?
default: {
break;
}
}
}
} // namespace tmem
} // namespace g3d
} // namespace nw4r
static GXTexRegion *TexRegionCallback(const GXTexObj *pObj, GXTexMapID map) {
GXTexFmt fmt = GXGetTexObjFormat(pObj);
GXBool mipmap = GXGetTexObjMipMap(pObj);
switch (fmt) {
case GX_TF_RGBA8: {
return mipmap ? &saaTexRegion[TEX_REGION_RGBA8_MIPMAP][map] : &saaTexRegion[TEX_REGION_RGBA8][map];
}
case GX_TF_C4:
case GX_TF_C8:
case GX_TF_C14X2: {
return mipmap ? &saaTexRegion[TEX_REGION_CI_MIPMAP][map] : &saaTexRegion[TEX_REGION_CI][map];
}
default: {
return mipmap ? &saaTexRegion[TEX_REGION_DEFAULT_MIPMAP][map] : &saaTexRegion[TEX_REGION_DEFAULT][map];
}
}
}
static GXTlutRegion *TlutRegionCallback(u32 id) {
GXTlutRegion *pRegion = NULL;
if (id < sTlutRegionNum) {
pRegion = &saaTlutRegion[id];
}
return pRegion;
}
static void setTexRegion_(TMemCachePlan plan) {
if (plan == TMEM_CACHE_NONE) {
GXSetTexRegionCallback(sfpDefaultTexRegionCallback);
return;
}
for (int i = 0; i < GX_MAX_TEXMAP; i++) {
// clang-format off
GXInitTexCacheRegion(
&saaTexRegion[TEX_REGION_DEFAULT][i],
FALSE,
scaaaTexRegionAddr[plan - 1].addrDefaultEven[i],
scaaaTexRegionSize[plan - 1].sizeDefaultEven[i],
NULL,
3);
GXInitTexCacheRegion(
&saaTexRegion[TEX_REGION_DEFAULT_MIPMAP][i],
FALSE,
scaaaTexRegionAddr[plan - 1].addrDefaultMipMapEven[i],
scaaaTexRegionSize[plan - 1].sizeDefaultMipMapEven[i],
scaaaTexRegionAddr[plan - 1].addrDefaultMipMapOdd[i],
scaaaTexRegionSize[plan - 1].sizeDefaultMipMapOdd[i]);
GXInitTexCacheRegion(
&saaTexRegion[TEX_REGION_CI][i],
FALSE,
scaaaTexRegionAddr[plan - 1].addrCiEven[i],
scaaaTexRegionSize[plan - 1].sizeCiEven[i],
NULL,
3);
GXInitTexCacheRegion(
&saaTexRegion[TEX_REGION_CI_MIPMAP][i],
FALSE,
scaaaTexRegionAddr[plan - 1].addrCiMipMapEven[i],
scaaaTexRegionSize[plan - 1].sizeCiMipMapEven[i],
scaaaTexRegionAddr[plan - 1].addrCiMipMapOdd[i],
scaaaTexRegionSize[plan - 1].sizeCiMipMapOdd[i]);
GXInitTexCacheRegion(
&saaTexRegion[TEX_REGION_RGBA8][i],
FALSE,
scaaaTexRegionAddr[plan - 1].addrRgba8Even[i],
scaaaTexRegionSize[plan - 1].sizeRgba8Even[i],
scaaaTexRegionAddr[plan - 1].addrRgba8Odd[i],
scaaaTexRegionSize[plan - 1].sizeRgba8Odd[i]);
GXInitTexCacheRegion(
&saaTexRegion[TEX_REGION_RGBA8_MIPMAP][i],
FALSE,
scaaaTexRegionAddr[plan - 1].addrRgba8MipMapEven[i],
scaaaTexRegionSize[plan - 1].sizeRgba8MipMapEven[i],
scaaaTexRegionAddr[plan - 1].addrRgba8MipMapOdd[i],
scaaaTexRegionSize[plan - 1].sizeRgba8MipMapOdd[i]);
// clang-format on
}
GXSetTexRegionCallback(TexRegionCallback);
}

Some files were not shown because too many files have changed in this diff Show More