📄 mlrloadobj.cpp
字号:
//===========================================================================//
// Copyright (C) Microsoft Corporation. All rights reserved. //
//===========================================================================//
#include "MLRStuff.hpp"
#include "ctype.h"
#if !defined(MSTRING_HPP)
#include "MString.hpp"
#endif
#if !defined(MLRSTATE_HPP)
#include "MLRState.hpp"
#endif
#if !defined(MLRPOLYMESH_HPP)
#include "MLRPolyMesh.hpp"
#endif
#if !defined(MLRSHAPE_HPP)
#include "MLRShape.hpp"
#endif
// #define FORGETFUL 1
// length of longest input line in ".obj" file (including continuations)
const int BUFFER_SIZE = 8192;
// maximum number of vertices in a single polygon
const int FACE_SIZE = 4096;
// initial allocation size for growable arrays
const int CHUNK = 4096;
// how many different material library files
const int MAX_MTL_FILES = 512;
// case insensitive string equality test
#define SAME(_a, _b) (stricmp(_a,_b) == 0)
// list of textures defined by Wavefront material files
typedef struct TEX
{
char *name;
// pfTexture *texture;
// float su; // u-axis texture scale factor
// float sv; // v-axis texture scale factor
} TEX;
/* list of materials defined by Wavefront material files typedef struct MTL
{
char *name;
MLRState *state;
// pfMaterial *material;
// pfTexture *texture;
// int refl_mapped;
} MTL;
*/
typedef struct Polygon
{
Polygon() {nr = 0; };
int nr;
int *vIndex;
int *cIndex;
int *nIndex;
int *tIndex;
} Poly;
// number of input lines skipped (recognized but not processed) or unknown
static int numSkip = 0;
static int numOther = 0;
int numPrimitives = 0;
MLRState currentState;
// function type and argument declarations
static void loadMtl (char *fileName);
static void useMtl (char *name);
#ifdef FORGETFUL
static void forgetMaterials (void);
static void forgetMaterialFiles (void);
#endif
#define GROW(_v, _t) \
if (_v == 0) \
{ \
_v ## Available = CHUNK; \
_v = (_t *)malloc(sizeof(_t)*_v ## Available); \
} \
else \
if (_v ## Count >= _v ## Available) \
{ \
_v ## Available *= 2; \
_v = (_t *)realloc(_v, sizeof(_t)*_v ## Available); \
}
MLRPolyMesh*
BuildPolyMesh(Poly *p, unsigned int& pCount,
Point3D *v, Vector3D *n,
Vector2DOf<Scalar> *t, RGBAColor *c)
{
if(pCount <= 0)
{
return NULL;
}
MLRPolyMesh *pm = new MLRPolyMesh;
int *length = new int [pCount];
pm->SetPrimitiveLength (length, pCount);
int i, j, k, count[4] = {0, 0, 0, 0}, indexCount = 0;
static int list[10000];
memset(&list, 0, 10000*sizeof(int));
for(i=0;i<pCount;i++)
{
length[i] = p[i].nr;
indexCount += p[i].nr;
for(j=0;j<p[i].nr;j++)
{
list[p[i].vIndex[j]] |= 1;
if(p[i].cIndex)
{
list[p[i].cIndex[j]] |= 2;
}
if(p[i].nIndex)
{
list[p[i].nIndex[j]] |= 4;
}
if(p[i].tIndex)
{
list[p[i].tIndex[j]] |= 8;
}
}
}
pm->SetPrimitiveLength(length, pCount);
for(i=0;i<10000;i++)
{
if(list[i] & 1)
{
count[0]++;
}
if(list[i] & 2)
{
count[1]++;
}
if(list[i] & 4)
{
count[2]++;
}
if(list[i] & 8)
{
count[3]++;
}
}
Point3D *coords = new Point3D [count[0]];
for(i=0,j=0;i<10000;i++)
{
if(list[i] & 1)
{
list[i] |= j<<4;
coords[j] = v[i];
j++;
}
}
int *vIndex = new int [indexCount];
for(i=0,k=0;i<pCount;i++)
{
for(j=0;j<p[i].nr;j++)
{
vIndex[k++] = list[p[i].vIndex[j]]>>4;
}
}
pm->SetData(MLRPrimitive::CoordType, coords, count[0], vIndex, indexCount);
if(p[0].nIndex)
{
Vector3D *normals = new Vector3D [count[2]];
for(i=0,j=0;i<10000;i++)
{
list[i] &= 0xf;
if(list[i] & 4)
{
list[i] |= j<<4;
normals[j] = n[i];
j++;
}
}
int *nIndex = new int [indexCount];
for(i=0,k=0;i<pCount;i++)
{
for(j=0;j<p[i].nr;j++)
{
nIndex[k++] = list[p[i].nIndex[j]]>>4;
}
}
pm->SetData(MLRPrimitive::NormalType, normals, count[2], nIndex, indexCount);
}
if(p[0].cIndex)
{
RGBAColor *colors = new RGBAColor [count[1]];
for(i=0,j=0;i<10000;i++)
{
list[i] &= 0xf;
if(list[i] & 4)
{
list[i] |= j<<2;
colors[j] = c[i];
j++;
}
}
int *cIndex = new int [indexCount];
for(i=0,k=0;i<pCount;i++)
{
for(j=0;j<p[i].nr;j++)
{
cIndex[k++] = list[p[i].cIndex[j]]>>4;
}
}
pm->SetData(MLRPrimitive::ColorType, colors, count[1], cIndex, indexCount);
}
if(p[0].tIndex)
{
Vector2DOf<Scalar> *texCoords = new Vector2DOf<Scalar> [count[3]];
for(i=0,j=0;i<10000;i++)
{
list[i] &= 0xf;
if(list[i] & 8)
{
list[i] |= j<<4;
texCoords[j] = t[i];
j++;
}
}
int *tIndex = new int [indexCount];
for(i=0,k=0;i<pCount;i++)
{
for(j=0;j<p[i].nr;j++)
{
tIndex[k++] = list[p[i].tIndex[j]]>>4;
}
}
pm->SetData(MLRPrimitive::TexCoordType, texCoords, count[3], tIndex, indexCount);
}
for(i=0;i<pCount;i++)
{
delete [] p[i].vIndex;
if(p[i].nIndex)
{
delete [] p[i].nIndex;
}
if(p[i].cIndex)
{
delete [] p[i].cIndex;
}
if(p[i].tIndex)
{
delete [] p[i].tIndex;
}
}
pCount = 0;
return pm;
}
//
// pfdLoadFile_obj -- Load Wavefront ".obj" files into IRIS Performer
//
MLRShape*
MLRLoadObj (const char *fileName)
{
FILE *objFile;
char buffer[BUFFER_SIZE];
char token[BUFFER_SIZE];
char *next = 0;
char *backslash = 0;
MLRShape *shape = new MLRShape;
int width = 0;
int numTris = 0;
int numPolys = 0;
int numGroups = 0;
// int colorsDefined = 0;
// growable vertex coordinate list (X, Y, Z)
Point3D *v = 0;
unsigned int vCount = 0;
unsigned int vAvailable = 0;
// growable vertex normal list (Nx, Ny, Nz)
Vector3D *n = 0;
unsigned int nCount = 0;
unsigned int nAvailable = 0;
// growable texture coordinate list (S, T )
Vector2DOf<Scalar> *t = 0;
unsigned int tCount = 0;
unsigned int tAvailable = 0;
// growable color list (Cr, Cg, Cb, Ca)
RGBAColor *c = 0;
unsigned int cCount = 0;
unsigned int cAvailable = 0;
// growable polygon list
Poly *p = 0;
unsigned int pCount = 0;
unsigned int pAvailable = 0;
// tmp count vars
int i;
if ((objFile = fopen(fileName, "rt")) == 0)
return 0;
Logical backface_following_polygons = False;
// read Wavefront ".obj" file
while (fgets(buffer, BUFFER_SIZE, objFile) != 0)
{
// concatenate continuation lines
while ((backslash = strchr(buffer, '\\')) != 0)
{
// replace backslash with space (thanks to Ken Sakai)
*backslash++ = ' ';
*backslash = '\0';
// keep reading
if (fgets(backslash, (int)(BUFFER_SIZE - strlen(buffer)), objFile) == 0)
break;
}
// find first non-"space" character in line
for (next = buffer; *next != '\0' && isspace(*next); next++) {};
// skip blank lines and comments ('$' is comment in "cow.obj")
if (*next == '\0' || *next == '#' || *next == '!' || *next == '$')
continue;
// extract token
sscanf(next, "%s%n", token, &width);
next += width;
// identify token
if (SAME(token, "v"))
{
// enlarge vertex coordinate list
GROW(v, Point3D);
// Set default values for vertex coordinate
v[vCount][0] = v[vCount][1] = v[vCount][2] = 0.0f;
// read vertex coordinate into list
sscanf(next, "%f %f %f",
&v[vCount][0], &v[vCount][1], &v[vCount][2]);
/* Added to correct our OWN obj format
float f = v[vCount][PF_Y];
v[vCount][PF_Y] = -v[vCount][PF_Z];
v[vCount][PF_Z] = f;
*/
// advance vertex count
++vCount;
} else if (SAME(token, "vn"))
{
// enlarge vertex normal list
GROW(n, Vector3D);
// Set default values for vertex normal
n[nCount][0] = n[nCount][1] = n[nCount][2] = 0.0f;
// read vertex normal into list
sscanf(next, "%f %f %f",
&n[nCount][0], &n[nCount][1], &n[nCount][2]);
/*
float f = n[nCount][PF_Y];
n[nCount][PF_Y] = -n[nCount][PF_Z];
n[nCount][PF_Z] = f;
*/
// advance normal count
++nCount;
} else if (SAME(token, "vt"))
{
// enlarge texture coordinate list
GROW(t, Vector2DOf<Scalar>);
// Set default values for vertex normal
t[tCount][0] = t[tCount][1] = 0.0f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -