@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
83 lines (57 loc) • 2.72 kB
JavaScript
import { query_vertex_is_boundary } from "../query/query_vertex_is_boundary.js";
import { compute_face_normal_change_dot_product } from "./compute_face_normal_change_dot_product.js";
import { compute_edge_collapse_cost_quadratic } from "./quadratic/compute_edge_collapse_cost_quadratic.js";
/**
* Value to be used when collapse would flip normal of one or more adjacent faces
* @type {number}
*/
const INVALID_FLIP_COST = Number.MAX_VALUE;
/**
* Approximate cost of collapsing an edge, removing victim vertex from topology and merging it with the target vertex
* NOTE: adapted from THREE.js mesh simplification code
* @param {TopoVertex} victim
* @param {TopoVertex} target
* @param {TopoEdge} victim_edge
* @param {Map<number, Quadratic3>} vertex_quadratics
* @return {number}
*/
export function computeEdgeCollapseCost(victim, target, victim_edge, vertex_quadratics) {
// console.warn('+computeEdgeCollapseCost');
// if we collapse edge uv by moving u to v then how
// much different will the model change, i.e. the "error".
const edge_length = victim_edge.lengthSqr;
let curvature = 0;
let normal_cost = 0;
// find the "sides" triangles that are on the edge uv
const side_faces = victim_edge.faces;
const side_face_count = side_faces.length;
// use the triangle facing most away from the sides
// to determine our curvature term
const victim_faces = victim.faces;
const victim_face_count = victim_faces.length;
let fixed_cost = 0;
for (let i = 0; i < victim_face_count; i++) {
const face = victim_faces[i];
// check if face normal would be flipped by the operation, this is very undesirable
const face_normal_change = compute_face_normal_change_dot_product(face, victim, target);
if (face_normal_change < 0) {
// normal change beyond 90deg, increase the cost significantly
return INVALID_FLIP_COST;
}
}
const quadratic_cost = compute_edge_collapse_cost_quadratic(victim, target, target, vertex_quadratics);
if (side_face_count < 2) {
// we add some arbitrary cost for borders,
curvature = 1;
fixed_cost += 1;
}
if (query_vertex_is_boundary(victim)) {
// prefer not to erase border vertices to preserve shape
curvature += 1;
fixed_cost += 1;
}
const amt = quadratic_cost + edge_length * (curvature + normal_cost) + fixed_cost;
// console.warn(`edge_length:${edge_length}, curvature:${curvature}, normal_cost:${normal_cost}`);
// console.warn('-computeEdgeCollapseCost');
return amt;
}