fix two other bugs in the same function
[xonotic/netradiant.git] / tools / quake3 / q3map2 / tjunction.c
index 0c322c729cb87059b1667f58ae2dd71edc20c923..f274f9580a38cff8791ce0608e5b119093272234 100644 (file)
@@ -55,7 +55,7 @@ typedef struct edgeLine_s {
        vec3_t          origin;
        vec3_t          dir;
 
-       edgePoint_t     chain;          // unused element of doubly linked list
+       edgePoint_t     *chain;         // unused element of doubly linked list
 } edgeLine_t;
 
 typedef struct {
@@ -63,14 +63,14 @@ typedef struct {
        bspDrawVert_t   *dv[2];
 } originalEdge_t;
 
-#define        MAX_ORIGINAL_EDGES      0x100000
-originalEdge_t originalEdges[MAX_ORIGINAL_EDGES];
+originalEdge_t *originalEdges = NULL;
 int                            numOriginalEdges;
+int                            allocatedOriginalEdges = 0;
 
 
-#define        MAX_EDGE_LINES          0x100000
-edgeLine_t             edgeLines[MAX_EDGE_LINES];
+edgeLine_t             *edgeLines = NULL;
 int                            numEdgeLines;
+int                            allocatedEdgeLines = 0;
 
 int                            c_degenerateEdges;
 int                            c_addedVerts;
@@ -100,14 +100,14 @@ void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) {
        p->intercept = d;
        VectorCopy( v, p->xyz );
 
-       if ( e->chain.next == &e->chain ) {
-               e->chain.next = e->chain.prev = p;
-               p->next = p->prev = &e->chain;
+       if ( e->chain->next == e->chain ) {
+               e->chain->next = e->chain->prev = p;
+               p->next = p->prev = e->chain;
                return;
        }
 
-       scan = e->chain.next;
-       for ( ; scan != &e->chain ; scan = scan->next ) {
+       scan = e->chain->next;
+       for ( ; scan != e->chain ; scan = scan->next ) {
                d = p->intercept - scan->intercept;
                if ( d > -LINE_POSITION_EPSILON && d < LINE_POSITION_EPSILON ) {
                        free( p );
@@ -153,9 +153,7 @@ int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) {
 
        if ( !createNonAxial ) {
                if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) {
-                       if ( numOriginalEdges == MAX_ORIGINAL_EDGES ) {
-                               Error( "MAX_ORIGINAL_EDGES" );
-                       }
+                       AUTOEXPAND_BY_REALLOC(originalEdges, numOriginalEdges, allocatedOriginalEdges, 1024);
                        originalEdges[ numOriginalEdges ].dv[0] = (bspDrawVert_t *)v1;
                        originalEdges[ numOriginalEdges ].dv[1] = (bspDrawVert_t *)v2;
                        originalEdges[ numOriginalEdges ].length = d;
@@ -192,14 +190,13 @@ int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) {
        }
 
        // create a new edge
-       if ( numEdgeLines >= MAX_EDGE_LINES ) {
-               Error( "MAX_EDGE_LINES" );
-       }
+       AUTOEXPAND_BY_REALLOC(edgeLines, numEdgeLines, allocatedEdgeLines, 1024);
 
        e = &edgeLines[ numEdgeLines ];
        numEdgeLines++;
 
-       e->chain.next = e->chain.prev = &e->chain;
+       e->chain = safe_malloc( sizeof(edgePoint_t) );
+       e->chain->next = e->chain->prev = e->chain;
 
        VectorCopy( v1, e->origin );
        VectorCopy( dir, e->dir );
@@ -377,12 +374,12 @@ void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
 
 
                if ( start < end ) {
-                       p = e->chain.next;
+                       p = e->chain->next;
                } else {
-                       p = e->chain.prev;
+                       p = e->chain->prev;
                }
 
-               for (  ; p != &e->chain ;  ) {
+               for (  ; p != e->chain ;  ) {
                        if ( start < end ) {
                                if ( p->intercept > end - ON_EPSILON ) {
                                        break;
@@ -519,7 +516,6 @@ int         c_broken = 0;
 
 qboolean FixBrokenSurface( mapDrawSurface_t *ds )
 {
-       qboolean        valid = qtrue;
        bspDrawVert_t   *dv1, *dv2, avg;
        int                     i, j, k;
        float           dist;
@@ -534,10 +530,6 @@ qboolean FixBrokenSurface( mapDrawSurface_t *ds )
        /* check all verts */
        for( i = 0; i < ds->numVerts; i++ )
        {
-               /* don't remove points if winding is a triangle */
-               if( ds->numVerts == 3 )
-                       return valid;
-               
                /* get verts */
                dv1 = &ds->verts[ i ];
                dv2 = &ds->verts[ (i + 1) % ds->numVerts ];
@@ -547,7 +539,6 @@ qboolean FixBrokenSurface( mapDrawSurface_t *ds )
                dist = VectorLength( avg.xyz );
                if( dist < DEGENERATE_EPSILON )
                {
-                       valid = qfalse;
                        Sys_FPrintf( SYS_VRB, "WARNING: Degenerate T-junction edge found, fixing...\n" );
 
                        /* create an average drawvert */
@@ -581,13 +572,16 @@ qboolean FixBrokenSurface( mapDrawSurface_t *ds )
                                memcpy( dv2, dv1, sizeof( bspDrawVert_t ) );
                        }
                        ds->numVerts--;
+                       
+                       /* after welding, we have to consider the same vertex again, as it now has a new neighbor dv2 */
+                       --i;
+
+                       /* should ds->numVerts have become 0, then i is now -1. In the next iteration, the loop will abort. */
                }
        }
        
        /* one last check and return */
-       if( ds->numVerts < 3 )
-               valid = qfalse;
-       return valid;
+       return ds->numVerts >= 3;
 }
 
 
@@ -632,7 +626,7 @@ void FixTJunctions( entity_t *ent )
        shaderInfo_t            *si;
        int                                     axialEdgeLines;
        originalEdge_t          *e;
-       
+       bspDrawVert_t   *dv;
        
        /* meta mode has its own t-junction code (currently not as good as this code) */
        //%     if( meta )
@@ -683,7 +677,8 @@ void FixTJunctions( entity_t *ent )
        // this gives the most accurate edge description
        for ( i = 0 ; i < numOriginalEdges ; i++ ) {
                e = &originalEdges[i];
-               e->dv[ 0 ]->lightmap[ 0 ][ 0 ] = AddEdge( e->dv[ 0 ]->xyz, e->dv[ 1 ]->xyz, qtrue );
+               dv = e->dv[0]; // e might change during AddEdge
+               dv->lightmap[ 0 ][ 0 ] = AddEdge( e->dv[ 0 ]->xyz, e->dv[ 1 ]->xyz, qtrue );
        }
 
        Sys_FPrintf( SYS_VRB, "%9d axial edge lines\n", axialEdgeLines );