Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

optimesh

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

optimesh - npm Package Compare versions

Comparing version 1.0.23 to 1.0.24

4

package.json
{
"name": "optimesh",
"version": "1.0.23",
"version": "1.0.24",
"description": "OptiMesh reduces meshes resolution to optimize performance, memory usage and download size",
"cdn": "https://cdn.jsdelivr.net/npm/optimesh@1.0.23/build/main.js",
"cdn": "https://cdn.jsdelivr.net/npm/optimesh@1.0.24/build/main.js",
"main": "build/main.js",

@@ -7,0 +7,0 @@ "jsnext:main": "build/main.module.js",

@@ -14,4 +14,4 @@ import commonjs from 'rollup-plugin-commonjs';

indent: '\t',
banner: 'var dvlpThree = dvlpThree || THREE;',
external: ['dvlp-three', 'dvlpThree', 'THREE']
banner: 'var dvlpThree = (typeof dvlpThree !== \'undefined\' && dvlpThree) || (typeof THREE !== \'undefined\' && THREE);',
external: ['dvlp-three']
},

@@ -22,4 +22,4 @@ {

indent: '\t',
banner: 'var dvlpThree = dvlpThree || THREE;',
external: ['dvlp-three', 'dvlpThree', 'THREE']
banner: 'var dvlpThree = (typeof dvlpThree !== \'undefined\' && dvlpThree) || (typeof THREE !== \'undefined\' && THREE);',
external: ['dvlp-three']
}

@@ -26,0 +26,0 @@ ],

@@ -1,9 +0,10 @@

