three.js绘制网波浪

无图不欢,先上图
在这里插入图片描述

使用方法(以vue3为例)

<template>
    <div class="net" ref="net"></div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import NetAnimation from '@/utils/netAnimation.js'

let net = ref(null)
onMounted(() => {
    new NetAnimation({
        dom: net.value,
        pointLightsAttr: [{},{},{}],
        axesHelperAttr: {
            show: true,
            length: 100
        },
        controlAttr: {
            show: true
        }
    })
})

</script>
  
<style scoped lang="scss">
.net{
    width: 100%;
    height: 100%;
    background-color: #02112e;
}
</style>

netAnimation.js源码

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

class NetAnimation {
    constructor(opt) {
        this.dom = opt.dom
        this.w = null
        this.h = null
        this.netMaxY = opt.netMaxY

        this.scene = null

        this.renderer = null

        this.camera = null
        this.cameraAttr = opt.cameraAttr

        this.ambientLight = null
        this.ambientLightAttr = opt.ambientLightAttr

        this.pointLights = []
        this.pointLightsAttr = opt.pointLightsAttr

        this.axesHelper = null
        this.axesHelperAttr = opt.axesHelperAttr

        this.control = null
        this.controlAttr = opt.controlAttr

        this.plane = null
        this.planeAttr = opt.planeAttr

        this.animationIndex = 0
        this.requestAnimationFrame = null

        this.init()
    }
    init = () => {
        if(!this.dom){
            return
        }
        this.w = this.dom.clientWidth * (window.devicePixelRatio || 1)
        this.h = this.dom.clientHeight * (window.devicePixelRatio || 1)

        // 创建场景
        this.scene = this.createScene()

        // 创建render
        this.renderer = this.createWebGLRenderer({dom: this.dom});

        // 创建相机
        const cameraAttr = {
            style: {
                fov: 45,
                aspect: this.w / this.h,
                near: 0.01,
                far: 10000
            },
            position: {
                x: this.w / 2,
                y: this.w / 2,
                z: this.h * 2
            }
        }
        if(this.cameraAttr){
            this.cameraAttr = Object.assign(cameraAttr, this.cameraAttr)
        }else{
            this.cameraAttr = cameraAttr
        }
        this.camera = this.createPerspectiveCamera(this.cameraAttr.style)
        this.camera.position.set(this.cameraAttr.position.x, this.cameraAttr.position.y, this.cameraAttr.position.z);
        this.camera.lookAt(this.scene.position);

        // 创建环境光
        const ambientLightAttr = {
            show: true,
            style: {
                color: "#fff",
                intensity: 0.1
            }
        }
        if(this.ambientLightAttr){
            this.ambientLightAttr = Object.assign(ambientLightAttr, this.ambientLightAttr)
        }else{
            this.ambientLightAttr = ambientLightAttr
        }
        if(this.ambientLightAttr.show){
            this.ambientLight = this.createAmbientLight(this.ambientLightAttr.style);
            this.scene.add(this.ambientLight);
        }

        // 创建点光源
        if(!this.netMaxY){
            this.netMaxY = 60
        }
        const pointLightAttr =  [{
            style: {
                color: '#fff',
                intensity: 0.8,
                distance: this.w
            },
            position: {
                x: this.w * 0.1,
                y: this.netMaxY * 4,
                z: 0
            }
        },{
            style: {
                color: '#fff',
                intensity: 1,
                distance: this.w
            },
            position: {
                x: - this.w * 0.2,
                y: this.netMaxY * 4,
                z: - this.netMaxY * 4
            }
        },{
            style: {
                color: '#fff',
                intensity: 1,
                distance: this.w
            },
            position: {
                x: this.w,
                y: this.netMaxY * 4,
                z: this.netMaxY * 4
            }
        }]
        if(this.pointLightsAttr?.length){
            this.pointLightsAttr.forEach((pointLightItem, pointLightIndex) => {
                pointLightItem = Object.assign(pointLightAttr[pointLightIndex % pointLightAttr.length], pointLightItem)

                const pointLight = this.createPointLight(pointLightItem.style);
                pointLight.position.set(pointLightItem.position.x, pointLightItem.position.y, pointLightItem.position.z);
                this.pointLights.push(pointLight)
            })
            this.scene.add(...this.pointLights);
        }

        // 创建辅助线
        const axesHelperAttr = {
            show: false,
            length: 100
        }
        if(this.axesHelperAttr){
            this.axesHelperAttr = Object.assign(axesHelperAttr, this.axesHelperAttr)
        }else{
            this.axesHelperAttr = axesHelperAttr
        }
        if(this.axesHelperAttr.show){
            this.axesHelper = this.createAxesHelper(this.axesHelperAttr.length)
            this.scene.add(this.axesHelper);
        }

        // 创建轨道控制
        const controlAttr = {
            show: false
        }
        if(this.controlAttr){
            this.controlAttr = Object.assign(controlAttr, this.controlAttr)
        }else{
            this.controlAttr = controlAttr
        }
        if(this.controlAttr.show){
            this.createControl(this.camera, this.dom);
        }

        let planeAttr = {
            width: this.w,
            height: this.h,
            widthSegments: Math.floor(this.w / 20),
            heightSegments: Math.floor(this.h / 60)
        }
        if(this.planeAttr){
            this.planeAttr = Object.assign(planeAttr, this.planeAttr)
        }else{
            this.planeAttr = planeAttr
        }
        const geometry = this.createPlaneGeometry(this.planeAttr)
        const material = this.createMeshPlaneMaterial({
            color: "#ffffff",
            wireframe: true,
        });
        this.plane = this.createMesh({geometry, materialBasic: material});
        this.plane.rotation.x = Math.PI * -0.5;
        // this.plane.rotation.z = 45 * (Math.PI / 180);
        // this.plane.position.z = 100;
        this.scene.add( this.plane )

        // 渲染
        this.render()
    }
    render = () => {
        //循环调用
        this.requestAnimationFrame = requestAnimationFrame(this.render);
        this.animation()
        this.renderer.render(this.scene, this.camera);
    }
    unmount = () => {
        cancelAnimationFrame(this.requestAnimationFrame)
    }
    animation = () => {
        let animationSpeed = 10
        let sinXNum = this.planeAttr.widthSegments
        let sinYNum = this.planeAttr.heightSegments

        const geometry = this.plane.geometry
        const att_p = geometry.getAttribute('position');
        let i = 0;
        let xi = 0
        let yi = 0
        while(i < att_p.count){
            let x = att_p.getX(i)
            let y = att_p.getY(i)

            xi = Math.floor(i / sinXNum)
            yi = i - xi * sinXNum
            let z = (Math.sin(((xi + this.animationIndex / animationSpeed) % sinXNum / sinXNum * Math.PI * 2)) + Math.sin(((yi + xi + this.animationIndex / animationSpeed) % sinYNum / sinYNum * Math.PI * 2))) * (this.netMaxY / 2)
            att_p.setXYZ( i, x, y, z );
            i += 1;
        }
        att_p.needsUpdate = true;
        geometry.computeVertexNormals();

        this.animationIndex++
        this.animationIndex %= sinXNum * sinYNum * animationSpeed
    }
    // 以下皆为实体创建方法
    createScene = () => {
        return new THREE.Scene();
    }
    createPerspectiveCamera = ({ fov, aspect, near, far }) => {
        // fov — 摄像机视锥体垂直视野角度
        // aspect — 摄像机视锥体长宽比
        // near — 摄像机视锥体近端面
        // far — 摄像机视锥体远端面
        return new THREE.PerspectiveCamera(fov, aspect, near, far);
    }
    createWebGLRenderer = ({ dom, width, height }) => {
        // renderDom — dom
        // width — 渲染宽度 一般取domclientWidth
        // height — 渲染高度 一般取clientHeight
        if (width === undefined) {
            width = dom.clientWidth;
        }
        if (height === undefined) {
            height = dom.clientHeight;
        }
        const renderer = new THREE.WebGLRenderer();
        renderer.setPixelRatio(window.devicePixelRatio || 1);
        renderer.setClearColor('#fff', 0); //设置背景颜色和透明度
        renderer.setSize(width, height);
        dom.appendChild(renderer.domElement);
    
        return renderer;
    }
    createAmbientLight = ({ color, intensity }) => {
        // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
        // intensity - (可选参数) 光照强度。 缺省值 1。
        return new THREE.AmbientLight(color, intensity);
    }
    createPointLight = ({ color, intensity, distance, decay }) => {
        // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
        // intensity - (可选参数) 光照强度。 缺省值 1。
        // distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
        // decay - 沿着光照距离的衰退量。缺省值 2。
        return new THREE.PointLight(color, intensity, distance, decay);
    }
    createPlaneGeometry = ({width, height, widthSegments, heightSegments}) => {
        return new THREE.PlaneGeometry(width, height, widthSegments, heightSegments);
    }
    createMeshPlaneMaterial = (data) => {
        return new THREE.MeshLambertMaterial(data);
    }
    createMesh = ({geometry, materialBasic}) => {
        return new THREE.Mesh(geometry, materialBasic);
    }
    createAxesHelper = (length) => {
        return new THREE.AxesHelper(length)
    }
    createControl = (camera, dom) => {
        return new OrbitControls(camera, dom);
    };
}

