threeJS导入FBX模型

初认threeJS

Three.js 是一款运行在浏览器中的 3D 引擎,你可以用它创建各种三维场景,包括了摄影机、光影、材质等各种对象。你可以在它的主页上看到许多精彩的演示。官方地址:http://www.webgl3d.cn/



前言

这里会说到导入fbx模型,以及在开发中遇到的问题,最后是怎么解决的


一、加载three

npm install three
npm install --save @types/three

二、html部分

  <section class="pane-box" id="threeBox">
    <div id="myThree" />
  </section>

三、使用步骤

1.引入库

代码如下(示例):

import * as THREE from 'three'
import { FBXLoader } from "three/examples/jsm/loaders/FBXLoader"
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

2.引入背景图

代码如下(示例):

import BG from "@/assets/fbxResource/envImg/bg.jpeg";
import negx from "@/assets/img/negx.png";
import negy from "@/assets/img/negy.png";
import negz from "@/assets/img/negz.png";
import posx from "@/assets/img/posx.png";
import posy from "@/assets/img/posy.png";
import posz from "@/assets/img/posz.png";
//模型加载器
let FBXModule = new FBXLoader();

3. 引入模型

//模型,这里可以引入多个模型
const models = {name:'像素人',path:"./public/blueMan.fbx",position:[0, 0, 0],type:'fbx'}

4. 创建场景

这里写了加载了3中背景,我的项目中只用到了背景图片

Scene(){
    this.Scene =  new THREE.Scene()
    //设置背景色
    // this.Scene.background = new THREE.Color(0xffffff);
    //设置背景图
     this.Scene.background = new THREE.TextureLoader().load(BG)
     //设置3d环境背景图
     // this.Scene.background = new THREE.CubeTextureLoader().load([posx,negx,posy,negy,posz,negz,]);
     THREE.Cache.enabled = true;
     console.log("scene...",this.Scene)
     // this.Scene.background = textureCube
    }

5. 添加渲染器

 Renderer(){
this.Renderer = new THREE.WebGLRenderer({antialias: true,alpha: true,premultipliedAlpha:true,precision: 'highp'})
this.Renderer.setPixelRatio(window.devicePixelRatio); 
this.Renderer.setSize(threeBox.clientWidth, threeBox.clientHeight - 20);
this.Renderer.setClearColor(0x00ff00);
//允许在场景中使用阴影贴图
this.Renderer.shadowMap.enabled = true;
 //是否使用物理上正确的光照模式
this.Renderer.physicallyCorrectLights = true;
 //定义渲染器的输出编码
this.Renderer.outputEncoding = THREE.sRGBEncoding;
 myThree.appendChild(this.Renderer.domElement);
 }

6. 添加相机

这里提到两种相机,不知道区别的小伙伴 去官网看看

 Camera(){
		let canvasSize = threeBox.clientWidth / threeBox.clientHeight; //窗口宽高比
        //透视摄像机
        this.Camera = new THREE.PerspectiveCamera(45, canvasSize,1, 100000)
        //正交摄像机
        //let k = 500 / 600;
        //let s = 10;
        //this.Camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 2000);//创建相机对象
        this.Camera.position.set(200, 500, 300);
        this.Camera.lookAt(this.Scene.position)
        }

7. 计算模型剧中

//包围盒全自动计算:模型整体居中
let ModelAutoCenter = function(group:any){
    let box3 = new THREE.Box3()
    // 计算层级模型group的包围盒
    // 模型group是加载一个三维模型返回的对象,包含多个网格模型
    box3.expandByObject(group)
    // 计算一个层级模型对应包围盒的几何体中心在世界坐标中的位置
    let center = new THREE.Vector3()
    box3.getCenter(center)

    // 重新设置模型的位置,使之居中。
    group.position.x = group.position.x - center.x
    group.position.y = group.position.y - center.y 
    group.position.z = group.position.z - center.z
    console.log("center.x", group.position.y,center.y)
}

8. 加载模型FBX

