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

Revision 10283, 32.6 kB (checked in by robert, 6 years ago)

From Gregory Jaegy and Robert Osfield, added support for static linking of OpenFlight? plugin

  • 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
[10283]156REGISTER_FLTRECORD(Header, HEADER_OP)
[5038]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
[10283]295REGISTER_FLTRECORD(Group, GROUP_OP)
[5038]296
297
[10283]298
[5038]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
[8563]317        float64 max;            // Maximum value with respect to the local coord system
[5038]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)
[7756]335    META_dispose(_dof)
[5038]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
[8385]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::notify(osg::NOTICE)<<"Warning: OpenFlight DegreeOfFreedom::readRecord() found erroneous axis definition:"<<std::endl;
400            osg::notify(osg::NOTICE)<<"    localOrigin="<<localOrigin<<std::endl;
401            osg::notify(osg::NOTICE)<<"    pointOnXAxis="<<pointOnXAxis<<std::endl;
402            osg::notify(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        }
[5038]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
[8385]418
[5038]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
[10283]461REGISTER_FLTRECORD(DegreeOfFreedom, DOF_OP)
[5038]462
463
[10283]464
[5038]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)
[7756]483    META_dispose(_lod)
[5038]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();
[5229]494        /*int16 specialEffectID1 =*/ in.readInt16();
495        /*int16 specialEffectID2 =*/ in.readInt16();
496        /*uint32 flags =*/ in.readUInt32();
[5038]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
[10283]518REGISTER_FLTRECORD(LevelOfDetail, LOD_OP)
[5038]519
520
[10283]521
[5038]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)
[7756]539    META_dispose(_lod)
[5038]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();
[5229]549        /*int16 specialEffectID1 =*/ in.readInt16();
550        /*int16 specialEffectID2 =*/ in.readInt16();
551        /*uint32 flags =*/ in.readUInt32();
[5038]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
[10283]575REGISTER_FLTRECORD(OldLevelOfDetail, OLD_LOD_OP)
[5038]576
577
[10283]578
[5038]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)
[7756]599    META_dispose(_multiSwitch)
[5038]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
618protected:
619
620    virtual ~Switch() {}
[5229]621    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
[5038]622    {
623        std::string id = in.readString(8);
624        in.forward(4);
625        _currentMask = in.readUInt32();
626        _numberOfMasks = in.readUInt32();
627        _wordsInMask = in.readUInt32();
628
629        _multiSwitch = new osgSim::MultiSwitch;
630        _multiSwitch->setName(id);
631
632        /* Example:
633        | word #0 || word #1 || word #2 |     <- Mask #0
634        | word #0 || word #1 || word #2 |     <- Mask #1
635        In this example numberOfMasks=2 and wordsInMask=3, currentMask can be 0 or 1.
636        */
637
638        for (unsigned int n=0; n<_numberOfMasks*_wordsInMask; n++)
639        {
640            uint32 maskWord = in.readUInt32();
641            _masks.push_back(maskWord);
642        }
643
644        _multiSwitch->setActiveSwitchSet(_currentMask);
645
646        // Add this implementation to parent implementation.
647        if (_parent.valid())
648            _parent->addChild(*_multiSwitch);
649    }
650};
651
[10283]652REGISTER_FLTRECORD(Switch, SWITCH_OP)
[5038]653
654
[10283]655
[5038]656/** ExternalReference
657*/
658class ExternalReference : public PrimaryRecord
659{
[5136]660    osg::ref_ptr<osg::ProxyNode> _external;
[5038]661
[5236]662    // Parent pool override flags
663    static const unsigned long COLOR_PALETTE_OVERRIDE        = 0x80000000u >> 0;
664    static const unsigned long MATERIAL_PALETTE_OVERRIDE     = 0x80000000u >> 1;
665    static const unsigned long TEXTURE_PALETTE_OVERRIDE      = 0x80000000u >> 2;
666    static const unsigned long LINE_STYLE_PALETTE_OVERRIDE   = 0x80000000u >> 3;
667    static const unsigned long SOUND_PALETTE_OVERRIDE        = 0x80000000u >> 4;
668    static const unsigned long LIGHT_SOURCE_PALETTE_OVERRIDE = 0x80000000u >> 5;
669    static const unsigned long LIGHT_POINT_PALETTE_OVERRIDE  = 0x80000000u >> 6;
670    static const unsigned long SHADER_PALETTE_OVERRIDE       = 0x80000000u >> 7;
671
[5038]672public:
673
674    ExternalReference() {}
675
676    META_Record(ExternalReference)
677
678    META_setID(_external)
679    META_setComment(_external)
680    META_setMultitexture(_external)
681    META_addChild(_external)
[7756]682    META_dispose(_external)
[5038]683
684protected:
685
686    virtual ~ExternalReference() {}
[5236]687    virtual void readRecord(RecordInputStream& in, Document& document)
[5038]688    {
689        std::string strFile = in.readString(200);
690
[5136]691        _external = new osg::ProxyNode;
692        _external->setCenterMode(osg::ProxyNode::USE_BOUNDING_SPHERE_CENTER);
693        _external->setFileName(0,strFile);
[5038]694
[5236]695        // Set parent pools as user data
[5281]696        if (document.version() >= VERSION_14_2)
697        {
[6906]698            in.forward(4);
[5236]699
[9573]700            uint32 mask = in.readUInt32(~0u);
[5281]701
702            // Possible bug in models with version number 15.4.1 ?
703            // Symptoms: Black trees in VegaPlayer town.
704            if (document.version() == 1541)
[9573]705                mask = ~0u;
[5281]706
[6091]707            ParentPools* parentPools = new ParentPools;
708
709            if ((mask & COLOR_PALETTE_OVERRIDE) == 0)
710                parentPools->setColorPool(document.getColorPool());
711
712            if ((mask & MATERIAL_PALETTE_OVERRIDE) == 0)
713                parentPools->setMaterialPool(document.getMaterialPool());
714
715            if ((mask & TEXTURE_PALETTE_OVERRIDE) == 0)
716                parentPools->setTexturePool(document.getTexturePool());
717
718            if ((document.version() >= VERSION_15_1) && ((mask & LIGHT_SOURCE_PALETTE_OVERRIDE) == 0))
719                parentPools->setLightSourcePool(document.getLightSourcePool());
720
721            if ((document.version() >= VERSION_15_8) && ((mask & LIGHT_POINT_PALETTE_OVERRIDE) == 0))
722                parentPools->setLPAppearancePool(document.getLightPointAppearancePool());
723
724            if ((document.version() >= VERSION_16_0) && ((mask & SHADER_PALETTE_OVERRIDE) == 0))
725                parentPools->setShaderPool(document.getShaderPool());
726
727            _external->setUserData(parentPools);
[5281]728        }
729
[5038]730        // Add this implementation to parent implementation.
731        if (_parent.valid())
732            _parent->addChild(*_external);
733    }
734
735};
736
[10283]737REGISTER_FLTRECORD(ExternalReference, EXTERNAL_REFERENCE_OP)
[5038]738
739
[10283]740
[5038]741/** InstanceDefinition
742*/
743class InstanceDefinition : public PrimaryRecord
744{
[7756]745    int _number;
[5038]746    osg::ref_ptr<osg::Group> _instanceDefinition;
747
748public:
749
[7756]750    InstanceDefinition():_number(0) {}
[5038]751
752    META_Record(InstanceDefinition)
753
754    META_setID(_instanceDefinition)
755    META_setComment(_instanceDefinition)
756    META_setMultitexture(_instanceDefinition)
757    META_addChild(_instanceDefinition)
758
759protected:
760
761    virtual ~InstanceDefinition() {}
762    virtual void readRecord(RecordInputStream& in, Document& document)
763    {
764        in.forward(2);
[7756]765        _number = (int)in.readUInt16();
[5038]766
767        _instanceDefinition = new osg::Group;
[7756]768    }
[5038]769
[7756]770    virtual void dispose(Document& document)
771    {
772        // Insert transform(s)
773        if (_matrix.valid())
774        {
775            osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform(*_matrix);
776            transform->setDataVariance(osg::Object::STATIC);
777            transform->addChild(_instanceDefinition.get());
778            _instanceDefinition = transform.get();
779        }
780
[5038]781        //  Add to instance definition table.
[7756]782        document.setInstanceDefinition(_number,_instanceDefinition.get());
[5038]783    }
[7756]784
[5038]785};
786
[10283]787REGISTER_FLTRECORD(InstanceDefinition, INSTANCE_DEFINITION_OP)
[5038]788
789
[10283]790
[5038]791/** InstanceReference
792  * The InstanceReference is a leaf record.
793  */
794class InstanceReference : public PrimaryRecord
795{
796public:
797
798    InstanceReference() {}
799
800    META_Record(InstanceReference)
801
802protected:
803
804    virtual ~InstanceReference() {}
805    virtual void readRecord(RecordInputStream& in, Document& document)
806    {
807        in.forward(2);
808        uint16 number = in.readUInt16();
809
810        // Get definition.
811        osg::Node* instance = document.getInstanceDefinition(number);
812
813        // Add this implementation to parent implementation.
[7756]814        if (_parent.valid() && instance)
[5038]815            _parent->addChild(*instance);
816    }
817};
818
[10283]819REGISTER_FLTRECORD(InstanceReference, INSTANCE_REFERENCE_OP)
[5038]820
821
[10283]822
[5038]823/** Extension
824*/
825class Extension : public PrimaryRecord
826{
827    osg::ref_ptr<osg::Group> _extension;
828
829public:
830
831    Extension() {}
832
833    META_Record(Extension)
834
835    META_setID(_extension)
836    META_setComment(_extension)
837    META_setMultitexture(_extension)
838    META_addChild(_extension)
[7756]839    META_dispose(_extension)
[5038]840
841protected:
842
843    virtual ~Extension() {}
[5229]844    virtual void readRecord(RecordInputStream& in, Document& /*document*/)
[5038]845    {
846        std::string id = in.readString(8);
847        std::string siteId = in.readString(8);
848        in.forward(1);
849
850        _extension = new osg::Group;
851        _extension->setName(id);
852
853        // Add this implementation to parent implementation.
854        if (_parent.valid())
855            _parent->addChild(*_extension);
856    }
857};
858
[10283]859REGISTER_FLTRECORD(Extension, EXTENSION_OP)
[5038]860
861
[10283]862
[5528]863/** Object
864*/
865class Object : public PrimaryRecord
866{
867    static const unsigned int HIDE_IN_DAYLIGHT = 0x80000000u >> 0;
868    static const unsigned int HIDE_AT_DUSK     = 0x80000000u >> 1;
869    static const unsigned int HIDE_AT_NIGHT    = 0x80000000u >> 2;
870    static const unsigned int NO_ILLUMINATION  = 0x80000000u >> 3;
871    static const unsigned int FLAT_SHADED      = 0x80000000u >> 4;
872    static const unsigned int SHADOW_OBJECT    = 0x80000000u >> 5;
873
874    osg::ref_ptr<osg::Group> _object;
875
876public:
877
878    Object() {}
879
880    META_Record(Object)
881
882    META_setID(_object)
883    META_setComment(_object)
[7756]884    META_addChild(_object)
[5528]885
[7756]886protected:
887
888    virtual void readRecord(RecordInputStream& in, Document& document)
[5539]889    {
[7756]890        std::string id = in.readString(8);
[5539]891
[7756]892        _object = new osg::Group;
893        _object->setName(id);
894
[7931]895        if (document.getReadObjectRecordData())
896        {
897            osgSim::ObjectRecordData* ord = new osgSim::ObjectRecordData;
898            ord->_flags = in.readUInt32();
899            ord->_relativePriority = in.readInt16();
900            ord->_transparency = in.readUInt16();
901            ord->_effectID1 = in.readInt16();
902            ord->_effectID2 = in.readInt16();
903            ord->_significance = in.readInt16();
904
905            _object->setUserData( ord );
906        }
907        else
908        {
909            /*uint32 flags =*/ in.readUInt32();
910        }
911       
[7756]912        // Postpone add-to-parent until we know a bit more.
[5539]913    }
914
[7756]915    virtual void dispose(Document& document)
[5528]916    {
[7756]917        if (!_parent.valid() || !_object.valid()) return;
[5528]918
[7756]919        // Is it safe to remove _object?
920        if (!document.getPreserveObject() && isSafeToRemoveObject() && !_matrix.valid())
921        {
922            // Add children of _object to parent.
923            // _object will not be added to graph.
924            for (unsigned int i=0; i<_object->getNumChildren(); ++i)
925            {
926                _parent->addChild(*(_object->getChild(i)));
927            }
928        }
929        else
930        {
931            _parent->addChild(*_object);
932        }
[5528]933
[7756]934        // Insert transform(s)
935        if (_matrix.valid())
936        {
937            insertMatrixTransform(*_object,*_matrix,_numberOfReplications);
938        }
939    }
[5528]940
[7756]941    bool isSafeToRemoveObject() const
[5528]942    {
[7756]943        // The following tests need a valid parent.
944        if (_parent.valid())
[5528]945        {
946            // LODs adds an empty child group so it is safe to remove this object record.
947            if (typeid(*_parent)==typeid(flt::LevelOfDetail))
[7756]948                return true;
[5528]949
950            if (typeid(*_parent)==typeid(flt::OldLevelOfDetail))
[7756]951                return true;
[5528]952
953            // If parent is a Group record we have to check for animation.
954            Group* parentGroup = dynamic_cast<flt::Group*>(_parent.get());
955            if (parentGroup && !parentGroup->hasAnimation())
[7756]956                return true;
[5528]957        }
958
[7756]959        return false;
[5528]960    }
[7756]961
[5528]962};
963
[10283]964REGISTER_FLTRECORD(Object, OBJECT_OP)
[5528]965
[6091]966
[10283]967
[6091]968/** LightSource
969*/
970class LightSource : public PrimaryRecord
971{
972    static const unsigned int ENABLED = 0x80000000u >> 0;
973    static const unsigned int GLOBAL  = 0x80000000u >> 1;
974    static const unsigned int EXPORT  = 0x80000000u >> 3;
975
976    osg::ref_ptr<osg::LightSource> _lightSource;
977
978public:
979
980    LightSource() {}
981
982    META_Record(LightSource)
983
984    META_setID(_lightSource)
985    META_setComment(_lightSource)
[7756]986    META_dispose(_lightSource)
[6091]987
988protected:
989
990    virtual ~LightSource() {}
991    virtual void readRecord(RecordInputStream& in, Document& document)
992    {
993        std::string id = in.readString(8);
994        in.forward(4);
995        int32 index = in.readInt32();
996        in.forward(4);
997        uint32 flags = in.readUInt32();
998        in.forward(4);
999        osg::Vec3d pos = in.readVec3d();
1000        float32 yaw = in.readFloat32();
1001        float32 pitch = in.readFloat32();
1002
1003        _lightSource = new osg::LightSource; 
1004        _lightSource->setName(id);
1005
1006        LightSourcePool* pool = document.getOrCreateLightSourcePool();
1007        osg::Light* lightFromPool = pool->get(index);
1008        if (lightFromPool)
1009        {
1010            // Make a clone of light in pool.
1011            osg::Light* light = new osg::Light(*lightFromPool);
1012
1013            // TODO: Find a better way to set light number.
1014            light->setLightNum(1);
1015
1016            // Position
1017            float w = lightFromPool->getPosition().w();
1018            if (w > 0.0) // positional light?
1019                light->setPosition(osg::Vec4(pos,w));
1020
1021            // Apply yaw and pitch for infinite and spot light.
1022            if ((w==0.0) || (light->getSpotCutoff()<180.0))
1023            {
1024                // TODO: What direction is zero yaw and pitch?
[6098]1025                osg::Quat rotation = ( osg::Quat(osg::inDegrees(double(yaw)),osg::Vec3(0.0,0.0,1.0)) *
1026                                       osg::Quat(osg::inDegrees(double(pitch)),osg::Vec3(1.0,0.0,0.0)) );
[6091]1027                light->setDirection(rotation*osg::Vec3(0.0,1.0,0.0));
1028            }
1029
1030            _lightSource->setLight(light);
1031            _lightSource->setLocalStateSetModes((flags & ENABLED) ? osg::StateAttribute::ON : osg::StateAttribute::OFF);
1032
1033            // Global light.
1034            if (flags & GLOBAL)
1035            {
1036                // Apply light source to header node.
1037                osg::Node* header = document.getHeaderNode();
1038                if (header)
1039                    _lightSource->setStateSetModes(*(header->getOrCreateStateSet()),osg::StateAttribute::ON);
1040            }
1041        }
1042
1043        if (_parent.valid())
1044            _parent->addChild(*_lightSource);
1045    }
1046};
1047
[10283]1048REGISTER_FLTRECORD(LightSource, LIGHT_SOURCE_OP)
[6091]1049
1050
[10283]1051
[5038]1052} // end namespace
[5122]1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
[5136]1065
1066
Note: See TracBrowser for help on using the browser.