• three.js 8 物体


    import * as THREE from 'three';
    import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
    import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper";
    
    /**
     * 3d Object 物体
     * https://threejs.org/docs/index.html#api/zh/objects/Bone
     */
    export class ThreeDoc8Object {
        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);
    
            // AxesHelper  3个坐标轴的对象.
            this.addAxesHelper(scene);
    
    
            // 骨骼,什么的太难了,后续再看。。。Bone、Skeleton、SkinnedMesh
    
            //
            // let group = this.setGroup(scene);
            // 实例化网格(InstancedMesh) - 不知为何会无效
            // this.setInstancedMesh(scene)
            // 线
            // this.addLine(scene);
            // 环线(LineLoop) - 什么区别?
            // this.addLineLoop(scene);
            // 线段(LineSegments) - 22一对,组成线段
            // this.addLineSegments(scene);
            // 多细节层次(LOD,Levels of Detail) - 没观察出来什么细节东西
            // this.addLOD(scene);
            // 网格(Mesh)
            this.addMesh(scene);
            // 精灵(Sprite)
            this.addSprite(scene);
    
    
            // 包围盒辅助线框对象
            // const box = new THREE.BoxHelper(dodecahedron, 0xffff00);
            // scene.add(box);
    
            // 半球光(HemisphereLight)
            this.addHemisphereLight(scene);
            // 平面光光源(RectAreaLight)
            this.addRectAreaLight(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;
            // camera.lookAt(0, 0, 0);
    
            // 添加控制器
            let orb = new OrbitControls(camera, document.body);
            orb.addEventListener('change', function () {
                renderer.render(scene, camera);
            });
    
            renderer.render(scene, camera);
    
            function animate() {
                requestAnimationFrame(animate);
                group.rotation.y += 0.01; // 组横向旋转
                renderer.render(scene, camera);
            }
    
            // animate();
        }
    
        /**
         * AxesHelper
         * 用于简单模拟3个坐标轴的对象.
         * 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
         * AxesHelper( size : Number )
         * size -- (可选的) 表示代表轴的线段长度. 默认为 1.
         */
        addAxesHelper(scene) {
            const axesHelper = new THREE.AxesHelper(12);
            scene.add(axesHelper);
        }
    
        /**
         * 半球光(HemisphereLight) - 喜欢这个光
         * 光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色。
         * 半球光不能投射阴影。
         *
         * HemisphereLight( skyColor : Integer, groundColor : Integer, intensity : Float )
         * skyColor - (可选参数) 天空中发出光线的颜色。 缺省值 0xffffff。
         * groundColor - (可选参数) 地面发出光线的颜色。 缺省值 0xffffff。
         * intensity - (可选参数) 光照强度。 缺省值 1。
         */
        addHemisphereLight(scene) {
            const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 100);
            scene.add(light);
            light.position.set(0, -10, 0);
            const helper = new THREE.HemisphereLightHelper(light, 3);
            scene.add(helper);
        }
    
        /**
         * 平面光光源(RectAreaLight) - 这个光源也不错!
         * 平面光光源从一个矩形平面上均匀地发射光线。这种光源可以用来模拟像明亮的窗户或者条状灯光光源。
         * 注意事项:
         * 不支持阴影。
         * 只支持 MeshStandardMaterial 和 MeshPhysicalMaterial 两种材质。
         * 你必须在你的场景中加入 RectAreaLightUniformsLib ,并调用init()。
         *
         * RectAreaLight( color : Integer, intensity : Float, width : Float, height : Float )
         * color - (可选参数) 十六进制数字表示的光照颜色。缺省值为 0xffffff (白色)
         * intensity - (可选参数) 光源强度/亮度 。缺省值为 1。
         * width - (可选参数) 光源宽度。缺省值为 10。
         * height - (可选参数) 光源高度。缺省值为 10。
         */
        addRectAreaLight(scene) {
            const width = 20;
            const height = 10;
            const intensity = 100;
            const rectLight = new THREE.RectAreaLight(0xffffff, intensity, width, height);
            rectLight.position.set(10, 10, 0);
            rectLight.lookAt(0, 0, 0);
            scene.add(rectLight);
    
            let rectLightHelper = new RectAreaLightHelper(rectLight);
            scene.add(rectLightHelper);
        }
    
        /**
         * 成组
         */
        setGroup(scene) {
            const lGeometry = new THREE.SphereGeometry(5, 32, 16);
            const sGeometry = new THREE.SphereGeometry(0.5, 32, 16);
            const material = new THREE.MeshStandardMaterial({ color: 0x049EF4 });
    
            const cubeL = new THREE.Mesh(lGeometry, material);
            cubeL.position.set(0, 0, 0);
    
            const cubeS = new THREE.Mesh(sGeometry, material);
            cubeS.position.set(-5, 0, -5);
    
    //create a group and add the two cubes
    //These cubes can now be rotated / scaled etc as a group
            const group = new THREE.Group();
            group.add(cubeL);
            group.add(cubeS);
    
            scene.add(group);
    
            const box = new THREE.BoxHelper(group, 0xffff00);
            scene.add(box);
    
            return group;
        }
    
        /**
         * 实例化网格(InstancedMesh)
         * 一种具有实例化渲染支持的特殊版本的Mesh。你可以使用 InstancedMesh 来渲染大量具有相同几何体与材质、但具有不同世界变换的物体。
         * 使用 InstancedMesh 将帮助你减少 draw call 的数量,从而提升你应用程序的整体渲染性能。
         * InstancedMesh( geometry : BufferGeometry, material : Material, count : Integer )
         * geometry - 一个 BufferGeometry 的实例。
         * material - 一个 Material 的实例。默认为一个新的 MeshBasicMaterial 。
         * count - 实例的数量
         */
        setInstancedMesh(scene) {
            const geometry = new THREE.SphereGeometry(0.5, 32, 16);
            const material = new THREE.MeshStandardMaterial({ color: 0x049EF4 });
            let mesh = new THREE.InstancedMesh(geometry, material, 10);
            // mesh.instanceMatrix.setUsage( DynamicDrawUsage ); // will be updated every frame
            scene.add(mesh);
        }
    
        /**
         * 线(Line)
         * 一条连续的线。
         * Line( geometry : BufferGeometry, material : Material )
         * geometry —— 表示线段的顶点,默认值是一个新的BufferGeometry。
         * material —— 线的材质,默认值是一个新的具有随机颜色的LineBasicMaterial。
         */
        addLine(scene) {
            const material = new THREE.LineBasicMaterial({
                color: 0x049EF4
            });
    
            const step = 3;
            const points = [
                new THREE.Vector3(-step, 0, 0),
                new THREE.Vector3(0, step, 0),
                new THREE.Vector3(step, 0, 0),
                new THREE.Vector3(0, -step, 0),
                new THREE.Vector3(-step, 0, 0),
                new THREE.Vector3(0, 0, -step),
                new THREE.Vector3(step, 0, 0),
                new THREE.Vector3(0, 0, step),
                new THREE.Vector3(0, -step, 0),
            ];
            points.push(points);
    
            const geometry = new THREE.BufferGeometry().setFromPoints(points);
    
            const line = new THREE.Line(geometry, material);
    
            const box = new THREE.BoxHelper(line, 0xffff00);
            scene.add(box);
            scene.add(line);
        }
    
        /**
         * 环线(LineLoop)
         * 一条头尾相接的连续的线。
         *
         * 它几乎和Line是相同的,唯一的区别是它在渲染时使用的是gl.LINE_LOOP, 而不是gl.LINE_STRIP, 它绘制一条直线到下一个顶点,
         * 并将最后一个顶点连回第一个顶点。
         * LineLoop( geometry : BufferGeometry, material : Material )
         * geometry —— 表示环线上的点的顶点列表。
         * material —— 线的材质,默认值是LineBasicMaterial。
         * @param scene
         */
        addLineLoop(scene) {
            const material = new THREE.LineBasicMaterial({
                color: 0x049EF4
            });
    
            const step = 3;
            const points = [
                new THREE.Vector3(-step, 0, 0),
                new THREE.Vector3(0, step, 0),
                new THREE.Vector3(step, 0, 0),
                new THREE.Vector3(0, -step, 0),
            ];
            points.push(points);
    
            const geometry = new THREE.BufferGeometry().setFromPoints(points);
    
            const line = new THREE.LineLoop(geometry, material);
    
            const box = new THREE.BoxHelper(line, 0xffff00);
            scene.add(box);
            scene.add(line);
        }
    
        /**
         * 线段(LineSegments)
         * 在若干对的顶点之间绘制的一系列的线。
         *
         * 它和Line几乎是相同的,唯一的区别是它在渲染时使用的是gl.LINES, 而不是gl.LINE_STRIP。
         * LineSegments( geometry : BufferGeometry, material : Material )
         * geometry —— 表示每条线段的两个顶点。
         * material —— 线的材质,默认值是LineBasicMaterial。
         * @param scene
         */
        addLineSegments(scene) {
            const material = new THREE.LineBasicMaterial({
                color: 0x049EF4
            });
    
            const step = 3;
            const points = [
                new THREE.Vector3(-step, -step / 2, -step / 2),
                new THREE.Vector3(step, -step / 2, -step / 2),
                new THREE.Vector3(-step, step / 2, -step / 2),
                new THREE.Vector3(step, step / 2, -step / 2),
                new THREE.Vector3(-step, -step / 2, step / 2),
                new THREE.Vector3(step, -step / 2, step / 2),
                new THREE.Vector3(-step, step / 2, step / 2),
                new THREE.Vector3(step, step / 2, step / 2),
                new THREE.Vector3(-step / 2, step / 2, step),
                new THREE.Vector3(-step / 2, step / 2, -step),
                new THREE.Vector3(step / 2, step / 2, step),
                new THREE.Vector3(step / 2, step / 2, -step),
                new THREE.Vector3(-step / 2, -step / 2, step),
                new THREE.Vector3(-step / 2, -step / 2, -step),
                new THREE.Vector3(step / 2, -step / 2, step),
                new THREE.Vector3(step / 2, -step / 2, -step),
                new THREE.Vector3(step / 2, step, step / 2),
                new THREE.Vector3(step / 2, -step, step / 2),
                new THREE.Vector3(step / 2, step, -step / 2),
                new THREE.Vector3(step / 2, -step, -step / 2),
                new THREE.Vector3(-step / 2, step, step / 2),
                new THREE.Vector3(-step / 2, -step, step / 2),
                new THREE.Vector3(-step / 2, step, -step / 2),
                new THREE.Vector3(-step / 2, -step, -step / 2),
            ];
            points.push(points);
    
            const geometry = new THREE.BufferGeometry().setFromPoints(points);
    
            const line = new THREE.LineSegments(geometry, material);
    
            const box = new THREE.BoxHelper(line, 0xffff00);
            scene.add(box);
            scene.add(line);
        }
    
        /**
         * 多细节层次(LOD,Levels of Detail)
         * 多细节层次 —— 在显示网格时,根据摄像机距离物体的距离,来使用更多或者更少的几何体来对其进行显示。
         *
         * 每一个级别都和一个几何体相关联,且在渲染时,可以根据给定的距离,来在这些级别对应的几何体之间进行切换。 通常情况下,你会创建多个几何体,
         * 比如说三个,一个距离很远(低细节),一个距离适中(中等细节),还有一个距离非常近(高质量)。
         * @param scene
         */
        addLOD(scene) {
            const lod = new THREE.LOD();
            //Create spheres with 3 levels of detail and create new LOD levels for them
            for (let i = 0; i < 3; i++) {
                const geometry = new THREE.IcosahedronGeometry(10, 3 - i);
                const material = new THREE.LineBasicMaterial({ color: 0x049EF4 });
                const mesh = new THREE.Mesh(geometry, material);
                lod.addLevel(mesh, i * 75);
            }
            scene.add(lod);
        }
    
        /**
         * 网格(Mesh)
         * 表示基于以三角形为polygon mesh(多边形网格)的物体的类。 同时也作为其他类的基类,例如SkinnedMesh。
         * Mesh( geometry : BufferGeometry, material : Material )
         * geometry —— (可选)BufferGeometry的实例,默认值是一个新的BufferGeometry。
         * material —— (可选)一个Material,或是一个包含有Material的数组,默认是一个新的MeshBasicMaterial。
         * @param scene
         */
        addMesh(scene) {
            const geometry = new THREE.SphereGeometry( 1, 32,16 );
            const material = new THREE.MeshBasicMaterial( { color: 0x049EF4 } );
            const mesh = new THREE.Mesh( geometry, material );
    
            let edges = new THREE.EdgesHelper(mesh, 0x00ff00);
            scene.add(edges);
    
            scene.add( mesh );
        }
    
        /**
         * 精灵(Sprite)
         * 精灵是一个总是面朝着摄像机的平面,通常含有使用一个半透明的纹理。
         * 精灵不会投射任何阴影,即使设置了 castShadow = true 也将不会有任何效果。
         * Sprite( material : Material )
         * material - (可选值)是SpriteMaterial的一个实例。 默认值是一个白色的SpriteMaterial。
         * @param scene
         */
        addSprite(scene) {
            const map = new THREE.TextureLoader().load( "assets/floor-wb.png" );
            const material = new THREE.SpriteMaterial( { map: map } );
    
            const sprite = new THREE.Sprite( material );
            sprite.scale.set(10, 10, 0);
            scene.add( sprite );
        }
    }
  • 相关阅读:
    NSString拼接字符串
    2020/4/26
    2020/4/25
    2020/4/24
    2020/4/22
    2020/4/22
    2020/4/20
    2020/4/19
    2020/4/18
    2020/4/17
  • 原文地址:https://www.cnblogs.com/guofan/p/16333143.html
Copyright © 2020-2023  润新知