getBasicMesh.js 3.38 KB
import {
    Mesh,
    BufferGeometry,
    BoxGeometry,
    Box3,
    Vector3,
    Matrix4,
    SphereGeometry,
    ConeGeometry,
    CylinderGeometry
} from 'three';
import { getSceneMeshMaterials } from '@/utility/constants/materials';
import { MESH_NAME } from '@/utility/constants/mesh-named';
import { getGeometryVolume } from '@/utility/jsm/function/getGeometryVolume';
import safeStringify from 'fast-safe-stringify';

import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from 'three-mesh-bvh';

BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
Mesh.prototype.raycast = acceleratedRaycast;

// hot fix
let cubecount = 0;
let spherecount = 0;
let conecount = 0;
let cylindercount = 0;

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

const meshPreporcess = (geometry, name, title) => {
    const material = getSceneMeshMaterials();
    const mesh = new Mesh(geometry, material);
    mesh.name = `${MESH_NAME}${name}`;
    mesh.title = title;
    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(-center.x, -center.y, -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;
    return mesh;
};

const addCube = ({ length, width, height }) => {
    const name = cubecount === 0 ? 'cube' : `${cubecount}_cube`;
    const geometry = new BoxGeometry(length, width, height, 3, 3, 3);
    geometryPreprocess(geometry);
    const mesh = meshPreporcess(geometry, name, name);
    cubecount += 1;
    return mesh;
};

const addSphere = ({ radius, resolution }) => {
    const name = spherecount === 0 ? 'sphere' : `${spherecount}_sphere`;
    const geometry = new SphereGeometry(radius, resolution, resolution);
    geometryPreprocess(geometry);
    const mesh = meshPreporcess(geometry, name, name);
    spherecount += 1;
    return mesh;
};

const addCone = ({ radius, resolution, height }) => {
    const name = conecount === 0 ? 'cone' : `${conecount}_cone`;
    const geometry = new ConeGeometry(radius, height, resolution);
    geometry.applyMatrix4(new Matrix4().makeRotationX(Math.PI * 0.5));
    geometryPreprocess(geometry);
    const mesh = meshPreporcess(geometry, name, name);
    conecount += 1;
    return mesh;
};

const addCyliner = ({ radius, resolution, height }) => {
    const name = cylindercount === 0 ? 'cylinder' : `${cylindercount}_cylinder`;
    const geometry = new CylinderGeometry(radius, radius, height, resolution);
    geometry.applyMatrix4(new Matrix4().makeRotationX(Math.PI * 0.5));
    geometryPreprocess(geometry);
    const mesh = meshPreporcess(geometry, name, name);
    cylindercount += 1;
    return mesh;
};

export { addCone, addCube, addCyliner, addSphere };