WebGL_0020:threejs 加载glb模型,加载图片贴图,加载canvas贴图,创建精灵模型并贴图,设置正交相机射线方法

1,threejs 加载glb模型

import * as THREE from 'three';
import type { MapViewer } from '@/utils/map3d/mapViewer';
import { STATIC_URL } from '@/config';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

const getSpriteMaterial = (color: THREE.Color, text: string) => {
  const canvas = document.createElement('canvas');
  canvas.width = 64;
  canvas.height = 64;

  const context: any = canvas.getContext('2d');
  context.beginPath();
  context.arc(32, 32, 16, 0, 2 * Math.PI);
  context.closePath();
  context.fillStyle = color.getStyle();
  context.fill();

  if (text) {
    context.font = '24px Arial';
    context.textAlign = 'center';
    context.fillStyle = '#FFFFFF';
    context.fillText(text, 32, 41);
  }

  const texture = new THREE.CanvasTexture(canvas);

  return new THREE.SpriteMaterial({ map: texture });
};

//WG ADD 增加获取canvas贴图方法
const getCanvasTexture = (color: THREE.Color, text: string) => {
  const canvas = document.createElement('canvas');
  canvas.width = 64;
  canvas.height = 64;
  const context: any = canvas.getContext('2d');
  context.fillStyle = 'blue';
  context.fillRect(0, 0, 100, 100);
  if (text) {
    context.font = '30px Arial';
    context.textAlign = 'center';
    context.fillStyle = '#ffffff';
    context.fillText(text, 32, 41);
  }
  const texture = new THREE.CanvasTexture(canvas);
  texture.flipY = false;
  return texture;
};

