mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Recast: revert to post polygon transformation
In commit a2d5d52dc4e571388b9b86f21e40a5110a69665e, the logic has been adjusted to build the polygon in the right order in the algorithm itself, but some indices are incorrect causing bad tesselation. The issue is somewhere in RecastMesh.cpp, writing polygon indices in the incorrect order '0, 3, 2, 1' instead of '3, 2, 1, 0'. Reverted to using "REVERSE_DIRECTION 0" for RecastMesh.cpp. Additional notes, tesselation appears correct when building the mesh with the layered partitioner, monotone and watershed causes bad tesselation. The vertex order is however still incorrect.
This commit is contained in:
parent
a8b302f165
commit
1e48d8abd9
@ -1222,7 +1222,6 @@ unsigned char* Editor_TileMesh::buildTileMesh(const int tx, const int ty, const
|
||||
return 0;
|
||||
}
|
||||
|
||||
//rcFlipPolyMesh(*m_pmesh);
|
||||
if (!rcBuildPolyMeshDetail(m_ctx, *m_pmesh, *m_chf,
|
||||
m_cfg.detailSampleDist, m_cfg.detailSampleMaxError,
|
||||
*m_dmesh))
|
||||
@ -1231,7 +1230,6 @@ unsigned char* Editor_TileMesh::buildTileMesh(const int tx, const int ty, const
|
||||
return 0;
|
||||
}
|
||||
|
||||
//rcFlipPolyMeshDetail(*m_dmesh,m_pmesh->nverts);
|
||||
if (!m_keepInterResults)
|
||||
{
|
||||
rcFreeCompactHeightfield(m_chf);
|
||||
|
@ -1164,9 +1164,6 @@ bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst);
|
||||
/// @returns True if the operation completed successfully.
|
||||
bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh);
|
||||
|
||||
void rcFlipPolyMesh(rcPolyMesh& mesh);
|
||||
void rcFlipPolyMeshDetail(rcPolyMeshDetail& mdetail, int poly_tris);
|
||||
|
||||
/// @}
|
||||
|
||||
#endif // RECAST_H
|
||||
|
182
src/thirdparty/recast/Recast/Source/RecastMesh.cpp
vendored
182
src/thirdparty/recast/Recast/Source/RecastMesh.cpp
vendored
@ -184,7 +184,7 @@ inline bool leftOn(const int* a, const int* b, const int* c)
|
||||
{
|
||||
return area2(a, b, c) <= 0;
|
||||
}
|
||||
#define REVERSE_DIRECTION 1
|
||||
#define REVERSE_DIRECTION 0
|
||||
inline bool right(const int* a, const int* b, const int* c)
|
||||
{
|
||||
return area2(a, b, c) > 0;
|
||||
@ -254,7 +254,7 @@ static bool vequal(const int* a, const int* b)
|
||||
#endif
|
||||
// Returns T if (v_i, v_j) is a proper internal *or* external
|
||||
// diagonal of P, *ignoring edges incident to v_i and v_j*.
|
||||
static bool diagonalie(int i, int j, int n, const int* verts, int* indices)
|
||||
static bool diagonalie(int i, int j, int n, const int* verts, const int* indices)
|
||||
{
|
||||
const int* d0 = &verts[(indices[i] & 0x0fffffff) * 4];
|
||||
const int* d1 = &verts[(indices[j] & 0x0fffffff) * 4];
|
||||
@ -281,7 +281,7 @@ static bool diagonalie(int i, int j, int n, const int* verts, int* indices)
|
||||
|
||||
// Returns true if the diagonal (i,j) is strictly internal to the
|
||||
// polygon P in the neighborhood of the i endpoint.
|
||||
static bool inCone(int i, int j, int n, const int* verts, int* indices)
|
||||
static bool inCone(int i, int j, int n, const int* verts, const int* indices)
|
||||
{
|
||||
const int* pi = &verts[(indices[i] & 0x0fffffff) * 4];
|
||||
const int* pj = &verts[(indices[j] & 0x0fffffff) * 4];
|
||||
@ -306,13 +306,13 @@ static bool inCone(int i, int j, int n, const int* verts, int* indices)
|
||||
|
||||
// Returns T if (v_i, v_j) is a proper internal
|
||||
// diagonal of P.
|
||||
static bool diagonal(int i, int j, int n, const int* verts, int* indices)
|
||||
static bool diagonal(int i, int j, int n, const int* verts, const int* indices)
|
||||
{
|
||||
return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices);
|
||||
}
|
||||
|
||||
|
||||
static bool diagonalieLoose(int i, int j, int n, const int* verts, int* indices)
|
||||
static bool diagonalieLoose(int i, int j, int n, const int* verts, const int* indices)
|
||||
{
|
||||
const int* d0 = &verts[(indices[i] & 0x0fffffff) * 4];
|
||||
const int* d1 = &verts[(indices[j] & 0x0fffffff) * 4];
|
||||
@ -337,7 +337,7 @@ static bool diagonalieLoose(int i, int j, int n, const int* verts, int* indices)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool inConeLoose(int i, int j, int n, const int* verts, int* indices)
|
||||
static bool inConeLoose(int i, int j, int n, const int* verts, const int* indices)
|
||||
{
|
||||
const int* pi = &verts[(indices[i] & 0x0fffffff) * 4];
|
||||
const int* pj = &verts[(indices[j] & 0x0fffffff) * 4];
|
||||
@ -360,7 +360,7 @@ static bool inConeLoose(int i, int j, int n, const int* verts, int* indices)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool diagonalLoose(int i, int j, int n, const int* verts, int* indices)
|
||||
static bool diagonalLoose(int i, int j, int n, const int* verts, const int* indices)
|
||||
{
|
||||
return inConeLoose(i, j, n, verts, indices) && diagonalieLoose(i, j, n, verts, indices);
|
||||
}
|
||||
@ -670,10 +670,10 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho
|
||||
{
|
||||
int* e = &edges[m * 3];
|
||||
#if REVERSE_DIRECTION
|
||||
if (e[2] == b)
|
||||
if (e[0] == b)
|
||||
{
|
||||
// Exists, increment vertex share count.
|
||||
e[1]++;
|
||||
e[2]++;
|
||||
exists = true;
|
||||
}
|
||||
#else
|
||||
@ -689,7 +689,7 @@ static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned sho
|
||||
if (!exists)
|
||||
{
|
||||
int* e = &edges[nedges*3];
|
||||
e[0] = a;
|
||||
e[0] = a; // todo for REVERSE_DIRECTION, figure out if we need to flip here as well.
|
||||
e[1] = b;
|
||||
e[2] = 1;
|
||||
nedges++;
|
||||
@ -1033,6 +1033,77 @@ static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short
|
||||
return true;
|
||||
}
|
||||
|
||||
void flipPolyMesh(rcPolyMesh& mesh)
|
||||
{
|
||||
for (int i = 0; i < mesh.npolys; i++)
|
||||
{
|
||||
const int nvp = mesh.nvp;
|
||||
|
||||
auto polyBegin = mesh.polys+2*nvp*i;
|
||||
auto neisBegins = mesh.polys+2*nvp*i+nvp;
|
||||
|
||||
int curCount = 0;
|
||||
|
||||
for (int j = 0; j < nvp; j++)
|
||||
{
|
||||
if (polyBegin[j] != 0xffff)
|
||||
curCount++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Flip order of vertexes
|
||||
for (int j = 0; j < curCount/2; j++)
|
||||
{
|
||||
rdSwap(polyBegin[j], polyBegin[curCount-j-1]);
|
||||
rdSwap(neisBegins[j], neisBegins[curCount-j-1]);
|
||||
}
|
||||
|
||||
if (curCount)
|
||||
{
|
||||
// Shift neis directions left, this is needed because the neis index edges
|
||||
// not vertexes
|
||||
const unsigned short zval = neisBegins[0];
|
||||
for (int j = 0; j < curCount-1; j++)
|
||||
{
|
||||
neisBegins[j] = neisBegins[j + 1];
|
||||
}
|
||||
neisBegins[curCount-1] = zval;
|
||||
}
|
||||
|
||||
// Flip neis directions.
|
||||
/*
|
||||
original code for reference
|
||||
cur.x ==0 && next.x ==0 -> 0
|
||||
cur.y ==h && next.x ==h -> 1
|
||||
cur.x ==w && next.x ==w -> 2
|
||||
cur.y ==0 && next.y ==0 -> 3
|
||||
|
||||
3
|
||||
###
|
||||
0 ### 2
|
||||
###
|
||||
1
|
||||
*/
|
||||
|
||||
//const int lkup[4] = { 0,1,2,3 }; // NOOP
|
||||
const int lkup[4] = { 2,1,0,3 }; // flip x only
|
||||
//const int lkup[4] = { 0,3,2,1 }; // flip y only
|
||||
//const int lkup[4] = { 2,3,0,1 }; // flip x and y
|
||||
//const int lkup[4] = { 3,0,1,2 }; // exchange x/y (90 deg)
|
||||
//const int lkup[4] = { 1,2,3,0 }; // -90 deg
|
||||
//const int lkup[4] = { 2,3,0,1 }; // 180 deg
|
||||
|
||||
for (int j = 0; j < curCount; j++)
|
||||
{
|
||||
if ((neisBegins[j] & 0x8000) && (neisBegins[j] != 0xffff))
|
||||
{
|
||||
neisBegins[j] = (unsigned short)lkup[neisBegins[j] & 0x3] | 0x8000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper
|
||||
@ -1374,9 +1445,13 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||||
break;
|
||||
|
||||
vi[0] = p[0];
|
||||
#if REVERSE_DIRECTION
|
||||
vi[1] = p[j];
|
||||
vi[2] = p[j-1];
|
||||
|
||||
#else
|
||||
vi[1] = p[j-1];
|
||||
vi[2] = p[j];
|
||||
#endif
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
const unsigned short* v = &mesh.verts[vi[k]*3];
|
||||
@ -1400,6 +1475,10 @@ bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMe
|
||||
ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff);
|
||||
}
|
||||
|
||||
#if !REVERSE_DIRECTION
|
||||
flipPolyMesh(mesh);
|
||||
#endif // !REVERSE_DIRECTION
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1646,84 +1725,3 @@ bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst)
|
||||
|
||||
return true;
|
||||
}
|
||||
void shift_left(unsigned short* arr, int count)
|
||||
{
|
||||
if (count == 0)return;
|
||||
auto zval = arr[0];
|
||||
for (int i = 0; i < count-1; i++)
|
||||
{
|
||||
arr[i] = arr[i + 1];
|
||||
}
|
||||
arr[count - 1] = zval;
|
||||
}
|
||||
void flip_neis_direction(unsigned short* arr, int count)
|
||||
{
|
||||
//const int lkup[4] = { 0,1,2,3 }; //NOOP
|
||||
const int lkup[4] = { 2,1,0,3 };// flip x only
|
||||
//const int lkup[4] = { 0,3,2,1 }; //flip y only
|
||||
//const int lkup[4] = { 2,3,0,1 }; //flip x and y
|
||||
//const int lkup[4] = { 3,0,1,2 }; //exchange x/y (90 deg)
|
||||
//const int lkup[4] = { 1,2,3,0 }; //-90 deg
|
||||
//const int lkup[4] = { 2,3,0,1 }; //180 deg
|
||||
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if ((arr[i] & 0x8000) && (arr[i] != 0xffff))
|
||||
{
|
||||
arr[i] = (unsigned short)lkup[arr[i] & 0x3] | 0x8000;
|
||||
}
|
||||
}
|
||||
|
||||
/* original code for reference
|
||||
cur.x ==0 && next.x ==0 -> 0
|
||||
cur.y ==h && next.x ==h -> 1
|
||||
cur.x ==w && next.x ==w -> 2
|
||||
cur.y ==0 && next.y ==0 -> 3
|
||||
|
||||
3
|
||||
###
|
||||
0 ### 2
|
||||
###
|
||||
1
|
||||
|
||||
if ((int)va[0] == 0 && (int)vb[0] == 0)
|
||||
p[nvp+j] = 0x8000 | 0;
|
||||
else if ((int)va[1] == h && (int)vb[1] == h)
|
||||
p[nvp+j] = 0x8000 | 1;
|
||||
else if ((int)va[0] == w && (int)vb[0] == w)
|
||||
p[nvp+j] = 0x8000 | 2;
|
||||
else if ((int)va[1] == 0 && (int)vb[1] == 0)
|
||||
p[nvp+j] = 0x8000 | 3;
|
||||
*/
|
||||
}
|
||||
void rcFlipPolyMesh(rcPolyMesh& /*mesh*/)
|
||||
{
|
||||
#if !REVERSE_DIRECTION
|
||||
for (int i = 0; i < mesh.npolys; i++)
|
||||
{
|
||||
int max_verts = mesh.nvp;
|
||||
auto poly_begin = mesh.polys + 2 * max_verts*i;
|
||||
auto poly_begin_neis = mesh.polys + 2 * max_verts*i+max_verts;//i.e. every second thing in this array is poly neis
|
||||
int cur_count = 0;
|
||||
for (int j = 0; j < max_verts; j++)
|
||||
{
|
||||
if (poly_begin[j] != 0xffff)
|
||||
cur_count++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
//flip order of vertexes
|
||||
///*
|
||||
for (int j = 0; j < cur_count / 2; j++)
|
||||
{
|
||||
std::swap(poly_begin[j], poly_begin[cur_count - j - 1]);
|
||||
std::swap(poly_begin_neis[j], poly_begin_neis[cur_count - j - 1]);
|
||||
|
||||
}
|
||||
//*/
|
||||
shift_left(poly_begin_neis, cur_count); //this is needed because the neis index edges not vertexes
|
||||
flip_neis_direction(poly_begin_neis, cur_count);
|
||||
}
|
||||
#endif // !REVERSE_DIRECTION
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "Shared/Include/SharedAssert.h"
|
||||
|
||||
static const unsigned RC_UNSET_HEIGHT = 0xffff;
|
||||
#define REVERSE_DIRECTION 1
|
||||
#define REVERSE_DIRECTION 1 // REVERSE_DIRECTION 0 is broken, 1 is producing correct results.
|
||||
|
||||
struct rcHeightPatch
|
||||
{
|
||||
@ -296,32 +296,13 @@ static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges,
|
||||
if (e == EV_UNDEF)
|
||||
{
|
||||
int* edge = &edges[nedges*4];
|
||||
edge[0] = s;
|
||||
edge[1] = t;
|
||||
edge[2] = l;
|
||||
edge[3] = r;
|
||||
return nedges++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EV_UNDEF;
|
||||
}
|
||||
}
|
||||
static int addEdgeFlipped(rcContext* ctx, int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r)
|
||||
{
|
||||
if (nedges >= maxEdges)
|
||||
{
|
||||
ctx->log(RC_LOG_ERROR, "addEdge: Too many edges (%d/%d).", nedges, maxEdges);
|
||||
return EV_UNDEF;
|
||||
}
|
||||
|
||||
// Add edge if not already in the triangulation.
|
||||
int e = findEdge(edges, nedges, s, t);
|
||||
if (e == EV_UNDEF)
|
||||
{
|
||||
int* edge = &edges[nedges * 4];
|
||||
#if REVERSE_DIRECTION
|
||||
edge[0] = t;
|
||||
edge[1] = s;
|
||||
#else
|
||||
edge[0] = s;
|
||||
edge[1] = t;
|
||||
#endif
|
||||
edge[2] = l;
|
||||
edge[3] = r;
|
||||
return nedges++;
|
||||
@ -464,10 +445,8 @@ static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges
|
||||
|
||||
#if REVERSE_DIRECTION
|
||||
#define updateFace updateRightFace
|
||||
#define addEdgeN addEdgeFlipped
|
||||
#else
|
||||
#define updateFace updateLeftFace
|
||||
#define addEdgeN addEdge
|
||||
#endif
|
||||
// Add new triangle or update edge info if s-t is on hull.
|
||||
if (pt < npts)
|
||||
@ -478,14 +457,14 @@ static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges
|
||||
// Add new edge or update face info of old edge.
|
||||
e = findEdge(edges, nedges, pt, s);
|
||||
if (e == EV_UNDEF)
|
||||
addEdgeN(ctx, edges, nedges, maxEdges, pt, s, nfaces, EV_UNDEF);
|
||||
addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, EV_UNDEF);
|
||||
else
|
||||
updateFace(&edges[e*4], pt, s, nfaces);
|
||||
|
||||
// Add new edge or update face info of old edge.
|
||||
e = findEdge(edges, nedges, t, pt);
|
||||
if (e == EV_UNDEF)
|
||||
addEdgeN(ctx, edges, nedges, maxEdges, t, pt, nfaces, EV_UNDEF);
|
||||
addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, EV_UNDEF);
|
||||
else
|
||||
updateFace(&edges[e*4], t, pt, nfaces);
|
||||
|
||||
@ -510,7 +489,7 @@ void delaunayHull(rcContext* ctx, const int npts, const float* pts,
|
||||
edges.resize(maxEdges*4);
|
||||
|
||||
for (int i = 0, j = nhull-1; i < nhull; j=i++)
|
||||
addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], EV_HULL, EV_UNDEF);
|
||||
addEdge(ctx, &edges[0], nedges, maxEdges, hull[i],hull[j], EV_HULL, EV_UNDEF);
|
||||
|
||||
int currentEdge = 0;
|
||||
while (currentEdge < nedges)
|
||||
@ -737,13 +716,19 @@ static void setTriFlags(rdIntArray& tris, int nhull, int* hull)
|
||||
{
|
||||
for (int i = 0; i < tris.size(); i += 4)
|
||||
{
|
||||
int a = tris[i + 0];
|
||||
int b = tris[i + 1];
|
||||
int c = tris[i + 2];
|
||||
int a = tris[i+0];
|
||||
int b = tris[i+1];
|
||||
int c = tris[i+2];
|
||||
unsigned short flags = 0;
|
||||
#if REVERSE_DIRECTION
|
||||
flags |= (onHull(a, c, nhull, hull) ? RD_DETAIL_EDGE_BOUNDARY : 0) << 0;
|
||||
flags |= (onHull(c, b, nhull, hull) ? RD_DETAIL_EDGE_BOUNDARY : 0) << 2;
|
||||
flags |= (onHull(b, a, nhull, hull) ? RD_DETAIL_EDGE_BOUNDARY : 0) << 4;
|
||||
#else
|
||||
flags |= (onHull(a, b, nhull, hull) ? RD_DETAIL_EDGE_BOUNDARY : 0) << 0;
|
||||
flags |= (onHull(b, c, nhull, hull) ? RD_DETAIL_EDGE_BOUNDARY : 0) << 2;
|
||||
flags |= (onHull(c, a, nhull, hull) ? RD_DETAIL_EDGE_BOUNDARY : 0) << 4;
|
||||
#endif
|
||||
tris[i + 3] = (int)flags;
|
||||
}
|
||||
}
|
||||
@ -1254,6 +1239,40 @@ static void getHeightData(rcContext* ctx, const rcCompactHeightfield& chf,
|
||||
}
|
||||
}
|
||||
|
||||
void flipPolyMeshDetail(rcPolyMeshDetail& mdetail, const int nverts)
|
||||
{
|
||||
for (int i = 0; i < mdetail.ntris; i++)
|
||||
{
|
||||
unsigned char* t = mdetail.tris + i * 4;
|
||||
bool skip = false;
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
// Vert is a poly vert not a detail vert, skip it.
|
||||
if (t[j] < nverts)
|
||||
{
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
rdSwap(t[0], t[2]);
|
||||
|
||||
// Flip tri flags.
|
||||
const unsigned char tf = t[3];
|
||||
|
||||
unsigned char flags = 0;
|
||||
flags |= ((tf >> 2) & 0b11) << 0;
|
||||
flags |= ((tf >> 0) & 0b11) << 2;
|
||||
flags |= ((tf >> 4) & 0b11) << 4;
|
||||
|
||||
t[3] = flags;
|
||||
}
|
||||
}
|
||||
|
||||
/// @par
|
||||
///
|
||||
/// See the #rcConfig documentation for more information on the configuration parameters.
|
||||
@ -1476,14 +1495,25 @@ bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompa
|
||||
{
|
||||
const int* t = &tris[j*4];
|
||||
|
||||
#if REVERSE_DIRECTION
|
||||
dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0];
|
||||
dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[2];
|
||||
dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[1];
|
||||
dmesh.tris[dmesh.ntris*4+3] = (unsigned char)t[3];
|
||||
#else
|
||||
dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0];
|
||||
dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[1];
|
||||
dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[2];
|
||||
dmesh.tris[dmesh.ntris*4+3] = (unsigned char)t[3];
|
||||
#endif // !REVERSE_DIRECTION
|
||||
dmesh.ntris++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef REVERSE_DIRECTION
|
||||
flipPolyMeshDetail(dmesh, mesh.nverts)
|
||||
#endif // !REVERSE_DIRECTION
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1563,30 +1593,3 @@ bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int
|
||||
|
||||
return true;
|
||||
}
|
||||
#if !REVERSE_DIRECTION
|
||||
static unsigned char flip_flags(unsigned char flags_in)
|
||||
{
|
||||
unsigned char flags = 0;
|
||||
flags |= ((flags_in >>2) & 0b11) << 0;
|
||||
flags |= ((flags_in >>0) & 0b11) << 2;
|
||||
flags |= ((flags_in >>4) & 0b11) << 4;
|
||||
return flags;
|
||||
}
|
||||
#endif // !REVERSE_DIRECTION
|
||||
void rcFlipPolyMeshDetail(rcPolyMeshDetail& /*mdetail*/,int /*poly_tris*/)
|
||||
{
|
||||
#if !REVERSE_DIRECTION
|
||||
for (int i = 0; i < mdetail.ntris; i++)
|
||||
{
|
||||
auto tri_begin = mdetail.tris + i * 4;
|
||||
bool skip = false;
|
||||
for (int j = 0; j < 3; j++)
|
||||
if (tri_begin[j] < poly_tris)
|
||||
skip = true;
|
||||
if (skip)
|
||||
continue;
|
||||
std::swap(tri_begin[0], tri_begin[2]);
|
||||
tri_begin[3]=flip_flags(tri_begin[3]);
|
||||
}
|
||||
#endif // !REVERSE_DIRECTION
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user