]> git.mxchange.org Git - flightgear.git/blobdiff - src/Objects/obj.cxx
Better memory clean up and ocean texture generation. Moved cloud generation
[flightgear.git] / src / Objects / obj.cxx
index 3e7f998d1e350f9704bba8e27493590c7a6a3956..7571dd0d43a00789493384c4931cb82807b88a7a 100644 (file)
 #  include <math.h>
 #endif
 
-#ifdef HAVE_WINDOWS_H
-#  include <windows.h>
-#endif
-
 #include <stdio.h>
 #include <string.h>
-#include <GL/glut.h>
-#include <XGL/xgl.h>
 
 // #if defined ( __sun__ )
 // extern "C" void *memmove(void *, const void *, size_t);
 #include <Include/fg_constants.h>
 #include <Main/options.hxx>
 #include <Math/mat3.h>
+#include <Math/fg_geodesy.hxx>
 #include <Math/fg_random.h>
 #include <Math/point3d.hxx>
 #include <Math/polar3d.hxx>
 #include <Misc/stopwatch.hxx>
+#include <Misc/texcoord.hxx>
 #include <Scenery/tileentry.hxx>
 
 #include "materialmgr.hxx"
@@ -97,9 +93,8 @@ static void calc_normal(Point3D p1, Point3D p2,
 
 #define FG_TEX_CONSTANT 69.0
 
-
 // Calculate texture coordinates for a given point.
-static Point3D calc_tex_coords(const Point3D& node, const Point3D& ref) {
+static Point3D local_calc_tex_coords(const Point3D& node, const Point3D& ref) {
     Point3D cp;
     Point3D pp;
     // double tmplon, tmplat;
@@ -134,38 +129,184 @@ static Point3D calc_tex_coords(const Point3D& node, const Point3D& ref) {
 }
 
 
-// Load a .obj file and build the GL fragment list
+// Generate a generic ocean tile on the fly
+ssgBranch *fgGenTile( const string& path, FGTileEntry *t) {
+    fgFRAGMENT fragment;
+    fragment.init();
+    fragment.tile_ptr = t;
+
+    ssgSimpleState *state = NULL;
+
+    ssgBranch *tile = new ssgBranch () ;
+    tile -> setName ( (char *)path.c_str() ) ;
+
+    // find Ocean material in the properties list
+    if ( ! material_mgr.find( "Ocean", fragment.material_ptr )) {
+       FG_LOG( FG_TERRAIN, FG_ALERT, 
+               "Ack! unknown usemtl name = " << "Ocean" 
+               << " in " << path );
+    }
+
+    // set the texture width and height values for this
+    // material
+    FGMaterial m = fragment.material_ptr->get_m();
+    double tex_width = m.get_xsize();
+    double tex_height = m.get_ysize();
+
+    // set ssgState
+    state = fragment.material_ptr->get_state();
+
+    // Calculate center point
+    FGBucket b = t->tile_bucket;
+    double clon = b.get_center_lon();
+    double clat = b.get_center_lat();
+    double height = b.get_height();
+    double width = b.get_width();
+
+    Point3D center = fgGeodToCart(Point3D(clon*DEG_TO_RAD,clat*DEG_TO_RAD,0.0));
+    t->center = center;
+    fragment.center = center;
+    // cout << "center = " << center << endl;;
+    
+    // Caculate corner vertices
+    Point3D geod[4];
+    geod[0] = Point3D( clon - width/2.0, clat - height/2.0, 0.0 );
+    geod[1] = Point3D( clon + width/2.0, clat - height/2.0, 0.0 );
+    geod[2] = Point3D( clon + width/2.0, clat + height/2.0, 0.0 );
+    geod[3] = Point3D( clon - width/2.0, clat + height/2.0, 0.0 );
+
+    Point3D rad[4];
+    int i;
+    for ( i = 0; i < 4; ++i ) {
+       rad[i] = Point3D( geod[i].x() * DEG_TO_RAD, geod[i].y() * DEG_TO_RAD,
+                         geod[i].z() );
+    }
+
+    Point3D cart[4], rel[4];
+    t->nodes.clear();
+    for ( i = 0; i < 4; ++i ) {
+       cart[i] = fgGeodToCart(rad[i]);
+       rel[i] = cart[i] - center;
+       t->nodes.push_back( rel[i] );
+       // cout << "corner " << i << " = " << cart[i] << endl;
+    }
+
+    t->ncount = 4;
+
+    // Calculate bounding radius
+    t->bounding_radius = center.distance3D( cart[0] );
+    fragment.bounding_radius = t->bounding_radius;
+    // cout << "bounding radius = " << t->bounding_radius << endl;
+
+    // Calculate normals
+    Point3D normals[4];
+    for ( i = 0; i < 4; ++i ) {
+       normals[i] = cart[i];
+       double length = normals[i].distance3D( Point3D(0.0) );
+       normals[i] /= length;
+       // cout << "normal = " << normals[i] << endl;
+    }
+
+    // Calculate texture coordinates
+    point_list geod_nodes;
+    geod_nodes.clear();
+    for ( i = 0; i < 4; ++i ) {
+       geod_nodes.push_back( geod[i] );
+    }
+    int_list rectangle;
+    rectangle.clear();
+    for ( i = 0; i < 4; ++i ) {
+       rectangle.push_back( i );
+    }
+    point_list texs = calc_tex_coords( b, geod_nodes, rectangle, 
+                                      1000.0 / tex_width );
+
+    // Build flight gear structure
+    fragment.add_face(0, 1, 2);
+    fragment.add_face(0, 2, 3);
+    t->fragment_list.push_back(fragment);
+
+    // Allocate ssg structure
+    sgVec3 *vtlist = new sgVec3 [ 4 ];
+    t->vec3_ptrs.push_back( vtlist );
+    sgVec3 *vnlist = new sgVec3 [ 4 ];
+    t->vec3_ptrs.push_back( vnlist );
+    sgVec2 *tclist = new sgVec2 [ 4 ];
+    t->vec2_ptrs.push_back( tclist );
+
+    for ( i = 0; i < 4; ++i ) {
+       sgSetVec3( vtlist[i], 
+                  rel[i].x(), rel[i].y(), rel[i].z() );
+       sgSetVec3( vnlist[i], 
+                  normals[i].x(), normals[i].y(), normals[i].z() );
+       sgSetVec2( tclist[i], texs[i].x(), texs[i].y() );
+    }
+    
+    unsigned short *vindex = new unsigned short [ 4 ];
+    t->index_ptrs.push_back( vindex );
+    unsigned short *tindex = new unsigned short [ 4 ];
+    t->index_ptrs.push_back( tindex );
+    for ( i = 0; i < 4; ++i ) {
+       vindex[i] = i;
+       tindex[i] = i;
+    }
+
+    ssgLeaf *leaf = 
+       new ssgVTable ( GL_TRIANGLE_FAN,
+                       4, vindex, vtlist,
+                       4, vindex, vnlist,
+                       4, tindex, tclist,
+                       0, NULL, NULL ) ;
+    leaf->setState( state );
+
+    tile->addKid( leaf );
+    // if ( current_options.get_clouds() ) {
+    //    fgGenCloudTile(path, t, tile);
+    // }
+
+    return tile;
+}
+
+
+// Load a .obj file and build the fragment list
 ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
     fgFRAGMENT fragment;
     Point3D pp;
-    double approx_normal[3], normal[3] /*, scale = 0.0 */;
+    double approx_normal[3] /*, normal[3], scale = 0.0 */;
     // double x, y, z, xmax, xmin, ymax, ymin, zmax, zmin;
     // GLfloat sgenparams[] = { 1.0, 0.0, 0.0, 0.0 };
-    GLint display_list = 0;
+    // GLint display_list = 0;
     int shading;
     bool in_fragment = false, in_faces = false;
     int vncount, vtcount;
     int n1 = 0, n2 = 0, n3 = 0, n4 = 0;
     int tex;
-    int last1 = 0, last2 = 0, odd = 0;
+    int last1 = 0, last2 = 0;
+    bool odd = false;
     point_list nodes;
     Point3D node;
     Point3D center;
+    double scenery_version = 0.0;
     double tex_width = 1000.0, tex_height = 1000.0;
     bool shared_done = false;
     int_list fan_vertices;
     int_list fan_tex_coords;
     int i;
     ssgSimpleState *state = NULL;
+    sgVec3 *vtlist, *vnlist;
+    sgVec2 *tclist;
 
     ssgBranch *tile = new ssgBranch () ;
-    tile -> setName ( path.c_str() ) ;
+
+    tile -> setName ( (char *)path.c_str() ) ;
 
     // Attempt to open "path.gz" or "path"
     fg_gzifstream in( path );
     if ( ! in.is_open() ) {
        FG_LOG( FG_TERRAIN, FG_ALERT, "Cannot open file: " << path );
-       return NULL;
+       FG_LOG( FG_TERRAIN, FG_ALERT, "default to ocean tile: " << path );
+
+       return fgGenTile( path, t );
     }
 
     shading = current_options.get_shading();
@@ -182,11 +323,17 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
 
     // ignore initial comments and blank lines. (priming the pump)
     // in >> skipcomment;
-    string line;
+    // string line;
+
+    string token;
+    char c;
 
+#ifdef __MWERKS__
+    while ( in.get(c) && c  != '\0' ) {
+       in.putback(c);
+#else
     while ( ! in.eof() ) {
-       string token;
-       char c;
+#endif
 
 #if defined( MACOS )
        in >> ::skipws;
@@ -202,7 +349,11 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
 
            in >> token;
 
-           if ( token == "gbs" ) {
+           if ( token == "Version" ) {
+               // read scenery versions number
+               in >> scenery_version;
+               // cout << "scenery_version = " << scenery_version << endl;
+           } else if ( token == "gbs" ) {
                // reference point (center offset)
                in >> t->center >> t->bounding_radius;
                center = t->center;
@@ -222,47 +373,51 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                // shared_done true and build the ssg shared lists
                if ( ! shared_done ) {
                    // sanity check
-                   if ( nodes.size() != vncount ) {
+                   if ( (int)nodes.size() != vncount ) {
                        FG_LOG( FG_TERRAIN, FG_ALERT, 
                                "Tile has mismatched nodes and normals: " 
                                << path );
-                       exit(-1);
+                       // exit(-1);
                    }
                    shared_done = true;
 
-                   t->vtlist = new sgVec3 [ nodes.size() ];
-                   t->vnlist = new sgVec3 [ vncount ];
-                   t->tclist = new sgVec2 [ vtcount ];
+                   vtlist = new sgVec3 [ nodes.size() ];
+                   t->vec3_ptrs.push_back( vtlist );
+                   vnlist = new sgVec3 [ vncount ];
+                   t->vec3_ptrs.push_back( vnlist );
+                   tclist = new sgVec2 [ vtcount ];
+                   t->vec2_ptrs.push_back( tclist );
 
                    for ( i = 0; i < (int)nodes.size(); ++i ) {
-                       sgSetVec3( t->vtlist[i], 
+                       sgSetVec3( vtlist[i], 
                                   nodes[i][0], nodes[i][1], nodes[i][2] );
                    }
                    for ( i = 0; i < vncount; ++i ) {
-                       sgSetVec3( t->vnlist[i], 
+                       sgSetVec3( vnlist[i], 
                                   normals[i][0], 
                                   normals[i][1],
                                   normals[i][2] );
                    }
                    for ( i = 0; i < vtcount; ++i ) {
-                       sgSetVec2( t->tclist[i],
-                                  tex_coords[i][0], tex_coords[i][1] );
+                       sgSetVec2( tclist[i],
+                                  tex_coords[i][0],
+                                  tex_coords[i][1] );
                    }
                }
 
                // series of individual triangles
-               if ( in_faces ) {
-                   xglEnd();
-               }
+               // if ( in_faces ) {
+               //     xglEnd();
+               // }
 
                // this also signals the start of a new fragment
                if ( in_fragment ) {
                    // close out the previous structure and start the next
-                   xglEndList();
+                   // xglEndList();
                    // printf("xglEnd(); xglEndList();\n");
 
                    // update fragment
-                   fragment.display_list = display_list;
+                   // fragment.display_list = display_list;
 
                    // push this fragment onto the tile's object list
                    t->fragment_list.push_back(fragment);
@@ -272,8 +427,8 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
 
                // printf("start of fragment (usemtl)\n");
 
-               display_list = xglGenLists(1);
-               xglNewList(display_list, GL_COMPILE);
+               // display_list = xglGenLists(1);
+               // xglNewList(display_list, GL_COMPILE);
                // printf("xglGenLists(); xglNewList();\n");
                in_faces = false;
 
@@ -377,32 +532,32 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
 
                // fgPrintf( FG_TERRAIN, FG_DEBUG, "(t) = ");
 
-               xglBegin(GL_TRIANGLE_STRIP);
+               // xglBegin(GL_TRIANGLE_STRIP);
                // printf("xglBegin(tristrip) %d %d %d\n", n1, n2, n3);
 
-               odd = 1
+               odd = true
                // scale = 1.0;
 
                if ( shading ) {
                    // Shading model is "GL_SMOOTH" so use precalculated
                    // (averaged) normals
                    // MAT3_SCALE_VEC(normal, normals[n1], scale);
-                   xglNormal3dv(normal);
-                   pp = calc_tex_coords(nodes[n1], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n1].get_n());            
+                   // xglNormal3dv(normal);
+                   pp = local_calc_tex_coords(nodes[n1], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n1].get_n());         
 
                    // MAT3_SCALE_VEC(normal, normals[n2], scale);
-                   xglNormal3dv(normal);
-                   pp = calc_tex_coords(nodes[n2], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n2].get_n());                            
+                   // xglNormal3dv(normal);
+                   pp = local_calc_tex_coords(nodes[n2], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n2].get_n());                         
 
                    // MAT3_SCALE_VEC(normal, normals[n3], scale);
-                   xglNormal3dv(normal);
-                   pp = calc_tex_coords(nodes[n3], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n3].get_n());
+                   // xglNormal3dv(normal);
+                   pp = local_calc_tex_coords(nodes[n3], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n3].get_n());
                } else {
                    // Shading model is "GL_FLAT" so calculate per face
                    // normals on the fly.
@@ -414,23 +569,23 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                                    nodes[n3], approx_normal);
                    }
                    // MAT3_SCALE_VEC(normal, approx_normal, scale);
-                   xglNormal3dv(normal);
+                   // xglNormal3dv(normal);
 
-                   pp = calc_tex_coords(nodes[n1], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n1].get_n());            
+                   pp = local_calc_tex_coords(nodes[n1], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n1].get_n());         
 
-                   pp = calc_tex_coords(nodes[n2], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n2].get_n());            
+                   pp = local_calc_tex_coords(nodes[n2], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n2].get_n());         
                    
