• three.js 物体、路径与移动,3D效果


    在二维实现的基础上,替换路径数组,生成3维曲线,设置潜艇的3维坐标延路径移动

    import * as THREE from 'three';
    import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
    import { DragControls } from "three/examples/jsm/controls/DragControls";
    import { Pieces } from "../@share/pieces";
    
    /**
     * 3d 动画测试,路径与移动 - 空间中
     * https://threejs.org/docs/index.html#api/zh/extras/curves/CatmullRomCurve3 - 三维样条曲线
     * https://threejs.org/docs/index.html#api/zh/extras/core/Curve - 核心
     */
    export class ThreePathAndMove3d {
        constructor(canvasId) {
            this.work(canvasId);
        }
    
        work(canvasId) {
            // 创建 3d 场景
            const scene = new THREE.Scene();
            scene.background = new THREE.Color(0x9e9e9e);
    
            // 渲染器
            const renderer = this.addRenderer();
    
            // 创建相机
            const camera = this.makeCamera();
            // .multiplyScalar() 矩阵的每个元素乘以参数。
            camera.position.set(-60, 20, 150).multiplyScalar(3);
            // 朝向
            camera.lookAt(0, 0, 0);
            // 控制相机
            const controls = new OrbitControls(camera, renderer.domElement);
            controls.update();
    
            // 初始化灯光
            // 方向光
            const light = new THREE.DirectionalLight(0xffffff, 1);
            light.position.set(0, 20, 0)
            scene.add(light);
            // 方向光
            const light2 = new THREE.DirectionalLight(0xffffff, 1);
            light2.position.set(1, 2, 4);
            scene.add(light2);
    
            // 添加物体
            const boat = this.makeObject(scene);
    
            // 绘制路径
            const len = 300;
            const curve = this.addPath(scene, len / 2);
            console.log(curve);
    
            const boatPosition = new THREE.Vector3();
            const boatTarget = new THREE.Vector3();
    
            function render(time) {
                time *= 0.0005;
                const boatTime = time * 0.05;
                curve.getPointAt(boatTime % 1, boatPosition);
                // 获取路径前一点坐标,用于头部向前
                curve.getPointAt((boatTime + 0.01) % 1, boatTarget);
                // 位移
                boat.position.set(boatPosition.x, boatPosition.y, boatPosition.z);
                boat.lookAt(boatTarget.x, boatTarget.y, boatTarget.z);
    
                // 加载渲染器
                renderer.render(scene, camera)
                // 开始动画
                requestAnimationFrame(render)
            }
    
            // 开始渲染
            requestAnimationFrame(render);
        }
    
        /**
         * 创建相机公用方法
         * */
        makeCamera(fov = 40) {
            const aspect = 2 // the canvas default
            const zNear = 0.1
            const zFar = 1000
            return new THREE.PerspectiveCamera(fov, aspect, zNear, zFar)
        }
    
        /**
         * 添加平面
         */
        addArea(scene, len) {
            const groundGeometry = new THREE.PlaneGeometry(len, len);
            const groundMaterial = new THREE.MeshPhongMaterial({ color: 0x23ADE5 });
            const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
            groundMesh.rotation.x = Math.PI * -0.5;
            scene.add(groundMesh);
        }
    
        /**
         * 添加渲染器
         */
        addRenderer() {
            let renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(window.innerWidth, window.innerHeight);
            // 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。
            document.body.appendChild(renderer.domElement);
            return renderer;
        }
    
        /**
         * 添加船只
         */
        makeObject(scene) {
            const boat = new THREE.Object3D();
            boat.position.y = -1;
            scene.add(boat);
    
            const bodyRadius = 2;
            const bodyLength = 10;
            // 舰体
            const bodyGeometry = new THREE.CapsuleGeometry(bodyRadius, bodyLength, 4, 32);
            const bodyMaterial = new THREE.MeshPhongMaterial({ color: 0x6688aa });
            const bodyMesh = new THREE.Mesh(bodyGeometry, bodyMaterial);
            bodyMesh.rotation.x = Math.PI * 0.5;
            boat.add(bodyMesh);
    
            const doorRadius = bodyRadius / 7 * 5;
            const doorHeight = 2;
            // 舰桥
            const doorGeometry = new THREE.CylinderGeometry(doorRadius, doorRadius, doorHeight, 36);
            const doorMesh = new THREE.Mesh(doorGeometry, bodyMaterial);
            doorMesh.position.set(0, 2, -2);
            boat.add(doorMesh);
    
            const glassRadius = doorRadius / 7;
            const glassHeight = bodyLength / 2;
            // 潜望镜
            const glassGeometry = new THREE.CylinderGeometry(glassRadius, glassRadius, glassHeight, 36);
            const glassMesh = new THREE.Mesh(glassGeometry, bodyMaterial);
            glassMesh.position.set(0, 2, -2.9);
            boat.add(glassMesh);
    
            const swingWidth = 5;
            const swingHeight = doorHeight / 20;
            // 舰桥翼
            const swingGeometry = new THREE.BoxGeometry(swingWidth, swingHeight, 1, 36);
            const swingMesh = new THREE.Mesh(swingGeometry, bodyMaterial);
            swingMesh.position.set(0, 2.5, -2);
            boat.add(swingMesh);
    
            const swingTailHeight = doorHeight / 8;
            const swingTailWidth = 4;
            // 尾翼
            const swingTail1Geometry = new THREE.BoxGeometry(swingTailWidth, swingTailHeight, 2, 36);
            const swingT1Mesh = new THREE.Mesh(swingTail1Geometry, bodyMaterial);
            swingT1Mesh.position.set(0, 0, -6);
            boat.add(swingT1Mesh);
            const swingTail2Geometry = new THREE.BoxGeometry(swingTailHeight, swingTailWidth, 2, 36);
            const swingT2Mesh = new THREE.Mesh(swingTail2Geometry, bodyMaterial);
            swingT2Mesh.position.set(0, 0, -6);
            boat.add(swingT2Mesh);
    
            return boat;
        }
    
        /**
         * 添加路径
         */
        addPath(scene, num) {
            let max = num;
            let min = -num;
            let pointArr = [];
            // 随机点
            for (let i = 0; i < 10; i++) {
                let point = Pieces.getRandomNumberByCount(3, max, 0, min);
                pointArr.push(new THREE.Vector3(point[0], point[1], point[2]));
            }
            /**
             * CatmullRomCurve3
             * 使用Catmull-Rom算法, 从一系列的点创建一条平滑的三维样条曲线。
             * CatmullRomCurve3( points : Array, closed : Boolean, curveType : String, tension : Float )
             * points – Vector3点数组
             * closed – 该曲线是否闭合,默认值为false。
             * curveType – 曲线的类型,默认值为centripetal。
             * tension – 曲线的张力,默认为0.5。
             * @type {CatmullRomCurve3}
             */
            const curve = new THREE.CatmullRomCurve3(pointArr, true);
    
            const points = curve.getPoints(50);
            const geometry = new THREE.BufferGeometry().setFromPoints(points);
            const material = new THREE.LineBasicMaterial({ color: 0xffffff });
            const splineObject = new THREE.Line(geometry, material);
            scene.add(splineObject);
    
            const boxHelper = new THREE.BoxHelper(splineObject);
            scene.add(boxHelper);
    
            return curve;
        }
    
    }
  • 相关阅读:
    4
    3
    iOS常用的三种支付方式
    iOS开发技术之银联支付
    iOS开发技术之支付宝支付
    iOS开发技术之微信支付
    Subversion使用总结
    如何在已有 Xcode 项目中 加入Cordova框架(或者称PhoneGap框架)进行iOS移动跨平台开发
    iOS开发中Masonry的使用总结:
    iOS开发中的权限适配问题总结
  • 原文地址:https://www.cnblogs.com/guofan/p/16356142.html
Copyright © 2020-2023  润新知