www.pudn.com > OBJReadandRender.rar > LoadOBJ.cpp, change:2009-06-16,size:8960b


#include "stdafx.h" 
#include <GL/gl.h> 
#include <GL/glu.h> 
#include "loadOBJ.h" 
 
char *gMatName; 
 
void ParseOBJString(char *buffer,CStringArray *words,int *cnt) 
{ 
/// 局部变量 /////////////////////////////////////////////////////////// 
	CString in = buffer, temp; 
/////////////////////////////////////////////////////////////////////////////// 
	 
	in.TrimLeft(); 
	in.TrimRight(); 
	*cnt = 0; 
	do  
	{ 
		temp = in.SpanExcluding(" \t");		// 得到下一个空格或TAB键的位置 
		words->Add(temp); 
		if (temp == in) break; 
		in = in.Right(in.GetLength() - temp.GetLength()); 
		in.TrimLeft(); 
		*cnt = *cnt + 1;			 
	} while (1); 
	*cnt = *cnt + 1; 
} 
 
void LoadMaterialLib(CString name,t_Visual *visual) 
{ 
/// 局部变量 /////////////////////////////////////////////////////////// 
	int cnt; 
	char buffer[MAX_STRINGLENGTH]; 
	CStringArray words; 
	CString temp; 
	FILE *fp; 
	int matCnt = 0,curMat = -1; 
/////////////////////////////////////////////////////////////////////////////// 
	strcpy(visual->map,""); 
	fp = fopen((LPCTSTR)name,"r"); 
	if (fp != NULL) 
	{ 
		// FIRST PASS SETS UP THE NUMBER OF OBJECTS IN THE FILE 
		while (!feof(fp)) 
		{ 
			fgets(buffer,MAX_STRINGLENGTH,fp);	// 从文件中得到一个字符串 
			ParseOBJString(buffer,&words,&cnt);	// 将字符串分成cnt WORDS 
			if (cnt > 0)						// 确定有字符 
			{ 
				temp = words.GetAt(0);			// 检查第一个字符 
				if (temp.GetLength() > 0) 
				{ 
					if (temp == "newmtl")		// 环境光 
					{ 
						matCnt++; 
					} 
				} 
			} 
			words.RemoveAll();		            // 清除存放字符的缓冲区 
		} 
 
		gMatName = (char *)malloc(20 * matCnt); 
		visual->matColor = (tVector *)malloc(sizeof(tVector) * matCnt); 
		visual->Ka = (tColor *)malloc(sizeof(tColor) * matCnt); 
		visual->Kd = (tColor *)malloc(sizeof(tColor) * matCnt); 
		visual->Ks = (tColor *)malloc(sizeof(tColor) * matCnt); 
		fseek(fp,0,SEEK_SET); 
		// 得到数据 
		while (!feof(fp)) 
		{ 
			fgets(buffer,MAX_STRINGLENGTH,fp);	    // 从文件中得到一个字符串 
			ParseOBJString(buffer,&words,&cnt);	 
			if (cnt > 0)						 
			{ 
				temp = words.GetAt(0);			 
				if (temp.GetLength() > 0) 
				{ 
					if (temp == "newmtl")			// 环境光 
					{ 
						curMat++; 
						strncpy(&gMatName[20 * curMat],words.GetAt(1),20); 
					} 
					else if (temp == "Ka")			// 环境光 
					{ 
						visual->Ka[curMat].r = (float)atof(words.GetAt(1)); 
						visual->Ka[curMat].g = (float)atof(words.GetAt(2)); 
						visual->Ka[curMat].b = (float)atof(words.GetAt(3)); 
					} 
					else if (temp == "Kd")		    // 漫反射颜色 
					{ 
						visual->Kd[curMat].r = (float)atof(words.GetAt(1)); 
						visual->Kd[curMat].g = (float)atof(words.GetAt(2)); 
						visual->Kd[curMat].b = (float)atof(words.GetAt(3)); 
						visual->matColor[curMat].r = visual->Kd[curMat].r; 
						visual->matColor[curMat].g = visual->Kd[curMat].g; 
						visual->matColor[curMat].b = visual->Kd[curMat].b; 
					} 
					else if (temp == "Ks")		    // 镜面反射颜色 
					{ 
						visual->Ks[curMat].r = (float)atof(words.GetAt(1)); 
						visual->Ks[curMat].g = (float)atof(words.GetAt(2)); 
						visual->Ks[curMat].b = (float)atof(words.GetAt(3)); 
					} 
					else if (temp == "Ns")		    // 镜面反射参数 
					{ 
						visual->Ns[curMat] = (float)atof(words.GetAt(1)); 
					} 
					else if (temp == "map_Kd")	    // 文理文件路径 
					{ 
						strcpy(&visual->map[curMat * 80],(LPCTSTR)words.GetAt(1)); 
					} 
					else if (temp == "map_Ks")	    // 文理文件路径 
					{ 
						strcpy(&visual->map2[curMat * 80],(LPCTSTR)words.GetAt(1)); 
					} 
				} 
			} 
			words.RemoveAll();		 
		} 
		fclose(fp); 
	} 
 
	visual->matCnt = matCnt; 
} 
 
