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

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

Warning fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#include <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 = (float)atof(token);
543        nbTokenRead++;
544
545        // ZMAX
546        token = strtok(0, "_");
547        if(!token)
548            break;
549        locs[idx].zmax= (float)atof(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.