getline と stringstream を使用してデータを解析する Wavefront .obj ファイル パーサーがあります。最初はモデルが小さかったときは問題ありませんでしたが、今では 207000 行までのモデルを読み込もうとすると、すべての要素をカウントする最初のパスだけで、高速で途方もない時間 (4.7 秒) がかかります。 PC を終了し、2 回目のパスには 30 分かかります。一方、Blender はモデル全体をわずか 2 秒程度でロードします。現在デバッグモードでVisual Studio 2012を使用しています。
要素をカウントするための私のコードは次のようになります。
istringstream input(obj);
string line;
while (getline(input, line)) {
if (line.find("# ") != string::npos) {
// Comments.
}
else if (line.find("f ") != string::npos) {
faces++;
}
else if (line.find("v ") != string::npos) {
vertices += 3;
}
else if (line.find("vn ") != string::npos) {
normals += 3;
}
else if (line.find("vt ") != string::npos) {
uvCoordinates += 2;
}
else if (line.find("o ") != string::npos) {
// Count here, if needed.
}
}
〜30秒かかるデータ全体を実際にロードするためのコード:
istringstream input(obj);
string line;
if (faces.capacity() > UINT_MAX / 3) {
LOGE("Model cannot have more faces than: %d", UINT_MAX / 3);
return false;
}
while (getline(input, line)) {
vector<string> arr = stringSplit(line, ' ');
string param = arr[0];
int params = arr.size();
if (line.length() == 0) {
continue;
}
if (arr[0] == "v") { // Vertices.
vertices.push_back(stringToFloat(arr[1].c_str()));
vertices.push_back(stringToFloat(arr[2].c_str()));
vertices.push_back(stringToFloat(arr[3].c_str()));
}
else if (arr[0] == "vn") { // Normals.
normals.push_back(stringToFloat(arr[1].c_str()));
normals.push_back(stringToFloat(arr[2].c_str()));
normals.push_back(stringToFloat(arr[3].c_str()));
}
else if (arr[0] == "f") { // Faces.
if (params < 4) {
//LOGI("LINE: %s", line.c_str());
continue;
}
else if (params > 4) {
LOGI("Line: %s", line.c_str());
LOGE("Obj models must only contain triangulated faces.");
return false;
}
Face face;
parseFace(face, line);
faces.push_back(face);
}
else if (arr[0] == "vt") { // UV coordinates.
uvCoordinates.push_back(stringToFloat(arr[1].c_str()));
uvCoordinates.push_back(stringToFloat(arr[2].c_str()));
}
else if (arr[0] == "mtllib") { // Material.
material = arr[1];
}
else if (arr[0] == "o") { // Sub-model.
// Separate models here, if needed.
}
}
obj 変数は、ファイルの内容全体を含む文字列です。最初のループの内側からすべてを削除しても、時間への影響は何も変わりません。これを最適化する方法についてのアイデアはありますか?