BSPMesh CreateMesh(GEOMETRY_T geometry, face_id_list_t face_ids, MIPTEX_DIRECTORY_ENTRY_T miptex_entry) { var faces = geometry.faces; // get number of triangles required to build model var num_tris = 0; for (var i = 0; i < face_ids.length; ++i) { var face = faces[face_ids[i]]; num_tris += face.num_edges - 2; } var verts = new Vector3[num_tris * 3]; // 3 vertices, xyz per tri var uvs = new Vector2[num_tris * 3]; // 3 uvs, uv per tri var verts_ofs = 0; for (var i = 0; i < face_ids.length; ++i) { var face = faces[face_ids[i]]; verts_ofs = this.addFaceVerts(geometry, face, verts, uvs, verts_ofs, miptex_entry); } return(new BSPMesh(verts, uvs)); }
Hash <UInt32, face_id_list_t> getFaceIdsPerTexture(GEOMETRY_T geometry, dmodel_t model) { var texinfos = geometry.texinfos; var faces = geometry.faces; var face_id_lists = new Hash <UInt32, face_id_list_t>(); // important to note that this is a hash var start = model.face_id; var end = start + model.num_faces; for (var i = start; i < end; ++i) { var face = faces[i]; var tex_id = texinfos[face.texinfo_id].tex_id; var face_ids = face_id_lists[tex_id]; if (face_ids == null) { face_ids = new face_id_list_t(); } face_ids[face_ids.length] = i; face_id_lists[tex_id] = face_ids; } return(face_id_lists); }
BSPModel CreateModel(ref GEOMETRY_T geometry, dmodel_t model) { var face_id_lists = this.getFaceIdsPerTexture(geometry, model); var geometries = new List <BSPModelGeometry>(); var faces = new List <BSPFace>(); foreach (var i in face_id_lists.sortedKeys) { var miptex_entry = this.miptex_directory[i]; var face_ids = face_id_lists[i]; foreach (var face_id in face_ids) { faces.Add(this.faces[face_id]); } var mesh = this.CreateMesh(geometry, face_ids, miptex_entry); geometries.Add(new BSPModelGeometry(i, mesh, faces.ToArray())); faces.Clear(); } var result = new BSPModel(geometries.ToArray(), faces.ToArray()); result.origin = TransformVector(model.origin); result.boundbox = TransformBoundbox(model.bbox); return(result); }
int addFaceVerts(GEOMETRY_T geometry, dface_t face, Vector3[] verts, Vector2[] uvs, int verts_ofs, MIPTEX_DIRECTORY_ENTRY_T miptex_entry) { var edge_list = geometry.edge_list; var edges = geometry.edges; var vertices = geometry.vertices; var texinfo = geometry.texinfos[face.texinfo_id]; var tex_width = miptex_entry.width; var tex_height = miptex_entry.height; var vert_ids = new DynamicArray <int>(); var start = face.edge_id; var end = start + face.num_edges; int i; for (i = start; i < end; ++i) { var edge_id = edge_list[i]; var edge = edges[Math.Abs(edge_id)]; if (edge_id > 0) { vert_ids[vert_ids.length] = edge.v1; } else { vert_ids[vert_ids.length] = edge.v2; } } var num_tris = vert_ids.length - 2; for (i = 0; i < num_tris; ++i) { // reverse winding order to have correct normals var c = vert_ids[0]; var b = vert_ids[i + 1]; var a = vert_ids[i + 2]; int vi = (verts_ofs + i) * 3; int uvi = (verts_ofs + i) * 3; Vector3 vert = vertices[a]; verts[vi] = vert; uvs[uvi].x = (Vector3.Dot(vert, texinfo.vec_s) + texinfo.dist_s) / tex_width; uvs[uvi].y = -(Vector3.Dot(vert, texinfo.vec_t) + texinfo.dist_t) / tex_height; vert = vertices[b]; verts[vi + 1] = vert; uvs[uvi + 1].x = (Vector3.Dot(vert, texinfo.vec_s) + texinfo.dist_s) / tex_width; uvs[uvi + 1].y = -(Vector3.Dot(vert, texinfo.vec_t) + texinfo.dist_t) / tex_height; vert = vertices[c]; verts[vi + 2] = vert; uvs[uvi + 2].x = (Vector3.Dot(vert, texinfo.vec_s) + texinfo.dist_s) / tex_width; uvs[uvi + 2].y = -(Vector3.Dot(vert, texinfo.vec_t) + texinfo.dist_t) / tex_height; } return(verts_ofs + i); // next position in verts }
BSPModel[] CreateModels(GEOMETRY_T geometry) { var models = new BSPModel[geometry.models.Length]; for (var i = 0; i < geometry.models.Length; ++i) { models[i] = this.CreateModel(ref geometry, geometry.models[i]); } return(models); }
Vector3[] getVertices(GEOMETRY_T geometry, dface_t face) { // get number of triangles required to build model var num_tris = face.num_edges - 2; var verts = new Vector3[num_tris * 3]; // 3 vertices, xyz per tri this.getVertices(geometry, face, verts); return(verts); }
BSPFace[] CreateFaces(GEOMETRY_T geometry) { var faces = geometry.faces; var collisions = new BSPFace[faces.Length]; for (int i = 0; i < faces.Length; ++i) { var vertices = getVertices(geometry, faces[i]); collisions[i] = new BSPFace(i, vertices); } return(collisions); }
void getVertices(GEOMETRY_T geometry, dface_t face, Vector3[] verts) { var edge_list = geometry.edge_list; var edges = geometry.edges; var vertices = geometry.vertices; var vert_ids = new DynamicArray <int>(); var start = face.edge_id; var end = start + face.num_edges; int i; for (i = start; i < end; ++i) { var edge_id = edge_list[i]; var edge = edges[Math.Abs(edge_id)]; if (edge_id > 0) { vert_ids[vert_ids.length] = edge.v1; } else { vert_ids[vert_ids.length] = edge.v2; } } var num_tris = vert_ids.length - 2; for (i = 0; i < num_tris; ++i) { // reverse winding order to have correct normals var c = vert_ids[0]; var b = vert_ids[i + 1]; var a = vert_ids[i + 2]; int vi = i * 3; Vector3 vert = vertices[a]; verts[vi] = vert; vert = vertices[b]; verts[vi + 1] = vert; vert = vertices[c]; verts[vi + 2] = vert; } }
MDLGeometry expandGeometry(GEOMETRY_T geometry) { var triangles = geometry.triangles; var skin_verts = geometry.skin_verts; var num_tris = triangles.Length; float sw = this.header.skin_width; float sh = this.header.skin_height; // expand uvs var uvs = new Vector2[num_tris * 3]; // 3 per face, size 2 (u, v) for (var i = 0; i < num_tris; ++i) { var t = triangles[i]; var ff = t.front_facing != 0; var a = t.vert_indices[0]; var b = t.vert_indices[1]; var c = t.vert_indices[2]; var idx = i * 3; var uv = skin_verts[c]; uvs[idx + 0].x = (!ff && uv.onseam != 0) ? uv.s / sw + 0.5f : uv.s / sw; uvs[idx + 0].y = 1 - uv.t / sh; // uvs are upside down so invert uv = skin_verts[b]; uvs[idx + 1].x = (!ff && uv.onseam != 0) ? uv.s / sw + 0.5f : uv.s / sw; uvs[idx + 1].y = 1 - uv.t / sh; uv = skin_verts[a]; uvs[idx + 2].x = (!ff && uv.onseam != 0) ? uv.s / sw + 0.5f : uv.s / sw; uvs[idx + 2].y = 1 - uv.t / sh; } // expand frames var sx = this.header.scale.x; var sy = this.header.scale.y; var sz = this.header.scale.z; var ox = this.header.scale_origin.x; var oy = this.header.scale_origin.y; var oz = this.header.scale_origin.z; var frames = geometry.frames; var new_frames = new DynamicArray <MDLFrame>(); for (var j = 0; j < frames.Length; ++j) { var f = frames[j]; var verts = new Vector3[num_tris * 3]; // 3 per face, size 3 (x, y, z) for (var i = 0; i < num_tris; ++i) { var t = triangles[i]; var a = t.vert_indices[0]; var b = t.vert_indices[1]; var c = t.vert_indices[2]; var idx = i * 3; var vert = f.verts[c]; verts[idx + 0].x = vert.x * sx + ox; verts[idx + 0].y = vert.y * sy + oy; verts[idx + 0].z = vert.z * sz + oz; vert = f.verts[b]; verts[idx + 1].x = vert.x * sx + ox; verts[idx + 1].y = vert.y * sy + oy; verts[idx + 1].z = vert.z * sz + oz; vert = f.verts[a]; verts[idx + 2].x = vert.x * sx + ox; verts[idx + 2].y = vert.y * sy + oy; verts[idx + 2].z = vert.z * sz + oz; } new_frames[j] = new MDLFrame(f.name, verts); } return(new MDLGeometry(uvs, new_frames.ToArray(), geometry.frame_groups, true)); }