■ 2. 環境
- blender 5.0.1にWeb3D X3D/VRML2 formatアドオンを入れて.x3d形式でエクスポート
- VS CodeにLive Serverを入れてEdgeで閲覧
■ 1. 遭遇した問題
- X3DOMでメッシュを表示しようとした際、頂点座標(
Coordinate)とUV座標(TextureCoordinate)を指定したのに、なぜかUVが反映されず、正面からテクスチャをそのまま張り付けたような見た目になる

blenderでの画面

ブラウザで見た画面 - エクスポートされたコードの記述を見直しても、特に間違っているようには見えない
<IndexedFaceSet solid="false" texCoordIndex="0 1 2 -1 "coordIndex="2 0 1 -1 "
>
<Coordinate DEF="coords_ME_立方体_005"
point="1.000000 1.000000 0.000000 -1.000000 1.000000 0.000000 0.000000 -1.000000 0.000000 "
/>
<TextureCoordinate point="1.0000 0.0000 1.0000 1.0000 0.0000 1.0000 " />
</IndexedFaceSet>
■ 2. 結論(解決策)
-
<Coordinate />というように「自己閉じタグ(空要素タグ)」で書いていたのが原因 -
<Coordinate></Coordinate>と開始・終了タグを明記することで、あっさりテクスチャが反映されるようになる
■ 3. なぜこんなことが起きるのか?(原因)
- XMLの仕様上は
/>で閉じても問題ないが、HTMLファイル内に直接記述した場合、ブラウザのHTMLパーサーが/>を終了タグとして認識してくれないため - HTMLでは
<img>などの特定のタグ以外は自己閉じが無視される仕様 - 結果として、ブラウザは
<Coordinate>が閉じられていないと勘違いし、続く<TextureCoordinate>を兄弟要素ではなく、子要素として内部に飲み込んでしまう - 開発者ツールの「Elements(要素)」タブで見ると、無惨にもネストされてしまったDOMツリーが確認できる
■ 4. まとめ
- ReactのJSX環境などに慣れていると
/>で閉じる癖がついてしまっているが、X3DOMを生HTMLで書く時はブラウザの解釈仕様に注意が必要 - カスタムタグは律儀に閉じよう
追記
変換スクリプト
import sys
import re
import os
def main():
if len(sys.argv) < 2:
print("python x3d_fixer.py <ファイル名> で指定してください。")
sys.exit(1)
input_file = sys.argv[1]
if not os.path.exists(input_file):
print(f"ファイルが見つかりません。")
sys.exit(1)
try:
# ファイルの読み込み
with open(input_file, 'r', encoding='utf-8') as f:
content = f.read()
# 正規表現で置換
fixed_content = re.sub(r'<([a-zA-Z0-9_]+)([^>]*?)\s*/>', r'<\1\2></\1>', content)
# 出力ファイル名の生成
output_file = f"fixed_{os.path.basename(input_file)}"
# 変換結果の保存
with open(output_file, 'w', encoding='utf-8') as f:
f.write(fixed_content)
print(f" 変換終了。'{output_file}' を確認してください。")
except Exception as e:
print(f"何かエラー: {e}")
if __name__ == "__main__":
main()