const useViewHelper = (mapViewer: MapViewer) => {
  const viewer = mapViewer.viewer;
  const helperGroup = new THREE.Group();
  const interactiveObjects: Array<THREE.Object3D> = [];

  const color1 = new THREE.Color('#ff4000');
  const color2 = new THREE.Color('#0032ff');
  const color3 = new THREE.Color('#46ff00');
  const color4 = new THREE.Color('#888888');

  const width = 150;
  const offsetX = 300;
  const viewport = new THREE.Vector4();

  const domElement = viewer.renderer.domElement;

  // const orthoCamera = new THREE.OrthographicCamera(-2, 2, 2, -2, -10, 10);
  const orthoCamera = new THREE.OrthographicCamera(-2, 2, 2, -2, -2, 2);
  // const orthoCamera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000);
  orthoCamera.position.set(0, 0, 0);
  //WG orthoCamera.rotation.order = 'ZXY';
  // orthoCamera.rotation.order = 'ZXY';
  // orthoCamera.rotation.x = Math.PI / 2;
  orthoCamera.lookAt(new THREE.Vector3(0, 0, -1));
  orthoCamera.updateMatrixWorld();

  const cameraChange = (e: any) => {
    // console.log(e.camera);
    orthoCamera.rotation.copy(e.camera.rotation);
    orthoCamera.updateMatrixWorld();
  };

  let handleMouseDown = (event: any) => {
    let mouse = new THREE.Vector2();

    const rect = domElement.getBoundingClientRect();
    const x = rect.left + domElement.clientWidth - width - offsetX;
    mouse.x = event.clientX - x;
    mouse.y = event.clientY - rect.top;

    if (mouse.x < 0 || mouse.y > width) return;

    mouse.x = (mouse.x / width) * 2 - 1;
    mouse.y = -(mouse.y / width) * 2 + 1;

    let raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, orthoCamera);
    raycaster.ray.origin.sub(orthoCamera.getWorldDirection(new THREE.Vector3()));

    let intersects = raycaster.intersectObjects(interactiveObjects);

    console.log(intersects);
    if (intersects.length > 0) {
      mapViewer.setViews(intersects[0].object.name);
    }
  };

  const renderHelper = () => {
    const x = domElement.offsetWidth - width - offsetX;
    const y = domElement.offsetHeight - width;

    viewer.renderer.getViewport(viewport);

    viewer.renderer.setViewport(x, y, width, width);

    viewer.renderer.render(helperGroup, orthoCamera);

    viewer.renderer.setViewport(viewport.x, viewport.y, viewport.z, viewport.w);
  };


  //WG ADD 增加加载模型的方法
  // function loadMod() {
  //   let terminalGeo: THREE.BufferGeometry | null = null;
  //   let gltfLoader = new GLTFLoader();
  //   let terminalMeh: THREE.Mesh | null = null;
  //   return new Promise(resovle => {
  //     gltfLoader.load(`${STATIC_URL}/model/terminal.glb`, (gltf) => {
  //       const model = gltf.scene.getObjectByName('平面') as THREE.Mesh;
  //       terminalGeo = model.geometry as THREE.BufferGeometry;
  //       const material = new THREE.MeshBasicMaterial({ color: '#e5380a' });
  //       terminalMeh = new THREE.Mesh(terminalGeo.clone(), material);
  //       helperGroup.add(terminalMeh);
  //       resovle(terminalMeh);
  //     });
  //   });
  // };
  // await loadMod();


  function create() {


    // const geometry = new THREE.BoxGeometry(0.8, 0.02, 0.02);
    // geometry.translate(0.4, 0, 0);
    // // X轴
    // const xAxis = new THREE.Mesh(
    //   geometry,
    //   new THREE.MeshBasicMaterial({
    //     color: color1,
    //     side: 2,
    //     depthWrite: false
    //   })
    // );

    // const posXAxisHelper = new THREE.Sprite(getSpriteMaterial(color1, 'X'));
    // posXAxisHelper.name = 'R';
    // posXAxisHelper.position.x = 0.8;
    // posXAxisHelper.scale.setScalar(0.4);
    // posXAxisHelper.updateMatrixWorld();

    // const negXAxisHelper = new THREE.Sprite(getSpriteMaterial(color4, '-X'));
    // negXAxisHelper.name = 'L';
    // negXAxisHelper.position.x = -0.8;
    // negXAxisHelper.scale.setScalar(0.4);
    // negXAxisHelper.updateMatrixWorld();

    // // Y轴
    // const yAxis = new THREE.Mesh(
    //   geometry,
    //   new THREE.MeshBasicMaterial({
    //     color: color2,
    //     side: 2,
    //     depthWrite: false
    //   })
    // );
    // yAxis.rotation.y = -Math.PI / 2;
    // yAxis.updateMatrixWorld();

    // const posYAxisHelper = new THREE.Sprite(getSpriteMaterial(color2, 'Y'));
    // posYAxisHelper.name = 'U';
    // posYAxisHelper.position.z = 0.8;
    // posYAxisHelper.scale.setScalar(0.4);
    // posYAxisHelper.updateMatrixWorld();

    // const negYAxisHelper = new THREE.Sprite(getSpriteMaterial(color4, '-Y'));
    // negYAxisHelper.name = 'F';
    // negYAxisHelper.position.z = -0.8;
    // negYAxisHelper.scale.setScalar(0.4);
    // negYAxisHelper.updateMatrixWorld();

    // // Z轴
    // const zAxis = new THREE.Mesh(
    //   geometry,
    //   new THREE.MeshBasicMaterial({
    //     color: color3,
    //     side: 2,
    //     depthWrite: false
    //   })
    // );
    // zAxis.rotation.z = Math.PI / 2;
    // zAxis.updateMatrixWorld();

    // const posZAxisHelper = new THREE.Sprite(getSpriteMaterial(color3, 'Z'));
    // posZAxisHelper.name = 'B';
    // posZAxisHelper.position.y = 0.8;
    // posZAxisHelper.scale.setScalar(0.4);
    // posZAxisHelper.updateMatrixWorld();

    // const negZAxisHelper = new THREE.Sprite(getSpriteMaterial(color4, '-Z'));
    // negZAxisHelper.name = 'D';
    // negZAxisHelper.position.y = -0.8;
    // negZAxisHelper.scale.setScalar(0.4);
    // negZAxisHelper.updateMatrixWorld();


    // let terminalGeo: THREE.BufferGeometry | null = null;
    // let gltfLoader = new GLTFLoader();
    // gltfLoader.load(`${STATIC_URL}/model/terminal.glb`, (gltf) => {
    //   const model = gltf.scene.getObjectByName('平面') as THREE.Mesh;
    //   terminalGeo = model.geometry as THREE.BufferGeometry;
    // });

    // if (terminalGeo) {
    //   const material = new THREE.MeshBasicMaterial({ color: '#e5380a' });
    //   const terminalMeh = new THREE.Mesh(terminalGeo.clone(), material);
    //   terminalMeh.addEventListener('drag', handleDrag);
    //   terminalMeh.addEventListener('mouseup', handleMouseup);
    //   terminals.push(terminalMeh);
    //   return terminalMeh;
    // }


    //WG ADD 调用加载模型方法
    // let terminalGeo: THREE.BufferGeometry | null = null;
    let gltfLoader = new GLTFLoader();
    // let terminalMeh: THREE.Mesh | null = null;
    gltfLoader.load(`${STATIC_URL}/model/navbox.glb`, (gltf) => {

      const model = gltf.scene;
      model.traverse((child) => {
        if (child instanceof THREE.Mesh) {

          // // 创建新的材质
          // const newMaterial = new THREE.MeshBasicMaterial({
          //   color: 0xffffff, // 设置你想要的颜色
          //   // map: new THREE.TextureLoader().load(`${STATIC_URL}/model/front.png`) // 设置纹理贴图
          //   map: getCanvasTexture(color4, '前')
          // });
          // // 赋予新的材质
          // child.material = newMaterial;

          let newMat: THREE.MeshBasicMaterial | null = null;
          let lmap: THREE.CanvasTexture | null = null;
          switch (child.name) {
            case 'Front_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xffffff,
                map: getCanvasTexture(color4, '上')
              });
              child.material = newMat;
              child.name = '上';
              interactiveObjects.push(child);
              break;
            case 'After_1':
              lmap = getCanvasTexture(color4, '下');
              lmap.rotation = THREE.MathUtils.degToRad(180);
              lmap.center.set(0.5, 0.5);
              newMat = new THREE.MeshBasicMaterial({
                color: 0xffffff,
                map: lmap
              });
              child.material = newMat;
              child.name = '下';
              interactiveObjects.push(child);
              break;
            case 'Left_1':
              lmap = getCanvasTexture(color4, '左');
              lmap.rotation = THREE.MathUtils.degToRad(90);
              lmap.center.set(0.5, 0.5);
              newMat = new THREE.MeshBasicMaterial({
                color: 0xffffff,
                map: lmap
              });
              child.material = newMat;
              child.name = '左';
              interactiveObjects.push(child);
              break;
            case 'Right_1':
              lmap = getCanvasTexture(color4, '右');
              lmap.rotation = THREE.MathUtils.degToRad(-90);
              lmap.center.set(0.5, 0.5);
              newMat = new THREE.MeshBasicMaterial({
                color: 0xffffff,
                map: lmap
              });
              child.material = newMat;
              child.name = '右';
              interactiveObjects.push(child);
              break;
            case 'Up_1':
              lmap = getCanvasTexture(color4, '前');
              lmap.rotation = THREE.MathUtils.degToRad(180);
              lmap.center.set(0.5, 0.5);
              newMat = new THREE.MeshBasicMaterial({
                color: 0xffffff,
                map: lmap
              });
              child.material = newMat;
              child.name = '前';
              interactiveObjects.push(child);
              break;
            case 'Lower_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xffffff,
                map: getCanvasTexture(color4, '后')
              });
              child.material = newMat;
              child.name = '后';
              interactiveObjects.push(child);
              break;



            case 'Horn_1_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '上角4';
              interactiveObjects.push(child);
              break;
            case 'Horn_2_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '上角3';
              interactiveObjects.push(child);
              break;
            case 'Horn_3_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '下角3';
              interactiveObjects.push(child);
              break;
            case 'Horn_4_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '下角4';
              interactiveObjects.push(child);
              break;
            case 'Horn_5_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '上角1';
              interactiveObjects.push(child);
              break;
            case 'Horn_6_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '上角2';
              interactiveObjects.push(child);
              break;
            case 'Horn_7_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;
              child.name = '下角2';
              interactiveObjects.push(child);
              break;
            case 'Horn_8_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0xFFFFFF,
                side: THREE.DoubleSide
              });
              child.material = newMat;

              child.name = '下角1';
              interactiveObjects.push(child);
              break;



            case 'Up_front_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '上边3';
              interactiveObjects.push(child);
              break;
            case 'Right_up_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '中边3';
              interactiveObjects.push(child);
              break;
            case 'Up_after_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '下边3';
              interactiveObjects.push(child);
              break;
            case 'Left_up_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '中边4';
              interactiveObjects.push(child);
              break;
            case 'Left_front_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '上边4';
              interactiveObjects.push(child);
              break;
            case 'Right_front_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '上边2';
              interactiveObjects.push(child);
              break;
            case 'Right_after_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '下边2';
              interactiveObjects.push(child);
              break;
            case 'Left_after_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '下边4';
              interactiveObjects.push(child);
              break;
            case 'Lower_front_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '上边1';
              interactiveObjects.push(child);
              break;
            case 'Right_lower_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '中边2';
              interactiveObjects.push(child);
              break;
            case 'Lower_after_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '下边1';
              interactiveObjects.push(child);
              break;
            case 'Left_lower_1':
              newMat = new THREE.MeshBasicMaterial({
                color: 0x5A5858
              });
              child.material = newMat;
              child.name = '中边1';
              interactiveObjects.push(child);
              break;
            
            default:
              break;
          }

        }
      });

      helperGroup.add(model);

    });

    viewer.addEventListener('camera_changed', cameraChange);

    viewer.addEventListener('render.pass.perspective_overlay', renderHelper);

    domElement.addEventListener('mousedown', handleMouseDown, false);
  }

  function dispose() {
    if (interactiveObjects.length > 0) {
      helperGroup.traverse((item: any) => {
        if (item.geometry) {
          item.geometry.dispose();
          item.material.map?.dispose();
          item.material.dispose();
        }
      });

      helperGroup.children.length = 0;
      interactiveObjects.length = 0;

      viewer.removeEventListener('camera_changed', cameraChange);
      viewer.removeEventListener('render.pass.perspective_overlay', renderHelper);

      domElement.removeEventListener('mousedown', handleMouseDown);
    }
  }

  return {
    create,
    dispose
  };
};

