代码

100 阅读3分钟

代码

<template>
    <div>
        <div id="my-three">
        </div>        
    </div>
</template>
​
<script setup>
    import * as THREE from 'three'
    import { BackSide } from 'three';
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
    import { onMounted,watch  } from 'vue'
    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
    import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
    import {EffectComposer} from 'three/examples/jsm/postprocessing/EffectComposer.js';
    import {RenderPass} from 'three/examples/jsm/postprocessing/RenderPass.js';
    import {ShaderPass} from 'three/examples/jsm/postprocessing/ShaderPass.js';
    import {OutlinePass} from 'three/examples/jsm/postprocessing/OutlinePass.js';
    import {FXAAShader} from 'three/examples/jsm/shaders/FXAAShader.js';
    import Stats from 'three/addons/libs/stats.module.js';
    import gsap from 'gsap'
    import { TweenMax, Power0 } from "gsap";
    import * as dat from "dat.gui"
    import nipplejs from 'nipplejs';
    let stats = new Stats();
    let mixer; 
    let lastTime = 0;
    let composer, effectFXAA, outlinePass,outlineColor=['#fff','#c40000'],selectedObjects,mesh;
    const raycaster = new THREE.Raycaster();
    const mouse = new THREE.Vector2();
    let meshes = [],
    clonemeshes = [];
    const clock = new THREE.Clock();

    //创建一个三维场景
    const scene = new THREE.Scene();
    scene.background = new THREE.Color( 0xbfd1e5 );

    const vertices1 = [];//model1的点位
    const vertices2 = [];//model2的点位

    const ambientLight = new THREE.AmbientLight( 0xbbbbbb );
    scene.add( ambientLight );

    const light = new THREE.DirectionalLight( 0xffffff, 5 );
    light.position.set( 10, 10, 5 );
    light.castShadow = true;
    const d = 10;
    light.shadow.camera.left = - d;
    light.shadow.camera.right = d;
    light.shadow.camera.top = d;
    light.shadow.camera.bottom = - d;

    light.shadow.camera.near = 2;
    light.shadow.camera.far = 50;

    light.shadow.mapSize.x = 1024;
    light.shadow.mapSize.y = 1024;

    scene.add( light );

    //创建一个透视相机,窗口宽度,窗口高度
    const width = window.innerWidth, height = window.innerHeight;
    const camera = new THREE.PerspectiveCamera(45, width/height, 1, 1000);
    //设置相机位置
    camera.position.set(5,1,6)
    //设置相机方向
    //camera.lookAt(0,0,0);

    //创建辅助坐标轴
    const axesHelper = new THREE.AxesHelper(200);//参数200标示坐标系大小,可以根据场景大小去设置
    //scene.add(axesHelper);

    //创建一个WebGL渲染器
    const renderer = new THREE.WebGLRenderer()
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize(width,height)//设置渲染区尺寸
    renderer.shadowMap.enabled = true;
    renderer.render(scene,camera)//执行渲染操作、指定场景、相机作为参数

    const axis = new THREE.Vector3(1,1,1);//向量axis
    //mesh.rotateOnAxis(axis,Math.PI/8);//绕axis轴旋转π/8

    const gridHelper = new THREE.GridHelper(10, 100, 0x004444, 0x004444);
    scene.add(gridHelper);
    

    const controls = new OrbitControls(camera, renderer.domElement)//创建控件对象
    controls.addEventListener('change',()=>{
        renderer.render(scene, camera)//监听鼠标,键盘事件
    })

    // 添加高亮效果
    renderer.domElement.addEventListener( 'pointermove', onPointerMove );

    const size = renderer.getSize(new THREE.Vector2());
    const _pixelRatio = renderer.getPixelRatio();
    const _width = size.width;
    const _height = size.height;

    const renderTarget = new THREE.WebGLRenderTarget(
        _width * _pixelRatio,
        _height * _pixelRatio,
        {
            minFilter: THREE.LinearFilter,
            magFilter: THREE.LinearFilter,
            format: THREE.RGBAFormat,
            encoding: THREE.sRGBEncoding
        }
    );

    renderTarget.texture.name = "EffectComposer.rt1";
    composer = new EffectComposer(renderer, renderTarget);

    const renderPass = new RenderPass(scene, camera);
    composer.addPass(renderPass);

    outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera);
    composer.addPass(outlinePass);

    effectFXAA = new ShaderPass(FXAAShader);
    effectFXAA.uniforms['resolution'].value.set(1 / window.innerWidth, 1 / window.innerHeight);
    composer.addPass(effectFXAA);

    outlinePass.visibleEdgeColor.set(outlineColor[0]); // 边缘可见部分发颜色 sColor[0].color
    outlinePass.hiddenEdgeColor.set(outlineColor[1]); // 边缘遮挡部分发光颜色 sColor[1].color
    outlinePass.edgeStrength = Number(10.0); //边框的亮度
    outlinePass.edgeGlow = Number(1); //光晕[0,1]
    outlinePass.edgeThickness = Number(1.0); //边缘浓度
    outlinePass.pulsePeriod = Number(1.8); //呼吸闪烁的速度 闪烁频率 ,默认0 ,值越大频率越低
    outlinePass.usePatternTexture = false; //是否使用父级的材质
    outlinePass.downSampleRatio = 2; // 边框弯曲度
    outlinePass.clear = true;



    controls.minDistance = 1.5
    controls.maxDistance = 50;
    onMounted(()=>{
        document.getElementById('my-three')?.appendChild( stats.dom );
        document.getElementById('my-three')?.appendChild(renderer.domElement)

        // shownipple()
    })

    controls.enablePan = true
    controls.enableDamping = true

    animate()
    function animate(currentTime){
        //mesh.rotateOnAxis(axis.normalize(),0.1);//绕axis轴旋转π/8
        const deltaTime = (currentTime - lastTime) / 1000;
        lastTime = currentTime;
        if (mixer) {
            mixer.update(deltaTime); // deltaTime is the time since the last frame
        }
        
        controls.update();
        stats.update();
        renders()
        requestAnimationFrame(animate);
        renderer.render(scene,camera)
    }


    let model
    let pointCloud,pointCloud2,pointCloudGeometry,pointCloudGeometry2,pointCloudMaterial
    let modelOpacity = 0;
    addmodel()
    function addmodel(){
        new RGBELoader()
        .setPath( './model/hdr/' )
        .load( '33.hdr', function ( texture ) {

            texture.mapping = THREE.EquirectangularReflectionMapping;

            scene.background = texture;
            scene.environment = texture;

            renderer.render( scene, camera )

            const loader = new GLTFLoader();
                // 加载地图模型
                loader.load('./model/robot/sicrun.glb', function(gltf){
                    //将模型添加至场景
                    // 将模型添加至场景    
                    model = gltf.scene//.children[0];
                    scene.add( model )
                    
                    model.traverse((child) => {
                        if (child instanceof THREE.Mesh) {
                            const geometry = child.geometry;
                            //设置透明度  设置为透明
                            child.material.transparent = true;
                            child.material.opacity = modelOpacity;

                            if (geometry instanceof THREE.BufferGeometry) {
                                const position = geometry.attributes.position.array;
                                for (let i = 0; i < position.length; i += 3) {
                                    vertices1.push(new THREE.Vector3( position[i], position[i + 1], position[i + 2]));
                                }
                            }
                        }
                    });

                    // 创建点云对象
                    pointCloudGeometry = new THREE.BufferGeometry().setFromPoints(vertices1);
                    pointCloudMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.03 }); // 调整点的大小和颜色
                    pointCloud = new THREE.Points(pointCloudGeometry, pointCloudMaterial);

                    // 将点云添加到场景中
                    scene.add(pointCloud);
                    
                    let mxposition = pointCloudGeometry.attributes.position
                    createMesh( mxposition, scene, 4.05, - 500, - 350, 600, 0xff7744 );
                })
        } );
    }

    function checkIntersection() {
        raycaster.setFromCamera( mouse, camera );
        const intersects = raycaster.intersectObject( scene, true );
        if ( intersects.length > 0 ) {
            const selectedObject = intersects[ 0 ].object;
            addSelectedObject( selectedObject );
            outlinePass.selectedObjects = selectedObjects;
        } else {
            // outlinePass.selectedObjects = [];
        }
    }

    function addSelectedObject( object ) {
        selectedObjects = [];
        selectedObjects.push( object );
    }

    function onPointerMove( event ) {
        if ( event.isPrimary === false ) return;
        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
        checkIntersection();
    }

    function createMesh( positions, scene, scale, x, y, z, color ) {
        const geometry = new THREE.BufferGeometry();
        geometry.setAttribute( 'position', positions.clone() );
        geometry.setAttribute( 'initialPosition', positions.clone() );
        geometry.attributes.position.setUsage( THREE.DynamicDrawUsage );
        const clones = [
            [ 0, 0, 0 ]
        ];
        for ( let i = 0; i < clones.length; i ++ ) {
            const c = ( i < clones.length - 1 ) ? 0x252525 : color;
            mesh = new THREE.Points( geometry, new THREE.PointsMaterial( { size: 30, color: c } ) );
            mesh.scale.x = mesh.scale.y = mesh.scale.z = scale;
            mesh.position.x = x + clones[ i ][ 0 ];
            mesh.position.y = y + clones[ i ][ 1 ];
            mesh.position.z = z + clones[ i ][ 2 ];
            clonemeshes.push( { mesh: mesh, speed: 0.5 + Math.random() } );
        }
        meshes.push( {
            mesh: mesh, 
            verticesDown: 0, 
            verticesUp: 0, 
            direction: 0, 
            speed: 15, 
            delay: Math.floor( 200 + 200 * Math.random() ),
            start: Math.floor( 100 + 200 * Math.random() ),
        } );
    }
    function renders(){
        let delta = 10 * clock.getDelta();
		delta = delta < 2 ? delta : 2;
        for ( let j = 0; j < meshes.length; j ++ ) {
            const data = meshes[ j ];
            const positions = data.mesh.geometry.attributes.position;
            const initialPositions = data.mesh.geometry.attributes.initialPosition;
            const count = positions.count;
            if ( data.start > 0 ) {
                data.start -= 1;
            } else {
                if ( data.direction === 0 ) {
                    data.direction = - 1;
                }
            }
            for ( let i = 0; i < count; i ++ ) {
                const px = positions.getX( i );
                const py = positions.getY( i );
                const pz = positions.getZ( i );
                // falling down
                if ( data.direction < 0 ) {
                    if ( py > 0 ) {
                        debugger
                        positions.setXYZ(
                            i,
                            px + 1.5 * ( 0.50 - Math.random() ) * data.speed * delta,
                            py + 3.0 * ( 0.25 - Math.random() ) * data.speed * delta,
                            pz + 1.5 * ( 0.50 - Math.random() ) * data.speed * delta
                        );
                    } else {
                        data.verticesDown += 1;
                    }
                }
            }
            console.log(positions)
            positions.needsUpdate = true;
            }
    }
   
</script>
​
<style lang='less'>
    body{
        margin: 0;
        padding: 0;
    }
    .my-three{
       
    }
    .buttons{
        position: fixed;
        right: 10px;
        top: 10px;
    }
</style>