📄 mlrloadobj.cpp
字号:
// read texture coordinate into list
sscanf(next, "%f %f", &t[tCount][0], &t[tCount][1]);
// advance texture coordinate count
++tCount;
} else if (SAME(token, "vc"))
{
static Scalar r, g, b, a;
// enlarge color list
GROW(c, RGBAColor);
// Set default values for color
r = g = b = 0.0f;
a = 1.0f;
// read color into list
sscanf(next, "%f %f %f %f", &r, &g, &b, &a);
c[cCount] = RGBAColor(r, g, b, a);
// advance color count
++cCount;
} else if (SAME(token, "g"))
{
++numGroups;
backface_following_polygons = (strstr(next, " bf_") != 0);
//DEBUG_STREAM << "'g " << next << "' bf=" <<
// backface_following_polygons << endl;
} else if (SAME(token, "f") || SAME(token, "fo"))
{
int count;
int textureValid = 1;
int normalsValid = 1;
int colorsValid = 1;
int vi[FACE_SIZE];
int ti[FACE_SIZE];
int ni[FACE_SIZE];
int ci[FACE_SIZE];
char *slash;
char vertexData[256];
// parse vertex data from input buffer
for (count = 0; count < FACE_SIZE; count++)
{
// read the next vertices' data packet
if (sscanf(next, "%s%n", vertexData, &width) != 1)
break;
// advance next pointer past data packet ("n/n/n")
next += width;
// get vertex coordinate index
vi[count] = (int)strtol(vertexData, 0, 10);
// get texture coordinate index
ti[count] = 0;
if ((slash = strchr(vertexData, '/')) == 0 ||
(ti[count] = (int)strtol(slash+1, 0, 10)) == 0)
textureValid = 0;
// get vertex normal index
ni[count] = 0;
if (slash == 0 || (slash = strchr(slash+1, '/')) == 0 ||
(ni[count] = (int)strtol(slash+1, 0, 10)) == 0)
normalsValid = 0;
// get color index
ci[count] = 0;
if (slash == 0 || (slash = strchr(slash+1, '/')) == 0 ||
(ci[count] = (int)strtol(slash+1, 0, 10)) == 0)
colorsValid = 0;
// form cannonical indices:
// convert ".obj" 1-based indices to 0-based (subtract 1)
// convert negative indices to positive (count from 0)
if (vi[count] >= 0)
vi[count] -= 1;
else
vi[count] += vCount;
if (ti[count] >= 0)
ti[count] -= 1;
else
ti[count] += tCount;
if (ni[count] >= 0)
ni[count] -= 1;
else
ni[count] += nCount;
if (ci[count] >= 0)
ci[count] -= 1;
else
ci[count] += cCount;
}
if(count > 2)
{
// enlarge polygon list
GROW(p, Poly);
p[pCount].nr = count;
p[pCount].vIndex = new int [p[pCount].nr];
// Setup vertex position information
for (i = 0; i < count; i++)
{
p[pCount].vIndex[i] = vi[i];
}
// Setup normal vector information
if (normalsValid)
{
for (i = 0; i < count; i++)
{
p[pCount].nIndex[i] = ni[i];
}
}
// Setup color information
if (colorsValid)
{
p[pCount].cIndex = new int [p[pCount].nr];
for (i = 0; i < count; i++)
{
p[pCount].cIndex[i] = ci[i];
}
}
// Setup texture coordinates information
if (textureValid)
{
p[pCount].tIndex = new int [p[pCount].nr];
for (i = 0; i < count; i++)
{
p[pCount].tIndex[i] = ti[i];
}
}
++pCount;
numTris += count - 2;
numPolys++;
}
} else if (SAME(token, "usemtl"))
{
if(numPrimitives > 0)
{
MLRPolyMesh *pm = BuildPolyMesh(p, pCount, v, n, t, c);
shape->Add(pm);
}
numPrimitives++;
char mtlName[1024];
sscanf(next, "%s", mtlName);
useMtl(mtlName);
} else if (SAME(token, "mtllib"))
{
char libName[1024];
sscanf(next, "%s", libName);
loadMtl(libName);
} else if (
SAME(token, "bevel") ||
SAME(token, "bmat") ||
SAME(token, "bsp") ||
SAME(token, "bzp") ||
SAME(token, "c_interp") ||
SAME(token, "cdc") ||
SAME(token, "con") ||
SAME(token, "cstype") ||
SAME(token, "ctech") ||
SAME(token, "curv") ||
SAME(token, "curv2") ||
SAME(token, "d_interp") ||
SAME(token, "deg") ||
SAME(token, "end") ||
SAME(token, "hole") ||
SAME(token, "l") ||
SAME(token, "lod") ||
SAME(token, "maplib") ||
SAME(token, "mg") ||
SAME(token, "o") ||
SAME(token, "p") ||
SAME(token, "param") ||
SAME(token, "parm") ||
SAME(token, "res") ||
SAME(token, "s") ||
SAME(token, "scrv") ||
SAME(token, "shadow_obj") ||
SAME(token, "sp") ||
SAME(token, "stech") ||
SAME(token, "step") ||
SAME(token, "surf") ||
SAME(token, "trace_obj") ||
SAME(token, "trim") ||
SAME(token, "usemap") ||
SAME(token, "vp"))
{
++numSkip;
}
else
{
fprintf(stderr, "unrecognized: %s", buffer);
++numOther;
}
}
// close Wavefront ".obj" file
fclose(objFile);
MLRPolyMesh *pm = BuildPolyMesh(p, pCount, v, n, t, c);
shape->Add(pm);
// release dynamically allocated vertex, normal, and texture data
if (v != 0) free(v);
if (n != 0) free(n);
if (t != 0) free(t);
if (c != 0) free(c);
if (p != 0) free(p);
// note -- if you define this, then material files will be read anew
// for every file that references them. could be slow for big
// material files and many models. on the other hand, if you
// don't define it then the lists will linger after the files
// have all been loaded -- wasting space.
#ifdef FORGETFUL
// discard material info
forgetMaterials();
forgetMaterialFiles();
#endif
// print statistics
//pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "pfdLoadFile_obj: %s", fileName);
fprintf(stdout, " Input Data:");
if (numSkip != 0)
fprintf(stdout, " Skipped tokens: %8ld", numSkip);
if (numOther != 0)
fprintf(stdout, " Unrecognized tokens:%8ld", numOther);
if (numGroups != 0)
fprintf(stdout, " Groups processed: %8ld", numGroups);
if (vCount != 0)
fprintf(stdout, " Vertex coordinates: %8ld", vCount);
if (nCount != 0)
fprintf(stdout, " Vertex normals: %8ld", nCount);
if (tCount != 0)
fprintf(stdout, " Texture coordinates:%8ld", tCount);
if (cCount != 0)
fprintf(stdout, " Vertex colors: %8ld", cCount);
if (numTris != 0)
fprintf(stdout, " Input polygons: %8ld", numPolys);
if (numTris != 0)
fprintf(stdout, " Total triangles: %8ld", numTris);
return shape;
}
// ***
// *** P R O C E S S M A T E R I A L F I L E S
// **
const int MTL_NOT_DEFINED = 0x0001;
const int MTL_HAS_GEOSTATE = 0x0002;
const int MTL_HAS_AMBIENT = 0x0004;
const int MTL_HAS_DIFFUSE = 0x0008;
const int MTL_HAS_ALPHA = 0x0010;
const int MTL_HAS_SPECULAR = 0x0020;
const int MTL_HAS_SHININESS = 0x0040;
const int MTL_HAS_TEXTURE = 0x0080;
const int MTL_HAS_REFLECTION = 0x0100;
const int MTL_IS_TWO_SIDED = 0x0200;
// data for a single wavefront material
typedef struct objMaterial
{
char library[1024]; // library name
char name[1024]; // material name
int defined; // defined fields
RGBColor ambient; // Ka field
RGBColor diffuse; // Kd field
RGBColor specular; // Ks field
float alpha; // Tr field (actually, 1-Tr)
float shininess; // Ns field
char texture[1024]; // texture map name
float su; // u-axis tc scale
float sv; // v-axis tc scale
char reflect[1024]; // reflection mode
} objMaterial;
static objMaterial *mtlList = 0;
static int mtlListCount = 0;
static int mtlListSize = 0;
static void
reSetMaterial (objMaterial *m)
{
if (m == 0)
return;
memset(m->library, '\0', sizeof(m->library));
memset(m->name, '\0', sizeof(m->name));
m->defined = 0;
m->ambient = RGBColor ( 0.0f, 0.0f, 0.0f);
m->diffuse = RGBColor ( 0.0f, 0.0f, 0.0f);
m->specular = RGBColor (0.0f, 0.0f, 0.0f);
m->alpha = 1.0f;
m->shininess = 0.0f;
memset(m->texture, '\0', sizeof(m->texture));
m->su = 0.0f;
m->sv = 0.0f;
memset(m->reflect, '\0', sizeof(m->reflect));
}
#ifdef PRINT_MATERIALS_AS_PARSED
static void
printMtl (objMaterial *m)
{
if (m == 0)
return;
fprintf(stdout, " library: %s\n", m->library);
fprintf(stdout, " name: %s\n", m->name);
fprintf(stdout, " defined: 0x%x\n", m->defined);
fprintf(stdout, " ambient: %g %g %g\n",
m->ambient[0], m->ambient[1], m->ambient[2]);
fprintf(stdout, " diffuse: %g %g %g\n",
m->diffuse[0], m->diffuse[1], m->diffuse[2]);
fprintf(stdout, " specular: %g %g %g\n",
m->specular[0], m->specular[1], m->specular[2]);
fprintf(stdout, " alpha: %g\n", m->alpha);
fprintf(stdout, "shininess: %g\n", m->shininess);
fprintf(stdout, " texture: %s\n", m->texture);
fprintf(stdout, " su: %g\n", m->su);
fprintf(stdout, " sv: %g\n", m->sv);
fprintf(stdout, " reflect: %s\n", m->reflect);
fprintf(stdout, "\n");
fflush (stdout);
}
#endif
static void
rememberMaterial (objMaterial *m)
{
int i;
if (m == 0)
return;
#ifdef PRINT_MATERIALS_AS_PARSED
printMtl (m);
#endif
// check for "empty" definition -- don't add junk
if (m->name[0] == '\0' || m->defined == 0)
return;
// look for name in material list -- don't add duplicates
for (i = 0; i < mtlListCount; i++)
if (strcmp(m->name, mtlList[i].name) == 0)
{
// XXX the best thing is to do a compare and warn user
// XXX if the old and new definitions are not identical
if (
//*m != mtlList[i]
(m->defined != (mtlList[i].defined & ~MTL_HAS_GEOSTATE)) ||
!Close_Enough(m->ambient.red, mtlList[i].ambient.red, 1e-6f) ||
!Close_Enough(m->ambient.green, mtlList[i].ambient.green, 1e-6f) ||
!Close_Enough(m->ambient.blue, mtlList[i].ambient.blue, 1e-6f) ||
!Close_Enough(m->diffuse.red, mtlList[i].diffuse.red, 1e-6f) ||
!Close_Enough(m->diffuse.green, mtlList[i].diffuse.green, 1e-6f) ||
!Close_Enough(m->diffuse.blue, mtlList[i].diffuse.blue, 1e-6f) ||
!Close_Enough(m->specular.red, mtlList[i].specular.red, 1e-6f) ||
!Close_Enough(m->specular.green, mtlList[i].specular.green, 1e-6f) ||
!Close_Enough(m->specular.blue, mtlList[i].specular.blue, 1e-6f) ||
!Close_Enough(m->alpha, mtlList[i].alpha, 1e-6f) ||
!Close_Enough(m->shininess, mtlList[i].shininess, 1e-6f) ||
strcmp(m->texture, mtlList[i].texture) ||
!Close_Enough(m->su, mtlList[i].su, 1e-6f) ||
!Close_Enough(m->sv, mtlList[i].sv, 1e-6f) ||
strcmp(m->reflect, mtlList[i].reflect)
)
{
DEBUG_STREAM << "* Warning: Material '" << m->name << "' in " <<
m->library << " ignored (already defined by " << mtlList[i].library << ")" << endl;
DEBUG_STREAM << " " << mtlList[i].library << " " << mtlList[i].name << " " << mtlList[i].texture << endl;
DEBUG_STREAM << " " << m->library << " " << m->name << " " << m->texture << endl;
}
return;
}
// grow material list
if (mtlListSize == 0)
{
// create material list
mtlListSize = 1;
mtlList = (objMaterial *)malloc(mtlListSize*sizeof(objMaterial));
} else if (mtlListCount >= mtlListSize)
{
// grow material list
mtlListSize *= 2;
mtlList = (objMaterial *)realloc(mtlList, mtlListSize*sizeof(objMaterial));
}
#ifdef PRINT_MATERIALS_AS_PARSED
printf("mtlListSize=%d, mtlListCount=%d, sizeof(objMaterial)=%d\n",
mtlListSize, mtlListCount, sizeof(objMaterial));
#endif
// add material to list
mtlList[mtlListCount++] = *m;
}
#ifdef FORGETFUL
static void
forgetMaterials (void)
{
// delete list
if (mtlList != 0)
pfFree(mtlList);
mtlList = 0;
mtlListSize = 0;
mtlListCount = 0;
}
#endif
static void
defineMtl (objMaterial *m)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -