diff --git a/src/mem.c b/src/mem.c index e6143aa..b3639e9 100644 --- a/src/mem.c +++ b/src/mem.c @@ -21,22 +21,9 @@ void *mem_mark(void) { } // mem_bump is guaranteed to return a pointer aligned to 8 bytes. -// It is not guaranteed to return a pointer that immediately follows the -// previous one it handed out; use mem_bump_unaligned for that. void *mem_bump(uint32_t size) { - // In addition to aligning the size itself, we must also align - // bump_len since a previous direct call to mem_bump_unaligned may - // have destroyed its alignment. - bump_len = round_up_to_word(bump_len); size = round_up_to_word(size); - return mem_bump_unaligned(size); -} - -// The only time this ever gets called is for loading primitives and objects. -// Ideally we would never call it at all, given the risk of bus errors. - -void *mem_bump_unaligned(uint32_t size) { error_if(bump_len + temp_len + size >= MEM_HUNK_BYTES, "Failed to allocate %d bytes in hunk mem", size); uint8_t *p = &hunk[bump_len]; bump_len += size; diff --git a/src/mem.h b/src/mem.h index 450a917..cfd5839 100644 --- a/src/mem.h +++ b/src/mem.h @@ -7,7 +7,6 @@ #define MEM_HUNK_BYTES (16 * 1024 * 1024) void *mem_bump(uint32_t size); -void *mem_bump_unaligned(uint32_t size); void *mem_mark(void); void mem_reset(void *p); diff --git a/src/wipeout/droid.c b/src/wipeout/droid.c index 6d52cc4..b816d1b 100755 --- a/src/wipeout/droid.c +++ b/src/wipeout/droid.c @@ -49,12 +49,12 @@ void droid_init(droid_t *droid, ship_t *ship) { void droid_draw(droid_t *droid) { droid->cycle_timer += system_tick() * M_PI * 2; - Prm prm = {.primitive = droid_model->primitives}; int rf = sinf(droid->cycle_timer) * 127 + 128; int gf = sinf(droid->cycle_timer + 0.2) * 127 + 128; int bf = sinf(droid->cycle_timer * 0.5 + 0.1) * 127 + 128; for (int i = 0; i < 11; i++) { + primitive_t *prm = &droid_model->primitives[i]; rgba_t color; if (i < 2) { @@ -67,21 +67,19 @@ void droid_draw(droid_t *droid) { color = rgba(rf, 40, 40, 0xFF); } - switch (prm.f3->type) { - case PRM_TYPE_GT3: - prm.gt3->color[0] = - prm.gt3->color[1] = - prm.gt3->color[2] = color; - prm.gt3++; + switch (prm->type) { + case PRM_TYPE_TRI: + for (int j = 0; j < 3; j++) { + prm->u.tri.v[j].color = color; + } break; - - case PRM_TYPE_GT4: - prm.gt4->color[0] = - prm.gt4->color[1] = - prm.gt4->color[2] = color; - prm.gt4->color[3] = rgba(40,40,40,0xFF); - prm.gt4++; + case PRM_TYPE_QUAD: + for (int j = 0; j < 4; j++) { + prm->u.quad.v[j].color = color; + } break; + default: + die("Can't happen: Expected primitive type %x or %x, got %x", PRM_TYPE_TRI, PRM_TYPE_QUAD, prm->type); } } diff --git a/src/wipeout/object.c b/src/wipeout/object.c index 1a874eb..10162b1 100755 --- a/src/wipeout/object.c +++ b/src/wipeout/object.c @@ -6,6 +6,32 @@ #include "object.h" +// Altering this enum (other than by adding to the end) +// will break compatibility with the assets. +enum { + PSX_PRM_TYPE_F3 = 1, + PSX_PRM_TYPE_FT3, + PSX_PRM_TYPE_F4, + PSX_PRM_TYPE_FT4, + PSX_PRM_TYPE_G3, + PSX_PRM_TYPE_GT3, + PSX_PRM_TYPE_G4, + PSX_PRM_TYPE_GT4, + + PSX_PRM_TYPE_TSPR = 10, + PSX_PRM_TYPE_BSPR, + + PSX_PRM_TYPE_SPLINE = 20, +}; + +// The types above can be interpreted as flags like so. +// (You must decrement the type by one for this to work.) +enum { + PSX_PRM_FLAG_TEXTURED = 1 << 0, + PSX_PRM_FLAG_QUAD = 1 << 1, + PSX_PRM_FLAG_GOURAUD = 1 << 2, +}; + Object *objects_load(char *name, texture_list_t tl) { uint32_t length = 0; uint8_t *bytes = platform_load_asset(name, &length); @@ -20,7 +46,7 @@ Object *objects_load(char *name, texture_list_t tl) { uint32_t p = 0; while (p < length) { - Object *object = mem_bump_unaligned(sizeof(Object)); + Object *object = mem_bump(sizeof(Object)); if (prevObject) { prevObject->next = object; } @@ -81,355 +107,108 @@ Object *objects_load(char *name, texture_list_t tl) { p += 2; // padding } - object->primitives = mem_mark(); + object->primitives = mem_bump(object->primitives_len * sizeof(primitive_t)); for (int i = 0; i < object->primitives_len; i++) { - Prm prm; - int16_t prm_type = get_i16(bytes, &p); - int16_t prm_flag = get_i16(bytes, &p); - - switch (prm_type) { - case PRM_TYPE_F3: - prm.ptr = mem_bump_unaligned(sizeof(F3)); - prm.f3->coords[0] = get_i16(bytes, &p); - prm.f3->coords[1] = get_i16(bytes, &p); - prm.f3->coords[2] = get_i16(bytes, &p); - prm.f3->pad1 = get_i16(bytes, &p); - prm.f3->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_F4: - prm.ptr = mem_bump_unaligned(sizeof(F4)); - prm.f4->coords[0] = get_i16(bytes, &p); - prm.f4->coords[1] = get_i16(bytes, &p); - prm.f4->coords[2] = get_i16(bytes, &p); - prm.f4->coords[3] = get_i16(bytes, &p); - prm.f4->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_FT3: - prm.ptr = mem_bump_unaligned(sizeof(FT3)); - prm.ft3->coords[0] = get_i16(bytes, &p); - prm.ft3->coords[1] = get_i16(bytes, &p); - prm.ft3->coords[2] = get_i16(bytes, &p); - - prm.ft3->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.ft3->cba = get_i16(bytes, &p); - prm.ft3->tsb = get_i16(bytes, &p); - prm.ft3->u0 = get_i8(bytes, &p); - prm.ft3->v0 = get_i8(bytes, &p); - prm.ft3->u1 = get_i8(bytes, &p); - prm.ft3->v1 = get_i8(bytes, &p); - prm.ft3->u2 = get_i8(bytes, &p); - prm.ft3->v2 = get_i8(bytes, &p); - - prm.ft3->pad1 = get_i16(bytes, &p); - prm.ft3->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_FT4: - prm.ptr = mem_bump_unaligned(sizeof(FT4)); - prm.ft4->coords[0] = get_i16(bytes, &p); - prm.ft4->coords[1] = get_i16(bytes, &p); - prm.ft4->coords[2] = get_i16(bytes, &p); - prm.ft4->coords[3] = get_i16(bytes, &p); - - prm.ft4->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.ft4->cba = get_i16(bytes, &p); - prm.ft4->tsb = get_i16(bytes, &p); - prm.ft4->u0 = get_i8(bytes, &p); - prm.ft4->v0 = get_i8(bytes, &p); - prm.ft4->u1 = get_i8(bytes, &p); - prm.ft4->v1 = get_i8(bytes, &p); - prm.ft4->u2 = get_i8(bytes, &p); - prm.ft4->v2 = get_i8(bytes, &p); - prm.ft4->u3 = get_i8(bytes, &p); - prm.ft4->v3 = get_i8(bytes, &p); - prm.ft4->pad1 = get_i16(bytes, &p); - prm.ft4->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_G3: - prm.ptr = mem_bump_unaligned(sizeof(G3)); - prm.g3->coords[0] = get_i16(bytes, &p); - prm.g3->coords[1] = get_i16(bytes, &p); - prm.g3->coords[2] = get_i16(bytes, &p); - prm.g3->pad1 = get_i16(bytes, &p); - prm.g3->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.g3->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.g3->color[2] = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_G4: - prm.ptr = mem_bump_unaligned(sizeof(G4)); - prm.g4->coords[0] = get_i16(bytes, &p); - prm.g4->coords[1] = get_i16(bytes, &p); - prm.g4->coords[2] = get_i16(bytes, &p); - prm.g4->coords[3] = get_i16(bytes, &p); - prm.g4->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.g4->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.g4->color[2] = rgba_from_u32(get_u32(bytes, &p)); - prm.g4->color[3] = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_GT3: - prm.ptr = mem_bump_unaligned(sizeof(GT3)); - prm.gt3->coords[0] = get_i16(bytes, &p); - prm.gt3->coords[1] = get_i16(bytes, &p); - prm.gt3->coords[2] = get_i16(bytes, &p); - - prm.gt3->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.gt3->cba = get_i16(bytes, &p); - prm.gt3->tsb = get_i16(bytes, &p); - prm.gt3->u0 = get_i8(bytes, &p); - prm.gt3->v0 = get_i8(bytes, &p); - prm.gt3->u1 = get_i8(bytes, &p); - prm.gt3->v1 = get_i8(bytes, &p); - prm.gt3->u2 = get_i8(bytes, &p); - prm.gt3->v2 = get_i8(bytes, &p); - prm.gt3->pad1 = get_i16(bytes, &p); - prm.gt3->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.gt3->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.gt3->color[2] = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_GT4: - prm.ptr = mem_bump_unaligned(sizeof(GT4)); - prm.gt4->coords[0] = get_i16(bytes, &p); - prm.gt4->coords[1] = get_i16(bytes, &p); - prm.gt4->coords[2] = get_i16(bytes, &p); - prm.gt4->coords[3] = get_i16(bytes, &p); - - prm.gt4->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.gt4->cba = get_i16(bytes, &p); - prm.gt4->tsb = get_i16(bytes, &p); - prm.gt4->u0 = get_i8(bytes, &p); - prm.gt4->v0 = get_i8(bytes, &p); - prm.gt4->u1 = get_i8(bytes, &p); - prm.gt4->v1 = get_i8(bytes, &p); - prm.gt4->u2 = get_i8(bytes, &p); - prm.gt4->v2 = get_i8(bytes, &p); - prm.gt4->u3 = get_i8(bytes, &p); - prm.gt4->v3 = get_i8(bytes, &p); - prm.gt4->pad1 = get_i16(bytes, &p); - prm.gt4->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.gt4->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.gt4->color[2] = rgba_from_u32(get_u32(bytes, &p)); - prm.gt4->color[3] = rgba_from_u32(get_u32(bytes, &p)); - break; - - - case PRM_TYPE_LSF3: - prm.ptr = mem_bump_unaligned(sizeof(LSF3)); - prm.lsf3->coords[0] = get_i16(bytes, &p); - prm.lsf3->coords[1] = get_i16(bytes, &p); - prm.lsf3->coords[2] = get_i16(bytes, &p); - prm.lsf3->normal = get_i16(bytes, &p); - prm.lsf3->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSF4: - prm.ptr = mem_bump_unaligned(sizeof(LSF4)); - prm.lsf4->coords[0] = get_i16(bytes, &p); - prm.lsf4->coords[1] = get_i16(bytes, &p); - prm.lsf4->coords[2] = get_i16(bytes, &p); - prm.lsf4->coords[3] = get_i16(bytes, &p); - prm.lsf4->normal = get_i16(bytes, &p); - prm.lsf4->pad1 = get_i16(bytes, &p); - prm.lsf4->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSFT3: - prm.ptr = mem_bump_unaligned(sizeof(LSFT3)); - prm.lsft3->coords[0] = get_i16(bytes, &p); - prm.lsft3->coords[1] = get_i16(bytes, &p); - prm.lsft3->coords[2] = get_i16(bytes, &p); - prm.lsft3->normal = get_i16(bytes, &p); - - prm.lsft3->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.lsft3->cba = get_i16(bytes, &p); - prm.lsft3->tsb = get_i16(bytes, &p); - prm.lsft3->u0 = get_i8(bytes, &p); - prm.lsft3->v0 = get_i8(bytes, &p); - prm.lsft3->u1 = get_i8(bytes, &p); - prm.lsft3->v1 = get_i8(bytes, &p); - prm.lsft3->u2 = get_i8(bytes, &p); - prm.lsft3->v2 = get_i8(bytes, &p); - prm.lsft3->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSFT4: - prm.ptr = mem_bump_unaligned(sizeof(LSFT4)); - prm.lsft4->coords[0] = get_i16(bytes, &p); - prm.lsft4->coords[1] = get_i16(bytes, &p); - prm.lsft4->coords[2] = get_i16(bytes, &p); - prm.lsft4->coords[3] = get_i16(bytes, &p); - prm.lsft4->normal = get_i16(bytes, &p); - - prm.lsft4->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.lsft4->cba = get_i16(bytes, &p); - prm.lsft4->tsb = get_i16(bytes, &p); - prm.lsft4->u0 = get_i8(bytes, &p); - prm.lsft4->v0 = get_i8(bytes, &p); - prm.lsft4->u1 = get_i8(bytes, &p); - prm.lsft4->v1 = get_i8(bytes, &p); - prm.lsft4->u2 = get_i8(bytes, &p); - prm.lsft4->v2 = get_i8(bytes, &p); - prm.lsft4->u3 = get_i8(bytes, &p); - prm.lsft4->v3 = get_i8(bytes, &p); - prm.lsft4->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSG3: - prm.ptr = mem_bump_unaligned(sizeof(LSG3)); - prm.lsg3->coords[0] = get_i16(bytes, &p); - prm.lsg3->coords[1] = get_i16(bytes, &p); - prm.lsg3->coords[2] = get_i16(bytes, &p); - prm.lsg3->normals[0] = get_i16(bytes, &p); - prm.lsg3->normals[1] = get_i16(bytes, &p); - prm.lsg3->normals[2] = get_i16(bytes, &p); - prm.lsg3->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsg3->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsg3->color[2] = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSG4: - prm.ptr = mem_bump_unaligned(sizeof(LSG4)); - prm.lsg4->coords[0] = get_i16(bytes, &p); - prm.lsg4->coords[1] = get_i16(bytes, &p); - prm.lsg4->coords[2] = get_i16(bytes, &p); - prm.lsg4->coords[3] = get_i16(bytes, &p); - prm.lsg4->normals[0] = get_i16(bytes, &p); - prm.lsg4->normals[1] = get_i16(bytes, &p); - prm.lsg4->normals[2] = get_i16(bytes, &p); - prm.lsg4->normals[3] = get_i16(bytes, &p); - prm.lsg4->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsg4->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsg4->color[2] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsg4->color[3] = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSGT3: - prm.ptr = mem_bump_unaligned(sizeof(LSGT3)); - prm.lsgt3->coords[0] = get_i16(bytes, &p); - prm.lsgt3->coords[1] = get_i16(bytes, &p); - prm.lsgt3->coords[2] = get_i16(bytes, &p); - prm.lsgt3->normals[0] = get_i16(bytes, &p); - prm.lsgt3->normals[1] = get_i16(bytes, &p); - prm.lsgt3->normals[2] = get_i16(bytes, &p); - - prm.lsgt3->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.lsgt3->cba = get_i16(bytes, &p); - prm.lsgt3->tsb = get_i16(bytes, &p); - prm.lsgt3->u0 = get_i8(bytes, &p); - prm.lsgt3->v0 = get_i8(bytes, &p); - prm.lsgt3->u1 = get_i8(bytes, &p); - prm.lsgt3->v1 = get_i8(bytes, &p); - prm.lsgt3->u2 = get_i8(bytes, &p); - prm.lsgt3->v2 = get_i8(bytes, &p); - prm.lsgt3->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsgt3->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsgt3->color[2] = rgba_from_u32(get_u32(bytes, &p)); - break; - - case PRM_TYPE_LSGT4: - prm.ptr = mem_bump_unaligned(sizeof(LSGT4)); - prm.lsgt4->coords[0] = get_i16(bytes, &p); - prm.lsgt4->coords[1] = get_i16(bytes, &p); - prm.lsgt4->coords[2] = get_i16(bytes, &p); - prm.lsgt4->coords[3] = get_i16(bytes, &p); - prm.lsgt4->normals[0] = get_i16(bytes, &p); - prm.lsgt4->normals[1] = get_i16(bytes, &p); - prm.lsgt4->normals[2] = get_i16(bytes, &p); - prm.lsgt4->normals[3] = get_i16(bytes, &p); - - prm.lsgt4->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.lsgt4->cba = get_i16(bytes, &p); - prm.lsgt4->tsb = get_i16(bytes, &p); - prm.lsgt4->u0 = get_i8(bytes, &p); - prm.lsgt4->v0 = get_i8(bytes, &p); - prm.lsgt4->u1 = get_i8(bytes, &p); - prm.lsgt4->v1 = get_i8(bytes, &p); - prm.lsgt4->u2 = get_i8(bytes, &p); - prm.lsgt4->v2 = get_i8(bytes, &p); - prm.lsgt4->pad1 = get_i16(bytes, &p); - prm.lsgt4->color[0] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsgt4->color[1] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsgt4->color[2] = rgba_from_u32(get_u32(bytes, &p)); - prm.lsgt4->color[3] = rgba_from_u32(get_u32(bytes, &p)); + primitive_t *prm = &object->primitives[i]; + + int psx_prm_type = get_i16(bytes, &p); + prm->flag = get_i16(bytes, &p); + switch (psx_prm_type) { + case PSX_PRM_TYPE_F3: + case PSX_PRM_TYPE_FT3: + case PSX_PRM_TYPE_F4: + case PSX_PRM_TYPE_FT4: + case PSX_PRM_TYPE_G3: + case PSX_PRM_TYPE_GT3: + case PSX_PRM_TYPE_G4: + case PSX_PRM_TYPE_GT4: + psx_prm_type--; // Flags trick does not line up right without this. + if (psx_prm_type & PSX_PRM_FLAG_QUAD) { + prm->type = PRM_TYPE_QUAD; + for (int j = 0; j < 4; j++) { + prm->u.quad.v[j].coord = get_i16(bytes, &p); + } + + if (psx_prm_type & PSX_PRM_FLAG_TEXTURED) { + prm->u.quad.texture = texture_from_list(tl, get_i16(bytes, &p)); + p += 2 + 2; // csb/tsb + for (int j = 0; j < 4; j++) { + prm->u.quad.v[j].u = get_i8(bytes, &p); + prm->u.quad.v[j].v = get_i8(bytes, &p); + } + p += 2; // padding + } + if (psx_prm_type & PSX_PRM_FLAG_GOURAUD) { + prm->u.quad.v[0].color = rgba_from_u32(get_u32(bytes, &p)); + prm->u.quad.v[1].color = rgba_from_u32(get_u32(bytes, &p)); + prm->u.quad.v[2].color = rgba_from_u32(get_u32(bytes, &p)); + prm->u.quad.v[3].color = rgba_from_u32(get_u32(bytes, &p)); + } else { + prm->u.quad.v[0].color = + prm->u.quad.v[1].color = + prm->u.quad.v[2].color = + prm->u.quad.v[3].color = rgba_from_u32(get_u32(bytes, &p)); + } + } else { + prm->type = PRM_TYPE_TRI; + for (int j = 0; j < 3; j++) { + prm->u.tri.v[j].coord = get_i16(bytes, &p); + } + + if (psx_prm_type & PSX_PRM_FLAG_TEXTURED) { + prm->u.tri.texture = texture_from_list(tl, get_i16(bytes, &p)); + p += 2 + 2; // csb/tsb + for (int j = 0; j < 3; j++) { + prm->u.tri.v[j].u = get_i8(bytes, &p); + prm->u.tri.v[j].v = get_i8(bytes, &p); + } + } + p += 2; // padding + if (psx_prm_type & PSX_PRM_FLAG_GOURAUD) { + prm->u.tri.v[0].color = rgba_from_u32(get_u32(bytes, &p)); + prm->u.tri.v[1].color = rgba_from_u32(get_u32(bytes, &p)); + prm->u.tri.v[2].color = rgba_from_u32(get_u32(bytes, &p)); + } else { + prm->u.tri.v[0].color = + prm->u.tri.v[1].color = + prm->u.tri.v[2].color = rgba_from_u32(get_u32(bytes, &p)); + } + } break; + case PSX_PRM_TYPE_TSPR: + case PSX_PRM_TYPE_BSPR: + prm->type = PRM_TYPE_SPR; + prm->u.spr.coord = get_i16(bytes, &p); + prm->u.spr.width = get_i16(bytes, &p); + prm->u.spr.height = get_i16(bytes, &p); + prm->u.spr.texture = texture_from_list(tl, get_i16(bytes, &p)); + prm->u.spr.color = rgba_from_u32(get_u32(bytes, &p)); - case PRM_TYPE_TSPR: - case PRM_TYPE_BSPR: - prm.ptr = mem_bump_unaligned(sizeof(SPR)); - prm.spr->coord = get_i16(bytes, &p); - prm.spr->width = get_i16(bytes, &p); - prm.spr->height = get_i16(bytes, &p); - prm.spr->texture = texture_from_list(tl, get_i16(bytes, &p)); - prm.spr->color = rgba_from_u32(get_u32(bytes, &p)); + object->vertices[prm->u.spr.coord].y += ((psx_prm_type == PSX_PRM_TYPE_TSPR ? prm->u.spr.height : -prm->u.spr.height) >> 1); break; - - case PRM_TYPE_SPLINE: - prm.ptr = mem_bump_unaligned(sizeof(Spline)); - prm.spline->control1.x = get_i32(bytes, &p); - prm.spline->control1.y = get_i32(bytes, &p); - prm.spline->control1.z = get_i32(bytes, &p); + case PSX_PRM_TYPE_SPLINE: + p += 52; + /* TODO: Implement spline. + prm->type = psx_prm_type; + prm->psx.spline.control1.x = get_i32(bytes, &p); + prm->psx.spline.control1.y = get_i32(bytes, &p); + prm->psx.spline.control1.z = get_i32(bytes, &p); p += 4; // padding - prm.spline->position.x = get_i32(bytes, &p); - prm.spline->position.y = get_i32(bytes, &p); - prm.spline->position.z = get_i32(bytes, &p); + prm->psx.spline.position.x = get_i32(bytes, &p); + prm->psx.spline.position.y = get_i32(bytes, &p); + prm->psx.spline.position.z = get_i32(bytes, &p); p += 4; // padding - prm.spline->control2.x = get_i32(bytes, &p); - prm.spline->control2.y = get_i32(bytes, &p); - prm.spline->control2.z = get_i32(bytes, &p); + prm->psx.spline.control2.x = get_i32(bytes, &p); + prm->psx.spline.control2.y = get_i32(bytes, &p); + prm->psx.spline.control2.z = get_i32(bytes, &p); p += 4; // padding - prm.spline->color = rgba_from_u32(get_u32(bytes, &p)); + prm->psx.spline.color = rgba_from_u32(get_u32(bytes, &p)); + */ break; - - case PRM_TYPE_POINT_LIGHT: - prm.ptr = mem_bump_unaligned(sizeof(PointLight)); - prm.pointLight->position.x = get_i32(bytes, &p); - prm.pointLight->position.y = get_i32(bytes, &p); - prm.pointLight->position.z = get_i32(bytes, &p); - p += 4; // padding - prm.pointLight->color = rgba_from_u32(get_u32(bytes, &p)); - prm.pointLight->startFalloff = get_i16(bytes, &p); - prm.pointLight->endFalloff = get_i16(bytes, &p); - break; - - case PRM_TYPE_SPOT_LIGHT: - prm.ptr = mem_bump_unaligned(sizeof(SpotLight)); - prm.spotLight->position.x = get_i32(bytes, &p); - prm.spotLight->position.y = get_i32(bytes, &p); - prm.spotLight->position.z = get_i32(bytes, &p); - p += 4; // padding - prm.spotLight->direction.x = get_i16(bytes, &p); - prm.spotLight->direction.y = get_i16(bytes, &p); - prm.spotLight->direction.z = get_i16(bytes, &p); - p += 2; // padding - prm.spotLight->color = rgba_from_u32(get_u32(bytes, &p)); - prm.spotLight->startFalloff = get_i16(bytes, &p); - prm.spotLight->endFalloff = get_i16(bytes, &p); - prm.spotLight->coneAngle = get_i16(bytes, &p); - prm.spotLight->spreadAngle = get_i16(bytes, &p); - break; - - case PRM_TYPE_INFINITE_LIGHT: - prm.ptr = mem_bump_unaligned(sizeof(InfiniteLight)); - prm.infiniteLight->direction.x = get_i16(bytes, &p); - prm.infiniteLight->direction.y = get_i16(bytes, &p); - prm.infiniteLight->direction.z = get_i16(bytes, &p); - p += 2; // padding - prm.infiniteLight->color = rgba_from_u32(get_u32(bytes, &p)); - break; - - default: - die("bad primitive type %x \n", prm_type); + die("Unknown primitive type %x", prm->type); } // switch - - prm.f3->type = prm_type; - prm.f3->flag = prm_flag; } // each prim } // each object @@ -440,327 +219,54 @@ Object *objects_load(char *name, texture_list_t tl) { void object_draw(Object *object, mat4_t *mat) { vec3_t *vertex = object->vertices; - - Prm poly = {.primitive = object->primitives}; - int primitives_len = object->primitives_len; - render_set_model_mat(mat); - // TODO: check for PRM_SINGLE_SIDED - - for (int i = 0; i < primitives_len; i++) { - int coord0; - int coord1; - int coord2; - int coord3; - switch (poly.primitive->type) { - case PRM_TYPE_GT3: - coord0 = poly.gt3->coords[0]; - coord1 = poly.gt3->coords[1]; - coord2 = poly.gt3->coords[2]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .uv = {poly.gt3->u2, poly.gt3->v2}, - .color = poly.gt3->color[2] - }, - { - .pos = vertex[coord1], - .uv = {poly.gt3->u1, poly.gt3->v1}, - .color = poly.gt3->color[1] - }, - { - .pos = vertex[coord0], - .uv = {poly.gt3->u0, poly.gt3->v0}, - .color = poly.gt3->color[0] - }, - } - }, poly.gt3->texture); - - poly.gt3 += 1; - break; - - case PRM_TYPE_GT4: - coord0 = poly.gt4->coords[0]; - coord1 = poly.gt4->coords[1]; - coord2 = poly.gt4->coords[2]; - coord3 = poly.gt4->coords[3]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .uv = {poly.gt4->u2, poly.gt4->v2}, - .color = poly.gt4->color[2] - }, - { - .pos = vertex[coord1], - .uv = {poly.gt4->u1, poly.gt4->v1}, - .color = poly.gt4->color[1] - }, - { - .pos = vertex[coord0], - .uv = {poly.gt4->u0, poly.gt4->v0}, - .color = poly.gt4->color[0] - }, - } - }, poly.gt4->texture); - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .uv = {poly.gt4->u2, poly.gt4->v2}, - .color = poly.gt4->color[2] - }, - { - .pos = vertex[coord3], - .uv = {poly.gt4->u3, poly.gt4->v3}, - .color = poly.gt4->color[3] - }, - { - .pos = vertex[coord1], - .uv = {poly.gt4->u1, poly.gt4->v1}, - .color = poly.gt4->color[1] - }, - } - }, poly.gt4->texture); - - poly.gt4 += 1; - break; - - case PRM_TYPE_FT3: - coord0 = poly.ft3->coords[0]; - coord1 = poly.ft3->coords[1]; - coord2 = poly.ft3->coords[2]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .uv = {poly.ft3->u2, poly.ft3->v2}, - .color = poly.ft3->color - }, - { - .pos = vertex[coord1], - .uv = {poly.ft3->u1, poly.ft3->v1}, - .color = poly.ft3->color - }, - { - .pos = vertex[coord0], - .uv = {poly.ft3->u0, poly.ft3->v0}, - .color = poly.ft3->color - }, - } - }, poly.ft3->texture); - - poly.ft3 += 1; - break; - - case PRM_TYPE_FT4: - coord0 = poly.ft4->coords[0]; - coord1 = poly.ft4->coords[1]; - coord2 = poly.ft4->coords[2]; - coord3 = poly.ft4->coords[3]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .uv = {poly.ft4->u2, poly.ft4->v2}, - .color = poly.ft4->color - }, - { - .pos = vertex[coord1], - .uv = {poly.ft4->u1, poly.ft4->v1}, - .color = poly.ft4->color - }, - { - .pos = vertex[coord0], - .uv = {poly.ft4->u0, poly.ft4->v0}, - .color = poly.ft4->color - }, - } - }, poly.ft4->texture); - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .uv = {poly.ft4->u2, poly.ft4->v2}, - .color = poly.ft4->color - }, - { - .pos = vertex[coord3], - .uv = {poly.ft4->u3, poly.ft4->v3}, - .color = poly.ft4->color - }, - { - .pos = vertex[coord1], - .uv = {poly.ft4->u1, poly.ft4->v1}, - .color = poly.ft4->color - }, - } - }, poly.ft4->texture); - - poly.ft4 += 1; - break; - - case PRM_TYPE_G3: - coord0 = poly.g3->coords[0]; - coord1 = poly.g3->coords[1]; - coord2 = poly.g3->coords[2]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .color = poly.g3->color[2] - }, - { - .pos = vertex[coord1], - .color = poly.g3->color[1] - }, - { - .pos = vertex[coord0], - .color = poly.g3->color[0] - }, - } - }, RENDER_NO_TEXTURE); - - poly.g3 += 1; - break; - - case PRM_TYPE_G4: - coord0 = poly.g4->coords[0]; - coord1 = poly.g4->coords[1]; - coord2 = poly.g4->coords[2]; - coord3 = poly.g4->coords[3]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .color = poly.g4->color[2] - }, - { - .pos = vertex[coord1], - .color = poly.g4->color[1] - }, - { - .pos = vertex[coord0], - .color = poly.g4->color[0] - }, - } - }, RENDER_NO_TEXTURE); - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .color = poly.g4->color[2] - }, - { - .pos = vertex[coord3], - .color = poly.g4->color[3] - }, - { - .pos = vertex[coord1], - .color = poly.g4->color[1] - }, - } - }, RENDER_NO_TEXTURE); - - poly.g4 += 1; - break; - - case PRM_TYPE_F3: - coord0 = poly.f3->coords[0]; - coord1 = poly.f3->coords[1]; - coord2 = poly.f3->coords[2]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .color = poly.f3->color - }, - { - .pos = vertex[coord1], - .color = poly.f3->color - }, - { - .pos = vertex[coord0], - .color = poly.f3->color - }, - } - }, RENDER_NO_TEXTURE); - - poly.f3 += 1; - break; - - case PRM_TYPE_F4: - coord0 = poly.f4->coords[0]; - coord1 = poly.f4->coords[1]; - coord2 = poly.f4->coords[2]; - coord3 = poly.f4->coords[3]; - - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .color = poly.f4->color - }, - { - .pos = vertex[coord1], - .color = poly.f4->color - }, - { - .pos = vertex[coord0], - .color = poly.f4->color - }, - } - }, RENDER_NO_TEXTURE); - render_push_tris((tris_t) { - .vertices = { - { - .pos = vertex[coord2], - .color = poly.f4->color - }, - { - .pos = vertex[coord3], - .color = poly.f4->color - }, - { - .pos = vertex[coord1], - .color = poly.f4->color - }, - } - }, RENDER_NO_TEXTURE); - - poly.f4 += 1; - break; - - case PRM_TYPE_TSPR: - case PRM_TYPE_BSPR: - coord0 = poly.spr->coord; - + for (int i = 0; i < object->primitives_len; i++) { + primitive_t *prm = &object->primitives[i]; + vertex_t v[4]; + switch (prm->type) { + case PRM_TYPE_SPR: render_push_sprite( - vec3( - vertex[coord0].x, - vertex[coord0].y + ((poly.primitive->type == PRM_TYPE_TSPR ? poly.spr->height : -poly.spr->height) >> 1), - vertex[coord0].z - ), - vec2i(poly.spr->width, poly.spr->height), - poly.spr->color, - poly.spr->texture + vertex[prm->u.spr.coord], + vec2i(prm->u.spr.width, prm->u.spr.height), + prm->u.spr.color, + prm->u.spr.texture ); - - poly.spr += 1; break; - - default: + case PRM_TYPE_TRI: + for (int j = 0; j < 3; j++) { + primitive_vertex_t p = prm->u.tri.v[j]; + v[j] = (vertex_t){ + .pos = vertex[p.coord], + .uv = {p.u, p.v}, + .color = p.color + }; + } + render_push_tris((tris_t) {.vertices = {v[2],v[1],v[0]}}, prm->u.quad.texture); + // Double sided polygons are achieved by submitting them twice with different winding orders. + if (flags_not(prm->flag, PRM_SINGLE_SIDED)) { + render_push_tris((tris_t) {.vertices = {v[1],v[2],v[0]}}, prm->u.quad.texture); + } break; - + case PRM_TYPE_QUAD: + for (int j = 0; j < 4; j++) { + primitive_vertex_t p = prm->u.quad.v[j]; + v[j] = (vertex_t){ + .pos = vertex[p.coord], + .uv = {p.u, p.v}, + .color = p.color + }; + } + render_push_tris((tris_t) {.vertices = {v[2],v[1],v[0]}}, prm->u.quad.texture); + render_push_tris((tris_t) {.vertices = {v[2],v[3],v[1]}}, prm->u.quad.texture); + // See above. + if (flags_not(prm->flag, PRM_SINGLE_SIDED)) { + render_push_tris((tris_t) {.vertices = {v[1],v[2],v[0]}}, prm->u.quad.texture); + render_push_tris((tris_t) {.vertices = {v[3],v[2],v[1]}}, prm->u.quad.texture); + } + break; + default: + die("Can't happen: Unknown primitive type %x", prm->type); } } } diff --git a/src/wipeout/object.h b/src/wipeout/object.h index b8dc17f..2e883ee 100755 --- a/src/wipeout/object.h +++ b/src/wipeout/object.h @@ -6,290 +6,55 @@ #include "../utils.h" #include "image.h" -// Primitive Structure Stub ( Structure varies with primitive type ) - -typedef struct Primitive { - int16_t type; // Type of Primitive - int16_t flag; -} Primitive; - - -typedef struct F3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t pad1; - rgba_t color; -} F3; - -typedef struct FT3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - int16_t pad1; - rgba_t color; -} FT3; - -typedef struct F4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - rgba_t color; -} F4; - -typedef struct FT4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - uint8_t u3; - uint8_t v3; - int16_t pad1; - rgba_t color; -} FT4; - -typedef struct G3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t pad1; - rgba_t color[3]; -} G3; - -typedef struct GT3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - int16_t pad1; - rgba_t color[3]; -} GT3; - -typedef struct G4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - rgba_t color[4]; -} G4; - -typedef struct GT4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - uint8_t u3; - uint8_t v3; - int16_t pad1; - rgba_t color[4]; -} GT4; - - - - -/* LIGHT SOURCED POLYGONS -*/ - -typedef struct LSF3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t normal; // Indices of the normals - rgba_t color; -} LSF3; - -typedef struct LSFT3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t normal; // Indices of the normals - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - rgba_t color; -} LSFT3; - -typedef struct LSF4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - int16_t normal; // Indices of the normals - int16_t pad1; - rgba_t color; -} LSF4; - -typedef struct LSFT4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - int16_t normal; // Indices of the normals - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - uint8_t u3; - uint8_t v3; - rgba_t color; -} LSFT4; - -typedef struct LSG3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t normals[3]; // Indices of the normals - rgba_t color[3]; -} LSG3; - -typedef struct LSGT3 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[3]; // Indices of the coords - int16_t normals[3]; // Indices of the normals - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - rgba_t color[3]; -} LSGT3; - -typedef struct LSG4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - int16_t normals[4]; // Indices of the normals - rgba_t color[4]; -} LSG4; - -typedef struct LSGT4 { - int16_t type; // Type of primitive - int16_t flag; - int16_t coords[4]; // Indices of the coords - int16_t normals[4]; // Indices of the normals - int16_t texture; - int16_t cba; - int16_t tsb; - uint8_t u0; - uint8_t v0; - uint8_t u1; - uint8_t v1; - uint8_t u2; - uint8_t v2; - uint8_t u3; - uint8_t v3; - int16_t pad1; - rgba_t color[4]; -} LSGT4; - - - - - +enum { + // "Universal" primitives (models are converted to use these at load time.) + PRM_TYPE_TRI, + PRM_TYPE_QUAD, + PRM_TYPE_SPR, +}; -/* OTHER PRIMITIVE TYPES -*/ -typedef struct SPR { - int16_t type; - int16_t flag; +typedef struct { int16_t coord; - int16_t width; - int16_t height; - int16_t texture; - rgba_t color; -} SPR; - - -typedef struct Spline { - int16_t type; // Type of primitive - int16_t flag; - vec3_t control1; - vec3_t position; - vec3_t control2; - rgba_t color; -} Spline; - - -typedef struct PointLight { - int16_t type; - int16_t flag; - vec3_t position; - rgba_t color; - int16_t startFalloff; - int16_t endFalloff; -} PointLight; - - -typedef struct SpotLight { - int16_t type; - int16_t flag; - vec3_t position; - vec3_t direction; - rgba_t color; - int16_t startFalloff; - int16_t endFalloff; - int16_t coneAngle; - int16_t spreadAngle; -} SpotLight; - - -typedef struct InfiniteLight { - int16_t type; - int16_t flag; - vec3_t direction; + uint8_t u, v; rgba_t color; -} InfiniteLight; - - - - +} primitive_vertex_t; +typedef struct Primitive { + int8_t type; + int8_t flag; + union { + struct { + int16_t texture; + primitive_vertex_t v[3]; + } tri; + + struct { + int16_t texture; + primitive_vertex_t v[4]; + } quad; + + struct { + int16_t texture; + int16_t coord; + int16_t width; + int16_t height; + rgba_t color; + } spr; + + /* TODO: Implement spline. + * The struct is commented out now to avoid paying for unimplemented features + * (it makes the union substantially larger.) + */ + /* + struct { + vec3_t control1; + vec3_t position; + vec3_t control2; + rgba_t color; + } spline; + */ + } u; +} primitive_t; // PRIMITIVE FLAGS @@ -297,38 +62,6 @@ typedef struct InfiniteLight { #define PRM_SHIP_ENGINE 0x0002 #define PRM_TRANSLUCENT 0x0004 -// Altering this enum (other than adding to the end) -// will break compatibility with the assets. -enum { - PRM_TYPE_F3 = 1, - PRM_TYPE_FT3, - PRM_TYPE_F4, - PRM_TYPE_FT4, - PRM_TYPE_G3, - PRM_TYPE_GT3, - PRM_TYPE_G4, - PRM_TYPE_GT4, - - PRM_TYPE_LF2, - PRM_TYPE_TSPR, - PRM_TYPE_BSPR, - - PRM_TYPE_LSF3, - PRM_TYPE_LSFT3, - PRM_TYPE_LSF4, - PRM_TYPE_LSFT4, - PRM_TYPE_LSG3, - PRM_TYPE_LSGT3, - PRM_TYPE_LSG4, - PRM_TYPE_LSGT4, - - PRM_TYPE_SPLINE, - - PRM_TYPE_INFINITE_LIGHT, - PRM_TYPE_POINT_LIGHT, - PRM_TYPE_SPOT_LIGHT, -}; - typedef struct Object { char name[16]; @@ -340,7 +73,7 @@ typedef struct Object { vec3_t *normals; // Pointer to 3D Normals int16_t primitives_len; // Number of Primitives - Primitive *primitives; // Pointer to Z Sort Primitives + primitive_t *primitives; // Pointer to Z Sort Primitives vec3_t origin; int32_t extent; // Flags for object characteristics @@ -349,37 +82,6 @@ typedef struct Object { struct Object *next; // Next object in list } Object; -typedef union Prm { - uint8_t *ptr; - int16_t *sptr; - int32_t *lptr; - Object *object; - Primitive *primitive; - - F3 *f3; - FT3 *ft3; - F4 *f4; - FT4 *ft4; - G3 *g3; - GT3 *gt3; - G4 *g4; - GT4 *gt4; - SPR *spr; - Spline *spline; - PointLight *pointLight; - SpotLight *spotLight; - InfiniteLight *infiniteLight; - - LSF3 *lsf3; - LSFT3 *lsft3; - LSF4 *lsf4; - LSFT4 *lsft4; - LSG3 *lsg3; - LSGT3 *lsgt3; - LSG4 *lsg4; - LSGT4 *lsgt4; -} Prm; - Object *objects_load(char *name, texture_list_t tl); void object_draw(Object *object, mat4_t *mat); diff --git a/src/wipeout/race.c b/src/wipeout/race.c index 6ae100c..344942e 100755 --- a/src/wipeout/race.c +++ b/src/wipeout/race.c @@ -87,7 +87,7 @@ void race_update(void) { game_set_scene(GAME_SCENE_MAIN_MENU); } float duration = system_time() - attract_start_time; - if ((!active_menu && duration > 30) || duration > 120) { + if ((!active_menu && duration > 30) || duration > 0.1) { game_set_scene(GAME_SCENE_TITLE); } } @@ -101,8 +101,8 @@ void race_update(void) { render_set_view(g.camera.position, g.camera.angle); render_set_screen_position(g.camera.shake); - render_set_cull_backface(false); scene_draw(&g.camera); + render_set_cull_backface(false); track_draw(&g.camera); render_set_cull_backface(true); diff --git a/src/wipeout/scene.c b/src/wipeout/scene.c index 6896d1f..c4381be 100755 --- a/src/wipeout/scene.c +++ b/src/wipeout/scene.c @@ -11,7 +11,6 @@ #define SCENE_OIL_PUMPS_MAX 2 #define SCENE_RED_LIGHTS_MAX 4 #define SCENE_STANDS_MAX 20 -#define AURORA_BOREALIS_PRIMITIVES_MAX 80 static Object *scene_objects; static Object *sky_object; @@ -33,12 +32,7 @@ typedef struct { static scene_stand_t stands[SCENE_STANDS_MAX]; static int stands_len; -static struct { - bool enabled; - GT4 *primitives[AURORA_BOREALIS_PRIMITIVES_MAX]; - int16_t *coords[AURORA_BOREALIS_PRIMITIVES_MAX]; - int16_t grey_coords[AURORA_BOREALIS_PRIMITIVES_MAX]; -} aurora_borealis; +static bool aurora_borealis_enabled; void scene_pulsate_red_light(Object *obj); void scene_move_oil_pump(Object *obj); @@ -110,7 +104,7 @@ void scene_load(const char *base_path, float sky_y_offset) { obj = obj->next; } - aurora_borealis.enabled = false; + aurora_borealis_enabled = false; } void scene_init(void) { @@ -131,7 +125,7 @@ void scene_update(void) { sfx_set_position(stands[i].sfx, stands[i].pos, vec3(0, 0, 0), 0.4); } - if (aurora_borealis.enabled) { + if (aurora_borealis_enabled) { scene_update_aurora_borealis(); } } @@ -173,9 +167,12 @@ rgba_t start_boom_lights[] = { void scene_set_start_booms(int light_index) { for (int i = 0; i < start_booms_len; i++) { - Prm libPoly = {.primitive = start_booms[i]->primitives}; - rgba_t color; for (int j = 0; j < len(start_boom_lights); j++) { + primitive_t *prm = &start_booms[i]->primitives[j]; + + error_if(prm->type != PRM_TYPE_QUAD, "Can't happen: Expected primitive type %x, got %x", PRM_TYPE_QUAD, prm->type); + + rgba_t color; if (j == light_index) { color = start_boom_lights[light_index]; } else { @@ -183,9 +180,8 @@ void scene_set_start_booms(int light_index) { } for (int v = 0; v < 4; v++) { - libPoly.gt4->color[v] = color; + prm->u.quad.v[v].color = color; } - libPoly.gt4 += 1; } } } @@ -193,10 +189,12 @@ void scene_set_start_booms(int light_index) { void scene_pulsate_red_light(Object *obj) { uint8_t r = clamp(sinf(system_cycle_time() * M_PI * 2) * 128 + 128, 0, 255); - Prm libPoly = {.primitive = obj->primitives}; + primitive_t *prm = obj->primitives; + + error_if(prm->type != PRM_TYPE_QUAD, "Can't happen: Expected primitive type %x, got %x", PRM_TYPE_QUAD, prm->type); for (int v = 0; v < 4; v++) { - libPoly.gt4->color[v] = rgba(r,0,0,0xFF); + prm->u.quad.v[v].color = rgba(r,0,0,0xFF); } } @@ -204,61 +202,34 @@ void scene_move_oil_pump(Object *pump) { mat4_set_yaw_pitch_roll(&pump->mat, vec3(sinf(system_cycle_time() * 0.125 * M_PI * 2), 0, 0)); } -void scene_init_aurora_borealis(void) { - aurora_borealis.enabled = true; - clear(aurora_borealis.grey_coords); +static void scene_aurora_set_vertex_color(primitive_vertex_t *v, float phase) { + float y = sky_object->vertices[v->coord].y; + if (y > -6800 || y < -11000) return; - int count = 0; - int16_t *coords; - float y; - - Prm poly = {.primitive = sky_object->primitives}; - for (int i = 0; i < sky_object->primitives_len; i++) { - switch (poly.primitive->type) { - case PRM_TYPE_GT3: - poly.gt3 += 1; - break; - case PRM_TYPE_GT4: - coords = poly.gt4->coords; - y = sky_object->vertices[coords[0]].y; - if (y < -6000) { // -8000 - aurora_borealis.primitives[count] = poly.gt4; - aurora_borealis.coords[count] = poly.gt4->coords; - if (y > -6800) { - aurora_borealis.grey_coords[count] = -1; - } - else if (y < -11000) { - aurora_borealis.grey_coords[count] = -2; - } - count++; - } - poly.gt4 += 1; - break; - } - } -} - -rgba_t scene_aurora_color_from_coordinate(int16_t coord, float phase) { - return rgba( - (sinf(coord * phase) * 64.0) + 190, - (sinf(coord * (phase + 0.054)) * 64.0) + 190, - (sinf(coord * (phase + 0.039)) * 64.0) + 190, + v->color = rgba( + (sinf(v->coord * phase) * 64.0) + 190, + (sinf(v->coord * (phase + 0.054)) * 64.0) + 190, + (sinf(v->coord * (phase + 0.039)) * 64.0) + 190, 0xFF ); } +void scene_init_aurora_borealis() { + aurora_borealis_enabled = true; +} + void scene_update_aurora_borealis(void) { float phase = system_time() / 30.0; - for (int i = 0; i < AURORA_BOREALIS_PRIMITIVES_MAX; i++) { - int16_t *coords = aurora_borealis.coords[i]; - GT4 *primitive = aurora_borealis.primitives[i]; - if (aurora_borealis.grey_coords[i] != -2) { - primitive->color[0] = scene_aurora_color_from_coordinate(coords[0], phase); - primitive->color[1] = scene_aurora_color_from_coordinate(coords[1], phase); - } - if (aurora_borealis.grey_coords[i] != -1) { - primitive->color[2] = scene_aurora_color_from_coordinate(coords[2], phase); - primitive->color[3] = scene_aurora_color_from_coordinate(coords[3], phase); + + for (int i = 0; i < sky_object->primitives_len; i++) { + primitive_t *prm = &sky_object->primitives[i]; + + // The skybox contains triangles but none of them are of interest to us. + if (prm->type == PRM_TYPE_TRI) continue; + error_if(prm->type != PRM_TYPE_QUAD, "Can't happen: Expected primitive type %x, got %x", PRM_TYPE_QUAD, prm->type); + + for (int j = 0; j < len(prm->u.quad.v); j++) { + scene_aurora_set_vertex_color(&prm->u.quad.v[j], phase); } } } diff --git a/src/wipeout/ship.c b/src/wipeout/ship.c index 9f669fa..aed5d71 100644 --- a/src/wipeout/ship.c +++ b/src/wipeout/ship.c @@ -270,46 +270,19 @@ void ship_init_exhaust_plume(ship_t *self) { int16_t indices[64]; int16_t indices_len = 0; - Prm prm = {.primitive = self->model->primitives}; - for (int i = 0; i < self->model->primitives_len; i++) { - if (flags_is(prm.primitive->flag, PRM_SHIP_ENGINE)) { - flags_add(prm.primitive->flag, PRM_TRANSLUCENT); - - switch (prm.primitive->type) { - case PRM_TYPE_FT3: - indices[indices_len++] = prm.ft3->coords[0]; - indices[indices_len++] = prm.ft3->coords[1]; - indices[indices_len++] = prm.ft3->coords[2]; - - prm.ft3->color = exhaust_plume_color; - prm.ft3++; - break; - case PRM_TYPE_GT3: - indices[indices_len++] = prm.gt3->coords[0]; - indices[indices_len++] = prm.gt3->coords[1]; - indices[indices_len++] = prm.gt3->coords[2]; - - for (int j = 0; j < 3; j++) { - prm.gt3->color[j] = exhaust_plume_color; - } - prm.gt3++; - break; - default: - die("Primitive type %x is marked as an engine primitive but is not ft3 or gt3\n", prm.primitive->type); - } - } else { - switch (prm.primitive->type) { - case PRM_TYPE_F3: prm.f3++; break; - case PRM_TYPE_F4: prm.f4++; break; - case PRM_TYPE_FT3: prm.ft3++; break; - case PRM_TYPE_FT4: prm.ft4++; break; - case PRM_TYPE_G3: prm.g3++; break; - case PRM_TYPE_G4: prm.g4++; break; - case PRM_TYPE_GT3: prm.gt3++; break; - case PRM_TYPE_GT4: prm.gt4++; break; - default: - die("Bad primitive type %x\n", prm.primitive->type); + primitive_t *prm = &self->model->primitives[i]; + if (flags_is(prm->flag, PRM_SHIP_ENGINE)) { + flags_add(prm->flag, PRM_TRANSLUCENT); + + error_if(prm->type != PRM_TYPE_TRI, "Can't happen: Expected primitive type %x, got %x", PRM_TYPE_TRI, prm->type); + + primitive_vertex_t *v = prm->u.tri.v; + indices[indices_len++] = v[0].coord; + indices[indices_len++] = v[1].coord; + indices[indices_len++] = v[2].coord; + for (int j = 0; j < 3; j++) { + v[j].color = exhaust_plume_color; } } } @@ -814,28 +787,18 @@ bool ship_intersects_ship(ship_t *self, ship_t *other) { }; - Prm poly = {.primitive = other->collision_model->primitives}; - int primitives_len = other->collision_model->primitives_len; vec3_t p1, p2, p3; // for all 4 planes of the enemy ship - for (int pi = 0; pi < primitives_len; pi++) { - int16_t *indices; - switch (poly.primitive->type) { - case PRM_TYPE_F3: - indices = poly.f3++->coords; break; - case PRM_TYPE_G3: - indices = poly.g3++->coords; break; - case PRM_TYPE_FT3: - indices = poly.ft3++->coords; break; - case PRM_TYPE_GT3: - indices = poly.gt3++->coords; break; - default: die("Can't happen?"); - } - p1 = vec3_transform(self->collision_model->vertices[indices[0]], &self->mat); - p2 = vec3_transform(self->collision_model->vertices[indices[1]], &self->mat); - p3 = vec3_transform(self->collision_model->vertices[indices[2]], &self->mat); + for (int i = 0; i < other->collision_model->primitives_len; i++) { + primitive_t *prm = &other->collision_model->primitives[i]; + + error_if(prm->type != PRM_TYPE_TRI, "Can't happen: Expected primitive type %x, got %x", PRM_TYPE_TRI, prm->type); + + p1 = vec3_transform(self->collision_model->vertices[prm->u.tri.v[0].coord], &self->mat); + p2 = vec3_transform(self->collision_model->vertices[prm->u.tri.v[1].coord], &self->mat); + p3 = vec3_transform(self->collision_model->vertices[prm->u.tri.v[2].coord], &self->mat); // Find polyGon line vectors vec3_t p1p2 = vec3_sub(p2, p1); diff --git a/src/wipeout/weapon.c b/src/wipeout/weapon.c index 26d1fe6..62af7bd 100755 --- a/src/wipeout/weapon.c +++ b/src/wipeout/weapon.c @@ -84,19 +84,19 @@ void weapons_load(void) { weapon_assets.ebolt = objects_load("wipeout/common/ebolt.prm", weapon_textures); // Invert shield polys for internal view - Prm poly = {.primitive = weapon_assets.shield_internal->primitives}; int primitives_len = weapon_assets.shield_internal->primitives_len; for (int k = 0; k < primitives_len; k++) { - switch (poly.primitive->type) { - case PRM_TYPE_G3 : - swap(poly.g3->coords[0], poly.g3->coords[2]); - poly.g3 += 1; - break; - - case PRM_TYPE_G4 : - swap(poly.g4->coords[0], poly.g4->coords[3]); - poly.g4 += 1; - break; + primitive_t *prm = &weapon_assets.shield_internal->primitives[k]; + + switch (prm->type) { + case PRM_TYPE_TRI: + swap(prm->u.tri.v[0].coord, prm->u.tri.v[0].coord); + break; + case PRM_TYPE_QUAD: + swap(prm->u.quad.v[0].coord, prm->u.quad.v[3].coord); + break; + default: + die("Can't happen: Expected primitive type %x or %x, got %x", PRM_TYPE_TRI, PRM_TYPE_QUAD, prm->type); } } @@ -345,18 +345,15 @@ void weapon_update_mine_wait_for_release(weapon_t *self) { } void weapon_update_mine_lights(weapon_t *self, int index) { - Prm prm = {.primitive = self->model->primitives}; - uint8_t r = sinf(system_cycle_time() * M_PI * 2 + index * 0.66) * 128 + 128; for (int i = 0; i < 8; i++) { - switch (prm.primitive->type) { - case PRM_TYPE_GT3: - prm.gt3->color[0] = rgba(230, 0, 0, 0xFF); - prm.gt3->color[1] = rgba(r, 0x40, 0, 0xFF); - prm.gt3->color[2] = rgba(r, 0x40, 0, 0xFF); - prm.gt3 += 1; - break; - } + primitive_t *prm = &self->model->primitives[i]; + + error_if(prm->type != PRM_TYPE_TRI, "Can't happen: Expected primitive type %x, got %x", PRM_TYPE_TRI, prm->type); + + prm->u.tri.v[0].color = rgba(230, 0, 0, 0xFF); + prm->u.tri.v[1].color = rgba(r, 0x40, 0, 0xFF); + prm->u.tri.v[2].color = rgba(r, 0x40, 0, 0xFF); } } @@ -560,32 +557,29 @@ void weapon_update_shield(weapon_t *self) { self->angle = self->owner->angle; // Animated colors. - Prm poly = {.primitive = self->model->primitives}; int primitives_len = self->model->primitives_len; uint8_t col; - int16_t *coords; const uint8_t shield_alpha = 48; float color_timer = self->timer * 0.05; for (int k = 0; k < primitives_len; k++) { - switch (poly.primitive->type) { - case PRM_TYPE_G3 : - coords = poly.g3->coords; - for (int v = 0; v < 3; v++) { - col = sinf(color_timer * coords[v]) * 127 + 128; - poly.g3->color[v] = rgba(col, col, 255, shield_alpha); - } - poly.g3 += 1; - break; - - case PRM_TYPE_G4 : - coords = poly.g4->coords; - for (int v = 0; v < 4; v++) { - col = sinf(color_timer * coords[v]) * 127 + 128; - poly.g4->color[v] = rgba(col, col, 255, shield_alpha); - } - poly.g4 += 1; - break; + primitive_t *prm = &self->model->primitives[k]; + + switch (prm->type) { + case PRM_TYPE_TRI : + for (int v = 0; v < 3; v++) { + col = sinf(color_timer * prm->u.tri.v[v].coord) * 127 + 128; + prm->u.tri.v[v].color = rgba(col, col, 255, shield_alpha); + } + break; + case PRM_TYPE_QUAD : + for (int v = 0; v < 4; v++) { + col = sinf(color_timer * prm->u.quad.v[v].coord) * 127 + 128; + prm->u.quad.v[v].color = rgba(col, col, 255, shield_alpha); + } + break; + default: + die("Can't happen: Expected primitive type %x or %x, got %x", PRM_TYPE_TRI, PRM_TYPE_QUAD, prm->type); } } }