import { addToSBWithOversize, emptyOversizedContainer, emptyOversizedContainerIndex, removeFieldFromSBWithOversize, zeroFill } from './BufferArrayManager';
import { emptyOversizedContainer, emptyOversizedContainerIndex, zeroFill } from './BufferArrayManager';
import * as CostWorker from './Worker/simplify.worker.js';
import { getIndexedPositions } from './Utils';
const {
BufferGeometry,
BufferAttribute,
Vector3
} = dvlpThree;
import { Vector2, Vector3, BufferAttribute, BufferGeometry } from 'dvlp-three';
// const {
// BufferGeometry,
// BufferAttribute,
// Vector2, Vector3
// } = dvlpThree;
export class WebWorker {

@@ -361,2 +362,32 @@ constructor(worker) {

// borrowed from geometry
var cb = new Vector3(),
ab = new Vector3();
var v1Temp = new Vector3(),
v2Temp = new Vector3();
var v2Tmp = new Vector2();
function computeFaceNormal(faceId, facesView, verticesView) {
getVertexOnFaceId(faceId, facesView, verticesView, 1, v1Temp);
getVertexOnFaceId(faceId, facesView, verticesView, 2, v2Temp);
cb.subVectors(v2Temp, v1Temp);
getVertexOnFaceId(faceId, facesView, verticesView, 0, v2Temp);
ab.subVectors(v2Temp, v1Temp);
cb.cross(ab);
cb.normalize();
// do not pass around, this will mutate
return cb;
}
function getVertexOnFaceId(faceId, facesView, verticesView, index, target) {
const vertexId = facesView[faceId * 3 + index];
target.set(
verticesView[vertexId * 3],
verticesView[vertexId * 3 + 1],
verticesView[vertexId * 3 + 2]
);
}
function loadGeometry(dataArrays, geometry) {

@@ -415,877 +446,2 @@ const {

function pushIfUnique(array, object) {
if (array.indexOf(object) === -1) array.push(object);
}
function removeFromArray(array, object) {
var k = array.indexOf(object);
if (k > -1) array.splice(k, 1);
}
function getVertexOnFaceId(faceId, facesView, verticesView, index, target) {
const vertexId = facesView[faceId * 3 + index];
target.set(
verticesView[vertexId * 3],
verticesView[vertexId * 3 + 1],
verticesView[vertexId * 3 + 2]
);
}
// borrowed from geometry
var cb = new Vector3(),
ab = new Vector3();
var v1Temp = new Vector3(),
v2Temp = new Vector3();
function computeFaceNormal(faceId, facesView, verticesView) {
getVertexOnFaceId(faceId, facesView, verticesView, 1, v1Temp);
getVertexOnFaceId(faceId, facesView, verticesView, 2, v2Temp);
cb.subVectors(v2Temp, v1Temp);
getVertexOnFaceId(faceId, facesView, verticesView, 0, v2Temp);
ab.subVectors(v2Temp, v1Temp);
cb.cross(ab);
cb.normalize();
// do not pass around, this will mutate
return cb;
}
function replaceVertex(
faceId,
oldvId,
newvId,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
) {
// replace correct vertex in face index
facesView[
faceId * 3 + getVertexIndexOnFaceId(faceId, oldvId, facesView)
] = newvId;
removeFaceFromVertex(oldvId, faceId, vertexFacesView, specialFaceCases);
setVertexFaceAtIndex(newvId, faceId, vertexFacesView, specialFaceCases);
const v1 = facesView[faceId * 3];
const v2 = facesView[faceId * 3 + 1];
const v3 = facesView[faceId * 3 + 2];
removeVertexIfNonNeighbor(
oldvId,
v1,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
);
removeVertexIfNonNeighbor(
v1,
oldvId,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
);
removeVertexIfNonNeighbor(
oldvId,
v2,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
);
removeVertexIfNonNeighbor(
v2,
oldvId,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
);
removeVertexIfNonNeighbor(
oldvId,
v3,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
);
removeVertexIfNonNeighbor(
v3,
oldvId,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
);
setVertexNeighboursAtIndex(v1, v2, vertexNeighboursView, specialCases);
setVertexNeighboursAtIndex(v1, v3, vertexNeighboursView, specialCases);
setVertexNeighboursAtIndex(v2, v1, vertexNeighboursView, specialCases);
setVertexNeighboursAtIndex(v2, v3, vertexNeighboursView, specialCases);
setVertexNeighboursAtIndex(v3, v1, vertexNeighboursView, specialCases);
setVertexNeighboursAtIndex(v3, v2, vertexNeighboursView, specialCases);
// computeNormal();
}
function getVertexNeighbours(vertexId, dataArrayViews, target) {
const neighbors = target || [];
let count = 0;
for (var i = 0; i < dataArrayViews.facesView.length; i++) {
if (dataArrayViews.facesView[i] === vertexId) {
const faceVertexIndex = i % 3;
const faceId = i - faceVertexIndex;
for (var j = 0; j < 3; j++) {
if (faceVertexIndex === j) continue;
const vertexId = dataArrayViews.facesView[faceId];
if (neighbors.indexOf(vertexId) === -1) {
// neighbors.push(vertexId);
count++;
target[vertexId * FIELDS_NO] = count;
target[vertexId * FIELDS_NO + count] = vertexId;
}
}
}
}
return neighbors;
}
function removeVertexFromNeighbour(
atIndex,
neighbourIndex,
target,
specialCases
) {
removeFieldFromSBWithOversize(atIndex, neighbourIndex, target, specialCases);
removeFieldFromSBWithOversize(neighbourIndex, atIndex, target, specialCases);
}
function removeFromNeighboursIndex(atIndex, target, specialCases) {
const index = atIndex * FIELDS_NO;
let count = target[index];
for (var i = 0; i < count && i < FIELDS_NO - 1; i++) {
const neighbourId = target[index + i + 1];
target[index + i + 1] = 0;
removeFieldFromSBWithOversize(neighbourId, atIndex, target, specialCases);
}
if (count > FIELDS_NO - 1) {
specialCases[index].forEach(neighbourId =>
removeFieldFromSBWithOversize(neighbourId, atIndex, target, specialCases)
);
}
target[index] = 0;
specialCases[index] = [];
return;
}
function removeFaceFromVertex(
vertexId,
faceId,
vertexFacesView,
specialFaceCases
) {
return removeFieldFromSBWithOversize(
vertexId,
faceId,
vertexFacesView,
specialFaceCases
);
}
function removeVertexIfNonNeighbor(
vertexId,
neighbourId,
facesView,
vertexFacesView,
vertexNeighboursView,
specialCases,
specialFaceCases,
dataArrayViews
) {
// location both for facesView and vertexNeighboursView
const locationIndex = vertexId * FIELDS_NO;
const count = vertexFacesView[locationIndex];
for (var i = 0; i < count; i++) {
const faceId = getFaceIdByVertexAndIndex(vertexId, i, dataArrayViews);
if (faceIdHasVertexId(faceId, neighbourId, facesView)) return;
}
removeVertexFromNeighbour(
vertexId,
neighbourId,
vertexNeighboursView,
specialCases
);
}
function setVertexNeighboursAtIndex(
atIndex,
neighbourIndex,
target,
specialCases,
specialCasesIndex
) {
addToSBWithOversize(
atIndex,
neighbourIndex,
target,
specialCases,
specialCasesIndex
);
}
function setVertexFaceAtIndex(
atIndex,
faceIndex,
target,
specialFaceCases,
specialFaceCasesIndex
) {
addToSBWithOversize(
atIndex,
faceIndex,
target,
specialFaceCases,
specialFaceCasesIndex
);
}
function buildVertexNeighboursIndex(
facesView,
target,
vertexFacesView,
specialCases,
specialCasesIndex,
specialFaceCases,
specialFaceCasesIndex,
from,
to
) {
// each face takes 3 fields a. b. c vertices ids
for (var i = from; i < to; i += 3) {
const faceId = i / 3;
setVertexNeighboursAtIndex(
facesView[i],
facesView[i + 1],
target,
specialCases,
specialCasesIndex
);
setVertexNeighboursAtIndex(
facesView[i],
facesView[i + 2],
target,
specialCases,
specialCasesIndex
);
setVertexNeighboursAtIndex(
facesView[i + 1],
facesView[i],
target,
specialCases,
specialCasesIndex
);
setVertexNeighboursAtIndex(
facesView[i + 1],
facesView[i + 2],
target,
specialCases,
specialCasesIndex
);
setVertexNeighboursAtIndex(
facesView[i + 2],
facesView[i],
target,
specialCases,
specialCasesIndex
);
setVertexNeighboursAtIndex(
facesView[i + 2],
facesView[i + 1],
target,
specialCases,
specialCasesIndex
);
setVertexFaceAtIndex(
facesView[i],
faceId,
vertexFacesView,
specialFaceCases,
specialFaceCasesIndex
);
setVertexFaceAtIndex(
facesView[i + 1],
faceId,
vertexFacesView,
specialFaceCases,
specialFaceCasesIndex
);
setVertexFaceAtIndex(
facesView[i + 2],
faceId,
vertexFacesView,
specialFaceCases,
specialFaceCasesIndex
);
}
}
export function computeLeastCosts(dataArrayViews, fromIndex, toIndex) {
// compute all edge collapse costs
for (let i = fromIndex; i < toIndex; i++) {
computeEdgeCostAtVertex(i, dataArrayViews);
}
buildFullIndex(
dataArrayViews.costStore,
dataArrayViews.collapseQueue,
fromIndex,
toIndex
);
}
export function computeEdgeCostAtVertex(vId, dataArrayViews) {
// compute the edge collapse cost for all edges that start
// from vertex v. Since we are only interested in reducing
// the object by selecting the min cost edge at each step, we
// only cache the cost of the least cost edge at this vertex
// (in member variable collapse) as well as the value of the
// cost (in member variable collapseCost).
const neighboursView = dataArrayViews.vertexNeighboursView;
const count = neighboursView[vId * FIELDS_NO];
if (count === 0) {
// collapse if no neighbors.
dataArrayViews.neighbourCollapse[vId] = -1;
dataArrayViews.costStore[vId] = 0;
return;
}
dataArrayViews.costStore[vId] = 100000;
dataArrayViews.neighbourCollapse[vId] = -1;
// search all neighboring edges for 'least cost' edge
for (var i = 0; i < count; i++) {
const nextNeighbourId = getVertexNeighbourByIndex(vId, i, dataArrayViews);
var collapseCost = tryComputeEdgeCollapseCost(
vId,
nextNeighbourId,
dataArrayViews
);
if (dataArrayViews.neighbourCollapse[vId] === -1) {
dataArrayViews.neighbourCollapse[vId] = nextNeighbourId;
dataArrayViews.costStore[vId] = collapseCost;
dataArrayViews.costMinView[vId] = collapseCost;
dataArrayViews.costTotalView[vId] = 0;
dataArrayViews.costCountView[vId] = 0;
}
dataArrayViews.costCountView[vId]++;
dataArrayViews.costTotalView[vId] += collapseCost;
if (collapseCost < dataArrayViews.costMinView[vId]) {
dataArrayViews.neighbourCollapse[vId] = nextNeighbourId;
dataArrayViews.costMinView[vId] = collapseCost;
}
}
const cost =
dataArrayViews.costTotalView[vId] / dataArrayViews.costCountView[vId];
// we average the cost of collapsing at this vertex
dataArrayViews.costStore[vId] = cost;
}
function faceIdHasVertexId(faceId, vertexId, facesView) {
if (facesView[faceId * 3] === vertexId) return true;
if (facesView[faceId * 3 + 1] === vertexId) return true;
if (facesView[faceId * 3 + 2] === vertexId) return true;
return false;
}
const posA = new Vector3();
const posB = new Vector3();
function tryComputeEdgeCollapseCost(uId, vId, dataArrayViews) {
try {
return computeEdgeCollapseCost(uId, vId, dataArrayViews);
} catch (e) {
console.log(
'Vertex neighbourhood data overwritten by another thread. Retrying'
);
return tryComputeEdgeCollapseCost(uId, vId, dataArrayViews);
}
}
function computeEdgeCollapseCost(uId, vId, dataArrayViews) {
// if we collapse edge uv by moving u to v then how
// much different will the model change, i.e. the 'error'.
posA.set(
dataArrayViews.verticesView[vId * 3],
dataArrayViews.verticesView[vId * 3 + 1],
dataArrayViews.verticesView[vId * 3 + 2]
);
posB.set(
dataArrayViews.verticesView[uId * 3],
dataArrayViews.verticesView[uId * 3 + 1],
dataArrayViews.verticesView[uId * 3 + 2]
);
var edgelengthSquared = posA.distanceToSquared(posB);
var curvature = 0;
var sideFaces = [];
var vertexFaceCount = dataArrayViews.vertexFacesView[uId * FIELDS_NO];
var i,
il = vertexFaceCount,
face,
sideFace;
// find the 'sides' triangles that are on the edge uv
for (i = 0; i < il; i++) {
var faceId = getFaceIdByVertexAndIndex(uId, i, dataArrayViews);
if (faceIdHasVertexId(faceId, vId, dataArrayViews.facesView)) {
sideFaces.push(faceId);
}
}
var faceNormal = new Vector3();
var sideFaceNormal = new Vector3();
// use the triangle facing most away from the sides
// to determine our curvature term
for (i = 0; i < il; i++) {
var minCurvature = 1;
var faceId = getFaceIdByVertexAndIndex(uId, i, dataArrayViews);
for (var j = 0; j < sideFaces.length; j++) {
var sideFaceId = sideFaces[j];
sideFaceNormal.set(
dataArrayViews.faceNormalView[sideFaceId * 3],
dataArrayViews.faceNormalView[sideFaceId * 3 + 1],
dataArrayViews.faceNormalView[sideFaceId * 3 + 2]
);
faceNormal.set(
dataArrayViews.faceNormalView[faceId * 3],
dataArrayViews.faceNormalView[faceId * 3 + 1],
dataArrayViews.faceNormalView[faceId * 3 + 2]
);
// use dot product of face normals.
var dotProd = faceNormal.dot(sideFaceNormal);
minCurvature = Math.min(minCurvature, (1.001 - dotProd) * 0.5);
}
curvature = Math.max(curvature, minCurvature);
}
// crude approach in attempt to preserve borders
// though it seems not to be totally correct
var borders = 0;
if (sideFaces.length < 2) {
// we add some arbitrary cost for borders,
//borders += 1;
curvature += 10;
}
var costUV = computeUVsCost(uId, vId, dataArrayViews);
var amt =
edgelengthSquared + // edge length should take into account model size
curvature * curvature +
borders * borders +
costUV * costUV;
return amt;
}
function getFromBigData(
parentId,
childId,
storage,
oversizeStorage,
oversizeStorageIndex
) {
// childId is 0 indexed!
const childIndex = childId + 1;
const index = parentId * FIELDS_NO + childIndex;
if (childIndex <= FIELDS_NO - 1) {
return storage[index];
} else {
const index = oversizeStorageIndex[parentId];
const offset = index * FIELDS_OVERSIZE;
return oversizeStorage[offset + childIndex];
}
}
function getVertexNeighbourByIndex(vId, neighbourIndex, dataArrayViews) {
return getFromBigData(
vId,
neighbourIndex,
dataArrayViews.vertexNeighboursView,
dataArrayViews.specialCases,
dataArrayViews.specialCasesIndex
);
}
function getFaceIdByVertexAndIndex(vId, i, dataArrayViews) {
return getFromBigData(
vId,
i,
dataArrayViews.vertexFacesView,
dataArrayViews.specialFaceCases,
dataArrayViews.specialFaceCasesIndex
);
}
// check if there are multiple texture coordinates at U and V vertices(finding texture borders)
function computeUVsCost(uId, vId, dataArrayViews) {
// if (!u.faces[0].faceVertexUvs || !u.faces[0].faceVertexUvs) return 0;
// if (!v.faces[0].faceVertexUvs || !v.faces[0].faceVertexUvs) return 0;
var UVsAroundVertex = [];
var UVcost = 0;
// uncomment when ready
let oversize = false;
let facesCount = dataArrayViews.vertexFacesView[vId * FIELDS_NO];
if (facesCount > FIELDS_NO - 1) {
facesCount = FIELDS_NO - 1;
oversize = true;
}
for (var i = facesCount - 1; i >= 0; i--) {
var fid = getFaceIdByVertexAndIndex(vId, i, dataArrayViews);
if (faceIdHasVertexId(fid, uId, dataArrayViews.facesView)) {
UVsAroundVertex.push(getUVsOnVertexId(fid, vId, dataArrayViews));
}
}
if (oversize) {
dataArrayViews.specialFaceCases[vId * FIELDS_NO].forEach(fid => {
if (faceIdHasVertexId(fid, uId, dataArrayViews.facesView)) {
UVsAroundVertex.push(getUVsOnVertexId(fid, vId, dataArrayViews));
}
});
}
UVsAroundVertex.reduce((prev, uv) => {
if (prev.x && (prev.x !== uv.x || prev.y !== uv.y)) {
UVcost += 1;
}
return uv;
}, {});
UVsAroundVertex.length = 0;
const facesCount2 = dataArrayViews.vertexFacesView[uId * FIELDS_NO];
// check if all coordinates around U have the same value
for (i = facesCount2 - 1; i >= 0; i--) {
let fid2 = getFaceIdByVertexAndIndex(uId, i, dataArrayViews);
if (fid2 === undefined) {
debugger;
fid2 = getFaceIdByVertexAndIndex(uId, i, dataArrayViews);
}
if (faceIdHasVertexId(fid2, vId, dataArrayViews.facesView))
UVsAroundVertex.push(getUVsOnVertexId(fid2, uId, dataArrayViews));
}
UVsAroundVertex.reduce((prev, uv) => {
if (prev.x && (prev.x !== uv.x || prev.y !== uv.y)) {
UVcost += 1;
}
return uv;
}, {});
return UVcost;
}
function removeVertex(vId, dataArrayViews) {
// console.assert(v.faces.length === 0);
removeFromNeighboursIndex(
vId,
dataArrayViews.vertexNeighboursView,
dataArrayViews.specialCases
);
}
function removeFace(fid, dataArrayViews) {
const v1 = dataArrayViews.facesView[fid * 3];
const v2 = dataArrayViews.facesView[fid * 3 + 1];
const v3 = dataArrayViews.facesView[fid * 3 + 2];
dataArrayViews.facesView[fid * 3] = -1;
dataArrayViews.facesView[fid * 3 + 1] = -1;
dataArrayViews.facesView[fid * 3 + 2] = -1;
// if (f.v1) removeFromArray(f.v1.faces, f);
// if (f.v2) removeFromArray(f.v2.faces, f);
// if (f.v3) removeFromArray(f.v3.faces, f);
removeFaceFromVertex(
v1,
fid,
dataArrayViews.vertexFacesView,
dataArrayViews.specialFaceCases
);
removeFaceFromVertex(
v2,
fid,
dataArrayViews.vertexFacesView,
dataArrayViews.specialFaceCases
);
removeFaceFromVertex(
v3,
fid,
dataArrayViews.vertexFacesView,
dataArrayViews.specialFaceCases
);
// TODO optimize this!
var vs = [v1, v2, v3];
var v1a, v2a;
for (var i = 0; i < 3; i++) {
v1a = vs[i];
v2a = vs[(i + 1) % 3];
if ((!v1a && v1a !== 0) || !v2a !== 0) continue;
// v1.removeIfNonNeighbor(v2, dataArrayViews.facesView);
// v2.removeIfNonNeighbor(v1, dataArrayViews.facesView);
removeVertexIfNonNeighbor(
v1a,
v2a,
dataArrayViews.facesView,
dataArrayViews.vertexFacesView,
dataArrayViews.vertexNeighboursView,
dataArrayViews.specialCases,
dataArrayViews.specialFaceCases,
dataArrayViews
);
removeVertexIfNonNeighbor(
v2a,
v1a,
dataArrayViews.facesView,
dataArrayViews.vertexFacesView,
dataArrayViews.vertexNeighboursView,
dataArrayViews.specialCases,
dataArrayViews.specialFaceCases,
dataArrayViews
);
}
}
var moveToThisNormalValues = [new Vector3(), new Vector3(), new Vector3()];
function collapse(uId, vId, preserveTexture, dataArrayViews) {
if (vId === null) {
// u is a vertex all by itself so just delete it..
removeVertex(uId, dataArrayViews);
return true;
}
const neighboursView = dataArrayViews.vertexNeighboursView;
const neighboursCountV = neighboursView[vId * FIELDS_NO];
const neighboursCountU = neighboursView[uId * FIELDS_NO];
var i;
var tmpVertices = [];
for (i = 0; i < neighboursCountU; i++) {
pushIfUnique(
tmpVertices,
getVertexNeighbourByIndex(uId, i, dataArrayViews)
);
}
for (i = 0; i < neighboursCountV; i++) {
pushIfUnique(
tmpVertices,
getVertexNeighbourByIndex(vId, i, dataArrayViews)
);
}
let UVx = 0;
let UVy = 0;
let facesCount = dataArrayViews.vertexFacesView[uId * FIELDS_NO];
// delete triangles on edge uv:
for (i = facesCount - 1; i >= 0; i--) {
const faceId = getFaceIdByVertexAndIndex(uId, i, dataArrayViews);
if (faceIdHasVertexId(faceId, vId, dataArrayViews.facesView)) {
if (preserveTexture) {
// get uvs on remaining vertex
UVx =
dataArrayViews.facesUVsView[
faceId * 6 +
getVertexIndexOnFaceId(faceId, vId, dataArrayViews.facesView) * 2
];
UVy =
dataArrayViews.facesUVsView[
faceId * 6 +
getVertexIndexOnFaceId(faceId, vId, dataArrayViews.facesView) *
2 +
1
];
}
// if (u.faces[i].normal) {
var middleGroundNormal = getPointInBetweenByPerc(
getNormalsOnVertexId(faceId, uId, dataArrayViews),
getNormalsOnVertexId(faceId, vId, dataArrayViews),
0.5
);
moveToThisNormalValues[0] = middleGroundNormal;
// }
removeFace(faceId, dataArrayViews);
}
}
facesCount = dataArrayViews.vertexFacesView[uId * FIELDS_NO];
if (preserveTexture && facesCount) {
for (i = facesCount - 1; i >= 0; i--) {
var faceId = getFaceIdByVertexAndIndex(uId, i, dataArrayViews);
dataArrayViews.facesUVsView[
faceId * 6 +
getVertexIndexOnFaceId(faceId, uId, dataArrayViews.facesView) * 2
] = UVx;
dataArrayViews.facesUVsView[
faceId * 6 +
getVertexIndexOnFaceId(faceId, uId, dataArrayViews.facesView) * 2 +
1
] = UVy;
//var faceVerticeUVsgetNormalsOnVertex(face, u);
// var faceVerticeNormals = getNormalsOnVertexId(face, u);
// faceVerticeNormals.copy(moveToThisNormalValues[0]);
dataArrayViews.faceNormalsView[
faceId * 9 +
getVertexIndexOnFaceId(faceId, uId, dataArrayViews.facesView) * 3
] = moveToThisNormalValues[0].x;
dataArrayViews.faceNormalsView[
faceId * 9 +
getVertexIndexOnFaceId(faceId, uId, dataArrayViews.facesView) * 3 +
1
] = moveToThisNormalValues[0].y;
dataArrayViews.faceNormalsView[
faceId * 9 +
getVertexIndexOnFaceId(faceId, uId, dataArrayViews.facesView) * 3 +
2
] = moveToThisNormalValues[0].z;
}
}
// update remaining triangles to have v instead of u
for (i = facesCount - 1; i >= 0; i--) {
replaceVertex(
getFaceIdByVertexAndIndex(uId, i, dataArrayViews),
uId,
vId,
dataArrayViews.facesView,
dataArrayViews.vertexFacesView,
dataArrayViews.vertexNeighboursView,
dataArrayViews.specialCases,
dataArrayViews.specialFaceCases,
dataArrayViews
);
}
removeVertex(uId, dataArrayViews);
// recompute the edge collapse costs in neighborhood
for (i = 0; i < tmpVertices.length; i++) {
// uncomment when ready
computeEdgeCostAtVertex(tmpVertices[i], dataArrayViews);
}
return true;
}
function getPointInBetweenByPerc(pointA, pointB, percentage) {
var dir = new Vector3().copy(pointB).sub(pointA);
var len = dir.length();
dir = dir.normalize().multiplyScalar(len * percentage);
return dir.add(pointA);
}
function getUVsOnVertexId(faceId, vertexId, dataArrayViews) {
return {
x:
dataArrayViews.facesUVsView[
faceId * 6 +
getVertexIndexOnFaceId(faceId, vertexId, dataArrayViews.facesView) * 2
],
y:
dataArrayViews.facesUVsView[
faceId * 6 +
getVertexIndexOnFaceId(faceId, vertexId, dataArrayViews.facesView) *
2 +
1
]
};
}
function getNormalsOnVertexId(faceId, vertexId, dataArrayViews) {
//return face.vertexNormals[getVertexIndexOnFaceId(faceId, vertexId)];
return {
x:
dataArrayViews.faceNormalsView[
faceId * 9 +
getVertexIndexOnFaceId(faceId, vertexId, dataArrayViews.facesView) * 3
],
y:
dataArrayViews.faceNormalsView[
faceId * 9 +
getVertexIndexOnFaceId(faceId, vertexId, dataArrayViews.facesView) *
3 +
1
],
z:
dataArrayViews.faceNormalsView[
faceId * 9 +
getVertexIndexOnFaceId(faceId, vertexId, dataArrayViews.facesView) *
3 +
2
]
};
}
function getVertexIndexOnFaceId(faceId, vertexId, facesView) {
if (vertexId === facesView[faceId * 3]) return 0;
if (vertexId === facesView[faceId * 3 + 1]) return 1;
if (vertexId === facesView[faceId * 3 + 2]) return 2;
throw new Error('Vertex not found ' + vertexId);
}
function requestFreeWorkers(workers, verticesLength, onWorkersReady) {

@@ -1695,2 +851,3 @@ // at least 2000 vertices per worker, limit amount of workers

// TODO: import cost worker code locally
// console.timeEnd('Mesh simplification');

@@ -1791,209 +948,2 @@ // if (typeof SharedArrayBuffer === 'undefined') {

function collapseLeastCostEdges(
vertices,
faces,
percentage,
dataArrayViews,
neighbourCollapse,
preserveTexture,
from,
to
) {
// 1. get available workers (with mesh loaded)
// 2. split the work between them up to vertices.length
// 3. send a task computeEdgesCost(fromIndex, toIndex)
// 4. when all return (with correct mesh id) proceed with collapsing
const originalLength = to - from; // vertices.length;
var nextVertexId;
var howManyToRemove = Math.round(originalLength * percentage);
var z = howManyToRemove;
var skip = 0;
// const costsOrdered = new Float32Array(vertices.length);
// for (var i = from; i < to; i++) {
// // costs[i] = vertices[i].collapseCost;
// costsOrdered[i] = costStore[i]; // vertices[i].collapseCost;
// }
// costsOrdered.sort();
// let current = 0;
// function getNext() {
// const vertex = vertices[costStore.indexOf(costsOrdered[current])];
// console.log(vertex && vertex.id);
// current++;
// if (!vertex) {
// return getNext();
// }
// return vertex;
// }
// const collapsedArr = [];
let collapsedCount = 0;
while (z--) {
// nextVertexId = minimumCostEdge(vertices, skip, from, to, dataArrayViews);
nextVertexId = takeNextValue(dataArrayViews.collapseQueue);
if (nextVertexId === false) {
buildFullIndex(
dataArrayViews.costStore,
dataArrayViews.collapseQueue,
from,
to
);
nextVertexId = takeNextValue(dataArrayViews.collapseQueue);
}
if (dataArrayViews.vertexWorkStatus[nextVertexId] === 1) {
console.log('work on this one going. skipping');
continue;
}
if (dataArrayViews.vertexWorkStatus[nextVertexId] === 2) {
// console.log('this one was already removed');
continue;
}
//if (collapsedArr.includes(nextVertexId)) {
// console.log('WTF');
//}
//collapsedArr.push(nextVertexId);
collapsedCount++;
if (!nextVertexId) {
console.log('no next vertex');
break;
}
if (nextVertexId < from || nextVertexId >= to) {
console.log('skipping: ', nextVertexId);
skip++;
continue;
}
const neighbourId = dataArrayViews.neighbourCollapse[nextVertexId];
if (dataArrayViews.vertexWorkStatus[neighbourId] === 1) {
console.log('work on collapse neighbour going. skipping');
continue;
}
if (dataArrayViews.vertexWorkStatus[neighbourId] === 2) {
console.log('this neighbour was already removed');
continue;
}
var collapsed = collapse(
nextVertexId,
neighbourId,
preserveTexture,
dataArrayViews
);
if (!collapsed) {
console.log('not collapsed');
skip++;
}
// TEMO: this kind of fixes but breaks everything
// looks what's happening in CONSOLE.ASSERT
dataArrayViews.costStore[nextVertexId] = 9999;
}
// console.log(
// 'Worker index in job',
// workerIndex,
// 'Worker ID in global pool',
// dataArrayViews.id,
// ' removed ',
// collapsedCount,
// ' / ',
// dataArrayViews.verticesView.length / 3
// );
}
function minimumCostEdge(vertices, skip, from, to, dataArrayViews) {
// O(n * n) approach. TODO optimize this
var leastV = from + skip;
// var leastV = from + skip;
if (leastV === null) {
skip++;
return minimumCostEdge(vertices, skip, from, to, dataArrayViews);
}
// var v;
if (from + skip >= to) {
return false;
}
for (var i = from; i < to; i++) {
if (i < from || i >= to - 1) {
continue;
}
// v = vertices[i];
// if (!v) continue;
if (dataArrayViews.costStore[i] < dataArrayViews.costStore[leastV]) {
leastV = i;
}
}
return leastV;
}
const EMPTY_QUEUE_VALUE = 99999;
let costsOrderedIndexes;
function buildFullIndex(valuesArr, orderingArr, fromIndex, toIndex) {
costsOrderedIndexes =
costsOrderedIndexes && costsOrderedIndexes.length === toIndex - fromIndex
? costsOrderedIndexes
: new Uint32Array(toIndex - fromIndex);
for (var i = fromIndex; i < toIndex; i++) {
costsOrderedIndexes[i - fromIndex] = i;
}
// sort indexes
costsOrderedIndexes.sort((a, b) =>
valuesArr[a] < valuesArr[b] ? -1 : (valuesArr[b] < valuesArr[a]) | 0
);
for (i = 0; i < orderingArr.length; i++) {
if (i === 0) {
orderingArr[0] = 1;
continue;
}
orderingArr[i] = costsOrderedIndexes[i - 1];
}
}
/**@abstract returns next value
* 0 - first element is the current value
* taken value is replaced by EMPTY_QUEUE_VALUE (99999)
*/
function takeNextValue(orderingArr) {
// debugger;
if (orderingArr[0] === orderingArr.length) {
for (var i = 1; i < orderingArr.length; i++) {
if (orderingArr[i] !== EMPTY_QUEUE_VALUE) {
const value = orderingArr[i];
orderingArr[i] = EMPTY_QUEUE_VALUE;
orderingArr[0] = i + 1;
return value;
}
}
return false; // when no non-empty entries
}
for (i = orderingArr[0]; i < orderingArr.length; i++) {
if (orderingArr[i] !== EMPTY_QUEUE_VALUE) {
const value = orderingArr[i];
orderingArr[i] = EMPTY_QUEUE_VALUE;
orderingArr[0] = i + 1;
return value;
}
}
orderingArr[0] = orderingArr.length; // this will restart using wrapping to begginning
return takeNextValue(orderingArr);
}
// taken from Geometry.mergeVertices to merge positions in buffer geometry

@@ -2000,0 +950,0 @@ function mergeBGVertices(attributes, targetPositions, targetFaces, targetUVs) {

@@ -219,6 +219,6 @@ import { meshSimplifier, killWorkers, createWorkers } from './MeshSimplifier';

toWireframe(modelGroup, controls.wireframe);
if (modelOptimizedGroup) {
modelOptimizedGroup.rotation.copy(modelGroup.rotation);
}
}
if (modelOptimizedGroup) {
modelOptimizedGroup.rotation.copy(modelGroup.rotation);
}

@@ -225,0 +225,0 @@ if (localStorage.stopEverything === 'false') {

@@ -1526,3 +1526,4 @@ export default () => {

console.error('not collapsed' + e.message);
throw e;
// in case of an error add vertex to done but continue
dataArrayViews.vertexWorkStatus[nextVertexId] = 2
}

@@ -1529,0 +1530,0 @@ // WARNING: don't reset skip if any kind of failure happens above

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc