1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-05 10:17:46 +00:00

fix more style

This commit is contained in:
NotAdam 2019-01-26 19:43:42 +11:00
parent e5f612bc43
commit 29edf87924
4 changed files with 432 additions and 374 deletions

View file

@ -23,293 +23,309 @@
struct BoundsItem struct BoundsItem
{ {
float bmin[2]; float bmin[ 2 ];
float bmax[2]; float bmax[ 2 ];
int i; int i;
}; };
static int compareItemX(const void* va, const void* vb) static int compareItemX( const void* va, const void* vb )
{ {
const BoundsItem* a = (const BoundsItem*)va; const BoundsItem* a = ( const BoundsItem* ) va;
const BoundsItem* b = (const BoundsItem*)vb; const BoundsItem* b = ( const BoundsItem* ) vb;
if (a->bmin[0] < b->bmin[0]) if( a->bmin[ 0 ] < b->bmin[ 0 ] )
return -1; return -1;
if (a->bmin[0] > b->bmin[0]) if( a->bmin[ 0 ] > b->bmin[ 0 ] )
return 1; return 1;
return 0; return 0;
} }
static int compareItemY(const void* va, const void* vb) static int compareItemY( const void* va, const void* vb )
{ {
const BoundsItem* a = (const BoundsItem*)va; const BoundsItem* a = ( const BoundsItem* ) va;
const BoundsItem* b = (const BoundsItem*)vb; const BoundsItem* b = ( const BoundsItem* ) vb;
if (a->bmin[1] < b->bmin[1]) if( a->bmin[ 1 ] < b->bmin[ 1 ] )
return -1; return -1;
if (a->bmin[1] > b->bmin[1]) if( a->bmin[ 1 ] > b->bmin[ 1 ] )
return 1; return 1;
return 0; return 0;
} }
static void calcExtends(const BoundsItem* items, const int /*nitems*/, static void calcExtends( const BoundsItem* items, const int /*nitems*/,
const int imin, const int imax, const int imin, const int imax,
float* bmin, float* bmax) float* bmin, float* bmax )
{ {
bmin[0] = items[imin].bmin[0]; bmin[ 0 ] = items[ imin ].bmin[ 0 ];
bmin[1] = items[imin].bmin[1]; bmin[ 1 ] = items[ imin ].bmin[ 1 ];
bmax[0] = items[imin].bmax[0]; bmax[ 0 ] = items[ imin ].bmax[ 0 ];
bmax[1] = items[imin].bmax[1]; bmax[ 1 ] = items[ imin ].bmax[ 1 ];
for (int i = imin+1; i < imax; ++i) for( int i = imin + 1; i < imax; ++i )
{ {
const BoundsItem& it = items[i]; const BoundsItem& it = items[ i ];
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0]; if( it.bmin[ 0 ] < bmin[ 0 ] )
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1]; bmin[ 0 ] = it.bmin[ 0 ];
if( it.bmin[ 1 ] < bmin[ 1 ] )
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0]; bmin[ 1 ] = it.bmin[ 1 ];
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
} if( it.bmax[ 0 ] > bmax[ 0 ] )
bmax[ 0 ] = it.bmax[ 0 ];
if( it.bmax[ 1 ] > bmax[ 1 ] )
bmax[ 1 ] = it.bmax[ 1 ];
}
} }
inline int longestAxis(float x, float y) inline int longestAxis( float x, float y )
{ {
return y > x ? 1 : 0; return y > x ? 1 : 0;
} }
static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk, static void subdivide( BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk,
int& curNode, rcChunkyTriMeshNode* nodes, const int maxNodes, int& curNode, rcChunkyTriMeshNode* nodes, const int maxNodes,
int& curTri, int* outTris, const int* inTris) int& curTri, int* outTris, const int* inTris )
{ {
int inum = imax - imin; int inum = imax - imin;
int icur = curNode; int icur = curNode;
if (curNode > maxNodes)
return;
rcChunkyTriMeshNode& node = nodes[curNode++]; if( curNode > maxNodes )
return;
if (inum <= trisPerChunk)
{ rcChunkyTriMeshNode& node = nodes[ curNode++ ];
// Leaf
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax); if( inum <= trisPerChunk )
{
// Copy triangles. // Leaf
node.i = curTri; calcExtends( items, nitems, imin, imax, node.bmin, node.bmax );
node.n = inum;
// Copy triangles.
for (int i = imin; i < imax; ++i) node.i = curTri;
{ node.n = inum;
const int* src = &inTris[items[i].i*3];
int* dst = &outTris[curTri*3]; for( int i = imin; i < imax; ++i )
curTri++; {
dst[0] = src[0]; const int* src = &inTris[ items[ i ].i * 3 ];
dst[1] = src[1]; int* dst = &outTris[ curTri * 3 ];
dst[2] = src[2]; curTri++;
} dst[ 0 ] = src[ 0 ];
} dst[ 1 ] = src[ 1 ];
else dst[ 2 ] = src[ 2 ];
{ }
// Split }
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax); else
{
int axis = longestAxis(node.bmax[0] - node.bmin[0], // Split
node.bmax[1] - node.bmin[1]); calcExtends( items, nitems, imin, imax, node.bmin, node.bmax );
if (axis == 0) int axis = longestAxis( node.bmax[ 0 ] - node.bmin[ 0 ],
{ node.bmax[ 1 ] - node.bmin[ 1 ] );
// Sort along x-axis
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemX); if( axis == 0 )
} {
else if (axis == 1) // Sort along x-axis
{ qsort( items + imin, static_cast<size_t>(inum), sizeof( BoundsItem ), compareItemX );
// Sort along y-axis }
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemY); else if( axis == 1 )
} {
// Sort along y-axis
int isplit = imin+inum/2; qsort( items + imin, static_cast<size_t>(inum), sizeof( BoundsItem ), compareItemY );
}
// Left
subdivide(items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris); int isplit = imin + inum / 2;
// Right
subdivide(items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris); // Left
subdivide( items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris );
int iescape = curNode - icur; // Right
// Negative index means escape. subdivide( items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris );
node.i = -iescape;
} int iescape = curNode - icur;
// Negative index means escape.
node.i = -iescape;
}
} }
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris, bool rcCreateChunkyTriMesh( const float* verts, const int* tris, int ntris,
int trisPerChunk, rcChunkyTriMesh* cm) int trisPerChunk, rcChunkyTriMesh* cm )
{ {
int nchunks = (ntris + trisPerChunk-1) / trisPerChunk; int nchunks = ( ntris + trisPerChunk - 1 ) / trisPerChunk;
cm->nodes = new rcChunkyTriMeshNode[nchunks*4]; cm->nodes = new rcChunkyTriMeshNode[nchunks * 4];
if (!cm->nodes) if( !cm->nodes )
return false; return false;
cm->tris = new int[ntris*3];
if (!cm->tris)
return false;
cm->ntris = ntris;
// Build tree cm->tris = new int[ntris * 3];
BoundsItem* items = new BoundsItem[ntris]; if( !cm->tris )
if (!items) return false;
return false;
for (int i = 0; i < ntris; i++) cm->ntris = ntris;
{
const int* t = &tris[i*3];
BoundsItem& it = items[i];
it.i = i;
// Calc triangle XZ bounds.
it.bmin[0] = it.bmax[0] = verts[t[0]*3+0];
it.bmin[1] = it.bmax[1] = verts[t[0]*3+2];
for (int j = 1; j < 3; ++j)
{
const float* v = &verts[t[j]*3];
if (v[0] < it.bmin[0]) it.bmin[0] = v[0];
if (v[2] < it.bmin[1]) it.bmin[1] = v[2];
if (v[0] > it.bmax[0]) it.bmax[0] = v[0]; // Build tree
if (v[2] > it.bmax[1]) it.bmax[1] = v[2]; BoundsItem* items = new BoundsItem[ntris];
} if( !items )
} return false;
int curTri = 0; for( int i = 0; i < ntris; i++ )
int curNode = 0; {
subdivide(items, ntris, 0, ntris, trisPerChunk, curNode, cm->nodes, nchunks*4, curTri, cm->tris, tris); const int* t = &tris[ i * 3 ];
BoundsItem& it = items[ i ];
delete [] items; it.i = i;
// Calc triangle XZ bounds.
cm->nnodes = curNode; it.bmin[ 0 ] = it.bmax[ 0 ] = verts[ t[ 0 ] * 3 + 0 ];
it.bmin[ 1 ] = it.bmax[ 1 ] = verts[ t[ 0 ] * 3 + 2 ];
// Calc max tris per node. for( int j = 1; j < 3; ++j )
cm->maxTrisPerChunk = 0; {
for (int i = 0; i < cm->nnodes; ++i) const float* v = &verts[ t[ j ] * 3 ];
{ if( v[ 0 ] < it.bmin[ 0 ] )
rcChunkyTriMeshNode& node = cm->nodes[i]; it.bmin[ 0 ] = v[ 0 ];
const bool isLeaf = node.i >= 0; if( v[ 2 ] < it.bmin[ 1 ] )
if (!isLeaf) continue; it.bmin[ 1 ] = v[ 2 ];
if (node.n > cm->maxTrisPerChunk)
cm->maxTrisPerChunk = node.n; if( v[ 0 ] > it.bmax[ 0 ] )
} it.bmax[ 0 ] = v[ 0 ];
if( v[ 2 ] > it.bmax[ 1 ] )
return true; it.bmax[ 1 ] = v[ 2 ];
}
}
int curTri = 0;
int curNode = 0;
subdivide( items, ntris, 0, ntris, trisPerChunk, curNode, cm->nodes, nchunks * 4, curTri, cm->tris, tris );
delete[] items;
cm->nnodes = curNode;
// Calc max tris per node.
cm->maxTrisPerChunk = 0;
for( int i = 0; i < cm->nnodes; ++i )
{
rcChunkyTriMeshNode& node = cm->nodes[ i ];
const bool isLeaf = node.i >= 0;
if( !isLeaf )
continue;
if( node.n > cm->maxTrisPerChunk )
cm->maxTrisPerChunk = node.n;
}
return true;
} }
inline bool checkOverlapRect(const float amin[2], const float amax[2], inline bool checkOverlapRect( const float amin[2], const float amax[2],
const float bmin[2], const float bmax[2]) const float bmin[2], const float bmax[2] )
{ {
bool overlap = true; bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; overlap = ( amin[ 0 ] > bmax[ 0 ] || amax[ 0 ] < bmin[ 0 ] ) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; overlap = ( amin[ 1 ] > bmax[ 1 ] || amax[ 1 ] < bmin[ 1 ] ) ? false : overlap;
return overlap; return overlap;
} }
int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm, int rcGetChunksOverlappingRect( const rcChunkyTriMesh* cm,
float bmin[2], float bmax[2], float bmin[2], float bmax[2],
int* ids, const int maxIds) int* ids, const int maxIds )
{ {
// Traverse tree // Traverse tree
int i = 0; int i = 0;
int n = 0; int n = 0;
while (i < cm->nnodes) while( i < cm->nnodes )
{ {
const rcChunkyTriMeshNode* node = &cm->nodes[i]; const rcChunkyTriMeshNode* node = &cm->nodes[ i ];
const bool overlap = checkOverlapRect(bmin, bmax, node->bmin, node->bmax); const bool overlap = checkOverlapRect( bmin, bmax, node->bmin, node->bmax );
const bool isLeafNode = node->i >= 0; const bool isLeafNode = node->i >= 0;
if (isLeafNode && overlap) if( isLeafNode && overlap )
{ {
if (n < maxIds) if( n < maxIds )
{ {
ids[n] = i; ids[ n ] = i;
n++; n++;
} }
} }
if (overlap || isLeafNode) if( overlap || isLeafNode )
i++; i++;
else else
{ {
const int escapeIndex = -node->i; const int escapeIndex = -node->i;
i += escapeIndex; i += escapeIndex;
} }
} }
return n; return n;
} }
static bool checkOverlapSegment( const float p[2], const float q[2],
static bool checkOverlapSegment(const float p[2], const float q[2], const float bmin[2], const float bmax[2] )
const float bmin[2], const float bmax[2])
{ {
static const float EPSILON = 1e-6f; static const float EPSILON = 1e-6f;
float tmin = 0; float tmin = 0;
float tmax = 1; float tmax = 1;
float d[2]; float d[2];
d[0] = q[0] - p[0]; d[ 0 ] = q[ 0 ] - p[ 0 ];
d[1] = q[1] - p[1]; d[ 1 ] = q[ 1 ] - p[ 1 ];
for (int i = 0; i < 2; i++) for( int i = 0; i < 2; i++ )
{ {
if (fabsf(d[i]) < EPSILON) if( fabsf( d[ i ] ) < EPSILON )
{ {
// Ray is parallel to slab. No hit if origin not within slab // Ray is parallel to slab. No hit if origin not within slab
if (p[i] < bmin[i] || p[i] > bmax[i]) if( p[ i ] < bmin[ i ] || p[ i ] > bmax[ i ] )
return false; return false;
} }
else else
{ {
// Compute intersection t value of ray with near and far plane of slab // Compute intersection t value of ray with near and far plane of slab
float ood = 1.0f / d[i]; float ood = 1.0f / d[ i ];
float t1 = (bmin[i] - p[i]) * ood; float t1 = ( bmin[ i ] - p[ i ] ) * ood;
float t2 = (bmax[i] - p[i]) * ood; float t2 = ( bmax[ i ] - p[ i ] ) * ood;
if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; } if( t1 > t2 )
if (t1 > tmin) tmin = t1; {
if (t2 < tmax) tmax = t2; float tmp = t1;
if (tmin > tmax) return false; t1 = t2;
} t2 = tmp;
} }
return true; if( t1 > tmin )
tmin = t1;
if( t2 < tmax )
tmax = t2;
if( tmin > tmax )
return false;
}
}
return true;
} }
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm, int rcGetChunksOverlappingSegment( const rcChunkyTriMesh* cm,
float p[2], float q[2], float p[2], float q[2],
int* ids, const int maxIds) int* ids, const int maxIds )
{ {
// Traverse tree // Traverse tree
int i = 0; int i = 0;
int n = 0; int n = 0;
while (i < cm->nnodes) while( i < cm->nnodes )
{ {
const rcChunkyTriMeshNode* node = &cm->nodes[i]; const rcChunkyTriMeshNode* node = &cm->nodes[ i ];
const bool overlap = checkOverlapSegment(p, q, node->bmin, node->bmax); const bool overlap = checkOverlapSegment( p, q, node->bmin, node->bmax );
const bool isLeafNode = node->i >= 0; const bool isLeafNode = node->i >= 0;
if (isLeafNode && overlap) if( isLeafNode && overlap )
{ {
if (n < maxIds) if( n < maxIds )
{ {
ids[n] = i; ids[ n ] = i;
n++; n++;
} }
} }
if (overlap || isLeafNode) if( overlap || isLeafNode )
i++; i++;
else else
{ {
const int escapeIndex = -node->i; const int escapeIndex = -node->i;
i += escapeIndex; i += escapeIndex;
} }
} }
return n; return n;
} }

View file

@ -21,39 +21,48 @@
struct rcChunkyTriMeshNode struct rcChunkyTriMeshNode
{ {
float bmin[2]; float bmin[ 2 ];
float bmax[2]; float bmax[ 2 ];
int i; int i;
int n; int n;
}; };
struct rcChunkyTriMesh struct rcChunkyTriMesh
{ {
inline rcChunkyTriMesh() : nodes(0), nnodes(0), tris(0), ntris(0), maxTrisPerChunk(0) {}; inline rcChunkyTriMesh() :
inline ~rcChunkyTriMesh() { delete [] nodes; delete [] tris; } nodes( 0 ), nnodes( 0 ), tris( 0 ), ntris( 0 ), maxTrisPerChunk( 0 )
{
};
rcChunkyTriMeshNode* nodes; inline ~rcChunkyTriMesh()
int nnodes; {
int* tris; delete[] nodes;
int ntris; delete[] tris;
int maxTrisPerChunk; }
rcChunkyTriMeshNode* nodes;
int nnodes;
int* tris;
int ntris;
int maxTrisPerChunk;
private: private:
// Explicitly disabled copy constructor and copy assignment operator. // Explicitly disabled copy constructor and copy assignment operator.
rcChunkyTriMesh(const rcChunkyTriMesh&); rcChunkyTriMesh( const rcChunkyTriMesh& );
rcChunkyTriMesh& operator=(const rcChunkyTriMesh&);
rcChunkyTriMesh& operator=( const rcChunkyTriMesh& );
}; };
/// Creates partitioned triangle mesh (AABB tree), /// Creates partitioned triangle mesh (AABB tree),
/// where each node contains at max trisPerChunk triangles. /// where each node contains at max trisPerChunk triangles.
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris, bool rcCreateChunkyTriMesh( const float* verts, const int* tris, int ntris,
int trisPerChunk, rcChunkyTriMesh* cm); int trisPerChunk, rcChunkyTriMesh* cm );
/// Returns the chunk indices which overlap the input rectable. /// Returns the chunk indices which overlap the input rectable.
int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm, float bmin[2], float bmax[2], int* ids, const int maxIds); int rcGetChunksOverlappingRect( const rcChunkyTriMesh* cm, float bmin[2], float bmax[2], int* ids, const int maxIds );
/// Returns the chunk indices which overlap the input segment. /// Returns the chunk indices which overlap the input segment.
int rcGetChunksOverlappingSegment(const rcChunkyTriMesh* cm, float p[2], float q[2], int* ids, const int maxIds); int rcGetChunksOverlappingSegment( const rcChunkyTriMesh* cm, float p[2], float q[2], int* ids, const int maxIds );
#endif // CHUNKYTRIMESH_H #endif // CHUNKYTRIMESH_H

