2013-06-01 57 views
0

我試圖寫一個DirectX引擎的模型文件加載...文件加載太慢! (C++)

它看起來像這樣的時刻:

irrFireMesh* irrFireDevice::loadModel(char* filename) 
{ 

ifstream in_stream; 
string line; 
in_stream.open(filename); 
int vertexCount = 0; 
int vCount = -1; 

irrFireMesh* triangleMesh = new irrFireMesh(); 
irrFireVertex* vertices; 
unsigned long* indices; 
irrFireMaterial* mat; 

while(getline(in_stream, line, '\n')) 
{ 
    std::string word; 
    std::stringstream stream(line); 
    std::string param[15]; 
    int i = 0; 
    while(getline(stream, word, ' ')){ 
    param[i] = word; 
    i++; 
    } 

    then = timeGetTime(); 
    if(param[0] == "newbuf") 
    { 
     vertexCount = StI(param[1]); 
     vertices = new irrFireVertex[vertexCount]; 
     if(!vertices) return NULL; 
     indices = new unsigned long[vertexCount]; 
     if(!indices) return NULL; 
     mat = new irrFireMaterial(this); 
     cout<<"Begin buffer width "<<vertexCount<<" vertices"<<endl; 
     vCount = -1; 
     continue; 
    } 
    if(vertexCount <= 0) continue; 

    if(param[0] == "endbuf") 
    { 
     irrFireMeshBuffer* mbuf = new irrFireMeshBuffer(); 

     mbuf->vertexCount = vertexCount; 
     mbuf->indexCount = vertexCount; 
     mbuf->vertices = vertices; 
     mbuf->indices = indices; 
     mat->INITIALIZE(); 
     mbuf->material = mat; 
     triangleMesh->addMeshBuffer(mbuf); 
     vertexCount = 0; 
     cout<<"End buffer width "<<vCount+1<<" vertices."<<endl; 
     continue; 
    } 

    if(param[0] == "v") 
    { 
     vCount++; 
     vertices[vCount].position = D3DXVECTOR3(StF(param[1]), StF(param[3]), StF(param[2])); 
     vertices[vCount].color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f); 
     vertices[vCount].uv = D3DXVECTOR2((StF(param[1]) + StF(param[3]))*10.0f, StF(param[2])*10.0f); 
     indices[vCount] = vCount; 
     if((vCount+1) % 3 == 0) 
     { 
      D3DXVECTOR3 NRML, D1, D2; 
      D1 = vertices[vCount-2].position - vertices[vCount-1].position; 
      D2 = vertices[vCount-1].position - vertices[vCount].position; 
      D3DXVec3Cross(&NRML, &D1, &D2); 
      D3DXVec3Normalize(&NRML, &NRML); 

      vertices[vCount-2].normal = NRML; 
      vertices[vCount-1].normal = NRML; 
      vertices[vCount].normal = NRML; 
     } 
     continue; 
    } 
} 

in_stream.close(); 
return triangleMesh; 
} 

爲三角形會是什麼樣子模型文件這樣的:

newbuf 3 
v 0.0 0.0 0.0 
v 0.5 1.0 0.0 
v 1.0 0.0 0.0 
endbuf 

它像它應該是,但太慢,加載複雜的模型時... 你能指出瓶頸給我,並指出解決這一更快的方法嗎?

編輯: 好吧,我通過基準某些功能所需的時間和事實證明,該分析部分

if(param[0] == "v") 
{ 
. 
. 
. 
} 

解析23400個頂點時發生在總共約4000毫秒。但是,當我更換

vertices[vCount].position = D3DXVECTOR3(StF(param[1]), StF(param[3]), StF(param[2])); 

vertices[vCount].position = D3DXVECTOR3(0.0f, 0.0f, 0.0f); 

只需要大約300毫秒的總額。所以性能殺手似乎是StF(),看起來像這樣:

float StF(string in) 
{ 
stringstream mystr(""); 
mystr<<in; 
float res = 0; 
mystr>>res; 
return res; 
} 

任何想法,如何做到這一點的權利?因爲這顯然太慢...

+1

有一堆東西至少是有問題的。 'char const * filename'。太多使用'new'。使用'new []'(應該是std :: vector)。原始指針的使用,您的代碼在多種情況下泄漏內存。檢查'new'的結果爲null,它會拋出一個異常。儘管如此,這並不是一個性能殺手。嘗試將'ios_base :: binary'添加到'open()'調用中,這將避免一些不必要的轉換。然後,創建一個基準測試程序,您只需載入文件的行數,並在此處發佈時間以及當前代碼的時間,因爲「太慢」是什麼原因? –

+0

好的,我會記住這一點,但不是std ::矢量這種東西慢嗎?我聽說過類似的東西......我加載了一個帶有23400個頂點的模型,並測量了可能導致性能下降的部分時間:getline(...)總共需要778 ms(平均0.03 ms),需要參數拆分部分共計1164毫秒(平均0.05毫秒),參數解析部分總共需要4816毫秒(0.20毫秒平均值)。我預計參數拆分部分會更加昂貴......我將開始另一個測試並測量所需時間由StF()函數... – theCNG27

+0

另外,您是否正在編譯優化打開(例如發佈模式)? – Joe

回答

1

「新」命令的開銷取決於遇到多少「newbuf」部分,但在我看來,你需要新的命令,因爲你需要保存每個陣列。根據是否可以修改網格類,轉換爲矢量可能不是一個選項。

如果您有權訪問分析器,那麼可以使用它來驗證它在哪裏花費時間。它可以告訴你哪些代碼行比其他代碼差。很多時候,這應該是您嘗試優化時的第一步;通常情況下,如果你只是試圖眼球,你最終會猜測錯誤。

以文本格式讀取會變慢。另外,從字符串到浮點的轉換需要一點時間,以及新的命令。您可能可以將每個「newbuf」部分讀作一個字符串數組,並對該處理進行多線程處理(並行處理新處理和其他處理)。在將數組添加回目標網格之前,您必須先進行同步。

+0

謝謝!多線程就像一個好主意!我會嘗試的!我現在拋出了getline()和param []部分,並以類​​似下面的方式結束: while(!in_stream.eof()) \t {0}前綴[10] = {0}; in_stream >>前綴; 開關(前綴[0]){ 情況'v':{x,y,y} in_stream >> x >> y >> z; vCount ++; – theCNG27