From ae44478b30d890fe0fb04022f44d474dcdcc3f9d Mon Sep 17 00:00:00 2001 From: Lassi Pulkkinen Date: Thu, 31 Oct 2024 03:11:21 +0200 Subject: Initial commit (import old repo) --- section_geometry.ha | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 section_geometry.ha (limited to 'section_geometry.ha') diff --git a/section_geometry.ha b/section_geometry.ha new file mode 100644 index 0000000..c39780e --- /dev/null +++ b/section_geometry.ha @@ -0,0 +1,164 @@ +use comparray; + +fn section_build_geometry(pos: SectionPos) []Vertex = { + const section = getsection(pos) as *Section; + + if (section.bstates.palette_size == 1 + && section.bstates.data_constant == 0) { + return []; + }; + + const neighbors = [ + getsection(SectionPos { x = pos.x - 1, y = pos.y, z = pos.z }), + getsection(SectionPos { x = pos.x + 1, y = pos.y, z = pos.z }), + getsection(SectionPos { x = pos.x, y = pos.y - 1, z = pos.z }), + getsection(SectionPos { x = pos.x, y = pos.y + 1, z = pos.z }), + getsection(SectionPos { x = pos.x, y = pos.y, z = pos.z - 1 }), + getsection(SectionPos { x = pos.x, y = pos.y, z = pos.z + 1 }), + ]; + + let vertices: []Vertex = alloc([], 1024); + + for (let y = 0u8; y < 16; y += 1) + for (let z = 0u8; z < 16; z += 1) + for (let x = 0u8; x < 16; x += 1) { + const i = x | z << 4 | y: size << 8; + const bstate = comparray::lookup(§ion.bstates, comparray::get(§ion.bstates, i)); + + if (bstate == 0) continue; + + const render_bstate = &BSTATES_RENDER[bstate]; + for (let i = 0z; i < len(render_bstate.parts); i += 1) { + const part = &render_bstate.parts[i]; + const geom = part.model.geom as *ModelGeom; + + for (let j = 0z; j < len(geom.faces); j += 1) { + const face = &geom.faces[j]; + + if (face.cull_face != CullFace::NONE) { + let axis = 0u8; + for (true; axis += 1) { + if (part.swizzle >> axis >> axis & 3 + == face.cull_face >> 1) break; + }; + const flip = part.flags: u8 >> axis; + const sign = (face.cull_face: u8 ^ flip) & 1; + const cull_face = axis << 1 | sign; + + let neighbor = [x, y, z]; + const coord = &neighbor[axis]; + *coord += (sign << 1) - 1; + const section_ = if (*coord & 0xf0 != 0) + neighbors[cull_face] else section; + *coord &= 0x0f; + + match (section_) { + case let section_: *Section => + const k = neighbor[0] | neighbor[2] << 4 + | neighbor[1]: size << 8; + const bstate_ = comparray::lookup(§ion_.bstates, comparray::get(§ion_.bstates, k)); + if ((bstate >= 77 && bstate <= 92 || !(bstate_ >= 77 && bstate_ <= 92)) + && len((BSTATES_RENDER[bstate_].parts[0].model.geom as *ModelGeom).faces) != 0) continue; + case null => + if (axis != 1) continue; + }; + }; + + let face_vertices: [4][3]u16 = [[0...]...]; + for (let k = 0z; k < 4; k += 1) { + const vert = &face.vertices[k]; + let vx = vert[part.swizzle & 3]; + if (part.flags & BstateRenderPartFlags::FLIP_X != 0) + vx = 6144 - vx; + vx += x: u16 * 2048; + let vy = vert[part.swizzle >> 2 & 3]; + if (part.flags & BstateRenderPartFlags::FLIP_Y != 0) + vy = 6144 - vy; + vy += y: u16 * 2048; + let vz = vert[part.swizzle >> 4]; + if (part.flags & BstateRenderPartFlags::FLIP_Z != 0) + vz = 6144 - vz; + vz += z: u16 * 2048; + face_vertices[k] = [vx, vy, vz]; + }; + + let normal = [ + face.normal[part.swizzle & 3], + face.normal[part.swizzle >> 2 & 3], + face.normal[part.swizzle >> 4], + ]; + if (part.flags & BstateRenderPartFlags::FLIP_X != 0) + normal[0] = -normal[0]; + if (part.flags & BstateRenderPartFlags::FLIP_Y != 0) + normal[1] = -normal[1]; + if (part.flags & BstateRenderPartFlags::FLIP_Z != 0) + normal[2] = -normal[2]; + + const sprite = part.model.textures[face.texture]; + + const tex_left = face.texcoord[0]; + const tex_top = face.texcoord[1]; + const tex_right = face.texcoord[2]; + const tex_bottom = face.texcoord[3]; + const flags_left: VertexFlags = if (tex_left < tex_right) 0 else VertexFlags::U_EXCL; + const flags_top: VertexFlags = if (tex_top < tex_bottom) 0 else VertexFlags::V_EXCL; + const flags_right = flags_left ^ VertexFlags::U_EXCL; + const flags_bottom = flags_top ^ VertexFlags::V_EXCL; + let texcoord: [4][2]u16 = [ + [tex_left, tex_top], + [tex_left, tex_bottom], + [tex_right, tex_bottom], + [tex_right, tex_top], + ]; + let flags = [ + flags_left | flags_top, + flags_left | flags_bottom, + flags_right | flags_bottom, + flags_right | flags_top, + ]; + const mask = 1 << face.dir; + const flip_u = part.flip_u & mask != 0; + const flip_v = part.flip_v & mask != 0; + const swap_uv = part.swap_uv & mask != 0; + const tex_flipped = tex_left < tex_right + != tex_top < tex_bottom; + // flipping the texture reverses the apparent + // rotation wrt. the rotation applied to the + // texcoords, so we need to compensate. + const (flip_u, flip_v) = if (tex_flipped) + (flip_v, flip_u) else (flip_u, flip_v); + for (let k = 0u8; k < 4; k += 1) { + const uv = &texcoord[k]; + const f = &flags[k]; + if (swap_uv) { + *uv = [uv[1], uv[0]]; + const u_excl = *f & VertexFlags::U_EXCL; + const v_excl = *f & VertexFlags::V_EXCL; + *f = u_excl << 1 | v_excl >> 1; + }; + if (flip_u) { + uv[0] = 128 - uv[0]; + *f ^= VertexFlags::U_EXCL; + }; + if (flip_v) { + uv[1] = 128 - uv[1]; + *f ^= VertexFlags::V_EXCL; + }; + uv[0] = sprite.x: u16 + (sprite.width * uv[0] >> 7): u16; + uv[1] = sprite.y: u16 + (sprite.height * uv[1] >> 7): u16; + }; + + append(vertices, [ + Vertex { position = face_vertices[0], normal = normal, texcoord = texcoord[face.rotation & 3], flags = flags[face.rotation & 3] }, + Vertex { position = face_vertices[1], normal = normal, texcoord = texcoord[1 + face.rotation & 3], flags = flags[1 + face.rotation & 3] }, + Vertex { position = face_vertices[2], normal = normal, texcoord = texcoord[2 + face.rotation & 3], flags = flags[2 + face.rotation & 3] }, + Vertex { position = face_vertices[2], normal = normal, texcoord = texcoord[2 + face.rotation & 3], flags = flags[2 + face.rotation & 3] }, + Vertex { position = face_vertices[3], normal = normal, texcoord = texcoord[3 + face.rotation & 3], flags = flags[3 + face.rotation & 3] }, + Vertex { position = face_vertices[0], normal = normal, texcoord = texcoord[face.rotation & 3], flags = flags[face.rotation & 3] }, + ]...); + }; + }; + }; + + return vertices; +}; -- cgit v1.2.3