WebGL10---3D模型的加载与使用

1、关于模型的基础知识

      3D模型由顶点(vertex)组成,顶点之间连成三角形或四边形(在一个平面上),多个三角形或四边形就能够组成复杂的立体模型;

使用ParaView查看3D模型

 

2、模型在three.js中的表示

      模型由面组成,面分为三角形和四边形。三角形和四边形面组成了网格模型。在three.js中用THREE.Mesh来表示网格模式。

THREE.Mesh可以和THREE.Line相提并论;区别是THREE.Line表示的是线条,THREE.Mesh表示面的集合;

       THREE.Mesh = function(geometry,material)

       参数说明:① geometry 是一个THREE.Geometry类型的对象,是一个包含顶点和顶点之间的连接关系对象;

                        ② Material:是一个定义的材质;

 

3、模型的加载

     

      ① 服务器上的模型文件大多是存储模型的顶点信息,这些信息可以以文本的方式存储的(并不一定需要文本的方式存储)。

Three.js支持很多种3D模型格式,例如:ply,stl,obj,vtk等等。随着three.js的升级,会支持越来越多的文件格式;

      ② 第二步是浏览器下载文本文件,这是一件很普通的事情,只需要使用javascript的异步请求就可以实现;

      ③ javascript 解析文本并生成一个geometry,最终生成Mesh;

 

4、顶点和面索引之间的关系

        加载vtk模型,主要分为2步:

        ① 将vtk文件中的点,转换为geometry的vertices数组中;

         ② 将vtk文件中每个点的索引,转换为geometry的faces中;

    

 

 关于vtk文件的加载

        //构造函数

        THREE.VTKLoader = function(){

                 THREE.EventDispatcher.call(this);//继承自监听器,使这个类有监听的功能;

         };

         //VTKLoader的原型函数,里面包含了VTKLoader的成员函数,成员变量的定义;

         THREE.VTKLoader.prototype = {

                 //构造函数

                 constructor: THREE.VTKLoader,

                //加载函数:url表示要加载的vtk文件的url路径,callback表示加载完成后要调用的后续处理函数;

                load: function(url,callback){

                       //将类自身保存在scope中,scope表示域的意思,这里为了避免this的歧义

                       var scope = this;

                       //ajax异步请求

                       var request = new XMLHttpRequest();

                       //加载完成的监听器,加载完成后,将调用第二个参数定义的回调函数

                       request.addEventListener('load',function(event){

                              //对服务器加载下来的数据进行解析;

                             var geometry = scope.parse(event.target.responseText);

                             //解析完成后,发一个load事件,表示数据解析完成

                             scope.dispatchEvent({ type:'load',content: geometry });

                             //如果设置了回调函数,那么调用回调函数

                             if(callback) callback(geometry);

                       },false);

                       //加载过程中,向自身发送进度progress信息,信息中包含了已经加载的数据的字节数和文件总共的字节数

                       //通过两者的比例了解加载的进度;

                      request.addEventListener('progress',function(event){

                              //发送正在加载的信息,两个参数分别是已经加载了多少字节,总共多少字节

                              scope.dispatchEvent({ type:'progress',loader:event.loader,total: event.total});

                      },false);

                      //加载出错的监听器,加载的过程中也可能出错;

                      request.addEventListener('error',function(){

                               //加载出错后需要发布的错误消息

                               scope.dispatchEvent({ type:'error',message: 'could not  load url'});

                      },false);

                      //初始化HTTP请求参数,例如: url和http方法,但是并不发送请求。

                      request.open('get',url,true);

                      //发送http请求,开始下载

                      request.send(null);

                },

               //data是从服务器传过来的数据,其实就是vtk文件中的文本数据;

                parse:function(data){

                       //new 一个几何体

                       var geometry = new THREE.Geometry();

                       //定义一个内部函数vertex,用参数x,y,z生成一个顶点,并放入geometry的vertices数组中

                      function vertex(x,y,z){

                             geometry.vertices.push(new THREE.Vector3(x,y,z));

                      }

                      //定义一个面索引函数face3,将面的3个点的索引放入geometry的faces数组中;

                      function face3(x,y,z){

                              geometry.faces.push(new THREE.Face3(x,y,z));

                       }

                       //定义一个面索引函数face4,将面的四个点的索引放入;

                       function face4(a,b,c,d){

                              geometry.faces.push(new THREE.Face4(a,b,c,d));

                       }

                       //pattern存放模式字符串,result是临时变量;

                      var pattern,result;

                      //float float float ,pattern是一个正在表达式,能够匹配3个空格隔开的float

                      pattern = /([\+|\-]?[\d]+[\.][\d|\-|e]+)[ ]+([\+|\-]?[\d]+[\.][\d|\-|e]+)[ ]+([\+|\-]?[\d]+[\.][\d|\-|e]+)/g;                  

                   // exec是正则表达式的执行匹配函数,result返回一个包含3个字符串的数组,如果data读到了最后,那么result将返回null
                   // while 循环在data中,寻找符合正则表示式的数据,将符合条件的数据,转换为一个顶点
                    while ( ( result = pattern.exec( data ) ) != null ) {
                                       // ["1.0 2.0 3.0", "1.0", "2.0", "3.0"]
                                     // 将字符串转换为float,并放入geometry中
                               vertex( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
                     }
// 3 int int int,这里匹配面数据,如3 21216 21215 20399,这类数据是面索引数据 pattern = /3[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)/g; // 取出data中的所有面索引数据, while ( ( result = pattern.exec( data ) ) != null ) { // ["3 1 2 3", "1", "2", "3"] // 将面数据放入geometry的faces中 face3( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 3 ] ) ); } // 4 int int int int // 这里是4个顶点一个面的情况,本例的vtk文件,没有这种情况 pattern = /4[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)/g; while ( ( result = pattern.exec( data ) ) != null ) { // ["4 1 2 3 4", "1", "2", "3", "4"] face4( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 3 ] ), parseInt( result[ 4 ] ) ); } // 这里的4个函数,在后面解释 geometry.computeCentroids(); geometry.computeFaceNormals(); geometry.computeVertexNormals(); geometry.computeBoundingSphere(); return geometry;

 

               }

          }

posted @ 2019-02-26 17:37  倩妞驾到  阅读(4462)  评论(1编辑  收藏  举报