Hi Robert -- The attached preserves OpenFlight Object record data as
UserData in the osg::Group corresponding to the Object record.
The files are:
include/osgSim/ObjectRecordData -- The new class. Derives from Object to
support .osg IO.
src/osgPlugins/OpenFlight/PrimaryRecords.cpp -- Reads data into that
class.
src/osgPlugins/osgSim/IO_ObjectRecordData.cpp -- .osg IO support.
I know we had discussed deriving the new class from osg::Referenced, but I
couldn't see a way to support .osg IO without deriving it from osg::Object.
I've tested this with my (under development) FLT exporter and can preserve
the Object record data in round trips between FLT and OSG.
Feedback welcome,
Paul Martz
Skew Matrix Software LLC
http://www.skew-matrix.com <http://www.skew-matrix.com/>
303 859 9466
ObjectRecordData
Description: Binary data
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */
//
// OpenFlight® loader for OpenSceneGraph
//
// Copyright (C) 2005-2007 Brede Johansen
//
#include <assert.h>
#include <typeinfo>
#include <osg/Notify>
#include <osg/ShadeModel>
#include <osg/ProxyNode>
#include <osg/Sequence>
#include <osg/LOD>
#include <osg/ProxyNode>
#include <osg/LightSource>
#include <osgDB/FileUtils>
#include <osgSim/DOFTransform>
#include <osgSim/MultiSwitch>
#include <osgSim/GeographicLocation>
#include <osgSim/ObjectRecordData>
#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_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();
in.forward( 4*6 );
/*int32 projectionType =*/ in.readInt32();
in.forward( 4*7 );
/*int16 nextDOF =*/ in.readInt16();
/*int16 vertStorage =*/ in.readInt16();
/*int32 dbOrigin =*/ in.readInt32();
/*float64 swX =*/ in.readFloat64();
/*float64 swY =*/ in.readFloat64();
/*float64 deltaX =*/ in.readFloat64();
/*float64 deltaY =*/ in.readFloat64();
in.forward( 2*2 ); /* some "next bead" IDs */
in.forward( 4*2 ); /* reserved */
in.forward( 4*2 ); /* more "next bead" IDs */
in.forward( 4 ); /* reserved */
/*float64 swLat =*/ in.readFloat64();
/*float64 swLong =*/ in.readFloat64();
/*float64 neLat =*/ in.readFloat64();
/*float64 neLong =*/ in.readFloat64();
float64 originLat = in.readFloat64();
float64 originLong = in.readFloat64();
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);
// Store model origin in returned Node userData.
osgSim::GeographicLocation* loc = new osgSim::GeographicLocation;
loc->set( originLat, originLong );
_header->setUserData( loc );
osg::notify(osg::INFO) << "DB lat=" << originLat << " lon=" <<
originLong << std::endl;
document.setHeaderNode(_header.get());
}
virtual void dispose(Document& document)
{
if (_header.valid())
{
// Preset sampler uniforms.
ShaderPool* sp = document.getShaderPool();
if (sp && !sp->empty())
{
_header->getOrCreateStateSet()->addUniform( new
osg::Uniform("TextureUnit0", 0) );
_header->getOrCreateStateSet()->addUniform( new
osg::Uniform("TextureUnit1", 1) );
_header->getOrCreateStateSet()->addUniform( new
osg::Uniform("TextureUnit2", 2) );
_header->getOrCreateStateSet()->addUniform( new
osg::Uniform("TextureUnit3", 3) );
}
}
}
};
RegisterRecordProxy<Header> g_Header(HEADER_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;
uint32 _flags;
bool _forwardAnim;
bool _backwardAnim;
int32 _loopCount;
float32 _loopDuration;
float32 _lastFrameDuration;
public:
Group():
_flags(0),
_forwardAnim(false),
_backwardAnim(false),
_loopCount(0),
_loopDuration(0),
_lastFrameDuration(0)
{}
META_Record(Group)
META_setID(_group)
META_setComment(_group)
META_setMultitexture(_group)
META_addChild(_group)
bool hasAnimation() const { return _forwardAnim || _backwardAnim; }
protected:
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);
_flags = in.readUInt32(0);
/*uint16 specialId0 =*/ in.readUInt16();
/*uint16 specialId1 =*/ in.readUInt16();
/*uint16 significance =*/ in.readUInt16();
/*int8 layer =*/ in.readInt8();
in.forward(5);
// version >= VERSION_15_8
_loopCount = in.readInt32(0);
_loopDuration = in.readFloat32(0.0f);
_lastFrameDuration = in.readFloat32(0.0f);
// Check for forward animation (sequence)
_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
_backwardAnim = ( (document.version() >= VERSION_15_8) &&
((_flags & BACKWARD_ANIM) != 0) );
if (_forwardAnim || _backwardAnim)
_group = new osg::Sequence;
else
_group = new osg::Group;
_group->setName(id);
// Add this implementation to parent implementation.
if (_parent.valid())
_parent->addChild(*_group);
}
virtual void dispose(Document& document)
{
if (!_group.valid()) return;
// Insert transform(s)
if (_matrix.valid())
{
insertMatrixTransform(*_group,*_matrix,_numberOfReplications);
}
// Children are added!
osg::Sequence* sequence = dynamic_cast<osg::Sequence*>(_group.get());
if (sequence && sequence->getNumChildren() > 0)
{
// Regardless of forwards or backwards, animation could have swing
bit set.
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);
// Loop timing available from version 15.8.
if (document.version() >= VERSION_15_8)
{
// Set frame duration.
float frameDuration = _loopDuration /
float(sequence->getNumChildren());
for (unsigned int i=0; i < sequence->getNumChildren(); i++)
sequence->setTime(i, frameDuration);
// Set number of repetitions.
if (_loopCount > 0)
sequence->setDuration(1.0f, _loopCount);
else
sequence->setDuration(1.0f); // Run continuously
}
else // No timing available.
{
// Set frame duration
float frameDuration = 0.1f; // 10Hz
for (unsigned int i=0; i < sequence->getNumChildren(); i++)
sequence->setTime(i, frameDuration);
// Run continuously
sequence->setDuration(1.0f);
}
sequence->setMode(osg::Sequence::START);
}
}
};
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_setMultitexture(_dof)
META_addChild(_dof)
META_dispose(_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_setMultitexture(_lod)
META_addChild(_impChild0)
META_dispose(_lod)
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_setMultitexture(_lod)
META_addChild(_impChild0)
META_dispose(_lod)
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_setMultitexture(_multiSwitch)
META_dispose(_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;
// Parent pool override flags
static const unsigned long COLOR_PALETTE_OVERRIDE = 0x80000000u >> 0;
static const unsigned long MATERIAL_PALETTE_OVERRIDE = 0x80000000u >> 1;
static const unsigned long TEXTURE_PALETTE_OVERRIDE = 0x80000000u >> 2;
static const unsigned long LINE_STYLE_PALETTE_OVERRIDE = 0x80000000u >> 3;
static const unsigned long SOUND_PALETTE_OVERRIDE = 0x80000000u >> 4;
static const unsigned long LIGHT_SOURCE_PALETTE_OVERRIDE = 0x80000000u >> 5;
static const unsigned long LIGHT_POINT_PALETTE_OVERRIDE = 0x80000000u >> 6;
static const unsigned long SHADER_PALETTE_OVERRIDE = 0x80000000u >> 7;
public:
ExternalReference() {}
META_Record(ExternalReference)
META_setID(_external)
META_setComment(_external)
META_setMultitexture(_external)
META_addChild(_external)
META_dispose(_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);
// Set parent pools as user data
if (document.version() >= VERSION_14_2)
{
in.forward(4);
uint32 mask = in.readUInt32(~0);
// Possible bug in models with version number 15.4.1 ?
// Symptoms: Black trees in VegaPlayer town.
if (document.version() == 1541)
mask = ~0;
ParentPools* parentPools = new ParentPools;
if ((mask & COLOR_PALETTE_OVERRIDE) == 0)
parentPools->setColorPool(document.getColorPool());
if ((mask & MATERIAL_PALETTE_OVERRIDE) == 0)
parentPools->setMaterialPool(document.getMaterialPool());
if ((mask & TEXTURE_PALETTE_OVERRIDE) == 0)
parentPools->setTexturePool(document.getTexturePool());
if ((document.version() >= VERSION_15_1) && ((mask &
LIGHT_SOURCE_PALETTE_OVERRIDE) == 0))
parentPools->setLightSourcePool(document.getLightSourcePool());
if ((document.version() >= VERSION_15_8) && ((mask &
LIGHT_POINT_PALETTE_OVERRIDE) == 0))
parentPools->setLPAppearancePool(document.getLightPointAppearancePool());
if ((document.version() >= VERSION_16_0) && ((mask &
SHADER_PALETTE_OVERRIDE) == 0))
parentPools->setShaderPool(document.getShaderPool());
_external->setUserData(parentPools);
}
// Add this implementation to parent implementation.
if (_parent.valid())
_parent->addChild(*_external);
}
};
RegisterRecordProxy<ExternalReference>
g_ExternalReference(EXTERNAL_REFERENCE_OP);
/** InstanceDefinition
*/
class InstanceDefinition : public PrimaryRecord
{
int _number;
osg::ref_ptr<osg::Group> _instanceDefinition;
public:
InstanceDefinition():_number(0) {}
META_Record(InstanceDefinition)
META_setID(_instanceDefinition)
META_setComment(_instanceDefinition)
META_setMultitexture(_instanceDefinition)
META_addChild(_instanceDefinition)
protected:
virtual ~InstanceDefinition() {}
virtual void readRecord(RecordInputStream& in, Document& document)
{
in.forward(2);
_number = (int)in.readUInt16();
_instanceDefinition = new osg::Group;
}
virtual void dispose(Document& document)
{
// Insert transform(s)
if (_matrix.valid())
{
osg::ref_ptr<osg::MatrixTransform> transform = new
osg::MatrixTransform(*_matrix);
transform->setDataVariance(osg::Object::STATIC);
transform->addChild(_instanceDefinition.get());
_instanceDefinition = transform.get();
}
// 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() && instance)
_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_setMultitexture(_extension)
META_addChild(_extension)
META_dispose(_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);
/** 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_addChild(_object)
protected:
virtual void readRecord(RecordInputStream& in, Document& document)
{
std::string id = in.readString(8);
_object = new osg::Group;
_object->setName(id);
osgSim::ObjectRecordData* ord = new osgSim::ObjectRecordData;
_object->setUserData( ord );
ord->_flags = in.readUInt32();
ord->_relativePriority = in.readInt16();
ord->_transparency = in.readUInt16();
ord->_effectID1 = in.readInt16();
ord->_effectID2 = in.readInt16();
ord->_significance = in.readInt16();
// Postpone add-to-parent until we know a bit more.
}
virtual void dispose(Document& document)
{
if (!_parent.valid() || !_object.valid()) return;
// Is it safe to remove _object?
if (!document.getPreserveObject() && isSafeToRemoveObject() &&
!_matrix.valid())
{
// Add children of _object to parent.
// _object will not be added to graph.
for (unsigned int i=0; i<_object->getNumChildren(); ++i)
{
_parent->addChild(*(_object->getChild(i)));
}
}
else
{
_parent->addChild(*_object);
}
// Insert transform(s)
if (_matrix.valid())
{
insertMatrixTransform(*_object,*_matrix,_numberOfReplications);
}
}
bool isSafeToRemoveObject() const
{
// The following tests need a valid parent.
if (_parent.valid())
{
// LODs adds an empty child group so it is safe to remove this
object record.
if (typeid(*_parent)==typeid(flt::LevelOfDetail))
return true;
if (typeid(*_parent)==typeid(flt::OldLevelOfDetail))
return true;
// If parent is a Group record we have to check for animation.
Group* parentGroup = dynamic_cast<flt::Group*>(_parent.get());
if (parentGroup && !parentGroup->hasAnimation())
return true;
}
return false;
}
};
RegisterRecordProxy<Object> g_Object(OBJECT_OP);
/** LightSource
*/
class LightSource : public PrimaryRecord
{
static const unsigned int ENABLED = 0x80000000u >> 0;
static const unsigned int GLOBAL = 0x80000000u >> 1;
static const unsigned int EXPORT = 0x80000000u >> 3;
osg::ref_ptr<osg::LightSource> _lightSource;
public:
LightSource() {}
META_Record(LightSource)
META_setID(_lightSource)
META_setComment(_lightSource)
META_dispose(_lightSource)
protected:
virtual ~LightSource() {}
virtual void readRecord(RecordInputStream& in, Document& document)
{
std::string id = in.readString(8);
in.forward(4);
int32 index = in.readInt32();
in.forward(4);
uint32 flags = in.readUInt32();
in.forward(4);
osg::Vec3d pos = in.readVec3d();
float32 yaw = in.readFloat32();
float32 pitch = in.readFloat32();
_lightSource = new osg::LightSource;
_lightSource->setName(id);
LightSourcePool* pool = document.getOrCreateLightSourcePool();
osg::Light* lightFromPool = pool->get(index);
if (lightFromPool)
{
// Make a clone of light in pool.
osg::Light* light = new osg::Light(*lightFromPool);
// TODO: Find a better way to set light number.
light->setLightNum(1);
// Position
float w = lightFromPool->getPosition().w();
if (w > 0.0) // positional light?
light->setPosition(osg::Vec4(pos,w));
// Apply yaw and pitch for infinite and spot light.
if ((w==0.0) || (light->getSpotCutoff()<180.0))
{
// TODO: What direction is zero yaw and pitch?
osg::Quat rotation = (
osg::Quat(osg::inDegrees(double(yaw)),osg::Vec3(0.0,0.0,1.0)) *
osg::Quat(osg::inDegrees(double(pitch)),osg::Vec3(1.0,0.0,0.0)) );
light->setDirection(rotation*osg::Vec3(0.0,1.0,0.0));
}
_lightSource->setLight(light);
_lightSource->setLocalStateSetModes((flags & ENABLED) ?
osg::StateAttribute::ON : osg::StateAttribute::OFF);
// Global light.
if (flags & GLOBAL)
{
// Apply light source to header node.
osg::Node* header = document.getHeaderNode();
if (header)
_lightSource->setStateSetModes(*(header->getOrCreateStateSet()),osg::StateAttribute::ON);
}
}
if (_parent.valid())
_parent->addChild(*_lightSource);
}
};
RegisterRecordProxy<LightSource> g_LightSource(LIGHT_SOURCE_OP);
} // end namespace
#include <osgSim/ObjectRecordData>
#include <osg/io_utils>
#include <iostream>
#include <string>
#include <osgDB/Registry>
#include <osgDB/Input>
#include <osgDB/Output>
#include <osgDB/ParameterOutput>
//#include <map>
bool ObjectRecordData_readLocalData( osg::Object &obj, osgDB::Input &fr );
bool ObjectRecordData_writeLocalData( const osg::Object &obj, osgDB::Output &fw
);
osgDB::RegisterDotOsgWrapperProxy ObjectRecordData_Proxy
(
new osgSim::ObjectRecordData,
"ObjectRecordData",
"Object ObjectRecordData",
&ObjectRecordData_readLocalData,
&ObjectRecordData_writeLocalData,
osgDB::DotOsgWrapper::READ_AND_WRITE
);
static const int numBits( 6 );
typedef std::pair< std::string,unsigned int> FlagBits;
static FlagBits flagBits[numBits] = {
FlagBits( std::string("DONT_DISPLAY_IN_DAYLIGHT"),
osgSim::ObjectRecordData::DONT_DISPLAY_IN_DAYLIGHT ),
FlagBits( "DONT_DISPLAY_AT_DUSK",
osgSim::ObjectRecordData::DONT_DISPLAY_AT_DUSK ),
FlagBits( "DONT_DISPLAY_AT_NIGHT",
osgSim::ObjectRecordData::DONT_DISPLAY_AT_NIGHT ),
FlagBits( "DONT_ILLUMINATE", osgSim::ObjectRecordData::DONT_ILLUMINATE ),
FlagBits( "FLAT_SHADED", osgSim::ObjectRecordData::FLAT_SHADED ),
FlagBits( "GROUPS_SHADOW_OBJECT",
osgSim::ObjectRecordData::GROUPS_SHADOW_OBJECT )
};
bool ObjectRecordData_readLocalData(osg::Object &obj, osgDB::Input &fr)
{
bool iteratorAdvanced = false;
osgSim::ObjectRecordData &ord = static_cast<osgSim::ObjectRecordData&>(obj);
if (fr.matchSequence("flags %i"))
{
unsigned int flags;
fr[1].getUInt( flags );
ord._flags = flags;
fr += 2;
iteratorAdvanced = true;
}
if (fr.matchSequence("relativePriority %i"))
{
int relativePriority;
fr[1].getInt( relativePriority );
ord._relativePriority = (short) relativePriority;
fr += 2;
iteratorAdvanced = true;
}
if (fr.matchSequence("transparency %i"))
{
int transparency;
fr[1].getInt( transparency );
ord._transparency = (unsigned short) transparency;
fr += 2;
iteratorAdvanced = true;
}
if (fr.matchSequence("effectID1 %i"))
{
int effectID1;
fr[1].getInt( effectID1 );
ord._effectID1 = (short) effectID1;
fr += 2;
iteratorAdvanced = true;
}
if (fr.matchSequence("effectID2 %i"))
{
int effectID2;
fr[1].getInt( effectID2 );
ord._effectID2 = (short) effectID2;
fr += 2;
iteratorAdvanced = true;
}
if (fr.matchSequence("significance %i"))
{
int significance;
fr[1].getInt( significance );
ord._significance = (short) significance;
fr += 2;
iteratorAdvanced = true;
}
return iteratorAdvanced;
}
bool ObjectRecordData_writeLocalData(const osg::Object &obj, osgDB::Output &fw)
{
const osgSim::ObjectRecordData &ord = static_cast<const
osgSim::ObjectRecordData&>(obj);
fw.indent() << "flags " << ord._flags << std::endl;
fw.indent() << "relativePriority " << ord._relativePriority << std::endl;
fw.indent() << "transparency " << ord._transparency << std::endl;
fw.indent() << "effectID1 " << ord._effectID1 << std::endl;
fw.indent() << "effectID2 " << ord._effectID2 << std::endl;
fw.indent() << "significance " << ord._significance << std::endl;
return true;
}
_______________________________________________ osg-submissions mailing list [email protected] http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
