root/OpenSceneGraph/trunk/src/osgPlugins/OpenFlight/PrimaryRecords.cpp @ 9573

Revision 9573, 32.8 kB (checked in by robert, 6 years ago)

Fixed warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[7748]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
[5038]14//
15// OpenFlight® loader for OpenSceneGraph
16//
[7748]17//  Copyright (C) 2005-2007  Brede Johansen
[5038]18//
19
[5528]20#include <assert.h>
21#include <typeinfo>
[5038]22#include <osg/Notify>
23#include <osg/ShadeModel>
24#include <osg/ProxyNode>
25#include <osg/Sequence>
26#include <osg/LOD>
[5136]27#include <osg/ProxyNode>
[6091]28#include <osg/LightSource>
[5038]29#include <osgDB/FileUtils>
30#include <osgSim/DOFTransform>
31#include <osgSim/MultiSwitch>
[5401]32#include <osgSim/GeographicLocation>
[7931]33#include <osgSim/ObjectRecordData>
[8385]34
35#include <osg/Notify>
36#include <osg/io_utils>
37
[5038]38#include "Registry.h"
39#include "Document.h"
40#include "RecordInputStream.h"
41
42namespace flt {
43
44/** Header
45*/
46class Header : public PrimaryRecord
47{
48    static const unsigned int SAVE_VERTEX_NORMALS_BIT = 0x80000000u >> 0;
49    static const unsigned int PACKED_COLOR_MODE_BIT   = 0x80000000u >> 1;
50    static const unsigned int CAD_VIEW_MODE_BIT       = 0x80000000u >> 2;
51
52    osg::ref_ptr<osg::Group> _header;
53
54public:
55
56    Header() {}
57
58    META_Record(Header)
59
60    META_setID(_header)
61    META_setComment(_header)
62    META_setMultitexture(_header)
63    META_addChild(_header)
64
65protected:
66
67    virtual ~Header() {}
68
69    virtual void readRecord(RecordInputStream& in, Document& document)
70    {
71        std::string id = in.readString(8);
72        osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl;
73
74        uint32 format = in.readUInt32();
75        osg::notify(osg::DEBUG_INFO) << "Format: " << format << std::endl;
76        document._version = format;
77
[5229]78        /*uint32 revision =*/ in.readUInt32();
[5038]79
80        std::string revisionTime = in.readString(32);
81        osg::notify(osg::INFO) << "Last revision: " << revisionTime << std::endl;
82
83        in.forward(4*2);
84
85        // Flight v.11 & 12 use integer coordinates
86        int16 multDivUnits = in.readInt16();        // Units multiplier/divisor
87        uint8 units = in.readUInt8();               // 0=Meters 1=Kilometers 4=Feet 5=Inches 8=Nautical miles
[5229]88        /*uint8 textureWhite =*/ in.readUInt8();
89        /*uint32 flags =*/ in.readUInt32();
[5401]90       
91        in.forward( 4*6 );
92        /*int32 projectionType =*/ in.readInt32();
[5038]93
[5401]94        in.forward( 4*7 );
95        /*int16 nextDOF =*/ in.readInt16();
96        /*int16 vertStorage =*/ in.readInt16();
97        /*int32 dbOrigin =*/ in.readInt32();
98
99        /*float64 swX =*/ in.readFloat64();
100        /*float64 swY =*/ in.readFloat64();
101        /*float64 deltaX =*/ in.readFloat64();
102        /*float64 deltaY =*/ in.readFloat64();
103
104        in.forward( 2*2 ); /* some "next bead" IDs */
105        in.forward( 4*2 ); /* reserved */
106        in.forward( 4*2 ); /* more "next bead" IDs */
107        in.forward( 4 ); /* reserved */
108
109        /*float64 swLat =*/ in.readFloat64();
110        /*float64 swLong =*/ in.readFloat64();
111        /*float64 neLat =*/ in.readFloat64();
112        /*float64 neLong =*/ in.readFloat64();
113        float64 originLat = in.readFloat64();
114        float64 originLong = in.readFloat64();
115
[5038]116        if (document.getDoUnitsConversion())
117            document._unitScale = unitsToMeters((CoordUnits)units) / unitsToMeters(document.getDesiredUnits());
118
119        if (document._version < VERSION_13)
120        {
121            if (multDivUnits >= 0)
122                document._unitScale *= (double)multDivUnits;
123            else
124                document._unitScale /= (double)(-multDivUnits);
125        }
126
127        _header = new osg::Group;
128        _header->setName(id);
129
[5401]130        // Store model origin in returned Node userData.
131        osgSim::GeographicLocation* loc = new osgSim::GeographicLocation;
132        loc->set( originLat, originLong );
133        _header->setUserData( loc );
134        osg::notify(osg::INFO) << "DB lat=" << originLat << " lon=" << originLong << std::endl;
135
[5038]136        document.setHeaderNode(_header.get());
137    }
138
[7756]139    virtual void dispose(Document& document)
[6165]140    {
141        if (_header.valid())
142        {
143            // Preset sampler uniforms.
144            ShaderPool* sp = document.getShaderPool();
145            if (sp && !sp->empty())
146            {
147                _header->getOrCreateStateSet()->addUniform( new osg::Uniform("TextureUnit0", 0) );
148                _header->getOrCreateStateSet()->addUniform( new osg::Uniform("TextureUnit1", 1) );
149                _header->getOrCreateStateSet()->addUniform( new osg::Uniform("TextureUnit2", 2) );
150                _header->getOrCreateStateSet()->addUniform( new osg::Uniform("TextureUnit3", 3) );
151            }
152        }
153    }
[5038]154};
155
156RegisterRecordProxy<Header> g_Header(HEADER_OP);
157
158
159/** Group
160*/
161class Group : public PrimaryRecord
162{
163    static const unsigned int FORWARD_ANIM     = 0x80000000u >> 1;
164    static const unsigned int SWING_ANIM       = 0x80000000u >> 2;
165    static const unsigned int BOUND_BOX_FOLLOW = 0x80000000u >> 3;
166    static const unsigned int FREEZE_BOUND_BOX = 0x80000000u >> 4;
167    static const unsigned int DEFAULT_PARENT   = 0x80000000u >> 5;
168    static const unsigned int BACKWARD_ANIM    = 0x80000000u >> 6;
169
170    osg::ref_ptr<osg::Group> _group;
[6256]171    uint32 _flags;
[5528]172    bool _forwardAnim;
173    bool _backwardAnim;
[6256]174    int32 _loopCount;
[5621]175    float32 _loopDuration;
[6256]176    float32 _lastFrameDuration;
[5038]177
178public:
179
[5528]180    Group():
[6256]181        _flags(0),
[5528]182        _forwardAnim(false),
[6256]183        _backwardAnim(false),
184        _loopCount(0),
185        _loopDuration(0),
186        _lastFrameDuration(0)
[5528]187    {}
[5038]188
189    META_Record(Group)
190
191    META_setID(_group)
192    META_setComment(_group)
193    META_setMultitexture(_group)
194    META_addChild(_group)
195
[5528]196    bool hasAnimation() const { return _forwardAnim || _backwardAnim; }
197
[5038]198protected:
199
200    void readRecord(RecordInputStream& in, Document& document)
201    {
202        std::string id = in.readString(8);
203        osg::notify(osg::DEBUG_INFO) << "ID: " << id << std::endl;
204
[5229]205        /*int16 relativePriority =*/ in.readInt16();
[5038]206        in.forward(2);
[6256]207        _flags = in.readUInt32(0);
[5229]208        /*uint16 specialId0 =*/ in.readUInt16();
209        /*uint16 specialId1 =*/ in.readUInt16();
210        /*uint16 significance =*/ in.readUInt16();
211        /*int8 layer =*/ in.readInt8();
[5038]212        in.forward(5);
[5624]213        // version >= VERSION_15_8
[6256]214        _loopCount = in.readInt32(0);
215        _loopDuration = in.readFloat32(0.0f);
216        _lastFrameDuration = in.readFloat32(0.0f);
[5038]217
218        // Check for forward animation (sequence)
[6256]219        _forwardAnim = (_flags & FORWARD_ANIM) != 0;
[5038]220
221        // For versions prior to 15.8, the swing bit can be set independently
222        // of the animation bit.  This implies forward animation (with swing)
[6256]223        if ((document.version() < VERSION_15_8) && (_flags & SWING_ANIM))
[5528]224            _forwardAnim = true;
[5038]225       
226        // OpenFlight 15.8 adds backwards animations
[5528]227        _backwardAnim = ( (document.version() >= VERSION_15_8) &&
[6256]228            ((_flags & BACKWARD_ANIM) != 0) );
[5038]229
[5528]230        if (_forwardAnim || _backwardAnim)
[6256]231            _group = new osg::Sequence;
[5038]232        else
233            _group = new osg::Group;
234
235        _group->setName(id);
236
237        // Add this implementation to parent implementation.
238        if (_parent.valid())
239            _parent->addChild(*_group);
240    }
241
[7756]242    virtual void dispose(Document& document)
[5624]243    {
[7756]244        if (!_group.valid()) return;
245
246        // Insert transform(s)
247        if (_matrix.valid())
248        {
249            insertMatrixTransform(*_group,*_matrix,_numberOfReplications);
250        }
251
[6256]252        // Children are added!
253        osg::Sequence* sequence = dynamic_cast<osg::Sequence*>(_group.get());
254        if (sequence && sequence->getNumChildren() > 0)
[5624]255        {
[6256]256            // Regardless of forwards or backwards, animation could have swing bit set.
257            osg::Sequence::LoopMode loopMode = ((_flags & SWING_ANIM) == 0) ?
258                osg::Sequence::LOOP : osg::Sequence::SWING;
259
260            if (_forwardAnim)
261                sequence->setInterval(loopMode, 0, -1);
262            else 
263                sequence->setInterval(loopMode, -1, 0);
264
265            // Loop timing available from version 15.8.
266            if (document.version() >= VERSION_15_8)
[5624]267            {
[6256]268                // Set frame duration.
269                float frameDuration = _loopDuration / float(sequence->getNumChildren());
270                for (unsigned int i=0; i < sequence->getNumChildren(); i++)
271                    sequence->setTime(i, frameDuration);
272
273                // Set number of repetitions.
274                if (_loopCount > 0)
275                    sequence->setDuration(1.0f, _loopCount);
276                else
277                    sequence->setDuration(1.0f);        // Run continuously
[5624]278            }
[6256]279            else // No timing available.
280            {
281                // Set frame duration
282                float frameDuration = 0.1f;     // 10Hz
283                for (unsigned int i=0; i < sequence->getNumChildren(); i++)
284                    sequence->setTime(i, frameDuration);
285
286                // Run continuously
287                sequence->setDuration(1.0f);
288            }
289
290            sequence->setMode(osg::Sequence::START);
[5624]291        }
292    }
[5038]293};
294
295RegisterRecordProxy<Group> g_Group(GROUP_OP);
296
297
298/** DegreeOfFreedom
299*/
300class DegreeOfFreedom : public PrimaryRecord
301{
302    // Flags
303    static const unsigned long LIMIT_TRANSLATION_X = 0x80000000u >> 0;
304    static const unsigned long LIMIT_TRANSLATION_Y = 0x80000000u >> 1;
305    static const unsigned long LIMIT_TRANSLATION_Z = 0x80000000u >> 2;
306    static const unsigned long LIMIT_PITCH         = 0x80000000u >> 3;
307    static const unsigned long LIMIT_ROLL          = 0x80000000u >> 4;
308    static const unsigned long LIMIT_YAW           = 0x80000000u >> 5;
309    static const unsigned long LIMIT_SCALE_X       = 0x80000000u >> 6;
310    static const unsigned long LIMIT_SCALE_Y       = 0x80000000u >> 7;
311    static const unsigned long LIMIT_SCALE_Z       = 0x80000000u >> 8;
312
313    struct Range
314    {
315        float64 min;            // Minimum value with respect to the local coord system
[8563]316        float64 max;            // Maximum value with respect to the local coord system
[5038]317        float64 current;        // Current value with respect to the local coord system
318        float64 increment;      // Increment
319    };
320
321    osg::ref_ptr<osgSim::DOFTransform> _dof;
322
323public:
324
325    DegreeOfFreedom():
326        _dof(new osgSim::DOFTransform) {}
327
328    META_Record(DegreeOfFreedom)
329
330    META_setID(_dof)
331    META_setComment(_dof)
332    META_setMultitexture(_dof)
333    META_addChild(_dof)
[7756]334    META_dispose(_dof)
[5038]335
336protected:
337
338    virtual ~DegreeOfFreedom() {}
339    virtual void readRecord(RecordInputStream& in, Document& document)
340    {
341        std::string id = in.readString(8);
342        in.forward(4);                                  // Reserved
343        osg::Vec3d localOrigin = in.readVec3d();
344        osg::Vec3d pointOnXAxis = in.readVec3d();
345        osg::Vec3d pointInXYPlane = in.readVec3d();
346        Range rangeZ = readRange(in);                   // Legal z values with respect to the local coord system
347        Range rangeY = readRange(in);                   // Legal y values with respect to the local coord system
348        Range rangeX = readRange(in);                   // Legal x values with respect to the local coord system
349        Range rangePitch = readRange(in);               // Legal pitch values (rotation about the x-axis)
350        Range rangeRoll = readRange(in);                // Legal roll values( rotation about the y-axis)
351        Range rangeYaw = readRange(in);                 // Legal yaw values (rotation about the z-axis)
352        Range rangeScaleZ = readRange(in);              // Legal z scale values (about local origin)
353        Range rangeScaleY = readRange(in);              // Legal y scale values about local origin)
354        Range rangeScaleX = readRange(in);              // Legal x scale values (about local origin)
355        uint32 flags = in.readUInt32();                 // Flags, bits from left to right (see OF doc)
356
357        // out of range check, required for racecar.flt (Creator Gallery)
358        if (!valid(localOrigin))
359            localOrigin = osg::Vec3d(0,0,0);
360        if (!valid(pointOnXAxis))
361            pointOnXAxis = osg::X_AXIS;
362        if (!valid(pointInXYPlane))
363            pointInXYPlane = osg::Y_AXIS;
364
365        _dof->setName(id);
366
367        //tranlsations:
368        _dof->setMinTranslate(osg::Vec3(rangeX.min,rangeY.min,rangeZ.min)*document.unitScale());
369        _dof->setMaxTranslate(osg::Vec3(rangeX.max,rangeY.max,rangeZ.max)*document.unitScale());
370        _dof->setCurrentTranslate(osg::Vec3(rangeX.current,rangeY.current,rangeZ.current)*document.unitScale());
371        _dof->setIncrementTranslate(osg::Vec3(rangeX.increment,rangeY.increment,rangeZ.increment)*document.unitScale());
372
373        //rotations:
374        _dof->setMinHPR(osg::Vec3(osg::inDegrees(rangeYaw.min),osg::inDegrees(rangePitch.min),osg::inDegrees(rangeRoll.min)));
375        _dof->setMaxHPR(osg::Vec3(osg::inDegrees(rangeYaw.max),osg::inDegrees(rangePitch.max),osg::inDegrees(rangeRoll.max)));
376        _dof->setCurrentHPR(osg::Vec3(osg::inDegrees(rangeYaw.current),osg::inDegrees(rangePitch.current),osg::inDegrees(rangeRoll.current)));
377        _dof->setIncrementHPR(osg::Vec3(osg::inDegrees(rangeYaw.increment),osg::inDegrees(rangePitch.increment),osg::inDegrees(rangeRoll.increment)));
378
379        //scales:
380        _dof->setMinScale(osg::Vec3(rangeScaleX.min,rangeScaleY.min,rangeScaleZ.min));
381        _dof->setMaxScale(osg::Vec3(rangeScaleX.max,rangeScaleY.max,rangeScaleZ.max));
382        _dof->setCurrentScale(osg::Vec3(rangeScaleX.current,rangeScaleY.current,rangeScaleZ.current));
383        _dof->setIncrementScale(osg::Vec3(rangeScaleX.increment,rangeScaleY.increment,rangeScaleZ.increment));
384
385        // compute axis.
386        osg::Vec3 xAxis = pointOnXAxis - localOrigin;
387        osg::Vec3 xyPlaneVector = pointInXYPlane - localOrigin;
388        osg::Vec3 zAxis = xAxis ^ xyPlaneVector;
389        osg::Vec3 yAxis = zAxis ^ xAxis;
390
391        // normalize
[8385]392        float length_x = xAxis.normalize();
393        float length_y = yAxis.normalize();
394        float length_z = zAxis.normalize();
395       
396        if ((length_x*length_y*length_z)==0.0f)
397        {
398            osg::notify(osg::NOTICE)<<"Warning: OpenFlight DegreeOfFreedom::readRecord() found erroneous axis definition:"<<std::endl;
399            osg::notify(osg::NOTICE)<<"    localOrigin="<<localOrigin<<std::endl;
400            osg::notify(osg::NOTICE)<<"    pointOnXAxis="<<pointOnXAxis<<std::endl;
401            osg::notify(osg::NOTICE)<<"    pointInXYPlane="<<pointInXYPlane<<std::endl;
402           
403            xAxis.set(1.0f,0.0f,0.0f);
404            yAxis.set(0.0f,1.0f,0.0f);
405            zAxis.set(0.0f,0.0f,1.0f);
406        }
[5038]407
408        // scale origin
409        osg::Vec3 origin = localOrigin * document.unitScale();
410
411        // create putmatrix
412        osg::Matrix inv_putmat(xAxis.x(), xAxis.y(), xAxis.z(), 0.0,
413                               yAxis.x(), yAxis.y(), yAxis.z(), 0.0,
414                               zAxis.x(), zAxis.y(), zAxis.z(), 0.0,
415                               origin.x(), origin.y(), origin.z(), 1.0);
416
[8385]417
[5038]418        _dof->setInversePutMatrix(inv_putmat);
419        _dof->setPutMatrix(osg::Matrix::inverse(inv_putmat));
420
421        _dof->setLimitationFlags(flags);
422        _dof->setAnimationOn(document.getDefaultDOFAnimationState());
423//      _dof->setHPRMultOrder(osgSim::DOFTransform::HPR);
424
425        // Add this implementation to parent implementation.
426        if (_parent.valid())
427            _parent->addChild(*_dof);
428    }
429
430    Range readRange(RecordInputStream& in) const
431    {
432        Range range;
433        range.min = in.readFloat64();
434        range.max = in.readFloat64();
435        range.current = in.readFloat64();
436        range.increment = in.readFloat64();
437
438        // Extend valid range (See Creator help on DOF).
439        if (range.current < range.min) range.min = range.current;
440        if (range.current > range.max) range.max = range.current;
441
442        const float64 epsilon = 1.0e-7;
443        if (fabs(range.max-range.min) < epsilon)
444            range.increment = 0;
445
446        return range;
447    }
448
449    bool valid(const osg::Vec3d& v) const
450    {
451        const osg::Vec3d bad(-1.0e8,-1.0e8,-1.0e8);
452        const float64 epsilon = 1.0e-7;
453
454        return (fabs(v.x()-bad.x()) > epsilon) ||
455               (fabs(v.y()-bad.y()) > epsilon) ||
456               (fabs(v.z()-bad.z()) > epsilon);
457    }
458};
459
460RegisterRecordProxy<DegreeOfFreedom> g_DegreeOfFreedom(DOF_OP);
461
462
463/** LevelOfDetail - To recreate the LevelOfDetail record in OSG we have to create a LOD node with one Group node under it.
464 *  OSG representation Children of the LevelOfDetail record will be added to
465*/
466class LevelOfDetail : public PrimaryRecord
467{
468    osg::ref_ptr<osg::LOD> _lod;
469    osg::ref_ptr<osg::Group> _impChild0;
470
471public:
472
473    LevelOfDetail() {}
474
475    META_Record(LevelOfDetail)
476
477    META_setID(_lod)
478    META_setComment(_lod)
479    META_setMultitexture(_lod)
480    META_addChild(_impChild0)
[7756]481    META_dispose(_lod)
[5038]482
483protected:
484
485    virtual ~LevelOfDetail() {}
486    virtual void readRecord(RecordInputStream& in, Document& document)
487    {
488        std::string id = in.readString(8);
489        in.forward(4);
490        float64 switchInDistance = in.readFloat64();
491        float64 switchOutDistance = in.readFloat64();
[5229]492        /*int16 specialEffectID1 =*/ in.readInt16();
493        /*int16 specialEffectID2 =*/ in.readInt16();
494        /*uint32 flags =*/ in.readUInt32();
[5038]495        osg::Vec3d center = in.readVec3d();
496
497        _lod = new osg::LOD;
498        _lod->setName(id);
499        _lod->setCenter(center*document.unitScale());
500
501        _impChild0 = new osg::Group;
502        _impChild0->setName("LOD child0");
503
504        // Add child to lod.
505        _lod->addChild(_impChild0.get(),
506             (float)switchOutDistance * document.unitScale(),
507             (float)switchInDistance * document.unitScale());
508
509        // Add this implementation to parent implementation.
510        if (_parent.valid())
511            _parent->addChild(*_lod);
512    }
513
514};
515
516RegisterRecordProxy<LevelOfDetail> g_LevelOfDetail(LOD_OP);
517
518
519/** OldLevelOfDetail
520  */
521class OldLevelOfDetail : public PrimaryRecord
522{
523    osg::ref_ptr<osg::LOD> _lod;
524    osg::ref_ptr<osg::Group> _impChild0;
525
526public:
527
528    OldLevelOfDetail() {}
529
530    META_Record(OldLevelOfDetail)
531
532    META_setID(_lod)
533    META_setComment(_lod)
534    META_setMultitexture(_lod)
535    META_addChild(_impChild0)
[7756]536    META_dispose(_lod)
[5038]537
538protected:
539
540    virtual ~OldLevelOfDetail() {}
541    virtual void readRecord(RecordInputStream& in, Document& document)
542    {
543        std::string id = in.readString(8);
544        uint32 switchInDistance = in.readUInt32();
545        uint32 switchOutDistance = in.readUInt32();
[5229]546        /*int16 specialEffectID1 =*/ in.readInt16();
547        /*int16 specialEffectID2 =*/ in.readInt16();
548        /*uint32 flags =*/ in.readUInt32();
[5038]549
550        osg::Vec3 center;
551        center.x() = (float)in.readInt32();
552        center.y() = (float)in.readInt32();
553        center.z() = (float)in.readInt32();
554
555        _lod = new osg::LOD;
556        _lod->setName(id);
557        _lod->setCenter(center*document.unitScale());
558        _lod->setRange(0, (float)switchOutDistance * document.unitScale(),
559                          (float)switchInDistance * document.unitScale());
560
561        // Add child to lod.
562        _impChild0 = new osg::Group;
563        _lod->addChild(_impChild0.get());
564
565        // Add this implementation to parent implementation.
566        if (_parent.valid())
567            _parent->addChild(*_lod);
568    }
569
570};
571
572RegisterRecordProxy<OldLevelOfDetail> g_OldLevelOfDetail(OLD_LOD_OP);
573
574
575/** Switch
576*/
577class Switch : public PrimaryRecord
578{
579    uint32 _currentMask;
580    uint32 _numberOfMasks;
581    uint32 _wordsInMask;
582    std::vector<uint32> _masks;
583
584    osg::ref_ptr<osgSim::MultiSwitch> _multiSwitch;
585
586public:
587
588    Switch() {}
589
590    META_Record(Switch)
591
592    META_setID(_multiSwitch)
593    META_setComment(_multiSwitch)
594    META_setMultitexture(_multiSwitch)
[7756]595    META_dispose(_multiSwitch)
[5038]596
597    virtual void addChild(osg::Node& child)
598    {
599        if (_multiSwitch.valid())
600        {
601            unsigned int nChild = _multiSwitch->getNumChildren();
602            for (unsigned int nMask=0; nMask<_numberOfMasks; ++nMask)
603            {
604                // test if this child is active in the current mask (itMask)
605                unsigned int nMaskBit = nChild % 32;
606                unsigned int nMaskWord = nMask * _wordsInMask + nChild / 32;
607                _multiSwitch->setValue(nMask, nChild, (_masks[nMaskWord] & (uint32(1) << nMaskBit))!=0 );
608            }
609
610            _multiSwitch->addChild(&child);
611        }
612    }
613
614protected:
615
616    virtual ~Switch() {}
[5229]617    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
[5038]618    {
619        std::string id = in.readString(8);
620        in.forward(4);
621        _currentMask = in.readUInt32();
622        _numberOfMasks = in.readUInt32();
623        _wordsInMask = in.readUInt32();
624
625        _multiSwitch = new osgSim::MultiSwitch;
626        _multiSwitch->setName(id);
627
628        /* Example:
629        | word #0 || word #1 || word #2 |     <- Mask #0
630        | word #0 || word #1 || word #2 |     <- Mask #1
631        In this example numberOfMasks=2 and wordsInMask=3, currentMask can be 0 or 1.
632        */
633
634        for (unsigned int n=0; n<_numberOfMasks*_wordsInMask; n++)
635        {
636            uint32 maskWord = in.readUInt32();
637            _masks.push_back(maskWord);
638        }
639
640        _multiSwitch->setActiveSwitchSet(_currentMask);
641
642        // Add this implementation to parent implementation.
643        if (_parent.valid())
644            _parent->addChild(*_multiSwitch);
645    }
646};
647
648RegisterRecordProxy<Switch> g_Switch(SWITCH_OP);
649
650
651/** ExternalReference
652*/
653class ExternalReference : public PrimaryRecord
654{
[5136]655    osg::ref_ptr<osg::ProxyNode> _external;
[5038]656
[5236]657    // Parent pool override flags
658    static const unsigned long COLOR_PALETTE_OVERRIDE        = 0x80000000u >> 0;
659    static const unsigned long MATERIAL_PALETTE_OVERRIDE     = 0x80000000u >> 1;
660    static const unsigned long TEXTURE_PALETTE_OVERRIDE      = 0x80000000u >> 2;
661    static const unsigned long LINE_STYLE_PALETTE_OVERRIDE   = 0x80000000u >> 3;
662    static const unsigned long SOUND_PALETTE_OVERRIDE        = 0x80000000u >> 4;
663    static const unsigned long LIGHT_SOURCE_PALETTE_OVERRIDE = 0x80000000u >> 5;
664    static const unsigned long LIGHT_POINT_PALETTE_OVERRIDE  = 0x80000000u >> 6;
665    static const unsigned long SHADER_PALETTE_OVERRIDE       = 0x80000000u >> 7;
666
[5038]667public:
668
669    ExternalReference() {}
670
671    META_Record(ExternalReference)
672
673    META_setID(_external)
674    META_setComment(_external)
675    META_setMultitexture(_external)
676    META_addChild(_external)
[7756]677    META_dispose(_external)
[5038]678
679protected:
680
681    virtual ~ExternalReference() {}
[5236]682    virtual void readRecord(RecordInputStream& in, Document& document)
[5038]683    {
684        std::string strFile = in.readString(200);
685
[5136]686        _external = new osg::ProxyNode;
687        _external->setCenterMode(osg::ProxyNode::USE_BOUNDING_SPHERE_CENTER);
688        _external->setFileName(0,strFile);
[5038]689
[5236]690        // Set parent pools as user data
[5281]691        if (document.version() >= VERSION_14_2)
692        {
[6906]693            in.forward(4);
[5236]694
[9573]695            uint32 mask = in.readUInt32(~0u);
[5281]696
697            // Possible bug in models with version number 15.4.1 ?
698            // Symptoms: Black trees in VegaPlayer town.
699            if (document.version() == 1541)
[9573]700                mask = ~0u;
[5281]701
[6091]702            ParentPools* parentPools = new ParentPools;
703
704            if ((mask & COLOR_PALETTE_OVERRIDE) == 0)
705                parentPools->setColorPool(document.getColorPool());
706
707            if ((mask & MATERIAL_PALETTE_OVERRIDE) == 0)
708                parentPools->setMaterialPool(document.getMaterialPool());
709
710            if ((mask & TEXTURE_PALETTE_OVERRIDE) == 0)
711                parentPools->setTexturePool(document.getTexturePool());
712
713            if ((document.version() >= VERSION_15_1) && ((mask & LIGHT_SOURCE_PALETTE_OVERRIDE) == 0))
714                parentPools->setLightSourcePool(document.getLightSourcePool());
715
716            if ((document.version() >= VERSION_15_8) && ((mask & LIGHT_POINT_PALETTE_OVERRIDE) == 0))
717                parentPools->setLPAppearancePool(document.getLightPointAppearancePool());
718
719            if ((document.version() >= VERSION_16_0) && ((mask & SHADER_PALETTE_OVERRIDE) == 0))
720                parentPools->setShaderPool(document.getShaderPool());
721
722            _external->setUserData(parentPools);
[5281]723        }
724
[5038]725        // Add this implementation to parent implementation.
726        if (_parent.valid())
727            _parent->addChild(*_external);
728    }
729
730};
731
732RegisterRecordProxy<ExternalReference> g_ExternalReference(EXTERNAL_REFERENCE_OP);
733
734
735/** InstanceDefinition
736*/
737class InstanceDefinition : public PrimaryRecord
738{
[7756]739    int _number;
[5038]740    osg::ref_ptr<osg::Group> _instanceDefinition;
741
742public:
743
[7756]744    InstanceDefinition():_number(0) {}
[5038]745
746    META_Record(InstanceDefinition)
747
748    META_setID(_instanceDefinition)
749    META_setComment(_instanceDefinition)
750    META_setMultitexture(_instanceDefinition)
751    META_addChild(_instanceDefinition)
752
753protected:
754
755    virtual ~InstanceDefinition() {}
756    virtual void readRecord(RecordInputStream& in, Document& document)
757    {
758        in.forward(2);
[7756]759        _number = (int)in.readUInt16();
[5038]760
761        _instanceDefinition = new osg::Group;
[7756]762    }
[5038]763
[7756]764    virtual void dispose(Document& document)
765    {
766        // Insert transform(s)
767        if (_matrix.valid())
768        {
769            osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform(*_matrix);
770            transform->setDataVariance(osg::Object::STATIC);
771            transform->addChild(_instanceDefinition.get());
772            _instanceDefinition = transform.get();
773        }
774
[5038]775        //  Add to instance definition table.
[7756]776        document.setInstanceDefinition(_number,_instanceDefinition.get());
[5038]777    }
[7756]778
[5038]779};
780
781RegisterRecordProxy<InstanceDefinition> g_InstanceDefinition(INSTANCE_DEFINITION_OP);
782
783
784/** InstanceReference
785  * The InstanceReference is a leaf record.
786  */
787class InstanceReference : public PrimaryRecord
788{
789public:
790
791    InstanceReference() {}
792
793    META_Record(InstanceReference)
794
795protected:
796
797    virtual ~InstanceReference() {}
798    virtual void readRecord(RecordInputStream& in, Document& document)
799    {
800        in.forward(2);
801        uint16 number = in.readUInt16();
802
803        // Get definition.
804        osg::Node* instance = document.getInstanceDefinition(number);
805
806        // Add this implementation to parent implementation.
[7756]807        if (_parent.valid() && instance)
[5038]808            _parent->addChild(*instance);
809    }
810};
811
812RegisterRecordProxy<InstanceReference> g_InstanceReference(INSTANCE_REFERENCE_OP);
813
814
815/** Extension
816*/
817class Extension : public PrimaryRecord
818{
819    osg::ref_ptr<osg::Group> _extension;
820
821public:
822
823    Extension() {}
824
825    META_Record(Extension)
826
827    META_setID(_extension)
828    META_setComment(_extension)
829    META_setMultitexture(_extension)
830    META_addChild(_extension)
[7756]831    META_dispose(_extension)
[5038]832
833protected:
834
835    virtual ~Extension() {}
[5229]836    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
[5038]837    {
838        std::string id = in.readString(8);
839        std::string siteId = in.readString(8);
840        in.forward(1);
841
842        _extension = new osg::Group;
843        _extension->setName(id);
844
845        // Add this implementation to parent implementation.
846        if (_parent.valid())
847            _parent->addChild(*_extension);
848    }
849};
850
851RegisterRecordProxy<Extension> g_Extension(EXTENSION_OP);
852
853
[5528]854/** Object
855*/
856class Object : public PrimaryRecord
857{
858    static const unsigned int HIDE_IN_DAYLIGHT = 0x80000000u >> 0;
859    static const unsigned int HIDE_AT_DUSK     = 0x80000000u >> 1;
860    static const unsigned int HIDE_AT_NIGHT    = 0x80000000u >> 2;
861    static const unsigned int NO_ILLUMINATION  = 0x80000000u >> 3;
862    static const unsigned int FLAT_SHADED      = 0x80000000u >> 4;
863    static const unsigned int SHADOW_OBJECT    = 0x80000000u >> 5;
864
865    osg::ref_ptr<osg::Group> _object;
866
867public:
868
869    Object() {}
870
871    META_Record(Object)
872
873    META_setID(_object)
874    META_setComment(_object)
[7756]875    META_addChild(_object)
[5528]876
[7756]877protected:
878
879    virtual void readRecord(RecordInputStream& in, Document& document)
[5539]880    {
[7756]881        std::string id = in.readString(8);
[5539]882
[7756]883        _object = new osg::Group;
884        _object->setName(id);
885
[7931]886        if (document.getReadObjectRecordData())
887        {
888            osgSim::ObjectRecordData* ord = new osgSim::ObjectRecordData;
889            ord->_flags = in.readUInt32();
890            ord->_relativePriority = in.readInt16();
891            ord->_transparency = in.readUInt16();
892            ord->_effectID1 = in.readInt16();
893            ord->_effectID2 = in.readInt16();
894            ord->_significance = in.readInt16();
895
896            _object->setUserData( ord );
897        }
898        else
899        {
900            /*uint32 flags =*/ in.readUInt32();
901        }
902       
[7756]903        // Postpone add-to-parent until we know a bit more.
[5539]904    }
905
[7756]906    virtual void dispose(Document& document)
[5528]907    {
[7756]908        if (!_parent.valid() || !_object.valid()) return;
[5528]909
[7756]910        // Is it safe to remove _object?
911        if (!document.getPreserveObject() && isSafeToRemoveObject() && !_matrix.valid())
912        {
913            // Add children of _object to parent.
914            // _object will not be added to graph.
915            for (unsigned int i=0; i<_object->getNumChildren(); ++i)
916            {
917                _parent->addChild(*(_object->getChild(i)));
918            }
919        }
920        else
921        {
922            _parent->addChild(*_object);
923        }
[5528]924
[7756]925        // Insert transform(s)
926        if (_matrix.valid())
927        {
928            insertMatrixTransform(*_object,*_matrix,_numberOfReplications);
929        }
930    }
[5528]931
[7756]932    bool isSafeToRemoveObject() const
[5528]933    {
[7756]934        // The following tests need a valid parent.
935        if (_parent.valid())
[5528]936        {
937            // LODs adds an empty child group so it is safe to remove this object record.
938            if (typeid(*_parent)==typeid(flt::LevelOfDetail))
[7756]939                return true;
[5528]940
941            if (typeid(*_parent)==typeid(flt::OldLevelOfDetail))
[7756]942                return true;
[5528]943
944            // If parent is a Group record we have to check for animation.
945            Group* parentGroup = dynamic_cast<flt::Group*>(_parent.get());
946            if (parentGroup && !parentGroup->hasAnimation())
[7756]947                return true;
[5528]948        }
949
[7756]950        return false;
[5528]951    }
[7756]952
[5528]953};
954
955RegisterRecordProxy<Object> g_Object(OBJECT_OP);
956
[6091]957
958/** LightSource
959*/
960class LightSource : public PrimaryRecord
961{
962    static const unsigned int ENABLED = 0x80000000u >> 0;
963    static const unsigned int GLOBAL  = 0x80000000u >> 1;
964    static const unsigned int EXPORT  = 0x80000000u >> 3;
965
966    osg::ref_ptr<osg::LightSource> _lightSource;
967
968public:
969
970    LightSource() {}
971
972    META_Record(LightSource)
973
974    META_setID(_lightSource)
975    META_setComment(_lightSource)
[7756]976    META_dispose(_lightSource)
[6091]977
978protected:
979
980    virtual ~LightSource() {}
981    virtual void readRecord(RecordInputStream& in, Document& document)
982    {
983        std::string id = in.readString(8);
984        in.forward(4);
985        int32 index = in.readInt32();
986        in.forward(4);
987        uint32 flags = in.readUInt32();
988        in.forward(4);
989        osg::Vec3d pos = in.readVec3d();
990        float32 yaw = in.readFloat32();
991        float32 pitch = in.readFloat32();
992
993        _lightSource = new osg::LightSource; 
994        _lightSource->setName(id);
995
996        LightSourcePool* pool = document.getOrCreateLightSourcePool();
997        osg::Light* lightFromPool = pool->get(index);
998        if (lightFromPool)
999        {
1000            // Make a clone of light in pool.
1001            osg::Light* light = new osg::Light(*lightFromPool);
1002
1003            // TODO: Find a better way to set light number.
1004            light->setLightNum(1);
1005
1006            // Position
1007            float w = lightFromPool->getPosition().w();
1008            if (w > 0.0) // positional light?
1009                light->setPosition(osg::Vec4(pos,w));
1010
1011            // Apply yaw and pitch for infinite and spot light.
1012            if ((w==0.0) || (light->getSpotCutoff()<180.0))
1013            {
1014                // TODO: What direction is zero yaw and pitch?
[6098]1015                osg::Quat rotation = ( osg::Quat(osg::inDegrees(double(yaw)),osg::Vec3(0.0,0.0,1.0)) *
1016                                       osg::Quat(osg::inDegrees(double(pitch)),osg::Vec3(1.0,0.0,0.0)) );
[6091]1017                light->setDirection(rotation*osg::Vec3(0.0,1.0,0.0));
1018            }
1019
1020            _lightSource->setLight(light);
1021            _lightSource->setLocalStateSetModes((flags & ENABLED) ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
1022
1023            // Global light.
1024            if (flags & GLOBAL)
1025            {
1026                // Apply light source to header node.
1027                osg::Node* header = document.getHeaderNode();
1028                if (header)
1029                    _lightSource->setStateSetModes(*(header->getOrCreateStateSet()),osg::StateAttribute::ON);
1030            }
1031        }
1032
1033        if (_parent.valid())
1034            _parent->addChild(*_lightSource);
1035    }
1036};
1037
1038RegisterRecordProxy<LightSource> g_LightSource(LIGHT_SOURCE_OP);
1039
1040
[5038]1041} // end namespace
[5122]1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
[5136]1054
1055
Note: See TracBrowser for help on using the browser.