export default NetAnimation

如果电脑性能不错,可以考虑使用以下netAnimation2.js源码

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

class NetAnimation {
    constructor(opt) {
        this.dom = opt.dom
        this.w = null
        this.h = null
        this.netMaxY = opt.netMaxY

        this.scene = null

        this.renderer = null

        this.camera = null
        this.cameraAttr = opt.cameraAttr

        this.ambientLight = null
        this.ambientLightAttr = opt.ambientLightAttr

        this.pointLights = []
        this.pointLightsAttr = opt.pointLightsAttr

        this.axesHelper = null
        this.axesHelperAttr = opt.axesHelperAttr

        this.control = null
        this.controlAttr = opt.controlAttr

        this.points = []
        this.lines = []
        this.isSameNormalStyle = opt.isSameNormalStyle
        this.pointAttr = opt.pointAttr
        this.lineAttr = opt.lineAttr
        this.pointsAttr = []
        this.linesArrt = []

        this.animationIndex = 0
        this.requestAnimationFrame = null

        this.init()
    }
    init = () => {
        if(!this.dom){
            return
        }
        this.w = this.dom.clientWidth * (window.devicePixelRatio || 1)
        this.h = this.dom.clientHeight * (window.devicePixelRatio || 1)

        // 创建场景
        this.scene = this.createScene()

        // 创建render
        this.renderer = this.createWebGLRenderer({dom: this.dom});

        // 创建相机
        const cameraAttr = {
            style: {
                fov: 45,
                aspect: this.w / this.h,
                near: 0.01,
                far: 10000
            },
            position: {
                x: this.w / 2,
                y: this.w / 2,
                z: this.h * 2
            }
        }
        if(this.cameraAttr){
            this.cameraAttr = Object.assign(cameraAttr, this.cameraAttr)
        }else{
            this.cameraAttr = cameraAttr
        }
        this.camera = this.createPerspectiveCamera(this.cameraAttr.style)
        this.camera.position.set(this.cameraAttr.position.x, this.cameraAttr.position.y, this.cameraAttr.position.z);
        this.camera.lookAt(this.scene.position);

        // 创建环境光
        const ambientLightAttr = {
            show: true,
            style: {
                color: "#fff",
                intensity: 0.1
            }
        }
        if(this.ambientLightAttr){
            this.ambientLightAttr = Object.assign(ambientLightAttr, this.ambientLightAttr)
        }else{
            this.ambientLightAttr = ambientLightAttr
        }
        if(this.ambientLightAttr.show){
            this.ambientLight = this.createAmbientLight(this.ambientLightAttr.style);
            // this.scene.add(this.ambientLight);
        }

        // 创建点光源
        if(!this.netMaxY){
            this.netMaxY = 100
        }
        const pointLightAttr =  [{
            style: {
                color: '#fff',
                intensity: 0.8,
                distance: this.w
            },
            position: {
                x: this.w * 0.1,
                y: this.netMaxY * 4,
                z: 0
            }
        },{
            style: {
                color: '#fff',
                intensity: 1,
                distance: this.w
            },
            position: {
                x: - this.w * 0.2,
                y: this.netMaxY * 4,
                z: - this.netMaxY * 4
            }
        },{
            style: {
                color: '#fff',
                intensity: 1,
                distance: this.w
            },
            position: {
                x: this.w,
                y: this.netMaxY * 4,
                z: this.netMaxY * 4
            }
        }]
        if(this.pointLightsAttr?.length){
            this.pointLightsAttr.forEach((pointLightItem, pointLightIndex) => {
                pointLightItem = Object.assign(pointLightAttr[pointLightIndex % pointLightAttr.length], pointLightItem)

                const pointLight = this.createPointLight(pointLightItem.style);
                pointLight.position.set(pointLightItem.position.x, pointLightItem.position.y, pointLightItem.position.z);
                this.pointLights.push(pointLight)
            })
            this.scene.add(...this.pointLights);
        }

        // 创建辅助线
        const axesHelperAttr = {
            show: false,
            length: 100
        }
        if(this.axesHelperAttr){
            this.axesHelperAttr = Object.assign(axesHelperAttr, this.axesHelperAttr)
        }else{
            this.axesHelperAttr = axesHelperAttr
        }
        if(this.axesHelperAttr.show){
            this.axesHelper = this.createAxesHelper(this.axesHelperAttr.length)
            this.scene.add(this.axesHelper);
        }

        // 创建轨道控制
        const controlAttr = {
            show: false
        }
        if(this.controlAttr){
            this.controlAttr = Object.assign(controlAttr, this.controlAttr)
        }else{
            this.controlAttr = controlAttr
        }
        if(this.controlAttr.show){
            this.createControl(this.camera, this.dom);
        }

        // 创建点、线
        console.time('a')
        this.initPointLineData()
        if(this.pointsAttr?.length){
            // 点geometry、material
            // let pointGeometry = null
            // let pointMaterial = null
            // let pointmMesh = null
            // 线geometry、material
            let lineMaterial = null
            if(this.isSameNormalStyle === undefined){
                this.isSameNormalStyle = true
                // pointGeometry = this.createSphereGeometry(this.pointAttr.style.normal.geometry);
                // pointMaterial = this.createMeshLambertMaterial(this.pointAttr.style.normal.material);
                // pointmMesh = this.createMesh({geometry: pointGeometry, materialBasic: pointMaterial});

                lineMaterial = this.createMeshLineMaterial(this.lineAttr.style.normal.material);
            }
            // this.pointsAttr.forEach(pointAttrItem => {
            //     // 创建点Mesh
            //     let mesh = null
            //     if(!this.isSameNormalStyle){
            //         pointGeometry = this.createSphereGeometry(pointAttrItem.style.normal.geometry);
            //         pointMaterial = this.createMeshLambertMaterial(pointAttrItem.style.normal.material);
            //         mesh = this.createMesh({geometry: pointGeometry, materialBasic: pointMaterial});
            //     }else{
            //         mesh = pointmMesh.clone();
            //     }
            //     mesh.position.set(pointAttrItem.position.x, pointAttrItem.position.y, pointAttrItem.position.z);
            //     this.points.push(mesh)
            // })
            this.linesArrt.forEach(lineAttrItem => {
                // 创建线Mesh
                let linePositions = []
                lineAttrItem.forEach(linePoint => {
                    let i = (linePoint.row * this.pointAttr.col) + linePoint.col
                    linePositions.push({
                        ...this.pointsAttr[i].position
                    })
                })
                const lineGeometry = this.createLineGeometry(linePositions);
                // if(!this.isSameNormalStyle){
                //     lineMaterial = this.createMeshLineMaterial(lineAttrItem.style.normal.material);
                // }
                const lineMesh = this.createMesh({geometry: lineGeometry, materialBasic: lineMaterial});
                this.lines.push(lineMesh)
            })

            // this.scene.add(...this.points);
            this.scene.add(...this.lines);
        }
        console.timeEnd('a')

        // 渲染
        this.render()
    }
    initPointLineData() {
        const pointAttr = {
            width: this.w,
            height: Math.floor(this.w / 2),
            row: Math.floor(this.w / 40),
            col: Math.floor(this.w / 20),
            // width: this.w * 2,
            // height: this.w,
            // row: this.w / 20,
            // col: this.w / 10,
            // row: 10,
            // col: 10,
            style: {
                normal: {
                    geometry: {
                        radius: 3,
                        widthSegments: 320,
                        heightSegments: 160,
                    },
                    material: {
                        color: "#ffffff",
                        wireframe: false, //是否将几何体渲染为线框,默认值为false(即渲染为平面多边形)
                    },
                },
                light: {
                    geometry: {
                        radius: 1,
                        widthSegments: 320,
                        heightSegments: 160,
                    },
                    material: {
                        color: "#ffffff",
                        wireframe: false,
                    },
                }
            }
        }
        if(this.pointAttr){
            this.pointAttr = Object.assign(pointAttr, this.pointAttr)
        }else{
            this.pointAttr = pointAttr
        }

        const lineAttr = {
            style: {
                normal: {
                    material: {
                        color: "#fff",
                        // color: "#3587C7",
                        linewidth: 1,
                    },
                },
                light: {
                    material: {
                        color: "#ffffff",
                        linewidth: 1,
                    },
                }
            }
        };
        if(this.lineAttr){
            this.lineAttr = Object.assign(lineAttr, this.lineAttr)
        }else{
            this.lineAttr = lineAttr
        }

        const startX = -this.pointAttr.width / 2
        const startZ = -this.pointAttr.height / 2
        const stepX = this.pointAttr.width / this.pointAttr.col
        const stepZ = this.pointAttr.height / this.pointAttr.row
        const sinXNum = this.pointAttr.row / 4
        const sinZNum = this.pointAttr.col / 4
        for(let i = 0 ; i < this.pointAttr.row; i++){
            for(let j = 0 ; j < this.pointAttr.col; j++){
                const x = startX + j * stepX
                const z = startZ + i * stepZ
                const y = (Math.sin((i % sinXNum / sinXNum * Math.PI * 2)) + Math.sin(((j + i) % sinZNum / sinZNum * Math.PI * 2))) * (this.netMaxY / 2)
                this.pointsAttr.push({
                    row: i,
                    col: j,
                    position: {
                        x, y, z
                    },
                    style: {...this.pointAttr.style}
                })

                if(!this.linesArrt[i]){
                    this.linesArrt[i] = []
                }
                this.linesArrt[i][j] = {
                    row: i,
                    col: j
                }
                if(!this.linesArrt[this.pointAttr.row + j]){
                    this.linesArrt[this.pointAttr.row + j] = []
                }
                this.linesArrt[this.pointAttr.row + j][i] = {
                    row: i,
                    col: j
                }
            }
        }
    }
    render = () => {
        //循环调用
        this.requestAnimationFrame = requestAnimationFrame(this.render);
        this.animation()
        this.renderer.render(this.scene, this.camera);
    }
    unmount = () => {
        cancelAnimationFrame(this.requestAnimationFrame)
    }
    animation = () => {
        const sinXNum = this.pointAttr.row / 4
        const sinZNum = this.pointAttr.col / 4
        const count = this.pointAttr.row * this.pointAttr.col
        const animationSpeed = 10 //值越大越慢
        console.time('b')
        // if(this.animationIndex % 10 === 0){
            this.pointsAttr.forEach((pointAttrItem, pointAttrIndex) => {
                const i = pointAttrItem.row
                const j = pointAttrItem.col
                pointAttrItem.position.y = (Math.sin(((i + this.animationIndex / animationSpeed) % sinXNum / sinXNum * Math.PI * 2)) + Math.sin(((j + i + this.animationIndex / animationSpeed) % sinZNum / sinZNum * Math.PI * 2))) * 30
            })
            this.linesArrt.forEach((lineAttrItem, lineAttrIndex) => {
                let linePositions = []
                lineAttrItem.forEach(linePoint => {
                    let i = (linePoint.row * this.pointAttr.col) + linePoint.col
                    let point = this.pointsAttr[i]
                    linePositions.push({
                        ...point.position
                    })
                })
                const lineGeometry = this.createLineGeometry(linePositions);
                this.updateGeometry(this.lines[lineAttrIndex].geometry, lineGeometry)
            })
        // }
        console.timeEnd('b')
        this.animationIndex++
        this.animationIndex %= count * animationSpeed
    }
    updateGeometry = (geometry, geometry_source) => {
        const att_p = geometry.getAttribute('position');
        const att_ps = geometry_source.getAttribute('position');
        let i = 0;
        while(i < att_p.count){
            att_p.setXYZ( i, att_ps.getX(i), att_ps.getY(i),att_ps.getZ(i) );
            i += 1;
        }
        att_p.needsUpdate = true;
        geometry.computeVertexNormals();
    };
    rand = (n,m) => {
        var c = m - n + 1;
        return Math.floor(Math.random() * c + n);
    }    
    // 以下皆为实体创建方法
    createScene = () => {
        return new THREE.Scene();
    }
    createPerspectiveCamera = ({ fov, aspect, near, far }) => {
        // fov — 摄像机视锥体垂直视野角度
        // aspect — 摄像机视锥体长宽比
        // near — 摄像机视锥体近端面
        // far — 摄像机视锥体远端面
        return new THREE.PerspectiveCamera(fov, aspect, near, far);
    }
    createWebGLRenderer = ({ dom, width, height }) => {
        // renderDom — dom
        // width — 渲染宽度 一般取domclientWidth
        // height — 渲染高度 一般取clientHeight
        if (width === undefined) {
            width = dom.clientWidth;
        }
        if (height === undefined) {
            height = dom.clientHeight;
        }
        const renderer = new THREE.WebGLRenderer();
        renderer.setPixelRatio(window.devicePixelRatio || 1);
        renderer.setClearColor('#fff', 0); //设置背景颜色和透明度
        renderer.setSize(width, height);
        dom.appendChild(renderer.domElement);
    
        return renderer;
    }
    createAmbientLight = ({ color, intensity }) => {
        // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
        // intensity - (可选参数) 光照强度。 缺省值 1。
        return new THREE.AmbientLight(color, intensity);
    }
    createPointLight = ({ color, intensity, distance, decay }) => {
        // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
        // intensity - (可选参数) 光照强度。 缺省值 1。
        // distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
        // decay - 沿着光照距离的衰退量。缺省值 2。
        return new THREE.PointLight(color, intensity, distance, decay);
    }
    createSphereGeometry = ({
        radius,
        widthSegments,
        heightSegments,
        phiStart,
        phiLength,
        thetaStart,
        thetaLength
    }) => {
        /*
            radius — 球体半径,默认为1。
            widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。
            heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。
            phiStart — 指定水平(经线)起始角度,默认值为0。。
            phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。
            thetaStart — 指定垂直(纬线)起始角度,默认值为0。
            thetaLength — 指定垂直(纬线)扫描角度大小,默认值为 Math.PI。
        */
        return new THREE.SphereGeometry(
            radius,
            widthSegments,
            heightSegments,
            phiStart,
            phiLength,
            thetaStart,
            thetaLength
        );
    }
    createMeshLambertMaterial = (data) => {
        return new THREE.MeshLambertMaterial(data);
    }
    createLineGeometry = (points) => {
        // const pointsVector3 = [];
        // for (let i = 0; i < points.length; i++) {
        //     pointsVector3.push(new THREE.Vector3(points[i].x, points[i].y, points[i].z));
        // }
        // const geometry = new THREE.BufferGeometry().setFromPoints(pointsVector3);
        // const line = new MeshLine();
        // line.setGeometry(geometry);
        // return line
        let pointsVector3 = []
        points.forEach(point => {
            pointsVector3.push(new THREE.Vector3(point.x, point.y, point.z))
        })
        let curve = new THREE.CatmullRomCurve3(pointsVector3);
        var CurvePath = new THREE.CurvePath();// 创建CurvePath对象
	    // CurvePath.curves.push(line1, curve, line2);// 插入多段线条
	    CurvePath.curves.push(curve);
        return new THREE.TubeGeometry(CurvePath, points.length * 10, 1, 25, false);
    }
    createMeshLineMaterial = (data) => {
        // return new MeshLineMaterial({
        //     lineWidth: data.linewidth,
        //     color: data.color || "white",
        //     dashArray: data.dashArray || 0,
        //     transparent: true,
        // })
        return new THREE.MeshLambertMaterial({
            color: data.color || "white"
        });
    }
    createMesh = ({geometry, materialBasic}) => {
        return new THREE.Mesh(geometry, materialBasic);
    }
    createAxesHelper = (length) => {
        return new THREE.AxesHelper(length)
    }
    createControl = (camera, dom) => {
        return new OrbitControls(camera, dom);
    };
}

