]> git.mxchange.org Git - flightgear.git/blobdiff - src/Objects/obj.cxx
Moving towards increased dependence on ssg.
[flightgear.git] / src / Objects / obj.cxx
index 6172ac69281d5f71fbb0c5f415c28420616d04ec..38729da3f1fb2f230960eb652d055106abcaf5b0 100644 (file)
 #  include <math.h>
 #endif
 
-#ifdef HAVE_WINDOWS_H
-#  include <windows.h>
-#endif
+// #ifdef HAVE_WINDOWS_H
+// #  include <windows.h>
+// #endif
 
 #include <stdio.h>
 #include <string.h>
-#include <GL/glut.h>
-#include <XGL/xgl.h>
+// #include <GL/glut.h>
+// #include <XGL/xgl.h>
 
 // #if defined ( __sun__ )
 // extern "C" void *memmove(void *, const void *, size_t);
@@ -46,8 +46,9 @@
 #include <Include/compiler.h>
 
 #include STL_STRING
-#include <map>          // STL
-#include <ctype.h>      // isdigit()
+#include <map>                 // STL
+#include <vector>              // STL
+#include <ctype.h>             // isdigit()
 
 #include <Debug/logstream.hxx>
 #include <Misc/fgstream.hxx>
 #include "obj.hxx"
 
 FG_USING_STD(string);
+FG_USING_STD(vector);
+
+
+typedef vector < int > int_list;
+typedef int_list::iterator int_list_iterator;
+typedef int_list::const_iterator int_point_list_iterator;
 
 
 static double normals[FG_MAX_NODES][3];
@@ -127,16 +134,17 @@ static Point3D calc_tex_coords(const Point3D& node, const Point3D& ref) {
 }
 
 
-// Load a .obj file and build the GL fragment list
-int fgObjLoad( const string& path, FGTileEntry *t) {
+// 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;
-    int in_fragment = 0, in_faces = 0, vncount, vtcount;
+    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;
@@ -144,19 +152,25 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
     Point3D node;
     Point3D center;
     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;
 
-    // printf("loading %s\n", path.c_str() );
+    ssgBranch *tile = new ssgBranch () ;
+    tile -> setName ( 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 0;
+       return NULL;
     }
 
     shading = current_options.get_shading();
 
-    in_fragment = 0;
+    in_fragment = false;
     t->ncount = 0;
     vncount = 0;
     vtcount = 0;
@@ -180,7 +194,7 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
     while ( ! in.eof() ) {
 #endif
 
-#ifdef __MWERKS__
+#if defined( MACOS )
        in >> ::skipws;
 #else
        in >> skipws;
@@ -210,32 +224,64 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
            } else if ( token == "usemtl" ) {
                // material property specification
 
-               // series of individual triangles
-               if ( in_faces ) {
-                   xglEnd();
+               // if first usemtl with shared_done = false, then set
+               // shared_done true and build the ssg shared lists
+               if ( ! shared_done ) {
+                   // sanity check
+                   if ( (int)nodes.size() != vncount ) {
+                       FG_LOG( FG_TERRAIN, FG_ALERT, 
+                               "Tile has mismatched nodes and normals: " 
+                               << path );
+                       // exit(-1);
+                   }
+                   shared_done = true;
+
+                   t->vtlist = new sgVec3 [ nodes.size() ];
+                   t->vnlist = new sgVec3 [ vncount ];
+                   t->tclist = new sgVec2 [ vtcount ];
+
+                   for ( i = 0; i < (int)nodes.size(); ++i ) {
+                       sgSetVec3( t->vtlist[i], 
+                                  nodes[i][0], nodes[i][1], nodes[i][2] );
+                   }
+                   for ( i = 0; i < vncount; ++i ) {
+                       sgSetVec3( t->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] );
+                   }
                }
 
+               // series of individual triangles
+               // 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);
                } else {
-                   in_fragment = 1;
+                   in_fragment = true;
                }
 
                // 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 = 0;
+               in_faces = false;
 
                // reset the existing face list
                // printf("cleaning a fragment with %d faces\n", 
@@ -259,6 +305,7 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
                FGMaterial m = fragment.material_ptr->get_m();
                tex_width = m.get_xsize();
                tex_height = m.get_ysize();
+               state = fragment.material_ptr->get_state();
                // cout << "(w) = " << tex_width << " (h) = " 
                //      << tex_width << endl;
 
@@ -336,7 +383,7 @@ int 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; 
@@ -346,22 +393,22 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
                    // Shading model is "GL_SMOOTH" so use precalculated
                    // (averaged) normals
                    // MAT3_SCALE_VEC(normal, normals[n1], scale);
-                   xglNormal3dv(normal);
+                   // xglNormal3dv(normal);
                    pp = calc_tex_coords(nodes[n1], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n1].get_n());            
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n1].get_n());         
 
                    // MAT3_SCALE_VEC(normal, normals[n2], scale);
