记一次threejs加载fbx文件

1,601 阅读2分钟

背景

在维护现有项目的时候,发现项目中居然有用到了threejs,之前没有了解过,想想是时候学习一波新知识了。这个仅限于刚入们的同学们。

threejs基本知识

  • 场景
  • 相机
  • 渲染器

这跟现实中拍照一般,场景就像是需要拍摄的实物,而相机对象就是生活中的相机,而渲染器就是我们拍照的瞬间。

image.png

利用threejs加载fbx文件

<template>
  <div class="Create" id="threeDom"></div>
</template>

import { defineComponent, onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader";

const Zlib = require("three/examples/js/libs/fflate.min");
(Window as any).Zlib = Zlib.Zlib;

export default defineComponent({
  setup() {
    const initThree = () => {
      const secene = new THREE.Scene();
      const loader = new FBXLoader();
      let mixer: any, AnimationAction: any, bee: any; // 相机、混合变量
      loader.load(
        "/model/demo.FBX",
        function(obj) {
          secene.add(obj);
          // obj.translateX(-2);
          obj.translateY(-2);
          obj.rotateX(-0.1);
          // obj作为参数创建一个混合器,解析播放obj及其子对象包含的动画数据
          mixer = new THREE.AnimationMixer(obj);
          // 查看动画数据
          console.log(obj.animations, "查看动画数据");
          // obj.animations[0]:获得剪辑对象clip
          AnimationAction = mixer.clipAction(obj.animations[0]);
          AnimationAction.loop = THREE.LoopOnce; // 不循环播放
          AnimationAction.time = 2; //操作对象设置开始播放时间

          obj.animations[0].duration = 3;
          bee = obj;
          console.log(AnimationAction, "AnimationAction");
          AnimationAction.play();
        },
        function onProgress(xhr: any) {
          // 后台打印查看模型文件加载进度
          console.log(
            "加载完成的百分比" + (xhr.loaded / xhr.total) * 100 + "%"
          );
          const progress = (xhr.loaded / xhr.total) * 100;
          window.parent.postMessage(
            {
              data: progress
            },
            "*"
          );
        }
      );

      // 光源设置
      const point = new THREE.PointLight(0xffffff);
      point.intensity = 0.3;
      point.position.set(0, 200, 300); // 点光源的位置
      secene.add(point); // 点光源添加到场景中
      // 环境光
      const ambient = new THREE.AmbientLight(0xffffff);
      ambient.intensity = 1.6;
      secene.add(ambient);

      /**
       * 相机设置
       */
      const width = window.innerWidth; // 窗口宽度
      const height = window.innerHeight; // 窗口高度
      const k = width / height; // 宽高比
      const s = 2.5; // 三维场景显示范围控制系数,系数越大,显示的范围越大
      // 创建相机
      const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
      camera.position.set(0, 0, 200); // 设置相机位置
      camera.lookAt(secene.position); // 设置相机方向(指向的场景对象)

      /**
       * 创建渲染器对象
       */
      const container: any = document.getElementById("threeDom");
      const renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      renderer.setSize(width, height); // 设置渲染区域尺寸
      renderer.setClearColor(0xffffff, 1.0); // 设置背景颜色
      container.appendChild(renderer.domElement);

      // 创建一个时钟对象
      const clock = new THREE.Clock();
      function render() {
        renderer.render(secene, camera); // 执行渲染操作
        requestAnimationFrame(render); // 请求再次执行渲染函数render,渲染下一帧
        if (mixer) {
          // 更新混合器相关的时间
          mixer.update(clock.getDelta());
        }
      }
      render();

      //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
      const controls = new OrbitControls(camera, container);
      controls.enableZoom = false;
      controls.minPolarAngle = Math.PI / 2;
      controls.maxPolarAngle = Math.PI / 2;
      controls.enablePan = false;

    };

    onMounted(() => {
      initThree();
    });
  },
  components: {}
});
</script>