天天看點

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

轉載:[原][osgearth]osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

跑osgearthviewer程式

使用一個earth檔案做參數傳入

跟進代碼。

首先osgearthviewer程式加載earth的方式分為兩種:

1.根據earth檔案(load方式)

2.使用SDK加載(create方式)

我們使用earth檔案是load方式,直接看load函數,定位到這個位置

// load an earth file, and support all or our example command-line options
    // and earth file <external> tags    
    osg::Node* node = MapNodeHelper().load(arguments, &viewer);      

上面的函數是用來加載earth檔案的,仔細看一下這個函數

發現這個函數是通過osgDB的加載機制來實作earth檔案的加載。

下面我們先要搞清楚的是osgDB的加載機制

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

這是osgDB讀取的調用順序

回到,我們自己的程式,我将代碼調試過程截圖:

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)
【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)
【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

這裡有不少預設的屬性,而我們是定位到自定義的部分:(下圖)

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

因為,我隻用了一個傳入參數,是以,這個循環隻執行一次,就是調用了一次readRefNodeFile檔案

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)
【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

這個函數好像是管理緩存什麼的,我們在函數裡定位到這裡:(下圖)

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

這個read才是開始真正解析資料了。

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)
1 ReaderWriter::ReadResult Registry::read(const ReadFunctor& readFunctor)
  2 {
        
       ......關于osga和zip檔案的
 52     // first attempt to load the file from existing ReaderWriter's第一次嘗試從現有ReaderWriter的加載檔案
 53     AvailableReaderWriterIterator itr(_rwList, _pluginMutex);
 54     for(;itr.valid();++itr)
 55     {
 56         ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
 57         if (readFunctor.isValid(rr)) 
 58             return rr;
 59         else results.push_back(rr);
 60     }
 61 
 62     // check loaded archives.檢查加載的檔案
 63     AvailableArchiveIterator aaitr(_archiveCache, _archiveCacheMutex);
 64     for(;aaitr.valid();++aaitr)
 65     {
 66         ReaderWriter::ReadResult rr = readFunctor.doRead(*aaitr);
 67         if (readFunctor.isValid(rr)) 
 68             return rr;
 69         else
 70         {
 71             // don't pass on FILE_NOT_FOUND results as we don't want to prevent non archive plugins that haven't been
 72             // loaded yet from getting a chance to test for the presence of the file.
 73             if (rr.status()!=ReaderWriter::ReadResult::FILE_NOT_FOUND) results.push_back(rr);
 74         }
 75     }
 76 
 77     // now look for a plug-in to load the file.現在尋找一個插件加載檔案!!!
 78     std::string libraryName = createLibraryNameForFile(readFunctor._filename);
 79     if (loadLibrary(libraryName)!=NOT_LOADED)
 80     {
 81         for(;itr.valid();++itr)
 82         {
 83             ReaderWriter::ReadResult rr = readFunctor.doRead(*itr);
 84             if (readFunctor.isValid(rr)) 
 85                 return rr;
 86             else results.push_back(rr);
 87         }
 88     }
 89 
 90     //If the filename contains a server address and wasn't loaded by any of the plugins, try to find a plugin which supports the server
 91     //protocol and supports wildcards. If not successfully use curl as a last fallback
 92     if (containsServerAddress(readFunctor._filename))
 93     {
 94         ReaderWriter* rw = getReaderWriterForProtocolAndExtension(
 95             osgDB::getServerProtocol(readFunctor._filename),
 96             osgDB::getFileExtension(readFunctor._filename)
 97         );
 98 
 99         if (rw)
100         {
101             return readFunctor.doRead(*rw);
102         }
103         else
104         {
105             return  ReaderWriter::ReadResult("Warning: Could not find the .curl plugin to read from server.");
106         }
107     }
108 
109     if (results.empty())
110     {
111         return ReaderWriter::ReadResult("Warning: Could not find plugin to read objects from file \""+readFunctor._filename+"\".");
112     }
113 
114     // sort the results so the most relevant (i.e. ERROR_IN_READING_FILE is more relevant than FILE_NOT_FOUND) results get placed at the end of the results list.
115     std::sort(results.begin(), results.end());
116     ReaderWriter::ReadResult result = results.back();
117 
118     if (result.message().empty())
119     {
120         switch(result.status())
121         {
122             case(ReaderWriter::ReadResult::FILE_NOT_HANDLED): result.message() = "Warning: reading \""+readFunctor._filename+"\" not supported."; break;
123             case(ReaderWriter::ReadResult::FILE_NOT_FOUND): result.message() = "Warning: could not find file \""+readFunctor._filename+"\"."; break;
124             case(ReaderWriter::ReadResult::ERROR_IN_READING_FILE): result.message() = "Warning: Error in reading to \""+readFunctor._filename+"\"."; break;
125             default: break;
126         }
127     }
128 
129     return result;
130 }      
【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

 在第一次進入次函數時

它在78行  擷取了插件叫osgDB_earth.dll(osgdb_earthd.dll)

它在第83行 開始加載插件調用了doRead函數

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

而doRead函數就是利用osgDB的機制調用,第三方插件osgDB_Earth中的讀取方式:

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

正式開始讀取本地earth檔案(為什麼是本地,因為讀取伺服器上的似乎有另外一套處理方案)振奮人心!

readstring直接調用doRead(URI.cpp)

 但是,doRead當函數調用到加載URIReadCallback的時候,給我帶來不少麻煩

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

這裡使用的類是osgearth的Registry構造,讓我一度和osgDB的Registry搞混。

調試了好久,而且由于裡面加載了一個osgText::readFontFile("arial.ttf");

是以導緻之前的readImplementation又被調用了一遍,非常打調試的連續性······MBD

繼續在ReaderWriterOsgEarth的readNode函數中往下

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

一番磨難,似乎看到了勝利的曙光,進入到readNode函數中:

【OSG】osgearthviewer讀取earth檔案,代碼解析(earth檔案讀取的一幀)

看到了序列化,關于序列化,我有另外一個部落格,可以看下

osg