export default NetAnimation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/277260.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第四节 参数传递对堆栈的影响 1

深入浅出图解C#堆与栈 C# Heaping VS Stacking 第四节 参数传递对堆栈的影响1 [深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈](https://mp.csdn.net/mdeditor/101021023)[深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理](http…

嵌入式开发——ADC开发

学习目标 了解ADC开发流程掌握采样方式能够使用ADC进行芯片内部通道进行采样能够使用ADC对外部电路进行采样学习内容 GD32F4的ADC 特点: 16个外部模拟输入通道;1个内部温度传感通道(VSENSE);1个内部参考电压输入通道(VREFINT);1个外部监测电池VBAT供电引脚输入通道。ADC开…

C++ BuilderXE10 关于Intraweb关于IWTemplateProcessorHTML1操作

1、端口设置,port参数修改端口号。 2、初始化设置成ciMultiThreaded。这样可以避免ADO组件的加载错误。 3、IWTemplateProcessorHTML1设置&#xff0c; IWForm1->LayoutMgr IWTemplateProcessorHTML1;//关联模板(IWForm1. html) IWTemplateProcessorHTML1->RenderStyles…

独立容器 Rancher Server 证书过期解决

问题 Rancher无法登录 容器报错X509&#xff1a;certificate has expired or is not ye valid 在某天需要发布新版本的时候&#xff0c;发现rancher无法登录&#xff0c;于是到服务器上查看rancher日志&#xff0c;发现以下内容&#xff1a; docker logs -f rancher --since10…

