three.js 5 辅助对象

import * as THREE from 'three';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";

/**
 * 3d helper 辅助对象
 * https://threejs.org/docs/index.html#api/zh/helpers/Box3Helper
 */
export class ThreeDoc5Helper {
    constructor(canvasId) {
        this.work(canvasId);
    }

    work(canvasId) {
        // 创建 3d 场景
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0x9e9e9e);

        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。
        document.body.appendChild(renderer.domElement);

        // ArrowHelper 3维箭头对象.
        this.addArrowHelper(scene);
        // AxesHelper  3个坐标轴的对象.
        this.addAxesHelper(scene);
        // BoxHelper  包围盒的辅助对象
        this.addBoxHelper(scene);
        // Box3Helper 模拟3维包围盒 Box3 的辅助对象.
        // this.addBox3Helper(scene);
        // CameraHelper 用于模拟相机视锥体的辅助对象
        this.addCameraHelper(scene);
        // DirectionalLightHelper 用于模拟场景中平行光的辅助对象
        this.addDirectionalLightHelper(scene);
        // GridHelper 坐标格辅助对象. 坐标格实际上是2维线数组.
        this.addGridHelper(scene);
        // PolarGridHelper 极坐标格辅助对象.
        this.addPolarGridHelper(scene);
        // HemisphereLightHelper 虚拟的球形网格 模拟 半球形光源
        this.addHemisphereLightHelper(scene);
        // PlaneHelper 用于模拟平面 Plane 的辅助对象.
        this.addPlaneHelper(scene);
        // PointLightHelper 虚拟的球形网格 模拟 点光源
        this.addPointLightHelper(scene);
        // SkeletonHelper 模拟骨骼的辅助对象 - 暂时没搞
        // this.addSkeletonHelper(scene);
        // SpotLightHelper 模拟聚光灯 锥形辅助对象.
        this.addSpotLightHelper(scene);



        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        // 设置相机位置
        camera.position.x = 10;
        camera.position.y = 10;
        camera.position.z = 10;
        // const helper = new THREE.CameraHelper( camera );
        // scene.add( helper );
        // camera.lookAt(0, 0, 0);

        // 添加控制器
        let orb = new OrbitControls(camera, document.body);
        orb.addEventListener('change', function () {
            renderer.render(scene, camera);
        });