export { useViewHelper };

 

2,设置正交相机射线方法

let handleMouseDown = (event: any) => {
    let mouse = new THREE.Vector2();

    const rect = domElement.getBoundingClientRect();
    const x = rect.left + domElement.clientWidth - width - offsetX;
    mouse.x = event.clientX - x;
    mouse.y = event.clientY - rect.top;

    if (mouse.x < 0 || mouse.y > width) return;

    mouse.x = (mouse.x / width) * 2 - 1;
    mouse.y = -(mouse.y / width) * 2 + 1;

    let raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, orthoCamera);

    //WG raycaster.ray.origin.sub(orthoCamera.getWorldDirection(new THREE.Vector3()));

    // 计算射线的起点和方向
    // const rayOrigin = raycaster.ray.origin;
    // const rayDirection = raycaster.ray.direction;
    // // 获取相机的世界方向
    // const cameraDirection = new THREE.Vector3();
    // orthoCamera.getWorldDirection(cameraDirection);
    // // 将射线起点设置为相机位置加上相机的反向向量
    // rayOrigin.copy(orthoCamera.position);
    // rayDirection.copy(cameraDirection).negate();
    // 设置射线的起点为摄像机的位置
    // raycaster.ray.origin.copy(orthoCamera.position);
    // // 设置射线的方向为摄像机的查看方向
    // raycaster.ray.direction.set(0, 0, -1); // 假设摄像机沿着 Z 轴负方向查看
    // raycaster.ray.direction.applyMatrix4(orthoCamera.matrixWorldInverse);

    raycaster.ray.origin.sub(orthoCamera.getWorldDirection(new THREE.Vector3())).sub(orthoCamera.getWorldDirection(new THREE.Vector3()));

    let intersects = raycaster.intersectObjects(interactiveObjects);

    console.log(intersects);
    if (intersects.length > 0) {
      mapViewer.setViews(intersects[0].object.name);
    }
  };

 

posted @ 2024-09-05 17:38  琥珀君  阅读(52)  评论(0编辑  收藏  举报