From Brede Johnansen, support for continuation records.

This commit is contained in:
Robert Osfield
2007-12-11 16:42:10 +00:00
parent ffab16ba2f
commit 32e520d5a1
7 changed files with 176 additions and 128 deletions

View File

@@ -1,7 +1,7 @@
//
// OpenFlight<68> loader for OpenSceneGraph
//
// Copyright (C) 2005-2006 Brede Johansen
// Copyright (C) 2005-2007 Brede Johansen
//
#include "DataInputStream.h"
@@ -18,92 +18,131 @@ DataInputStream::DataInputStream(std::streambuf* sb):
_byteswap = osg::getCpuByteOrder() == osg::LittleEndian;
}
int8 DataInputStream::readInt8(int8 def)
{
int8 d=def;
vread((char*)&d, sizeof(int8));
int8 d;
read((char*)&d, sizeof(int8));
if (!good())
return def;
return d;
}
uint8 DataInputStream::readUInt8(uint8 def)
{
uint8 d=def;
vread((char*)&d, sizeof(uint8));
uint8 d;
read((char*)&d, sizeof(uint8));
if (!good())
return def;
return d;
}
int16 DataInputStream::readInt16(int16 def)
{
int16 d=def;
vread((char*)&d, sizeof(int16));
if (_byteswap && good())
int16 d;
read((char*)&d, sizeof(int16));
if (!good())
return def;
if (_byteswap)
osg::swapBytes2((char *)&d);
return d;
}
uint16 DataInputStream::readUInt16(uint16 def)
{
uint16 d=def;
vread((char*)&d, sizeof(uint16));
if (_byteswap && good())
uint16 d;
read((char*)&d, sizeof(uint16));
if (!good())
return def;
if (_byteswap)
osg::swapBytes2((char *)&d);
return d;
}
int32 DataInputStream::readInt32(int32 def)
{
int32 d=def;
vread((char*)&d, sizeof(int32));
if (_byteswap && good())
int32 d;
read((char*)&d, sizeof(int32));
if (!good())
return def;
if (_byteswap)
osg::swapBytes4((char *)&d);
return d;
}
uint32 DataInputStream::readUInt32(uint32 def)
{
uint32 d=def;
vread((char*)&d, sizeof(uint32));
if (_byteswap && good())
uint32 d;
read((char*)&d, sizeof(uint32));
if (!good())
return def;
if (_byteswap)
osg::swapBytes4((char *)&d);
return d;
}
float32 DataInputStream::readFloat32(float32 def)
{
float32 d=def;
vread((char*)&d, sizeof(float32));
if (_byteswap && good())
float32 d;
read((char*)&d, sizeof(float32));
if (!good())
return def;
if (_byteswap)
osg::swapBytes4((char*)&d);
return d;
}
float64 DataInputStream::readFloat64(float64 def)
{
float64 d=def;
vread((char*)&d, sizeof(float64));
if (_byteswap && good())
float64 d;
read((char*)&d, sizeof(float64));
if (!good())
return def;
if (_byteswap)
osg::swapBytes8((char*)&d);
return d;
}
void DataInputStream::readCharArray(char* data, int size)
{
vread(data,size);
read(data,size);
}
std::string DataInputStream::readString(int size)
{
char* buf = new char[size+1];
vread(buf,size);
read(buf,size);
buf[size] = '\0';
std::string str = buf;
delete [] buf;
@@ -188,10 +227,11 @@ int16 DataInputStream::peekInt16()
std::istream& DataInputStream::forward(std::istream::off_type off)
{
return vforward(off);
//return vforward(off);
return seekg(off, std::ios_base::cur);
}
#if 0
std::istream& DataInputStream::vread(char_type *str, std::streamsize count)
{
return read(str,count);
@@ -202,4 +242,4 @@ std::istream& DataInputStream::vforward(std::istream::off_type off)
{
return seekg(off, std::ios_base::cur);
}
#endif

View File

@@ -1,13 +1,12 @@
//
// OpenFlight<68> loader for OpenSceneGraph
//
// Copyright (C) 2005-2006 Brede Johansen
// Copyright (C) 2005-2007 Brede Johansen
//
#ifndef FLT_DATAINPUTSTREAM
#define FLT_DATAINPUTSTREAM 1
//#include <iostream> // for ifstream
#include <istream>
#include <string>
#include <osg/Vec3f>
@@ -47,9 +46,6 @@ class DataInputStream : public std::istream
protected:
virtual std::istream& vread(char_type *str, std::streamsize count);
virtual std::istream& vforward(std::istream::off_type off);
bool _byteswap;
};

View File

@@ -34,10 +34,15 @@ protected:
virtual void readRecord(RecordInputStream& in, Document& document)
{
uint32 paletteSize = in.readUInt32();
in.moveToStartOfRecord();
// Enteries in vertex pool found by offset from start of this record.
const int RECORD_HEADER_SIZE = 4;
const int OFFSET = RECORD_HEADER_SIZE+sizeof(paletteSize);
std::string buffer(paletteSize,'\0');
in.read(&(*buffer.begin()),paletteSize);
in.read(&buffer[OFFSET], paletteSize-OFFSET);
// Keep a copy of the vertex pool in memory for later reference.
document.setVertexPool(new VertexPool(buffer));
}
};

