diff --git a/src/osgPlugins/flt/Input.cpp b/src/osgPlugins/flt/Input.cpp index 3e281c797..456680a3b 100644 --- a/src/osgPlugins/flt/Input.cpp +++ b/src/osgPlugins/flt/Input.cpp @@ -127,6 +127,20 @@ bool FileInput::_readBody(SRecHeader* pData) } +bool FileInput::_readContinuedBody(char* pData, int nBytes) +{ + // Read record body + if (nBytes > 0) + { + int nItemsRead = _read(pData, nBytes); + if (nItemsRead != 1) + return false; + } + + return true; +} + + SRecHeader* FileInput::readRecord() { SRecHeader hdr; @@ -151,6 +165,56 @@ SRecHeader* FileInput::readRecord() if (!_readBody(pData)) return NULL; + + // Add support for OpenFlight 15.7 (1570) continuation records + // + + // Record and FaceRecord both want to rewindLast, so save and restore + // the current file offset. + const long lRecOffsetSave = _lRecOffset; + + int nTotalLen = hdr.length(); + // From spec, in practice only these three records can be continued: + bool bContinuationPossible = ( + (hdr.opcode()==COLOR_NAME_PALETTE_OP) || + (hdr.opcode()==EXTENSION_OP) || + (hdr.opcode()==LOCAL_VERTEX_POOL_OP) ); + + while (bContinuationPossible) + { + SRecHeader hdr2; + if (_readHeader( &hdr2 )) + { + if (hdr2.opcode() == CONTINUATION_OP) + { + int nNewChunkLen = hdr2.length() - 4; + size_t nNewLen = nTotalLen + nNewChunkLen; + pData = (SRecHeader*)::realloc( (void*)pData, nNewLen ); + if (pData == NULL) + return NULL; + + if (!_readContinuedBody( ((char*)pData) + nTotalLen, nNewChunkLen )) + return NULL; + nTotalLen = (int)nNewLen; + } + else + { + // Not a continuation record. Rewind, then exit loop. + rewindLast(); + bContinuationPossible = false; + } + } + else + // Probably EOF + bContinuationPossible = false; + } + + _lRecOffset = lRecOffsetSave; + + // + // END support for continuation records + + return pData; } diff --git a/src/osgPlugins/flt/Input.h b/src/osgPlugins/flt/Input.h index 394212b7a..dba1975aa 100644 --- a/src/osgPlugins/flt/Input.h +++ b/src/osgPlugins/flt/Input.h @@ -45,6 +45,7 @@ class Input virtual bool _readHeader(SRecHeader* pHdr) = 0; virtual bool _readBody(SRecHeader* pData) = 0; + virtual bool _readContinuedBody(char* pData, int nBytes) = 0; }; @@ -67,6 +68,7 @@ class FileInput : public Input private: virtual bool _readHeader(SRecHeader* pHdr); virtual bool _readBody(SRecHeader* pData); + virtual bool _readContinuedBody(char* pData, int nBytes); void _init(); size_t _read(void *buffer, size_t size); @@ -95,6 +97,7 @@ class MemInput : public Input private: virtual bool _readHeader(SRecHeader* pHdr); virtual bool _readBody(SRecHeader* pData); + virtual bool _readContinuedBody(char* pData, int nBytes); void _init(); size_t _read(void *buffer, size_t size); diff --git a/src/osgPlugins/flt/LocalVertexPoolRecord.cpp b/src/osgPlugins/flt/LocalVertexPoolRecord.cpp index f30396c93..b8c508331 100644 --- a/src/osgPlugins/flt/LocalVertexPoolRecord.cpp +++ b/src/osgPlugins/flt/LocalVertexPoolRecord.cpp @@ -34,7 +34,9 @@ using namespace flt; RegisterRecordProxy g_LocalVertexPoolProxy; LocalVertexPoolRecord *_current = NULL; -LocalVertexPoolRecord::LocalVertexPoolRecord() : AncillaryRecord() +LocalVertexPoolRecord::LocalVertexPoolRecord() + : AncillaryRecord(), + _vertexSizeBytesCache(0) { } @@ -72,22 +74,16 @@ char *LocalVertexPoolRecord::_getStartOfAttribute ( const uint32 &whichVertex, c // Get pointer to start of vertex data. char *startOfVertices = (char *) this->_getStartOfVertices(); - // The size of all the vertex information is the size of the entire record - // minus the size of the record's header. - size_t sizeOfAllVertices = _pData->_wLength - sizeof ( SLocalVertexPool ); - // The number of vertices. - uint32 numVertices = this->getNumVertices(); + //uint32 numVertices = this->getNumVertices(); - // The size of each individual vertex is the size of all of them divided by - // how many there are. - size_t sizeOfVertex = sizeOfAllVertices / numVertices; + // NOTE This function formerly computed sizeOfVertex by taking the record length and dividing + // by the number of vertices. This is wrong in 15.7 and beyond, as the record could + // exceed 65535 bytes and be continued, in which case the "original" record length + // field does not contain the actual length of the data. - // If we're doing the math right (and the record data is good) then there - // should not be a remainder when doing the integer division above. - assert ( 0 == ( sizeOfAllVertices % numVertices ) ); - assert ( 0 == ( sizeOfAllVertices % sizeOfVertex ) ); - assert ( sizeOfAllVertices == sizeOfVertex * numVertices ); + // The size of each individual vertex depends on its attributes, and is cached. + size_t sizeOfVertex = this->_getVertexSizeBytes(); // Set the start of the desired vertex's data. char *startOfAttribute = &startOfVertices[whichVertex * sizeOfVertex]; @@ -95,13 +91,6 @@ char *LocalVertexPoolRecord::_getStartOfAttribute ( const uint32 &whichVertex, c // Now adjust for the offset within this vertex. startOfAttribute += offset; - // Should be true. It means that the address we are returning should not be - // greater than the start of the last vertex's attribute. - assert ( ( ( (uint32) startOfAttribute ) - ( (uint32) startOfVertices ) ) <= ( sizeOfAllVertices - sizeOfVertex + offset ) ); - - // Double check, make sure we are not off the end of this record. - assert ( ( ( (uint32) startOfAttribute ) - ( (uint32) startOfVertices ) ) < sizeOfAllVertices ); - // Return the pointer. return startOfAttribute; } @@ -377,7 +366,10 @@ void LocalVertexPoolRecord::endian() // Should be true. It means that we walked the pointer "vertex" to the // end of the record, but not past it. - assert ( pool->RecHeader._wLength == ( (uint16) ( ( ( (uint32) vertex ) - ( (uint32) pool ) ) ) ) ); + // If equal, vertex pool record was not continued. + // If 16bit record length is less than length of vertex pool, then the original vertex + // pool record was continued with one or more CONTINUATION_OP records. + assert ( pool->RecHeader._wLength <= ( ( (uint32) vertex ) - ( (uint32) pool ) ) ); } @@ -483,6 +475,55 @@ void LocalVertexPoolRecord::_initAttributeOffsets() } +/////////////////////////////////////////////////////////////////////////////// +// +// Compute the size of each vertex based on its attributes. Cache the +// result for later reference. +// +/////////////////////////////////////////////////////////////////////////////// + +int LocalVertexPoolRecord::_getVertexSizeBytes() const +{ + if (_vertexSizeBytesCache == 0) + { + if ( hasAttribute ( POSITION ) ) + _vertexSizeBytesCache += SIZE_POSITION; + + if ( hasAttribute ( COLOR_INDEX ) || hasAttribute ( RGB_COLOR ) ) + _vertexSizeBytesCache += SIZE_COLOR; + + if ( hasAttribute ( NORMAL ) ) + _vertexSizeBytesCache += SIZE_NORMAL; + + if ( hasAttribute ( BASE_UV ) ) + _vertexSizeBytesCache += SIZE_BASE_UV; + + if ( hasAttribute ( UV_1 ) ) + _vertexSizeBytesCache += SIZE_UV_1; + + if ( hasAttribute ( UV_2 ) ) + _vertexSizeBytesCache += SIZE_UV_2; + + if ( hasAttribute ( UV_3 ) ) + _vertexSizeBytesCache += SIZE_UV_3; + + if ( hasAttribute ( UV_4 ) ) + _vertexSizeBytesCache += SIZE_UV_4; + + if ( hasAttribute ( UV_5 ) ) + _vertexSizeBytesCache += SIZE_UV_5; + + if ( hasAttribute ( UV_6 ) ) + _vertexSizeBytesCache += SIZE_UV_6; + + if ( hasAttribute ( UV_7 ) ) + _vertexSizeBytesCache += SIZE_UV_7; + } + + return _vertexSizeBytesCache; +} + + /////////////////////////////////////////////////////////////////////////////// // // This is called after the record is read. diff --git a/src/osgPlugins/flt/LocalVertexPoolRecord.h b/src/osgPlugins/flt/LocalVertexPoolRecord.h index 7c48aee52..7fc58d323 100644 --- a/src/osgPlugins/flt/LocalVertexPoolRecord.h +++ b/src/osgPlugins/flt/LocalVertexPoolRecord.h @@ -33,6 +33,7 @@ public: POSITION = 0x80000000, // Has Position - indicates that each vertex in the list includes x, y, and z coordinates (three double-precision floating point values) COLOR_INDEX = 0x40000000, // Has Color Index- indicates that each vertex in the list includes a color value that is a color table index (one integer value) RGB_COLOR = 0x20000000, // Has RGB Color - indicates that each vertex in the list includes a color value that is a packed RGB color value (one integer value) NOTE: Bits 2 and 3 are mutually exclusive - a vertex can have either a color index or an RGB color value or neither, but cannot have both a color index and an RGB value. + // In 15.8, has RGBA color NORMAL = 0x10000000, // Has Normal - indicates that each vertex in the list includes a normal (three single-precision floating point values) BASE_UV = 0x08000000, // Has Base UV - indicates that each vertex in the list includes uv texture coordinates for the base texture (two single-precision floating point values) UV_1 = 0x04000000, // Has UV 1 - indicates that each vertex in the list includes uv texture coordinates for layer 1 (two single-precision floating point values) @@ -87,6 +88,9 @@ protected: char * _getStartOfAttribute ( const uint32 &whichVertex, const uint32 &attributeOffset ) const; void _initAttributeOffsets(); + + int _getVertexSizeBytes() const; + mutable int _vertexSizeBytesCache; }; diff --git a/src/osgPlugins/flt/opcodes.h b/src/osgPlugins/flt/opcodes.h index fa6bdc515..60fc9f70f 100644 --- a/src/osgPlugins/flt/opcodes.h +++ b/src/osgPlugins/flt/opcodes.h @@ -10,12 +10,8 @@ #define HEADER_OP 1 #define GROUP_OP 2 -#define OLD_LOD_OP 3 #define OBJECT_OP 4 #define FACE_OP 5 -#define OLD_VERTEX_OP 7 -#define OLD_VERTEX_COLOR_OP 8 -#define OLD_VERTEX_COLOR_NORMAL_OP 9 #define PUSH_LEVEL_OP 10 #define POP_LEVEL_OP 11 #define DOF_OP 14 @@ -23,24 +19,20 @@ #define POP_SUBFACE_OP 20 #define PUSH_EXTENSION_OP 21 #define POP_EXTENSION_OP 22 +#define CONTINUATION_OP 23 // ignored #define COMMENT_OP 31 #define COLOR_PALETTE_OP 32 #define LONG_ID_OP 33 -/* -Ignore 40-48 -#define OLD_TRANSLATE_OP 44 -*/ #define MATRIX_OP 49 #define VECTOR_OP 50 #define MULTI_TEXTURE_OP 52 #define UV_LIST_OP 53 -#define BSP_OP 55 -#define REPLICATE_OP 60 +#define BSP_OP 55 // ignored +#define REPLICATE_OP 60 // ignored #define INSTANCE_REFERENCE_OP 61 #define INSTANCE_DEFINITION_OP 62 #define EXTERNAL_REFERENCE_OP 63 #define TEXTURE_PALETTE_OP 64 -#define OLD_MATERIAL_PALETTE_OP 66 #define VERTEX_PALETTE_OP 67 #define VERTEX_C_OP 68 #define VERTEX_CN_OP 69 @@ -49,27 +41,28 @@ Ignore 40-48 #define VERTEX_LIST_OP 72 #define LOD_OP 73 #define BOUNDING_BOX_OP 74 -/* -Ignore 76-82 #define ROTATE_ABOUT_EDGE_OP 76 #define TRANSLATE_OP 78 #define SCALE_OP 79 #define ROTATE_ABOUT_POINT_OP 80 #define ROTATE_SCALE_TO_POINT_OP 81 #define PUT_TRANSFORM_OP 82 -*/ -#define EYEPOINT_TRACKPLANE_OP 83 +#define EYEPOINT_TRACKPLANE_OP 83 // ignored #define MESH_OP 84 #define LOCAL_VERTEX_POOL_OP 85 #define MESH_PRIMITIVE_OP 86 #define ROAD_SEGMENT_OP 87 -#define ROAD_ZONE_OP 88 +#define ROAD_ZONE_OP 88 // ignored #define MORPH_VERTEX_LIST_OP 89 -#define LINKAGE_PALETTE_OP 90 +#define LINKAGE_PALETTE_OP 90 // ignored +#define SOUND_OP 91 // ignored #define ROAD_PATH_OP 92 -#define SOUND_PALETTE_OP 93 +#define SOUND_PALETTE_OP 93 // ignored #define GENERAL_MATRIX_OP 94 +#define TEXT_OP 95 // ignored #define SWITCH_OP 96 +#define LINE_STYLE_PALETTE_OP 97 // ignored +#define CLIP_REGION_OP 98 // ignored #define EXTENSION_OP 100 #define LIGHT_SOURCE_OP 101 #define LIGHT_SOURCE_PALETTE_OP 102 @@ -80,11 +73,46 @@ Ignore 76-82 #define LIGHT_POINT_OP 111 #define TEXTURE_MAPPING_PALETTE_OP 112 #define MATERIAL_PALETTE_OP 113 -#define COLOR_NAME_PALETTE_OP 114 -#define CAT_OP 115 -#define CAT_DATA_OP 116 -#define RESERVED_OP 124 +#define COLOR_NAME_PALETTE_OP 114 // ignored +#define CAT_OP 115 // ignored +#define CAT_DATA_OP 116 // ignored +#define PUSH_ATTRIBUTE_OP 122 // ignored +#define POP_ATTRIBUTE_OP 123 // ignored +#define CURVE_OP 126 // ignored #define ROAD_CONSTRUCTION_OP 127 +#define LIGHT_PT_APPEARANCE_PALETTE_OP 128 // ignored +#define LIGHT_PT_ANIMATION_PALETTE_OP 129 // ignored +#define INDEXED_LIGHT_PT_OP 130 // ignored +#define LIGHT_PT_SYSTEM_OP 131 // ignored +#define INDEXED_STRING_OP 132 // ignored + + +// Obsolete opcodes as of 15.8 +#define OBS_VERTEX_WITH_ID_OP 6 +#define OBS_TRANSLATE_OP_0 12 +#define OBS_DOF_OP 13 +#define OBS_INSTANCE_REF_OP 16 +#define OBS_INSTANCE_DEF_OP 17 +#define OBS_TRANSLATE_OP_1 40 +#define OBS_ROTATE_POINT_OP_0 41 +#define OBS_ROTATE_EDGE_OP 42 +#define OBS_SCALE_OP_0 43 +#define OBS_SCALE_OP_1 45 +#define OBS_ROTATE_POINT_OP_1 46 +#define OBS_ROTATE_SCALE_POINT_OP 47 +#define OBS_PUT_OP 48 +#define OBS_EYEPOINT_PALETTE_OP 65 +#define OBS_SCALE_OP_2 77 + + +// Obsolete, but still referenced (possibly supported) by this loader +#define OLD_LOD_OP 3 +#define OLD_VERTEX_OP 7 +#define OLD_VERTEX_COLOR_OP 8 +#define OLD_VERTEX_COLOR_NORMAL_OP 9 +#define OLD_TRANSLATE_OP 44 +#define OLD_MATERIAL_PALETTE_OP 66 + #endif // __FLT_OPCODE_H