UNPKG

@polygonjs/polygonjs

Version:

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

154 lines (153 loc) 5.76 kB
"use strict"; import { LineBasicMaterial, Vector4, Vector3, BufferGeometry, BufferAttribute, LineSegments } from "three"; import { Attribute } from "../../../Attribute"; import { QuadPrimitive } from "../QuadPrimitive"; import { stringMatchMask } from "../../../../String"; import { ThreejsPrimitiveTriangle } from "../../three/ThreejsPrimitiveTriangle"; import { prepareObject } from "./QuadToObject3DCommon"; import { NEIGHBOUR_INDICES, quadHalfEdgeIndices } from "../graph/QuadGraphCommon"; const _v4 = new Vector4(); const _p0 = new Vector3(); const _p1 = new Vector3(); const _p2 = new Vector3(); const _p3 = new Vector3(); const _neighbourData = { quadNode: null, neighbourIndex: null }; const _indices = { index0: -1, index1: -1 }; const _lineMaterialByColorStyle = /* @__PURE__ */ new Map(); function _createOrFindLineMaterial(color) { let material = _lineMaterialByColorStyle.get(color.getStyle()); if (!material) { material = new LineBasicMaterial({ color, linewidth: 1 }); _lineMaterialByColorStyle.set(color.getStyle(), material); } return material; } export function quadToLine(quadObject, graph, options) { const { splitQuads, unsharedEdges, wireframeColor } = options; const quadGeometry = quadObject.geometry; const quadsCount = quadGeometry.quadsCount(); const indices = quadGeometry.index; const srcPositions = quadGeometry.attributes.position.array; const edges = /* @__PURE__ */ new Map(); const buildUnsharedEdges = () => { const newIndices = new Array(); const positions = []; for (let i = 0; i < quadsCount; i++) { const currentNode = graph.quadNode(i); for (const ni of NEIGHBOUR_INDICES) { graph.neighbourData(i, ni, _neighbourData); if (_neighbourData.quadNode == null) { quadHalfEdgeIndices(currentNode.indices, ni, _indices); const i0 = _indices.index0; const i1 = _indices.index1; _p0.fromArray(srcPositions, i0 * 3); _p1.fromArray(srcPositions, i1 * 3); positions.push(_p0.x, _p0.y, _p0.z); positions.push(_p1.x, _p1.y, _p1.z); newIndices.push(newIndices.length); newIndices.push(newIndices.length); } } } const geometry2 = new BufferGeometry(); geometry2.setAttribute(Attribute.POSITION, new BufferAttribute(new Float32Array(positions), 3)); geometry2.setIndex(newIndices); return geometry2; }; const splitGeometry = () => { const newIndices = new Array(); const positions = []; for (let i = 0; i < quadsCount; i++) { _v4.fromArray(indices, i * 4); _p0.fromArray(srcPositions, _v4.x * 3); _p1.fromArray(srcPositions, _v4.y * 3); _p2.fromArray(srcPositions, _v4.z * 3); _p3.fromArray(srcPositions, _v4.w * 3); const j = i * 4 * 3; const k = i * 8; const m = i * 4; _p0.toArray(positions, j); _p1.toArray(positions, j + 3); _p2.toArray(positions, j + 6); _p3.toArray(positions, j + 9); newIndices[k] = m; newIndices[k + 1] = m + 1; newIndices[k + 2] = m + 1; newIndices[k + 3] = m + 2; newIndices[k + 4] = m + 2; newIndices[k + 5] = m + 3; newIndices[k + 6] = m + 3; newIndices[k + 7] = m; } const geometry2 = new BufferGeometry(); geometry2.setAttribute(Attribute.POSITION, new BufferAttribute(new Float32Array(positions), 3)); geometry2.setIndex(newIndices); return geometry2; }; const unsplitGeometry = () => { const newIndices = new Array(); const addEdgeUnsplit = (a, b) => { if (edges.get(a) == b || edges.get(b) == a) { return; } edges.set(a, b); edges.set(b, a); newIndices.push(a, b); }; for (let i = 0; i < quadsCount; i++) { _v4.fromArray(indices, i * 4); addEdgeUnsplit(_v4.x, _v4.y); addEdgeUnsplit(_v4.y, _v4.z); addEdgeUnsplit(_v4.z, _v4.w); addEdgeUnsplit(_v4.w, _v4.x); } const positions = [...srcPositions]; const geometry2 = new BufferGeometry(); geometry2.setAttribute(Attribute.POSITION, new BufferAttribute(new Float32Array(positions), 3)); geometry2.setIndex(newIndices); return geometry2; }; const geometry = unsharedEdges ? buildUnsharedEdges() : splitQuads ? splitGeometry() : unsplitGeometry(); const material = _createOrFindLineMaterial(wireframeColor); const lineSegments = new LineSegments(geometry, material); if (splitQuads) { const primitiveAttributes = QuadPrimitive.attributesFromGeometry(quadGeometry); if (primitiveAttributes) { const primitiveAttributeNames = Object.keys(primitiveAttributes).filter( (attributeName) => stringMatchMask(attributeName, options.primitiveAttributes) ); for (const primitiveAttributeName of primitiveAttributeNames) { const srcAttribute = primitiveAttributes[primitiveAttributeName]; const destPrimitivesCount = quadsCount * 4; const destAttribute = { itemSize: srcAttribute.itemSize, isString: srcAttribute.isString, array: new Array(destPrimitivesCount * srcAttribute.itemSize) }; ThreejsPrimitiveTriangle.addAttribute(lineSegments, primitiveAttributeName, destAttribute); const srcArray = srcAttribute.array; const destArray = destAttribute.array; const srcArraySize = srcArray.length; let j = 0; for (let i = 0; i < srcArraySize; i++) { destArray[j] = srcArray[i]; destArray[j + 1] = srcArray[i]; destArray[j + 2] = srcArray[i]; destArray[j + 3] = srcArray[i]; j += 4; } } } } prepareObject(lineSegments, { shadow: false }); return lineSegments; }