Three.js 导入fbx

其实可以先看看官方案例
你想要的东西 官方里面都有,就看你找不找得到了。。。。
话不多说
我们先看看这个例子吧

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - FBX loader</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <style>
            body {
                font-family: Monospace;
                background-color: #000;
                color: #fff;
                margin: 0px;
                overflow: hidden;
            }
            #info {
                color: #fff;
                position: absolute;
                top: 10px;
                width: 100%;
                text-align: center;
                z-index: 100;
                display:block;
            }
            #info a {
                color: #046;
                font-weight: bold;
            }
        </style>
    </head>

    <body>
        <div id="info">
            <a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - FBXLoader<br />
            Character and animation from <a href="https://www.mixamo.com/" target="_blank" rel="noopener">Mixamo</a>
        </div>

        <script src="../build/three.js"></script>

        <script src="js/libs/inflate.min.js"></script>
        <script src="js/loaders/FBXLoader.js"></script>

        <script src="js/controls/OrbitControls.js"></script>

        <script src="js/Detector.js"></script>
        <script src="js/libs/stats.min.js"></script>

        <script>

            if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

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

            var clock = new THREE.Clock();

            var mixers = [];

            init();
            animate();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
                camera.position.set( 100, 200, 300 );

                controls = new THREE.OrbitControls( camera );
                controls.target.set( 0, 100, 0 );
                controls.update();

                scene = new THREE.Scene();
                scene.background = new THREE.Color( 0xa0a0a0 );
                scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );

                light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
                light.position.set( 0, 200, 0 );
                scene.add( light );

                light = new THREE.DirectionalLight( 0xffffff );
                light.position.set( 0, 200, 100 );
                light.castShadow = true;
                light.shadow.camera.top = 180;
                light.shadow.camera.bottom = -100;
                light.shadow.camera.left = -120;
                light.shadow.camera.right = 120;
                scene.add( light );

                // scene.add( new THREE.CameraHelper( light.shadow.camera ) );

                // ground
                var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
                mesh.rotation.x = - Math.PI / 2;
                mesh.receiveShadow = true;
                scene.add( mesh );

                var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
                grid.material.opacity = 0.2;
                grid.material.transparent = true;
                scene.add( grid );

                // model
                var loader = new THREE.FBXLoader();
                loader.load( 'models/fbx/Samba Dancing.fbx', function ( object ) {

                    object.mixer = new THREE.AnimationMixer( object );
                    mixers.push( object.mixer );

                    var action = object.mixer.clipAction( object.animations[ 0 ] );
                    action.play();

                    object.traverse( function ( child ) {

                        if ( child.isMesh ) {

                            child.castShadow = true;
                            child.receiveShadow = true;

                        }

                    } );

                    scene.add( object );

                } );

                renderer = new THREE.WebGLRenderer();
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.shadowMap.enabled = true;
                container.appendChild( renderer.domElement );

                window.addEventListener( 'resize', onWindowResize, false );

                // stats
                stats = new Stats();
                container.appendChild( stats.dom );

            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            //

            function animate() {

                requestAnimationFrame( animate );

                if ( mixers.length > 0 ) {

                    for ( var i = 0; i < mixers.length; i ++ ) {

                        mixers[ i ].update( clock.getDelta() );

                    }

                }

                renderer.render( scene, camera );

                stats.update();

            }

        </script>

    </body>
</html>

首先我们找到这个例子,然后对其解析,化为自己的知识


image.png

我们看到引入的js库有以上几类
首当其先的为three.js
然后是inflate.min.js,我也不知道这是干撒的,但是当我百度这个找到了后,怀着崇敬的心情以及准备自我翻译作用的时候,我看到了汉字+五十音的时候,心中崩腾过了emmm。2只羊驼。只好勉强看汉字,应该是压缩用的吧。。。知道的麻烦给个准信。。。


image.png

接着是FBXLoader.js库,看名字就知道是fbx文件的加载库
所以,我们这个时候应该看看源码。


image.png

