From Brede Johnansen, support for continuation records.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user