Vue集成three.js并加载glb、gltf、FBX、json模型的场景分析

目录
  • 先上几个网址
  • 安装
  • 组件中引入
  • 基本使用
  • 补充

最近刚开始做的一个项目,后面有个模块要通过three.js实现3D的场景,因为之前也没接触过3D这块,就提前学了一下,做个记录。

先上几个网址

ThreeJS官方:http://www.thingjs.com/guide/city2/

ThreeJS文档:https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene

免费模型网:http://glbxz.com/err/search.php?keyword=%E5%85%8D%E8%B4%B9

接下来就我做的一个demo开始

安装

npm i three
npm i three-orbitcontrols
npm i stats.js // 性能监测

组件中引入

import * as THREE from 'three'
import * as Stats from 'stats.js'
import OrbitControls from 'three-orbitcontrols'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'

基本使用

1.创建场景

this.scene = new THREE.Scene();

2.相机

this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置摄像机位置,相机方向逆X轴方向,倾斜向下看
this.camera.position.set(360, 360, 360);
// 指向场景中心
this.camera.lookAt(this.scene.position);

3. 渲染器

this.renderer = new THREE.WebGLRenderer({ antialias: true });
// 设置环境
this.renderer.setClearColor(new THREE.Color("#f1f9fb"));
// 设置场景大小
this.renderer.setSize(window.innerWidth / window.innerHeight);
// 渲染器开启阴影效果
this.renderer.shadowMap.enabled = true;

4.创建纹理加载器

this.textureLoader = new THREE.TextureLoader();

5.创建组合对象

加载外部模型的时候,基本上都是一个组合对象,因为外部模型都是比较大的,把零散的模型组合到一块便于操作,可以使用THREE.Group来操作一组对象,包括旋转,缩放,移动等,里面的子对象都会受到影响。THREE.Group继承自THREE.Object3D对象,并且和THREE.Object3D对象没有任何区别,仅仅是名字上的差异

this.groupBox = new THREE.Group();

6.添加坐标轴,辅助判断位置

let axes = new THREE.AxesHelper(1000);
this.scene.add(axes);

7.点光源

// 点光源
let point = new THREE.PointLight(0xffffff);
point.position.set(500, 300, 400); // 点光源位置
this.scene.add(point); // 点光源添加到场景中

8.环境光

// 环境光
let ambient = new THREE.AmbientLight(0x999999);
this.scene.add(ambient);

9.性能监测

//创建性能监测
this.stats = new Stats()
this.stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom
this.stats.domElement.style.position = 'absolute'; //绝对坐标  this.stats.domElement.style.left = '0px';// (0,0)px,左上角
this.stats.domElement.style.top = '0px';
$('#stats').appendChild(this.stats.domElement)

10.相机控件

//创建相机控件
this.control = new OrbitControls(this.camera, this.renderer.domElement)
this.control.enableDamping = true
// 动态阻尼系数 就是鼠标拖拽旋转灵敏度,阻尼越小越灵敏
this.control.dampingFactor = 0.5;
// 是否可以缩放
this.control.enableZoom = true;
// 是否自动旋转
this.control.autoRotate = false;
// 设置相机距离原点的最近距离
this.control.minDistance = 20;
// 设置相机距离原点的最远距离
this.control.maxDistance = 1000;
// 是否开启右键拖拽
this.control.enablePan = true;
// 上下翻转的最大角度
this.control.maxPolarAngle = 1.5;
// 上下翻转的最小角度
this.control.minPolarAngle = 0.0;
// 是否可以旋转
this.enableRotate = true;

11.渲染canvas到容器

$('#container').appendChild(this.renderer.domElement);

12.加载glb、gltf模型

