Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three-stdlib /modifiers /SimplifyModifier.cjs
| ; | |
| var __defProp = Object.defineProperty; | |
| var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | |
| var __publicField = (obj, key, value) => { | |
| __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); | |
| return value; | |
| }; | |
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | |
| const THREE = require("three"); | |
| const BufferGeometryUtils = require("../utils/BufferGeometryUtils.cjs"); | |
| const cb = /* @__PURE__ */ new THREE.Vector3(); | |
| const ab = /* @__PURE__ */ new THREE.Vector3(); | |
| function pushIfUnique(array, object) { | |
| if (array.indexOf(object) === -1) | |
| array.push(object); | |
| } | |
| function removeFromArray(array, object) { | |
| const k = array.indexOf(object); | |
| if (k > -1) | |
| array.splice(k, 1); | |
| } | |
| class Vertex { | |
| constructor(v, id) { | |
| __publicField(this, "position"); | |
| __publicField(this, "id"); | |
| __publicField(this, "faces"); | |
| __publicField(this, "neighbors"); | |
| __publicField(this, "collapseCost"); | |
| __publicField(this, "collapseNeighbor"); | |
| __publicField(this, "minCost", 0); | |
| __publicField(this, "totalCost", 0); | |
| __publicField(this, "costCount", 0); | |
| this.position = v; | |
| this.id = id; | |
| this.faces = []; | |
| this.neighbors = []; | |
| this.collapseCost = 0; | |
| this.collapseNeighbor = null; | |
| } | |
| addUniqueNeighbor(vertex) { | |
| pushIfUnique(this.neighbors, vertex); | |
| } | |
| removeIfNonNeighbor(n) { | |
| const neighbors = this.neighbors; | |
| const faces = this.faces; | |
| const offset = neighbors.indexOf(n); | |
| if (offset === -1) | |
| return; | |
| for (let i = 0; i < faces.length; i++) { | |
| if (faces[i].hasVertex(n)) | |
| return; | |
| } | |
| neighbors.splice(offset, 1); | |
| } | |
| } | |
| class Triangle { | |
| constructor(v1, v2, v3, a, b, c) { | |
| __publicField(this, "a"); | |
| __publicField(this, "b"); | |
| __publicField(this, "c"); | |
| __publicField(this, "v1"); | |
| __publicField(this, "v2"); | |
| __publicField(this, "v3"); | |
| __publicField(this, "normal", new THREE.Vector3()); | |
| this.a = a; | |
| this.b = b; | |
| this.c = c; | |
| this.v1 = v1; | |
| this.v2 = v2; | |
| this.v3 = v3; | |
| this.computeNormal(); | |
| v1.faces.push(this); | |
| v1.addUniqueNeighbor(v2); | |
| v1.addUniqueNeighbor(v3); | |
| v2.faces.push(this); | |
| v2.addUniqueNeighbor(v1); | |
| v2.addUniqueNeighbor(v3); | |
| v3.faces.push(this); | |
| v3.addUniqueNeighbor(v1); | |
| v3.addUniqueNeighbor(v2); | |
| } | |
| computeNormal() { | |
| const vA = this.v1.position; | |
| const vB = this.v2.position; | |
| const vC = this.v3.position; | |
| cb.subVectors(vC, vB); | |
| ab.subVectors(vA, vB); | |
| cb.cross(ab).normalize(); | |
| this.normal.copy(cb); | |
| } | |
| hasVertex(v) { | |
| return v === this.v1 || v === this.v2 || v === this.v3; | |
| } | |
| replaceVertex(oldv, newv) { | |
| if (oldv === this.v1) | |
| this.v1 = newv; | |
| else if (oldv === this.v2) | |
| this.v2 = newv; | |
| else if (oldv === this.v3) | |
| this.v3 = newv; | |
| removeFromArray(oldv.faces, this); | |
| newv.faces.push(this); | |
| oldv.removeIfNonNeighbor(this.v1); | |
| this.v1.removeIfNonNeighbor(oldv); | |
| oldv.removeIfNonNeighbor(this.v2); | |
| this.v2.removeIfNonNeighbor(oldv); | |
| oldv.removeIfNonNeighbor(this.v3); | |
| this.v3.removeIfNonNeighbor(oldv); | |
| this.v1.addUniqueNeighbor(this.v2); | |
| this.v1.addUniqueNeighbor(this.v3); | |
| this.v2.addUniqueNeighbor(this.v1); | |
| this.v2.addUniqueNeighbor(this.v3); | |
| this.v3.addUniqueNeighbor(this.v1); | |
| this.v3.addUniqueNeighbor(this.v2); | |
| this.computeNormal(); | |
| } | |
| } | |
| class SimplifyModifier { | |
| constructor() { | |
| __publicField(this, "computeEdgeCollapseCost", (u, v) => { | |
| const edgelength = v.position.distanceTo(u.position); | |
| let curvature = 0; | |
| const sideFaces = []; | |
| let i, il = u.faces.length, face, sideFace; | |
| for (i = 0; i < il; i++) { | |
| face = u.faces[i]; | |
| if (face.hasVertex(v)) { | |
| sideFaces.push(face); | |
| } | |
| } | |
| for (i = 0; i < il; i++) { | |
| let minCurvature = 1; | |
| face = u.faces[i]; | |
| for (let j = 0; j < sideFaces.length; j++) { | |
| sideFace = sideFaces[j]; | |
| const dotProd = face.normal.dot(sideFace.normal); | |
| minCurvature = Math.min(minCurvature, (1.001 - dotProd) / 2); | |
| } | |
| curvature = Math.max(curvature, minCurvature); | |
| } | |
| const borders = 0; | |
| if (sideFaces.length < 2) { | |
| curvature = 1; | |
| } | |
| const amt = edgelength * curvature + borders; | |
| return amt; | |
| }); | |
| __publicField(this, "computeEdgeCostAtVertex", (v) => { | |
| if (v.neighbors.length === 0) { | |
| v.collapseNeighbor = null; | |
| v.collapseCost = -0.01; | |
| return; | |
| } | |
| v.collapseCost = 1e5; | |
| v.collapseNeighbor = null; | |
| for (let i = 0; i < v.neighbors.length; i++) { | |
| const collapseCost = this.computeEdgeCollapseCost(v, v.neighbors[i]); | |
| if (!v.collapseNeighbor) { | |
| v.collapseNeighbor = v.neighbors[i]; | |
| v.collapseCost = collapseCost; | |
| v.minCost = collapseCost; | |
| v.totalCost = 0; | |
| v.costCount = 0; | |
| } | |
| v.costCount++; | |
| v.totalCost += collapseCost; | |
| if (collapseCost < v.minCost) { | |
| v.collapseNeighbor = v.neighbors[i]; | |
| v.minCost = collapseCost; | |
| } | |
| } | |
| v.collapseCost = v.totalCost / v.costCount; | |
| }); | |
| __publicField(this, "removeFace", (f, faces) => { | |
| removeFromArray(faces, f); | |
| if (f.v1) | |
| removeFromArray(f.v1.faces, f); | |
| if (f.v2) | |
| removeFromArray(f.v2.faces, f); | |
| if (f.v3) | |
| removeFromArray(f.v3.faces, f); | |
| const vs = [f.v1, f.v2, f.v3]; | |
| let v1, v2; | |
| for (let i = 0; i < 3; i++) { | |
| v1 = vs[i]; | |
| v2 = vs[(i + 1) % 3]; | |
| if (!v1 || !v2) | |
| continue; | |
| v1.removeIfNonNeighbor(v2); | |
| v2.removeIfNonNeighbor(v1); | |
| } | |
| }); | |
| __publicField(this, "collapse", (vertices, faces, u, v) => { | |
| if (!v) { | |
| this.removeVertex(u, vertices); | |
| return; | |
| } | |
| let i; | |
| const tmpVertices = []; | |
| for (i = 0; i < u.neighbors.length; i++) { | |
| tmpVertices.push(u.neighbors[i]); | |
| } | |
| for (i = u.faces.length - 1; i >= 0; i--) { | |
| if (u.faces[i].hasVertex(v)) { | |
| this.removeFace(u.faces[i], faces); | |
| } | |
| } | |
| for (i = u.faces.length - 1; i >= 0; i--) { | |
| u.faces[i].replaceVertex(u, v); | |
| } | |
| this.removeVertex(u, vertices); | |
| for (i = 0; i < tmpVertices.length; i++) { | |
| this.computeEdgeCostAtVertex(tmpVertices[i]); | |
| } | |
| }); | |
| __publicField(this, "minimumCostEdge", (vertices) => { | |
| let least = vertices[0]; | |
| for (let i = 0; i < vertices.length; i++) { | |
| if (vertices[i].collapseCost < least.collapseCost) { | |
| least = vertices[i]; | |
| } | |
| } | |
| return least; | |
| }); | |
| __publicField(this, "modify", (geometry, count) => { | |
| geometry = geometry.clone(); | |
| const attributes = geometry.attributes; | |
| for (let name in attributes) { | |
| if (name !== "position") | |
| geometry.deleteAttribute(name); | |
| } | |
| geometry = BufferGeometryUtils.mergeVertices(geometry); | |
| const vertices = []; | |
| const faces = []; | |
| const positionAttribute = geometry.getAttribute("position"); | |
| for (let i = 0; i < positionAttribute.count; i++) { | |
| const v = new THREE.Vector3().fromBufferAttribute(positionAttribute, i); | |
| const vertex = new Vertex(v, i); | |
| vertices.push(vertex); | |
| } | |
| const geomIndex = geometry.getIndex(); | |
| if (geomIndex !== null) { | |
| for (let i = 0; i < geomIndex.count; i += 3) { | |
| const a = geomIndex.getX(i); | |
| const b = geomIndex.getX(i + 1); | |
| const c = geomIndex.getX(i + 2); | |
| const triangle = new Triangle(vertices[a], vertices[b], vertices[c], a, b, c); | |
| faces.push(triangle); | |
| } | |
| } else { | |
| for (let i = 0; i < positionAttribute.count; i += 3) { | |
| const a = i; | |
| const b = i + 1; | |
| const c = i + 2; | |
| const triangle = new Triangle(vertices[a], vertices[b], vertices[c], a, b, c); | |
| faces.push(triangle); | |
| } | |
| } | |
| for (let i = 0, il = vertices.length; i < il; i++) { | |
| this.computeEdgeCostAtVertex(vertices[i]); | |
| } | |
| let nextVertex; | |
| let z = count; | |
| while (z--) { | |
| nextVertex = this.minimumCostEdge(vertices); | |
| if (!nextVertex) { | |
| console.log("THREE.SimplifyModifier: No next vertex"); | |
| break; | |
| } else { | |
| this.collapse(vertices, faces, nextVertex, nextVertex.collapseNeighbor); | |
| } | |
| } | |
| const simplifiedGeometry = new THREE.BufferGeometry(); | |
| const position = []; | |
| let index = []; | |
| for (let i = 0; i < vertices.length; i++) { | |
| const vertex = vertices[i].position; | |
| position.push(vertex.x, vertex.y, vertex.z); | |
| } | |
| for (let i = 0; i < faces.length; i++) { | |
| const face = faces[i]; | |
| const a = vertices.indexOf(face.v1); | |
| const b = vertices.indexOf(face.v2); | |
| const c = vertices.indexOf(face.v3); | |
| index.push(a, b, c); | |
| } | |
| simplifiedGeometry.setAttribute("position", new THREE.Float32BufferAttribute(position, 3)); | |
| simplifiedGeometry.setIndex(index); | |
| return simplifiedGeometry; | |
| }); | |
| } | |
| removeVertex(v, vertices) { | |
| console.assert(v.faces.length === 0); | |
| while (v.neighbors.length) { | |
| const n = v.neighbors.pop(); | |
| removeFromArray(n.neighbors, v); | |
| } | |
| removeFromArray(vertices, v); | |
| } | |
| } | |
| exports.SimplifyModifier = SimplifyModifier; | |
| //# sourceMappingURL=SimplifyModifier.cjs.map | |
Xet Storage Details
- Size:
- 9.66 kB
- Xet hash:
- e92669016c9eed1e5ad5cf83c4cbddbef5c7bb0c4922c009e9b19c1d13aee74b
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.