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

Revision 10415, 27.6 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 <osg/Group>
2#include <osg/Object>
3#include <osg/Node>
4#include <osg/Notify>
5#include <osg/MatrixTransform>
6#include <osg/BoundingSphere>
7#include <osgDB/Registry>
8#include <osgDB/FileUtils>
9#include <osg/io_utils>
10
11#include <iostream>
12#include <sstream>
13#include <stdlib.h>
14#include <string.h>
15
16#include "ReaderWriterTXP.h"
17#include "TXPNode.h"
18#include "TXPArchive.h"
19#include "TXPPagedLOD.h"
20#include "TXPSeamLOD.h"
21#include "TileMapper.h"
22
23#define ReaderWriterTXPERROR(s) osg::notify(osg::NOTICE) << "txp::ReaderWriterTXP::" << (s) << " error: "
24
25
26
27namespace
28{
29    char gbuf[2048];
30}
31
32using namespace txp;
33
34int ReaderWriterTXP::_archiveId = 0;
35
36osgDB::ReaderWriter::ReadResult ReaderWriterTXP::local_readNode(const std::string& file, const osgDB::ReaderWriter::Options* options)
37{
38
39    std::string name = osgDB::getSimpleFileName(file);
40
41    // We load archive.txp
42    if (strncmp(name.c_str(),"archive",7)==0)
43    {
44        std::string fileName = osgDB::findDataFile( file, options );
45        if ( fileName.empty() )
46            return ReadResult::FILE_NOT_FOUND;
47
48        osg::ref_ptr<TXPNode> txpNode = new TXPNode;
49        txpNode->setArchiveName(fileName);
50        if (options)
51        {
52            txpNode->setOptions(options->getOptionString());
53        }
54       
55
56        //modified by Brad Anderegg on May-27-08
57        //calling getArchive will create a new TXPArchive if the specified one does not exist
58        //we will set our osgdb loader options on the archive and set the appropriate archive on
59        //the txpNode.
60        int id = ++_archiveId;
61        TXPArchive* archive = getArchive(id,osgDB::getFilePath(fileName));
62
63        if (archive != NULL)
64        {
65            archive->setId(id);
66
67            if (options && options->getOptionString().find("loadMaterialsToStateSet")!=std::string::npos)
68            {
69               archive->SetMaterialAttributesToStateSetVar(true);
70            }
71
72            txpNode->loadArchive(archive);
73           
74            return txpNode.get();
75        }
76        else
77        {
78            return ReadResult::ERROR_IN_READING_FILE;
79        }
80    }
81
82    // We load tileLOD_XxY_ID.txp
83    else if (strncmp(name.c_str(),"tile",4)==0)
84    {
85        int x,y,lod;
86        unsigned int id;
87        sscanf(name.c_str(),"tile%d_%dx%d_%u",&lod,&x,&y,&id);
88        TXPArchive* archive = getArchive(id,osgDB::getFilePath(file));
89
90        // The way this is done a 'tile' should only be created for lod 0 only,
91        // something is wrong if this is no the case
92        if(lod != 0)
93        {
94            ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "paged 'tile' should be at lod 0" << std::endl;
95            return ReadResult::ERROR_IN_READING_FILE;
96        }
97
98        trpgEndian endian = archive->GetEndian();
99        archive->ReadSubArchive( 0, 0, endian);
100        archive->ReadSubArchive( y, x, endian);
101
102//    std::cout << "Attempted " << x << " " << y << std::endl;
103       
104        TXPArchive::TileInfo info;
105        if (!archive->getTileInfo(x,y,lod,info))
106            return ReadResult::ERROR_IN_READING_FILE;
107
108        std::vector<TXPArchive::TileLocationInfo> childrenLoc;
109        osg::ref_ptr<osg::Node> tileContent = getTileContent(info,x,y,lod,archive, childrenLoc);
110       
111        tileContent->setName("TileContent");
112
113        bool asChildren = false;
114        std::string childrenInfoStr;
115
116        int numLods = archive->getNumLODs();
117
118        int majorVersion, minorVersion;
119        archive->GetVersion(majorVersion, minorVersion);
120        if(majorVersion ==2 && minorVersion >=1)
121        {
122        // Version 2.1 and over
123        // The tile table only contains lod 0 and the children
124        // info are stored in its parent. SO if we do not want
125        // to be forced to reparse the parent we need to save that
126        // info. For now we just add it to the node name
127
128        if(childrenLoc.size() > 0)
129        {
130        asChildren = true;
131        createChildrenLocationString(childrenLoc, childrenInfoStr);
132        }
133        }
134        else
135        {
136        if (lod < (numLods-1))
137        asChildren = true;
138        }
139
140    if (asChildren)
141        {
142            char pagedLODfile[1024];
143            sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d",
144            archive->getDir(),
145            lod,
146            x,
147            y,
148            archive->getId());
149
150            strcat(pagedLODfile, childrenInfoStr.c_str());
151            strcat(pagedLODfile, ".txp");
152
153
154            // there are tile sets which do not maintain the z extents in
155            // the tile table.  This attempt to address the issue by using
156            // the geometry bounding sphere.  The downside is that this is
157            // not coupled to the generation and may result in runtime cracks
158            if (info.center.z() == 0)
159            {
160                osg::BoundingSphere bSphere = tileContent->getBound();
161
162                info.center.z() = bSphere.center().z();
163                info.radius = bSphere.radius();
164            }
165
166
167            osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
168            // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
169            pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
170            pagedLOD->setFileName(1,pagedLODfile);
171            pagedLOD->setRange(1,0,info.minRange);
172            pagedLOD->setCenter(info.center);
173            pagedLOD->setRadius(info.radius);
174            pagedLOD->setPriorityOffset(0,numLods-lod);
175            pagedLOD->setPriorityScale(0,1.0f);
176            pagedLOD->setNumChildrenThatCannotBeExpired(1);
177            pagedLOD->setTileId(x,y,lod);
178
179            const trpgHeader* header = archive->GetHeader();
180            trpgHeader::trpgTileType tileType;
181            header->GetTileOriginType(tileType);
182            if(tileType == trpgHeader::TileLocal)
183            {
184                osg::Vec3d sw(info.bbox._min);
185                pagedLOD->setCenter(info.center - sw);
186            }
187
188            return pagedLOD.get();
189        }
190        else
191            return tileContent.get();
192    }
193
194   
195    // For 2.0 and lower we load subtilesLOD_XxY_ID.txp
196    // For 2.1 and over  we load subtilesLOD_XxY_ID_NBCHILD_{X_Y_FID_FOFFSET_ZMIN_ZMAX_X_Y_ADDR ....}.txp
197    else if (strncmp(name.c_str(),"sub",3)==0)
198    {
199        int x,y,lod;
200        unsigned int id;
201        sscanf(name.c_str(),"subtiles%d_%dx%d_%u",&lod,&x,&y,&id);
202        TXPArchive* archive = getArchive(id,osgDB::getFilePath(file));
203
204        int majorVersion, minorVersion;
205        archive->GetVersion(majorVersion, minorVersion);
206
207        std::vector<TXPArchive::TileLocationInfo> childrenLoc;
208
209        osg::ref_ptr<osg::Group> subtiles = new osg::Group;
210
211        int numLods = archive->getNumLODs();
212
213        if(majorVersion == 2  && minorVersion >= 1)
214        {
215            int nbChild;
216
217            sscanf(name.c_str(),"subtiles%d_%dx%d_%u_%d",&lod,&x,&y,&id, &nbChild);
218            std::vector<TXPArchive::TileLocationInfo> locs;
219            bool status = true;
220            status = extractChildrenLocations(name, lod, locs, nbChild);
221        if(majorVersion >= TRPG_NOMERGE_VERSION_MAJOR && minorVersion >=TRPG_NOMERGE_VERSION_MINOR && archive->GetHeader()->GetIsMaster())
222        {
223        for(int idx=0;idx<nbChild;idx++)
224        {
225            //figure out the block row/col
226            int blockx,blocky;
227            unsigned int denom = (1 << locs[idx].lod); // this should work up to lod 31
228            blockx = locs[idx].x/denom;
229            blocky = locs[idx].y/denom;
230            locs[idx].addr.col = blockx;
231            locs[idx].addr.row = blocky;
232        }
233        }
234
235            if(!status)
236            {
237        ReaderWriterTXPERROR("ReaderWriterTXP::local_readNode()") << "'subtile' filename children parsing failed " << std::endl;
238        return ReadResult::ERROR_IN_READING_FILE;
239            }
240
241            const trpgHeader* header = archive->GetHeader();
242            trpgHeader::trpgTileType tileType;
243            header->GetTileOriginType(tileType);
244
245        TXPArchive::TileLocationInfo plInfo;
246        plInfo.x = x;
247        plInfo.y = y;
248        plInfo.lod = lod;
249            TXPArchive::TileInfo parentInfo;
250            archive->getTileInfo(plInfo,parentInfo);
251
252            for(int idx = 0; idx < nbChild; ++idx)
253            {
254        std::vector<TXPArchive::TileLocationInfo> childrenChildLoc;
255               
256        TXPArchive::TileLocationInfo& loc = locs[idx];
257               
258        TXPArchive::TileInfo info;
259        if (!archive->getTileInfo(loc,info))
260            continue;
261
262        osg::ref_ptr<osg::Node> tileContent = getTileContent(info, loc, archive, childrenChildLoc);
263
264        tileContent->setName("TileContent");
265
266        if(childrenChildLoc.size() > 0)
267        {
268            std::string childInfoStr;
269            createChildrenLocationString(childrenChildLoc, childInfoStr);
270
271            char pagedLODfile[1024];
272            sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d%s.txp",
273                archive->getDir(),
274                loc.lod,
275                loc.x,
276                loc.y,
277                archive->getId(),
278                childInfoStr.c_str());
279
280                    // there are tile sets which do not maintain the z extents in
281                    // the tile table.  This attempt to address the issue by using
282                    // the geometry bounding sphere.  The downside is that this is
283                    // not coupled to the generation and may result in runtime cracks
284                    if (info.center.z() == 0)
285                    {
286                        osg::BoundingSphere bSphere = tileContent->getBound();
287
288                        info.center.z() = bSphere.center().z();
289                        info.radius = bSphere.radius();
290                    }
291
292            osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
293                    // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
294            pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
295            pagedLOD->setFileName(1,pagedLODfile);
296            pagedLOD->setRange(1,0,info.minRange);
297            pagedLOD->setCenter(info.center);
298            pagedLOD->setRadius(info.radius);
299            pagedLOD->setPriorityOffset(0,numLods - loc.lod);
300            pagedLOD->setPriorityScale(0,1.0f);
301            pagedLOD->setNumChildrenThatCannotBeExpired(1);
302            pagedLOD->setTileId(loc.x, loc.y, loc.lod);
303
304            if(tileType == trpgHeader::TileLocal)
305            {
306            osg::Vec3d center(info.center - parentInfo.bbox._min);
307            osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
308            sw[2] = 0.0;
309            pagedLOD->setCenter(center - sw);
310            osg::Matrix offset;
311            offset.setTrans(sw);
312            osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
313            tform->addChild(pagedLOD.get());
314            subtiles->addChild(tform);
315            }
316            else
317            subtiles->addChild(pagedLOD.get());
318            subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod)); // is this really needed?
319        }
320        else
321        {
322            subtiles->setUserData(new TileIdentifier(loc.x, loc.y, loc.lod));
323            if(tileType == trpgHeader::TileLocal)
324            {
325            osg::Vec3d center(info.center - parentInfo.bbox._min);
326            osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
327            sw[2] = 0.0;
328            osg::Matrix offset;
329            offset.setTrans(sw);
330            osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
331            tform->addChild(tileContent.get());
332            subtiles->addChild(tform);
333            }
334            else
335            subtiles->addChild(tileContent.get());
336        }
337            }
338        }
339        else
340        {
341           
342        int sizeX, sizeY;
343        archive->getLODSize(lod+1,sizeX,sizeY);
344
345        const trpgHeader* header = archive->GetHeader();
346        trpgHeader::trpgTileType tileType;
347        header->GetTileOriginType(tileType);
348
349        TXPArchive::TileInfo parentInfo;
350        archive->getTileInfo(x,y,lod,parentInfo);
351
352        for (int ix = 0; ix < 2; ix++)
353        {
354        for (int iy = 0; iy < 2; iy++)
355        {
356            int tileX = x*2+ix;
357            int tileY = y*2+iy;
358            int tileLOD = lod+1;
359
360            TXPArchive::TileInfo info;
361            if (!archive->getTileInfo(tileX,tileY,tileLOD,info))
362            continue;
363
364            osg::ref_ptr<osg::Node> tileContent = getTileContent(info,tileX,tileY,tileLOD,archive, childrenLoc);
365
366            tileContent->setName("TileContent");
367
368            if (tileLOD < (numLods-1))
369            {
370            char pagedLODfile[1024];
371            sprintf(pagedLODfile,"%s\\subtiles%d_%dx%d_%d.txp",
372                archive->getDir(),
373                tileLOD,
374                tileX,
375                tileY,
376                archive->getId());
377
378            // there are tile sets which do not maintain the z extents in
379            // the tile table.  This attempt to address the issue by using
380            // the geometry bounding sphere.  The downside is that this is
381            // not coupled to the generation and may result in runtime cracks
382            if (info.center.z() == 0)
383            {
384                osg::BoundingSphere bSphere = tileContent->getBound();
385
386                info.center.z() = bSphere.center().z();
387                info.radius = bSphere.radius();
388            }
389
390            osg::ref_ptr<TXPPagedLOD> pagedLOD = new TXPPagedLOD;
391                        // note: use maximum(info.maxRange,1e7) as just maxRange would result in some corner tiles from being culled out.
392            pagedLOD->addChild(tileContent.get(),info.minRange,osg::maximum(info.maxRange,1e7));
393            pagedLOD->setFileName(1,pagedLODfile);
394            pagedLOD->setRange(1,0,info.minRange);
395            pagedLOD->setCenter(info.center);
396            pagedLOD->setRadius(info.radius);
397            pagedLOD->setPriorityOffset(0,numLods-lod);
398            pagedLOD->setPriorityScale(0,1.0f);
399            pagedLOD->setNumChildrenThatCannotBeExpired(1);
400            pagedLOD->setTileId(tileX,tileY,tileLOD);
401
402            if(tileType == trpgHeader::TileLocal)
403            {
404                osg::Vec3d center(info.center - parentInfo.bbox._min);
405                osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
406                sw[2] = 0.0;
407                pagedLOD->setCenter(center - sw);
408                osg::Matrix offset;
409                offset.setTrans(sw);
410                osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
411                tform->addChild(pagedLOD.get());
412                subtiles->addChild(tform);
413            }
414            else
415                subtiles->addChild(pagedLOD.get());
416            }
417            else
418            {
419            subtiles->setUserData(new TileIdentifier(tileX,tileY,tileLOD));
420            if(tileType == trpgHeader::TileLocal)
421            {
422                osg::Vec3d center(info.center - parentInfo.bbox._min);
423                osg::Vec3d sw(info.bbox._min - parentInfo.bbox._min);
424                sw[2] = 0.0;
425                osg::Matrix offset;
426                offset.setTrans(sw);
427                osg::MatrixTransform *tform = new osg::MatrixTransform(offset);
428                tform->addChild(tileContent.get());
429                subtiles->addChild(tform);
430            }
431            else
432                subtiles->addChild(tileContent.get());
433            }
434
435        }
436        }
437        }
438
439        //osg::notify(osg::NOTICE) << "Subtiles for " << x << " " << y << " " << lod << " lodaded" << std::endl;
440        return subtiles.get();
441    }
442   
443    return ReadResult::ERROR_IN_READING_FILE;
444}
445
446// If you change this then you have to change extractChildrenLocation()
447void ReaderWriterTXP::createChildrenLocationString(const std::vector<TXPArchive::TileLocationInfo>& locs, std::string& locString) const
448{
449    std::stringstream theLoc;
450
451    if(locs.size() == 0)
452    {
453        theLoc << "_" << locs.size();
454    }
455    else
456    {
457   
458        theLoc << "_" << locs.size() << "_" << "{" ;
459
460        for(unsigned int idx = 0; idx < locs.size(); ++idx)
461        {
462            const TXPArchive::TileLocationInfo& loc = locs[idx];
463
464            theLoc << loc.x
465                   << "_" 
466                   << loc.y
467                   << "_" 
468                   << loc.addr.file
469                   << "_" 
470                   << loc.addr.offset
471                   << "_"
472                   << loc.zmin
473                   << "_"
474                   << loc.zmax;
475            if(idx != locs.size() -1)
476                theLoc << "_";
477        }
478    }
479
480    theLoc << "}" << std::ends;
481
482    locString = theLoc.str();
483}
484bool ReaderWriterTXP::extractChildrenLocations(const std::string& name, int parentLod, std::vector<TXPArchive::TileLocationInfo>& locs, int nbChild) const
485{
486    locs.clear();
487
488    if(nbChild == 0)
489        return true;
490
491    locs.resize(nbChild);
492
493    // We look for '{', which should be the start of the list of {x,y,addr} children data
494    // '}' should end the list.
495    // We expect: X,Y,FID,FOFFSET,ZMIN,ZMAX
496    std::string::size_type startOfList = name.find_last_of('{');
497    if(startOfList == std::string::npos)
498        return false;
499
500    std::string::size_type endOfList = name.find_last_of('}');
501    if(endOfList == std::string::npos)
502        return false;
503
504    // Extract the data
505    strcpy(gbuf, name.substr(startOfList + 1, endOfList - startOfList - 1).c_str());
506    char *token = strtok( gbuf, "_" );
507
508    int nbTokenRead = 0;
509    for(int idx = 0; idx < nbChild; idx++)
510    {
511        // X
512        if(!token)
513            break;
514        locs[idx].x = atoi(token);
515        nbTokenRead++;
516
517        // Y
518        token = strtok(0, "_");
519        if(!token)
520            break;
521        locs[idx].y = atoi(token);
522        nbTokenRead++;
523
524        // FID
525        token = strtok(0, "_");
526        if(!token)
527            break;
528        locs[idx].addr.file = atoi(token);
529        nbTokenRead++;
530
531        // OFFSET
532        token = strtok(0, "_");
533        if(!token)
534            break;
535        locs[idx].addr.offset = atoi(token);
536        nbTokenRead++;
537
538        // ZMIN
539        token = strtok(0, "_");
540        if(!token)
541            break;
542        locs[idx].zmin = osg::asciiToFloat(token);
543        nbTokenRead++;
544
545        // ZMAX
546        token = strtok(0, "_");
547        if(!token)
548            break;
549        locs[idx].zmax = osg::asciiToFloat(token);
550        nbTokenRead++;
551
552        locs[idx].lod = parentLod+1;
553
554     
555
556        token = strtok(0, "_");
557    }
558
559    if(nbTokenRead != nbChild*6)
560        return false;
561    else
562        return true;
563
564
565}
566
567TXPArchive *ReaderWriterTXP::getArchive(int id, const std::string& dir)
568{
569    TXPArchive* archive = NULL;
570
571    std::map< int,osg::ref_ptr<TXPArchive> >::iterator iter = _archives.find(id);
572   
573
574    if (iter != _archives.end())
575    {
576        archive = iter->second.get();
577    }
578
579    if (archive == NULL)
580    {
581#ifdef _WIN32
582        const char _PATHD = '\\';
583#elif defined(macintosh)
584        const char _PATHD = ':';
585#else
586        const char _PATHD = '/';
587#endif
588        std::string archiveName = dir+_PATHD+"archive.txp";
589        archive = new TXPArchive;
590        if (archive->openFile(archiveName) == false)
591        {
592            ReaderWriterTXPERROR("getArchive()") << "failed to load archive: \"" << archiveName << "\"" << std::endl;
593            return NULL;
594        }
595
596        if (archive->loadMaterials() == false)
597        {
598            ReaderWriterTXPERROR("getArchive()") << "failed to load materials from archive: \"" << archiveName << "\"" << std::endl;
599            return NULL;
600        }
601
602        if (archive->loadModels() == false)
603        {
604            ReaderWriterTXPERROR("getArchive()") << "failed to load models from archive: \"" << archiveName << "\"" << std::endl;
605            return NULL;
606        }
607
608        if (archive->loadLightAttributes() == false)
609        {
610            ReaderWriterTXPERROR("getArchive()") << "failed to load light attributes from archive: \"" << archiveName << "\"" << std::endl;
611            return NULL;
612        }
613
614        if (archive->loadTextStyles() == false)
615        {
616            ReaderWriterTXPERROR("getArchive()") << "failed to load text styles from archive: \"" << archiveName << "\"" << std::endl;
617            return NULL;
618        }
619
620        archive->setId(id);
621
622        _archives[id] = archive;
623    }
624
625    return archive;
626}
627
628class SeamFinder: public osg::NodeVisitor
629{
630public:
631    SeamFinder(int x, int y, int lod, const TXPArchive::TileInfo& info, TXPArchive *archive ):
632    osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
633    _x(x), _y(y), _lod(lod), _info(info), _archive(archive)
634    {}
635
636    virtual void apply(osg::Group& group)
637    {
638        for (unsigned int i = 0; i < group.getNumChildren(); i++)
639        {
640        osg::Node* child = group.getChild(i);
641        osg::Node* seam = seamReplacement(child);
642        if (child != seam)
643        {
644            group.replaceChild(child,seam);
645        }
646        else
647        {
648            child->accept(*this);
649        }
650        }
651    }
652
653protected:
654    osg::Node* seamReplacement(osg::Node* node);
655   
656    SeamFinder& operator = (const SeamFinder&) { return *this; }
657
658    int _x, _y, _lod;
659    const TXPArchive::TileInfo& _info;
660    TXPArchive *_archive;
661};
662
663osg::Node* SeamFinder::seamReplacement(osg::Node* node)
664{
665    osg::Group* group = node->asGroup();
666    if ( group == 0 )
667        return node;
668
669    std::vector<osg::Node*> nonSeamChildren;
670    osg::LOD* hiRes = 0;
671    osg::LOD* loRes = 0;
672
673    const trpgHeader* header = _archive->GetHeader();
674    trpgHeader::trpgTileType tileType;
675    header->GetTileOriginType(tileType);
676
677    for (unsigned int i = 0; i < group->getNumChildren(); i++)
678    {
679        osg::LOD* lod = dynamic_cast<osg::LOD*>(group->getChild(i));
680        if (lod == 0)
681        {
682            nonSeamChildren.push_back(group->getChild(i));
683            continue;
684        }
685
686        bool nonSeamChild = true;
687
688    // looks like the problem is in here - likely due to seamLOD info
689    // not being adjusted properly in tiled databases
690        // seam center is outside the bounding box of the tile
691    osg::Vec3 lodCenter = lod->getCenter();
692
693        if(tileType == trpgHeader::TileLocal)
694        {
695            trpg2dPoint tileExtents;
696            header->GetTileSize(0, tileExtents);
697            osg::BoundingBox bbox;
698            _archive->getExtents(bbox);
699            osg::Vec3 offset(0.0, 0.0, 0.0);
700
701            int divider = (0x1 << _lod);
702            // calculate which tile model is located in
703            tileExtents.x /= divider;
704            tileExtents.y /= divider;
705            offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5;
706            offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5;
707        lodCenter += offset;
708        }
709
710        if (!_info.bbox.contains(lodCenter))
711        {
712            // seams have center as the neighbour tile
713            osg::Vec3 d = _info.center - lodCenter;
714            if (((fabs(d.x())-_info.size.x()) > 0.0001) && ((fabs(d.y())-_info.size.y()) > 0.0001))
715            {
716                nonSeamChildren.push_back(lod);
717                continue;
718            }
719
720            // low res seam has min/max ranges of lod+1 range/lod 0 range
721            if ((fabs((float)_info.minRange-lod->getMinRange(0))<0.001)&&(fabs((float)_info.lod0Range-lod->getMaxRange(0))<0.001))
722            {
723
724                if (loRes==0)
725                {
726                    loRes = lod;
727                    nonSeamChild = false;
728                }
729            }
730
731            // hi res seam has min/max ranges of 0 range/lod+1 range
732            if ((lod->getMinRange(0)==0.0f)&&(fabs(_info.minRange-lod->getMaxRange(0))<0.001))
733            {
734                if (hiRes==0)
735                {
736                    hiRes = lod;
737                    nonSeamChild = false;
738                }
739            }
740        }
741        if (nonSeamChild)
742        {
743            nonSeamChildren.push_back(lod);
744        }
745    }
746
747    if (loRes)
748    {
749        int dx = 0;
750        int dy = 0;
751        int lod = _lod;
752    osg::Vec3 lodCenter = loRes->getCenter();
753
754        if(tileType == trpgHeader::TileLocal)
755        {
756            trpg2dPoint tileExtents;
757            header->GetTileSize(0, tileExtents);
758            osg::BoundingBox bbox;
759            _archive->getExtents(bbox);
760            osg::Vec3 offset(0.0, 0.0, 0.0);
761
762            int divider = (0x1 << _lod);
763            // calculate which tile model is located in
764            tileExtents.x /= divider;
765            tileExtents.y /= divider;
766            offset[0] = _x*tileExtents.x;// + tileExtents.x*0.5;
767            offset[1] = _y*tileExtents.y;// + tileExtents.y*0.5;
768        lodCenter += offset;
769        }
770
771        osg::Vec3 delta = lodCenter-_info.center;
772        if (fabs(delta.x())>fabs(delta.y()))
773        {
774            if ( delta.x() < 0.0 )
775                --dx;    // west
776            else
777                dx++;                  // east
778        }
779        else
780        {
781            if ( delta.y() < 0.0 )
782                --dy;    // south
783            else
784                ++dy;                  // north
785        }
786
787        TXPSeamLOD* seam = new TXPSeamLOD(_x, _y, lod, dx, dy);
788    seam->setCenter(loRes->getCenter());
789        seam->addChild(loRes->getChild(0));        // low res
790        if (hiRes)
791        {
792            seam->addChild(hiRes->getChild(0));    // high res
793        }
794 
795        if (nonSeamChildren.empty())
796        {
797            return seam;
798        }
799        else
800        {
801            osg::Group* newGroup = new osg::Group;
802
803            newGroup->addChild(seam);
804           
805            for (unsigned int i = 0; i < nonSeamChildren.size(); i++)
806                newGroup->addChild(nonSeamChildren[i]);
807               
808            return newGroup;
809        }
810    }
811
812    return node;
813}
814
815osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, int x, int y, int lod, TXPArchive* archive,  std::vector<TXPArchive::TileLocationInfo>& childrenLoc)
816{
817    if ( archive == 0 )
818        return false;
819
820    int majorVersion, minorVersion;
821    archive->GetVersion(majorVersion, minorVersion);
822
823    double realMinRange = info.minRange;
824    double realMaxRange = info.maxRange;
825    double  usedMaxRange = osg::maximum(info.maxRange,1e7);
826    osg::Vec3 tileCenter;
827    osg::Group* tileGroup = archive->getTileContent(x,y,lod,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc);
828
829    // if group has only one child, then simply use its child.   
830    while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())
831    {
832        tileGroup = tileGroup->getChild(0)->asGroup();
833    }
834       
835    bool doSeam = false;
836    if(majorVersion == 2 && minorVersion >= 1)
837        doSeam = (childrenLoc.size() > 0);
838    else
839        doSeam = (lod < (archive->getNumLODs() - 1));
840
841    // Handle seams
842    if (doSeam)
843    {
844        SeamFinder sfv(x,y,lod,info,archive);
845        tileGroup->accept(sfv);
846    }
847
848    return tileGroup;
849}
850
851// this version only gets called if the TXP version is >= than 2.1
852osg::Node* ReaderWriterTXP::getTileContent(const TXPArchive::TileInfo &info, const TXPArchive::TileLocationInfo& loc, TXPArchive* archive,  std::vector<TXPArchive::TileLocationInfo>& childrenLoc)
853{
854    if ( archive == 0 )
855        return false;
856
857    // int numLods = archive->getNumLODs();
858
859    double realMinRange = info.minRange;
860    double realMaxRange = info.maxRange;
861    double usedMaxRange = osg::maximum(info.maxRange,1e7);
862    osg::Vec3 tileCenter;
863    osg::Group* tileGroup = archive->getTileContent(loc,realMinRange,realMaxRange,usedMaxRange,tileCenter, childrenLoc);
864
865    // if group has only one child, then simply use its child.   
866    while (tileGroup->getNumChildren()==1 && tileGroup->getChild(0)->asGroup())
867    {
868        tileGroup = tileGroup->getChild(0)->asGroup();
869    }
870       
871    // Handle seams
872    if (childrenLoc.size() > 0)
873    {
874        SeamFinder sfv(loc.x, loc.y, loc.lod, info, archive);
875        tileGroup->accept(sfv);
876    }
877
878    return tileGroup;
879}
880
881REGISTER_OSGPLUGIN(txp, ReaderWriterTXP)
Note: See TracBrowser for help on using the browser.