loadGlbModel() {
  const loader = new GLTFLoader()
  // const dracoLoader = new DRACOLoader()
  // dracoLoader.setDecoderPath('/draco/')
  // dracoLoader.preload()
  // loader.setDRACOLoader(dracoLoader)
  loader.load(`${this.publicPath}model/12OJJ6MOWT722N61Z5N92KA9C.glb`, (gltf) => {
    console.log(gltf, 'gltf----->>>')
    gltf.scene.scale.set(100,100,100)  //  设置模型大小缩放
    gltf.scene.position.set(0,0,0)
    let axis = new THREE.Vector3(0,1,0);//向量axis
    gltf.scene.rotateOnAxis(axis,Math.PI/2);
    //绕axis轴逆旋转π/16
    gltf.scene.rotateOnAxis(axis,Math.PI/-20);
    gltf.scene.rotateOnAxis(axis,Math.PI/50);
    // gltf.rotateY(Math.PI / 2);
    // this.groupBox.add(gltf);
    this.scene.add(gltf.scene)
  }, (xhr) => {
      console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
  }, (error) => {
      console.error(error)
  })
},

13.加载FBX模型

//  加载 FBX 模型
loadFbxModel() {
  const loader = new FBXLoader();
  loader.load(`${this.publicPath}model/glbxz.com6031.FBX`, object => {//加载路径fbx文件
    console.log(object, 'object----->>>')
    object.traverse( child => {
      if ( child.isMesh ){
        child.castShadow = true;
        child.receiveShadow = true;
      }
    });
    this.scene.add(object);//模型
  })
},

14.加载json模型

//加载 JSON格式 模型
loadJsonModel() {
  //设置相机位置
  this.camera.position.z = 130
  this.camera.position.y = 80
  const loader = new THREE.ObjectLoader()
  loader.load(`${this.publicPath}model/xxxx.json`, json => {
    //处理加载模型为黑色问题
    json.traverse(child => {
      if (child.isMesh) {
        child.material.emissive = child.material.color
        child.material.emissiveMap = child.material.map
      }
    })
    this.scene.add(group)
  }, xhr => {
    // called while loading is progressing
    console.log(`${( xhr.loaded / xhr.total * 100 )}% loaded`);
  }, error => {
    // called when loading has errors
    console.error('An error happened', error);
  })
},

15.创建材质

