学习WebGL_009_解析obj文件

作者: DSLMing
时间: 2019.10.18

参考
FunWithWebGL2 011-Parsing.OBJ

解析.OBJ文件

今天,我们将学习如何使用Blender生成OBJ文件,以及如何使用javascript将数据解析为WebGL可以呈现的内容。 我们将首先解析一个多维数据集,然后再尝试一个动漫风格的海盗女孩模型。

ObjLoader源码

class ObjLoader{
	static domToMesh(meshName,elmID,flipYUV){
		var d = ObjLoader.parseFromDom(elmID,flipYUV);
		return gl.fCreateMeshVAO(meshName,d[0],d[1],d[2],d[3],3);
	}

	static parseFromDom(elmID,flipYUV){ return ObjLoader.parseObjText(document.getElementById(elmID).innerHTML,flipYUV); }

	static parseObjText(txt,flipYUV){
		txt = txt.trim() + "\n"; //add newline to be able to access last line in the for loop

    // Line text from obj file,文本的每一行
    let line
    //Line split into an array,一行被分割的若干元素由数组表示
    let item
    // Itm split into an array, used for faced decoding,将其拆分为数组,用于面对式解码
		let	ary
		let i
    // 用于计算缓存数组的索引
    let ind
    // 确定人脸是否为四边形
		let	isQuad = false
    // Cache Dictionary key = itm array element, val = final index of the vertice
    // 高速缓存字典键= itm数组元素,val =顶点的最终索引
    let aCache = []
    // 从obj读取的缓存顶点数组
		let	cVert = []
    // 从obj读取的缓存法线数组
		let	cNorm = []
    // Cache UV array
		let cUV = []
    // 最终索引排序顶点数组
		let fVert = []
    // 最终的法线数组
		let	fNorm = []
    // Final Index Sorted UV array
		let fUV = []
    // Final Sorted index array
		let fIndex = []
    // Final count of unique vertices
		let	fIndexCnt = 0
		let posA = 0
		let posB = txt.indexOf("\n",0);

		while(posB > posA){
			line = txt.substring(posA,posB).trim();
			switch(line.charAt(0)){
				//......................................................
				// Cache Vertex Data for Index processing when going through face data
				// Sample Data (x,y,z)
				// v -1.000000 1.000000 1.000000
				// vt 0.000000 0.666667
				// vn 0.000000 0.000000 -1.000000
				case "v":
					itm = line.split(" "); itm.shift();
					switch(line.charAt(1)){
						case " ": cVert.push(parseFloat(itm[0]) , parseFloat(itm[1]) , parseFloat(itm[2]) ); break;		//VERTEX
						case "t": cUV.push( parseFloat(itm[0]) , parseFloat(itm[1]) );	break;							//UV
						case "n": cNorm.push( parseFloat(itm[0]) , parseFloat(itm[1]) , parseFloat(itm[2]) ); break;	//NORMAL
					}
				break;

				//......................................................
				// Process face data
				// 所有索引值都从1开始,但是javascript数组索引从0开始。因此需要始终从索引中减去1来进行匹配
				// Sample Data [Vertex Index, UV Index, Normal Index], Each line is a triangle or quad.
				// 样品数据[顶点索引, 纹理索引, 法线信息],每条线是三角形或四边形。
				// f 1/1/1 2/2/1 3/3/1 4/4/1
				// f 34/41/36 34/41/35 34/41/36
				// f 34//36 34//35 34//36
				case "f":
					itm = line.split(" ");
					itm.shift();
					isQuad = false;

					for(i=0; i < itm.length; i++){
						//--------------------------------
						//In the event the face is a quad
						if(i == 3 && !isQuad){
							i = 2; //Last vertex in the first triangle is the start of the 2nd triangle in a quad.
							isQuad = true;
						}

						//--------------------------------
						//Has this vertex data been processed?
						if(itm[i] in aCache){
							fIndex.push( aCache[itm[i]] ); //it has, add its index to the list.
						}else{
							//New Unique vertex data, Process it.
							ary = itm[i].split("/");

							//Parse Vertex Data and save final version ordred correctly by index
							ind = (parseInt(ary[0])-1) * 3;
							fVert.push( cVert[ind] , cVert[ind+1] , cVert[ind+2] );

							//Parse Normal Data and save final version ordered correctly by index
							ind = (parseInt(ary[2])-1) * 3;
							fNorm.push( cNorm[ind] , cNorm[ind+1] , cNorm[ind+2] );

							//Parse Texture Data if available and save final version ordered correctly by index
							if(ary[1] != ""){
								ind = (parseInt(ary[1])-1) * 2;
								fUV.push( cUV[ind] ,
									(!flipYUV)? cUV[ind+1] : 1-cUV[ind+1]
								);
							}

							//Cache the vertex item value and its new index.
							//The idea is to create an index for each unique set of vertex data base on the face data
							//So when the same item is found, just add the index value without duplicating vertex,normal and texture.
							aCache[ itm[i] ] = fIndexCnt;
							fIndex.push(fIndexCnt);
							fIndexCnt++;
						}

						//--------------------------------
						//In a quad, the last vertex of the second triangle is the first vertex in the first triangle.
						if(i == 3 && isQuad) fIndex.push( aCache[itm[0]] );
					}
				break;
			}

			//Get Ready to parse the next line of the obj data.
			posA = posB+1;
			posB = txt.indexOf("\n",posA);
		}
		return [fIndex,fVert,fNorm,fUV];
	}
}//cls
发布了74 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_21476953/article/details/102627629
009
今日推荐