UNPKG

@itwin/core-frontend

Version:
205 lines • 9.71 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Rendering */ Object.defineProperty(exports, "__esModule", { value: true }); exports.upsampleRealityMeshParams = upsampleRealityMeshParams; const core_geometry_1 = require("@itwin/core-geometry"); const core_common_1 = require("@itwin/core-common"); const RealityMeshParams_1 = require("../../render/RealityMeshParams"); const core_bentley_1 = require("@itwin/core-bentley"); class UpsampleIndexMap extends Map { _next = 0; indices = new Array(); addTriangle(indices) { for (const index of indices) { let mapIndex = this.get(index); if (undefined === mapIndex) this.set(index, mapIndex = this._next++); this.indices.push(mapIndex); } } } class ClipAxis { vertical; lessThan; value; constructor(vertical, lessThan, value) { this.vertical = vertical; this.lessThan = lessThan; this.value = value; } } function upsampleRealityMeshParams(params, uvSampleRange) { const indexMap = new UpsampleIndexMap(); const uvParams = core_common_1.QParams2d.fromZeroToOne(); const uvLow = core_common_1.QPoint2d.create(uvSampleRange.low, uvParams); const uvHigh = core_common_1.QPoint2d.create(uvSampleRange.high, uvParams); const uvRange = core_geometry_1.Range2d.createXYXY(uvLow.x, uvLow.y, uvHigh.x, uvHigh.y); const clipAxes = new Array(); const addedPoints = new Array(), addedParams = new Array(), addedNormals = new Array(); if (uvLow.x > 0) clipAxes.push(new ClipAxis(true, false, uvLow.x)); if (uvHigh.x < core_common_1.Quantization.rangeScale16) clipAxes.push(new ClipAxis(true, true, uvHigh.x)); if (uvLow.y > 0) clipAxes.push(new ClipAxis(false, false, uvLow.y)); if (uvHigh.y < core_common_1.Quantization.rangeScale16) clipAxes.push(new ClipAxis(false, true, uvHigh.y)); const triangleRange = core_geometry_1.Range2d.createNull(); for (let i = 0; i < params.indices.length;) { const triangleIndices = [params.indices[i++], params.indices[i++], params.indices[i++]]; core_geometry_1.Range2d.createNull(triangleRange); for (const index of triangleIndices) { const paramIndex = 2 * index; triangleRange.extendXY(params.uvs.points[paramIndex], params.uvs.points[paramIndex + 1]); } if (uvRange.intersectsRange(triangleRange)) { if (uvRange.containsRange(triangleRange)) { indexMap.addTriangle(triangleIndices); } else { addClipped(params, triangleIndices, indexMap, clipAxes, 0, addedPoints, addedParams, addedNormals); } } } const parentPoints = params.positions; const parentParams = params.uvs; const parentNormals = params.normals; const parentPointCount = parentPoints.points.length / 3; const zRange = core_geometry_1.Range1d.createNull(); const builder = new RealityMeshParams_1.RealityMeshParamsBuilder({ positionRange: parentPoints.params.computeRange(), initialVertexCapacity: indexMap.size, initialIndexCapacity: indexMap.indices.length, wantNormals: parentNormals !== undefined, }); const pos = new core_common_1.QPoint3d(); const uv = new core_common_1.QPoint2d(); for (const entry of indexMap.entries()) { const parentIndex = entry[0]; let normal; if (parentIndex < parentPointCount) { const pointIndex = 3 * parentIndex; pos.setFromScalars(parentPoints.points[pointIndex], parentPoints.points[pointIndex + 1], parentPoints.points[pointIndex + 2]); const paramIndex = 2 * parentIndex; uv.setFromScalars(parentParams.points[paramIndex], parentParams.points[paramIndex + 1]); if (parentNormals) normal = parentNormals[parentIndex]; } else { const addedIndex = parentIndex - parentPointCount; addedPoints[addedIndex].clone(pos); addedParams[addedIndex].clone(uv); if (addedNormals.length > 0) normal = addedNormals[addedIndex]; } builder.addQuantizedVertex(pos, uv, normal); zRange.extendX(pos.z); } builder.addIndices(indexMap.indices); const mesh = builder.finish(); const qParams = mesh.positions.params; return { mesh: builder.finish(), heightRange: core_geometry_1.Range1d.createXX(core_common_1.Quantization.unquantize(zRange.low, qParams.origin.z, qParams.scale.z), core_common_1.Quantization.unquantize(zRange.high, qParams.origin.z, qParams.scale.z)), }; } function interpolate(value0, value1, fraction) { return value0 + (value1 - value0) * fraction; } function interpolateInt(value0, value1, fraction) { return Math.floor(.5 + interpolate(value0, value1, fraction)); } function interpolateQPoint3d(qPoint, qNext, fraction) { return core_common_1.QPoint3d.fromScalars(interpolateInt(qPoint.x, qNext.x, fraction), interpolateInt(qPoint.y, qNext.y, fraction), interpolateInt(qPoint.z, qNext.z, fraction)); } function interpolateQPoint2d(qPoint, qNext, fraction) { return core_common_1.QPoint2d.fromScalars(interpolateInt(qPoint.x, qNext.x, fraction), interpolateInt(qPoint.y, qNext.y, fraction)); } function interpolateOctEncodedNormal(normal0, normal1, fraction) { const n0 = core_common_1.OctEncodedNormal.decodeValue(normal0); const n1 = core_common_1.OctEncodedNormal.decodeValue(normal1); if (undefined !== n0 && undefined !== n1) { const n = core_geometry_1.Vector3d.create(interpolate(n0.x, n1.x, fraction), interpolate(n0.y, n1.y, fraction), interpolate(n0.z, n1.z, fraction)); n.normalizeInPlace(); return core_common_1.OctEncodedNormal.encode(n); } else { return core_common_1.OctEncodedNormal.encode(core_geometry_1.Vector3d.create(0, 0, 1)); } } function addClipped(params, triangleIndices, indexMap, clipAxes, clipIndex, addedPoints, addedParams, addedNormals) { if (clipIndex === clipAxes.length) { indexMap.addTriangle(triangleIndices); return; } const inside = [false, false, false]; const values = [0, 0, 0]; const clipOutput = []; const parentPoints = params.positions.points; const parentParams = params.uvs.points; const parentNormals = params.normals; const clipAxis = clipAxes[clipIndex++]; const clipValue = clipAxis.value; const parentPointCount = parentPoints.length / 3; const scratchQPoint3d = new core_common_1.QPoint3d(), scratchQPoint3d1 = new core_common_1.QPoint3d(); const scratchQPoint2d = new core_common_1.QPoint2d(), scratchQPoint2d1 = new core_common_1.QPoint2d(); const getPoint = (index, result) => { if (index < parentPointCount) { const pointIndex = index * 3; result.setFromScalars(parentPoints[pointIndex], parentPoints[pointIndex + 1], parentPoints[pointIndex + 2]); } else { addedPoints[index - parentPointCount].clone(result); } return result; }; const getParam = (index, result) => { if (index < parentPointCount) { const pointIndex = index * 2; result.setFromScalars(parentParams[pointIndex], parentParams[pointIndex + 1]); } else { addedParams[index - parentPointCount].clone(result); } return result; }; const getNormal = (index) => { if (!parentNormals) return undefined; return (index < parentPointCount) ? parentNormals[index] : addedNormals[index - parentPointCount]; }; for (let i = 0; i < 3; i++) { const index = triangleIndices[i]; const thisParam = getParam(index, scratchQPoint2d); const thisValue = clipAxis.vertical ? thisParam.x : thisParam.y; values[i] = thisValue; inside[i] = clipAxis.lessThan ? (thisValue < clipValue) : (thisValue > clipValue); } for (let i = 0; i < 3; i++) { const index = triangleIndices[i]; const next = (i + 1) % 3; if (inside[i]) clipOutput.push(index); if (inside[i] !== inside[next]) { const nextIndex = triangleIndices[next]; const fraction = (clipValue - values[i]) / (values[next] - values[i]); clipOutput.push(parentPointCount + addedPoints.length); addedPoints.push(interpolateQPoint3d(getPoint(index, scratchQPoint3d), getPoint(nextIndex, scratchQPoint3d1), fraction)); addedParams.push(interpolateQPoint2d(getParam(index, scratchQPoint2d), getParam(nextIndex, scratchQPoint2d1), fraction)); if (parentNormals) addedNormals.push(interpolateOctEncodedNormal((0, core_bentley_1.expectDefined)(getNormal(index)), (0, core_bentley_1.expectDefined)(getNormal(nextIndex)), fraction)); } } if (clipOutput.length > 2) { addClipped(params, clipOutput.slice(0, 3), indexMap, clipAxes, clipIndex, addedPoints, addedParams, addedNormals); if (clipOutput.length > 3) addClipped(params, [clipOutput[0], clipOutput[2], clipOutput[3]], indexMap, clipAxes, clipIndex, addedPoints, addedParams, addedNormals); } } //# sourceMappingURL=UpsampleRealityMeshParams.js.map