Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/src/goddard/particles.c
7858 views
1
#include <PR/ultratypes.h>
2
3
#include "debug_utils.h"
4
#include "draw_objects.h"
5
#include "dynlist_proc.h"
6
#include "gd_math.h"
7
#include "gd_types.h"
8
#include "macros.h"
9
#include "objects.h"
10
#include "particles.h"
11
#include "renderer.h"
12
#include "skin.h"
13
14
// static types
15
typedef union {
16
struct ObjVertex *vtx;
17
struct ObjParticle *ptc;
18
} VtxPtc;
19
20
struct Connection {
21
struct GdObj header; // this header is never used
22
u8 filler14[8];
23
VtxPtc node1; // first connected vertex or particle
24
VtxPtc node2; // second connected vertex or particle
25
f32 unk24;
26
u32 unk28; // union tag? 0 = vertex; 1 = particle?
27
};
28
29
// data
30
UNUSED static void *sUnused801A81D0 = NULL;
31
static s32 D_801A81D4[25] = {
32
/* ID? X Y Z */
33
9, 3, 12, -14, 25, 5, 16, -25, 42, 4, 15, -39, 55,
34
-6, 20, -23, 70, -2, 20, -23, 135, 0, 16, 0, 0 /* Terminator */
35
};
36
static s32 D_801A8238[5] = {
37
/* ID? X Y Z */
38
15, 0, 22, 0, 0 /* Terminator */
39
};
40
41
// static bss
42
static struct ObjFace *D_801B9EF0;
43
44
// fn declarations
45
struct Connection *make_connection(struct ObjVertex *, struct ObjVertex *);
46
void Unknown80181D14(struct ObjFace *);
47
void func_80181EB0(struct Connection *);
48
void func_80182088(struct Connection *);
49
void move_particle(struct ObjParticle *);
50
struct Connection *make_connection(struct ObjVertex *, struct ObjVertex *);
51
int func_80182778(struct ObjParticle *);
52
void func_80182A08(struct ObjParticle *, struct GdVec3f *b);
53
void func_801838D0(struct ObjParticle *);
54
void Unknown801835C8(struct ObjParticle *ptc);
55
56
static void connect_vertices(struct ObjVertex *vtx1, struct ObjVertex *vtx2) {
57
struct Connection *newConn;
58
register struct ListNode *link;
59
60
if (vtx1 == vtx2) {
61
return;
62
}
63
link = gGdSkinNet->unk1C0->firstMember;
64
while (link != NULL) {
65
// FIXME: types
66
struct Connection *conn = (struct Connection *) link->obj;
67
68
if ((conn->node1.vtx == vtx1 || conn->node1.vtx == vtx2)
69
&& (conn->node2.vtx == vtx1 || conn->node2.vtx == vtx2)) {
70
break;
71
}
72
link = link->next;
73
}
74
if (link == NULL) {
75
newConn = make_connection(vtx1, vtx2);
76
//! make_connection never sets the header, so not sure what happens here
77
addto_group(gGdSkinNet->unk1C0, &newConn->header);
78
}
79
}
80
81
/* 2304E4 -> 230680 */
82
void Unknown80181D14(struct ObjFace *face) {
83
s32 i;
84
s32 j;
85
struct ObjVertex *vtx1;
86
struct ObjVertex *vtx2;
87
88
for (i = 0; i < face->vtxCount - 1; i++) {
89
vtx1 = face->vertices[i];
90
vtx2 = face->vertices[i + 1];
91
connect_vertices(vtx1, vtx2);
92
}
93
if (D_801B9EF0 != NULL) {
94
for (i = 0; i < face->vtxCount; i++) {
95
vtx1 = face->vertices[i];
96
for (j = 0; j < D_801B9EF0->vtxCount; j++) {
97
vtx2 = D_801B9EF0->vertices[j];
98
connect_vertices(vtx1, vtx2);
99
}
100
}
101
}
102
D_801B9EF0 = face;
103
}
104
105
/* 230680 -> 230858 */
106
void func_80181EB0(struct Connection *cxn) {
107
struct GdVec3f sp34;
108
UNUSED u8 unused[0x2C];
109
struct ObjParticle *sp4 = cxn->node1.ptc;
110
struct ObjParticle *sp0 = cxn->node2.ptc;
111
112
sp34.x = 0.0f;
113
sp34.y = sp4->pos.y - sp0->pos.y;
114
sp34.z = 0.0f;
115
sp34.y *= 0.01;
116
sp4->unk38.x -= sp34.x;
117
sp4->unk38.y -= sp34.y;
118
sp4->unk38.z -= sp34.z;
119
sp0->unk38.x += sp34.x;
120
sp0->unk38.y += sp34.y;
121
sp0->unk38.z += sp34.z;
122
if (!(sp4->flags & 2)) {
123
sp4->pos.x -= sp34.x;
124
sp4->pos.y -= sp34.y;
125
sp4->pos.z -= sp34.z;
126
}
127
if (!(sp0->flags & 2)) {
128
sp0->pos.x += sp34.x;
129
sp0->pos.y += sp34.y;
130
sp0->pos.z += sp34.z;
131
}
132
}
133
134
/* @ 230858 -> 230B70 */
135
void func_80182088(struct Connection *cxn) {
136
struct GdVec3f sp4C;
137
UNUSED u8 unused[0x24];
138
f32 sp24;
139
f32 sp20;
140
struct ObjParticle *sp1C;
141
struct ObjParticle *sp18;
142
143
if (cxn->unk28 & 1) {
144
func_80181EB0(cxn);
145
return;
146
}
147
sp1C = cxn->node1.ptc;
148
sp18 = cxn->node2.ptc;
149
sp4C.x = sp1C->pos.x - sp18->pos.x;
150
sp4C.y = sp1C->pos.y - sp18->pos.y;
151
sp4C.z = sp1C->pos.z - sp18->pos.z;
152
sp20 = gd_vec3f_magnitude(&sp4C);
153
sp24 = sp20 - cxn->unk24;
154
sp4C.x /= sp20;
155
sp4C.y /= sp20;
156
sp4C.z /= sp20;
157
sp4C.x *= sp24 * 0.1;
158
sp4C.y *= sp24 * 0.1;
159
sp4C.z *= sp24 * 0.1;
160
sp1C->unk38.x -= sp4C.x;
161
sp1C->unk38.y -= sp4C.y;
162
sp1C->unk38.z -= sp4C.z;
163
sp18->unk38.x += sp4C.x;
164
sp18->unk38.y += sp4C.y;
165
sp18->unk38.z += sp4C.z;
166
if (!(sp1C->flags & 2)) {
167
sp1C->pos.x -= sp4C.x;
168
sp1C->pos.y -= sp4C.y;
169
sp1C->pos.z -= sp4C.z;
170
}
171
if (!(sp18->flags & 2)) {
172
sp18->pos.x += sp4C.x;
173
sp18->pos.y += sp4C.y;
174
sp18->pos.z += sp4C.z;
175
}
176
}
177
178
/* 230B70 -> 230CC0 */
179
void func_801823A0(struct ObjNet *net) {
180
register struct ListNode *link;
181
struct Connection *cxn;
182
183
gGdSkinNet = net;
184
switch (net->unk3C) {
185
case 1: // Shape; Are these flags the same as net->netType (+0x1EC)?
186
net->unk1C8 = net->shapePtr->vtxGroup;
187
net->unk1C0 = make_group(0);
188
D_801B9EF0 = NULL;
189
190
apply_to_obj_types_in_group(OBJ_TYPE_FACES, (applyproc_t) Unknown80181D14,
191
net->shapePtr->faceGroup);
192
net->unk3C = 2;
193
break;
194
case 2:
195
link = net->unk1C0->firstMember;
196
while (link != NULL) {
197
// FIXME: types
198
cxn = (struct Connection *) link->obj;
199
func_80182088(cxn);
200
link = link->next;
201
}
202
apply_to_obj_types_in_group(OBJ_TYPE_PARTICLES, (applyproc_t) move_particle, net->unk1C8);
203
apply_to_obj_types_in_group(OBJ_TYPE_PLANES, (applyproc_t) reset_plane, net->unk1CC);
204
break;
205
}
206
}
207
208
/* 230CC0 -> 230DCC */
209
struct ObjParticle *make_particle(u32 flags, s32 colourNum, f32 x, f32 y, f32 z) {
210
struct ObjParticle *particle = (struct ObjParticle *) make_object(OBJ_TYPE_PARTICLES);
211
UNUSED u8 unused[8];
212
213
particle->pos.x = x;
214
particle->pos.y = y;
215
particle->pos.z = z;
216
particle->unk38.x = particle->unk38.y = particle->unk38.z = 0.0f;
217
particle->colourNum = colourNum;
218
particle->flags = flags | 8;
219
particle->timeout = -1;
220
particle->id = D_801B9E40; /* should this be D_801B9E40++? */
221
particle->shapePtr = NULL;
222
particle->unkB0 = 1;
223
return particle;
224
}
225
226
/* 230DCC -> 230F48 */
227
struct Connection *make_connection(struct ObjVertex *vtx1, struct ObjVertex *vtx2) {
228
struct Connection *conn = gd_malloc_perm(sizeof(struct Connection));
229
struct GdVec3f sp28;
230
struct GdVec3f sp1C;
231
232
if (conn == NULL) {
233
fatal_print("Cant allocate connection memory!");
234
}
235
conn->node1.vtx = vtx1;
236
conn->node2.vtx = vtx2;
237
d_stash_dynobj();
238
set_cur_dynobj((struct GdObj *)vtx1);
239
d_get_world_pos(&sp28);
240
set_cur_dynobj((struct GdObj *)vtx2);
241
d_get_world_pos(&sp1C);
242
sp28.x -= sp1C.x;
243
sp28.y -= sp1C.y;
244
sp28.z -= sp1C.z;
245
conn->unk24 = gd_vec3f_magnitude(&sp28);
246
// Duplicate conditional. Possibly should've checked `vtx2`;
247
// Also, this shouldn't be called with particle types...
248
if (vtx1->header.type == OBJ_TYPE_PARTICLES && vtx1->header.type == OBJ_TYPE_PARTICLES) {
249
if ((((struct ObjParticle *) vtx1)->flags & 4) && (((struct ObjParticle *) vtx2)->flags & 4)) {
250
conn->unk28 |= 1;
251
}
252
}
253
d_unstash_dynobj();
254
return conn;
255
}
256
257
/* 230F48 -> 2311D8 */
258
int func_80182778(struct ObjParticle *ptc) {
259
s32 sp4 = 0;
260
261
if (ptc->unk7C->animSeqNum == 2 && ptc->unk74 == 1) {
262
while (D_801A81D4[sp4] != 0) {
263
if (D_801A81D4[sp4] == ptc->unk7C->frame) {
264
ptc->pos.x = D_801A81D4[sp4 + 1] * 10.0f;
265
ptc->pos.y = D_801A81D4[sp4 + 2] * 10.0f;
266
ptc->pos.z = D_801A81D4[sp4 + 3] * 10.0f;
267
return TRUE;
268
}
269
sp4 += 4;
270
}
271
}
272
if (ptc->unk7C->animSeqNum == 1 && ptc->unk74 == 1) {
273
while (D_801A8238[sp4] != 0) {
274
if (D_801A8238[sp4] == ptc->unk7C->frame) {
275
ptc->pos.x = D_801A8238[sp4 + 1] * 10.0f;
276
ptc->pos.y = D_801A8238[sp4 + 2] * 10.0f;
277
ptc->pos.z = D_801A8238[sp4 + 3] * 10.0f;
278
return TRUE;
279
}
280
sp4 += 4;
281
}
282
}
283
return FALSE;
284
}
285
286
/* 2311D8 -> 231454 */
287
void func_80182A08(struct ObjParticle *ptc, struct GdVec3f *b) {
288
register struct ListNode *link;
289
struct ObjParticle *sp20;
290
291
if (ptc->subParticlesGrp != NULL) {
292
link = ptc->subParticlesGrp->firstMember;
293
while (link != NULL) {
294
// FIXME: types
295
sp20 = (struct ObjParticle *) link->obj;
296
if (sp20->timeout <= 0) {
297
sp20->pos.x = ptc->pos.x;
298
sp20->pos.y = ptc->pos.y;
299
sp20->pos.z = ptc->pos.z;
300
sp20->timeout = 12.0f - gd_rand_float() * 5.0f;
301
do {
302
sp20->unk38.x = gd_rand_float() * 50.0 - 25.0;
303
sp20->unk38.y = gd_rand_float() * 50.0 - 25.0;
304
sp20->unk38.z = gd_rand_float() * 50.0 - 25.0;
305
} while (gd_vec3f_magnitude(&sp20->unk38) > 30.0);
306
sp20->unk38.x += b->x;
307
sp20->unk38.y += b->y;
308
sp20->unk38.z += b->z;
309
sp20->header.drawFlags &= ~OBJ_INVISIBLE;
310
sp20->flags |= 8;
311
}
312
link = link->next;
313
}
314
}
315
}
316
317
/* 231454 -> 231D40; orig name: Unknown80182C84 */
318
void move_particle(struct ObjParticle *ptc) {
319
f32 sp7C;
320
UNUSED u8 unused2[12];
321
struct GdVec3f sp64;
322
struct ObjParticle *sp60;
323
UNUSED u8 unused1[4];
324
s32 i;
325
UNUSED u8 unused4[4];
326
UNUSED u8 unused5[4];
327
struct ObjCamera *sp4C;
328
struct GdVec3f sp40;
329
struct GdVec3f sp34;
330
331
if (ptc->flags & 2) {
332
return;
333
}
334
if (!(ptc->flags & 8)) {
335
return;
336
}
337
if (ptc->unk60 == 3) {
338
sp40.x = -gViewUpdateCamera->unkE8[2][0] * 50.0f;
339
sp40.y = -gViewUpdateCamera->unkE8[2][1] * 50.0f;
340
sp40.z = gViewUpdateCamera->unkE8[2][2] * 50.0f;
341
sp34.x = gViewUpdateCamera->unkE8[2][0] * -20.0f;
342
sp34.y = gViewUpdateCamera->unkE8[2][1] * -20.0f;
343
sp34.z = gViewUpdateCamera->unkE8[2][2] * -20.0f;
344
}
345
if (ptc->attachedToObj != NULL) {
346
set_cur_dynobj(ptc->attachedToObj);
347
if (ptc->unk60 == 3) {
348
if (ptc->unk64 == 3) {
349
sp4C = (struct ObjCamera *) ptc->attachedToObj;
350
// Camera->unk18C = ObjView here
351
if (sp4C->unk18C->pickedObj != NULL) {
352
set_cur_dynobj(sp4C->unk18C->pickedObj);
353
ptc->flags |= 0x20;
354
; // needed to match
355
} else {
356
ptc->flags &= ~0x10;
357
ptc->flags &= ~0x20;
358
}
359
}
360
}
361
d_get_world_pos(&sp64);
362
ptc->pos.x = sp64.x;
363
ptc->pos.y = sp64.y;
364
ptc->pos.z = sp64.z;
365
}
366
sp7C = -0.4f;
367
ptc->pos.x += ptc->unk38.x;
368
ptc->pos.y += ptc->unk38.y;
369
ptc->pos.z += ptc->unk38.z;
370
if (ptc->flags & 1) {
371
ptc->unk38.y += sp7C;
372
}
373
func_801838D0(ptc);
374
switch (ptc->unkB0) {
375
case 1:
376
ptc->unkB0 = 2;
377
if (ptc->unk60 == 3) {
378
switch (ptc->unk64) {
379
case 1:
380
ptc->subParticlesGrp = make_group(0);
381
for (i = 0; i < 50; i++) {
382
sp60 = make_particle(1, -1, ptc->pos.x, ptc->pos.y, ptc->pos.z);
383
sp60->shapePtr = ptc->shapePtr;
384
addto_group(ptc->subParticlesGrp, &sp60->header);
385
sp60->flags &= ~8;
386
}
387
break;
388
case 2:
389
case 3:
390
ptc->subParticlesGrp = make_group(0);
391
for (i = 0; i < 30; i++) {
392
sp60 = make_particle(1, -1, ptc->pos.x, ptc->pos.y, ptc->pos.z);
393
sp60->shapePtr = ptc->shapePtr;
394
addto_group(ptc->subParticlesGrp, &sp60->header);
395
sp60->flags &= ~8;
396
}
397
break;
398
}
399
}
400
break;
401
default:
402
break;
403
}
404
ptc->unk38.x *= 0.9;
405
ptc->unk38.y *= 0.9;
406
ptc->unk38.z *= 0.9;
407
if (ptc->unk60 == 3) {
408
switch (ptc->unk64) {
409
case 1:
410
if (func_80182778(ptc) && ptc->subParticlesGrp != NULL) {
411
register struct ListNode *link;
412
413
if (ptc->unk80 != NULL) {
414
ptc->unk80->unk3C |= 1;
415
ptc->unk80->position.x = ptc->pos.x;
416
ptc->unk80->position.y = ptc->pos.y;
417
ptc->unk80->position.z = ptc->pos.z;
418
}
419
link = ptc->subParticlesGrp->firstMember;
420
while (link != NULL) {
421
struct ObjParticle *sp2C = (struct ObjParticle *) link->obj;
422
423
sp2C->pos.x = ptc->pos.x;
424
sp2C->pos.y = ptc->pos.y;
425
sp2C->pos.z = ptc->pos.z;
426
sp2C->timeout = 20;
427
do {
428
sp2C->unk38.x = gd_rand_float() * 64.0 - 32.0;
429
sp2C->unk38.y = gd_rand_float() * 64.0 - 32.0;
430
sp2C->unk38.z = gd_rand_float() * 64.0 - 32.0;
431
} while (gd_vec3f_magnitude(&sp2C->unk38) > 32.0);
432
sp2C->unk30 = gd_rand_float() * 180.0f;
433
sp2C->header.drawFlags &= ~OBJ_INVISIBLE;
434
sp2C->flags |= 8;
435
link = link->next;
436
}
437
}
438
break;
439
case 3:
440
if ((ptc->flags & 0x20) && !(ptc->flags & 0x10)) {
441
func_80182A08(ptc, &sp40);
442
ptc->flags |= 0x10;
443
}
444
break;
445
case 2:
446
func_80182A08(ptc, &sp34);
447
break;
448
}
449
apply_to_obj_types_in_group(OBJ_TYPE_PARTICLES, (applyproc_t) move_particle, ptc->subParticlesGrp);
450
}
451
if (ptc->timeout >= 0) {
452
if (ptc->timeout-- <= 0) {
453
ptc->header.drawFlags |= OBJ_INVISIBLE;
454
ptc->flags &= ~8;
455
}
456
}
457
}
458
459
/* 231D40 -> 231D98; orig name: func_80183570 */
460
void move_particles_in_grp(struct ObjGroup *group) {
461
start_timer("particles");
462
gGdSkinNet = NULL;
463
apply_to_obj_types_in_group(OBJ_TYPE_PARTICLES, (applyproc_t) move_particle, group);
464
stop_timer("particles");
465
}
466
467
#define ABS(x) ((x) < 0.0f ? -(x) : (x))
468
/* 231D98 -> 232040 */
469
void Unknown801835C8(struct ObjParticle *ptc) {
470
struct GdVec3f sp54;
471
f32 sp50;
472
register struct ListNode *link;
473
474
gd_printf("p(%d)=", ptc->attachedObjsGrp->memberCount);
475
link = ptc->attachedObjsGrp->firstMember;
476
while (link != NULL) {
477
// FIXME: types
478
struct ObjParticle *sp48 = (struct ObjParticle *) link->obj;
479
480
sp54.x = sp48->pos.x - ptc->pos.x;
481
sp54.y = sp48->pos.y - ptc->pos.y;
482
sp54.z = sp48->pos.z - ptc->pos.z;
483
sp50 = 150.0f - (ABS(sp54.x) + ABS(sp54.y) + ABS(sp54.z));
484
gd_printf(",%f ", sp50);
485
sp50 *= 0.00000005;
486
ptc->pos.x += sp50 * sp54.x;
487
ptc->pos.y += sp50 * sp54.y;
488
ptc->pos.z += sp50 * sp54.z;
489
sp48->pos.x -= sp50 * sp54.x;
490
sp48->pos.y -= sp50 * sp54.y;
491
sp48->pos.z -= sp50 * sp54.z;
492
link = link->next;
493
}
494
gd_printf("\n");
495
}
496
497
/**
498
* Unused
499
*/
500
void stub_particles_1(UNUSED s32 a) {
501
}
502
503
/**
504
* Unused
505
*/
506
void stub_particles_2(UNUSED s32 a) {
507
}
508
509
/**
510
* Unused
511
*/
512
void stub_particles_3(UNUSED s32 a, UNUSED s32 b, UNUSED s32 c) {
513
}
514
515
/**
516
* Unused
517
*/
518
void stub_particles_4(UNUSED s32 a, UNUSED s32 b, UNUSED s32 c) {
519
}
520
521
/* 2320A0 -> 2320D4; pad to 2320E0 */
522
void func_801838D0(struct ObjParticle *ptc) {
523
D_801B9E3C = ptc;
524
if (ptc->pos.y < -15.0f) {
525
}
526
}
527
528