View File

@@ -1,7 +1,7 @@
//
// OpenFlight loader for OpenSceneGraph
//
// Copyright (C) 2005-2006 Brede Johansen
// Copyright (C) 2005-2007 Brede Johansen
//
#include <stdexcept>
@@ -229,12 +229,81 @@ class FLTReaderWriter : public ReaderWriter
}
}
const int RECORD_HEADER_SIZE = 4;
opcode_type continuationOpcode = -1;
std::string continuationBuffer;
while (fin.good() && !document.done())
{
// read records
flt::RecordInputStream recordStream(fin.rdbuf());
while (recordStream.good() && !document.done())
// The continuation record complicates things a bit.
// Get current read position in stream.
std::istream::pos_type pos = fin.tellg();
// get opcode and size
flt::DataInputStream dataStream(fin.rdbuf());
opcode_type opcode = (opcode_type)dataStream.readUInt16();
size_type size = (size_type)dataStream.readUInt16();
// variable length record complete?
if (!continuationBuffer.empty() && opcode!=CONTINUATION_OP)
{
recordStream.readRecord(document);
// parse variable length record
std::stringbuf sb(continuationBuffer);
flt::RecordInputStream recordStream(&sb);
recordStream.readRecordBody(continuationOpcode, continuationBuffer.length(), document);
continuationOpcode = -1;
continuationBuffer.clear();
}
// variable length record use continuation buffer in case next
// record is a continuation record.
if (opcode==EXTENSION_OP ||
opcode==NAME_TABLE_OP ||
opcode==LOCAL_VERTEX_POOL_OP ||
opcode==MESH_PRIMITIVE_OP)
{
continuationOpcode = opcode;
if (size > RECORD_HEADER_SIZE)
{
// Put record in buffer.
std::string buffer((std::string::size_type)size-RECORD_HEADER_SIZE,'\0');
fin.read(&buffer[0], size-RECORD_HEADER_SIZE);
// Can't parse it until we know we have the complete record.
continuationBuffer = buffer;
}
}
else if (opcode==CONTINUATION_OP)
{
if (size > RECORD_HEADER_SIZE)
{
std::string buffer((std::string::size_type)size-RECORD_HEADER_SIZE,'\0');
fin.read(&buffer[0], size-RECORD_HEADER_SIZE);
// The record continues.
continuationBuffer.append(buffer);
}
}
else if (opcode==VERTEX_PALETTE_OP)
{
// Vertex Palette needs the file stream as it reads beyond the current record.
flt::RecordInputStream recordStream(fin.rdbuf());
recordStream.readRecordBody(opcode, size, document);
}
else // normal (fixed size) record.
{
// Put record in buffer.
std::string buffer((std::string::size_type)size,'\0');
if (size > RECORD_HEADER_SIZE)
fin.read(&buffer[0], size-RECORD_HEADER_SIZE);
// Parse buffer.
std::stringbuf sb(buffer);
flt::RecordInputStream recordStream(&sb);
recordStream.readRecordBody(opcode, size, document);
}
}

View File

