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

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

From Mathias Froehlich, "We are currently getting issues with locale settings and some osg plugins.
Therefore I have changed all the occurances of atof by asciiToFloat or
asciiToDouble.

I believe that it is safe to do so at least for all the plugins.
Included here are also asciiToFloat conversion of environment variables. One
might argue that these should be locale dependent. But IMO these should be
set and interpreted by osg independent of the current locale.
"

  • 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 = osg::asciiToFloat(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.