root/OpenSceneGraph/trunk/src/osgPlugins/txp/TXPArchive.cpp @ 13041

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

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <osg/Notify>
2#include <osg/Geode>
3#include <osg/ShapeDrawable>
4#include <osg/AlphaFunc>
5#include <osg/Group>
6#include <osg/Image>
7#include <osg/Texture2D>
8#include <osg/Material>
9#include <osg/TexEnv>
10#include <osg/CullFace>
11#include <osg/Light>
12#include <osg/StateSet>
13#include <osg/Point>
14#include <osg/BlendFunc>
15#include <osg/MatrixTransform>
16#include <osgDB/FileUtils>
17#include <osgDB/FileUtils>
18#include <osgDB/FileNameUtils>
19#include <osgDB/fstream>
20#include <osgDB/ReadFile>
21#include <osgDB/WriteFile>
22#include <osgSim/Sector>
23#include <osgSim/LightPoint>
24#include <osgSim/LightPointNode>
25#include <osgSim/BlinkSequence>
26#include <iostream>
27
28#if defined(linux)
29include <unistd.h>
30define _access access
31#endif
32
33#include "TXPArchive.h"
34#include "TXPParser.h"
35#include "TileMapper.h"
36
37#include <OpenThreads/ScopedLock>
38
39using namespace txp;
40
41#define TXPArchiveERROR(s) OSG_NOTICE << "txp::TXPArchive::" << (s) << " error: "
42
43
44void TXPArchive::SetTexMap(int key,osg::ref_ptr<osg::Texture2D> ref)
45{
46    _texmap[key] = ref;
47}
48
49osg::ref_ptr<osg::Texture2D> TXPArchive::GetTexMapEntry(int key)
50{
51    return _texmap[key];
52}
53
54void TXPArchive::SetStatesMap(int key,osg::ref_ptr<osg::StateSet> ref)
55{
56    _statesMap[key] = ref;
57}
58
59osg::ref_ptr<osg::StateSet> TXPArchive::GetStatesMapEntry(int key)
60{
61    return _statesMap[key];
62}
63
64TXPArchive::TXPArchive():
65    trpgr_Archive(),
66    _id(-1),
67    _numLODs(0),
68    _swExtents(0.0,0.0),
69    _neExtents(0.0,0.0),
70    _majorVersion(-1),
71    _minorVersion(-1),
72    _isMaster(false),
73    _loadMaterialsToStateSet(false)
74{
75}
76
77TXPArchive::~TXPArchive()
78{
79    CloseFile();
80}
81
82
83void  TXPArchive::getExtents(osg::BoundingBox& extents)
84{
85    TileInfo sw, ne;
86    trpg2iPoint tileExtents;
87
88    this->GetHeader()->GetLodSize(0, tileExtents);
89    this->getTileInfo(0, 0, 0, sw);
90    this->getTileInfo(tileExtents.x-1, tileExtents.y-1, 0, ne);
91    extents.set(sw.bbox._min, sw.bbox._max);
92    extents.expandBy(ne.bbox);
93}
94
95
96bool TXPArchive::openFile(const std::string& archiveName)
97{
98    std::string path = osgDB::getFilePath(archiveName);
99    std::string name = osgDB::getSimpleFileName(archiveName);
100
101    if(path.empty())
102    {
103        SetDirectory(".");
104    }
105    else
106    {
107        // push the path to the front of the list so that all subsequenct
108        // files get loaded relative to this if possible.
109        osgDB::getDataFilePathList().push_front(path);
110        SetDirectory(path.c_str());
111    }
112
113    if (!OpenFile(name.c_str()))
114    {
115        TXPArchiveERROR("openFile()") << "couldn't open archive: " << archiveName << std::endl;
116        return false;
117    }
118
119    if (!ReadHeader(false))
120    {
121        TXPArchiveERROR("openFile()") << "couldn't read header for archive: " << archiveName << std::endl;
122        return false;
123    }
124
125    const trpgHeader *header = GetHeader();
126    if (header)
127    {
128        header->GetNumLods(_numLODs);
129        header->GetExtents(_swExtents,_neExtents);
130        header->GetVersion(_majorVersion, _minorVersion);
131    _isMaster = header->GetIsMaster();
132    }
133
134    int numTextures;
135    texTable.GetNumTextures(numTextures);
136
137    int numModel;
138    modelTable.GetNumModels(numModel);
139    _models.clear();
140
141    int numMaterials;
142    materialTable.GetNumMaterial(numMaterials);
143
144    return true;
145}
146
147bool TXPArchive::loadMaterial(int ix)
148{
149    int i = ix;
150
151
152    if (GetStatesMapEntry(ix).get())
153    return true;
154
155    osg::StateSet* osg_state_set = new osg::StateSet;
156
157    const trpgMaterial *mat;
158    mat = materialTable.GetMaterialRef(0,i);
159
160    // Set texture
161    int numMatTex;
162    mat->GetNumTexture(numMatTex);
163
164    // TODO : multitextuting
165    // also note that multitexturing in terrapage can came from two sides
166    // - multiple textures per material, and multiple materials per geometry
167    // Note: Only in theory.  The only type you'll encounter is multiple
168    //         materials per polygon.
169    if( numMatTex )
170    {
171        osg::Material *osg_material     = new osg::Material;
172
173        float64 alpha;
174        mat->GetAlpha(alpha);
175
176        trpgColor color;
177        mat->GetAmbient(color);
178        osg_material->setAmbient( osg::Material::FRONT_AND_BACK ,
179                  osg::Vec4(color.red, color.green, color.blue, alpha));
180        mat->GetDiffuse(color);
181        osg_material->setDiffuse(osg::Material::FRONT_AND_BACK ,
182                 osg::Vec4(color.red, color.green, color.blue, alpha));
183
184        mat->GetSpecular(color);
185        osg_material->setSpecular(osg::Material::FRONT_AND_BACK ,
186                  osg::Vec4(color.red, color.green, color.blue, alpha));
187        mat->GetEmission(color);
188        osg_material->setEmission(osg::Material::FRONT_AND_BACK ,
189                  osg::Vec4(color.red, color.green, color.blue, alpha));
190
191        float64 shinines;
192        mat->GetShininess(shinines);
193        osg_material->setShininess(osg::Material::FRONT_AND_BACK , (float)shinines);
194
195        osg_material->setAlpha(osg::Material::FRONT_AND_BACK ,(float)alpha);
196        osg_state_set->setAttributeAndModes(osg_material, osg::StateAttribute::ON);
197
198        SetUserDataToMaterialAttributes(*osg_state_set, *mat);
199
200        if( alpha < 1.0f )
201        {
202            osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);
203            osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
204        }
205
206        int alphaFunc;
207        mat->GetAlphaFunc(alphaFunc);
208        if( alphaFunc>=GL_NEVER && alphaFunc<=GL_ALWAYS)
209        {
210            float64 ref;
211            mat->GetAlphaRef(ref);
212            osg::AlphaFunc *osg_alpha_func = new osg::AlphaFunc;
213            osg_alpha_func->setFunction((osg::AlphaFunc::ComparisonFunction)alphaFunc,(float)ref);
214            osg_state_set->setAttributeAndModes(osg_alpha_func, osg::StateAttribute::ON);
215        }
216
217        for (int ntex = 0; ntex < numMatTex; ntex ++ )
218        {
219            int texId;
220            trpgTextureEnv texEnv;
221            mat->GetTexture(ntex,texId,texEnv);
222
223            // Set up texture environment
224            osg::TexEnv       *osg_texenv       = new osg::TexEnv();
225            int32 te_mode;
226            texEnv.GetEnvMode(te_mode);
227            switch( te_mode )
228            {
229            case trpgTextureEnv::Alpha :
230                osg_texenv->setMode(osg::TexEnv::REPLACE);
231                break;
232            case trpgTextureEnv::Decal:
233                osg_texenv->setMode(osg::TexEnv::DECAL);
234                break;
235            case trpgTextureEnv::Blend :
236                osg_texenv->setMode(osg::TexEnv::BLEND);
237                break;
238            case trpgTextureEnv::Modulate :
239                osg_texenv->setMode(osg::TexEnv::MODULATE);
240                break;
241            }
242
243            osg_state_set->setTextureAttribute(ntex,osg_texenv);
244
245            int wrap_s, wrap_t;
246            texEnv.GetWrap(wrap_s, wrap_t);
247
248            loadTexture(texId);
249            osg::Texture2D* osg_texture = GetTexMapEntry(texId).get();
250            if(osg_texture)
251            {
252
253                osg_texture->setWrap(osg::Texture2D::WRAP_S, wrap_s == trpgTextureEnv::Repeat ? osg::Texture2D::REPEAT: osg::Texture2D::CLAMP_TO_EDGE );
254                osg_texture->setWrap(osg::Texture2D::WRAP_T, wrap_t == trpgTextureEnv::Repeat ? osg::Texture2D::REPEAT: osg::Texture2D::CLAMP_TO_EDGE );
255
256                // -----------
257                // Min filter
258                // -----------
259                int32 minFilter;
260                texEnv.GetMinFilter(minFilter);
261                switch (minFilter)
262                {
263                case trpgTextureEnv::Point:
264                case trpgTextureEnv::Nearest:
265                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
266                    break;
267                case trpgTextureEnv::Linear:
268                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
269                    break;
270                case trpgTextureEnv::MipmapPoint:
271                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_NEAREST);
272                    break;
273                case trpgTextureEnv::MipmapLinear:
274                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST_MIPMAP_LINEAR);
275                    break;
276                case trpgTextureEnv::MipmapBilinear:
277                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_NEAREST);
278                    break;
279                case trpgTextureEnv::MipmapTrilinear:
280                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR_MIPMAP_LINEAR);
281                    break;
282                default:
283                    osg_texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
284                    break;
285                }
286
287
288                // -----------
289                // Mag filter
290                // -----------
291                int32 magFilter;
292                texEnv.GetMagFilter(magFilter);
293                switch (magFilter)
294                {
295                case trpgTextureEnv::Point:
296                case trpgTextureEnv::Nearest:
297                    osg_texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
298                    break;
299                case trpgTextureEnv::Linear:
300                default:
301                    osg_texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
302                    break;
303                }
304
305                // pass on to the stateset.
306                osg_state_set->setTextureAttributeAndModes(ntex,osg_texture, osg::StateAttribute::ON);
307
308                if(osg_texture->getImage() &&  osg_texture->getImage()->isImageTranslucent())
309                {
310                    osg_state_set->setMode(GL_BLEND,osg::StateAttribute::ON);
311                    osg_state_set->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
312                }
313            }
314        }
315
316        int cullMode;
317        mat->GetCullMode(cullMode);
318
319        // Culling mode in txp means opposite from osg i.e. Front-> show front face
320        if( cullMode != trpgMaterial::FrontAndBack)
321        {
322            osg::CullFace* cull_face = new osg::CullFace;
323            switch (cullMode)
324            {
325            case trpgMaterial::Front:
326                cull_face->setMode(osg::CullFace::BACK);
327                break;
328            case trpgMaterial::Back:
329                cull_face->setMode(osg::CullFace::FRONT);
330                break;
331            }
332            osg_state_set->setAttributeAndModes(cull_face, osg::StateAttribute::ON);
333        }
334    }
335    SetStatesMap(i,osg_state_set);
336
337    return true;
338}
339
340bool TXPArchive::loadMaterials()
341{
342    return true;
343}
344
345bool TXPArchive::loadTexture(int i)
346{
347    if (GetTexMapEntry(i).get())
348    return true;
349
350    bool separateGeo = false;
351    int majorVer,minorVer;
352    GetVersion(majorVer,minorVer);
353    if((majorVer >= TRPG_NOMERGE_VERSION_MAJOR) && (minorVer>=TRPG_NOMERGE_VERSION_MINOR))
354    {
355    separateGeo = true;
356    }
357    trpgrImageHelper image_helper(this->GetEndian(),getDir(),materialTable,texTable,separateGeo);
358
359    const trpgTexture *tex;
360    tex = texTable.GetTextureRef(i);
361    if (!tex)
362    return false;
363
364    trpgTexture::ImageMode mode;
365    tex->GetImageMode(mode);
366    if(mode == trpgTexture::External)
367    {
368    char texName[ 1024 ];
369    texName[ 0 ] = 0;
370        tex->GetName(texName,1023);
371
372        // Create a texture by name.
373        osg::ref_ptr<osg::Texture2D> osg_texture = new osg::Texture2D();
374
375        // make sure the Texture unref's the Image after apply, when it is no longer needed.
376        osg_texture->setUnRefImageDataAfterApply(true);
377
378        // Load Texture and Create Texture State
379        std::string filename = osgDB::getSimpleFileName(texName);
380        std::string path(getDir());
381#ifdef _WIN32
382        const char _PATHD = '\\';
383#elif defined(macintosh)
384        const char _PATHD = ':';
385#else
386        const char _PATHD = '/';
387#endif
388        if( path == "." )
389            path = "";
390        else
391            path += _PATHD ;
392
393        std::string theFile = path + filename ;
394        osg::ref_ptr<osg::Image> image = osgDB::readRefImageFile(theFile);
395        if (image.valid())
396        {
397            osg_texture->setImage(image.get());
398        }
399        else
400        {
401            OSG_WARN << "TrPageArchive::LoadMaterials() error: "
402                   << "couldn't open image: " << filename << std::endl;
403        }
404    SetTexMap(i,osg_texture);
405    }
406    else if( mode == trpgTexture::Local )
407    {
408    SetTexMap(i,getLocalTexture(image_helper,tex));
409    }
410    else if( mode == trpgTexture::Template )
411    {
412    SetTexMap(i,0L);
413    }
414    else
415    {
416    SetTexMap(i,0L);
417    }
418
419    return (GetTexMapEntry(i).get() != 0);
420}
421
422bool TXPArchive::loadModel(int ix)
423{
424    trpgModel *mod = modelTable.GetModelRef(ix);
425    int type;
426    if(!mod)
427    return false;
428    mod->GetType(type);
429
430    // Only dealing with external models currently
431    if (type == trpgModel::External)
432    {
433        char name[1024];
434        mod->GetName(name,1023);
435
436        // Load the model.  It's probably not TerraPage
437    osg::Node *osg_model = osgDB::readNodeFile( name );
438    if ( !osg_model )
439        {
440            OSG_WARN << "TrPageArchive::LoadModels() error: "
441                   << "failed to load model: "
442                   << name << std::endl;
443        }
444    // Do this even if it's NULL
445    _models[ ix ] = osg_model;
446    }
447/*
448  else
449  {
450  trpgMemReadBuffer buf(GetEndian());
451  mod->Read(buf);
452  Group *osg_model = parse->ParseScene(buf, m_gstates , m_models);
453  m_models.push_back(osg_model);
454  }
455*/
456    return true;
457}
458
459bool TXPArchive::loadModels()
460{
461    OSG_INFO << "txp:: Loading models ..." << std::endl;
462
463    int numModel;
464    modelTable.GetNumModels(numModel);
465
466    // use a pointer to the models map to bootstrap our map
467    trpgModelTable::ModelMapType *mt = modelTable.GetModelMap();
468    trpgModelTable::ModelMapType::iterator itr = mt->begin();
469    for (  ; itr != mt->end( ); itr++)
470    {
471    loadModel(itr->first);
472    }
473    OSG_INFO << "txp:: ... done." << std::endl;
474    return true;
475}
476
477bool TXPArchive::loadLightAttributes()
478{
479    OSG_INFO << "txp:: Loading light attributes ..." << std::endl;
480
481    trpgLightTable::LightMapType *lm  = lightTable.getLightMap();
482    trpgLightTable::LightMapType::iterator itr = lm->begin();
483    for ( ; itr != lm->end() ; itr++)
484    {
485        trpgLightAttr* ref = &itr->second;
486
487        osgSim::LightPointNode* osgLight = new osgSim::LightPointNode();
488
489        osg::Point* osgPoint = new osg::Point();
490
491        osgSim::LightPoint lp ;
492        lp._on = true;
493
494        trpgColor col;
495        ref->GetFrontColor(col);
496        lp._color = osg::Vec4(col.red, col.green,col.blue, 1.0);
497
498        float64 inten;
499        ref->GetFrontIntensity(inten);
500        lp._intensity = inten;
501
502        trpgLightAttr::PerformerAttr perfAttr;
503        ref->GetPerformerAttr(perfAttr);
504
505        // point part
506        //osgPoint->setSize(perfAttr.actualSize);
507        osgPoint->setSize(5);
508        osgPoint->setMaxSize(perfAttr.maxPixelSize);
509        osgPoint->setMinSize(perfAttr.minPixelSize);
510        osgPoint->setFadeThresholdSize(perfAttr.transparentFallofExp);
511        //numbers that are going to appear are "experimental"
512        osgPoint->setDistanceAttenuation(osg::Vec3(0.0001, 0.0005, 0.00000025));
513//        osgPoint->setDistanceAttenuation(osg::Vec3(1.0, 0.0, 1.0));
514
515        osg::StateSet* stateSet = new osg::StateSet();
516        stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
517        stateSet->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON);
518        stateSet->setAttributeAndModes(osgPoint, osg::StateAttribute::ON );
519        stateSet->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::ON);
520
521        osgLight->setMaxPixelSize(perfAttr.maxPixelSize);
522        osgLight->setMinPixelSize(perfAttr.minPixelSize);
523
524//        float64 clamp;
525//        ref->GetPerformerTpClamp(clamp);
526//        osgLight->setMaxVisibleDistance2(clamp);
527
528        trpg3dPoint normal;
529        ref->GetNormal(normal);
530
531//        lp._radius = clamp;
532
533        trpgLightAttr::LightDirectionality direc;
534        ref->GetDirectionality(direc);
535        if( direc == trpgLightAttr::trpg_Unidirectional)
536        {
537            osgSim::AzimElevationSector*  sec = new osgSim::AzimElevationSector();
538            float64 tmp;
539            ref->GetHLobeAngle(tmp);
540            float64 tmpfade;
541            ref->GetLobeFalloff(tmpfade);
542            sec->setAzimuthRange(-tmp/2.0,tmp/2.0,tmpfade);
543
544            ref->GetVLobeAngle(tmp);
545            sec->setElevationRange(0,tmp, tmpfade);
546
547            lp._sector = sec;
548            osgLight->addLightPoint(lp);
549        }
550        else if( direc == trpgLightAttr::trpg_Bidirectional )
551        {
552            osgSim::AzimElevationSector*  front = new osgSim::AzimElevationSector();
553            float64 tmp;
554            ref->GetHLobeAngle(tmp);
555            float64 tmpfade;
556            ref->GetLobeFalloff(tmpfade);
557            front->setAzimuthRange(-tmp/2.0,tmp/2.0,tmpfade);
558
559            ref->GetVLobeAngle(tmp);
560            front->setElevationRange(0,tmp, tmpfade);
561
562            lp._sector = front;
563            osgLight->addLightPoint(lp);
564
565            osgSim::AzimElevationSector*  back = new osgSim::AzimElevationSector();
566            back->setAzimuthRange(osg::PI-tmp/2.0,osg::PI+tmp/2.0,tmpfade);
567            back->setElevationRange(0,tmp, tmpfade);
568            lp._sector = back;
569            osgLight->addLightPoint(lp);
570        }
571    else
572    {
573            osgLight->addLightPoint(lp);
574        }
575
576    addLightAttribute(osgLight, stateSet, osg::Vec3(normal.x,normal.y,normal.z),itr->first);
577    }
578
579    OSG_INFO << "txp:: ... done." << std::endl;
580    return true;
581}
582
583void trim(std::string& str)
584{
585    while (!str.empty() && isspace(str[str.length()-1]))
586    str.erase(str.length()-1);
587    while (!str.empty() && isspace(str[0]))
588        str.erase(0,1);
589}
590bool TXPArchive::loadTextStyles()
591{
592    const trpgTextStyleTable *textStyleTable = GetTextStyleTable();
593    if ( !textStyleTable )
594    return false;
595    if ( textStyleTable->GetNumStyle() < 1 )
596    return true;
597
598    // try fontmap.txt
599    std::map< std::string, std::string > fontmap;
600
601    std::string fmapfname = std::string(getDir())+"\\fontmap.txt";
602    osgDB::ifstream fmapfile;
603    fmapfile.open(fmapfname.c_str(),std::ios::in);
604
605    if (fmapfile.is_open())
606    {
607    OSG_INFO << "txp:: Font map file found: " << fmapfname << std::endl;
608    std::string line;
609    while (std::getline(fmapfile,line))
610    {
611        std::string::size_type ix = line.find_first_of('=');
612        if (ix != std::string::npos)
613        {
614        std::string fontname = line.substr(0,ix);
615        std::string fontfilename = line.substr(ix+1,line.length()-ix+1);
616
617        trim(fontname);
618        trim(fontfilename);
619
620        fontmap[fontname] = fontfilename;
621
622        }
623    }
624    fmapfile.close();
625    }
626    else
627    {
628    OSG_NOTICE << "txp:: No font map file found: " << fmapfname << std::endl;
629    OSG_NOTICE << "txp:: All fonts defaulted to arial.ttf" << std::endl;
630    }
631
632    const trpgTextStyleTable::StyleMapType *smap = textStyleTable->getStyleMap();
633    trpgTextStyleTable::StyleMapType::const_iterator itr = smap->begin();
634    for (  ; itr != smap->end(); itr++)
635    {
636    const trpgTextStyle *textStyle = &itr->second;
637    if ( !textStyle )
638        continue;
639
640    const std::string *fontName = textStyle->GetFont();
641    if ( !fontName )
642        continue;
643
644    std::string fontfilename = fontmap[*fontName];
645    if ( !fontfilename.length() )
646        fontfilename = "arial.ttf";
647    osg::ref_ptr< osgText::Font > font = osgText::readFontFile(fontfilename);
648
649    _fonts[itr->first] = font;
650
651    const trpgMatTable* matTable = GetMaterialTable();
652    if (matTable)
653    {
654        int matId = textStyle->GetMaterial();
655        const trpgMaterial* mat = matTable->GetMaterialRef(0,matId);
656        if (mat)
657        {
658        trpgColor faceColor;
659        mat->GetColor(faceColor);
660
661        float64 alpha;
662        mat->GetAlpha(alpha);
663
664        _fcolors[itr->first] = osg::Vec4(faceColor.red, faceColor.green, faceColor.blue, alpha );
665        }
666    }
667    }
668
669    return true;
670}
671
672void TXPArchive::addLightAttribute(osgSim::LightPointNode* lpn, osg::StateSet* fallback, const osg::Vec3& att,int handle)
673{
674    DeferredLightAttribute la;
675    la.lightPoint = lpn;
676    la.fallback = fallback;
677    la.attitude = att;
678    _lights[handle] = la;
679}
680
681bool TXPArchive::getTileInfo(const TileLocationInfo& loc, TileInfo& info)
682{
683    info.minRange = 0.0;
684    info.maxRange = 0.0;
685    info.radius = 0.f;
686    info.center.set(0.f,0.f,0.f);
687    info.bbox.set(0.f,0.f,0.f,0.f,0.f,0.f);
688
689    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
690
691    header.GetLodRange(loc.lod,info.maxRange);
692    header.GetLodRange(loc.lod+1,info.minRange);
693    header.GetLodRange(0,info.lod0Range);
694
695    trpg2dPoint sw,ne;
696    header.GetExtents(sw,ne);
697
698    trpg2dPoint size;
699    header.GetTileSize(loc.lod,size);
700
701    info.size.x() = size.x;
702    info.size.y() = size.y;
703    info.size.z() = 0.f;
704
705    info.center.set(
706        sw.x+(loc.x*size.x)+(size.x/2.f),
707        sw.y+(loc.y*size.y)+(size.y/2.f),
708        (loc.zmin + loc.zmax)/2.f
709    );
710    info.bbox.set(
711        osg::Vec3(
712            info.center.x()-(size.x/2.f),
713            info.center.y()-(size.y/2.f),
714            loc.zmin
715        ),
716        osg::Vec3(
717            info.center.x()+(size.x/2.f),
718            info.center.y()+(size.y/2.f),
719            loc.zmax
720        )
721    );
722    info.radius = osg::Vec3(size.x/2.f, size.y/2.f,0.f).length() * 1.3;
723
724    return true;
725
726}
727
728bool TXPArchive::getTileInfo(int x, int y, int lod, TileInfo& info)
729{
730    trpgwAppAddress addr;
731    float minz = 0.f;
732    float maxz = 0.f;
733    tileTable.GetTile(x, y, lod, addr, minz, maxz);
734
735    TileLocationInfo loc(x, y, lod, addr,  minz, maxz);
736
737    return getTileInfo(loc, info);
738}
739
740osg::Group* TXPArchive::getTileContent(
741    int x, int y, int lod,
742    double realMinRange,
743    double realMaxRange,
744    double usedMaxRange,
745    osg::Vec3& tileCenter,
746    std::vector<TileLocationInfo>& childInfoList)
747{
748    if(_majorVersion == 2 && _minorVersion >= 1)
749    {
750    // Version 2.1
751    // This call is valid only for lod = 0
752    if(lod != 0)
753        return new osg::Group;
754    }
755
756    trpgwAppAddress addr;
757    float minz = 0.f;
758    float maxz = 0.f;
759    tileTable.GetTile(x, y, lod, addr, minz, maxz);
760    TileLocationInfo loc(x,y,lod,addr, minz,maxz);
761
762    return getTileContent(loc, realMinRange, realMaxRange, usedMaxRange, tileCenter, childInfoList);
763
764}
765
766class ModelVisitor : public osg::NodeVisitor
767{
768    TXPArchive* _archive;
769    TXPArchive::TileLocationInfo _tileInfo;
770//     int _x;
771//     int _y;
772//     int _lod;
773
774public:
775    ModelVisitor(TXPArchive* archive, const TXPArchive::TileLocationInfo& loc):
776        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
777        _archive(archive), _tileInfo(loc)
778    {
779    }
780
781    virtual void apply(osg::MatrixTransform& xform)
782    {
783        const trpgHeader* header = _archive->GetHeader();
784        trpgHeader::trpgTileType tileType;
785        header->GetTileOriginType(tileType);
786        const osg::Referenced* ref = xform.getUserData();
787        const TileIdentifier* tileID = dynamic_cast<const txp::TileIdentifier*>(ref);
788
789        if(!tileID) return; // bail early - this isn't a loaded model
790
791        if(tileType == trpgHeader::TileLocal && tileID->lod == 9999)
792        {
793        trpg2dPoint tileExtents;
794        header->GetTileSize(0, tileExtents);
795        osg::BoundingBox bbox;
796        _archive->getExtents(bbox);
797        osg::Vec3 offset(xform.getMatrix().getTrans());
798        offset[0] -= bbox._min[0];
799        offset[1] -= bbox._min[1];
800
801        trpg2dPoint offsetXY, tileID(_tileInfo.x,_tileInfo.y);
802        int divider = (0x01 << _tileInfo.lod);
803        // calculate which tile model is located in
804        tileExtents.x /= divider;
805        tileExtents.y /= divider;
806        offset[0] -= tileID.x*tileExtents.x;
807        offset[1] -= tileID.y*tileExtents.y;
808
809        osg::Matrix mat(xform.getMatrix());
810        mat.setTrans(offset);
811        xform.setMatrix(mat);
812        }
813    }
814};
815
816
817osg::Group* TXPArchive::getTileContent(
818    const TileLocationInfo& loc,
819    double realMinRange,
820    double realMaxRange,
821    double usedMaxRange,
822    osg::Vec3& tileCenter,
823    std::vector<TileLocationInfo>& childInfoList)
824{
825
826    if (_parser.get() == 0)
827    {
828        _parser = new TXPParser();
829        _parser->setArchive(this);
830    }
831
832    trpgMemReadBuffer buf(GetEndian());
833    bool readStatus;
834    trpgTileTable::TileMode tileMode;
835    tileTable.GetMode(tileMode);
836    if(tileMode == trpgTileTable::External)
837    readStatus = ReadExternalTile(loc.x, loc.y, loc.lod, buf);
838    else
839    readStatus = ReadTile(loc.addr, buf);
840
841    if(!readStatus)
842    return new osg::Group;
843    trpgTileHeader *tilehdr = _parser->getTileHeaderRef();
844
845    int majVersion,minVersion;
846    GetVersion(majVersion,minVersion);
847    // only compute block # if we are a master archive.
848    if((majVersion >= TRPG_NOMERGE_VERSION_MAJOR) && (minVersion >= TRPG_NOMERGE_VERSION_MINOR) && (_isMaster))
849    {
850    if(tilehdr)
851    {
852        int x,y;
853        unsigned int denom = (1 << loc.lod); // this should work up to lod 31
854        x = loc.x/denom;
855        y = loc.y/denom;
856        tilehdr->SetBlockNo(y,x);
857    }
858    }
859
860    osg::Group *tileGroup = _parser->parseScene(buf,_statesMap,_models,realMinRange,realMaxRange,usedMaxRange);
861    tileCenter = _parser->getTileCenter();
862
863    int nbChild = _parser->GetNbChildrenRef();
864
865    childInfoList.clear();
866    for(int idx = 0; idx < nbChild; idx++)
867    {
868    const trpgChildRef *childRef = _parser->GetChildRef(idx);
869
870    if(childRef)
871    {
872        TileLocationInfo loc;
873        childRef->GetTileLoc(loc.x, loc.y, loc.lod);
874        childRef->GetTileZValue(loc.zmin, loc.zmax);
875        childRef->GetTileAddress(loc.addr);
876        childInfoList.push_back(loc);
877
878    }
879    }
880
881    // Fix up model MatrixTransform
882    ModelVisitor mv(this, loc);
883    tileGroup->accept(mv);
884
885    // Prune
886    OSGStatesMapType::iterator itr = _statesMap.begin();
887    while( itr != _statesMap.end( ) )
888    {
889    if(itr->second.valid() &&
890       (itr->second->referenceCount()==1))
891    {
892        // unreference it.
893            itr->second = NULL;
894
895            OSGStatesMapType::iterator toRemove = itr;
896            ++itr;
897
898        // remove it from the map
899            _statesMap.erase( toRemove );
900        }
901        else
902        {
903            ++itr;
904        }
905    }
906
907    OSGTexMapType::iterator mitr = _texmap.begin();
908    while( mitr != _texmap.end( ) )
909    {
910    if(mitr->second.valid() &&
911       (mitr->second->referenceCount()==1))
912    {
913        // unreference it.
914            mitr->second = NULL;
915
916            OSGTexMapType::iterator toRemove = mitr;
917            ++mitr;
918
919        // remove it from the map
920            _texmap.erase( toRemove );
921    }
922        else
923        {
924            ++mitr;
925        }
926    }
927
928    return tileGroup;
929}
930
931bool TXPArchive::getLODSize(int lod, int& x, int& y)
932{
933    x = y = 0;
934
935    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
936
937    trpg2iPoint size;
938    if (header.GetLodSize(lod,size))
939    {
940        x = size.x;
941        y = size.y;
942    }
943
944    return true;
945}
Note: See TracBrowser for help on using the browser.