当前位置: 首页 > 工具软件 > 3Dmol.js > 使用案例 >

React+three.js 加载gltf 3D模型

谈炳
2023-12-01

最近要在react项目中加载gltf格式的3D模型
gltf资源一般包括描述模型场景、节点层次结构等内容的 .gltf 文件,描述几何、纹理信息的 .bin 数据文件 和 用于模型纹理的 .jpg、.png 等图片文。

准备工作:
1.安装three:npm install thress -s.
2.gltf资源文件(在项目中我直接放在了public文件夹下)

import React, { Component } from "react";
import * as THREE from "three/build/three";
import Stats from 'three/examples/jsm/libs/stats.module';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { RoughnessMipmapper } from "three/examples/jsm/utils/RoughnessMipmapper";

export default class Three_3D extends Component {
  
  initThree() {
    threeStart();

    var container, stats, controls;
    var camera, scene, renderer, light;
    var width, height;

    function threeStart() {
      init();
      render();
      loadGLTF("pedestrian_overpass_2k.hdr", "Bot_Skinned.gltf");
      animation();
    }
    function render() {
      renderer.render(scene, camera);
    }

    function animation() {
      requestAnimationFrame(animation);
      renderer.render(scene, camera);
      //stats.update();
    }

    function init() {
      container = document.getElementById("canvas-frame");
      width = container.offsetWidth;
      height = container.offsetHeight;

      //性能插件
       //stats = new Stats();
       //stats.domElement.style.position = 'relative';
       //stats.domElement.style.left = '0px'; // (0,0)px,左上角
       //stats.domElement.style.top = '50px';
       //container.appendChild(stats.domElement);
      
      renderer = new THREE.WebGLRenderer({
        antialias: true,
      });
      renderer.setSize(width, height);
      //renderer.setClearColor(0x999999, 1.0);
      renderer.setPixelRatio(window.devicePixelRatio);

      renderer.toneMapping = THREE.ACESFilmicToneMapping;
      renderer.toneMappingExposure = 1;
      renderer.outputEncoding = THREE.sRGBEncoding;
      container.appendChild(renderer.domElement);



      //相机
      camera = new THREE.PerspectiveCamera(50, width / height, 1, 10000);
      camera.position.set(0, 0, 400); //设置相机位置
      //camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.25, 20);
      //camera.position.set(-1.8, 0.6, 2.7);

      //场景
      scene = new THREE.Scene();

      //环境光源
      // light = new THREE.AmbientLight(0xFFFFFF);
      // light.position.set(300, 300, 0);
      // scene.add(light);

      //相机控件
      controls = new OrbitControls(camera, renderer.domElement);
      //controls.screenSpacePanning = true;
      controls.addEventListener("change", render); 
      controls.minDistance = 2;
      controls.maxDistance = 10;
      controls.target.set(0, 0, -0.2);
      controls.update();
    }

    function loadGLTF(backImage, gltf) {
      new RGBELoader()
        .setDataType(THREE.UnsignedByteType)
        .setPath("")
        .load(backImage, function (texture) {
          var envMap = pmremGenerator.fromEquirectangular(texture).texture;

          scene.background = envMap;
          scene.environment = envMap;

          texture.dispose();
          pmremGenerator.dispose();

          render();

          // model

          // use of RoughnessMipmapper is optional
          var roughnessMipmapper = new RoughnessMipmapper(renderer);

          var loader = new GLTFLoader().setPath("");
          loader.load(gltf, function (gltf) {
            gltf.scene.traverse(function (child) {
              if (child.isMesh) {
                // TOFIX RoughnessMipmapper seems to be broken with WebGL 2.0
                // roughnessMipmapper.generateMipmaps( child.material );
              }
            });

            scene.add(gltf.scene);
            roughnessMipmapper.dispose();
            render();
          });
        });

      var pmremGenerator = new THREE.PMREMGenerator(renderer);
      pmremGenerator.compileEquirectangularShader();

      window.addEventListener("resize", onWindowResize, false);
    }

    function onWindowResize() {
      camera.aspect = width / height;
      camera.updateProjectionMatrix();

      renderer.setSize(width, height);

      render();
    }
  }

  /**
   * 开始Three
   */
  componentDidMount() {
    this.initThree();
  }
  render() {
    return <div id="canvas-frame" style={{ height: '100%', width: '100%' }}></div>;
  }
}

 类似资料: