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:
parent
e5f612bc43
commit
29edf87924
4 changed files with 432 additions and 374 deletions
|
@ -23,115 +23,119 @@
|
||||||
|
|
||||||
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 ] )
|
||||||
|
bmin[ 1 ] = it.bmin[ 1 ];
|
||||||
|
|
||||||
if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0];
|
if( it.bmax[ 0 ] > bmax[ 0 ] )
|
||||||
if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1];
|
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)
|
if( curNode > maxNodes )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rcChunkyTriMeshNode& node = nodes[curNode++];
|
rcChunkyTriMeshNode& node = nodes[ curNode++ ];
|
||||||
|
|
||||||
if (inum <= trisPerChunk)
|
if( inum <= trisPerChunk )
|
||||||
{
|
{
|
||||||
// Leaf
|
// Leaf
|
||||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
calcExtends( items, nitems, imin, imax, node.bmin, node.bmax );
|
||||||
|
|
||||||
// Copy triangles.
|
// Copy triangles.
|
||||||
node.i = curTri;
|
node.i = curTri;
|
||||||
node.n = inum;
|
node.n = inum;
|
||||||
|
|
||||||
for (int i = imin; i < imax; ++i)
|
for( int i = imin; i < imax; ++i )
|
||||||
{
|
{
|
||||||
const int* src = &inTris[items[i].i*3];
|
const int* src = &inTris[ items[ i ].i * 3 ];
|
||||||
int* dst = &outTris[curTri*3];
|
int* dst = &outTris[ curTri * 3 ];
|
||||||
curTri++;
|
curTri++;
|
||||||
dst[0] = src[0];
|
dst[ 0 ] = src[ 0 ];
|
||||||
dst[1] = src[1];
|
dst[ 1 ] = src[ 1 ];
|
||||||
dst[2] = src[2];
|
dst[ 2 ] = src[ 2 ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Split
|
// Split
|
||||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
calcExtends( items, nitems, imin, imax, node.bmin, node.bmax );
|
||||||
|
|
||||||
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
int axis = longestAxis( node.bmax[ 0 ] - node.bmin[ 0 ],
|
||||||
node.bmax[1] - node.bmin[1]);
|
node.bmax[ 1 ] - node.bmin[ 1 ] );
|
||||||
|
|
||||||
if (axis == 0)
|
if( axis == 0 )
|
||||||
{
|
{
|
||||||
// Sort along x-axis
|
// Sort along x-axis
|
||||||
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemX);
|
qsort( items + imin, static_cast<size_t>(inum), sizeof( BoundsItem ), compareItemX );
|
||||||
}
|
}
|
||||||
else if (axis == 1)
|
else if( axis == 1 )
|
||||||
{
|
{
|
||||||
// Sort along y-axis
|
// Sort along y-axis
|
||||||
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemY);
|
qsort( items + imin, static_cast<size_t>(inum), sizeof( BoundsItem ), compareItemY );
|
||||||
}
|
}
|
||||||
|
|
||||||
int isplit = imin+inum/2;
|
int isplit = imin + inum / 2;
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
subdivide(items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
subdivide( items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris );
|
||||||
// Right
|
// Right
|
||||||
subdivide(items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
subdivide( items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris );
|
||||||
|
|
||||||
int iescape = curNode - icur;
|
int iescape = curNode - icur;
|
||||||
// Negative index means escape.
|
// Negative index means escape.
|
||||||
|
@ -139,61 +143,66 @@ static void subdivide(BoundsItem* items, int nitems, int imin, int imax, int tri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
cm->tris = new int[ntris * 3];
|
||||||
if (!cm->tris)
|
if( !cm->tris )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cm->ntris = ntris;
|
cm->ntris = ntris;
|
||||||
|
|
||||||
// Build tree
|
// Build tree
|
||||||
BoundsItem* items = new BoundsItem[ntris];
|
BoundsItem* items = new BoundsItem[ntris];
|
||||||
if (!items)
|
if( !items )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int i = 0; i < ntris; i++)
|
for( int i = 0; i < ntris; i++ )
|
||||||
{
|
{
|
||||||
const int* t = &tris[i*3];
|
const int* t = &tris[ i * 3 ];
|
||||||
BoundsItem& it = items[i];
|
BoundsItem& it = items[ i ];
|
||||||
it.i = i;
|
it.i = i;
|
||||||
// Calc triangle XZ bounds.
|
// Calc triangle XZ bounds.
|
||||||
it.bmin[0] = it.bmax[0] = verts[t[0]*3+0];
|
it.bmin[ 0 ] = it.bmax[ 0 ] = verts[ t[ 0 ] * 3 + 0 ];
|
||||||
it.bmin[1] = it.bmax[1] = verts[t[0]*3+2];
|
it.bmin[ 1 ] = it.bmax[ 1 ] = verts[ t[ 0 ] * 3 + 2 ];
|
||||||
for (int j = 1; j < 3; ++j)
|
for( int j = 1; j < 3; ++j )
|
||||||
{
|
{
|
||||||
const float* v = &verts[t[j]*3];
|
const float* v = &verts[ t[ j ] * 3 ];
|
||||||
if (v[0] < it.bmin[0]) it.bmin[0] = v[0];
|
if( v[ 0 ] < it.bmin[ 0 ] )
|
||||||
if (v[2] < it.bmin[1]) it.bmin[1] = v[2];
|
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];
|
if( v[ 0 ] > it.bmax[ 0 ] )
|
||||||
if (v[2] > it.bmax[1]) it.bmax[1] = v[2];
|
it.bmax[ 0 ] = v[ 0 ];
|
||||||
|
if( v[ 2 ] > it.bmax[ 1 ] )
|
||||||
|
it.bmax[ 1 ] = v[ 2 ];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int curTri = 0;
|
int curTri = 0;
|
||||||
int curNode = 0;
|
int curNode = 0;
|
||||||
subdivide(items, ntris, 0, ntris, trisPerChunk, curNode, cm->nodes, nchunks*4, curTri, cm->tris, tris);
|
subdivide( items, ntris, 0, ntris, trisPerChunk, curNode, cm->nodes, nchunks * 4, curTri, cm->tris, tris );
|
||||||
|
|
||||||
delete [] items;
|
delete[] items;
|
||||||
|
|
||||||
cm->nnodes = curNode;
|
cm->nnodes = curNode;
|
||||||
|
|
||||||
// Calc max tris per node.
|
// Calc max tris per node.
|
||||||
cm->maxTrisPerChunk = 0;
|
cm->maxTrisPerChunk = 0;
|
||||||
for (int i = 0; i < cm->nnodes; ++i)
|
for( int i = 0; i < cm->nnodes; ++i )
|
||||||
{
|
{
|
||||||
rcChunkyTriMeshNode& node = cm->nodes[i];
|
rcChunkyTriMeshNode& node = cm->nodes[ i ];
|
||||||
const bool isLeaf = node.i >= 0;
|
const bool isLeaf = node.i >= 0;
|
||||||
if (!isLeaf) continue;
|
if( !isLeaf )
|
||||||
if (node.n > cm->maxTrisPerChunk)
|
continue;
|
||||||
|
if( node.n > cm->maxTrisPerChunk )
|
||||||
cm->maxTrisPerChunk = node.n;
|
cm->maxTrisPerChunk = node.n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,38 +210,38 @@ bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
{
|
{
|
||||||
|
@ -245,64 +254,71 @@ int rcGetChunksOverlappingRect(const rcChunkyTriMesh* cm,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if( t1 > tmin )
|
||||||
|
tmin = t1;
|
||||||
|
if( t2 < tmax )
|
||||||
|
tmax = t2;
|
||||||
|
if( tmin > tmax )
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
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
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,16 +21,24 @@
|
||||||
|
|
||||||
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 )
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ~rcChunkyTriMesh()
|
||||||
|
{
|
||||||
|
delete[] nodes;
|
||||||
|
delete[] tris;
|
||||||
|
}
|
||||||
|
|
||||||
rcChunkyTriMeshNode* nodes;
|
rcChunkyTriMeshNode* nodes;
|
||||||
int nnodes;
|
int nnodes;
|
||||||
|
@ -40,20 +48,21 @@ struct rcChunkyTriMesh
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue