diff --git a/simgear/io/lowtest.cxx b/simgear/io/lowtest.cxx index 843c13f9..85620357 100644 --- a/simgear/io/lowtest.cxx +++ b/simgear/io/lowtest.cxx @@ -23,6 +23,8 @@ int main() { } cout << "endian" << endl; + cout << "sizeof(short) = " << sizeof(short) << endl; + short s = 1111; cout << "short s = " << s << endl; sgEndianSwap((unsigned short *)&s); diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 4e7d2b26..01141d45 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -58,11 +58,20 @@ enum { SG_TRIANGLE_FACES = 10, SG_TRIANGLE_STRIPS = 11, SG_TRIANGLE_FANS = 12 -} tgObjectTypes; +} sgObjectTypes; enum { - SG_MATERIAL = 0 -} tgPropertyTypes; + SG_IDX_VERTICES = 0x0001, + SG_IDX_NORMALS = 0x0010, + SG_IDX_COLORS = 0x0100, + SG_IDX_TEXCOORDS = 0x1000 +} sgIndexTypes; + +enum { + SG_MATERIAL = 0, + SG_INDEX_TYPES = 1 +} sgPropertyTypes; + class sgSimpleBuffer { @@ -148,11 +157,130 @@ double sgCalcBoundingRadius( Point3D center, point_list& wgs84_nodes ) { } + +// read object properties +static void read_object( gzFile fp, + int obj_type, + int nproperties, + int nelements, + group_list *vertices, + group_list *normals, + group_list *colors, + group_list *texcoords, + string_list *materials ) +{ + unsigned int nbytes; + char idx_mask; + int idx_size; + bool do_vertices, do_normals, do_colors, do_texcoords; + int j, k, idx; + static sgSimpleBuffer buf( 32768 ); // 32 Kb + char material[256]; + + // default values + if ( obj_type == SG_POINTS ) { + idx_size = 1; + idx_mask = SG_IDX_VERTICES; + do_vertices = true; + do_normals = false; + do_colors = false; + do_texcoords = false; + } else { + idx_size = 2; + idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS); + do_vertices = true; + do_normals = false; + do_colors = false; + do_texcoords = true; + } + + for ( j = 0; j < nproperties; ++j ) { + char prop_type; + sgReadChar( fp, &prop_type ); + + sgReadUInt( fp, &nbytes ); + // cout << "property size = " << nbytes << endl; + if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } + char *ptr = buf.get_ptr(); + sgReadBytes( fp, nbytes, ptr ); + if ( prop_type == SG_MATERIAL ) { + strncpy( material, ptr, nbytes ); + material[nbytes] = '\0'; + // cout << "material type = " << material << endl; + } else if ( prop_type == SG_INDEX_TYPES ) { + idx_mask = ptr[0]; + idx_size = 0; + do_vertices = false; + do_normals = false; + do_colors = false; + do_texcoords = false; + if ( idx_mask & SG_IDX_VERTICES ) { + do_vertices = true; + ++idx_size; + } + if ( idx_mask & SG_IDX_NORMALS ) { + do_normals = true; + ++idx_size; + } + if ( idx_mask & SG_IDX_COLORS ) { + do_colors = true; + ++idx_size; + } + if ( idx_mask & SG_IDX_TEXCOORDS ) { + do_texcoords = true; + ++idx_size; + } + } + } + + for ( j = 0; j < nelements; ++j ) { + sgReadUInt( fp, &nbytes ); + // cout << "element size = " << nbytes << endl; + if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } + char *ptr = buf.get_ptr(); + sgReadBytes( fp, nbytes, ptr ); + int count = nbytes / (idx_size * sizeof(short)); + short *sptr = (short *)ptr; + int_list vs; vs.clear(); + int_list ns; ns.clear(); + int_list cs; cs.clear(); + int_list tcs; tcs.clear(); + for ( k = 0; k < count; ++k ) { + if ( sgIsBigEndian() ) { + for ( idx = 0; idx < idx_size; ++idx ) { + sgEndianSwap( (unsigned short *)&(sptr[idx]) ); + } + } + idx = 0; + if ( do_vertices ) { + vs.push_back( sptr[idx++] ); + } + if ( do_normals ) { + ns.push_back( sptr[idx++] ); + } + if ( do_colors ) { + cs.push_back( sptr[idx++] ); + } + if ( do_texcoords ) { + tcs.push_back( sptr[idx++] ); + } + // cout << sptr[0] << " "; + sptr += idx_size; + } + // cout << endl; + vertices->push_back( vs ); + normals->push_back( ns ); + colors->push_back( cs ); + texcoords->push_back( tcs ); + materials->push_back( material ); + } +} + + // read a binary file and populate the provided structures. bool SGBinObject::read_bin( const string& file ) { Point3D p; int i, j, k; - char material[256]; unsigned int nbytes; static sgSimpleBuffer buf( 32768 ); // 32 Kb @@ -165,17 +293,26 @@ bool SGBinObject::read_bin( const string& file ) { texcoords.clear(); pts_v.clear(); + pts_n.clear(); + pts_c.clear(); + pts_tc.clear(); pt_materials.clear(); tris_v.clear(); + tris_n.clear(); + tris_c.clear(); tris_tc.clear(); tri_materials.clear(); strips_v.clear(); + strips_n.clear(); + strips_c.clear(); strips_tc.clear(); strip_materials.clear(); fans_v.clear(); + fans_n.clear(); + fans_c.clear(); fans_tc.clear(); fan_materials.clear(); @@ -417,92 +554,27 @@ bool SGBinObject::read_bin( const string& file ) { } } } else if ( obj_type == SG_POINTS ) { - // read points properties - for ( j = 0; j < nproperties; ++j ) { - char prop_type; - sgReadChar( fp, &prop_type ); - - sgReadUInt( fp, &nbytes ); - // cout << "property size = " << nbytes << endl; - if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } - char *ptr = buf.get_ptr(); - sgReadBytes( fp, nbytes, ptr ); - if ( prop_type == SG_MATERIAL ) { - strncpy( material, ptr, nbytes ); - material[nbytes] = '\0'; - // cout << "material type = " << material << endl; - } - } - // read point elements - for ( j = 0; j < nelements; ++j ) { - sgReadUInt( fp, &nbytes ); - // cout << "element size = " << nbytes << endl; - if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } - char *ptr = buf.get_ptr(); - sgReadBytes( fp, nbytes, ptr ); - int count = nbytes / sizeof(short); - short *sptr = (short *)ptr; - int_list vs; - vs.clear(); - for ( k = 0; k < count; ++k ) { - if ( sgIsBigEndian() ) { - sgEndianSwap( (unsigned short *)&(sptr[0]) ); - } - vs.push_back( sptr[0] ); - // cout << sptr[0] << " "; - ++sptr; - } - // cout << endl; - pts_v.push_back( vs ); - pt_materials.push_back( material ); - } + read_object( fp, SG_POINTS, nproperties, nelements, + &pts_v, &pts_n, &pts_c, &pts_tc, &pt_materials ); } else if ( obj_type == SG_TRIANGLE_FACES ) { // read triangle face properties - for ( j = 0; j < nproperties; ++j ) { - char prop_type; - sgReadChar( fp, &prop_type ); - - sgReadUInt( fp, &nbytes ); - // cout << "property size = " << nbytes << endl; - if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } - char *ptr = buf.get_ptr(); - sgReadBytes( fp, nbytes, ptr ); - if ( prop_type == SG_MATERIAL ) { - strncpy( material, ptr, nbytes ); - material[nbytes] = '\0'; - // cout << "material type = " << material << endl; - } - } - - // read triangle face elements - for ( j = 0; j < nelements; ++j ) { - sgReadUInt( fp, &nbytes ); - // cout << "element size = " << nbytes << endl; - if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } - char *ptr = buf.get_ptr(); - sgReadBytes( fp, nbytes, ptr ); - int count = nbytes / (sizeof(short) * 2); - short *sptr = (short *)ptr; - int_list vs, tcs; - vs.clear(); tcs.clear(); - for ( k = 0; k < count; ++k ) { - if ( sgIsBigEndian() ) { - sgEndianSwap( (unsigned short *)&(sptr[0]) ); - sgEndianSwap( (unsigned short *)&(sptr[1]) ); - } - vs.push_back( sptr[0] ); - tcs.push_back( sptr[1] ); - // cout << sptr[0] << "/" << sptr[1] << " "; - sptr += 2; - } - // cout << endl; - tris_v.push_back( vs ); - tris_tc.push_back( tcs ); - tri_materials.push_back( material ); - } + read_object( fp, SG_TRIANGLE_FACES, nproperties, nelements, + &tris_v, &tris_n, &tris_c, &tris_tc, &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 ); +#if 0 + // default values + idx_size = 2; + idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS); + do_vertices = true; + do_normals = false; + do_colors = false; + do_texcoords = true; + for ( j = 0; j < nproperties; ++j ) { char prop_type; sgReadChar( fp, &prop_type ); @@ -538,15 +610,27 @@ bool SGBinObject::read_bin( const string& file ) { vs.push_back( sptr[0] ); tcs.push_back( sptr[1] ); // cout << sptr[0] << "/" << sptr[1] << " "; - sptr += 2; + sptr += idx_size; } // cout << endl; strips_v.push_back( vs ); strips_tc.push_back( tcs ); strip_materials.push_back( material ); } +#endif } 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 ); +#if 0 + // default values + idx_size = 2; + idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS); + do_vertices = true; + do_normals = false; + do_colors = false; + do_texcoords = true; + for ( j = 0; j < nproperties; ++j ) { char prop_type; sgReadChar( fp, &prop_type ); @@ -582,13 +666,14 @@ bool SGBinObject::read_bin( const string& file ) { vs.push_back( sptr[0] ); tcs.push_back( sptr[1] ); // cout << sptr[0] << "/" << sptr[1] << " "; - sptr += 2; + sptr += idx_size; } // cout << endl; fans_v.push_back( vs ); fans_tc.push_back( tcs ); fan_materials.push_back( material ); } +#endif } else { // unknown object type, just skip @@ -638,6 +723,8 @@ bool SGBinObject::write_bin( const string& base, const string& name, sgVec3 pt; sgVec4 color; int i, j; + char idx_mask; + int idx_size; string dir = base + "/" + b.gen_base_path(); string command = "mkdir -p " + dir; @@ -826,19 +913,40 @@ bool SGBinObject::write_bin( const string& base, const string& name, // write group headers sgWriteChar( fp, (char)SG_POINTS ); // type - sgWriteShort( fp, 1 ); // nproperties + sgWriteShort( fp, 2 ); // nproperties sgWriteShort( fp, end - start ); // nelements sgWriteChar( fp, (char)SG_MATERIAL ); // property sgWriteUInt( fp, material.length() ); // nbytes sgWriteBytes( fp, material.length(), material.c_str() ); + idx_mask = 0; + idx_size = 0; + if ( pts_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; } + if ( pts_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; } + if ( pts_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; } + if ( pts_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; } + sgWriteChar( fp, (char)SG_INDEX_TYPES ); // property + sgWriteUInt( fp, 1 ); // nbytes + sgWriteChar( fp, idx_mask ); + // write strips for ( i = start; i < end; ++i ) { // nbytes - sgWriteUInt( fp, pts_v[i].size() * sizeof(short) ); + sgWriteUInt( fp, pts_v[i].size() * idx_size * sizeof(short) ); for ( j = 0; j < (int)pts_v[i].size(); ++j ) { - sgWriteShort( fp, (short)pts_v[i][j] ); + if ( pts_v.size() ) { + sgWriteShort( fp, (short)pts_v[i][j] ); + } + if ( pts_n.size() ) { + sgWriteShort( fp, (short)pts_n[i][j] ); + } + if ( pts_c.size() ) { + sgWriteShort( fp, (short)pts_c[i][j] ); + } + if ( pts_tc.size() ) { + sgWriteShort( fp, (short)pts_tc[i][j] ); + } } } @@ -865,20 +973,41 @@ bool SGBinObject::write_bin( const string& base, const string& name, // write group headers sgWriteChar( fp, (char)SG_TRIANGLE_FACES ); // type - sgWriteShort( fp, 1 ); // nproperties + sgWriteShort( fp, 2 ); // nproperties sgWriteShort( fp, 1 ); // nelements sgWriteChar( fp, (char)SG_MATERIAL ); // property sgWriteUInt( fp, material.length() ); // nbytes sgWriteBytes( fp, material.length(), material.c_str() ); - sgWriteUInt( fp, (end - start) * 3 * 2 * sizeof(short) ); // nbytes + idx_mask = 0; + idx_size = 0; + if ( tris_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; } + if ( tris_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; } + if ( tris_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; } + if ( tris_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; } + sgWriteChar( fp, (char)SG_INDEX_TYPES ); // property + sgWriteUInt( fp, 1 ); // nbytes + sgWriteChar( fp, idx_mask ); + + // nbytes + sgWriteUInt( fp, (end - start) * 3 * idx_size * sizeof(short) ); // write group for ( i = start; i < end; ++i ) { for ( j = 0; j < 3; ++j ) { - sgWriteShort( fp, (short)tris_v[i][j] ); - sgWriteShort( fp, (short)tris_tc[i][j] ); + if ( tris_v.size() ) { + sgWriteShort( fp, (short)tris_v[i][j] ); + } + if ( tris_n.size() ) { + sgWriteShort( fp, (short)tris_n[i][j] ); + } + if ( tris_c.size() ) { + sgWriteShort( fp, (short)tris_c[i][j] ); + } + if ( tris_tc.size() ) { + sgWriteShort( fp, (short)tris_tc[i][j] ); + } } } @@ -905,20 +1034,40 @@ bool SGBinObject::write_bin( const string& base, const string& name, // write group headers sgWriteChar( fp, (char)SG_TRIANGLE_STRIPS ); // type - sgWriteShort( fp, 1 ); // nproperties + sgWriteShort( fp, 2 ); // nproperties sgWriteShort( fp, end - start ); // nelements sgWriteChar( fp, (char)SG_MATERIAL ); // property sgWriteUInt( fp, material.length() ); // nbytes sgWriteBytes( fp, material.length(), material.c_str() ); + idx_mask = 0; + idx_size = 0; + if ( strips_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; } + if ( strips_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; } + if ( strips_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; } + if ( strips_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size;} + sgWriteChar( fp, (char)SG_INDEX_TYPES ); // property + sgWriteUInt( fp, 1 ); // nbytes + sgWriteChar( fp, idx_mask ); + // write strips for ( i = start; i < end; ++i ) { // nbytes - sgWriteUInt( fp, strips_v[i].size() * 2 * sizeof(short) ); + sgWriteUInt( fp, strips_v[i].size() * idx_size * sizeof(short)); for ( j = 0; j < (int)strips_v[i].size(); ++j ) { - sgWriteShort( fp, (short)strips_v[i][j] ); - sgWriteShort( fp, (short)strips_tc[i][j] ); + if ( strips_v.size() ) { + sgWriteShort( fp, (short)strips_v[i][j] ); + } + if ( strips_n.size() ) { + sgWriteShort( fp, (short)strips_n[i][j] ); + } + if ( strips_c.size() ) { + sgWriteShort( fp, (short)strips_c[i][j] ); + } + if ( strips_tc.size() ) { + sgWriteShort( fp, (short)strips_tc[i][j] ); + } } } @@ -945,20 +1094,40 @@ bool SGBinObject::write_bin( const string& base, const string& name, // write group headers sgWriteChar( fp, (char)SG_TRIANGLE_FANS ); // type - sgWriteShort( fp, 1 ); // nproperties + sgWriteShort( fp, 2 ); // nproperties sgWriteShort( fp, end - start ); // nelements sgWriteChar( fp, (char)SG_MATERIAL ); // property sgWriteUInt( fp, material.length() ); // nbytes sgWriteBytes( fp, material.length(), material.c_str() ); + idx_mask = 0; + idx_size = 0; + if ( fans_v.size() ) { idx_mask |= SG_IDX_VERTICES; ++idx_size; } + if ( fans_n.size() ) { idx_mask |= SG_IDX_NORMALS; ++idx_size; } + if ( fans_c.size() ) { idx_mask |= SG_IDX_COLORS; ++idx_size; } + if ( fans_tc.size() ) { idx_mask |= SG_IDX_TEXCOORDS; ++idx_size; } + sgWriteChar( fp, (char)SG_INDEX_TYPES ); // property + sgWriteUInt( fp, 1 ); // nbytes + sgWriteChar( fp, idx_mask ); + // write fans for ( i = start; i < end; ++i ) { // nbytes - sgWriteUInt( fp, fans_v[i].size() * 2 * sizeof(short) ); + sgWriteUInt( fp, fans_v[i].size() * idx_size * sizeof(short) ); for ( j = 0; j < (int)fans_v[i].size(); ++j ) { - sgWriteShort( fp, (short)fans_v[i][j] ); - sgWriteShort( fp, (short)fans_tc[i][j] ); + if ( fans_v.size() ) { + sgWriteShort( fp, (short)fans_v[i][j] ); + } + if ( fans_n.size() ) { + sgWriteShort( fp, (short)fans_n[i][j] ); + } + if ( fans_c.size() ) { + sgWriteShort( fp, (short)fans_c[i][j] ); + } + if ( fans_tc.size() ) { + sgWriteShort( fp, (short)fans_tc[i][j] ); + } } } diff --git a/simgear/io/sg_binobj.hxx b/simgear/io/sg_binobj.hxx index b8f181ad..edd80f9c 100644 --- a/simgear/io/sg_binobj.hxx +++ b/simgear/io/sg_binobj.hxx @@ -91,21 +91,35 @@ class SGBinObject { Point3D gbs_center; float gbs_radius; - point_list wgs84_nodes; - point_list colors; - point_list normals; - point_list texcoords; - group_list pts_v; - string_list pt_materials; - group_list tris_v; - group_list tris_tc; - string_list tri_materials; - group_list strips_v; - group_list strips_tc; - string_list strip_materials; - group_list fans_v; - group_list fans_tc; - string_list fan_materials; + + point_list wgs84_nodes; // vertex list + point_list colors; // color list + point_list normals; // normal list + point_list 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 public: @@ -131,11 +145,21 @@ public: inline group_list get_pts_v() const { return pts_v; } inline void set_pts_v( group_list g ) { pts_v = g; } + inline group_list get_pts_n() const { return pts_n; } + inline void set_pts_n( group_list g ) { pts_n = g; } + inline group_list get_pts_c() const { return pts_c; } + inline void set_pts_c( group_list g ) { pts_c = g; } + inline group_list get_pts_tc() const { return pts_tc; } + inline void set_pts_tc( group_list g ) { pts_tc = g; } inline string_list get_pt_materials() const { return pt_materials; } inline void set_pt_materials( string_list s ) { pt_materials = s; } inline group_list get_tris_v() const { return tris_v; } inline void set_tris_v( group_list g ) { tris_v = g; } + inline group_list get_tris_n() const { return tris_n; } + inline void set_tris_n( group_list g ) { tris_n = g; } + inline group_list get_tris_c() const { return tris_c; } + inline void set_tris_c( group_list g ) { tris_c = g; } inline group_list get_tris_tc() const { return tris_tc; } inline void set_tris_tc( group_list g ) { tris_tc = g; } inline string_list get_tri_materials() const { return tri_materials; } @@ -143,6 +167,10 @@ public: inline group_list get_strips_v() const { return strips_v; } inline void set_strips_v( group_list g ) { strips_v = g; } + inline group_list get_strips_n() const { return strips_n; } + inline void set_strips_n( group_list g ) { strips_n = g; } + inline group_list get_strips_c() const { return strips_c; } + inline void set_strips_c( group_list g ) { strips_c = g; } inline group_list get_strips_tc() const { return strips_tc; } inline void set_strips_tc( group_list g ) { strips_tc = g; } inline string_list get_strip_materials() const { return strip_materials; } @@ -150,6 +178,10 @@ public: inline group_list get_fans_v() const { return fans_v; } inline void set_fans_v( group_list g ) { fans_v = g; } + inline group_list get_fans_n() const { return fans_n; } + inline void set_fans_n( group_list g ) { fans_n = g; } + inline group_list get_fans_c() const { return fans_c; } + inline void set_fans_c( group_list g ) { fans_c = g; } inline group_list get_fans_tc() const { return fans_tc; } inline void set_fans_tc( group_list g ) { fans_tc = g; } inline string_list get_fan_materials() const { return fan_materials; }