Object *objects_load(char *name, texture_list_t tl) {
uint32_t length = 0;
uint8_t *bytes = platform_load_asset(name, &length);
if (!bytes) {
die("Failed to load file %s\n", name);
}
printf("load: %s\n", name);
Object *objectList = mem_mark();
Object *prevObject = NULL;
uint32_t p = 0;
while (p < length) {
Object *object = mem_bump(sizeof(Object));
if (prevObject) {
prevObject->next = object;
}
prevObject = object;
for (int i = 0; i < 16; i++) {
object->name = get_i8(bytes, &p);
}
object->mat = mat4_identity();
object->vertices_len = get_i16(bytes, &p); p += 2;
object->vertices = NULL; get_i32(bytes, &p);
object->normals_len = get_i16(bytes, &p); p += 2;
object->normals = NULL; get_i32(bytes, &p);
object->primitives_len = get_i16(bytes, &p); p += 2;
object->primitives = NULL; get_i32(bytes, &p);
get_i32(bytes, &p);
get_i32(bytes, &p);
get_i32(bytes, &p); // Skeleton ref
object->extent = get_i32(bytes, &p);
object->flags = get_i16(bytes, &p); p += 2;
object->next = NULL; get_i32(bytes, &p);
p += 3 * 3 * 2; // relative rot matrix
p += 2; // padding
object->origin.x = get_i32(bytes, &p);
object->origin.y = get_i32(bytes, &p);
object->origin.z = get_i32(bytes, &p);
p += 3 * 3 * 2; // absolute rot matrix
p += 2; // padding
p += 3 * 4; // absolute translation matrix
p += 2; // skeleton update flag
p += 2; // padding
p += 4; // skeleton super
p += 4; // skeleton sub
p += 4; // skeleton next
object->radius = 0;
object->vertices = mem_bump(object->vertices_len * sizeof(vec3_t));
for (int i = 0; i < object->vertices_len; i++) {
object->vertices.x = get_i16(bytes, &p);
object->vertices.y = get_i16(bytes, &p);
object->vertices.z = get_i16(bytes, &p);
p += 2; // padding
if (fabsf(object->vertices.x) > object->radius) {
object->radius = fabsf(object->vertices.x);
}
if (fabsf(object->vertices.y) > object->radius) {
object->radius = fabsf(object->vertices.y);
}
if (fabsf(object->vertices.z) > object->radius) {
object->radius = fabsf(object->vertices.z);
}
}
object->normals = mem_bump(object->normals_len * sizeof(vec3_t));
for (int i = 0; i < object->normals_len; i++) {
object->normals.x = get_i16(bytes, &p);
object->normals.y = get_i16(bytes, &p);
object->normals.z = get_i16(bytes, &p);
p += 2; // padding
}
object->primitives = mem_mark();
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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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(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));
break;
case PRM_TYPE_TSPR:
case PRM_TYPE_BSPR:
prm.ptr = mem_bump(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));
break;
case PRM_TYPE_SPLINE:
prm.ptr = mem_bump(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);
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);
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);
p += 4; // padding
prm.spline->color = rgba_from_u32(get_u32(bytes, &p));
break;
case PRM_TYPE_POINT_LIGHT:
prm.ptr = mem_bump(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(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(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);
} // switch
prm.f3->type = prm_type;
prm.f3->flag = prm_flag;
} // each prim
} // each object
mem_temp_free(bytes);
return objectList;
}