-                   pp = calc_tex_coords(nodes[n3], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n3].get_n());            
+                   pp = local_calc_tex_coords(nodes[n3], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n3].get_n());         
                }
                // printf("some normals, texcoords, and vertices\n");
 
-               odd = 1 - odd;
+               odd = !odd;
                last1 = n2;
                last2 = n3;
 
@@ -449,7 +604,7 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
 
                if ( n4 > 0 ) {
                    fragment.add_face(n3, n2, n4);
-
+                   
                    if ( shading ) {
                        // Shading model is "GL_SMOOTH"
                        // MAT3_SCALE_VEC(normal, normals[n4], scale);
@@ -459,54 +614,71 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                                    approx_normal);
                        // MAT3_SCALE_VEC(normal, approx_normal, scale);
                    }
-                   xglNormal3dv(normal);
-                   pp = calc_tex_coords(nodes[n4], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n4].get_n());            
+                   // xglNormal3dv(normal);
+                   pp = local_calc_tex_coords(nodes[n4], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n4].get_n());         
                    
-                   odd = 1 - odd;
+                   odd = !odd;
                    last1 = n3;
                    last2 = n4;
                    // printf("a normal, texcoord, and vertex (4th)\n");
                }
-           } else if ( token == "tf" ) {
+           } else if ( (token == "tf") || (token == "ts") ) {
                // triangle fan
                // fgPrintf( FG_TERRAIN, FG_DEBUG, "new fan");
 
                fan_vertices.clear();
                fan_tex_coords.clear();
+               odd = true;
 
-               xglBegin(GL_TRIANGLE_FAN);
+               // xglBegin(GL_TRIANGLE_FAN);
 
                in >> n1;
                fan_vertices.push_back( n1 );
-               xglNormal3dv(normals[n1]);
+               // xglNormal3dv(normals[n1]);
                if ( in.get( c ) && c == '/' ) {
                    in >> tex;
                    fan_tex_coords.push_back( tex );
+                   if ( scenery_version >= 0.4 ) {
+                       if ( tex_width > 0 ) {
+                           tclist[tex][0] *= (1000.0 / tex_width);
+                       }
+                       if ( tex_height > 0 ) {
+                           tclist[tex][1] *= (1000.0 / tex_height);
+                       }
+                   }
                    pp.setx( tex_coords[tex][0] * (1000.0 / tex_width) );
                    pp.sety( tex_coords[tex][1] * (1000.0 / tex_height) );
                } else {
                    in.putback( c );
-                   pp = calc_tex_coords(nodes[n1], center);
+                   pp = local_calc_tex_coords(nodes[n1], center);
                }
-               xglTexCoord2f(pp.x(), pp.y());
-               xglVertex3dv(nodes[n1].get_n());
+               // xglTexCoord2f(pp.x(), pp.y());
+               // xglVertex3dv(nodes[n1].get_n());
 
                in >> n2;
                fan_vertices.push_back( n2 );
-               xglNormal3dv(normals[n2]);
+               // xglNormal3dv(normals[n2]);
                if ( in.get( c ) && c == '/' ) {
                    in >> tex;
                    fan_tex_coords.push_back( tex );
+                   if ( scenery_version >= 0.4 ) {
+                       if ( tex_width > 0 ) {
+                           tclist[tex][0] *= (1000.0 / tex_width);
+                       }
+                       if ( tex_height > 0 ) {
+                           tclist[tex][1] *= (1000.0 / tex_height);
+                       }
+                   }
                    pp.setx( tex_coords[tex][0] * (1000.0 / tex_width) );
                    pp.sety( tex_coords[tex][1] * (1000.0 / tex_height) );
                } else {
                    in.putback( c );
-                   pp = calc_tex_coords(nodes[n2], center);
+                   pp = local_calc_tex_coords(nodes[n2], center);
                }
-               xglTexCoord2f(pp.x(), pp.y());
-               xglVertex3dv(nodes[n2].get_n());
+               // xglTexCoord2f(pp.x(), pp.y());
+               // xglVertex3dv(nodes[n2].get_n());
                
                // read all subsequent numbers until next thing isn't a number
                while ( true ) {
@@ -528,42 +700,79 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                    // cout << "  triangle = " 
                    //      << n1 << "," << n2 << "," << n3 
                    //      << endl;
-                   xglNormal3dv(normals[n3]);
+                   // xglNormal3dv(normals[n3]);
                    if ( in.get( c ) && c == '/' ) {
                        in >> tex;
                        fan_tex_coords.push_back( tex );
+                       if ( scenery_version >= 0.4 ) {
+                           if ( tex_width > 0 ) {
+                               tclist[tex][0] *= (1000.0 / tex_width);
+                           }
+                           if ( tex_height > 0 ) {
+                               tclist[tex][1] *= (1000.0 / tex_height);
+                           }
+                       }
                        pp.setx( tex_coords[tex][0] * (1000.0 / tex_width) );
                        pp.sety( tex_coords[tex][1] * (1000.0 / tex_height) );
                    } else {
                        in.putback( c );
-                       pp = calc_tex_coords(nodes[n3], center);
+                       pp = local_calc_tex_coords(nodes[n3], center);
                    }
-                   xglTexCoord2f(pp.x(), pp.y());
-                   xglVertex3dv(nodes[n3].get_n());
+                   // xglTexCoord2f(pp.x(), pp.y());
+                   // xglVertex3dv(nodes[n3].get_n());
 
-                   fragment.add_face(n1, n2, n3);
-                   n2 = n3;
+                   if ( token == "tf" ) {
+                       // triangle fan
+                       fragment.add_face(n1, n2, n3);
+                       n2 = n3;
+                   } else {
+                       // triangle strip
+                       if ( odd ) {
+                           fragment.add_face(n1, n2, n3);
+                       } else {
+                           fragment.add_face(n2, n1, n3);
+                       }
+                       odd = !odd;
+                       n1 = n2;
+                       n2 = n3;
+                   }
                }
 
-               xglEnd();
+               // xglEnd();
 
                // build the ssg entity
                unsigned short *vindex = 
                    new unsigned short [ fan_vertices.size() ];
+               t->index_ptrs.push_back( vindex );
+
                unsigned short *tindex = 
                    new unsigned short [ fan_tex_coords.size() ];
+               t->index_ptrs.push_back( tindex );
+
                for ( i = 0; i < (int)fan_vertices.size(); ++i ) {
                    vindex[i] = fan_vertices[i];
                }
                for ( i = 0; i < (int)fan_tex_coords.size(); ++i ) {
                    tindex[i] = fan_tex_coords[i];
                }
-               ssgLeaf *leaf = 
-                   new ssgVTable ( GL_TRIANGLE_FAN,
-                                   fan_vertices.size(), vindex, t->vtlist,
-                                   fan_vertices.size(), vindex, t->vnlist,
-                                   fan_tex_coords.size(), tindex, t->tclist,
-                                   0, NULL, NULL ) ;
+               ssgLeaf *leaf;
+               if ( token == "tf" ) {
+                   // triangle fan
+                   leaf = 
+                       new ssgVTable ( GL_TRIANGLE_FAN,
+                                       fan_vertices.size(), vindex, vtlist,
+                                       fan_vertices.size(), vindex, vnlist,
+                                       fan_tex_coords.size(), tindex, tclist,
+                                       0, NULL, NULL ) ;
+               } else {
+                   // triangle strip
+                   leaf = 
+                       new ssgVTable ( GL_TRIANGLE_STRIP,
+                                       fan_vertices.size(), vindex, vtlist,
+                                       fan_vertices.size(), vindex, vnlist,
+                                       fan_tex_coords.size(), tindex, tclist,
+                                       0, NULL, NULL ) ;
+               }
                leaf->setState( state );
 
                tile->addKid( leaf );
@@ -572,7 +781,7 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                // unoptimized face
 
                if ( !in_faces ) {
-                   xglBegin(GL_TRIANGLES);
+                   // xglBegin(GL_TRIANGLES);
                    // printf("xglBegin(triangles)\n");
                    in_faces = true;
                }
@@ -582,20 +791,20 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                fragment.add_face(n1, n2, n3);
 
                // xglNormal3d(normals[n1][0], normals[n1][1], normals[n1][2]);
-               xglNormal3dv(normals[n1]);
-               pp = calc_tex_coords(nodes[n1], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n1].get_n());
-
-               xglNormal3dv(normals[n2]);
-               pp = calc_tex_coords(nodes[n2], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n2].get_n());
+               // xglNormal3dv(normals[n1]);
+               pp = local_calc_tex_coords(nodes[n1], center);
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n1].get_n());
+
+               // xglNormal3dv(normals[n2]);
+               pp = local_calc_tex_coords(nodes[n2], center);
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n2].get_n());
                