@@ -1,7 +1,7 @@
//
// OpenFlight<68> loader for OpenSceneGraph
//
// Copyright (C) 2005-2006 Brede Johansen
// Copyright (C) 2005-2007 Brede Johansen
//
#include <iostream>
@@ -16,48 +16,19 @@ using namespace std;
RecordInputStream::RecordInputStream(std::streambuf* sb):
DataInputStream(sb),
_recordSize(0),
_recordOffset(0)
_recordSize(0)
{}
std::istream& RecordInputStream::vread(char_type *str, std::streamsize count)
{
if ((_recordSize>0) && (_recordOffset+count > _recordSize))
{
setstate(ios::failbit); // end-of-record (EOR)
return *this;
}
_recordOffset += count;
return DataInputStream::vread(str,count);
}
std::istream& RecordInputStream::vforward(std::istream::off_type off)
{
if ((_recordSize>0) && (_recordOffset+off > _recordSize))
{
setstate(ios::failbit); // end-of-record (EOR)
return *this;
}
_recordOffset += off;
return DataInputStream::vforward(off);
}
bool RecordInputStream::readRecord(Document& document)
{
// Get current read position in stream.
_start = tellg();
_recordOffset = 0;
opcode_type opcode = (opcode_type)readUInt16();
size_type size = (size_type)readUInt16();
// Get record header without bounds check.
_recordSize = 0; // disable boundary check
uint16 opcode = readUInt16();
int size = (int)readUInt16();
return readRecordBody(opcode, size, document);
}
bool RecordInputStream::readRecordBody(opcode_type opcode, size_type size, Document& document)
{
// Correct endian error in Creator v2.5 gallery models.
// Last pop level record in little-endian.
const uint16 LITTLE_ENDIAN_POP_LEVEL_OP = 0x0B00;
@@ -70,29 +41,12 @@ bool RecordInputStream::readRecord(Document& document)
_recordSize = size;
// Update end-of-record
_end = _start + (std::istream::pos_type)size;
#if 0
// TODO: Peek at next opcode looking for continuation record.
seekg(_end, std::ios_base::beg);
if (_istream->fail())
return false;
int16 nextOpcode = readUInt16();
seekg(_start+(std::istream::pos_type)4, std::ios_base::beg);
if (nextOpcode == CONTINUATION_OP)
{
}
#endif
// Get prototype record
Record* prototype = Registry::instance()->getPrototype((int)opcode);
if (prototype)
{
#if 0 //def _DEBUG
#if 0 // for debuging
{
for (int i=0; i<document.level(); i++)
cout << " ";
@@ -101,17 +55,11 @@ bool RecordInputStream::readRecord(Document& document)
cout << endl;
}
#endif
// Create from prototype.
osg::ref_ptr<Record> record = prototype->cloneType();
{
// Create from prototype.
osg::ref_ptr<Record> record = prototype->cloneType();
// Read record
record->read(*this,document);
}
// Clear failbit, it's used for end-of-record testing.
clear(rdstate() & ~std::ios::failbit);
// Read record
record->read(*this,document);
}
else // prototype not found
{
@@ -121,8 +69,5 @@ bool RecordInputStream::readRecord(Document& document)
Registry::instance()->addPrototype(opcode,new DummyRecord);
}
// Move to beginning of next record
seekg(_end, std::ios_base::beg);
return good();
}

View File

@@ -1,7 +1,7 @@
//
// OpenFlight<68> loader for OpenSceneGraph
//
// Copyright (C) 2005-2006 Brede Johansen
// Copyright (C) 2005-2007 Brede Johansen
//
#ifndef FLT_RECORDINPUTSTREAM_H
@@ -14,31 +14,24 @@ namespace flt {
class Document;
typedef int opcode_type;
typedef std::streamsize size_type;
class RecordInputStream : public DataInputStream
{
public:
explicit RecordInputStream(std::streambuf* sb);
bool readRecord(Document& data);
bool readRecord(Document&);
bool readRecordBody(opcode_type, size_type, Document&);
inline std::istream::pos_type getStartOfRecord() const { return _start; }
inline std::istream::pos_type getEndOfRecord() const { return _end; }
inline std::streamsize getRecordSize() const { return _end-_start; }
inline std::streamsize getRecordBodySize() const { return getRecordSize()-(std::streamsize)4; }
inline void moveToStartOfRecord() { seekg(_start /*,std::ios_base::beg*/); }
inline void setEndOfRecord(std::istream::pos_type pos) { _end=pos; }
inline std::streamsize getRecordSize() const { return _recordSize; }
inline std::streamsize getRecordBodySize() const { return _recordSize-(std::streamsize)4; }
protected:
virtual std::istream& vread(char_type *str, std::streamsize count);
virtual std::istream& vforward(std::istream::off_type off);
int _recordSize;
int _recordOffset;
std::istream::pos_type _start; // start of record
std::istream::pos_type _end; // end of record
std::streamsize _recordSize;
};
} // end namespace

View File

@@ -1,7 +1,7 @@
//
// OpenFlight<68> loader for OpenSceneGraph
//
// Copyright (C) 2005-2006 Brede Johansen
// Copyright (C) 2005-2007 Brede Johansen
//
#include "Record.h"
@@ -228,7 +228,7 @@ class AbsoluteVertex : public Record
vertex.setCoord(osg::Vec3(x,y,z) * document.unitScale());
// optional texture coordinates
if (in.tellg() < in.getEndOfRecord())
if (in.getRecordBodySize() > (4+4+4))
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(0,uv);
@@ -276,7 +276,7 @@ class ShadedVertex : public Record
vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool
// optional texture coordinates
if (in.tellg() < in.getEndOfRecord())
if (in.getRecordBodySize() > (4+4+4+1+1+2))
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(0,uv);
@@ -324,7 +324,7 @@ class NormalVertex : public Record
vertex.setColor(getColorFromPool(colorIndex, document.getColorPool())); // Color from pool
// optional texture coordinates
if (in.tellg() < in.getEndOfRecord())
if (in.getRecordBodySize() > (4+4+4+1+1+2+3*8))
{
osg::Vec2f uv = in.readVec2f();
vertex.setUV(0,uv);