Figure out some steps in hole cutting logic
This commit is contained in:
parent
2a30dbd8c9
commit
8036e3d60f
|
@ -14,6 +14,9 @@
|
|||
#define GET_CURRENT_POINT(surfaceEdge, isReverse) ((isReverse) ? (surfaceEdge)->bIndex : (surfaceEdge->aIndex))
|
||||
#define GET_NEXT_POINT(surfaceEdge, isReverse) ((isReverse) ? (surfaceEdge)->aIndex : (surfaceEdge->bIndex))
|
||||
|
||||
#define SET_NEXT_EDGE(surfaceEdge, isReverse, value) do { if (isReverse) (surfaceEdge)->nextEdgeReverse = (value); else (surfaceEdge)->nextEdge = (value); } while (0)
|
||||
#define SET_PREV_EDGE(surfaceEdge, isReverse, value) do { if (isReverse) (surfaceEdge)->prevEdgeReverse = (value); else (surfaceEdge)->prevEdge = (value); } while (0)
|
||||
|
||||
#define MAX_SEARCH_ITERATIONS 20
|
||||
|
||||
#define ADDITIONAL_EDGE_CAPACITY 32
|
||||
|
@ -36,7 +39,7 @@ struct PortalSurfaceBuilder {
|
|||
// set when hasEdge is true
|
||||
struct SurfaceEdgeWithSide cuttingEdge;
|
||||
// set when hasEdge is false
|
||||
struct Vector2s16* startingPoint;
|
||||
int startingPoint;
|
||||
};
|
||||
short hasEdge;
|
||||
short hasConnected;
|
||||
|
@ -221,44 +224,34 @@ enum IntersectionType portalSurfaceIntersect(struct Vector2s16* pointA, struct V
|
|||
return IntersectionTypePoint;
|
||||
}
|
||||
|
||||
void portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* pointA, struct Vector2s16* pointDir) {
|
||||
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
||||
|
||||
for (int iteration = 0; iteration < MAX_INTERSECT_LOOPS; ++iteration) {
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
|
||||
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
||||
|
||||
if (nextEdge.edgeIndex == surfaceBuilder->edgeOnSearchLoop.edgeIndex && nextEdge.isReverse == surfaceBuilder->edgeOnSearchLoop.isReverse) {
|
||||
// finished searching loop
|
||||
break;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
||||
|
||||
struct Vector2s16* edgeA = portalSurfaceGetPoint(surfaceBuilder, GET_CURRENT_POINT(edge, currentEdge.isReverse));
|
||||
struct Vector2s16* edgeB = portalSurfaceGetPoint(surfaceBuilder, GET_NEXT_POINT(edge, currentEdge.isReverse));
|
||||
|
||||
struct Vector2s16 intersectionPoint;
|
||||
|
||||
enum IntersectionType intersectType = portalSurfaceIntersect(pointA, pointDir, edgeA, edgeB, &intersectionPoint);
|
||||
|
||||
if (intersectType) {
|
||||
|
||||
}
|
||||
|
||||
currentEdge = nextEdge;
|
||||
}
|
||||
}
|
||||
|
||||
int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edge, struct Vector2s16* point) {
|
||||
if (surfaceBuilder->currentEdge == ADDITIONAL_EDGE_CAPACITY || surfaceBuilder->currentVertex == ADDITIONAL_VERTEX_CAPACITY) {
|
||||
return 0;
|
||||
int portalSurfaceNewVertex(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* point) {
|
||||
if (surfaceBuilder->currentVertex == ADDITIONAL_VERTEX_CAPACITY) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
surfaceBuilder->additionalVertices[surfaceBuilder->currentVertex] = *point;
|
||||
int newVertexIndex = surfaceBuilder->currentVertex + surfaceBuilder->surface->vertexCount;
|
||||
++surfaceBuilder->currentVertex;
|
||||
|
||||
return newVertexIndex;
|
||||
}
|
||||
|
||||
int portalSurfaceNewEdge(struct PortalSurfaceBuilder* surfaceBuilder) {
|
||||
if (surfaceBuilder->currentEdge == ADDITIONAL_EDGE_CAPACITY) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int newEdgeIndex = surfaceBuilder->currentEdge + surfaceBuilder->surface->edgeCount;
|
||||
++surfaceBuilder->currentEdge;
|
||||
return newEdgeIndex;
|
||||
}
|
||||
|
||||
int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct SurfaceEdgeWithSide* edge, struct Vector2s16* point) {
|
||||
int newVertexIndex = portalSurfaceNewVertex(surfaceBuilder, point);
|
||||
|
||||
if (newVertexIndex == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* existingEdge = portalSurfaceGetEdge(surfaceBuilder, edge->edgeIndex);
|
||||
|
||||
|
@ -268,9 +261,13 @@ int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct S
|
|||
portalSurfaceNextEdge(surfaceBuilder, edge, &nextEdge);
|
||||
portalSurfacePrevEdge(surfaceBuilder, edge, &prevReverseEdge);
|
||||
|
||||
struct SurfaceEdge* newEdge = &surfaceBuilder->additionalEdges[surfaceBuilder->currentEdge];
|
||||
int newEdgeIndex = surfaceBuilder->currentEdge + surfaceBuilder->surface->edgeCount;
|
||||
++surfaceBuilder->currentEdge;
|
||||
int newEdgeIndex = portalSurfaceNewEdge(surfaceBuilder);
|
||||
|
||||
if (newEdgeIndex == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* newEdge = portalSurfaceGetEdge(surfaceBuilder, newEdgeIndex);
|
||||
|
||||
newEdge->bIndex = existingEdge->bIndex;
|
||||
newEdge->aIndex = newVertexIndex;
|
||||
|
@ -293,15 +290,155 @@ int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, struct S
|
|||
|
||||
struct SurfaceEdge* prevEdgePtr = portalSurfaceGetEdge(surfaceBuilder, prevReverseEdge.edgeIndex);
|
||||
|
||||
if (prevReverseEdge.isReverse) {
|
||||
prevEdgePtr->nextEdgeReverse = newEdgeIndex;
|
||||
} else {
|
||||
prevEdgePtr->nextEdge = newEdgeIndex;
|
||||
SET_NEXT_EDGE(prevEdgePtr, prevReverseEdge.isReverse, newEdgeIndex);
|
||||
|
||||
return newVertexIndex;
|
||||
}
|
||||
|
||||
int portalSurfaceConnectToPoint(struct PortalSurfaceBuilder* surfaceBuilder, int pointIndex, struct SurfaceEdgeWithSide* edge) {
|
||||
int newEdge = portalSurfaceNewEdge(surfaceBuilder);
|
||||
|
||||
if (newEdge == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* newEdgePtr = portalSurfaceGetEdge(surfaceBuilder, newEdge);
|
||||
|
||||
if (surfaceBuilder->hasEdge) {
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
portalSurfaceNextEdge(surfaceBuilder, &surfaceBuilder->cuttingEdge, &nextEdge);
|
||||
|
||||
struct SurfaceEdge* cuttingEdgePtr = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->cuttingEdge.edgeIndex);
|
||||
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
||||
|
||||
newEdgePtr->aIndex = GET_NEXT_POINT(cuttingEdgePtr, surfaceBuilder->cuttingEdge.isReverse);
|
||||
|
||||
newEdgePtr->prevEdge = surfaceBuilder->cuttingEdge.edgeIndex;
|
||||
newEdgePtr->nextEdgeReverse = nextEdge.edgeIndex;
|
||||
|
||||
SET_NEXT_EDGE(cuttingEdgePtr, surfaceBuilder->cuttingEdge.isReverse, newEdge);
|
||||
SET_PREV_EDGE(nextEdgePtr, nextEdge.isReverse, newEdge);
|
||||
} else {
|
||||
newEdgePtr->prevEdge = newEdge;
|
||||
newEdgePtr->nextEdgeReverse = newEdge;
|
||||
newEdgePtr->aIndex = surfaceBuilder->startingPoint;
|
||||
}
|
||||
|
||||
newEdgePtr->bIndex = pointIndex;
|
||||
|
||||
if (edge) {
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
portalSurfaceNextEdge(surfaceBuilder, edge, &nextEdge);
|
||||
|
||||
struct SurfaceEdge* edgePtr = portalSurfaceGetEdge(surfaceBuilder, edge->edgeIndex);
|
||||
struct SurfaceEdge* nextEdgePtr = portalSurfaceGetEdge(surfaceBuilder, nextEdge.edgeIndex);
|
||||
|
||||
newEdgePtr->nextEdge = nextEdge.edgeIndex;
|
||||
newEdgePtr->prevEdgeReverse = edge->edgeIndex;
|
||||
|
||||
SET_NEXT_EDGE(edgePtr, edge->isReverse, newEdge);
|
||||
SET_PREV_EDGE(nextEdgePtr, nextEdge.isReverse, newEdge);
|
||||
} else {
|
||||
newEdgePtr->nextEdge = newEdge;
|
||||
newEdgePtr->prevEdgeReverse = newEdge;
|
||||
}
|
||||
|
||||
surfaceBuilder->hasEdge = 1;
|
||||
surfaceBuilder->cuttingEdge.edgeIndex = newEdge;
|
||||
surfaceBuilder->cuttingEdge.isReverse = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct Vector2s16* portalSurfaceIntersectEdgeWithLoop(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* pointA, struct Vector2s16* pointDir) {
|
||||
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
||||
|
||||
for (int iteration = 0; iteration < MAX_INTERSECT_LOOPS; ++iteration) {
|
||||
struct SurfaceEdgeWithSide nextEdge;
|
||||
|
||||
portalSurfaceNextEdge(surfaceBuilder, ¤tEdge, &nextEdge);
|
||||
|
||||
if (nextEdge.edgeIndex == surfaceBuilder->edgeOnSearchLoop.edgeIndex && nextEdge.isReverse == surfaceBuilder->edgeOnSearchLoop.isReverse) {
|
||||
// finished searching loop
|
||||
break;
|
||||
}
|
||||
|
||||
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, currentEdge.edgeIndex);
|
||||
|
||||
struct Vector2s16* edgeA = portalSurfaceGetPoint(surfaceBuilder, GET_CURRENT_POINT(edge, currentEdge.isReverse));
|
||||
struct Vector2s16* edgeB = portalSurfaceGetPoint(surfaceBuilder, GET_NEXT_POINT(edge, currentEdge.isReverse));
|
||||
|
||||
struct Vector2s16 intersectionPoint;
|
||||
|
||||
enum IntersectionType intersectType = portalSurfaceIntersect(pointA, pointDir, edgeA, edgeB, &intersectionPoint);
|
||||
|
||||
if (intersectionPoint.equalTest == pointA->equalTest) {
|
||||
currentEdge = nextEdge;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (intersectType == IntersectionTypePoint) {
|
||||
int newPointIndex;
|
||||
|
||||
if (intersectionPoint.equalTest == edgeA->equalTest) {
|
||||
newPointIndex = GET_CURRENT_POINT(edge, currentEdge.isReverse);
|
||||
} else if (intersectionPoint.equalTest == edgeB->equalTest) {
|
||||
newPointIndex = GET_NEXT_POINT(edge, currentEdge.isReverse);
|
||||
} else {
|
||||
newPointIndex = portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, &intersectionPoint);
|
||||
|
||||
if (newPointIndex == -1) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!portalSurfaceConnectToPoint(surfaceBuilder, newPointIndex, ¤tEdge)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surfaceBuilder->hasConnected = 1;
|
||||
|
||||
return portalSurfaceGetPoint(surfaceBuilder, newPointIndex);
|
||||
} else if (intersectType == IntersectionTypeColinear) {
|
||||
int newPointIndex;
|
||||
|
||||
if (intersectionPoint.equalTest == edgeA->equalTest) {
|
||||
newPointIndex = GET_CURRENT_POINT(edge, currentEdge.isReverse);
|
||||
portalSurfacePrevEdge(surfaceBuilder, ¤tEdge, &surfaceBuilder->cuttingEdge);
|
||||
} else if (intersectionPoint.equalTest == edgeB->equalTest) {
|
||||
newPointIndex = GET_NEXT_POINT(edge, currentEdge.isReverse);
|
||||
surfaceBuilder->cuttingEdge = currentEdge;
|
||||
} else {
|
||||
int newPointIndex = portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, &intersectionPoint);
|
||||
|
||||
if (newPointIndex == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
surfaceBuilder->cuttingEdge = currentEdge;
|
||||
}
|
||||
|
||||
surfaceBuilder->hasEdge = 1;
|
||||
surfaceBuilder->hasConnected = 1;
|
||||
|
||||
return portalSurfaceGetPoint(surfaceBuilder, newPointIndex);
|
||||
}
|
||||
|
||||
currentEdge = nextEdge;
|
||||
}
|
||||
|
||||
struct Vector2s16 pointB;
|
||||
vector2s16Add(pointA, pointDir, &pointB);
|
||||
|
||||
int newPointIndex = portalSurfaceNewVertex(surfaceBuilder, &pointB);
|
||||
|
||||
if (!portalSurfaceConnectToPoint(surfaceBuilder, newPointIndex, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return portalSurfaceGetPoint(surfaceBuilder, newPointIndex);
|
||||
}
|
||||
|
||||
int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder, struct Vector2s16* point) {
|
||||
struct SurfaceEdgeWithSide currentEdge = surfaceBuilder->edgeOnSearchLoop;
|
||||
|
||||
|
@ -331,7 +468,7 @@ int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder,
|
|||
} else if (point->equalTest == edgeB->equalTest) {
|
||||
surfaceBuilder->cuttingEdge = currentEdge;
|
||||
} else {
|
||||
if (!portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, point)) {
|
||||
if (portalSurfaceSplitEdge(surfaceBuilder, ¤tEdge, point) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -349,7 +486,9 @@ int portalSurfaceFindStartingPoint(struct PortalSurfaceBuilder* surfaceBuilder,
|
|||
|
||||
surfaceBuilder->hasEdge = 0;
|
||||
surfaceBuilder->hasConnected = 0;
|
||||
surfaceBuilder->startingPoint = point;
|
||||
surfaceBuilder->startingPoint = surfaceBuilder->surface->vertexCount;
|
||||
surfaceBuilder->additionalVertices[0] = *point;
|
||||
++surfaceBuilder->currentVertex;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -362,28 +501,44 @@ struct PortalSurface* portalSurfaceCutHole(struct PortalSurface* surface, struct
|
|||
surfaceBuilder.additionalEdges = stackMalloc(sizeof(struct SurfaceEdge) * ADDITIONAL_EDGE_CAPACITY);
|
||||
surfaceBuilder.currentEdge = 0;
|
||||
|
||||
if (!portalSurfaceFindEnclosingFace(surface, &loop[0], &surfaceBuilder.edgeOnSearchLoop)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!portalSurfaceFindStartingPoint(&surfaceBuilder, &loop[0])) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Vector2s16* prev = &loop[0];
|
||||
|
||||
for (int i = 1; i < loopSize; ++i) {
|
||||
struct Vector2s16* next = &loop[0];
|
||||
if (!portalSurfaceFindEnclosingFace(surface, prev, &surfaceBuilder.edgeOnSearchLoop)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!portalSurfaceFindStartingPoint(&surfaceBuilder, prev)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (int i = 1; i < loopSize;) {
|
||||
struct Vector2s16* next = &loop[i];
|
||||
struct Vector2s16 dir;
|
||||
|
||||
vector2s16Sub(next, prev, &dir);
|
||||
portalSurfaceIntersectEdgeWithLoop(&surfaceBuilder, prev, &dir);
|
||||
struct Vector2s16* newPoint = portalSurfaceIntersectEdgeWithLoop(&surfaceBuilder, prev, &dir);
|
||||
|
||||
if (!newPoint) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (newPoint->equalTest == next->equalTest) {
|
||||
// only increment i if the next point was reached
|
||||
++i;
|
||||
}
|
||||
|
||||
prev = newPoint;
|
||||
}
|
||||
|
||||
stackMallocFree(surfaceBuilder.additionalEdges);
|
||||
stackMallocFree(surfaceBuilder.additionalVertices);
|
||||
|
||||
return NULL;
|
||||
|
||||
error:
|
||||
stackMallocFree(surfaceBuilder.additionalEdges);
|
||||
stackMallocFree(surfaceBuilder.additionalVertices);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void portalSurface2DPoint(struct PortalSurface* surface, struct Vector3* at, struct Vector2s16* output) {
|
||||
|
|
Loading…
Reference in a new issue