-                   xglNormal3dv(normal);
+                   // xglNormal3dv(normal);
                    pp = calc_tex_coords(nodes[n2], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n2].get_n());                            
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n2].get_n());                         
 
                    // MAT3_SCALE_VEC(normal, normals[n3], scale);
-                   xglNormal3dv(normal);
+                   // xglNormal3dv(normal);
                    pp = calc_tex_coords(nodes[n3], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n3].get_n());
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n3].get_n());
                } else {
                    // Shading model is "GL_FLAT" so calculate per face
                    // normals on the fly.
@@ -373,19 +420,19 @@ int 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());            
+                   // 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());            
+                   // 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());            
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n3].get_n());         
                }
                // printf("some normals, texcoords, and vertices\n");
 
@@ -418,10 +465,10 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
                                    approx_normal);
                        // MAT3_SCALE_VEC(normal, approx_normal, scale);
                    }
-                   xglNormal3dv(normal);
+                   // xglNormal3dv(normal);
                    pp = calc_tex_coords(nodes[n4], center);
-                   xglTexCoord2f(pp.lon(), pp.lat());
-                   xglVertex3dv(nodes[n4].get_n());            
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n4].get_n());         
                    
                    odd = 1 - odd;
                    last1 = n3;
@@ -432,33 +479,40 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
                // triangle fan
                // fgPrintf( FG_TERRAIN, FG_DEBUG, "new fan");
 
-               xglBegin(GL_TRIANGLE_FAN);
+               fan_vertices.clear();
+               fan_tex_coords.clear();
+
+               // xglBegin(GL_TRIANGLE_FAN);
 
                in >> n1;
-               xglNormal3dv(normals[n1]);
+               fan_vertices.push_back( n1 );
+               // xglNormal3dv(normals[n1]);
                if ( in.get( c ) && c == '/' ) {
                    in >> tex;
+                   fan_tex_coords.push_back( tex );
                    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);
                }
-               xglTexCoord2f(pp.x(), pp.y());
-               xglVertex3dv(nodes[n1].get_n());
+               // xglTexCoord2f(pp.x(), pp.y());
+               // xglVertex3dv(nodes[n1].get_n());
 
                in >> n2;
-               xglNormal3dv(normals[n2]);
+               fan_vertices.push_back( n2 );
+               // xglNormal3dv(normals[n2]);
                if ( in.get( c ) && c == '/' ) {
                    in >> tex;
+                   fan_tex_coords.push_back( tex );
                    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);
                }
-               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 ) {
@@ -476,33 +530,57 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
                    }
 
                    in >> n3;
+                   fan_vertices.push_back( n3 );
                    // 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 );
                        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);
                    }
-                   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;
                }
 
-               xglEnd();
+               // xglEnd();
+
+               // build the ssg entity
+               unsigned short *vindex = 
+                   new unsigned short [ fan_vertices.size() ];
+               unsigned short *tindex = 
+                   new unsigned short [ fan_tex_coords.size() ];
+               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 ) ;
+               leaf->setState( state );
+
+               tile->addKid( leaf );
+
            } else if ( token == "f" ) {
                // unoptimized face
 
                if ( !in_faces ) {
-                   xglBegin(GL_TRIANGLES);
+                   // xglBegin(GL_TRIANGLES);
                    // printf("xglBegin(triangles)\n");
-                   in_faces = 1;
+                   in_faces = true;
                }
 
                // fgPrintf( FG_TERRAIN, FG_DEBUG, "new triangle = %s", line);*/
@@ -510,20 +588,20 @@ int 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]);
+               // xglNormal3dv(normals[n1]);
                pp = calc_tex_coords(nodes[n1], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n1].get_n());
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n1].get_n());
 
-               xglNormal3dv(normals[n2]);
+               // xglNormal3dv(normals[n2]);
                pp = calc_tex_coords(nodes[n2], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n2].get_n());
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n2].get_n());
                
-               xglNormal3dv(normals[n3]);
+               // xglNormal3dv(normals[n3]);
                pp = calc_tex_coords(nodes[n3], center);
-               xglTexCoord2f(pp.lon(), pp.lat());
-               xglVertex3dv(nodes[n3].get_n());
+               // 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
@@ -568,11 +646,11 @@ int 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());
+               // xglTexCoord2f(pp.lon(), pp.lat());
+               // xglVertex3dv(nodes[n1].get_n());
                // printf("a normal, texcoord, and vertex (4th)\n");
    
                odd = 1 - odd;
@@ -602,11 +680,11 @@ int 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());            
+                   // xglTexCoord2f(pp.lon(), pp.lat());
+                   // xglVertex3dv(nodes[n2].get_n());         
                    // printf("a normal, texcoord, and vertex (4th)\n");
 
                    odd = 1 -odd;
@@ -630,12 +708,12 @@ int 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);
@@ -663,7 +741,7 @@ int fgObjLoad( const string& path, FGTileEntry *t) {
            "Loaded " << path << " in " 
            << stopwatch.elapsedSeconds() << " seconds" );
     
-    return 1;
+    return tile;
 }