// 创建材质
createMaterial() {
  // 创建三维用到的材质
  /**
   *
   * MeshBasicMaterial: 网格基础材质
   * MeshDepthMaterial: 网格深度材质
   * MeshNormalMaterial: 网格法向材质
   * MeshLambertMaterial: 网格Lambert 材质
   * MeshPhongMaterial: 网格 Phong式材质
   * MeshStandardMaterial: 网格标准材质
   * MeshPhysicalMaterial: 网格物理材质
   * MeshToonMaterial: 网格卡通材质
   * ShadowMaterial: 阴影材质
   * ShaderMaterial: 着色器材质
   * LineBasicMaterial: 直线基础材质
   * LineDashMaterial: 虚线材质
   */
  // 外墙
  let wallMaterial = new THREE.MeshLambertMaterial({ color: 0x00ffff });
  let wallGeo = new THREE.BoxGeometry(439 + 2 + 2, 120, 376.5 + 2 + 2); // 创建几何体
  let wallMesh = new THREE.Mesh(wallGeo, wallMaterial);
  wallMesh.position.set(0, 60, 0); //(0, 60, -14.95);
  this.scene.add(wallMesh) // 添加结果到场景中
  // 内墙
  let wallInnerMaterial = new THREE.MeshLambertMaterial({
    color: 0x2d1bff,
  });
  let wallInnerGeo = new THREE.BoxGeometry(439, 120, 376.5); //(270, 120, 390);
  let wallInnerMesh = new THREE.Mesh(wallInnerGeo, wallInnerMaterial);
  wallInnerMesh.position.set(0, 60, 0); //(0, 60, -14.95);
  this.scene.add(wallInnerMesh)  // 添加结果到场景中
  // 门
  let doorTexture = this.textureLoader.load(
    require("../../../../assets/img/1.png") // 暂时注掉
  );
  let boxTextureMaterial = new THREE.MeshStandardMaterial({
    map: doorTexture,
    metalness: 0.2,
    roughness: 0.07,
    side: THREE.DoubleSide,
  });
  //let doorInnerMaterial = new THREE.MeshLambertMaterial({color: 0x2D1BFF});
  let doorGeo = new THREE.BoxGeometry(2, 80, 74.5);
  let doorMesh = new THREE.Mesh(doorGeo, boxTextureMaterial);
  doorMesh.position.set(-220.5, 40, 0);
  this.scene.add(doorMesh);  // 添加结果到场景中

  /**
   *  threeBSP - 引用还有问题
   */
  // //转BSP
  // let wallBSP = new ThreeBSP(wallMesh);
  // let wallInnerBSP = new ThreeBSP(wallInnerMesh);
  // let doorBSP = new ThreeBSP(doorMesh);
  // // let window1BSP = new ThreeBSP(this.createWindowRight());
  // //let window2BSP = new ThreeBSP(this.createWindowRight());// createWindowLeft
  // let wallResultBSP = wallBSP.subtract(wallInnerBSP);
  // wallResultBSP = wallResultBSP.subtract(doorBSP);
  // // wallResultBSP = wallResultBSP.subtract(window1BSP);
  // //wallResultBSP = wallResultBSP.subtract(window2BSP);
  // let wallResultMesh = wallResultBSP.toMesh();

  // //转换后的Mesh配置属性
  // let wallTexture = this.textureLoader.load(require("../../../../assets/img/3.jpg")); // 暂时注掉
  // let wallTextureMaterial = new THREE.MeshStandardMaterial({
  //   map: wallTexture,
  //   metalness: 0.2,
  //   roughness: 0.07,
  //   side: THREE.DoubleSide,
  // });
  // let wallInnerTexture = this.textureLoader.load(
  //   require("../../../../assets/img/6.jpg") // 暂时注掉
  // );
  // let wallInnerTextureMaterial = new THREE.MeshStandardMaterial({
  //   map: wallInnerTexture,
  //   metalness: 0.2,
  //   roughness: 0.07,
  //   side: THREE.DoubleSide,
  // });
  // let wallResultMeshMaterial = [];
  // wallResultMeshMaterial.push(wallTextureMaterial);
  // wallResultMeshMaterial.push(wallInnerTextureMaterial);
  // //wallResultMeshMaterial.push(boxTextureMaterial);
  // wallResultMesh.material = wallResultMeshMaterial;

  // // console.log(wallResultMesh.geometry.faces, 112233);
  // wallResultMesh.geometry.faces.forEach((item, i) => {
  //   if (i < 160) {
  //     item.materialIndex = 0;
  //   } else {
  //     item.materialIndex = 1;
  //   }
  // });

  // wallResultMesh.geometry.computeFaceNormals();
  // wallResultMesh.geometry.computeVertexNormals();
  // //添加结果到场景中
  // this.scene.add(wallResultMesh);
},

16.进行渲染

render() {
  let animate = () => {
    //循环调用函数
    this.clearAnim = requestAnimationFrame(animate)
    //更新相机控件
    this.control.update()
    // 更新性能插件
    this.stats.update()
    //渲染界面
    this.renderer.render(this.scene, this.camera)
  }
  animate()
}

17.为模型绑定事件

这里以点击事件为例

this.renderer.domElement.addEventListener('click', this.modelMouseClick, false)
// 模型的点击事件
modelMouseClick( event ) {
  var raycaster = new THREE.Raycaster();
  var mouse = new THREE.Vector2();
  // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
  mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
  mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  raycaster.setFromCamera(mouse, this.camera);
  const intersects = raycaster.intersectObjects(this.scene.children);
  // 根据它来判断点击的什么,length为0即没有点击到模型
  console.log(intersects, 'intersects----->>>')
}

完整代码

<template>
  <div id="import-template">
    <!-- 放性能监测的容器 -->
    <div id="stats"></div>
    <!-- 3D模型容器 -->
    <div id="container"></div>
  </div>
</template>

<script>
// import '@/utils/ThreeBSP.js' // 不可以这么引
import * as THREE from 'three'
import * as Stats from 'stats.js'
// import * as dat from 'dat.gui'
import OrbitControls from 'three-orbitcontrols'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
const $ = name => document.querySelector(name)

