void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back ){ int w, h, split; float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE]; bspDrawVert_t *dv, *v1, *v2; int c_front, c_back, c_on; mesh_t *f, *b; int i; float frac; int frontAprox, backAprox; for ( i = 0 ; i < 2 ; i++ ) { dv = in->verts; c_front = 0; c_back = 0; c_on = 0; for ( h = 0 ; h < in->height ; h++ ) { for ( w = 0 ; w < in->width ; w++, dv++ ) { d[h][w] = DotProduct( dv->xyz, normal ) - dist; if ( d[h][w] > ON_EPSILON ) { c_front++; } else if ( d[h][w] < -ON_EPSILON ) { c_back++; } else { c_on++; } } } *front = NULL; *back = NULL; if ( !c_front ) { *back = in; return; } if ( !c_back ) { *front = in; return; } // find a split point split = -1; for ( w = 0 ; w < in->width - 1 ; w++ ) { if ( ( d[0][w] < 0 ) != ( d[0][w + 1] < 0 ) ) { if ( split == -1 ) { split = w; break; } } } if ( split == -1 ) { if ( i == 1 ) { Sys_FPrintf( SYS_VRB, "No crossing points in patch\n" ); *front = in; return; } in = TransposeMesh( in ); InvertMesh( in ); continue; } // make sure the split point stays the same for all other rows for ( h = 1 ; h < in->height ; h++ ) { for ( w = 0 ; w < in->width - 1 ; w++ ) { if ( ( d[h][w] < 0 ) != ( d[h][w + 1] < 0 ) ) { if ( w != split ) { Sys_Printf( "multiple crossing points for patch -- can't clip\n" ); *front = in; return; } } } if ( ( d[h][split] < 0 ) == ( d[h][split + 1] < 0 ) ) { Sys_Printf( "differing crossing points for patch -- can't clip\n" ); *front = in; return; } } break; } // create two new meshes f = safe_malloc( sizeof( *f ) ); f->width = split + 2; if ( !( f->width & 1 ) ) { f->width++; frontAprox = 1; } else { frontAprox = 0; } if ( f->width > MAX_PATCH_SIZE ) { Error( "MAX_PATCH_SIZE after split" ); } f->height = in->height; f->verts = safe_malloc( sizeof( f->verts[0] ) * f->width * f->height ); b = safe_malloc( sizeof( *b ) ); b->width = in->width - split; if ( !( b->width & 1 ) ) { b->width++; backAprox = 1; } else { backAprox = 0; } if ( b->width > MAX_PATCH_SIZE ) { Error( "MAX_PATCH_SIZE after split" ); } b->height = in->height; b->verts = safe_malloc( sizeof( b->verts[0] ) * b->width * b->height ); if ( d[0][0] > 0 ) { *front = f; *back = b; } else { *front = b; *back = f; } // distribute the points for ( w = 0 ; w < in->width ; w++ ) { for ( h = 0 ; h < in->height ; h++ ) { if ( w <= split ) { f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ]; } else { b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ]; } } } // clip the crossing line for ( h = 0; h < in->height; h++ ) { dv = &f->verts[ h * f->width + split + 1 ]; v1 = &in->verts[ h * in->width + split ]; v2 = &in->verts[ h * in->width + split + 1 ]; frac = d[h][split] / ( d[h][split] - d[h][split + 1] ); /* interpolate */ //% for( i = 0; i < 10; i++ ) //% dv->xyz[ i ] = v1->xyz[ i ] + frac * (v2->xyz[ i ] - v1->xyz[ i ]); //% dv->xyz[10] = 0; // set all 4 colors to 0 LerpDrawVertAmount( v1, v2, frac, dv ); if ( frontAprox ) { f->verts[ h * f->width + split + 2 ] = *dv; } b->verts[ h * b->width ] = *dv; if ( backAprox ) { b->verts[ h * b->width + 1 ] = *dv; } } /* PrintMesh( in ); Sys_Printf("\n"); PrintMesh( f ); Sys_Printf("\n"); PrintMesh( b ); Sys_Printf("\n"); */ FreeMesh( in ); }
/* ================= SubdivideMeshQuads ================= */ mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable ) { int i, j, k, w, h, maxsubdivisions, subdivisions; vec3_t dir; float length, maxLength, amount; mesh_t out; bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; out.width = in->width; out.height = in->height; for ( i = 0 ; i < in->width ; i++ ) { for ( j = 0 ; j < in->height ; j++ ) { expand[j][i] = in->verts[j*in->width+i]; } } if (maxsize > MAX_EXPANDED_AXIS) Error("SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS"); // horizontal subdivisions maxsubdivisions = (maxsize - in->width) / (in->width - 1); for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1) { maxLength = 0; for ( i = 0 ; i < out.height ; i++ ) { VectorSubtract(expand[i][j+1].xyz, expand[i][j].xyz, dir); length = VectorLength( dir ); if (length > maxLength) { maxLength = length; } } subdivisions = (int) (maxLength / minLength); if (subdivisions > maxsubdivisions) subdivisions = maxsubdivisions; widthtable[w] = subdivisions + 1; if (subdivisions <= 0) continue; out.width += subdivisions; for ( i = 0 ; i < out.height ; i++ ) { for ( k = out.width - 1 ; k > j + subdivisions; k-- ) { expand[i][k] = expand[i][k-subdivisions]; } for (k = 1; k <= subdivisions; k++) { amount = (float) k / (subdivisions + 1); LerpDrawVertAmount(&expand[i][j], &expand[i][j+subdivisions+1], amount, &expand[i][j+k]); } } } maxsubdivisions = (maxsize - in->height) / (in->height - 1); for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1) { maxLength = 0; for ( i = 0 ; i < out.width ; i++ ) { VectorSubtract(expand[j+1][i].xyz, expand[j][i].xyz, dir); length = VectorLength( dir ); if (length > maxLength) { maxLength = length; } } subdivisions = (int) (maxLength / minLength); if (subdivisions > maxsubdivisions) subdivisions = maxsubdivisions; heighttable[h] = subdivisions + 1; if (subdivisions <= 0) continue; out.height += subdivisions; for ( i = 0 ; i < out.width ; i++ ) { for ( k = out.height - 1 ; k > j + subdivisions; k-- ) { expand[k][i] = expand[k-subdivisions][i]; } for (k = 1; k <= subdivisions; k++) { amount = (float) k / (subdivisions + 1); LerpDrawVertAmount(&expand[j][i], &expand[j+subdivisions+1][i], amount, &expand[j+k][i]); } } } // collapse the verts out.verts = &expand[0][0]; for ( i = 1 ; i < out.height ; i++ ) { memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) ); } return CopyMesh(&out); }
void FixMetaTJunctions( void ){ int i, j, k, f, fOld, start, vertIndex, triIndex, numTJuncs; metaTriangle_t *tri, *newTri; shaderInfo_t *si; bspDrawVert_t *a, *b, *c, junc; float dist, amount; vec3_t pt; vec4_t plane; edge_t edges[ 3 ]; /* this code is crap; revisit later */ return; /* note it */ Sys_FPrintf( SYS_VRB, "--- FixMetaTJunctions ---\n" ); /* init pacifier */ fOld = -1; start = I_FloatTime(); /* walk triangle list */ numTJuncs = 0; for ( i = 0; i < numMetaTriangles; i++ ) { /* get triangle */ tri = &metaTriangles[ i ]; /* print pacifier */ f = 10 * i / numMetaTriangles; if ( f != fOld ) { fOld = f; Sys_FPrintf( SYS_VRB, "%d...", f ); } /* attempt to early out */ si = tri->si; if ( ( si->compileFlags & C_NODRAW ) || si->autosprite || si->notjunc ) { continue; } /* calculate planes */ VectorCopy( tri->plane, plane ); plane[ 3 ] = tri->plane[ 3 ]; CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] ); CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] ); CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] ); /* walk meta vert list */ for ( j = 0; j < numMetaVerts; j++ ) { /* get vert */ VectorCopy( metaVerts[ j ].xyz, pt ); /* debug code: darken verts */ if ( i == 0 ) { VectorSet( metaVerts[ j ].color[ 0 ], 8, 8, 8 ); } /* determine if point lies in the triangle's plane */ dist = DotProduct( pt, plane ) - plane[ 3 ]; if ( fabs( dist ) > TJ_PLANE_EPSILON ) { continue; } /* skip this point if it already exists in the triangle */ for ( k = 0; k < 3; k++ ) { if ( fabs( pt[ 0 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 0 ] ) <= TJ_POINT_EPSILON && fabs( pt[ 1 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 1 ] ) <= TJ_POINT_EPSILON && fabs( pt[ 2 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 2 ] ) <= TJ_POINT_EPSILON ) { break; } } if ( k < 3 ) { continue; } /* walk edges */ for ( k = 0; k < 3; k++ ) { /* ignore bogus edges */ if ( fabs( edges[ k ].kingpinLength ) < TJ_EDGE_EPSILON ) { continue; } /* determine if point lies on the edge */ dist = DotProduct( pt, edges[ k ].plane ) - edges[ k ].plane[ 3 ]; if ( fabs( dist ) > TJ_EDGE_EPSILON ) { continue; } /* determine how far along the edge the point lies */ amount = ( pt[ edges[ k ].kingpin ] - edges[ k ].origin[ edges[ k ].kingpin ] ) / edges[ k ].kingpinLength; if ( amount <= 0.0f || amount >= 1.0f ) { continue; } #if 0 dist = DotProduct( pt, edges[ k ].edge ) - edges[ k ].edge[ 3 ]; if ( dist <= -0.0f || dist >= edges[ k ].length ) { continue; } amount = dist / edges[ k ].length; #endif /* debug code: brighten this point */ //% metaVerts[ j ].color[ 0 ][ 0 ] += 5; //% metaVerts[ j ].color[ 0 ][ 1 ] += 4; VectorSet( metaVerts[ tri->indexes[ k ] ].color[ 0 ], 255, 204, 0 ); VectorSet( metaVerts[ tri->indexes[ ( k + 1 ) % 3 ] ].color[ 0 ], 255, 204, 0 ); /* the edge opposite the zero-weighted vertex was hit, so use that as an amount */ a = &metaVerts[ tri->indexes[ k % 3 ] ]; b = &metaVerts[ tri->indexes[ ( k + 1 ) % 3 ] ]; c = &metaVerts[ tri->indexes[ ( k + 2 ) % 3 ] ]; /* make new vert */ LerpDrawVertAmount( a, b, amount, &junc ); VectorCopy( pt, junc.xyz ); /* compare against existing verts */ if ( VectorCompare( junc.xyz, a->xyz ) || VectorCompare( junc.xyz, b->xyz ) || VectorCompare( junc.xyz, c->xyz ) ) { continue; } /* see if we can just re-use the existing vert */ if ( !memcmp( &metaVerts[ j ], &junc, sizeof( junc ) ) ) { vertIndex = j; } else { /* find new vertex (note: a and b are invalid pointers after this) */ firstSearchMetaVert = numMetaVerts; vertIndex = FindMetaVertex( &junc ); if ( vertIndex < 0 ) { continue; } } /* make new triangle */ triIndex = AddMetaTriangle(); if ( triIndex < 0 ) { continue; } /* get triangles */ tri = &metaTriangles[ i ]; newTri = &metaTriangles[ triIndex ]; /* copy the triangle */ memcpy( newTri, tri, sizeof( *tri ) ); /* fix verts */ tri->indexes[ ( k + 1 ) % 3 ] = vertIndex; newTri->indexes[ k ] = vertIndex; /* recalculate edges */ CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] ); CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] ); CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] ); /* debug code */ metaVerts[ vertIndex ].color[ 0 ][ 0 ] = 255; metaVerts[ vertIndex ].color[ 0 ][ 1 ] = 204; metaVerts[ vertIndex ].color[ 0 ][ 2 ] = 0; /* add to counter and end processing of this vert */ numTJuncs++; break; } } } /* print time */ Sys_FPrintf( SYS_VRB, " (%d)\n", (int) ( I_FloatTime() - start ) ); /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d T-junctions added\n", numTJuncs ); }