UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

168 lines (131 loc) 4.88 kB
// import { assert } from "../../../../assert.js"; import { tm_face_kill } from "../tm_face_kill.js"; import { tm_kill_only_edge } from "../tm_kill_only_edge.js"; import { tm_vert_splice } from "../tm_vert_splice.js"; /** * * @param {TopoMesh} mesh * @param {TopoTriangle} face */ function cleanupDanglingEdges(face, mesh) { // find dangling edges const edges = face.edges; const edge_count = edges.length; for (let i = 0; i < edge_count; i++) { const edge = edges[i]; if (edge.faces.length === 0) { // dangling edge, remove edge.unlink(); tm_kill_only_edge(mesh, edge); //TODO consider to clean up dangling vertices as well } } } /** * * @param {TopoMesh} mesh * @param {TopoTriangle} victim_face * @param {TopoVertex} vertex_victim * @param {TopoVertex} vertex_successor */ function collapseFaceToEdge(mesh, victim_face, vertex_victim, vertex_successor) { /** * @type {TopoEdge} */ let victim_edge; /** * @type {TopoEdge} */ let successor_edge; const collapsing_face_edges = victim_face.edges; const collapsing_face_edge_0 = collapsing_face_edges[0]; const collapsing_face_edge_1 = collapsing_face_edges[1]; // classify corner edges if (collapsing_face_edge_0.v0 === vertex_victim) { victim_edge = collapsing_face_edge_0; successor_edge = collapsing_face_edge_1; } else if (collapsing_face_edge_0.v1 === vertex_victim) { victim_edge = collapsing_face_edge_0; successor_edge = collapsing_face_edge_1; } else if (collapsing_face_edge_1.v0 === vertex_victim) { victim_edge = collapsing_face_edge_1; successor_edge = collapsing_face_edge_0; } else { victim_edge = collapsing_face_edge_1; successor_edge = collapsing_face_edge_0; } victim_edge.unlink(); tm_kill_only_edge(mesh, victim_edge); // debugValidateMesh(mesh); // migrate faces const victims_faces = victim_edge.faces; const victims_face_count = victims_faces.length; for (let i = 0; i < victims_face_count; i++) { const face = victims_faces[i]; if (!face.containsEdge(successor_edge)) { successor_edge.addFace(face); face.addEdge(successor_edge); } } // debugValidateMesh(mesh); } /** * Removed edge from the mesh by replacing one of the edge vertices (victim) with the other vertex of the edge (replacement) * Patches the rest of the topology * Useful for mesh simplification * @param {TopoMesh} mesh * @param {TopoEdge} edge * @param {TopoVertex} victim * @param {TopoVertex} replacement */ export function partialEdgeCollapse(mesh, edge, victim, replacement) { // debugValidateMesh(mesh); // identify triangles attached to the edge const edge_faces = edge.faces; const edge_face_count = edge_faces.length; // unlink the edge edge.unlink(); // remove the edge tm_kill_only_edge(mesh, edge); // debugValidateMesh(mesh); for (let i = 0; i < edge_face_count; i++) { const edge_face = edge_faces[i]; // get the other two edges const remaining_edges = edge_face.edges; // remove the face tm_face_kill(mesh, edge_face); // topology_find_broken_links(mesh); // debugValidateMesh(mesh); if (remaining_edges.length === 2) { // const remaining_edge_0 = remaining_edges[0]; // const remaining_edge_1 = remaining_edges[1]; // merge the two remaining edges of the face that's being removed // remaining_edge_0.merge(remaining_edge_1); collapseFaceToEdge(mesh, edge_face, victim, replacement); // debugValidateMesh(mesh); // topology_find_broken_links(mesh); // remove absorbed edge // mesh.removeEdge(remaining_edge_1); // topology_find_broken_links(mesh); } // debugValidateMesh(mesh); // cleanupDanglingEdges(edge_face, mesh); } } /** * Removed edge from the mesh by replacing one of the edge vertices (victim) with the other vertex of the edge (replacement) * Patches the rest of the topology * Useful for mesh simplification * @param {TopoMesh} mesh * @param {TopoEdge} edge * @param {TopoVertex} victim * @param {TopoVertex} replacement */ export function collapseEdge(mesh, edge, victim, replacement) { assert.notEqual(victim, replacement, 'victim === replacement'); partialEdgeCollapse(mesh, edge, victim, replacement); // replace the victim vertex with the replacer tm_vert_splice(mesh,replacement,victim); }