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,293 +23,309 @@
|
|||
|
||||
struct BoundsItem
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
int i;
|
||||
float bmin[ 2 ];
|
||||
float bmax[ 2 ];
|
||||
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* b = (const BoundsItem*)vb;
|
||||
if (a->bmin[0] < b->bmin[0])
|
||||
return -1;
|
||||
if (a->bmin[0] > b->bmin[0])
|
||||
return 1;
|
||||
return 0;
|
||||
const BoundsItem* a = ( const BoundsItem* ) va;
|
||||
const BoundsItem* b = ( const BoundsItem* ) vb;
|
||||
if( a->bmin[ 0 ] < b->bmin[ 0 ] )
|
||||
return -1;
|
||||
if( a->bmin[ 0 ] > b->bmin[ 0 ] )
|
||||
return 1;
|
||||
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* b = (const BoundsItem*)vb;
|
||||
if (a->bmin[1] < b->bmin[1])
|
||||
return -1;
|
||||
if (a->bmin[1] > b->bmin[1])
|
||||
return 1;
|
||||
return 0;
|
||||
const BoundsItem* a = ( const BoundsItem* ) va;
|
||||
const BoundsItem* b = ( const BoundsItem* ) vb;
|
||||
if( a->bmin[ 1 ] < b->bmin[ 1 ] )
|
||||
return -1;
|
||||
if( a->bmin[ 1 ] > b->bmin[ 1 ] )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void calcExtends(const BoundsItem* items, const int /*nitems*/,
|
||||
const int imin, const int imax,
|
||||
float* bmin, float* bmax)
|
||||
static void calcExtends( const BoundsItem* items, const int /*nitems*/,
|
||||
const int imin, const int imax,
|
||||
float* bmin, float* bmax )
|
||||
{
|
||||
bmin[0] = items[imin].bmin[0];
|
||||
bmin[1] = items[imin].bmin[1];
|
||||
bmin[ 0 ] = items[ imin ].bmin[ 0 ];
|
||||
bmin[ 1 ] = items[ imin ].bmin[ 1 ];
|
||||
|
||||
bmax[0] = items[imin].bmax[0];
|
||||
bmax[1] = items[imin].bmax[1];
|
||||
bmax[ 0 ] = items[ imin ].bmax[ 0 ];
|
||||
bmax[ 1 ] = items[ imin ].bmax[ 1 ];
|
||||
|
||||
for (int i = imin+1; i < imax; ++i)
|
||||
{
|
||||
const BoundsItem& it = items[i];
|
||||
if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0];
|
||||
if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1];
|
||||
for( int i = imin + 1; i < imax; ++i )
|
||||
{
|
||||
const BoundsItem& it = items[ i ];
|
||||
if( it.bmin[ 0 ] < bmin[ 0 ] )
|
||||
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[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,
|
||||
int& curNode, rcChunkyTriMeshNode* nodes, const int maxNodes,
|
||||
int& curTri, int* outTris, const int* inTris)
|
||||
static void subdivide( BoundsItem* items, int nitems, int imin, int imax, int trisPerChunk,
|
||||
int& curNode, rcChunkyTriMeshNode* nodes, const int maxNodes,
|
||||
int& curTri, int* outTris, const int* inTris )
|
||||
{
|
||||
int inum = imax - imin;
|
||||
int icur = curNode;
|
||||
int inum = imax - imin;
|
||||
int icur = curNode;
|
||||
|
||||
if (curNode > maxNodes)
|
||||
return;
|
||||
if( curNode > maxNodes )
|
||||
return;
|
||||
|
||||
rcChunkyTriMeshNode& node = nodes[curNode++];
|
||||
rcChunkyTriMeshNode& node = nodes[ curNode++ ];
|
||||
|
||||
if (inum <= trisPerChunk)
|
||||
{
|
||||
// Leaf
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
if( inum <= trisPerChunk )
|
||||
{
|
||||
// Leaf
|
||||
calcExtends( items, nitems, imin, imax, node.bmin, node.bmax );
|
||||
|
||||
// Copy triangles.
|
||||
node.i = curTri;
|
||||
node.n = inum;
|
||||
// Copy triangles.
|
||||
node.i = curTri;
|
||||
node.n = inum;
|
||||
|
||||
for (int i = imin; i < imax; ++i)
|
||||
{
|
||||
const int* src = &inTris[items[i].i*3];
|
||||
int* dst = &outTris[curTri*3];
|
||||
curTri++;
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split
|
||||
calcExtends(items, nitems, imin, imax, node.bmin, node.bmax);
|
||||
for( int i = imin; i < imax; ++i )
|
||||
{
|
||||
const int* src = &inTris[ items[ i ].i * 3 ];
|
||||
int* dst = &outTris[ curTri * 3 ];
|
||||
curTri++;
|
||||
dst[ 0 ] = src[ 0 ];
|
||||
dst[ 1 ] = src[ 1 ];
|
||||
dst[ 2 ] = src[ 2 ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split
|
||||
calcExtends( items, nitems, imin, imax, node.bmin, node.bmax );
|
||||
|
||||
int axis = longestAxis(node.bmax[0] - node.bmin[0],
|
||||
node.bmax[1] - node.bmin[1]);
|
||||
int axis = longestAxis( node.bmax[ 0 ] - node.bmin[ 0 ],
|
||||
node.bmax[ 1 ] - node.bmin[ 1 ] );
|
||||
|
||||
if (axis == 0)
|
||||
{
|
||||
// Sort along x-axis
|
||||
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemX);
|
||||
}
|
||||
else if (axis == 1)
|
||||
{
|
||||
// Sort along y-axis
|
||||
qsort(items+imin, static_cast<size_t>(inum), sizeof(BoundsItem), compareItemY);
|
||||
}
|
||||
if( axis == 0 )
|
||||
{
|
||||
// Sort along x-axis
|
||||
qsort( items + imin, static_cast<size_t>(inum), sizeof( BoundsItem ), compareItemX );
|
||||
}
|
||||
else if( axis == 1 )
|
||||
{
|
||||
// Sort along y-axis
|
||||
qsort( items + imin, static_cast<size_t>(inum), sizeof( BoundsItem ), compareItemY );
|
||||
}
|
||||
|
||||
int isplit = imin+inum/2;
|
||||
int isplit = imin + inum / 2;
|
||||
|
||||
// Left
|
||||
subdivide(items, nitems, imin, isplit, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris);
|
||||
// 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 );
|
||||
// Right
|
||||
subdivide( items, nitems, isplit, imax, trisPerChunk, curNode, nodes, maxNodes, curTri, outTris, inTris );
|
||||
|
||||
int iescape = curNode - icur;
|
||||
// Negative index means escape.
|
||||
node.i = -iescape;
|
||||
}
|
||||
int iescape = curNode - icur;
|
||||
// Negative index means escape.
|
||||
node.i = -iescape;
|
||||
}
|
||||
}
|
||||
|
||||
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm)
|
||||
bool rcCreateChunkyTriMesh( const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm )
|
||||
{
|
||||
int nchunks = (ntris + trisPerChunk-1) / trisPerChunk;
|
||||
int nchunks = ( ntris + trisPerChunk - 1 ) / trisPerChunk;
|
||||
|
||||
cm->nodes = new rcChunkyTriMeshNode[nchunks*4];
|
||||
if (!cm->nodes)
|
||||
return false;
|
||||
cm->nodes = new rcChunkyTriMeshNode[nchunks * 4];
|
||||
if( !cm->nodes )
|
||||
return false;
|
||||
|
||||
cm->tris = new int[ntris*3];
|
||||
if (!cm->tris)
|
||||
return false;
|
||||
cm->tris = new int[ntris * 3];
|
||||
if( !cm->tris )
|
||||
return false;
|
||||
|
||||
cm->ntris = ntris;
|
||||
cm->ntris = ntris;
|
||||
|
||||
// Build tree
|
||||
BoundsItem* items = new BoundsItem[ntris];
|
||||
if (!items)
|
||||
return false;
|
||||
// Build tree
|
||||
BoundsItem* items = new BoundsItem[ntris];
|
||||
if( !items )
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < ntris; i++)
|
||||
{
|
||||
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];
|
||||
for( int i = 0; i < ntris; i++ )
|
||||
{
|
||||
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];
|
||||
if (v[2] > it.bmax[1]) it.bmax[1] = v[2];
|
||||
}
|
||||
}
|
||||
if( v[ 0 ] > it.bmax[ 0 ] )
|
||||
it.bmax[ 0 ] = v[ 0 ];
|
||||
if( v[ 2 ] > it.bmax[ 1 ] )
|
||||
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);
|
||||
int curTri = 0;
|
||||
int curNode = 0;
|
||||
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.
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool checkOverlapRect(const float amin[2], const float amax[2],
|
||||
const float bmin[2], const float bmax[2])
|
||||
inline bool checkOverlapRect( const float amin[2], const float amax[2],
|
||||
const float bmin[2], const float bmax[2] )
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
|
||||
return overlap;
|
||||
bool overlap = true;
|
||||
overlap = ( amin[ 0 ] > bmax[ 0 ] || amax[ 0 ] < bmin[ 0 ] ) ? false : overlap;
|
||||
overlap = ( amin[ 1 ] > bmax[ 1 ] || amax[ 1 ] < bmin[ 1 ] ) ? false : overlap;
|
||||
return overlap;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while (i < cm->nnodes)
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[i];
|
||||
const bool overlap = checkOverlapRect(bmin, bmax, node->bmin, node->bmax);
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while( i < cm->nnodes )
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[ i ];
|
||||
const bool overlap = checkOverlapRect( bmin, bmax, node->bmin, node->bmax );
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
|
||||
if (isLeafNode && overlap)
|
||||
{
|
||||
if (n < maxIds)
|
||||
{
|
||||
ids[n] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if( isLeafNode && overlap )
|
||||
{
|
||||
if( n < maxIds )
|
||||
{
|
||||
ids[ n ] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap || isLeafNode)
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
if( overlap || isLeafNode )
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool checkOverlapSegment(const float p[2], const float q[2],
|
||||
const float bmin[2], const float bmax[2])
|
||||
static bool checkOverlapSegment( const float p[2], const float q[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 tmax = 1;
|
||||
float d[2];
|
||||
d[0] = q[0] - p[0];
|
||||
d[1] = q[1] - p[1];
|
||||
float tmin = 0;
|
||||
float tmax = 1;
|
||||
float d[2];
|
||||
d[ 0 ] = q[ 0 ] - p[ 0 ];
|
||||
d[ 1 ] = q[ 1 ] - p[ 1 ];
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (fabsf(d[i]) < EPSILON)
|
||||
{
|
||||
// Ray is parallel to slab. No hit if origin not within slab
|
||||
if (p[i] < bmin[i] || p[i] > bmax[i])
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute intersection t value of ray with near and far plane of slab
|
||||
float ood = 1.0f / d[i];
|
||||
float t1 = (bmin[i] - p[i]) * ood;
|
||||
float t2 = (bmax[i] - p[i]) * ood;
|
||||
if (t1 > t2) { float tmp = t1; t1 = t2; t2 = tmp; }
|
||||
if (t1 > tmin) tmin = t1;
|
||||
if (t2 < tmax) tmax = t2;
|
||||
if (tmin > tmax) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
for( int i = 0; i < 2; i++ )
|
||||
{
|
||||
if( fabsf( d[ i ] ) < EPSILON )
|
||||
{
|
||||
// Ray is parallel to slab. No hit if origin not within slab
|
||||
if( p[ i ] < bmin[ i ] || p[ i ] > bmax[ i ] )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute intersection t value of ray with near and far plane of slab
|
||||
float ood = 1.0f / d[ i ];
|
||||
float t1 = ( bmin[ i ] - p[ i ] ) * ood;
|
||||
float t2 = ( bmax[ i ] - p[ i ] ) * ood;
|
||||
if( t1 > t2 )
|
||||
{
|
||||
float tmp = t1;
|
||||
t1 = t2;
|
||||
t2 = tmp;
|
||||
}
|
||||
if( t1 > tmin )
|
||||
tmin = t1;
|
||||
if( t2 < tmax )
|
||||
tmax = t2;
|
||||
if( tmin > tmax )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while (i < cm->nnodes)
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[i];
|
||||
const bool overlap = checkOverlapSegment(p, q, node->bmin, node->bmax);
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
// Traverse tree
|
||||
int i = 0;
|
||||
int n = 0;
|
||||
while( i < cm->nnodes )
|
||||
{
|
||||
const rcChunkyTriMeshNode* node = &cm->nodes[ i ];
|
||||
const bool overlap = checkOverlapSegment( p, q, node->bmin, node->bmax );
|
||||
const bool isLeafNode = node->i >= 0;
|
||||
|
||||
if (isLeafNode && overlap)
|
||||
{
|
||||
if (n < maxIds)
|
||||
{
|
||||
ids[n] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if( isLeafNode && overlap )
|
||||
{
|
||||
if( n < maxIds )
|
||||
{
|
||||
ids[ n ] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap || isLeafNode)
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
if( overlap || isLeafNode )
|
||||
i++;
|
||||
else
|
||||
{
|
||||
const int escapeIndex = -node->i;
|
||||
i += escapeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
|
|
@ -21,39 +21,48 @@
|
|||
|
||||
struct rcChunkyTriMeshNode
|
||||
{
|
||||
float bmin[2];
|
||||
float bmax[2];
|
||||
int i;
|
||||
int n;
|
||||
float bmin[ 2 ];
|
||||
float bmax[ 2 ];
|
||||
int i;
|
||||
int n;
|
||||
};
|
||||
|
||||
struct rcChunkyTriMesh
|
||||
{
|
||||
inline rcChunkyTriMesh() : nodes(0), nnodes(0), tris(0), ntris(0), maxTrisPerChunk(0) {};
|
||||
inline ~rcChunkyTriMesh() { delete [] nodes; delete [] tris; }
|
||||
inline rcChunkyTriMesh() :
|
||||
nodes( 0 ), nnodes( 0 ), tris( 0 ), ntris( 0 ), maxTrisPerChunk( 0 )
|
||||
{
|
||||
};
|
||||
|
||||
rcChunkyTriMeshNode* nodes;
|
||||
int nnodes;
|
||||
int* tris;
|
||||
int ntris;
|
||||
int maxTrisPerChunk;
|
||||
inline ~rcChunkyTriMesh()
|
||||
{
|
||||
delete[] nodes;
|
||||
delete[] tris;
|
||||
}
|
||||
|
||||
rcChunkyTriMeshNode* nodes;
|
||||
int nnodes;
|
||||
int* tris;
|
||||
int ntris;
|
||||
int maxTrisPerChunk;
|
||||
|
||||
private:
|
||||
// Explicitly disabled copy constructor and copy assignment operator.
|
||||
rcChunkyTriMesh(const rcChunkyTriMesh&);
|
||||
rcChunkyTriMesh& operator=(const rcChunkyTriMesh&);
|
||||
// Explicitly disabled copy constructor and copy assignment operator.
|
||||
rcChunkyTriMesh( const rcChunkyTriMesh& );
|
||||
|
||||
rcChunkyTriMesh& operator=( const rcChunkyTriMesh& );
|
||||
};
|
||||
|
||||
/// Creates partitioned triangle mesh (AABB tree),
|
||||
/// where each node contains at max trisPerChunk triangles.
|
||||
bool rcCreateChunkyTriMesh(const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm);
|
||||
bool rcCreateChunkyTriMesh( const float* verts, const int* tris, int ntris,
|
||||
int trisPerChunk, rcChunkyTriMesh* cm );
|
||||
|
||||
/// 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.
|
||||
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
|
||||
|
|
|
@ -20,154 +20,160 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <math.h>
|
||||
|
||||
rcMeshLoaderObj::rcMeshLoaderObj() :
|
||||
m_scale(1.0f),
|
||||
m_verts(0),
|
||||
m_tris(0),
|
||||
m_normals(0),
|
||||
m_vertCount(0),
|
||||
m_triCount(0)
|
||||
m_scale( 1.0f ),
|
||||
m_verts( 0 ),
|
||||
m_tris( 0 ),
|
||||
m_normals( 0 ),
|
||||
m_vertCount( 0 ),
|
||||
m_triCount( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
rcMeshLoaderObj::~rcMeshLoaderObj()
|
||||
{
|
||||
delete [] m_verts;
|
||||
delete [] m_normals;
|
||||
delete [] m_tris;
|
||||
delete[] m_verts;
|
||||
delete[] m_normals;
|
||||
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;
|
||||
float* nv = new float[cap*3];
|
||||
if (m_vertCount)
|
||||
memcpy(nv, m_verts, m_vertCount*3*sizeof(float));
|
||||
delete [] m_verts;
|
||||
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;
|
||||
float* dst = &m_verts[ m_vertCount * 3 ];
|
||||
*dst++ = x * m_scale;
|
||||
*dst++ = y * m_scale;
|
||||
*dst++ = z * m_scale;
|
||||
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;
|
||||
int* nv = new int[cap*3];
|
||||
if (m_triCount)
|
||||
memcpy(nv, m_tris, m_triCount*3*sizeof(int));
|
||||
delete [] m_tris;
|
||||
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];
|
||||
int* dst = &m_tris[ m_triCount * 3 ];
|
||||
*dst++ = a;
|
||||
*dst++ = b;
|
||||
*dst++ = c;
|
||||
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 done = false;
|
||||
int n = 0;
|
||||
while (!done && buf < bufEnd)
|
||||
while( !done && buf < bufEnd )
|
||||
{
|
||||
char c = *buf;
|
||||
buf++;
|
||||
// multirow
|
||||
switch (c)
|
||||
switch( c )
|
||||
{
|
||||
case '\\':
|
||||
break;
|
||||
case '\n':
|
||||
if (start) break;
|
||||
if( start )
|
||||
break;
|
||||
done = true;
|
||||
break;
|
||||
case '\r':
|
||||
break;
|
||||
case '\t':
|
||||
case ' ':
|
||||
if (start) break;
|
||||
if( start )
|
||||
break;
|
||||
// else falls through
|
||||
default:
|
||||
start = false;
|
||||
row[n++] = c;
|
||||
if (n >= len-1)
|
||||
row[ n++ ] = c;
|
||||
if( n >= len - 1 )
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
row[n] = '\0';
|
||||
row[ n ] = '\0';
|
||||
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;
|
||||
while (*row != '\0')
|
||||
while( *row != '\0' )
|
||||
{
|
||||
// Skip initial white space
|
||||
while (*row != '\0' && (*row == ' ' || *row == '\t'))
|
||||
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')
|
||||
while( *row != '\0' && *row != ' ' && *row != '\t' )
|
||||
{
|
||||
if (*row == '/') *row = '\0';
|
||||
if( *row == '/' )
|
||||
*row = '\0';
|
||||
row++;
|
||||
}
|
||||
if (*s == '\0')
|
||||
if( *s == '\0' )
|
||||
continue;
|
||||
int vi = atoi(s);
|
||||
data[j++] = vi < 0 ? vi+vcnt : vi-1;
|
||||
if (j >= n) return j;
|
||||
int vi = atoi( s );
|
||||
data[ j++ ] = vi < 0 ? vi + vcnt : vi - 1;
|
||||
if( j >= n )
|
||||
return j;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
bool rcMeshLoaderObj::load(const std::string& filename)
|
||||
bool rcMeshLoaderObj::load( const std::string& filename )
|
||||
{
|
||||
char* buf = 0;
|
||||
FILE* fp = fopen(filename.c_str(), "rb");
|
||||
if (!fp)
|
||||
FILE* fp = fopen( filename.c_str(), "rb" );
|
||||
if( !fp )
|
||||
return false;
|
||||
if (fseek(fp, 0, SEEK_END) != 0)
|
||||
if( fseek( fp, 0, SEEK_END ) != 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
long bufSize = ftell(fp);
|
||||
if (bufSize < 0)
|
||||
long bufSize = ftell( fp );
|
||||
if( bufSize < 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
if (fseek(fp, 0, SEEK_SET) != 0)
|
||||
if( fseek( fp, 0, SEEK_SET ) != 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
buf = new char[bufSize];
|
||||
if (!buf)
|
||||
if( !buf )
|
||||
{
|
||||
fclose(fp);
|
||||
fclose( fp );
|
||||
return false;
|
||||
}
|
||||
size_t readLen = fread(buf, bufSize, 1, fp);
|
||||
fclose(fp);
|
||||
size_t readLen = fread( buf, bufSize, 1, fp );
|
||||
fclose( fp );
|
||||
|
||||
if (readLen != 1)
|
||||
if( readLen != 1 )
|
||||
{
|
||||
delete[] buf;
|
||||
return false;
|
||||
|
@ -177,66 +183,67 @@ bool rcMeshLoaderObj::load(const std::string& filename)
|
|||
char* srcEnd = buf + bufSize;
|
||||
char row[512];
|
||||
int face[32];
|
||||
float x,y,z;
|
||||
float x, y, z;
|
||||
int nv;
|
||||
int vcap = 0;
|
||||
int tcap = 0;
|
||||
|
||||
while (src < srcEnd)
|
||||
while( src < srcEnd )
|
||||
{
|
||||
// Parse one row
|
||||
row[0] = '\0';
|
||||
src = parseRow(src, srcEnd, row, sizeof(row)/sizeof(char));
|
||||
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')
|
||||
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);
|
||||
sscanf( row + 1, "%f %f %f", &x, &y, &z );
|
||||
addVertex( x, y, z, vcap );
|
||||
}
|
||||
if (row[0] == 'f')
|
||||
if( row[ 0 ] == 'f' )
|
||||
{
|
||||
// Faces
|
||||
nv = parseFace(row+1, face, 32, m_vertCount);
|
||||
for (int i = 2; i < nv; ++i)
|
||||
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)
|
||||
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);
|
||||
addTriangle( a, b, c, tcap );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] buf;
|
||||
delete[] buf;
|
||||
|
||||
// Calculate normals.
|
||||
m_normals = new float[m_triCount*3];
|
||||
for (int i = 0; i < m_triCount*3; i += 3)
|
||||
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];
|
||||
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)
|
||||
for( int j = 0; j < 3; ++j )
|
||||
{
|
||||
e0[j] = v1[j] - v0[j];
|
||||
e1[j] = v2[j] - v0[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)
|
||||
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;
|
||||
d = 1.0f / d;
|
||||
n[ 0 ] *= d;
|
||||
n[ 1 ] *= d;
|
||||
n[ 2 ] *= d;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,24 +25,50 @@ class rcMeshLoaderObj
|
|||
{
|
||||
public:
|
||||
rcMeshLoaderObj();
|
||||
|
||||
~rcMeshLoaderObj();
|
||||
|
||||
bool load(const std::string& fileName);
|
||||
bool load( const std::string& fileName );
|
||||
|
||||
const float* getVerts() const { return m_verts; }
|
||||
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; }
|
||||
const float* getVerts() const
|
||||
{
|
||||
return m_verts;
|
||||
}
|
||||
|
||||
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:
|
||||
// Explicitly disabled copy constructor and copy assignment operator.
|
||||
rcMeshLoaderObj(const rcMeshLoaderObj&);
|
||||
rcMeshLoaderObj& operator=(const rcMeshLoaderObj&);
|
||||
rcMeshLoaderObj( const rcMeshLoaderObj& );
|
||||
|
||||
void addVertex(float x, float y, float z, int& cap);
|
||||
void addTriangle(int a, int b, int c, int& cap);
|
||||
rcMeshLoaderObj& operator=( const rcMeshLoaderObj& );
|
||||
|
||||
void addVertex( float x, float y, float z, int& cap );
|
||||
|
||||
void addTriangle( int a, int b, int c, int& cap );
|
||||
|
||||
std::string m_filename;
|
||||
float m_scale;
|
||||
|
|
Loading…
Add table
Reference in a new issue