点群OBJで負の頂点番号が問題になる理由
点群OBJをアップロードしたとき、一部だけ面が抜ける、三角形が欠ける、モデル内部が見える、離れた位置に不自然な面が伸びるといった現象が起きることがあります。こうした症状の原因の一つが、OBJファイルの面定義に使われている負の頂点番号です。
OBJでは、頂点を表す行と、それらの頂点を結んで面を作る行が記録されています。頂点は通常「v」で始まる行、面は「f」で始まる行です。面の行には、どの頂点をどの順番で結ぶかを示す番号が書かれています。
正の頂点番号を使った面定義は、次のような形式です。
text v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 1.0 1.0 0.0 f 1 2 3
この例では、1番目、2番目、3番目の頂点を結んで一つの三角形を作っています。OBJの頂点番号は1から始まるため、最初の頂点が1、次の頂点が2、その次が3です。
一方、同じ面を負の番号で表すこともできます。
text v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 1.0 1.0 0.0 f -3 -2 -1
負の番号は、面の行より前に定義されている頂点を、直近の要素から逆向きに数える相対番号です。「-1」はその時点で最後に定義された頂点、「-2」はその一つ前、「-3」はさらに一つ前を示します。そのため、上の例では「f 1 2 3」と「f -3 -2 -1」が同じ三角形を表します。
ここで重要なのは、負の頂点番号そのものが必ずしも誤りではないことです。OBJの表現として成立している場合でも、アップロード先や変換処理が負番号に対応していないと、該当する面が読み飛ばされたり、誤った頂点へ接続されたりする可能性があります。
また、負番号の範囲が実際に定義済みの頂点数を超えている場合や、変換処理がOBJの番号規則を誤解している場合にも面が抜けます。ファイル全体の最終的な頂点数を基準に単純置換すると、途中に面定義が挟まっているOBJでは別の頂点へ変換されるおそれがあります。
点群から作成したOBJは、頂点数や面数が非常に多くなる傾向があります。数十万から数百万行あるファイルでは、一部の不正な面定義を目視だけで見つけることは困難です。さらに、頂点番号だけでなく、テクスチャ座標番号や法線番号にも負番号が使われている場合があります。
したがって、点群OBJアップロードで面が抜けたときは、負番号をすべて機械的に削除するのではなく、OBJの行順序と各要素の数を確認しながら、正しい正番号へ変換する必要があります。
面抜けを直す前に知っておきたいOBJの番号規則
負の頂点番号を安全に修正するには、OBJの番号がどのように管理されているかを理解しておく必要があります。特に重要なのは、OBJの番号が0ではなく1から始まることと、オブジェクト名やグループ名が変わっても、頂点などの番号列は原則としてファイル内で通し番号になることです。
OBJでは、頂点位置、テクスチャ座標、頂点法線が別々の行として記録されます。
text v 10.0 20.0 30.0 vt 0.25 0.75 vn 0.0 0.0 1.0
「v」は三次元空間上の頂点位置、「vt」は画像を面へ割り当てるためのテクスチャ座標、「vn」は陰影計算などに使われる頂点法線です。それぞれ独立した番号列を持っています。
面定義には複数の書き方があります。
text f 1 2 3 f 1/1 2/2 3/3 f 1//1 2//1 3//1 f 1/1/1 2/2/1 3/3/1
最初の形式は頂点番号だけを指定しています。二つ目は頂点番号とテクスチャ座標番号、三つ目は頂点番号と法線番号、四つ目は三種類すべてを指定しています。
「1/1/1」の最初の1は頂点位置、二番目の1はテクスチャ座標、三番目の1は法線を参照します。負番号が使われる場合も、それぞれの番号列を別々に数えなければなりません。
たとえば、次の面定義があるとします。
text f -3/-3/-1 -2/-2/-1 -1/-1/-1
頂点番号の「-1」は、その時点で最後に定義されたv行を基準にします。テクスチャ座標番号の「-1」は最後に定義されたvt行を基準にし、法線番号の「-1」は最後に定義されたvn行を基準にします。三種類の行数が同じとは限らないため、すべてを頂点数だけで変換すると誤った参照になります。
正番号への変換には、次の考え方を使います。
text 正番号 = その面行までに定義された要素数 + 負番号 + 1
面行の直前までに頂点が100個あり、面定義に「-1」があれば、正番号は100です。
text 100 + (-1) + 1 = 100
「-5」であれば96です。
text 100 + (-5) + 1 = 96
この計算で最後に1を加えるのは、OBJの正番号が1から始まるためです。配列処理で使われる0始まりの番号と混同すると、一つずつずれた頂点を参照してしまいます。
さらに注意したいのが、変換に使用する要素数です。面行の後にも頂点行が続いている場合、ファイル全体の最終的な頂点数を使ってはいけません。負番号は、その面行が現れた時点までに定義済みの要素を基準にしています。
たとえば、面行の時点で頂点が100個あり、その後に50個の頂点が追加されているとします。このとき「-1」は100番の頂点です。ファイル全体の150個を基準にして変換すると150番になり、まったく別の位置を参照します。
OBJ内に「o」や「g」で始まるオブジェクト名やグループ名があっても、それだけを理由に頂点番号を1へ戻してはいけません。v、vt、vnの番号列は通常、オブジェクトやグループをまたいでファイル全体で管理されます。変換時は名称ではなく、v、vt、vnの各定義数を継続して数えることが基本です。
手順1 原本を保全して面抜けの範囲を特定する
最初の手順は、元のOBJを直接編集せず、原本と作業用ファイルを分けることです。負番号の変換では、計算式や対象列を一つ間違えるだけで、多数の面が別の頂点へ接続される可能性があります。上書き保存してしまうと、正常だった面まで戻せなくなるため、修正前の状態を必ず保全します。
原本、作業用、修正済みの三つに分けて管理すると、途中で問題が起きても比較しやすくなります。ファイル名には更新日や修正内容を含め、どの時点のデータか判別できるようにします。
次に、面抜けがファイル全体で起きているのか、一部の領域だけで起きているのかを確認します。モデル全体が表示されず、頂点だけが見えている場合は、負番号だけでなく、面行そのものが存在しない可能性があります。
点群をOBJへ保存したデータでは、v行だけが記録され、f行が存在しない場合があります。OBJには点要素を表すp行もありますが、アプリケーションによってはv行だけを点として表示する独自の扱いもあります。いずれの場合も、点同士を結ぶf行がなければポリゴン面は構成されません。アップロード先が点表示に対応していない場合は、データが消えたように見えることがあります。
一方、モデルの一部だけが欠けている場合は、欠けた領域に対応するf行が不正になっている可能性があります。負番号を含む面行の割合を調べることで、原因の範囲を絞り込めます。
たとえば、面行を検索し、次のような記述がどの程度含まれているか確認します。
text f -3 -2 -1 f -4/-4 -3/-3 -2/-2 -1/-1 f -3//-1 -2//-1 -1//-1
負番号を含む面が、欠けている領域の面数とおおむね一致する場合は、アップロード先が負番号を処理できていない可能性が高まります。ただし、負番号を含むだけで不正と決めつけず、参照範囲が成立しているかを次の手順で確認します。
原本確認では、行頭の文字を正確に見分けることも重要です。「v」「vt」「vn」は似ていますが、それぞれ別の要素です。頂点数を数えるときにvt行やvn行まで含めると、変換結果がずれます。
頂点位置として数えるのは、行頭のキーワードが「v」である行です。テクスチャ座標として数えるのは「vt」、法線として数えるのは「vn」です。前方や後方に不要な空白が含まれるファイルもあるため、自動処理では先頭の空白を除去し、キーワードを空白区切りで判定します。
同時に、元の頂点数と面数を記録します。修正後に面数が大きく減っていれば、変換処理が一部の面を削除した可能性があります。逆に、面数が同じでも、頂点参照が変わって形状が崩れることがあるため、件数だけで正常と判断してはいけません。
欠けた位置、負番号を含む面数、総頂点数、総面数、ファイル容量を記録しておくと、修正前後の比較が容易になります。
手順2 面行ごとの頂点数を数えて負番号を読み替える
二つ目の手順では、OBJを先頭から順番に読み、各面行に到達した時点の頂点数を把握します。負番号を正確に解釈するための中心的な作業です。
次のようなOBJを考えます。
text v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 1.0 1.0 0.0 f -3 -2 -1 v 0.0 1.0 0.0 f -4 -2 -1
最初の面行に到達した時点では、v行が3個あります。そのため「-3」「-2」「-1」は、それぞれ1、2、3へ変換されます。
text f 1 2 3
次の面行に到達した時点では、v行が4個に増えています。「-4」「-2」「-1」は、それぞれ1、3、4です。
text f 1 3 4
このファイルの最終的な頂点数は4個ですが、最初の面行を4個基準で変換すると「-3」は2になり、本来の面とは異なる頂点を参照します。このため、先にファイル全体のv行を数え、すべての負番号を同じ総数で置き換える方法は安全ではありません。
テクスチャ座標と法線が含まれる場合は、三つのカウンターを独立して管理します。面行へ到達するまでに出現したv、vt、vnの数をそれぞれ保持し、参照部分ごとに変換します。
たとえば、ある面行の時点で、頂点が500個、テクスチャ座標が480個、法線が300個あるとします。
text f -3/-3/-1 -2/-2/-1 -1/-1/-1
最初の参照「-3/-3/-1」は、次の正番号に変換されます。
頂点番号は500を基準にするため498、テクスチャ座標番号は480を基準にするため478、法線番号は300を基準にするため300です。
したがって、最初の参照は次のようになります。
text 498/478/300
同じ計算を残りの参照にも適用すると、面全体は次のようになります。
text f 498/478/300 499/479/300 500/480/300
面参照を分解するときは、斜線の数を維持します。「1//5」はテクスチャ座標を省略し、頂点1と法線5を指定する形式です。これを「1/5」と書き換えると、5が法線ではなくテクスチャ座標として解釈されます。
次の形式は、それぞれ意味が異なります。
text f 1 2 3 f 1/4 2/5 3/6 f 1//7 2//7 3//7 f 1/4/7 2/5/7 3/6/7
自動変換では、参照文字列を斜線で分割した後、空欄を削除せずに保持する必要があります。特に二重斜線を一重斜線へまとめる処理は避けます。
負番号を読み替えた結果が1未満になる場合、その面行は存在しない要素を参照しています。面行の時点で頂点が10個しかないのに「-11」が指定されていれば、変換結果は0です。
text 10 + (-11) + 1 = 0
OBJで0番は有効な頂点番号ではありません。その面は参照範囲外であり、負番号を正番号へ書き換えるだけでは修復できません。元の書き出し処理、結合処理、分割処理などで頂点行が失われていないか確認する必要があります。
手順3 負の頂点番号を正の番号へ変換する
三つ目の手順では、確認した基準数を使って負番号を正番号へ変換します。変換対象は原則としてf行の参照番号です。座標値に含まれる負の数まで置換しないよう注意します。
頂点座標には、負の座標値が普通に使われます。
text v -12.5 3.2 -0.8
これは三次元空間上の位置を示す数値であり、負の頂点番号ではありません。文字列全体からマイナス記号を探して一括置換すると、座標形状が破壊されます。必ず行種別を判定し、「f」で始まる面行だけを処理します。
面行の各参照について、最初の値をvの現在数、二番目の値をvtの現在数、三番目の値をvnの現在数で変換します。正の番号はそのまま残し、負の番号だけを変換します。
面行に正番号と負番号が混在していることもあります。
text f 120 -3 -2 -1
この場合、120は絶対番号として維持し、負番号だけを変換します。面行の時点で頂点数が200個なら、次のようになります。
text f 120 198 199 200
変換時には、面の頂点順序も維持します。面を構成する頂点の並び順は、面の向きや表裏の判定に関係します。「-3 -2 -1」を数値順に並べ替えてはいけません。
たとえば「f -1 -2 -3」を正番号へ変換したとき、頂点数が100なら「f 100 99 98」です。これを小さい順に「98 99 100」へ並べ替えると、頂点をたどる向きが反転します。片面表示を行う環境では、面が裏向きと判定されて見えなくなる可能性があります。修正では番号の表現だけを変え、参照の順序は変更しないことが基本です。
三角形だけでなく、四角形や五角形以上の面にも同じ変換を適用できます。
text f -4 -3 -2 -1
面行の時点で頂点数が300個なら、次のようになります。
text f 297 298 299 300
ただし、アップロード先によっては多角形の分割処理に差があり、負番号を修正しても面が正しく表示されない場合があります。その場合は、負番号の変換とは別の工程として、面を三角形へ分割する方法を検討します。
負番号から正番号への変換後は、元の行に含まれる空白、グループ名、オブジェクト名、材質指定などを必要以上に変更しないほうが安全です。一度に複数の修正を行うと、面抜けが解消した理由や、新しい問題が発生した原因を判別しにくくなります。
修正対象が負番号であると判断できた段階では、まず番号表現だけを正番号へ変換します。改行コード、文字コード、面の三角形化、法線再計算、不要頂点削除などは、必要性を確認してから別の処理として行います。
変換前後の一例は次のとおりです。
`text 変換前 f -3/-3/-1 -2/-2/-1 -1/-1/-1
変換時点の要素数 v = 1250 vt = 1240 vn = 800
変換後 f 1248/1238/800 1249/1239/800 1250/1240/800 `
このように、v、vt、vnの基準数を分けて計算すれば、テクスチャや法線を維持したまま正番号へ変換できます。
手順4 面定義と属性番号の整合性を検証する
四つ目の手順では、変換後の面行が有効な範囲に収まっているかを検証します。変換処理が完了しても、参照先が存在しなければアップロード時の面抜けは解消しません。
最初に、すべての頂点番号が1以上であり、その面行までに定義されたv行の数以下になっていることを確認します。テクスチャ座標番号と法線番号も、それぞれvt行数とvn行数の範囲内でなければなりません。
正番号へ変換した後に0や負番号が残っていれば、変換漏れか参照範囲外です。基準数を超える番号がある場合は、誤った要素数で計算した可能性があります。
次に、一つの面が三つ以上の有効な頂点参照を持っているか確認します。一般的なポリゴン面を構成するには、少なくとも三つの頂点が必要です。
text f 10 11
このように二つしか参照がない行は、ポリゴン面として成立しません。また、三つの番号があっても同じ頂点が重複している場合があります。
text f 10 10 11
この面は異なる三頂点で囲まれていないため、面積が0になる可能性があります。読み込み処理で縮退した面として除外され、面が抜けて見えることがあります。
番号が異なっていても、参照先の座標が完全に同じ場合は、同様に面積が0になることがあります。点群からメッシュを生成する過程では、重複頂点や極端に近い頂点が残る場合があります。番号範囲の検査とあわせて、面を構成する座標の重複も確認すると安全です。
面参照の書式が一つの行内で不統一になっていないかも確認します。
text f 1/1/1 2//1 3/3/1
このような混在は、読み込み側によって解釈が分かれる可能性があります。テクスチャ座標を使用する面では各頂点に対応するvt番号を指定し、使用しない場合は面全体で省略形式を統一するほうが互換性を確保しやすくなります。
片面表示の環境で一部の面だけが消える場合は、頂点法線の向きだけでなく、面の頂点順序を確認します。一般的な描画処理では、面の表裏は頂点を並べた順序、いわゆるワインディングによって判定されます。負番号の変換時に参照順を並べ替えると、面の向きが反転して裏面として除外されることがあります。
一方、vn行で指定する頂点法線は主に陰影や滑らかな見え方に影響します。面のワインディングと法線方向が一致していない場合、面そのものは存在していても、陰影が不自然になったり、周囲より暗く見えたりすることがあります。表裏による非表示と陰影の異常は分けて確認することが重要です。
OBJ内でグループやオブジェクトが複数に分かれている場合は、グループ境界で番号を誤ってリセットしていないか確認します。次のようにグループが変わっても、頂点番号は通常そのまま継続します。
`text g area_1 v 0.0 0.0 0.0 v 1.0 0.0 0.0 v 1.0 1.0 0.0 f 1 2 3
g area_2 v 0.0 1.0 0.0 f 1 3 4 `
area_2の直前に追加された頂点は4番です。グループが変わったため1番へ戻るわけではありません。変換処理でグループごとにカウンターをリセットすると、後半の面が誤った頂点へ接続されます。
検証結果は、正常な面、参照範囲外の面、参照数不足の面、重複頂点を含む面、書式不統一の面に分けて記録すると、修正方針を決めやすくなります。範囲外の面を無条件に削除すると欠損が残るため、元データから復元できるかを先に確認します。
手順5 小分けアップロードで修正結果を確認する
五つ目の手順では、修正済みのOBJをいきなり本番データとして置き換えず、小さな範囲でアップロードを試します。大容量の点群OBJでは、アップロード、変換、表示までに時間がかかるため、毎回ファイル全体を使うと原因確認の効率が下がります。
まず、面抜けが発生していた領域を含む小規模な検証用OBJを作成します。対象領域の頂点、面、必要なテクスチャ座標、法線を取り出し、参照番号を検証用ファイル内で振り直します。
単純に元ファイルの一部分だけを切り出すと、面が参照している頂点行が含まれず、別のエラーを作る可能性があります。切り出す際は、対象面が使用するすべてのv、vt、vnを含める必要があります。
小分けファイルをアップロードし、負番号を正番号へ変換した面が表示されるか確認します。面の有無だけでなく、形状、位置、表裏、色、陰影も確認します。誤った頂点へ接続されていると、面は表示されても長い三角形や突起として現れることがあります。
検証時には、修正前と修正後でカメラ位置や表示条件をそろえます。表示位置が変わると、小さな欠損を見落としやすくなります。欠けていた場所を複数の方向から確認し、裏側から見たときだけ消えるのか、どの方向から見ても面自体が存在しないのかを区別します。
小分けファイルで正常に表示されたら、次に対象範囲を広げます。最初は数百面、次に数千面、その後に全体というように段階的に確認すると、ファイル容量や面数に起因する問題と、番号変換に起因する問題を分けやすくなります。
全体ファイルの確認では、修正前後の頂点数と面数を比較します。負番号を正番号へ変換するだけであれば、原則として頂点数と面数は変わりません。面数が減っている場合は、変換中に行が削除された可能性があります。
ファイル容量は番号の桁数が増えることで多少変化します。「-1」が「1250000」へ変われば文字数が増えるため、修正後の容量が大きくなること自体は異常とは限りません。
アップロード完了後は、表示できたかどうかだけでなく、処理中に警告や除外件数が記録されていないか確認します。アップロード自体が完了していても、不正な面だけを読み飛ばして処理を継続する仕組みがあります。
修正後の検証では、欠損していた面の数とアップロード時に除外された面の数を照合します。除外件数が0になり、欠損部分が正しく表示され、形状の崩れもなければ、負番号の変換が有効だったと判断できます。
自動修正するときの実装上の注意
大容量の点群OBJでは、手作業で負番号を書き換える方法は現実的ではありません。自動修正処理を作る場合は、OBJを先頭から一行ずつ読みながら、v、vt、vnの現在数を管理します。
基本的な処理の流れは次のようになります。
`text 頂点数を0にする テクスチャ座標数を0にする 法線数を0にする
ファイルを先頭から一行ずつ読む
v行なら頂点数を1増やす vt行ならテクスチャ座標数を1増やす vn行なら法線数を1増やす
f行なら参照を分解する 負の頂点番号を現在の頂点数で変換する 負のテクスチャ座標番号を現在のテクスチャ座標数で変換する 負の法線番号を現在の法線数で変換する 検証後の面行を書き出す
その他の行は原則としてそのまま書き出す `
行種別の判定順序にも注意が必要です。「v」で始まるという前方一致だけで判定すると、vtやvnまでv行として数える実装になることがあります。行頭のキーワードを分離し、「v」「vt」「vn」を明確に区別します。
空行やコメント行、オブジェクト名、グループ名、材質指定などは、修正の目的に関係しない限りそのまま維持します。コメントに「f -3 -2 -1」という文字列が書かれていても、実際の面定義ではないため変換してはいけません。
非常に長い面行が含まれる場合は、一行全体を扱えるようにします。固定長の読み込み処理では、面行の途中で切れてしまい、後半の頂点参照が失われることがあります。継続行を使用しているOBJを扱う場合は、行末の継続記号にも対応する必要があります。
ファイル全体を一度にメモリへ読み込むより、一行ずつ読み、別ファイルへ順次書き出す方式のほうが、大容量データを扱いやすくなります。ただし、途中でエラーが発生した場合に不完全な出力ファイルが残るため、作業用の一時ファイルへ書き出し、全処理が成功してから修正済みファイル名へ切り替える方法が安全です。
変換時には、処理した面数、負番号を変換した件数、範囲外だった参照数、無効と判断した面数を記録します。単に「処理完了」とするのではなく、変換結果を確認できる記録を残すことで、面抜けが続いた場合の原因調査に利用できます。
範囲外の番号を検出したときは、勝手に1番へ置き換えたり、末尾の頂点へ丸めたりしてはいけません。そのような補正をすると、ファイルは読み込めても、遠く離れた頂点同士が結ばれて形状が大きく崩れます。範囲外の面は別の検査対象として記録し、元データから正しい参照を復元できるか確認します。
負番号を直しても面が抜ける場合の確認事項
負番号をすべて正番号へ変換しても面が抜ける場合は、別の原因が残っている可能性があります。最初に確認したいのは、OBJに必要なf行が本当に存在するかどうかです。
点群として取得したデータをOBJへ保存した場合、頂点情報だけが記録され、面が生成されていないことがあります。p行で点要素が定義されている場合や、アプリケーションがv行を点として独自に表示する場合でも、f行による面の接続情報がなければポリゴン面は表示できません。この場合は負番号の修正ではなく、点群から面を生成する処理が必要です。
次に確認するのは、面が参照する頂点の座標です。三つの異なる番号を参照していても、座標が同じ位置に重なっていれば面積が0になります。ほぼ一直線上に並んでいる場合も、極端に細い面となり、読み込み時に除外されることがあります。
面を構成する頂点の並び順にも注意が必要です。表側から見ると表示される一方、反対側からは表示されない場合、片面表示とワインディングが関係している可能性があります。周囲の面と頂点順序が逆になっていると、一部だけ裏向きになります。
頂点法線が周囲と逆向きになっている場合は、面が欠けるというより、陰影や明るさが不自然になることがあります。面の非表示を調べるときは頂点順序と片面表示の設定を確認し、陰影の異常を調べるときはvn行や法線再計算の結果を確認します。
四角形以上の面が含まれている場合は、面の形状がねじれていないか確認します。同一平面上にない四頂点を一つの面として定義すると、読み込み側の分割方法によって見え方が変わることがあります。三角形へ分割して比較すると、負番号以外の問題を切り分けられます。
頂点番号が整数として記録されているかも確認します。面行に小数、文字、余計な区切り記号が含まれていると、その面が読み飛ばされます。
text f 10 11.0 12 f 10,11,12 f 10 abc 12
このような記述は、通常の頂点参照として扱えません。番号変換後に不要な記号が入っていないか確認します。
テクスチャ座標や法線の参照だけが範囲外になっている場合もあります。頂点番号が正常でも、「f 10/500/20」の500番に対応するvt行が存在しなければ、読み込み側が面全体を無効と判断する可能性があります。
一時的な切り分けとして、頂点番号だけを残した検証用の面を作る方法があります。
`text 変換前 f 10/500/20 11/501/20 12/502/20
頂点のみの検証 f 10 11 12 `
頂点番号だけなら表示される場合、面の位置ではなく、テクスチャ座標または法線の参照に問題がある可能性があります。ただし、これは原因確認用であり、必要な属性を恒久的に削除するかどうかは用途に応じて判断します。
同じ面が重複して定義されている場合は、表示時にちらつきが生じることがあります。負番号の面と正番号の面が同じ頂点を参照して重複しているケースもあるため、変換後の面参照を正規化して比較すると重複を見つけやすくなります。
ファイルの途中で頂点行が削除された一方、後続の面番号が更新されていない場合は、多数の面が一つずつずれます。この問題は負番号の変換だけでは解消できません。削除前のOBJや元の生成データと比較し、頂点と面の対応を再構築する必要があります。
再発を防ぐ書き出しと運用ルール
負の頂点番号による面抜けを再発させないためには、修正後のファイルだけでなく、OBJを書き出す工程とアップロード前の検査方法を見直すことが重要です。
利用するアップロード先が負番号へ対応しているか不明な場合は、OBJの面参照を正番号で出力すると互換性上の問題を避けやすくなります。正番号であれば、ファイルの先頭から数えた参照先が明示されるため、相対番号に未対応の処理でも読み込める可能性が高まります。
書き出し後は、アップロード前に自動検査を実施します。検査では、負番号の有無だけでなく、0番、範囲外番号、頂点数不足、重複参照、存在しないテクスチャ座標番号、存在しない法線番号を確認します。
OBJを結合する工程では、後から追加する面の正番号を、先に存在するv、vt、vnの数に応じて加算する必要があります。複数のOBJを単純に連結すると、二つ目以降のファイルにある「f 1 2 3」が、一つ目のファイルの頂点を参照します。
負番号を使えば一部の結合処理を簡略化できる場合がありますが、アップロード先との互換性を優先するなら、結合後に正番号へ確定させる運用が適しています。
ファイルを分割するときも、面行だけを切り出してはいけません。各面が参照する頂点、テクスチャ座標、法線を抽出し、分割後のファイル内で番号を振り直します。分割前の番号を残すと、分割後には存在しない要素を参照する可能性があります。
点群から面を生成する工程では、生成直後の頂点数と面数を保存し、OBJ書き出し後の数と比較します。書き出し後に面数が減っていれば、ファイル変換の段階で面が失われた可能性があります。
アップロード後にも同じ件数を確認できる場合は、生成時、書き出し時、アップロード時の三段階で比較します。どの段階で面数が変化したかが分かれば、原因調査の範囲を大幅に絞れます。
修正プログラムや変換設定を変更したときは、大規模な実データだけで試すのではなく、正番号、負番号、テクスチャ付き、法線付き、四角形を含む小さな検証用OBJを用意します。期待する形状と変換結果を固定しておけば、処理の更新による不具合を早期に発見できます。
運用上は、原本を保存し、修正履歴を残し、変換前後の検査結果を関連付けて管理します。同じファイル名で何度も上書きすると、どの処理が適用されたデータか分からなくなります。
特に、点群OBJアップロードの直前に手作業で頂点削除や面削除を行う場合は、削除後に番号が適切に更新されているかを確認します。頂点行だけを削除し、面行の参照を更新しなければ、削除した位置より後ろにある多数の面がずれます。
負番号を使うか正番号を使うかだけでなく、頂点と面の変更を常に一体として扱うことが、安定したアップロードにつながります。
まとめ
点群OBJアップロードで面が抜ける場合、f行に含まれる負の頂点番号が原因になっていることがあります。ただし、負番号はOBJの表現として成立する場合があり、マイナス記号があるだけで不正とは限りません。
問題になるのは、アップロード先が負番号に対応していない場合、参照範囲を超えた負番号が含まれる場合、または誤った基準数で正番号へ変換した場合です。
修正では、最初に原本を保全し、負番号を含む面と面抜けの範囲を確認します。次に、OBJを先頭から読み、各面行の時点で定義済みのv、vt、vnを別々に数えます。
負番号は「現在の要素数+負番号+1」で正番号へ変換します。ファイル全体の最終的な頂点数を一律に使うのではなく、面行が現れた時点の数を基準にすることが重要です。
変換後は、番号が有効範囲内にあるか、面が三つ以上の異なる頂点を参照しているか、テクスチャ座標と法線の番号が存在するかを確認します。その後、小規模な検証用OBJから段階的にアップロードし、欠損、形状、面の向き、属性の状態を比較します。
負番号を修正しても面が抜ける場合は、f行の欠落、面積が0の面、範囲外の属性番号、ワインディングによる裏向き、多角形のねじれ、頂点削除後の番号ずれなどを確認します。頂点法線は主に陰影へ影響するため、片面表示の表裏判定とは分けて調査することが重要です。
点群OBJを継続的に扱う現場では、書き出し時に正番号を使用し、アップロード前に参照範囲を自動検査する運用が有効です。取得した点群の確認、共有、現場での活用まで含めて作業の流れを整える際は、LRTK Phoneを活用した点群運用も次の選択肢として確認してみてください。