|
|
@ -10,15 +10,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
#define MAX_SEARCH_ITERATIONS 32
|
|
|
|
#define MAX_SEARCH_ITERATIONS 32
|
|
|
|
|
|
|
|
|
|
|
|
#define ADDITIONAL_EDGE_CAPACITY 64
|
|
|
|
#define ADDITIONAL_EDGE_CAPACITY 128
|
|
|
|
#define ADDITIONAL_VERTEX_CAPACITY 32
|
|
|
|
#define ADDITIONAL_VERTEX_CAPACITY 32
|
|
|
|
|
|
|
|
|
|
|
|
#define VERIFY_INTEGRITY 0
|
|
|
|
#define VERIFY_INTEGRITY 1
|
|
|
|
|
|
|
|
|
|
|
|
#define VERY_FAR_AWAY 1e15f
|
|
|
|
#define VERY_FAR_AWAY 1e15f
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceFindEnclosingFace(struct PortalSurface* surface, struct Vector2s16* aroundPoint, struct SurfaceEdgeWithSide* output) {
|
|
|
|
int portalSurfaceFindEnclosingFace(struct PortalSurface* surface, struct Vector2s16* aroundPoint) {
|
|
|
|
float minDistance = VERY_FAR_AWAY;
|
|
|
|
float minDistance = VERY_FAR_AWAY;
|
|
|
|
|
|
|
|
int result = -1;
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2 aroundPointF;
|
|
|
|
struct Vector2 aroundPointF;
|
|
|
|
|
|
|
|
|
|
|
@ -27,9 +28,16 @@ int portalSurfaceFindEnclosingFace(struct PortalSurface* surface, struct Vector2
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < surface->edgeCount; ++i) {
|
|
|
|
for (int i = 0; i < surface->edgeCount; ++i) {
|
|
|
|
struct SurfaceEdge* edge = &surface->edges[i];
|
|
|
|
struct SurfaceEdge* edge = &surface->edges[i];
|
|
|
|
|
|
|
|
struct SurfaceEdge* nextEdge = &surface->edges[edge->nextEdge];
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* as16 = &surface->vertices[edge->aIndex];
|
|
|
|
if (edge->reverseEdge != -1 && edge->pointIndex > nextEdge->pointIndex) {
|
|
|
|
struct Vector2s16* bs16 = &surface->vertices[edge->bIndex];
|
|
|
|
// to avoid redundant calcuations only check
|
|
|
|
|
|
|
|
// each pair of vertcies once
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* as16 = &surface->vertices[edge->pointIndex];
|
|
|
|
|
|
|
|
struct Vector2s16* bs16 = &surface->vertices[nextEdge->pointIndex];
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2 a;
|
|
|
|
struct Vector2 a;
|
|
|
|
struct Vector2 b;
|
|
|
|
struct Vector2 b;
|
|
|
@ -66,13 +74,11 @@ int portalSurfaceFindEnclosingFace(struct PortalSurface* surface, struct Vector2
|
|
|
|
|
|
|
|
|
|
|
|
if (distSqr < minDistance) {
|
|
|
|
if (distSqr < minDistance) {
|
|
|
|
minDistance = distSqr;
|
|
|
|
minDistance = distSqr;
|
|
|
|
|
|
|
|
result = vector2Cross(&edgeOffset, &pointOffset) < 0.0f ? edge->reverseEdge : i;
|
|
|
|
output->edgeIndex = i;
|
|
|
|
|
|
|
|
output->isReverse = vector2Cross(&edgeOffset, &pointOffset) < 0.0f;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return minDistance != VERY_FAR_AWAY;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* portalSurfaceGetEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
|
|
|
struct SurfaceEdge* portalSurfaceGetEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
|
|
@ -83,48 +89,33 @@ struct Vector2s16* portalSurfaceGetVertex(struct PortalSurfaceBuilder* surfaceBu
|
|
|
|
return &surfaceBuilder->vertices[vertexIndex];
|
|
|
|
return &surfaceBuilder->vertices[vertexIndex];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void portalSurfaceNextEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge, struct SurfaceEdgeWithSide* nextEdge) {
|
|
|
|
int portalSurfaceNextEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge->edgeIndex);
|
|
|
|
return surfaceBuilder->edges[edgeIndex].nextEdge;
|
|
|
|
int edgeIndex = currentEdge->edgeIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nextEdge->edgeIndex = SB_GET_NEXT_EDGE(edge, currentEdge->isReverse);
|
|
|
|
|
|
|
|
nextEdge->isReverse = portalSurfaceGetEdge(surfaceBuilder, nextEdge->edgeIndex)->prevEdgeReverse == edgeIndex;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void portalSurfacePrevEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge, struct SurfaceEdgeWithSide* prevEdge) {
|
|
|
|
int portalSurfaceNextPoint(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge->edgeIndex);
|
|
|
|
return surfaceBuilder->edges[surfaceBuilder->edges[edgeIndex].nextEdge].pointIndex;
|
|
|
|
int edgeIndex = currentEdge->edgeIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
prevEdge->edgeIndex = SB_GET_PREV_EDGE(edge, currentEdge->isReverse);
|
|
|
|
int portalSurfacePrevEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
|
|
|
prevEdge->isReverse = portalSurfaceGetEdge(surfaceBuilder, prevEdge->edgeIndex)->nextEdgeReverse == edgeIndex;
|
|
|
|
return surfaceBuilder->edges[edgeIndex].prevEdge;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceReverseEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex) {
|
|
|
|
|
|
|
|
return surfaceBuilder->edges[edgeIndex].reverseEdge;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if VERIFY_INTEGRITY
|
|
|
|
#if VERIFY_INTEGRITY
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceIsWellFormed(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
int portalSurfaceIsWellFormed(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
|
|
|
|
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
|
|
|
|
struct SurfaceEdgeWithSide current;
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, i);
|
|
|
|
current.edgeIndex = i;
|
|
|
|
struct SurfaceEdge* next = portalSurfaceGetEdge(surfaceBuilder, edge->nextEdge);
|
|
|
|
|
|
|
|
struct SurfaceEdge* prev = portalSurfaceGetEdge(surfaceBuilder, edge->prevEdge);
|
|
|
|
for (current.isReverse = 0; current.isReverse < 2; ++current.isReverse) {
|
|
|
|
struct SurfaceEdge* reverse = edge->reverseEdge == -1 ? NULL : portalSurfaceGetEdge(surfaceBuilder, edge->reverseEdge);
|
|
|
|
if (current.isReverse && portalSurfaceGetEdge(surfaceBuilder, i)->nextEdgeReverse == NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide check;
|
|
|
|
if (next->prevEdge != i || prev->nextEdge != i || (reverse != NULL && reverse->reverseEdge != i)) {
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, ¤t, &check);
|
|
|
|
return 0;
|
|
|
|
struct SurfaceEdge* checkPtr = portalSurfaceGetEdge(surfaceBuilder, check.edgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (checkPtr->prevEdge != i && checkPtr->prevEdgeReverse != i) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, ¤t, &check);
|
|
|
|
|
|
|
|
checkPtr = portalSurfaceGetEdge(surfaceBuilder, check.edgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (checkPtr->nextEdge != i && checkPtr->nextEdgeReverse != i) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -133,16 +124,15 @@ int portalSurfaceIsWellFormed(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfacePointInsideFace(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge, struct Vector2s16* point) {
|
|
|
|
int portalSurfacePointInsideFace(struct PortalSurfaceBuilder* surfaceBuilder, int currentEdge, struct Vector2s16* point) {
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, currentEdge, &nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* edgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge->edgeIndex);
|
|
|
|
struct SurfaceEdge* edgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* corner = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(edgePtr, currentEdge->isReverse));
|
|
|
|
struct Vector2s16* corner = portalSurfaceGetVertex(surfaceBuilder, nextEdgePtr->pointIndex);
|
|
|
|
struct Vector2s16* prevPoint = portalSurfaceGetVertex(surfaceBuilder, SB_GET_CURRENT_POINT(edgePtr, currentEdge->isReverse));
|
|
|
|
struct Vector2s16* prevPoint = portalSurfaceGetVertex(surfaceBuilder, edgePtr->pointIndex);
|
|
|
|
struct Vector2s16* nextPoint = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(nextEdgePtr, nextEdge.isReverse));
|
|
|
|
struct Vector2s16* nextPoint = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, nextEdgePtr->nextEdge)->pointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16 nextDir;
|
|
|
|
struct Vector2s16 nextDir;
|
|
|
|
struct Vector2s16 prevDir;
|
|
|
|
struct Vector2s16 prevDir;
|
|
|
@ -156,57 +146,54 @@ int portalSurfacePointInsideFace(struct PortalSurfaceBuilder* surfaceBuilder, st
|
|
|
|
return vector2s16FallsBetween(&nextDir, &prevDir, &pointDir);
|
|
|
|
return vector2s16FallsBetween(&nextDir, &prevDir, &pointDir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceIsEdgeValid(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge) {
|
|
|
|
int portalSurfaceIsEdgeValid(struct PortalSurfaceBuilder* surfaceBuilder, int currentEdge) {
|
|
|
|
return SB_GET_NEXT_EDGE(portalSurfaceGetEdge(surfaceBuilder, currentEdge->edgeIndex), currentEdge->isReverse) != NO_EDGE_CONNECTION;
|
|
|
|
return surfaceBuilder->edges[currentEdge].nextEdge != NO_EDGE_CONNECTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceNextLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* currentEdge, struct SurfaceEdgeWithSide* nextFace) {
|
|
|
|
// Steps to the next surface around a vertex
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, currentEdge, nextFace);
|
|
|
|
int portalSurfaceNextLoop(struct PortalSurfaceBuilder* surfaceBuilder, int currentEdge) {
|
|
|
|
nextFace->isReverse = !nextFace->isReverse;
|
|
|
|
int nextFace = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
nextFace = portalSurfaceReverseEdge(surfaceBuilder, nextFace);
|
|
|
|
|
|
|
|
|
|
|
|
if (portalSurfaceIsEdgeValid(surfaceBuilder, nextFace)) {
|
|
|
|
if (nextFace != NO_EDGE_CONNECTION) {
|
|
|
|
return 1;
|
|
|
|
return nextFace;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*nextFace = *currentEdge;
|
|
|
|
// hit the edge, the next surface is all the way back
|
|
|
|
nextFace->isReverse = !nextFace->isReverse;
|
|
|
|
nextFace = portalSurfaceReverseEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (i < MAX_SEARCH_ITERATIONS && portalSurfaceIsEdgeValid(surfaceBuilder, nextFace)) {
|
|
|
|
while (i < MAX_SEARCH_ITERATIONS && portalSurfaceReverseEdge(surfaceBuilder, currentEdge) != NO_EDGE_CONNECTION) {
|
|
|
|
struct SurfaceEdgeWithSide prevFace;
|
|
|
|
currentEdge = portalSurfaceReverseEdge(surfaceBuilder, currentEdge);
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, nextFace, &prevFace);
|
|
|
|
currentEdge = portalSurfacePrevEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
*nextFace = prevFace;
|
|
|
|
|
|
|
|
nextFace->isReverse = !nextFace->isReverse;
|
|
|
|
|
|
|
|
++i;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nextFace->isReverse = !nextFace->isReverse;
|
|
|
|
return i < MAX_SEARCH_ITERATIONS ? currentEdge : NO_EDGE_CONNECTION;
|
|
|
|
|
|
|
|
|
|
|
|
return i < MAX_SEARCH_ITERATIONS;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceFindCurrentFace(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* forPoint, struct SurfaceEdgeWithSide* edgeToAdjust) {
|
|
|
|
// Find the edge with the associated triangle that contain the point forPoint around a vertex
|
|
|
|
|
|
|
|
int portalSurfaceFindCurrentFace(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* forPoint, int currentEdge) {
|
|
|
|
int i = 0;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (i < MAX_SEARCH_ITERATIONS && !portalSurfacePointInsideFace(surfaceBuilder, edgeToAdjust, forPoint)) {
|
|
|
|
while (i < MAX_SEARCH_ITERATIONS && !portalSurfacePointInsideFace(surfaceBuilder, currentEdge, forPoint)) {
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = portalSurfaceNextLoop(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceNextLoop(surfaceBuilder, edgeToAdjust, &nextEdge)) {
|
|
|
|
if (nextEdge == NO_EDGE_CONNECTION) {
|
|
|
|
return 0;
|
|
|
|
return NO_EDGE_CONNECTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (i != 0 && edgeToAdjust->edgeIndex == surfaceBuilder->edgeOnSearchLoop.edgeIndex) {
|
|
|
|
if (i != 0 && currentEdge == surfaceBuilder->edgeOnSearchLoop) {
|
|
|
|
// a full loop and no face found
|
|
|
|
// a full loop and no face found
|
|
|
|
return 0;
|
|
|
|
return NO_EDGE_CONNECTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*edgeToAdjust = nextEdge;
|
|
|
|
currentEdge = nextEdge;
|
|
|
|
++i;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return i < MAX_SEARCH_ITERATIONS;
|
|
|
|
return i < MAX_SEARCH_ITERATIONS ? currentEdge : NO_EDGE_CONNECTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceFindNextLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* forPoint) {
|
|
|
|
int portalSurfaceFindNextLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* forPoint) {
|
|
|
@ -214,17 +201,19 @@ int portalSurfaceFindNextLoop(struct PortalSurfaceBuilder* surfaceBuilder, struc
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
|
|
|
int currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
|
|
|
|
|
|
|
|
|
|
|
int nextIndex = SB_GET_NEXT_EDGE(portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->cuttingEdge.edgeIndex), surfaceBuilder->cuttingEdge.isReverse);
|
|
|
|
int nextIndex = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->cuttingEdge)->nextEdge;
|
|
|
|
|
|
|
|
|
|
|
|
// the cutting edge is its own next edge
|
|
|
|
// the cutting edge is its own next edge
|
|
|
|
// this means edgeOnSearchLoop will already be correct
|
|
|
|
// this means edgeOnSearchLoop will already be correct
|
|
|
|
if (nextIndex == surfaceBuilder->cuttingEdge.edgeIndex) {
|
|
|
|
if (nextIndex == surfaceBuilder->cuttingEdge) {
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceFindCurrentFace(surfaceBuilder, forPoint, ¤tEdge)) {
|
|
|
|
currentEdge = portalSurfaceFindCurrentFace(surfaceBuilder, forPoint, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (currentEdge == NO_EDGE_CONNECTION) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -333,13 +322,13 @@ int portalSurfaceNewVertex(struct PortalSurfaceBuilder* surfaceBuilder, struct V
|
|
|
|
return newVertexIndex;
|
|
|
|
return newVertexIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceNewEdge(struct PortalSurfaceBuilder* surfaceBuilder, int isLoopEdge, struct OriginalEdgeMapping* originalEdge) {
|
|
|
|
int portalSurfaceNewEdge(struct PortalSurfaceBuilder* surfaceBuilder, int isLoopEdge, int originalEdge) {
|
|
|
|
while (surfaceBuilder->checkForEdgeReuse < surfaceBuilder->currentEdge) {
|
|
|
|
while (surfaceBuilder->checkForEdgeReuse < surfaceBuilder->currentEdge) {
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->checkForEdgeReuse);
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->checkForEdgeReuse);
|
|
|
|
|
|
|
|
|
|
|
|
if (edge->nextEdge == NO_EDGE_CONNECTION && edge->nextEdgeReverse == NO_EDGE_CONNECTION) {
|
|
|
|
if (edge->nextEdge == NO_EDGE_CONNECTION) {
|
|
|
|
surfaceBuilder->isLoopEdge[surfaceBuilder->checkForEdgeReuse] = isLoopEdge;
|
|
|
|
surfaceBuilder->isLoopEdge[surfaceBuilder->checkForEdgeReuse] = isLoopEdge;
|
|
|
|
surfaceBuilder->originalEdgeIndex[surfaceBuilder->checkForEdgeReuse] = *originalEdge;
|
|
|
|
surfaceBuilder->originalEdgeIndex[surfaceBuilder->checkForEdgeReuse] = originalEdge;
|
|
|
|
|
|
|
|
|
|
|
|
return surfaceBuilder->checkForEdgeReuse;
|
|
|
|
return surfaceBuilder->checkForEdgeReuse;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -353,7 +342,7 @@ int portalSurfaceNewEdge(struct PortalSurfaceBuilder* surfaceBuilder, int isLoop
|
|
|
|
|
|
|
|
|
|
|
|
int newEdgeIndex = surfaceBuilder->currentEdge;
|
|
|
|
int newEdgeIndex = surfaceBuilder->currentEdge;
|
|
|
|
surfaceBuilder->isLoopEdge[surfaceBuilder->currentEdge] = isLoopEdge;
|
|
|
|
surfaceBuilder->isLoopEdge[surfaceBuilder->currentEdge] = isLoopEdge;
|
|
|
|
surfaceBuilder->originalEdgeIndex[newEdgeIndex] = *originalEdge;
|
|
|
|
surfaceBuilder->originalEdgeIndex[newEdgeIndex] = originalEdge;
|
|
|
|
++surfaceBuilder->currentEdge;
|
|
|
|
++surfaceBuilder->currentEdge;
|
|
|
|
++surfaceBuilder->checkForEdgeReuse;
|
|
|
|
++surfaceBuilder->checkForEdgeReuse;
|
|
|
|
return newEdgeIndex;
|
|
|
|
return newEdgeIndex;
|
|
|
@ -399,21 +388,17 @@ void portalSurfaceLerpVtx(struct PortalSurfaceBuilder* surfaceBuilder, int aInde
|
|
|
|
result->v.cn[3] = (short)mathfLerp(a->v.cn[3], b->v.cn[3], lerp);
|
|
|
|
result->v.cn[3] = (short)mathfLerp(a->v.cn[3], b->v.cn[3], lerp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void portalSurfaceCalcVertex(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* loopEdge, int resultIndex) {
|
|
|
|
void portalSurfaceCalcVertex(struct PortalSurfaceBuilder* surfaceBuilder, int loopEdge, int resultIndex) {
|
|
|
|
struct SurfaceEdgeWithSide originalEdge;
|
|
|
|
int originalEdge = surfaceBuilder->originalEdgeIndex[loopEdge];
|
|
|
|
struct OriginalEdgeMapping originalEdgeMapping = surfaceBuilder->originalEdgeIndex[loopEdge->edgeIndex];
|
|
|
|
|
|
|
|
SB_ORIGINAL_EDGE_TO_EDGE_WITH_SIDE(loopEdge->isReverse ? originalEdgeMapping.originalEdgeReverse : originalEdgeMapping.originalEdge, &originalEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* originalEdgePtr = &surfaceBuilder->original->edges[originalEdge.edgeIndex];
|
|
|
|
struct SurfaceEdge* originalEdgePtr = &surfaceBuilder->original->edges[originalEdge];
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = originalEdgePtr->nextEdge;
|
|
|
|
nextEdge.edgeIndex = SB_GET_NEXT_EDGE(originalEdgePtr, originalEdge.isReverse);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* nextEdgePtr = &surfaceBuilder->original->edges[nextEdge.edgeIndex];
|
|
|
|
struct SurfaceEdge* nextEdgePtr = &surfaceBuilder->original->edges[nextEdge];
|
|
|
|
nextEdge.isReverse = nextEdgePtr->prevEdgeReverse == originalEdge.edgeIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int aIndex = SB_GET_CURRENT_POINT(originalEdgePtr, originalEdge.isReverse);
|
|
|
|
int aIndex = originalEdgePtr->pointIndex;
|
|
|
|
int bIndex = SB_GET_NEXT_POINT(originalEdgePtr, originalEdge.isReverse);
|
|
|
|
int bIndex = nextEdgePtr->pointIndex;
|
|
|
|
int cIndex = SB_GET_NEXT_POINT(nextEdgePtr, nextEdge.isReverse);
|
|
|
|
int cIndex = surfaceBuilder->original->edges[nextEdgePtr->nextEdge].pointIndex;
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector3 barycentericCoords;
|
|
|
|
struct Vector3 barycentericCoords;
|
|
|
|
|
|
|
|
|
|
|
@ -445,134 +430,146 @@ void portalSurfaceCalcVertex(struct PortalSurfaceBuilder* surfaceBuilder, struct
|
|
|
|
result->v.cn[3] = (short)vector3EvalBarycentric1D(&barycentericCoords, a->v.cn[3], b->v.cn[3], c->v.cn[3]);
|
|
|
|
result->v.cn[3] = (short)vector3EvalBarycentric1D(&barycentericCoords, a->v.cn[3], b->v.cn[3], c->v.cn[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edge, struct Vector2s16* point) {
|
|
|
|
int portalSurfaceSplitEdgeWithVertex(struct PortalSurfaceBuilder* surfaceBuilder, int edge, int newVertexIndex) {
|
|
|
|
|
|
|
|
struct SurfaceEdge* existingEdge = portalSurfaceGetEdge(surfaceBuilder, edge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int newEdgeIndex = portalSurfaceNewEdge(surfaceBuilder, 0, surfaceBuilder->originalEdgeIndex[edge]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (newEdgeIndex == -1) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* newEdge = portalSurfaceGetEdge(surfaceBuilder, newEdgeIndex);
|
|
|
|
|
|
|
|
newEdge->pointIndex = newVertexIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int newReverseEdgeIndex = NO_EDGE_CONNECTION;
|
|
|
|
|
|
|
|
struct SurfaceEdge* newReverseEdge = NULL;
|
|
|
|
|
|
|
|
struct SurfaceEdge* existingReverseEdge = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (existingEdge->reverseEdge != NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
newReverseEdgeIndex = portalSurfaceNewEdge(surfaceBuilder, 0, surfaceBuilder->originalEdgeIndex[existingEdge->reverseEdge]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (newReverseEdgeIndex == -1) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newReverseEdge = portalSurfaceGetEdge(surfaceBuilder, newReverseEdgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newEdge->reverseEdge = newReverseEdgeIndex;
|
|
|
|
|
|
|
|
newReverseEdge->reverseEdge = newEdgeIndex;
|
|
|
|
|
|
|
|
newReverseEdge->pointIndex = newVertexIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
existingReverseEdge = portalSurfaceGetEdge(surfaceBuilder, existingEdge->reverseEdge);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
newEdge->reverseEdge = NO_EDGE_CONNECTION;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newEdge->nextEdge = existingEdge->nextEdge;
|
|
|
|
|
|
|
|
newEdge->prevEdge = edge;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
existingEdge->nextEdge = newEdgeIndex;
|
|
|
|
|
|
|
|
portalSurfaceGetEdge(surfaceBuilder, newEdge->nextEdge)->prevEdge = newEdgeIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (newReverseEdge) {
|
|
|
|
|
|
|
|
newReverseEdge->nextEdge = existingReverseEdge->nextEdge;
|
|
|
|
|
|
|
|
newReverseEdge->prevEdge = existingEdge->reverseEdge;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
existingReverseEdge->nextEdge = newReverseEdgeIndex;
|
|
|
|
|
|
|
|
portalSurfaceGetEdge(surfaceBuilder, newReverseEdge->nextEdge)->prevEdge = newReverseEdgeIndex;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edge, struct Vector2s16* point) {
|
|
|
|
int newVertexIndex = portalSurfaceNewVertex(surfaceBuilder, point);
|
|
|
|
int newVertexIndex = portalSurfaceNewVertex(surfaceBuilder, point);
|
|
|
|
|
|
|
|
|
|
|
|
if (newVertexIndex == -1) {
|
|
|
|
if (newVertexIndex == -1) {
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* existingEdge = portalSurfaceGetEdge(surfaceBuilder, edge->edgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
struct SurfaceEdge* existingEdge = portalSurfaceGetEdge(surfaceBuilder, edge);
|
|
|
|
struct SurfaceEdgeWithSide prevReverseEdge;
|
|
|
|
struct SurfaceEdge* nextExistingEdge = portalSurfaceGetEdge(surfaceBuilder, existingEdge->nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
int hasReverseEdge = existingEdge->nextEdgeReverse != NO_EDGE_CONNECTION;
|
|
|
|
portalSurfaceLerpVtx(surfaceBuilder, existingEdge->pointIndex, nextExistingEdge->pointIndex, newVertexIndex);
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, edge, &nextEdge);
|
|
|
|
if (!portalSurfaceSplitEdgeWithVertex(surfaceBuilder, edge, newVertexIndex)) {
|
|
|
|
|
|
|
|
|
|
|
|
if (hasReverseEdge) {
|
|
|
|
|
|
|
|
prevReverseEdge = *edge;
|
|
|
|
|
|
|
|
prevReverseEdge.isReverse = !prevReverseEdge.isReverse;
|
|
|
|
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, &prevReverseEdge, &prevReverseEdge);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int newEdgeIndex = portalSurfaceNewEdge(surfaceBuilder, 0, &surfaceBuilder->originalEdgeIndex[edge->edgeIndex]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (newEdgeIndex == -1) {
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceLerpVtx(surfaceBuilder, SB_GET_CURRENT_POINT(existingEdge, edge->isReverse), SB_GET_NEXT_POINT(existingEdge, edge->isReverse), newVertexIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* newEdge = portalSurfaceGetEdge(surfaceBuilder, newEdgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_NEXT_POINT(newEdge, edge->isReverse, SB_GET_NEXT_POINT(existingEdge, edge->isReverse));
|
|
|
|
|
|
|
|
SB_SET_CURRENT_POINT(newEdge, edge->isReverse, newVertexIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_NEXT_EDGE(newEdge, edge->isReverse, SB_GET_NEXT_EDGE(existingEdge, edge->isReverse));
|
|
|
|
|
|
|
|
SB_SET_PREV_EDGE(newEdge, edge->isReverse, edge->edgeIndex);
|
|
|
|
|
|
|
|
SB_SET_NEXT_EDGE(newEdge, !edge->isReverse, hasReverseEdge ? edge->edgeIndex : NO_EDGE_CONNECTION);
|
|
|
|
|
|
|
|
SB_SET_PREV_EDGE(newEdge, !edge->isReverse, hasReverseEdge ? SB_GET_PREV_EDGE(existingEdge, !edge->isReverse) : NO_EDGE_CONNECTION);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_NEXT_POINT(existingEdge, edge->isReverse, newVertexIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_NEXT_EDGE(existingEdge, edge->isReverse, newEdgeIndex);
|
|
|
|
|
|
|
|
if (hasReverseEdge) {
|
|
|
|
|
|
|
|
SB_SET_PREV_EDGE(existingEdge, !edge->isReverse, newEdgeIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_PREV_EDGE(nextEdgePtr, nextEdge.isReverse, newEdgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (hasReverseEdge) {
|
|
|
|
|
|
|
|
struct SurfaceEdge* prevEdgePtr = portalSurfaceGetEdge(surfaceBuilder, prevReverseEdge.edgeIndex);
|
|
|
|
|
|
|
|
SB_SET_NEXT_EDGE(prevEdgePtr, prevReverseEdge.isReverse, newEdgeIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if VERIFY_INTEGRITY
|
|
|
|
#if VERIFY_INTEGRITY
|
|
|
|
if (!portalSurfaceIsWellFormed(surfaceBuilder)) {
|
|
|
|
if (!portalSurfaceIsWellFormed(surfaceBuilder)) {
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return newVertexIndex;
|
|
|
|
return newVertexIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceConnectToPoint(struct PortalSurfaceBuilder* surfaceBuilder, int pointIndex, struct SurfaceEdgeWithSide* edge, int isLoopEdge) {
|
|
|
|
int portalSurfaceConnectToPoint(struct PortalSurfaceBuilder* surfaceBuilder, int pointIndex, int edgeIndex, int isLoopEdge) {
|
|
|
|
struct OriginalEdgeMapping originalEdge = surfaceBuilder->originalEdgeIndex[surfaceBuilder->edgeOnSearchLoop.edgeIndex];
|
|
|
|
int originalEdge = surfaceBuilder->originalEdgeIndex[surfaceBuilder->edgeOnSearchLoop];
|
|
|
|
|
|
|
|
|
|
|
|
if (surfaceBuilder->edgeOnSearchLoop.isReverse) {
|
|
|
|
int newEdge = portalSurfaceNewEdge(surfaceBuilder, isLoopEdge, originalEdge);
|
|
|
|
originalEdge.originalEdge = originalEdge.originalEdgeReverse;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (newEdge == -1) {
|
|
|
|
originalEdge.originalEdgeReverse = originalEdge.originalEdge;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int newEdge = portalSurfaceNewEdge(surfaceBuilder, isLoopEdge, &originalEdge);
|
|
|
|
int newReverseEdge = portalSurfaceNewEdge(surfaceBuilder, isLoopEdge, originalEdge);
|
|
|
|
|
|
|
|
|
|
|
|
if (newEdge == -1) {
|
|
|
|
if (newEdge == -1) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* newEdgePtr = portalSurfaceGetEdge(surfaceBuilder, newEdge);
|
|
|
|
struct SurfaceEdge* newEdgePtr = portalSurfaceGetEdge(surfaceBuilder, newEdge);
|
|
|
|
|
|
|
|
struct SurfaceEdge* newReverseEdgePtr = portalSurfaceGetEdge(surfaceBuilder, newReverseEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
newEdgePtr->reverseEdge = newReverseEdge;
|
|
|
|
|
|
|
|
newReverseEdgePtr->reverseEdge = newEdge;
|
|
|
|
|
|
|
|
|
|
|
|
if (surfaceBuilder->hasEdge) {
|
|
|
|
if (surfaceBuilder->hasEdge) {
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = portalSurfaceNextEdge(surfaceBuilder, surfaceBuilder->cuttingEdge);
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, &surfaceBuilder->cuttingEdge, &nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* cuttingEdgePtr = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->cuttingEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* cuttingEdgePtr = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->cuttingEdge);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
newEdgePtr->aIndex = SB_GET_NEXT_POINT(cuttingEdgePtr, surfaceBuilder->cuttingEdge.isReverse);
|
|
|
|
newEdgePtr->pointIndex = nextEdgePtr->pointIndex;
|
|
|
|
|
|
|
|
|
|
|
|
newEdgePtr->prevEdge = surfaceBuilder->cuttingEdge.edgeIndex;
|
|
|
|
newEdgePtr->prevEdge = surfaceBuilder->cuttingEdge;
|
|
|
|
newEdgePtr->nextEdgeReverse = nextEdge.edgeIndex;
|
|
|
|
newReverseEdgePtr->nextEdge = nextEdge;
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_NEXT_EDGE(cuttingEdgePtr, surfaceBuilder->cuttingEdge.isReverse, newEdge);
|
|
|
|
cuttingEdgePtr->nextEdge = newEdge;
|
|
|
|
SB_SET_PREV_EDGE(nextEdgePtr, nextEdge.isReverse, newEdge);
|
|
|
|
nextEdgePtr->prevEdge = newReverseEdge;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
newEdgePtr->prevEdge = newEdge;
|
|
|
|
newEdgePtr->prevEdge = newReverseEdge;
|
|
|
|
newEdgePtr->nextEdgeReverse = newEdge;
|
|
|
|
newReverseEdgePtr->nextEdge = newEdge;
|
|
|
|
newEdgePtr->aIndex = surfaceBuilder->startingPoint;
|
|
|
|
newEdgePtr->pointIndex = surfaceBuilder->startingPoint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
newEdgePtr->bIndex = pointIndex;
|
|
|
|
newReverseEdgePtr->pointIndex = pointIndex;
|
|
|
|
|
|
|
|
|
|
|
|
if (edge) {
|
|
|
|
if (edgeIndex != NO_EDGE_CONNECTION) {
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = portalSurfaceNextEdge(surfaceBuilder, edgeIndex);
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, edge, &nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* edgePtr = portalSurfaceGetEdge(surfaceBuilder, edge->edgeIndex);
|
|
|
|
struct SurfaceEdge* edgePtr = portalSurfaceGetEdge(surfaceBuilder, edgeIndex);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
newEdgePtr->nextEdge = nextEdge.edgeIndex;
|
|
|
|
newEdgePtr->nextEdge = nextEdge;
|
|
|
|
newEdgePtr->prevEdgeReverse = edge->edgeIndex;
|
|
|
|
newReverseEdgePtr->prevEdge = edgeIndex;
|
|
|
|
|
|
|
|
|
|
|
|
SB_SET_NEXT_EDGE(edgePtr, edge->isReverse, newEdge);
|
|
|
|
edgePtr->nextEdge = newReverseEdge;
|
|
|
|
SB_SET_PREV_EDGE(nextEdgePtr, nextEdge.isReverse, newEdge);
|
|
|
|
nextEdgePtr->prevEdge = newEdge;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
newEdgePtr->nextEdge = newEdge;
|
|
|
|
newEdgePtr->nextEdge = newReverseEdge;
|
|
|
|
newEdgePtr->prevEdgeReverse = newEdge;
|
|
|
|
newReverseEdgePtr->prevEdge = newEdge;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
surfaceBuilder->hasEdge = 1;
|
|
|
|
surfaceBuilder->hasEdge = 1;
|
|
|
|
surfaceBuilder->cuttingEdge.edgeIndex = newEdge;
|
|
|
|
surfaceBuilder->cuttingEdge = newEdge;
|
|
|
|
surfaceBuilder->cuttingEdge.isReverse = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if VERIFY_INTEGRITY
|
|
|
|
#if VERIFY_INTEGRITY
|
|
|
|
if (!portalSurfaceIsWellFormed(surfaceBuilder)) {
|
|
|
|
if (!portalSurfaceIsWellFormed(surfaceBuilder)) {
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
@ -582,7 +579,7 @@ int portalSurfaceConnectToPoint(struct PortalSurfaceBuilder* surfaceBuilder, int
|
|
|
|
#define COLLAPSE_DISTANCE 8
|
|
|
|
#define COLLAPSE_DISTANCE 8
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* pointA, struct Vector2s16* pointB, int isFinalPoint) {
|
|
|
|
struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* pointA, struct Vector2s16* pointB, int isFinalPoint) {
|
|
|
|
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
|
|
|
int currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16 pointDir;
|
|
|
|
struct Vector2s16 pointDir;
|
|
|
|
vector2s16Sub(pointB, pointA, &pointDir);
|
|
|
|
vector2s16Sub(pointB, pointA, &pointDir);
|
|
|
@ -592,27 +589,24 @@ struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilde
|
|
|
|
for (iteration = 0;
|
|
|
|
for (iteration = 0;
|
|
|
|
iteration < MAX_INTERSECT_LOOPS && (
|
|
|
|
iteration < MAX_INTERSECT_LOOPS && (
|
|
|
|
iteration == 0 ||
|
|
|
|
iteration == 0 ||
|
|
|
|
currentEdge.edgeIndex != surfaceBuilder->edgeOnSearchLoop.edgeIndex ||
|
|
|
|
currentEdge != surfaceBuilder->edgeOnSearchLoop
|
|
|
|
currentEdge.isReverse != surfaceBuilder->edgeOnSearchLoop.isReverse
|
|
|
|
); (currentEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge)), ++iteration) {
|
|
|
|
); portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, ¤tEdge), ++iteration) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!isFinalPoint && surfaceBuilder->isLoopEdge[currentEdge.edgeIndex]) {
|
|
|
|
if (!isFinalPoint && surfaceBuilder->isLoopEdge[currentEdge]) {
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* edgeA = portalSurfaceGetVertex(surfaceBuilder, SB_GET_CURRENT_POINT(edge, currentEdge.isReverse));
|
|
|
|
int nextPointIndex = surfaceBuilder->edges[edge->nextEdge].pointIndex;
|
|
|
|
struct Vector2s16* edgeB = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(edge, currentEdge.isReverse));
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* edgeA = portalSurfaceGetVertex(surfaceBuilder, edge->pointIndex);
|
|
|
|
|
|
|
|
struct Vector2s16* edgeB = portalSurfaceGetVertex(surfaceBuilder, nextPointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16 intersectionPoint;
|
|
|
|
struct Vector2s16 intersectionPoint;
|
|
|
|
|
|
|
|
|
|
|
|
enum IntersectionType intersectType = portalSurfaceIntersect(pointA, &pointDir, edgeA, edgeB, &intersectionPoint);
|
|
|
|
enum IntersectionType intersectType = portalSurfaceIntersect(pointA, &pointDir, edgeA, edgeB, &intersectionPoint);
|
|
|
|
|
|
|
|
|
|
|
|
if (intersectionPoint.equalTest == pointA->equalTest) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (intersectType == IntersectionTypePoint) {
|
|
|
|
if (intersectType == IntersectionTypePoint) {
|
|
|
|
int newPointIndex;
|
|
|
|
int newPointIndex;
|
|
|
|
|
|
|
|
|
|
|
@ -625,20 +619,28 @@ struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilde
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (intersectionPoint.equalTest == edgeA->equalTest) {
|
|
|
|
if (intersectionPoint.equalTest == edgeA->equalTest) {
|
|
|
|
newPointIndex = SB_GET_CURRENT_POINT(edge, currentEdge.isReverse);
|
|
|
|
newPointIndex = edge->pointIndex;
|
|
|
|
portalSurfaceFindCurrentFace(surfaceBuilder, pointA, ¤tEdge);
|
|
|
|
currentEdge = portalSurfaceFindCurrentFace(surfaceBuilder, pointA, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (currentEdge == NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
} else if (intersectionPoint.equalTest == edgeB->equalTest) {
|
|
|
|
} else if (intersectionPoint.equalTest == edgeB->equalTest) {
|
|
|
|
newPointIndex = SB_GET_NEXT_POINT(edge, currentEdge.isReverse);
|
|
|
|
newPointIndex = nextPointIndex;
|
|
|
|
portalSurfaceFindCurrentFace(surfaceBuilder, pointA, ¤tEdge);
|
|
|
|
currentEdge = portalSurfaceFindCurrentFace(surfaceBuilder, pointA, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (currentEdge == NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
newPointIndex = portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, &intersectionPoint);
|
|
|
|
newPointIndex = portalSurfaceSplitEdge(surfaceBuilder, currentEdge, &intersectionPoint);
|
|
|
|
|
|
|
|
|
|
|
|
if (newPointIndex == -1) {
|
|
|
|
if (newPointIndex == -1) {
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceConnectToPoint(surfaceBuilder, newPointIndex, ¤tEdge, 1)) {
|
|
|
|
if (!portalSurfaceConnectToPoint(surfaceBuilder, newPointIndex, currentEdge, 1)) {
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -650,13 +652,13 @@ struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilde
|
|
|
|
int newPointIndex;
|
|
|
|
int newPointIndex;
|
|
|
|
|
|
|
|
|
|
|
|
if (intersectionPoint.equalTest == edgeA->equalTest) {
|
|
|
|
if (intersectionPoint.equalTest == edgeA->equalTest) {
|
|
|
|
newPointIndex = SB_GET_CURRENT_POINT(edge, currentEdge.isReverse);
|
|
|
|
newPointIndex = edge->pointIndex;
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, ¤tEdge, &surfaceBuilder->cuttingEdge);
|
|
|
|
surfaceBuilder->cuttingEdge = portalSurfacePrevEdge(surfaceBuilder, currentEdge);
|
|
|
|
} else if (intersectionPoint.equalTest == edgeB->equalTest) {
|
|
|
|
} else if (intersectionPoint.equalTest == edgeB->equalTest) {
|
|
|
|
newPointIndex = SB_GET_NEXT_POINT(edge, currentEdge.isReverse);
|
|
|
|
newPointIndex = nextPointIndex;
|
|
|
|
surfaceBuilder->cuttingEdge = currentEdge;
|
|
|
|
surfaceBuilder->cuttingEdge = currentEdge;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
newPointIndex = portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, &intersectionPoint);
|
|
|
|
newPointIndex = portalSurfaceSplitEdge(surfaceBuilder, currentEdge, &intersectionPoint);
|
|
|
|
|
|
|
|
|
|
|
|
if (newPointIndex == -1) {
|
|
|
|
if (newPointIndex == -1) {
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
@ -674,9 +676,9 @@ struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilde
|
|
|
|
|
|
|
|
|
|
|
|
int newPointIndex = portalSurfaceNewVertex(surfaceBuilder, pointB);
|
|
|
|
int newPointIndex = portalSurfaceNewVertex(surfaceBuilder, pointB);
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceCalcVertex(surfaceBuilder, &surfaceBuilder->edgeOnSearchLoop, newPointIndex);
|
|
|
|
portalSurfaceCalcVertex(surfaceBuilder, surfaceBuilder->edgeOnSearchLoop, newPointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceConnectToPoint(surfaceBuilder, newPointIndex, NULL, 1)) {
|
|
|
|
if (!portalSurfaceConnectToPoint(surfaceBuilder, newPointIndex, NO_EDGE_CONNECTION, 1)) {
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -684,17 +686,19 @@ struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilde
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* point) {
|
|
|
|
int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* point) {
|
|
|
|
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
|
|
|
int currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* edgeA = portalSurfaceGetVertex(surfaceBuilder, SB_GET_CURRENT_POINT(portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex), currentEdge.isReverse));
|
|
|
|
struct Vector2s16* edgeA = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, currentEdge)->pointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
for (int iteration = 0; iteration < MAX_INTERSECT_LOOPS; ++iteration) {
|
|
|
|
for (int iteration = 0; iteration < MAX_INTERSECT_LOOPS; ++iteration) {
|
|
|
|
if (iteration > 0 && currentEdge.edgeIndex == surfaceBuilder->edgeOnSearchLoop.edgeIndex && currentEdge.isReverse == surfaceBuilder->edgeOnSearchLoop.isReverse) {
|
|
|
|
if (iteration > 0 && currentEdge == surfaceBuilder->edgeOnSearchLoop) {
|
|
|
|
// finished searching loop
|
|
|
|
// finished searching loop
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* edgeB = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex), currentEdge.isReverse));
|
|
|
|
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* edgeB = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, edge->nextEdge)->pointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16 edgeDir;
|
|
|
|
struct Vector2s16 edgeDir;
|
|
|
|
vector2s16Sub(edgeB, edgeA, &edgeDir);
|
|
|
|
vector2s16Sub(edgeB, edgeA, &edgeDir);
|
|
|
@ -704,11 +708,11 @@ int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder,
|
|
|
|
surfaceBuilder->hasConnected = 1;
|
|
|
|
surfaceBuilder->hasConnected = 1;
|
|
|
|
|
|
|
|
|
|
|
|
if (point->equalTest == edgeA->equalTest) {
|
|
|
|
if (point->equalTest == edgeA->equalTest) {
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, ¤tEdge, &surfaceBuilder->cuttingEdge);
|
|
|
|
surfaceBuilder->cuttingEdge = portalSurfacePrevEdge(surfaceBuilder, currentEdge);
|
|
|
|
} else if (point->equalTest == edgeB->equalTest) {
|
|
|
|
} else if (point->equalTest == edgeB->equalTest) {
|
|
|
|
surfaceBuilder->cuttingEdge = currentEdge;
|
|
|
|
surfaceBuilder->cuttingEdge = currentEdge;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, point) == -1) {
|
|
|
|
if (portalSurfaceSplitEdge(surfaceBuilder, currentEdge, point) == -1) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -721,34 +725,32 @@ int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
edgeA = edgeB;
|
|
|
|
edgeA = edgeB;
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
currentEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
|
|
|
|
|
|
|
currentEdge = nextEdge;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
surfaceBuilder->hasEdge = 0;
|
|
|
|
surfaceBuilder->hasEdge = 0;
|
|
|
|
surfaceBuilder->hasConnected = 0;
|
|
|
|
surfaceBuilder->hasConnected = 0;
|
|
|
|
surfaceBuilder->startingPoint = portalSurfaceNewVertex(surfaceBuilder, point);
|
|
|
|
surfaceBuilder->startingPoint = portalSurfaceNewVertex(surfaceBuilder, point);
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceCalcVertex(surfaceBuilder, &surfaceBuilder->edgeOnSearchLoop, surfaceBuilder->startingPoint);
|
|
|
|
portalSurfaceCalcVertex(surfaceBuilder, surfaceBuilder->edgeOnSearchLoop, surfaceBuilder->startingPoint);
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceJoinInnerLoopToOuterLoop(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
int portalSurfaceJoinInnerLoopToOuterLoop(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
struct SurfaceEdge* outerLoopEdge = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->edgeOnSearchLoop.edgeIndex);
|
|
|
|
struct SurfaceEdge* outerLoopEdge = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->edgeOnSearchLoop);
|
|
|
|
struct Vector2s16* outerLoopPoint = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(outerLoopEdge, surfaceBuilder->edgeOnSearchLoop.isReverse));
|
|
|
|
struct Vector2s16* outerLoopPoint = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, outerLoopEdge->nextEdge)->pointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->cuttingEdge;
|
|
|
|
int currentEdge = surfaceBuilder->cuttingEdge;
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge;
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide closestEdge;
|
|
|
|
int closestEdge;
|
|
|
|
int closestDistance = 0x7FFFFFFF;
|
|
|
|
int closestDistance = 0x7FFFFFFF;
|
|
|
|
|
|
|
|
|
|
|
|
while (portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge), nextEdge.edgeIndex != surfaceBuilder->cuttingEdge.edgeIndex) {
|
|
|
|
while ((nextEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge)), nextEdge != surfaceBuilder->cuttingEdge) {
|
|
|
|
struct Vector2s16* edgePoint = portalSurfaceGetVertex(
|
|
|
|
struct Vector2s16* edgePoint = portalSurfaceGetVertex(
|
|
|
|
surfaceBuilder,
|
|
|
|
surfaceBuilder,
|
|
|
|
SB_GET_NEXT_POINT(portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex), currentEdge.isReverse)
|
|
|
|
portalSurfaceNextPoint(surfaceBuilder, currentEdge)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
int edgeDistance = vector2s16DistSqr(outerLoopPoint, edgePoint);
|
|
|
|
int edgeDistance = vector2s16DistSqr(outerLoopPoint, edgePoint);
|
|
|
@ -762,42 +764,36 @@ int portalSurfaceJoinInnerLoopToOuterLoop(struct PortalSurfaceBuilder* surfaceBu
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
surfaceBuilder->cuttingEdge = closestEdge;
|
|
|
|
surfaceBuilder->cuttingEdge = closestEdge;
|
|
|
|
return portalSurfaceConnectToPoint(surfaceBuilder, SB_GET_NEXT_POINT(outerLoopEdge, surfaceBuilder->edgeOnSearchLoop.isReverse), &surfaceBuilder->edgeOnSearchLoop, 0);
|
|
|
|
return portalSurfaceConnectToPoint(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, outerLoopEdge->nextEdge)->pointIndex, surfaceBuilder->edgeOnSearchLoop, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceHasFlag(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edge, enum SurfaceEdgeFlags value) {
|
|
|
|
int portalSurfaceHasFlag(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex, enum SurfaceEdgeFlags value) {
|
|
|
|
return ((surfaceBuilder->edgeFlags[edge->edgeIndex] & (edge->isReverse ? value << 4 : value))) != 0;
|
|
|
|
return (surfaceBuilder->edgeFlags[edgeIndex] & value) != 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void portalSurfaceSetFlag(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edge, enum SurfaceEdgeFlags value) {
|
|
|
|
void portalSurfaceSetFlag(struct PortalSurfaceBuilder* surfaceBuilder, int edgeIndex, enum SurfaceEdgeFlags value) {
|
|
|
|
surfaceBuilder->edgeFlags[edge->edgeIndex] |= edge->isReverse ? value << 4 : value;
|
|
|
|
surfaceBuilder->edgeFlags[edgeIndex] |= value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void portalSurfaceMarkLoopAsUsed(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edgeOnLoop) {
|
|
|
|
void portalSurfaceMarkLoopAsUsed(struct PortalSurfaceBuilder* surfaceBuilder, int edgeOnLoop) {
|
|
|
|
struct SurfaceEdgeWithSide currentEdge = *edgeOnLoop;
|
|
|
|
int currentEdge = edgeOnLoop;
|
|
|
|
|
|
|
|
|
|
|
|
int iteration;
|
|
|
|
int iteration;
|
|
|
|
|
|
|
|
|
|
|
|
for (iteration = 0; iteration < MAX_SEARCH_ITERATIONS && (iteration == 0 || currentEdge.edgeIndex != edgeOnLoop->edgeIndex || currentEdge.isReverse != edgeOnLoop->isReverse); ++iteration) {
|
|
|
|
for (iteration = 0; iteration < MAX_SEARCH_ITERATIONS && (iteration == 0 || currentEdge != edgeOnLoop); ++iteration) {
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, ¤tEdge, SurfaceEdgeFlagsUsed);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsUsed);
|
|
|
|
|
|
|
|
|
|
|
|
if (currentEdge.isReverse) {
|
|
|
|
surfaceBuilder->edges[currentEdge].nextEdge = NO_EDGE_CONNECTION;
|
|
|
|
surfaceBuilder->edges[currentEdge.edgeIndex].nextEdgeReverse = NO_EDGE_CONNECTION;
|
|
|
|
surfaceBuilder->edges[currentEdge].prevEdge = NO_EDGE_CONNECTION;
|
|
|
|
surfaceBuilder->edges[currentEdge.edgeIndex].prevEdgeReverse = NO_EDGE_CONNECTION;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
surfaceBuilder->edges[currentEdge.edgeIndex].nextEdge = NO_EDGE_CONNECTION;
|
|
|
|
|
|
|
|
surfaceBuilder->edges[currentEdge.edgeIndex].prevEdge = NO_EDGE_CONNECTION;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdge* surfaceEdge = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* surfaceEdge = portalSurfaceGetEdge(surfaceBuilder, nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
// since this function clears out nextEdge and prevEdge
|
|
|
|
// since this function clears out nextEdge and prevEdge
|
|
|
|
// portalSurfaceNextEdge will fail after the loop as been
|
|
|
|
// portalSurfaceNextEdge will fail after the loop as been
|
|
|
|
// marked. If this check fails the loop is finished
|
|
|
|
// marked. If this check fails the loop is finished
|
|
|
|
if (surfaceEdge->prevEdge != currentEdge.edgeIndex && surfaceEdge->prevEdgeReverse != currentEdge.edgeIndex) {
|
|
|
|
if (surfaceEdge->prevEdge != currentEdge) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -808,12 +804,10 @@ void portalSurfaceMarkLoopAsUsed(struct PortalSurfaceBuilder* surfaceBuilder, st
|
|
|
|
void portalSurfaceMarkHoleAsUsed(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
void portalSurfaceMarkHoleAsUsed(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
|
|
|
|
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
|
|
|
|
if (surfaceBuilder->isLoopEdge[i]) {
|
|
|
|
if (surfaceBuilder->isLoopEdge[i]) {
|
|
|
|
struct SurfaceEdgeWithSide edgeOnLoop;
|
|
|
|
int reverseEdge = surfaceBuilder->edges[i].reverseEdge;
|
|
|
|
edgeOnLoop.edgeIndex = i;
|
|
|
|
|
|
|
|
edgeOnLoop.isReverse = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceHasFlag(surfaceBuilder, &edgeOnLoop, SurfaceEdgeFlagsUsed)) {
|
|
|
|
if (!portalSurfaceHasFlag(surfaceBuilder, reverseEdge, SurfaceEdgeFlagsUsed)) {
|
|
|
|
portalSurfaceMarkLoopAsUsed(surfaceBuilder, &edgeOnLoop);
|
|
|
|
portalSurfaceMarkLoopAsUsed(surfaceBuilder, reverseEdge);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -823,44 +817,41 @@ void portalSurfaceMarkHoleAsUsed(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
surfaceBuilder->checkForEdgeReuse = 0;
|
|
|
|
surfaceBuilder->checkForEdgeReuse = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceConnectEdges(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* from, struct SurfaceEdgeWithSide* to, struct SurfaceEdgeWithSide* newEdge) {
|
|
|
|
int portalSurfaceConnectEdges(struct PortalSurfaceBuilder* surfaceBuilder, int from, int to) {
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, to->edgeIndex);
|
|
|
|
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, to);
|
|
|
|
surfaceBuilder->cuttingEdge = *from;
|
|
|
|
surfaceBuilder->cuttingEdge = from;
|
|
|
|
surfaceBuilder->hasEdge = 1;
|
|
|
|
surfaceBuilder->hasEdge = 1;
|
|
|
|
if (!portalSurfaceConnectToPoint(surfaceBuilder, SB_GET_NEXT_POINT(nextEdgePtr, to->isReverse), to, 0)) {
|
|
|
|
if (!portalSurfaceConnectToPoint(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, nextEdgePtr->nextEdge)->pointIndex, to, 0)) {
|
|
|
|
return 0;
|
|
|
|
return NO_EDGE_CONNECTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*newEdge = surfaceBuilder->cuttingEdge;
|
|
|
|
return surfaceBuilder->cuttingEdge;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceTriangulateLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edgeOnLoop) {
|
|
|
|
int portalSurfaceTriangulateLoop(struct PortalSurfaceBuilder* surfaceBuilder, int edgeOnLoop) {
|
|
|
|
if (portalSurfaceHasFlag(surfaceBuilder, edgeOnLoop, SurfaceEdgeFlagsTriangulated)) {
|
|
|
|
if (portalSurfaceHasFlag(surfaceBuilder, edgeOnLoop, SurfaceEdgeFlagsTriangulated)) {
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide currentEdge = *edgeOnLoop;
|
|
|
|
int currentEdge = edgeOnLoop;
|
|
|
|
int iteration = 0;
|
|
|
|
int iteration = 0;
|
|
|
|
struct SurfaceEdge* currentEdgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
|
|
|
struct SurfaceEdge* currentEdgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
// Find the starting point
|
|
|
|
// Find the starting point
|
|
|
|
while (!IS_ORIGINAL_VERTEX_INDEX(surfaceBuilder, SB_GET_CURRENT_POINT(currentEdgePtr, currentEdge.isReverse)) || IS_ORIGINAL_VERTEX_INDEX(surfaceBuilder, SB_GET_NEXT_POINT(currentEdgePtr, currentEdge.isReverse))) {
|
|
|
|
while (!IS_ORIGINAL_VERTEX_INDEX(surfaceBuilder, currentEdgePtr->pointIndex) || IS_ORIGINAL_VERTEX_INDEX(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, currentEdgePtr->nextEdge)->pointIndex)) {
|
|
|
|
++iteration;
|
|
|
|
++iteration;
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, ¤tEdge);
|
|
|
|
currentEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
currentEdgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
|
|
|
currentEdgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
if (iteration == MAX_SEARCH_ITERATIONS || (currentEdge.edgeIndex == edgeOnLoop->edgeIndex && currentEdge.isReverse == edgeOnLoop->isReverse)) {
|
|
|
|
if (iteration == MAX_SEARCH_ITERATIONS || currentEdge == edgeOnLoop) {
|
|
|
|
if (iteration == 3) {
|
|
|
|
if (iteration == 3) {
|
|
|
|
// already a triangle
|
|
|
|
// already a triangle
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide prevEdge;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
|
|
|
int nextEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, ¤tEdge, &prevEdge);
|
|
|
|
int prevEdge = portalSurfacePrevEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, ¤tEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &nextEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, nextEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &prevEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, prevEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -870,27 +861,24 @@ int portalSurfaceTriangulateLoop(struct PortalSurfaceBuilder* surfaceBuilder, st
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (iteration = 0; iteration < MAX_SEARCH_ITERATIONS; ++iteration) {
|
|
|
|
for (iteration = 0; iteration < MAX_SEARCH_ITERATIONS; ++iteration) {
|
|
|
|
currentEdgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
|
|
|
currentEdgePtr = portalSurfaceGetEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* edgePointA = portalSurfaceGetVertex(surfaceBuilder, SB_GET_CURRENT_POINT(currentEdgePtr, currentEdge.isReverse));
|
|
|
|
struct Vector2s16* edgePointA = portalSurfaceGetVertex(surfaceBuilder, currentEdgePtr->pointIndex);
|
|
|
|
struct Vector2s16* edgePointB = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(currentEdgePtr, currentEdge.isReverse));
|
|
|
|
struct Vector2s16* edgePointB = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, currentEdgePtr->nextEdge)->pointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide nextEdge;
|
|
|
|
int nextEdge = portalSurfaceNextEdge(surfaceBuilder, currentEdge);
|
|
|
|
struct SurfaceEdgeWithSide prevEdge;
|
|
|
|
int prevEdge = portalSurfacePrevEdge(surfaceBuilder, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
|
|
|
int prevPointIndex = portalSurfaceGetEdge(surfaceBuilder, prevEdge)->pointIndex;
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, ¤tEdge, &prevEdge);
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* nextPoint = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceNextPoint(surfaceBuilder, nextEdge));
|
|
|
|
int prevPointIndex = SB_GET_CURRENT_POINT(portalSurfaceGetEdge(surfaceBuilder, prevEdge.edgeIndex), prevEdge.isReverse);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* nextPoint = portalSurfaceGetVertex(surfaceBuilder, SB_GET_NEXT_POINT(portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex), nextEdge.isReverse));
|
|
|
|
|
|
|
|
struct Vector2s16* prevPoint = portalSurfaceGetVertex(surfaceBuilder, prevPointIndex);
|
|
|
|
struct Vector2s16* prevPoint = portalSurfaceGetVertex(surfaceBuilder, prevPointIndex);
|
|
|
|
|
|
|
|
|
|
|
|
// check if finished
|
|
|
|
// check if finished
|
|
|
|
if (nextPoint == prevPoint) {
|
|
|
|
if (nextPoint == prevPoint) {
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, ¤tEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &nextEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, nextEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &prevEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, prevEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -902,49 +890,47 @@ int portalSurfaceTriangulateLoop(struct PortalSurfaceBuilder* surfaceBuilder, st
|
|
|
|
vector2s16Sub(nextPoint, edgePointB, &nextEdgeDir);
|
|
|
|
vector2s16Sub(nextPoint, edgePointB, &nextEdgeDir);
|
|
|
|
vector2s16Sub(edgePointB, prevPoint, &prevEdgeDir);
|
|
|
|
vector2s16Sub(edgePointB, prevPoint, &prevEdgeDir);
|
|
|
|
|
|
|
|
|
|
|
|
struct SurfaceEdgeWithSide nextCurrentEdge;
|
|
|
|
int nextCurrentEdge;
|
|
|
|
if (IS_ORIGINAL_VERTEX_INDEX(surfaceBuilder, prevPointIndex) && vector2s16Cross(&prevEdgeDir, &nextEdgeDir) > vector2s16Cross(&edgeDir, &nextEdgeDir)) {
|
|
|
|
if (IS_ORIGINAL_VERTEX_INDEX(surfaceBuilder, prevPointIndex) && vector2s16Cross(&prevEdgeDir, &nextEdgeDir) > vector2s16Cross(&edgeDir, &nextEdgeDir)) {
|
|
|
|
struct SurfaceEdgeWithSide prevPrevEdge;
|
|
|
|
int prevPrevEdge = portalSurfacePrevEdge(surfaceBuilder, prevEdge);
|
|
|
|
portalSurfacePrevEdge(surfaceBuilder, &prevEdge, &prevPrevEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceConnectEdges(surfaceBuilder, &prevPrevEdge, ¤tEdge, &nextCurrentEdge)) {
|
|
|
|
nextCurrentEdge = portalSurfaceConnectEdges(surfaceBuilder, prevPrevEdge, currentEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nextCurrentEdge == NO_EDGE_CONNECTION) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &prevEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, prevEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, ¤tEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (!portalSurfaceConnectEdges(surfaceBuilder, &prevEdge, &nextEdge, &nextCurrentEdge)) {
|
|
|
|
nextCurrentEdge = portalSurfaceConnectEdges(surfaceBuilder, prevEdge, nextEdge);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (nextCurrentEdge == NO_EDGE_CONNECTION) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, ¤tEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &nextEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, nextEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentEdge = nextCurrentEdge;
|
|
|
|
currentEdge = nextCurrentEdge;
|
|
|
|
|
|
|
|
|
|
|
|
nextCurrentEdge.isReverse = !nextCurrentEdge.isReverse;
|
|
|
|
nextCurrentEdge = portalSurfaceReverseEdge(surfaceBuilder, nextCurrentEdge);
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, &nextCurrentEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
|
|
|
|
|
|
|
|
portalSurfaceSetFlag(surfaceBuilder, nextCurrentEdge, SurfaceEdgeFlagsTriangulated);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int portalSurfaceTriangulate(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
int portalSurfaceTriangulate(struct PortalSurfaceBuilder* surfaceBuilder) {
|
|
|
|
struct SurfaceEdgeWithSide edge;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
|
|
|
|
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
|
|
|
|
edge.edgeIndex = i;
|
|
|
|
if (portalSurfaceGetEdge(surfaceBuilder, i)->nextEdge == NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
for (edge.isReverse = 0; edge.isReverse < 2; ++edge.isReverse) {
|
|
|
|
}
|
|
|
|
if (SB_GET_NEXT_EDGE(portalSurfaceGetEdge(surfaceBuilder, edge.edgeIndex), edge.isReverse) == NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceTriangulateLoop(surfaceBuilder, &edge)) {
|
|
|
|
if (!portalSurfaceTriangulateLoop(surfaceBuilder, i)) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -966,11 +952,10 @@ int portalSurfacePokeHole(struct PortalSurface* surface, struct Vector2s16* loop
|
|
|
|
surfaceBuilder.currentEdge = surface->edgeCount;
|
|
|
|
surfaceBuilder.currentEdge = surface->edgeCount;
|
|
|
|
surfaceBuilder.checkForEdgeReuse = surface->edgeCount;
|
|
|
|
surfaceBuilder.checkForEdgeReuse = surface->edgeCount;
|
|
|
|
surfaceBuilder.edgeFlags = stackMalloc(sizeof(u8) * edgeCapacity);
|
|
|
|
surfaceBuilder.edgeFlags = stackMalloc(sizeof(u8) * edgeCapacity);
|
|
|
|
surfaceBuilder.originalEdgeIndex = stackMalloc(sizeof(struct OriginalEdgeMapping) * edgeCapacity);
|
|
|
|
surfaceBuilder.originalEdgeIndex = stackMalloc(sizeof(u8) * edgeCapacity);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < surface->edgeCount; ++i) {
|
|
|
|
for (int i = 0; i < surface->edgeCount; ++i) {
|
|
|
|
surfaceBuilder.originalEdgeIndex[i].originalEdge = i;
|
|
|
|
surfaceBuilder.originalEdgeIndex[i] = i;
|
|
|
|
surfaceBuilder.originalEdgeIndex[i].originalEdgeReverse = i | 0x80;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
surfaceBuilder.gfxVertices = stackMalloc(sizeof(Vtx) * (surface->vertexCount + ADDITIONAL_EDGE_CAPACITY));
|
|
|
|
surfaceBuilder.gfxVertices = stackMalloc(sizeof(Vtx) * (surface->vertexCount + ADDITIONAL_EDGE_CAPACITY));
|
|
|
@ -981,7 +966,9 @@ int portalSurfacePokeHole(struct PortalSurface* surface, struct Vector2s16* loop
|
|
|
|
|
|
|
|
|
|
|
|
struct Vector2s16* prev = &loop[0];
|
|
|
|
struct Vector2s16* prev = &loop[0];
|
|
|
|
|
|
|
|
|
|
|
|
if (!portalSurfaceFindEnclosingFace(surface, prev, &surfaceBuilder.edgeOnSearchLoop)) {
|
|
|
|
surfaceBuilder.edgeOnSearchLoop = portalSurfaceFindEnclosingFace(surface, prev);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (surfaceBuilder.edgeOnSearchLoop == -1) {
|
|
|
|
goto error;
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1011,13 +998,16 @@ int portalSurfacePokeHole(struct PortalSurface* surface, struct Vector2s16* loop
|
|
|
|
struct SurfaceEdge* firstEdge = portalSurfaceGetEdge(&surfaceBuilder, firstEdgeIndex);
|
|
|
|
struct SurfaceEdge* firstEdge = portalSurfaceGetEdge(&surfaceBuilder, firstEdgeIndex);
|
|
|
|
struct SurfaceEdge* lastEdge = portalSurfaceGetEdge(&surfaceBuilder, lastEdgeIndex);
|
|
|
|
struct SurfaceEdge* lastEdge = portalSurfaceGetEdge(&surfaceBuilder, lastEdgeIndex);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (firstEdge->reverseEdge != NO_EDGE_CONNECTION) {
|
|
|
|
|
|
|
|
struct SurfaceEdge* firstEdgeReverse = portalSurfaceGetEdge(&surfaceBuilder, firstEdge->reverseEdge);
|
|
|
|
|
|
|
|
firstEdgeReverse->nextEdge = lastEdgeIndex;
|
|
|
|
|
|
|
|
firstEdgeReverse->pointIndex = firstEdge->pointIndex;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
firstEdge->prevEdge = lastEdgeIndex;
|
|
|
|
firstEdge->prevEdge = lastEdgeIndex;
|
|
|
|
firstEdge->nextEdgeReverse = lastEdgeIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastEdge->nextEdge = firstEdgeIndex;
|
|
|
|
lastEdge->nextEdge = firstEdgeIndex;
|
|
|
|
lastEdge->prevEdgeReverse = firstEdgeIndex;
|
|
|
|
lastEdge->prevEdge = firstEdgeIndex;
|
|
|
|
|
|
|
|
|
|
|
|
lastEdge->bIndex = firstEdge->aIndex;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--surfaceBuilder.currentVertex;
|
|
|
|
--surfaceBuilder.currentVertex;
|
|
|
|
|
|
|
|
|
|
|
|