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 (R) loader for OpenSceneGraph
16 //
17 //  Copyright (C) 2005-2007  Brede Johansen
18 //
19 
20 #include <assert.h>
21 #include <osg/Light>
22 #include <osg/Texture2D>
23 #include <osg/TexEnv>
24 #include <osg/BlendFunc>
25 #include <osgSim/LightPointNode>
26 #include <osgDB/ReadFile>
27 #include <osgDB/FileUtils>
28 #include "Registry.h"
29 #include "Document.h"
30 #include "AttrData.h"
31 #include "RecordInputStream.h"
32 
33 #if defined(OSG_GLES1_AVAILABLE) || defined(OSG_GLES2_AVAILABLE)
34     #define GL_RGB5                     0x8050
35     #define GL_RGBA4                    0x8056
36     #define GL_RGBA8                    0x8058
37     #define GL_RGBA12                   0x805A
38     #define GL_RGB12                    0x8053
39     #define GL_LUMINANCE12_ALPHA4       0x8046
40     #define GL_LUMINANCE12_ALPHA12      0x8047
41     #define GL_INTENSITY16              0x804D
42 #endif
43 
44 #if defined(OSG_GL3_AVAILABLE)
45     #define GL_LUMINANCE12_ALPHA4       0x8046
46     #define GL_LUMINANCE12_ALPHA12      0x8047
47     #define GL_INTENSITY16              0x804D
48 #endif
49 
50 namespace flt {
51 
52 class VertexPalette : public Record
53 {
54 public:
55 
VertexPalette()56     VertexPalette() {}
57 
58     META_Record(VertexPalette)
59 
60 protected:
61 
~VertexPalette()62     virtual ~VertexPalette() {}
63 
readRecord(RecordInputStream & in,Document & document)64     virtual void readRecord(RecordInputStream& in, Document& document)
65     {
66         uint32 paletteSize = in.readUInt32();
67 
68         // Entries in vertex pool found by offset from start of this record.
69         const uint32 RECORD_HEADER_SIZE = 4;
70         const uint32 OFFSET = RECORD_HEADER_SIZE+sizeof(paletteSize);
71 
72         std::string buffer(paletteSize,'\0');
73         if (OFFSET < paletteSize)
74         {
75             in.read(&buffer[OFFSET], paletteSize-OFFSET);
76         }
77 
78         // Keep a copy of the vertex pool in memory for later reference.
79         document.setVertexPool(new VertexPool(buffer));
80     }
81 };
82 
83 REGISTER_FLTRECORD(VertexPalette, VERTEX_PALETTE_OP)
84 
85 
86 
87 class ColorPalette : public Record
88 {
89 public:
90 
ColorPalette()91     ColorPalette() {}
92 
93     META_Record(ColorPalette)
94 
95 protected:
96 
~ColorPalette()97     virtual ~ColorPalette() {}
98 
readRecord(RecordInputStream & in,Document & document)99     virtual void readRecord(RecordInputStream& in, Document& document)
100     {
101         if (document.getColorPoolParent())
102             // Using parent's color pool -- ignore this record.
103             return;
104 
105         if (document.version() > VERSION_13)
106         {
107             bool oldVersion = false;
108             bool colorNameSection = in.getRecordSize() > 4228;
109             int maxColors = (document.version()>=VERSION_15_1) ? 1024 : 512;
110 
111             // It might be less.
112             if (!colorNameSection)
113             {
114                 // Max colors calculated by record size.
115                 int maxColorsByRecordSize = (in.getRecordBodySize()-128) / 4;
116                 if (maxColorsByRecordSize < maxColors)
117                     maxColors = maxColorsByRecordSize;
118             }
119 
120             ColorPool* cp = new ColorPool(oldVersion,maxColors);
121             document.setColorPool(cp);
122 
123             in.forward(128);
124             for (int i=0; i<maxColors; i++)
125             {
126                 uint8 alpha = in.readUInt8(1);
127                 uint8 blue  = in.readUInt8(1);
128                 uint8 green = in.readUInt8(1);
129                 uint8 red   = in.readUInt8(1);
130 
131                 (*cp)[i] = osg::Vec4((float)red/255,(float)green/255,(float)blue/255,(float)alpha/255);
132             }
133         }
134         else // version <= 13
135         {
136             bool oldVersion = true;
137             int maxColors = 32+56;
138 
139             ColorPool* cp = new ColorPool(oldVersion,maxColors);
140             document.setColorPool(cp);
141 
142             // variable intensity
143             for (int i=0; i < 32; i++)
144             {
145                 uint16 red   = in.readUInt16(1);
146                 uint16 green = in.readUInt16(1);
147                 uint16 blue  = in.readUInt16(1);
148                 (*cp)[i] = osg::Vec4((float)red/255,(float)green/255,(float)blue/255,1);
149             }
150 
151             // fixed intensity
152             for (int i=0; i < 56; i++)
153             {
154                 uint16 red   = in.readUInt16(1);
155                 uint16 green = in.readUInt16(1);
156                 uint16 blue  = in.readUInt16(1);
157                 (*cp)[i+32] = osg::Vec4((float)red/255,(float)green/255,(float)blue/255,1);
158             }
159         }
160     }
161 };
162 
163 
164 REGISTER_FLTRECORD(ColorPalette, COLOR_PALETTE_OP)
165 
166 
167 
168 class NameTable : public Record
169 {
170 public:
171 
NameTable()172     NameTable() {}
173 
174     META_Record(NameTable)
175 
176 protected:
177 
~NameTable()178     virtual ~NameTable() {}
179 
readRecord(RecordInputStream &,Document &)180     virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/)
181     {
182     }
183 };
184 
185 REGISTER_FLTRECORD(NameTable, NAME_TABLE_OP)
186 
187 
188 
189 class MaterialPalette : public Record
190 {
191 public:
192 
MaterialPalette()193     MaterialPalette() {}
194 
195     META_Record(MaterialPalette)
196 
197 protected:
198 
~MaterialPalette()199     virtual ~MaterialPalette() {}
200 
readRecord(RecordInputStream & in,Document & document)201     virtual void readRecord(RecordInputStream& in, Document& document)
202     {
203         if (document.getMaterialPoolParent())
204             // Using parent's material pool -- ignore this record.
205             return;
206 
207         int32 index = in.readInt32();
208         std::string name = in.readString(12);
209         /*uint32 flags =*/ in.readUInt32();
210         osg::Vec3f ambient = in.readVec3f();
211         osg::Vec3f diffuse = in.readVec3f();
212         osg::Vec3f specular = in.readVec3f();
213         osg::Vec3f emissive = in.readVec3f();
214         float32 shininess = in.readFloat32();
215         float32 alpha = in.readFloat32();
216 
217         osg::Material* material = new osg::Material;
218         material->setName(name);
219         material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(ambient,alpha));
220         material->setDiffuse (osg::Material::FRONT_AND_BACK,osg::Vec4(diffuse,alpha));
221         material->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(specular,alpha));
222         material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(emissive,alpha));
223 
224         if (shininess>=0.0f)
225         {
226             material->setShininess(osg::Material::FRONT_AND_BACK,shininess);
227         }
228         else
229         {
230             OSG_INFO<<"Warning: OpenFlight shininess value out of range: "<<shininess<<std::endl;
231         }
232 
233         MaterialPool* mp = document.getOrCreateMaterialPool();
234         (*mp)[index] = material;
235     }
236 };
237 
238 REGISTER_FLTRECORD(MaterialPalette, MATERIAL_PALETTE_OP)
239 
240 
241 
242 class OldMaterialPalette : public Record
243 {
244 public:
245 
OldMaterialPalette()246     OldMaterialPalette() {}
247 
248     META_Record(OldMaterialPalette)
249 
250 protected:
251 
~OldMaterialPalette()252     virtual ~OldMaterialPalette() {}
253 
readRecord(RecordInputStream & in,Document & document)254     virtual void readRecord(RecordInputStream& in, Document& document)
255     {
256         if (document.getMaterialPoolParent())
257             // Using parent's material pool -- ignore this record.
258             return;
259 
260         for (int i=0; i < 64; i++)
261         {
262             osg::Vec3f ambient = in.readVec3f();
263             osg::Vec3f diffuse = in.readVec3f();
264             osg::Vec3f specular = in.readVec3f();
265             osg::Vec3f emissive = in.readVec3f();
266             float32 shininess = in.readFloat32();
267             float32 alpha = in.readFloat32();
268             /*uint32 flags =*/ in.readUInt32();
269             std::string name = in.readString(12);
270             in.forward(4*28);
271 
272             osg::Material* material = new osg::Material;
273             material->setAmbient(osg::Material::FRONT_AND_BACK,osg::Vec4(ambient,alpha));
274             material->setDiffuse (osg::Material::FRONT_AND_BACK,osg::Vec4(diffuse,alpha));
275             material->setSpecular(osg::Material::FRONT_AND_BACK,osg::Vec4(specular,alpha));
276             material->setEmission(osg::Material::FRONT_AND_BACK,osg::Vec4(emissive,alpha));
277 
278             if (shininess>=0.0f)
279             {
280                 material->setShininess(osg::Material::FRONT_AND_BACK,shininess);
281             }
282             else
283             {
284                 OSG_INFO<<"Warning: OpenFlight shininess value out of range: "<<shininess<<std::endl;
285             }
286 
287             MaterialPool* mp = document.getOrCreateMaterialPool();
288             (*mp)[i] = material;
289         }
290     }
291 
292 };
293 
294 REGISTER_FLTRECORD(OldMaterialPalette, OLD_MATERIAL_PALETTE_OP)
295 
296 
297 
298 class TexturePalette : public Record
299 {
300 public:
301 
TexturePalette()302     TexturePalette() {}
303 
304     META_Record(TexturePalette)
305 
306 protected:
307 
~TexturePalette()308     virtual ~TexturePalette() {}
309 
convertWrapMode(int32 attrWrapMode,const Document & document) const310     osg::Texture2D::WrapMode convertWrapMode(int32 attrWrapMode, const Document& document) const
311     {
312         osg::Texture2D::WrapMode osgWrapMode = osg::Texture2D::REPEAT;
313         switch (attrWrapMode)
314         {
315         case AttrData::WRAP_CLAMP:
316             if (document.getReplaceClampWithClampToEdge())
317                 osgWrapMode = osg::Texture2D::CLAMP_TO_EDGE;
318             else
319                 osgWrapMode = osg::Texture2D::CLAMP;
320             break;
321         case AttrData::WRAP_MIRRORED_REPEAT:
322             osgWrapMode = osg::Texture2D::MIRROR;
323             break;
324         case AttrData::WRAP_REPEAT:
325             osgWrapMode = osg::Texture2D::REPEAT;
326             break;
327         }
328 
329         return osgWrapMode;
330     }
331 
readTexture(const std::string & filename,const Document & document) const332     osg::StateSet* readTexture(const std::string& filename, const Document& document) const
333     {
334         osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile(filename,document.getOptions());
335         if (!image) return NULL;
336 
337         // Create stateset to hold texture and attributes.
338         osg::StateSet* stateset = new osg::StateSet;
339 
340         osg::Texture2D* texture = new osg::Texture2D;
341         texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT);
342         texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::REPEAT);
343         texture->setResizeNonPowerOfTwoHint(true);
344         texture->setImage(image.get());
345         stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
346 
347         // Since the .attr file is optional according to the OpenFlight spec, check to see
348         // if the file exists before reading it, to avoid printing an unnecessary warning.
349         std::string attrname = filename + ".attr";
350         if (!osgDB::fileExists(attrname))
351             return stateset;
352 
353         // Read optional attribute file
354         osg::ref_ptr<AttrData> attr = osgDB::readRefFile<AttrData>(attrname,document.getOptions());
355         if (attr.valid())
356         {
357             // Wrap mode
358             osg::Texture2D::WrapMode wrap_s = convertWrapMode(attr->wrapMode_u,document);
359             texture->setWrap(osg::Texture2D::WRAP_S,wrap_s);
360 
361             osg::Texture2D::WrapMode wrap_t = convertWrapMode(attr->wrapMode_v,document);
362             texture->setWrap(osg::Texture2D::WRAP_T,wrap_t);
363 
364             // Min filter
365             switch (attr->minFilterMode)
366             {
367             case AttrData::MIN_FILTER_POINT:
368                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
369                 break;
370             case AttrData::MIN_FILTER_BILINEAR:
371                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
372                 break;
373             case AttrData::MIN_FILTER_MIPMAP_POINT:
374                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_NEAREST);
375                 break;
376             case AttrData::MIN_FILTER_MIPMAP_LINEAR:
377                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_LINEAR);
378                 break;
379             case AttrData::MIN_FILTER_MIPMAP_BILINEAR:
380                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
381                 break;
382             case AttrData::MIN_FILTER_MIPMAP_TRILINEAR:
383                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR);
384                 break;
385             case AttrData::MIN_FILTER_BICUBIC:
386             case AttrData::MIN_FILTER_BILINEAR_GEQUAL:
387             case AttrData::MIN_FILTER_BILINEAR_LEQUAL:
388             case AttrData::MIN_FILTER_BICUBIC_GEQUAL:
389             case AttrData::MIN_FILTER_BICUBIC_LEQUAL:
390                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
391                 break;
392             default:
393                 texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR);
394                 break;
395             }
396 
397             // Mag filter
398             switch (attr->magFilterMode)
399             {
400             case AttrData::MAG_FILTER_POINT:
401                 texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
402                 break;
403             case AttrData::MAG_FILTER_BILINEAR:
404             case AttrData::MAG_FILTER_BILINEAR_GEQUAL:
405             case AttrData::MAG_FILTER_BILINEAR_LEQUAL:
406             case AttrData::MAG_FILTER_SHARPEN:
407             case AttrData::MAG_FILTER_BICUBIC:
408             case AttrData::MAG_FILTER_BICUBIC_GEQUAL:
409             case AttrData::MAG_FILTER_BICUBIC_LEQUAL:
410             case AttrData::MAG_FILTER_ADD_DETAIL:
411             case AttrData::MAG_FILTER_MODULATE_DETAIL:
412                 texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
413                 break;
414             }
415 
416             // Internal mode
417             switch(attr->intFormat)
418             {
419             case AttrData::INTERNAL_FORMAT_TX_I_12A_4:
420                 texture->setInternalFormat(GL_LUMINANCE12_ALPHA4);
421                 break;
422             case AttrData::INTERNAL_FORMAT_TX_IA_8:
423                 texture->setInternalFormat(GL_LUMINANCE_ALPHA);
424                 break;
425             case AttrData::INTERNAL_FORMAT_TX_RGB_5:
426                 texture->setInternalFormat(GL_RGB5);
427                 break;
428             case AttrData::INTERNAL_FORMAT_TX_RGBA_4:
429                 texture->setInternalFormat(GL_RGBA4);
430                 break;
431             case AttrData::INTERNAL_FORMAT_TX_IA_12:
432                 texture->setInternalFormat(GL_LUMINANCE12_ALPHA12);
433                 break;
434             case AttrData::INTERNAL_FORMAT_TX_RGBA_8:
435                 texture->setInternalFormat(GL_RGBA8);
436                 break;
437             case AttrData::INTERNAL_FORMAT_TX_RGBA_12:
438                 texture->setInternalFormat(GL_RGBA12);
439                 break;
440             case AttrData::INTERNAL_FORMAT_TX_I_16:
441                 texture->setInternalFormat(GL_INTENSITY16);
442                 break;
443             case AttrData::INTERNAL_FORMAT_TX_RGB_12:
444                 texture->setInternalFormat(GL_RGB12);
445                 break;
446             case AttrData::INTERNAL_FORMAT_DEFAULT:
447             default:
448                 // Do nothing, just use the image data format
449                 break;
450             }
451 
452             osg::TexEnv* texenv = new osg::TexEnv;
453             switch (attr->texEnvMode)
454             {
455             case AttrData::TEXENV_MODULATE:
456                 texenv->setMode(osg::TexEnv::MODULATE);
457                 break;
458             case AttrData::TEXENV_BLEND:
459                 texenv->setMode(osg::TexEnv::BLEND);
460                 break;
461             case AttrData::TEXENV_DECAL:
462                 texenv->setMode(osg::TexEnv::DECAL);
463                 break;
464             case AttrData::TEXENV_COLOR:
465                 texenv->setMode(osg::TexEnv::REPLACE);
466                 break;
467             case AttrData::TEXENV_ADD:
468                 texenv->setMode(osg::TexEnv::ADD);
469                 break;
470             }
471             stateset->setTextureAttribute(0, texenv);
472         }
473 
474         return stateset;
475     }
476 
readRecord(RecordInputStream & in,Document & document)477     virtual void readRecord(RecordInputStream& in, Document& document)
478     {
479         if (document.getTexturePoolParent())
480             // Using parent's texture pool -- ignore this record.
481             return;
482 
483         int maxLength = (document.version() < VERSION_14) ? 80 : 200;
484         std::string filename = in.readString(maxLength);
485         int32 index = in.readInt32(-1);
486         /*int32 x =*/ in.readInt32();
487         /*int32 y =*/ in.readInt32();
488 
489         // Need full path for unique key in local texture cache.
490         std::string pathname = osgDB::findDataFile(filename,document.getOptions());
491         if (pathname.empty())
492         {
493             OSG_WARN << "Can't find texture (" << index << ") " << filename << std::endl;
494             return;
495         }
496 
497         // Is texture in local cache?
498         osg::ref_ptr<osg::StateSet> stateset = flt::Registry::instance()->getTextureFromLocalCache(pathname);
499 
500         // Read file if not in cache.
501         if (!stateset.valid())
502         {
503             stateset = readTexture(pathname,document);
504 
505             // Add to texture cache.
506             flt::Registry::instance()->addTextureToLocalCache(pathname,stateset.get());
507         }
508 
509         // Add to texture pool.
510         TexturePool* tp = document.getOrCreateTexturePool();
511         (*tp)[index] = stateset;
512     }
513 };
514 
515 REGISTER_FLTRECORD(TexturePalette, TEXTURE_PALETTE_OP)
516 
517 
518 
519 class EyepointAndTrackplanePalette : public Record
520 {
521 public:
522 
EyepointAndTrackplanePalette()523     EyepointAndTrackplanePalette() {}
524 
525     META_Record(EyepointAndTrackplanePalette)
526 
527 protected:
528 
~EyepointAndTrackplanePalette()529     virtual ~EyepointAndTrackplanePalette() {}
530 
readRecord(RecordInputStream &,Document &)531     virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/) {}
532 };
533 
534 REGISTER_FLTRECORD(EyepointAndTrackplanePalette, EYEPOINT_AND_TRACKPLANE_PALETTE_OP)
535 
536 
537 
538 class LinkagePalette : public Record
539 {
540 public:
541 
LinkagePalette()542     LinkagePalette() {}
543 
544     META_Record(LinkagePalette)
545 
546 protected:
547 
~LinkagePalette()548     virtual ~LinkagePalette() {}
549 
readRecord(RecordInputStream &,Document &)550     virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/) {}
551 };
552 
553 REGISTER_FLTRECORD(LinkagePalette, LINKAGE_PALETTE_OP)
554 
555 
556 
557 class SoundPalette : public Record
558 {
559 public:
560 
SoundPalette()561     SoundPalette() {}
562 
563     META_Record(SoundPalette)
564 
565 protected:
566 
~SoundPalette()567     virtual ~SoundPalette() {}
568 
readRecord(RecordInputStream &,Document &)569     virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/) {}
570 };
571 
572 REGISTER_FLTRECORD(SoundPalette, SOUND_PALETTE_OP)
573 
574 
575 
576 class LightSourcePalette : public Record
577 {
578 public:
579 
LightSourcePalette()580     LightSourcePalette() {}
581 
582     META_Record(LightSourcePalette)
583 
584     enum LightType
585     {
586         INFINITE_LIGHT = 0,
587         LOCAL_LIGHT = 1,
588         SPOT_LIGHT = 2
589     };
590 
591 protected:
592 
~LightSourcePalette()593     virtual ~LightSourcePalette() {}
594 
readRecord(RecordInputStream & in,Document & document)595     virtual void readRecord(RecordInputStream& in, Document& document)
596     {
597         if (document.getLightSourcePoolParent())
598             // Using parent's texture pool -- ignore this record.
599             return;
600 
601         int32 index = in.readInt32(-1);
602         in.forward(2*4);
603         std::string name = in.readString(20);
604         in.forward(4);
605         osg::Vec4f ambient = in.readVec4f();
606         osg::Vec4f diffuse = in.readVec4f();
607         osg::Vec4f specular = in.readVec4f();
608         int32 type = in.readInt32();
609         in.forward(4*10);
610         float32 spotExponent = in.readFloat32();
611         float32 spotCutoff = in.readFloat32();
612         /*float32 yaw =*/ in.readFloat32();
613         /*float32 pitch =*/ in.readFloat32();
614         float32 constantAttenuation = in.readFloat32();
615         float32 linearAttenuation = in.readFloat32();
616         float32 quadraticAttenuation = in.readFloat32();
617         /*int32 active =*/ in.readInt32();
618 
619         osg::ref_ptr<osg::Light> light = new osg::Light;
620         light->setAmbient(ambient);
621         light->setDiffuse(diffuse);
622         light->setSpecular(specular);
623 
624         switch (type)
625         {
626         case INFINITE_LIGHT:
627             light->setPosition(osg::Vec4(0.0f,0.0f,1.0f,0.0f));
628             break;
629         case LOCAL_LIGHT:
630             light->setPosition(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
631             light->setConstantAttenuation(constantAttenuation);
632             light->setLinearAttenuation(linearAttenuation);
633             light->setQuadraticAttenuation(quadraticAttenuation);
634             break;
635         case SPOT_LIGHT:
636             light->setPosition(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
637             light->setDirection(osg::Vec3(0.0f,1.0f,0.0f));
638             light->setConstantAttenuation(constantAttenuation);
639             light->setLinearAttenuation(linearAttenuation);
640             light->setQuadraticAttenuation(quadraticAttenuation);
641             light->setSpotExponent(spotExponent);
642             light->setSpotCutoff(spotCutoff);
643             break;
644         }
645 
646         // Add to pool
647         LightSourcePool* pool = document.getOrCreateLightSourcePool();
648         (*pool)[index] = light.get();
649     }
650 };
651 
652 REGISTER_FLTRECORD(LightSourcePalette, LIGHT_SOURCE_PALETTE_OP)
653 
654 
655 
656 class LightPointAppearancePalette : public Record
657 {
658 public:
659 
LightPointAppearancePalette()660     LightPointAppearancePalette() {}
661 
662     META_Record(LightPointAppearancePalette)
663 
664 protected:
665 
~LightPointAppearancePalette()666     virtual ~LightPointAppearancePalette() {}
667 
readRecord(RecordInputStream & in,Document & document)668     virtual void readRecord(RecordInputStream& in, Document& document)
669     {
670         if (document.getLightPointAppearancePoolParent())
671             // Using parent's light point appearance pool -- ignore this record.
672             return;
673 
674         osg::ref_ptr<LPAppearance> appearance = new LPAppearance;
675 
676         in.forward(4);
677         appearance->name = in.readString(256);
678         appearance->index = in.readInt32(-1);
679         appearance->materialCode = in.readInt16();
680         appearance->featureID = in.readInt16();
681 
682         int32 backColorIndex = in.readInt32();
683         appearance->backColor = document.getColorPool() ?
684                             document.getColorPool()->getColor(backColorIndex) :
685                             osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
686 
687         appearance->displayMode = in.readInt32();
688         appearance->intensityFront = in.readFloat32();
689         appearance->intensityBack = in.readFloat32();
690         appearance->minDefocus = in.readFloat32();
691         appearance->maxDefocus = in.readFloat32();
692         appearance->fadingMode = in.readInt32();
693         appearance->fogPunchMode = in.readInt32();
694         appearance->directionalMode = in.readInt32();
695         appearance->rangeMode = in.readInt32();
696         appearance->minPixelSize = in.readFloat32();
697         appearance->maxPixelSize = in.readFloat32();
698         appearance->actualPixelSize = in.readFloat32();
699         appearance->transparentFalloffPixelSize = in.readFloat32();
700         appearance->transparentFalloffExponent = in.readFloat32();
701         appearance->transparentFalloffScalar = in.readFloat32();
702         appearance->transparentFalloffClamp = in.readFloat32();
703         appearance->fogScalar = in.readFloat32();
704         appearance->fogIntensity = in.readFloat32();
705         appearance->sizeDifferenceThreshold = in.readFloat32();
706         appearance->directionality = in.readInt32();
707         appearance->horizontalLobeAngle = in.readFloat32();
708         appearance->verticalLobeAngle = in.readFloat32();
709         appearance->lobeRollAngle = in.readFloat32();
710         appearance->directionalFalloffExponent = in.readFloat32();
711         appearance->directionalAmbientIntensity = in.readFloat32();
712         appearance->significance = in.readFloat32();
713         appearance->flags = in.readUInt32();
714         appearance->visibilityRange = in.readFloat32();
715         appearance->fadeRangeRatio = in.readFloat32();
716         appearance->fadeInDuration = in.readFloat32();
717         appearance->fadeOutDuration = in.readFloat32();
718         appearance->LODRangeRatio = in.readFloat32();
719         appearance->LODScale = in.readFloat32();
720 
721         if(document.version() > VERSION_15_8)
722             appearance->texturePatternIndex = in.readInt16(-1);
723         else
724            appearance->texturePatternIndex = -1;
725 
726         // The final short is reserved; don't bother reading it.
727 
728         // Add to pool
729         LightPointAppearancePool* lpaPool = document.getOrCreateLightPointAppearancePool();
730         (*lpaPool)[appearance->index] = appearance.get();
731     }
732 
733 };
734 
735 REGISTER_FLTRECORD(LightPointAppearancePalette, LIGHT_POINT_APPEARANCE_PALETTE_OP)
736 
737 
738 
739 class LightPointAnimationPalette : public Record
740 {
741 public:
742 
LightPointAnimationPalette()743     LightPointAnimationPalette() {}
744 
745     META_Record(LightPointAnimationPalette)
746 
747 protected:
748 
~LightPointAnimationPalette()749     virtual ~LightPointAnimationPalette() {}
750 
readRecord(RecordInputStream & in,Document & document)751     virtual void readRecord(RecordInputStream& in, Document& document)
752     {
753          if (document.getLightPointAnimationPoolParent())
754             // Using parent's light point animation pool -- ignore this record.
755             return;
756 
757         osg::ref_ptr<LPAnimation> animation = new LPAnimation;
758 
759         in.forward(4);
760         animation->name = in.readString(256);
761         animation->index = in.readInt32(-1);
762         // Rotating or strobe
763         animation->animationPeriod = in.readFloat32();
764         animation->animationPhaseDelay = in.readFloat32();
765         animation->animationEnabledPeriod = in.readFloat32();
766         animation->axisOfRotation = in.readVec3f();
767         animation->flags = in.readUInt32();
768         animation->animationType = in.readInt32();
769 
770         // Morse code
771         animation->morseCodeTiming = in.readInt32();
772         animation->wordRate = in.readInt32();
773         animation->characterRate = in.readInt32();
774         animation->morseCodeString = in.readString(1024);
775 
776         // Flashing sequence
777         int32 numberOfSequences = in.readInt32();
778         for (int n=0; n<numberOfSequences; ++n)
779         {
780             LPAnimation::Pulse pulse;
781             pulse.state = in.readUInt32();
782             pulse.duration = in.readFloat32();
783             pulse.color = in.readColor32();
784 
785             animation->sequence.push_back(pulse);
786         }
787 
788         // Add to pool
789         LightPointAnimationPool* lpaPool = document.getOrCreateLightPointAnimationPool();
790         (*lpaPool)[animation->index] = animation.get();
791     }
792 };
793 
794 REGISTER_FLTRECORD(LightPointAnimationPalette, LIGHT_POINT_ANIMATION_PALETTE_OP)
795 
796 
797 
798 class LineStylePalette : public Record
799 {
800 public:
801 
LineStylePalette()802     LineStylePalette() {}
803 
804     META_Record(LineStylePalette)
805 
806 protected:
807 
~LineStylePalette()808     virtual ~LineStylePalette() {}
809 
readRecord(RecordInputStream &,Document &)810     virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/)
811     {
812     }
813 };
814 
815 REGISTER_FLTRECORD(LineStylePalette, LINE_STYLE_PALETTE_OP)
816 
817 
818 
819 class TextureMappingPalette : public Record
820 {
821 public:
822 
TextureMappingPalette()823     TextureMappingPalette() {}
824 
825     META_Record(TextureMappingPalette)
826 
827 protected:
828 
~TextureMappingPalette()829     virtual ~TextureMappingPalette() {}
830 
readRecord(RecordInputStream &,Document &)831     virtual void readRecord(RecordInputStream& /*in*/, Document& /*document*/)
832     {
833     }
834 };
835 
836 REGISTER_FLTRECORD(TextureMappingPalette, TEXTURE_MAPPING_PALETTE_OP)
837 
838 
839 
840 class ShaderPalette : public Record
841 {
842 public:
843 
ShaderPalette()844     ShaderPalette() {}
845 
846     META_Record(ShaderPalette)
847 
848     enum ShaderType
849     {
850         CG=0,
851         CGFX=1,
852         GLSL=2
853     };
854 
855 protected:
856 
~ShaderPalette()857     virtual ~ShaderPalette() {}
858 
readRecord(RecordInputStream & in,Document & document)859     virtual void readRecord(RecordInputStream& in, Document& document)
860     {
861         if (document.getShaderPoolParent())
862             // Using parent's shader pool -- ignore this record.
863             return;
864 
865         int32 index = in.readInt32(-1);
866         int32 type = in.readInt32(-1);
867         std::string name = in.readString(1024);
868 
869         if (type == CG)
870         {
871             // CG support is currently not implemented. Just parse.
872             std::string vertexProgramFilename = in.readString(1024);
873             std::string fragmentProgramFilename = in.readString(1024);
874             /*int32 vertexProgramProfile =*/ in.readInt32();
875             /*int32 fragmentProgramProfile =*/ in.readInt32();
876             std::string vertexProgramEntry = in.readString(256);
877             std::string fragmentProgramEntry = in.readString(256);
878         }
879         else if (type == GLSL)
880         {
881             int32 vertexProgramFileCount(1);
882             int32 fragmentProgramFileCount(1);
883 
884             if (document.version() >= VERSION_16_1)
885             {
886                 // In 16.1, possibly multiple filenames for each vertex and fragment program.
887                 vertexProgramFileCount = in.readInt32();
888                 fragmentProgramFileCount = in.readInt32();
889             }
890             // else 16.0
891             //   Technically, 16.0 didn't support GLSL, but this plugin
892             //   supports it with a single vertex shader filename and a
893             //   single fragment shader filename.
894 
895             osg::Program* program = new osg::Program;
896             program->setName(name);
897 
898             // Read vertex programs
899             int idx;
900             for( idx=0; idx<vertexProgramFileCount; idx++)
901             {
902                 std::string vertexProgramFilename = in.readString(1024);
903 
904                 std::string vertexProgramFilePath = osgDB::findDataFile(vertexProgramFilename,document.getOptions());
905                 if (!vertexProgramFilePath.empty())
906                 {
907                     osg::ref_ptr<osg::Shader> vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, vertexProgramFilePath);
908                     if (vertexShader)
909                         program->addShader( vertexShader );
910                 }
911             }
912 
913             // Read fragment programs
914             for( idx=0; idx<fragmentProgramFileCount; idx++)
915             {
916                 std::string fragmentProgramFilename = in.readString(1024);
917 
918                 std::string fragmentProgramFilePath = osgDB::findDataFile(fragmentProgramFilename,document.getOptions());
919                 if (!fragmentProgramFilePath.empty())
920                 {
921                     osg::ref_ptr<osg::Shader> fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, fragmentProgramFilePath);
922                     if (fragmentShader)
923                         program->addShader( fragmentShader );
924                 }
925             }
926 
927             // Add to shader pool
928             ShaderPool* shaderPool = document.getOrCreateShaderPool();
929             (*shaderPool)[index] = program;
930         }
931     }
932 };
933 
934 REGISTER_FLTRECORD(ShaderPalette, SHADER_PALETTE_OP)
935 
936 
937 } // end namespace
938 
939 
940