Digimon World 3 decomp
The European version, SLES_039.36
Loading...
Searching...
No Matches
model_mesh.c
Go to the documentation of this file.
1/* The first object of FIGHTSTG.PRO, the models and their meshes.
2 FIGHTSTG.PRO was seven objects: each one's jump tables are aligned to 8
3 from the start of its own rodata, and they are 4 bytes past a multiple of
4 8 from 0x80082464 (USA) to 0x80082480, from 0x800825B4 to 0x800825D0 and
5 from 0x8008267C on. Where each object's code starts is only known to be
6 between the function with the last jump table of the object before and
7 the one with its first; the last object (camera_task.c) differs between
8 the versions. The second object is stage.c; the third to the sixth are
9 cut into modules, in their link order (entrance.c to fader.c, lights.c
10 and face.c, battle_script.c and first_tech.c, item.c to interp.c), each
11 with its own rodata and data; a cut is only where each jump table keeps
12 its place. Each object's or module's data is in its own file, in address
13 order; the zeros that end the file, after the last object's data, are
14 here. */
15
16#include "battle/battle_mode.h"
17#include "engine/gte.h"
18
19/* Blends a bone's position, rotation and scale from the saved pose
20 (FIGHTSTG_saveBlendPose) towards their first keys at or after the model's
21 frame, by its blend; when either scale has a 0, the key's is taken as it
22 is */
23void FIGHTSTG_blendBone(Model *model, ModelBone *bone) {
24 s32 i;
25 void *archive;
26 SVECTOR *key;
27 SVECTOR *out;
28 SVECTOR cur;
29 SVECTOR prev;
30 SVECTOR diff;
31 SVECTOR step;
32
33 archive = FILE_CACHE.getEntry(bone->keyFile);
34 for (i = 0; i < 9; i += 3) {
35 key = FILE_CACHE.getArchiveEntry(i / 3, archive);
36 switch (i) {
37 case 3:
38 out = &bone->rot;
39 break;
40 case 6:
41 out = &bone->scale;
42 break;
43 case 0:
44 default:
45 out = &bone->pos;
46 break;
47 }
48 for (; key->pad < model->frame; key++) {
49 }
50 cur = *key;
51 switch (i) {
52 case 0:
53 default:
54 prev = bone->prevPos;
55 break;
56 case 3:
57 prev = bone->prevRot;
58 break;
59 case 6:
60 prev = bone->prevScale;
61 break;
62 }
63 if (i == 6 && (prev.vx == 0 || prev.vy == 0 || prev.vz == 0 || cur.vx == 0 || cur.vy == 0 || cur.vz == 0)) {
64 *out = cur;
65 return;
66 }
67 gte_lddp(model->blend);
68 diff.vx = cur.vx - prev.vx;
69 diff.vy = cur.vy - prev.vy;
70 diff.vz = cur.vz - prev.vz;
71 gte_ldsv(&diff);
72 gte_gpf12();
73 *out = prev;
74 gte_stsv(&step);
75 out->vx += step.vx;
76 out->vy += step.vy;
77 out->vz += step.vz;
78 }
79}
80
81/* Sets a bone's position, rotation and scale to their keys at FRAME,
82 interpolated between the keys around it */
83void FIGHTSTG_poseBone(Model *model, ModelBone *bone, s32 frame) {
84 s32 i;
85 void *archive;
86 SVECTOR *key;
87 SVECTOR *out;
88 s32 found;
89 s32 span;
90 SVECTOR cur;
91 SVECTOR prev;
92 SVECTOR diff;
93 SVECTOR step;
94
95 archive = FILE_CACHE.getEntry(bone->keyFile);
96 for (i = 0; i < 9; i += 3) {
97 key = FILE_CACHE.getArchiveEntry(i / 3, archive);
98 found = 0;
99 switch (i) {
100 case 3:
101 out = &bone->rot;
102 break;
103 case 6:
104 out = &bone->scale;
105 break;
106 case 0:
107 default:
108 out = &bone->pos;
109 break;
110 }
111 for (;; key++) {
112 if (key->pad == frame) {
113 found = 1;
114 break;
115 }
116 if (key->pad >= frame) {
117 break;
118 }
119 }
120 if (found) {
121 *out = *key;
122 } else {
123 cur = key[0];
124 prev = key[-1];
125 span = cur.pad - prev.pad;
126 gte_lddp(((frame - prev.pad) << 12) / span);
127 diff.vx = cur.vx - prev.vx;
128 diff.vy = cur.vy - prev.vy;
129 diff.vz = cur.vz - prev.vz;
130 gte_ldsv(&diff);
131 gte_gpf12();
132 *out = prev;
133 gte_stsv(&step);
134 out->vx += step.vx;
135 out->vy += step.vy;
136 out->vz += step.vz;
137 }
138 }
139}
140
141/* Moves the root bone by the model's move along its rotation, then poses
142 (FIGHTSTG_poseBone) or blends (FIGHTSTG_blendBone) each other bone */
143void FIGHTSTG_poseBones(Model *model, Mesh **children) {
144 ModelBone *bone = model->bones;
145 VECTOR moved;
146 s32 i;
147
148 if (model->move.xy != 0 || model->move.v.vz != 0) {
149 gte_SetRotMatrix(&bone->local);
150 gte_ldv0(&model->move.v);
151 gte_rtv0();
152 gte_stlvnl(&moved);
153 model->bones->pos.vx += moved.vx;
154 model->bones->pos.vy += moved.vy;
155 model->bones->pos.vz += moved.vz;
156 model->move.v.vz = 0;
157 model->move.v.vy = 0;
158 model->move.v.vx = 0;
159 }
160 bone = model->bones;
161 if (model->blending == 0) {
162 for (i = 1, bone++; i < model->boneCount; i++, bone++) {
163 FIGHTSTG_poseBone(model, bone, model->frame);
164 }
165 } else {
166 for (i = 1, bone++; i < model->boneCount; i++, bone++) {
167 FIGHTSTG_blendBone(model, bone);
168 }
169 }
170}
171
172/* Saves each bone's pose as the one a blend starts from */
174 ModelBone *bone = model->bones;
175 s32 i;
176
177 for (i = 0; i < model->boneCount; i++, bone++) {
178 bone->prevPos = bone->pos;
179 bone->prevRot = bone->rot;
180 bone->prevScale = bone->scale;
181 }
182}
183
184/* Model.setMotion: lays out the motion's keyframes */
185void FIGHTSTG_setMotion(Model *model, s32 motion, s32 restart) {
186 MotionStep *step;
187 s32 count;
188 s32 n;
189 s32 i;
190 s32 to;
191 s32 from;
192
193 if (restart != 1 && model->motion == motion) {
194 return;
195 }
196 model->motion = motion;
197 model->keyframe = 1;
198 model->motionDone = 0;
199 model->toIdle = 0;
200 step = FILE_CACHE.getArchiveEntry(motion - 1, FILE_CACHE.getEntry(model->motionFile));
201 count = 0;
202 while (step->index != 0x7FFF) {
203 n = step->count;
204 if (n == 0) {
205 model->keyframes[count] = step->frame;
206 model->blendTargets[count] = step->endFrame;
207 count++;
208 break;
209 }
210 if (step->endFrame == 0) {
211 to = step[1].frame;
212 if (to == -1) {
213 to = model->idleFrames[model->control->idleMotion];
214 model->toIdle = 1;
215 }
216 if (step->index != 0) {
217 from = step[-1].endFrame;
218 } else {
219 from = 0xFFFF;
220 }
221 for (i = 0; i < n; i++) {
222 model->blendSources[count] = from;
223 model->blendTargets[count] = to;
224 model->keyframes[count] = (((i + 1) << 12) / (n + 1)) | 0x8000;
225 count++;
226 }
227 } else {
228 for (i = 0; i < n; i++) {
229 model->keyframes[count] = step->frame + i;
230 model->blendTargets[count] = 0;
231 count++;
232 }
233 }
234 step++;
235 }
236 model->keyframeCount = count;
237 model->keyframe = 1;
238}
239
240/* Steps a model's motion by the frames gone by, blending into a new pose
241 where a keyframe has 0x8000, and starts the idle motion when it ends */
243 s32 key = model->keyframe;
244 ModelBone *bone;
245 s32 i;
246
247 if (model->motionDone == 0) {
248 if (model->keyframes[key] & 0x8000) {
249 if (model->blendTarget != model->blendTargets[key]) {
250 model->blendTarget = model->blendTargets[key];
251 if (model->blendSources[key] != 0xFFFF) {
252 bone = model->bones;
253 for (i = 1, bone++; i < model->boneCount; i++, bone++) {
254 FIGHTSTG_poseBone(model, bone, model->blendSources[key]);
255 }
256 }
258 }
259 model->frame = model->blendTargets[key];
260 model->blend = model->keyframes[key] & 0x7FFF;
261 model->blending = 1;
262 } else {
263 model->blendTarget = 0;
264 model->frame = model->keyframes[key];
265 model->blending = 0;
266 }
268 if (model->keyframe >= model->keyframeCount) {
269 model->keyframe = model->keyframeCount - 1;
270 }
271 key = model->keyframe;
272 switch (model->keyframes[key]) {
273 case 0x8000:
274 model->keyframe = model->blendTargets[key];
275 break;
276 case 0xFFFF:
277 model->motionDone = 1;
278 model->control->motionDone = 1;
279 break;
280 }
281 } else {
282 model->blendTarget = 0;
283 model->blending = 0;
284 if (model->hasIdle != 0 && model->toIdle != 0) {
285 model->control->motion = model->control->idleMotion + 1;
286 FIGHTSTG_setMotion(model, model->control->idleMotion + 1, 0);
287 }
288 }
289}
290
291/* The model's task: loads its textures and makes its meshes and face, then
292 each frame follows its control's motion, steps and poses it, places the
293 root at the control's position, builds each bone's matrices (a bone scaled
294 to 48 or less is hidden) and queues its meshes on the control's layers;
295 frees the bones when killed */
296void FIGHTSTG_updateModel(Model *model, Mesh **children) {
297 TimLoader loader;
298 VECTOR scale;
299 ModelBone *bone;
300 void *archive;
301 MotionStep *idle;
302 s32 i;
303 s32 j;
304 ModelBone *drawn;
305 s32 b;
306 ModelBone *linked;
307 s32 c;
308 s32 d;
309
310 switch (model->state) {
311 case TASK_INIT:
312 default:
313 if (model->texFile != 0) {
314 initTimLoader(&loader);
315 loader.setImagePos(model->texPos.x, model->texPos.y);
316 loader.loadArchive(FILE_CACHE.getEntry(model->texFile));
317 }
318 for (b = 0, linked = model->bones; b < model->boneCount; b++, linked++) {
319 if (b != 0) {
320 linked->parentMatrix = &model->bones[linked->parent].world;
321 }
322 }
323 for (c = 0; c < model->boneCount; c++) {
324 if (c != 0) {
325 children[c + 1] = FIGHTSTG_createMesh(FILE_CACHE.getEntry(model->bones[c].file), model->texPos);
326 }
327 }
328 /* child 0 is the face, the others the bones' meshes */
329 children[0] = (Mesh *)FIGHTSTG_createFace(model, model->control->fighter);
330 model->motion = 1;
331 if (model->hasIdle != 0) {
332 archive = FILE_CACHE.getEntry(model->motionFile);
333 /* where the first step of each idle motion starts */
334 idle = FILE_CACHE.getArchiveEntry(0, archive);
335 model->idleFrames[0] = idle->frame;
336 idle = FILE_CACHE.getArchiveEntry(1, archive);
337 model->idleFrames[1] = idle->frame;
338 }
339 FIGHTSTG_setMotion(model, model->control->idleMotion + 1, 1);
340 model->control->motion = model->control->idleMotion + 1;
341 model->nextState(model);
342 break;
343 case TASK_RUN:
344 if (model->control->restart != 0 || model->motion != model->control->motion) {
345 model->control->restart = 0;
346 FIGHTSTG_setMotion(model, model->control->motion, 1);
347 switch (model->control->motion) {
348 case 1:
349 model->control->idleMotion = 0;
350 break;
351 case 2:
352 model->control->idleMotion = 1;
353 break;
354 }
355 }
356 if (model->boneCount == 0) {
357 break;
358 }
359 FIGHTSTG_stepMotion(model);
360 FIGHTSTG_poseBones(model, children);
361 model->bones[0].pos.vx = model->control->pos.x;
362 model->bones[0].pos.vy = model->control->pos.y;
363 model->bones[0].pos.vz = model->control->pos.z;
364 model->bones[0].rot.vx = model->control->rot.x;
365 model->bones[0].rot.vy = model->control->rot.y;
366 model->bones[0].rot.vz = model->control->rot.z;
367 for (i = 0, bone = model->bones; i < model->boneCount; i++, bone++) {
368 scale.vx = bone->scale.vx;
369 scale.vy = bone->scale.vy;
370 scale.vz = bone->scale.vz;
371 if ((scale.vx | scale.vy | scale.vz) <= 48) {
372 bone->visible = 0;
373 } else {
374 bone->visible = 1;
375 RotMatrixZYX_gte(&bone->rot, &bone->local);
376 ScaleMatrix(&bone->local, &scale);
377 bone->local.t[0] = bone->pos.vx;
378 bone->local.t[1] = bone->pos.vy;
379 bone->local.t[2] = bone->pos.vz;
380 gte_CompMatrix(bone->parentMatrix, &bone->local, &bone->world);
381 }
382 }
383 for (j = 0; j < 2; j++) {
384 if (model->control->layers[j].enabled) {
385 for (d = 0, drawn = model->bones; d < model->boneCount; d++, drawn++) {
386 if (d != 0 && drawn->visible) {
387 if (model->control->layers[j].wireframe) {
388 children[d + 1]->drawWireframe(children[d + 1], model->control->layers[j].layerId, &drawn->world);
389 } else {
390 children[d + 1]->draw(children[d + 1], model->control->layers[j].layerId, &drawn->world);
391 }
392 }
393 }
394 }
395 }
396 break;
397 case TASK_DONE:
398 break;
399 case TASK_KILL:
400 if (model->bones != NULL) {
401 HEAP.free(model->bones);
402 }
403 break;
404 }
405}
406
407/* Model.setColor: sets the color mode, and the color unless COLOR is NULL, of
408 the meshes of each bone but the root (once for each of the control's
409 enabled layers) */
410void FIGHTSTG_setModelColor(Model *model, s32 mode, CVECTOR *color) {
411 Mesh **children = model->children;
412 s32 i;
413 s32 j;
414
415 for (i = 0; i < 2; i++) {
416 if (model->control->layers[i].enabled) {
417 for (j = 0; j < model->boneCount; j++) {
418 if (j != 0) {
419 children[j + 1]->colorMode = mode;
420 if (color != NULL) {
421 children[j + 1]->color = *color;
422 }
423 }
424 }
425 }
426 }
427}
428
429/* Model.setBoneNoBoundsCheck: sets bone's Mesh noBoundsCheck when either of the
430 control's layers is enabled and bone isn't 0. The match
431 depends on the pointer to the bone's slot, which children[bone + 1]
432 computes with the addu's operands the other way round. */
433void FIGHTSTG_setBoneNoBoundsCheck(Model *model, s32 bone, s32 value) {
434 Mesh **meshes = (Mesh **)model->children + bone;
435 s32 i;
436
437 for (i = 0; i < 2; i++) {
438 if (model->control->layers[i].enabled && bone != 0) {
439 meshes[1]->noBoundsCheck = value;
440 }
441 }
442}
443
444/* Model.isMotionDone */
446 return model->motionDone;
447}
448
449/* Creates a model (registered as BATTLE_TASK_MODEL) from the bone list in
450 FILE: each bone's parent, mesh file and keys file, with the file's high
451 half; HASIDLE makes its motions go back to its idle motion */
452Model *FIGHTSTG_createModel(s32 file, s32 motionFile, Vec2 texPos, ModelControl *control, s32 hasIdle) {
453 s32 high = file & 0xFFFF0000;
454 s32 *entry = FILE_CACHE.getEntry(file);
455 s32 count = entry[1] + 1;
456 Model *model = createTaskWithId(FIGHTSTG_updateModel, sizeof(Model), (entry[1] + 2) * 4, BATTLE_TASK_MODEL);
457 s32 i;
458
459 model->bones = HEAP.alloc(count * sizeof(ModelBone), 2);
460 model->control = control;
461 model->hasIdle = hasIdle;
462 model->texPos = texPos;
463 model->texFile = *entry++;
464 if (model->texFile != 0) {
465 model->texFile |= high;
466 }
467 model->boneCount = count;
468 model->bones[0].parent = 0;
469 model->bones[0].file = 0;
470 model->bones[0].keyFile = 0;
472 model->bones[0].pos.vx = 0;
473 model->bones[0].pos.vy = 0;
474 model->bones[0].pos.vz = 0;
475 model->bones[0].rot.vx = 0;
476 model->bones[0].rot.vy = 0;
477 model->bones[0].rot.vz = 0;
478 model->bones[0].scale.vx = 0x1000;
479 model->bones[0].scale.vy = 0x1000;
480 model->bones[0].scale.vz = 0x1000;
481 entry++;
482 for (i = 1; i < count; i++) {
483 model->bones[i].parent = *entry++;
484 model->bones[i].file = *entry++ | high;
485 model->bones[i].keyFile = *entry++ | high;
486 }
490 model->motionFile = motionFile;
492 return model;
493}
494
495/* A model whose motions go back to its idle motion (FIGHTSTG_createModel):
496 the fighters' */
497Model *FIGHTSTG_createIdlingModel(s32 file, s32 motionFile, Vec2 texPos, ModelControl *control) {
498 return FIGHTSTG_createModel(file, motionFile, texPos, control, 1);
499}
500
501/* A model whose motions just end (FIGHTSTG_createModel) */
502Model *FIGHTSTG_createPlainModel(s32 file, s32 motionFile, Vec2 texPos, ModelControl *control) {
503 return FIGHTSTG_createModel(file, motionFile, texPos, control, 0);
504}
505
506/* The colors of a Mesh's normals under the lights, through its matrix */
508 ShortVec3 *normal = mesh->normals;
509 s32 count = normal->x;
510 MATRIX light;
511 CVECTOR *color;
512 s32 i;
513
514 normal++;
515 if (count == 0) {
516 return;
517 }
518 gte_CompMatrix(&GsLIGHTWSMATRIX, &mesh->matrix, &light);
519 gte_SetLightMatrix(&light);
520 if (mesh->colors == NULL) {
521 mesh->colors = HEAP.alloc(count * 4, 2);
522 }
523 color = mesh->colors;
524 gte_ldv0_unaligned(normal);
525 gte_ncs();
526 gte_strgb(color);
527 i = 1;
528 normal++;
529 while (i < count) {
530 gte_ldv0_unaligned(normal);
531 gte_ncs();
532 normal++;
533 color++;
534 i++;
535 gte_strgb(color);
536 }
537}
538
539/* The screen positions of a Mesh's vertices and their depths in the layer's
540 ordering table */
541void FIGHTSTG_projectMesh(Mesh *mesh, Layer *layer) {
542 ShortVec3 *vertex = mesh->vertices;
543 s32 shift = 14 - layer->getOtShift(layer);
544 s32 count = vertex->x;
545 s32 *screen;
546 s32 *depth;
547 s32 i;
548 s32 z;
549
550 vertex++;
551 if (mesh->screen == NULL) {
552 mesh->screen = HEAP.alloc(count * 4, 2);
553 }
554 screen = mesh->screen;
555 if (mesh->depth == NULL) {
556 mesh->depth = HEAP.alloc(count * 4, 2);
557 }
558 depth = mesh->depth;
559 gte_ldv0_unaligned(vertex);
560 gte_rtps();
561 gte_stsxy(screen);
562 gte_stszotz(&z);
563 i = 1;
564 vertex++;
565 while (i < count) {
566 gte_ldv0_unaligned(vertex);
567 gte_rtps();
568 vertex++;
569 screen++;
570 i++;
571 *depth++ = z >> shift;
572 gte_stsxy(screen);
573 gte_stszotz(&z);
574 }
575 *depth = z >> shift;
576}
577
578/* Adds the polygon in state as a gouraud-shaded textured triangle or quad;
579 the colors, points and UVs are copied a word or a halfword at a time. */
581 *(CVECTOR *)&state->prim.gt4->r0 = state->colors[0];
582 *(CVECTOR *)&state->prim.gt4->r1 = state->colors[1];
583 *(CVECTOR *)&state->prim.gt4->r2 = state->colors[2];
584 if (state->quad) {
585 *(CVECTOR *)&state->prim.gt4->r3 = state->colors[3];
586 }
587 *(s32 *)&state->prim.gt4->x0 = state->sxy[0];
588 *(s32 *)&state->prim.gt4->x1 = state->sxy[1];
589 *(s32 *)&state->prim.gt4->x2 = state->sxy[2];
590 *(u16 *)&state->prim.gt4->u0 = *(u16 *)state->uv[0];
591 *(u16 *)&state->prim.gt4->u1 = *(u16 *)state->uv[1];
592 *(u16 *)&state->prim.gt4->u2 = *(u16 *)state->uv[2];
593 state->prim.gt4->clut = state->clut;
594 state->prim.gt4->tpage = state->tpage;
595 if (state->quad) {
596 setPolyGT4(state->prim.gt4);
597 if (state->abr) {
598 setSemiTrans(state->prim.gt4, 1);
599 }
600 *(s32 *)&state->prim.gt4->x3 = state->sxy[3];
601 *(u16 *)&state->prim.gt4->u3 = *(u16 *)state->uv[3];
602 addPrim(state->ot, state->prim.gt4);
603 state->prim.gt4++;
604 } else {
605 setPolyGT3(state->prim.gt3);
606 if (state->abr) {
607 setSemiTrans(state->prim.gt3, 1);
608 }
609 addPrim(state->ot, state->prim.gt3);
610 state->prim.gt3++;
611 }
612}
613
614/* The same as a flat-shaded textured triangle or quad */
616 *(CVECTOR *)&state->prim.ft4->r0 = state->colors[0];
617 *(s32 *)&state->prim.ft4->x0 = state->sxy[0];
618 *(s32 *)&state->prim.ft4->x1 = state->sxy[1];
619 *(s32 *)&state->prim.ft4->x2 = state->sxy[2];
620 *(u16 *)&state->prim.ft4->u0 = *(u16 *)state->uv[0];
621 *(u16 *)&state->prim.ft4->u1 = *(u16 *)state->uv[1];
622 *(u16 *)&state->prim.ft4->u2 = *(u16 *)state->uv[2];
623 state->prim.ft4->clut = state->clut;
624 state->prim.ft4->tpage = state->tpage;
625 if (state->quad) {
626 setPolyFT4(state->prim.ft4);
627 if (state->abr) {
628 setSemiTrans(state->prim.ft4, 1);
629 }
630 *(s32 *)&state->prim.ft4->x3 = state->sxy[3];
631 *(u16 *)&state->prim.ft4->u3 = *(u16 *)state->uv[3];
632 addPrim(state->ot, state->prim.ft4);
633 state->prim.ft4++;
634 } else {
635 setPolyFT3(state->prim.ft3);
636 if (state->abr) {
637 setSemiTrans(state->prim.ft3, 1);
638 }
639 addPrim(state->ot, state->prim.ft3);
640 state->prim.ft3++;
641 }
642}
643
644/* Whether a Mesh may be on screen: the screen positions of the 9 points of
645 its bounds against the layer's clip, 64 pixels bigger each way;
646 noBoundsCheck skips the check. The match depends on the + 128s kept in w
647 and h, which gcc otherwise folds into the - 64s. */
649 ShortVec3 *corner;
650 s32 left;
651 s32 right;
652 s32 top;
653 s32 bottom;
654 s32 x;
655 s32 y;
656 s32 w;
657 s32 h;
658 s32 i;
659 DVECTOR screen;
660 s32 flag;
661
662 if (mesh->noBoundsCheck != 0) {
663 return 1;
664 }
665 corner = mesh->bounds;
666 left = 0;
667 right = 0;
668 top = 0;
669 bottom = 0;
670 for (i = 0; i < 9; ) {
671 gte_ldv0_unaligned(corner);
672 gte_rtps();
673 if (i == 0) {
674 x = layer->env.clip.x - 64;
675 left = x - layer->offsetX;
676 w = layer->env.clip.w + 128;
677 right = x + w - layer->offsetX;
678 y = layer->env.clip.y - 64;
679 top = y - layer->offsetY;
680 h = layer->env.clip.h + 128;
681 bottom = y + h - layer->offsetY;
682 }
683 i++;
684 corner++;
685 gte_stsxy(&screen);
686 gte_stflg(&flag);
687 if (screen.vx >= left && screen.vx <= right && screen.vy >= top && screen.vy <= bottom) {
688 return 1;
689 }
690 }
691 return 0;
692}
693
694/* Sets the texture page, the CLUT and the UV offset from a command's bytes */
695static inline void setMeshTexture(MeshDrawState *state) {
696 s32 x, y;
697 s32 cx, cy, tp;
698
699 x = state->texPos.x;
700 y = state->texPos.y;
701 state->u = state->cmd[1] + (state->cmd[2] << 8);
702 state->v = state->cmd[3];
703 cx = state->cmd[4];
704 cx += x;
705 cy = state->cmd[5] + y;
706 tp = state->cmd[6];
707 state->clut = getClut(cx, cy);
708 state->tpage = getTPage(tp, state->abr ? state->abr - 1 : 0, x + (state->cmd[2] << 6), y);
709 state->cmd += 7;
710}
711
712/* Draws a run of polygons: adds each one that faces the camera to the
713 ordering table, then steps past its indices and UVs */
714static inline void drawMeshPolygons(MeshDrawState *state) {
715 s32 opz;
716 s32 otz;
717 s32 i0, i1, i2, i3;
718 s32 z1, z2;
719 s32 n;
720 s32 k;
721 u8 *p;
722 u8 *q;
723
724 do {
725 state->cmd++;
726 i0 = state->cmd[0];
727 i1 = state->cmd[1];
728 i2 = state->cmd[2];
729 i3 = 0;
730 if (state->quad) {
731 i3 = state->cmd[3];
732 }
733 state->sxy[0] = state->screen[i0];
734 state->sxy[1] = state->screen[i1];
735 state->sxy[2] = state->screen[i2];
736 if (state->quad) {
737 state->sxy[3] = state->screen[i3];
738 }
739 /* the checks and drawing are a do-while with breaks: its loop
740 notes weigh their references 4 instead of 3, so the screen
741 points outrank the screen base and the depth base outranks z1 */
742 do {
743 gte_ldsxy3(state->sxy[0], state->sxy[1], state->sxy[2]);
744 gte_nclip();
745 if (state->sxy[0] == state->sxy[1] || state->sxy[0] == state->sxy[2] ||
746 state->sxy[1] == state->sxy[2]) {
747 break;
748 }
749 if (state->quad && (state->sxy[0] == state->sxy[3] || state->sxy[1] == state->sxy[3] ||
750 state->sxy[2] == state->sxy[3])) {
751 break;
752 }
753 gte_stopz(&opz);
754 if (opz <= 0) {
755 break;
756 }
757 if (state->lit) {
758 p = state->cmd + (state->quad + 3);
759 state->colors[0] = state->normalColors[p[0]];
760 state->colors[1] = state->normalColors[p[1]];
761 state->colors[2] = state->normalColors[p[2]];
762 if (state->quad) {
763 state->colors[3] = state->normalColors[p[3]];
764 }
765 }
766 if (state->textured) {
767 k = state->quad + 3;
768 q = state->cmd + (state->lit ? k + (state->quad + 3) : k);
769 state->uv[0][0] = q[0] + state->u;
770 state->uv[0][1] = q[1] + state->v;
771 state->uv[1][0] = q[2] + state->u;
772 state->uv[1][1] = q[3] + state->v;
773 state->uv[2][0] = q[4] + state->u;
774 state->uv[2][1] = q[5] + state->v;
775 if (state->quad) {
776 state->uv[3][0] = q[6] + state->u;
777 state->uv[3][1] = q[7] + state->v;
778 }
779 }
780 otz = state->depth[i0];
781 z1 = state->depth[i1];
782 z2 = state->depth[i2];
783 if (state->quad) {
784 gte_AverageZ4(otz, z1, z2, state->depth[i3], &otz);
785 } else {
786 gte_AverageZ3(otz, z1, z2, &otz);
787 }
788 state->ot = state->otBase + otz;
789 if (state->gouraud) {
791 } else {
792 if (!state->lit) {
793 state->colors[0] = state->color[0];
794 }
796 }
797 } while (0);
798 n = state->quad + 3;
799 state->cmd += n;
800 if (state->lit) {
801 state->cmd += n;
802 }
803 if (state->textured) {
804 state->cmd += n * 2;
805 }
806 } while (*state->cmd == 0);
807}
808
809/* A layer callback that draws a Mesh: walks its command bytes (see
810 MeshDrawState), setting its texture (setMeshTexture), and adds each
811 polygon that faces the camera to the layer's ordering table
812 (drawMeshPolygons). The match depends on the mesh coming in as a void *,
813 on the ?: for q and on each polygon's checks and drawing being a
814 do-while (0) with breaks (both in drawMeshPolygons). */
815void FIGHTSTG_drawMesh(void *arg, Layer *layer) {
816 Mesh *mesh = arg;
817 MATRIX m;
818 MeshDrawState state;
819 u32 op;
820 s32 hi;
821 s32 lo;
822
823 gte_CompMatrix(&GsWSMATRIX, &mesh->matrix, &m);
826 if (FIGHTSTG_isMeshOnScreen(mesh, layer) == 0) {
827 return;
828 }
829 FIGHTSTG_projectMesh(mesh, layer);
830 FIGHTSTG_lightMesh(mesh);
831 state.cmd = mesh->commands;
832 state.texPos = mesh->texPos;
833 state.screen = mesh->screen;
834 state.depth = mesh->depth;
835 state.normalColors = mesh->colors;
836 state.otBase = layer->getOt(layer);
837 state.prim.ptr = GFX.funcs.getPrim();
838 while (*state.cmd != 0xFF) {
839 op = *state.cmd;
840 hi = op >> 4;
841 lo = op & 0xF;
842 if (hi != 0) {
843 switch (hi) {
844 case 8:
845 state.quad = lo;
846 break;
847 case 9:
848 state.textured = lo;
849 break;
850 case 10:
851 state.unk8 = lo;
852 break;
853 case 11:
854 state.unk4 = lo;
855 break;
856 case 12:
857 state.lit = lo;
858 break;
859 case 13:
860 state.gouraud = lo;
861 break;
862 case 14:
863 state.abr = lo;
864 break;
865 }
866 state.cmd++;
867 } else {
868 switch (lo) {
869 case 1:
870 setMeshTexture(&state);
871 break;
872 case 2:
873 case 3:
874 case 4:
875 case 5:
876 if (mesh->colorMode != 0) {
877 state.color[lo - 2].r = mesh->color.r;
878 state.color[lo - 2].g = mesh->color.g;
879 state.color[lo - 2].b = mesh->color.b;
880 } else {
881 state.color[lo - 2].r = state.cmd[1];
882 state.color[lo - 2].g = state.cmd[2];
883 state.color[lo - 2].b = state.cmd[3];
884 }
885 state.cmd += 4;
886 break;
887 case 0:
888 drawMeshPolygons(&state);
889 break;
890 }
891 }
892 }
893 GFX.funcs.setPrim(state.prim.ptr);
894}
895
896/* A primitive tag's word with its address replaced: the top byte of tag and
897 the low 24 bits of addr. The match depends on word being set twice: as one
898 expression, sched1 moves the tag's mask after the address's, which swaps
899 their registers. */
900static inline u_long linkTag(u_long tag, u_long addr) {
901 u_long word = tag & 0xFF000000;
902 word |= addr;
903 return word;
904}
905
906/* Draws a Mesh as wireframe: each polygon of its command runs as a green
907 LINE_F4 through its screen points, with a LINE_F2 to close a quad. Each
908 addPrim is written out with linkTag. */
910 MATRIX m;
911 MeshDrawState state;
912 u32 op;
913 s32 hi;
914 s32 lo;
915 s32 i0, i1, i2, i3;
916 s32 n;
917 u_long tag;
918
919 gte_CompMatrix(&GsWSMATRIX, &mesh->matrix, &m);
922 if (FIGHTSTG_isMeshOnScreen(mesh, layer) == 0) {
923 return;
924 }
925 FIGHTSTG_projectMesh(mesh, layer);
926 state.cmd = mesh->commands;
927 state.texPos = mesh->texPos;
928 state.screen = mesh->screen;
929 state.depth = mesh->depth;
930 state.normalColors = mesh->colors;
931 state.otBase = layer->getOt(layer);
932 state.ot = state.otBase;
933 state.prim.ptr = GFX.funcs.getPrim();
934 while (*state.cmd != 0xFF) {
935 op = *state.cmd;
936 hi = op >> 4;
937 lo = op & 0xF;
938 if (hi != 0) {
939 switch (hi) {
940 case 8:
941 state.quad = lo;
942 break;
943 case 9:
944 state.textured = lo;
945 break;
946 case 12:
947 state.lit = lo;
948 break;
949 }
950 state.cmd++;
951 } else {
952 switch (lo) {
953 case 1:
954 state.cmd += 7;
955 break;
956 case 2:
957 case 3:
958 case 4:
959 case 5:
960 state.cmd += 4;
961 break;
962 case 0:
963 do {
964 state.cmd++;
965 i0 = state.cmd[0];
966 i1 = state.cmd[1];
967 i2 = state.cmd[2];
968 i3 = 0;
969 if (state.quad) {
970 i3 = state.cmd[3];
971 }
972 state.sxy[0] = state.screen[i0];
973 state.sxy[1] = state.screen[i1];
974 state.sxy[2] = state.screen[i2];
975 if (state.quad) {
976 state.sxy[3] = state.screen[i3];
977 }
978 setLineF4(state.prim.lineF4);
979 setRGB0(state.prim.lineF4, 0, 0xFF, 0);
980 *(s32 *)&state.prim.lineF4->x0 = state.sxy[0];
981 *(s32 *)&state.prim.lineF4->x1 = state.sxy[1];
982 if (!state.quad) {
983 *(s32 *)&state.prim.lineF4->x2 = state.sxy[2];
984 *(s32 *)&state.prim.lineF4->x3 = state.sxy[0];
985 } else {
986 *(s32 *)&state.prim.lineF4->x2 = state.sxy[3];
987 *(s32 *)&state.prim.lineF4->x3 = state.sxy[2];
988 }
989 tag = *state.prim.tag;
990 *state.prim.tag = linkTag(tag, getaddr(state.ot));
991 tag = *state.ot;
992 *state.ot = linkTag(tag, (u_long)state.prim.ptr & 0xFFFFFF);
993 state.prim.lineF4++;
994 if (state.quad) {
995 setLineF2(state.prim.lineF2);
996 setRGB0(state.prim.lineF2, 0, 0xFF, 0);
997 *(s32 *)&state.prim.lineF2->x0 = state.sxy[2];
998 *(s32 *)&state.prim.lineF2->x1 = state.sxy[0];
999 tag = *state.prim.tag;
1000 *state.prim.tag = linkTag(tag, getaddr(state.ot));
1001 tag = *state.ot;
1002 *state.ot = linkTag(tag, (u_long)state.prim.ptr & 0xFFFFFF);
1003 state.prim.lineF2++;
1004 }
1005 n = state.quad + 3;
1006 state.cmd += n;
1007 if (state.lit) {
1008 state.cmd += n;
1009 }
1010 if (state.textured) {
1011 state.cmd += n * 2;
1012 }
1013 } while (*state.cmd == 0);
1014 break;
1015 }
1016 }
1017 }
1018 GFX.funcs.setPrim(state.prim.ptr);
1019}
1020
1021/* Mesh.draw: has the layer draw the Mesh (FIGHTSTG_drawMesh) with MATRIX */
1022void FIGHTSTG_queueMeshDraw(Mesh *mesh, s32 layerId, MATRIX *matrix) {
1023 Layer *layer = GFX.funcs.getLayer(layerId);
1024
1025 layer->addCallback(layer, FIGHTSTG_drawMesh, mesh);
1026 mesh->matrix = *matrix;
1027}
1028
1029/* Mesh.drawWireframe: has the layer draw the Mesh as wireframe
1030 (FIGHTSTG_drawMeshWireframe) with MATRIX */
1031void FIGHTSTG_queueMeshWireframe(Mesh *mesh, s32 layerId, MATRIX *matrix) {
1032 Layer *layer = GFX.funcs.getLayer(layerId);
1033
1034 layer->addCallback(layer, FIGHTSTG_drawMeshWireframe, mesh);
1035 mesh->matrix = *matrix;
1036}
1037
1038/* The Mesh's task: frees its screen positions, depths and colors when killed */
1040 switch (mesh->state) {
1041 case TASK_INIT:
1042 case TASK_RUN:
1043 case TASK_DONE:
1044 break;
1045 case TASK_KILL:
1046 if (mesh->screen != NULL) {
1047 HEAP.free(mesh->screen);
1048 }
1049 if (mesh->depth != NULL) {
1050 HEAP.free(mesh->depth);
1051 }
1052 if (mesh->colors != NULL) {
1053 HEAP.free(mesh->colors);
1054 }
1055 break;
1056 }
1057}
1058
1059/* Creates a Mesh from an archive: its vertices (entry 0), normals (1),
1060 commands (2) and bounds (5) */
1061Mesh *FIGHTSTG_createMesh(void *archive, Vec2 texPos) {
1062 Mesh *mesh = createTask(FIGHTSTG_updateMesh, sizeof(Mesh), 0);
1063
1064 mesh->archive = archive;
1065 mesh->vertices = FILE_CACHE.getArchiveEntry(0, archive);
1066 mesh->normals = FILE_CACHE.getArchiveEntry(1, archive);
1067 mesh->commands = FILE_CACHE.getArchiveEntry(2, archive);
1068 mesh->bounds = FILE_CACHE.getArchiveEntry(5, archive);
1069 mesh->texPos = texPos;
1072 return mesh;
1073}
1074
1075/* the variables that end the file: zeros after camera_task.c's data, which
1076 the objects after this one read; the three unused words are read and
1077 written by nothing in either version */
1079s32 FIGHTSTG_partnerIdleMotion = 0; /* the partner's idle motion while stage 0x1D is up */
1081CameraView FIGHTSTG_fighterView = { 0 }; /* the view FIGHTSTG_getFighterView makes */
1083RECT FIGHTSTG_fighterCameraRect = { 0 }; /* FIGHTSTG_updatePartnerView's layer */
1084DR_MOVE FIGHTSTG_cursorBarMoves[4] = { { 0 } }; /* FIGHTSTG_drawCursorBar draws its bar with them */
1085u_long FIGHTSTG_cursorBarOt[2] = { 0 }; /* and their ordering table */
1086BattleEvent FIGHTSTG_newEvent = { 0 }; /* what FIGHTSTG_pushEvent is given */
Battle FIGHTSTG_battle
the battle: its fighters, speed and drawing functions
Definition battle.c:16
#define BATTLE_TASK_MODEL
a model (FIGHTSTG_updateModel)
Definition types.h:20
FIGHTSTG.PRO: the battle.
#define NULL
Definition common.h:17
signed int s32
Definition common.h:11
unsigned int u32
Definition common.h:12
unsigned short u16
Definition common.h:10
unsigned char u8
Definition common.h:8
GfxState GFX
GFX: the graphics state and its methods.
Definition display.c:209
#define TASK_RUN
Definition task.h:35
#define TASK_KILL
Definition task.h:37
#define TASK_INIT
Tasks: every game object is a task, a heap block that starts with this header and is updated once per...
Definition task.h:34
#define TASK_DONE
Definition task.h:36
Face * FIGHTSTG_createFace(Model *model, s32 fighter)
Creates the face of fighter's model, with its parts (FIGHTSTG_fighterCache.getFace); none for fighter...
Definition face.c:119
FileCache FILE_CACHE
The file cache.
Definition file_cache.c:7
The GTE instructions that C can't say, as the SDK's inline_c.h has them but with the real encodings i...
#define gte_rtps()
V0 through RT and TR, then the perspective (SXY2, SZ3)
Definition gte.h:80
#define gte_lddp(r0)
the interpolation factor (IR0)
Definition gte.h:10
#define gte_ldv0(r0)
an SVECTOR into V0
Definition gte.h:62
#define gte_rtv0()
MAC1-MAC3 = RT * V0 >> 12.
Definition gte.h:86
#define gte_SetLightMatrix(r0)
a MATRIX's rotation into the GTE's light matrix (L)
Definition gte.h:187
#define gte_ldsv(r0)
an SVECTOR into IR1-IR3
Definition gte.h:16
#define gte_stopz(r0)
MAC0 into a word.
Definition gte.h:230
#define gte_strgb(r0)
RGB2 into a word.
Definition gte.h:209
#define gte_stszotz(r0)
SZ3 / 4 into a word, the depth in the ordering table.
Definition gte.h:117
#define gte_stsv(r0)
IR1-IR3 into an SVECTOR.
Definition gte.h:34
#define gte_SetTransMatrix(r0)
a MATRIX's translation into the GTE (TR)
Definition gte.h:127
#define gte_ncs()
the color of V0 as a normal under the lights (RGB2)
Definition gte.h:203
#define gte_stsxy(r0)
SXY2 into a word.
Definition gte.h:92
#define gte_stflg(r0)
the flags into a word
Definition gte.h:99
#define gte_nclip()
MAC0 = the winding of SXY0-SXY2, which side of a polygon faces us.
Definition gte.h:224
#define gte_stlvnl(r0)
MAC1-MAC3 into a VECTOR.
Definition gte.h:108
#define gte_ldsxy3(r0, r1, r2)
three screen points (SXY0-SXY2)
Definition gte.h:216
#define gte_SetRotMatrix(r0)
a MATRIX's rotation into the GTE (RT)
Definition gte.h:46
#define gte_gpf12()
IR1-IR3 = IR0 * IR1-IR3 >> 12.
Definition gte.h:28
#define gte_ldv0_unaligned(r0)
an SVECTOR that may not be word aligned into V0
Definition gte.h:69
Heap HEAP
The functions that return what a call left in v0 (allocMemHigh, findTask) and the ones that take othe...
Definition heap.c:184
MATRIX IDENTITY_MATRIX
the root bone's parent (src/engine/data/matrices.c)
Definition matrices.c:12
void FIGHTSTG_saveBlendPose(Model *model)
Saves each bone's pose as the one a blend starts from.
Definition model_mesh.c:173
s32 FIGHTSTG_isMotionDone(Model *model)
Model.isMotionDone.
Definition model_mesh.c:445
void FIGHTSTG_drawMeshWireframe(Mesh *mesh, Layer *layer)
Draws a Mesh as wireframe: each polygon of its command runs as a green LINE_F4 through its screen poi...
Definition model_mesh.c:909
void FIGHTSTG_addMeshPolyGT(MeshDrawState *state)
Adds the polygon in state as a gouraud-shaded textured triangle or quad; the colors,...
Definition model_mesh.c:580
s32 FIGHTSTG_unused2
void FIGHTSTG_blendBone(Model *model, ModelBone *bone)
Blends a bone's position, rotation and scale from the saved pose (FIGHTSTG_saveBlendPose) towards the...
Definition model_mesh.c:23
s32 FIGHTSTG_unused0
the variables that end the file: zeros after camera_task.c's data, which the objects after this one r...
void FIGHTSTG_queueMeshWireframe(Mesh *mesh, s32 layerId, MATRIX *matrix)
Mesh.drawWireframe: has the layer draw the Mesh as wireframe (FIGHTSTG_drawMeshWireframe) with MATRIX...
s32 FIGHTSTG_unused1
void FIGHTSTG_setModelColor(Model *model, s32 mode, CVECTOR *color)
Model.setColor: sets the color mode, and the color unless COLOR is NULL, of the meshes of each bone b...
Definition model_mesh.c:410
static void drawMeshPolygons(MeshDrawState *state)
Draws a run of polygons: adds each one that faces the camera to the ordering table,...
Definition model_mesh.c:714
Model * FIGHTSTG_createModel(s32 file, s32 motionFile, Vec2 texPos, ModelControl *control, s32 hasIdle)
Creates a model (registered as BATTLE_TASK_MODEL) from the bone list in FILE: each bone's parent,...
Definition model_mesh.c:452
static void setMeshTexture(MeshDrawState *state)
Sets the texture page, the CLUT and the UV offset from a command's bytes.
Definition model_mesh.c:695
s32 FIGHTSTG_isMeshOnScreen(Mesh *mesh, Layer *layer)
Whether a Mesh may be on screen: the screen positions of the 9 points of its bounds against the layer...
Definition model_mesh.c:648
void FIGHTSTG_projectMesh(Mesh *mesh, Layer *layer)
The screen positions of a Mesh's vertices and their depths in the layer's ordering table.
Definition model_mesh.c:541
u_long FIGHTSTG_cursorBarOt[2]
and their ordering table
void FIGHTSTG_queueMeshDraw(Mesh *mesh, s32 layerId, MATRIX *matrix)
Mesh.draw: has the layer draw the Mesh (FIGHTSTG_drawMesh) with MATRIX.
void FIGHTSTG_updateMesh(Mesh *mesh)
The Mesh's task: frees its screen positions, depths and colors when killed.
Model * FIGHTSTG_createIdlingModel(s32 file, s32 motionFile, Vec2 texPos, ModelControl *control)
A model whose motions go back to its idle motion (FIGHTSTG_createModel): the fighters'.
Definition model_mesh.c:497
void FIGHTSTG_drawMesh(void *arg, Layer *layer)
A layer callback that draws a Mesh: walks its command bytes (see MeshDrawState), setting its texture ...
Definition model_mesh.c:815
void FIGHTSTG_addMeshPolyFT(MeshDrawState *state)
The same as a flat-shaded textured triangle or quad.
Definition model_mesh.c:615
DR_MOVE FIGHTSTG_cursorBarMoves[4]
FIGHTSTG_drawCursorBar draws its bar with them.
void FIGHTSTG_lightMesh(Mesh *mesh)
The colors of a Mesh's normals under the lights, through its matrix.
Definition model_mesh.c:507
BattleEvent FIGHTSTG_newEvent
what FIGHTSTG_pushEvent is given
void FIGHTSTG_updateModel(Model *model, Mesh **children)
The model's task: loads its textures and makes its meshes and face, then each frame follows its contr...
Definition model_mesh.c:296
void FIGHTSTG_poseBones(Model *model, Mesh **children)
Moves the root bone by the model's move along its rotation, then poses (FIGHTSTG_poseBone) or blends ...
Definition model_mesh.c:143
Model * FIGHTSTG_createPlainModel(s32 file, s32 motionFile, Vec2 texPos, ModelControl *control)
A model whose motions just end (FIGHTSTG_createModel)
Definition model_mesh.c:502
static u_long linkTag(u_long tag, u_long addr)
A primitive tag's word with its address replaced: the top byte of tag and the low 24 bits of addr.
Definition model_mesh.c:900
RECT FIGHTSTG_fighterCameraRect
FIGHTSTG_updatePartnerView's layer.
CameraView FIGHTSTG_fighterView
the view FIGHTSTG_getFighterView makes
void FIGHTSTG_setBoneNoBoundsCheck(Model *model, s32 bone, s32 value)
Model.setBoneNoBoundsCheck: sets bone's Mesh noBoundsCheck when either of the control's layers is ena...
Definition model_mesh.c:433
s32 FIGHTSTG_partnerIdleMotion
the partner's idle motion while stage 0x1D is up
void FIGHTSTG_poseBone(Model *model, ModelBone *bone, s32 frame)
Sets a bone's position, rotation and scale to their keys at FRAME, interpolated between the keys arou...
Definition model_mesh.c:83
void FIGHTSTG_setMotion(Model *model, s32 motion, s32 restart)
Model.setMotion: lays out the motion's keyframes.
Definition model_mesh.c:185
Mesh * FIGHTSTG_createMesh(void *archive, Vec2 texPos)
Creates a Mesh from an archive: its vertices (entry 0), normals (1), commands (2) and bounds (5)
void FIGHTSTG_stepMotion(Model *model)
Steps a model's motion by the frames gone by, blending into a new pose where a keyframe has 0x8000,...
Definition model_mesh.c:242
An event of the battle, as it is queued (FIGHTSTG_pushEvent)
Definition battle.h:102
s32 frames
since the last update
Definition battle.h:239
Where the battle camera looks from and to, as a GsRVIEW2 with the transform of its coordinate system.
Definition camera.h:49
void *(* getArchiveEntry)(s32 index, void *archive)
Definition file.h:97
void *(* getEntry)(u32 fileAndIndex)
Definition file.h:96
void *(* getPrim)(void)
Definition gfx.h:19
struct Layer *(* getLayer)(s32 id)
Definition gfx.h:28
void(* setPrim)(void *next)
Definition gfx.h:20
GfxFuncs funcs
Definition gfx.h:77
void *(* alloc)(s32 size, s32 tag)
Definition heap.h:29
void(* free)(void *ptr)
Definition heap.h:27
A drawing layer (GFX.funcs.createLayer): a DRAWENV with a pair of ordering tables,...
Definition gfx.h:128
void(* addCallback)()
Definition gfx.h:161
s32(* getOtShift)()
Definition gfx.h:158
DRAWENV env
Definition gfx.h:129
s16 offsetX
Definition gfx.h:133
s16 offsetY
Definition gfx.h:134
u_long *(* getOt)(struct Layer *)
Definition gfx.h:157
A Mesh's drawing state while its drawer (FIGHTSTG_drawMesh) walks its command bytes: a high nibble of...
Definition model.h:45
u_long * ot
Definition model.h:75
s32 gouraud
Definition model.h:51
u8 uv[4][2]
Definition model.h:76
s32 * depth
Definition model.h:55
s32 abr
the semi-transparency mode + 1, 0 for opaque
Definition model.h:52
s32 textured
Definition model.h:46
LINE_F4 * lineF4
Definition model.h:72
LINE_F2 * lineF2
Definition model.h:71
POLY_GT3 * gt3
Definition model.h:69
u16 tpage
Definition model.h:61
void * ptr
Definition model.h:65
s32 unk8
the 0xA nibble: on the disc, 0 but in two effect meshes; nothing reads it
Definition model.h:48
u8 * cmd
Definition model.h:53
CVECTOR colors[4]
the polygon's vertex colors
Definition model.h:77
s32 sxy[4]
the polygon's screen points
Definition model.h:74
POLY_GT4 * gt4
Definition model.h:70
s32 unk4
the 0xB nibble: on the disc, 1 on the textured polygons that are not lit and 0 on those that are; not...
Definition model.h:47
POLY_FT4 * ft4
Definition model.h:68
union MeshDrawState::@2 prim
CVECTOR color[4]
Definition model.h:63
u_long * otBase
Definition model.h:56
POLY_FT3 * ft3
Definition model.h:67
CVECTOR * normalColors
Definition model.h:57
s32 * screen
Definition model.h:54
u_long * tag
the primitive's first word
Definition model.h:66
Vec2 texPos
Definition model.h:58
Draws one bone of a Model (FIGHTSTG_createMesh), from the parts of an archive.
Definition model.h:21
ShortVec3 * normals
the count in [0].x, then the normals
Definition model.h:28
CVECTOR * colors
its normals' colors under the lights
Definition model.h:34
void * archive
Definition model.h:26
ShortVec3 * bounds
9 points (FIGHTSTG_isMeshOnScreen)
Definition model.h:30
void(* drawWireframe)(struct Mesh *mesh, s32 layerId, MATRIX *matrix)
Definition model.h:37
s32 colorMode
Model.setColor's.
Definition model.h:24
CVECTOR color
Definition model.h:25
ShortVec3 * vertices
the count in [0].x, then the vertices
Definition model.h:27
Vec2 texPos
Definition model.h:31
u8 * commands
see MeshDrawState
Definition model.h:29
MATRIX matrix
Definition model.h:35
s32 * depth
and their depths in the ordering table
Definition model.h:33
s32 state
Definition model.h:22
void(* draw)(struct Mesh *mesh, s32 layerId, MATRIX *matrix)
Definition model.h:36
s32 noBoundsCheck
Definition model.h:23
s32 * screen
where its vertices land on screen
Definition model.h:32
One part of a Model: a mesh (Mesh) placed by a matrix relative to its parent's.
Definition model.h:82
SVECTOR prevPos
the pose the motion blends from
Definition model.h:93
s32 parent
Definition model.h:83
MATRIX world
Definition model.h:92
MATRIX local
Definition model.h:90
SVECTOR pos
Definition model.h:87
s32 visible
0 while its scale is tiny
Definition model.h:86
MATRIX * parentMatrix
Definition model.h:91
SVECTOR prevRot
Definition model.h:94
s32 keyFile
its keys' file: positions, rotations and scales by frame
Definition model.h:85
SVECTOR prevScale
Definition model.h:95
s32 file
the mesh's file and index
Definition model.h:84
SVECTOR scale
Definition model.h:89
SVECTOR rot
Definition model.h:88
What drives a Model, owned by whoever created it.
Definition model.h:99
ShortVec3 rot
Definition model.h:108
s32 restart
play it again from the start
Definition model.h:103
s32 wireframe
they are drawn as wireframe (Mesh.drawWireframe)
Definition model.h:114
s32 enabled
Definition model.h:112
ShortVec3 pos
Definition model.h:107
s32 layerId
the layer its meshes are drawn in
Definition model.h:113
struct ModelControl::@3 layers[2]
the model is drawn once for each one enabled
s32 motion
the motion to play
Definition model.h:102
s32 fighter
the Models task's
Definition model.h:105
s32 idleMotion
Definition model.h:106
s32 motionDone
Definition model.h:104
A 3D model (FIGHTSTG_createModel), registered with id 0x11: a tree of bones, each drawn by a Mesh chi...
Definition model.h:132
void * children
Definition model.h:133
s32 keyframeCount
Definition model.h:154
s32 xy
vx and vy as one word
Definition model.h:138
Vec2 texPos
where its textures go in VRAM
Definition model.h:142
u16 keyframes[0x640]
Definition model.h:155
s32 motionFile
Definition model.h:144
u16 blendSources[0x640]
and the one it blends from, 0xFFFF for the saved pose
Definition model.h:157
u16 blendTargets[0x640]
the frame a blending keyframe blends into
Definition model.h:156
ModelBone * bones
Definition model.h:135
s32 frame
the pose's
Definition model.h:148
SVECTOR v
moves the root bone, along its rotation
Definition model.h:137
s32(* isMotionDone)(struct Model *model)
Definition model.h:159
s32 motionDone
Definition model.h:146
s32 blending
Definition model.h:151
s32 toIdle
the motion ends in the idle motion
Definition model.h:153
s32 texFile
Definition model.h:143
s32 idleFrames[2]
where the two idle motions start
Definition model.h:149
void(* setColor)()
(model, mode, color): its meshes'
Definition model.h:160
s32 motion
Definition model.h:145
s32 keyframe
Definition model.h:147
ModelControl * control
Definition model.h:141
s32 boneCount
Definition model.h:134
void(* setMotion)(struct Model *model, s32 motion, s32 restart)
Definition model.h:158
s32 state
Definition model.h:133
void(* setBoneNoBoundsCheck)()
Definition model.h:161
s32 hasIdle
it goes back to its idle motion
Definition model.h:140
s32 blend
how far, in 4096ths
Definition model.h:152
void(* nextState)(struct Model *task)
Definition model.h:133
s32 blendTarget
the frame it blends into, 0 for none
Definition model.h:150
union Model::@4 move
A motion in the motions' archive: its keyframes, step by step.
Definition model.h:119
s16 frame
Definition model.h:122
s16 index
0x7FFF ends them
Definition model.h:120
s16 count
frames, 0 for the last one
Definition model.h:121
s16 endFrame
the frame it ends on; 0: it blends into the next one
Definition model.h:123
A position or rotation, without the SVECTOR pad.
Definition model.h:14
s16 x
Definition model.h:15
s16 z
Definition model.h:17
s16 y
Definition model.h:16
Uploads TIM images to VRAM (initTimLoader); acts on TIM_LOADER.
Definition gfx.h:325
void(* setImagePos)()
(x, y)
Definition gfx.h:336
void(* loadArchive)()
(archive): each image 64 halfwords to the right
Definition gfx.h:338
Definition gfx.h:352
s32 y
Definition gfx.h:354
s32 x
Definition gfx.h:353
void * createTask(void(*update)(), s32 size, s32 childrenSize)
createTaskWithId for a task nothing needs to find
Definition task.c:105
void * createTaskWithId(void(*update)(), s32 size, s32 childrenSize, s32 id)
Allocates a zeroed task of size bytes (header included) with room for childrenSize / 4 child tasks.
Definition task.c:80
void initTimLoader(TimLoader *obj)
Clears a TIM loader, gives it its methods and binds it.
Definition tim_loader.c:119