ClickHouse基础知识(五):ClickHouse的SQL 操作

基本上来说传统关系型数据库&#xff08;以 MySQL 为例&#xff09;的 SQL 语句&#xff0c;ClickHouse 基本都支持&#xff0c; 这里不会从头讲解 SQL 语法只介绍 ClickHouse 与标准 SQL&#xff08;MySQL&#xff09;不一致的地方。 1. Insert 基本与标准 SQL&#xff08;My…

探索 EndNote:卓越文献管理工具的功能与应用

引言 在当今科研与学术写作的领域&#xff0c;文献管理是每一位研究者都不可避免面对的挑战。为了有效地整理、引用和协作&#xff0c;研究者需要强大而灵活的文献管理工具。EndNote作为一款备受推崇的文献管理软件&#xff0c;在解决这一问题上发挥着关键作用。本文将深入探讨…

手写操作系统 - 汇编实现进入保护模式

前言 在了解段页门得基础上&#xff0c;理解如何从实时模式进入保护模式如何引入C语言得开发与调试 生成内核&#xff1a;汇编与C语言如何生成内核调试C语言汇编、C语言如何互调 手写64位操作系统内核规划图&#xff1a; boot程序起始0扇区&#xff0c;共占1个扇区 setup程…

数字化时代背景下服装表演创新研究

