Additions to the binary file format to make it *much* more flexible.

For each major primative type: points, triangles, fans, and strips, you
can specify an index list of vertices, normals, colors, and texture
coordinates.  You can skip any of these you like to save on space.

Note that the work for this has only been done in the file format reader
and writer.  The FlightGear loader for instance still needs to have
support for this built in.

This is is one more small step towards runway lighting.
This commit is contained in:
curt
2002-03-10 22:49:01 +00:00
parent a2d95ac742
commit a3186af099
3 changed files with 320 additions and 117 deletions

View File

@@ -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);

View File

@@ -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] );
}
}
}

View File

@@ -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; }