Use threejs para renderizar el modelo 3D en uniapp vue3

Prefacio: Debido a las necesidades de la empresa, se debe integrar un modelo 3D en la aplicación. Después de ver la situación en el mercado, la mayoría de ellos son vue2 y no hay una versión vue3... Ahora vue3 no es algo nuevo El último modelo se colocará en la aplicación. El siguiente método de escritura no es compatible con la aplicación (se resolvió para renderizar en la aplicación, sígueme para ver) y es compatible con h5

plantilla:

<template>
  <view class="">
    <view id="threeView">456</view>
    <view class="">
      22222
    </view>
  </view>
</template>

js:

<script module="three" lang="renderjs" setup>
  import * as THREE from 'three'
  //引入轨道控制器(用来通过鼠标事件控制模型旋转、缩放、移动)
  import {
    OrbitControls
  } from 'three/examples/jsm/controls/OrbitControls.js'
  import {
    GLTFLoader
  } from 'three/examples/jsm/loaders/GLTFLoader.js'
  import {
    FBXLoader
  } from 'three/examples/jsm/loaders/FBXLoader.js'
  import {
    computed,
    onMounted,
    ref,
    watch
  } from 'vue'
  // 如果模型没有显示出来, 可能是cameraZ的值不够, 请注意
  let scene = '',
    camera = '',
    renderer = '',
    cube = '',
    sphere = '',
    step = '',
    stats = '',
    group = '',
    cameraZ = 500,
    url = '../../static/Eraser(1).glb',
    width = 800,
    height = 560,
    orbitcontrols = '';
  const init = () => {
    console.log(cameraZ, 'cameraZ');
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
    camera.position.set(0, 0, cameraZ);
    renderer = new THREE.WebGLRenderer({
      antialias: true
    });
    renderer.setClearColor(0xffffff, 0);
    renderer.setSize(width / 1.2, height / 1.2);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.shadowMapEnabled = true;
    document.getElementById("threeView").appendChild(renderer.domElement);
    orbitcontrols = new OrbitControls(camera, renderer.domElement); //移动控件
    orbitcontrols.enabled = true;
    orbitcontrols.enableRotate = true;
    orbitcontrols.enableZoom = false;
    orbitcontrols.autoRotate = true;
    orbitcontrols.minPolarAngle = Math.PI / 4;
    orbitcontrols.maxPolarAngle = 3 - (Math.PI / 4);
    console.log('78', url.endsWith('gltf'), url.endsWith('glb'))
    console.log(url)
    if (url.endsWith('gltf') || url.endsWith('glb')) {
      //设置了六个平行光  有些材质不接受环境光会很暗
      const directionLight1 = new THREE.DirectionalLight(0xffffff, 1);
      directionLight1.position.set(-300, 0, 0)
      scene.add(directionLight1);

      const directionLight2 = new THREE.DirectionalLight(0xffffff, 1);
      directionLight2.position.set(300, 0, 0)
      scene.add(directionLight2);

      const directionLight3 = new THREE.DirectionalLight(0xffffff, 1);
      directionLight3.position.set(0, 300, 0)
      scene.add(directionLight3);

      const directionLight4 = new THREE.DirectionalLight(0xffffff, 1);
      directionLight4.position.set(0, 300, 0)
      scene.add(directionLight4);

      const directionLight5 = new THREE.DirectionalLight(0xffffff, 1);
      directionLight5.position.set(0, 0, -300)
      scene.add(directionLight5);

      const directionLight6 = new THREE.DirectionalLight(0xffffff, 1);
      directionLight6.position.set(0, 0, 300)
      scene.add(directionLight6);
    }
    let Sun = new THREE.DirectionalLight(0xffffff, 1);
    Sun.position.set(0, 300, 0);
    Sun.castShadow = true;
    let Ambient = new THREE.AmbientLight(0xffffff, 1);
    scene.add(Ambient);
    scene.add(Sun);
  }
  const loadModel = () => {
    let loader1 = new GLTFLoader();
    let FBXloader = new FBXLoader();
    let rotateObj = [];
    const loadLoader = url.endsWith('fbx') ? FBXloader : loader1;
    loadLoader.load(url, function(gltf) {
      const loadscene = gltf.scene || gltf;

      loadscene.scale.set(1, 1, 1);

      let group = new THREE.Group();
      group.add(loadscene);

      let bbox = new THREE.Box3().setFromObject(group);
      // console.log(bbox,'bbox---');
      let mdlen = bbox.max.x - bbox.min.x; //边界的最小坐标值 边界的最大坐标值
      let mdhei = bbox.max.y - bbox.min.y;
      let mdwid = bbox.max.z - bbox.min.z;
      group.position.set(0, 0, 0);
      // console.log(camera,'相机的信息',group,'组的信息');
      let dist = Math.abs(camera.position.z - group.position.z - (mdwid / 2));
      //console.log('dist值为:' + dist );
      let vFov = camera.fov * Math.PI / 180; //弧度=角度*Math.PI/180
      //console.log('vFov值为:' + vFov );
      let vheight = 2 * Math.tan(vFov * 0.5) * dist;
      //console.log('vheight值为:' + vheight );
      let fraction = mdhei / vheight;
      // console.log('fraction值为:' + fraction );
      let finalHeight = height * fraction;
      //console.log('finalHeight值为:' + finalHeight);
      let finalWidth = (finalHeight * mdlen) / mdhei;
      //console.log('finalWidth值为:' + finalWidth );                

      let value1 = width / finalWidth;
      // console.log('value1缩放比例值为:' + value1);
      let value2 = height / finalHeight;
      // console.log('value2缩放比例值为:' + value2);

      if (value1 >= value2) {
        group.scale.set(value2, value2, value2);
      } else {
        group.scale.set(value1 / 2, value1 / 2, value1 / 2);
        // group.scale.set(value1,value1,value1);
      }
      let bbox2 = new THREE.Box3().setFromObject(group)
      // console.log(bbox2,'bbox2');
      let mdlen2 = bbox2.max.x - bbox2.min.x;
      let mdhei2 = bbox2.max.y - bbox2.min.y;
      let mdwid2 = bbox2.max.z - bbox2.min.z;
      group.position.set(-(bbox2.max.x + bbox2.min.x) / 2,
        -(bbox2.max.y + bbox2.min.y) / 2,
        -(bbox2.max.z + bbox2.min.z) / 2);
      document.getElementById("threeView").click(); //去掉加载效果
      scene.add(group);
      // let boxhelper = new THREE.BoxHelper(group,0xbe1915); //辅助线外面红色框
      // scene.add(boxhelper);  
    })
  }
  const animate = () => {
    requestAnimationFrame(animate);
    orbitcontrols.update(); //自动旋转
    renderer.render(scene, camera);
  }
  setTimeout(() => {
    init();
    animate();
    loadModel();
  }, 100)
</script>

El método de escritura anterior no es elegante y solo se usa temporalmente como demostración como referencia.

Nota: debe descargar tres manualmente, solo npm i tres en npm, y prestar atención a los atributos en el script

Enlace del modelo: disco de red Baidu, ingrese el código de extracción

Código de extracción: zsbn

おすすめ

転載: blog.csdn.net/Motion_zq/article/details/127514024