modelLoader(MODEL:any){
const loadTip:any = this.addLoadTip();
        this.Controls.autoRotate = false;
        let MTYPE = MODEL.type;
        console.log("Model22222---",MTYPE)
        FBXModule.load(MODEL.path, (geometry:any)=> {
                loadTip.textContent='加载完成!';
                //移除模型
                // this.Model &&  this.Scene.remove(this.Model);
                console.log("Model111---",this.Model)
                //@ts-ignore
                this.Model &&  myThree.children[0].remove();
                //设置相机位置
                this.Camera.position.set(...MODEL.position);
                //当前模型
                this.Model = 'fbx'.indexOf(MTYPE)!=-1?geometry:geometry.scene;

                console.log("Model22---",this.Model)
                //初始化当前模型
                MODEL.init && MODEL.init(this.Model,geometry)
                //默认遍历模型字节点,获取相关参数设置 特殊模型前往init回调中设置
                let that = this;

                this.Model.traverse((child:any) => {
                    if(child.isMesh) {
                        child.material.emissiveMap = child.material.map;
                    }
                })
                //模型自动居中
                 ModelAutoCenter(geometry)
                //加载完成后开始自动播放
                setTimeout(() => {
                    loadTip.style.display = 'none';
                }, 1000);
                this.Scene.add(this.Model);
            },
            (xhr:any)=>{
                //加载进度
                //@ts-ignore
                loadTip.textContent=(parseInt(xhr.loaded/xhr.total*100)+'%加载中...');
            },
            (err:any)=>{
                loadTip.textContent='模型加载失败!'
            }
        );
        }

9. 加载光源

addLight(){
 this.Lights = [
             //平行光(DirectionalLight)
             // color 光的颜色。 缺省值为 0xffffff (白色)。intensity - (可选参数) 光照的强度。缺省值为1。
             {name:'AmbientLight',obj:new THREE.AmbientLight(0xFFFFFF,2.2)},
             {name:'DirectionalLight_top',obj:new THREE.DirectionalLight(0xFFFFFF,2.2),position:[10, 80,65]},
             {name:'DirectionalLight_bottom',obj:new THREE.DirectionalLight(0x1B1B1B,2.2),position:[10, 80,65]},
             {name:'DirectionalLight_right1',obj:new THREE.DirectionalLight(0xFFFFFF,2.2),position:[10, 80,65]},
             {name:'DirectionalLight_right2',obj:new THREE.DirectionalLight(0xFFFFFF,2.2),position:[10, 80,65]},
         ];
         this.Lights.map((item:any)=>{
             item.obj.name=item.name;
             item.position && item.obj.position.set(...item.position);
             item.Helper = new THREE.PointLightHelper( item.obj );
             this.Scene.add(item.obj);
         })
        }

10. 添加事件

   addControls() {
		this.Controls = new OrbitControls(this.Camera, this.Renderer.domElement);
        // 如果使用animate方法时,将此函数删除
        //controls.addEventListener( 'change', render );
        // 使动画循环使用时阻尼或自转 意思是否有惯性
        this.Controls.enableDamping = false;
        //是否可以缩放
        this.Controls.enableZoom = true;
        //设置相机距离原点的最远距离-可以控制缩放程度
        this.Controls.minDistance = 0;
        //设置相机距离原点的最远距离
        this.Controls.maxDistance = 3000;//800
        //是否开启右键拖拽
        this.Controls.enablePan = true;
        //动态阻尼系数 就是鼠标拖拽旋转灵敏度
        this.Controls.dampingFactor = 0.5;
        //是否自动旋转
        this.Controls.autoRotate = false;
       this.Controls.autoRotateSpeed = 1;
       }

11. 添加加载进度

 addLoadTip(){
        document.querySelector('.loadTip') &&  myThree.removeChild(document.querySelector('.loadTip'));
        let  loadTip =  document.createElement('div');
        loadTip.className='loadTip'
        loadTip.style.cssText+='position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);border-radius:5px;background-color:rgba(0,0,0,0.5);padding:5px 10px;color:#fff;';
        myThree.appendChild(loadTip);
        return loadTip;
        }

12. 更新

animation(){
    //更新控制器
    this.Renderer.render(this.Scene, this.Camera);
    this.Controls.update();
    this.AnimationMixer && this.AnimationMixer.update(this.Tclock.getDelta());
    requestAnimationFrame(()=>this.animation());
},
onWindowResize() {
    //@ts-ignore
    this.Camera.aspect = threeBox.clientWidth / threeBox.clientHeight ;
    this.Camera.updateProjectionMatrix();
    //@ts-ignore
    this.Renderer.setSize(threeBox.clientWidth, threeBox.clientHeight - 20);
    this.Renderer.render(this.Scene, this.Camera);
},

13. 运行

run(){
        return new Promise((resolve, reject) => {
            this.init.Renderer.call(this)
            this.init.Scene.call(this)
            this.init.Camera.call(this)
            this.addControls();
            //添加环境光
            this.addLight()
            this.modelLoader(models);
            this.animation();
            //添加辅助面板
            window.onresize = ()=>this.onWindowResize();
            resolve(modelScene)
        })
    }

应用

import  { modelScene } from "./loadFbx";
setTimeout(()=>{
  modelScene.run()
},1000)

总结

例如:以上就是今天要讲的内容,本文仅仅简单介绍了three的导入fbx的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值