恩,一来就看到要求fbx格式以及一串的支持。
看正文
( function () {
//构造函数
    THREE.FBXLoader = function ( manager ) {

        this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

    };

    Object.assign( THREE.FBXLoader.prototype, {
//加载函数
        load: function ( url, onLoad, onProgress, onError ) {

            var self = this;

            var resourceDirectory = THREE.LoaderUtils.extractUrlBase( url );

            var loader = new THREE.FileLoader( this.manager );
            loader.setResponseType( 'arraybuffer' );
            loader.load( url, function ( buffer ) {

                try {
//解析
                    var scene = self.parse( buffer, resourceDirectory );
                    onLoad( scene );

                } catch ( error ) {

                    window.setTimeout( function () {

                        if ( onError ) onError( error );

                        self.manager.itemError( url );

                    }, 0 );

                }

            }, onProgress, onError );

        },

        parse: function ( FBXBuffer, resourceDirectory ) {

            var FBXTree;
                  //判断类型
            if ( isFbxFormatBinary( FBXBuffer ) ) {

                FBXTree = new BinaryParser().parse( FBXBuffer );

            } else {

                var FBXText = convertArrayBufferToString( FBXBuffer );

                if ( ! isFbxFormatASCII( FBXText ) ) {

                    throw new Error( 'THREE.FBXLoader: Unknown format.' );

                }

                if ( getFbxVersion( FBXText ) < 7000 ) {

                    throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion( FBXText ) );

                }

                FBXTree = new TextParser().parse( FBXText );

            }

            // console.log( FBXTree );
//一连串的emmmmm,解析以及构建(你猜)
            var connections = parseConnections( FBXTree );
            var images = parseImages( FBXTree );
            var textures = parseTextures( FBXTree, new THREE.TextureLoader( this.manager ).setPath( resourceDirectory ), images, connections );
            var materials = parseMaterials( FBXTree, textures, connections );
            var skeletons = parseDeformers( FBXTree, connections );
            var geometryMap = parseGeometries( FBXTree, connections, skeletons );
            var sceneGraph = parseScene( FBXTree, connections, skeletons, geometryMap, materials );
            return sceneGraph;
        }
    } );

上面最后的一串方法都在库后面放着的,有兴趣的可以看看。
然后是OrbitControls.js 接收的camera参数


image.png

这就是它的介绍,至于源码有兴趣的看看吧。
剩下的库有兴趣自己看看源码吧,找不到,去three.js官网下载压缩包,撒都有。
然后我们开始了解如何构造的


开始

上图emmm,不用说了
兼容

这句我想知道什么意思,查了一下原来是检查兼容性。一句话就解决了。。给个赞!
container = document.createElement( 'div' );
        document.body.appendChild( container );
//相机
        camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
        camera.position.set( 100, 200, 300 );
//控制器     相应鼠标左键右键点击
        controls = new THREE.OrbitControls( camera );
        controls.target.set( 0, 100, 0 );
        controls.update();
//舞台(场景)
        scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xa0a0a0 );
        scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );
//灯光
        light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
        light.position.set( 0, 200, 0 );
        scene.add( light );

        light = new THREE.DirectionalLight( 0xffffff );
        light.position.set( 0, 200, 100 );
        light.castShadow = true;
        light.shadow.camera.top = 180;
        light.shadow.camera.bottom = -100;
        light.shadow.camera.left = -120;
        light.shadow.camera.right = 120;
        scene.add( light );
// ground
        var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
        mesh.rotation.x = - Math.PI / 2;
        mesh.receiveShadow = true;
        scene.add( mesh );

        var grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
        grid.material.opacity = 0.2;
        grid.material.transparent = true;
        scene.add( grid );

明显的构建广场。最后就是加载model

// model
      //得到加载器
        var loader = new THREE.FBXLoader();
     //开始加载,并且异步加载,别问我,我也不知道,方法体里参数是
    //(url,onLoad,onProgress,onError)
    //所以对应咯
        loader.load( '../fbx/aa.FBX', function ( object ) {
            //动画
            object.mixer = new THREE.AnimationMixer( object );
            mixers.push( object.mixer );
            var action = object.mixer.clipAction( object.animations[ 0 ] );
            action.play();
            //那个,纹理maybe,理解错了 请指出
            object.traverse( function ( child ) {

                if ( child.isMesh ) {

                    child.castShadow = true;
                    child.receiveShadow = true;

                }

            } );

            scene.add( object );

        } );

好了,看不看得懂,不要紧,要懂得基本操作就好了,是在不行,自己去例子里面现学现卖。当然懂了最好
最后我们实际运行一下。

这鱼是在游的

ok,一切完美。
对了这些代码需要在服务器上执行,没有服务器?你的ide没有自带么?(webstorm)
最后,给个“毒”福利。
希望你们在看例子的时候
https://threejs.org/examples/#webgl_loader_fbx
能听这首歌 Its love -张碧晨
很带感!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容