-               xglNormal3dv(normals[n3]);
-               pp = calc_tex_coords(nodes[n3], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n3].get_n());
+               // xglNormal3dv(normals[n3]);
+               pp = local_calc_tex_coords(nodes[n3], center);
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n3].get_n());
                // printf("some normals, texcoords, and vertices (tris)\n");
            } else if ( token == "q" ) {
                // continue a triangle strip
@@ -640,14 +849,14 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                    }
                    // MAT3_SCALE_VEC(normal, approx_normal, scale);
                }
-               xglNormal3dv(normal);
+               // xglNormal3dv(normal);
 
-               pp = calc_tex_coords(nodes[n1], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n1].get_n());
+               pp = local_calc_tex_coords(nodes[n1], center);
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n1].get_n());
                // printf("a normal, texcoord, and vertex (4th)\n");
    
-               odd = 1 - odd;
+               odd = !odd;
                last1 = last2;
                last2 = n1;
 
@@ -674,14 +883,14 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
                        }
                        // MAT3_SCALE_VEC(normal, approx_normal, scale);
                    }
-                   xglNormal3dv(normal);
+                   // xglNormal3dv(normal);
                
-                   pp = calc_tex_coords(nodes[n2], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n2].get_n());            
+                   pp = local_calc_tex_coords(nodes[n2], center);
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n2].get_n());         
                    // printf("a normal, texcoord, and vertex (4th)\n");
 
-                   odd = 1 -odd;
+                   odd = !odd;
                    last1 = last2;
                    last2 = n2;
                }
@@ -702,12 +911,12 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
 
     if ( in_fragment ) {
        // close out the previous structure and start the next
-       xglEnd();
-       xglEndList();
+       // xglEnd();
+       // xglEndList();
        // printf("xglEnd(); xglEndList();\n");
        
        // update fragment
-       fragment.display_list = display_list;
+       // fragment.display_list = display_list;
        
        // push this fragment onto the tile's object list
        t->fragment_list.push_back(fragment);
@@ -731,10 +940,14 @@ ssgBranch *fgObjLoad( const string& path, FGTileEntry *t) {
     t->nodes = nodes;
 
     stopwatch.stop();
-    FG_LOG( FG_TERRAIN, FG_INFO
+    FG_LOG( FG_TERRAIN, FG_DEBUG
            "Loaded " << path << " in " 
            << stopwatch.elapsedSeconds() << " seconds" );
-    
+
+    // Generate a cloud layer above the tiles
+    // if ( current_options.get_clouds() ) {
+    //         fgGenCloudTile(path, t, tile);
+    // }
     return tile;
 }