The code is to get the indices from the .obj file that make up a face
static int parseFace(char* row, int* data, int n, int vcnt)
{
int j = 0;
while (*row != '\0')
{
// Skip initial white space
while (*row != '\0' && (*row == ' ' || *row == '\t'))
row++;
char* s = row;
// Find vertex delimiter and terminated the string there for conversion.
while (*row != '\0' && *row != ' ' && *row != '\t')
{
if (*row == '/') *row = '\0';
row++;
}
if (*s == '\0')
continue;
int vi = atoi(s);
data[j++] = vi < 0 ? vi+vcnt : vi-1;
if (j >= n) return j;
}
return j;
}
static char* parseRow(char* buf, char* bufEnd, char* row, int len)
{
bool cont = false;
bool start = true;
bool done = false;
int n = 0;
while (!done && buf < bufEnd)
{
char c = *buf;
buf++;
// multirow
switch (c)
{
case '\\':
cont = true; // multirow
break;
case '\n':
if (start) break;
done = true;
break;
case '\r':
break;
case '\t':
case ' ':
if (start) break;
default:
start = false;
cont = false;
row[n++] = c;
if (n >= len-1)
done = true;
break;
}
}
row[n] = '\0';
return buf;
}
void rcMeshLoaderX::addVertex(float x, float y, float z, int& cap)
{
if (m_vertCount+1 > cap)
{
cap = !cap ? 8 : cap*2;
float* nv = new float[cap*3];
if (m_vertCount)
memcpy(nv, m_verts, m_vertCount*3*sizeof(float));
delete [] m_verts;
m_verts = nv;
}
float* dst = &m_verts[m_vertCount*3];
*dst++ = x*m_scale;
*dst++ = y*m_scale;
*dst++ = z*m_scale;
m_vertCount++;
}
void rcMeshLoaderX::addTriangle(int a, int b, int c, int& cap)
{
if (m_triCount+1 > cap)
{
cap = !cap ? 8 : cap*2;
int* nv = new int[cap*3];
if (m_triCount)
memcpy(nv, m_tris, m_triCount*3*sizeof(int));
delete [] m_tris;
m_tris = nv;
}
int* dst = &m_tris[m_triCount*3];
*dst++ = a;
*dst++ = b;
*dst++ = c;
m_triCount++;
}
==================================
to be replaced
bool rcMeshLoaderX::load(const char* filename)
{
char* buf = 0;
FILE* fp = fopen(filename, "rb");
if (!fp)
return false;
fseek(fp, 0, SEEK_END);
int bufSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
buf = new char[bufSize];
if (!buf)
{
fclose(fp);
return false;
}
fread(buf, bufSize, 1, fp);
fclose(fp);
char* src = buf;
char* srcEnd = buf + bufSize;
char row[512];
int face[32];
float x,y,z;
int nv;
int vcap = 0;
int tcap = 0;
while (src < srcEnd)
{
// Parse one row
row[0] = '\0';
src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char));
// Skip comments
if (row[0] == '#') continue;
if (row[0] == 'v' && row[1] != 'n' && row[1] != 't')
{
// Vertex pos
sscanf(row+1, "%f %f %f", &x, &y, &z);
addVertex(x, y, z, vcap);
}
if (row[0] == 'f')
{
// Faces
nv = parseFace(row+1, face, 32, m_vertCount);
for (int i = 2; i < nv; ++i)
{
const int a = face[0];
const int b = face[i-1];
const int c = face[i];
if (a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount)
continue;
addTriangle(a, b, c, tcap);
}
}
}
delete [] buf;
// Calculate normals.
m_normals = new float[m_triCount*3];
for (int i = 0; i < m_triCount*3; i += 3)
{
const float* v0 = &m_verts[m_tris[i]*3];
const float* v1 = &m_verts[m_tris[i+1]*3];
const float* v2 = &m_verts[m_tris[i+2]*3];
float e0[3], e1[3];
for (int j = 0; j < 3; ++j)
{
e0[j] = v1[j] - v0[j];
e1[j] = v2[j] - v0[j];
}
float* n = &m_normals[i];
n[0] = e0[1]*e1[2] - e0[2]*e1[1];
n[1] = e0[2]*e1[0] - e0[0]*e1[2];
n[2] = e0[0]*e1[1] - e0[1]*e1[0];
float d = sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
if (d > 0)
{
d = 1.0f/d;
n[0] *= d;
n[1] *= d;
n[2] *= d;
}
}
strncpy(m_filename, filename, sizeof(m_filename));
m_filename[sizeof(m_filename)-1] = '\0';
return true;
}
===================================================
Replaced by
rcMeshLoaderX::rcMeshLoaderX(CMesh *mesh) {
LPDIRECT3DVERTEXBUFFER9 vb;
LPDIRECT3DINDEXBUFFER9 ib;
void *pVertices;
int vcap, tcap = 0;
auto dxMesh = mesh->GetStaticMesh();
D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH];
dxMesh->GetDeclaration(decl);
WORD offsetToPosition = 0;
for (UINT i = 0; i < MAXD3DDECLLENGTH; ++i)
{
if (D3DDECLUSAGE_POSITION == decl[i].Usage)
{
offsetToPosition = decl[i].Offset;
}
}
// Get Vertex Information
DWORD vertStride = dxMesh->GetNumBytesPerVertex();
DWORD numVerts = dxMesh->GetNumVertices();
BYTE* pIndices;
dxMesh->LockIndexBuffer(0, (LPVOID*)&pIndices);
for (DWORD i = 0; i < numVerts/3; ++i) {
// each vertex has an index, 3 indices become an triangle
int index0 = *(int*)(&pIndices[vertStride * i + offsetToPosition]);
int index1 = *(int*)(&pIndices[vertStride * i + offsetToPosition + 1]);
int index2 = *(int*)(&pIndices[vertStride * i + offsetToPosition + 2]);
addTriangle(index0, index1, index2, tcap);
}
BYTE* pVert;
dxMesh->UnlockIndexBuffer();
dxMesh->LockVertexBuffer(0, (LPVOID*)&pVert);
for (DWORD i = 0; i < numVerts; ++i)
{
D3DXVECTOR3 currentPos = *(D3DXVECTOR3*)(&pVert[vertStride * i + offsetToPosition]);
// vertices
//x
const float *v0 = ¤tPos.x;
//y
const float *v1 = ¤tPos.y;
//z
const float *v2 = ¤tPos.z;
addVertex(*v0, *v1, *v2, vcap);
float e0[3], e1[3];
for (int j = 0; j < 3; ++j)
{
e0[j] = v1[j] - v0[j];
e1[j] = v2[j] - v0[j];
}
float* n = &m_normals[i];
n[0] = e0[1]*e1[2] - e0[2]*e1[1];
n[1] = e0[2]*e1[0] - e0[0]*e1[2];
n[2] = e0[0]*e1[1] - e0[1]*e1[0];
float d = sqrtf(n[0]*n[0] + n[1]*n[1] + n[2]*n[2]);
if (d > 0)
{
d = 1.0f/d;
n[0] *= d;
n[1] *= d;
n[2] *= d;
}
}
dxMesh->UnlockVertexBuffer();
}
I was not quite familiar with the back-culling stuff and other things that
have to be considered on vertex level, so please give me some hints on how correct
this code could be....
Thanks
Jack