mergeVertics.js 2.19 KB
import { Float32BufferAttribute } from 'three';
/**
 * 刪除重複頂點,更新網格拓樸
 * @param {*BufferGeometry} geometry three.js幾何模型
 * @param {*Number} precisionPoints
 * 等同於 import { BufferGeometryUtils } from 'three/examples/jsm/utils/BufferGeometryUtils.js' 裡的 BufferGeometryUtils.mergeVertices
 * 但這個函式有bug,會讓有些模型網格破損,所以重寫一個
 */
export const mergeVertices = (geometry, precisionPoints = 4) => {
    const verticesMap = {};
    const unique = [],
        changes = [];
    const colorunique = [];
    const uvunique = [];
    const precision = Math.pow(10, precisionPoints);
    let position = geometry.getAttribute('position');
    let color = geometry.getAttribute('color');
    let uv = geometry.getAttribute('uv');
    let vertexLength = position.count;
    let i = 0;
    while (i < vertexLength) {
        const key =
            Math.round(position.getX(i) * precision) +
            '_' +
            Math.round(position.getY(i) * precision) +
            '_' +
            Math.round(position.getZ(i) * precision);
        if (verticesMap[key] === undefined) {
            verticesMap[key] = i;
            unique.push(position.getX(i), position.getY(i), position.getZ(i));
            if (color) {
                colorunique.push(color.getX(i), color.getY(i), color.getZ(i));
            }
            if (uv) {
                uvunique.push(uv.getX(i), uv.getY(i));
            }
            changes[i] = unique.length / 3 - 1;
        } else {
            changes[i] = changes[verticesMap[key]];
        }
        ++i;
    }
    if (unique.length == vertexLength * 3) {
        return; //頂點數量不變,原始模型沒有重複頂點,使用原始的拓樸即可
    }
    if (unique.length > 0) {
        geometry.setAttribute('position', new Float32BufferAttribute(unique, 3));
    }
    if (colorunique.length > 0) {
        geometry.setAttribute('color', new Float32BufferAttribute(colorunique, 3));
    }
    if (uvunique.length > 0) {
        geometry.setAttribute('uv', new Float32BufferAttribute(uvunique, 2));
    }
    if (changes.length > 0) {
        geometry.setIndex(changes);
    }
    geometry.computeVertexNormals();
};