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

Revision 13041, 32.6 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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
14//
15// OpenFlight® loader for OpenSceneGraph
16//
17//  Copyright (C) 2005-2007  Brede Johansen
18//
19
20#include <assert.h>
21#include <typeinfo>
22#include <osg/Notify>
23#include <osg/ShadeModel>
24#include <osg/ProxyNode>
25#include <osg/Sequence>
26#include <osg/LOD>
27#include <osg/ProxyNode>
28#include <osg/LightSource>
29#include <osgDB/FileUtils>
30#include <osgSim/DOFTransform>
31#include <osgSim/MultiSwitch>
32#include <osgSim/GeographicLocation>
33#include <osgSim/ObjectRecordData>
34
35#include <osg/Notify>
36#include <osg/io_utils>
37
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_DEBUG << "ID: " << id << std::endl;
73
74        uint32 format = in.readUInt32();
75        OSG_DEBUG << "Format: " << format << std::endl;
76        document._version = format;
77
78        /*uint32 revision =*/ in.readUInt32();
79
80        std::string revisionTime = in.readString(32);
81        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
88        /*uint8 textureWhite =*/ in.readUInt8();
89        /*uint32 flags =*/ in.readUInt32();
90
91        in.forward( 4*6 );
92        /*int32 projectionType =*/ in.readInt32();
93
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
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
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_INFO << "DB lat=" << originLat << " lon=" << originLong << std::endl;
135
136        document.setHeaderNode(_header.get());
137    }
138
139    virtual void dispose(Document& document)
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    }
154};
155
156REGISTER_FLTRECORD(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;
171    uint32 _flags;
172    bool _forwardAnim;
173    bool _backwardAnim;
174    int32 _loopCount;
175    float32 _loopDuration;
176    float32 _lastFrameDuration;
177
178public:
179
180    Group():
181        _flags(0),
182        _forwardAnim(false),
183        _backwardAnim(false),
184        _loopCount(0),
185        _loopDuration(0),
186        _lastFrameDuration(0)
187    {}
188
189    META_Record(Group)
190
191    META_setID(_group)
192    META_setComment(_group)
193    META_setMultitexture(_group)
194    META_addChild(_group)
195
196    bool hasAnimation() const { return _forwardAnim || _backwardAnim; }
197
198protected:
199
200    void readRecord(RecordInputStream& in, Document& document)
201    {
202        std::string id = in.readString(8);
203        OSG_DEBUG << "ID: " << id << std::endl;
204
205        /*int16 relativePriority =*/ in.readInt16();
206        in.forward(2);
207        _flags = in.readUInt32(0);
208        /*uint16 specialId0 =*/ in.readUInt16();
209        /*uint16 specialId1 =*/ in.readUInt16();
210        /*uint16 significance =*/ in.readUInt16();
211        /*int8 layer =*/ in.readInt8();
212        in.forward(5);
213        // version >= VERSION_15_8
214        _loopCount = in.readInt32(0);
215        _loopDuration = in.readFloat32(0.0f);
216        _lastFrameDuration = in.readFloat32(0.0f);
217
218        // Check for forward animation (sequence)
219        _forwardAnim = (_flags & FORWARD_ANIM) != 0;
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)
223        if ((document.version() < VERSION_15_8) && (_flags & SWING_ANIM))
224            _forwardAnim = true;
225
226        // OpenFlight 15.8 adds backwards animations
227        _backwardAnim = ( (document.version() >= VERSION_15_8) &&
228            ((_flags & BACKWARD_ANIM) != 0) );
229
230        if (_forwardAnim || _backwardAnim)
231            _group = new osg::Sequence;
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
242    virtual void dispose(Document& document)
243    {
244        if (!_group.valid()) return;
245
246        // Insert transform(s)
247        if (_matrix.valid())
248        {
249            insertMatrixTransform(*_group,*_matrix,_numberOfReplications);
250        }
251
252        // Children are added!
253        osg::Sequence* sequence = dynamic_cast<osg::Sequence*>(_group.get());
254        if (sequence && sequence->getNumChildren() > 0)
255        {
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)
267            {
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
278            }
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);
291        }
292    }
293};
294
295REGISTER_FLTRECORD(Group, GROUP_OP)
296
297
298
299/** DegreeOfFreedom
300*/
301class DegreeOfFreedom : public PrimaryRecord
302{
303    // Flags
304    static const unsigned long LIMIT_TRANSLATION_X = 0x80000000u >> 0;
305    static const unsigned long LIMIT_TRANSLATION_Y = 0x80000000u >> 1;
306    static const unsigned long LIMIT_TRANSLATION_Z = 0x80000000u >> 2;
307    static const unsigned long LIMIT_PITCH         = 0x80000000u >> 3;
308    static const unsigned long LIMIT_ROLL          = 0x80000000u >> 4;
309    static const unsigned long LIMIT_YAW           = 0x80000000u >> 5;
310    static const unsigned long LIMIT_SCALE_X       = 0x80000000u >> 6;
311    static const unsigned long LIMIT_SCALE_Y       = 0x80000000u >> 7;
312    static const unsigned long LIMIT_SCALE_Z       = 0x80000000u >> 8;
313
314    struct Range
315    {
316        float64 min;            // Minimum value with respect to the local coord system
317        float64 max;            // Maximum value with respect to the local coord system
318        float64 current;        // Current value with respect to the local coord system
319        float64 increment;      // Increment
320    };
321
322    osg::ref_ptr<osgSim::DOFTransform> _dof;
323
324public:
325
326    DegreeOfFreedom():
327        _dof(new osgSim::DOFTransform) {}
328
329    META_Record(DegreeOfFreedom)
330
331    META_setID(_dof)
332    META_setComment(_dof)
333    META_setMultitexture(_dof)
334    META_addChild(_dof)
335    META_dispose(_dof)
336
337protected:
338
339    virtual ~DegreeOfFreedom() {}
340    virtual void readRecord(RecordInputStream& in, Document& document)
341    {
342        std::string id = in.readString(8);
343        in.forward(4);                                  // Reserved
344        osg::Vec3d localOrigin = in.readVec3d();
345        osg::Vec3d pointOnXAxis = in.readVec3d();
346        osg::Vec3d pointInXYPlane = in.readVec3d();
347        Range rangeZ = readRange(in);                   // Legal z values with respect to the local coord system
348        Range rangeY = readRange(in);                   // Legal y values with respect to the local coord system
349        Range rangeX = readRange(in);                   // Legal x values with respect to the local coord system
350        Range rangePitch = readRange(in);               // Legal pitch values (rotation about the x-axis)
351        Range rangeRoll = readRange(in);                // Legal roll values( rotation about the y-axis)
352        Range rangeYaw = readRange(in);                 // Legal yaw values (rotation about the z-axis)
353        Range rangeScaleZ = readRange(in);              // Legal z scale values (about local origin)
354        Range rangeScaleY = readRange(in);              // Legal y scale values about local origin)
355        Range rangeScaleX = readRange(in);              // Legal x scale values (about local origin)
356        uint32 flags = in.readUInt32();                 // Flags, bits from left to right (see OF doc)
357
358        // out of range check, required for racecar.flt (Creator Gallery)
359        if (!valid(localOrigin))
360            localOrigin = osg::Vec3d(0,0,0);
361        if (!valid(pointOnXAxis))
362            pointOnXAxis = osg::X_AXIS;
363        if (!valid(pointInXYPlane))
364            pointInXYPlane = osg::Y_AXIS;
365
366        _dof->setName(id);
367
368        //tranlsations:
369        _dof->setMinTranslate(osg::Vec3(rangeX.min,rangeY.min,rangeZ.min)*document.unitScale());
370        _dof->setMaxTranslate(osg::Vec3(rangeX.max,rangeY.max,rangeZ.max)*document.unitScale());
371        _dof->setCurrentTranslate(osg::Vec3(rangeX.current,rangeY.current,rangeZ.current)*document.unitScale());
372        _dof->setIncrementTranslate(osg::Vec3(rangeX.increment,rangeY.increment,rangeZ.increment)*document.unitScale());
373
374        //rotations:
375        _dof->setMinHPR(osg::Vec3(osg::inDegrees(rangeYaw.min),osg::inDegrees(rangePitch.min),osg::inDegrees(rangeRoll.min)));
376        _dof->setMaxHPR(osg::Vec3(osg::inDegrees(rangeYaw.max),osg::inDegrees(rangePitch.max),osg::inDegrees(rangeRoll.max)));
377        _dof->setCurrentHPR(osg::Vec3(osg::inDegrees(rangeYaw.current),osg::inDegrees(rangePitch.current),osg::inDegrees(rangeRoll.current)));
378        _dof->setIncrementHPR(osg::Vec3(osg::inDegrees(rangeYaw.increment),osg::inDegrees(rangePitch.increment),osg::inDegrees(rangeRoll.increment)));
379
380        //scales:
381        _dof->setMinScale(osg::Vec3(rangeScaleX.min,rangeScaleY.min,rangeScaleZ.min));
382        _dof->setMaxScale(osg::Vec3(rangeScaleX.max,rangeScaleY.max,rangeScaleZ.max));
383        _dof->setCurrentScale(osg::Vec3(rangeScaleX.current,rangeScaleY.current,rangeScaleZ.current));
384        _dof->setIncrementScale(osg::Vec3(rangeScaleX.increment,rangeScaleY.increment,rangeScaleZ.increment));
385
386        // compute axis.
387        osg::Vec3 xAxis = pointOnXAxis - localOrigin;
388        osg::Vec3 xyPlaneVector = pointInXYPlane - localOrigin;
389        osg::Vec3 zAxis = xAxis ^ xyPlaneVector;
390        osg::Vec3 yAxis = zAxis ^ xAxis;
391
392        // normalize
393        float length_x = xAxis.normalize();
394        float length_y = yAxis.normalize();
395        float length_z = zAxis.normalize();
396
397        if ((length_x*length_y*length_z)==0.0f)
398        {
399            OSG_NOTICE<<"Warning: OpenFlight DegreeOfFreedom::readRecord() found erroneous axis definition:"<<std::endl;
400            OSG_NOTICE<<"    localOrigin="<<localOrigin<<std::endl;
401            OSG_NOTICE<<"    pointOnXAxis="<<pointOnXAxis<<std::endl;
402            OSG_NOTICE<<"    pointInXYPlane="<<pointInXYPlane<<std::endl;
403
404            xAxis.set(1.0f,0.0f,0.0f);
405            yAxis.set(0.0f,1.0f,0.0f);
406            zAxis.set(0.0f,0.0f,1.0f);
407        }
408
409        // scale origin
410        osg::Vec3 origin = localOrigin * document.unitScale();
411
412        // create putmatrix
413        osg::Matrix inv_putmat(xAxis.x(), xAxis.y(), xAxis.z(), 0.0,
414                               yAxis.x(), yAxis.y(), yAxis.z(), 0.0,
415                               zAxis.x(), zAxis.y(), zAxis.z(), 0.0,
416                               origin.x(), origin.y(), origin.z(), 1.0);
417
418
419        _dof->setInversePutMatrix(inv_putmat);
420        _dof->setPutMatrix(osg::Matrix::inverse(inv_putmat));
421
422        _dof->setLimitationFlags(flags);
423        _dof->setAnimationOn(document.getDefaultDOFAnimationState());
424//      _dof->setHPRMultOrder(osgSim::DOFTransform::HPR);
425
426        // Add this implementation to parent implementation.
427        if (_parent.valid())
428            _parent->addChild(*_dof);
429    }
430
431    Range readRange(RecordInputStream& in) const
432    {
433        Range range;
434        range.min = in.readFloat64();
435        range.max = in.readFloat64();
436        range.current = in.readFloat64();
437        range.increment = in.readFloat64();
438
439        // Extend valid range (See Creator help on DOF).
440        if (range.current < range.min) range.min = range.current;
441        if (range.current > range.max) range.max = range.current;
442
443        const float64 epsilon = 1.0e-7;
444        if (fabs(range.max-range.min) < epsilon)
445            range.increment = 0;
446
447        return range;
448    }
449
450    bool valid(const osg::Vec3d& v) const
451    {
452        const osg::Vec3d bad(-1.0e8,-1.0e8,-1.0e8);
453        const float64 epsilon = 1.0e-7;
454
455        return (fabs(v.x()-bad.x()) > epsilon) ||
456               (fabs(v.y()-bad.y()) > epsilon) ||
457               (fabs(v.z()-bad.z()) > epsilon);
458    }
459};
460
461REGISTER_FLTRECORD(DegreeOfFreedom, DOF_OP)
462
463
464
465/** LevelOfDetail - To recreate the LevelOfDetail record in OSG we have to create a LOD node with one Group node under it.
466 *  OSG representation Children of the LevelOfDetail record will be added to
467*/
468class LevelOfDetail : public PrimaryRecord
469{
470    osg::ref_ptr<osg::LOD> _lod;
471    osg::ref_ptr<osg::Group> _impChild0;
472
473public:
474
475    LevelOfDetail() {}
476
477    META_Record(LevelOfDetail)
478
479    META_setID(_lod)
480    META_setComment(_lod)
481    META_setMultitexture(_lod)
482    META_addChild(_impChild0)
483    META_dispose(_lod)
484
485protected:
486
487    virtual ~LevelOfDetail() {}
488    virtual void readRecord(RecordInputStream& in, Document& document)
489    {
490        std::string id = in.readString(8);
491        in.forward(4);
492        float64 switchInDistance = in.readFloat64();
493        float64 switchOutDistance = in.readFloat64();
494        /*int16 specialEffectID1 =*/ in.readInt16();
495        /*int16 specialEffectID2 =*/ in.readInt16();
496        /*uint32 flags =*/ in.readUInt32();
497        osg::Vec3d center = in.readVec3d();
498
499        _lod = new osg::LOD;
500        _lod->setName(id);
501        _lod->setCenter(center*document.unitScale());
502
503        _impChild0 = new osg::Group;
504        _impChild0->setName("LOD child0");
505
506        // Add child to lod.
507        _lod->addChild(_impChild0.get(),
508             (float)switchOutDistance * document.unitScale(),
509             (float)switchInDistance * document.unitScale());
510
511        // Add this implementation to parent implementation.
512        if (_parent.valid())
513            _parent->addChild(*_lod);
514    }
515
516};
517
518REGISTER_FLTRECORD(LevelOfDetail, LOD_OP)
519
520
521
522/** OldLevelOfDetail
523  */
524class OldLevelOfDetail : public PrimaryRecord
525{
526    osg::ref_ptr<osg::LOD> _lod;
527    osg::ref_ptr<osg::Group> _impChild0;
528
529public:
530
531    OldLevelOfDetail() {}
532
533    META_Record(OldLevelOfDetail)
534
535    META_setID(_lod)
536    META_setComment(_lod)
537    META_setMultitexture(_lod)
538    META_addChild(_impChild0)
539    META_dispose(_lod)
540
541protected:
542
543    virtual ~OldLevelOfDetail() {}
544    virtual void readRecord(RecordInputStream& in, Document& document)
545    {
546        std::string id = in.readString(8);
547        uint32 switchInDistance = in.readUInt32();
548        uint32 switchOutDistance = in.readUInt32();
549        /*int16 specialEffectID1 =*/ in.readInt16();
550        /*int16 specialEffectID2 =*/ in.readInt16();
551        /*uint32 flags =*/ in.readUInt32();
552
553        osg::Vec3 center;
554        center.x() = (float)in.readInt32();
555        center.y() = (float)in.readInt32();
556        center.z() = (float)in.readInt32();
557
558        _lod = new osg::LOD;
559        _lod->setName(id);
560        _lod->setCenter(center*document.unitScale());
561        _lod->setRange(0, (float)switchOutDistance * document.unitScale(),
562                          (float)switchInDistance * document.unitScale());
563
564        // Add child to lod.
565        _impChild0 = new osg::Group;
566        _lod->addChild(_impChild0.get());
567
568        // Add this implementation to parent implementation.
569        if (_parent.valid())
570            _parent->addChild(*_lod);
571    }
572
573};
574
575REGISTER_FLTRECORD(OldLevelOfDetail, OLD_LOD_OP)
576
577
578
579/** Switch
580*/
581class Switch : public PrimaryRecord
582{
583    uint32 _currentMask;
584    uint32 _numberOfMasks;
585    uint32 _wordsInMask;
586    std::vector<uint32> _masks;
587
588    osg::ref_ptr<osgSim::MultiSwitch> _multiSwitch;
589
590public:
591
592    Switch() {}
593
594    META_Record(Switch)
595
596    META_setID(_multiSwitch)
597    META_setComment(_multiSwitch)
598    META_setMultitexture(_multiSwitch)
599    META_dispose(_multiSwitch)
600
601    virtual void addChild(osg::Node& child)
602    {
603        if (_multiSwitch.valid())
604        {
605            unsigned int nChild = _multiSwitch->getNumChildren();
606            for (unsigned int nMask=0; nMask<_numberOfMasks; ++nMask)
607            {
608                // test if this child is active in the current mask (itMask)
609                unsigned int nMaskBit = nChild % 32;
610                unsigned int nMaskWord = nMask * _wordsInMask + nChild / 32;
611                _multiSwitch->setValue(nMask, nChild, (_masks[nMaskWord] & (uint32(1) << nMaskBit))!=0 );
612            }
613
614            _multiSwitch->addChild(&child);
615        }
616    }
617
618    virtual void setMultiSwitchValueName(unsigned int switchSet, const std::string& name)
619    {
620        if (_multiSwitch.valid())
621        {
622            _multiSwitch->setValueName(switchSet, name);
623        }
624    }
625
626protected:
627
628    virtual ~Switch() {}
629    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
630    {
631        std::string id = in.readString(8);
632        in.forward(4);
633        _currentMask = in.readUInt32();
634        _numberOfMasks = in.readUInt32();
635        _wordsInMask = in.readUInt32();
636
637        _multiSwitch = new osgSim::MultiSwitch;
638        _multiSwitch->setName(id);
639
640        /* Example:
641        | word #0 || word #1 || word #2 |     <- Mask #0
642        | word #0 || word #1 || word #2 |     <- Mask #1
643        In this example numberOfMasks=2 and wordsInMask=3, currentMask can be 0 or 1.
644        */
645
646        for (unsigned int n=0; n<_numberOfMasks*_wordsInMask; n++)
647        {
648            uint32 maskWord = in.readUInt32();
649            _masks.push_back(maskWord);
650        }
651
652        _multiSwitch->setActiveSwitchSet(_currentMask);
653
654        // Add this implementation to parent implementation.
655        if (_parent.valid())
656            _parent->addChild(*_multiSwitch);
657    }
658};
659
660REGISTER_FLTRECORD(Switch, SWITCH_OP)
661
662
663
664/** ExternalReference
665*/
666class ExternalReference : public PrimaryRecord
667{
668    osg::ref_ptr<osg::ProxyNode> _external;
669
670    // Parent pool override flags
671    static const unsigned long COLOR_PALETTE_OVERRIDE        = 0x80000000u >> 0;
672    static const unsigned long MATERIAL_PALETTE_OVERRIDE     = 0x80000000u >> 1;
673    static const unsigned long TEXTURE_PALETTE_OVERRIDE      = 0x80000000u >> 2;
674    static const unsigned long LINE_STYLE_PALETTE_OVERRIDE   = 0x80000000u >> 3;
675    static const unsigned long SOUND_PALETTE_OVERRIDE        = 0x80000000u >> 4;
676    static const unsigned long LIGHT_SOURCE_PALETTE_OVERRIDE = 0x80000000u >> 5;
677    static const unsigned long LIGHT_POINT_PALETTE_OVERRIDE  = 0x80000000u >> 6;
678    static const unsigned long SHADER_PALETTE_OVERRIDE       = 0x80000000u >> 7;
679
680public:
681
682    ExternalReference() {}
683
684    META_Record(ExternalReference)
685
686    META_setID(_external)
687    META_setComment(_external)
688    META_setMultitexture(_external)
689    META_addChild(_external)
690    META_dispose(_external)
691
692protected:
693
694    virtual ~ExternalReference() {}
695    virtual void readRecord(RecordInputStream& in, Document& document)
696    {
697        std::string strFile = in.readString(200);
698
699        _external = new osg::ProxyNode;
700        _external->setCenterMode(osg::ProxyNode::USE_BOUNDING_SPHERE_CENTER);
701        _external->setFileName(0,strFile);
702
703        // Set parent pools as user data
704        if (document.version() >= VERSION_14_2)
705        {
706            in.forward(4);
707
708            uint32 mask = in.readUInt32(~0u);
709
710            // Possible bug in models with version number 15.4.1 ?
711            // Symptoms: Black trees in VegaPlayer town.
712            if (document.version() == 1541)
713                mask = ~0u;
714
715            ParentPools* parentPools = new ParentPools;
716
717            if ((mask & COLOR_PALETTE_OVERRIDE) == 0)
718                parentPools->setColorPool(document.getColorPool());
719
720            if ((mask & MATERIAL_PALETTE_OVERRIDE) == 0)
721                parentPools->setMaterialPool(document.getMaterialPool());
722
723            if ((mask & TEXTURE_PALETTE_OVERRIDE) == 0)
724                parentPools->setTexturePool(document.getTexturePool());
725
726            if ((document.version() >= VERSION_15_1) && ((mask & LIGHT_SOURCE_PALETTE_OVERRIDE) == 0))
727                parentPools->setLightSourcePool(document.getLightSourcePool());
728
729            if ((document.version() >= VERSION_15_8) && ((mask & LIGHT_POINT_PALETTE_OVERRIDE) == 0))
730                parentPools->setLPAppearancePool(document.getLightPointAppearancePool());
731
732            if ((document.version() >= VERSION_16_0) && ((mask & SHADER_PALETTE_OVERRIDE) == 0))
733                parentPools->setShaderPool(document.getShaderPool());
734
735            _external->setUserData(parentPools);
736        }
737
738        // Add this implementation to parent implementation.
739        if (_parent.valid())
740            _parent->addChild(*_external);
741    }
742
743};
744
745REGISTER_FLTRECORD(ExternalReference, EXTERNAL_REFERENCE_OP)
746
747
748
749/** InstanceDefinition
750*/
751class InstanceDefinition : public PrimaryRecord
752{
753    int _number;
754    osg::ref_ptr<osg::Group> _instanceDefinition;
755
756public:
757
758    InstanceDefinition():_number(0) {}
759
760    META_Record(InstanceDefinition)
761
762    META_setID(_instanceDefinition)
763    META_setComment(_instanceDefinition)
764    META_setMultitexture(_instanceDefinition)
765    META_addChild(_instanceDefinition)
766
767protected:
768
769    virtual ~InstanceDefinition() {}
770    virtual void readRecord(RecordInputStream& in, Document& document)
771    {
772        in.forward(2);
773        _number = (int)in.readUInt16();
774
775        _instanceDefinition = new osg::Group;
776    }
777
778    virtual void dispose(Document& document)
779    {
780        // Insert transform(s)
781        if (_matrix.valid())
782        {
783            osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform(*_matrix);
784            transform->setDataVariance(osg::Object::STATIC);
785            transform->addChild(_instanceDefinition.get());
786            _instanceDefinition = transform.get();
787        }
788
789        //  Add to instance definition table.
790        document.setInstanceDefinition(_number,_instanceDefinition.get());
791    }
792
793};
794
795REGISTER_FLTRECORD(InstanceDefinition, INSTANCE_DEFINITION_OP)
796
797
798
799/** InstanceReference
800  * The InstanceReference is a leaf record.
801  */
802class InstanceReference : public PrimaryRecord
803{
804public:
805
806    InstanceReference() {}
807
808    META_Record(InstanceReference)
809
810protected:
811
812    virtual ~InstanceReference() {}
813    virtual void readRecord(RecordInputStream& in, Document& document)
814    {
815        in.forward(2);
816        uint16 number = in.readUInt16();
817
818        // Get definition.
819        osg::Node* instance = document.getInstanceDefinition(number);
820
821        // Add this implementation to parent implementation.
822        if (_parent.valid() && instance)
823            _parent->addChild(*instance);
824    }
825};
826
827REGISTER_FLTRECORD(InstanceReference, INSTANCE_REFERENCE_OP)
828
829
830
831/** Extension
832*/
833class Extension : public PrimaryRecord
834{
835    osg::ref_ptr<osg::Group> _extension;
836
837public:
838
839    Extension() {}
840
841    META_Record(Extension)
842
843    META_setID(_extension)
844    META_setComment(_extension)
845    META_setMultitexture(_extension)
846    META_addChild(_extension)
847    META_dispose(_extension)
848
849protected:
850
851    virtual ~Extension() {}
852    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
853    {
854        std::string id = in.readString(8);
855        std::string siteId = in.readString(8);
856        in.forward(1);
857
858        _extension = new osg::Group;
859        _extension->setName(id);
860
861        // Add this implementation to parent implementation.
862        if (_parent.valid())
863            _parent->addChild(*_extension);
864    }
865};
866
867REGISTER_FLTRECORD(Extension, EXTENSION_OP)
868
869
870
871/** Object
872*/
873class Object : public PrimaryRecord
874{
875    static const unsigned int HIDE_IN_DAYLIGHT = 0x80000000u >> 0;
876    static const unsigned int HIDE_AT_DUSK     = 0x80000000u >> 1;
877    static const unsigned int HIDE_AT_NIGHT    = 0x80000000u >> 2;
878    static const unsigned int NO_ILLUMINATION  = 0x80000000u >> 3;
879    static const unsigned int FLAT_SHADED      = 0x80000000u >> 4;
880    static const unsigned int SHADOW_OBJECT    = 0x80000000u >> 5;
881
882    osg::ref_ptr<osg::Group> _object;
883
884public:
885
886    Object() {}
887
888    META_Record(Object)
889
890    META_setID(_object)
891    META_setComment(_object)
892    META_addChild(_object)
893
894protected:
895
896    virtual void readRecord(RecordInputStream& in, Document& document)
897    {
898        std::string id = in.readString(8);
899
900        _object = new osg::Group;
901        _object->setName(id);
902
903        if (document.getReadObjectRecordData())
904        {
905            osgSim::ObjectRecordData* ord = new osgSim::ObjectRecordData;
906            ord->_flags = in.readUInt32();
907            ord->_relativePriority = in.readInt16();
908            ord->_transparency = in.readUInt16();
909            ord->_effectID1 = in.readInt16();
910            ord->_effectID2 = in.readInt16();
911            ord->_significance = in.readInt16();
912
913            _object->setUserData( ord );
914        }
915        else
916        {
917            /*uint32 flags =*/ in.readUInt32();
918        }
919
920        // Postpone add-to-parent until we know a bit more.
921    }
922
923    virtual void dispose(Document& document)
924    {
925        if (!_parent.valid() || !_object.valid()) return;
926
927        // Is it safe to remove _object?
928        if (!document.getPreserveObject() && isSafeToRemoveObject() && !_matrix.valid())
929        {
930            // Add children of _object to parent.
931            // _object will not be added to graph.
932            for (unsigned int i=0; i<_object->getNumChildren(); ++i)
933            {
934                _parent->addChild(*(_object->getChild(i)));
935            }
936        }
937        else
938        {
939            _parent->addChild(*_object);
940        }
941
942        // Insert transform(s)
943        if (_matrix.valid())
944        {
945            insertMatrixTransform(*_object,*_matrix,_numberOfReplications);
946        }
947    }
948
949    bool isSafeToRemoveObject() const
950    {
951        // The following tests need a valid parent.
952        if (_parent.valid())
953        {
954            // LODs adds an empty child group so it is safe to remove this object record.
955            if (typeid(*_parent)==typeid(flt::LevelOfDetail))
956                return true;
957
958            if (typeid(*_parent)==typeid(flt::OldLevelOfDetail))
959                return true;
960
961            // If parent is a Group record we have to check for animation.
962            Group* parentGroup = dynamic_cast<flt::Group*>(_parent.get());
963            if (parentGroup && !parentGroup->hasAnimation())
964                return true;
965        }
966
967        return false;
968    }
969
970};
971
972REGISTER_FLTRECORD(Object, OBJECT_OP)
973
974
975
976/** LightSource
977*/
978class LightSource : public PrimaryRecord
979{
980    static const unsigned int ENABLED = 0x80000000u >> 0;
981    static const unsigned int GLOBAL  = 0x80000000u >> 1;
982    static const unsigned int EXPORT  = 0x80000000u >> 3;
983
984    osg::ref_ptr<osg::LightSource> _lightSource;
985
986public:
987
988    LightSource() {}
989
990    META_Record(LightSource)
991
992    META_setID(_lightSource)
993    META_setComment(_lightSource)
994    META_dispose(_lightSource)
995
996protected:
997
998    virtual ~LightSource() {}
999    virtual void readRecord(RecordInputStream& in, Document& document)
1000    {
1001        std::string id = in.readString(8);
1002        in.forward(4);
1003        int32 index = in.readInt32();
1004        in.forward(4);
1005        uint32 flags = in.readUInt32();
1006        in.forward(4);
1007        osg::Vec3d pos = in.readVec3d();
1008        float32 yaw = in.readFloat32();
1009        float32 pitch = in.readFloat32();
1010
1011        _lightSource = new osg::LightSource;
1012        _lightSource->setName(id);
1013
1014        LightSourcePool* pool = document.getOrCreateLightSourcePool();
1015        osg::Light* lightFromPool = pool->get(index);
1016        if (lightFromPool)
1017        {
1018            // Make a clone of light in pool.
1019            osg::Light* light = new osg::Light(*lightFromPool);
1020
1021            // TODO: Find a better way to set light number.
1022            light->setLightNum(1);
1023
1024            // Position
1025            float w = lightFromPool->getPosition().w();
1026            if (w > 0.0) // positional light?
1027                light->setPosition(osg::Vec4(pos,w));
1028
1029            // Apply yaw and pitch for infinite and spot light.
1030            if ((w==0.0) || (light->getSpotCutoff()<180.0))
1031            {
1032                // TODO: What direction is zero yaw and pitch?
1033                osg::Quat rotation = ( osg::Quat(osg::inDegrees(double(yaw)),osg::Vec3(0.0,0.0,1.0)) *
1034                                       osg::Quat(osg::inDegrees(double(pitch)),osg::Vec3(1.0,0.0,0.0)) );
1035                light->setDirection(rotation*osg::Vec3(0.0,1.0,0.0));
1036            }
1037
1038            _lightSource->setLight(light);
1039            _lightSource->setLocalStateSetModes((flags & ENABLED) ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
1040
1041            // Global light.
1042            if (flags & GLOBAL)
1043            {
1044                // Apply light source to header node.
1045                osg::Node* header = document.getHeaderNode();
1046                if (header)
1047                    _lightSource->setStateSetModes(*(header->getOrCreateStateSet()),osg::StateAttribute::ON);
1048            }
1049        }
1050
1051        if (_parent.valid())
1052            _parent->addChild(*_lightSource);
1053    }
1054};
1055
1056REGISTER_FLTRECORD(LightSource, LIGHT_SOURCE_OP)
1057
1058
1059
1060} // end namespace
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
Note: See TracBrowser for help on using the browser.