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

Revision 11037, 29.3 kB (checked in by robert, 4 years ago)

From Ryan Kawicki, added removal of TXPArchive from ReaderWriterTXP when the TXPNode destructs to fix memory consumption issue relating to leaving unused archives in memory.

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