three.js绘制网波浪

news2025/1/20 1:46:15

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

使用方法(以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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面向搜索引擎优化初学者的 Google PageRank

即使你认为搜索已经摆脱了 PageRank 的影响&#xff0c;但时至今日&#xff0c;PageRank 很可能仍然存在于许多搜索巨头的系统中。 PageRank 曾经是搜索的核心&#xff0c;也是谷歌成为今天这个帝国的基础。 即使你认为搜索已经脱离了 PageRank&#xff0c;但不可否认的是&am…

阶段性复习(三)

if后面是赋值符&#xff0c;所以最后的值是a for&#xff08;&#xff1b; &#xff1b;&#xff09;是死循环 大小写转换 在这道题中&#xff0c;通过分析可知&#xff0c;在小写转换大写的过程中&#xff0c;需要满足的条件是word0&#xff0c;同时是小写&#xff0c;而在第…

Oracle 19c OCP 1z0 082考场真题解析第17题

考试科目&#xff1a;1Z0-082 考试题量&#xff1a;90 通过分数&#xff1a;60% 考试时间&#xff1a;150min 本文为云贝教育郭一军guoyJoe原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 17. Which three …

[C#]opencvsharp进行图像拼接普通拼接stitch算法拼接

介绍&#xff1a; opencvsharp进行图像拼一般有2种方式&#xff1a;一种是传统方法将2个图片上下或者左右拼接&#xff0c;还有一个方法就是融合拼接&#xff0c;stitch拼接就是一种非常好的算法。opencv里面已经有stitch拼接算法因此我们很容易进行拼接。 效果&#xff1a; …

Linux网络编程学习心得.5

1.libevent编写tcp服务器流程 创建套接字 绑定 监听 创建event_base根节点 初始化上树节点 lfd 上树 循环监听 收尾 普通的event事件 文件描述符 事件(底层缓冲区的读事件或者写事件) 触发 回调 高级的event事件 bufferevent事件 核心: 一个文件描述符 两…

【力扣题解】P654-最大二叉树-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P654-最大二叉树-Java题解&#x1f30f;题目描述&#x1f4a1;题解&#x1f30f;总结…

【Linux操作系统】探秘Linux奥秘:操作系统的入门与实战

&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;诗赋清音&#xff1a;柳垂轻絮拂人衣&#xff0c;心随风舞梦飞。 山川湖海皆可涉&#xff0c;勇者征途逐星辉。 目录 &#x1fa90;1 初识Linux OS …

【BERT】深入BERT模型2——模型中的重点内容,两个任务

前言 BERT出自论文&#xff1a;《BERT&#xff1a;Pre-training of Deep Bidirectional Transformers for Language Understanding》 2019年 近年来&#xff0c;在自然语言处理领域&#xff0c;BERT模型受到了极为广泛的关注&#xff0c;很多模型中都用到了BERT-base或者是BE…

Spring AOP<一>简介与基础使用

spring AOP 基础定义 含义使用切面组织多个Advice,Advice放在切面中定义。也就是说是定义通知的自定义类。自定义的AOP类Aspect连接点方法调用&#xff0c;异常抛出可以增强的点JoinPoint &#xff1a;也就是**被增强的方法的总称&#xff0c;可以获取具体方法的信息&#xff…

结构体:枚举

#include<iostream> using namespace std; int main() {enum weekday { mon, tus, wed, thu, fri, sat,sun }; //声明枚举类型 enum weekday day; //定义枚举变量 int a, b, c, d, e, f, g, loop; //定义整型变量 char ch A; //定义字符变量 f thu; //按照题意&a…

华为服务器安装银河麒麟V10操作系统(IBMC安装)

iBMC是华为面向服务器全生命周期的服务器嵌入式管理系统。提供硬件状态监控、部署、节能、安全等系列管理工具&#xff0c;标准化接口构建服务器管理更加完善的生态系统。 服务器BMC IP&#xff1a;192.168.2.100 一、准备工作 1、确保本机和服务器BMC管理口在同一网络 2、银…

如何使用ArcGIS Pro将Excel表转换为SHP文件

有的时候我们得到的数据是一张张的Excel表格&#xff0c;如果想要在ArcGIS Pro中进行分析或者制图则需要先转换为SHP格式&#xff0c;这里为大家介绍一下转换方法&#xff0c;希望能对你有所帮助。 数据来源 本教程所使用的数据是从水经微图中下载的POI数据&#xff0c;除了P…

荔枝派nano(f1c100s)基于I2C子系统的BME280驱动

硬件环境&#xff1a; 1、荔枝派nano&#xff08;f1c100s&#xff09; 2、使用f1c100s的i2c0&#xff0c;PE11和PE12引脚 软件环境&#xff1a; 1、Linux 4.15 2、BME280使用介绍 文章目录 一、I2C子系统1、应用层访问i2c设备2、驱动层访问i2c设备2.1、i2c总线设备驱动模型2.2、…

MySQL MVCC精讲

版本链 我们前面说过&#xff0c;对于使用InnoDB存储引擎的表来说&#xff0c;它的聚簇索引记录中都包含两个必要的隐藏列&#xff08;row_id并不是必要的&#xff0c;我们创建的表中有主键或者非NULL的UNIQUE键时都不会包含row_id列&#xff09;&#xff1a; trx_id&#xff…

《纳瓦尔宝典》围观纳瓦尔的财富+幸福指南

缘分碎碎念 之前一直有书友推荐《纳瓦尔宝典》&#xff0c;一直没机会看。到2023年底了&#xff0c;想要给辛苦一年的自己一个新年礼物&#xff08;哈哈哈&#xff09;&#xff0c;就买了一个电纸书用来看书&#xff08;保护眼睛&#xff09;&#xff0c;里面刚好有《纳瓦尔宝…

相对于一般的统计学,计量经济学的特色是什么?谈Stata与计量经济学

Stata作为一种数据分析软件&#xff0c;高度适用于依托计量经济学的研究领域&#xff0c;如宏观经济学、财政学等&#xff0c;当然在医学等学科应用也较为广泛&#xff0c;在处理面板数据方面也深具特色。计量经济学是指运用概率统计方法对经济变量之间的因果关系进行定量分析的…

【实用工具】Gradio快速部署深度学习应用1:图像分类

前言 在AI快速发展的今天&#xff0c;我们作为算法开发人员&#xff0c;也应该有一些趁手的工具帮助我们快速开发并验证自己的想法&#xff0c;Gradio可以实现快速搭建和共享的功能&#xff0c;能够展示出一个前端界面&#xff0c;把我们的算法包裹起来&#xff0c;快速验证算…

python+django超市进销存仓库管理系统s5264

本次设计任务是要设计一个超市进销存系统&#xff0c;通过这个系统能够满足超市进销存系统的管理及员工的超市进销存管理功能。系统的主要功能包括&#xff1a;首页、个人中心、员工管理、客户管理、供应商管理、承运商管理、仓库信息管理、商品类别管理、由管理员和员工&#…

程序的编译、链接

目录 前言&#xff1a; 前置知识回顾 宏 宏定义常量 宏定义语句 宏定义函数 条件编译 应用场景 编译过程概览 预编译阶段 编译阶段 汇编阶段 链接阶段 前言&#xff1a; 在ANSI C的任何一种实现中&#xff0c;存在两种不同的环境&#xff0c;第1种是翻译环境&#x…

2023年03月09日_谷歌视觉语言模型PaLM-E的介绍

自从最近微软凭借OpenAI 和ChatGPT火了一把之后呢 老对手Google就总想着扳回一局 之前发布了硬刚ChatGPT的Bard 但是没想到翻车了 弄巧成拙 所以呢Google这一周又发了个大招 发布了史上最大的视觉语言模型PaLM-E 这个模型有多夸张呢 参数量高达5,620亿 是ChatGTP-3的三…