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;
}