export default {
  data() {
    return {
      scene: null, // 场景
      camera: null, // 照相机
      renderer: null, // 渲染器
      mesh: null, // 网格
      textureLoader: null, // 纹理加载器
      mixer: null,
      groupBox: null,
      stats: null, // 性能监测
      control: null, // 相机控件
      publicPath: process.env.BASE_URL,
      clearAnim: null,
      clock: null
    }
  },
  created() {
    // this.init()
  },
  mounted() {
    this.init()
  },
  destroyed() {
    cancelAnimationFrame(this.clearAnim)  // 清除requestAnimationFrame
    this.renderer.domElement.removeEventListener('click', this.modelMouseClick, false)
    this.scene = null, // 场景
    this.camera = null, // 照相机
    this.renderer = null, // 渲染器
    this.mesh = null, // 网格
    this.textureLoader = null, // 纹理加载器
    this.mixer = null,
    this.groupBox = null,
    this.stats = null, // 性能监测
    this.control = null, // 相机控件
    this.publicPath = process.env.BASE_URL,
    this.clock = null
  },
  methods: {
    //初始化
    init() {
      // 场景
      this.scene = new THREE.Scene();
      // 1.2 相机
      this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
      // 设置摄像机位置,相机方向逆X轴方向,倾斜向下看
      this.camera.position.set(360, 360, 360);
      //this.camera.position.set(-20, 40 ,30)
      // 指向场景中心
      this.camera.lookAt(this.scene.position);
      // 1.3 渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      // 创建纹理加载器
      this.textureLoader = new THREE.TextureLoader();
      // 创建一个组合对象
      this.groupBox = new THREE.Group();
      // 添加坐标轴,辅助判断位置
      let axes = new THREE.AxesHelper(1000);
      this.scene.add(axes);
      // 设置环境
      this.renderer.setClearColor(new THREE.Color("#f1f9fb"));
      // 设置场景大小
      this.renderer.setSize(
        $('#container').getBoundingClientRect().width,
        $('#container').getBoundingClientRect().height
      );
      // 渲染器开启阴影效果
      this.renderer.shadowMap.enabled = true;
      // 点光源
      let point = new THREE.PointLight(0xffffff);
      point.position.set(500, 300, 400); // 点光源位置
      this.scene.add(point); // 点光源添加到场景中
      // 环境光
      let ambient = new THREE.AmbientLight(0x999999);
      this.scene.add(ambient);

      //创建性能监测
      this.stats = new Stats()
      this.stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom
      this.stats.domElement.style.position = 'absolute'; //绝对坐标
      this.stats.domElement.style.left = '0px';// (0,0)px,左上角
      this.stats.domElement.style.top = '0px';
      $('#stats').appendChild(this.stats.domElement)

      // 渲染div到canvas
      $('#container').appendChild(this.renderer.domElement);

      //创建相机控件
      this.control = new OrbitControls(this.camera, this.renderer.domElement)
      this.control.enableDamping = true
      // 动态阻尼系数 就是鼠标拖拽旋转灵敏度,阻尼越小越灵敏
      this.control.dampingFactor = 0.5;
      // 是否可以缩放
      this.control.enableZoom = true;
      // 是否自动旋转
      this.control.autoRotate = false;
      // 设置相机距离原点的最近距离
      this.control.minDistance = 20;
      // 设置相机距离原点的最远距离
      this.control.maxDistance = 1000;
      // 是否开启右键拖拽
      this.control.enablePan = true;
      // 上下翻转的最大角度
      this.control.maxPolarAngle = 1.5;
      // 上下翻转的最小角度
      this.control.minPolarAngle = 0.0;
      // 是否可以旋转
      this.enableRotate = true;
      this.loadGlbModel(); // 加载 glb、gltf模型
      // this.loadFbxModel() // 加载 FBX 模型
      // this.loadJsonModel() // 加载 json 模型
      // this.createMaterial() // 创建材质
      // 最后进行渲染
      this.render()
    },
    // 最后的渲染
    render() {
      let animate = () => {
        //循环调用函数
        this.clearAnim = requestAnimationFrame(animate)
        //更新相机控件
        this.control.update()
        // 更新性能插件
        this.stats.update()
        //渲染界面
        this.renderer.render(this.scene, this.camera)
      }
      animate()
      //  为模型绑定点击事件
      this.renderer.domElement.addEventListener('click', this.modelMouseClick, false)
    },
    // 创建材质
    createMaterial() {
      // 创建三维用到的材质
      /**
       *
       * MeshBasicMaterial: 网格基础材质
       * MeshDepthMaterial: 网格深度材质
       * MeshNormalMaterial: 网格法向材质
       * MeshLambertMaterial: 网格Lambert 材质
       * MeshPhongMaterial: 网格 Phong式材质
       * MeshStandardMaterial: 网格标准材质
       * MeshPhysicalMaterial: 网格物理材质
       * MeshToonMaterial: 网格卡通材质
       * ShadowMaterial: 阴影材质
       * ShaderMaterial: 着色器材质
       * LineBasicMaterial: 直线基础材质
       * LineDashMaterial: 虚线材质
       */
      // 外墙
      let wallMaterial = new THREE.MeshLambertMaterial({ color: 0x00ffff });
      let wallGeo = new THREE.BoxGeometry(439 + 2 + 2, 120, 376.5 + 2 + 2); // 创建几何体
      let wallMesh = new THREE.Mesh(wallGeo, wallMaterial);
      wallMesh.position.set(0, 60, 0); //(0, 60, -14.95);
      this.scene.add(wallMesh)
      // 内墙
      let wallInnerMaterial = new THREE.MeshLambertMaterial({
        color: 0x2d1bff,
      });
      let wallInnerGeo = new THREE.BoxGeometry(439, 120, 376.5); //(270, 120, 390);
      let wallInnerMesh = new THREE.Mesh(wallInnerGeo, wallInnerMaterial);
      wallInnerMesh.position.set(0, 60, 0); //(0, 60, -14.95);
      this.scene.add(wallInnerMesh)
      // 门
      let doorTexture = this.textureLoader.load(
        require("../../../../assets/img/1.png") // 暂时注掉
      );
      let boxTextureMaterial = new THREE.MeshStandardMaterial({
        map: doorTexture,
        metalness: 0.2,
        roughness: 0.07,
        side: THREE.DoubleSide,
      });
      //let doorInnerMaterial = new THREE.MeshLambertMaterial({color: 0x2D1BFF});
      let doorGeo = new THREE.BoxGeometry(2, 80, 74.5);
      let doorMesh = new THREE.Mesh(doorGeo, boxTextureMaterial);
      doorMesh.position.set(-220.5, 40, 0);
      this.scene.add(doorMesh);

      /**
       *  threeBSP - 引用还有问题
       */
      // //转BSP
      // let wallBSP = new ThreeBSP(wallMesh);
      // let wallInnerBSP = new ThreeBSP(wallInnerMesh);
      // let doorBSP = new ThreeBSP(doorMesh);
      // // let window1BSP = new ThreeBSP(this.createWindowRight());
      // //let window2BSP = new ThreeBSP(this.createWindowRight());// createWindowLeft
      // let wallResultBSP = wallBSP.subtract(wallInnerBSP);
      // wallResultBSP = wallResultBSP.subtract(doorBSP);
      // // wallResultBSP = wallResultBSP.subtract(window1BSP);
      // //wallResultBSP = wallResultBSP.subtract(window2BSP);
      // let wallResultMesh = wallResultBSP.toMesh();

      // //转换后的Mesh配置属性
      // let wallTexture = this.textureLoader.load(require("../../../../assets/img/3.jpg")); // 暂时注掉
      // let wallTextureMaterial = new THREE.MeshStandardMaterial({
      //   map: wallTexture,
      //   metalness: 0.2,
      //   roughness: 0.07,
      //   side: THREE.DoubleSide,
      // });
      // let wallInnerTexture = this.textureLoader.load(
      //   require("../../../../assets/img/6.jpg") // 暂时注掉
      // );
      // let wallInnerTextureMaterial = new THREE.MeshStandardMaterial({
      //   map: wallInnerTexture,
      //   metalness: 0.2,
      //   roughness: 0.07,
      //   side: THREE.DoubleSide,
      // });
      // let wallResultMeshMaterial = [];
      // wallResultMeshMaterial.push(wallTextureMaterial);
      // wallResultMeshMaterial.push(wallInnerTextureMaterial);
      // //wallResultMeshMaterial.push(boxTextureMaterial);
      // wallResultMesh.material = wallResultMeshMaterial;

      // // console.log(wallResultMesh.geometry.faces, 112233);
      // wallResultMesh.geometry.faces.forEach((item, i) => {
      //   if (i < 160) {
      //     item.materialIndex = 0;
      //   } else {
      //     item.materialIndex = 1;
      //   }
      // });

      // wallResultMesh.geometry.computeFaceNormals();
      // wallResultMesh.geometry.computeVertexNormals();
      // //添加结果到场景中
      // this.scene.add(wallResultMesh);
    },
    // 加载 GLTF 模型
    loadGlbModel() {
      const loader = new GLTFLoader()
      // const dracoLoader = new DRACOLoader()
      // dracoLoader.setDecoderPath('/draco/')
      // dracoLoader.preload()
      // loader.setDRACOLoader(dracoLoader)
      loader.load(`${this.publicPath}model/12OJJ6MOWT722N61Z5N92KA9C.glb`, (gltf) => {
        console.log(gltf, 'gltf----->>>')
        gltf.scene.scale.set(100,100,100)  //  设置模型大小缩放
        gltf.scene.position.set(0,0,0)
        let axis = new THREE.Vector3(0,1,0);//向量axis
        gltf.scene.rotateOnAxis(axis,Math.PI/2);
        //绕axis轴逆旋转π/16
        gltf.scene.rotateOnAxis(axis,Math.PI/-20);
        gltf.scene.rotateOnAxis(axis,Math.PI/50);
        // gltf.rotateY(Math.PI / 2);
        // this.groupBox.add(gltf);
        this.scene.add(gltf.scene)
      }, (xhr) => {
          console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
      }, (error) => {
          console.error(error)
      })
    },
    //  加载 FBX 模型
    loadFbxModel() {
      const loader = new FBXLoader();
      loader.load(`${this.publicPath}model/glbxz.com6031.FBX`, object => {//加载路径fbx文件
        console.log(object, 'object----->>>')
        object.traverse( child => {
          if ( child.isMesh ){
            child.castShadow = true;
            child.receiveShadow = true;
          }
        });
        this.scene.add(object);//模型
      })
    },
    //加载 JSON格式 模型
    loadJsonModel() {
      //设置相机位置
      this.camera.position.z = 130
      this.camera.position.y = 80
      const loader = new THREE.ObjectLoader()
      loader.load(`${this.publicPath}model/xxxx.json`, json => {
        //处理加载模型为黑色问题
        json.traverse(child => {
          if (child.isMesh) {
            child.material.emissive = child.material.color
            child.material.emissiveMap = child.material.map
          }
        })
        this.scene.add(group)
      }, xhr => {
        // called while loading is progressing
        console.log(`${( xhr.loaded / xhr.total * 100 )}% loaded`);
      }, error => {
        // called when loading has errors
        console.error('An error happened', error);
      })
    },
    // 模型的点击事件
    modelMouseClick( event ) {
      var raycaster = new THREE.Raycaster();
      var mouse = new THREE.Vector2();
      // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
      mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
      mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
      raycaster.setFromCamera(mouse, this.camera);
      const intersects = raycaster.intersectObjects(this.scene.children);
      // 根据它来判断点击的什么,length为0即没有点击到模型
      console.log(intersects, 'intersects----->>>')
    }
  }
}
</script>
<style scoped>
#import-template {
  width: 100%;
  height: 100%;
}
#stats {
  width: 100%;
  height: 50px;
  position: relative;
}
#container {
  width: 100%;
  height: calc(100% - 50px);
}
</style>