///////////////////////////////////////////////////////////////////////////////		 
void HandleFace(CStringArray *words,t_faceIndex *face) 
{ 
/// 局部变量 /////////////////////////////////////////////////////////// 
	int loop,loopcnt; 
	CString temp; 
	CString vStr,nStr,tStr;		 
	int nPos,tPos; 
/////////////////////////////////////////////////////////////////////////////// 
	loopcnt = words->GetSize(); 
	if (loopcnt > 4) loopcnt = 4; 
	 
	for (loop = 1; loop  loopcnt; loop++) 
	{ 
		temp = words->GetAt(loop);			 
		// 面的格式为 vertex/texture/normal 
		tPos = temp.Find('/');				            // 找到vertex和texture的分隔符 '/'  
		vStr = temp.Left(tPos);				            // 得到vertex的信息 
		temp.SetAt(tPos,' ');				            // 将 '/'变成空格,以便可以重来一边 
		nPos = temp.Find('/');				            // 找到texture和normal的分隔符 '/' 
		tStr = temp.Mid(tPos + 1, nPos - tPos - 1);		// 得到texture的信息 
		nStr = temp.Right(temp.GetLength() - nPos - 1);	// 得到normal的信息 
		face->v[loop - 1] = atoi(vStr) - 1;		        // 存储vertex的索引值 
		face->t[loop - 1] = atoi(tStr) - 1;		        // 存储texture的索引值 
		face->n[loop - 1] = atoi(nStr) - 1;		        // 存储normal的索引值 
	} 
} 
 
// 得到当前面所属的材质组 
int GetCurMat(CString name,t_Visual *visual) 
{ 
	for (int loop = 0; loop  visual->matCnt; loop++) 
		if (name == &gMatName[20 * loop]) 
			return loop; 
	return 0; 
} 
 
