Utilisez threejs pour rendre le modèle 3D dans uniapp vue3

Préface : En raison des besoins de l'entreprise, un modèle 3D doit être intégré dans l'application. Après avoir examiné la situation sur le marché, la plupart d'entre eux sont vue2, et il n'y a pas de version vue3... Maintenant, vue3 n'est pas une nouveauté . Modèle tardif Il sera placé dans l'application. La méthode d'écriture suivante ne prend pas en charge l'application (il a été résolu de rendre dans l'application, suivez-moi pour voir) et prend en charge h5

modèle:

<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>

La méthode d'écriture ci-dessus n'est pas élégante et n'est utilisée que temporairement comme démo à titre de référence.

Remarque : vous devez en télécharger manuellement trois par vous-même, juste npm i trois dans npm, et faire attention aux attributs du script

Lien modèle : disque réseau Baidu, veuillez entrer le code d'extraction

Code d'extraction : zsbn

Je suppose que tu aimes

Origine blog.csdn.net/Motion_zq/article/details/127514024
conseillé
Classement