Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/goddard/dynlist_proc.c
7858 views
1
#include <PR/ultratypes.h>
2
#include <stdio.h>
3
4
#include "bad_declarations.h"
5
#include "debug_utils.h"
6
#include "draw_objects.h"
7
#include "dynlist_proc.h"
8
#include "gd_main.h"
9
#include "gd_math.h"
10
#include "gd_types.h"
11
#include "joints.h"
12
#include "macros.h"
13
#include "objects.h"
14
#include "old_menu.h"
15
#include "particles.h"
16
#include "renderer.h"
17
#include "shape_helper.h"
18
#include "skin.h"
19
20
/**
21
* @file dynlist_proc.c
22
*
23
* Functions for parsing and processing Goddard's DynList object format.
24
* It also has utility functions for abstracting at runtime over the various
25
* flavors of `GdObj`s.
26
*/
27
28
// constants
29
/// Size of the dynamic object name buffer
30
#define DYNOBJ_NAME_SIZE 8
31
/// Total number of dynamic `GdObj`s that can be created
32
#define DYNOBJ_LIST_SIZE 3000
33
/// Maximum number of verticies supported when adding vertices node to an `ObjShape`
34
#define VTX_BUF_SIZE 3000
35
36
// types
37
/// Information about a dynamically created `GdObj`
38
struct DynObjInfo {
39
char name[DYNOBJ_NAME_SIZE];
40
struct GdObj *obj;
41
s32 num;
42
s32 unk;
43
};
44
/// @name DynList Accessors
45
/// Accessor marcos for easy interpretation of data in a `DynList` packet
46
///@{
47
#define Dyn1AsInt(dyn) ((dyn)->w1.word)
48
#define Dyn1AsPtr(dyn) ((dyn)->w1.ptr)
49
#define Dyn1AsStr(dyn) ((dyn)->w1.str)
50
#define Dyn1AsName(dyn) ((DynObjName)((dyn)->w1.ptr))
51
52
#define Dyn2AsInt(dyn) ((dyn)->w2.word)
53
#define Dyn2AsPtr(dyn) ((dyn)->w2.ptr)
54
#define Dyn2AsStr(dyn) ((dyn)->w2.str)
55
#define Dyn2AsName(dyn) ((DynObjName)((dyn)->w2.ptr))
56
57
#define DynVec(dyn) (&(dyn)->vec)
58
#define DynVecX(dyn) ((dyn)->vec.x)
59
#define DynVecY(dyn) ((dyn)->vec.y)
60
#define DynVecZ(dyn) ((dyn)->vec.z)
61
///@}
62
63
// data
64
static struct DynObjInfo *sGdDynObjList = NULL; // @ 801A8250; info for all loaded/made dynobjs
65
static struct GdObj *sDynListCurObj = NULL; // @ 801A8254
66
static struct GdBoundingBox sNullBoundingBox = { // @ 801A8258
67
0.0, 0.0, 0.0,
68
0.0, 0.0, 0.0
69
};
70
static s32 sUseIntegerNames = FALSE; // if TRUE, then all DynNames are specified as integers
71
72
// bss
73
static char sIntToStringBuf[DYNOBJ_NAME_SIZE]; ///< buffer for returning formated string from
74
///< `integer_name_to_string()`
75
static struct DynObjInfo sNullDynObjInfo; // @ 801B9F08
76
static char sDynNameSuffix[DYNOBJ_NAME_SIZE]; // @ 801B9F20; small buf for printing dynid to?
77
static s32
78
sUnnamedObjCount; // @ 801B9F28; used to print empty string ids (not NULL char *) to sDynNameSuffix
79
static s32 sLoadedDynObjs; // @ 801B9F2C; total loaded dynobjs
80
static struct DynObjInfo *sDynListCurInfo; // @ 801B9F30; info for most recently added object
81
static struct DynObjInfo *sParentObjInfo; ///< Information for `ObjNet` made by `d_add_net_with_subgroup()` or `ObjJoint` made by `d_attach_joint_to_net()`
82
static struct DynObjInfo *sStashedDynObjInfo; // @ 801B9F38
83
static struct GdObj *sStashedDynObj; // @ 801B9F3C
84
static s32 sDynNetCount; // @ 801B9F40
85
static char sDynNetNameSuffix[0x20]; // @ 801B9F48
86
static char sStashedDynNameSuffix[0x100]; // @ 801B9F68
87
88
// necessary foreward declarations
89
void d_add_net_with_subgroup(s32, DynObjName);
90
void d_end_net_with_subgroup(DynObjName);
91
void d_attach_joint_to_net(s32, DynObjName);
92
void d_addto_group(DynObjName);
93
void d_link_with(DynObjName);
94
void d_link_with_ptr(void *);
95
void d_set_normal(f32, f32, f32);
96
void d_make_vertex(struct GdVec3f *);
97
void d_set_rotation(f32, f32, f32);
98
void d_center_of_gravity(f32, f32, f32);
99
void d_set_shape_offset(f32, f32, f32);
100
void d_clear_flags(s32);
101
void d_attach(DynObjName);
102
void d_attach_to(s32, struct GdObj *);
103
void d_attachto_dynid(s32, DynObjName);
104
void d_set_att_offset(const struct GdVec3f *);
105
void d_set_nodegroup(DynObjName);
106
void d_set_matgroup(DynObjName);
107
void d_set_skinshape(DynObjName);
108
void d_set_planegroup(DynObjName);
109
void d_set_shapeptr(DynObjName);
110
void d_friction(f32, f32, f32);
111
void d_set_spring(f32);
112
void d_set_ambient(f32, f32, f32);
113
void d_set_control_type(s32);
114
void d_set_skin_weight(s32, f32);
115
void d_set_id(s32);
116
void d_set_material(void *, s32);
117
void d_map_materials(DynObjName);
118
void d_map_vertices(DynObjName);
119
void d_set_texture_st(f32, f32);
120
void d_use_texture(void *);
121
void d_make_netfromshapeid(DynObjName);
122
void d_make_netfromshape_ptrptr(struct ObjShape **);
123
void add_to_dynobj_list(struct GdObj *, DynObjName);
124
125
/**
126
* Store the active dynamic `GdObj` into a one object stash.
127
*/
128
void d_stash_dynobj(void) {
129
sStashedDynObjInfo = sDynListCurInfo;
130
sStashedDynObj = sDynListCurObj;
131
}
132
133
/**
134
* Set the stashed `GdObj` as the active dynamic `GdObj`.
135
*/
136
void d_unstash_dynobj(void) {
137
sDynListCurObj = sStashedDynObj;
138
sDynListCurInfo = sStashedDynObjInfo;
139
}
140
141
/**
142
* Reset dynlist related variables to a starting state
143
*/
144
void reset_dynlist(void) {
145
sUnnamedObjCount = 0;
146
sLoadedDynObjs = 0;
147
sDynNameSuffix[0] = '\0';
148
sGdDynObjList = NULL;
149
sDynListCurObj = NULL;
150
sDynNetCount = 0;
151
sUseIntegerNames = FALSE;
152
gd_strcpy(sNullDynObjInfo.name, "NullObj");
153
}
154
155
/**
156
* Parse a `DynList` array into active `GdObj`s.
157
*
158
* @returns Pointer to current dynamically created dynamic `GdObj`.
159
* Normally the dynlist specifically sets an object for return.
160
*/
161
struct GdObj *proc_dynlist(struct DynList *dylist) {
162
UNUSED u32 pad[2];
163
164
if (dylist++->cmd != 0xD1D4) {
165
fatal_printf("proc_dynlist() not a valid dyn list");
166
}
167
168
while (dylist->cmd != 58) {
169
switch (dylist->cmd) {
170
case 43:
171
d_set_name_suffix(Dyn1AsStr(dylist));
172
break;
173
case 15:
174
d_makeobj(Dyn2AsInt(dylist), Dyn1AsName(dylist));
175
break;
176
case 46:
177
d_add_net_with_subgroup(Dyn2AsInt(dylist), Dyn1AsName(dylist));
178
break;
179
case 48:
180
d_end_net_with_subgroup(Dyn1AsName(dylist));
181
break;
182
case 47:
183
d_attach_joint_to_net(Dyn2AsInt(dylist), Dyn1AsName(dylist));
184
break;
185
case 16:
186
d_start_group(Dyn1AsName(dylist));
187
break;
188
case 17:
189
d_end_group(Dyn1AsName(dylist));
190
break;
191
case 18:
192
d_addto_group(Dyn1AsName(dylist));
193
break;
194
case 30:
195
d_use_obj(Dyn1AsName(dylist));
196
break;
197
case 28:
198
d_link_with(Dyn1AsName(dylist));
199
break;
200
case 50:
201
d_add_valptr(Dyn1AsName(dylist), (u32) DynVecY(dylist), Dyn2AsInt(dylist),
202
(size_t) DynVecX(dylist));
203
break;
204
case 29:
205
d_link_with_ptr(Dyn1AsPtr(dylist));
206
break;
207
case 12:
208
proc_dynlist(Dyn1AsPtr(dylist));
209
break;
210
case 0:
211
d_use_integer_names(Dyn2AsInt(dylist));
212
break;
213
case 1:
214
d_set_init_pos(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
215
break;
216
case 2:
217
d_set_rel_pos(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
218
break;
219
case 3:
220
d_set_world_pos(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
221
break;
222
case 4:
223
d_set_normal(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
224
break;
225
case 5:
226
d_set_scale(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
227
break;
228
case 49:
229
d_make_vertex(DynVec(dylist));
230
break;
231
case 6:
232
d_set_rotation(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
233
break;
234
case 27:
235
d_center_of_gravity(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
236
break;
237
case 26:
238
d_set_shape_offset(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
239
break;
240
case 44:
241
d_set_parm_f(Dyn2AsInt(dylist), DynVecX(dylist));
242
break;
243
case 45:
244
d_set_parm_ptr(Dyn2AsInt(dylist), Dyn1AsPtr(dylist));
245
break;
246
case 8:
247
d_set_flags(Dyn2AsInt(dylist));
248
break;
249
case 9:
250
d_clear_flags(Dyn2AsInt(dylist));
251
break;
252
case 7:
253
d_set_obj_draw_flag(Dyn2AsInt(dylist));
254
break;
255
case 39:
256
d_attach(Dyn1AsName(dylist));
257
break;
258
case 40:
259
d_attachto_dynid(Dyn2AsInt(dylist), Dyn1AsName(dylist));
260
break;
261
case 41:
262
d_set_att_offset(DynVec(dylist));
263
break;
264
case 21:
265
d_set_nodegroup(Dyn1AsName(dylist));
266
break;
267
case 20:
268
d_set_matgroup(Dyn1AsName(dylist));
269
break;
270
case 22:
271
d_set_skinshape(Dyn1AsName(dylist));
272
break;
273
case 23:
274
d_set_planegroup(Dyn1AsName(dylist));
275
break;
276
case 24:
277
d_set_shapeptrptr(Dyn1AsPtr(dylist));
278
break;
279
case 25:
280
d_set_shapeptr(Dyn1AsName(dylist));
281
break;
282
case 19:
283
d_set_type(Dyn2AsInt(dylist));
284
break;
285
case 13:
286
d_set_colour_num(Dyn2AsInt(dylist));
287
break;
288
case 10:
289
d_friction(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
290
break;
291
case 11:
292
d_set_spring(DynVecX(dylist));
293
break;
294
case 33:
295
d_set_ambient(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
296
break;
297
case 34:
298
d_set_diffuse(DynVecX(dylist), DynVecY(dylist), DynVecZ(dylist));
299
break;
300
case 31:
301
d_set_control_type(Dyn2AsInt(dylist));
302
break;
303
case 32:
304
d_set_skin_weight(Dyn2AsInt(dylist), DynVecX(dylist));
305
break;
306
case 35:
307
d_set_id(Dyn2AsInt(dylist));
308
break;
309
case 36:
310
d_set_material(Dyn1AsPtr(dylist), Dyn2AsInt(dylist));
311
break;
312
case 37:
313
d_map_materials(Dyn1AsName(dylist));
314
break;
315
case 38:
316
d_map_vertices(Dyn1AsName(dylist));
317
break;
318
case 53:
319
d_set_texture_st(DynVecX(dylist), DynVecY(dylist));
320
break;
321
case 52:
322
d_use_texture(Dyn2AsPtr(dylist));
323
break;
324
case 54:
325
d_make_netfromshapeid(Dyn1AsName(dylist));
326
break;
327
case 55:
328
d_make_netfromshape_ptrptr(Dyn1AsPtr(dylist));
329
break;
330
default:
331
fatal_printf("proc_dynlist(): unkown command");
332
}
333
dylist++;
334
}
335
336
return sDynListCurObj;
337
}
338
339
/**
340
* Copy input `str` into a buffer that will be concatenated to a dynamic
341
* `GdObj`'s name string when creating a new dynamic object. If input
342
* is `NULL`, then a generic string is created based on the number of
343
* unnamed objects.
344
*/
345
void d_set_name_suffix(char *str) {
346
if (str != NULL) {
347
if (str[0] == '\0') {
348
sprintf(sDynNameSuffix, "__%d", ++sUnnamedObjCount);
349
} else {
350
gd_strcpy(sDynNameSuffix, str);
351
}
352
} else {
353
sDynNameSuffix[0] = '\0';
354
}
355
}
356
357
/**
358
* Concatenate input `str` into a buffer that will be concatenated to a dynamic
359
* `GdObj`'s name string when creating a new dynamic object. If input
360
* is `NULL`, then a generic string is created based on the number of
361
* unnamed objects.
362
*
363
* @note Not called
364
*/
365
void d_append_to_name_suffix(char *str) {
366
char buf[0xff + 1];
367
368
if (str != NULL) {
369
if (str[0] == '\0') {
370
sprintf(buf, "__%d", ++sUnnamedObjCount);
371
} else {
372
gd_strcpy(buf, str);
373
}
374
} else {
375
buf[0] = '\0';
376
}
377
378
gd_strcat(sDynNameSuffix, buf);
379
}
380
381
/**
382
* Stash the current string that is appended to a created dynamic `GdObj` name.
383
*/
384
static void stash_name_suffix(void) {
385
gd_strcpy(sStashedDynNameSuffix, sDynNameSuffix);
386
}
387
388
/**
389
* Pop the stash for the string that is appended to a created dynamic `GdObj` name.
390
*/
391
static void unstash_name_suffix(void) {
392
gd_strcpy(sDynNameSuffix, sStashedDynNameSuffix);
393
}
394
395
/**
396
* Get the `DynObjInfo` struct for object `name`
397
*
398
* @param name Either a string or integer id for a dynamic `GdObj`
399
* @returns pointer to that object's information
400
*/
401
static struct DynObjInfo *get_dynobj_info(DynObjName name) {
402
struct DynObjInfo *foundDynobj;
403
char buf[0x100];
404
s32 i;
405
406
if (sLoadedDynObjs == 0) {
407
return NULL;
408
}
409
410
if (sUseIntegerNames) {
411
sprintf(buf, "N%d", DynNameAsInt(name));
412
} else {
413
gd_strcpy(buf, DynNameAsStr(name));
414
}
415
416
gd_strcat(buf, sDynNameSuffix);
417
foundDynobj = NULL;
418
for (i = 0; i < sLoadedDynObjs; i++) {
419
if (gd_str_not_equal(sGdDynObjList[i].name, buf) == 0)
420
{
421
foundDynobj = &sGdDynObjList[i];
422
break;
423
}
424
}
425
426
return foundDynobj;
427
}
428
429
/**
430
* Reset the number of created dynamic objects and
431
* free the dynamic object information list (`sGdDynObjList`).
432
* The objects themselves still exist, though.
433
*
434
* @note Not called
435
*/
436
void reset_dynamic_objs(void) {
437
UNUSED s32 pad;
438
439
if (sLoadedDynObjs == 0) {
440
return;
441
}
442
443
gd_free(sGdDynObjList);
444
sLoadedDynObjs = 0;
445
sGdDynObjList = NULL;
446
}
447
448
/**
449
* Create an `ObjNet` and an associated node `ObjGroup`. This function creates
450
* its own naming string to append to later created dynamic objects.
451
*/
452
void d_add_net_with_subgroup(UNUSED s32 a0, DynObjName name) {
453
d_makeobj(D_NET, name);
454
d_set_obj_draw_flag(OBJ_INVISIBLE);
455
// this creates a string to append to the names of the objs created after this
456
sprintf(sDynNetNameSuffix, "c%d", ++sDynNetCount);
457
d_set_type(4);
458
stash_name_suffix();
459
d_set_name_suffix(sDynNetNameSuffix);
460
d_start_group(name);
461
unstash_name_suffix();
462
d_use_obj(name);
463
sParentObjInfo = sDynListCurInfo;
464
}
465
466
/**
467
* End the `ObjNet`+`ObjGroup` set created by `d_add_net_with_subgroup()`.
468
*/
469
void d_end_net_with_subgroup(DynObjName name) {
470
d_use_obj(name);
471
stash_name_suffix();
472
d_set_name_suffix(sDynNetNameSuffix);
473
d_end_group(name);
474
d_set_nodegroup(name);
475
unstash_name_suffix();
476
sParentObjInfo = NULL;
477
}
478
479
/**
480
* Create an `ObjJoint` and attach that to the `ObjNet` created by
481
* `d_add_net_with_subgroup()` or the most recent `ObjJoint` created
482
* by `d_attach_joint_to_net()`.
483
*
484
* @param arg0 Not used
485
* @param name Name for created `ObjJoint`
486
*/
487
void d_attach_joint_to_net(UNUSED s32 arg0, DynObjName name) {
488
UNUSED struct DynObjInfo *curInfo = sDynListCurInfo;
489
UNUSED u32 pad[2];
490
491
d_makeobj(D_JOINT, name);
492
d_set_type(3);
493
d_set_shapeptrptr(NULL);
494
d_attach_to(0xD, sParentObjInfo->obj);
495
sParentObjInfo = sDynListCurInfo;
496
}
497
498
/**
499
* Create a new `ObjNet` linked with the dynamic `ObjShape` `name`.
500
* The newly made net is added to the dynamic object list.
501
*/
502
void d_make_netfromshapeid(DynObjName name) {
503
struct DynObjInfo *dyninfo = get_dynobj_info(name);
504
struct ObjNet *net;
505
506
if (dyninfo == NULL) {
507
fatal_printf("dMakeNetFromShape(\"%s\"): Undefined object", DynNameAsStr(name));
508
}
509
510
net = make_netfromshape((struct ObjShape *) dyninfo->obj);
511
add_to_dynobj_list(&net->header, NULL);
512
}
513
514
/**
515
* Create a new `ObjNet` linked with the doubly indirected `ObjShape`.
516
* The newly made net is added to the dynamic object list, but
517
* the shape is not moved into the dynamic list.
518
*/
519
void d_make_netfromshape_ptrptr(struct ObjShape **shapePtr) {
520
UNUSED u32 pad;
521
struct ObjNet *net = make_netfromshape(*shapePtr);
522
523
printf("dMakeNetFromShapePtrPtr\n");
524
525
add_to_dynobj_list(&net->header, NULL);
526
}
527
528
/**
529
* Add `newobj` identified by `name` to the dynamic `GdObj` list. Once a `GdObj`
530
* is in the dynamic list, it can referred to by its `name` when that object is
531
* needed later.
532
*/
533
void add_to_dynobj_list(struct GdObj *newobj, DynObjName name) {
534
UNUSED u32 pad;
535
char idbuf[0x100];
536
537
start_memtracker("dynlist");
538
539
if (sGdDynObjList == NULL) {
540
sGdDynObjList = gd_malloc_temp(DYNOBJ_LIST_SIZE * sizeof(struct DynObjInfo));
541
if (sGdDynObjList == NULL) {
542
fatal_printf("dMakeObj(): Cant allocate dynlist memory");
543
}
544
}
545
546
stop_memtracker("dynlist");
547
548
if (sUseIntegerNames) {
549
sprintf(idbuf, "N%d", DynNameAsInt(name));
550
name = NULL;
551
} else {
552
sprintf(idbuf, "U%d", ((u32) sLoadedDynObjs) + 1);
553
}
554
555
if (DynNameAsStr(name) != NULL) {
556
if (get_dynobj_info(name) != NULL) {
557
fatal_printf("dMakeObj(\"%s\"): Object with same name already exists", DynNameAsStr(name));
558
}
559
gd_strcpy(sGdDynObjList[sLoadedDynObjs].name, DynNameAsStr(name));
560
} else {
561
gd_strcpy(sGdDynObjList[sLoadedDynObjs].name, idbuf);
562
}
563
564
gd_strcat(sGdDynObjList[sLoadedDynObjs].name, sDynNameSuffix);
565
566
if (gd_strlen(sGdDynObjList[sLoadedDynObjs].name) > (DYNOBJ_NAME_SIZE - 1)) {
567
fatal_printf("dyn list obj name too long '%s'", sGdDynObjList[sLoadedDynObjs].name);
568
}
569
570
sGdDynObjList[sLoadedDynObjs].num = sLoadedDynObjs;
571
sDynListCurInfo = &sGdDynObjList[sLoadedDynObjs];
572
sGdDynObjList[sLoadedDynObjs++].obj = newobj;
573
574
// A good place to bounds-check your array is
575
// after you finish writing a new member to it.
576
if (sLoadedDynObjs >= DYNOBJ_LIST_SIZE) {
577
fatal_printf("dMakeObj(): Too many dynlist objects");
578
}
579
580
sDynListCurObj = newobj;
581
}
582
583
/**
584
* Format `name` into string, if `DynObjName`s are currently being interpreted
585
* as numbers.
586
*
587
* @returns pointer to global buffer for id
588
* @retval NULL if `name` is `NULL` or if `DynObjName`s are interpreted as strings
589
*/
590
static char *integer_name_to_string(DynObjName name) {
591
if (DynNameAsInt(name) != 0 && sUseIntegerNames) {
592
sprintf(sIntToStringBuf, "N%d", DynNameAsInt(name));
593
return sIntToStringBuf;
594
}
595
596
return NULL;
597
}
598
599
/**
600
* Create a new `GdObj` of `type` and add that object to the
601
* dynamic object list with `name`. Created objects have default
602
* parameters, which are usually 0 or NULL.
603
*
604
* @returns pointer to created object
605
*/
606
struct GdObj *d_makeobj(enum DObjTypes type, DynObjName name) {
607
struct GdObj *dobj;
608
UNUSED struct ObjGroup *dgroup;
609
610
switch (type) {
611
case D_CAR_DYNAMICS:
612
fatal_printf("dmakeobj() Car dynamics are missing!");
613
break;
614
case D_JOINT:
615
dobj = &make_joint(0, 0.0f, 0.0f, 0.0f)->header;
616
break;
617
case D_ANOTHER_JOINT:
618
dobj = &make_joint(0, 0.0f, 0.0f, 0.0f)->header;
619
break;
620
case D_NET:
621
dobj = &make_net(0, NULL, NULL, NULL, NULL)->header;
622
break;
623
case D_GROUP:
624
dobj = &make_group(0)->header;
625
dgroup = (struct ObjGroup *) dobj;
626
break;
627
case D_DATA_GRP:
628
d_makeobj(D_GROUP, name);
629
((struct ObjGroup *) sDynListCurObj)->linkType = 1;
630
//! @bug Returns garbage when making `D_DATA_GRP` object
631
#ifdef AVOID_UB
632
return NULL;
633
#else
634
return;
635
#endif
636
case D_CAMERA:
637
dobj = &make_camera(0, NULL)->header;
638
break;
639
case D_BONE:
640
dobj = &make_bone(0, NULL, NULL, 0)->header;
641
break;
642
case D_PARTICLE:
643
dobj = &make_particle(0, 0, 0.0f, 0.0f, 0.0f)->header;
644
break;
645
case D_VERTEX:
646
dobj = &gd_make_vertex(0.0f, 0.0f, 0.0f)->header;
647
break;
648
case D_FACE:
649
dobj = &make_face_with_colour(1.0, 1.0, 1.0)->header;
650
break;
651
case D_PLANE:
652
dobj = &make_plane(FALSE, NULL)->header;
653
break;
654
case D_MATERIAL:
655
dobj = &make_material(0, NULL, 0)->header;
656
break;
657
case D_SHAPE:
658
dobj = &make_shape(0, integer_name_to_string(name))->header;
659
break;
660
case D_GADGET:
661
dobj = &make_gadget(0, 0)->header;
662
break;
663
case D_LABEL:
664
//! @bug When making a `D_LABEL`, the call to `make_label()`
665
//! compiles incorrectly due to Goddard only declaring
666
//! the functions, not prototyping the functions
667
dobj = &make_label(NULL, NULL, 8, 0, 0, 0)->header;
668
break;
669
case D_VIEW:
670
dobj = &make_view(NULL,
671
(VIEW_2_COL_BUF | VIEW_ALLOC_ZBUF | VIEW_UNK_2000 | VIEW_UNK_4000
672
| VIEW_1_CYCLE | VIEW_MOVEMENT | VIEW_DRAW),
673
2, 0, 0, 0, 0, NULL)
674
->header;
675
break;
676
case D_ANIMATOR:
677
dobj = &make_animator()->header;
678
break;
679
case D_LIGHT:
680
dobj = &make_light(0, NULL, 0)->header;
681
addto_group(gGdLightGroup, dobj);
682
break;
683
default:
684
fatal_printf("dMakeObj(): Unkown object type");
685
}
686
687
add_to_dynobj_list(dobj, name);
688
return dobj;
689
}
690
691
/**
692
* Attach dynamic object `name` to the current active `ObjJoint` object.
693
*
694
* @note This function doesn't actually do anything.
695
*/
696
void d_attach(DynObjName name) {
697
struct DynObjInfo *info;
698
699
if (sDynListCurObj == NULL) {
700
fatal_printf("proc_dynlist(): No current object");
701
}
702
703
info = get_dynobj_info(name);
704
if (info == NULL) {
705
fatal_printf("dAttach(\"%s\"): Undefined object", DynNameAsStr(name));
706
}
707
708
switch (sDynListCurObj->type) {
709
case OBJ_TYPE_JOINTS:
710
break;
711
default:
712
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dAttach()",
713
sDynListCurInfo->name, sDynListCurObj->type);
714
}
715
}
716
717
/**
718
* Attach the current dynamic `GdObj` into the proper subgroup of `obj` and set
719
* the "attach flags" of the current dynamic object to `flag`
720
*/
721
void d_attach_to(s32 flag, struct GdObj *obj) {
722
UNUSED u32 pad4C;
723
struct ObjGroup *attgrp;
724
UNUSED u32 pad[2];
725
UNUSED struct DynObjInfo *curInfo = sDynListCurInfo;
726
struct GdVec3f currObjPos; // transformed into attach offset
727
struct GdVec3f objPos;
728
729
d_stash_dynobj();
730
731
if (sDynListCurObj == NULL) {
732
fatal_printf("proc_dynlist(): No current object");
733
}
734
735
// find or generate attachment groups
736
switch (obj->type) {
737
case OBJ_TYPE_JOINTS:
738
if ((attgrp = ((struct ObjJoint *) obj)->attachedObjsGrp) == NULL) {
739
attgrp = ((struct ObjJoint *) obj)->attachedObjsGrp = make_group(0);
740
}
741
break;
742
case OBJ_TYPE_NETS:
743
if ((attgrp = ((struct ObjNet *) obj)->attachedObjsGrp) == NULL) {
744
attgrp = ((struct ObjNet *) obj)->attachedObjsGrp = make_group(0);
745
}
746
break;
747
case OBJ_TYPE_PARTICLES:
748
if ((attgrp = ((struct ObjParticle *) obj)->attachedObjsGrp) == NULL) {
749
attgrp = ((struct ObjParticle *) obj)->attachedObjsGrp = make_group(0);
750
}
751
break;
752
case OBJ_TYPE_ANIMATORS:
753
if ((attgrp = ((struct ObjAnimator *) obj)->attachedObjsGrp) == NULL) {
754
attgrp = ((struct ObjAnimator *) obj)->attachedObjsGrp = make_group(0);
755
}
756
break;
757
default:
758
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dAttachTo()",
759
sDynListCurInfo->name, sDynListCurObj->type);
760
}
761
762
if (group_contains_obj(attgrp, sDynListCurObj)) {
763
return;
764
}
765
766
addto_group(attgrp, sDynListCurObj);
767
768
if (flag & 9) {
769
d_get_world_pos(&currObjPos);
770
set_cur_dynobj(obj);
771
d_get_world_pos(&objPos);
772
773
currObjPos.x -= objPos.x;
774
currObjPos.y -= objPos.y;
775
currObjPos.z -= objPos.z;
776
}
777
778
d_unstash_dynobj();
779
switch (sDynListCurObj->type) {
780
case OBJ_TYPE_JOINTS:
781
((struct ObjJoint *) sDynListCurObj)->attachFlags = flag;
782
((struct ObjJoint *) sDynListCurObj)->attachedToObj = obj;
783
break;
784
case OBJ_TYPE_NETS:
785
((struct ObjNet *) sDynListCurObj)->attachFlags = flag;
786
((struct ObjNet *) sDynListCurObj)->attachedToObj = obj;
787
break;
788
case OBJ_TYPE_PARTICLES:
789
((struct ObjParticle *) sDynListCurObj)->attachFlags = flag;
790
((struct ObjParticle *) sDynListCurObj)->attachedToObj = obj;
791
break;
792
case OBJ_TYPE_ANIMATORS:
793
((struct ObjAnimator *) sDynListCurObj)->attachFlags = flag;
794
((struct ObjAnimator *) sDynListCurObj)->attachedToObj = obj;
795
break;
796
default:
797
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dAttachTo()",
798
sDynListCurInfo->name, sDynListCurObj->type);
799
}
800
801
if (flag & 9) {
802
d_set_att_offset(&currObjPos);
803
}
804
}
805
806
/**
807
* Attach the current dynamic object to dynamic object `name`. This function
808
* is a wrapper around `d_attach_to()`
809
*/
810
void d_attachto_dynid(s32 flag, DynObjName name) {
811
struct DynObjInfo *info;
812
813
if (name == NULL) {
814
return;
815
}
816
if (sDynListCurObj == NULL) {
817
fatal_printf("proc_dynlist(): No current object");
818
}
819
820
info = get_dynobj_info(name);
821
if (info == NULL) {
822
fatal_printf("dAttachTo(\"%s\"): Undefined object", DynNameAsStr(name));
823
}
824
825
d_attach_to(flag, info->obj);
826
}
827
828
/**
829
* Helper function to copy bytes. Where's memcpy when you need it?
830
*/
831
void copy_bytes(u8 *src, u8 *dst, s32 num) {
832
if (num == 0) {
833
return;
834
}
835
while (num--) {
836
*dst++ = *src++;
837
}
838
}
839
840
/**
841
* Allocate the animation data for `animator` onto the goddard heap.
842
* Animation data of type `::GD_ANIM_SCALE3S_POS3S_ROT3S` is converted to a `AnimMtxVec` struct,
843
* rather than solely byted copied like the other types.
844
*/
845
void alloc_animdata(struct ObjAnimator *animator) {
846
UNUSED u32 pad5C;
847
// probably should be three GdVec3fs, not triangle...
848
// vec0 = position; vec1 = scale? rotation?; vec2 = translation
849
struct GdTriangleF tri; //+58; temp float for converting half to f32?
850
s16(*halfarr)[9]; //+54; data to convert into a AnimMtxVec
851
struct AnimDataInfo *curAnimSrc; //+50; source animation data...
852
struct AnimDataInfo *animDst; //+4c; destination anim data II
853
struct AnimDataInfo *animDataArr; //+48; start of allocated anim data memory
854
struct ObjGroup *animgrp; //+44
855
s32 datasize; //+40; anim data allocation size?
856
s32 dataIdx; //+3C; byte count?
857
s32 animCnt; //+38; count of animdata "info" structs
858
s32 i; //+34
859
void *allocSpace; //+30; allocated animdata space
860
f32 allocMtxScale = 0.1f; //+2C; scale postion/rotation of GD_ANIM_SCALE3S_POS3S_ROT3S data
861
struct AnimMtxVec *curMtxVec; //+28
862
UNUSED u32 pad20;
863
864
start_memtracker("animdata");
865
866
if ((animgrp = animator->animdataGrp) == NULL) {
867
fatal_printf("no anim group");
868
}
869
870
if ((curAnimSrc = (struct AnimDataInfo *) animgrp->firstMember->obj) == NULL) {
871
fatal_printf("no animation data");
872
}
873
874
// count number of array-ed animation data structs
875
animDst = curAnimSrc;
876
animCnt = 0;
877
while (animDst++->count >= 0) {
878
animCnt++;
879
}
880
881
animDst = gd_malloc_perm(animCnt * sizeof(struct AnimDataInfo)); // gd_alloc_perm
882
if ((animDataArr = animDst) == NULL) {
883
fatal_printf("cant allocate animation data");
884
}
885
886
for (i = 0; i < animCnt; i++) {
887
allocSpace = NULL;
888
if (curAnimSrc->type != 0) {
889
switch (curAnimSrc->type) {
890
case GD_ANIM_CAMERA_EYE3S_LOOKAT3S:
891
datasize = sizeof(s16[6]);
892
break;
893
case GD_ANIM_ROT3S:
894
datasize = sizeof(s16[3]);
895
break;
896
case GD_ANIM_POS3S:
897
datasize = sizeof(s16[3]);
898
break;
899
case GD_ANIM_ROT3S_POS3S:
900
datasize = sizeof(s16[6]);
901
break;
902
case GD_ANIM_SCALE3F_ROT3F_POS3F:
903
datasize = sizeof(f32[3][3]);
904
break;
905
/* This function will convert the s16[9] array into a struct AnimMtxVec */
906
case GD_ANIM_SCALE3S_POS3S_ROT3S:
907
datasize = sizeof(struct AnimMtxVec);
908
break;
909
case GD_ANIM_MTX4x4:
910
datasize = sizeof(Mat4f);
911
break;
912
default:
913
fatal_printf("unknown anim type for allocation");
914
break;
915
}
916
917
allocSpace = gd_malloc_perm(curAnimSrc->count * datasize); // gd_alloc_perm
918
if (allocSpace == NULL) {
919
fatal_printf("cant allocate animation data");
920
}
921
922
if (curAnimSrc->type == GD_ANIM_SCALE3S_POS3S_ROT3S) {
923
for (dataIdx = 0; dataIdx < curAnimSrc->count; dataIdx++) {
924
halfarr = &((s16(*)[9]) curAnimSrc->data)[dataIdx];
925
curMtxVec = &((struct AnimMtxVec *) allocSpace)[dataIdx];
926
927
tri.p0.x = (f32)(*halfarr)[0] * allocMtxScale;
928
tri.p0.y = (f32)(*halfarr)[1] * allocMtxScale;
929
tri.p0.z = (f32)(*halfarr)[2] * allocMtxScale;
930
tri.p1.x = (f32)(*halfarr)[3] * allocMtxScale;
931
tri.p1.y = (f32)(*halfarr)[4] * allocMtxScale;
932
tri.p1.z = (f32)(*halfarr)[5] * allocMtxScale;
933
tri.p2.x = (f32)(*halfarr)[6];
934
tri.p2.y = (f32)(*halfarr)[7];
935
tri.p2.z = (f32)(*halfarr)[8];
936
937
gd_set_identity_mat4(&curMtxVec->matrix);
938
gd_rot_mat_about_vec(&curMtxVec->matrix, &tri.p1);
939
gd_add_vec3f_to_mat4f_offset(&curMtxVec->matrix, &tri.p2);
940
941
((struct AnimMtxVec *) allocSpace)[dataIdx].vec.x = tri.p0.x;
942
((struct AnimMtxVec *) allocSpace)[dataIdx].vec.y = tri.p0.y;
943
((struct AnimMtxVec *) allocSpace)[dataIdx].vec.z = tri.p0.z;
944
}
945
curAnimSrc->type = GD_ANIM_MTX4x4F_SCALE3F;
946
} else {
947
copy_bytes(curAnimSrc->data, allocSpace, curAnimSrc->count * datasize);
948
}
949
}
950
951
animDst[i].type = curAnimSrc->type;
952
animDst[i].count = curAnimSrc->count;
953
animDst[i].data = allocSpace;
954
955
curAnimSrc++; // next anim data struct
956
}
957
958
animgrp->firstMember->obj = (void *) animDataArr;
959
stop_memtracker("animdata");
960
}
961
962
/**
963
* Generate or create the various `ObjVertex`, `ObjFace`, and/or
964
* `ObjMaterial` when groups of those structures are attached to
965
* `shape`. This function is called when `d_set_nodegroup()`,
966
* `d_set_planegroup()`, or `d_set_matgroup()` are called
967
* when an `ObjShape` is the active dynamic object.
968
*
969
* @note Face/vertices need to be set before materials
970
*/
971
void chk_shapegen(struct ObjShape *shape) {
972
struct ObjFace *face; // sp5C; made face
973
struct ObjVertex *vtx; // sp58; made gdvtx
974
struct ObjVertex **vtxbuf; // sp54; heap storage for made gd vtx
975
struct ObjGroup *shapeMtls; // sp50
976
struct ObjGroup *shapeFaces; // sp4C
977
struct ObjGroup *shapeVtx; // sp48
978
UNUSED u32 pad44;
979
struct ObjGroup *madeFaces; // sp40
980
struct ObjGroup *madeVtx; // sp3C
981
u32 i; // sp38
982
struct GdVtxData *vtxdata; // sp34
983
struct GdFaceData *facedata; // sp30
984
struct GdObj *oldObjHead; // sp2C
985
986
start_memtracker("chk_shapegen");
987
imin("chk_shapegen");
988
shapeMtls = shape->mtlGroup;
989
shapeFaces = shape->faceGroup;
990
shapeVtx = shape->vtxGroup;
991
992
if (shapeVtx != NULL && shapeFaces != NULL) {
993
if ((shapeVtx->linkType & 1) && (shapeFaces->linkType & 1)) //? needs the double if
994
{
995
// These ListNodes point to special, compressed data structures
996
vtxdata = (struct GdVtxData *) shapeVtx->firstMember->obj;
997
facedata = (struct GdFaceData *) shapeFaces->firstMember->obj;
998
if (facedata->type != 1) {
999
fatal_printf("unsupported poly type");
1000
}
1001
1002
if (vtxdata->type != 1) {
1003
fatal_printf("unsupported vertex type");
1004
}
1005
1006
if (vtxdata->count >= VTX_BUF_SIZE) {
1007
fatal_printf("shapegen() too many vertices");
1008
}
1009
1010
vtxbuf = gd_malloc_temp(VTX_BUF_SIZE * sizeof(struct ObjVertex *));
1011
oldObjHead = gGdObjectList;
1012
1013
for (i = 0; i < vtxdata->count; i++) {
1014
vtx = gd_make_vertex(vtxdata->data[i][0], vtxdata->data[i][1], vtxdata->data[i][2]);
1015
vtx->normal.x = vtx->normal.y = vtx->normal.z = 0.0f;
1016
vtxbuf[i] = vtx;
1017
}
1018
1019
madeVtx = make_group_of_type(OBJ_TYPE_VERTICES, oldObjHead, NULL);
1020
1021
oldObjHead = gGdObjectList;
1022
for (i = 0; i < facedata->count; i++) {
1023
//! @bug Call to `make_face_with_colour()` compiles incorrectly
1024
//! due to Goddard only declaring the functions,
1025
//! not prototyping the functions
1026
face = make_face_with_colour(1.0, 1.0, 1.0);
1027
face->mtlId = (s32) facedata->data[i][0];
1028
add_3_vtx_to_face(face, vtxbuf[facedata->data[i][1]], vtxbuf[facedata->data[i][2]],
1029
vtxbuf[facedata->data[i][3]]);
1030
vtxbuf[facedata->data[i][1]]->normal.x += face->normal.x;
1031
vtxbuf[facedata->data[i][1]]->normal.y += face->normal.y;
1032
vtxbuf[facedata->data[i][1]]->normal.z += face->normal.z;
1033
1034
vtxbuf[facedata->data[i][2]]->normal.x += face->normal.x;
1035
vtxbuf[facedata->data[i][2]]->normal.y += face->normal.y;
1036
vtxbuf[facedata->data[i][2]]->normal.z += face->normal.z;
1037
1038
vtxbuf[facedata->data[i][3]]->normal.x += face->normal.x;
1039
vtxbuf[facedata->data[i][3]]->normal.y += face->normal.y;
1040
vtxbuf[facedata->data[i][3]]->normal.z += face->normal.z;
1041
}
1042
1043
if (shape->flag & 0x10) {
1044
for (i = 0; i < vtxdata->count; i++) {
1045
vtxbuf[i]->normal.x = vtxbuf[i]->pos.x;
1046
vtxbuf[i]->normal.y = vtxbuf[i]->pos.y;
1047
vtxbuf[i]->normal.z = vtxbuf[i]->pos.z;
1048
gd_normalize_vec3f(&vtxbuf[i]->normal);
1049
}
1050
} else {
1051
for (i = 0; i < vtxdata->count; i++) {
1052
gd_normalize_vec3f(&vtxbuf[i]->normal);
1053
}
1054
}
1055
1056
gd_free(vtxbuf);
1057
madeFaces = make_group_of_type(OBJ_TYPE_FACES, oldObjHead, NULL);
1058
shape->faceGroup = madeFaces;
1059
shape->vtxGroup = madeVtx;
1060
}
1061
}
1062
1063
if (shapeMtls != NULL) {
1064
if (shape->faceGroup) {
1065
map_face_materials(shape->faceGroup, shapeMtls);
1066
} else {
1067
fatal_printf("chk_shapegen() please set face group before mats");
1068
}
1069
}
1070
1071
imout();
1072
stop_memtracker("chk_shapegen");
1073
}
1074
1075
/**
1076
* Set the "node group" of the current dynamic object to dynamic object `name`.
1077
* The node group depends on the type of the current dynamic object:
1078
* * the vertex group is set for `ObjShape`
1079
* * the joints/weight group is set for `ObjNet`
1080
* * data is set for `ObjAnimator`
1081
* * something is set for `ObjGadget`
1082
*/
1083
void d_set_nodegroup(DynObjName name) {
1084
struct DynObjInfo *info; // sp2C
1085
UNUSED u32 pad[2];
1086
1087
if (sDynListCurObj == NULL) {
1088
fatal_printf("proc_dynlist(): No current object");
1089
}
1090
1091
info = get_dynobj_info(name);
1092
if (info == NULL) {
1093
fatal_printf("dSetNodeGroup(\"%s\"): Undefined group", DynNameAsStr(name));
1094
}
1095
1096
switch (sDynListCurObj->type) {
1097
case OBJ_TYPE_NETS:
1098
((struct ObjNet *) sDynListCurObj)->unk1C8 = (struct ObjGroup *) info->obj;
1099
((struct ObjNet *) sDynListCurObj)->unk1D0 = (struct ObjGroup *) info->obj;
1100
break;
1101
case OBJ_TYPE_SHAPES:
1102
((struct ObjShape *) sDynListCurObj)->vtxGroup = (struct ObjGroup *) info->obj;
1103
chk_shapegen((struct ObjShape *) sDynListCurObj);
1104
break;
1105
case OBJ_TYPE_GADGETS:
1106
((struct ObjGadget *) sDynListCurObj)->unk54 = (struct ObjGroup *) info->obj;
1107
break;
1108
case OBJ_TYPE_ANIMATORS:
1109
((struct ObjAnimator *) sDynListCurObj)->animdataGrp = (struct ObjGroup *) info->obj;
1110
alloc_animdata((struct ObjAnimator *) sDynListCurObj);
1111
break;
1112
default:
1113
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetNodeGroup()",
1114
sDynListCurInfo->name, sDynListCurObj->type);
1115
}
1116
}
1117
1118
/**
1119
* Set the material group of the current dynamic `ObjShape` to `name`.
1120
*/
1121
void d_set_matgroup(DynObjName name) {
1122
struct DynObjInfo *info;
1123
1124
if (sDynListCurObj == NULL) {
1125
fatal_printf("proc_dynlist(): No current object");
1126
}
1127
1128
info = get_dynobj_info(name);
1129
if (info == NULL) {
1130
fatal_printf("dSetMatGroup(\"%s\"): Undefined group", DynNameAsStr(name));
1131
}
1132
1133
switch (sDynListCurObj->type) {
1134
case OBJ_TYPE_SHAPES:
1135
((struct ObjShape *) sDynListCurObj)->mtlGroup = (struct ObjGroup *) info->obj;
1136
chk_shapegen((struct ObjShape *) sDynListCurObj);
1137
break;
1138
default:
1139
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetMatGroup()",
1140
sDynListCurInfo->name, sDynListCurObj->type);
1141
}
1142
}
1143
1144
/**
1145
* At one time in the past, this set the s and t value of the current
1146
* dynamic `ObjVertex`. However, this function does nothing now.
1147
* See `BetaVtx` for a possible remnant of vertex code that had
1148
* ST coordinates.
1149
*/
1150
void d_set_texture_st(UNUSED f32 s, UNUSED f32 t) {
1151
UNUSED u32 pad[2];
1152
1153
if (sDynListCurObj == NULL) {
1154
fatal_printf("proc_dynlist(): No current object");
1155
}
1156
1157
switch (sDynListCurObj->type) {
1158
case OBJ_TYPE_VERTICES:
1159
break; // ifdef-ed out?
1160
default:
1161
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetTextureST()",
1162
sDynListCurInfo->name, sDynListCurObj->type);
1163
}
1164
}
1165
1166
/**
1167
* Set the texture pointer of the current dynamic `ObjMaterial`.
1168
*/
1169
void d_use_texture(void *texture) {
1170
if (sDynListCurObj == NULL) {
1171
fatal_printf("proc_dynlist(): No current object");
1172
}
1173
1174
switch (sDynListCurObj->type) {
1175
case OBJ_TYPE_MATERIALS:
1176
((struct ObjMaterial *) sDynListCurObj)->texture = texture;
1177
break;
1178
default:
1179
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dUseTexture()",
1180
sDynListCurInfo->name, sDynListCurObj->type);
1181
}
1182
}
1183
1184
/**
1185
* Set the current dynamic `ObjNet`'s skin group with the vertex group from
1186
* the dynamic `ObjShape` with `name`.
1187
*/
1188
void d_set_skinshape(DynObjName name) {
1189
struct DynObjInfo *info;
1190
1191
if (sDynListCurObj == NULL) {
1192
fatal_printf("proc_dynlist(): No current object");
1193
}
1194
1195
info = get_dynobj_info(name);
1196
if (info == NULL) {
1197
fatal_printf("dSetSkinShape(\"%s\"): Undefined object", DynNameAsStr(name));
1198
}
1199
1200
switch (sDynListCurObj->type) {
1201
case OBJ_TYPE_NETS:
1202
((struct ObjNet *) sDynListCurObj)->skinGrp = ((struct ObjShape *) info->obj)->vtxGroup;
1203
break;
1204
default:
1205
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetSkinShape()",
1206
sDynListCurInfo->name, sDynListCurObj->type);
1207
}
1208
}
1209
1210
/**
1211
* Map the material ids for the `ObjFace`s in the current dynamic `ObjGroup`
1212
* to pointer to `ObjMaterial`s in the `ObjGroup` `name`.
1213
*
1214
* See `map_face_materials()` for more info.
1215
*/
1216
void d_map_materials(DynObjName name) {
1217
struct DynObjInfo *info;
1218
1219
if (sDynListCurObj == NULL) {
1220
fatal_printf("proc_dynlist(): No current object");
1221
}
1222
1223
info = get_dynobj_info(name);
1224
if (info == NULL) {
1225
fatal_printf("dMapMaterials(\"%s\"): Undefined group", DynNameAsStr(name));
1226
}
1227
1228
map_face_materials((struct ObjGroup *) sDynListCurObj, (struct ObjGroup *) info->obj);
1229
}
1230
1231
/**
1232
* For all faces in the current `ObjGroup`, resolve their vertex indices to
1233
* `ObjVertex` pointers that point to vertices in the specified vertex group.
1234
* Also compute normals for all faces in the current `ObjGroup` and all vertices
1235
* in the specified vertex group.
1236
* See `map_vertices()` for more info.
1237
* @param name name of a vertex group dynobj
1238
*/
1239
void d_map_vertices(DynObjName name) {
1240
struct DynObjInfo *info;
1241
1242
if (sDynListCurObj == NULL) {
1243
fatal_printf("proc_dynlist(): No current object");
1244
}
1245
1246
info = get_dynobj_info(name);
1247
if (info == NULL) {
1248
fatal_printf("dMapVertices(\"%s\"): Undefined group", DynNameAsStr(name));
1249
}
1250
1251
map_vertices((struct ObjGroup *) sDynListCurObj, (struct ObjGroup *) info->obj);
1252
}
1253
1254
/**
1255
* In practice, this is used to set the faces of the current
1256
* active dynamic `ObjShape` to the dynamic group `name` of `ObjFace`s.
1257
* It also has interactions with `ObjNet`s, but there are no examples
1258
* of that usage in existing code.
1259
*/
1260
void d_set_planegroup(DynObjName name) {
1261
struct DynObjInfo *info;
1262
UNUSED u32 pad[2];
1263
1264
if (sDynListCurObj == NULL) {
1265
fatal_printf("proc_dynlist(): No current object");
1266
}
1267
1268
info = get_dynobj_info(name);
1269
if (info == NULL) {
1270
fatal_printf("dSetPlaneGroup(\"%s\"): Undefined group", DynNameAsStr(name));
1271
}
1272
1273
switch (sDynListCurObj->type) {
1274
case OBJ_TYPE_NETS:
1275
((struct ObjNet *) sDynListCurObj)->unk1CC = (struct ObjGroup *) info->obj;
1276
break;
1277
case OBJ_TYPE_SHAPES:
1278
((struct ObjShape *) sDynListCurObj)->faceGroup = (struct ObjGroup *) info->obj;
1279
chk_shapegen((struct ObjShape *) sDynListCurObj);
1280
break;
1281
default:
1282
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetPlaneGroup()",
1283
sDynListCurInfo->name, sDynListCurObj->type);
1284
}
1285
}
1286
1287
/**
1288
* Set the shape pointer of the current active dynamic object to the
1289
* pointer pointed to by `shpPtrptr`.
1290
*/
1291
void d_set_shapeptrptr(struct ObjShape **shpPtrptr) {
1292
struct ObjShape *defaultptr = NULL;
1293
1294
if (sDynListCurObj == NULL) {
1295
fatal_printf("proc_dynlist(): No current object");
1296
}
1297
1298
if (shpPtrptr == NULL) {
1299
shpPtrptr = &defaultptr;
1300
}
1301
1302
switch (sDynListCurObj->type) {
1303
case OBJ_TYPE_JOINTS:
1304
((struct ObjJoint *) sDynListCurObj)->shapePtr = *shpPtrptr;
1305
((struct ObjJoint *) sDynListCurObj)->colourNum = 0;
1306
break;
1307
case OBJ_TYPE_NETS:
1308
((struct ObjNet *) sDynListCurObj)->shapePtr = *shpPtrptr;
1309
break;
1310
case OBJ_TYPE_BONES:
1311
((struct ObjBone *) sDynListCurObj)->shapePtr = *shpPtrptr;
1312
break;
1313
case OBJ_TYPE_GADGETS:
1314
((struct ObjGadget *) sDynListCurObj)->shapePtr = *shpPtrptr;
1315
break;
1316
case OBJ_TYPE_PARTICLES:
1317
((struct ObjParticle *) sDynListCurObj)->shapePtr = *shpPtrptr;
1318
break;
1319
case OBJ_TYPE_LIGHTS:
1320
((struct ObjLight *) sDynListCurObj)->unk9C = *shpPtrptr;
1321
break;
1322
default:
1323
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetShapePtrPtr()",
1324
sDynListCurInfo->name, sDynListCurObj->type);
1325
}
1326
}
1327
1328
/**
1329
* Set the shape pointer of the current active dynamic object to dynamic
1330
* `ObjShape` `name`.
1331
*/
1332
void d_set_shapeptr(DynObjName name) {
1333
struct DynObjInfo *info;
1334
if (name == NULL) {
1335
return;
1336
}
1337
1338
info = get_dynobj_info(name);
1339
if (info == NULL) {
1340
fatal_printf("dSetShapePtr(\"%s\"): Undefined object", DynNameAsStr(name));
1341
}
1342
1343
switch (sDynListCurObj->type) {
1344
case OBJ_TYPE_JOINTS:
1345
((struct ObjJoint *) sDynListCurObj)->shapePtr = (struct ObjShape *) info->obj;
1346
((struct ObjJoint *) sDynListCurObj)->colourNum = 0;
1347
break;
1348
case OBJ_TYPE_NETS:
1349
((struct ObjNet *) sDynListCurObj)->shapePtr = (struct ObjShape *) info->obj;
1350
break;
1351
case OBJ_TYPE_BONES:
1352
((struct ObjBone *) sDynListCurObj)->shapePtr = (struct ObjShape *) info->obj;
1353
break;
1354
case OBJ_TYPE_GADGETS:
1355
((struct ObjGadget *) sDynListCurObj)->shapePtr = (struct ObjShape *) info->obj;
1356
break;
1357
case OBJ_TYPE_PARTICLES:
1358
((struct ObjParticle *) sDynListCurObj)->shapePtr = (struct ObjShape *) info->obj;
1359
break;
1360
default:
1361
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetShapePtr()",
1362
sDynListCurInfo->name, sDynListCurObj->type);
1363
}
1364
}
1365
1366
/**
1367
* Set the current active dynamic object to object `name`.
1368
*/
1369
struct GdObj *d_use_obj(DynObjName name) {
1370
struct DynObjInfo *info = get_dynobj_info(name);
1371
if (info == NULL) {
1372
fatal_printf("dUseObj(\"%s\"): Undefined object", DynNameAsStr(name));
1373
}
1374
1375
sDynListCurObj = info->obj;
1376
sDynListCurInfo = info;
1377
1378
return info->obj;
1379
}
1380
1381
/**
1382
* Set the current active dynamic object to `obj`. This object can
1383
* any type of `GdObj`, not just an object created through the
1384
* dynmaic object system.
1385
*/
1386
void set_cur_dynobj(struct GdObj *obj) {
1387
sDynListCurObj = obj;
1388
sDynListCurInfo = &sNullDynObjInfo;
1389
}
1390
1391
/**
1392
* Start a dynamic `ObjGroup` identified with `name`.
1393
*/
1394
void d_start_group(DynObjName name) {
1395
d_makeobj(D_GROUP, name);
1396
}
1397
1398
/**
1399
* Add all dynamic objects created between the start of dynamic `ObjGroup` `name`
1400
* and this call.
1401
*/
1402
void d_end_group(DynObjName name) {
1403
UNUSED u32 pad;
1404
struct DynObjInfo *info = get_dynobj_info(name);
1405
struct ObjGroup *dynGrp;
1406
s32 i;
1407
1408
if (info == NULL) {
1409
fatal_printf("dEndGroup(\"%s\"): Undefined group", DynNameAsStr(name));
1410
}
1411
1412
dynGrp = (struct ObjGroup *) info->obj;
1413
for (i = info->num + 1; i < sLoadedDynObjs; i++) {
1414
if (sGdDynObjList[i].obj->type != OBJ_TYPE_GROUPS) {
1415
addto_group(dynGrp, sGdDynObjList[i].obj);
1416
}
1417
}
1418
}
1419
1420
/**
1421
* Add the current dynamic object to the dynamic `ObjGroup` `name`.
1422
*/
1423
void d_addto_group(DynObjName name) {
1424
UNUSED u32 pad;
1425
struct DynObjInfo *info = get_dynobj_info(name);
1426
struct ObjGroup *targetGrp;
1427
1428
if (info == NULL) {
1429
fatal_printf("dAddToGroup(\"%s\"): Undefined group", DynNameAsStr(name));
1430
}
1431
1432
targetGrp = (struct ObjGroup *) info->obj;
1433
addto_group(targetGrp, sDynListCurObj);
1434
}
1435
1436
/**
1437
* Set if `DynObjName` should be treated as integer values,
1438
* or as `char *` string pointers.
1439
*
1440
* @param isIntBool `TRUE` to interpret ids as integers
1441
*/
1442
void d_use_integer_names(s32 isIntBool) {
1443
sUseIntegerNames = isIntBool;
1444
}
1445
1446
/**
1447
* Set the initial position of the current dynamic object
1448
* to `(x, y, z)`.
1449
*/
1450
void d_set_init_pos(f32 x, f32 y, f32 z) {
1451
UNUSED u32 pad2c[3];
1452
struct GdObj *dynobj = sDynListCurObj; // sp28
1453
UNUSED u32 pad[1];
1454
1455
if (sDynListCurObj == NULL) {
1456
fatal_printf("proc_dynlist(): No current object");
1457
}
1458
1459
switch (sDynListCurObj->type) {
1460
case OBJ_TYPE_JOINTS:
1461
((struct ObjJoint *) dynobj)->worldPos.x = x;
1462
((struct ObjJoint *) dynobj)->worldPos.y = y;
1463
((struct ObjJoint *) dynobj)->worldPos.z = z;
1464
1465
((struct ObjJoint *) dynobj)->unk3C.x = x;
1466
((struct ObjJoint *) dynobj)->unk3C.y = y;
1467
((struct ObjJoint *) dynobj)->unk3C.z = z;
1468
1469
((struct ObjJoint *) dynobj)->initPos.x = x;
1470
((struct ObjJoint *) dynobj)->initPos.y = y;
1471
((struct ObjJoint *) dynobj)->initPos.z = z;
1472
break;
1473
case OBJ_TYPE_NETS:
1474
((struct ObjNet *) dynobj)->worldPos.x = x;
1475
((struct ObjNet *) dynobj)->worldPos.y = y;
1476
((struct ObjNet *) dynobj)->worldPos.z = z;
1477
1478
((struct ObjNet *) dynobj)->initPos.x = x;
1479
((struct ObjNet *) dynobj)->initPos.y = y;
1480
((struct ObjNet *) dynobj)->initPos.z = z;
1481
break;
1482
case OBJ_TYPE_PARTICLES:
1483
((struct ObjParticle *) dynobj)->pos.x = x;
1484
((struct ObjParticle *) dynobj)->pos.y = y;
1485
((struct ObjParticle *) dynobj)->pos.z = z;
1486
break;
1487
case OBJ_TYPE_CAMERAS:
1488
((struct ObjCamera *) dynobj)->worldPos.x = x;
1489
((struct ObjCamera *) dynobj)->worldPos.y = y;
1490
((struct ObjCamera *) dynobj)->worldPos.z = z;
1491
break;
1492
case OBJ_TYPE_VERTICES:
1493
d_set_rel_pos(x, y, z);
1494
1495
((struct ObjVertex *) dynobj)->initPos.x = x;
1496
((struct ObjVertex *) dynobj)->initPos.y = y;
1497
((struct ObjVertex *) dynobj)->initPos.z = z;
1498
break;
1499
default:
1500
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetInitPos()",
1501
sDynListCurInfo->name, sDynListCurObj->type);
1502
}
1503
}
1504
1505
/**
1506
* Set the velocity of the current active dynamic object. The
1507
* values of the input `GdVec3f` are copied into the object.
1508
*/
1509
void d_set_velocity(const struct GdVec3f *vel) {
1510
struct GdObj *dynobj = sDynListCurObj;
1511
1512
if (sDynListCurObj == NULL) {
1513
fatal_printf("proc_dynlist(): No current object");
1514
}
1515
1516
switch (sDynListCurObj->type) {
1517
case OBJ_TYPE_JOINTS:
1518
((struct ObjJoint *) dynobj)->velocity.x = vel->x;
1519
((struct ObjJoint *) dynobj)->velocity.y = vel->y;
1520
((struct ObjJoint *) dynobj)->velocity.z = vel->z;
1521
break;
1522
case OBJ_TYPE_NETS:
1523
((struct ObjNet *) dynobj)->velocity.x = vel->x;
1524
((struct ObjNet *) dynobj)->velocity.y = vel->y;
1525
((struct ObjNet *) dynobj)->velocity.z = vel->z;
1526
break;
1527
default:
1528
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetVelocity()",
1529
sDynListCurInfo->name, sDynListCurObj->type);
1530
}
1531
}
1532
1533
/**
1534
* Read the velocity value of the current dynamic object into `dst`
1535
*
1536
* @param[out] dst values are copied to this `GdVec3f`
1537
*/
1538
void d_get_velocity(struct GdVec3f *dst) {
1539
struct GdObj *dynobj = sDynListCurObj;
1540
1541
if (sDynListCurObj == NULL) {
1542
fatal_printf("proc_dynlist(): No current object");
1543
}
1544
1545
switch (sDynListCurObj->type) {
1546
case OBJ_TYPE_JOINTS:
1547
dst->x = ((struct ObjJoint *) dynobj)->velocity.x;
1548
dst->y = ((struct ObjJoint *) dynobj)->velocity.y;
1549
dst->z = ((struct ObjJoint *) dynobj)->velocity.z;
1550
break;
1551
case OBJ_TYPE_NETS:
1552
dst->x = ((struct ObjNet *) dynobj)->velocity.x;
1553
dst->y = ((struct ObjNet *) dynobj)->velocity.y;
1554
dst->z = ((struct ObjNet *) dynobj)->velocity.z;
1555
break;
1556
default:
1557
dst->x = dst->y = dst->z = 0.0f;
1558
break;
1559
}
1560
}
1561
1562
/**
1563
* Set the torque vectore for the current dynamic object.
1564
* Values from input `GdVec3f` are copied into the object.
1565
*
1566
* @note Not called
1567
*/
1568
void d_set_torque(const struct GdVec3f *src) {
1569
struct GdObj *dynobj = sDynListCurObj;
1570
1571
if (sDynListCurObj == NULL) {
1572
fatal_printf("proc_dynlist(): No current object");
1573
}
1574
1575
switch (sDynListCurObj->type) {
1576
case OBJ_TYPE_NETS:
1577
((struct ObjNet *) dynobj)->torque.x = src->x;
1578
((struct ObjNet *) dynobj)->torque.y = src->y;
1579
((struct ObjNet *) dynobj)->torque.z = src->z;
1580
break;
1581
default:
1582
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetTorque()",
1583
sDynListCurInfo->name, sDynListCurObj->type);
1584
}
1585
}
1586
1587
/**
1588
* Get the initial position of the current dynamic object and
1589
* store in `dst`.
1590
*/
1591
void d_get_init_pos(struct GdVec3f *dst) {
1592
struct GdObj *dynobj = sDynListCurObj;
1593
1594
if (sDynListCurObj == NULL) {
1595
fatal_printf("proc_dynlist(): No current object");
1596
}
1597
1598
switch (sDynListCurObj->type) {
1599
case OBJ_TYPE_JOINTS:
1600
dst->x = ((struct ObjJoint *) dynobj)->initPos.x;
1601
dst->y = ((struct ObjJoint *) dynobj)->initPos.y;
1602
dst->z = ((struct ObjJoint *) dynobj)->initPos.z;
1603
break;
1604
case OBJ_TYPE_NETS:
1605
dst->x = ((struct ObjNet *) dynobj)->initPos.x;
1606
dst->y = ((struct ObjNet *) dynobj)->initPos.y;
1607
dst->z = ((struct ObjNet *) dynobj)->initPos.z;
1608
break;
1609
case OBJ_TYPE_VERTICES:
1610
dst->x = ((struct ObjVertex *) dynobj)->initPos.x;
1611
dst->y = ((struct ObjVertex *) dynobj)->initPos.y;
1612
dst->z = ((struct ObjVertex *) dynobj)->initPos.z;
1613
break;
1614
default:
1615
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetInitPos()",
1616
sDynListCurInfo->name, sDynListCurObj->type);
1617
}
1618
}
1619
1620
/**
1621
* Get the initial rotation of the current dynamic object and
1622
* store in `dst`.
1623
*/
1624
void d_get_init_rot(struct GdVec3f *dst) {
1625
struct GdObj *dynobj = sDynListCurObj;
1626
1627
if (sDynListCurObj == NULL) {
1628
fatal_printf("proc_dynlist(): No current object");
1629
}
1630
1631
switch (sDynListCurObj->type) {
1632
case OBJ_TYPE_JOINTS:
1633
dst->x = ((struct ObjJoint *) dynobj)->unk6C.x;
1634
dst->y = ((struct ObjJoint *) dynobj)->unk6C.y;
1635
dst->z = ((struct ObjJoint *) dynobj)->unk6C.z;
1636
break;
1637
case OBJ_TYPE_NETS:
1638
dst->x = ((struct ObjNet *) dynobj)->unk68.x;
1639
dst->y = ((struct ObjNet *) dynobj)->unk68.y;
1640
dst->z = ((struct ObjNet *) dynobj)->unk68.z;
1641
break;
1642
case OBJ_TYPE_LIGHTS:
1643
dst->x = dst->y = dst->z = 0.0f;
1644
break;
1645
default:
1646
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetInitRot()",
1647
sDynListCurInfo->name, sDynListCurObj->type);
1648
}
1649
}
1650
1651
/**
1652
* Set the position of the current dynamic object.
1653
*
1654
* @note This function automatically adjusts the three zoom levels
1655
* for an `ObjCamera`.
1656
*/
1657
void d_set_rel_pos(f32 x, f32 y, f32 z) {
1658
struct GdObj *dynobj = sDynListCurObj; // sp34
1659
UNUSED struct GdVec3f unusedVec; // sp28
1660
1661
if (sDynListCurObj == NULL) {
1662
fatal_printf("proc_dynlist(): No current object");
1663
}
1664
1665
switch (sDynListCurObj->type) {
1666
case OBJ_TYPE_JOINTS:
1667
((struct ObjJoint *) dynobj)->unk3C.x = x;
1668
((struct ObjJoint *) dynobj)->unk3C.y = y;
1669
((struct ObjJoint *) dynobj)->unk3C.z = z;
1670
break;
1671
case OBJ_TYPE_CAMERAS:
1672
unusedVec.x = x;
1673
unusedVec.y = y;
1674
unusedVec.z = z;
1675
1676
((struct ObjCamera *) dynobj)->unk40.x = x;
1677
((struct ObjCamera *) dynobj)->unk40.y = y;
1678
((struct ObjCamera *) dynobj)->unk40.z = z;
1679
1680
((struct ObjCamera *) dynobj)->zoomPositions[0].x = x;
1681
((struct ObjCamera *) dynobj)->zoomPositions[0].y = y;
1682
((struct ObjCamera *) dynobj)->zoomPositions[0].z = z;
1683
1684
((struct ObjCamera *) dynobj)->zoomPositions[1].x = x * 1.5; //? 1.5f
1685
((struct ObjCamera *) dynobj)->zoomPositions[1].y = y * 1.5; //? 1.5f
1686
((struct ObjCamera *) dynobj)->zoomPositions[1].z = z * 1.5; //? 1.5f
1687
1688
((struct ObjCamera *) dynobj)->zoomPositions[2].x = x * 2.0f;
1689
((struct ObjCamera *) dynobj)->zoomPositions[2].y = y * 2.0f;
1690
((struct ObjCamera *) dynobj)->zoomPositions[2].z = z * 2.0f;
1691
1692
((struct ObjCamera *) dynobj)->maxZoomLevel = 2;
1693
break;
1694
case OBJ_TYPE_VERTICES:
1695
((struct ObjVertex *) dynobj)->pos.x = x;
1696
((struct ObjVertex *) dynobj)->pos.y = y;
1697
((struct ObjVertex *) dynobj)->pos.z = z;
1698
break;
1699
case OBJ_TYPE_LABELS:
1700
((struct ObjLabel *) dynobj)->position.x = x;
1701
((struct ObjLabel *) dynobj)->position.y = y;
1702
((struct ObjLabel *) dynobj)->position.z = z;
1703
break;
1704
case OBJ_TYPE_PARTICLES:
1705
((struct ObjParticle *) dynobj)->pos.x = x;
1706
((struct ObjParticle *) dynobj)->pos.y = y;
1707
((struct ObjParticle *) dynobj)->pos.z = z;
1708
break;
1709
case OBJ_TYPE_NETS:
1710
break;
1711
default:
1712
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetRelPos()",
1713
sDynListCurInfo->name, sDynListCurObj->type);
1714
}
1715
}
1716
1717
/**
1718
* Offset the current position of the current dynamic object.
1719
*/
1720
void d_addto_rel_pos(struct GdVec3f *src) {
1721
struct GdObj *dynobj = sDynListCurObj; // sp24
1722
1723
if (sDynListCurObj == NULL) {
1724
fatal_printf("proc_dynlist(): No current object");
1725
}
1726
1727
switch (sDynListCurObj->type) {
1728
case OBJ_TYPE_VERTICES:
1729
((struct ObjVertex *) dynobj)->pos.x += src->x;
1730
((struct ObjVertex *) dynobj)->pos.y += src->y;
1731
((struct ObjVertex *) dynobj)->pos.z += src->z;
1732
break;
1733
case OBJ_TYPE_JOINTS:
1734
((struct ObjJoint *) dynobj)->unk3C.x += src->x;
1735
((struct ObjJoint *) dynobj)->unk3C.y += src->y;
1736
((struct ObjJoint *) dynobj)->unk3C.z += src->z;
1737
break;
1738
case OBJ_TYPE_PARTICLES:
1739
((struct ObjParticle *) dynobj)->pos.x += src->x;
1740
((struct ObjParticle *) dynobj)->pos.y += src->y;
1741
((struct ObjParticle *) dynobj)->pos.z += src->z;
1742
break;
1743
default:
1744
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dAddToRelPos()",
1745
sDynListCurInfo->name, sDynListCurObj->type);
1746
}
1747
}
1748
1749
/**
1750
* Store the current dynamic object's position into `dst`.
1751
*/
1752
void d_get_rel_pos(struct GdVec3f *dst) {
1753
if (sDynListCurObj == NULL) {
1754
fatal_printf("proc_dynlist(): No current object");
1755
}
1756
1757
switch (sDynListCurObj->type) {
1758
case OBJ_TYPE_VERTICES:
1759
dst->x = ((struct ObjVertex *) sDynListCurObj)->pos.x;
1760
dst->y = ((struct ObjVertex *) sDynListCurObj)->pos.y;
1761
dst->z = ((struct ObjVertex *) sDynListCurObj)->pos.z;
1762
break;
1763
case OBJ_TYPE_JOINTS:
1764
dst->x = ((struct ObjJoint *) sDynListCurObj)->unk3C.x;
1765
dst->y = ((struct ObjJoint *) sDynListCurObj)->unk3C.y;
1766
dst->z = ((struct ObjJoint *) sDynListCurObj)->unk3C.z;
1767
break;
1768
case OBJ_TYPE_CAMERAS:
1769
dst->x = ((struct ObjCamera *) sDynListCurObj)->unk40.x;
1770
dst->y = ((struct ObjCamera *) sDynListCurObj)->unk40.y;
1771
dst->z = ((struct ObjCamera *) sDynListCurObj)->unk40.z;
1772
break;
1773
case OBJ_TYPE_PARTICLES:
1774
dst->x = ((struct ObjParticle *) sDynListCurObj)->pos.x;
1775
dst->y = ((struct ObjParticle *) sDynListCurObj)->pos.y;
1776
dst->z = ((struct ObjParticle *) sDynListCurObj)->pos.z;
1777
break;
1778
default:
1779
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetRelPos()",
1780
sDynListCurInfo->name, sDynListCurObj->type);
1781
}
1782
}
1783
1784
/**
1785
* Return a pointer to the attached object group of the current
1786
* dynamic object.
1787
*/
1788
struct ObjGroup *d_get_att_objgroup(void) {
1789
if (sDynListCurObj == NULL) {
1790
fatal_printf("proc_dynlist(): No current object");
1791
}
1792
1793
switch (sDynListCurObj->type) {
1794
case OBJ_TYPE_JOINTS:
1795
return ((struct ObjJoint *) sDynListCurObj)->attachedObjsGrp;
1796
break; // lol
1797
case OBJ_TYPE_NETS:
1798
return ((struct ObjNet *) sDynListCurObj)->attachedObjsGrp;
1799
break; // lol
1800
default:
1801
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetAttObjGroup()",
1802
sDynListCurInfo->name, sDynListCurObj->type);
1803
}
1804
// No null return due to `fatal_printf()` being a non-returning function?
1805
}
1806
1807
/**
1808
* Return a pointer to the object that the current dynamic object is attached to.
1809
*/
1810
struct GdObj *d_get_att_to_obj(void) {
1811
if (sDynListCurObj == NULL) {
1812
fatal_printf("proc_dynlist(): No current object");
1813
}
1814
1815
switch (sDynListCurObj->type) {
1816
case OBJ_TYPE_JOINTS:
1817
return ((struct ObjJoint *) sDynListCurObj)->attachedToObj;
1818
break; // lol
1819
case OBJ_TYPE_NETS:
1820
return ((struct ObjNet *) sDynListCurObj)->attachedToObj;
1821
break; // lol
1822
default:
1823
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetAttToObj()",
1824
sDynListCurInfo->name, sDynListCurObj->type);
1825
}
1826
// No null return due to `fatal_printf()` being a non-returning function?
1827
}
1828
1829
/**
1830
* Store the current dynamic object's scale into `dst`.
1831
*/
1832
void d_get_scale(struct GdVec3f *dst) {
1833
struct GdObj *dynobj; // sp24
1834
1835
if (sDynListCurObj == NULL) {
1836
fatal_printf("proc_dynlist(): No current object");
1837
}
1838
1839
dynobj = sDynListCurObj;
1840
switch (sDynListCurObj->type) {
1841
case OBJ_TYPE_JOINTS:
1842
dst->x = ((struct ObjJoint *) dynobj)->scale.x;
1843
dst->y = ((struct ObjJoint *) dynobj)->scale.y;
1844
dst->z = ((struct ObjJoint *) dynobj)->scale.z;
1845
break;
1846
case OBJ_TYPE_NETS:
1847
dst->x = ((struct ObjNet *) dynobj)->scale.x;
1848
dst->y = ((struct ObjNet *) dynobj)->scale.y;
1849
dst->z = ((struct ObjNet *) dynobj)->scale.z;
1850
break;
1851
case OBJ_TYPE_LIGHTS:
1852
dst->x = 1.0f;
1853
dst->y = 1.0f;
1854
dst->z = 1.0f;
1855
break;
1856
default:
1857
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetScale()",
1858
sDynListCurInfo->name, sDynListCurObj->type);
1859
}
1860
}
1861
1862
/**
1863
* Set the offset of the attached object on the current dynamic object.
1864
*/
1865
void d_set_att_offset(const struct GdVec3f *off) {
1866
struct GdObj *dynobj; // sp24
1867
1868
if (sDynListCurObj == NULL) {
1869
fatal_printf("proc_dynlist(): No current object");
1870
}
1871
1872
dynobj = sDynListCurObj;
1873
switch (sDynListCurObj->type) {
1874
case OBJ_TYPE_JOINTS:
1875
((struct ObjJoint *) dynobj)->attachOffset.x = off->x;
1876
((struct ObjJoint *) dynobj)->attachOffset.y = off->y;
1877
((struct ObjJoint *) dynobj)->attachOffset.z = off->z;
1878
1879
((struct ObjJoint *) dynobj)->initPos.x = off->x;
1880
((struct ObjJoint *) dynobj)->initPos.y = off->y;
1881
((struct ObjJoint *) dynobj)->initPos.z = off->z;
1882
break;
1883
case OBJ_TYPE_NETS:
1884
((struct ObjNet *) dynobj)->attachOffset.x = off->x;
1885
((struct ObjNet *) dynobj)->attachOffset.y = off->y;
1886
((struct ObjNet *) dynobj)->attachOffset.z = off->z;
1887
1888
((struct ObjNet *) dynobj)->initPos.x = off->x;
1889
((struct ObjNet *) dynobj)->initPos.y = off->y;
1890
((struct ObjNet *) dynobj)->initPos.z = off->z;
1891
break;
1892
case OBJ_TYPE_PARTICLES:
1893
break;
1894
default:
1895
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetAttOffset()",
1896
sDynListCurInfo->name, sDynListCurObj->type);
1897
}
1898
}
1899
1900
/**
1901
* An incorrectly-coded recursive function that was presumably supposed to
1902
* set the offset of an attached object. Now, it will only call itself
1903
* until it encounters a NULL pointer, which will trigger a `fatal_printf()`
1904
* call.
1905
*
1906
* @note Not called
1907
*/
1908
void d_set_att_to_offset(UNUSED u32 a) {
1909
struct GdObj *dynobj; // sp3c
1910
UNUSED u8 pad[24];
1911
1912
if (sDynListCurObj == NULL) {
1913
fatal_printf("proc_dynlist(): No current object");
1914
}
1915
1916
dynobj = sDynListCurObj;
1917
d_stash_dynobj();
1918
switch (sDynListCurObj->type) {
1919
case OBJ_TYPE_JOINTS:
1920
set_cur_dynobj(((struct ObjJoint *) dynobj)->attachedToObj);
1921
break;
1922
case OBJ_TYPE_NETS:
1923
set_cur_dynobj(((struct ObjNet *) dynobj)->attachedToObj);
1924
break;
1925
case OBJ_TYPE_PARTICLES:
1926
set_cur_dynobj(((struct ObjParticle *) dynobj)->attachedToObj);
1927
break;
1928
default:
1929
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetAttToOffset()",
1930
sDynListCurInfo->name, sDynListCurObj->type);
1931
}
1932
1933
if (sDynListCurObj == NULL) {
1934
fatal_printf("dSetAttOffset(): Object '%s' isnt attached to anything",
1935
sStashedDynObjInfo->name);
1936
}
1937
d_set_att_to_offset(a);
1938
d_unstash_dynobj();
1939
}
1940
1941
/**
1942
* Store the offset of the attached object into `dst`.
1943
*
1944
* @note Not called
1945
*/
1946
void d_get_att_offset(struct GdVec3f *dst) {
1947
if (sDynListCurObj == NULL) {
1948
fatal_printf("proc_dynlist(): No current object");
1949
}
1950
1951
switch (sDynListCurObj->type) {
1952
case OBJ_TYPE_JOINTS:
1953
dst->x = ((struct ObjJoint *) sDynListCurObj)->attachOffset.x;
1954
dst->y = ((struct ObjJoint *) sDynListCurObj)->attachOffset.y;
1955
dst->z = ((struct ObjJoint *) sDynListCurObj)->attachOffset.z;
1956
break;
1957
case OBJ_TYPE_NETS:
1958
dst->x = ((struct ObjNet *) sDynListCurObj)->attachOffset.x;
1959
dst->y = ((struct ObjNet *) sDynListCurObj)->attachOffset.y;
1960
dst->z = ((struct ObjNet *) sDynListCurObj)->attachOffset.z;
1961
break;
1962
case OBJ_TYPE_PARTICLES:
1963
break;
1964
default:
1965
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetAttOffset()",
1966
sDynListCurInfo->name, sDynListCurObj->type);
1967
}
1968
}
1969
1970
/**
1971
* Get the attached object flags for the current dynamic object.
1972
*/
1973
s32 d_get_att_flags(void) {
1974
s32 attflag; // sp24
1975
1976
if (sDynListCurObj == NULL) {
1977
fatal_printf("proc_dynlist(): No current object");
1978
}
1979
1980
switch (sDynListCurObj->type) {
1981
case OBJ_TYPE_JOINTS:
1982
attflag = ((struct ObjJoint *) sDynListCurObj)->attachFlags;
1983
break;
1984
case OBJ_TYPE_NETS:
1985
attflag = ((struct ObjNet *) sDynListCurObj)->attachFlags;
1986
break;
1987
case OBJ_TYPE_PARTICLES:
1988
attflag = ((struct ObjParticle *) sDynListCurObj)->attachFlags;
1989
break;
1990
default:
1991
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetAttFlags()",
1992
sDynListCurInfo->name, sDynListCurObj->type);
1993
}
1994
1995
return attflag;
1996
}
1997
1998
/**
1999
* Set the world position of the current dynamic object.
2000
*
2001
* @note Sets the upper left coordinates of an `ObjView`
2002
*/
2003
void d_set_world_pos(f32 x, f32 y, f32 z) {
2004
if (sDynListCurObj == NULL) {
2005
fatal_printf("proc_dynlist(): No current object");
2006
}
2007
2008
switch (sDynListCurObj->type) {
2009
case OBJ_TYPE_CAMERAS:
2010
((struct ObjCamera *) sDynListCurObj)->worldPos.x = x;
2011
((struct ObjCamera *) sDynListCurObj)->worldPos.y = y;
2012
((struct ObjCamera *) sDynListCurObj)->worldPos.z = z;
2013
break;
2014
case OBJ_TYPE_JOINTS:
2015
((struct ObjJoint *) sDynListCurObj)->worldPos.x = x;
2016
((struct ObjJoint *) sDynListCurObj)->worldPos.y = y;
2017
((struct ObjJoint *) sDynListCurObj)->worldPos.z = z;
2018
break;
2019
case OBJ_TYPE_NETS:
2020
((struct ObjNet *) sDynListCurObj)->worldPos.x = x;
2021
((struct ObjNet *) sDynListCurObj)->worldPos.y = y;
2022
((struct ObjNet *) sDynListCurObj)->worldPos.z = z;
2023
break;
2024
case OBJ_TYPE_GADGETS:
2025
((struct ObjGadget *) sDynListCurObj)->worldPos.x = x;
2026
((struct ObjGadget *) sDynListCurObj)->worldPos.y = y;
2027
((struct ObjGadget *) sDynListCurObj)->worldPos.z = z;
2028
break;
2029
case OBJ_TYPE_VIEWS:
2030
((struct ObjView *) sDynListCurObj)->upperLeft.x = x;
2031
((struct ObjView *) sDynListCurObj)->upperLeft.y = y;
2032
((struct ObjView *) sDynListCurObj)->upperLeft.z = z;
2033
break;
2034
case OBJ_TYPE_VERTICES:
2035
((struct ObjVertex *) sDynListCurObj)->pos.x = x;
2036
((struct ObjVertex *) sDynListCurObj)->pos.y = y;
2037
((struct ObjVertex *) sDynListCurObj)->pos.z = z;
2038
break;
2039
default:
2040
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetWorldPos()",
2041
sDynListCurInfo->name, sDynListCurObj->type);
2042
}
2043
}
2044
2045
/**
2046
* Set the normal of the current dynamic `ObjVertex`. The input `x, y, z` values
2047
* are normalized into a unit vector before setting the vertex normal.
2048
*/
2049
void d_set_normal(f32 x, f32 y, f32 z) {
2050
struct GdVec3f normal; // sp1C
2051
2052
if (sDynListCurObj == NULL) {
2053
fatal_printf("proc_dynlist(): No current object");
2054
}
2055
2056
normal.x = x;
2057
normal.y = y;
2058
normal.z = z;
2059
gd_normalize_vec3f(&normal);
2060
2061
switch (sDynListCurObj->type) {
2062
case OBJ_TYPE_VERTICES:
2063
((struct ObjVertex *) sDynListCurObj)->normal.x = normal.x;
2064
((struct ObjVertex *) sDynListCurObj)->normal.y = normal.y;
2065
((struct ObjVertex *) sDynListCurObj)->normal.z = normal.z;
2066
break;
2067
default:
2068
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetNormal()",
2069
sDynListCurInfo->name, sDynListCurObj->type);
2070
}
2071
}
2072
2073
/**
2074
* Get a pointer to the world position vector of the active
2075
* dynamic object. This is a pointer inside the actual object.
2076
*
2077
* @note Not called.
2078
*/
2079
struct GdVec3f *d_get_world_pos_ptr(void) {
2080
if (sDynListCurObj == NULL) {
2081
fatal_printf("proc_dynlist(): No current object");
2082
}
2083
2084
switch (sDynListCurObj->type) {
2085
case OBJ_TYPE_VERTICES:
2086
return &((struct ObjVertex *) sDynListCurObj)->pos;
2087
break;
2088
case OBJ_TYPE_PARTICLES:
2089
return &((struct ObjParticle *) sDynListCurObj)->pos;
2090
break;
2091
default:
2092
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetWorldPosPtr()",
2093
sDynListCurInfo->name, sDynListCurObj->type);
2094
}
2095
// No null return due to `fatal_printf()` being a non-returning function?
2096
}
2097
2098
/**
2099
* Copy the world position of the current dynamic object into `dst`.
2100
*/
2101
void d_get_world_pos(struct GdVec3f *dst) {
2102
if (sDynListCurObj == NULL) {
2103
fatal_printf("proc_dynlist(): No current object");
2104
}
2105
2106
switch (sDynListCurObj->type) {
2107
case OBJ_TYPE_VERTICES:
2108
dst->x = ((struct ObjVertex *) sDynListCurObj)->pos.x;
2109
dst->y = ((struct ObjVertex *) sDynListCurObj)->pos.y;
2110
dst->z = ((struct ObjVertex *) sDynListCurObj)->pos.z;
2111
break;
2112
case OBJ_TYPE_JOINTS:
2113
dst->x = ((struct ObjJoint *) sDynListCurObj)->worldPos.x;
2114
dst->y = ((struct ObjJoint *) sDynListCurObj)->worldPos.y;
2115
dst->z = ((struct ObjJoint *) sDynListCurObj)->worldPos.z;
2116
break;
2117
case OBJ_TYPE_NETS:
2118
dst->x = ((struct ObjNet *) sDynListCurObj)->worldPos.x;
2119
dst->y = ((struct ObjNet *) sDynListCurObj)->worldPos.y;
2120
dst->z = ((struct ObjNet *) sDynListCurObj)->worldPos.z;
2121
break;
2122
case OBJ_TYPE_PARTICLES:
2123
dst->x = ((struct ObjParticle *) sDynListCurObj)->pos.x;
2124
dst->y = ((struct ObjParticle *) sDynListCurObj)->pos.y;
2125
dst->z = ((struct ObjParticle *) sDynListCurObj)->pos.z;
2126
break;
2127
case OBJ_TYPE_CAMERAS:
2128
dst->x = ((struct ObjCamera *) sDynListCurObj)->worldPos.x;
2129
dst->y = ((struct ObjCamera *) sDynListCurObj)->worldPos.y;
2130
dst->z = ((struct ObjCamera *) sDynListCurObj)->worldPos.z;
2131
break;
2132
case OBJ_TYPE_BONES:
2133
dst->x = ((struct ObjBone *) sDynListCurObj)->worldPos.x;
2134
dst->y = ((struct ObjBone *) sDynListCurObj)->worldPos.y;
2135
dst->z = ((struct ObjBone *) sDynListCurObj)->worldPos.z;
2136
break;
2137
case OBJ_TYPE_SHAPES:
2138
dst->x = dst->y = dst->z = 0.0f;
2139
break;
2140
case OBJ_TYPE_LABELS:
2141
dst->x = dst->y = dst->z = 0.0f;
2142
break;
2143
case OBJ_TYPE_GADGETS:
2144
dst->x = ((struct ObjGadget *) sDynListCurObj)->worldPos.x;
2145
dst->y = ((struct ObjGadget *) sDynListCurObj)->worldPos.y;
2146
dst->z = ((struct ObjGadget *) sDynListCurObj)->worldPos.z;
2147
break;
2148
case OBJ_TYPE_PLANES:
2149
dst->x = ((struct ObjPlane *) sDynListCurObj)->boundingBox.minX;
2150
dst->y = ((struct ObjPlane *) sDynListCurObj)->boundingBox.minY;
2151
dst->z = ((struct ObjPlane *) sDynListCurObj)->boundingBox.minZ;
2152
2153
dst->x += ((struct ObjPlane *) sDynListCurObj)->boundingBox.maxX;
2154
dst->y += ((struct ObjPlane *) sDynListCurObj)->boundingBox.maxY;
2155
dst->z += ((struct ObjPlane *) sDynListCurObj)->boundingBox.maxZ;
2156
2157
dst->x *= 0.5; //? 0.5f
2158
dst->y *= 0.5; //? 0.5f
2159
dst->z *= 0.5; //? 0.5f
2160
break;
2161
case OBJ_TYPE_ZONES:
2162
dst->x = ((struct ObjZone *) sDynListCurObj)->boundingBox.minX;
2163
dst->y = ((struct ObjZone *) sDynListCurObj)->boundingBox.minY;
2164
dst->z = ((struct ObjZone *) sDynListCurObj)->boundingBox.minZ;
2165
2166
dst->x += ((struct ObjZone *) sDynListCurObj)->boundingBox.maxX;
2167
dst->y += ((struct ObjZone *) sDynListCurObj)->boundingBox.maxY;
2168
dst->z += ((struct ObjZone *) sDynListCurObj)->boundingBox.maxZ;
2169
2170
dst->x *= 0.5; //? 0.5f
2171
dst->y *= 0.5; //? 0.5f
2172
dst->z *= 0.5; //? 0.5f
2173
break;
2174
case OBJ_TYPE_LIGHTS:
2175
dst->x = ((struct ObjLight *) sDynListCurObj)->position.x;
2176
dst->y = ((struct ObjLight *) sDynListCurObj)->position.y;
2177
dst->z = ((struct ObjLight *) sDynListCurObj)->position.z;
2178
break;
2179
default:
2180
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetWorldPos()",
2181
sDynListCurInfo->name, sDynListCurObj->type);
2182
}
2183
}
2184
2185
/**
2186
* Create a new dynamic `ObjVertex` at point `pos`.
2187
*
2188
* @param[in] pos values are copied to set vertex position
2189
*/
2190
void d_make_vertex(struct GdVec3f *pos) {
2191
d_makeobj(D_VERTEX, AsDynName(NULL));
2192
d_set_init_pos(pos->x, pos->y, pos->z);
2193
}
2194
2195
/**
2196
* Scale the current dynamic object by factor `(x, y, z)`.
2197
*
2198
* @note Sets the lower right coordinates of an `ObjView`
2199
*/
2200
void d_set_scale(f32 x, f32 y, f32 z) {
2201
struct GdObj *initDynobj;
2202
2203
if (sDynListCurObj == NULL) {
2204
fatal_printf("proc_dynlist(): No current object");
2205
}
2206
2207
initDynobj = sDynListCurObj;
2208
d_stash_dynobj();
2209
switch (sDynListCurObj->type) {
2210
case OBJ_TYPE_JOINTS:
2211
((struct ObjJoint *) initDynobj)->scale.x = x;
2212
((struct ObjJoint *) initDynobj)->scale.y = y;
2213
((struct ObjJoint *) initDynobj)->scale.z = z;
2214
break;
2215
case OBJ_TYPE_NETS:
2216
((struct ObjNet *) initDynobj)->scale.x = x;
2217
((struct ObjNet *) initDynobj)->scale.y = y;
2218
((struct ObjNet *) initDynobj)->scale.z = z;
2219
break;
2220
case OBJ_TYPE_VIEWS:
2221
((struct ObjView *) initDynobj)->lowerRight.x = x;
2222
((struct ObjView *) initDynobj)->lowerRight.y = y;
2223
((struct ObjView *) initDynobj)->lowerRight.z = z;
2224
break;
2225
case OBJ_TYPE_PARTICLES:
2226
break;
2227
case OBJ_TYPE_GADGETS:
2228
if (((struct ObjGadget *) initDynobj)->shapePtr != NULL) {
2229
scale_verts_in_shape(((struct ObjGadget *) initDynobj)->shapePtr, x, y, z);
2230
}
2231
((struct ObjGadget *) initDynobj)->size.x = x;
2232
((struct ObjGadget *) initDynobj)->size.y = y;
2233
((struct ObjGadget *) initDynobj)->size.z = z;
2234
break;
2235
case OBJ_TYPE_LIGHTS:
2236
break;
2237
default:
2238
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetScale()",
2239
sDynListCurInfo->name, sDynListCurObj->type);
2240
}
2241
d_unstash_dynobj();
2242
}
2243
2244
/**
2245
* Set the rotation value of the current active dynamic object.
2246
*/
2247
void d_set_rotation(f32 x, f32 y, f32 z) {
2248
struct GdObj *dynobj; // sp2C
2249
UNUSED u32 pad;
2250
2251
if (sDynListCurObj == NULL) {
2252
fatal_printf("proc_dynlist(): No current object");
2253
}
2254
2255
dynobj = sDynListCurObj;
2256
switch (sDynListCurObj->type) {
2257
case OBJ_TYPE_JOINTS:
2258
((struct ObjJoint *) dynobj)->unk6C.x = x;
2259
((struct ObjJoint *) dynobj)->unk6C.y = y;
2260
((struct ObjJoint *) dynobj)->unk6C.z = z;
2261
break;
2262
case OBJ_TYPE_NETS:
2263
((struct ObjNet *) dynobj)->unk68.x = x;
2264
((struct ObjNet *) dynobj)->unk68.y = y;
2265
((struct ObjNet *) dynobj)->unk68.z = z;
2266
break;
2267
default:
2268
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetRotation()",
2269
sDynListCurInfo->name, sDynListCurObj->type);
2270
}
2271
}
2272
2273
/**
2274
* Set the center of gravity of the current dynamic `ObjNet`.
2275
*/
2276
void d_center_of_gravity(f32 x, f32 y, f32 z) {
2277
if (sDynListCurObj == NULL) {
2278
fatal_printf("proc_dynlist(): No current object");
2279
}
2280
2281
switch (sDynListCurObj->type) {
2282
case OBJ_TYPE_NETS:
2283
((struct ObjNet *) sDynListCurObj)->centerOfGravity.x = x;
2284
((struct ObjNet *) sDynListCurObj)->centerOfGravity.y = y;
2285
((struct ObjNet *) sDynListCurObj)->centerOfGravity.z = z;
2286
break;
2287
default:
2288
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dCofG()",
2289
sDynListCurInfo->name, sDynListCurObj->type);
2290
}
2291
}
2292
2293
/**
2294
* Set the shape offset of the current dynamic `ObjJoint`.
2295
*/
2296
void d_set_shape_offset(f32 x, f32 y, f32 z) {
2297
if (sDynListCurObj == NULL) {
2298
fatal_printf("proc_dynlist(): No current object");
2299
}
2300
2301
switch (sDynListCurObj->type) {
2302
case OBJ_TYPE_JOINTS:
2303
((struct ObjJoint *) sDynListCurObj)->shapeOffset.x = x;
2304
((struct ObjJoint *) sDynListCurObj)->shapeOffset.y = y;
2305
((struct ObjJoint *) sDynListCurObj)->shapeOffset.z = z;
2306
break;
2307
default:
2308
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dShapeOffset()",
2309
sDynListCurInfo->name, sDynListCurObj->type);
2310
}
2311
}
2312
2313
/**
2314
* Creates a new `ObjValPtr`.
2315
* If `vflags` is 0x40000, then `name` is the name of an object, and `offset`
2316
* is an offset to a field in that object. Otherwise, `offset` specifies a
2317
* the address of a standalone variable.
2318
*/
2319
void d_add_valptr(DynObjName name, u32 vflags, enum ValPtrType type, size_t offset) {
2320
struct GdObj *dynobj;
2321
struct ObjValPtr *valptr;
2322
struct DynObjInfo *info;
2323
2324
if (sDynListCurObj == NULL) {
2325
fatal_printf("proc_dynlist(): No current object");
2326
}
2327
2328
dynobj = sDynListCurObj;
2329
2330
if (vflags == 0x40000) {
2331
// value is an object field, and objId is the name of the object
2332
info = get_dynobj_info(name);
2333
if (info == NULL) {
2334
fatal_printf("dAddValPtr(\"%s\"): Undefined object", DynNameAsStr(name));
2335
}
2336
2337
valptr = make_valptr(info->obj, vflags, type, offset);
2338
} else {
2339
// value is a standalone variable
2340
valptr = make_valptr(name, vflags, type, offset);
2341
}
2342
2343
switch (sDynListCurObj->type) {
2344
case OBJ_TYPE_GADGETS:
2345
if (((struct ObjGadget *) dynobj)->valueGrp == NULL) {
2346
((struct ObjGadget *) dynobj)->valueGrp = make_group(0);
2347
}
2348
addto_group(((struct ObjGadget *) dynobj)->valueGrp, &valptr->header);
2349
break;
2350
case OBJ_TYPE_LABELS:
2351
((struct ObjLabel *) dynobj)->valptr = valptr;
2352
break;
2353
default:
2354
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dAddValPtr()",
2355
sDynListCurInfo->name, sDynListCurObj->type);
2356
}
2357
}
2358
2359
/**
2360
* Add a value processing function (`valptrproc_t`) to the current
2361
* dynamic `ObjLabel`.
2362
*/
2363
void d_add_valproc(valptrproc_t proc) {
2364
struct GdObj *dynobj;
2365
2366
if (sDynListCurObj == NULL) {
2367
fatal_printf("proc_dynlist(): No current object");
2368
}
2369
2370
dynobj = sDynListCurObj;
2371
switch (sDynListCurObj->type) {
2372
case OBJ_TYPE_LABELS:
2373
((struct ObjLabel *) dynobj)->valfn = proc;
2374
break;
2375
default:
2376
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dAddValProc()",
2377
sDynListCurInfo->name, sDynListCurObj->type);
2378
}
2379
}
2380
2381
/**
2382
* Link a variable pointer to the current active dynamic object.
2383
* In the final game, this is used to link arrays of raw vertex, face,
2384
* or animation data to `ObjGroup`s, or to link joints to `ObjAnimator`s.
2385
*/
2386
void d_link_with_ptr(void *ptr) {
2387
struct GdObj *dynobj; // sp34
2388
struct ObjValPtr *valptr; // sp30
2389
struct ListNode *link; // sp2C
2390
2391
if (sDynListCurObj == NULL) {
2392
fatal_printf("proc_dynlist(): No current object");
2393
}
2394
2395
dynobj = sDynListCurObj;
2396
imin("dLinkWithPtr");
2397
switch (sDynListCurObj->type) {
2398
case OBJ_TYPE_CAMERAS:
2399
((struct ObjCamera *) dynobj)->unk30 = ptr;
2400
break;
2401
case OBJ_TYPE_GROUPS:
2402
link = make_link_to_obj(NULL, ptr);
2403
((struct ObjGroup *) dynobj)->firstMember = link;
2404
break;
2405
case OBJ_TYPE_BONES:
2406
add_joint2bone((struct ObjBone *) dynobj, ptr);
2407
break;
2408
case OBJ_TYPE_VIEWS:
2409
((struct ObjView *) dynobj)->components = ptr;
2410
((struct ObjView *) dynobj)->unk1C =
2411
setup_view_buffers(((struct ObjView *) dynobj)->namePtr, ((struct ObjView *) dynobj),
2412
(s32)((struct ObjView *) dynobj)->upperLeft.x,
2413
(s32)((struct ObjView *) dynobj)->upperLeft.y,
2414
(s32)((struct ObjView *) dynobj)->lowerRight.x,
2415
(s32)((struct ObjView *) dynobj)->lowerRight.y);
2416
reset_nets_and_gadgets(((struct ObjView *) dynobj)->components);
2417
break;
2418
case OBJ_TYPE_FACES:
2419
if (((struct ObjFace *) dynobj)->vtxCount >= 4) {
2420
fatal_printf("too many points");
2421
}
2422
2423
((struct ObjFace *) dynobj)->vertices[((struct ObjFace *) dynobj)->vtxCount] = ptr;
2424
((struct ObjFace *) dynobj)->vtxCount++;
2425
2426
if (((struct ObjFace *) dynobj)->vtxCount >= 3) {
2427
calc_face_normal((struct ObjFace *) dynobj);
2428
}
2429
2430
break;
2431
case OBJ_TYPE_ANIMATORS:
2432
if (((struct ObjAnimator *) dynobj)->animatedPartsGrp == NULL) {
2433
((struct ObjAnimator *) dynobj)->animatedPartsGrp = make_group(0);
2434
}
2435
2436
addto_group(((struct ObjAnimator *) dynobj)->animatedPartsGrp, ptr);
2437
break;
2438
case OBJ_TYPE_LABELS:
2439
valptr = make_valptr(ptr, OBJ_TYPE_ALL, 0, 0);
2440
((struct ObjLabel *) dynobj)->valptr = valptr;
2441
break;
2442
default:
2443
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dLinkWithPtr()",
2444
sDynListCurInfo->name, sDynListCurObj->type);
2445
}
2446
imout();
2447
}
2448
2449
/**
2450
* Link the dynamic object `name` to the current dynamic object by wrapping
2451
* `d_link_with_ptr()`.
2452
*/
2453
void d_link_with(DynObjName name) {
2454
struct DynObjInfo *info; // sp1C
2455
struct DynObjInfo *origInfo = sDynListCurInfo; // sp18
2456
2457
if (sDynListCurObj == NULL) {
2458
fatal_printf("proc_dynlist(): No current object");
2459
}
2460
2461
if (name == NULL) {
2462
return;
2463
}
2464
2465
info = get_dynobj_info(name);
2466
if (info == NULL) {
2467
fatal_printf("dLinkWith(\"%s\"): Undefined object", DynNameAsStr(name));
2468
}
2469
2470
d_link_with_ptr(info->obj);
2471
set_cur_dynobj(origInfo->obj);
2472
sDynListCurInfo = origInfo;
2473
}
2474
2475
/**
2476
* Set the object specific flags of the current dynamic object.
2477
*/
2478
void d_set_flags(s32 flags) {
2479
struct GdObj *dynobj; // sp24
2480
2481
if (sDynListCurObj == NULL) {
2482
fatal_printf("proc_dynlist(): No current object");
2483
}
2484
2485
dynobj = sDynListCurObj;
2486
switch (sDynListCurObj->type) {
2487
case OBJ_TYPE_JOINTS:
2488
((struct ObjJoint *) dynobj)->flags |= flags;
2489
break;
2490
case OBJ_TYPE_BONES:
2491
((struct ObjBone *) dynobj)->unk104 |= flags;
2492
break;
2493
case OBJ_TYPE_NETS:
2494
((struct ObjNet *) dynobj)->flags |= flags;
2495
break;
2496
case OBJ_TYPE_CAMERAS:
2497
((struct ObjCamera *) dynobj)->flags |= flags;
2498
break;
2499
case OBJ_TYPE_VIEWS:
2500
((struct ObjView *) dynobj)->flags |= flags;
2501
break;
2502
case OBJ_TYPE_SHAPES:
2503
((struct ObjShape *) dynobj)->flag |= flags;
2504
break;
2505
case OBJ_TYPE_PARTICLES:
2506
((struct ObjParticle *) dynobj)->flags |= flags;
2507
break;
2508
case OBJ_TYPE_LIGHTS:
2509
((struct ObjLight *) dynobj)->flags |= flags;
2510
break;
2511
default:
2512
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetFlags()",
2513
sDynListCurInfo->name, sDynListCurObj->type);
2514
}
2515
}
2516
2517
/**
2518
* Clear object specific flags from the current dynamic object.
2519
*/
2520
void d_clear_flags(s32 flags) {
2521
if (sDynListCurObj == NULL) {
2522
fatal_printf("proc_dynlist(): No current object");
2523
}
2524
2525
switch (sDynListCurObj->type) {
2526
case OBJ_TYPE_JOINTS:
2527
((struct ObjJoint *) sDynListCurObj)->flags &= ~flags;
2528
break;
2529
case OBJ_TYPE_BONES:
2530
((struct ObjBone *) sDynListCurObj)->unk104 &= ~flags;
2531
break;
2532
case OBJ_TYPE_NETS:
2533
((struct ObjNet *) sDynListCurObj)->flags &= ~flags;
2534
break;
2535
case OBJ_TYPE_CAMERAS:
2536
((struct ObjCamera *) sDynListCurObj)->flags &= ~flags;
2537
break;
2538
case OBJ_TYPE_PARTICLES:
2539
((struct ObjParticle *) sDynListCurObj)->flags &= ~flags;
2540
break;
2541
default:
2542
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dClrFlags()",
2543
sDynListCurInfo->name, sDynListCurObj->type);
2544
}
2545
}
2546
2547
/**
2548
* Set variable float parameters on the current dynamic object.
2549
* These are mainly used for `ObjGadget`s to set the drawing size
2550
* range.
2551
*/
2552
void d_set_parm_f(enum DParmF param, f32 val) {
2553
if (sDynListCurObj == NULL) {
2554
fatal_printf("proc_dynlist(): No current object");
2555
}
2556
2557
switch (sDynListCurObj->type) {
2558
case OBJ_TYPE_SHAPES:
2559
switch (param) {
2560
case PARM_F_ALPHA:
2561
((struct ObjShape *) sDynListCurObj)->alpha = val;
2562
break;
2563
default:
2564
fatal_printf("%s: Object '%s'(%x) does not support this function.",
2565
"dSetParmf() - unsupported parm.", sDynListCurInfo->name,
2566
sDynListCurObj->type);
2567
}
2568
break;
2569
case OBJ_TYPE_GADGETS:
2570
switch (param) {
2571
case PARM_F_RANGE_MIN:
2572
((struct ObjGadget *) sDynListCurObj)->rangeMin = val;
2573
break;
2574
case PARM_F_RANGE_MAX:
2575
((struct ObjGadget *) sDynListCurObj)->rangeMax = val;
2576
break;
2577
case PARM_F_VARVAL:
2578
((struct ObjGadget *) sDynListCurObj)->varval.f = val;
2579
break;
2580
default:
2581
fatal_printf("%s: Object '%s'(%x) does not support this function.",
2582
"dSetParmf() - unsupported parm.", sDynListCurInfo->name,
2583
sDynListCurObj->type);
2584
}
2585
break;
2586
case OBJ_TYPE_VERTICES:
2587
switch (param) {
2588
case PARM_F_ALPHA:
2589
((struct ObjVertex *) sDynListCurObj)->alpha = val;
2590
break;
2591
default:
2592
fatal_printf("%s: Object '%s'(%x) does not support this function.",
2593
"dSetParmf() - unsupported parm.", sDynListCurInfo->name,
2594
sDynListCurObj->type);
2595
}
2596
break;
2597
default:
2598
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetParmf()",
2599
sDynListCurInfo->name, sDynListCurObj->type);
2600
}
2601
}
2602
2603
/**
2604
* Set various pointer parameters for the current dynamic object.
2605
* Normally, this is used to set `char *` pointer for various objects,
2606
* but it can also set the vertices for an `ObjFace`.
2607
*/
2608
void d_set_parm_ptr(enum DParmPtr param, void *ptr) {
2609
if (sDynListCurObj == NULL) {
2610
fatal_printf("proc_dynlist(): No current object");
2611
}
2612
2613
switch (sDynListCurObj->type) {
2614
case OBJ_TYPE_LABELS:
2615
switch (param) {
2616
case PARM_PTR_CHAR:
2617
((struct ObjLabel *) sDynListCurObj)->fmtstr = ptr;
2618
break;
2619
default:
2620
fatal_printf("Bad parm");
2621
}
2622
break;
2623
case OBJ_TYPE_VIEWS:
2624
switch (param) {
2625
case PARM_PTR_CHAR:
2626
((struct ObjView *) sDynListCurObj)->namePtr = ptr;
2627
break;
2628
default:
2629
fatal_printf("Bad parm");
2630
}
2631
break;
2632
case OBJ_TYPE_FACES:
2633
switch (param) {
2634
case PARM_PTR_OBJ_VTX:
2635
// Don't allow more than 4 vertices in a face
2636
if (((struct ObjFace *) sDynListCurObj)->vtxCount >= 4) {
2637
fatal_printf("dsetparmp() too many points");
2638
}
2639
// `ptr` here is a vertex index, not an actual pointer.
2640
// These vertex indices later get converted to `ObjVertex` pointers when `find_thisface_verts` is called.
2641
((struct ObjFace *) sDynListCurObj)->vertices[((struct ObjFace *) sDynListCurObj)->vtxCount++] = ptr;
2642
break;
2643
default:
2644
fatal_printf("Bad parm");
2645
}
2646
break;
2647
default:
2648
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetParmp()",
2649
sDynListCurInfo->name, sDynListCurObj->type);
2650
}
2651
}
2652
2653
/**
2654
* Set the generic drawing flags for the current dynamic object.
2655
*/
2656
void d_set_obj_draw_flag(enum ObjDrawingFlags flag) {
2657
if (sDynListCurObj == NULL) {
2658
fatal_printf("proc_dynlist(): No current object");
2659
}
2660
2661
sDynListCurObj->drawFlags |= flag;
2662
}
2663
2664
/**
2665
* Set an object specific type field for the current dynamic object.
2666
*/
2667
void d_set_type(s32 type) {
2668
struct GdObj *dynobj = sDynListCurObj; // sp24
2669
2670
if (sDynListCurObj == NULL) {
2671
fatal_printf("proc_dynlist(): No current object");
2672
}
2673
2674
switch (sDynListCurObj->type) {
2675
case OBJ_TYPE_NETS:
2676
((struct ObjNet *) dynobj)->netType = type;
2677
break;
2678
case OBJ_TYPE_GADGETS:
2679
((struct ObjGadget *) dynobj)->type = type;
2680
break;
2681
case OBJ_TYPE_GROUPS:
2682
((struct ObjGroup *) dynobj)->debugPrint = type;
2683
break;
2684
case OBJ_TYPE_JOINTS:
2685
((struct ObjJoint *) dynobj)->type = type;
2686
break;
2687
case OBJ_TYPE_PARTICLES:
2688
((struct ObjParticle *) dynobj)->unk60 = type;
2689
break;
2690
case OBJ_TYPE_MATERIALS:
2691
((struct ObjMaterial *) dynobj)->type = type;
2692
break;
2693
default:
2694
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetType()",
2695
sDynListCurInfo->name, sDynListCurObj->type);
2696
}
2697
}
2698
2699
/**
2700
* Set the specific object ID field for the current dynamic object.
2701
*/
2702
void d_set_id(s32 id) {
2703
struct GdObj *dynobj = sDynListCurObj; // sp24
2704
2705
if (sDynListCurObj == NULL) {
2706
fatal_printf("proc_dynlist(): No current object");
2707
}
2708
2709
switch (sDynListCurObj->type) {
2710
case OBJ_TYPE_MATERIALS:
2711
((struct ObjMaterial *) dynobj)->id = id;
2712
break;
2713
case OBJ_TYPE_JOINTS:
2714
((struct ObjJoint *) dynobj)->id = id;
2715
break;
2716
case OBJ_TYPE_VERTICES:
2717
((struct ObjVertex *) dynobj)->id = id;
2718
break;
2719
case OBJ_TYPE_LIGHTS:
2720
((struct ObjLight *) dynobj)->id = id;
2721
break;
2722
default:
2723
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetID()",
2724
sDynListCurInfo->name, sDynListCurObj->type);
2725
}
2726
}
2727
2728
// TODO: enumerate colors?
2729
/**
2730
* Set the colour of the current dynamic object. The input color is an index
2731
* for `gd_get_colour()`
2732
*/
2733
void d_set_colour_num(s32 colornum) {
2734
struct GdColour *rgbcolor;
2735
2736
if (sDynListCurObj == NULL) {
2737
fatal_printf("proc_dynlist(): No current object");
2738
}
2739
2740
switch (sDynListCurObj->type) {
2741
case OBJ_TYPE_JOINTS:
2742
((struct ObjJoint *) sDynListCurObj)->colourNum = colornum;
2743
break;
2744
case OBJ_TYPE_PARTICLES:
2745
((struct ObjParticle *) sDynListCurObj)->colourNum = colornum;
2746
break;
2747
case OBJ_TYPE_NETS:
2748
((struct ObjNet *) sDynListCurObj)->colourNum = colornum;
2749
break;
2750
case OBJ_TYPE_GADGETS:
2751
((struct ObjGadget *) sDynListCurObj)->colourNum = colornum;
2752
break;
2753
case OBJ_TYPE_FACES:
2754
rgbcolor = gd_get_colour(colornum);
2755
if (rgbcolor != NULL) {
2756
((struct ObjFace *) sDynListCurObj)->colour.r = rgbcolor->r;
2757
((struct ObjFace *) sDynListCurObj)->colour.g = rgbcolor->g;
2758
((struct ObjFace *) sDynListCurObj)->colour.b = rgbcolor->b;
2759
((struct ObjFace *) sDynListCurObj)->colourNum = colornum;
2760
} else {
2761
fatal_printf("dSetColNum: Unkown colour number");
2762
}
2763
break;
2764
default:
2765
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dColourNum()",
2766
sDynListCurInfo->name, sDynListCurObj->type);
2767
}
2768
}
2769
2770
/**
2771
* Set the material ID of the current dynamic `ObjFace`.
2772
*/
2773
void d_set_material(UNUSED void *a0, s32 mtlId) {
2774
if (sDynListCurObj == NULL) {
2775
fatal_printf("proc_dynlist(): No current object");
2776
}
2777
2778
switch (sDynListCurObj->type) {
2779
case OBJ_TYPE_FACES:
2780
((struct ObjFace *) sDynListCurObj)->mtlId = mtlId;
2781
break;
2782
default:
2783
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetMaterial()",
2784
sDynListCurInfo->name, sDynListCurObj->type);
2785
}
2786
}
2787
2788
/**
2789
* Set the friction vec of the current dynamic `ObjJoint`.
2790
*/
2791
void d_friction(f32 x, f32 y, f32 z) {
2792
if (sDynListCurObj == NULL) {
2793
fatal_printf("proc_dynlist(): No current object");
2794
}
2795
2796
switch (sDynListCurObj->type) {
2797
case OBJ_TYPE_JOINTS:
2798
((struct ObjJoint *) sDynListCurObj)->friction.x = x;
2799
((struct ObjJoint *) sDynListCurObj)->friction.y = y;
2800
((struct ObjJoint *) sDynListCurObj)->friction.z = z;
2801
break;
2802
default:
2803
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dFriction()",
2804
sDynListCurInfo->name, sDynListCurObj->type);
2805
}
2806
}
2807
2808
/**
2809
* Set the spring constant of the current dynamic `ObjBone`.
2810
*/
2811
void d_set_spring(f32 spring) {
2812
if (sDynListCurObj == NULL) {
2813
fatal_printf("proc_dynlist(): No current object");
2814
}
2815
2816
switch (sDynListCurObj->type) {
2817
case OBJ_TYPE_BONES:
2818
((struct ObjBone *) sDynListCurObj)->spring = spring;
2819
break;
2820
default:
2821
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetSpring()",
2822
sDynListCurInfo->name, sDynListCurObj->type);
2823
}
2824
}
2825
2826
/**
2827
* Set the ambient color of the current dynamic `ObjMaterial`.
2828
*/
2829
void d_set_ambient(f32 r, f32 g, f32 b) {
2830
if (sDynListCurObj == NULL) {
2831
fatal_printf("proc_dynlist(): No current object");
2832
}
2833
2834
switch (sDynListCurObj->type) {
2835
case OBJ_TYPE_MATERIALS:
2836
((struct ObjMaterial *) sDynListCurObj)->Ka.r = r;
2837
((struct ObjMaterial *) sDynListCurObj)->Ka.g = g;
2838
((struct ObjMaterial *) sDynListCurObj)->Ka.b = b;
2839
break;
2840
default:
2841
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetAmbient()",
2842
sDynListCurInfo->name, sDynListCurObj->type);
2843
}
2844
}
2845
2846
/**
2847
* Set the diffuse color of the current dynamic `ObjMaterial` or `ObjLight`.
2848
*/
2849
void d_set_diffuse(f32 r, f32 g, f32 b) {
2850
if (sDynListCurObj == NULL) {
2851
fatal_printf("proc_dynlist(): No current object");
2852
}
2853
2854
switch (sDynListCurObj->type) {
2855
case OBJ_TYPE_MATERIALS:
2856
((struct ObjMaterial *) sDynListCurObj)->Kd.r = r;
2857
((struct ObjMaterial *) sDynListCurObj)->Kd.g = g;
2858
((struct ObjMaterial *) sDynListCurObj)->Kd.b = b;
2859
break;
2860
case OBJ_TYPE_LIGHTS:
2861
((struct ObjLight *) sDynListCurObj)->diffuse.r = r;
2862
((struct ObjLight *) sDynListCurObj)->diffuse.g = g;
2863
((struct ObjLight *) sDynListCurObj)->diffuse.b = b;
2864
break;
2865
default:
2866
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetDiffuse()",
2867
sDynListCurInfo->name, sDynListCurObj->type);
2868
}
2869
}
2870
2871
/**
2872
* Set the control type of the current dynamic `ObjNet`.
2873
*/
2874
void d_set_control_type(s32 ctrltype) {
2875
if (sDynListCurObj == NULL) {
2876
fatal_printf("proc_dynlist(): No current object");
2877
}
2878
2879
switch (sDynListCurObj->type) {
2880
case OBJ_TYPE_NETS:
2881
((struct ObjNet *) sDynListCurObj)->ctrlType = ctrltype;
2882
break;
2883
default:
2884
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dControlType()",
2885
sDynListCurInfo->name, sDynListCurObj->type);
2886
}
2887
}
2888
2889
/**
2890
* Get a pointer to a `GdBoundingBox` in the current dynamic object.
2891
* If the current object does not have a bounding box, a pointer to
2892
* a global bounding box at (0,0) is returned.
2893
*/
2894
struct GdBoundingBox *d_get_bounding_box(void) {
2895
if (sDynListCurObj == NULL) {
2896
fatal_printf("proc_dynlist(): No current object");
2897
}
2898
2899
switch (sDynListCurObj->type) {
2900
case OBJ_TYPE_NETS:
2901
return &((struct ObjNet *) sDynListCurObj)->boundingBox;
2902
break;
2903
case OBJ_TYPE_PLANES:
2904
return &((struct ObjPlane *) sDynListCurObj)->boundingBox;
2905
break;
2906
case OBJ_TYPE_ZONES:
2907
return &((struct ObjZone *) sDynListCurObj)->boundingBox;
2908
break;
2909
default:
2910
return &sNullBoundingBox;
2911
}
2912
}
2913
2914
/**
2915
* Copy the matrix from the current dynamic object into `dst`.
2916
*/
2917
void d_get_matrix(Mat4f *dst) {
2918
struct GdObj *dynobj; // sp24
2919
2920
if (sDynListCurObj == NULL) {
2921
fatal_printf("proc_dynlist(): No current object");
2922
}
2923
2924
dynobj = sDynListCurObj;
2925
switch (sDynListCurObj->type) {
2926
case OBJ_TYPE_NETS:
2927
gd_copy_mat4f(&((struct ObjNet *) dynobj)->mat128, dst);
2928
break;
2929
break; // lol
2930
case OBJ_TYPE_JOINTS:
2931
gd_copy_mat4f(&((struct ObjJoint *) dynobj)->matE8, dst);
2932
break;
2933
case OBJ_TYPE_CAMERAS:
2934
gd_copy_mat4f(&((struct ObjCamera *) dynobj)->unkE8, dst);
2935
break;
2936
case OBJ_TYPE_PARTICLES:
2937
gd_set_identity_mat4(dst);
2938
break;
2939
case OBJ_TYPE_SHAPES:
2940
gd_set_identity_mat4(dst);
2941
break;
2942
default:
2943
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetMatrix()",
2944
sDynListCurInfo->name, sDynListCurObj->type);
2945
}
2946
}
2947
2948
/**
2949
* Set the matrix of the current dynamic object by copying `src` into the object.
2950
*/
2951
void d_set_matrix(Mat4f *src) {
2952
if (sDynListCurObj == NULL) {
2953
fatal_printf("proc_dynlist(): No current object");
2954
}
2955
2956
switch (sDynListCurObj->type) {
2957
case OBJ_TYPE_NETS:
2958
gd_copy_mat4f(src, &((struct ObjNet *) sDynListCurObj)->mat128);
2959
//! @bug When setting an `ObjNet` matrix, the source is copied twice
2960
//! due to a probable copy-paste line repeat error
2961
gd_copy_mat4f(src, &((struct ObjNet *) sDynListCurObj)->mat128);
2962
break;
2963
case OBJ_TYPE_JOINTS:
2964
gd_copy_mat4f(src, &((struct ObjJoint *) sDynListCurObj)->matE8);
2965
break;
2966
case OBJ_TYPE_CAMERAS:
2967
gd_copy_mat4f(src, &((struct ObjCamera *) sDynListCurObj)->unk64);
2968
break;
2969
default:
2970
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetMatrix()",
2971
sDynListCurInfo->name, sDynListCurObj->type);
2972
}
2973
}
2974
2975
/**
2976
* Set the rotation matrix of the current dynamic object by copying
2977
* the input matrix `src`.
2978
*/
2979
void d_set_rot_mtx(Mat4f *src) {
2980
if (sDynListCurObj == NULL) {
2981
fatal_printf("proc_dynlist(): No current object");
2982
}
2983
2984
switch (sDynListCurObj->type) {
2985
case OBJ_TYPE_JOINTS:
2986
gd_copy_mat4f(src, &((struct ObjJoint *) sDynListCurObj)->mat128);
2987
break;
2988
case OBJ_TYPE_NETS:
2989
gd_copy_mat4f(src, &((struct ObjNet *) sDynListCurObj)->mat168);
2990
break;
2991
default:
2992
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetRMatrix()",
2993
sDynListCurInfo->name, sDynListCurObj->type);
2994
}
2995
}
2996
2997
/**
2998
* Get a pointer to the current dynamic object's rotation matrix.
2999
*/
3000
Mat4f *d_get_rot_mtx_ptr(void) {
3001
if (sDynListCurObj == NULL) {
3002
fatal_printf("proc_dynlist(): No current object");
3003
}
3004
3005
switch (sDynListCurObj->type) {
3006
case OBJ_TYPE_JOINTS:
3007
return &((struct ObjJoint *) sDynListCurObj)->mat128;
3008
case OBJ_TYPE_NETS:
3009
return &((struct ObjNet *) sDynListCurObj)->mat168;
3010
default:
3011
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetRMatrixPtr()",
3012
sDynListCurInfo->name, sDynListCurObj->type);
3013
}
3014
// No null return due to `fatal_printf()` being a non-returning function?
3015
}
3016
3017
/**
3018
* Copy `src` into the matrix of the current dynamic object.
3019
* TODO: What is an IMatrix?
3020
*/
3021
void d_set_i_matrix(Mat4f *src) {
3022
struct GdObj *dynobj;
3023
3024
if (sDynListCurObj == NULL) {
3025
fatal_printf("proc_dynlist(): No current object");
3026
}
3027
3028
dynobj = sDynListCurObj;
3029
switch (sDynListCurObj->type) {
3030
case OBJ_TYPE_NETS:
3031
gd_copy_mat4f(src, &((struct ObjNet *) dynobj)->matE8);
3032
break;
3033
case OBJ_TYPE_JOINTS:
3034
gd_copy_mat4f(src, &((struct ObjJoint *) dynobj)->mat168);
3035
break;
3036
case OBJ_TYPE_LIGHTS:
3037
((struct ObjLight *) dynobj)->position.x = (*src)[3][0];
3038
((struct ObjLight *) dynobj)->position.y = (*src)[3][1];
3039
((struct ObjLight *) dynobj)->position.z = (*src)[3][2];
3040
break;
3041
default:
3042
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetIMatrix()",
3043
sDynListCurInfo->name, sDynListCurObj->type);
3044
}
3045
}
3046
3047
/**
3048
* Get a pointer to the current dynamic object's matrix.
3049
*/
3050
Mat4f *d_get_matrix_ptr(void) {
3051
if (sDynListCurObj == NULL) {
3052
fatal_printf("proc_dynlist(): No current object");
3053
}
3054
3055
switch (sDynListCurObj->type) {
3056
case OBJ_TYPE_NETS:
3057
return &((struct ObjNet *) sDynListCurObj)->mat128;
3058
break;
3059
case OBJ_TYPE_CAMERAS:
3060
return &((struct ObjCamera *) sDynListCurObj)->unk64;
3061
break;
3062
case OBJ_TYPE_BONES:
3063
return &((struct ObjBone *) sDynListCurObj)->mat70;
3064
break;
3065
case OBJ_TYPE_JOINTS:
3066
return &((struct ObjJoint *) sDynListCurObj)->matE8;
3067
break;
3068
default:
3069
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetMatrixPtr()",
3070
sDynListCurInfo->name, sDynListCurObj->type);
3071
}
3072
// No null return due to `fatal_printf()` being a non-returning function?
3073
}
3074
3075
/**
3076
* Get a pointer to the current dynamic object's matrix.
3077
* TODO: What is an IMatrix?
3078
*/
3079
Mat4f *d_get_i_mtx_ptr(void) {
3080
struct GdObj *dynobj; // sp24
3081
3082
if (sDynListCurObj == NULL) {
3083
fatal_printf("proc_dynlist(): No current object");
3084
}
3085
3086
dynobj = sDynListCurObj;
3087
switch (sDynListCurObj->type) {
3088
case OBJ_TYPE_NETS:
3089
return &((struct ObjNet *) dynobj)->matE8;
3090
break;
3091
case OBJ_TYPE_JOINTS:
3092
return &((struct ObjJoint *) dynobj)->mat168;
3093
break;
3094
default:
3095
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dGetIMatrixPtr()",
3096
sDynListCurInfo->name, sDynListCurObj->type);
3097
}
3098
// No null return due to `fatal_printf()` being a non-returning function?
3099
}
3100
3101
/**
3102
* Use the dynamic object system to calculate the distance between
3103
* two `GdObj`s. The objects don't have to be dynamic objects.
3104
*/
3105
f32 d_calc_world_dist_btwn(struct GdObj *obj1, struct GdObj *obj2) {
3106
struct GdVec3f obj1pos; // sp34
3107
struct GdVec3f obj2pos; // sp28
3108
struct GdVec3f posdiff; // sp1C
3109
3110
set_cur_dynobj(obj1);
3111
d_get_world_pos(&obj1pos);
3112
set_cur_dynobj(obj2);
3113
d_get_world_pos(&obj2pos);
3114
3115
posdiff.x = obj2pos.x - obj1pos.x;
3116
posdiff.y = obj2pos.y - obj1pos.y;
3117
posdiff.z = obj2pos.z - obj1pos.z;
3118
3119
return gd_vec3f_magnitude(&posdiff);
3120
}
3121
3122
/**
3123
* Create a new weight for the vertex `vtxId` in the current dynamic `ObjJoint`.
3124
* The input weight value is out of 100.
3125
*/
3126
void d_set_skin_weight(s32 vtxId, f32 percentWeight) {
3127
if (sDynListCurObj == NULL) {
3128
fatal_printf("proc_dynlist(): No current object");
3129
}
3130
3131
switch (sDynListCurObj->type) {
3132
case OBJ_TYPE_JOINTS:
3133
set_skin_weight((struct ObjJoint *) sDynListCurObj, vtxId, NULL,
3134
percentWeight / 100.0);
3135
break;
3136
default:
3137
fatal_printf("%s: Object '%s'(%x) does not support this function.", "dSetSkinWeight()",
3138
sDynListCurInfo->name, sDynListCurObj->type);
3139
}
3140
}
3141
3142