View file

@ -20,154 +20,160 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <cstring> #include <cstring>
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include <math.h> #include <math.h>
rcMeshLoaderObj::rcMeshLoaderObj() : rcMeshLoaderObj::rcMeshLoaderObj() :
m_scale(1.0f), m_scale( 1.0f ),
m_verts(0), m_verts( 0 ),
m_tris(0), m_tris( 0 ),
m_normals(0), m_normals( 0 ),
m_vertCount(0), m_vertCount( 0 ),
m_triCount(0) m_triCount( 0 )
{ {
} }
rcMeshLoaderObj::~rcMeshLoaderObj() rcMeshLoaderObj::~rcMeshLoaderObj()
{ {
delete [] m_verts; delete[] m_verts;
delete [] m_normals; delete[] m_normals;
delete [] m_tris; delete[] m_tris;
} }
void rcMeshLoaderObj::addVertex(float x, float y, float z, int& cap) void rcMeshLoaderObj::addVertex( float x, float y, float z, int& cap )
{ {
if (m_vertCount+1 > cap) if( m_vertCount + 1 > cap )
{ {
cap = !cap ? 8 : cap*2; cap = !cap ? 8 : cap * 2;
float* nv = new float[cap*3]; float* nv = new float[cap * 3];
if (m_vertCount) if( m_vertCount )
memcpy(nv, m_verts, m_vertCount*3*sizeof(float)); memcpy( nv, m_verts, m_vertCount * 3 * sizeof( float ) );
delete [] m_verts; delete[] m_verts;
m_verts = nv; m_verts = nv;
} }
float* dst = &m_verts[m_vertCount*3]; float* dst = &m_verts[ m_vertCount * 3 ];
*dst++ = x*m_scale; *dst++ = x * m_scale;
*dst++ = y*m_scale; *dst++ = y * m_scale;
*dst++ = z*m_scale; *dst++ = z * m_scale;
m_vertCount++; m_vertCount++;
} }
void rcMeshLoaderObj::addTriangle(int a, int b, int c, int& cap) void rcMeshLoaderObj::addTriangle( int a, int b, int c, int& cap )
{ {
if (m_triCount+1 > cap) if( m_triCount + 1 > cap )
{ {
cap = !cap ? 8 : cap*2; cap = !cap ? 8 : cap * 2;
int* nv = new int[cap*3]; int* nv = new int[cap * 3];
if (m_triCount) if( m_triCount )
memcpy(nv, m_tris, m_triCount*3*sizeof(int)); memcpy( nv, m_tris, m_triCount * 3 * sizeof( int ) );
delete [] m_tris; delete[] m_tris;
m_tris = nv; m_tris = nv;
} }
int* dst = &m_tris[m_triCount*3]; int* dst = &m_tris[ m_triCount * 3 ];
*dst++ = a; *dst++ = a;
*dst++ = b; *dst++ = b;
*dst++ = c; *dst++ = c;
m_triCount++; m_triCount++;
} }
static char* parseRow(char* buf, char* bufEnd, char* row, int len) static char* parseRow( char* buf, char* bufEnd, char* row, int len )
{ {
bool start = true; bool start = true;
bool done = false; bool done = false;
int n = 0; int n = 0;
while (!done && buf < bufEnd) while( !done && buf < bufEnd )
{ {
char c = *buf; char c = *buf;
buf++; buf++;
// multirow // multirow
switch (c) switch( c )
{ {
case '\\': case '\\':
break; break;
case '\n': case '\n':
if (start) break; if( start )
break;
done = true; done = true;
break; break;
case '\r': case '\r':
break; break;
case '\t': case '\t':
case ' ': case ' ':
if (start) break; if( start )
break;
// else falls through // else falls through
default: default:
start = false; start = false;
row[n++] = c; row[ n++ ] = c;
if (n >= len-1) if( n >= len - 1 )
done = true; done = true;
break; break;
} }
} }
row[n] = '\0'; row[ n ] = '\0';
return buf; return buf;
} }
static int parseFace(char* row, int* data, int n, int vcnt) static int parseFace( char* row, int* data, int n, int vcnt )
{ {
int j = 0; int j = 0;
while (*row != '\0') while( *row != '\0' )
{ {
// Skip initial white space // Skip initial white space
while (*row != '\0' && (*row == ' ' || *row == '\t')) while( *row != '\0' && ( *row == ' ' || *row == '\t' ) )
row++; row++;
char* s = row; char* s = row;
// Find vertex delimiter and terminated the string there for conversion. // Find vertex delimiter and terminated the string there for conversion.
while (*row != '\0' && *row != ' ' && *row != '\t') while( *row != '\0' && *row != ' ' && *row != '\t' )
{ {
if (*row == '/') *row = '\0'; if( *row == '/' )
*row = '\0';
row++; row++;
} }
if (*s == '\0') if( *s == '\0' )
continue; continue;
int vi = atoi(s); int vi = atoi( s );
data[j++] = vi < 0 ? vi+vcnt : vi-1; data[ j++ ] = vi < 0 ? vi + vcnt : vi - 1;
if (j >= n) return j; if( j >= n )
return j;
} }
return j; return j;
} }
bool rcMeshLoaderObj::load(const std::string& filename) bool rcMeshLoaderObj::load( const std::string& filename )
{ {
char* buf = 0; char* buf = 0;
FILE* fp = fopen(filename.c_str(), "rb"); FILE* fp = fopen( filename.c_str(), "rb" );
if (!fp) if( !fp )
return false; return false;
if (fseek(fp, 0, SEEK_END) != 0) if( fseek( fp, 0, SEEK_END ) != 0 )
{ {
fclose(fp); fclose( fp );
return false; return false;
} }
long bufSize = ftell(fp); long bufSize = ftell( fp );
if (bufSize < 0) if( bufSize < 0 )
{ {
fclose(fp); fclose( fp );
return false; return false;
} }
if (fseek(fp, 0, SEEK_SET) != 0) if( fseek( fp, 0, SEEK_SET ) != 0 )
{ {
fclose(fp); fclose( fp );
return false; return false;
} }
buf = new char[bufSize]; buf = new char[bufSize];
if (!buf) if( !buf )
{ {
fclose(fp); fclose( fp );
return false; return false;
} }
size_t readLen = fread(buf, bufSize, 1, fp); size_t readLen = fread( buf, bufSize, 1, fp );
fclose(fp); fclose( fp );
if (readLen != 1) if( readLen != 1 )
{ {
delete[] buf; delete[] buf;
return false; return false;
@ -177,66 +183,67 @@ bool rcMeshLoaderObj::load(const std::string& filename)
char* srcEnd = buf + bufSize; char* srcEnd = buf + bufSize;
char row[512]; char row[512];
int face[32]; int face[32];
float x,y,z; float x, y, z;
int nv; int nv;
int vcap = 0; int vcap = 0;
int tcap = 0; int tcap = 0;
while (src < srcEnd) while( src < srcEnd )
{ {
// Parse one row // Parse one row
row[0] = '\0'; row[ 0 ] = '\0';
src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char)); src = parseRow( src, srcEnd, row, sizeof( row ) / sizeof( char ) );
// Skip comments // Skip comments
if (row[0] == '#') continue; if( row[ 0 ] == '#' )
if (row[0] == 'v' && row[1] != 'n' && row[1] != 't') continue;
if( row[ 0 ] == 'v' && row[ 1 ] != 'n' && row[ 1 ] != 't' )
{ {
// Vertex pos // Vertex pos
sscanf(row+1, "%f %f %f", &x, &y, &z); sscanf( row + 1, "%f %f %f", &x, &y, &z );
addVertex(x, y, z, vcap); addVertex( x, y, z, vcap );
} }
if (row[0] == 'f') if( row[ 0 ] == 'f' )
{ {
// Faces // Faces
nv = parseFace(row+1, face, 32, m_vertCount); nv = parseFace( row + 1, face, 32, m_vertCount );
for (int i = 2; i < nv; ++i) for( int i = 2; i < nv; ++i )
{ {
const int a = face[0]; const int a = face[ 0 ];
const int b = face[i-1]; const int b = face[ i - 1 ];
const int c = face[i]; const int c = face[ i ];
if (a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount) if( a < 0 || a >= m_vertCount || b < 0 || b >= m_vertCount || c < 0 || c >= m_vertCount )
continue; continue;
addTriangle(a, b, c, tcap); addTriangle( a, b, c, tcap );
} }
} }
} }
delete [] buf; delete[] buf;
// Calculate normals. // Calculate normals.
m_normals = new float[m_triCount*3]; m_normals = new float[m_triCount * 3];
for (int i = 0; i < m_triCount*3; i += 3) for( int i = 0; i < m_triCount * 3; i += 3 )
{ {
const float* v0 = &m_verts[m_tris[i]*3]; const float* v0 = &m_verts[ m_tris[ i ] * 3 ];
const float* v1 = &m_verts[m_tris[i+1]*3]; const float* v1 = &m_verts[ m_tris[ i + 1 ] * 3 ];
const float* v2 = &m_verts[m_tris[i+2]*3]; const float* v2 = &m_verts[ m_tris[ i + 2 ] * 3 ];
float e0[3], e1[3]; float e0[3], e1[3];
for (int j = 0; j < 3; ++j) for( int j = 0; j < 3; ++j )
{ {
e0[j] = v1[j] - v0[j]; e0[ j ] = v1[ j ] - v0[ j ];
e1[j] = v2[j] - v0[j]; e1[ j ] = v2[ j ] - v0[ j ];
} }
float* n = &m_normals[i]; float* n = &m_normals[ i ];
n[0] = e0[1]*e1[2] - e0[2]*e1[1]; n[ 0 ] = e0[ 1 ] * e1[ 2 ] - e0[ 2 ] * e1[ 1 ];
n[1] = e0[2]*e1[0] - e0[0]*e1[2]; n[ 1 ] = e0[ 2 ] * e1[ 0 ] - e0[ 0 ] * e1[ 2 ];
n[2] = e0[0]*e1[1] - e0[1]*e1[0]; 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]); float d = sqrtf( n[ 0 ] * n[ 0 ] + n[ 1 ] * n[ 1 ] + n[ 2 ] * n[ 2 ] );
if (d > 0) if( d > 0 )
{ {
d = 1.0f/d; d = 1.0f / d;
n[0] *= d; n[ 0 ] *= d;
n[1] *= d; n[ 1 ] *= d;
n[2] *= d; n[ 2 ] *= d;
} }
} }

