mirror of
https://github.com/zeldaret/ss
synced 2026-08-15 20:59:53 -04:00
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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,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,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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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]);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "m/m3d/m3d.h"
|
||||
#include "m/m_heap.h"
|
||||
|
||||
|
||||
namespace m3d {
|
||||
|
||||
anmMatClr_c::child_c::~child_c() {}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "m/m3d/m3d.h"
|
||||
#include "m/m_heap.h"
|
||||
|
||||
|
||||
namespace m3d {
|
||||
|
||||
int anmTexPat_c::child_c::getType() const {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -0,0 +1,9 @@
|
||||
#include <nw4r/g3d.h>
|
||||
|
||||
namespace nw4r {
|
||||
namespace g3d {
|
||||
|
||||
NW4R_G3D_RTTI_DEF(ScnMdl1Mat1Shp);
|
||||
|
||||
} // namespace g3d
|
||||
} // namespace nw4r
|
||||
@@ -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, ¶m);
|
||||
|
||||
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
|
||||
@@ -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), ¶m);
|
||||
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, ¶m);
|
||||
|
||||
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
|
||||
@@ -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
|
||||
@@ -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), ¶m);
|
||||
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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user