CopyMirror.js 3.1 KB
import { Matrix4, Vector3, Mesh, Box3, BufferGeometry } from 'three';
import { MODEL_COLOR, getSceneMeshMaterial } from '@/utility/constants/materials';
import { getGeometryVolume } from '@/utility/jsm/function/getGeometryVolume';
import safeStringify from 'fast-safe-stringify';
import { computeBoundsTree } from 'three-mesh-bvh';

BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;

const setMeshAttributes = (mesh) => {
    const { geometry } = mesh;
    geometry.computeVertexNormals();
    geometry.computeBoundsTree();
    geometry.volume = getGeometryVolume(geometry);

    const box = new Box3();
    geometry.boundsTree.getBoundingBox(box);
    mesh.box = box;

    // const center = box.max.clone().add(box.min).multiplyScalar(0.5);
    const voffset = new Vector3(0, 0, -box.min.z);
    const matrix = new Matrix4().setPosition(voffset);
    geometry.applyMatrix4(matrix);

    geometry.computeBoundsTree();
    geometry.json = safeStringify.stableStringify([geometry.attributes.position]);

    geometry.boundsTree.getBoundingBox(box);
    mesh.box = box;
    geometry.originCenter = box.max.clone().add(box.min).multiplyScalar(0.5);
    mesh.rotateCenter = box.max.clone().add(box.min).multiplyScalar(0.5);
    mesh.finalRotateAngle = { X: 0, Y: 0, Z: 0 };
    mesh.matrixAutoUpdate = false;
    mesh.matrixWorldNeedsUpdate = true;
};

class CopyMirror {
    constructor({ scene }) {
        this._scene = scene;
        this.mode = 'origin'; // 'origin','xy','yz','xz
        this.numbers = 1;
        this.meshes = [];
        this.counts = 0;
    }

    setSelectMeshes = (meshes) => {
        this.meshes = meshes;
    };

    setMirrorTypes = (val) => {
        this.mode = val;
    };

    setDuplicateValues = (val) => {
        this.numbers = val;
    };

    applyToMeshes = () => {
        if (this.meshes.length === 0) return null;
        if (!this._scene) return null;
        const matrix = new Matrix4();
        switch (this.mode) {
            case 'xy':
                matrix.makeScale(1, 1, -1);
                break;
            case 'yz':
                matrix.makeScale(-1, 1, 1);
                break;
            case 'xz':
                matrix.makeScale(1, -1, 1);
                break;
            default:
                break;
        }
        const copyMeshes = [];
        for (let i = 0; i < this.numbers; i++) {
            this.meshes.forEach((el) => {
                const name =
                    this.mode === 'origin' ? `${this.counts + 1}_copy_` : `${this.counts + 1}_mirror_${this.mode}_`;
                const geometry = el.geometry.clone();
                geometry.applyMatrix4(el.matrix.clone().premultiply(matrix));
                const material = getSceneMeshMaterial(MODEL_COLOR);
                const mesh = new Mesh(geometry, material);
                mesh.material.color.setHex(MODEL_COLOR);
                setMeshAttributes(mesh);
                mesh.title = name + el.title;
                mesh.name = name + el.name;
                copyMeshes.push(mesh);
                this.counts++;
            });
        }
        return copyMeshes;
    };
}

export default CopyMirror;