]> git.mxchange.org Git - simgear.git/commitdiff
- secondary tc and vertex attribs in .btg file
authorPeter Sadrozinski <peter@localhost.localdomain>
Sat, 11 Jan 2014 03:42:16 +0000 (22:42 -0500)
committerChristian Schmitt <chris@ilovelinux.de>
Sat, 5 Apr 2014 19:48:38 +0000 (21:48 +0200)
- decrease debug when writing btg files
- deprecate some set_xxx apis

simgear/io/decode_binobj.cxx
simgear/io/sg_binobj.cxx
simgear/io/sg_binobj.hxx
simgear/io/test_binobj.cxx
simgear/scene/tgdb/SGTexturedTriangleBin.hxx
simgear/scene/tgdb/obj.cxx

index 41880e1257a80c839a43911207835c47a4f0ff3a..a6aa9101c620f35e4ab5fefd5a48caa42a0a92b8 100644 (file)
@@ -82,9 +82,9 @@ int main( int argc, char **argv ) {
     group_list pts_v = obj.get_pts_v();
     group_list pts_n = obj.get_pts_n();
     for ( i = 0; i < (int)pts_v.size(); ++i ) {
-       material = pt_materials[i];
-       vertex_index = pts_v[i];
-       normal_index = pts_n[i];
+        material = pt_materials[i];
+        vertex_index = pts_v[i];
+        normal_index = pts_n[i];
         cout << "# usemtl " << material << endl;
         cout << "pt ";
         for ( j = 0; j < (int)vertex_index.size(); ++j ) {
@@ -97,12 +97,12 @@ int main( int argc, char **argv ) {
     string_list tri_materials = obj.get_tri_materials();
     group_list tris_v = obj.get_tris_v();
     group_list tris_n = obj.get_tris_n();
-    group_list tris_tc = obj.get_tris_tc();
+    group_tci_list tris_tc = obj.get_tris_tcs();
     for ( i = 0; i < (int)tris_v.size(); ++i ) {
-       material = tri_materials[i];
-       vertex_index = tris_v[i];
-       normal_index = tris_n[i];
-       tex_index = tris_tc[i];
+        material = tri_materials[i];
+        vertex_index = tris_v[i];
+        normal_index = tris_n[i];
+        tex_index = tris_tc[0][i];
         cout << "# usemtl " << material << endl;
         cout << "f ";
         for ( j = 0; j < (int)vertex_index.size(); ++j ) {
@@ -120,12 +120,12 @@ int main( int argc, char **argv ) {
     string_list strip_materials = obj.get_strip_materials();
     group_list strips_v = obj.get_strips_v();
     group_list strips_n = obj.get_strips_n();
-    group_list strips_tc = obj.get_strips_tc();
+    group_tci_list strips_tc = obj.get_strips_tcs();
     for ( i = 0; i < (int)strips_v.size(); ++i ) {
-       material = strip_materials[i];
-       vertex_index = strips_v[i];
-       normal_index = strips_n[i];
-       tex_index = strips_tc[i];
+        material = strip_materials[i];
+        vertex_index = strips_v[i];
+        normal_index = strips_n[i];
+        tex_index = strips_tc[0][i];
         cout << "# usemtl " << material << endl;
         cout << "ts ";
         for ( j = 0; j < (int)vertex_index.size(); ++j ) {
@@ -142,12 +142,12 @@ int main( int argc, char **argv ) {
     string_list fan_materials = obj.get_fan_materials();
     group_list fans_v = obj.get_fans_v();
     group_list fans_n = obj.get_fans_n();
-    group_list fans_tc = obj.get_fans_tc();
+    group_tci_list fans_tc = obj.get_fans_tcs();
     for ( i = 0; i < (int)fans_v.size(); ++i ) {
-       material = fan_materials[i];
-       vertex_index = fans_v[i];
-       normal_index = fans_n[i];
-       tex_index = fans_tc[i];
+        material = fan_materials[i];
+        vertex_index = fans_v[i];
+        normal_index = fans_n[i];
+        tex_index = fans_tc[0][i];
         cout << "# usemtl " << material << endl;
         cout << "tf ";
         for ( j = 0; j < (int)vertex_index.size(); ++j ) {
index 69cdd477c61fb23dfcba21b66b97dd718b3b9c01..5e5dafff870579b41bb9305aa13a9d629d0ce4a8 100644 (file)
@@ -58,9 +58,11 @@ enum sgObjectTypes {
     SG_BOUNDING_SPHERE = 0,
 
     SG_VERTEX_LIST = 1,
-    SG_COLOR_LIST = 4,
     SG_NORMAL_LIST = 2,
     SG_TEXCOORD_LIST = 3,
+    SG_COLOR_LIST = 4,
+    SG_VA_FLOAT_LIST = 5,
+    SG_VA_INTEGER_LIST = 6,
 
     SG_POINTS = 9,
 
@@ -70,15 +72,32 @@ enum sgObjectTypes {
 };
 
 enum sgIndexTypes {
-    SG_IDX_VERTICES =  0x01,
-    SG_IDX_NORMALS =   0x02,
-    SG_IDX_COLORS =    0x04,
-    SG_IDX_TEXCOORDS = 0x08
+    SG_IDX_VERTICES =    0x01,
+    SG_IDX_NORMALS =     0x02,
+    SG_IDX_COLORS =      0x04,
+    SG_IDX_TEXCOORDS_0 = 0x08,
+    SG_IDX_TEXCOORDS_1 = 0x10,
+    SG_IDX_TEXCOORDS_2 = 0x20,
+    SG_IDX_TEXCOORDS_3 = 0x40,
+};
+
+enum sgVertexAttributeTypes {
+    // vertex attributes
+    SG_VA_INTEGER_0 = 0x00000001,
+    SG_VA_INTEGER_1 = 0x00000002,
+    SG_VA_INTEGER_2 = 0x00000004,
+    SG_VA_INTEGER_3 = 0x00000008,
+
+    SG_VA_FLOAT_0 =   0x00000100,
+    SG_VA_FLOAT_1 =   0x00000200,
+    SG_VA_FLOAT_2 =   0x00000400,
+    SG_VA_FLOAT_3 =   0x00000800,
 };
 
 enum sgPropertyTypes {
     SG_MATERIAL = 0,
-    SG_INDEX_TYPES = 1
+    SG_INDEX_TYPES = 1,
+    SG_VERT_ATTRIBS = 2
 };
 
 
@@ -130,6 +149,17 @@ public:
         }
     }
     
+    float readInt()
+    {
+        unsigned int* p = reinterpret_cast<unsigned int*>(ptr + offset);
+        if ( sgIsBigEndian() ) {            
+            sgEndianSwap((uint32_t *) p);
+        }
+        
+        offset += sizeof(unsigned int);
+        return *p;
+    }
+    
     SGVec3d readVec3d()
     {
         double* p = reinterpret_cast<double*>(ptr + offset);
@@ -202,15 +232,19 @@ template <class T>
 static void read_indices(char* buffer, 
                          size_t bytes,
                          int indexMask,
+                         int vaMask,
                          int_list& vertices, 
                          int_list& normals,
                          int_list& colors,
-                         int_list& texCoords)
+                         tci_list& texCoords,
+                         vai_list& vas
+                        )
 {
     const int indexSize = sizeof(T) * std::bitset<32>(indexMask).count();
-    const int count = bytes / indexSize;
+    const int vaSize = sizeof(T) * std::bitset<32>(vaMask).count();
+    const int count = bytes / (indexSize + vaSize);
     
-// fix endian-ness of the whole lot, if required
+    // fix endian-ness of the whole lot, if required
     if (sgIsBigEndian()) {
         int indices = bytes / sizeof(T);
         T* src = reinterpret_cast<T*>(buffer);
@@ -224,7 +258,21 @@ static void read_indices(char* buffer,
         if (indexMask & SG_IDX_VERTICES) vertices.push_back(*src++);
         if (indexMask & SG_IDX_NORMALS) normals.push_back(*src++);
         if (indexMask & SG_IDX_COLORS) colors.push_back(*src++);
-        if (indexMask & SG_IDX_TEXCOORDS) texCoords.push_back(*src++);
+        if (indexMask & SG_IDX_TEXCOORDS_0) texCoords[0].push_back(*src++);
+        if (indexMask & SG_IDX_TEXCOORDS_1) texCoords[1].push_back(*src++);
+        if (indexMask & SG_IDX_TEXCOORDS_2) texCoords[2].push_back(*src++);
+        if (indexMask & SG_IDX_TEXCOORDS_3) texCoords[3].push_back(*src++);
+        
+        if ( vaMask ) {
+            if (vaMask & SG_VA_INTEGER_0) vas[0].push_back(*src++);
+            if (vaMask & SG_VA_INTEGER_1) vas[1].push_back(*src++);
+            if (vaMask & SG_VA_INTEGER_2) vas[2].push_back(*src++);
+            if (vaMask & SG_VA_INTEGER_3) vas[3].push_back(*src++);
+            if (vaMask & SG_VA_FLOAT_0) vas[4].push_back(*src++);
+            if (vaMask & SG_VA_FLOAT_1) vas[5].push_back(*src++);
+            if (vaMask & SG_VA_FLOAT_2) vas[6].push_back(*src++);
+            if (vaMask & SG_VA_FLOAT_3) vas[7].push_back(*src++);
+        }
     } // of elements in the index
 }
 
@@ -249,15 +297,19 @@ void write_indice(gzFile fp, uint32_t value)
 
 
 template <class T>
-void write_indices(gzFile fp, unsigned char indexMask, 
+void write_indices(gzFile fp, 
+    unsigned char indexMask, 
+    unsigned int vaMask,
     const int_list& vertices, 
     const int_list& normals, 
     const int_list& colors,
-    const int_list& texCoords)
+    const tci_list& texCoords,
+    const vai_list& vas )
 {
     unsigned int count = vertices.size();
     const int indexSize = sizeof(T) * std::bitset<32>(indexMask).count();
-    sgWriteUInt(fp, indexSize * count);
+    const int vaSize = sizeof(T) * std::bitset<32>(vaMask).count();
+    sgWriteUInt(fp, (indexSize + vaSize) * count);
             
     for (unsigned int i=0; i < count; ++i) {
         write_indice(fp, static_cast<T>(vertices[i]));
@@ -268,8 +320,45 @@ void write_indices(gzFile fp, unsigned char indexMask,
         if (indexMask & SG_IDX_COLORS) {
             write_indice(fp, static_cast<T>(colors[i]));
         }
-        if (indexMask & SG_IDX_TEXCOORDS) {
-            write_indice(fp, static_cast<T>(texCoords[i]));
+        if (indexMask & SG_IDX_TEXCOORDS_0) {
+            write_indice(fp, static_cast<T>(texCoords[0][i]));
+        }
+        if (indexMask & SG_IDX_TEXCOORDS_1) {
+            write_indice(fp, static_cast<T>(texCoords[1][i]));
+        }
+        if (indexMask & SG_IDX_TEXCOORDS_2) {
+            write_indice(fp, static_cast<T>(texCoords[2][i]));
+        }
+        if (indexMask & SG_IDX_TEXCOORDS_3) {
+            write_indice(fp, static_cast<T>(texCoords[3][i]));
+        }
+        
+        if (vaMask) {
+            if (vaMask & SG_VA_INTEGER_0) {
+                write_indice(fp, static_cast<T>(vas[0][i]));
+            }
+            if (vaMask & SG_VA_INTEGER_1) {
+                write_indice(fp, static_cast<T>(vas[1][i]));
+            }
+            if (vaMask & SG_VA_INTEGER_2) {
+                write_indice(fp, static_cast<T>(vas[2][i]));
+            }
+            if (vaMask & SG_VA_INTEGER_3) {
+                write_indice(fp, static_cast<T>(vas[3][i]));
+            }
+
+            if (vaMask & SG_VA_FLOAT_0) {
+                write_indice(fp, static_cast<T>(vas[4][i]));
+            }
+            if (vaMask & SG_VA_FLOAT_1) {
+                write_indice(fp, static_cast<T>(vas[5][i]));
+            }
+            if (vaMask & SG_VA_FLOAT_2) {
+                write_indice(fp, static_cast<T>(vas[6][i]));
+            }
+            if (vaMask & SG_VA_FLOAT_3) {
+                write_indice(fp, static_cast<T>(vas[7][i]));
+            }
         }
     }
 }
@@ -281,13 +370,15 @@ void SGBinObject::read_object( gzFile fp,
                          int nproperties,
                          int nelements,
                          group_list& vertices, 
-                          group_list& normals,
-                          group_list& colors,
-                          group_list& texCoords,
-                          string_list& materials)
+                         group_list& normals,
+                         group_list& colors,
+                         group_tci_list& texCoords,
+                         group_vai_list& vertexAttribs,
+                         string_list& materials)
 {
-    unsigned int nbytes;
+    unsigned int  nbytes;
     unsigned char idx_mask;
+    unsigned int  vertex_attrib_mask;
     int j;
     sgSimpleBuffer buf( 32768 );  // 32 Kb
     char material[256];
@@ -296,26 +387,49 @@ void SGBinObject::read_object( gzFile fp,
     if ( obj_type == SG_POINTS ) {
         idx_mask = SG_IDX_VERTICES;
     } else {
-        idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS);
+        idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS_0);
     }
-
+    vertex_attrib_mask = 0;
+    
     for ( j = 0; j < nproperties; ++j ) {
         char prop_type;
         sgReadChar( fp, &prop_type );
         sgReadUInt( fp, &nbytes );
+        
         buf.resize(nbytes);
         char *ptr = buf.get_ptr();
-        sgReadBytes( fp, nbytes, ptr );
-        if ( prop_type == SG_MATERIAL ) {
-            if (nbytes > 255) {
-                nbytes = 255;
-            }
-            strncpy( material, ptr, nbytes );
-            material[nbytes] = '\0';
-            // cout << "material type = " << material << endl;
-        } else if ( prop_type == SG_INDEX_TYPES ) {
-            idx_mask = ptr[0];
-            //cout << std::hex << "index mask:" << idx_mask << std::dec << endl;
+        
+        switch( prop_type )
+        {
+            case SG_MATERIAL:
+                sgReadBytes( fp, nbytes, ptr );
+                if (nbytes > 255) {
+                    nbytes = 255;
+                }
+                strncpy( material, ptr, nbytes );
+                material[nbytes] = '\0';
+                break;
+                
+            case SG_INDEX_TYPES:
+                if (nbytes == 1) {
+                    sgReadChar( fp, (char *)&idx_mask );                    
+                } else {
+                    sgReadBytes( fp, nbytes, ptr );                    
+                }
+                break;
+
+            case SG_VERT_ATTRIBS:
+                if (nbytes == 4) {
+                    sgReadUInt( fp, &vertex_attrib_mask );
+                } else {
+                    sgReadBytes( fp, nbytes, ptr );
+                }
+                break;
+                
+            default:
+                sgReadBytes( fp, nbytes, ptr );
+                SG_LOG(SG_IO, SG_ALERT, "Found UNKNOWN property type with nbytes == " << nbytes << " mask is " << (int)idx_mask );
+                break;
         }
     }
 
@@ -345,17 +459,20 @@ void SGBinObject::read_object( gzFile fp,
         int_list vs;
         int_list ns;
         int_list cs;
-        int_list tcs;
+        tci_list tcs;
+        vai_list vas;
+
         if (version >= 10) {
-            read_indices<uint32_t>(ptr, nbytes, idx_mask, vs, ns, cs, tcs);
+            read_indices<uint32_t>(ptr, nbytes, idx_mask, vertex_attrib_mask, vs, ns, cs, tcs, vas );
         } else {
-            read_indices<uint16_t>(ptr, nbytes, idx_mask, vs, ns, cs, tcs);
+            read_indices<uint16_t>(ptr, nbytes, idx_mask, vertex_attrib_mask, vs, ns, cs, tcs, vas );
         }
 
         vertices.push_back( vs );
         normals.push_back( ns );
         colors.push_back( cs );
         texCoords.push_back( tcs );
+        vertexAttribs.push_back( vas );
         materials.push_back( material );
     } // of element iteration
 }
@@ -380,25 +497,29 @@ bool SGBinObject::read_bin( const string& file ) {
     pts_v.clear();
     pts_n.clear();
     pts_c.clear();
-    pts_tc.clear();
+    pts_tcs.clear();
+    pts_vas.clear();
     pt_materials.clear();
 
     tris_v.clear();
     tris_n.clear();
     tris_c.clear();
-    tris_tc.clear();
+    tris_tcs.clear();
+    tris_vas.clear();
     tri_materials.clear();
 
     strips_v.clear();
     strips_n.clear();
     strips_c.clear();
-    strips_tc.clear();
+    strips_tcs.clear();
+    strips_vas.clear();
     strip_materials.clear();
 
     fans_v.clear();
     fans_n.clear();
     fans_c.clear();
-    fans_tc.clear();
+    fans_tcs.clear();
+    fans_vas.clear();
     fan_materials.clear();
 
     gzFile fp;
@@ -419,10 +540,9 @@ bool SGBinObject::read_bin( const string& file ) {
     sgReadUInt( fp, &header );
     if ( ((header & 0xFF000000) >> 24) == 'S' &&
          ((header & 0x00FF0000) >> 16) == 'G' ) {
-        // cout << "Good header" << endl;
+    
         // read file version
         version = (header & 0x0000FFFF);
-        // cout << "File version = " << version << endl;
     } else {
         // close the file before we return
         gzclose(fp);
@@ -460,7 +580,7 @@ bool SGBinObject::read_bin( const string& file ) {
         nobjects = v;
     }
      
-     //cout << "Total objects to read = " << nobjects << endl;
+    SG_LOG(SG_IO, SG_DEBUG, "SGBinObject::read_bin Total objects to read = " << nobjects);
 
     if ( sgReadError() ) {
         throw sg_io_exception("Error reading BTG file header", sg_location(file));
@@ -489,9 +609,10 @@ bool SGBinObject::read_bin( const string& file ) {
             nelements = v;
         }
 
-         //cout << "object " << i << " = " << (int)obj_type << " props = "
-         //     << nproperties << " elements = " << nelements << endl;
-            
+        SG_LOG(SG_IO, SG_DEBUG, "SGBinObject::read_bin object " << i << 
+                " = " << (int)obj_type << " props = " << nproperties << 
+                " elements = " << nelements);
+         
         if ( obj_type == SG_BOUNDING_SPHERE ) {
             // read bounding sphere properties
             read_properties( fp, nproperties );
@@ -521,7 +642,7 @@ bool SGBinObject::read_bin( const string& file ) {
                 wgs84_nodes.reserve( count );
                 for ( k = 0; k < count; ++k ) {
                     SGVec3f v = buf.readVec3f();
-                // extend from float to double, hmmm
+                    // extend from float to double, hmmm
                     wgs84_nodes.push_back( SGVec3d(v[0], v[1], v[2]) );
                 }
             }
@@ -581,23 +702,60 @@ bool SGBinObject::read_bin( const string& file ) {
                     texcoords.push_back( buf.readVec2f() );
                 }
             }
+        } else if ( obj_type == SG_VA_FLOAT_LIST ) {
+            // read vertex attribute (float) properties
+            read_properties( fp, nproperties );
+            
+            // read vertex attribute list elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+                int count = nbytes / (sizeof(float));
+                va_flt.reserve(count);
+                for ( k = 0; k < count; ++k ) {
+                    va_flt.push_back( buf.readFloat() );
+                }
+            }
+        } else if ( obj_type == SG_VA_INTEGER_LIST ) {
+            // read vertex attribute (integer) properties
+            read_properties( fp, nproperties );
+            
+            // read vertex attribute list elements
+            for ( j = 0; j < nelements; ++j ) {
+                sgReadUInt( fp, &nbytes );
+                buf.resize( nbytes );
+                buf.reset();
+                char *ptr = buf.get_ptr();
+                sgReadBytes( fp, nbytes, ptr );
+                int count = nbytes / (sizeof(unsigned int));
+                va_int.reserve(count);
+                for ( k = 0; k < count; ++k ) {
+                    va_int.push_back( buf.readInt() );
+                }
+            }
         } else if ( obj_type == SG_POINTS ) {
             // read point elements
             read_object( fp, SG_POINTS, nproperties, nelements,
-                         pts_v, pts_n, pts_c, pts_tc, pt_materials );
+                         pts_v, pts_n, pts_c, pts_tcs,
+                         pts_vas, pt_materials );
         } else if ( obj_type == SG_TRIANGLE_FACES ) {
             // read triangle face properties
             read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements,
-                         tris_v, tris_n, tris_c, tris_tc, tri_materials );
+                         tris_v, tris_n, tris_c, tris_tcs,
+                         tris_vas, tri_materials );
         } else if ( obj_type == SG_TRIANGLE_STRIPS ) {
             // read triangle strip properties
             read_object( fp, SG_TRIANGLE_STRIPS, nproperties, nelements,
-                         strips_v, strips_n, strips_c, strips_tc,
-                         strip_materials );
+                         strips_v, strips_n, strips_c, strips_tcs,
+                         strips_vas, strip_materials );
         } else if ( obj_type == SG_TRIANGLE_FANS ) {
             // read triangle fan properties
             read_object( fp, SG_TRIANGLE_FANS, nproperties, nelements,
-                         fans_v, fans_n, fans_c, fans_tc, fan_materials );
+                         fans_v, fans_n, fans_c, fans_tcs,
+                         fans_vas, fan_materials );
         } else {
             // unknown object type, just skip
             read_properties( fp, nproperties );
@@ -652,9 +810,13 @@ unsigned int SGBinObject::count_objects(const string_list& materials)
     return result;
 }
 
-void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts,
-    const group_list& normals, const group_list& colors, 
-    const group_list& texCoords, const string_list& materials)
+void SGBinObject::write_objects(gzFile fp, int type, 
+                                const group_list& verts,
+                                const group_list& normals, 
+                                const group_list& colors, 
+                                const group_tci_list& texCoords,
+                                const group_vai_list& vertexAttribs, 
+                                const string_list& materials)
 {
     if (verts.empty()) {
         return;
@@ -666,45 +828,77 @@ void SGBinObject::write_objects(gzFile fp, int type, const group_list& verts,
     
     while (start < materials.size()) {
         m = materials[start];
-    // find range of objects with identical material, write out as a single object
+        // find range of objects with identical material, write out as a single object
         for (end = start+1; (end < materials.size()) && (m == materials[end]); ++end) {}
     
+        // calc the number of elements
         const int count = end - start;
-        write_header(fp, type, 2, count);
+
+        // calc the number of properties
+        unsigned int va_mask = 0;
+        unsigned int va_count = vertexAttribs.size();
+        for ( unsigned int va=0; va<va_count; va++ ) {
+            if ( !vertexAttribs[va].empty() && !vertexAttribs[va].front().empty() ) {
+                va_mask |= ( 1 << va );
+            }
+        }
+
+        if ( va_mask ) {
+            write_header(fp, type, 3, count);
+        } else {
+            write_header(fp, type, 2, count);
+        }
         
     // properties
+        // material property
         sgWriteChar( fp, (char)SG_MATERIAL );        // property
         sgWriteUInt( fp, m.length() );        // nbytes
         sgWriteBytes( fp, m.length(), m.c_str() );
     
+        // index mask property
         unsigned char idx_mask = 0;
-        if ( !verts.empty() && !verts.front().empty()) idx_mask |= SG_IDX_VERTICES;
-        if ( !normals.empty() && !normals.front().empty()) idx_mask |= SG_IDX_NORMALS;
-        if ( !colors.empty() && !colors.front().empty()) idx_mask |= SG_IDX_COLORS;
-        if ( !texCoords.empty() && !texCoords.front().empty()) idx_mask |= SG_IDX_TEXCOORDS;
+        if ( !verts.empty() && !verts[start].empty()) idx_mask |= SG_IDX_VERTICES;
+        if ( !normals.empty() && !normals[start].empty()) idx_mask |= SG_IDX_NORMALS;
+        if ( !colors.empty() && !colors[start].empty()) idx_mask |= SG_IDX_COLORS;
+        if ( !texCoords.empty() && !texCoords[start][0].empty()) idx_mask |= SG_IDX_TEXCOORDS_0;
+        if ( !texCoords.empty() && !texCoords[start][1].empty()) idx_mask |= SG_IDX_TEXCOORDS_1;
+        if ( !texCoords.empty() && !texCoords[start][2].empty()) idx_mask |= SG_IDX_TEXCOORDS_2;
+        if ( !texCoords.empty() && !texCoords[start][3].empty()) idx_mask |= SG_IDX_TEXCOORDS_3;
         
         if (idx_mask == 0) {
             SG_LOG(SG_IO, SG_ALERT, "SGBinObject::write_objects: object with material:"
                 << m << "has no indices set");
         }
-    
-    
+
         sgWriteChar( fp, (char)SG_INDEX_TYPES );     // property
         sgWriteUInt( fp, 1 );                        // nbytes
         sgWriteChar( fp, idx_mask );
-    
-//        cout << "material:" << m << ", count =" << count << endl;
+
+        // vertex attribute property
+        if (va_mask != 0) {
+            sgWriteChar( fp, (char)SG_VERT_ATTRIBS );    // property
+            sgWriteUInt( fp, 4 );                        // nbytes
+            sgWriteChar( fp, va_mask );
+        }
+        
     // elements
         for (unsigned int i=start; i < end; ++i) {
             const int_list& va(verts[i]);
             const int_list& na((idx_mask & SG_IDX_NORMALS) ? normals[i] : emptyList);
             const int_list& ca((idx_mask & SG_IDX_COLORS) ? colors[i] : emptyList);
-            const int_list& tca((idx_mask & SG_IDX_TEXCOORDS) ? texCoords[i] : emptyList);
+
+            // pass the whole texcoord array - we'll figure out which indicies to write 
+            // in write_indices
+            const tci_list& tca( texCoords[i] );
+
+            // pass the whole vertex array - we'll figure out which indicies to write 
+            // in write_indices
+            const vai_list& vaa( vertexAttribs[i] );
             
             if (version == 7) {
-                write_indices<uint16_t>(fp, idx_mask, va, na, ca, tca);
+                write_indices<uint16_t>(fp, idx_mask, va_mask, va, na, ca, tca, vaa);
             } else {
-                write_indices<uint32_t>(fp, idx_mask, va, na, ca, tca);
+                write_indices<uint32_t>(fp, idx_mask, va_mask, va, na, ca, tca, vaa);
             }
         }
     
@@ -749,7 +943,6 @@ bool SGBinObject::write_bin_file(const SGPath& file)
     
     SGPath file2(file);
     file2.create_dir( 0755 );
-    cout << "Output file = " << file.str() << endl;
 
     gzFile fp;
     if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) {
@@ -759,19 +952,19 @@ bool SGBinObject::write_bin_file(const SGPath& file)
 
     sgClearWriteError();
 
-    cout << "points size = " << pts_v.size() << "  pt_materials = " 
-         << pt_materials.size() << endl;
-    cout << "triangles size = " << tris_v.size() << "  tri_materials = " 
-         << tri_materials.size() << endl;
-    cout << "strips size = " << strips_v.size() << "  strip_materials = " 
-         << strip_materials.size() << endl;
-    cout << "fans size = " << fans_v.size() << "  fan_materials = " 
-         << fan_materials.size() << endl;
+    SG_LOG(SG_IO, SG_DEBUG, "points size = " << pts_v.size() 
+         << "  pt_materials = " << pt_materials.size() );
+    SG_LOG(SG_IO, SG_DEBUG, "triangles size = " << tris_v.size() 
+         << "  tri_materials = " << tri_materials.size() );
+    SG_LOG(SG_IO, SG_DEBUG, "strips size = " << strips_v.size() 
+         << "  strip_materials = " << strip_materials.size() );
+    SG_LOG(SG_IO, SG_DEBUG, "fans size = " << fans_v.size() 
+         << "  fan_materials = " << fan_materials.size() );
 
-    cout << "nodes = " << wgs84_nodes.size() << endl;
-    cout << "colors = " << colors.size() << endl;
-    cout << "normals = " << normals.size() << endl;
-    cout << "tex coords = " << texcoords.size() << endl;
+    SG_LOG(SG_IO, SG_DEBUG, "nodes = " << wgs84_nodes.size() );
+    SG_LOG(SG_IO, SG_DEBUG, "colors = " << colors.size() );
+    SG_LOG(SG_IO, SG_DEBUG, "normals = " << normals.size() );
+    SG_LOG(SG_IO, SG_DEBUG, "tex coords = " << texcoords.size() );
 
     version = 10;
     bool shortMaterialsRanges = 
@@ -803,7 +996,8 @@ bool SGBinObject::write_bin_file(const SGPath& file)
     nobjects += count_objects(strip_materials);
     nobjects += count_objects(fan_materials);
 
-    cout << "total top level objects = " << nobjects << endl;
+    SG_LOG(SG_IO, SG_DEBUG, "total top level objects = " << nobjects);
+
     if (version == 7) {
         sgWriteUShort( fp, (uint16_t) nobjects );
     } else {
@@ -849,10 +1043,10 @@ bool SGBinObject::write_bin_file(const SGPath& file)
       sgWriteVec2( fp, texcoords[i]);
     }
 
-    write_objects(fp, SG_POINTS, pts_v, pts_n, pts_c, pts_tc, pt_materials);
-    write_objects(fp, SG_TRIANGLE_FACES, tris_v, tris_n, tris_c, tris_tc, tri_materials);
-    write_objects(fp, SG_TRIANGLE_STRIPS, strips_v, strips_n, strips_c, strips_tc, strip_materials);
-    write_objects(fp, SG_TRIANGLE_FANS, fans_v, fans_n, fans_c, fans_tc, fan_materials);
+    write_objects(fp, SG_POINTS, pts_v, pts_n, pts_c, pts_tcs, pts_vas, pt_materials);
+    write_objects(fp, SG_TRIANGLE_FACES, tris_v, tris_n, tris_c, tris_tcs, tris_vas, tri_materials);
+    write_objects(fp, SG_TRIANGLE_STRIPS, strips_v, strips_n, strips_c, strips_tcs, strips_vas, strip_materials);
+    write_objects(fp, SG_TRIANGLE_FANS, fans_v, fans_n, fans_c, fans_tcs, fans_vas, fan_materials);
     
     // close the file
     gzclose(fp);
@@ -952,7 +1146,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
             }
             // cout << "group = " << start << " to " << end - 1 << endl;
 
-      SGSphered d;
+      SGSphered d( SGVec3d(0.0, 0.0, 0.0), -1.0 );
       for ( i = start; i < end; ++i ) {
         for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
           d.expandBy(wgs84_nodes[ tris_v[i][j] ]);
@@ -972,7 +1166,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
             for ( i = start; i < end; ++i ) {
                 fprintf(fp, "f");
                 for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
-                    fprintf(fp, " %d/%d", tris_v[i][j], tris_tc[i][j] );
+                    fprintf(fp, " %d/%d", tris_v[i][j], tris_tcs[i][0][j] );
                 }
                 fprintf(fp, "\n");
             }
@@ -1001,7 +1195,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
             // cout << "group = " << start << " to " << end - 1 << endl;
 
 
-      SGSphered d;
+      SGSphered d( SGVec3d(0.0, 0.0, 0.0), -1.0 );
       for ( i = start; i < end; ++i ) {
         for ( j = 0; j < (int)tris_v[i].size(); ++j ) {
           d.expandBy(wgs84_nodes[ tris_v[i][j] ]);
@@ -1021,7 +1215,7 @@ bool SGBinObject::write_ascii( const string& base, const string& name,
             for ( i = start; i < end; ++i ) {
                 fprintf(fp, "ts");
                 for ( j = 0; j < (int)strips_v[i].size(); ++j ) {
-                    fprintf(fp, " %d/%d", strips_v[i][j], strips_tc[i][j] );
+                    fprintf(fp, " %d/%d", strips_v[i][j], strips_tcs[i][0][j] );
                 }
                 fprintf(fp, "\n");
             }
@@ -1061,3 +1255,27 @@ void SGBinObject::read_properties(gzFile fp, int nproperties)
     }
 }
 
+bool SGBinObject::add_point( const SGBinObjectPoint& pt )
+{
+    // add the point info
+    pt_materials.push_back( pt.material );
+    
+    pts_v.push_back( pt.v_list );
+    pts_n.push_back( pt.n_list );    
+    pts_c.push_back( pt.c_list );
+    
+    return true;
+}
+
+bool SGBinObject::add_triangle( const SGBinObjectTriangle& tri )
+{
+    // add the triangle info and keep lists aligned
+    tri_materials.push_back( tri.material );
+    tris_v.push_back( tri.v_list );
+    tris_n.push_back( tri.n_list );
+    tris_c.push_back( tri.c_list );
+    tris_tcs.push_back( tri.tc_list );
+    tris_vas.push_back( tri.va_list );
+    
+    return true;
+}
\ No newline at end of file
index d594113de0ef3b9e8f3b622df2e2441520f0d66e..bbf1f90f24934a1b2e14e1f6c1b2545190df94bc 100644 (file)
 
 #include <vector>
 #include <string>
+#include <boost/array.hpp>
 
-/** STL Structure used to store object information */
+#define MAX_TC_SETS     (4)
+#define MAX_VAS         (8)
+
+// I really want to pass around fixed length arrays, as the size 
+// has to be hardcoded
+// but it's a C++0x feature use boost in its absence
+typedef boost::array<int_list, MAX_TC_SETS> tci_list;
+typedef boost::array<int_list, MAX_VAS>     vai_list;
+
+/** STL Structure used to store (integer index) object information */
 typedef std::vector < int_list > group_list;
 typedef group_list::iterator group_list_iterator;
 typedef group_list::const_iterator const_group_list_iterator;
 
+/** STL Structure used to store (tc index) object information */
+typedef std::vector < tci_list > group_tci_list;
+typedef group_tci_list::iterator group_tci_list_iterator;
+typedef group_tci_list::const_iterator const_group_tci_list_iterator;
+
+/** STL Structure used to store (va index) object information */
+typedef std::vector < vai_list > group_vai_list;
+typedef group_vai_list::iterator group_vai_list_iterator;
+typedef group_vai_list::const_iterator const_group_vai_list_iterator;
+
+
 // forward decls
 class SGBucket;
 class SGPath;
 
+class SGBinObjectPoint {
+public:
+    std::string material;
+    int_list    v_list;
+    int_list    n_list;
+    int_list    c_list;
+    
+    void clear( void ) {
+        material = "";
+        v_list.clear();
+        n_list.clear();
+        c_list.clear();
+    };    
+};
+
+class SGBinObjectTriangle {
+public:
+    std::string material;
+    int_list    v_list;
+    int_list    n_list;
+    int_list    c_list;
+    
+    tci_list    tc_list;
+    vai_list    va_list;
+
+    void clear( void ) {
+        material = "";
+        v_list.clear();
+        n_list.clear();
+        c_list.clear();
+        for ( unsigned int i=0; i<MAX_TC_SETS; i++ ) {
+            tc_list[i].clear();
+        }
+        for ( unsigned int i=0; i<MAX_VAS; i++ ) {
+            va_list[i].clear();
+        }
+    };
+    
+};
+
+
+
 /**
  * A class to manipulate the simgear 3d object format.
  * This class provides functionality to both read and write the binary format.
@@ -86,34 +149,40 @@ private:
     SGVec3d gbs_center;
     float gbs_radius;
 
-    std::vector<SGVec3d> wgs84_nodes;  // vertex list
-    std::vector<SGVec4f> colors;       // color list
-    std::vector<SGVec3f> normals;      // normal list
-    std::vector<SGVec2f> texcoords;    // texture coordinate list
-
-    group_list pts_v;          // points vertex index
-    group_list pts_n;          // points normal index
-    group_list pts_c;          // points color index
-    group_list pts_tc;         // points texture coordinate index
-    string_list pt_materials;  // points materials
-
-    group_list tris_v;         // triangles vertex index
-    group_list tris_n;         // triangles normal index
-    group_list tris_c;         // triangles color index
-    group_list tris_tc;                // triangles texture coordinate index
-    string_list tri_materials; // triangles materials
-
-    group_list strips_v;       // tristrips vertex index
-    group_list strips_n;       // tristrips normal index
-    group_list strips_c;       // tristrips color index
-    group_list strips_tc;      // tristrips texture coordinate index
-    string_list strip_materials;// tristrips materials
-
-    group_list fans_v;         // fans vertex index
-    group_list fans_n;         // fans normal index
-    group_list fans_c;         // fans color index
-    group_list fans_tc;                // fans texture coordinate index
-    string_list fan_materials; // fans materials
+    std::vector<SGVec3d> wgs84_nodes;   // vertex list
+    std::vector<SGVec4f> colors;        // color list
+    std::vector<SGVec3f> normals;       // normal list
+    std::vector<SGVec2f> texcoords;     // texture coordinate list
+    std::vector<float>   va_flt;        // vertex attribute list (floats)
+    std::vector<int>     va_int;        // vertex attribute list (ints) 
+    
+    group_list pts_v;                  // points vertex index
+    group_list pts_n;                  // points normal index
+    group_list pts_c;                  // points color index
+    group_tci_list pts_tcs;             // points texture coordinates ( up to 4 sets )
+    group_vai_list pts_vas;             // points vertex attributes ( up to 8 sets )
+    string_list pt_materials;           // points materials
+
+    group_list tris_v;                 // triangles vertex index
+    group_list tris_n;                 // triangles normal index
+    group_list tris_c;                 // triangles color index
+    group_tci_list tris_tcs;            // triangles texture coordinates ( up to 4 sets )
+    group_vai_list tris_vas;            // triangles vertex attributes ( up to 8 sets )
+    string_list tri_materials;          // triangles materials
+
+    group_list strips_v;               // tristrips vertex index
+    group_list strips_n;               // tristrips normal index
+    group_list strips_c;               // tristrips color index
+    group_tci_list strips_tcs;          // tristrips texture coordinates ( up to 4 sets )
+    group_vai_list strips_vas;          // tristrips vertex attributes ( up to 8 sets )
+    string_list strip_materials;        // tristrips materials
+
+    group_list fans_v;                 // fans vertex index
+    group_list fans_n;                 // fans normal index
+    group_list fans_c;                 // fans color index
+    group_tci_list fans_tcs;            // fanss texture coordinates ( up to 4 sets )
+    group_vai_list fans_vas;            // fans vertex attributes ( up to 8 sets )
+    string_list fan_materials;         // fans materials
 
     void read_properties(gzFile fp, int nproperties);
     
@@ -124,17 +193,23 @@ private:
                              group_list& vertices, 
                              group_list& normals,
                              group_list& colors,
-                             group_list& texCoords,
+                             group_tci_list& texCoords,
+                             group_vai_list& vertexAttribs,
                              string_list& materials);
                              
     void write_header(gzFile fp, int type, int nProps, int nElements);
-    void write_objects(gzFile fp, int type, const group_list& verts,
-        const group_list& normals, const group_list& colors, 
-        const group_list& texCoords, const string_list& materials);
+    void write_objects(gzFile fp, 
+                       int type, 
+                       const group_list& verts,
+                       const group_list& normals, 
+                       const group_list& colors, 
+                       const group_tci_list& texCoords, 
+                       const group_vai_list& vertexAttribs,
+                       const string_list& materials);
         
     unsigned int count_objects(const string_list& materials);
-public:
-
+    
+public:    
     inline unsigned short get_version() const { return version; }
 
     inline const SGVec3d& get_gbs_center() const { return gbs_center; }
@@ -143,10 +218,8 @@ public:
     inline float get_gbs_radius() const { return gbs_radius; }
     inline void set_gbs_radius( float r ) { gbs_radius = r; }
 
-    inline const std::vector<SGVec3d>& get_wgs84_nodes() const
-    { return wgs84_nodes; }
-    inline void set_wgs84_nodes( const std::vector<SGVec3d>& n )
-    { wgs84_nodes = n; }
+    inline const std::vector<SGVec3d>& get_wgs84_nodes() const { return wgs84_nodes; }
+    inline void set_wgs84_nodes( const std::vector<SGVec3d>& n ) { wgs84_nodes = n; }
 
     inline const std::vector<SGVec4f>& get_colors() const { return colors; }
     inline void set_colors( const std::vector<SGVec4f>& c ) { colors = c; }
@@ -157,51 +230,38 @@ public:
     inline const std::vector<SGVec2f>& get_texcoords() const { return texcoords; }
     inline void set_texcoords( const std::vector<SGVec2f>& t ) { texcoords = t; }
     
+    // Points API
+    bool add_point( const SGBinObjectPoint& pt );
     inline const group_list& get_pts_v() const { return pts_v; }
-    inline void set_pts_v( const group_list& g ) { pts_v = g; }
-    inline const group_list& get_pts_n() const { return pts_n; }
-    inline void set_pts_n( const group_list& g ) { pts_n = g; }
-    inline const group_list& get_pts_c() const { return pts_c; }
-    inline void set_pts_c( const group_list& g ) { pts_c = g; }
-    inline const group_list& get_pts_tc() const { return pts_tc; }
-    inline void set_pts_tc( const group_list& g ) { pts_tc = g; }
+    inline const group_list& get_pts_n() const { return pts_n; }    
+    inline const group_tci_list& get_pts_tcs() const { return pts_tcs; }
+    inline const group_vai_list& get_pts_vas() const { return pts_vas; }
     inline const string_list& get_pt_materials() const { return pt_materials; }
-    inline void set_pt_materials( const string_list& s ) { pt_materials = s; }
 
+    // Triangles API
+    bool add_triangle( const SGBinObjectTriangle& tri );
     inline const group_list& get_tris_v() const { return tris_v; }
-    inline void set_tris_v( const group_list& g ) { tris_v = g; }
     inline const group_list& get_tris_n() const { return tris_n; }
-    inline void set_tris_n( const group_list& g ) { tris_n = g; }
     inline const group_list& get_tris_c() const { return tris_c; }
-    inline void set_tris_c( const group_list& g ) { tris_c = g; }
-    inline const group_list& get_tris_tc() const { return tris_tc; }
-    inline void set_tris_tc( const group_list& g ) { tris_tc = g; }
+    inline const group_tci_list& get_tris_tcs() const { return tris_tcs; }
+    inline const group_vai_list& get_tris_vas() const { return tris_vas; }
     inline const string_list& get_tri_materials() const { return tri_materials; }
-    inline void set_tri_materials( const string_list& s ) { tri_materials = s; }
     
+    // Strips API (deprecated - read only)
     inline const group_list& get_strips_v() const { return strips_v; }
-    inline void set_strips_v( const group_list& g ) { strips_v = g; }
     inline const group_list& get_strips_n() const { return strips_n; }
-    inline void set_strips_n( const group_list& g ) { strips_n = g; }
     inline const group_list& get_strips_c() const { return strips_c; }
-    inline void set_strips_c( const group_list& g ) { strips_c = g; }
-
-    inline const group_list& get_strips_tc() const { return strips_tc; }
-    inline void set_strips_tc( const group_list& g ) { strips_tc = g; }
+    inline const group_tci_list& get_strips_tcs() const { return strips_tcs; }
+    inline const group_vai_list& get_strips_vas() const { return strips_vas; }
     inline const string_list& get_strip_materials() const { return strip_materials; }
-    inline void set_strip_materials( const string_list& s ) { strip_materials = s; }
-    
+
+    // Fans API (deprecated - read only )
     inline const group_list& get_fans_v() const { return fans_v; }
-    inline void set_fans_v( const group_list& g ) { fans_v = g; }
     inline const group_list& get_fans_n() const { return fans_n; }
-    inline void set_fans_n( const group_list& g ) { fans_n = g; }
     inline const group_list& get_fans_c() const { return fans_c; }
-    inline void set_fans_c( const group_list& g ) { fans_c = g; }
-
-    inline const group_list& get_fans_tc() const { return fans_tc; }
-    inline void set_fans_tc( const group_list& g ) { fans_tc = g; }
+    inline const group_tci_list& get_fans_tcs() const { return fans_tcs; }
+    inline const group_vai_list& get_fans_vas() const { return fans_vas; }
     inline const string_list& get_fan_materials() const { return fan_materials; }
-    inline void set_fan_materials( const string_list& s ) { fan_materials = s; }
 
     /**
      * Read a binary file object and populate the provided structures.
index 00b697906c1cabbe5c2fb22263fc97b8123b74ee..f51a9a19980fd58e14da691fd93b3e35c4e6caae 100644 (file)
@@ -103,6 +103,15 @@ int_list make_tri(int maxIndex)
     return r;
 }
 
+tci_list make_tri_tcs(int maxIndex)
+{
+    tci_list tci;
+    tci[0].push_back(random() % maxIndex);
+    tci[0].push_back(random() % maxIndex);
+    tci[0].push_back(random() % maxIndex);
+    return tci;
+}
+
 void compareTris(const SGBinObject& a, const SGBinObject& b)
 {
     unsigned int count = a.get_tri_materials().size();
@@ -113,32 +122,31 @@ void compareTris(const SGBinObject& a, const SGBinObject& b)
 
         COMPARE(a.get_tri_materials()[i], b.get_tri_materials()[i]);
         
-        const int_list& tA(a.get_tris_tc()[i]);
-        const int_list& tB(b.get_tris_tc()[i]);
+        const int_list& tA(a.get_tris_tcs()[i][0]);
+        const int_list& tB(b.get_tris_tcs()[i][0]);
         VERIFY(tA == tB);
     }
 }
 
 void generate_tris(SGBinObject& b, int count)
 {
-    group_list v, n, tc;
+    group_list v, n;
+    group_tci_list tc;
     string_list materials;
 
     int maxVertices = b.get_wgs84_nodes().size();
     int maxNormals = b.get_normals().size();
     int maxTCs = b.get_texcoords().size();
     
+    SGBinObjectTriangle sgboTri;
     for (int t=0; t<count; ++t) {
-        v.push_back(make_tri(maxVertices));
-        n.push_back(make_tri(maxNormals));
-        tc.push_back(make_tri(maxTCs));
-        materials.push_back("material1");
+        sgboTri.material = "material1";    
+        sgboTri.v_list = make_tri(maxVertices);
+        sgboTri.n_list = make_tri(maxNormals);
+        sgboTri.tc_list[0] = make_tri(maxTCs);
+
+        b.add_triangle( sgboTri );
     }
-    
-    b.set_tris_v(v);
-    b.set_tris_n(n);
-    b.set_tris_tc(tc);
-    b.set_tri_materials(materials);
 }
  
 void test_basic()
index bd30900e25860216f085faeb60bd70eb16b7bd64..67b8e98025d985841bf1c5ccbebeb0f71911c729 100644 (file)
 
 
 struct SGVertNormTex {
-  SGVertNormTex()
-  { }
-  SGVertNormTex(const SGVec3f& v, const SGVec3f& n, const SGVec2f& t) :
-    vertex(v), normal(n), texCoord(t)
-  { }
+  SGVertNormTex() { 
+      tc_mask = 0;
+  }
+
   struct less
   {
+    inline bool tc_is_less ( const SGVertNormTex& l,
+                             const SGVertNormTex& r,
+                             int   idx ) const
+    {
+        if ( r.tc_mask & 1<<idx ) {
+            if ( l.tc_mask & 1<<idx ) {
+                if (l.texCoord[idx] < r.texCoord[idx]) {
+                    return true;
+                }
+            }
+        } 
+        
+        return false;
+    };
+    
     inline bool operator() (const SGVertNormTex& l,
                             const SGVertNormTex& r) const
     {
@@ -49,13 +63,35 @@ struct SGVertNormTex {
       else if (r.vertex < l.vertex) return false;
       else if (l.normal < r.normal) return true;
       else if (r.normal < l.normal) return false;
-      else return l.texCoord < r.texCoord;
+      else if ( tc_is_less( l, r, 0 ) ) return true;
+      else if ( tc_is_less( r, l, 0 ) ) return false;
+      else if ( tc_is_less( l, r, 1 ) ) return true;
+      else if ( tc_is_less( r, l, 1 ) ) return false;
+      else if ( tc_is_less( l, r, 2 ) ) return true;
+      else if ( tc_is_less( r, l, 2 ) ) return false;
+      else if ( tc_is_less( l, r, 3 ) ) return true;
+      else return false;
     }
   };
 
+  void SetVertex( const SGVec3f& v )          { vertex = v; }
+  const SGVec3f& GetVertex( void ) const      { return vertex; }
+  
+  void SetNormal( const SGVec3f& n )          { normal = n; }
+  const SGVec3f& GetNormal( void ) const      { return normal; }
+  
+  void SetTexCoord( unsigned idx, const SGVec2f& tc ) { 
+      texCoord[idx] = tc; 
+      tc_mask |= 1 << idx; 
+  }
+  const SGVec2f& GetTexCoord( unsigned idx ) const { return texCoord[idx]; }
+
+private:  
   SGVec3f vertex;
   SGVec3f normal;
-  SGVec2f texCoord;
+  SGVec2f texCoord[4];
+  
+  unsigned tc_mask;
 };
 
 // Use a DrawElementsUShort if there are few enough vertices,
@@ -101,6 +137,7 @@ public:
   SGTexturedTriangleBin()
   {
     mt_init(&seed, 123);
+    has_sec_tcs = false;
   }
 
   // Computes and adds random surface points to the points list.
@@ -114,12 +151,12 @@ public:
     unsigned num = getNumTriangles();
     for (unsigned i = 0; i < num; ++i) {
       triangle_ref triangleRef = getTriangleRef(i);
-      SGVec3f v0 = getVertex(triangleRef[0]).vertex;
-      SGVec3f v1 = getVertex(triangleRef[1]).vertex;
-      SGVec3f v2 = getVertex(triangleRef[2]).vertex;
-      SGVec2f t0 = getVertex(triangleRef[0]).texCoord;
-      SGVec2f t1 = getVertex(triangleRef[1]).texCoord;
-      SGVec2f t2 = getVertex(triangleRef[2]).texCoord;
+      SGVec3f v0 = getVertex(triangleRef[0]).GetVertex();
+      SGVec3f v1 = getVertex(triangleRef[1]).GetVertex();
+      SGVec3f v2 = getVertex(triangleRef[2]).GetVertex();
+      SGVec2f t0 = getVertex(triangleRef[0]).GetTexCoord(0);
+      SGVec2f t1 = getVertex(triangleRef[1]).GetTexCoord(0);
+      SGVec2f t2 = getVertex(triangleRef[2]).GetTexCoord(0);
       SGVec3f normal = cross(v1 - v0, v2 - v0);
       
       // Compute the area
@@ -180,12 +217,12 @@ public:
     unsigned num = getNumTriangles();
     for (unsigned i = 0; i < num; ++i) {
       triangle_ref triangleRef = getTriangleRef(i);
-      SGVec3f v0 = getVertex(triangleRef[0]).vertex;
-      SGVec3f v1 = getVertex(triangleRef[1]).vertex;
-      SGVec3f v2 = getVertex(triangleRef[2]).vertex;
-      SGVec2f t0 = getVertex(triangleRef[0]).texCoord;
-      SGVec2f t1 = getVertex(triangleRef[1]).texCoord;
-      SGVec2f t2 = getVertex(triangleRef[2]).texCoord;
+      SGVec3f v0 = getVertex(triangleRef[0]).GetVertex();
+      SGVec3f v1 = getVertex(triangleRef[1]).GetVertex();
+      SGVec3f v2 = getVertex(triangleRef[2]).GetVertex();
+      SGVec2f t0 = getVertex(triangleRef[0]).GetTexCoord(0);
+      SGVec2f t1 = getVertex(triangleRef[1]).GetTexCoord(0);
+      SGVec2f t2 = getVertex(triangleRef[2]).GetTexCoord(0);
       SGVec3f normal = cross(v1 - v0, v2 - v0);
       
       // Ensure the slope isn't too steep by checking the
@@ -257,12 +294,12 @@ public:
     unsigned num = getNumTriangles();
     for (unsigned i = 0; i < num; ++i) {
       triangle_ref triangleRef = getTriangleRef(i);
-      SGVec3f v0 = getVertex(triangleRef[0]).vertex;
-      SGVec3f v1 = getVertex(triangleRef[1]).vertex;
-      SGVec3f v2 = getVertex(triangleRef[2]).vertex;
-      SGVec2f t0 = getVertex(triangleRef[0]).texCoord;
-      SGVec2f t1 = getVertex(triangleRef[1]).texCoord;
-      SGVec2f t2 = getVertex(triangleRef[2]).texCoord;
+      SGVec3f v0 = getVertex(triangleRef[0]).GetVertex();
+      SGVec3f v1 = getVertex(triangleRef[1]).GetVertex();
+      SGVec3f v2 = getVertex(triangleRef[2]).GetVertex();
+      SGVec2f t0 = getVertex(triangleRef[0]).GetTexCoord(0);
+      SGVec2f t1 = getVertex(triangleRef[1]).GetTexCoord(0);
+      SGVec2f t2 = getVertex(triangleRef[2]).GetTexCoord(0);
       SGVec3f normal = cross(v1 - v0, v2 - v0);
       
       // Compute the area
@@ -324,7 +361,8 @@ public:
     // FIXME: do not include all values here ...
     osg::Vec3Array* vertices = new osg::Vec3Array;
     osg::Vec3Array* normals = new osg::Vec3Array;
-    osg::Vec2Array* texCoords = new osg::Vec2Array;
+    osg::Vec2Array* priTexCoords = new osg::Vec2Array;
+    osg::Vec2Array* secTexCoords = new osg::Vec2Array;
 
     osg::Vec4Array* colors = new osg::Vec4Array;
     colors->push_back(osg::Vec4(1, 1, 1, 1));
@@ -341,7 +379,12 @@ public:
     geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
     geometry->setColorArray(colors);
     geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
-    geometry->setTexCoordArray(0, texCoords);
+    if ( has_sec_tcs ) {
+        geometry->setTexCoordArray(0, priTexCoords);
+        geometry->setTexCoordArray(1, secTexCoords);
+    } else {
+        geometry->setTexCoordArray(0, priTexCoords);
+    }        
 
     const unsigned invalid = ~unsigned(0);
     std::vector<unsigned> indexMap(getNumVertices(), invalid);
@@ -351,25 +394,34 @@ public:
       triangle_ref triangle = triangles[i];
       if (indexMap[triangle[0]] == invalid) {
         indexMap[triangle[0]] = vertices->size();
-        vertices->push_back(toOsg(getVertex(triangle[0]).vertex));
-        normals->push_back(toOsg(getVertex(triangle[0]).normal));
-        texCoords->push_back(toOsg(getVertex(triangle[0]).texCoord));
+        vertices->push_back(toOsg(getVertex(triangle[0]).GetVertex()));
+        normals->push_back(toOsg(getVertex(triangle[0]).GetNormal()));
+        priTexCoords->push_back(toOsg(getVertex(triangle[0]).GetTexCoord(0)));
+        if ( has_sec_tcs ) {
+            secTexCoords->push_back(toOsg(getVertex(triangle[0]).GetTexCoord(1)));
+        }
       }
       deFacade.push_back(indexMap[triangle[0]]);
 
       if (indexMap[triangle[1]] == invalid) {
         indexMap[triangle[1]] = vertices->size();
-        vertices->push_back(toOsg(getVertex(triangle[1]).vertex));
-        normals->push_back(toOsg(getVertex(triangle[1]).normal));
-        texCoords->push_back(toOsg(getVertex(triangle[1]).texCoord));
+        vertices->push_back(toOsg(getVertex(triangle[1]).GetVertex()));
+        normals->push_back(toOsg(getVertex(triangle[1]).GetNormal()));
+        priTexCoords->push_back(toOsg(getVertex(triangle[1]).GetTexCoord(0)));
+        if ( has_sec_tcs ) {
+            secTexCoords->push_back(toOsg(getVertex(triangle[1]).GetTexCoord(1)));
+        }
       }
       deFacade.push_back(indexMap[triangle[1]]);
 
       if (indexMap[triangle[2]] == invalid) {
         indexMap[triangle[2]] = vertices->size();
-        vertices->push_back(toOsg(getVertex(triangle[2]).vertex));
-        normals->push_back(toOsg(getVertex(triangle[2]).normal));
-        texCoords->push_back(toOsg(getVertex(triangle[2]).texCoord));
+        vertices->push_back(toOsg(getVertex(triangle[2]).GetVertex()));
+        normals->push_back(toOsg(getVertex(triangle[2]).GetNormal()));
+        priTexCoords->push_back(toOsg(getVertex(triangle[2]).GetTexCoord(0)));
+        if ( has_sec_tcs ) {
+            secTexCoords->push_back(toOsg(getVertex(triangle[2]).GetTexCoord(1)));
+        }
       }
       deFacade.push_back(indexMap[triangle[2]]);
     }
@@ -387,14 +439,19 @@ public:
       return 0;
 
     triangle_ref triangleRef = getTriangleRef(0);
-    SGVec3f v0 = getVertex(triangleRef[0]).vertex;
+    SGVec3f v0 = getVertex(triangleRef[0]).GetVertex();
       
     return floor(v0.x());
   }
+  
+  void hasSecondaryTexCoord( bool sec_tc ) { has_sec_tcs = sec_tc; }
 
 private:
   // Random seed for the triangle.
   mt seed;
+  
+  // does the triangle array have secondary texture coordinates
+  bool has_sec_tcs;
 };
 
 #endif
index 8885e405a81cd0ee7147879fd2adb949343e8e47..1b55325d9b2ea698b79c9554227b2a1ebd454970 100644 (file)
@@ -219,72 +219,107 @@ public:
 
   static void
   addTriangleGeometry(SGTexturedTriangleBin& triangles,
-                      const std::vector<SGVec3d>& vertices,
-                      const std::vector<SGVec3f>& normals,
-                      const std::vector<SGVec2f>& texCoords,
-                      const int_list& tris_v,
-                      const int_list& tris_n,
-                      const int_list& tris_tc,
-                      const SGVec2f& tcScale)
+                      const SGBinObject& obj, unsigned grp,
+                      const SGVec2f& tc0Scale, 
+                      const SGVec2f& tc1Scale)
   {
+    const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
+    const std::vector<SGVec3f>& normals(obj.get_normals());
+    const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
+    const int_list& tris_v(obj.get_tris_v()[grp]);
+    const int_list& tris_n(obj.get_tris_n()[grp]);
+    const tci_list& tris_tc(obj.get_tris_tcs()[grp]);
+    bool  num_norms_is_num_verts = true;  
+    
     if (tris_v.size() != tris_n.size()) {
-      // If the normal indices do not match, they should be inmplicitly
-      // the same than the vertex indices. So just call ourselves again
-      // with the matching index vector.
-      addTriangleGeometry(triangles, vertices, normals, texCoords,
-                          tris_v, tris_v, tris_tc, tcScale);
-      return;
+        // If the normal indices do not match, they should be inmplicitly
+        // the same than the vertex indices. 
+        num_norms_is_num_verts = false;
     }
 
+    if ( !tris_tc[1].empty() ) {
+        triangles.hasSecondaryTexCoord(true);
+    }
+    
     for (unsigned i = 2; i < tris_v.size(); i += 3) {
-      SGVertNormTex v0;
-      v0.vertex = toVec3f(vertices[tris_v[i-2]]);
-      v0.normal = normals[tris_n[i-2]];
-      v0.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i-2);
-      SGVertNormTex v1;
-      v1.vertex = toVec3f(vertices[tris_v[i-1]]);
-      v1.normal = normals[tris_n[i-1]];
-      v1.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i-1);
-      SGVertNormTex v2;
-      v2.vertex = toVec3f(vertices[tris_v[i]]);
-      v2.normal = normals[tris_n[i]];
-      v2.texCoord = getTexCoord(texCoords, tris_tc, tcScale, i);
-      triangles.insert(v0, v1, v2);
+        SGVertNormTex v0;
+        v0.SetVertex( toVec3f(vertices[tris_v[i-2]]) );
+        v0.SetNormal( num_norms_is_num_verts ? normals[tris_n[i-2]] : 
+                                               normals[tris_v[i-2]] );
+        v0.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i-2) );
+        if (!tris_tc[1].empty()) {
+            v0.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i-2) );
+        }
+        SGVertNormTex v1;
+        v1.SetVertex( toVec3f(vertices[tris_v[i-1]]) );
+        v1.SetNormal( num_norms_is_num_verts ? normals[tris_n[i-1]] : 
+                                               normals[tris_v[i-1]] );
+        v1.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i-1) );
+        if (!tris_tc[1].empty()) {
+            v1.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i-1) );
+        }
+        SGVertNormTex v2;
+        v2.SetVertex( toVec3f(vertices[tris_v[i]]) );
+        v2.SetNormal( num_norms_is_num_verts ? normals[tris_n[i]] : 
+                                               normals[tris_v[i]] );
+        v2.SetTexCoord( 0, getTexCoord(texCoords, tris_tc[0], tc0Scale, i) );
+        if (!tris_tc[1].empty()) {
+            v2.SetTexCoord( 1, getTexCoord(texCoords, tris_tc[1], tc1Scale, i) );
+        }
+        
+        triangles.insert(v0, v1, v2);
     }
   }
 
   static void
   addStripGeometry(SGTexturedTriangleBin& triangles,
-                   const std::vector<SGVec3d>& vertices,
-                   const std::vector<SGVec3f>& normals,
-                   const std::vector<SGVec2f>& texCoords,
-                   const int_list& strips_v,
-                   const int_list& strips_n,
-                   const int_list& strips_tc,
-                   const SGVec2f& tcScale)
+                   const SGBinObject& obj, unsigned grp,
+                   const SGVec2f& tc0Scale, 
+                   const SGVec2f& tc1Scale)
   {
-    if (strips_v.size() != strips_n.size()) {
-      // If the normal indices do not match, they should be inmplicitly
-      // the same than the vertex indices. So just call ourselves again
-      // with the matching index vector.
-      addStripGeometry(triangles, vertices, normals, texCoords,
-                       strips_v, strips_v, strips_tc, tcScale);
-      return;
-    }
-
+      const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
+      const std::vector<SGVec3f>& normals(obj.get_normals());
+      const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
+      const int_list& strips_v(obj.get_strips_v()[grp]);
+      const int_list& strips_n(obj.get_strips_n()[grp]);
+      const tci_list& strips_tc(obj.get_strips_tcs()[grp]);
+      bool  num_norms_is_num_verts = true;  
+      
+      if (strips_v.size() != strips_n.size()) {
+          // If the normal indices do not match, they should be inmplicitly
+          // the same than the vertex indices. 
+          num_norms_is_num_verts = false;
+      }
+      
+      if ( !strips_tc[1].empty() ) {
+          triangles.hasSecondaryTexCoord(true);
+      }
+      
     for (unsigned i = 2; i < strips_v.size(); ++i) {
       SGVertNormTex v0;
-      v0.vertex = toVec3f(vertices[strips_v[i-2]]);
-      v0.normal = normals[strips_n[i-2]];
-      v0.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i-2);
+      v0.SetVertex( toVec3f(vertices[strips_v[i-2]]) );
+      v0.SetNormal( num_norms_is_num_verts ? normals[strips_n[i-2]] : 
+                                             normals[strips_v[i-2]] );
+      v0.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[0], tc0Scale, i-2) );
+      if (!strips_tc[1].empty()) {
+          v0.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i-2) );
+      }
       SGVertNormTex v1;
-      v1.vertex = toVec3f(vertices[strips_v[i-1]]);
-      v1.normal = normals[strips_n[i-1]];
-      v1.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i-1);
+      v1.SetVertex( toVec3f(vertices[strips_v[i-1]]) );
+      v1.SetNormal( num_norms_is_num_verts ? normals[strips_n[i-1]] : 
+                                             normals[strips_v[i-1]] );
+      v1.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[1], tc0Scale, i-1) );
+      if (!strips_tc[1].empty()) {
+          v1.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i-1) );
+      }
       SGVertNormTex v2;
-      v2.vertex = toVec3f(vertices[strips_v[i]]);
-      v2.normal = normals[strips_n[i]];
-      v2.texCoord = getTexCoord(texCoords, strips_tc, tcScale, i);
+      v2.SetVertex( toVec3f(vertices[strips_v[i]]) );
+      v2.SetNormal( num_norms_is_num_verts ? normals[strips_n[i]] : 
+                                             normals[strips_v[i]] );
+      v2.SetTexCoord( 0, getTexCoord(texCoords, strips_tc[0], tc0Scale, i) );
+      if (!strips_tc[1].empty()) {
+          v2.SetTexCoord( 1, getTexCoord(texCoords, strips_tc[1], tc1Scale, i) );
+      }
       if (i%2)
         triangles.insert(v1, v0, v2);
       else
@@ -294,36 +329,53 @@ public:
 
   static void
   addFanGeometry(SGTexturedTriangleBin& triangles,
-                 const std::vector<SGVec3d>& vertices,
-                 const std::vector<SGVec3f>& normals,
-                 const std::vector<SGVec2f>& texCoords,
-                 const int_list& fans_v,
-                 const int_list& fans_n,
-                 const int_list& fans_tc,
-                 const SGVec2f& tcScale)
+                 const SGBinObject& obj, unsigned grp,
+                 const SGVec2f& tc0Scale, 
+                 const SGVec2f& tc1Scale)
   {
-    if (fans_v.size() != fans_n.size()) {
-      // If the normal indices do not match, they should be implicitly
-      // the same than the vertex indices. So just call ourselves again
-      // with the matching index vector.
-      addFanGeometry(triangles, vertices, normals, texCoords,
-                     fans_v, fans_v, fans_tc, tcScale);
-      return;
-    }
-
+      const std::vector<SGVec3d>& vertices(obj.get_wgs84_nodes());
+      const std::vector<SGVec3f>& normals(obj.get_normals());
+      const std::vector<SGVec2f>& texCoords(obj.get_texcoords());
+      const int_list& fans_v(obj.get_fans_v()[grp]);
+      const int_list& fans_n(obj.get_fans_n()[grp]);
+      const tci_list& fans_tc(obj.get_fans_tcs()[grp]);
+      bool  num_norms_is_num_verts = true;  
+      
+      if (fans_v.size() != fans_n.size()) {
+          // If the normal indices do not match, they should be inmplicitly
+          // the same than the vertex indices. 
+          num_norms_is_num_verts = false;
+      }
+      
+      if ( !fans_tc[1].empty() ) {
+          triangles.hasSecondaryTexCoord(true);
+      }
+      
     SGVertNormTex v0;
-    v0.vertex = toVec3f(vertices[fans_v[0]]);
-    v0.normal = normals[fans_n[0]];
-    v0.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 0);
+    v0.SetVertex( toVec3f(vertices[fans_v[0]]) );
+    v0.SetNormal( num_norms_is_num_verts ? normals[fans_n[0]] : 
+                                           normals[fans_v[0]] );
+    v0.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, 0) );
+    if (!fans_tc[1].empty()) {
+        v0.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, 0) );
+    }
     SGVertNormTex v1;
-    v1.vertex = toVec3f(vertices[fans_v[1]]);
-    v1.normal = normals[fans_n[1]];
-    v1.texCoord = getTexCoord(texCoords, fans_tc, tcScale, 1);
+    v1.SetVertex( toVec3f(vertices[fans_v[1]]) );
+    v1.SetNormal( num_norms_is_num_verts ? normals[fans_n[1]] : 
+                                           normals[fans_v[1]] );
+    v1.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, 1) );
+    if (!fans_tc[1].empty()) {
+        v1.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, 1) );
+    }
     for (unsigned i = 2; i < fans_v.size(); ++i) {
       SGVertNormTex v2;
-      v2.vertex = toVec3f(vertices[fans_v[i]]);
-      v2.normal = normals[fans_n[i]];
-      v2.texCoord = getTexCoord(texCoords, fans_tc, tcScale, i);
+      v2.SetVertex( toVec3f(vertices[fans_v[i]]) );
+      v2.SetNormal( num_norms_is_num_verts ? normals[fans_n[i]] : 
+                                             normals[fans_v[i]] );
+      v2.SetTexCoord( 0, getTexCoord(texCoords, fans_tc[0], tc0Scale, i) );
+      if (!fans_tc[1].empty()) {
+          v2.SetTexCoord( 1, getTexCoord(texCoords, fans_tc[1], tc1Scale, i) );
+      }
       triangles.insert(v0, v1, v2);
       v1 = v2;
     }
@@ -344,7 +396,7 @@ public:
   insertSurfaceGeometry(const SGBinObject& obj, SGMaterialLib* matlib)
   {
     if (obj.get_tris_n().size() < obj.get_tris_v().size() ||
-        obj.get_tris_tc().size() < obj.get_tris_v().size()) {
+        obj.get_tris_tcs().size() < obj.get_tris_v().size()) {
       SG_LOG(SG_TERRAIN, SG_ALERT,
              "Group list sizes for triangles do not match!");
       return false;
@@ -352,44 +404,38 @@ public:
 
     for (unsigned grp = 0; grp < obj.get_tris_v().size(); ++grp) {
       std::string materialName = obj.get_tri_materials()[grp];
-      SGVec2f tcScale = getTexCoordScale(materialName, matlib);
+      SGVec2f tc0Scale = getTexCoordScale(materialName, matlib);
+      SGVec2f tc1Scale(1.0, 1.0);
       addTriangleGeometry(materialTriangleMap[materialName],
-                          obj.get_wgs84_nodes(), obj.get_normals(),
-                          obj.get_texcoords(), obj.get_tris_v()[grp],
-                          obj.get_tris_n()[grp], obj.get_tris_tc()[grp],
-                          tcScale);
+                          obj, grp, tc0Scale, tc1Scale );
     }
 
     if (obj.get_strips_n().size() < obj.get_strips_v().size() ||
-        obj.get_strips_tc().size() < obj.get_strips_v().size()) {
+        obj.get_strips_tcs().size() < obj.get_strips_v().size()) {
       SG_LOG(SG_TERRAIN, SG_ALERT,
              "Group list sizes for strips do not match!");
       return false;
     }
     for (unsigned grp = 0; grp < obj.get_strips_v().size(); ++grp) {
       std::string materialName = obj.get_strip_materials()[grp];
-      SGVec2f tcScale = getTexCoordScale(materialName, matlib);
+      SGVec2f tc0Scale = getTexCoordScale(materialName, matlib);
+      SGVec2f tc1Scale(1.0, 1.0);
       addStripGeometry(materialTriangleMap[materialName],
-                       obj.get_wgs84_nodes(), obj.get_normals(),
-                       obj.get_texcoords(), obj.get_strips_v()[grp],
-                       obj.get_strips_n()[grp], obj.get_strips_tc()[grp],
-                       tcScale);
+                          obj, grp, tc0Scale, tc1Scale);
     }
 
     if (obj.get_fans_n().size() < obj.get_fans_v().size() ||
-        obj.get_fans_tc().size() < obj.get_fans_v().size()) {
+        obj.get_fans_tcs().size() < obj.get_fans_v().size()) {
       SG_LOG(SG_TERRAIN, SG_ALERT,
              "Group list sizes for fans do not match!");
       return false;
     }
     for (unsigned grp = 0; grp < obj.get_fans_v().size(); ++grp) {
       std::string materialName = obj.get_fan_materials()[grp];
-      SGVec2f tcScale = getTexCoordScale(materialName, matlib);
+      SGVec2f tc0Scale = getTexCoordScale(materialName, matlib);
+      SGVec2f tc1Scale(1.0, 1.0);
       addFanGeometry(materialTriangleMap[materialName],
-                     obj.get_wgs84_nodes(), obj.get_normals(),
-                     obj.get_texcoords(), obj.get_fans_v()[grp],
-                     obj.get_fans_n()[grp], obj.get_fans_tc()[grp],
-                     tcScale);
+                       obj, grp, tc0Scale, tc1Scale );
     }
     return true;
   }
@@ -399,30 +445,37 @@ public:
     if (materialTriangleMap.empty())
       return 0;
 
-    EffectGeode* eg = 0;
-    osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : 0);
+    EffectGeode* eg = NULL;
+    osg::Group* group = (materialTriangleMap.size() > 1 ? new osg::Group : NULL);
+    if (group) {
+        group->setName("surfaceGeometryGroup");
+    }
+    
     //osg::Geode* geode = new osg::Geode;
     SGMaterialTriangleMap::const_iterator i;
     for (i = materialTriangleMap.begin(); i != materialTriangleMap.end(); ++i) {
       osg::Geometry* geometry = i->second.buildGeometry(useVBOs);
-      SGMaterial *mat = 0;
-      if (matlib)
+      SGMaterial *mat = NULL;
+      if (matlib) {
         mat = matlib->findCached(i->first);
+      }
       eg = new EffectGeode;
       eg->setName("EffectGeode");
-      if (mat)
+      if (mat) {
         eg->setEffect(mat->get_effect(i->second));
+      }
       eg->addDrawable(geometry);
       eg->runGenerators(geometry);  // Generate extra data needed by effect
       if (group) {
-        group->setName("surfaceGeometryGroup");
         group->addChild(eg);
       }
     }
-    if (group)
+    
+    if (group) {
         return group;
-    else
+    } else {
         return eg;
+    }
   }
 
   void computeRandomSurfaceLights(SGMaterialLib* matlib)
@@ -522,12 +575,12 @@ public:
       for (unsigned i = 0; i < num; ++i) {
         SGTexturedTriangleBin::triangle_ref triangleRef = triangleBin.getTriangleRef(i);
 
-        SGVec3f vorigin = triangleBin.getVertex(triangleRef[0]).vertex;
-        SGVec3f v0 = triangleBin.getVertex(triangleRef[1]).vertex - vorigin;
-        SGVec3f v1 = triangleBin.getVertex(triangleRef[2]).vertex - vorigin;
-        SGVec2f torigin = triangleBin.getVertex(triangleRef[0]).texCoord;
-        SGVec2f t0 = triangleBin.getVertex(triangleRef[1]).texCoord - torigin;
-        SGVec2f t1 = triangleBin.getVertex(triangleRef[2]).texCoord - torigin;
+        SGVec3f vorigin = triangleBin.getVertex(triangleRef[0]).GetVertex();
+        SGVec3f v0 = triangleBin.getVertex(triangleRef[1]).GetVertex() - vorigin;
+        SGVec3f v1 = triangleBin.getVertex(triangleRef[2]).GetVertex() - vorigin;
+        SGVec2f torigin = triangleBin.getVertex(triangleRef[0]).GetTexCoord(0);
+        SGVec2f t0 = triangleBin.getVertex(triangleRef[1]).GetTexCoord(0) - torigin;
+        SGVec2f t1 = triangleBin.getVertex(triangleRef[2]).GetTexCoord(0) - torigin;
         SGVec3f normal = cross(v0, v1);
 
         // Ensure the slope isn't too steep by checking the
@@ -941,6 +994,9 @@ public:
         maxError = propertyNode->getDoubleValue("/sim/rendering/terrain/simplifier/max-error", maxError);
       }
 
+      // PSADRO TODO : we can do this in terragear 
+      // - why not add a bitmask of flags to the btg so we can precompute this?
+      // and only do it if it hasn't been done already
       SGVec3d center = tile.get_gbs_center();
       SGGeod geodPos = SGGeod::fromCart(center);
       SGQuatd hlOr = SGQuatd::fromLonLat(geodPos)*SGQuatd::fromEulerDeg(0, 0, 180);