@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
207 lines (206 loc) • 6.75 kB
JavaScript
"use strict";
import { BufferAttribute, Vector3 } from "three";
import { setToArray } from "../../SetUtils";
import { ThreejsCoreObject } from "../modules/three/ThreejsCoreObject";
import { textureFromAttribLookupId, textureFromAttribLookupUv } from "./TextureFromAttribute";
const v0 = new Vector3();
export var AttribAdjacency = /* @__PURE__ */ ((AttribAdjacency2) => {
AttribAdjacency2["BASE_NAME"] = "adjacency";
AttribAdjacency2["COUNT"] = "adjacencyCount";
return AttribAdjacency2;
})(AttribAdjacency || {});
export function adjacencyAttribName(baseAttribName, index) {
return `${baseAttribName}${index}`;
}
function _adjacencyVertices(geometry, vertices) {
const position = geometry.attributes.position;
if (!(position instanceof BufferAttribute)) {
console.warn("position is not a BufferAttribute");
return;
}
for (let i = 0, il = position.count; i < il; i++) {
v0.fromBufferAttribute(position, i);
vertices.push(v0.clone());
}
}
function _adjacencyGroupFaces(geometry, vertices) {
const index = geometry.index;
if (!index) {
console.warn("no index");
return;
}
const verticesCount = vertices.length;
const indexCount = index.count / 3;
const faces = Array.from({ length: verticesCount }, () => new Array());
for (let i = 0, il = indexCount; i < il; i++) {
const i3 = i * 3;
const a = index.getX(i3 + 0);
const b = index.getX(i3 + 1);
const c = index.getX(i3 + 2);
const face = { a, b, c };
faces[a].push(face);
faces[b].push(face);
faces[c].push(face);
}
return faces;
}
const _indexPairByFirstIndex = /* @__PURE__ */ new Map();
const _endIndices = /* @__PURE__ */ new Set();
function filterAjacency(indexPairs) {
_indexPairByFirstIndex.clear();
_endIndices.clear();
for (const indexPair of indexPairs) {
_indexPairByFirstIndex.set(indexPair[0], indexPair);
_endIndices.add(indexPair[1]);
}
let startIndex = 0;
let i = 0;
for (const indexPair of indexPairs) {
if (!_endIndices.has(indexPair[0])) {
startIndex = i;
break;
}
i++;
}
const expectedCount = indexPairs.length;
const rawList = new Array(expectedCount).fill(-1);
const result = new Array();
let currentIndexPair = indexPairs[startIndex];
for (let i2 = 0; i2 < expectedCount; i2++) {
rawList[i2] = currentIndexPair[0];
currentIndexPair = _indexPairByFirstIndex.get(currentIndexPair[1]);
if (!currentIndexPair) {
break;
}
}
for (let i2 = 0; i2 < expectedCount; i2 += 2) {
result.push([rawList[i2], rawList[i2 + 1]]);
}
return result;
}
const _pointSet = /* @__PURE__ */ new Set();
const _pointArray = [];
export function populateAdjacency2(faces, vertices) {
const adjacency = Array.from({ length: vertices.length }, () => new Array());
for (let r = 0; r < faces.length; r++) {
const pointFaces = faces[r];
if (pointFaces.length == 0) {
console.warn(`point ${r} has no face`);
}
_pointSet.clear();
for (const pointFace of pointFaces) {
switch (r) {
case pointFace.a: {
_pointSet.add([pointFace.b, pointFace.c]);
break;
}
case pointFace.b: {
_pointSet.add([pointFace.c, pointFace.a]);
break;
}
case pointFace.c: {
_pointSet.add([pointFace.a, pointFace.b]);
break;
}
}
}
setToArray(_pointSet, _pointArray);
adjacency[r] = filterAjacency(_pointArray);
}
return adjacency;
}
export const POPULATE_ADJACENCY_DEFAULT = {
adjacencyCountName: "adjacencyCount" /* COUNT */,
adjacencyBaseName: "adjacency" /* BASE_NAME */
};
export function populateAdjacency3(object, params) {
const { adjacencyCountName, adjacencyBaseName } = params;
const geometry = object.geometry;
if (!geometry) {
return;
}
const position = geometry.attributes.position;
if (!(position instanceof BufferAttribute)) {
console.warn("position is not a BufferAttribute");
return;
}
const index = geometry.index;
if (!index) {
console.warn("no index");
return;
}
const vertices = [];
_adjacencyVertices(geometry, vertices);
const faces = _adjacencyGroupFaces(geometry, vertices);
if (!faces) {
return;
}
const adjacency = populateAdjacency2(faces, vertices);
let maxAdjacencyCount = -1;
for (const arr of adjacency) {
if (arr.length > maxAdjacencyCount) {
maxAdjacencyCount = arr.length;
}
}
const attribSize = 2;
const attributesCount = Math.ceil(maxAdjacencyCount);
ThreejsCoreObject.addAttribute(object, adjacencyCountName, maxAdjacencyCount);
const pointsCount = position.count;
const _addAdjacencyAttributes = () => {
for (let attribIndex = 0; attribIndex < attributesCount; attribIndex++) {
const attribName = adjacencyAttribName(adjacencyBaseName, attribIndex);
const values = new Array(pointsCount * attribSize).fill(-1);
for (let pointIndex = 0; pointIndex < pointsCount; pointIndex++) {
const pointAdjacency = adjacency[pointIndex][attribIndex];
if (pointAdjacency) {
for (let i = 0; i < attribSize; i++) {
const value = pointAdjacency[i];
values[pointIndex * attribSize + i] = value != null ? value : -1;
}
}
}
const valuesArray = new Float32Array(values);
geometry.setAttribute(attribName, new BufferAttribute(valuesArray, attribSize));
}
};
_addAdjacencyAttributes();
textureFromAttribLookupUv(geometry);
textureFromAttribLookupId(geometry);
}
export function unpackAdjacency3(object, params) {
var _a;
const { adjacencyCountName, adjacencyBaseName } = params;
const geometry = object.geometry;
if (!geometry) {
return [];
}
const indices = (_a = geometry.index) == null ? void 0 : _a.array;
if (!indices) {
return [];
}
const pointsCount = indices.length;
const adjacencies = [];
const adjacencyCount = ThreejsCoreObject.attribValue(object, adjacencyCountName, 0);
for (let i = 0; i < pointsCount; i++) {
const index = indices[i];
for (let attribIndex = 0; attribIndex < adjacencyCount; attribIndex++) {
const attribName = adjacencyAttribName(adjacencyBaseName, attribIndex);
const attribute = geometry.getAttribute(attribName);
const array = attribute.array;
let pointAdjacency = adjacencies[index];
if (!pointAdjacency) {
pointAdjacency = [];
adjacencies[index] = pointAdjacency;
}
const i0 = array[index * 2];
const i1 = array[index * 2 + 1];
if (!pointAdjacency.includes(i0)) {
pointAdjacency.push(i0);
}
if (!pointAdjacency.includes(i1)) {
pointAdjacency.push(i1);
}
}
}
return adjacencies;
}