效果

最后再补充一下,有个threeBSP,,到现在还没知道怎么去引用,搞这个东西才两天,很多还需要慢慢摸索 ,好像这个threBSP不支持npm装,而且必须要引在THREE后面。。。慢慢再搞

<script src="https://johnson2heng.github.io/three.js-demo/lib/threebsp.js"></script>

这个是threeBSP在线的包,如果向上面例子按需引入THREE,那应该怎么去引这个包呢,,

不断学习中。。。

补充

接上面的问题,【已解决】ThreeBSP引入问题

见下篇博文three.js 利用uv和ThreeBSP制作一个快递柜功能

到此这篇关于Vue集成three.js,并加载glb、gltf、FBX、json模型的文章就介绍到这了,更多相关Vue集成three.js内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue+three.js实现炫酷的3D登陆页面示例详解

    目录 前言: Three.js的基础知识 关于场景 关于光源 关于相机(重要) 关于渲染器 完善效果 创建一个左上角的地球 使地球自转 创建星星 使星星运动 创建云以及运动轨迹 使云运动 完成three.js有关效果 结语 前言: 大家好,我是xx传媒严导(xx这两个字请自行脑补) . 该篇文章用到的主要技术:vue3.three.js 我们先看看成品效果: 高清大图预览(会有些慢): 座机小图预览: 废话不多说,直接进入正题 Three.js的基础知识 想象一下,在一个虚拟的3D世界中都需要什

  • 关于vue中使用three.js报错的解决方法

    目录 前言 1.vue的问题? 2.Proxy的异常情况 3.Three.js的问题 4.defineProperty异常情况 5.解决 总结 前言 最近在学习three.js,同时也学习一下vue3,然后就出现问题了,报错直接用不了,错误信息如下: Uncaught TypeError: 'get' on proxy: property 'modelViewMatrix' is a read-only and non-configurable data property on the prox

  • vue中利用three.js实现全景图的完整示例

    粗暴一点,直接上代码: 第一步: 通过指令下载three.js npm install three -S 第二步: 在组件中引用 import * as THREE from 'three' 第三步: html部分 <div id="container"></div> js部分 <script> import * as THREE from 'three'; var camera; var renderer; var scene; export de

  • vue页面引入three.js实现3d动画场景操作

    vue中安装Three.js 近来无聊顺便研究一些关于3D图形化库.three.js是JavaScript编写的WebGL第三方库.Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它通过控制相机.视角.材质等相关属性来创造大量3D动画场景. 我们开始引入three.js相关插件. 1.首先利用淘宝镜像,操作命令为: cnpm install three 2.接下来利用npm安装轨道控件插件: 关注我的微信公众号[前端基础教程从0开始],加我微信,可以免费为您解答问题.回复"1&qu

  • Vue集成three.js并加载glb、gltf、FBX、json模型的场景分析

    目录 先上几个网址 安装 组件中引入 基本使用 补充 最近刚开始做的一个项目,后面有个模块要通过three.js实现3D的场景,因为之前也没接触过3D这块,就提前学了一下,做个记录. 先上几个网址 ThreeJS官方:http://www.thingjs.com/guide/city2/ ThreeJS文档:https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene 免费模型网:http://glbxz.

  • vue.js页面加载执行created,mounted的先后顺序说明

    created页面加载未渲染html之前执行. mounted渲染html后再执行. 由于created在html模板生产之前所以无法对Dom进行操作而mounted可以. 补充知识:关于Vue子组件data选项某个属性引用子组件props定义的属性的几点思考 学过Vue的都知道Vue等MVVM框架相对于传统的JS库比如Jquery最大的区别在于数据驱动视图,重点在于数据,拿到数据后将数据通过模板{{}}语法或者v-html展示在页面上. 我们也都知道在Vue父子组件可以通过Props实现父组件

  • 在Vue.js中加载字体的正确方法

    添加字体不应该对性能产生负面影响.在本文中,我们将探讨在 Vue 应用程序中加载字体的最佳实践. 正确声明 font-face 的字体 确保正确声明字体是加载字体的重要方面.这是通过使用 font-face 属性来声明你选择的字体来实现的.在你的 Vue 项目中,这个声明可以在你的根 CSS 文件中完成.在进入这个问题之前,我们先来看看 Vue 应用的结构. /root public/ fonts/ Roboto/ Roboto-Regular.woff2 Roboto-Regular.woff

  • 浅谈vue中使用图片懒加载vue-lazyload插件详细指南

    在vue中使用图片懒加载详细指南,分享给大家.具体如下: 说明 当网络请求比较慢的时候,提前给这张图片添加一个像素比较低的占位图片,不至于堆叠在一块,或显示大片空白,让用户体验更好一点. 使用方式 使用vue的 vue-lazyload 插件 插件地址:https://www.npmjs.com/package/vue-lazyload 案例 demo: 懒加载案例demo Installation 安装方式 npm $ npm i vue-lazyload -D CDN CDN: https:

  • js实现加载更多功能实例

    项目的一个前端页面展示已购买商品时,要求能下拉加载更多.关于如何实现『加载更多』功能,网上有插件可用,例如比较著名的使用iscroll.js实现的上拉加载更多.下拉刷新功能. 但实际用起来却是很麻烦.由于是第三方插件,要按照对方定义的方法使用,用起来总感觉很不顺心.再加上iscroll.js本身并没有集成加载更多的功能,需要进行自行扩展.想继续使用iscroll.js实现加载更多功能的,上面给的链接可以看看. h5项目里需要实现简单的分页功能,由于是移动端,考虑用『加载更多』会更好,而不是PC端

  • 详解vue 模拟后台数据(加载本地json文件)调试

    本文介绍了vue 模拟后台数据(加载本地json文件)调试,分享给大家,也给自己留个笔记 首先创建一个本地json文件,放在项目中如下 { "runRedLight":{ "CurrentPage": 1, "TotalPages": 0, "TotalItems": 0, "ItemsPerPage": 100, "Items":[ {"DEVICEID":&quo

  • 基于Vue渲染与插件的加载顺序的问题详解

    Vue实践分享(三)在实际项目的开发过程中,经常会遇到页面还没渲染完成而插件就已经开始加载的问题,这样就会导致显示和功能出错. 可以通过Vue中的nextTick来解决 Vue.nextTick(function() { //widget }); 这样就会在页面渲染完成后再执行nextTick内的插件 以上这篇基于Vue渲染与插件的加载顺序的问题详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们. 您可能感兴趣的文章: 浅谈Vue的加载顺序探讨 Vue.js学习教程

  • vue实现的上拉加载更多数据/分页功能示例

    本文实例讲述了vue实现的上拉加载更多数据/分页功能.分享给大家供大家参考,具体如下: 加载状态 <div v-if='has_log == 0'> <load-more tip="上拉加载" :show-loading="false" background-color="#fbf9fe"></load-more> </div> <div v-if='has_log == 1'> <

  • vue中img src 动态加载本地json的图片路径写法

    目录: 注意:本地json文件和json文件里的图片地址都必须写在static 静态文件夹里:否则json文件里的url地址找不到. major_info.json文件里的图片路径写法 页面通过v-bind的方式加载: PS:vue中图片src路径赋值 vue中引入static文件夹中图片,本以为src中直接写入图片所在路径即可,结果发现图片无法显示,控制台报404错误,图片无法找到.网上找到解决方案,在此mark一下,以便以后查询. 图片src路径动态赋值 <img class="thu

  • vue+layui实现select动态加载后台数据的例子

    刚开始由于layui form渲染与vue渲染有时间差 有时会导致 select里面是空白的 后来就想办法 等vue数据渲染完 再渲染layui form 试过模块化导入layui form组件 然后等vue数据渲染完后手动进行渲染 这种方式有一个小问题 有时候会提示render方法未定义 可能是由于执行顺序原因 vue先执行了 最后把vue代码放到layui.use里面 问题解决 可能不是最好的实现方式 如有更好的实现方式欢迎指出 共同进步 页面代码 <div id="demo"

随机推荐