打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
three.js 源码注释(二十五)Core/Geometry.js

转载请保留此句:商域无疆 - 本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、html5、WEBGL、THREE.JS,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。


俺也是刚开始学,好多地儿肯定不对还请见谅.

以下代码是THREE.JS 源码文件中Core/Geometry.js文件的注释.

更多更新在 : https://github.com/omni360/three.js.sourcecode


/*** @author mrdoob / http://mrdoob.com/* @author kile / http://kile.stravaganza.org/* @author alteredq / http://alteredqualia.com/* @author mikael emtinger / http://gomo.se/* @author zz85 / http://www.lab4games.net/zz85/blog* @author bhouston / http://exocortex.com*//*///Geometry是场景中由顶点和三角面构成的几何体对象的基类,保存描述几何体所有必要的数据.Geometry对象的功能函数采用定义构造的函数原型对象来实现./// 用法:var geometry = new THREE.Geometry();geometry.vertices.push( new THREE.Vector3( -10, 10, 0 ),new THREE.Vector3( -10, -10, 0 ),new THREE.Vector3( 10, -10, 0 ));geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );geometry.computeBoundingSphere();*////GeometryTHREE.Geometry = function () {/********************************************下面是Geometry对象的属性定义****************************************/this.id = THREE.GeometryIdCount ++; //Geometry对象id属性.this.uuid = THREE.Math.generateUUID(); //调用THREE.Math.generateUUID()方法,Geometry对象uuid(通用唯一识别码)属性,this.name = ''; //Geometry对象name属性,可以为当前对象定义一个名称,初始化为''this.vertices = []; //Geometry对象顶点位置存放在this.vertices属性中,该属性是一个数组,初始化为空数组.// NOTE: 若要更新this.vertices属性,需要将 Geometry.verticesNeedUpdat设置为true.this.colors = []; // one-to-one vertex colors, used in Points and Line// 根据索引的顺序一对一的保存顶点颜色,用于点和线.// NOTE: 网格顶点的颜色存放在面里面.如果要更新this.colors属性需要将Geometry.colorsNeedUpdate设置为true.this.faces = []; //将Geometry对象的三角面存放在this.faces属性中,该属性是一个数组,初始化为空数组.这个数组描述在模型中每个顶点式怎样彼此连接的.//如果要更新this.faces属性,需要将Geometry.elementsNeedUpdate 设置为true.this.faceVertexUvs = [ [] ]; //将Geometry对象的三角面的uv层存放在this.faceVertexUvs属性中,按照三角面的索引顺序,将三角面的顶点按照顶点在三角面中的索引顺序存放在数组中,这里是一个二维数组.//NOTE:如果要更新this.faceVertexUvs的值,需要将Geometry.uvsNeedUpdate属性设置为true/*///MorphTargets///原文地址:http://www.codesec.netrYzuuu///先睹为快//////MorphTargets允许物体发生变形。如果该物体的geometry有 $n$ 个顶点,那么MorphTargets允许你再指定 $n$ 个, $2n$ 个, $3n$ 个甚至更多个顶点///(比如,$ pcdot n$ 个),同时mesh对象提供一个数组morphTargetInfluences(公式中$ f_{j} $表示morphTargetInfluences[j]),具有 $p$ 个元素,///每个元素取值在0-1之间。渲染这个物体的时候,某个顶点 $V_{i}$ 的位置其实变了,成了://////$$V_{i}=V_{i}+sum_{j=0}^{p}f_{j}cdot (V_{j,i}-V_{i})$$//////举个简单的例子,一个立方体有8个顶点, MorphTargets又指定了8个顶点,立方体的一个顶点为(1,1,1),而在 MorphTargets中与之对应的顶点为(2,2,2),///那么当 morphTargetInfluences[0]为0.5的时候,实际渲染的时候该顶点的位置就成了(1.5,1.5,1.5)。这样做的好处是显而易见的,你可以通过简单地调整/// morphTargetInfluences数组来使物体形变,只要之前你设置好了。//////向物体加入morphTargets的方法很简单://////var geometry = new THREE.CubeGeometry(100,100,100);/// var material = new THREE.MeshLambertMaterial({color:0xffffff, morphTargets:true});////// var vertices = [];/// for(var i=0; iapplyMatrix///仿射矩阵///返回新的Geometry对象applyMatrix: function ( matrix ) {var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix ); //调用THREE.Matrix3().getNormalMatrix方法,获得规范化的matrixfor ( var i = 0, il = this.vertices.length; i < il; i ++ ) { //遍历vertices数组,var vertex = this.vertices[ i ];vertex.applyMatrix4( matrix ); //对每个顶点应用变换.}for ( var i = 0, il = this.faces.length; i < il; i ++ ) { //遍历faces数组,var face = this.faces[ i ];face.normal.applyMatrix3( normalMatrix ).normalize();for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { //遍历faces的vertexNormal数组,face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); //对faces中的vertexNormal中的每个顶点应用变换.}}if ( this.boundingBox instanceof THREE.Box3 ) {this.computeBoundingBox(); //重新计算当前Geometry对象的立方体界限}if ( this.boundingSphere instanceof THREE.Sphere ) {this.computeBoundingSphere(); //重新计算当前Geometry对象的球体界限}},/*///center方法通过计算出当前Geometry对象的立方体界限的中心,获得当前对象的中心.*////center///返回中心点坐标center: function () {this.computeBoundingBox(); //调用computeBoundingBox方法,获得当前Geometry对象的立方体界限var offset = new THREE.Vector3();offset.addVectors( this.boundingBox.min, this.boundingBox.max ); //offset.multiplyScalar( - 0.5 ); //计算出当前Geometry对象的立方体界限的中心this.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) ); //调用applyMatrix方法,将对象中的每个顶点应用变换,改变相对新的中心点的顶点坐标this.computeBoundingBox(); //重新计算当前Geometry对象的立方体界限return offset; //返回中心点坐标},/*///computeFaceNormals方法重新计算三角面对象的法线向量,计算法线向量,影响的是face数组中每个元素的normal属性,一个face只有1个*////computeFaceNormals///返回重算法线向量后的几何体对象computeFaceNormals: function () {var cb = new THREE.Vector3(), ab = new THREE.Vector3();for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { //遍历faces数组,var face = this.faces[ f ];var vA = this.vertices[ face.a ];var vB = this.vertices[ face.b ];var vC = this.vertices[ face.c ];cb.subVectors( vC, vB );ab.subVectors( vA, vB );cb.cross( ab ); //返回叉积cb.normalize(); //规范化cbface.normal.copy( cb ); //一一重新设置face的法线向量}},/*///computeVertexNormals方法重新计算三角面对象顶点的法线向量,face数组中每个元素的vertexNormal属性,一个face3型对象有3个,一个face4型对象有4个,/// 但是需要注意的是,被多个表面共享的顶点,其法线向量只有一个,同时受到多个表面的影响。比如中心在原点,三组表面都垂直于轴的立方体,/// 其第一象限中的顶点,法线向量是(1,1,1)的归一化。虽然看上去不可思议,平面的顶点的法线居然不是垂直于平面的,但这种指定法线的方法/// 在利用平面模拟曲面的时候有很好的效果。////// 定义:顶点法线(Vertex Normal)是过顶点的一个矢量,用于在高洛德着色(Gouraud Shading)中的计算光照和纹理效果。在生成曲面时,/// 通常令顶点法线和相邻平面的法线保持等角,如图1,这样进行渲染时,会在平面接缝处产生一种平滑过渡的效果。如果是多边形,/// 则令顶点法线等于该点所属平面(三角形)的法线,如图2,以便在接缝处产生突出的边缘。////// 参考:http://en.wikipedia.org/wiki/Vertex_normal/// 参考:http://blog.csdn.net/sophistcxf/article/details/9095911/// 参考:http://www.cnblogs.com/flying_bat/archive/2007/10/13/923286.html*////computeVertexNormals///true表示face数组中的发现没有被计算,false或者忽略表示已经计算过了///返回重算法线向量后的几何体对象computeVertexNormals: function ( areaWeighted ) {var v, vl, f, fl, face, vertices;vertices = new Array( this.vertices.length );for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {vertices[ v ] = new THREE.Vector3();}if ( areaWeighted ) { //face 的法线向量必须已经计算过了,如果没有,在这里计算.// vertex normals weighted by triangle areas// http://www.iquilezles.org/www/articles/normals/normals.htmvar vA, vB, vC, vD;var cb = new THREE.Vector3(), ab = new THREE.Vector3(),db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {//TODO: 可以直接调用computeFaceNormal()方法.face = this.faces[ f ];vA = this.vertices[ face.a ];vB = this.vertices[ face.b ];vC = this.vertices[ face.c ];cb.subVectors( vC, vB );ab.subVectors( vA, vB );cb.cross( ab );vertices[ face.a ].add( cb );vertices[ face.b ].add( cb );vertices[ face.c ].add( cb );}} else {for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {face = this.faces[ f ];vertices[ face.a ].add( face.normal ); //一一求出vertices[ face.b ].add( face.normal );vertices[ face.c ].add( face.normal );}}for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {vertices[ v ].normalize(); //一一规范化顶点数组}for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {face = this.faces[ f ];face.vertexNormals[ 0 ] = vertices[ face.a ].clone(); //一一重新设置vertexNormals的法线向量face.vertexNormals[ 1 ] = vertices[ face.b ].clone(); //一一重新设置vertexNormals的法线向量face.vertexNormals[ 2 ] = vertices[ face.c ].clone(); //一一重新设置vertexNormals的法线向量}},/*///computeMorphNormals方法重新计算三角面对象变形顶点的法线向量,morph应该是用作显示固定连续动画的变形效果。face数组中每个元素的vertexNormal属性,一个face3型对象有3个,一个face4型对象有4个,/// 但是需要注意的是,被多个表面共享的顶点,其法线向量只有一个,同时受到多个表面的影响。比如中心在原点,三组表面都垂直于轴的立方体,/// 其第一象限中的顶点,法线向量是(1,1,1)的归一化。虽然看上去不可思议,平面的顶点的法线居然不是垂直于平面的,但这种指定法线的方法/// 在利用平面模拟曲面的时候有很好的效果。////// 定义:顶点法线(Vertex Normal)是过顶点的一个矢量,用于在高洛德着色(Gouraud Shading)中的计算光照和纹理效果。在生成曲面时,/// 通常令顶点法线和相邻平面的法线保持等角,如图1,这样进行渲染时,会在平面接缝处产生一种平滑过渡的效果。如果是多边形,/// 则令顶点法线等于该点所属平面(三角形)的法线,如图2,以便在接缝处产生突出的边缘。////// 参考:http://en.wikipedia.org/wiki/Vertex_normal/// 参考:http://blog.csdn.net/sophistcxf/article/details/9095911/// 参考:http://www.cnblogs.com/flying_bat/archive/2007/10/13/923286.html*////computeMorphNormals///返回重算变形顶点法线向量后的几何体对象computeMorphNormals: function () {var i, il, f, fl, face;// save original normals// 保存初始法线向量值// - create temp variables on first access// 首次访问,创建临时变量// otherwise just copy (for faster repeated calls)// 否则只是复制,更快的重复调用.for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {face = this.faces[ f ];if ( ! face.__originalFaceNormal ) {face.__originalFaceNormal = face.normal.clone();} else {face.__originalFaceNormal.copy( face.normal );}if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {if ( ! face.__originalVertexNormals[ i ] ) {face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();} else {face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );}}}// use temp geometry to compute face and vertex normals for each morph// 使用临时几何体对象计算每个面和顶点法线向量var tmpGeo = new THREE.Geometry();tmpGeo.faces = this.faces;for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {// create on first access// 首次读取,先创建.if ( ! this.morphNormals[ i ] ) {this.morphNormals[ i ] = {};this.morphNormals[ i ].faceNormals = [];this.morphNormals[ i ].vertexNormals = [];var dstNormalsFace = this.morphNormals[ i ].faceNormals;var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;var faceNormal, vertexNormals;for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {faceNormal = new THREE.Vector3();vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };dstNormalsFace.push( faceNormal );dstNormalsVertex.push( vertexNormals );}}var morphNormals = this.morphNormals[ i ];// set vertices to morph target// 设置顶点到变形顶点tmpGeo.vertices = this.morphTargets[ i ].vertices;// compute morph normals// 计算变形顶点法线向量tmpGeo.computeFaceNormals();tmpGeo.computeVertexNormals();// store morph normals// 保存变形顶点法线向量var faceNormal, vertexNormals;for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { //遍历三角面的vertexNormal数组face = this.faces[ f ];faceNormal = morphNormals.faceNormals[ f ];vertexNormals = morphNormals.vertexNormals[ f ];faceNormal.copy( face.normal );vertexNormals.a.copy( face.vertexNormals[ 0 ] );vertexNormals.b.copy( face.vertexNormals[ 1 ] );vertexNormals.c.copy( face.vertexNormals[ 2 ] ); //一一存储}}// restore original normals// 恢复原来的平面法线向量.for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {face = this.faces[ f ];face.normal = face.__originalFaceNormal;face.vertexNormals = face.__originalVertexNormals;}},/*///computeTangents方法重新计算三角面对象顶点的切线空间,///TBN切线是一个有方向的单位长度,沿着网格表面指向水平(U)纹理方向。在Three.js中切线被描述为Vector4,包括x,y,z这些组件定义的矢量,///如果需要,及w用来翻转副法线。////// 参考:http://blog.csdn.net/bonchoix/article/details/8619624/// 参考:http://azykise.blog.163.com/blog/static/1730802442010431113010224//// 参考:http://blog.csdn.net/meegomeego/article/details/8605463/// 参考:http://shiba.hpe.sh.cn/jiaoyanzu/wuli/showArticle.aspx?articleId=474&classId=4////// NOTE:几何体Geometry对象必须有vertex UV属性,0层将被使用.*////computeTangents///返回重算切线空间后的几何体对象computeTangents: function () {// based on http://www.terathon.com/code/tangent.html// tangents go to verticesvar f, fl, v, vl, i, il, vertexIndex,face, uv, vA, vB, vC, uvA, uvB, uvC,x1, x2, y1, y2, z1, z2,s1, s2, t1, t2, r, t, test,tan1 = [], tan2 = [],sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),n = new THREE.Vector3(), w;for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {tan1[ v ] = new THREE.Vector3();tan2[ v ] = new THREE.Vector3();}/*///handleTriangle方法重新计算三角面对象的切线空间的TB,TBN.*////handleTriangle///几何体对象///三角面角点a的索引///三角面角点b的索引///三角面角点c的索引///三角面角点a的索引///三角面角点b的索引///三角面角点c的索引function handleTriangle( context, a, b, c, ua, ub, uc ) {vA = context.vertices[ a ];vB = context.vertices[ b ];vC = context.vertices[ c ];uvA = uv[ ua ];uvB = uv[ ub ];uvC = uv[ uc ];x1 = vB.x - vA.x;x2 = vC.x - vA.x;y1 = vB.y - vA.y;y2 = vC.y - vA.y;z1 = vB.z - vA.z;z2 = vC.z - vA.z;s1 = uvB.x - uvA.x;s2 = uvC.x - uvA.x;t1 = uvB.y - uvA.y;t2 = uvC.y - uvA.y;r = 1.0 / ( s1 * t2 - s2 * t1 );sdir.set( ( t2 * x1 - t1 * x2 ) * r,( t2 * y1 - t1 * y2 ) * r,( t2 * z1 - t1 * z2 ) * r );tdir.set( ( s1 * x2 - s2 * x1 ) * r,( s1 * y2 - s2 * y1 ) * r,( s1 * z2 - s2 * z1 ) * r );tan1[ a ].add( sdir );tan1[ b ].add( sdir );tan1[ c ].add( sdir );tan2[ a ].add( tdir );tan2[ b ].add( tdir );tan2[ c ].add( tdir );}for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { //遍历所有的三角面face = this.faces[ f ];uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents// 使用UV属性的0层.handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 ); //一一计算切线坐标空间}var faceIndex = [ 'a', 'b', 'c', 'd' ];for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { //遍历所有三角面face = this.faces[ f ];for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i ++ ) {n.copy( face.vertexNormals[ i ] );vertexIndex = face[ faceIndex[ i ] ];t = tan1[ vertexIndex ];// Gram-Schmidt orthogonalizetmp.copy( t );tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();// Calculate handedness// 计算tmp2.crossVectors( face.vertexNormals[ i ], t );test = tmp2.dot( tan2[ vertexIndex ] );w = ( test < 0.0 ) ? - 1.0 : 1.0;face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w ); //切线是一个有方向的单位长度,沿着网格表面指向水平(U)纹理方向。在Three.js中切线被描述为Vector4,包括x,y,z这些组件定义的矢量,如果需要,及w用来翻转副法线。}}this.hasTangents = true; //将全局属性hasTangents设置为true.},/*///computeLineDistances方法重新计算顶点数组将顶点按照索引顺序依次连线产生的几何线段的长度///NOTE:如果已经要更新this.lineDistances属性,需要将Geometry.lineDistancesNeedUpdate设置为true*////computeLineDistances///返回重算相邻顶点长度后的几何体对象computeLineDistances: function () {var d = 0;var vertices = this.vertices;for ( var i = 0, il = vertices.length; i < il; i ++ ) { //遍历所有的顶点.if ( i > 0 ) {d += vertices[ i ].distanceTo( vertices[ i - 1 ] );}this.lineDistances[ i ] = d; //一一将相邻两点的长度保存在this.lineDistances属性中}},/*///computeBoundingBox方法重新计算当前几何体对象的立方体界限,并更新this.boundingBox[]属性.*////computeBoundingBox///返回重算立方体界限后的几何体对象computeBoundingBox: function () {if ( this.boundingBox === null ) {this.boundingBox = new THREE.Box3();}this.boundingBox.setFromPoints( this.vertices ); //计算当前几何体对象的立方体界限并更新this.boundingBox[]属性.},/*///computeBoundingSphere方法重新计算当前几何体对象的球体界限,并更新this.boundingSphere[]属性.*////computeBoundingSphere///返回重算球体界限后的几何体对象computeBoundingSphere: function () {if ( this.boundingSphere === null ) {this.boundingSphere = new THREE.Sphere();}this.boundingSphere.setFromPoints( this.vertices ); //计算当前几何体对象的球体界限并更新this.boundingSphere[]属性.},/*///merge方法将两个几何体对象或者Object3D里面的几何体对象合并,(使用对象的变换)将几何体的顶点,面,UV分别合并.*////merge///要被合并的几何体.///可选参数,变换矩阵,当指定了该参数,合并后的对象会应用变换///材质索引偏移量///返回合并后的几何体对象merge: function ( geometry, matrix, materialIndexOffset ) {if ( geometry instanceof THREE.Geometry === false ) { //如果geometry不是THREE.Geometry,//提示用户对象类型错误.console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );return; //退出.}var normalMatrix,vertexOffset = this.vertices.length,uvPosition = this.faceVertexUvs[ 0 ].length,vertices1 = this.vertices,vertices2 = geometry.vertices,faces1 = this.faces,faces2 = geometry.faces,uvs1 = this.faceVertexUvs[ 0 ],uvs2 = geometry.faceVertexUvs[ 0 ];if ( materialIndexOffset === undefined ) materialIndexOffset = 0;if ( matrix !== undefined ) {normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );}// vertices// 合并顶点数组for ( var i = 0, il = vertices2.length; i < il; i ++ ) {var vertex = vertices2[ i ];var vertexCopy = vertex.clone();if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); //应用变换vertices1.push( vertexCopy ); //合并数组.}// faces// 合并三角面数组for ( i = 0, il = faces2.length; i < il; i ++ ) {var face = faces2[ i ], faceCopy, normal, color,faceVertexNormals = face.vertexNormals,faceVertexColors = face.vertexColors;faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );faceCopy.normal.copy( face.normal );if ( normalMatrix !== undefined ) {faceCopy.normal.applyMatrix3( normalMatrix ).normalize();}for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { //遍历三角面顶点法线向量属猪normal = faceVertexNormals[ j ].clone();if ( normalMatrix !== undefined ) {normal.applyMatrix3( normalMatrix ).normalize(); // 一一合并}faceCopy.vertexNormals.push( normal );}faceCopy.color.copy( face.color );for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { //遍历三角面顶点颜色数组color = faceVertexColors[ j ];faceCopy.vertexColors.push( color.clone() ); //一一合并}faceCopy.materialIndex = face.materialIndex + materialIndexOffset; //改变materialIndex属性.faces1.push( faceCopy );}// uvs// 合并UV数组for ( i = 0, il = uvs2.length; i < il; i ++ ) { //遍历uv数组var uv = uvs2[ i ], uvCopy = [];if ( uv === undefined ) {continue;}for ( var j = 0, jl = uv.length; j < jl; j ++ ) { //uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );}uvs1.push( uvCopy ); //一一合并.}},/*///mergeVertices方法用来清理几何体中重复的顶点.*////mergeVertices///返回新的几何体对象/** Checks for duplicate vertices with hashmap.* 用HashMap检查重复的顶点* Duplicated vertices are removed* 删除重复的顶点* and faces' vertices are updated.* 并且更新面的顶点*/mergeVertices: function () {var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)// 定义HashMap查找顶点的位置坐标,确保顶点的位置坐标是唯一的.var unique = [], changes = [];var v, key;var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001// 数字的小数点长度,比如值为4,相应的小数为0.0001var precision = Math.pow( 10, precisionPoints );var i,il, face;var indices, k, j, jl, u;for ( i = 0, il = this.vertices.length; i < il; i ++ ) { //遍历顶点数组v = this.vertices[ i ];key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); //设置HashMap的key属性值if ( verticesMap[ key ] === undefined ) {verticesMap[ key ] = i;unique.push( this.vertices[ i ] );changes[ i ] = unique.length - 1; //生成HashMap容器} else {//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);changes[ i ] = changes[ verticesMap[ key ] ];}};// if faces are completely degenerate after merging vertices, we// have to remove them from the geometry.// 如果三角面的顶点有重复,我们将要把这些多余的顶点从几何体对象里删除var faceIndicesToRemove = [];for ( i = 0, il = this.faces.length; i < il; i ++ ) { //遍历三角面数组属性face = this.faces[ i ];face.a = changes[ face.a ];face.b = changes[ face.b ];face.c = changes[ face.c ];indices = [ face.a, face.b, face.c ];var dupIndex = - 1;// if any duplicate vertices are found in a Face3// 如果在Face3中发现任何重复的顶点,// we have to remove the face as nothing can be saved// 我们将删除顶点for ( var n = 0; n < 3; n ++ ) { //对面的3个点进行遍历.if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {dupIndex = n;faceIndicesToRemove.push( i ); //将要删除的面放到数组faceIndicesToRemove中break;}}}for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { //遍历要删除的面的数组var idx = faceIndicesToRemove[ i ];this.faces.splice( idx, 1 ); //删除对应的面for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { //遍历几何体对象的faceVertexUvs属性this.faceVertexUvs[ j ].splice( idx, 1 ); //删除对应的uv}}// Use unique set of vertices// 使用不包含重复顶点的vertecs数组.var diff = this.vertices.length - unique.length;this.vertices = unique;return diff; //返回新的几何体对象.},// Geometry splitting/*///makeGroups方法根据设置的最大顶点数量(参数maxVerticesInGroup),将对象内的面点分离出来,生成如下格式对象./// 这是一个box对象生成的./// {faces3: Array[12],id: 1materialIndex: 0,numMorphNormals: 0,numMorphTargets: 2,vertices: 36}*////makeGroups///可选参数,设置三角面对象的材质索引///可选参数,最大顶点数量///返回分离出去的对象makeGroups: ( function () {var geometryGroupCounter = 0;return function ( usesFaceMaterial, maxVerticesInGroup ) {var f, fl, face, materialIndex,groupHash, hash_map = {},geometryGroup;var numMorphTargets = this.morphTargets.length;var numMorphNormals = this.morphNormals.length;this.geometryGroups = {};this.geometryGroupsList = [];for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {face = this.faces[ f ];materialIndex = usesFaceMaterial ? face.materialIndex : 0;if ( ! ( materialIndex in hash_map ) ) {hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };}groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;if ( ! ( groupHash in this.geometryGroups ) ) {geometryGroup = { 'id': geometryGroupCounter++, 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };this.geometryGroups[ groupHash ] = geometryGroup;this.geometryGroupsList.push(geometryGroup);}if ( this.geometryGroups[ groupHash ].vertices + 3 > maxVerticesInGroup ) { //如果大于参数maxVerticesInGrouphash_map[ materialIndex ].counter += 1;groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;if ( ! ( groupHash in this.geometryGroups ) ) {geometryGroup = { 'id': geometryGroupCounter++, 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };this.geometryGroups[ groupHash ] = geometryGroup;this.geometryGroupsList.push(geometryGroup);}}this.geometryGroups[ groupHash ].faces3.push( f );this.geometryGroups[ groupHash ].vertices += 3;}};} )(),/*clone方法///clone方法克隆一个几何体对象,将顶点数组,三角面数组,三角面顶点uv分别复制.*////clone///返回克隆的几何体对象clone: function () {var geometry = new THREE.Geometry();var vertices = this.vertices;for ( var i = 0, il = vertices.length; i < il; i ++ ) {geometry.vertices.push( vertices[ i ].clone() );}var faces = this.faces;for ( var i = 0, il = faces.length; i < il; i ++ ) {geometry.faces.push( faces[ i ].clone() );}var uvs = this.faceVertexUvs[ 0 ];for ( var i = 0, il = uvs.length; i < il; i ++ ) {var uv = uvs[ i ], uvCopy = [];for ( var j = 0, jl = uv.length; j < jl; j ++ ) {uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );}geometry.faceVertexUvs[ 0 ].push( uvCopy );}return geometry; //返回克隆的几何体对象.},/*dispose方法///dispose方法从内存中删除对象,释放资源.///NOTE: 当删除几何体对象,不要忘记调用这个方法,否则会导致内存泄露.*////disposedispose: function () {this.dispatchEvent( { type: 'dispose' } ); //调度事件.}};///EventDispatcher方法应用到当前Geometry对象.THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );///设置全局的Geometry对象计数器.THREE.GeometryIdCount = 0;;>

商域无疆 (http://blog.csdn.net/omni360/)

本文遵循“署名-非商业用途-保持一致”创作公用协议

转载请保留此句:商域无疆 - 本博客专注于 敏捷开发及移动和物联设备研究:数据可视化、GOLANG、Html5、WEBGL、THREE.JS,否则,出自本博客的文章拒绝转载或再转载,谢谢合作。


以下代码是THREE.JS 源码文件中Core/Geometry.js文件的注释.

更多更新在 : https://github.com/omni360/three.js.sourcecode

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Three.js - 走进3D的奇妙世界
Three.js Demo源码分析
THREE.js为正方体的6个面贴上图片
【新提醒】【如何在Unity中生成八面体球(下)】
从零开始学习OpenGL ES之四 – 光效
DIY一个人工智能珠宝设计师v1.0
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服