UNPKG

mesh-simplifier

Version:

Collection of mesh simplification methods written in Typescript

1,031 lines (866 loc) 26.8 kB
/* Copyright (c) 2020-present NAVER Corp. name: mesh-simplifier license: MIT author: NAVER Corp. repository: https://github.com/naver/mesh-simplifier version: 1.0.1 */ import * as THREE from 'three'; /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var Vector3 = /*#__PURE__*/ function () { function Vector3(v0, v1, v2) { if (v0 === void 0) { v0 = 0; } if (v1 === void 0) { v1 = 0; } if (v2 === void 0) { v2 = 0; } this.x = v0; this.y = v1; this.z = v2; } var __proto = Vector3.prototype; Vector3.addVectors = function (v1, v2) { return new Vector3().copy(v1).add(v2); }; Vector3.subVectors = function (v1, v2) { return new Vector3().copy(v1).sub(v2); }; __proto.copy = function (other) { this.x = other.x; this.y = other.y; this.z = other.z; return this; }; __proto.add = function (other) { this.x += other.x; this.y += other.y; this.z += other.z; return this; }; __proto.sub = function (other) { this.x -= other.x; this.y -= other.y; this.z -= other.z; return this; }; __proto.dot = function (other) { var _a = this, x1 = _a.x, y1 = _a.y, z1 = _a.z; var x2 = other.x, y2 = other.y, z2 = other.z; return x1 * x2 + y1 * y2 + z1 * z2; }; __proto.cross = function (other) { var _a = this, x1 = _a.x, y1 = _a.y, z1 = _a.z; var x2 = other.x, y2 = other.y, z2 = other.z; this.x = y1 * z2 - z1 * y2; this.y = z1 * x2 - x1 * z2; this.z = x1 * y2 - y1 * x2; return this; }; __proto.normalize = function () { var length = this.length(); if (length > 0) { var invLength = 1 / length; this.x *= invLength; this.y *= invLength; this.z *= invLength; } return this; }; __proto.length = function () { var _a = this, x = _a.x, y = _a.y, z = _a.z; return Math.sqrt(x * x + y * y + z * z); }; __proto.scaleSclar = function (factor) { this.x *= factor; this.y *= factor; this.z *= factor; return this; }; return Vector3; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var Triangle = /*#__PURE__*/ function () { function Triangle(idx) { this.originalIndex = idx; this.v = [0, 0, 0]; this.err = [0, 0, 0, 0]; this.deleted = false; this.dirty = false; this.n = new Vector3(); } return Triangle; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ // Original code from // https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification/blob/master/src.gl/Simplify.h var SymmetricMatrix = /*#__PURE__*/ function () { function SymmetricMatrix(m11, m12, m13, m14, m22, m23, m24, m33, m34, m44) { if (m11 === void 0) { m11 = 0; } if (m12 === void 0) { m12 = 0; } if (m13 === void 0) { m13 = 0; } if (m14 === void 0) { m14 = 0; } if (m22 === void 0) { m22 = 0; } if (m23 === void 0) { m23 = 0; } if (m24 === void 0) { m24 = 0; } if (m33 === void 0) { m33 = 0; } if (m34 === void 0) { m34 = 0; } if (m44 === void 0) { m44 = 0; } this.m = new Array(10); this.set(m11, m12, m13, m14, m22, m23, m24, m33, m34, m44); } var __proto = SymmetricMatrix.prototype; SymmetricMatrix.makePlane = function (a, b, c, d) { return new SymmetricMatrix(a * a, a * b, a * c, a * d, b * b, b * c, b * d, c * c, c * d, d * d); }; __proto.copy = function (other) { var m = other.m; this.m = m.concat(); return this; }; __proto.set = function (m11, m12, m13, m14, m22, m23, m24, m33, m34, m44) { var m = this.m; m[0] = m11; m[1] = m12; m[2] = m13; m[3] = m14; m[4] = m22; m[5] = m23; m[6] = m24; m[7] = m33; m[8] = m34; m[9] = m44; }; __proto.det = function (a11, a12, a13, a21, a22, a23, a31, a32, a33) { var m = this.m; var det = m[a11] * m[a22] * m[a33] + m[a13] * m[a21] * m[a32] + m[a12] * m[a23] * m[a31] - m[a13] * m[a22] * m[a31] - m[a11] * m[a23] * m[a32] - m[a12] * m[a21] * m[a33]; return det; }; __proto.add = function (other) { var m = this.m; var n = other.m; this.set(m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3], m[4] + n[4], m[5] + n[5], m[6] + n[6], m[7] + n[7], m[8] + n[8], m[9] + n[9]); return this; }; return SymmetricMatrix; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var Vertex = /*#__PURE__*/ function () { function Vertex(idx) { this.originalIndex = idx; this.p = new Vector3(); this.tstart = 0; this.tcount = 0; this.q = new SymmetricMatrix(); this.border = false; } return Vertex; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var Ref = /*#__PURE__*/ function () { function Ref() { this.tid = 0; this.tvertex = 0; } return Ref; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var Face3 = /*#__PURE__*/ function () { function Face3(a, b, c) { this.a = a; this.b = b; this.c = c; } return Face3; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var Timer = /*#__PURE__*/ function () { function Timer() { this._diff = 0; this._startTime = null; } var __proto = Timer.prototype; Object.defineProperty(__proto, "diff", { /** * Time diff in miliseconds */ get: function () { return this._diff; }, enumerable: false, configurable: true }); __proto.start = function () { if (typeof process !== "undefined" && process.hrtime) { // Use high resolution timer in Node this._startTime = process.hrtime(); } else { this._startTime = Date.now(); } }; __proto.end = function () { // Not started if (this._startTime == null) return; if (typeof process !== "undefined" && process.hrtime) { // Use high resolution timer in Node var diff = process.hrtime(this._startTime); var diffInMiliSeconds = 1000 * (diff[0] + diff[1] * 1e-9); // diff[1] is in nanoseconds this._diff = diffInMiliSeconds; } else { this._diff = Date.now() - this._startTime; } this._startTime = null; }; return Timer; }(); /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license * Original code: https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification * License: MIT */ var FastQuadric = /*#__PURE__*/ function () { function FastQuadric(_a) { var _b = _a === void 0 ? {} : _a, _c = _b.targetPercentage, targetPercentage = _c === void 0 ? 0.5 : _c, _d = _b.aggressiveness, aggressiveness = _d === void 0 ? 7 : _d; this._triangles = []; this._vertices = []; this._refs = []; this.targetPercentage = targetPercentage; this.aggressiveness = aggressiveness; this._timer = new Timer(); } var __proto = FastQuadric.prototype; Object.defineProperty(__proto, "timeConsumed", { get: function () { return this._timer.diff; }, enumerable: false, configurable: true }); __proto.simplify = function (target) { var _this = this; var timer = this._timer; timer.start(); if (target.geometries) { target.geometries.forEach(function (geometry) { _this._process(geometry); }); } else { this._process(target); } timer.end(); return this; }; __proto._process = function (geometry) { this._getData(geometry); var triangles = this._triangles; var vertices = this._vertices; var refs = this._refs; var targetPercentage = this.targetPercentage; var aggressiveness = this.aggressiveness; var targetCount = this._triangles.length * targetPercentage; triangles.forEach(function (triangle) { return triangle.deleted = false; }); var deletedTriangles = 0; var deleted0 = []; var deleted1 = []; var triangleCount = triangles.length; for (var iteration = 0; iteration < 100; iteration++) { // Break when target number of triangles reached if (triangleCount - deletedTriangles <= targetCount) break; // Update mesh once in a while if (iteration % 5 === 0) { this._updateMesh(iteration); } // Clear dirty flag triangles.forEach(function (triangle) { return triangle.dirty = false; }); // // All triangles with edges below the threshold will be removed // // The following numbers works well for most models. // If it does not, try to adjust the 3 parameters // var threshold = 0.000000001 * Math.pow(iteration + 3, aggressiveness); for (var i = triangles.length - 1; i >= 0; i--) { var t = triangles[i]; if (t.err[3] > threshold || t.deleted || t.dirty) continue; for (var j = 0; j < 3; j++) { if (t.err[j] < threshold) { var i0 = t.v[j]; var i1 = t.v[(j + 1) % 3]; var v0 = vertices[i0]; var v1 = vertices[i1]; // Border check if (v0.border || v1.border) continue; // Compute vertex to collapse to var p = new Vector3(); this._calculateError(i0, i1, p); deleted0.splice(0); // normals temporarily deleted1.splice(0); // normals temporarily // Don't remove if flipped if (this._flipped(p, i1, v0, deleted0)) continue; if (this._flipped(p, i0, v1, deleted1)) continue; // Not flipped, so remove edge v0.p = p; v0.q.add(v1.q); var tstart = refs.length; deletedTriangles += this._updateTriangles(i0, v0, deleted0); deletedTriangles += this._updateTriangles(i0, v1, deleted1); var tcount = refs.length - tstart; v0.tstart = tstart; v0.tcount = tcount; break; } } // Done? if (triangleCount - deletedTriangles <= targetCount) break; } } this._compactMesh(); this._setData(geometry); }; __proto._getData = function (geometry) { var data = geometry.prepare(); this._vertices = data.vertices.map(function (v, idx) { var vertex = new Vertex(idx); vertex.p.copy(v); return vertex; }); this._triangles = data.faces.map(function (f, idx) { var triangle = new Triangle(idx); triangle.v = [f.a, f.b, f.c]; return triangle; }); this._refs = []; }; __proto._setData = function (geometry) { var triangles = this._triangles; var vertices = this._vertices.map(function (vertex) { return vertex.p; }); var faces = triangles.map(function (triangle) { var v = triangle.v; return new Face3(v[0], v[1], v[2]); }); var unculledVertices = this._vertices.map(function (v) { return v.originalIndex; }); var unculledFaces = this._triangles.map(function (f) { return f.originalIndex; }); geometry.update({ vertices: vertices, faces: faces, unculledVertices: unculledVertices, unculledFaces: unculledFaces }); }; __proto._flipped = function (p, i, v, deleted) { var triangles = this._triangles; var vertices = this._vertices; var refs = this._refs; for (var k = 0; k < v.tcount; k++) { var ref = refs[v.tstart + k]; var t = triangles[ref.tid]; if (t.deleted) continue; var s = ref.tvertex; var id1 = t.v[(s + 1) % 3]; var id2 = t.v[(s + 2) % 3]; if (id1 === i || id2 === i) { deleted[k] = true; continue; } var d1 = Vector3.subVectors(vertices[id1].p, p); var d2 = Vector3.subVectors(vertices[id2].p, p); d1.normalize(); d2.normalize(); if (Math.abs(d1.dot(d2)) > 0.999) return true; var n = new Vector3().copy(d1).cross(d2); n.normalize(); deleted[k] = false; if (n.dot(t.n) < 0.2) return true; } return false; }; __proto._updateTriangles = function (i, v, deleted) { var triangles = this._triangles; var refs = this._refs; var p = new Vector3(); var deletedCount = 0; for (var k = 0; k < v.tcount; k++) { var r = refs[v.tstart + k]; var t = triangles[r.tid]; if (t.deleted) continue; if (deleted[k]) { t.deleted = true; deletedCount++; continue; } t.v[r.tvertex] = i; t.dirty = true; t.err[0] = this._calculateError(t.v[0], t.v[1], p); t.err[1] = this._calculateError(t.v[1], t.v[2], p); t.err[2] = this._calculateError(t.v[2], t.v[0], p); t.err[3] = Math.min(t.err[0], t.err[1], t.err[2]); refs.push(r); } return deletedCount; }; __proto._updateMesh = function (iteration) { var _this = this; var vertices = this._vertices; var refs = this._refs; if (iteration > 0) { // compact triangles this._triangles = this._triangles.filter(function (triangle) { return !triangle.deleted; }); } else { // // Init Quadrics by Plane & Edge Errors // // required at the beginning ( iteration == 0 ) // recomputing during the simplification is not required, // but mostly improves the result for closed meshes // vertices.forEach(function (vertex) { return vertex.q = new SymmetricMatrix(); }); this._triangles.forEach(function (t) { var p = t.v.map(function (v) { return vertices[v].p; }); var n = Vector3.subVectors(p[1], p[0]).cross(Vector3.subVectors(p[2], p[0])).normalize(); t.n = n; var tmp = SymmetricMatrix.makePlane(n.x, n.y, n.z, -n.dot(p[0])); t.v.forEach(function (v) { return vertices[v].q.add(tmp); }); }); this._triangles.forEach(function (t) { var p = new Vector3(); t.v.forEach(function (v, i) { t.err[i] = _this._calculateError(v, t.v[(i + 1) % 3], p); }); }); } // Init Reference ID list vertices.forEach(function (vertex) { vertex.tstart = 0; vertex.tcount = 0; }); var triangles = this._triangles; triangles.forEach(function (triangle) { triangle.v.forEach(function (v) { return vertices[v].tcount++; }); }); var tstart = 0; vertices.forEach(function (v) { v.tstart = tstart; tstart += v.tcount; v.tcount = 0; }); // Write References for (var i = refs.length; i < triangles.length * 3; i++) { refs[i] = new Ref(); } triangles.forEach(function (t, i) { for (var j = 0; j < 3; j++) { var v = vertices[t.v[j]]; refs[v.tstart + v.tcount].tid = i; refs[v.tstart + v.tcount].tvertex = j; v.tcount++; } }); // Identify boundary : vertices[].border=0,1 if (iteration === 0) { vertices.forEach(function (vertex) { return vertex.border = false; }); vertices.forEach(function (v) { // clear var vcount = []; var vids = []; for (var i = 0; i < v.tcount; i++) { var k = refs[v.tstart + i].tid; var t = triangles[k]; for (var j = 0; j < 3; j++) { var id = t.v[j]; var ofs = 0; while (ofs < vcount.length) { if (vids[ofs] === id) break; ofs++; } if (ofs === vcount.length) { vcount.push(1); vids.push(id); } else { vcount[ofs]++; } } } for (var j = 0; j < vcount.length; j++) { if (vcount[j] === 1) { vertices[vids[j]].border = true; } } }); } }; // Error for one edge __proto._calculateError = function (idV1, idV2, result) { // Compute interpolated vertex var vertices = this._vertices; var v1 = vertices[idV1]; var v2 = vertices[idV2]; var q = new SymmetricMatrix().copy(v1.q).add(v2.q); var border = v1.border && v2.border; var det = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7); var error = 0; if (det !== 0 && !border) { // q_delta is invertible result.x = -1 / det * q.det(1, 2, 3, 4, 5, 6, 5, 7, 8); // vx = A41/det(q_delta) result.y = 1 / det * q.det(0, 2, 3, 1, 5, 6, 2, 7, 8); // vy = A42/det(q_delta) result.z = -1 / det * q.det(0, 1, 3, 1, 4, 6, 2, 5, 8); // vz = A43/det(q_delta) error = this._vertexError(q, result); } else { var p1 = v1.p; var p2 = v2.p; var p3 = new Vector3((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5, (p1.z + p2.z) * 0.5); var error1 = this._vertexError(q, p1); var error2 = this._vertexError(q, p2); var error3 = this._vertexError(q, p3); error = Math.min(error1, error2, error3); if (error1 === error) result.copy(p1); if (error2 === error) result.copy(p2); if (error3 === error) result.copy(p3); } return error; }; __proto._vertexError = function (q, v) { var x = v.x, y = v.y, z = v.z; var m = q.m; var err = m[0] * x * x + 2 * m[1] * x * y + 2 * m[2] * x * z + 2 * m[3] * x + m[4] * y * y + 2 * m[5] * y * z + 2 * m[6] * y + m[7] * z * z + 2 * m[8] * z + m[9]; return err; }; __proto._compactMesh = function () { this._triangles = this._triangles.filter(function (t) { return !t.deleted; }); var triangles = this._triangles; var vertices = this._vertices; vertices.forEach(function (vertex) { return vertex.tcount = 0; }); triangles.forEach(function (triangle) { triangle.v.forEach(function (v) { vertices[v].tcount = 1; }); }); var dst = 0; vertices.forEach(function (vertex) { if (vertex.tcount > 0) { vertex.tstart = dst; vertices[dst].originalIndex = vertex.originalIndex; vertices[dst].p = vertex.p; dst++; } }); triangles.forEach(function (t) { t.v.forEach(function (v, i) { t.v[i] = vertices[v].tstart; }); }); vertices.splice(dst); // resize }; return FastQuadric; }(); var getUintArrayByVertexLength = function (length) { if (length < 256) { return Uint8Array; } else if (length < 65536) { return Uint16Array; } else { return Uint32Array; } }; /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ /** * Adapter class for three.js geometry * @example * import * as THREE from "three"; * import { FastQuadric, ThreeGeometry } from "mesh-simplifier"; * * const geometry = new THREE.TorusKnotGeometry(10); * const adaptedGeometry = new ThreeGeometry(geometry); * * const simplifier = new FastQuadric(); * simplifier.simplify(adaptedGeometry); * * // Now do whatever you want with simplified geometry * const material = new THREE.MeshBasicMaterial(); * const mesh = new THREE.Mesh(adaptedGeometry.simplified, material); */ var ThreeGeometry = /*#__PURE__*/ function () { function ThreeGeometry(geometry) { this.originalGeometry = geometry; } var __proto = ThreeGeometry.prototype; __proto.prepare = function () { var _a, _b; var geometry = this.originalGeometry; var position = geometry.attributes.position; var face = geometry.index; var vertexCount = (_a = position === null || position === void 0 ? void 0 : position.count) !== null && _a !== void 0 ? _a : 0; var faceCount = ((_b = face === null || face === void 0 ? void 0 : face.count) !== null && _b !== void 0 ? _b : 0) / 3; var vertices = new Array(vertexCount); var faces = new Array(faceCount); for (var idx = 0; idx < vertexCount; idx++) { var startIdx = position.itemSize * idx; var arr = position.array; vertices[idx] = new Vector3(arr[startIdx + 0], arr[startIdx + 1], arr[startIdx + 2]); } for (var idx = 0; idx < faceCount; idx++) { var startIdx = 3 * idx; var arr = face.array; faces[idx] = new Face3(arr[startIdx + 0], arr[startIdx + 1], arr[startIdx + 2]); } return { vertices: vertices, faces: faces }; }; __proto.update = function (datas) { var vertices = datas.vertices, faces = datas.faces, unculledVertices = datas.unculledVertices; var geometry = this.originalGeometry; var hasUV = geometry.hasAttribute("uv"); if (hasUV) { var uvArray_1 = new Float32Array(2 * vertices.length); var origUV_1 = geometry.attributes.uv; unculledVertices.forEach(function (vertexIdx, idx) { var offset = idx * 2; uvArray_1[offset + 0] = origUV_1.getX(vertexIdx); uvArray_1[offset + 1] = origUV_1.getY(vertexIdx); }); geometry.setAttribute("uv", new THREE.BufferAttribute(uvArray_1, 2)); } var IndexTypedArray = getUintArrayByVertexLength(vertices.length); var vertexArray = new Float32Array(3 * vertices.length); var faceArray = new IndexTypedArray(3 * faces.length); vertices.forEach(function (vertex, idx) { var offset = idx * 3; vertexArray[offset + 0] = vertex.x; vertexArray[offset + 1] = vertex.y; vertexArray[offset + 2] = vertex.z; }); faces.forEach(function (face, idx) { var offset = idx * 3; faceArray[offset + 0] = face.a; faceArray[offset + 1] = face.b; faceArray[offset + 2] = face.c; }); var vertexBuffer = new THREE.BufferAttribute(vertexArray, 3); var faceBuffer = new THREE.BufferAttribute(faceArray, 1); geometry.setAttribute("position", vertexBuffer); geometry.setIndex(faceBuffer); geometry.computeVertexNormals(); return this; }; return ThreeGeometry; }(); var THREE_STANDARD_MAPS = ["alphaMap", "aoMap", "bumpMap", "displacementMap", "emissiveMap", "envMap", "lightMap", "map", "metalnessMap", "normalMap"]; /* * Copyright (c) 2020 NAVER Corp. * egjs projects are licensed under the MIT license */ var ThreeAdapter = /*#__PURE__*/ function () { function ThreeAdapter(original, clone) { if (clone === void 0) { clone = false; } this.object = clone ? original.clone() : original; if (clone) { this._cloneMeshes(original); } } var __proto = ThreeAdapter.prototype; Object.defineProperty(__proto, "geometries", { get: function () { var geometries = []; this.object.traverse(function (obj) { if (obj.isMesh) { var mesh = obj; var threeGeometry = new ThreeGeometry(mesh.geometry); geometries.push(threeGeometry); } }); return geometries; }, enumerable: false, configurable: true }); __proto._cloneMeshes = function (original) { var _this = this; var origMeshes = []; var clonedMeshes = []; original.traverse(function (obj) { if (obj.isMesh) origMeshes.push(obj); }); this.object.traverse(function (obj) { if (obj.isMesh) clonedMeshes.push(obj); }); clonedMeshes.forEach(function (mesh, meshIdx) { var origMesh = origMeshes[meshIdx]; mesh.geometry = mesh.geometry.clone(); mesh.material = Array.isArray(mesh.material) ? mesh.material.map(function (mat) { return _this._cloneMaterial(mat); }) : _this._cloneMaterial(mesh.material); if (mesh.isSkinnedMesh) { _this._skinnedMeshToMesh(mesh, origMesh.skeleton); } }); }; __proto._cloneMaterial = function (mat) { var clonedMat = mat.clone(); if (mat.type === "MeshStandardMaterial") { var standardMat_1 = mat; THREE_STANDARD_MAPS.forEach(function (mapName) { if (standardMat_1[mapName] == null) return; var prevMat = standardMat_1[mapName]; standardMat_1[mapName] = standardMat_1[mapName].clone(); standardMat_1[mapName].needsUpdate = true; if (mapName === "metalnessMap" && prevMat === standardMat_1.roughnessMap) { standardMat_1.roughnessMap = standardMat_1.metalnessMap; } }); } else { for (var property in clonedMat) { if (clonedMat[property] && clonedMat[property].isTexture) { clonedMat[property] = clonedMat[property].clone(); clonedMat[property].needsUpdate = true; } } } clonedMat.needsUpdate = true; return clonedMat; }; __proto._skinnedMeshToMesh = function (skinnedMesh, skeleton) { var geometry = skinnedMesh.geometry; var positions = geometry.attributes.position; var skinIndicies = geometry.attributes.skinIndex; var skinWeights = geometry.attributes.skinWeight; skinnedMesh.updateMatrixWorld(); skeleton.update(); var boneMatricies = skeleton.boneMatrices; var finalMatrix = new THREE.Matrix4(); var _loop_1 = function (posIdx) { finalMatrix.identity(); var skinned = new THREE.Vector4(); skinned.set(0, 0, 0, 0); var skinVertex = new THREE.Vector4(); skinVertex.set(positions.getX(posIdx), positions.getY(posIdx), positions.getZ(posIdx), 1).applyMatrix4(skinnedMesh.bindMatrix); var weights = [skinWeights.getX(posIdx), skinWeights.getY(posIdx), skinWeights.getZ(posIdx), skinWeights.getW(posIdx)]; var indicies = [skinIndicies.getX(posIdx), skinIndicies.getY(posIdx), skinIndicies.getZ(posIdx), skinIndicies.getW(posIdx)]; weights.forEach(function (weight, index) { var boneMatrix = new THREE.Matrix4().fromArray(boneMatricies, indicies[index] * 16).multiplyScalar(weight); skinned.add(skinVertex.clone().applyMatrix4(boneMatrix)); }); var transformed = skinned.applyMatrix4(skinnedMesh.bindMatrixInverse); positions.setXYZ(posIdx, transformed.x, transformed.y, transformed.z); }; for (var posIdx = 0; posIdx < positions.count; posIdx++) { _loop_1(posIdx); } var parent = skinnedMesh.parent; var mesh = new THREE.Mesh(skinnedMesh.geometry, skinnedMesh.material).copy(skinnedMesh); mesh.geometry.deleteAttribute("skinIndex"); mesh.geometry.deleteAttribute("skinWeight"); parent.remove(skinnedMesh); parent.add(mesh); }; return ThreeAdapter; }(); export { Face3, FastQuadric, SymmetricMatrix, ThreeAdapter, ThreeGeometry, Vector3 }; //# sourceMappingURL=mesh-simplifier.esm.js.map