root/OpenSceneGraph/trunk/src/osgPlugins/txp/TXPParser.cpp @ 9637

Revision 9637, 57.3 kB (checked in by robert, 5 years ago)

Warning fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <stdlib.h>
2
3#include <osg/AlphaFunc>
4#include <osg/Group>
5#include <osg/Material>
6#include <osg/TexEnv>
7#include <osg/LOD>
8#include <osg/Geode>
9#include <osg/Billboard>
10#include <osg/Matrix>
11#include <osg/MatrixTransform>
12#include <osg/Geometry>
13#include <osg/CullFace>
14#include <osg/Light>
15#include <osg/Notify>
16#include <osg/PolygonOffset>
17#include <osg/MatrixTransform>
18#include <osg/PagedLOD>
19#include <osgSim/LightPointNode>
20#include <osg/Point>
21#include <osg/ShapeDrawable>
22#include <osg/ApplicationUsage>
23#include <osgText/Text>
24
25#include <osgUtil/Optimizer>
26
27#include "TXPParser.h"
28#include "TXPArchive.h"
29
30using namespace txp;
31
32#include <sstream>
33
34static osg::ApplicationUsageProxy TXP_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_TXP_DEFAULT_MAX_ANISOTROPY \"<value> [<value>]\"","1.0 | 2.0 | 4.0 | 8.0 | 16.0");
35
36
37class LayerGroup : public osg::Group
38{
39public:
40    LayerGroup() : osg::Group() {}
41   
42    LayerGroup(const LayerGroup& gg,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
43        osg::Group(gg, copyop)
44    {};
45   
46    META_Node(txp, LayerGroup);
47protected:
48    virtual ~LayerGroup() {}
49};
50
51class LayerVisitor : public osg::NodeVisitor
52{
53public:
54    LayerVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) {}
55    virtual void apply(osg::Group& node)
56    {
57        LayerGroup *lg = dynamic_cast<LayerGroup*>(&node);
58        if (lg)
59        {
60            for (unsigned int i=1; i < lg->getNumChildren(); ++i)
61            {
62                osg::Node *child = lg->getChild(i);
63                osg::StateSet *sset = child->getOrCreateStateSet();
64                osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
65                polyoffset->setFactor(-1.0f);
66                polyoffset->setUnits(-200.0f*i);
67                sset->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);
68            }
69        }
70        traverse(node);
71    }
72};
73
74TXPParser::TXPParser():
75    _archive(0),
76    _currentTop(0),
77    _root(0),
78    _underBillboardSubgraph(false),
79    _numBillboardLevels(0),
80    _underLayerSubgraph(false),
81    _numLayerLevels(0),
82    _layerGeode(0),
83    _defaultMaxAnisotropy(1.0f),
84    _realMinRange(0.0),
85    _realMaxRange(0.0),
86    _usedMaxRange(0.0),
87    _childRefCB(0)
88{
89    AddCallback(TRPG_ATTACH,    new attachRead(this));
90    AddCallback(TRPG_CHILDREF,  new childRefRead(this));
91    AddCallback(TRPG_GEOMETRY,  new geomRead(this));
92    AddCallback(TRPG_GROUP,     new groupRead(this));
93    AddCallback(TRPG_LOD,       new lodRead(this));
94    AddCallback(TRPG_MODELREF,  new modelRefRead(this));
95    AddCallback(TRPG_BILLBOARD, new billboardRead(this));
96    AddCallback(TRPG_LIGHT,     new lightRead(this));
97    AddCallback(TRPG_LAYER,     new layerRead(this));
98    AddCallback(TRPG_LABEL,     new labelRead(this));
99    AddCallback(TRPGTILEHEADER, new tileHeaderRead(this));
100
101    _childRefCB = dynamic_cast<childRefRead *>(GetCallback(TRPG_CHILDREF));
102   
103    if (getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY"))
104    {
105        _defaultMaxAnisotropy = atof(getenv("OSG_TXP_DEFAULT_MAX_ANISOTROPY"));
106    }
107   
108}
109
110TXPParser::~TXPParser()
111{
112}
113
114osg::Group *TXPParser::parseScene(
115    trpgReadBuffer &buf,
116    std::map<int,osg::ref_ptr<osg::StateSet> > &materials,
117    std::map<int,osg::ref_ptr<osg::Node> > &models,
118    double realMinRange, double realMaxRange, double usedMaxRange)
119{
120    if (_archive == 0) return NULL;
121
122    if(_childRefCB)
123       _childRefCB->Reset();
124
125    _root = new osg::Group();
126    _currentTop = _root.get();
127
128    _materialMap = &materials;
129    _localMaterials.clear();
130    _models = &models;
131
132    _underBillboardSubgraph = false;
133    _numBillboardLevels = 0;
134    _underLayerSubgraph = false;
135    _numLayerLevels = 0;
136
137    _realMinRange = realMinRange;
138    _realMaxRange = realMaxRange;
139    _usedMaxRange = usedMaxRange;
140
141    _tileCenter = osg::Vec3(0.f,0.f,0.f);
142
143    if (!Parse(buf))
144    {
145        osg::notify(osg::NOTICE) << "txp::TXPParser::parseScene(): failed to parse the given tile" << std::endl;
146        return NULL;
147    }
148
149    for (std::map<osg::Group*,int>::iterator i = _tileGroups.begin(); i != _tileGroups.end(); i++)
150    {
151        replaceTileLod((*i).first);
152    }
153    _tileGroups.clear();
154
155    try
156    {
157       LayerVisitor lv;
158       _root->accept(lv);
159
160       //modified by Brad Anderegg May-27-08
161       //running the optimizer on the terrain fixes some major preformance issues, unfortunately the texture atlas builder seems to get messed up
162       //on some of the textures (usually around buildings) and the tri stripper seems to occasionally crash and also mess up the indices on certain buildings.
163       osgUtil::Optimizer opt;
164       opt.optimize(_root.get(), (osgUtil::Optimizer::ALL_OPTIMIZATIONS ^ osgUtil::Optimizer::TEXTURE_ATLAS_BUILDER) ^ osgUtil::Optimizer::TRISTRIP_GEOMETRY);
165    }
166    catch (...)
167    {
168       osg::notify(osg::NOTICE) << "txp::TXPParser::parseScene(): exception thrown in the osg::Optimizer" << std::endl;
169    }
170
171
172    return _root.get();
173}
174
175void TXPParser::replaceTileLod(osg::Group* group)
176{
177    if (group->getNumChildren() == 2)
178    {
179        osg::LOD* loLOD = dynamic_cast<osg::LOD*>(group->getChild(0));
180        osg::LOD* hiLOD = dynamic_cast<osg::LOD*>(group->getChild(1));
181
182        if (loLOD && hiLOD)
183        {
184            osg::Group *g = dynamic_cast<osg::Group*>(hiLOD->getChild(0));
185            if (!g) return;
186            if (g->getNumChildren()) return;
187
188            _tileCenter = loLOD->getCenter();
189
190            group->addChild(loLOD->getChild(0));
191            group->removeChild(loLOD);
192            group->removeChild(hiLOD);
193        }
194    }
195}
196
197
198unsigned int TXPParser::GetNbChildrenRef() const
199{
200   if(_childRefCB)
201         return _childRefCB->GetNbChildrenRef();
202      else
203         return 0;
204}
205
206const trpgChildRef* TXPParser::GetChildRef(unsigned int idx) const
207{
208   if(_childRefCB)
209      return _childRefCB->GetChildRef(idx);
210   else
211      return 0;
212}
213
214bool TXPParser::StartChildren(void * /*in*/)
215{
216
217    bool pushParent = true;
218    if (_underBillboardSubgraph )
219    {
220        if (_numBillboardLevels > 0) pushParent = false;
221        _numBillboardLevels++;
222    }
223    else
224    if (_underLayerSubgraph)
225    {
226        if (_numLayerLevels > 0) pushParent = false;
227        _numLayerLevels++;
228    }
229    if (pushParent)
230    {
231        _parents.push(_currentTop);
232        _currentTop = _currentNode->asGroup();
233    }
234   
235    return true;
236}
237
238bool TXPParser::EndChildren(void *)
239{
240    bool popParent = true;
241    if (_underLayerSubgraph)
242    {
243        _numLayerLevels--;
244        if (_numLayerLevels == 0)
245        {
246            _underLayerSubgraph = false;
247        }
248        else
249            popParent = false;
250    }
251    else
252    if (_underBillboardSubgraph)
253    {
254        _numBillboardLevels--;
255        if (_numBillboardLevels == 0)
256        {
257            _underBillboardSubgraph = false;
258        }
259        else
260            popParent = false;
261    }
262    if (popParent)
263    {
264        if (_parents.size())
265        {
266            _currentTop = _parents.top();
267            _parents.pop();
268        }
269        else
270            _currentTop = _root.get();
271    }
272
273    return true;
274}
275
276DeferredLightAttribute& TXPParser::getLightAttribute(int ix)
277{
278    return _archive->getLightAttribute(ix);
279}
280
281class FindEmptyGroupsVisitor : public osg::NodeVisitor
282{
283public:
284    FindEmptyGroupsVisitor(osg::NodeList& nl):
285      osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _nl(nl) {};
286
287    virtual void apply(osg::Group& group)
288    {
289        if (group.getNumChildren()==0)
290        {
291            _nl.push_back(&group);
292        }
293        traverse(group);
294    }
295protected:
296
297    FindEmptyGroupsVisitor& operator = (const FindEmptyGroupsVisitor&) { return *this; }
298
299    osg::NodeList& _nl;
300};
301
302void TXPParser::removeEmptyGroups()
303{
304    if (_root.get() && _root->getNumChildren())
305    {
306        osg::NodeList nl;
307        FindEmptyGroupsVisitor fegv(nl);
308
309        _root->accept(fegv);
310
311        for (unsigned int i = 0; i < nl.size(); i++)
312        {
313            osg::Node* node = nl[i].get();
314            if (node == NULL) continue;
315
316            osg::Node::ParentList parents = node->getParents();
317            for (unsigned int j = 0; j < parents.size(); j++)
318            {
319                osg::Group* parent = parents[j];
320                if (parent) parent->removeChild(node);
321            }
322        }
323    }
324}
325
326osg::Geode* TXPParser::createBoundingBox(int x,int y, int lod)
327{
328    TXPArchive::TileInfo info;
329
330    _archive->getTileInfo(x,y,lod,info);
331
332    osg::Geode* geode = new osg::Geode();
333
334    osg::TessellationHints* hints = new osg::TessellationHints;
335    hints->setDetailRatio(0.5f);
336    osg::ShapeDrawable* sd = new osg::ShapeDrawable(
337            new osg::Box(
338                info.center,
339                info.bbox.xMax()-info.bbox.xMin(),
340                info.bbox.yMax()-info.bbox.yMin(),
341                1
342            ),
343            hints
344        );
345   
346    if (lod==0)
347    {
348        sd->setColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
349    }
350    else
351    if (lod==1)
352    {
353        sd->setColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
354    }
355    else
356    if (lod==2)
357    {
358        sd->setColor(osg::Vec4(0.0f,1.0f,0.0f,1.0f));
359    }
360    else
361    if (lod==3)
362    {
363        sd->setColor(osg::Vec4(0.0f,0.0f,1.0f,1.0f));
364    }
365    else
366    if (lod==4)
367    {
368        sd->setColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f));
369    }
370    geode->addDrawable( sd );
371
372    return geode;
373}
374
375void TXPParser::loadLocalMaterials()
376{
377    bool separateGeo = false;
378    int majorVer,minorVer;
379    this->getArchive()->GetVersion(majorVer,minorVer);
380    if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR)) {
381    separateGeo = true;
382    }
383    // new to 2.0 LOCAL materials
384    trpgrImageHelper image_helper(
385        _archive->GetEndian(),
386        _archive->getDir(),
387        *_archive->GetMaterialTable(),
388        *_archive->GetTexTable(),
389        separateGeo
390    );
391    trpgTileHeader* tile_head = getTileHeaderRef();
392
393    int n_materials;
394    tile_head->GetNumLocalMaterial(n_materials);
395
396    int n_mat;
397    tile_head->GetNumMaterial(n_mat);
398
399    _localMaterials.clear();
400    _localMaterials.resize(n_materials);
401    {
402        for (int i = 0; i < n_materials; i++)
403        {
404            osg::StateSet* osg_state_set = new osg::StateSet;
405           
406            trpgLocalMaterial locmat;
407            tile_head->GetLocalMaterial(i,locmat);
408           
409            const trpgMaterial* mat = 0;
410            const trpgTexture *tex = 0;
411
412            int32 size;
413            image_helper.GetImageInfoForLocalMat(&locmat, &mat,&tex,size);
414
415            int num_tex;
416            mat->GetNumTexture(num_tex);
417            for (int texNo = 0 ; texNo < num_tex; ++texNo)
418            {
419                int texId;
420                trpgTextureEnv texEnv;
421                mat->GetTexture(texNo,texId,texEnv);
422
423                // Set up texture environment
424                osg::TexEnv       *osg_texenv       = new osg::TexEnv();
425                int32 te_mode;
426                texEnv.GetEnvMode(te_mode);
427                switch( te_mode )
428                {
429                case trpgTextureEnv::Alpha :
430                    osg_texenv->setMode(osg::TexEnv::REPLACE);
431            break;
432                case trpgTextureEnv::Decal:
433                    osg_texenv->setMode(osg::TexEnv::DECAL);
434                    break;
435                case trpgTextureEnv::Blend :
436                    osg_texenv->setMode(osg::TexEnv::BLEND);
437                    break;
438                case trpgTextureEnv::Modulate :
439                    osg_texenv->setMode(osg::TexEnv::MODULATE);
440                    break;
441                }
442           
443                osg_state_set->setTextureAttribute(texNo,osg_texenv);
444
445                image_helper.GetNthImageInfoForLocalMat(&locmat, texNo, &mat,&tex,size);
446           
447                trpgTexture::ImageMode mode;
448                tex->GetImageMode(mode);
449                osg::Texture2D* osg_texture = 0L;
450                if(mode == trpgTexture::Template)
451                    osg_texture = getTemplateTexture(image_helper,&locmat, tex, texNo);
452                else if(mode == trpgTexture::Local)
453                    osg_texture = getLocalTexture(image_helper,tex);
454                else if(mode == trpgTexture::Global)
455                    osg_texture = _archive->getGlobalTexture(texId);
456
457                if(osg_texture)
458                {
459                    if(osg_texture->getImage())
460                    {
461                        GLenum gltype = osg_texture->getImage()->getPixelFormat();
462                        if( gltype == GL_RGBA || gltype == GL_LUMINANCE_ALPHA )
463                        {
464                            osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);
465                            osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
466                        }
467                    }
468                    else
469                    {
470                        osg::notify(osg::WARN) << "No image\n";
471                    }
472                    osg_state_set->setTextureAttributeAndModes(texNo,osg_texture, osg::StateAttribute::ON);
473
474                    int wrap_s, wrap_t;   
475                    texEnv.GetWrap(wrap_s, wrap_t);
476                    osg_texture->setWrap(osg::Texture2D::WRAP_S, wrap_s == trpgTextureEnv::Repeat ? osg::Texture2D::REPEAT: osg::Texture2D::CLAMP_TO_EDGE );
477                    osg_texture->setWrap(osg::Texture2D::WRAP_T, wrap_t == trpgTextureEnv::Repeat ? osg::Texture2D::REPEAT: osg::Texture2D::CLAMP_TO_EDGE );
478                   
479                    // by default is anisotropic filtering.
480                    osg_texture->setMaxAnisotropy(_defaultMaxAnisotropy);
481                }
482                else
483                {
484                    osg::notify(osg::WARN) << "No texture\n";
485                }
486            }
487
488            osg::Material     *osg_material     = new osg::Material;
489           
490            float64 alpha;
491            mat->GetAlpha(alpha);
492           
493            trpgColor color;
494            mat->GetAmbient(color);
495            osg_material->setAmbient( osg::Material::FRONT_AND_BACK ,
496                osg::Vec4(color.red, color.green, color.blue, alpha));
497            mat->GetDiffuse(color);
498            osg_material->setDiffuse(osg::Material::FRONT_AND_BACK ,
499                osg::Vec4(color.red, color.green, color.blue, alpha));
500           
501            mat->GetSpecular(color);
502            osg_material->setSpecular(osg::Material::FRONT_AND_BACK ,
503                osg::Vec4(color.red, color.green, color.blue, alpha));
504            mat->GetEmission(color);
505            osg_material->setEmission(osg::Material::FRONT_AND_BACK ,
506                osg::Vec4(color.red, color.green, color.blue, alpha));
507           
508            float64 shinines;
509            mat->GetShininess(shinines);
510            osg_material->setShininess(osg::Material::FRONT_AND_BACK , (float)shinines);
511           
512            osg_material->setAlpha(osg::Material::FRONT_AND_BACK ,(float)alpha);
513            osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
514
515            _archive->SetUserDataToMaterialAttributes(*osg_state_set, *mat);
516
517            if( alpha < 1.0f )
518            {
519                osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);
520                osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
521            }
522           
523           
524        /* This controls what alpha values in a texture mean.  It can take the values:
525           None,Always,Equal,GreaterThanOrEqual,GreaterThan,
526           LessThanOrEqual,LessThan,Never,NotEqual
527        */
528            int alphaFunc;
529            mat->GetAlphaFunc(alphaFunc);
530            if( alphaFunc>=GL_NEVER && alphaFunc<=GL_ALWAYS)
531            {
532                float64 ref;
533                mat->GetAlphaRef(ref);
534                osg::AlphaFunc *osg_alpha_func = new osg::AlphaFunc;
535                osg_alpha_func->setFunction((osg::AlphaFunc::ComparisonFunction)alphaFunc,(float)ref);
536                osg_state_set->setAttributeAndModes(osg_alpha_func, osg::StateAttribute::ON);
537            }
538
539            int cullMode;
540            mat->GetCullMode(cullMode);
541           
542            // Culling mode in txp means opposite from osg i.e. Front-> show front face
543            if( cullMode != trpgMaterial::FrontAndBack)
544            {
545                osg::CullFace* cull_face = new osg::CullFace;
546                switch (cullMode)
547                {
548                case trpgMaterial::Front:
549                    cull_face->setMode(osg::CullFace::BACK);
550                    break;
551                case trpgMaterial::Back:
552                    cull_face->setMode(osg::CullFace::FRONT);
553                    break;
554                }
555                osg_state_set->setAttributeAndModes(cull_face, osg::StateAttribute::ON);
556            }
557            _localMaterials[i] = osg_state_set;
558        }
559    }
560}
561
562bool TXPParser::requestModel(int ix)
563{
564    return _archive->loadModel(ix);
565}
566
567//----------------------------------------------------------------------------
568//
569// LOD Reader Class
570//
571//----------------------------------------------------------------------------
572void* lodRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
573{
574    trpgLod lod;
575    if (!lod.Read(buf)) return NULL;
576
577    // Pull out the LOD data we'll need
578    trpg3dPoint center;
579    lod.GetCenter(center);
580
581    double in,out,width;
582    lod.GetLOD(in,out,width);
583
584    double minRange = MIN(in,out);
585    double maxRange = MAX(in,out+width);
586
587    // Create a new osg LOD
588    osg::ref_ptr<osg::LOD> osgLod = new osg::LOD();
589    osg::ref_ptr<GeodeGroup> osgLodG = new GeodeGroup;
590
591    osgLod->addChild(osgLodG.get());
592
593    osg::Vec3 osgCenter;
594    osgCenter[0] = center.x;
595    osgCenter[1] = center.y;
596    osgCenter[2] = center.z;
597    osgLod->setCenter(osgCenter);
598#if 1
599    osgLod->setRange(0,minRange, maxRange );
600#else
601    osgLod->setRange(
602        0,
603        _parse->checkAndGetMinRange(minRange),
604        _parse->checkAndGetMaxRange(maxRange)
605    );
606#endif
607   
608    // Our LODs are binary so we need to add a group under this LOD and attach stuff
609    // to that instead of the LOD
610    // Add it into the scene graph
611    _parse->setCurrentNode(osgLodG.get());
612    _parse->getCurrTop()->addChild(osgLod.get());
613    _parse->setPotentionalTileGroup(_parse->getCurrTop());
614
615    return (void*)1;
616}
617
618//----------------------------------------------------------------------------
619//
620// Tile Header Reader Class
621//
622//----------------------------------------------------------------------------
623void* tileHeaderRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
624{
625    trpgTileHeader *tileHead = _parse->getTileHeaderRef();
626    if (!tileHead->Read(buf))
627        return NULL;
628    _parse->loadLocalMaterials();
629    return (void *) 1;
630}
631
632//----------------------------------------------------------------------------
633//
634// Model Reference Reader Class
635//
636//----------------------------------------------------------------------------
637void *modelRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
638{
639    trpgModelRef model;
640    if (!model.Read(buf)) return NULL;
641
642    // Get the matrix and pfNode for the model
643    int modelID;
644    model.GetModel(modelID);
645    float64 mat[16];
646    model.GetMatrix(mat);
647    osg::Matrix osg_Mat(
648        (float)mat[0], (float)mat[1], (float)mat[2], (float)mat[3],
649        (float)mat[4], (float)mat[5], (float)mat[6], (float)mat[7],
650        (float)mat[8], (float)mat[9], (float)mat[10],(float)mat[11],
651        (float)mat[12],(float)mat[13],(float)mat[14],(float)mat[15]
652        );
653   
654    // Note: Array check before you do this
655    osg::Node *osg_Model = NULL;
656    std::map<int,osg::ref_ptr<osg::Node> >*modelList = _parse->getModels();
657    //if( modelList->size() )
658    {
659       osg_Model = (*modelList)[modelID].get();
660
661       if (osg_Model==NULL)
662       {
663           _parse->requestModel(modelID);
664           osg_Model = (*modelList)[modelID].get();
665       }
666
667        // Create the SCS and position the model
668        if (osg_Model)
669        {
670            osg::MatrixTransform *scs = new osg::MatrixTransform();
671            scs->setMatrix(osg_Mat);
672            scs->addChild(osg_Model);
673
674            // Add the SCS to the hierarchy
675            _parse->setCurrentNode(scs);
676            _parse->getCurrTop()->addChild(scs);
677        }
678    }
679    return (void *) 1;
680}
681
682//----------------------------------------------------------------------------
683//
684// Billboard Reader Class
685//
686//----------------------------------------------------------------------------
687void* billboardRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
688{
689    // Read in the txp billboard
690    trpgBillboard bill;
691    if (!bill.Read(buf)) return NULL;
692
693    if (_parse->underBillboardSubgraph())
694    {
695        // we don't allow anything under a billboard except geometry
696        osg::notify(osg::WARN) << "TerraPage loader: can only have geometry nodes beneath a billboard.\n";
697    }
698    else
699    {
700        GeodeGroup* grp = new GeodeGroup;
701        _parse->setCurrentNode(grp);
702        _parse->getCurrTop()->addChild(grp);
703
704        TXPParser::TXPBillboardInfo info;
705        if (bill.GetType(info.type) && bill.GetMode(info.mode) && bill.GetCenter(info.center) && bill.GetAxis(info.axis))
706        {
707            // save this state for processing of the geometry node(s)
708            _parse->setLastBillboardInfo(info);
709            _parse->setUnderBillboardSubgraph(true);
710        }
711    }
712    return (void *)1;
713}
714
715//----------------------------------------------------------------------------
716//
717// Group Reader Class
718//
719//----------------------------------------------------------------------------
720void* groupRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
721{
722    trpgGroup group;
723    if (!group.Read(buf)) return NULL;
724
725    if (_parse->underLayerSubgraph()) return (void*)1;
726
727    osg::ref_ptr<GeodeGroup> osgGroup = new GeodeGroup();
728    _parse->setCurrentNode(osgGroup.get());
729    _parse->getCurrTop()->addChild(osgGroup.get());
730    return (void*)1;
731}
732
733//----------------------------------------------------------------------------
734//
735// Attach Reader Class
736//
737//----------------------------------------------------------------------------
738void* attachRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
739{
740    trpgAttach group;
741    if (!group.Read(buf)) return NULL;
742
743    // Create a new group
744    osg::ref_ptr<osg::Group> osgGroup = new osg::Group();
745    _parse->setCurrentNode(osgGroup.get());
746    _parse->getCurrTop()->addChild(osgGroup.get());
747    return (void*)1;
748}
749
750void* childRefRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
751{
752   
753   // This object contribute nothing to the scenegraph, except
754   // where the children tile should connect.
755   // It only contain location info of the children tile
756   childRefList.push_back(trpgChildRef());
757   trpgReadWriteable& obj = childRefList.back();
758
759   if(obj.Read(buf))
760      return &obj;
761    else
762      return 0;
763
764}
765void childRefRead::Reset()
766{
767   childRefList.clear();
768}
769
770
771//----------------------------------------------------------------------------
772//
773// light Reader Class
774//
775//----------------------------------------------------------------------------
776void* lightRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
777{
778    trpgLight light;
779    if (!light.Read(buf)) return NULL;
780
781    int attr_index;
782    light.GetAttrIndex(attr_index);
783
784    uint32 nvert;
785    light.GetNumVertices(nvert);
786
787    const trpgLightTable *lt = _parse->getArchive()->GetLightTable();
788    trpgLightAttr *ref = const_cast<trpgLightAttr*>(lt->GetLightAttrRef(attr_index));
789    if (!ref)
790    {
791        osg::notify(osg::NOTICE) << "NULL LightAttr " << attr_index << std::endl;
792        return (void*)1;
793    }
794
795    osgSim::LightPointNode *lpNode = new osgSim::LightPointNode();
796
797    trpgColor col;
798    ref->GetFrontColor(col);
799
800    float64 inten;
801    ref->GetFrontIntensity(inten);
802
803    trpgLightAttr::PerformerAttr perfAttr;
804    ref->GetPerformerAttr(perfAttr);
805
806    lpNode->setMaxPixelSize(perfAttr.maxPixelSize);
807    lpNode->setMinPixelSize(perfAttr.minPixelSize);   
808
809    trpg3dPoint norm;
810    ref->GetNormal(norm);
811
812    trpgLightAttr::LightDirectionality direc;
813    ref->GetDirectionality(direc);
814
815    for ( unsigned i=0; i < nvert; i++ )
816    {
817        trpg3dPoint pt;
818        light.GetVertex(i, pt);
819
820        osgSim::LightPoint lp(
821            true,
822            osg::Vec3(pt.x,pt.y,pt.z),
823            osg::Vec4(col.red, col.green,col.blue, 1.0),
824            inten
825        );
826
827        switch (direc)
828        {
829        case trpgLightAttr::trpg_Unidirectional:
830            {
831                float lobeVert=0.f, lobeHorz=0.f, lobeRoll=0.f;
832                float64 tmp;
833
834                ref->GetHLobeAngle(tmp);
835                lobeHorz = osg::DegreesToRadians( tmp );
836               
837                ref->GetVLobeAngle(tmp);
838                lobeVert = osg::DegreesToRadians( tmp );
839               
840                ref->GetLobeRollAngle(tmp);
841                lobeRoll = osg::DegreesToRadians( tmp );
842
843                osg::Vec3 normal(norm.x,norm.y,norm.z);
844                lp._sector = new osgSim::DirectionalSector( normal, lobeHorz, lobeVert, lobeRoll );
845            }
846            break;
847        case trpgLightAttr::trpg_Bidirectional:
848            {
849                float lobeVert=0.f, lobeHorz=0.f, lobeRoll=0.f;
850                float64 tmp;
851
852                ref->GetHLobeAngle(tmp);
853                lobeHorz = osg::DegreesToRadians( tmp );
854               
855                ref->GetVLobeAngle(tmp);
856                lobeVert = osg::DegreesToRadians( tmp );
857               
858                ref->GetLobeRollAngle(tmp);
859                lobeRoll = osg::DegreesToRadians( tmp );
860
861                osg::Vec3 normal(norm.x,norm.y,norm.z);
862                lp._sector = new osgSim::DirectionalSector( normal, lobeHorz, lobeVert, lobeRoll );
863
864                ref->GetBackColor(col);
865                ref->GetBackIntensity(inten);
866
867                osgSim::LightPoint lp2(
868                    true,
869                    osg::Vec3(pt.x,pt.y,pt.z),
870                    osg::Vec4(col.red, col.green,col.blue, 1.0),
871                    inten
872                );
873
874                lp2._sector = new osgSim::DirectionalSector( -normal, lobeHorz, lobeVert, lobeRoll );
875                lpNode->addLightPoint( lp2 );
876            }
877            break;
878        default:
879            ;
880        }
881
882        lpNode->addLightPoint( lp);
883
884    }
885
886    _parse->setCurrentNode(lpNode);
887    _parse->getCurrTop()->addChild(lpNode);
888
889#if 0
890
891    DefferedLightAttribute& dla = _parse->getLightAttribute(attr_index);
892    osgSim::LightPointNode* node = dla.lightPoint.get();
893
894    uint32 nvert;
895    light.GetNumVertices(nvert);
896
897    if( node->getLightPoint(0)._sector.valid() ) // osgSim::LightPoint is a must
898    {
899        for(unsigned int i = 0; i < nvert; i++)
900        {
901            trpg3dPoint pt;
902            light.GetVertex(i, pt);
903            osg::Matrix matrix;
904        //        matrix.makeTranslate(pt.x,pt.y,pt.z);
905            matrix.makeRotate(osg::Quat(0.0,dla.attitude));
906            matrix.setTrans(pt.x,pt.y,pt.z);
907            osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform();
908            trans->setMatrix(matrix);
909            trans->addChild(node);
910
911            _parse->setCurrentNode(trans.get());
912            _parse->getCurrTop()->addChild(trans.get());
913        }
914    }
915    else
916    { //Fall back to osg::Points
917        osg::Vec3Array* vertices = new osg::Vec3Array(nvert);
918        osg::Vec4Array* colors = new osg::Vec4Array(nvert);
919
920        for(unsigned int i = 0; i < nvert; i++)
921        {
922            trpg3dPoint pt;
923            light.GetVertex(i, pt);
924            (*vertices)[i] = osg::Vec3(pt.x,pt.y,pt.z);
925            (*colors)[i] = node->getLightPoint(0)._color;
926        }
927
928        osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
929        geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS,0,nvert));
930        geom->setVertexArray(vertices);
931        geom->setColorArray(colors);
932        geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
933
934        geom->setUseDisplayList(false);
935        geom->setStateSet(dla.fallback.get());
936
937        osg::Geode* g = new osg::Geode;
938        g->addDrawable(geom.get());
939        _parse->setCurrentNode(g);
940        _parse->getCurrTop()->addChild(g);
941    }
942#endif
943
944    return (void *) 1;
945}
946
947//----------------------------------------------------------------------------
948//
949// Layer Reader Class
950//
951//----------------------------------------------------------------------------
952void* layerRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
953{
954    trpgLayer group;
955    if (!group.Read(buf)) return NULL;
956
957    osg::ref_ptr<LayerGroup> osgGroup = new LayerGroup();
958    _parse->setCurrentNode(osgGroup.get());
959    _parse->getCurrTop()->addChild(osgGroup.get());
960    return (void*)1;
961}
962
963//----------------------------------------------------------------------------
964//
965// Label Reader Class
966//
967//----------------------------------------------------------------------------
968void* labelRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
969{
970    trpgLabel label;
971    if (!label.Read(buf)) return NULL;
972
973    const std::string *labelText = label.GetText();
974    if (!labelText) return (void*)1;
975
976    osg::Vec3 pos(label.GetLocation().x, label.GetLocation().y, label.GetLocation().z);
977
978    osg::ref_ptr< osg::Geode > textGeode = new osg::Geode;
979    osg::ref_ptr< osgText::Text > text = new osgText::Text;
980
981    // Text
982    std::ostringstream os;
983    std::string::size_type nl;
984    std::string lb = *labelText;
985    while ( (nl=lb.find_first_of('\\')) != std::string::npos)
986    {
987        std::string sub = lb.substr(0,nl);
988        switch (lb[nl+1])
989        {
990        case 'n':
991            lb.erase(0,nl+2);
992            if (sub.length()) os << sub << std::endl;
993            break;
994        case 't':
995            lb.erase(0,nl+2);
996            os << sub << "     ";//'\t';
997            break;
998        default:
999            lb.erase(0,nl+1);
1000            os << '\\' << sub;
1001            break;
1002        }
1003       
1004    }
1005    if (lb.length()) os << lb;
1006    text->setText(os.str());
1007
1008    // Position
1009    text->setPosition(pos);
1010    // Alignment
1011    switch (label.GetAlignment())
1012    {
1013    case trpgLabel::Left:
1014        text->setAlignment(osgText::Text::LEFT_BOTTOM);
1015        break;
1016    case trpgLabel::Right:
1017        text->setAlignment(osgText::Text::RIGHT_BOTTOM);
1018        break;
1019    default:
1020        text->setAlignment(osgText::Text::CENTER_BOTTOM);
1021    }
1022    // Axis alignment
1023    text->setAxisAlignment(osgText::Text::XZ_PLANE);
1024
1025    const trpgLabelPropertyTable *labelPropertyTable = _parse->getArchive()->GetLabelPropertyTable();
1026    const trpgLabelProperty *labelProperty = labelPropertyTable ?
1027        labelPropertyTable->GetPropertyRef(label.GetProperty()) : 0;
1028   
1029    bool addTextGeodeIntoSceneGraph = true;
1030    if (labelProperty)
1031    {
1032        const trpgTextStyleTable *textStyleTable = _parse->getArchive()->GetTextStyleTable();
1033        if (!textStyleTable) return (void*)1;
1034
1035        const trpgTextStyle *textStyle = textStyleTable->GetStyleRef(labelProperty->GetFontStyle());
1036        if (!textStyle) return (void*)1;
1037
1038        // Size
1039        text->setCharacterSize(textStyle->GetCharacterSize()*label.GetScale()*2);
1040        text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);
1041
1042        // Font
1043        text->setFont(_parse->getArchive()->getStyles()[labelProperty->GetFontStyle()].get());
1044
1045        // Color
1046        text->setColor(_parse->getArchive()->getTextColors()[labelProperty->GetFontStyle()]);
1047
1048        // Cube
1049        osg::ref_ptr<osg::ShapeDrawable> cube = 0;
1050
1051        // Type
1052        switch (labelProperty->GetType())
1053        {
1054        case trpgLabelProperty::Billboard:
1055            text->setAxisAlignment(osgText::Text::XY_PLANE);
1056            text->setAutoRotateToScreen(true);
1057            break;
1058        case trpgLabelProperty::VertBillboard:
1059            addTextGeodeIntoSceneGraph = false;
1060            {
1061                osg::ref_ptr< osg::Billboard > billboard = new osg::Billboard;
1062                text->setPosition(osg::Vec3(0.f,0.f,0.f));
1063                billboard->addDrawable(text.get());
1064                billboard->setAxis(osg::Vec3(0.0f,0.0,1.0f) );
1065                billboard->setNormal(osg::Vec3(0.0f,-1.0,0.0f));
1066                billboard->setMode(osg::Billboard::AXIAL_ROT);
1067                billboard->setPosition(0,pos);
1068
1069                _parse->getCurrTop()->addChild(billboard.get());
1070            }
1071            break;
1072        case trpgLabelProperty::Cube:
1073            addTextGeodeIntoSceneGraph = false;
1074            {
1075                osg::Group* group = new osg::Group;
1076
1077                osg::BoundingBox box = text->getBound();
1078                float shift = box.radius()+1.f;
1079
1080                // front
1081                text->setAlignment(osgText::Text::CENTER_CENTER);
1082
1083                // back
1084                osg::ref_ptr<osgText::Text> backText = new osgText::Text(*text);
1085                backText->setPosition(osg::Vec3(pos.x(),pos.y()+shift,pos.z()));
1086                backText->setAxisAlignment(osgText::Text::REVERSED_XZ_PLANE);
1087
1088                // top
1089                osg::ref_ptr<osgText::Text> topText = new osgText::Text(*text);
1090                topText->setPosition(osg::Vec3(pos.x(),pos.y(),pos.z()+shift));
1091                topText->setAxisAlignment(osgText::Text::XY_PLANE);
1092
1093                // bottom
1094                osg::ref_ptr<osgText::Text> bottomText = new osgText::Text(*text);
1095                bottomText->setPosition(osg::Vec3(pos.x(),pos.y(),pos.z()-shift));
1096                bottomText->setAxisAlignment(osgText::Text::REVERSED_XY_PLANE);
1097
1098                // left
1099                osg::ref_ptr<osgText::Text> leftText = new osgText::Text(*text);
1100                leftText->setPosition(osg::Vec3(pos.x()-shift,pos.y(),pos.z()));
1101                leftText->setAxisAlignment(osgText::Text::REVERSED_YZ_PLANE);
1102
1103                // right
1104                osg::ref_ptr<osgText::Text> rightText = new osgText::Text(*text);
1105                rightText->setPosition(osg::Vec3(pos.x()+shift,pos.y(),pos.z()));
1106                rightText->setAxisAlignment(osgText::Text::YZ_PLANE);
1107
1108                text->setPosition(osg::Vec3(pos.x(),pos.y()-shift,pos.z()));
1109
1110                osg::TessellationHints* hints = new osg::TessellationHints;
1111                hints->setDetailRatio(0.5f);
1112                cube = new osg::ShapeDrawable(new osg::Box(pos,2*shift),hints);
1113
1114                osg::ref_ptr<osg::PolygonOffset> polyoffset = new osg::PolygonOffset;
1115                polyoffset->setFactor(10.0f);
1116                polyoffset->setUnits(10.0f);
1117                osg::ref_ptr<osg::StateSet> ss = cube->getOrCreateStateSet();
1118                ss->setAttributeAndModes(polyoffset.get(),osg::StateAttribute::ON);
1119                cube->setStateSet(ss.get());
1120
1121                textGeode->addDrawable(cube.get());
1122                textGeode->addDrawable(text.get());
1123                textGeode->addDrawable(backText.get());
1124                textGeode->addDrawable(topText.get());
1125                textGeode->addDrawable(bottomText.get());
1126                textGeode->addDrawable(leftText.get());
1127                textGeode->addDrawable(rightText.get());
1128
1129                group->addChild(textGeode.get());
1130
1131                _parse->getCurrTop()->addChild(group);
1132            }
1133            break;
1134        default:
1135            break;
1136        }
1137
1138         const std::vector<trpg3dPoint> *supports = label.GetSupports();
1139         if (supports && supports->size())
1140         {
1141             osg::ref_ptr<osg::Geode> supGeode = new osg::Geode;
1142
1143             int supId = labelProperty->GetSupport();
1144             const trpgSupportStyleTable *supTable = _parse->getArchive()->GetSupportStyleTable();
1145             const trpgSupportStyle *supStyle = supTable ? supTable->GetStyleRef(supId) : 0;
1146             if (supStyle)
1147             {
1148                int matId = supStyle->GetMaterial();
1149
1150                osg::Vec4 supLineColor(1.f,1.f,1.f,1.f);
1151                 _parse->loadMaterial(matId);
1152                osg::ref_ptr<osg::StateSet>  sset = (*_parse->getMaterials())[matId];
1153
1154                if (cube.get())
1155                {
1156                    osg::StateSet* ss = cube->getOrCreateStateSet();
1157                    ss->merge(*sset);
1158                }
1159
1160                const trpgMatTable* matTable = _parse->getArchive()->GetMaterialTable();
1161                if (matTable)
1162                {
1163                    const trpgMaterial* mat = matTable->GetMaterialRef(0,matId);
1164                    if (mat)
1165                    {
1166                        trpgColor faceColor;
1167                        mat->GetColor(faceColor);
1168
1169                        float64 alpha;
1170                        mat->GetAlpha(alpha);
1171
1172                        supLineColor = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha );
1173                    }
1174                }
1175               
1176                 switch (supStyle->GetType())
1177                 {
1178                 case trpgSupportStyle::Line:
1179                     {
1180                        osg::Geometry* linesGeom = new osg::Geometry();
1181                        osg::Vec3Array* vertices = new osg::Vec3Array(supports->size()*2);
1182
1183                        int cnt = 0;
1184                        for (unsigned int i = 0; i < supports->size(); i++)
1185                        {
1186                            const trpg3dPoint& supPt = (*supports)[i];
1187                            (*vertices)[cnt++].set(pos);
1188                            (*vertices)[cnt++].set(osg::Vec3(supPt.x,supPt.y,supPt.z));
1189                        }
1190
1191                        linesGeom->setVertexArray(vertices);
1192
1193                        osg::Vec4Array* colors = new osg::Vec4Array;
1194                        colors->push_back(supLineColor);
1195                        linesGeom->setColorArray(colors);
1196                        linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
1197                       
1198                        osg::Vec3Array* normals = new osg::Vec3Array;
1199                        normals->push_back(osg::Vec3(0.0f,-1.0f,0.0f));
1200                        linesGeom->setNormalArray(normals);
1201                        linesGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
1202
1203
1204                        linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,supports->size()*2));
1205                        supGeode->addDrawable(linesGeom);
1206                     }
1207
1208                     _parse->getCurrTop()->addChild(supGeode.get());
1209                     break;
1210                 case trpgSupportStyle::Cylinder:
1211                     {
1212                        osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
1213                        hints->setDetailRatio(0.5f);
1214
1215                        for (unsigned int i = 0; i < supports->size(); i++)
1216                        {
1217                            const trpg3dPoint& supPt = (*supports)[i];
1218                           
1219                            osg::Vec3 supPos(supPt.x,supPt.y,supPt.z);
1220                            osg::Vec3 supCenter = (supPos+pos)/2.f;
1221                            float supHeight = (supPos-pos).length();
1222
1223                            osg::Vec3 d = pos-supPos;
1224                            d.normalize();
1225                            osg::Quat r;
1226
1227                            r.makeRotate(osg::Vec3(0.f,0.f,1.f),d);
1228
1229                            osg::Cylinder* cylinder = new osg::Cylinder(supCenter,10.f,supHeight);
1230                            cylinder->setRotation(r);
1231
1232                            osg::ShapeDrawable* cylinderDrawable = new osg::ShapeDrawable(cylinder,hints.get());
1233                            osg::StateSet* ss = cylinderDrawable->getOrCreateStateSet();
1234                            ss->merge(*sset);
1235
1236                            supGeode->addDrawable(cylinderDrawable);
1237
1238                        }
1239                       
1240                        _parse->getCurrTop()->addChild(supGeode.get());
1241                     }
1242                     break;
1243                 default:
1244                    break;
1245                 }
1246
1247                 
1248             }
1249         }
1250    }
1251    if (addTextGeodeIntoSceneGraph)
1252    {
1253        _parse->getCurrTop()->addChild(textGeode.get());
1254        textGeode->addDrawable(text.get());
1255    }
1256
1257    return (void*)1;
1258}
1259
1260//----------------------------------------------------------------------------
1261//
1262// Geometry Reader Class
1263//
1264//----------------------------------------------------------------------------
1265// Apply transformation on geometry
1266class TransformFunctor : public osg::Drawable::AttributeFunctor
1267{
1268public:
1269
1270    osg::Matrix _m;
1271    osg::Matrix _im;
1272
1273    TransformFunctor(const osg::Matrix& m)
1274    {
1275        _m = m;
1276        _im.invert(_m);
1277    }
1278       
1279    virtual ~TransformFunctor() {}
1280
1281    virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
1282    {
1283        if (type == osg::Drawable::VERTICES)
1284        {
1285            osg::Vec3* end = begin+count;
1286            for (osg::Vec3* itr=begin;itr<end;++itr)
1287            {
1288                (*itr) = (*itr)*_m;
1289            }
1290        }
1291        else 
1292        if (type == osg::Drawable::NORMALS)
1293        {
1294            osg::Vec3* end = begin+count;
1295            for (osg::Vec3* itr=begin;itr<end;++itr)
1296            {
1297                // note post mult by inverse for normals.
1298                (*itr) = osg::Matrix::transform3x3(_im,(*itr));
1299                (*itr).normalize();
1300            }
1301        }
1302    }
1303
1304    inline void SetMatrix(const osg::Matrix& m)
1305    {
1306        _m = m;
1307        _im.invert(_m);
1308    }
1309
1310};
1311
1312void* geomRead::Parse(trpgToken /*tok*/,trpgReadBuffer &buf)
1313{
1314    trpgGeometry geom;
1315    if (!geom.Read(buf)) return NULL;
1316
1317    // Get the necessary info out of the geom
1318    trpgGeometry::PrimType primType;
1319    int numPrims;
1320    int numVert;
1321    int numNorm;
1322    geom.GetPrimType(primType);
1323    geom.GetNumPrims(numPrims);
1324    geom.GetNumVertex(numVert);
1325    geom.GetNumNormal(numNorm);
1326   
1327    // Get vertices
1328    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array(numVert);
1329    geom.GetVertices((float *)&(vertices->front()));
1330   
1331    // Turn the trpgGeometry into something osg can understand
1332    osg::ref_ptr<osg::Geometry> geometry;
1333   
1334    // Get texture coordinates
1335    ;
1336    int num_tex;
1337    geom.GetNumTexCoordSets(num_tex);
1338    std::vector< osg::ref_ptr<osg::Vec2Array> > tex_coords(num_tex);
1339    for (int texno = 0; texno < num_tex; texno++)
1340    {
1341        const trpgTexData* td = geom.GetTexCoordSet(texno);
1342        if (td)
1343        {
1344            tex_coords[texno] = new osg::Vec2Array(numVert);
1345            const float* sourcePtr = &(td->floatData[0]);
1346            float* destinationPtr = (float*)&((*tex_coords[texno])[0]);
1347            for (int i=0 ;i < numVert; ++i)
1348            {
1349                *destinationPtr++ = *sourcePtr++;
1350                *destinationPtr++ = *sourcePtr++;
1351            }
1352        }
1353    }
1354   
1355    // The normals
1356    osg::ref_ptr<osg::Vec3Array> normals;
1357    if (numNorm == numVert)
1358    {
1359        normals = new osg::Vec3Array(numVert);
1360        geom.GetNormals((float*)&(normals->front()));
1361    }
1362   
1363    // Set up the primitive type
1364    switch (primType)
1365    {
1366    case trpgGeometry::Triangles:
1367    {
1368    geometry = new osg::Geometry;
1369    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,numPrims*3));
1370    }
1371    break;
1372    case trpgGeometry::Quads:
1373    {
1374    geometry = new osg::Geometry;
1375    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,numPrims*4));
1376    }
1377    break;
1378    case trpgGeometry::TriStrips:
1379    {
1380    geometry = new osg::Geometry;
1381    osg::DrawArrayLengths* dal = new osg::DrawArrayLengths(osg::PrimitiveSet::TRIANGLE_STRIP,0,numPrims);
1382    geom.GetPrimLengths(reinterpret_cast<int*>(&(dal->front())));
1383    geometry->addPrimitiveSet(dal);
1384    }
1385    break;
1386    case trpgGeometry::TriFans:
1387    {
1388    geometry = new osg::Geometry;
1389    osg::DrawArrayLengths* dal = new osg::DrawArrayLengths(osg::PrimitiveSet::TRIANGLE_FAN,0,numPrims);
1390    geom.GetPrimLengths(reinterpret_cast<int*>(&(dal->front())));
1391    geometry->addPrimitiveSet(dal);
1392
1393    // Need to flip the fans coords.
1394    int ind = 0;
1395    int i;
1396    for (i=0;i<numPrims;++i)
1397    {
1398        int length = (*dal)[i];
1399        int start=ind+1;
1400        int end=ind+length-1;
1401        // Swap from start+1 to end
1402        // Swap vertices, texture coords & normals
1403        for (; start < end; ++start, --end )
1404        {
1405        std::swap((*vertices)[start], (*vertices)[end]);
1406        for(int texno = 0; texno < num_tex; texno ++ )
1407        {
1408            if( tex_coords[texno].valid() )
1409            {
1410            std::swap((*tex_coords[texno])[start], (*tex_coords[texno])[end]);
1411            }
1412        }
1413        if(normals.valid())
1414        {
1415            std::swap((*normals)[start], (*normals)[end]);
1416        }
1417        }
1418        ind += length;
1419    }
1420    }
1421    break;
1422    default:
1423        break;
1424    };
1425   
1426   
1427    // Add it to the current parent group
1428    osg::Group *top = _parse->getCurrTop();
1429
1430    // Is this geode group
1431    GeodeGroup *geodeTop = dynamic_cast<GeodeGroup*>(top);
1432
1433    if (geometry.valid() && top)
1434    {
1435
1436       //modifed by Brad Anderegg on May-27-08
1437       //using display lists actually increases our framerate by
1438       //a fair amount, on certain laptops it increased by as much as 1000%
1439       geometry->setUseDisplayList(true);
1440
1441        geometry->setVertexArray(vertices.get());
1442        if (normals.valid())
1443        {
1444            geometry->setNormalArray(normals.get());
1445            geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
1446        }
1447
1448        bool local;
1449        int matId;
1450        int  matNo;
1451        geom.GetNumMaterial(matNo);
1452        osg::ref_ptr<osg::StateSet>  sset = 0L;
1453        for(int n_mat = 0; n_mat < matNo ; ++n_mat)
1454        {
1455            osg::ref_ptr<osg::StateSet> tmp_ss = 0L;
1456            geom.GetMaterial(n_mat,matId,local);
1457            if( local )
1458                tmp_ss = (*_parse->getLocalMaterials())[matId];
1459            else
1460            {
1461                _parse->loadMaterial(matId);
1462                tmp_ss = (*_parse->getMaterials())[matId];
1463            }
1464            if(sset.valid())
1465            {
1466                if(tmp_ss.valid())
1467                  {
1468                    osg::StateAttribute* texenv0 = tmp_ss->getTextureAttribute(0,osg::StateAttribute::TEXENV);
1469                    if(texenv0)
1470                        sset->setTextureAttribute(n_mat,texenv0);
1471                    osg::StateAttribute* tex0 = tmp_ss->getTextureAttribute(0,osg::StateAttribute::TEXTURE);
1472                    if(tex0)
1473                        sset->setTextureAttributeAndModes(n_mat,tex0,osg::StateAttribute::ON);
1474                    // submitted by a. danklefsen
1475                    // Alion science and Technology 2/12/07
1476                    // copy fid/smc codes over to this new state set from the prev state set.
1477                    sset->setUserData(tmp_ss->getUserData());
1478                }
1479//                sset->merge(*tmp_ss.get());
1480            }
1481            else 
1482                sset = tmp_ss;
1483        }
1484
1485        if (!tex_coords.empty())
1486        {
1487            for (int texno = 0; texno < num_tex; texno++)
1488            {
1489                geometry->setTexCoordArray( texno, tex_coords[texno].get());
1490            }
1491        }
1492
1493        if (_parse->underBillboardSubgraph())
1494        {
1495            geometry->setStateSet(sset.get());
1496
1497            TXPParser::TXPBillboardInfo info;
1498            _parse->getLastBillboardInfo(info);
1499
1500            osg::ref_ptr<osg::Billboard> billboard = new osg::Billboard;
1501            billboard->setAxis(osg::Vec3(0.0f,0.0,1.0f) );
1502            billboard->setNormal(osg::Vec3(0.0f,-1.0,0.0f));
1503           
1504            geometry->setUseDisplayList(true);
1505
1506            switch (info.mode)
1507            {
1508            case trpgBillboard::World:
1509                billboard->setMode(osg::Billboard::POINT_ROT_WORLD);
1510                break;
1511            case trpgBillboard::Eye:
1512                billboard->setMode(osg::Billboard::POINT_ROT_EYE);
1513                break;
1514            default:
1515                billboard->setMode(osg::Billboard::AXIAL_ROT);
1516                break;
1517            }
1518
1519            switch (info.type)
1520            {
1521            case trpgBillboard::Individual:
1522            {
1523                // compute center of billboard geometry
1524                const osg::BoundingBox& bbox = geometry->getBound();
1525                osg::Vec3 center ((bbox._min + bbox._max) * 0.5f);
1526
1527                // make billboard geometry coordinates relative to computed center
1528                osg::Matrix matrix;
1529                matrix.makeTranslate(-center[0], -center[1], -center[2]);
1530
1531                TransformFunctor tf(matrix);
1532                geometry->accept(tf);
1533                geometry->dirtyBound();
1534
1535                billboard->addDrawable(geometry.get());
1536                billboard->setPosition(0, center);
1537            }
1538            break;
1539            case trpgBillboard::Group:
1540            {
1541                osg::Vec3 center(info.center.x, info.center.y, info.center.z);
1542
1543                // make billboard geometry coordinates relative to specified center
1544                osg::Matrix matrix;
1545                matrix.makeTranslate(-center[0], -center[1], -center[2]);
1546
1547                TransformFunctor tf(matrix);
1548                geometry->accept(tf);
1549                geometry->dirtyBound();
1550
1551                billboard->addDrawable(geometry.get());
1552                billboard->setPosition(0, center);
1553            }
1554            break;
1555            default:
1556                billboard->addDrawable(geometry.get());
1557                osg::notify(osg::WARN) << "TerraPage loader: fell through case: " <<  __FILE__ << " " << __LINE__  << ".\n";
1558                break;
1559            }
1560
1561            top->addChild(billboard.get());
1562        }
1563        else
1564#if 0
1565        if (_parse->underLayerSubgraph())
1566        {
1567            osg::Geode* layer = _parse->getLayerGeode();
1568
1569            if (layer->getNumDrawables())
1570            {
1571                osg::StateSet* poStateSet = new osg::StateSet;
1572                osg::PolygonOffset* polyoffset = new osg::PolygonOffset;
1573
1574                poStateSet->merge(*sset.get());
1575                polyoffset->setFactor(-1.0f);//*layer->getNumDrawables());
1576                polyoffset->setUnits(-20.0f);//*layer->getNumDrawables());
1577                poStateSet->setAttributeAndModes(polyoffset,osg::StateAttribute::ON);
1578
1579
1580                geometry->setStateSet(poStateSet);
1581            }
1582            else
1583            {
1584                geometry->setStateSet(sset.get());
1585            }
1586
1587            layer->addDrawable(geometry.get());
1588        }
1589        else
1590#else
1591        {
1592            geometry->setStateSet(sset.get());
1593            if (geodeTop)
1594            {
1595                geodeTop->getGeode()->addDrawable(geometry.get());
1596                _parse->setCurrentNode(geodeTop->getGeode());
1597            }
1598            else
1599            {
1600                osg::Geode* geode = new osg::Geode;
1601                geode->addDrawable(geometry.get());
1602
1603                _parse->setCurrentNode(geode);
1604                _parse->getCurrTop()->addChild(geode);
1605            }
1606        }
1607#endif       
1608       
1609    }
1610    else
1611    {
1612        osg::notify(osg::WARN)<<"Detected potential memory leak in TXPParser.cpp"<<std::endl;
1613    }
1614   
1615    return (void *) 1;
1616}
1617
1618
1619namespace
1620{
1621    void check_format(trpgTexture::ImageType type, int depth, GLenum& internalFormat, GLenum& pixelFormat, GLenum&)
1622    {
1623        switch(type)
1624        {
1625        case trpgTexture::trpg_RGB8:
1626            internalFormat = GL_RGB;
1627            pixelFormat    = GL_RGB;
1628            break;
1629        case trpgTexture::trpg_RGBA8:
1630            internalFormat = GL_RGBA;
1631            pixelFormat    = GL_RGBA;
1632            break;
1633        case trpgTexture::trpg_INT8:
1634            internalFormat = GL_LUMINANCE;
1635            pixelFormat    = GL_LUMINANCE;
1636            break;
1637        case trpgTexture::trpg_INTA8:
1638            internalFormat = GL_LUMINANCE_ALPHA;
1639            pixelFormat    = GL_LUMINANCE_ALPHA;
1640            break;
1641        case trpgTexture::trpg_FXT1:
1642        case trpgTexture::trpg_Filler:
1643        case trpgTexture::trpg_RGBX: // MCM
1644        case trpgTexture::trpg_Unknown:
1645            break;
1646        case trpgTexture::trpg_DDS:
1647        case trpgTexture::trpg_DXT1:
1648            if(depth == 3)
1649            {
1650                internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1651                pixelFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1652            }
1653            else
1654            {
1655                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1656                pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1657            }
1658            break;
1659        case trpgTexture::trpg_DXT3:
1660            if(depth == 3)
1661            {
1662                // not supported.
1663            }
1664            else
1665            {
1666                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1667                pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
1668            }
1669            break;
1670        case trpgTexture::trpg_DXT5:
1671            if(depth == 3)
1672            {
1673                // not supported.
1674            }
1675            else
1676            {
1677                internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
1678                pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
1679            }
1680            break;
1681        case trpgTexture::trpg_MCM5:
1682        case trpgTexture::trpg_MCM6R:
1683        case trpgTexture::trpg_MCM6A:
1684        case trpgTexture::trpg_MCM7RA:
1685        case trpgTexture::trpg_MCM7AR:
1686            break;
1687        }
1688    }
1689}
1690
1691//----------------------------------------------------------------------------
1692// Get a template texture via the image helper
1693osg::Texture2D* txp::getLocalTexture(trpgrImageHelper& image_helper, const trpgTexture* tex)
1694{
1695    osg::Texture2D* osg_texture= 0L;
1696
1697    trpg2iPoint s;
1698    tex->GetImageSize(s);
1699    int32 depth;
1700    tex->GetImageDepth(depth);
1701    trpgTexture::ImageType type;
1702    tex->GetImageType(type);
1703   
1704    GLenum internalFormat = (GLenum)-1;
1705    GLenum pixelFormat = (GLenum)-1;
1706    GLenum dataType = GL_UNSIGNED_BYTE;
1707
1708    check_format(type,depth,internalFormat , pixelFormat , dataType);
1709   
1710    if(pixelFormat!=(GLenum)-1)
1711    {
1712        osg_texture = new osg::Texture2D();
1713
1714        // make sure the Texture unref's the Image after apply, when it is no longer needed.               
1715        osg_texture->setUnRefImageDataAfterApply(true);
1716
1717        osg::Image* image = new osg::Image;
1718        char* data = 0L;
1719
1720        bool bMipmap;
1721        tex->GetIsMipmap(bMipmap);
1722        int32 num_mipmaps = bMipmap  ?  tex->CalcNumMipmaps() : 1; // this is currently line 130
1723
1724        // osg::Image do their own mipmaps
1725        if(num_mipmaps <= 1)
1726        {
1727            int32 size = tex->CalcTotalSize();
1728            data = new char [size];
1729            image_helper.GetLocalGL(tex,data,size);
1730            image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
1731                    (unsigned char*)data,osg::Image::USE_NEW_DELETE);
1732        }
1733        else
1734        {
1735            int32 size = tex->CalcTotalSize();
1736            trpgTexture* tmp_tex = const_cast<trpgTexture*>(tex);
1737
1738            data = new char [size];
1739            image_helper.GetLocalGL(tex,data,size);
1740            // Load entire texture including mipmaps
1741            image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
1742                    (unsigned char*)data,
1743                    osg::Image::USE_NEW_DELETE);
1744
1745            // now set mipmap data (offsets into image raw data)
1746            osg::Image::MipmapDataType mipmaps;
1747            // number of offsets in osg is one less than num_mipmaps
1748            // because it's assumed that first offset iz 0
1749            mipmaps.resize(num_mipmaps-1);
1750            for( int k = 1 ; k < num_mipmaps;k++ )
1751            {
1752                mipmaps[k-1] = tmp_tex->MipLevelOffset(k);
1753            }
1754
1755            image->setMipmapLevels(mipmaps);
1756
1757        }
1758
1759        osg_texture->setImage(image);
1760    }
1761    return osg_texture;
1762}
1763
1764//----------------------------------------------------------------------------
1765// Get a locale texture via the image helper
1766osg::Texture2D* txp::getTemplateTexture(trpgrImageHelper& image_helper, trpgLocalMaterial* locmat, const trpgTexture* tex, int index)
1767{
1768    osg::Texture2D* osg_texture= 0L;
1769
1770    trpg2iPoint s;
1771    tex->GetImageSize(s);
1772    int32 depth;
1773    tex->GetImageDepth(depth);
1774    trpgTexture::ImageType type;
1775    tex->GetImageType(type);
1776   
1777    GLenum internalFormat = (GLenum)-1;
1778    GLenum pixelFormat = (GLenum)-1;
1779    GLenum dataType = GL_UNSIGNED_BYTE;
1780
1781    check_format(type,depth,internalFormat , pixelFormat , dataType);
1782   
1783    if(pixelFormat!=(GLenum)-1)
1784    {
1785        osg_texture = new osg::Texture2D();
1786
1787        // make sure the Texture unref's the Image after apply, when it is no longer needed.               
1788        osg_texture->setUnRefImageDataAfterApply(true);
1789
1790        osg::Image* image = new osg::Image;
1791        char* data = 0L;
1792
1793        bool bMipmap;
1794        tex->GetIsMipmap(bMipmap);
1795        int32 num_mipmaps = bMipmap  ?  tex->CalcNumMipmaps() : 1; // this is currently line 130
1796
1797        // osg::Image do their own mipmaps
1798        if(num_mipmaps <= 1)
1799        {
1800            int32 size = tex->CalcTotalSize();
1801            data = new char [size];
1802            image_helper.GetNthImageForLocalMat(locmat,index, data,size);
1803
1804            image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
1805                    (unsigned char*)data,osg::Image::USE_NEW_DELETE);
1806        }
1807        else
1808        {
1809            int32 size = tex->CalcTotalSize();
1810            trpgTexture* tmp_tex = const_cast<trpgTexture*>(tex);
1811
1812            data = new char [size];
1813
1814            image_helper.GetNthImageForLocalMat(locmat,index, data,size);
1815
1816            // Load entire texture including mipmaps
1817            image->setImage(s.x,s.y,1,internalFormat, pixelFormat, dataType,
1818                    (unsigned char*)data,
1819                    osg::Image::USE_NEW_DELETE);
1820
1821            // now set mipmap data (offsets into image raw data)
1822            osg::Image::MipmapDataType mipmaps;
1823            // number of offsets in osg is one less than num_mipmaps
1824            // because it's assumed that first offset iz 0
1825            mipmaps.resize(num_mipmaps-1);
1826            for( int k = 1 ; k < num_mipmaps;k++ )
1827            {
1828                mipmaps[k-1] = tmp_tex->MipLevelOffset(k);
1829            }
1830
1831            image->setMipmapLevels(mipmaps);
1832
1833        }
1834
1835        osg_texture->setImage(image);
1836    }
1837    return osg_texture;
1838}
1839
1840
Note: See TracBrowser for help on using the browser.