static void GrowGroup_r( parseMesh_t *pm, int patchNum, int patchCount, parseMesh_t **meshes, byte *bordering, byte *group ) { int i; const byte *row; /* early out check */ if( group[ patchNum ] ) return; /* set it */ group[ patchNum ] = 1; row = bordering + patchNum * patchCount; /* check maximums */ if( meshes[ patchNum ]->longestCurve > pm->longestCurve ) pm->longestCurve = meshes[ patchNum ]->longestCurve; if( meshes[ patchNum ]->maxIterations > pm->maxIterations ) pm->maxIterations = meshes[ patchNum ]->maxIterations; /* walk other patches */ for( i = 0; i < patchCount; i++ ) { if( row[ i ] ) GrowGroup_r( pm, i, patchCount, meshes, bordering, group ); } }
void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) { int i; const byte *row; if ( group[patchNum] ) { return; } group[patchNum] = 1; row = bordering + patchNum * patchCount; for ( i = 0 ; i < patchCount ; i++ ) { if ( row[i] ) { GrowGroup_r( i, patchCount, bordering, group ); } } }
void PatchMapDrawSurfs( entity_t *e ) { int i, j, k, l, c1, c2; parseMesh_t *pm; parseMesh_t *check, *scan; mapDrawSurface_t *ds; int patchCount, groupCount; bspDrawVert_t *v1, *v2; vec3_t bounds[ 2 ]; byte *bordering; /* ydnar: mac os x fails with these if not static */ MAC_STATIC parseMesh_t *meshes[ MAX_MAP_DRAW_SURFS ]; MAC_STATIC qboolean grouped[ MAX_MAP_DRAW_SURFS ]; MAC_STATIC byte group[ MAX_MAP_DRAW_SURFS ]; /* note it */ Sys_FPrintf( SYS_VRB, "--- PatchMapDrawSurfs ---\n" ); /* fetch patches from the entity */ patchCount = 0; for ( pm = e->patches ; pm ; pm = pm->next ) { meshes[patchCount] = pm; patchCount++; } if ( !patchCount ) return; bordering = (byte *)safe_malloc( patchCount * patchCount ); memset( bordering, 0, patchCount * patchCount ); // build the bordering matrix for ( k = 0 ; k < patchCount ; k++ ) { bordering[k*patchCount+k] = 1; for ( l = k+1 ; l < patchCount ; l++ ) { check = meshes[k]; scan = meshes[l]; c1 = scan->mesh.width * scan->mesh.height; v1 = scan->mesh.verts; for ( i = 0 ; i < c1 ; i++, v1++ ) { c2 = check->mesh.width * check->mesh.height; v2 = check->mesh.verts; for ( j = 0 ; j < c2 ; j++, v2++ ) { if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0 && fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0 && fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) { break; } } if ( j != c2 ) { break; } } if ( i != c1 ) { // we have a connection bordering[k*patchCount+l] = bordering[l*patchCount+k] = 1; } else { // no connection bordering[k*patchCount+l] = bordering[l*patchCount+k] = 0; } } } /* build groups */ memset( grouped, 0, patchCount ); groupCount = 0; for ( i = 0; i < patchCount; i++ ) { /* get patch */ scan = meshes[ i ]; /* start a new group */ if( !grouped[ i ] ) groupCount++; /* recursively find all patches that belong in the same group */ memset( group, 0, patchCount ); GrowGroup_r( scan, i, patchCount, meshes, bordering, group ); /* bound them */ ClearBounds( bounds[ 0 ], bounds[ 1 ] ); for( j = 0; j < patchCount; j++ ) { if ( group[ j ] ) { grouped[ j ] = qtrue; check = meshes[ j ]; c1 = check->mesh.width * check->mesh.height; v1 = check->mesh.verts; for( k = 0; k < c1; k++, v1++ ) AddPointToBounds( v1->xyz, bounds[ 0 ], bounds[ 1 ] ); } } /* debug code */ //% Sys_Printf( "Longest curve: %f Iterations: %d\n", scan->longestCurve, scan->maxIterations ); /* create drawsurf */ scan->grouped = qtrue; ds = DrawSurfaceForMesh( e, scan, NULL ); /* ydnar */ VectorCopy( bounds[ 0 ], ds->bounds[ 0 ] ); VectorCopy( bounds[ 1 ], ds->bounds[ 1 ] ); } /* emit some statistics */ Sys_FPrintf( SYS_VRB, "%9d patches\n", patchCount ); Sys_FPrintf( SYS_VRB, "%9d patch LOD groups\n", groupCount ); }
/* ===================== PatchMapDrawSurfs Any patches that share an edge need to choose their level of detail as a unit, otherwise the edges would pull apart. ===================== */ void PatchMapDrawSurfs( entity_t *e ) { parseMesh_t *pm; parseMesh_t *check, *scan; mapDrawSurface_t *ds; int patchCount, groupCount; int i, j, k, l, c1, c2; drawVert_t *v1, *v2; vec3_t bounds[2]; byte *bordering; parseMesh_t *meshes[MAX_MAP_DRAW_SURFS]; qboolean grouped[MAX_MAP_DRAW_SURFS]; byte group[MAX_MAP_DRAW_SURFS]; qprintf( "----- PatchMapDrawSurfs -----\n" ); patchCount = 0; for ( pm = e->patches ; pm ; pm = pm->next ) { meshes[patchCount] = pm; patchCount++; } if ( !patchCount ) { return; } bordering = malloc( patchCount * patchCount ); memset( bordering, 0, patchCount * patchCount ); // build the bordering matrix for ( k = 0 ; k < patchCount ; k++ ) { bordering[k*patchCount+k] = 1; for ( l = k+1 ; l < patchCount ; l++ ) { check = meshes[k]; scan = meshes[l]; c1 = scan->mesh.width * scan->mesh.height; v1 = scan->mesh.verts; for ( i = 0 ; i < c1 ; i++, v1++ ) { c2 = check->mesh.width * check->mesh.height; v2 = check->mesh.verts; for ( j = 0 ; j < c2 ; j++, v2++ ) { if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0 && fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0 && fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) { break; } } if ( j != c2 ) { break; } } if ( i != c1 ) { // we have a connection bordering[k*patchCount+l] = bordering[l*patchCount+k] = 1; } else { // no connection bordering[k*patchCount+l] = bordering[l*patchCount+k] = 0; } } } // build groups memset( grouped, 0, sizeof(grouped) ); groupCount = 0; for ( i = 0 ; i < patchCount ; i++ ) { if ( !grouped[i] ) { groupCount++; } // recursively find all patches that belong in the same group memset( group, 0, patchCount ); GrowGroup_r( i, patchCount, bordering, group ); // bound them ClearBounds( bounds[0], bounds[1] ); for ( j = 0 ; j < patchCount ; j++ ) { if ( group[j] ) { grouped[j] = qtrue; scan = meshes[j]; c1 = scan->mesh.width * scan->mesh.height; v1 = scan->mesh.verts; for ( k = 0 ; k < c1 ; k++, v1++ ) { AddPointToBounds( v1->xyz, bounds[0], bounds[1] ); } } } // create drawsurf scan = meshes[i]; scan->grouped = qtrue; ds = DrawSurfaceForMesh( &scan->mesh ); ds->shaderInfo = scan->shaderInfo; VectorCopy( bounds[0], ds->lightmapVecs[0] ); VectorCopy( bounds[1], ds->lightmapVecs[1] ); } qprintf( "%5i patches\n", patchCount ); qprintf( "%5i patch LOD groups\n", groupCount ); }