BOOL LoadOBJ(const char *filename,t_Visual *visual) 
{ 
/// 局部变量 /////////////////////////////////////////////////////////// 
	int loop,loop2,cnt; 
	char buffer[MAX_STRINGLENGTH]; 
	CStringArray words; 
	CString temp; 
	FILE *fp; 
	long vCnt = 0, nCnt = 0, tCnt = 0, fCnt = 0; 
	long vPos = 0, nPos = 0, tPos = 0, fPos = 0; 
	t_faceIndex *face = NULL; 
	float *data; 
	int	   curMat = 0; 
	float vertexScale = 1.0; 
 
	strcpy(visual->map,""); 
	strcpy(visual->map2,""); 
/////////////////////////////////////////////////////////////////////////////// 
	fp = fopen(filename,"r"); 
	visual->glTex = 0; 
	if (fp != NULL) 
	{ 
		while (!feof(fp)) 
		{ 
			fgets(buffer,MAX_STRINGLENGTH,fp);	 
			ParseOBJString(buffer,&words,&cnt);	 
			if (cnt > 0)						 
			{ 
				temp = words.GetAt(0);			 
				if (temp.GetLength() > 0) 
				{ 
					if (temp[0] == 'v')			                            // 找到顶点信息v 
					{ 
						if (temp.GetLength() > 1 && temp[1] == 'n')			// 找到顶点法向量信息vn 
							nCnt++; 
						else if (temp.GetLength() > 1 && temp[1] == 't')	// 找到顶点纹理信息vt 
							tCnt++; 
						else 
							vCnt++;											 
					} 
					else if (temp[0] == 'f') 
						fCnt++;												// 找到面信息f 
					else if (temp == "mtllib")                              
					{ 
						LoadMaterialLib(words.GetAt(1),visual);             // 读取材质文件 
					} 
				} 
			} 
			words.RemoveAll();		 
		} 
 
		if (vCnt > 0) 
		{ 
			visual->vertex = (tVector *)malloc(vCnt * sizeof(tVector)); 
			visual->deformData = (tVector *)malloc(sizeof(tVector) * vCnt); 
			if (nCnt > 0) 
			{ 
				visual->normal = (tVector *)malloc(nCnt * sizeof(tVector)); 
			} 
			if (tCnt > 0) 
			{ 
				visual->texture = (tVector *)malloc(tCnt * sizeof(tVector)); 
			} 
			if (fCnt > 0) 
			{ 
				visual->index = (t_faceIndex *)malloc(fCnt * sizeof(t_faceIndex)); 
			} 
			fseek(fp,0,SEEK_SET); 
 
			while (!feof(fp)) 
			{ 
				fgets(buffer,MAX_STRINGLENGTH,fp); 
				ParseOBJString(buffer,&words,&cnt); 
				if (cnt > 0) 
				{ 
					temp = words.GetAt(0); 
					if (temp.GetLength() > 0) 
					{ 
						if (temp[0] == 'v')		 
						{ 
							if (temp.GetLength() > 1 && temp[1] == 'n')	 
							{ 
								visual->normal[nPos].x = (float)atof(words.GetAt(1)); 
								visual->normal[nPos].y = (float)atof(words.GetAt(2)); 
								visual->normal[nPos].z = (float)atof(words.GetAt(3)); 
								nPos++; 
							} 
							else if (temp.GetLength() > 1 && temp[1] == 't')	 
							{ 
								visual->texture[tPos].u = (float)atof(words.GetAt(1)); 
								visual->texture[tPos].v = (float)atof(words.GetAt(2)); 
								tPos++; 
							} 
							else											 
							{ 
								visual->vertex[vPos].x = (float)atof(words.GetAt(1)) * vertexScale; 
								visual->vertex[vPos].y = (float)atof(words.GetAt(2)) * vertexScale; 
								visual->vertex[vPos].z = (float)atof(words.GetAt(3)) * vertexScale; 
								vPos++; 
							} 
						} 
						else if (temp[0] == 'f')			// f v/t/n v/t/n v/t/n	 
						{ 
							if (words.GetSize() > 4) 
							{ 
								sprintf(buffer,"Face %d has more than 3 vertices",fPos); 
								MessageBox(NULL,buffer,"ERROR",MB_OK); 
							} 
							HandleFace(&words,&visual->index[fPos]); 
 
							visual->index[fPos].mat = curMat; 
							fPos++; 
						} 
						else if (temp == "usemtl")			// f v/t/n v/t/n v/t/n	 
						{ 
							curMat = GetCurMat(words.GetAt(1),visual); 
						} 
						else if (temp == "scale")			// f v/t/n v/t/n v/t/n	 
						{ 
							 vertexScale = atof(words.GetAt(1)); 
						} 
					} 
				} 
				words.RemoveAll();		 
			} 
 
			visual->vertexCnt = vPos;	// 保存顶点v的数量 
			visual->faceCnt = fCnt;    	// 保存面的数量 
			visual->uvCnt = tCnt;	    // 保存顶点纹理vt的数量 
			visual->normalCnt = nCnt;	// 保存顶点法向量vn的数量 
		} 
 
		fclose(fp); 
 
		if (gMatName) 
			free(gMatName); 
	} 
	else 
		return FALSE; 
	return TRUE; 
}