drawPlatformRange.js 5.03 KB
import { Vector3, Object3D, CatmullRomCurve3, TubeGeometry, MeshBasicMaterial, Mesh } from 'three';
import { PLATFORMRANGE_LINE_COLOR } from '@/utility/constants/materials';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js';

const boxLineWidth = 0.1;
const internalLineWidth = 0.05;

const drawTubeLine = (points, color, lineWidth = 1, closed = false) => {
    const fittedCurve = new CatmullRomCurve3(points, true, 'centripetal', 0);
    const geometry = new TubeGeometry(fittedCurve, 256, lineWidth, 64, closed);
    const material = new MeshBasicMaterial({ color });
    const mesh = new Mesh(geometry, material);
    return mesh;
};

const drawRectangle = (v0, v1, v2, v3, color) => {
    const line0 = drawTubeLine([v0, v1], color, boxLineWidth, true);
    const line1 = drawTubeLine([v1, v2], color, boxLineWidth, true);
    const line2 = drawTubeLine([v2, v3], color, boxLineWidth, true);
    const line3 = drawTubeLine([v3, v0], color, boxLineWidth, true);
    const object3d = new Object3D();
    object3d.add(line0).add(line1).add(line2).add(line3);
    return object3d;
};

const drawDoubleSideText = (group, text, color, size, offset, path, callback = null) => {
    const loader = new FontLoader();
    loader.load(path, (font) => {
        const geometry = new TextGeometry(text, {
            font,
            size,
            height: 0.005,
            curveSegments: 12
        });
        geometry.computeBoundingBox();
        geometry.translate(-geometry.boundingBox.max.x * 0.45, offset, 0.005);
        const material = new MeshBasicMaterial({
            color
        });
        const mesh = new Mesh(geometry, material);

        mesh.rotation.x = Math.PI;
        mesh.rotation.y = Math.PI;

        group.add(mesh);

        if (callback) callback(group);
    });
};

const drawGrid = (x, y, boundx, boundy, interval, lineWidth) => {
    const xmax = x * 0.5 - boundx;
    const ymax = y * 0.5 - boundy;

    const leftbound = -xmax;
    const rightbound = xmax;

    const topbound = ymax;
    const bottombound = -ymax;

    const columnLines = new Object3D();
    for (let i = leftbound; i <= rightbound; i += interval) {
        const v0 = new Vector3(i, topbound, 0);
        const v1 = new Vector3(i, bottombound, 0);
        const columnLine = drawTubeLine([v0, v1], PLATFORMRANGE_LINE_COLOR, lineWidth, true);
        columnLines.add(columnLine);
    }

    const rowLines = new Object3D();
    for (let i = bottombound; i <= topbound; i += interval) {
        const v0 = new Vector3(leftbound, i, 0);
        const v1 = new Vector3(rightbound, i, 0);
        const columnLine = drawTubeLine([v0, v1], PLATFORMRANGE_LINE_COLOR, lineWidth, true);
        rowLines.add(columnLine);
    }

    const grid = new Object3D();
    grid.add(columnLines).add(rowLines);

    return grid;
};

export const drawPlatformRange = (x, y, z, interval, distanceWidth, distanceLength, lengthBound) => {
    const xhalf = x * 0.5;
    const yhalf = y * 0.5;

    // bottom
    const v0 = new Vector3(xhalf, yhalf, 0);
    const v1 = new Vector3(-xhalf, yhalf, 0);
    const v2 = new Vector3(-xhalf, -yhalf, 0);
    const v3 = new Vector3(xhalf, -yhalf, 0);

    // top
    const v4 = new Vector3(xhalf, yhalf, z);
    const v5 = new Vector3(-xhalf, yhalf, z);
    const v6 = new Vector3(-xhalf, -yhalf, z);
    const v7 = new Vector3(xhalf, -yhalf, z);

    // side
    // v0 v4
    // v1 v5
    // v2 v6
    // v3 v7

    const bottomLine = drawRectangle(v0, v1, v2, v3, PLATFORMRANGE_LINE_COLOR);
    const topLine = drawRectangle(v4, v5, v6, v7, PLATFORMRANGE_LINE_COLOR);

    const line04 = drawTubeLine([v0, v4], PLATFORMRANGE_LINE_COLOR, boxLineWidth, true);
    const line15 = drawTubeLine([v1, v5], PLATFORMRANGE_LINE_COLOR, boxLineWidth, true);
    const Line26 = drawTubeLine([v2, v6], PLATFORMRANGE_LINE_COLOR, boxLineWidth, true);
    const line37 = drawTubeLine([v3, v7], PLATFORMRANGE_LINE_COLOR, boxLineWidth, true);

    // grid
    const gridInternal = drawGrid(x, y, distanceWidth, distanceLength, interval, internalLineWidth);
    const gridBox = drawGrid(x, y, interval * 3 + distanceWidth, lengthBound * 2 + distanceLength, 20, boxLineWidth);

    const box = new Object3D();
    box.add(bottomLine); // .add(topLine).add(line04).add(line15).add(Line26).add(line37);

    const v0Triangle = new Vector3(10, yhalf, 0);
    const v1Triangle = new Vector3(0, yhalf + 10, 0);
    const v2Triangle = new Vector3(-10, yhalf, 0);

    const lineTriangle0 = drawTubeLine([v0Triangle, v1Triangle], PLATFORMRANGE_LINE_COLOR, internalLineWidth, true);
    const lineTriangle1 = drawTubeLine([v1Triangle, v2Triangle], PLATFORMRANGE_LINE_COLOR, internalLineWidth, true);

    const object3d = new Object3D();
    object3d.add(box).add(gridInternal).add(gridBox).add(lineTriangle0).add(lineTriangle1);

    drawDoubleSideText(
        object3d,
        'FRONT',
        PLATFORMRANGE_LINE_COLOR,
        2.5,
        -yhalf - interval * 0.7,
        '/assets/helvetiker_bold.typeface.json'
    );

    return object3d;
};