服装表演是一门独具魅力的艺术,它既高于生活,又来源于生活。这一艺术形式通过舞台上的服装、音乐、舞蹈和表演艺术家的表现力,将时尚与创意融为一体,向观众传递着独特的美感和情感。然而,如今,我们生活在一个飞速发展的数字化时代,这为服装表演的教育带来了前所未有的机遇和挑战…

NCNN环境部署及yolov5pt转ncnn模型转换推理

该内容还未完整&#xff0c;笔记内容&#xff0c;持续补充。 〇开发环境版本 vs2022 cmake3.21.1 ncnn20231027发行版 yolov5s v6.2 vunlkan1.2.198.1 Protobuf3.20.0 Opencv3.4.1 一、模型转换 yolov5s v6.2训练的pt模型&#xff0c;直接导出tourchscript&#xff0c…

帆软报表中定时调度中使用自己的短信平台,并且不使用官方商城里的模板

1 当我们在定时调度里中完成某些任务后,需要通过短信平台来发送一些短信,此时的配置界面是这样的: 此时需要帆软市场,并且短信模板只能使用帆软市场里配置的短信模板。 限制太多,使用起来非常不方便,如果我们想要使用自己的短信签名,并且使用自己的短信发送平台。那么可…

ebay会员收费吗,ebay会员活动的权益有哪些?-站斧浏览器

