UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

207 lines (206 loc) 6.75 kB
"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; }