fix some surface generator bugs after refactor

This commit is contained in:
James Lambert 2023-08-27 21:27:26 -06:00
parent d51d939ec6
commit 80d98219e2
3 changed files with 99 additions and 58 deletions

View file

@ -110,9 +110,14 @@ int portalSurfaceReverseEdge(struct PortalSurfaceBuilder* surfaceBuilder, int ed
int portalSurfaceIsWellFormed(struct PortalSurfaceBuilder* surfaceBuilder) {
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
struct SurfaceEdge* edge = portalSurfaceGetEdge(surfaceBuilder, i);
if (edge->nextEdge == NO_EDGE_CONNECTION) {
continue;
}
struct SurfaceEdge* next = portalSurfaceGetEdge(surfaceBuilder, edge->nextEdge);
struct SurfaceEdge* prev = portalSurfaceGetEdge(surfaceBuilder, edge->prevEdge);
struct SurfaceEdge* reverse = edge->reverseEdge == -1 ? NULL : portalSurfaceGetEdge(surfaceBuilder, edge->reverseEdge);
struct SurfaceEdge* reverse = edge->reverseEdge == NO_EDGE_CONNECTION ? NULL : portalSurfaceGetEdge(surfaceBuilder, edge->reverseEdge);
if (next->prevEdge != i || prev->nextEdge != i || (reverse != NULL && reverse->reverseEdge != i)) {
return 0;
@ -134,6 +139,10 @@ int portalSurfacePointInsideFace(struct PortalSurfaceBuilder* surfaceBuilder, in
struct Vector2s16* prevPoint = portalSurfaceGetVertex(surfaceBuilder, edgePtr->pointIndex);
struct Vector2s16* nextPoint = portalSurfaceGetVertex(surfaceBuilder, portalSurfaceGetEdge(surfaceBuilder, nextEdgePtr->nextEdge)->pointIndex);
if (prevPoint->equalTest == nextPoint->equalTest) {
return 1;
}
struct Vector2s16 nextDir;
struct Vector2s16 prevDir;
@ -205,9 +214,9 @@ int portalSurfaceFindNextLoop(struct PortalSurfaceBuilder* surfaceBuilder, struc
int nextIndex = portalSurfaceGetEdge(surfaceBuilder, surfaceBuilder->cuttingEdge)->nextEdge;
// the cutting edge is its own next edge
// the cutting edge is extended into a face already
// this means edgeOnSearchLoop will already be correct
if (nextIndex == surfaceBuilder->cuttingEdge) {
if (portalSurfaceGetEdge(surfaceBuilder, nextIndex)->reverseEdge == surfaceBuilder->cuttingEdge) {
return 1;
}
@ -329,6 +338,8 @@ int portalSurfaceNewEdge(struct PortalSurfaceBuilder* surfaceBuilder, int isLoop
if (edge->nextEdge == NO_EDGE_CONNECTION) {
surfaceBuilder->isLoopEdge[surfaceBuilder->checkForEdgeReuse] = isLoopEdge;
surfaceBuilder->originalEdgeIndex[surfaceBuilder->checkForEdgeReuse] = originalEdge;
// ensure this isn't returned on the next call
edge->nextEdge = 0;
return surfaceBuilder->checkForEdgeReuse;
}
@ -445,9 +456,11 @@ int portalSurfaceSplitEdgeWithVertex(struct PortalSurfaceBuilder* surfaceBuilder
int newReverseEdgeIndex = NO_EDGE_CONNECTION;
struct SurfaceEdge* newReverseEdge = NULL;
struct SurfaceEdge* existingReverseEdge = NULL;
int existingReverseEdgeIndex = existingEdge->reverseEdge;
if (existingEdge->reverseEdge != NO_EDGE_CONNECTION) {
newReverseEdgeIndex = portalSurfaceNewEdge(surfaceBuilder, 0, surfaceBuilder->originalEdgeIndex[existingEdge->reverseEdge]);
if (existingReverseEdgeIndex != NO_EDGE_CONNECTION) {
newReverseEdgeIndex = portalSurfaceNewEdge(surfaceBuilder, 0, surfaceBuilder->originalEdgeIndex[existingReverseEdgeIndex]);
if (newReverseEdgeIndex == -1) {
return 0;
@ -455,11 +468,16 @@ int portalSurfaceSplitEdgeWithVertex(struct PortalSurfaceBuilder* surfaceBuilder
newReverseEdge = portalSurfaceGetEdge(surfaceBuilder, newReverseEdgeIndex);
newEdge->reverseEdge = newReverseEdgeIndex;
newReverseEdge->reverseEdge = newEdgeIndex;
newReverseEdge->pointIndex = newVertexIndex;
existingReverseEdge = portalSurfaceGetEdge(surfaceBuilder, existingEdge->reverseEdge);
existingReverseEdge = portalSurfaceGetEdge(surfaceBuilder, existingReverseEdgeIndex);
existingReverseEdge->reverseEdge = newEdgeIndex;
newEdge->reverseEdge = existingReverseEdgeIndex;
existingEdge->reverseEdge = newReverseEdgeIndex;
newReverseEdge->reverseEdge = edge;
} else {
newEdge->reverseEdge = NO_EDGE_CONNECTION;
}
@ -472,7 +490,7 @@ int portalSurfaceSplitEdgeWithVertex(struct PortalSurfaceBuilder* surfaceBuilder
if (newReverseEdge) {
newReverseEdge->nextEdge = existingReverseEdge->nextEdge;
newReverseEdge->prevEdge = existingEdge->reverseEdge;
newReverseEdge->prevEdge = existingReverseEdgeIndex;
existingReverseEdge->nextEdge = newReverseEdgeIndex;
portalSurfaceGetEdge(surfaceBuilder, newReverseEdge->nextEdge)->prevEdge = newReverseEdgeIndex;
@ -509,7 +527,7 @@ int portalSurfaceSplitEdge(struct PortalSurfaceBuilder* surfaceBuilder, int edge
int portalSurfaceConnectToPoint(struct PortalSurfaceBuilder* surfaceBuilder, int pointIndex, int edgeIndex, int isLoopEdge) {
int originalEdge = surfaceBuilder->originalEdgeIndex[surfaceBuilder->edgeOnSearchLoop];
int newEdge = portalSurfaceNewEdge(surfaceBuilder, isLoopEdge, originalEdge);
int newEdge = portalSurfaceNewEdge(surfaceBuilder, 0, originalEdge);
if (newEdge == -1) {
return 0;
@ -785,8 +803,15 @@ void portalSurfaceMarkLoopAsUsed(struct PortalSurfaceBuilder* surfaceBuilder, in
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsUsed);
int reverseEdge = surfaceBuilder->edges[currentEdge].reverseEdge;
if (reverseEdge != NO_EDGE_CONNECTION) {
surfaceBuilder->edges[reverseEdge].reverseEdge = NO_EDGE_CONNECTION;
}
surfaceBuilder->edges[currentEdge].nextEdge = NO_EDGE_CONNECTION;
surfaceBuilder->edges[currentEdge].prevEdge = NO_EDGE_CONNECTION;
surfaceBuilder->edges[currentEdge].reverseEdge = NO_EDGE_CONNECTION;
struct SurfaceEdge* surfaceEdge = portalSurfaceGetEdge(surfaceBuilder, nextEdge);
@ -804,10 +829,8 @@ void portalSurfaceMarkLoopAsUsed(struct PortalSurfaceBuilder* surfaceBuilder, in
void portalSurfaceMarkHoleAsUsed(struct PortalSurfaceBuilder* surfaceBuilder) {
for (int i = 0; i < surfaceBuilder->currentEdge; ++i) {
if (surfaceBuilder->isLoopEdge[i]) {
int reverseEdge = surfaceBuilder->edges[i].reverseEdge;
if (!portalSurfaceHasFlag(surfaceBuilder, reverseEdge, SurfaceEdgeFlagsUsed)) {
portalSurfaceMarkLoopAsUsed(surfaceBuilder, reverseEdge);
if (!portalSurfaceHasFlag(surfaceBuilder, i, SurfaceEdgeFlagsUsed)) {
portalSurfaceMarkLoopAsUsed(surfaceBuilder, i);
}
}
}
@ -875,7 +898,7 @@ int portalSurfaceTriangulateLoop(struct PortalSurfaceBuilder* surfaceBuilder, in
struct Vector2s16* prevPoint = portalSurfaceGetVertex(surfaceBuilder, prevPointIndex);
// check if finished
if (nextPoint == prevPoint) {
if (nextPoint == prevPoint) {
portalSurfaceSetFlag(surfaceBuilder, currentEdge, SurfaceEdgeFlagsTriangulated);
portalSurfaceSetFlag(surfaceBuilder, nextEdge, SurfaceEdgeFlagsTriangulated);
portalSurfaceSetFlag(surfaceBuilder, prevEdge, SurfaceEdgeFlagsTriangulated);
@ -993,21 +1016,23 @@ int portalSurfacePokeHole(struct PortalSurface* surface, struct Vector2s16* loop
if (index == PORTAL_LOOP_SIZE && !surfaceBuilder.hasConnected) {
// the portal loop is fully contained
int firstEdgeIndex = surface->edgeCount;
int lastEdgeIndex = surfaceBuilder.currentEdge - 1;
int lastEdgeIndex = surfaceBuilder.currentEdge - 2;
struct SurfaceEdge* firstEdge = portalSurfaceGetEdge(&surfaceBuilder, firstEdgeIndex);
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;
if (firstEdge->reverseEdge == NO_EDGE_CONNECTION || lastEdge->reverseEdge == NO_EDGE_CONNECTION) {
goto error;
}
firstEdge->prevEdge = lastEdgeIndex;
struct SurfaceEdge* firstEdgeReverse = portalSurfaceGetEdge(&surfaceBuilder, firstEdge->reverseEdge);
struct SurfaceEdge* lastEdgeReverse = portalSurfaceGetEdge(&surfaceBuilder, lastEdge->reverseEdge);
firstEdgeReverse->nextEdge = lastEdge->reverseEdge;
lastEdgeReverse->prevEdge = firstEdge->reverseEdge;
lastEdgeReverse->pointIndex = firstEdge->pointIndex;
firstEdge->prevEdge = lastEdgeIndex;
lastEdge->nextEdge = firstEdgeIndex;
lastEdge->prevEdge = firstEdgeIndex;
--surfaceBuilder.currentVertex;

View file

@ -197,12 +197,7 @@ void gfxBuilderBuildGfx(struct GfxBuilderState* gfxBuilder, struct PortalSurface
struct DisplayListResult newGfxFromSurfaceBuilder(struct PortalSurfaceBuilder* surfaceBuilder) {
struct GfxBuilderState builderState;
int possibleTriangleCount = (
// each edge can have 2 sides
surfaceBuilder->currentEdge * 2
// round up just in case
+ 2
) / 3;
int possibleTriangleCount = surfaceBuilder->currentEdge / 3;
builderState.triangles = stackMalloc(sizeof(struct GfxTraingleIndices) * possibleTriangleCount);
builderState.triangleCount = 0;

View file

@ -72,31 +72,34 @@ class Vertex:
return Vertex(self.x * scalar, self.y * scalar)
class Edge:
def __init__(self, aIndex, bIndex, nextEdge, prevEdge, nextEdgeReverse, prevEdgeReverse):
self.aIndex = aIndex
self.bIndex = bIndex
self.nextEdge = nextEdge
self.prevEdge = prevEdge
self.nextEdgeReverse = nextEdgeReverse
self.prevEdgeReverse = prevEdgeReverse
def __init__(self, pointIndex, nextEdge, prevEdge, reverseEdge):
self.pointIndex = int(pointIndex)
self.nextEdge = int(nextEdge)
self.prevEdge = int(prevEdge)
self.reverseEdge = int(reverseEdge)
def __repr__(self):
return "Edge(" + str(self.aIndex) + ", " + str(self.bIndex) + ", " + str(self.nextEdge) + ", " + str(self.prevEdge) + ", " + str(self.nextEdgeReverse) + ", " + str(self.prevEdgeReverse) + ")"
return "Edge(" + str(self.pointIndex) + ", " + str(self.nextEdge) + ", " + str(self.prevEdge) + ", " + str(self.reverseEdge) + ")"
next_color = [0.1, 0.2, 0]
prev_color = [0.2, 0.1, 0]
next_color_reverse = [0.15, 0.2, 0]
prev_color_reverse = [0.2, 0.15, 0]
class SurfaceConnections:
def __init__(self, vertices, edges):
self.vertices = vertices
self.edges = edges
def generate_connection(self, fromEdge, toEdge, color, vertex_pos, vertex_color, indices):
fromMidpoint = self.vertices[fromEdge.aIndex].midpoint(self.vertices[fromEdge.bIndex])
toMidpoint = self.vertices[toEdge.aIndex].midpoint(self.vertices[toEdge.bIndex])
if fromEdge.pointIndex >= len(self.vertices) or toEdge.pointIndex >= len(self.vertices):
return
if fromEdge.nextEdge >= len(self.edges) or toEdge.nextEdge >= len(self.edges):
return
if self.edges[fromEdge.nextEdge].pointIndex >= len(self.vertices) or self.edges[toEdge.nextEdge].pointIndex >= len(self.vertices):
return
fromMidpoint = self.vertices[fromEdge.pointIndex].midpoint(self.vertices[self.edges[fromEdge.nextEdge].pointIndex])
toMidpoint = self.vertices[toEdge.pointIndex].midpoint(self.vertices[self.edges[toEdge.nextEdge].pointIndex])
midpointMidpoint = fromMidpoint.midpoint(toMidpoint)
@ -141,8 +144,14 @@ class SurfaceConnections:
curr_vertex = int(len(vertex_pos) / 3)
pointA = self.vertices[edge.aIndex]
pointB = self.vertices[edge.bIndex]
if edge.nextEdge >= len(self.edges) or self.edges[edge.nextEdge].pointIndex >= len(self.vertices):
continue
if edge.pointIndex >= len(self.vertices):
continue
pointA = self.vertices[edge.pointIndex]
pointB = self.vertices[self.edges[edge.nextEdge].pointIndex]
vertex_pos.append(pointA.x)
vertex_pos.append(pointA.y)
@ -171,12 +180,6 @@ class SurfaceConnections:
if edge.prevEdge != 255:
self.generate_connection(edge, self.edges[edge.prevEdge], prev_color, vertex_pos, vertex_color, indices)
if edge.nextEdgeReverse != 255:
self.generate_connection(edge, self.edges[edge.nextEdgeReverse], next_color_reverse, vertex_pos, vertex_color, indices)
if edge.prevEdgeReverse != 255:
self.generate_connection(edge, self.edges[edge.prevEdgeReverse], prev_color_reverse, vertex_pos, vertex_color, indices)
array_type = (gl.GLfloat * len(vertex_pos))
@ -225,8 +228,20 @@ class SurfaceConnections:
def distance_to_edge(self, edge_index, from_point):
edge = self.edges[edge_index]
a = self.vertices[edge.aIndex]
b = self.vertices[edge.bIndex]
a = self.vertices[edge.pointIndex]
if edge.nextEdge == 255:
return 10000000000000
if edge.nextEdge >= len(self.edges):
print("WARNING: " + str(edge.nextEdge) + " is an invalid edge index")
return 10000000000000
if self.edges[edge.nextEdge].pointIndex >= len(self.vertices):
print("WARNING: " + str(self.edges[edge.nextEdge].pointIndex) + " is an invalid vertex index")
return 10000000000000
b = self.vertices[self.edges[edge.nextEdge].pointIndex]
edge_dir = b.sub(a)
point_dir = from_point.sub(a)
@ -354,13 +369,12 @@ def extract_surface_data(surfaceBuilder):
for edge_index in range(0, edge_count):
input_edge = input_edges[edge_index]
output_edges.append(Edge(
input_edge["aIndex"],
input_edge["bIndex"],
input_edge["pointIndex"],
input_edge["nextEdge"],
input_edge["prevEdge"],
input_edge["nextEdgeReverse"],
input_edge["prevEdgeReverse"]
input_edge["reverseEdge"]
))
return SurfaceConnections(output_vertices, output_edges)
@ -435,8 +449,15 @@ def main():
closest_edge = surface.edges[closest_edge_index]
print(f"Edge index {closest_edge_index}")
print(closest_edge)
print(surface.vertices[closest_edge.aIndex])
print(surface.vertices[closest_edge.bIndex])
print(f"Vertex index {closest_edge.pointIndex}")
print(surface.vertices[closest_edge.pointIndex])
print(f"Next vertex index {surface.edges[closest_edge.nextEdge].pointIndex}")
print(surface.vertices[surface.edges[closest_edge.nextEdge].pointIndex])
if closest_edge.reverseEdge != 255:
print(f"Reverse edge index {closest_edge.reverseEdge}")
print(surface.edges[closest_edge.reverseEdge])
last_button = current_button