From 7f1d04962e956c30121223a747db4c33b05b8732 Mon Sep 17 00:00:00 2001 From: curt Date: Sat, 16 May 1998 13:09:57 +0000 Subject: [PATCH] Beginning to add support for view frustum culling. Added some temporary code to calculate bouding radius, until the scenery generation tools and scenery can be updated. --- Scenery/obj.cxx | 49 +++++++-------- Scenery/tilecache.cxx | 14 ++++- Scenery/tilecache.hxx | 16 +++-- Scenery/tilemgr.cxx | 135 ++++++++++++++++++++++++++++-------------- 4 files changed, 139 insertions(+), 75 deletions(-) diff --git a/Scenery/obj.cxx b/Scenery/obj.cxx index 53bb6985e..f7e635f2d 100644 --- a/Scenery/obj.cxx +++ b/Scenery/obj.cxx @@ -56,7 +56,8 @@ static double normals[MAXNODES][3]; /* given three points defining a triangle, calculate the normal */ -void calc_normal(double p1[3], double p2[3], double p3[3], double normal[3]) +static void calc_normal(double p1[3], double p2[3], + double p3[3], double normal[3]) { double v1[3], v2[3]; double temp; @@ -93,12 +94,19 @@ fgPolarPoint3d calc_tex_coords(double *node, fgCartesianPoint3d *ref) { } +// Calculate distance between (0,0,0) and the specified point +static double calc_dist(double *p) { + return ( sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]) ); +} + + /* Load a .obj file and generate the GL call list */ GLint fgObjLoad(char *path, fgCartesianPoint3d *ref, double *radius) { fgOPTIONS *o; + fgCartesianPoint3d cp; fgPolarPoint3d pp; char fgpath[256], line[256], winding_str[256]; - double approx_normal[3], normal[3], scale; + double approx_normal[3], normal[3], scale, dist; // double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin; // GLfloat sgenparams[] = { 1.0, 0.0, 0.0, 0.0 }; GLint tile; @@ -146,6 +154,7 @@ GLint fgObjLoad(char *path, fgCartesianPoint3d *ref, double *radius) { first = 1; ncount = 1; vncount = 1; + *radius = 0.0; while ( fggets(f, line, 250) != NULL ) { if ( line[0] == '#' ) { @@ -163,27 +172,14 @@ GLint fgObjLoad(char *path, fgCartesianPoint3d *ref, double *radius) { &nodes[ncount][0], &nodes[ncount][1], &nodes[ncount][2]); - /* first time through set min's and max'es */ - /* - if ( ncount == 1 ) { - xmin = x; - xmax = x; - ymin = y; - ymax = y; - zmin = z; - zmax = z; + // temporary code to calculate bounding radius + dist = calc_dist(nodes[ncount]); + // printf("node = %.2f %.2f %.2f dist = %.2f\n", + // nodes[ncount][0], nodes[ncount][1], nodes[ncount][2], + // dist); + if ( (dist > *radius) && (dist < 100000.0) ) { + *radius = dist; } - */ - - /* keep track of min/max vertex values */ - /* - if ( x < xmin ) xmin = x; - if ( x > xmax ) xmax = x; - if ( y < ymin ) ymin = y; - if ( y > ymax ) ymax = y; - if ( z < zmin ) zmin = z; - if ( z > zmax ) zmax = z; - */ ncount++; } else { @@ -448,9 +444,14 @@ GLint fgObjLoad(char *path, fgCartesianPoint3d *ref, double *radius) { /* $Log$ -/* Revision 1.3 1998/05/03 00:48:01 curt -/* Updated texture coordinate fmod() parameter. +/* Revision 1.4 1998/05/16 13:09:57 curt +/* Beginning to add support for view frustum culling. +/* Added some temporary code to calculate bouding radius, until the +/* scenery generation tools and scenery can be updated. /* + * Revision 1.3 1998/05/03 00:48:01 curt + * Updated texture coordinate fmod() parameter. + * * Revision 1.2 1998/05/02 01:52:14 curt * Playing around with texture coordinates. * diff --git a/Scenery/tilecache.cxx b/Scenery/tilecache.cxx index dc1bb3200..61c5b6194 100644 --- a/Scenery/tilecache.cxx +++ b/Scenery/tilecache.cxx @@ -131,13 +131,16 @@ void fgTileCacheEntryFree( int index ) { /* Return info for a tile cache entry */ void fgTileCacheEntryInfo( int index, GLint *display_list, - fgCartesianPoint3d *local_ref ) { + fgCartesianPoint3d *local_ref, + double *radius ) { *display_list = tile_cache[index].display_list; /* fgPrintf(FG_TERRAIN, FG_DEBUG, "Display list = %d\n", *display_list); */ local_ref->x = tile_cache[index].local_ref.x; local_ref->y = tile_cache[index].local_ref.y; local_ref->z = tile_cache[index].local_ref.z; + + *radius = tile_cache[index].bounding_radius; } @@ -199,9 +202,14 @@ int fgTileCacheNextAvail( void ) { /* $Log$ -/* Revision 1.7 1998/05/13 18:26:41 curt -/* Root path info moved to fgOPTIONS. +/* Revision 1.8 1998/05/16 13:09:57 curt +/* Beginning to add support for view frustum culling. +/* Added some temporary code to calculate bouding radius, until the +/* scenery generation tools and scenery can be updated. /* + * Revision 1.7 1998/05/13 18:26:41 curt + * Root path info moved to fgOPTIONS. + * * Revision 1.6 1998/05/02 01:52:17 curt * Playing around with texture coordinates. * diff --git a/Scenery/tilecache.hxx b/Scenery/tilecache.hxx index 436602a62..9d2080880 100644 --- a/Scenery/tilecache.hxx +++ b/Scenery/tilecache.hxx @@ -49,7 +49,7 @@ /* For best results ... i.e. to avoid tile load problems and blank areas * - * FG_TILE_CACHE_SIZE >= (o->tile_radius + 1) ** 2 */ + * FG_TILE_CACHE_SIZE >= (o->tile_diameter + 1) ** 2 */ #define FG_TILE_CACHE_SIZE 121 @@ -81,17 +81,23 @@ void fgTileCacheEntryFillIn( int index, struct fgBUCKET *p ); /* Return info for a tile cache entry */ void fgTileCacheEntryInfo( int index, GLint *display_list, - fgCartesianPoint3d *local_ref ); + fgCartesianPoint3d *local_ref, + double *radius ); #endif /* _TILECACHE_HXX */ /* $Log$ -/* Revision 1.6 1998/05/07 23:15:20 curt -/* Fixed a glTexImage2D() usage bug where width and height were mis-swapped. -/* Added support for --tile-radius=n option. +/* Revision 1.7 1998/05/16 13:09:57 curt +/* Beginning to add support for view frustum culling. +/* Added some temporary code to calculate bouding radius, until the +/* scenery generation tools and scenery can be updated. /* + * Revision 1.6 1998/05/07 23:15:20 curt + * Fixed a glTexImage2D() usage bug where width and height were mis-swapped. + * Added support for --tile-radius=n option. + * * Revision 1.5 1998/05/02 01:52:17 curt * Playing around with texture coordinates. * diff --git a/Scenery/tilemgr.cxx b/Scenery/tilemgr.cxx index df64c5993..dbf36ac22 100644 --- a/Scenery/tilemgr.cxx +++ b/Scenery/tilemgr.cxx @@ -45,9 +45,11 @@ #include #include #include
+#include
+#include -#define FG_LOCAL_X_Y 81 /* max(o->tile_radius) ** 2 */ +#define FG_LOCAL_X_Y 81 /* max(o->tile_diameter) ** 2 */ /* closest (potentially viewable) tiles, centered on current tile. @@ -90,8 +92,8 @@ int fgTileMgrUpdate( void ) { o = ¤t_options; fgBucketFind(FG_Longitude * RAD_TO_DEG, FG_Latitude * RAD_TO_DEG, &p1); - dw = o->tile_radius / 2; - dh = o->tile_radius / 2; + dw = o->tile_diameter / 2; + dh = o->tile_diameter / 2; if ( (p1.lon == p_last.lon) && (p1.lat == p_last.lat) && (p1.x == p_last.x) && (p1.y == p_last.y) ) { @@ -105,16 +107,16 @@ int fgTileMgrUpdate( void ) { fgPrintf( FG_TERRAIN, FG_INFO, " Updating Tile list for %d,%d %d,%d\n", p1.lon, p1.lat, p1.x, p1.y); fgPrintf( FG_TERRAIN, FG_INFO, " Loading %d tiles\n", - o->tile_radius * o->tile_radius); + o->tile_diameter * o->tile_diameter); /* wipe tile cache */ fgTileCacheInit(); /* build the local area list and update cache */ - for ( j = 0; j < o->tile_radius; j++ ) { - for ( i = 0; i < o->tile_radius; i++ ) { + for ( j = 0; j < o->tile_diameter; j++ ) { + for ( i = 0; i < o->tile_diameter; i++ ) { fgBucketOffset(&p1, &p2, i - dw, j - dh); - fgTileMgrLoadTile(&p2, &tiles[(j*o->tile_radius) + i]); + fgTileMgrLoadTile(&p2, &tiles[(j*o->tile_diameter) + i]); } } } else { @@ -131,54 +133,54 @@ int fgTileMgrUpdate( void ) { if ( (p1.lon > p_last.lon) || ( (p1.lon == p_last.lon) && (p1.x > p_last.x) ) ) { fgPrintf( FG_TERRAIN, FG_INFO, " Loading %d tiles\n", - o->tile_radius); - for ( j = 0; j < o->tile_radius; j++ ) { + o->tile_diameter); + for ( j = 0; j < o->tile_diameter; j++ ) { /* scrolling East */ - for ( i = 0; i < o->tile_radius - 1; i++ ) { - tiles[(j*o->tile_radius) + i] = tiles[(j*o->tile_radius) + i + 1]; + for ( i = 0; i < o->tile_diameter - 1; i++ ) { + tiles[(j*o->tile_diameter) + i] = tiles[(j*o->tile_diameter) + i + 1]; } /* load in new column */ fgBucketOffset(&p_last, &p2, dw + 1, j - dh); - fgTileMgrLoadTile(&p2, &tiles[(j*o->tile_radius) + o->tile_radius - 1]); + fgTileMgrLoadTile(&p2, &tiles[(j*o->tile_diameter) + o->tile_diameter - 1]); } } else if ( (p1.lon < p_last.lon) || ( (p1.lon == p_last.lon) && (p1.x < p_last.x) ) ) { fgPrintf( FG_TERRAIN, FG_INFO, " Loading %d tiles\n", - o->tile_radius); - for ( j = 0; j < o->tile_radius; j++ ) { + o->tile_diameter); + for ( j = 0; j < o->tile_diameter; j++ ) { /* scrolling West */ - for ( i = o->tile_radius - 1; i > 0; i-- ) { - tiles[(j*o->tile_radius) + i] = tiles[(j*o->tile_radius) + i - 1]; + for ( i = o->tile_diameter - 1; i > 0; i-- ) { + tiles[(j*o->tile_diameter) + i] = tiles[(j*o->tile_diameter) + i - 1]; } /* load in new column */ fgBucketOffset(&p_last, &p2, -dw - 1, j - dh); - fgTileMgrLoadTile(&p2, &tiles[(j*o->tile_radius) + 0]); + fgTileMgrLoadTile(&p2, &tiles[(j*o->tile_diameter) + 0]); } } if ( (p1.lat > p_last.lat) || ( (p1.lat == p_last.lat) && (p1.y > p_last.y) ) ) { fgPrintf( FG_TERRAIN, FG_INFO, " Loading %d tiles\n", - o->tile_radius); - for ( i = 0; i < o->tile_radius; i++ ) { + o->tile_diameter); + for ( i = 0; i < o->tile_diameter; i++ ) { /* scrolling North */ - for ( j = 0; j < o->tile_radius - 1; j++ ) { - tiles[(j * o->tile_radius) + i] = - tiles[((j+1) * o->tile_radius) + i]; + for ( j = 0; j < o->tile_diameter - 1; j++ ) { + tiles[(j * o->tile_diameter) + i] = + tiles[((j+1) * o->tile_diameter) + i]; } /* load in new column */ fgBucketOffset(&p_last, &p2, i - dw, dh + 1); - fgTileMgrLoadTile(&p2, &tiles[((o->tile_radius-1)*o->tile_radius) + i]); + fgTileMgrLoadTile(&p2, &tiles[((o->tile_diameter-1)*o->tile_diameter) + i]); } } else if ( (p1.lat < p_last.lat) || ( (p1.lat == p_last.lat) && (p1.y < p_last.y) ) ) { fgPrintf( FG_TERRAIN, FG_INFO, " Loading %d tiles\n", - o->tile_radius); - for ( i = 0; i < o->tile_radius; i++ ) { + o->tile_diameter); + for ( i = 0; i < o->tile_diameter; i++ ) { /* scrolling South */ - for ( j = o->tile_radius - 1; j > 0; j-- ) { - tiles[(j * o->tile_radius) + i] = - tiles[((j-1) * o->tile_radius) + i]; + for ( j = o->tile_diameter - 1; j > 0; j-- ) { + tiles[(j * o->tile_diameter) + i] = + tiles[((j-1) * o->tile_diameter) + i]; } /* load in new column */ fgBucketOffset(&p_last, &p2, i - dw, -dh - 1); @@ -194,15 +196,47 @@ int fgTileMgrUpdate( void ) { } +// Calculate if point/radius is inside view frustum +// +static int viewable( fgCartesianPoint3d *cp, double radius ) { + fgVIEW *v; + MAT3hvec world, eye; + int viewable = 1; // start by assuming it's viewable + + v = ¤t_view; + + MAT3_SET_HVEC(world, cp->x, cp->y, cp->z, 1.0); + MAT3mult_vec(eye, world, v->WORLD_TO_EYE); + // printf( "\nworld -> eye = %.2f %.2f %.2f radius = %.2f\n", + // eye[0], eye[1], eye[2], radius); + + if ( eye[2] - radius > 0.0 ) { + // Check near clip plane + viewable = 0; + } else if ( eye[1] < -(v->slope_x) * (eye[0] + radius) ) { + // Check left edge + // y = m * (x - x0) = equation of a line intercepting X axis at x0 + printf( "eye[1] = %.2f slope_x = %.2f radius = %.2f\n", + eye[1], v->slope_x, radius); + viewable = 0; + } + + return(viewable); +} + + /* Render the local tiles */ void fgTileMgrRender( void ) { fgFLIGHT *f; fgOPTIONS *o; struct fgBUCKET p; - fgCartesianPoint3d local_ref; + fgCartesianPoint3d local_ref, offset; GLint display_list; + double radius; int i; int index; + int culled = 0; + int drawn = 0; f = current_aircraft.flight; o = ¤t_options; @@ -210,37 +244,52 @@ void fgTileMgrRender( void ) { /* Find current translation offset */ fgBucketFind(FG_Longitude * RAD_TO_DEG, FG_Latitude * RAD_TO_DEG, &p); index = fgTileCacheExists(&p); - fgTileCacheEntryInfo(index, &display_list, &scenery.next_center ); + fgTileCacheEntryInfo(index, &display_list, &scenery.next_center, &radius ); fgPrintf( FG_TERRAIN, FG_DEBUG, "Pos = (%.2f, %.2f) Current bucket = %d %d %d %d Index = %ld\n", FG_Longitude * RAD_TO_DEG, FG_Latitude * RAD_TO_DEG, p.lon, p.lat, p.x, p.y, fgBucketGenIndex(&p) ); - for ( i = 0; i < (o->tile_radius * o->tile_radius); i++ ) { + for ( i = 0; i < (o->tile_diameter * o->tile_diameter); i++ ) { index = tiles[i]; /* fgPrintf( FG_TERRAIN, FG_DEBUG, "Index = %d\n", index); */ - fgTileCacheEntryInfo(index, &display_list, &local_ref ); + fgTileCacheEntryInfo(index, &display_list, &local_ref, &radius ); if ( display_list >= 0 ) { - xglPushMatrix(); - xglTranslatef(local_ref.x - scenery.center.x, - local_ref.y - scenery.center.y, - local_ref.z - scenery.center.z); - /* xglTranslatef(-scenery.center.x, -scenery.center.y, - -scenery.center.z); */ - xglCallList(display_list); - xglPopMatrix(); + + offset.x = local_ref.x - scenery.center.x; + offset.y = local_ref.y - scenery.center.y; + offset.z = local_ref.z - scenery.center.z; + + if ( viewable(&offset, radius) ) { + drawn++; + xglPushMatrix(); + xglTranslatef(offset.x, offset.y, offset.z); + xglCallList(display_list); + xglPopMatrix(); + } else { + culled++; + } } } + + printf("drawn = %d culled = %d saved = %.2f\n", drawn, culled, + (double)culled / (double)(drawn + culled)); + } /* $Log$ -/* Revision 1.8 1998/05/07 23:15:21 curt -/* Fixed a glTexImage2D() usage bug where width and height were mis-swapped. -/* Added support for --tile-radius=n option. +/* Revision 1.9 1998/05/16 13:09:58 curt +/* Beginning to add support for view frustum culling. +/* Added some temporary code to calculate bouding radius, until the +/* scenery generation tools and scenery can be updated. /* + * Revision 1.8 1998/05/07 23:15:21 curt + * Fixed a glTexImage2D() usage bug where width and height were mis-swapped. + * Added support for --tile-radius=n option. + * * Revision 1.7 1998/05/06 03:16:42 curt * Added an option to control square tile radius. * -- 2.39.2