View file

@ -25,24 +25,50 @@ class rcMeshLoaderObj
{ {
public: public:
rcMeshLoaderObj(); rcMeshLoaderObj();
~rcMeshLoaderObj(); ~rcMeshLoaderObj();
bool load(const std::string& fileName); bool load( const std::string& fileName );
const float* getVerts() const { return m_verts; } const float* getVerts() const
const float* getNormals() const { return m_normals; } {
const int* getTris() const { return m_tris; } return m_verts;
int getVertCount() const { return m_vertCount; } }
int getTriCount() const { return m_triCount; }
const std::string& getFileName() const { return m_filename; } const float* getNormals() const
{
return m_normals;
}
const int* getTris() const
{
return m_tris;
}
int getVertCount() const
{
return m_vertCount;
}
int getTriCount() const
{
return m_triCount;
}
const std::string& getFileName() const
{
return m_filename;
}
private: private:
// Explicitly disabled copy constructor and copy assignment operator. // Explicitly disabled copy constructor and copy assignment operator.
rcMeshLoaderObj(const rcMeshLoaderObj&); rcMeshLoaderObj( const rcMeshLoaderObj& );
rcMeshLoaderObj& operator=(const rcMeshLoaderObj&);
void addVertex(float x, float y, float z, int& cap); rcMeshLoaderObj& operator=( const rcMeshLoaderObj& );
void addTriangle(int a, int b, int c, int& cap);
void addVertex( float x, float y, float z, int& cap );
void addTriangle( int a, int b, int c, int& cap );
std::string m_filename; std::string m_filename;
float m_scale; float m_scale;