1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
|
#ifndef NW4R_G3D_SCN_OBJ_H
#define NW4R_G3D_SCN_OBJ_H
#include <nw4r/types_nw4r.h>
#include "nw4r/g3d/g3d_obj.h"
#include "nw4r/math.h" // IWYU pragma: export
namespace nw4r {
namespace g3d {
extern const math::FRUSTUM *gpCullingFrustum;
enum ResMdlDrawMode {
RESMDL_DRAWMODE_SORT_OPA_NONE = 0,
RESMDL_DRAWMODE_SORT_OPA_Z = (1 << 0),
RESMDL_DRAWMODE_SORT_XLU_NONE = 0,
RESMDL_DRAWMODE_SORT_XLU_Z = (1 << 1),
RESMDL_DRAWMODE_IGNORE_MATERIAL = (1 << 2),
RESMDL_DRAWMODE_FORCE_LIGHTOFF = (1 << 3),
RESMDL_DRAWMODE_NOPPCSYNC = (1 << 4),
RESMDL_DRAWMODE_DEFAULT = RESMDL_DRAWMODE_SORT_XLU_Z,
REDMDL_DRAWMODE_SORT_NONE = 0,
RESMDL_DRAWMODE_SORT_Z = RESMDL_DRAWMODE_SORT_OPA_Z | RESMDL_DRAWMODE_SORT_XLU_Z,
};
/******************************************************************************
*
* ScnObj
*
******************************************************************************/
// Forward declarations
class IScnObjCallback;
class ScnObj : public G3dObj {
public:
enum ForEachResult {
FOREACHRESULT_OK,
FOREACHRESULT_CONTINUE,
FOREACHRESULT_RETURN,
FOREACHRESULT_GOBACK
};
typedef ForEachResult (*ForEachFunc)(ScnObj *pParent, void *pInfo);
enum ScnObjMtxType {
MTX_LOCAL,
MTX_WORLD,
MTX_VIEW,
MTX_TYPE_MAX
};
enum ScnObjBoundingVolumeType {
BOUNDINGVOLUME_AABB_LOCAL,
BOUNDINGVOLUME_AABB_WORLD,
BOUNDINGVOLUME_MAX
};
#define OPT(KEY, VALUE) OPTION_##KEY = (0x00000 | (VALUE))
enum ScnObjOption {
OPT(NONE, 0),
OPT(DISABLE_GATHER_SCNOBJ, 1),
OPT(DISABLE_CALC_WORLD, 2),
OPT(DISABLE_CALC_MAT, 3),
OPT(DISABLE_CALC_VTX, 4),
OPT(DISABLE_CALC_VIEW, 5),
OPT(DISABLE_DRAW_OPA, 6),
OPT(DISABLE_DRAW_XLU, 7),
OPT(DISABLE_UPDATEFRAME, 8),
OPT(ENABLE_CULLING, 9),
};
#undef OPT
enum Timing {
CALLBACK_TIMING_A = (1 << 0),
CALLBACK_TIMING_B = (1 << 1),
CALLBACK_TIMING_C = (1 << 2)
};
enum ExecOp {
EXECOP_CALC_WORLD = (1 << 0),
EXECOP_CALC_MAT = (1 << 1),
EXECOP_CALC_VIEW = (1 << 2),
EXECOP_DRAW_OPA = (1 << 4),
EXECOP_DRAW_XLU = (1 << 5)
};
public:
explicit ScnObj(MEMAllocator *pAllocator);
virtual void G3dProc(u32 task, u32 param, void *pInfo) = 0; // at 0xC
virtual ~ScnObj(); // at 0x10
virtual ForEachResult ForEach(ForEachFunc pFunc, void *pInfo,
bool postOrder) = 0; // at 0x1C
virtual bool SetScnObjOption(u32 option, u32 value); // at 0x20
virtual bool GetScnObjOption(u32 option, u32 *pValue) const; // at 0x24
virtual f32 GetValueForSortOpa() const; // at 0x28
virtual f32 GetValueForSortXlu() const; // at 0x2C
virtual void CalcWorldMtx(const math::MTX34 *pParent,
u32 *pParam); // at 0x30
void CalcViewMtx(const math::MTX34 *pCamera);
bool SetMtx(ScnObjMtxType type, const math::MTX34 *pMtx);
bool SetMtx(ScnObjMtxType type, const math::MTX34 &rMtx);
bool GetMtx(ScnObjMtxType type, math::MTX34 *pMtx) const;
const math::MTX34 *GetMtxPtr(ScnObjMtxType type) const {
return &mMtxArray[type];
}
void SetPriorityDrawOpa(int prio);
int GetPriorityDrawOpa() const {
return mPriorityDrawOpa;
}
void SetPriorityDrawXlu(int prio);
int GetPriorityDrawXlu() const {
return mPriorityDrawXlu;
}
void EnableScnObjCallbackTiming(Timing timing);
void DisableScnObjCallbackTiming(Timing timing);
void EnableScnObjCallbackExecOp(ExecOp op);
bool SetBoundingVolume(ScnObjBoundingVolumeType type, const math::AABB *pAABB);
bool GetBoundingVolume(ScnObjBoundingVolumeType type, math::AABB *pAABB) const;
bool SetBoundingVolume(const math::AABB *pAABB) {
return SetBoundingVolume(BOUNDINGVOLUME_AABB_LOCAL, pAABB);
}
void SetCallback(IScnObjCallback *cb) {
mpFuncObjExec = cb;
}
IScnObjCallback *GetScnObjCallback() {
return mpFuncObjExec;
}
protected:
enum ScnObjFlag {
SCNOBJFLAG_DISABLE_CALC_WORLD = (1 << 0),
SCNOBJFLAG_DISABLE_CALC_MAT = (1 << 1),
SCNOBJFLAG_DISABLE_CALC_VTX = (1 << 2),
SCNOBJFLAG_DISABLE_CALC_VIEW = (1 << 3),
SCNOBJFLAG_DISABLE_GATHER_SCNOBJ = (1 << 4),
SCNOBJFLAG_DISABLE_DRAW_OPA = (1 << 5),
SCNOBJFLAG_DISABLE_DRAW_XLU = (1 << 6),
SCNOBJFLAG_DISABLE_UPDATEFRAME = (1 << 7),
SCNOBJFLAG_IGNORE_ANMCHR_TRANS = (1 << 8),
SCNOBJFLAG_ENABLE_CULLING = (1 << 28),
SCNOBJFLAG_NOT_GATHER_DRAW_OPA = (1 << 29),
SCNOBJFLAG_NOT_GATHER_DRAW_XLU = (1 << 30),
SCNOBJFLAG_MTX_LOCAL_IDENTITY = (1 << 31),
SCNOBJFLAG_DISABLE_DRAW = SCNOBJFLAG_DISABLE_DRAW_OPA | SCNOBJFLAG_DISABLE_DRAW_XLU
};
protected:
void SetScnObjFlag(ScnObjFlag flag, u32 on) {
if (on) {
mScnObjFlags |= flag;
} else {
mScnObjFlags &= ~flag;
}
}
u32 TestScnObjFlag(ScnObjFlag flag) const {
return (mScnObjFlags & flag) != 0;
}
bool IsG3dProcDisabled(u32 task) const {
if (task < __G3DPROC_OPTIONAL_END && ((1 << (task - 1)) & mScnObjFlags)) {
return true;
}
return false;
}
/**
* Defined elsewhere to resolve circular dependency with IScnObjCallback
*/
inline void CheckCallback_CALC_VIEW(Timing timing, u32 param, void *pInfo);
inline void CheckCallback_CALC_MAT(Timing timing, u32 param, void *pInfo);
inline void CheckCallback_CALC_WORLD(Timing timing, u32 param, void *pInfo);
inline void CheckCallback_DRAW_OPA(Timing timing, u32 param, void *pInfo);
inline void CheckCallback_DRAW_XLU(Timing timing, u32 param, void *pInfo);
protected:
math::MTX34 mMtxArray[MTX_TYPE_MAX]; // at 0xC
math::AABB mAABB[BOUNDINGVOLUME_MAX]; // at 0x9C
private:
u32 mScnObjFlags; // at 0xCC
u8 mPriorityDrawOpa; // at 0xD0
u8 mPriorityDrawXlu; // at 0xD1
u8 PADDING_0xD2; // at 0xD2
u8 PADDING_0xD3; // at 0xD3
IScnObjCallback *mpFuncObjExec; // at 0xD4
u8 mCallbackTiming; // at 0xD8
u8 mCallbackDeleteOption; // at 0xD9
u16 mCallbackExecOpMask; // at 0xDA
NW4R_G3D_RTTI_DECL_DERIVED(ScnObj, G3dObj);
};
/******************************************************************************
*
* IScnObjGather
*
******************************************************************************/
class IScnObjGather {
public:
typedef bool (*LessThanFunc)(const ScnObj *pLhs, const ScnObj *pRhs);
enum CullingStatus {
CULLINGSTATUS_INTERSECT,
CULLINGSTATUS_INSIDE,
CULLINGSTATUS_OUTSIDE,
CULLINGSTATUS_NOTEST
};
enum CheckStatus {
CHECKSTATUS_GATHER_SCNOBJ,
CHECKSTATUS_IGNORE_SCNOBJ
};
public:
virtual ~IScnObjGather() {} // at 0x8
virtual CullingStatus Add(ScnObj *pObj, bool opa, bool xlu) = 0; // at 0xC
virtual void Clear() = 0; // at 0x10
virtual void ZSort() = 0; // at 0x14
virtual void Sort() = 0; // at 0x18
virtual void Sort(LessThanFunc pOpaFunc,
LessThanFunc pXluFunc) = 0; // at 0x1C
virtual void DrawOpa(ResMdlDrawMode *pForceMode) = 0; // at 0x20
virtual void DrawXlu(ResMdlDrawMode *pForceMode) = 0; // at 0x24
};
/******************************************************************************
*
* IScnObjCallback
*
******************************************************************************/
class IScnObjCallback {
public:
virtual ~IScnObjCallback() {} // at 0x8
virtual void
ExecCallback_CALC_WORLD(ScnObj::Timing /* timing */, ScnObj * /* pObj */, u32 /* param */, void * /* pInfo */) {
} // at 0xC
virtual void
ExecCallback_CALC_MAT(ScnObj::Timing /* timing */, ScnObj * /* pObj */, u32 /* param */, void * /* pInfo */) {
} // at 0x10
virtual void
ExecCallback_CALC_VIEW(ScnObj::Timing /* timing */, ScnObj * /* pObj */, u32 /* param */, void * /* pInfo */) {
} // at 0x14
virtual void
ExecCallback_DRAW_OPA(ScnObj::Timing /* timing */, ScnObj * /* pObj */, u32 /* param */, void * /* pInfo */) {
} // at 0x18
virtual void
ExecCallback_DRAW_XLU(ScnObj::Timing /* timing */, ScnObj * /* pObj */, u32 /* param */, void * /* pInfo */) {
} // at 0x1C
};
/******************************************************************************
*
* ScnObj implementation
*
******************************************************************************/
void ScnObj::CheckCallback_CALC_VIEW(Timing timing, u32 param, void *pInfo) {
if (mpFuncObjExec != NULL && (mCallbackExecOpMask & EXECOP_CALC_VIEW) && (mCallbackTiming & timing)) {
mpFuncObjExec->ExecCallback_CALC_VIEW(timing, this, param, pInfo);
}
}
void ScnObj::CheckCallback_CALC_MAT(Timing timing, u32 param, void *pInfo) {
if (mpFuncObjExec != NULL && (mCallbackExecOpMask & EXECOP_CALC_MAT) && (mCallbackTiming & timing)) {
mpFuncObjExec->ExecCallback_CALC_MAT(timing, this, param, pInfo);
}
}
void ScnObj::CheckCallback_CALC_WORLD(Timing timing, u32 param, void *pInfo) {
if (mpFuncObjExec != NULL && (mCallbackExecOpMask & EXECOP_CALC_WORLD) && (mCallbackTiming & timing)) {
mpFuncObjExec->ExecCallback_CALC_WORLD(timing, this, param, pInfo);
}
}
void ScnObj::CheckCallback_DRAW_OPA(Timing timing, u32 param, void *pInfo) {
if (mpFuncObjExec != NULL && (mCallbackExecOpMask & EXECOP_DRAW_OPA) && (mCallbackTiming & timing)) {
mpFuncObjExec->ExecCallback_DRAW_OPA(timing, this, param, pInfo);
}
}
void ScnObj::CheckCallback_DRAW_XLU(Timing timing, u32 param, void *pInfo) {
if (mpFuncObjExec != NULL && (mCallbackExecOpMask & EXECOP_DRAW_XLU) && (mCallbackTiming & timing)) {
mpFuncObjExec->ExecCallback_DRAW_XLU(timing, this, param, pInfo);
}
}
/******************************************************************************
*
* ScnLeaf
*
******************************************************************************/
class ScnLeaf : public ScnObj {
public:
enum ScaleProperty {
NOT_SCALED,
UNIFORM_SCALED,
NONUNIFORM_SCALED,
};
#define OPT(KEY, VALUE) OPTION_##KEY = (0x10000 | (VALUE))
enum ScnLeafOption {
OPT(NONE, 0),
OPT(DISABLE_DRAW_ALL, 1),
};
#undef OPT
public:
explicit ScnLeaf(MEMAllocator *pAllocator) : ScnObj(pAllocator), mScale(1.0f, 1.0f, 1.0f) {}
virtual void G3dProc(u32 task, u32 param, void *pInfo) = 0; // at 0xC
virtual ~ScnLeaf() {} // at 0x10
virtual ForEachResult ForEach(ForEachFunc pFunc, void *pInfo,
bool postOrder); // at 0x1C
virtual bool SetScnObjOption(u32 option, u32 value); // at 0x20
virtual bool GetScnObjOption(u32 option, u32 *pValue) const; // at 0x24
virtual void CalcWorldMtx(const math::MTX34 *pParent,
u32 *pParam); // at 0x30
ScaleProperty GetScaleProperty() const;
inline void SetScale(f32 x, f32 y, f32 z) {
mScale.x = x;
mScale.y = y;
mScale.z = z;
}
inline void SetScale(const math::VEC3 &scale) {
mScale = scale;
}
inline void GetScale(math::VEC3 *scale) const {
if (scale) {
*scale = mScale;
}
}
protected:
void DefG3dProcScnLeaf(u32 task, u32 param, void *pInfo);
private:
math::VEC3 mScale; // at 0xDC
NW4R_G3D_RTTI_DECL_DERIVED(ScnLeaf, ScnObj);
};
/******************************************************************************
*
* ScnGroup
*
******************************************************************************/
class ScnGroup : public ScnObj {
public:
ScnGroup(MEMAllocator *pAllocator, ScnObj **ppObj, u32 capacity);
virtual void G3dProc(u32 task, u32 param, void *pInfo); // at 0xC
virtual ~ScnGroup(); // at 0x10
virtual ForEachResult ForEach(ForEachFunc pFunc, void *pInfo,
bool postOrder); // at 0x1C
virtual bool Insert(u32 idx, ScnObj *pObj); // at 0x34
virtual ScnObj *Remove(u32 idx); // at 0x38
virtual bool Remove(ScnObj *pObj); // at 0x3C
ScnObj **Begin() {
return mpScnObjArray;
}
ScnObj **End() {
return mpScnObjArray + mNumScnObj;
}
ScnObj *operator[](u32 idx) {
return mpScnObjArray[idx];
}
u32 Size() const {
return mNumScnObj;
}
bool Empty() const {
return mNumScnObj == 0;
}
bool PushBack(ScnObj *pObj) {
return Insert(mNumScnObj, pObj);
}
ScnObj *PopBack() {
if (!Empty()) {
return Remove(Size() - 1);
}
return NULL;
}
void Clear() {
while (!Empty()) {
PopBack();
}
}
protected:
void DefG3dProcScnGroup(u32 task, u32 param, void *pInfo);
private:
void ScnGroup_G3DPROC_GATHER_SCNOBJ(u32 param, IScnObjGather *pCollection);
void ScnGroup_G3DPROC_CALC_WORLD(u32 param, const math::MTX34 *pParent);
void ScnGroup_G3DPROC_CALC_MAT(u32 param, void *pInfo);
void ScnGroup_G3DPROC_CALC_VIEW(u32 param, const math::MTX34 *pCamera);
private:
ScnObj **mpScnObjArray; // at 0xDC
u32 mSizeScnObj; // at 0xE0
u32 mNumScnObj; // at 0xE4
NW4R_G3D_RTTI_DECL_DERIVED(ScnGroup, ScnObj);
};
} // namespace g3d
} // namespace nw4r
#endif
|