From Paul Marz : "Input.h, Input.cpp -- Here's where support for reading the continuation

record goes. I added a new function to read a continued record body. I added
code in the existing ReadRecord routine to peek ahead for a CONTINUATION_OP
if the current record could possibly be continued.

opcodes.h -- Besides adding the opcode for CONTINUATION_OP, I also added new
15.8 opcodes. I labeled opcodes as "ignored" if I could easily discern that
our loader wasn't doing anything with them. For historical reasons, I added
all obsolete opcodes, prefixed with "OBS_".

LocalVertexPoolRecord.h, LocalVertexPoolRecord.cpp -- This is one of three
types of records that can be continued with a CONTINUATION_OP record. I
removed all invalid assertions that assumed the record length would always
be less than 65535. I replaced the "vertex size" calculation with a more
efficient method based on caching the size from attribute bits, rather than
taking the length of the record and dividing it by numVerts (which would
have been incorrect if the record had been continued)."
This commit is contained in:
Robert Osfield
2004-03-06 15:03:55 +00:00
parent c0f062f41f
commit 8d25f0766a
5 changed files with 184 additions and 44 deletions

View File

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

View File

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

View File

@@ -34,7 +34,9 @@ using namespace flt;
RegisterRecordProxy<LocalVertexPoolRecord> 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.

View File

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

View File

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