759 lines
22 KiB
C++
759 lines
22 KiB
C++
//
|
|
// OpenFlight® loader for OpenSceneGraph
|
|
//
|
|
// Copyright (C) 2005-2006 Brede Johansen
|
|
//
|
|
|
|
#include <osg/Notify>
|
|
#include <osg/ShadeModel>
|
|
#include <osg/ProxyNode>
|
|
#include <osg/Sequence>
|
|
#include <osg/LOD>
|
|
#include <osg/ProxyNode>
|
|
#include <osgDB/FileUtils>
|
|
#include <osgSim/DOFTransform>
|
|
#include <osgSim/MultiSwitch>
|
|
#include "Registry.h"
|
|
#include "Document.h"
|
|
#include "RecordInputStream.h"
|
|
|
|
namespace flt {
|
|
|
|
/** Header
|
|
*/
|
|
class Header : public PrimaryRecord
|
|
{
|
|
static const unsigned int SAVE_VERTEX_NORMALS_BIT = 0x80000000u >> 0;
|
|
static const unsigned int PACKED_COLOR_MODE_BIT = 0x80000000u >> 1;
|
|
static const unsigned int CAD_VIEW_MODE_BIT = 0x80000000u >> 2;
|
|
|
|
osg::ref_ptr<osg::Group> _header;
|
|
|
|
public:
|
|
|
|
Header() {}
|
|
|
|
META_Record(Header)
|
|
|
|
META_setID(_header)
|
|
META_setComment(_header)
|
|
// META_setMatrix(_header)
|
|
META_setMultitexture(_header)
|
|
META_addChild(_header)
|
|
|
|
protected:
|
|
|
|
virtual ~Header() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
std::string id = in.readString(8);
|
|
osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl;
|
|
|
|
uint32 format = in.readUInt32();
|
|
osg::notify(osg::DEBUG_INFO) << "Format: " << format << std::endl;
|
|
document._version = format;
|
|
|
|
/*uint32 revision =*/ in.readUInt32();
|
|
|
|
std::string revisionTime = in.readString(32);
|
|
osg::notify(osg::INFO) << "Last revision: " << revisionTime << std::endl;
|
|
|
|
in.forward(4*2);
|
|
|
|
// Flight v.11 & 12 use integer coordinates
|
|
int16 multDivUnits = in.readInt16(); // Units multiplier/divisor
|
|
uint8 units = in.readUInt8(); // 0=Meters 1=Kilometers 4=Feet 5=Inches 8=Nautical miles
|
|
/*uint8 textureWhite =*/ in.readUInt8();
|
|
/*uint32 flags =*/ in.readUInt32();
|
|
|
|
if (document.getDoUnitsConversion())
|
|
document._unitScale = unitsToMeters((CoordUnits)units) / unitsToMeters(document.getDesiredUnits());
|
|
|
|
if (document._version < VERSION_13)
|
|
{
|
|
if (multDivUnits >= 0)
|
|
document._unitScale *= (double)multDivUnits;
|
|
else
|
|
document._unitScale /= (double)(-multDivUnits);
|
|
}
|
|
|
|
_header = new osg::Group;
|
|
_header->setName(id);
|
|
|
|
document.setHeaderNode(_header.get());
|
|
}
|
|
|
|
};
|
|
|
|
RegisterRecordProxy<Header> g_Header(HEADER_OP);
|
|
|
|
|
|
/** Object
|
|
*/
|
|
class Object : public PrimaryRecord
|
|
{
|
|
static const unsigned int HIDE_IN_DAYLIGHT = 0x80000000u >> 0;
|
|
static const unsigned int HIDE_AT_DUSK = 0x80000000u >> 1;
|
|
static const unsigned int HIDE_AT_NIGHT = 0x80000000u >> 2;
|
|
static const unsigned int NO_ILLUMINATION = 0x80000000u >> 3;
|
|
static const unsigned int FLAT_SHADED = 0x80000000u >> 4;
|
|
static const unsigned int SHADOW_OBJECT = 0x80000000u >> 5;
|
|
|
|
osg::ref_ptr<osg::Group> _object;
|
|
|
|
public:
|
|
|
|
Object() {}
|
|
|
|
META_Record(Object)
|
|
|
|
META_setID(_object)
|
|
META_setComment(_object)
|
|
META_setMatrix(_object)
|
|
META_setMultitexture(_object)
|
|
META_addChild(_object)
|
|
|
|
protected:
|
|
|
|
virtual ~Object() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& /*document*/)
|
|
{
|
|
std::string id = in.readString(8);
|
|
uint32 flags = in.readUInt32();
|
|
|
|
_object = new osg::Group;
|
|
_object->setName(id);
|
|
|
|
// Flat shaded?
|
|
if (flags & FLAT_SHADED)
|
|
{
|
|
static osg::ref_ptr<osg::ShadeModel> shademodel;
|
|
if (!shademodel.valid())
|
|
{
|
|
shademodel = new osg::ShadeModel;
|
|
shademodel->setMode(osg::ShadeModel::FLAT);
|
|
}
|
|
_object->getOrCreateStateSet()->setAttribute(shademodel.get());
|
|
}
|
|
|
|
if (_parent.valid())
|
|
_parent->addChild(*_object);
|
|
}
|
|
};
|
|
|
|
RegisterRecordProxy<Object> g_Object(OBJECT_OP);
|
|
|
|
|
|
/** Group
|
|
*/
|
|
class Group : public PrimaryRecord
|
|
{
|
|
static const unsigned int FORWARD_ANIM = 0x80000000u >> 1;
|
|
static const unsigned int SWING_ANIM = 0x80000000u >> 2;
|
|
static const unsigned int BOUND_BOX_FOLLOW = 0x80000000u >> 3;
|
|
static const unsigned int FREEZE_BOUND_BOX = 0x80000000u >> 4;
|
|
static const unsigned int DEFAULT_PARENT = 0x80000000u >> 5;
|
|
static const unsigned int BACKWARD_ANIM = 0x80000000u >> 6;
|
|
|
|
osg::ref_ptr<osg::Group> _group;
|
|
|
|
public:
|
|
|
|
Group() {}
|
|
|
|
META_Record(Group)
|
|
|
|
META_setID(_group)
|
|
META_setComment(_group)
|
|
META_setMatrix(_group)
|
|
META_setMultitexture(_group)
|
|
META_addChild(_group)
|
|
|
|
protected:
|
|
|
|
virtual ~Group() {}
|
|
|
|
void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
std::string id = in.readString(8);
|
|
osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl;
|
|
|
|
/*int16 relativePriority =*/ in.readInt16();
|
|
in.forward(2);
|
|
uint32 flags = in.readUInt32();
|
|
/*uint16 specialId0 =*/ in.readUInt16();
|
|
/*uint16 specialId1 =*/ in.readUInt16();
|
|
/*uint16 significance =*/ in.readUInt16();
|
|
/*int8 layer =*/ in.readInt8();
|
|
in.forward(5);
|
|
/*uint32 loopCount =*/ in.readUInt32();
|
|
/*float32 loopDuration =*/ in.readFloat32();
|
|
/*float32 lastFrameDuration =*/ in.readFloat32();
|
|
|
|
// Check for forward animation (sequence)
|
|
bool forwardAnim = (flags & FORWARD_ANIM) != 0;
|
|
|
|
// For versions prior to 15.8, the swing bit can be set independently
|
|
// of the animation bit. This implies forward animation (with swing)
|
|
if ((document.version() < VERSION_15_8) && (flags & SWING_ANIM))
|
|
forwardAnim = true;
|
|
|
|
// OpenFlight 15.8 adds backwards animations
|
|
const bool backwardAnim = ( (document.version() >= VERSION_15_8) &&
|
|
((flags & BACKWARD_ANIM) != 0) );
|
|
|
|
if (forwardAnim || backwardAnim)
|
|
{
|
|
osg::ref_ptr<osg::Sequence> sequence = new osg::Sequence;
|
|
|
|
// Regardless of forwards or backwards, animation could have swing bit set
|
|
const osg::Sequence::LoopMode loopMode = ((flags & SWING_ANIM) == 0) ?
|
|
osg::Sequence::LOOP : osg::Sequence::SWING;
|
|
|
|
if (forwardAnim)
|
|
sequence->setInterval(loopMode, 0, -1);
|
|
else
|
|
sequence->setInterval(loopMode, -1, 0);
|
|
|
|
float speed=0.1f;
|
|
sequence->setDuration(speed);
|
|
sequence->setMode(osg::Sequence::START);
|
|
|
|
_group = sequence.get();
|
|
}
|
|
else
|
|
{
|
|
_group = new osg::Group;
|
|
}
|
|
|
|
_group->setName(id);
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_group);
|
|
}
|
|
|
|
};
|
|
|
|
RegisterRecordProxy<Group> g_Group(GROUP_OP);
|
|
|
|
|
|
/** DegreeOfFreedom
|
|
*/
|
|
class DegreeOfFreedom : public PrimaryRecord
|
|
{
|
|
// Flags
|
|
static const unsigned long LIMIT_TRANSLATION_X = 0x80000000u >> 0;
|
|
static const unsigned long LIMIT_TRANSLATION_Y = 0x80000000u >> 1;
|
|
static const unsigned long LIMIT_TRANSLATION_Z = 0x80000000u >> 2;
|
|
static const unsigned long LIMIT_PITCH = 0x80000000u >> 3;
|
|
static const unsigned long LIMIT_ROLL = 0x80000000u >> 4;
|
|
static const unsigned long LIMIT_YAW = 0x80000000u >> 5;
|
|
static const unsigned long LIMIT_SCALE_X = 0x80000000u >> 6;
|
|
static const unsigned long LIMIT_SCALE_Y = 0x80000000u >> 7;
|
|
static const unsigned long LIMIT_SCALE_Z = 0x80000000u >> 8;
|
|
|
|
struct Range
|
|
{
|
|
float64 min; // Minimum value with respect to the local coord system
|
|
float64 max; // Maximum value with respect to the local coordsystem
|
|
float64 current; // Current value with respect to the local coord system
|
|
float64 increment; // Increment
|
|
};
|
|
|
|
osg::ref_ptr<osgSim::DOFTransform> _dof;
|
|
|
|
public:
|
|
|
|
DegreeOfFreedom():
|
|
_dof(new osgSim::DOFTransform) {}
|
|
|
|
META_Record(DegreeOfFreedom)
|
|
|
|
META_setID(_dof)
|
|
META_setComment(_dof)
|
|
META_setMatrix(_dof)
|
|
META_setMultitexture(_dof)
|
|
META_addChild(_dof)
|
|
|
|
protected:
|
|
|
|
virtual ~DegreeOfFreedom() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
std::string id = in.readString(8);
|
|
in.forward(4); // Reserved
|
|
osg::Vec3d localOrigin = in.readVec3d();
|
|
osg::Vec3d pointOnXAxis = in.readVec3d();
|
|
osg::Vec3d pointInXYPlane = in.readVec3d();
|
|
Range rangeZ = readRange(in); // Legal z values with respect to the local coord system
|
|
Range rangeY = readRange(in); // Legal y values with respect to the local coord system
|
|
Range rangeX = readRange(in); // Legal x values with respect to the local coord system
|
|
Range rangePitch = readRange(in); // Legal pitch values (rotation about the x-axis)
|
|
Range rangeRoll = readRange(in); // Legal roll values( rotation about the y-axis)
|
|
Range rangeYaw = readRange(in); // Legal yaw values (rotation about the z-axis)
|
|
Range rangeScaleZ = readRange(in); // Legal z scale values (about local origin)
|
|
Range rangeScaleY = readRange(in); // Legal y scale values about local origin)
|
|
Range rangeScaleX = readRange(in); // Legal x scale values (about local origin)
|
|
uint32 flags = in.readUInt32(); // Flags, bits from left to right (see OF doc)
|
|
|
|
// out of range check, required for racecar.flt (Creator Gallery)
|
|
if (!valid(localOrigin))
|
|
localOrigin = osg::Vec3d(0,0,0);
|
|
if (!valid(pointOnXAxis))
|
|
pointOnXAxis = osg::X_AXIS;
|
|
if (!valid(pointInXYPlane))
|
|
pointInXYPlane = osg::Y_AXIS;
|
|
|
|
_dof->setName(id);
|
|
|
|
//tranlsations:
|
|
_dof->setMinTranslate(osg::Vec3(rangeX.min,rangeY.min,rangeZ.min)*document.unitScale());
|
|
_dof->setMaxTranslate(osg::Vec3(rangeX.max,rangeY.max,rangeZ.max)*document.unitScale());
|
|
_dof->setCurrentTranslate(osg::Vec3(rangeX.current,rangeY.current,rangeZ.current)*document.unitScale());
|
|
_dof->setIncrementTranslate(osg::Vec3(rangeX.increment,rangeY.increment,rangeZ.increment)*document.unitScale());
|
|
|
|
//rotations:
|
|
_dof->setMinHPR(osg::Vec3(osg::inDegrees(rangeYaw.min),osg::inDegrees(rangePitch.min),osg::inDegrees(rangeRoll.min)));
|
|
_dof->setMaxHPR(osg::Vec3(osg::inDegrees(rangeYaw.max),osg::inDegrees(rangePitch.max),osg::inDegrees(rangeRoll.max)));
|
|
_dof->setCurrentHPR(osg::Vec3(osg::inDegrees(rangeYaw.current),osg::inDegrees(rangePitch.current),osg::inDegrees(rangeRoll.current)));
|
|
_dof->setIncrementHPR(osg::Vec3(osg::inDegrees(rangeYaw.increment),osg::inDegrees(rangePitch.increment),osg::inDegrees(rangeRoll.increment)));
|
|
|
|
//scales:
|
|
_dof->setMinScale(osg::Vec3(rangeScaleX.min,rangeScaleY.min,rangeScaleZ.min));
|
|
_dof->setMaxScale(osg::Vec3(rangeScaleX.max,rangeScaleY.max,rangeScaleZ.max));
|
|
_dof->setCurrentScale(osg::Vec3(rangeScaleX.current,rangeScaleY.current,rangeScaleZ.current));
|
|
_dof->setIncrementScale(osg::Vec3(rangeScaleX.increment,rangeScaleY.increment,rangeScaleZ.increment));
|
|
|
|
// compute axis.
|
|
osg::Vec3 xAxis = pointOnXAxis - localOrigin;
|
|
osg::Vec3 xyPlaneVector = pointInXYPlane - localOrigin;
|
|
osg::Vec3 zAxis = xAxis ^ xyPlaneVector;
|
|
osg::Vec3 yAxis = zAxis ^ xAxis;
|
|
|
|
// normalize
|
|
xAxis.normalize();
|
|
yAxis.normalize();
|
|
zAxis.normalize();
|
|
|
|
// scale origin
|
|
osg::Vec3 origin = localOrigin * document.unitScale();
|
|
|
|
// create putmatrix
|
|
osg::Matrix inv_putmat(xAxis.x(), xAxis.y(), xAxis.z(), 0.0,
|
|
yAxis.x(), yAxis.y(), yAxis.z(), 0.0,
|
|
zAxis.x(), zAxis.y(), zAxis.z(), 0.0,
|
|
origin.x(), origin.y(), origin.z(), 1.0);
|
|
|
|
_dof->setInversePutMatrix(inv_putmat);
|
|
_dof->setPutMatrix(osg::Matrix::inverse(inv_putmat));
|
|
|
|
_dof->setLimitationFlags(flags);
|
|
_dof->setAnimationOn(document.getDefaultDOFAnimationState());
|
|
// _dof->setHPRMultOrder(osgSim::DOFTransform::HPR);
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_dof);
|
|
}
|
|
|
|
Range readRange(RecordInputStream& in) const
|
|
{
|
|
Range range;
|
|
range.min = in.readFloat64();
|
|
range.max = in.readFloat64();
|
|
range.current = in.readFloat64();
|
|
range.increment = in.readFloat64();
|
|
|
|
// Extend valid range (See Creator help on DOF).
|
|
if (range.current < range.min) range.min = range.current;
|
|
if (range.current > range.max) range.max = range.current;
|
|
|
|
const float64 epsilon = 1.0e-7;
|
|
if (fabs(range.max-range.min) < epsilon)
|
|
range.increment = 0;
|
|
|
|
return range;
|
|
}
|
|
|
|
bool valid(const osg::Vec3d& v) const
|
|
{
|
|
const osg::Vec3d bad(-1.0e8,-1.0e8,-1.0e8);
|
|
const float64 epsilon = 1.0e-7;
|
|
|
|
return (fabs(v.x()-bad.x()) > epsilon) ||
|
|
(fabs(v.y()-bad.y()) > epsilon) ||
|
|
(fabs(v.z()-bad.z()) > epsilon);
|
|
}
|
|
};
|
|
|
|
RegisterRecordProxy<DegreeOfFreedom> g_DegreeOfFreedom(DOF_OP);
|
|
|
|
|
|
/** LevelOfDetail - To recreate the LevelOfDetail record in OSG we have to create a LOD node with one Group node under it.
|
|
* OSG representation Children of the LevelOfDetail record will be added to
|
|
*/
|
|
class LevelOfDetail : public PrimaryRecord
|
|
{
|
|
osg::ref_ptr<osg::LOD> _lod;
|
|
osg::ref_ptr<osg::Group> _impChild0;
|
|
|
|
public:
|
|
|
|
LevelOfDetail() {}
|
|
|
|
META_Record(LevelOfDetail)
|
|
|
|
META_setID(_lod)
|
|
META_setComment(_lod)
|
|
META_setMatrix(_lod)
|
|
META_setMultitexture(_lod)
|
|
META_addChild(_impChild0)
|
|
|
|
protected:
|
|
|
|
virtual ~LevelOfDetail() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
std::string id = in.readString(8);
|
|
in.forward(4);
|
|
float64 switchInDistance = in.readFloat64();
|
|
float64 switchOutDistance = in.readFloat64();
|
|
/*int16 specialEffectID1 =*/ in.readInt16();
|
|
/*int16 specialEffectID2 =*/ in.readInt16();
|
|
/*uint32 flags =*/ in.readUInt32();
|
|
osg::Vec3d center = in.readVec3d();
|
|
|
|
_lod = new osg::LOD;
|
|
_lod->setName(id);
|
|
_lod->setCenter(center*document.unitScale());
|
|
|
|
_impChild0 = new osg::Group;
|
|
_impChild0->setName("LOD child0");
|
|
|
|
// Add child to lod.
|
|
_lod->addChild(_impChild0.get(),
|
|
(float)switchOutDistance * document.unitScale(),
|
|
(float)switchInDistance * document.unitScale());
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_lod);
|
|
}
|
|
|
|
};
|
|
|
|
RegisterRecordProxy<LevelOfDetail> g_LevelOfDetail(LOD_OP);
|
|
|
|
|
|
/** OldLevelOfDetail
|
|
*/
|
|
class OldLevelOfDetail : public PrimaryRecord
|
|
{
|
|
osg::ref_ptr<osg::LOD> _lod;
|
|
osg::ref_ptr<osg::Group> _impChild0;
|
|
|
|
public:
|
|
|
|
OldLevelOfDetail() {}
|
|
|
|
META_Record(OldLevelOfDetail)
|
|
|
|
META_setID(_lod)
|
|
META_setComment(_lod)
|
|
META_setMatrix(_lod)
|
|
META_setMultitexture(_lod)
|
|
META_addChild(_impChild0)
|
|
|
|
protected:
|
|
|
|
virtual ~OldLevelOfDetail() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
std::string id = in.readString(8);
|
|
uint32 switchInDistance = in.readUInt32();
|
|
uint32 switchOutDistance = in.readUInt32();
|
|
/*int16 specialEffectID1 =*/ in.readInt16();
|
|
/*int16 specialEffectID2 =*/ in.readInt16();
|
|
/*uint32 flags =*/ in.readUInt32();
|
|
|
|
osg::Vec3 center;
|
|
center.x() = (float)in.readInt32();
|
|
center.y() = (float)in.readInt32();
|
|
center.z() = (float)in.readInt32();
|
|
|
|
_lod = new osg::LOD;
|
|
_lod->setName(id);
|
|
_lod->setCenter(center*document.unitScale());
|
|
_lod->setRange(0, (float)switchOutDistance * document.unitScale(),
|
|
(float)switchInDistance * document.unitScale());
|
|
|
|
// Add child to lod.
|
|
_impChild0 = new osg::Group;
|
|
_lod->addChild(_impChild0.get());
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_lod);
|
|
}
|
|
|
|
};
|
|
|
|
RegisterRecordProxy<OldLevelOfDetail> g_OldLevelOfDetail(OLD_LOD_OP);
|
|
|
|
|
|
/** Switch
|
|
*/
|
|
class Switch : public PrimaryRecord
|
|
{
|
|
uint32 _currentMask;
|
|
uint32 _numberOfMasks;
|
|
uint32 _wordsInMask;
|
|
std::vector<uint32> _masks;
|
|
|
|
osg::ref_ptr<osgSim::MultiSwitch> _multiSwitch;
|
|
|
|
public:
|
|
|
|
Switch() {}
|
|
|
|
META_Record(Switch)
|
|
|
|
META_setID(_multiSwitch)
|
|
META_setComment(_multiSwitch)
|
|
META_setMatrix(_multiSwitch)
|
|
META_setMultitexture(_multiSwitch)
|
|
|
|
virtual void addChild(osg::Node& child)
|
|
{
|
|
if (_multiSwitch.valid())
|
|
{
|
|
unsigned int nChild = _multiSwitch->getNumChildren();
|
|
for (unsigned int nMask=0; nMask<_numberOfMasks; ++nMask)
|
|
{
|
|
// test if this child is active in the current mask (itMask)
|
|
unsigned int nMaskBit = nChild % 32;
|
|
unsigned int nMaskWord = nMask * _wordsInMask + nChild / 32;
|
|
_multiSwitch->setValue(nMask, nChild, (_masks[nMaskWord] & (uint32(1) << nMaskBit))!=0 );
|
|
}
|
|
|
|
_multiSwitch->addChild(&child);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual ~Switch() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& /*document*/)
|
|
{
|
|
std::string id = in.readString(8);
|
|
in.forward(4);
|
|
_currentMask = in.readUInt32();
|
|
_numberOfMasks = in.readUInt32();
|
|
_wordsInMask = in.readUInt32();
|
|
|
|
_multiSwitch = new osgSim::MultiSwitch;
|
|
_multiSwitch->setName(id);
|
|
|
|
/* Example:
|
|
| word #0 || word #1 || word #2 | <- Mask #0
|
|
| word #0 || word #1 || word #2 | <- Mask #1
|
|
In this example numberOfMasks=2 and wordsInMask=3, currentMask can be 0 or 1.
|
|
*/
|
|
|
|
for (unsigned int n=0; n<_numberOfMasks*_wordsInMask; n++)
|
|
{
|
|
uint32 maskWord = in.readUInt32();
|
|
_masks.push_back(maskWord);
|
|
}
|
|
|
|
_multiSwitch->setActiveSwitchSet(_currentMask);
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_multiSwitch);
|
|
}
|
|
};
|
|
|
|
RegisterRecordProxy<Switch> g_Switch(SWITCH_OP);
|
|
|
|
|
|
/** ExternalReference
|
|
*/
|
|
class ExternalReference : public PrimaryRecord
|
|
{
|
|
osg::ref_ptr<osg::ProxyNode> _external;
|
|
|
|
public:
|
|
|
|
ExternalReference() {}
|
|
|
|
META_Record(ExternalReference)
|
|
|
|
META_setID(_external)
|
|
META_setComment(_external)
|
|
META_setMatrix(_external)
|
|
META_setMultitexture(_external)
|
|
META_addChild(_external)
|
|
|
|
protected:
|
|
|
|
virtual ~ExternalReference() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& /*document*/)
|
|
{
|
|
std::string strFile = in.readString(200);
|
|
|
|
_external = new osg::ProxyNode;
|
|
_external->setCenterMode(osg::ProxyNode::USE_BOUNDING_SPHERE_CENTER);
|
|
_external->setFileName(0,strFile);
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_external);
|
|
}
|
|
|
|
};
|
|
|
|
RegisterRecordProxy<ExternalReference> g_ExternalReference(EXTERNAL_REFERENCE_OP);
|
|
|
|
|
|
/** InstanceDefinition
|
|
*/
|
|
class InstanceDefinition : public PrimaryRecord
|
|
{
|
|
osg::ref_ptr<osg::Group> _instanceDefinition;
|
|
|
|
public:
|
|
|
|
InstanceDefinition() {}
|
|
|
|
META_Record(InstanceDefinition)
|
|
|
|
META_setID(_instanceDefinition)
|
|
META_setComment(_instanceDefinition)
|
|
META_setMultitexture(_instanceDefinition)
|
|
META_addChild(_instanceDefinition)
|
|
|
|
virtual void setMatrix(osg::Matrix& matrix)
|
|
{
|
|
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform(matrix);
|
|
transform->setDataVariance(osg::Object::STATIC);
|
|
transform->addChild(_instanceDefinition.get());
|
|
_instanceDefinition = transform.get();
|
|
}
|
|
|
|
protected:
|
|
|
|
virtual ~InstanceDefinition() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
in.forward(2);
|
|
uint16 number = in.readUInt16();
|
|
|
|
_instanceDefinition = new osg::Group;
|
|
|
|
// Add to instance definition table.
|
|
document.setInstanceDefinition(number,_instanceDefinition.get());
|
|
}
|
|
};
|
|
|
|
RegisterRecordProxy<InstanceDefinition> g_InstanceDefinition(INSTANCE_DEFINITION_OP);
|
|
|
|
|
|
/** InstanceReference
|
|
* The InstanceReference is a leaf record.
|
|
*/
|
|
class InstanceReference : public PrimaryRecord
|
|
{
|
|
public:
|
|
|
|
InstanceReference() {}
|
|
|
|
META_Record(InstanceReference)
|
|
|
|
protected:
|
|
|
|
virtual ~InstanceReference() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& document)
|
|
{
|
|
in.forward(2);
|
|
uint16 number = in.readUInt16();
|
|
|
|
// Get definition.
|
|
osg::Node* instance = document.getInstanceDefinition(number);
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*instance);
|
|
}
|
|
};
|
|
|
|
RegisterRecordProxy<InstanceReference> g_InstanceReference(INSTANCE_REFERENCE_OP);
|
|
|
|
|
|
/** Extension
|
|
*/
|
|
class Extension : public PrimaryRecord
|
|
{
|
|
osg::ref_ptr<osg::Group> _extension;
|
|
|
|
public:
|
|
|
|
Extension() {}
|
|
|
|
META_Record(Extension)
|
|
|
|
META_setID(_extension)
|
|
META_setComment(_extension)
|
|
META_setMatrix(_extension)
|
|
META_setMultitexture(_extension)
|
|
META_addChild(_extension)
|
|
|
|
protected:
|
|
|
|
virtual ~Extension() {}
|
|
|
|
virtual void readRecord(RecordInputStream& in, Document& /*document*/)
|
|
{
|
|
std::string id = in.readString(8);
|
|
std::string siteId = in.readString(8);
|
|
in.forward(1);
|
|
|
|
_extension = new osg::Group;
|
|
_extension->setName(id);
|
|
|
|
// Add this implementation to parent implementation.
|
|
if (_parent.valid())
|
|
_parent->addChild(*_extension);
|
|
}
|
|
};
|
|
|
|
RegisterRecordProxy<Extension> g_Extension(EXTENSION_OP);
|
|
|
|
|
|
} // end namespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|