本項では行を解析しつつ法線ベクトルと3頂点を読み込む準備を行います。
前項で1行ずつ読み込むことができるようになったので、CgsTriangleにSTLフォーマットに従って文字列を解析するメンバー関数を追加してみましょう。
facet normal 行から endfacet 行までを読み込みます。
ファイルから1行ずつ読み込んでいますが、行によっては先頭から空白文字が入っていることがあります。解析の邪魔となるので空白文字を削除する処理を追加します。
【CgsTriangle.cpp】
bool CgsTriangle::ReadText(std::wifstream& ifs)
{
// ファイルを1行ずつ読み込む
std::wstring str;
while (std::getline(ifs, str)) {
// 先頭の空白文字削除
const size_t pos = str.find_first_not_of(L" \t");
if (pos != std::wstring::npos) {
str = str.substr(pos);
}
}
return false;
}
facet normal 0.000000e+000 9.999871e-001 -5.080036e-003
outer loop
vertex 3.803460e+001 3.995750e+001 3.959310e+001
vertex 3.603460e+001 3.995750e+001 3.959310e+001
vertex 3.803460e+001 3.998290e+001 4.459300e+001
endloop
endfacet
三角形データは
facet normal
outer loop
vertex
vertex
vertex
endloop
endfacet
の順に出現することが決まっているので何行目を読み込んでいるかを数えながら順に処理していきます。
【CgsTriangle.cpp】
bool CgsTriangle::ReadText(std::wifstream& ifs)
{
// ファイルを1行ずつ読み込む
int count = 0;
std::wstring str;
while (std::getline(ifs, str)) {
// 先頭の空白文字削除
const size_t pos = str.find_first_not_of(L" \t");
if (pos != std::wstring::npos) {
str = str.substr(pos);
}
if (count == 0 && str.find(L"facet normal") == 0) {
// 法線ベクトル読み込み
++count;
continue;
}
else if (count == 1 && str == L"outer loop") {
++count;
continue;
}
else if (1 < count && count < 5 && str.find(L"vertex") == 0) {
// 頂点読み込み
++count;
continue;
}
else if (count == 5 && str == L"endloop") {
++count;
continue;
}
else if (count == 6 && str == L"endfacet") {
return true;
}
break;
}
return false;
}
正しくファイルを開いて1行ずつファイルが読込めているか確認してみましょう。
「文字列解析」で追加した if () {} else if () {} の ++count; と return true;の行にブレイクポイントを設定してメニューの [デバッグ(D)]-[デバッグの開始(S)] を実行して「house.stl」を読み込んでみましょう。下図の様に「facet normal ~」の文字列が読み込まれ、F5キーを押下する毎に「outer loop」, 「vertex ~」, 「vertex ~」, 「vertex ~」,「endloop」,「endfacet」行が読み込まれていくでしょう。