ebay会员收费吗&#xff1f; 是的&#xff0c;ebay会员是需要付费的。不过&#xff0c;ebay也提供了免费试用期&#xff0c;让你可以在成为正式会员之前先行体验各项权益。 试用期结束后&#xff0c;你可以选择是否继续付费成为正式会员。对于经常使用ebay购物的用户来说&…

前端使用高德api的AMap.Autocomplete无效,使用AMap.Autocomplete报错

今天需要一个坐标拾取器&#xff0c;需要一个输入框输入模糊地址能筛选的功能 查看官方文档&#xff0c;有一个api可以直接满足我们的需求 AMap.Autocomplete 上代码 AMapLoader.load({"key": "你的key", // 申请好的Web端开发者Key&#xff0c;首次调…

linux cuda环境搭建

1&#xff0c;检查驱动是否安装 运行nvidia-smi&#xff0c;如果出现如下界面&#xff0c;说明驱动已经安装 记住cuda版本号 2&#xff0c;安装cudatoolkit 上官网CUDA Toolkit Archive | NVIDIA Developer 根据操作系统选择对应的toolkit 如果已经安装了驱动&#xff0c;选…

win32 WM_MENUSELECT消息学习

之前写了一些win32的程序&#xff0c;处理菜单单击都是处理WM_COMMAND消息&#xff0c;通过 LOWORD(wParam) 获取菜单ID&#xff0c;判断单击的是哪个菜单项&#xff1b; 还有一些其他菜单消息&#xff1b; 当在菜单项中移动光标或鼠标&#xff0c;程序会收到许多WM_MENUSELEC…