        renderer.render(scene, camera);
    }

    /**
     * ArrowHelper
     * 用于模拟方向的3维箭头对象.
     * ArrowHelper(dir : Vector3, origin : Vector3, length : Number, hex : Number, headLength : Number, headWidth : Number )
     * dir -- 基于箭头原点的方向. 必须为单位向量.
     * origin -- 箭头的原点.
     * length -- 箭头的长度. 默认为 1.
     * hex -- 定义的16进制颜色值. 默认为 0xffff00.
     * headLength -- 箭头头部(锥体)的长度. 默认为箭头长度的0.2倍(0.2 * length).
     * headWidth -- The width of the head of the arrow. Default is 0.2 * headLength.
     */
    addArrowHelper(scene) {
        const dir = new THREE.Vector3( 1, 2, 0 );

        //normalize the direction vector (convert to vector of length 1)
        dir.normalize();

        const origin = new THREE.Vector3( 0, 0, 0 );
        const length = 1;
        const hex = 0xffff00;

        const arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex );
        scene.add( arrowHelper );
    }

    /**
     * AxesHelper
     * 用于简单模拟3个坐标轴的对象.
     * 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
     * AxesHelper( size : Number )
     * size -- (可选的) 表示代表轴的线段长度. 默认为 1.
     */
    addAxesHelper(scene) {
        const axesHelper = new THREE.AxesHelper( 12 );
        scene.add( axesHelper );
    }

    /**
     * BoxHelper
     * 用于图形化地展示对象世界轴心对齐的包围盒的辅助对象。The actual bounding box is handled with Box3, this is just a visual
     * helper for debugging. It can be automatically resized with the BoxHelper.update method when the object it's created
     * from is transformed. 注意:要想能正常运行,目标对象必须包含 BufferGeometry , 所以当目标对象是精灵 Sprites 时将不能正常运行.
     * BoxHelper( object : Object3D, color : Color )
     * object -- (可选的) 被展示世界轴心对齐的包围盒的对象.
     * color -- (可选的) 线框盒子的16进制颜色值. 默认为 0xffff00.
     */
    addBoxHelper(scene) {
        // 添加 十二面体
        const geometry = new THREE.DodecahedronGeometry(1, 0);
        const material = new THREE.MeshPhongMaterial({ color: 0x049EF4 });
        const dodecahedron = new THREE.Mesh(geometry, material);
        scene.add(dodecahedron);
        // 添加边缘辅助线
        let edges = new THREE.EdgesHelper(dodecahedron, 0x00ff00);
        scene.add(edges);

        const box = new THREE.BoxHelper( dodecahedron, 0xffff00 );
        scene.add( box );

        // 官方事例
        // const sphere = new THREE.SphereGeometry();
        // const object = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( 0xff0000 ) );
        // const box = new THREE.BoxHelper( object, 0xffff00 );
        // scene.add( box );
    }

    /**
     * Box3Helper
     * 模拟3维包围盒 Box3 的辅助对象.
     * Box3Helper( box : Box3, color : Color )
     * box -- 被模拟的3维包围盒.
     * color -- (可选的) 线框盒子的颜色. 默认为 0xffff00.
     *
     * 创建一个新的线框盒子用以表示指定的3维包围盒.
     */
    addBox3Helper(scene) {
        const box = new THREE.Box3();
        box.setFromCenterAndSize( new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 2, 1, 3 ) );

        const helper = new THREE.Box3Helper( box, 0xffff00 );
        scene.add( helper );
    }

    /**
     * CameraHelper
     * 用于模拟相机视锥体的辅助对象.
     * 它使用 LineSegments 来模拟相机视锥体.
     * CameraHelper( camera : Camera )
     * camera -- 被模拟的相机.
     *
     * 为指定相机创建一个新的相机辅助对象 CameraHelper .
     */
    addCameraHelper(scene) {
        const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
        const helper = new THREE.CameraHelper( camera );
        scene.add( helper );
    }

    /**
     * DirectionalLightHelper
     * 用于模拟场景中平行光 DirectionalLight 的辅助对象. 其中包含了表示光位置的平面和表示光方向的线段.
     * DirectionalLightHelper( light : DirectionalLight, size : Number, color : Hex )
     * light-- 被模拟的光源.
     *
     * size -- (可选的) 平面的尺寸. 默认为 1.
     *
     * color -- (可选的) 如果没有设置颜色将使用光源的颜色.
     */
    addDirectionalLightHelper(scene) {
        const light = new THREE.DirectionalLight( 0xFFFFFF, 1 );
        light.position.set(0,-5,0);
        // scene.add( light );
        const helper = new THREE.DirectionalLightHelper( light, 5 );
        scene.add( helper );
    }

    /**
     * GridHelper
     * 坐标格辅助对象. 坐标格实际上是2维线数组.
     * GridHelper( size : number, divisions : Number, colorCenterLine : Color, colorGrid : Color )
     * size -- 坐标格尺寸. 默认为 10.
     * divisions -- 坐标格细分次数. 默认为 10.
     * colorCenterLine -- 中线颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x444444
     * colorGrid -- 坐标格网格线颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x888888
     *
     * 创建一个尺寸为 'size' 和 每个维度细分 'divisions' 次的坐标格. 颜色可选.
     */
    addGridHelper(scene) {
        const size = 10;
        const divisions = 10;

        const gridHelper = new THREE.GridHelper( size, divisions );
        scene.add( gridHelper );
    }

    /**
     * PolarGridHelper
     * 极坐标格辅助对象. 坐标格实际上是2维线数组.
     * PolarGridHelper( radius : Number, radials : Number, circles : Number, divisions : Number, color1 : Color, color2 : Color )
     * radius -- 极坐标格半径. 可以为任何正数. 默认为 10.
     * radials -- 径向辐射线数量. 可以为任何正整数. 默认为 16.
     * circles -- 圆圈的数量. 可以为任何正整数. 默认为 8.
     * divisions -- 圆圈细分段数. 可以为任何大于或等于3的正整数. 默认为 64.
     * color1 -- 极坐标格使用的第一个颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x444444
     * color2 -- 极坐标格使用的第二个颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x888888
     *
     * 创建一个半径为'radius' 包含 'radials' 条径向辐射线 和 'circles' 个细分成 'divisions' 段的圆圈的极坐标格辅助对象. 颜色可选.
     */
    addPolarGridHelper(scene) {
        const radius = 10;
        const radials = 16;
        const circles = 8;
        const divisions = 64;

        const helper = new THREE.PolarGridHelper( radius, radials, circles, divisions );
        scene.add( helper );
    }

    /**
     * HemisphereLightHelper
     * 创建一个虚拟的球形网格 Mesh 的辅助对象来模拟 半球形光源 HemisphereLight.
     * HemisphereLightHelper( light : HemisphereLight, sphereSize : Number, color : Hex )
     * light -- 被模拟的光源.
     *
     * size -- 用于模拟光源的网格尺寸.
     *
     * color -- (可选的) 如果没有赋值辅助对象将使用光源的颜色.
     */
    addHemisphereLightHelper(scene) {
        const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 100 );
        light.position.set(0,10,0);
        // 还是半球光源舒服!
        scene.add( light );
        const helper = new THREE.HemisphereLightHelper( light, 3 );
        scene.add( helper );
    }

    /**
     * PlaneHelper
     * 用于模拟平面 Plane 的辅助对象.
     * PlaneHelper( plane : Plane, size : Float, hex : Color )
     * plane -- 被模拟的平面.
     * size -- (可选的) 辅助对象的单边长度. 默认为 1.
     * color -- (可选的) 辅助对象的颜色. 默认为 0xffff00.
     *
     * 创建一个线框辅助对象来表示指定平面.
     */
    addPlaneHelper(scene) {
        const plane = new THREE.Plane( new THREE.Vector3( 0, 10, 0 ), 3 );
        const helper = new THREE.PlaneHelper( plane, 1, 0xffff00 );
        scene.add( helper );
    }

    /**
     * PointLightHelper
     * 创建一个虚拟的球形网格 Mesh 的辅助对象来模拟 点光源 PointLight.
     * PointLightHelper( light : PointLight, sphereSize : Float, color : Hex )
     * light -- 要模拟的光源.
     *
     * sphereSize -- (可选的) 球形辅助对象的尺寸. 默认为 1.
     *
     * color -- (可选的) 如果没有赋值辅助对象将使用光源的颜色.
     */
    addPointLightHelper(scene) {
        const pointLight = new THREE.PointLight( 0xff0000, 10000, 0 );
        pointLight.position.set( 1, -2, 0 );
        // 点光源不如半球光源好用
        // scene.add( pointLight );

        const sphereSize = 1;
        const pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
        scene.add( pointLightHelper );
    }

    /**
     * SkeletonHelper
     * 用来模拟骨骼 Skeleton 的辅助对象. 该辅助对象使用 LineBasicMaterial 材质.
     * SkeletonHelper( object : Object3D )
     * object -- Usually an instance of SkinnedMesh. However, any instance of Object3D can be used if it represents a
     * hierarchy of Bones (via Object3D.children).
     */
    addSkeletonHelper(scene) {
        const helper = new THREE.SkeletonHelper( skinnedMesh );
        scene.add( helper );
    }

    /**
     * SpotLightHelper
     * 用于模拟聚光灯 SpotLight 的锥形辅助对象.
     * SpotLightHelper( light : SpotLight, color : Hex )
     * light -- 被模拟的聚光灯 SpotLight .
     *
     * color -- (可选的) 如果没有赋值辅助对象将使用光源的颜色.
     */
    addSpotLightHelper(scene) {
        const spotLight = new THREE.SpotLight( 0xffffff, 100, 0 );
        spotLight.position.set( 5, 5, 1 );
        // 聚光灯只能找到证明,背面为阴影
        // scene.add( spotLight );

        const spotLightHelper = new THREE.SpotLightHelper( spotLight );
        scene.add( spotLightHelper );
    }
}

 

posted @ 2022-05-27 13:29  名字不好起啊  阅读(97)  评论(0编辑  收藏  举报