108 lines
2.9 KiB
JavaScript
108 lines
2.9 KiB
JavaScript
|
|
|
||
|
|
let
|
||
|
|
model_load_container = async (path) => {
|
||
|
|
/* Parse Retarded Model Format (.rmf):
|
||
|
|
struct {
|
||
|
|
u8 num_frames;
|
||
|
|
u8 num_verts; // per frame
|
||
|
|
u8 num_indices;
|
||
|
|
struct {
|
||
|
|
u8 x, y, z;
|
||
|
|
} verts[num_frames * num_verts];
|
||
|
|
struct {
|
||
|
|
u8 a_address_inc, b_index, c_index;
|
||
|
|
} indices[num_indices];
|
||
|
|
} rmf_data;
|
||
|
|
*/
|
||
|
|
let data = new Uint8Array(await (await fetch(path)).arrayBuffer()),
|
||
|
|
models = [];
|
||
|
|
|
||
|
|
for (let i = 0; i < data.length;) {
|
||
|
|
// let model_size = num_frames * num_verts * 3 + num_indices * 3
|
||
|
|
let model_size = (data[i++] * data[i++] + data[i++]) * 3;
|
||
|
|
models.push(data.subarray(i-3, i += model_size));
|
||
|
|
}
|
||
|
|
return models;
|
||
|
|
},
|
||
|
|
|
||
|
|
model_init = (data, sx = 1, sy = 1, sz = 1) => {
|
||
|
|
// Load header, prepare buffers
|
||
|
|
let j = 0,
|
||
|
|
num_frames = data[j++],
|
||
|
|
num_vertices = data[j++],
|
||
|
|
num_indices = data[j++],
|
||
|
|
vertices = new Float32Array(num_vertices * num_frames * 3),
|
||
|
|
indices = new Uint8Array(num_indices * 3),
|
||
|
|
|
||
|
|
index_increment = 0,
|
||
|
|
offset = 2,
|
||
|
|
|
||
|
|
// Load vertices, center on origin (-15), scale, find the
|
||
|
|
// min/max x and y to compute our UV coords accordingly.
|
||
|
|
min_x = 16,
|
||
|
|
max_x = -16,
|
||
|
|
min_y = 16,
|
||
|
|
max_y = -16;
|
||
|
|
|
||
|
|
for (let i = 0; i < num_vertices * num_frames * 3; i += 3) {
|
||
|
|
vertices[i] = (data[j++] - 15) * sx;
|
||
|
|
vertices[i+1] = (data[j++] - 15) * sy;
|
||
|
|
vertices[i+2] = (data[j++] - 15) * sz;
|
||
|
|
|
||
|
|
// Find min/max only for the first frame
|
||
|
|
if (i < num_vertices * 3) {
|
||
|
|
min_x = Math.min(min_x, vertices[i]);
|
||
|
|
max_x = Math.max(max_x, vertices[i]);
|
||
|
|
min_y = Math.min(min_y, vertices[i+1]);
|
||
|
|
max_y = Math.max(max_y, vertices[i+1]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Load indices, 1x 2bit increment, 2x 7bit absolute
|
||
|
|
for (let i = 0; i < num_indices * 3; i += 3) {
|
||
|
|
index_increment += data[j++];
|
||
|
|
indices[i] = index_increment;
|
||
|
|
indices[i+1] = data[j++];
|
||
|
|
indices[i+2] = data[j++];
|
||
|
|
}
|
||
|
|
|
||
|
|
// UV coords in texture space and width/height as fraction of model size
|
||
|
|
let uf = 1 / (max_x - min_x),
|
||
|
|
u = -min_x * uf,
|
||
|
|
vf = -1 / (max_y - min_y),
|
||
|
|
v = max_y * vf;
|
||
|
|
|
||
|
|
// Compute normals for each frame and face and submit to render buffer.
|
||
|
|
// Capture the current vertex offset for the first vertex of each frame.
|
||
|
|
let frames = [];
|
||
|
|
|
||
|
|
for (let frame_index = 0; frame_index < num_frames; frame_index++) {
|
||
|
|
frames.push(r_num_verts);
|
||
|
|
|
||
|
|
let vertex_offset = frame_index * num_vertices * 3;
|
||
|
|
for (let i = 0; i < num_indices * 3; i += 3) {
|
||
|
|
|
||
|
|
let mv = [], uv = [];
|
||
|
|
for (let face_vertex = 0, o = 0; face_vertex < 3; face_vertex++) {
|
||
|
|
let idx = indices[i + face_vertex] * 3;
|
||
|
|
mv[face_vertex] = vec3(
|
||
|
|
vertices[vertex_offset + idx + 0],
|
||
|
|
vertices[vertex_offset + idx + 1],
|
||
|
|
vertices[vertex_offset + idx + 2]
|
||
|
|
);
|
||
|
|
uv[face_vertex] = {
|
||
|
|
u: vertices[idx + 0] * uf + u,
|
||
|
|
v: vertices[idx + 1] * vf + v
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
let n = vec3_face_normal(mv[2], mv[1], mv[0]);
|
||
|
|
r_push_vert(mv[2], n, uv[2].u, uv[2].v);
|
||
|
|
r_push_vert(mv[1], n, uv[1].u, uv[1].v);
|
||
|
|
r_push_vert(mv[0], n, uv[0].u, uv[0].v);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return {f: frames, nv: num_indices * 3};
|
||
|
|
}
|