Hive讲课笔记:内部表与外部表

文章目录 一、导言二、内部表1.1 什么是内部表1.1.1 内部表的定义1.1.2 内部表的关键特性 1.2 创建与操作内部表1.2.1 创建并查看数据库1.2.2 在park数据库里创建student表1.2.3 在student表插入一条记录1.2.4 通过HDFS WebUI查看数据库与表 三、外部表2.1 什么是外部表2.2 创建…

Arduino stm32 USB CDC虚拟串口使用示例

Arduino stm32 USB CDC虚拟串口使用示例 &#x1f4cd;相关篇《STM32F401RCT6基于Arduino框架点灯程序》&#x1f516;本开发环境基于VSCode PIO&#x1f33f;验证芯片&#xff1a;STM32F401RC⌛USB CDC引脚&#xff1a; PA11、 PA12&#x1f527;platformio.ini配置信息&…

Spring 是如何解决循环依赖的

1.什么是循环依赖? 所谓的循环依赖是指&#xff0c;A 依赖 B&#xff0c;B 又依赖 A&#xff0c;它们之间形成了循环依赖。或者是 A 依赖 B&#xff0c;B 依赖 C&#xff0c;C 又依赖 A。它们之间的依赖关系如下&#xff1a; 2.通过手写代码演示理解Spring循环依赖 DEMO: pu…

Mini MyBatis-Plus(下)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 最核心的内容前两篇已经…

docker 安装可视化工具 Protainer 以及 汉化

一、创建保存数据的卷 安装网址&#xff1a;Install Portainer BE with Docker on Linux - Portainer Documentation docker pull portainer/portainer二、根据portainer镜像创建容器 docker run -d -p 8000:8000 -p 9000:9000\ --name portainer --restartalways \ -v /var/r…

【Python_PySide2学习笔记(二十)】消息对话框QMessageBox类的基本用法

消息对话框QMessageBox类的基本用法 消息对话框QMessageBox类的基本用法前言正文1、警告对话框 QMessageBox.warning()2、消息对话框 QMessageBox.information()3、提问对话框 QMessageBox.question()4、错误对话框 QMessageBox.critical()5、关于对话框 QMessageBox.about()6、…