From b159a72ce97db3c1903dd346307eecd5f18e5ffe Mon Sep 17 00:00:00 2001 From: Martin Spott Date: Mon, 5 Sep 2011 18:45:33 +0200 Subject: [PATCH 1/4] Fix CMake HLA fix --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49916a08..8a2a6f94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -89,7 +89,7 @@ check_include_file(windows.h HAVE_WINDOWS_H) if(ENABLE_RTI) # See if we have any rti library variant installed -find_package(RTI) + find_package(RTI) endif(ENABLE_RTI) check_function_exists(gettimeofday HAVE_GETTIMEOFDAY) From d9a281c493cac5bef5db95672aef5983beefa4d7 Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 4 Oct 2011 14:04:59 +0100 Subject: [PATCH 2/4] Support for 32-bit vertex indices in BTG files --- simgear/io/sg_binobj.cxx | 1419 +++++++++++++++++--------------------- simgear/io/sg_binobj.hxx | 39 +- 2 files changed, 662 insertions(+), 796 deletions(-) diff --git a/simgear/io/sg_binobj.cxx b/simgear/io/sg_binobj.cxx index 5f7a34d2..7a58321f 100644 --- a/simgear/io/sg_binobj.cxx +++ b/simgear/io/sg_binobj.cxx @@ -33,10 +33,12 @@ #include #include #include // for system() +#include #include #include #include +#include #include #include @@ -85,163 +87,282 @@ private: char *ptr; unsigned int size; - + size_t offset; public: - inline sgSimpleBuffer( unsigned int s ) + sgSimpleBuffer( unsigned int s = 0) : + ptr(NULL), + size(0), + offset(0) { - size = 1; - while ( size < s ) { - size *= 2; - } - SG_LOG(SG_EVENT, SG_DEBUG, "Creating a new buffer of size = " << size); - ptr = new char[size]; + resize(s); } - inline ~sgSimpleBuffer() { - delete [] ptr; + ~sgSimpleBuffer() + { + delete [] ptr; } - inline unsigned int get_size() const { return size; } - inline char *get_ptr() const { return ptr; } - inline void resize( unsigned int s ) { - if ( s > size ) { - if ( ptr != NULL ) { - delete [] ptr; - } - while ( size < s ) { - size *= 2; - } - SG_LOG(SG_EVENT, SG_DEBUG, "resizing buffer to size = " << size); - ptr = new char[size]; - } + unsigned int get_size() const { return size; } + char *get_ptr() const { return ptr; } + + void reset() + { + offset = 0; + } + + void resize( unsigned int s ) + { + if ( s > size ) { + if ( ptr != NULL ) { + delete [] ptr; + } + + if ( size == 0) { + size = 16; + } + + while ( size < s ) { + size = size << 1; + } + ptr = new char[size]; + } + } + + SGVec3d readVec3d() + { + double* p = reinterpret_cast(ptr + offset); + + if ( sgIsBigEndian() ) { + sgEndianSwap((uint64_t *) p + 0); + sgEndianSwap((uint64_t *) p + 1); + sgEndianSwap((uint64_t *) p + 2); + } + + offset += 3 * sizeof(double); + return SGVec3d(p); + } + + float readFloat() + { + float* p = reinterpret_cast(ptr + offset); + if ( sgIsBigEndian() ) { + sgEndianSwap((uint32_t *) p); + } + + offset += sizeof(float); + return *p; + } + + SGVec2f readVec2f() + { + float* p = reinterpret_cast(ptr + offset); + + if ( sgIsBigEndian() ) { + sgEndianSwap((uint32_t *) p + 0); + sgEndianSwap((uint32_t *) p + 1); + } + + offset += 2 * sizeof(float); + return SGVec2f(p); + } + + SGVec3f readVec3f() + { + float* p = reinterpret_cast(ptr + offset); + + if ( sgIsBigEndian() ) { + sgEndianSwap((uint32_t *) p + 0); + sgEndianSwap((uint32_t *) p + 1); + sgEndianSwap((uint32_t *) p + 2); + } + + offset += 3 * sizeof(float); + return SGVec3f(p); + } + + SGVec4f readVec4f() + { + float* p = reinterpret_cast(ptr + offset); + + if ( sgIsBigEndian() ) { + sgEndianSwap((uint32_t *) p + 0); + sgEndianSwap((uint32_t *) p + 1); + sgEndianSwap((uint32_t *) p + 2); + sgEndianSwap((uint32_t *) p + 3); + } + + offset += 4 * sizeof(float); + return SGVec4f(p); } }; +template +static void read_indices(char* buffer, + size_t bytes, + int indexMask, + int_list& vertices, + int_list& normals, + int_list& colors, + int_list& texCoords) +{ + const int indexSize = sizeof(T) * std::bitset<32>(indexMask).count(); + const int count = bytes / indexSize; + +// fix endian-ness of the whole lot, if required + if (sgIsBigEndian()) { + int indices = bytes / sizeof(T); + T* src = reinterpret_cast(buffer); + for (int i=0; i(buffer); + for (int i=0; i +void write_indice(gzFile fp, T value) +{ + sgWriteBytes(fp, sizeof(T), &value); +} + +// specialize template to call endian-aware conversion methods +template <> +void write_indice(gzFile fp, uint16_t value) +{ + sgWriteUShort(fp, value); +} + +template <> +void write_indice(gzFile fp, uint32_t value) +{ + sgWriteUInt(fp, value); +} + + +template +void write_indices(gzFile fp, unsigned char indexMask, + const int_list& vertices, + const int_list& normals, + const int_list& colors, + const int_list& texCoords) +{ + unsigned int count = vertices.size(); + const int indexSize = sizeof(T) * std::bitset<32>(indexMask).count(); + sgWriteUInt(fp, indexSize * count); + + for (unsigned int i=0; i < count; ++i) { + write_indice(fp, static_cast(vertices[i])); + + if (!normals.empty()) { + write_indice(fp, static_cast(normals[i])); + } + if (!colors.empty()) { + write_indice(fp, static_cast(colors[i])); + } + if (!texCoords.empty()) { + write_indice(fp, static_cast(texCoords[i])); + } + } +} + + // 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 ) +void SGBinObject::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; unsigned char idx_mask; - int idx_size; - bool do_vertices, do_normals, do_colors, do_texcoords; - int j, k, idx; + int j; 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; + idx_mask = SG_IDX_VERTICES; } 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; + idx_mask = (char)(SG_IDX_VERTICES | SG_IDX_TEXCOORDS); } 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]; - // cout << "idx_mask = " << (int)idx_mask << endl; - 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; - } - } + 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; + } } + if ( sgReadError() ) { + cout << "We detected an error reading object properties" << endl; + return; + } + 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(unsigned short)); - unsigned short *sptr = (unsigned 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( (uint16_t *)&(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 ); - } + sgReadUInt( fp, &nbytes ); + if ( sgReadError() ) { + cout << "We detected an error reading element size for :" << j << endl; + return; + } + + buf.resize( nbytes ); + char *ptr = buf.get_ptr(); + sgReadBytes( fp, nbytes, ptr ); + + if ( sgReadError() ) { + cout << "We detected an error reading object element:" << j << "bytes="<< nbytes << endl; + return; + } + + int_list vs; + int_list ns; + int_list cs; + int_list tcs; + if (version >= 10) { + read_indices(ptr, nbytes, idx_mask, vs, ns, cs, tcs); + } else { + read_indices(ptr, nbytes, idx_mask, vs, ns, cs, tcs); + } + + vertices.push_back( vs ); + normals.push_back( ns ); + colors.push_back( cs ); + texCoords.push_back( tcs ); + materials.push_back( material ); + } // of element iteration } // read a binary file and populate the provided structures. bool SGBinObject::read_bin( const string& file ) { SGVec3d p; - int i, j, k; + int i, k; + size_t j; unsigned int nbytes; sgSimpleBuffer buf( 32768 ); // 32 Kb @@ -279,13 +400,13 @@ bool SGBinObject::read_bin( const string& file ) { gzFile fp; if ( (fp = gzopen( file.c_str(), "rb" )) == NULL ) { - string filegz = file + ".gz"; - if ( (fp = gzopen( filegz.c_str(), "rb" )) == NULL ) { + string filegz = file + ".gz"; + if ( (fp = gzopen( filegz.c_str(), "rb" )) == NULL ) { SG_LOG( SG_EVENT, SG_ALERT, "ERROR: opening " << file << " or " << filegz << " for reading!"); - return false; - } + return false; + } } sgClearReadError(); @@ -294,16 +415,16 @@ bool SGBinObject::read_bin( const string& file ) { unsigned int header; 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; + ((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); + // close the file before we return + gzclose(fp); - return false; + return false; } // read creation time @@ -324,673 +445,383 @@ bool SGBinObject::read_bin( const string& file ) { #endif // read number of top level objects - unsigned short nobjects; - if ( version >= 7 ) { - sgReadUShort( fp, &nobjects ); + int nobjects; + if ( version >= 10) { // version 10 extends everything to be 32-bit + sgReadInt( fp, &nobjects ); + } else if ( version >= 7 ) { + uint16_t v; + sgReadUShort( fp, &v ); + nobjects = v; } else { - short tmp; - sgReadShort( fp, &tmp ); - nobjects = tmp; + int16_t v; + sgReadShort( fp, &v ); + nobjects = v; } - // cout << "Total objects to read = " << nobjects << endl; + + //cout << "Total objects to read = " << nobjects << endl; + if ( sgReadError() ) { + cout << "We detected an error while reading the file header" << endl; + return false; + } + // read in objects for ( i = 0; i < nobjects; ++i ) { - // read object header - char obj_type; - unsigned short nproperties, nelements; - sgReadChar( fp, &obj_type ); - if ( version >= 7 ) { - sgReadUShort( fp, &nproperties ); - sgReadUShort( fp, &nelements ); + // read object header + char obj_type; + uint32_t nproperties, nelements; + sgReadChar( fp, &obj_type ); + if ( version >= 10 ) { + sgReadUInt( fp, &nproperties ); + sgReadUInt( fp, &nelements ); + } else if ( version >= 7 ) { + uint16_t v; + sgReadUShort( fp, &v ); + nproperties = v; + sgReadUShort( fp, &v ); + nelements = v; } else { - short tmp; - sgReadShort( fp, &tmp ); - nproperties = tmp; - sgReadShort( fp, &tmp ); - nelements = tmp; + int16_t v; + sgReadShort( fp, &v ); + nproperties = v; + sgReadShort( fp, &v ); + nelements = v; } - // cout << "object " << i << " = " << (int)obj_type << " props = " - // << nproperties << " elements = " << nelements << endl; - - if ( obj_type == SG_BOUNDING_SPHERE ) { - // read bounding sphere properties - for ( j = 0; j < nproperties; ++j ) { - char prop_type; - sgReadChar( fp, &prop_type ); + //cout << "object " << i << " = " << (int)obj_type << " props = " + // << nproperties << " elements = " << nelements << endl; + + if ( obj_type == SG_BOUNDING_SPHERE ) { + // read bounding sphere properties + read_properties( fp, nproperties ); + + // read bounding sphere elements + for ( j = 0; j < nelements; ++j ) { + sgReadUInt( fp, &nbytes ); + buf.resize( nbytes ); + buf.reset(); + char *ptr = buf.get_ptr(); + sgReadBytes( fp, nbytes, ptr ); + gbs_center = buf.readVec3d(); + gbs_radius = buf.readFloat(); + } + } else if ( obj_type == SG_VERTEX_LIST ) { + // read vertex list properties + read_properties( fp, nproperties ); - 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 ); - } + // read vertex 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) * 3); + wgs84_nodes.reserve( count ); + for ( k = 0; k < count; ++k ) { + SGVec3f v = buf.readVec3f(); + // extend from float to double, hmmm + wgs84_nodes.push_back( SGVec3d(v[0], v[1], v[2]) ); + } + } + } else if ( obj_type == SG_COLOR_LIST ) { + // read color list properties + read_properties( fp, nproperties ); - // read bounding sphere 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 ); + // read color 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) * 4); + colors.reserve(count); + for ( k = 0; k < count; ++k ) { + colors.push_back( buf.readVec4f() ); + } + } + } else if ( obj_type == SG_NORMAL_LIST ) { + // read normal list properties + read_properties( fp, nproperties ); - double *dptr = (double *)ptr; - if ( sgIsBigEndian() ) { - sgEndianSwap( (uint64_t *)&(dptr[0]) ); - sgEndianSwap( (uint64_t *)&(dptr[1]) ); - sgEndianSwap( (uint64_t *)&(dptr[2]) ); - } - gbs_center = SGVec3d( dptr[0], dptr[1], dptr[2] ); - // cout << "Center = " << gbs_center << endl; - ptr += sizeof(double) * 3; - - float *fptr = (float *)ptr; - if ( sgIsBigEndian() ) { - sgEndianSwap( (uint32_t *)fptr ); - } - gbs_radius = fptr[0]; - // cout << "Bounding radius = " << gbs_radius << endl; - } - } else if ( obj_type == SG_VERTEX_LIST ) { - // read vertex list properties - for ( j = 0; j < nproperties; ++j ) { - char prop_type; - sgReadChar( fp, &prop_type ); + // read normal list elements + for ( j = 0; j < nelements; ++j ) { + sgReadUInt( fp, &nbytes ); + buf.resize( nbytes ); + buf.reset(); + unsigned char *ptr = (unsigned char *)(buf.get_ptr()); + sgReadBytes( fp, nbytes, ptr ); + int count = nbytes / 3; + normals.reserve( count ); + + for ( k = 0; k < count; ++k ) { + SGVec3f normal( (ptr[0]) / 127.5 - 1.0, + (ptr[1]) / 127.5 - 1.0, + (ptr[2]) / 127.5 - 1.0); + normals.push_back(normalize(normal)); + ptr += 3; + } + } + } else if ( obj_type == SG_TEXCOORD_LIST ) { + // read texcoord list properties + read_properties( fp, nproperties ); - 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 ); - } + // read texcoord 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) * 2); + texcoords.reserve(count); + for ( k = 0; k < count; ++k ) { + texcoords.push_back( buf.readVec2f() ); + } + } + } 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 ); + } 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 ); + } 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 ); + } 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 ); + } else { + // unknown object type, just skip + read_properties( fp, nproperties ); - // read vertex list 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(float) * 3); - float *fptr = (float *)ptr; - wgs84_nodes.reserve( count ); - for ( k = 0; k < count; ++k ) { - if ( sgIsBigEndian() ) { - sgEndianSwap( (uint32_t *)&(fptr[0]) ); - sgEndianSwap( (uint32_t *)&(fptr[1]) ); - sgEndianSwap( (uint32_t *)&(fptr[2]) ); - } - wgs84_nodes.push_back( SGVec3d(fptr[0], fptr[1], fptr[2]) ); - fptr += 3; - } - } - } else if ( obj_type == SG_COLOR_LIST ) { - // read color list 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 ); - } - - // read color list 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(float) * 4); - float *fptr = (float *)ptr; - colors.reserve(count); - for ( k = 0; k < count; ++k ) { - if ( sgIsBigEndian() ) { - sgEndianSwap( (uint32_t *)&(fptr[0]) ); - sgEndianSwap( (uint32_t *)&(fptr[1]) ); - sgEndianSwap( (uint32_t *)&(fptr[2]) ); - sgEndianSwap( (uint32_t *)&(fptr[3]) ); - } - SGVec4f color( fptr[0], fptr[1], fptr[2], fptr[3] ); - colors.push_back( color ); - fptr += 4; - } - } - } else if ( obj_type == SG_NORMAL_LIST ) { - // read normal list 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 ); - } - - // read normal list elements - for ( j = 0; j < nelements; ++j ) { - sgReadUInt( fp, &nbytes ); - // cout << "element size = " << nbytes << endl; - if ( nbytes > buf.get_size() ) { buf.resize( nbytes ); } - unsigned char *ptr = (unsigned char *)(buf.get_ptr()); - sgReadBytes( fp, nbytes, ptr ); - int count = nbytes / 3; - normals.reserve( count ); - for ( k = 0; k < count; ++k ) { - SGVec3f normal((ptr[0]) / 127.5 - 1.0, - (ptr[1]) / 127.5 - 1.0, - (ptr[2]) / 127.5 - 1.0); - - normals.push_back(normalize(normal)); - ptr += 3; - } - } - } else if ( obj_type == SG_TEXCOORD_LIST ) { - // read texcoord list 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 ); - } - - // read texcoord list 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(float) * 2); - float *fptr = (float *)ptr; - texcoords.reserve(count); - for ( k = 0; k < count; ++k ) { - if ( sgIsBigEndian() ) { - sgEndianSwap( (uint32_t *)&(fptr[0]) ); - sgEndianSwap( (uint32_t *)&(fptr[1]) ); - } - texcoords.push_back( SGVec2f( fptr[0], fptr[1] ) ); - fptr += 2; - } - } - } 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 ); - } 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 ); - } 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 ); - } 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 ); - } else { - // unknown object type, just skip - - // read 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 ); - } - - // read 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 ); - } - } + // read 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 ); + } + } + + if ( sgReadError() ) { + cout << "We detected an error while reading object:" << i << endl; + return false; + } } // close the file gzclose(fp); if ( sgReadError() ) { - cout << "We detected an error while reading the file." << endl; - return false; + cout << "We detected an error while reading the file." << endl; + return false; } return true; } +void SGBinObject::write_header(gzFile fp, int type, int nProps, int nElements) +{ + sgWriteChar(fp, (unsigned char) type); + if (version == 7) { + sgWriteUShort(fp, nProps); + sgWriteUShort(fp, nElements); + } else { + sgWriteUInt(fp, nProps); + sgWriteUInt(fp, nElements); + } +} + +unsigned int SGBinObject::count_objects(const string_list& materials) +{ + unsigned int result = 0; + unsigned int start = 0, end = 1; + unsigned int count = materials.size(); + string m; + + while ( start < count ) { + m = materials[start]; + for (end = start+1; (end < count) && (m == materials[end]); ++end) { } + ++result; + start = end; + } + + 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) +{ + if (verts.empty()) { + return; + } + + unsigned int start = 0, end = 1; + string m; + while (start < materials.size()) { + m = materials[start]; + // find range of objects with identical material, write out as a single object + for (end = start+1; (end < materials.size()) && (m == materials[end]); ++end) {} + + const int count = end - start; + write_header(fp, type, 2, count); + + // properties + sgWriteChar( fp, (char)SG_MATERIAL ); // property + sgWriteUInt( fp, m.length() ); // nbytes + sgWriteBytes( fp, m.length(), m.c_str() ); + + 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; + sgWriteChar( fp, (char)SG_INDEX_TYPES ); // property + sgWriteUInt( fp, 1 ); // nbytes + sgWriteChar( fp, idx_mask ); + +// cout << "material:" << m << ", count =" << count << endl; + // elements + for (unsigned int i=start; i < end; ++i) { + if (version == 7) { + write_indices(fp, idx_mask, verts[i], normals[i], colors[i], texCoords[i]); + } else { + write_indices(fp, idx_mask, verts[i], normals[i], colors[i], texCoords[i]); + } + } + + start = end; + } // of materials iteration +} // write out the structures to a binary file. We assume that the // groups come to us sorted by material property. If not, things // don't break, but the result won't be as optimal. bool SGBinObject::write_bin( const string& base, const string& name, - const SGBucket& b ) + const SGBucket& b ) { - int i, j; - unsigned char idx_mask; - int idx_size; SGPath file = base + "/" + b.gen_base_path() + "/" + name + ".gz"; - file.create_dir( 0755 ); + return write_bin_file(file); +} + +bool SGBinObject::write_bin_file(const SGPath& file) +{ + int i; + + SGPath file2(file); + file2.create_dir( 0755 ); cout << "Output file = " << file.str() << endl; gzFile fp; if ( (fp = gzopen( file.c_str(), "wb9" )) == NULL ) { - cout << "ERROR: opening " << file.str() << " for writing!" << endl; - return false; + cout << "ERROR: opening " << file.str() << " for writing!" << endl; + return false; } sgClearWriteError(); cout << "points size = " << pts_v.size() << " pt_materials = " - << pt_materials.size() << endl; + << pt_materials.size() << endl; cout << "triangles size = " << tris_v.size() << " tri_materials = " - << tri_materials.size() << endl; + << tri_materials.size() << endl; cout << "strips size = " << strips_v.size() << " strip_materials = " - << strip_materials.size() << endl; + << strip_materials.size() << endl; cout << "fans size = " << fans_v.size() << " fan_materials = " - << fan_materials.size() << endl; + << fan_materials.size() << endl; cout << "nodes = " << wgs84_nodes.size() << endl; cout << "colors = " << colors.size() << endl; cout << "normals = " << normals.size() << endl; cout << "tex coords = " << texcoords.size() << endl; + version = 10; + if (wgs84_nodes.size() < 0xffff) { + version = 7; // use smaller indices if possible + } + // write header magic + + /** Magic Number for our file format */ + #define SG_FILE_MAGIC_NUMBER ( ('S'<<24) + ('G'<<16) + version ) + sgWriteUInt( fp, SG_FILE_MAGIC_NUMBER ); time_t calendar_time = time(NULL); sgWriteLong( fp, (int32_t)calendar_time ); // calculate and write number of top level objects - string material; - int start; - int end; - unsigned short nobjects = 0; - nobjects++; // for gbs - nobjects++; // for vertices - nobjects++; // for colors - nobjects++; // for normals - nobjects++; // for texcoords - - // points - unsigned short npts = 0; - start = 0; end = 1; - while ( start < (int)pt_materials.size() ) { - material = pt_materials[start]; - while ( (end < (int)pt_materials.size()) && - (material == pt_materials[end]) ) { - end++; - } - npts++; - start = end; end = start + 1; - } - nobjects += npts; - - // tris - unsigned short ntris = 0; - start = 0; end = 1; - while ( start < (int)tri_materials.size() ) { - material = tri_materials[start]; - while ( (end < (int)tri_materials.size()) && - (material == tri_materials[end]) ) { - end++; - } - ntris++; - start = end; end = start + 1; - } - nobjects += ntris; - - // strips - unsigned short nstrips = 0; - start = 0; end = 1; - while ( start < (int)strip_materials.size() ) { - material = strip_materials[start]; - while ( (end < (int)strip_materials.size()) && - (material == strip_materials[end]) ) { - end++; - } - nstrips++; - start = end; end = start + 1; - } - nobjects += nstrips; - - // fans - unsigned short nfans = 0; - start = 0; end = 1; - while ( start < (int)fan_materials.size() ) { - material = fan_materials[start]; - while ( (end < (int)fan_materials.size()) && - (material == fan_materials[end]) ) { - end++; - } - nfans++; - start = end; end = start + 1; - } - nobjects += nfans; + int nobjects = 5; // gbs, vertices, colors, normals, texcoords + nobjects += count_objects(pt_materials); + nobjects += count_objects(tri_materials); + nobjects += count_objects(strip_materials); + nobjects += count_objects(fan_materials); cout << "total top level objects = " << nobjects << endl; - sgWriteUShort( fp, nobjects ); - + if (version == 7) { + sgWriteUShort( fp, (uint16_t) nobjects ); + } else { + sgWriteInt( fp, nobjects ); + } + // write bounding sphere - sgWriteChar( fp, (char)SG_BOUNDING_SPHERE ); // type - sgWriteUShort( fp, 0 ); // nproperties - sgWriteUShort( fp, 1 ); // nelements - + write_header( fp, SG_BOUNDING_SPHERE, 0, 1); sgWriteUInt( fp, sizeof(double) * 3 + sizeof(float) ); // nbytes sgWritedVec3( fp, gbs_center ); sgWriteFloat( fp, gbs_radius ); // dump vertex list - sgWriteChar( fp, (char)SG_VERTEX_LIST ); // type - sgWriteUShort( fp, 0 ); // nproperties - sgWriteUShort( fp, 1 ); // nelements + write_header( fp, SG_VERTEX_LIST, 0, 1); sgWriteUInt( fp, wgs84_nodes.size() * sizeof(float) * 3 ); // nbytes for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) { sgWriteVec3( fp, toVec3f(wgs84_nodes[i] - gbs_center)); } // dump vertex color list - sgWriteChar( fp, (char)SG_COLOR_LIST ); // type - sgWriteUShort( fp, 0 ); // nproperties - sgWriteUShort( fp, 1 ); // nelements + write_header( fp, SG_COLOR_LIST, 0, 1); sgWriteUInt( fp, colors.size() * sizeof(float) * 4 ); // nbytes for ( i = 0; i < (int)colors.size(); ++i ) { sgWriteVec4( fp, colors[i]); } // dump vertex normal list - sgWriteChar( fp, (char)SG_NORMAL_LIST ); // type - sgWriteUShort( fp, 0 ); // nproperties - sgWriteUShort( fp, 1 ); // nelements + write_header( fp, SG_NORMAL_LIST, 0, 1); sgWriteUInt( fp, normals.size() * 3 ); // nbytes char normal[3]; for ( i = 0; i < (int)normals.size(); ++i ) { SGVec3f p = normals[i]; - normal[0] = (unsigned char)((p.x() + 1.0) * 127.5); - normal[1] = (unsigned char)((p.y() + 1.0) * 127.5); - normal[2] = (unsigned char)((p.z() + 1.0) * 127.5); - sgWriteBytes( fp, 3, normal ); + normal[0] = (unsigned char)((p.x() + 1.0) * 127.5); + normal[1] = (unsigned char)((p.y() + 1.0) * 127.5); + normal[2] = (unsigned char)((p.z() + 1.0) * 127.5); + sgWriteBytes( fp, 3, normal ); } // dump texture coordinates - sgWriteChar( fp, (char)SG_TEXCOORD_LIST ); // type - sgWriteUShort( fp, 0 ); // nproperties - sgWriteUShort( fp, 1 ); // nelements + write_header( fp, SG_TEXCOORD_LIST, 0, 1); sgWriteUInt( fp, texcoords.size() * sizeof(float) * 2 ); // nbytes for ( i = 0; i < (int)texcoords.size(); ++i ) { sgWriteVec2( fp, texcoords[i]); } - // dump point groups if they exist - if ( pts_v.size() > 0 ) { - int start = 0; - int end = 1; - string material; - while ( start < (int)pt_materials.size() ) { - // find next group - material = pt_materials[start]; - while ( (end < (int)pt_materials.size()) && - (material == pt_materials[end]) ) - { - // cout << "end = " << end << endl; - end++; - } - // cout << "group = " << start << " to " << end - 1 << endl; - - // write group headers - sgWriteChar( fp, (char)SG_POINTS ); // type - sgWriteUShort( fp, 2 ); // nproperties - sgWriteUShort( 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() * idx_size - * sizeof(unsigned short) ); - for ( j = 0; j < (int)pts_v[i].size(); ++j ) { - if ( pts_v.size() ) { - sgWriteUShort( fp, (unsigned short)pts_v[i][j] ); - } - if ( pts_n.size() ) { - sgWriteUShort( fp, (unsigned short)pts_n[i][j] ); - } - if ( pts_c.size() ) { - sgWriteUShort( fp, (unsigned short)pts_c[i][j] ); - } - if ( pts_tc.size() ) { - sgWriteUShort( fp, (unsigned short)pts_tc[i][j] ); - } - } - } - - start = end; - end = start + 1; - } - } - - // dump individual triangles if they exist - if ( tris_v.size() > 0 ) { - int start = 0; - int end = 1; - string material; - while ( start < (int)tri_materials.size() ) { - // find next group - material = tri_materials[start]; - while ( (end < (int)tri_materials.size()) && - (material == tri_materials[end]) && - 3*(end-start) < 32760 ) - { - // cout << "end = " << end << endl; - end++; - } - // cout << "group = " << start << " to " << end - 1 << endl; - - // write group headers - sgWriteChar( fp, (char)SG_TRIANGLE_FACES ); // type - sgWriteUShort( fp, 2 ); // nproperties - sgWriteUShort( fp, 1 ); // 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 ( 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(unsigned short) ); - - // write group - for ( i = start; i < end; ++i ) { - for ( j = 0; j < 3; ++j ) { - if ( tris_v.size() ) { - sgWriteUShort( fp, (unsigned short)tris_v[i][j] ); - } - if ( tris_n.size() ) { - sgWriteUShort( fp, (unsigned short)tris_n[i][j] ); - } - if ( tris_c.size() ) { - sgWriteUShort( fp, (unsigned short)tris_c[i][j] ); - } - if ( tris_tc.size() ) { - sgWriteUShort( fp, (unsigned short)tris_tc[i][j] ); - } - } - } - - start = end; - end = start + 1; - } - } - - // dump triangle strips - if ( strips_v.size() > 0 ) { - int start = 0; - int end = 1; - string material; - while ( start < (int)strip_materials.size() ) { - // find next group - material = strip_materials[start]; - while ( (end < (int)strip_materials.size()) && - (material == strip_materials[end]) ) - { - // cout << "end = " << end << endl; - end++; - } - // cout << "group = " << start << " to " << end - 1 << endl; - - // write group headers - sgWriteChar( fp, (char)SG_TRIANGLE_STRIPS ); // type - sgWriteUShort( fp, 2 ); // nproperties - sgWriteUShort( 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() * idx_size - * sizeof(unsigned short)); - for ( j = 0; j < (int)strips_v[i].size(); ++j ) { - if ( strips_v.size() ) { - sgWriteUShort( fp, (unsigned short)strips_v[i][j] ); - } - if ( strips_n.size() ) { - sgWriteUShort( fp, (unsigned short)strips_n[i][j] ); - } - if ( strips_c.size() ) { - sgWriteUShort( fp, (unsigned short)strips_c[i][j] ); - } - if ( strips_tc.size() ) { - sgWriteUShort( fp, (unsigned short)strips_tc[i][j] ); - } - } - } - - start = end; - end = start + 1; - } - } - - // dump triangle fans - if ( fans_v.size() > 0 ) { - int start = 0; - int end = 1; - string material; - while ( start < (int)fan_materials.size() ) { - // find next group - material = fan_materials[start]; - while ( (end < (int)fan_materials.size()) && - (material == fan_materials[end]) ) - { - // cout << "end = " << end << endl; - end++; - } - // cout << "group = " << start << " to " << end - 1 << endl; - - // write group headers - sgWriteChar( fp, (char)SG_TRIANGLE_FANS ); // type - sgWriteUShort( fp, 2 ); // nproperties - sgWriteUShort( 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() * idx_size - * sizeof(unsigned short) ); - for ( j = 0; j < (int)fans_v[i].size(); ++j ) { - if ( fans_v.size() ) { - sgWriteUShort( fp, (unsigned short)fans_v[i][j] ); - } - if ( fans_n.size() ) { - sgWriteUShort( fp, (unsigned short)fans_n[i][j] ); - } - if ( fans_c.size() ) { - sgWriteUShort( fp, (unsigned short)fans_c[i][j] ); - } - if ( fans_tc.size() ) { - sgWriteUShort( fp, (unsigned short)fans_tc[i][j] ); - } - } - } - - start = end; - end = start + 1; - } - } - + 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); + // close the file gzclose(fp); if ( sgWriteError() ) { - cout << "We detected an error while writing the file." << endl; - return false; + cout << "We detected an error while writing the file." << endl; + return false; } return true; @@ -1001,7 +832,7 @@ bool SGBinObject::write_bin( const string& base, const string& name, // groups come to us sorted by material property. If not, things // don't break, but the result won't be as optimal. bool SGBinObject::write_ascii( const string& base, const string& name, - const SGBucket& b ) + const SGBucket& b ) { int i, j; @@ -1011,16 +842,16 @@ bool SGBinObject::write_ascii( const string& base, const string& name, FILE *fp; if ( (fp = fopen( file.c_str(), "w" )) == NULL ) { - cout << "ERROR: opening " << file.str() << " for writing!" << endl; - return false; + cout << "ERROR: opening " << file.str() << " for writing!" << endl; + return false; } cout << "triangles size = " << tris_v.size() << " tri_materials = " - << tri_materials.size() << endl; + << tri_materials.size() << endl; cout << "strips size = " << strips_v.size() << " strip_materials = " - << strip_materials.size() << endl; + << strip_materials.size() << endl; cout << "fans size = " << fans_v.size() << " fan_materials = " - << fan_materials.size() << endl; + << fan_materials.size() << endl; cout << "points = " << wgs84_nodes.size() << endl; cout << "tex coords = " << texcoords.size() << endl; @@ -1038,22 +869,22 @@ bool SGBinObject::write_ascii( const string& base, const string& name, // write bounding sphere fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n", - gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius); + gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius); fprintf(fp, "\n"); // dump vertex list fprintf(fp, "# vertex list\n"); for ( i = 0; i < (int)wgs84_nodes.size(); ++i ) { SGVec3d p = wgs84_nodes[i] - gbs_center; - - fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() ); + + fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z() ); } fprintf(fp, "\n"); fprintf(fp, "# vertex normal list\n"); for ( i = 0; i < (int)normals.size(); ++i ) { SGVec3f p = normals[i]; - fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() ); + fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z() ); } fprintf(fp, "\n"); @@ -1061,27 +892,27 @@ bool SGBinObject::write_ascii( const string& base, const string& name, fprintf(fp, "# texture coordinate list\n"); for ( i = 0; i < (int)texcoords.size(); ++i ) { SGVec2f p = texcoords[i]; - fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y() ); + fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y() ); } fprintf(fp, "\n"); // dump individual triangles if they exist if ( tris_v.size() > 0 ) { - fprintf(fp, "# triangle groups\n"); + fprintf(fp, "# triangle groups\n"); - int start = 0; - int end = 1; - string material; - while ( start < (int)tri_materials.size() ) { - // find next group - material = tri_materials[start]; - while ( (end < (int)tri_materials.size()) && - (material == tri_materials[end]) ) - { - // cout << "end = " << end << endl; - end++; - } - // cout << "group = " << start << " to " << end - 1 << endl; + int start = 0; + int end = 1; + string material; + while ( start < (int)tri_materials.size() ) { + // find next group + material = tri_materials[start]; + while ( (end < (int)tri_materials.size()) && + (material == tri_materials[end]) ) + { + // cout << "end = " << end << endl; + end++; + } + // cout << "group = " << start << " to " << end - 1 << endl; SGSphered d; for ( i = start; i < end; ++i ) { @@ -1092,44 +923,44 @@ bool SGBinObject::write_ascii( const string& base, const string& name, SGVec3d bs_center = d.getCenter(); double bs_radius = d.getRadius(); - - // write group headers - fprintf(fp, "\n"); - fprintf(fp, "# usemtl %s\n", material.c_str()); - fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n", - bs_center.x(), bs_center.y(), bs_center.z(), bs_radius); + + // write group headers + fprintf(fp, "\n"); + fprintf(fp, "# usemtl %s\n", material.c_str()); + fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n", + bs_center.x(), bs_center.y(), bs_center.z(), bs_radius); - // write groups - 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, "\n"); - } + // write groups + 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, "\n"); + } - start = end; - end = start + 1; - } + start = end; + end = start + 1; + } } // dump triangle groups if ( strips_v.size() > 0 ) { - fprintf(fp, "# triangle strips\n"); + fprintf(fp, "# triangle strips\n"); - int start = 0; - int end = 1; - string material; - while ( start < (int)strip_materials.size() ) { - // find next group - material = strip_materials[start]; - while ( (end < (int)strip_materials.size()) && - (material == strip_materials[end]) ) - { - // cout << "end = " << end << endl; - end++; - } - // cout << "group = " << start << " to " << end - 1 << endl; + int start = 0; + int end = 1; + string material; + while ( start < (int)strip_materials.size() ) { + // find next group + material = strip_materials[start]; + while ( (end < (int)strip_materials.size()) && + (material == strip_materials[end]) ) + { + // cout << "end = " << end << endl; + end++; + } + // cout << "group = " << start << " to " << end - 1 << endl; SGSphered d; @@ -1142,24 +973,24 @@ bool SGBinObject::write_ascii( const string& base, const string& name, SGVec3d bs_center = d.getCenter(); double bs_radius = d.getRadius(); - // write group headers - fprintf(fp, "\n"); - fprintf(fp, "# usemtl %s\n", material.c_str()); - fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n", - bs_center.x(), bs_center.y(), bs_center.z(), bs_radius); + // write group headers + fprintf(fp, "\n"); + fprintf(fp, "# usemtl %s\n", material.c_str()); + fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n", + bs_center.x(), bs_center.y(), bs_center.z(), bs_radius); - // write groups - 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, "\n"); - } - - start = end; - end = start + 1; - } + // write groups + 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, "\n"); + } + + start = end; + end = start + 1; + } } // close the file @@ -1170,3 +1001,21 @@ bool SGBinObject::write_ascii( const string& base, const string& name, return true; } + +void SGBinObject::read_properties(gzFile fp, int nproperties) +{ + sgSimpleBuffer buf; + uint32_t nbytes; + + // read properties + for ( int 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 ); + } +} + diff --git a/simgear/io/sg_binobj.hxx b/simgear/io/sg_binobj.hxx index 7f672640..d594113d 100644 --- a/simgear/io/sg_binobj.hxx +++ b/simgear/io/sg_binobj.hxx @@ -27,29 +27,24 @@ #ifndef _SG_BINOBJ_HXX #define _SG_BINOBJ_HXX +#include // for gzFile #include #include #include -#include +#include -#include -#include - -#include +#include #include - - /** STL Structure used to store 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; - -/** Magic Number for our file format */ -#define SG_FILE_MAGIC_NUMBER ( ('S'<<24) + ('G'<<16) + SG_BINOBJ_VERSION ) - +// forward decls +class SGBucket; +class SGPath; /** * A class to manipulate the simgear 3d object format. @@ -85,6 +80,7 @@ typedef group_list::const_iterator const_group_list_iterator; * - vertex: FLOAT, FLOAT, FLOAT */ class SGBinObject { +private: unsigned short version; SGVec3d gbs_center; @@ -119,6 +115,24 @@ class SGBinObject { group_list fans_tc; // fans texture coordinate index string_list fan_materials; // fans materials + void read_properties(gzFile fp, int nproperties); + + 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); + + 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); + + unsigned int count_objects(const string_list& materials); public: inline unsigned short get_version() const { return version; } @@ -207,6 +221,9 @@ public: */ bool write_bin( const std::string& base, const std::string& name, const SGBucket& b ); + + bool write_bin_file(const SGPath& file); + /** * Write out the structures to an ASCII file. We assume that the * groups come to us sorted by material property. If not, things From 64b6a4ebf25e215e9d3d75e0cce65ee95177fd5d Mon Sep 17 00:00:00 2001 From: Martin Spott Date: Fri, 7 Oct 2011 09:57:09 +0200 Subject: [PATCH 3/4] Add missing header for printf --- simgear/io/decode_binobj.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/simgear/io/decode_binobj.cxx b/simgear/io/decode_binobj.cxx index af2ae2b9..0c4a9922 100644 --- a/simgear/io/decode_binobj.cxx +++ b/simgear/io/decode_binobj.cxx @@ -10,6 +10,7 @@ #include #include +#include #include "sg_binobj.hxx" From 85e58b4a49d3c3b74afed3c766b47b65a6a95a66 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Sat, 8 Oct 2011 17:44:53 +0200 Subject: [PATCH 4/4] hla: for rti13 queue all callbacks. This is to avoid running into the rti13 ambassadors recursion guards. Newer rti standards will not requires this. --- simgear/hla/RTI13Federate.cxx | 453 +++++++++++++++++++++++----- simgear/hla/RTI13ObjectInstance.cxx | 105 ++++--- simgear/hla/RTI13ObjectInstance.hxx | 29 +- simgear/hla/RTIData.hxx | 7 + simgear/hla/RTIObjectClass.cxx | 1 + simgear/hla/RTIObjectInstance.hxx | 81 +---- 6 files changed, 465 insertions(+), 211 deletions(-) diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index 1eece869..08dbdd86 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -41,6 +41,27 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { { } + /// Generic callback to execute some notification on objects in a way that they are not prone to + /// ConcurrentAccess exceptions. + class QueueCallback : public SGReferenced { + public: + virtual ~QueueCallback() {} + virtual void operator()(FederateAmbassador& self) = 0; + }; + class TagQueueCallback : public QueueCallback { + public: + TagQueueCallback(const char* tag) + { + if (tag) + _tag.setData(tag, std::strlen(tag) + 1); + else + _tag.setData("", 1); + } + virtual ~TagQueueCallback() + { } + RTIData _tag; + }; + /// RTI federate ambassador callback functions. virtual void synchronizationPointRegistrationSucceeded(const char* label) throw (RTI::FederateInternalError) @@ -115,9 +136,21 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { } // Declaration Management + class StartRegistrationForObjectClassCallback : public QueueCallback { + public: + StartRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle) : + _objectClassHandle(objectClassHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.startRegistrationForObjectClassCallback(_objectClassHandle); } + private: + RTI::ObjectClassHandle _objectClassHandle; + }; virtual void startRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle) throw (RTI::ObjectClassNotPublished, RTI::FederateInternalError) + { _queueCallbackList.push_back(new StartRegistrationForObjectClassCallback(objectClassHandle)); } + void startRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle) { ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle); if (i == _objectClassMap.end()) @@ -127,9 +160,21 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { i->second->startRegistration(); } + class StopRegistrationForObjectClassCallback : public QueueCallback { + public: + StopRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle) : + _objectClassHandle(objectClassHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.stopRegistrationForObjectClassCallback(_objectClassHandle); } + private: + RTI::ObjectClassHandle _objectClassHandle; + }; virtual void stopRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle) throw (RTI::ObjectClassNotPublished, RTI::FederateInternalError) + { _queueCallbackList.push_back(new StopRegistrationForObjectClassCallback(objectClassHandle)); } + void stopRegistrationForObjectClassCallback(RTI::ObjectClassHandle objectClassHandle) { ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle); if (i == _objectClassMap.end()) @@ -151,23 +196,58 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { { } - // Object Management + class DiscoverObjectCallback : public TagQueueCallback { + public: + DiscoverObjectCallback(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char *tag) : + TagQueueCallback(tag), + _objectHandle(objectHandle), + _objectClassHandle(objectClassHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.discoverObjectInstanceCallback(_objectHandle, _objectClassHandle, _tag); } + private: + RTI::ObjectHandle _objectHandle; + RTI::ObjectClassHandle _objectClassHandle; + }; virtual void discoverObjectInstance(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char* tag) throw (RTI::CouldNotDiscover, RTI::ObjectClassNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new DiscoverObjectCallback(objectHandle, objectClassHandle, tag)); } + void discoverObjectInstanceCallback(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const RTIData& tag) { ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle); if (i == _objectClassMap.end()) - throw RTI::ObjectClassNotKnown("Federate: discoverObjectInstance()!"); + return; if (!i->second.valid()) return; SGSharedPtr objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get(), false); _objectInstanceMap[objectHandle] = objectInstance; - _queueCallbackList.push_back(new DiscoverObjectCallback(i->second, objectInstance, tagToData(tag))); + i->second->discoverInstance(objectInstance.get(), tag); } + class ReflectAttributeValuesTimestampCallback : public TagQueueCallback { + public: + ReflectAttributeValuesTimestampCallback(RTI::ObjectHandle objectHandle, + RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const SGTimeStamp& timeStamp, const char *tag) : + TagQueueCallback(tag), + _objectHandle(objectHandle), + _timeStamp(timeStamp) + { + _attributeHandleDataPairList.swap(attributeHandleDataPairList); + } + virtual void operator()(FederateAmbassador& self) + { + self.reflectAttributeValuesCallback(_objectHandle, _attributeHandleDataPairList, _timeStamp, _tag); + self.freeAttributeHandleDataPairList(_attributeHandleDataPairList); + } + private: + RTI::ObjectHandle _objectHandle; + RTI13AttributeHandleDataPairList _attributeHandleDataPairList; + SGTimeStamp _timeStamp; + }; virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle) throw (RTI::ObjectNotKnown, @@ -175,28 +255,79 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::FederateOwnsAttributes, RTI::InvalidFederationTime, RTI::FederateInternalError) + { + RTI13AttributeHandleDataPairList attributeHandleDataPairList; + + RTI::ULong numAttribs = attributeValuePairSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + appendAttributeHandleDataPair(attributeHandleDataPairList); + attributeHandleDataPairList.back().first = attributeValuePairSet.getHandle(i); + RTI::ULong length = attributeValuePairSet.getValueLength(i); + attributeHandleDataPairList.back().second.resize(length); + attributeValuePairSet.getValue(i, attributeHandleDataPairList.back().second.data(), length); + } + + _queueCallbackList.push_back(new ReflectAttributeValuesTimestampCallback(objectHandle, attributeHandleDataPairList, + RTI13Ambassador::toTimeStamp(fedTime), tag)); + } + void reflectAttributeValuesCallback(RTI::ObjectHandle objectHandle, RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const SGTimeStamp& timeStamp, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + return; if (!i->second.valid()) return; - i->second->reflectAttributeValues(attributeValuePairSet, RTI13Ambassador::toTimeStamp(fedTime), tagToData(tag)); + i->second->reflectAttributeValues(attributeHandleDataPairList, timeStamp, tag); } + class ReflectAttributeValuesCallback : public TagQueueCallback { + public: + ReflectAttributeValuesCallback(RTI::ObjectHandle objectHandle, RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const char *tag) : + TagQueueCallback(tag), + _objectHandle(objectHandle) + { + _attributeHandleDataPairList.swap(attributeHandleDataPairList); + } + virtual void operator()(FederateAmbassador& self) + { + self.reflectAttributeValuesCallback(_objectHandle, _attributeHandleDataPairList, _tag); + self.freeAttributeHandleDataPairList(_attributeHandleDataPairList); + } + private: + RTI::ObjectHandle _objectHandle; + RTI13AttributeHandleDataPairList _attributeHandleDataPairList; + }; virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const char* tag) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateOwnsAttributes, RTI::FederateInternalError) + { + RTI13AttributeHandleDataPairList attributeHandleDataPairList; + + RTI::ULong numAttribs = attributeValuePairSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + appendAttributeHandleDataPair(attributeHandleDataPairList); + attributeHandleDataPairList.back().first = attributeValuePairSet.getHandle(i); + RTI::ULong length = attributeValuePairSet.getValueLength(i); + attributeHandleDataPairList.back().second.resize(length); + attributeValuePairSet.getValue(i, attributeHandleDataPairList.back().second.data(), length); + } + + _queueCallbackList.push_back(new ReflectAttributeValuesCallback(objectHandle, attributeHandleDataPairList, tag)); + } + void reflectAttributeValuesCallback(RTI::ObjectHandle objectHandle, RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + return; if (!i->second.valid()) return; - i->second->reflectAttributeValues(attributeValuePairSet, tagToData(tag)); + i->second->reflectAttributeValues(attributeHandleDataPairList, tag); } virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, @@ -216,99 +347,202 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { { } + class RemoveObjectTimestampCallback : public TagQueueCallback { + public: + RemoveObjectTimestampCallback(RTI::ObjectHandle objectHandle, const SGTimeStamp& timeStamp, const char* tag) : + TagQueueCallback(tag), + _objectHandle(objectHandle), + _timeStamp(timeStamp) + { } + virtual void operator()(FederateAmbassador& self) + { self.removeObjectInstanceCallback(_objectHandle, _timeStamp, _tag); } + private: + RTI::ObjectHandle _objectHandle; + SGTimeStamp _timeStamp; + }; virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle) throw (RTI::ObjectNotKnown, RTI::InvalidFederationTime, RTI::FederateInternalError) + { _queueCallbackList.push_back(new RemoveObjectTimestampCallback(objectHandle, RTI13Ambassador::toTimeStamp(fedTime), tag)); } + void removeObjectInstanceCallback(RTI::ObjectHandle objectHandle, const SGTimeStamp& timeStamp, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!"); + return; if (i->second.valid()) - _queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag))); + i->second->removeInstance(tag); _objectInstanceMap.erase(i); } + class RemoveObjectCallback : public TagQueueCallback { + public: + RemoveObjectCallback(RTI::ObjectHandle objectHandle, const char* tag) : + TagQueueCallback(tag), + _objectHandle(objectHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.removeObjectInstanceCallback(_objectHandle, _tag); } + private: + RTI::ObjectHandle _objectHandle; + }; virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const char* tag) throw (RTI::ObjectNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new RemoveObjectCallback(objectHandle, tag)); } + void removeObjectInstanceCallback(RTI::ObjectHandle objectHandle, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!"); + return; if (i->second.valid()) - _queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag))); + i->second->removeInstance(tag); _objectInstanceMap.erase(i); } + class AttributeHandleSetCallback : public QueueCallback { + public: + AttributeHandleSetCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributeHandleSet) : + _objectHandle(objectHandle) + { + RTI::ULong numAttribs = attributeHandleSet.size(); + _attributes.reserve(numAttribs); + for (RTI::ULong i = 0; i < numAttribs; ++i) + _attributes.push_back(attributeHandleSet.getHandle(i)); + } + protected: + RTI::ObjectHandle _objectHandle; + std::vector _attributes; + }; + class AttributesInScopeCallback : public AttributeHandleSetCallback { + public: + AttributesInScopeCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributesInScopeCallback(_objectHandle, _attributes); } + }; virtual void attributesInScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributesInScopeCallback(objectHandle, attributes)); } + void attributesInScopeCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Attributes in scope for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributesInScope(attributes); } + class AttributesOutOfScopeCallback : public AttributeHandleSetCallback { + public: + AttributesOutOfScopeCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributesOutOfScopeCallback(_objectHandle, _attributes); } + }; virtual void attributesOutOfScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributesOutOfScopeCallback(objectHandle, attributes)); } + void attributesOutOfScopeCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Attributes in scope for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributesOutOfScope(attributes); } + class ProvideAttributeValueUpdateCallback : public AttributeHandleSetCallback { + public: + ProvideAttributeValueUpdateCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.provideAttributeValueUpdateCallback(_objectHandle, _attributes); } + }; virtual void provideAttributeValueUpdate(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::AttributeNotOwned, RTI::FederateInternalError) + { _queueCallbackList.push_back(new ProvideAttributeValueUpdateCallback(objectHandle, attributes)); } + void provideAttributeValueUpdateCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + return; if (!i->second.valid()) return; i->second->provideAttributeValueUpdate(attributes); } + class TurnUpdatesOnForObjectInstanceCallback : public AttributeHandleSetCallback { + public: + TurnUpdatesOnForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.turnUpdatesOnForObjectInstanceCallback(_objectHandle, _attributes); } + }; virtual void turnUpdatesOnForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotOwned, RTI::FederateInternalError) + { _queueCallbackList.push_back(new TurnUpdatesOnForObjectInstanceCallback(objectHandle, attributes)); } + void turnUpdatesOnForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Turn on attributes for unknown object!"); + return; if (!i->second.valid()) return; i->second->turnUpdatesOnForObjectInstance(attributes); } + class TurnUpdatesOffForObjectInstanceCallback : public AttributeHandleSetCallback { + public: + TurnUpdatesOffForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.turnUpdatesOffForObjectInstanceCallback(_objectHandle, _attributes); } + }; virtual void turnUpdatesOffForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotOwned, RTI::FederateInternalError) + { _queueCallbackList.push_back(new TurnUpdatesOffForObjectInstanceCallback(objectHandle, attributes)); } + void turnUpdatesOffForObjectInstanceCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("Turn off attributes for unknown object!"); + return; if (!i->second.valid()) return; i->second->turnUpdatesOffForObjectInstance(attributes); } // Ownership Management + class RequestAttributeOwnershipAssumptionCallback : public AttributeHandleSetCallback { + public: + RequestAttributeOwnershipAssumptionCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes, const RTIData& tag) : + AttributeHandleSetCallback(objectHandle, attributes), + _tag(tag) + { } + virtual void operator()(FederateAmbassador& self) + { self.requestAttributeOwnershipAssumptionCallback(_objectHandle, _attributes, _tag); } + protected: + RTIData _tag; + }; virtual void requestAttributeOwnershipAssumption(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes, const char* tag) throw (RTI::ObjectNotKnown, @@ -316,30 +550,50 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::AttributeAlreadyOwned, RTI::AttributeNotPublished, RTI::FederateInternalError) + { _queueCallbackList.push_back(new RequestAttributeOwnershipAssumptionCallback(objectHandle, attributes, tagToData(tag))); } + void requestAttributeOwnershipAssumptionCallback(RTI::ObjectHandle objectHandle, std::vector& attributes, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("requestAttributeOwnershipAssumption for unknown object!"); + return; if (!i->second.valid()) return; - i->second->requestAttributeOwnershipAssumption(attributes, tagToData(tag)); + i->second->requestAttributeOwnershipAssumption(attributes, tag); } + class AttributeOwnershipDivestitureNotificationCallback : public AttributeHandleSetCallback { + public: + AttributeOwnershipDivestitureNotificationCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributeOwnershipDivestitureNotificationCallback(_objectHandle, _attributes); } + }; virtual void attributeOwnershipDivestitureNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::AttributeNotOwned, RTI::AttributeDivestitureWasNotRequested, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributeOwnershipDivestitureNotificationCallback(objectHandle, attributes)); } + void attributeOwnershipDivestitureNotificationCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnershipDivestitureNotification for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributeOwnershipDivestitureNotification(attributes); } + class AttributeOwnershipAcquisitionNotificationCallback : public AttributeHandleSetCallback { + public: + AttributeOwnershipAcquisitionNotificationCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributeOwnershipAcquisitionNotificationCallback(_objectHandle, _attributes); } + }; virtual void attributeOwnershipAcquisitionNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, @@ -347,95 +601,174 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::AttributeAlreadyOwned, RTI::AttributeNotPublished, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributeOwnershipAcquisitionNotificationCallback(objectHandle, attributes)); } + void attributeOwnershipAcquisitionNotificationCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnershipAcquisitionNotification for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributeOwnershipAcquisitionNotification(attributes); } + class AttributeOwnershipUnavailableCallback : public AttributeHandleSetCallback { + public: + AttributeOwnershipUnavailableCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributeOwnershipUnavailableCallback(_objectHandle, _attributes); } + }; virtual void attributeOwnershipUnavailable(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::AttributeAlreadyOwned, RTI::AttributeAcquisitionWasNotRequested, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributeOwnershipUnavailableCallback(objectHandle, attributes)); } + void attributeOwnershipUnavailableCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnershipUnavailable for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributeOwnershipUnavailable(attributes); } + class RequestAttributeOwnershipReleaseCallback : public AttributeHandleSetCallback { + public: + RequestAttributeOwnershipReleaseCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes, const RTIData& tag) : + AttributeHandleSetCallback(objectHandle, attributes), + _tag(tag) + { } + virtual void operator()(FederateAmbassador& self) + { self.requestAttributeOwnershipReleaseCallback(_objectHandle, _attributes, _tag); } + protected: + RTIData _tag; + }; virtual void requestAttributeOwnershipRelease(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes, const char* tag) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::AttributeNotOwned, RTI::FederateInternalError) + { _queueCallbackList.push_back(new RequestAttributeOwnershipReleaseCallback(objectHandle, attributes, tagToData(tag))); } + void requestAttributeOwnershipReleaseCallback(RTI::ObjectHandle objectHandle, std::vector& attributes, const RTIData& tag) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("requestAttributeOwnershipRelease for unknown object!"); + return; if (!i->second.valid()) return; - i->second->requestAttributeOwnershipRelease(attributes, tagToData(tag)); + i->second->requestAttributeOwnershipRelease(attributes, tag); } + class ConfirmAttributeOwnershipAcquisitionCancellationCallback : public AttributeHandleSetCallback { + public: + ConfirmAttributeOwnershipAcquisitionCancellationCallback(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) : + AttributeHandleSetCallback(objectHandle, attributes) + { } + virtual void operator()(FederateAmbassador& self) + { self.confirmAttributeOwnershipAcquisitionCancellationCallback(_objectHandle, _attributes); } + }; virtual void confirmAttributeOwnershipAcquisitionCancellation(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::AttributeAlreadyOwned, RTI::AttributeAcquisitionWasNotCanceled, RTI::FederateInternalError) + { _queueCallbackList.push_back(new ConfirmAttributeOwnershipAcquisitionCancellationCallback(objectHandle, attributes)); } + void confirmAttributeOwnershipAcquisitionCancellationCallback(RTI::ObjectHandle objectHandle, const std::vector& attributes) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("confirmAttributeOwnershipAcquisitionCancellation for unknown object!"); + return; if (!i->second.valid()) return; i->second->confirmAttributeOwnershipAcquisitionCancellation(attributes); } + class InformAttributeOwnershipCallback : public QueueCallback { + public: + InformAttributeOwnershipCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle) : + _objectHandle(objectHandle), + _attributeHandle(attributeHandle), + _federateHandle(federateHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.informAttributeOwnershipCallback(_objectHandle, _attributeHandle, _federateHandle); } + private: + RTI::ObjectHandle _objectHandle; + RTI::AttributeHandle _attributeHandle; + RTI::FederateHandle _federateHandle; + }; virtual void informAttributeOwnership(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new InformAttributeOwnershipCallback(objectHandle, attributeHandle, federateHandle)); } + void informAttributeOwnershipCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("informAttributeOwnership for unknown object!"); + return; if (!i->second.valid()) return; i->second->informAttributeOwnership(attributeHandle, federateHandle); } + class AttributeIsNotOwnedCallback : public QueueCallback { + public: + AttributeIsNotOwnedCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) : + _objectHandle(objectHandle), + _attributeHandle(attributeHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributeIsNotOwnedCallback(_objectHandle, _attributeHandle); } + private: + RTI::ObjectHandle _objectHandle; + RTI::AttributeHandle _attributeHandle; + }; virtual void attributeIsNotOwned(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributeIsNotOwnedCallback(objectHandle, attributeHandle)); } + void attributeIsNotOwnedCallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeIsNotOwned for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributeIsNotOwned(attributeHandle); } + class AttributeOwnedByRTICallback : public QueueCallback { + public: + AttributeOwnedByRTICallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) : + _objectHandle(objectHandle), + _attributeHandle(attributeHandle) + { } + virtual void operator()(FederateAmbassador& self) + { self.attributeOwnedByRTICallback(_objectHandle, _attributeHandle); } + private: + RTI::ObjectHandle _objectHandle; + RTI::AttributeHandle _attributeHandle; + }; virtual void attributeOwnedByRTI(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) throw (RTI::ObjectNotKnown, RTI::AttributeNotKnown, RTI::FederateInternalError) + { _queueCallbackList.push_back(new AttributeOwnedByRTICallback(objectHandle, attributeHandle)); } + void attributeOwnedByRTICallback(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) { ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); if (i == _objectInstanceMap.end()) - throw RTI::ObjectNotKnown("attributeOwnedByRTI for unknown object!"); + return; if (!i->second.valid()) return; i->second->attributeOwnedByRTI(attributeHandle); @@ -448,8 +781,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::FederateInternalError) { _timeRegulationEnabled = true; - _federateTime = RTI13Ambassador::toTimeStamp(fedTime); - SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << _federateTime); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << RTI13Ambassador::toTimeStamp(fedTime)); } virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime) @@ -458,8 +790,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::FederateInternalError) { _timeConstrainedEnabled = true; - _federateTime = RTI13Ambassador::toTimeStamp(fedTime); - SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << _federateTime); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << RTI13Ambassador::toTimeStamp(fedTime)); } virtual void timeAdvanceGrant(const RTI::FedTime& fedTime) @@ -467,9 +798,8 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { RTI::TimeAdvanceWasNotInProgress, RTI::FederateInternalError) { - _federateTime = RTI13Ambassador::toTimeStamp(fedTime); _timeAdvancePending = false; - SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << _federateTime); + // SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << RTI13Ambassador::toTimeStamp(fedTime)); } virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle) @@ -483,7 +813,8 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { void processQueues() { while (!_queueCallbackList.empty()) { - (*_queueCallbackList.front())(); + (*_queueCallbackList.front())(*this); + // _queueCallbackListPool.splice(); _queueCallbackList.pop_front(); } } @@ -499,46 +830,6 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { return true; } - /// Generic callback to execute some notification on objects in a way that they are not prone to - /// ConcurrentAccess exceptions. - class QueueCallback : public SGReferenced { - public: - virtual ~QueueCallback() {} - virtual void operator()() = 0; - }; - - class DiscoverObjectCallback : public QueueCallback { - public: - DiscoverObjectCallback(SGSharedPtr objectClass, SGSharedPtr objectInstance, const RTIData& tag) : - _objectClass(objectClass), - _objectInstance(objectInstance), - _tag(tag) - { } - virtual void operator()() - { - _objectClass->discoverInstance(_objectInstance.get(), _tag); - _objectInstance->requestObjectAttributeValueUpdate(); - } - private: - SGSharedPtr _objectClass; - SGSharedPtr _objectInstance; - RTIData _tag; - }; - class RemoveObjectCallback : public QueueCallback { - public: - RemoveObjectCallback(SGSharedPtr objectInstance, const RTIData& tag) : - _objectInstance(objectInstance), - _tag(tag) - { } - virtual void operator()() - { - _objectInstance->removeInstance(_tag); - } - private: - SGSharedPtr _objectInstance; - RTIData _tag; - }; - // The rtiambassador to issue requests SGSharedPtr _rtiAmbassador; @@ -550,6 +841,19 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { // That is to make sure we do not call recursively into the RTI typedef std::list > QueueCallbackList; QueueCallbackList _queueCallbackList; + // QueueCallbackList _queueCallbackListPool; + + RTI13AttributeHandleDataPairList _attributeHandleDataPairPool; + void appendAttributeHandleDataPair(RTI13AttributeHandleDataPairList& attributeHandleDataPairList) + { + if (_attributeHandleDataPairPool.empty()) + attributeHandleDataPairList.push_back(RTI13AttributeHandleDataPair()); + else + attributeHandleDataPairList.splice(attributeHandleDataPairList.end(), + _attributeHandleDataPairPool, _attributeHandleDataPairPool.begin()); + } + void freeAttributeHandleDataPairList(RTI13AttributeHandleDataPairList& attributeHandleDataPairList) + { _attributeHandleDataPairPool.splice(_attributeHandleDataPairPool.end(), attributeHandleDataPairList); } // Top level information for dispatching federate object attribute updates typedef std::map > ObjectInstanceMap; @@ -563,7 +867,6 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { bool _timeRegulationEnabled; bool _timeConstrainedEnabled; bool _timeAdvancePending; - SGTimeStamp _federateTime; private: const RTIData& tagToData(const char* tag) diff --git a/simgear/hla/RTI13ObjectInstance.cxx b/simgear/hla/RTI13ObjectInstance.cxx index 723f9b17..f8ba657f 100644 --- a/simgear/hla/RTI13ObjectInstance.cxx +++ b/simgear/hla/RTI13ObjectInstance.cxx @@ -177,47 +177,56 @@ RTI13ObjectInstance::localDeleteObjectInstance() } void -RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag) +RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag) { // Retrieve an empty update struct from the memory pool - UpdateList updateList; - getUpdateFromPool(updateList); - - RTI::ULong numAttribs = attributeValuePairSet.size(); - for (RTI::ULong i = 0; i < numAttribs; ++i) { - unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i)); + RTIIndexDataPairList indexDataPairList; + for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); + i != attributeHandleDataPairList.end(); ++i) { + unsigned index = getAttributeIndex(i->first); // Get a RTIData from the data pool - getDataFromPool(index, updateList.back()._indexDataPairList); - RTI::ULong length = attributeValuePairSet.getValueLength(i); - updateList.back()._indexDataPairList.back().second.resize(length); - attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length); - updateList.back()._tag = tag; + getDataFromPool(indexDataPairList); + indexDataPairList.back().first = index; + indexDataPairList.back().second.swap(i->second); + } + + RTIObjectInstance::reflectAttributeValues(indexDataPairList, tag); + + RTIIndexDataPairList::iterator j = indexDataPairList.begin(); + for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); + i != attributeHandleDataPairList.end(); ++i, ++j) { + i->second.swap(j->second); } - RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag); // Return the update data back to the pool - putUpdateToPool(updateList); + putDataToPool(indexDataPairList); } void -RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag) +RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const SGTimeStamp& timeStamp, const RTIData& tag) { // Retrieve an empty update struct from the memory pool - UpdateList updateList; - getUpdateFromPool(updateList); - - RTI::ULong numAttribs = attributeValuePairSet.size(); - for (RTI::ULong i = 0; i < numAttribs; ++i) { - unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i)); + RTIIndexDataPairList indexDataPairList; + for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); + i != attributeHandleDataPairList.end(); ++i) { + unsigned index = getAttributeIndex(i->first); // Get a RTIData from the data pool - getDataFromPool(index, updateList.back()._indexDataPairList); - RTI::ULong length = attributeValuePairSet.getValueLength(i); - updateList.back()._indexDataPairList.back().second.resize(length); - attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length); - updateList.back()._tag = tag; + getDataFromPool(indexDataPairList); + indexDataPairList.back().first = index; + indexDataPairList.back().second.swap(i->second); } - scheduleUpdates(timeStamp, updateList); + RTIObjectInstance::reflectAttributeValues(indexDataPairList, timeStamp, tag); + + RTIIndexDataPairList::iterator j = indexDataPairList.begin(); + for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); + i != attributeHandleDataPairList.end(); ++i, ++j) { + i->second.swap(j->second); + } + + // Return the update data back to the pool + putDataToPool(indexDataPairList); } void @@ -273,12 +282,12 @@ RTI13ObjectInstance::requestObjectAttributeValueUpdate() } void -RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::provideAttributeValueUpdate(const std::vector& attributeHandleSet) { // Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update - RTI::ULong numAttribs = attributes.size(); + size_t numAttribs = attributeHandleSet.size(); for (RTI::ULong i = 0; i < numAttribs; ++i) { - unsigned index = getAttributeIndex(attributes.getHandle(i)); + unsigned index = getAttributeIndex(attributeHandleSet[i]); setAttributeForceUpdate(index); } } @@ -400,72 +409,72 @@ RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const R } void -RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet) +RTI13ObjectInstance::attributesInScope(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + size_t numAttribs = attributeHandleSet.size(); for (RTI::ULong i = 0; i < numAttribs; ++i) { - RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + RTI::AttributeHandle attributeHandle = attributeHandleSet[i]; setAttributeInScope(getAttributeIndex(attributeHandle), true); } } void -RTI13ObjectInstance::attributesOutOfScope(const RTI::AttributeHandleSet& attributeHandleSet) +RTI13ObjectInstance::attributesOutOfScope(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + size_t numAttribs = attributeHandleSet.size(); for (RTI::ULong i = 0; i < numAttribs; ++i) { - RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + RTI::AttributeHandle attributeHandle = attributeHandleSet[i]; setAttributeInScope(getAttributeIndex(attributeHandle), false); } } void -RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet) +RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + size_t numAttribs = attributeHandleSet.size(); for (RTI::ULong i = 0; i < numAttribs; ++i) { - RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + RTI::AttributeHandle attributeHandle = attributeHandleSet[i]; setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true); } } void -RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet) +RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const std::vector& attributeHandleSet) { - RTI::ULong numAttribs = attributeHandleSet.size(); + size_t numAttribs = attributeHandleSet.size(); for (RTI::ULong i = 0; i < numAttribs; ++i) { - RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + RTI::AttributeHandle attributeHandle = attributeHandleSet[i]; setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false); } } void -RTI13ObjectInstance::requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag) +RTI13ObjectInstance::requestAttributeOwnershipAssumption(const std::vector& attributes, const RTIData& tag) { } void -RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const std::vector& attributes) { } void -RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const std::vector& attributes) { } void -RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::attributeOwnershipUnavailable(const std::vector& attributes) { } void -RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag) +RTI13ObjectInstance::requestAttributeOwnershipRelease(const std::vector& attributes, const RTIData& tag) { } void -RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes) +RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const std::vector& attributes) { } diff --git a/simgear/hla/RTI13ObjectInstance.hxx b/simgear/hla/RTI13ObjectInstance.hxx index 654bff92..38fd92b2 100644 --- a/simgear/hla/RTI13ObjectInstance.hxx +++ b/simgear/hla/RTI13ObjectInstance.hxx @@ -37,6 +37,9 @@ namespace simgear { class RTI13Ambassador; class RTI13ObjectClass; +typedef std::pair RTI13AttributeHandleDataPair; +typedef std::list RTI13AttributeHandleDataPairList; + class RTI13ObjectInstance : public RTIObjectInstance { public: RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned); @@ -65,27 +68,27 @@ public: virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag); virtual void localDeleteObjectInstance(); - void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag); - void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag); + void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag); + void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); virtual void requestObjectAttributeValueUpdate(); - void provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes); + void provideAttributeValueUpdate(const std::vector& attributes); virtual void updateAttributeValues(const RTIData& tag); virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); - void attributesInScope(const RTI::AttributeHandleSet& attributes); - void attributesOutOfScope(const RTI::AttributeHandleSet& attributes); + void attributesInScope(const std::vector& attributes); + void attributesOutOfScope(const std::vector& attributes); - void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes); - void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes); + void turnUpdatesOnForObjectInstance(const std::vector& attributes); + void turnUpdatesOffForObjectInstance(const std::vector& attributes); // Not yet sure what to do here. But the dispatch functions are already there - void requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag); - void attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes); - void attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes); - void attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes); - void requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag); - void confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes); + void requestAttributeOwnershipAssumption(const std::vector& attributes, const RTIData& tag); + void attributeOwnershipDivestitureNotification(const std::vector& attributes); + void attributeOwnershipAcquisitionNotification(const std::vector& attributes); + void attributeOwnershipUnavailable(const std::vector& attributes); + void requestAttributeOwnershipRelease(const std::vector& attributes, const RTIData& tag); + void confirmAttributeOwnershipAcquisitionCancellation(const std::vector& attributes); void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle); void attributeIsNotOwned(RTI::AttributeHandle attributeHandle); void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle); diff --git a/simgear/hla/RTIData.hxx b/simgear/hla/RTIData.hxx index dff66dbf..2dc32b06 100644 --- a/simgear/hla/RTIData.hxx +++ b/simgear/hla/RTIData.hxx @@ -115,6 +115,13 @@ public: ensureCapacity(capacity); } + void swap(RTIData& data) + { + std::swap(_data, data._data); + std::swap(_size, data._size); + std::swap(_capacity, data._capacity); + } + void setData(char* data, unsigned size) { if (_capacity) diff --git a/simgear/hla/RTIObjectClass.cxx b/simgear/hla/RTIObjectClass.cxx index 98618cfc..dceb3029 100644 --- a/simgear/hla/RTIObjectClass.cxx +++ b/simgear/hla/RTIObjectClass.cxx @@ -39,6 +39,7 @@ RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIDat return; } hlaObjectClass->discoverInstance(objectInstance, tag); + objectInstance->requestObjectAttributeValueUpdate(); } void diff --git a/simgear/hla/RTIObjectInstance.hxx b/simgear/hla/RTIObjectInstance.hxx index e3e37b6d..61ff9328 100644 --- a/simgear/hla/RTIObjectInstance.hxx +++ b/simgear/hla/RTIObjectInstance.hxx @@ -60,20 +60,6 @@ public: virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; void removeInstance(const RTIData& tag); - // Call this if you want to roll up the queued timestamed updates - // and reflect that into the attached data elements. - void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp) - { - // replay all updates up to the given timestamp - UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp); - for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) { - for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) { - // FIXME have a variant that takes the timestamp? - reflectAttributeValues(j->_indexDataPairList, j->_tag); - } - putUpdateToPool(i->second); - } - } void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag); void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); void reflectAttributeValue(unsigned i, const RTIData& data) @@ -241,80 +227,25 @@ protected: // Is true if we should emit a requestattr bool _pendingAttributeUpdateRequest; - // Contains a full update as it came in from the RTI - struct Update { - RTIIndexDataPairList _indexDataPairList; - RTIData _tag; - }; - // A bunch of updates for the same timestamp - typedef std::list UpdateList; - // The timestamp sorted list of updates - typedef std::map UpdateListMap; - - // The timestamped updates sorted by timestamp - UpdateListMap _updateListMap; - - // The pool of unused updates so that we do not need to malloc/free each time - UpdateList _updateList; - - void getUpdateFromPool(UpdateList& updateList) - { - if (_updateList.empty()) - updateList.push_back(Update()); - else - updateList.splice(updateList.end(), _updateList, _updateList.begin()); - } - void putUpdateToPool(UpdateList& updateList) - { - for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i) - putDataToPool(i->_indexDataPairList); - _updateList.splice(_updateList.end(), updateList); - } - - // Appends the updates in the list to the given timestamps updates - void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList) - { - UpdateListMap::iterator i = _updateListMap.find(timeStamp); - if (i == _updateListMap.end()) - i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first; - i->second.splice(i->second.end(), updateList); - } + // Pool of update list entries + RTIIndexDataPairList _indexDataPairList; // This adds raw storage for attribute index i to the end of the dataPairList. - void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList) + void getDataFromPool(RTIIndexDataPairList& dataPairList) { - if (_attributeData.size() <= i) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!"); - return; - } - // Nothing left in the pool - so allocate something - if (_attributeData[i]._indexDataPairList.empty()) { + if (_indexDataPairList.empty()) { dataPairList.push_back(RTIIndexDataPairList::value_type()); - dataPairList.back().first = i; return; } // Take one from the pool - dataPairList.splice(dataPairList.end(), - _attributeData[i]._indexDataPairList, - _attributeData[i]._indexDataPairList.begin()); + dataPairList.splice(dataPairList.end(), _indexDataPairList, _indexDataPairList.begin()); } void putDataToPool(RTIIndexDataPairList& dataPairList) { - while (!dataPairList.empty()) { - // Put back into the pool - unsigned i = dataPairList.front().first; - if (_attributeData.size() <= i) { - // should not happen!!! - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!"); - dataPairList.pop_front(); - } else { - _attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(), - dataPairList, dataPairList.begin()); - } - } + _indexDataPairList.splice(_indexDataPairList.begin(), dataPairList); } struct AttributeData {