Open13

ThatOpen/engine_components を調べる

kiyukakiyuka

ドキュメントとか見ると半分以上が、HTML, CSS と Three.jsの内容だけどそこはスルーします。
IFC周辺について見ていくことにする。

そうするとドキュメントで言えば、チュートリアルパスの 「LOADING AND EDITING BIM DATA(BIMデータの読み込みと編集)」かな

https://docs.thatopen.com/components/tutorial-paths

kiyukakiyuka

ドキュメント見ても最小構成すらわからないので、GitHubのリポジトリ見てたらテンプレートがあった。

https://github.com/ThatOpen/engine_templates

git clone https://github.com/ThatOpen/engine_templates.git

cd engine_templates/templates/vanilla
npm install
npm run dev

kiyukakiyuka

たぶん最小構成

index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>OpenBIM App</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      #app {
        width: 100vw; 
        height: 100vh; 
        overflow: hidden;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>
src/main.ts
import * as OBC from "openbim-components"

const viewer = new OBC.Components()

const sceneComponent = new OBC.SimpleScene(viewer)
sceneComponent.setup()
viewer.scene = sceneComponent

const viewerContainer = document.getElementById("app") as HTMLDivElement
const rendererComponent = new OBC.PostproductionRenderer(viewer, viewerContainer)
viewer.renderer = rendererComponent

const cameraComponent = new OBC.OrthoPerspectiveCamera(viewer)
viewer.camera = cameraComponent

await viewer.init()

const ifcLoader = new OBC.FragmentIfcLoader(viewer)
await ifcLoader.setup()

const mainToolbar = new OBC.Toolbar(viewer)
mainToolbar.addChild(
  ifcLoader.uiElement.get("main"),
)

viewer.ui.addToolbar(mainToolbar)
kiyukakiyuka

テンプレートには、

  • グリッドの表示(OBC.SimpleGrid)
  • モデルクリックでハイライト(OBC.SimpleRaycaster)
  • カメラから見えていないオブジェクトの非表示(OBC.ScreenCuller)
  • プロパティ表示処理(OBC.IfcPropertiesProcessor)

があったけど、IFCファイルを読み込んでモデル表示するだけなら不要なので、最小限にするとこうなる構成

kiyukakiyuka

IFCの読み込みというか表示速度が速いというか軽いのなんでか知りたい。
とりあえず、ファイル指定での読み込み最小構成。

main.ts
import * as OBC from "openbim-components"

const container = document.getElementById("app") as HTMLDivElement

// Three.jsの準備
const viewer = new OBC.Components();
viewer.scene = new OBC.SimpleScene(viewer);
viewer.scene.setup();
viewer.renderer = new OBC.SimpleRenderer(viewer, container);
viewer.camera = new OBC.SimpleCamera(viewer);
viewer.raycaster = new OBC.SimpleRaycaster(viewer);
await viewer.init();

const scene = viewer.scene.get();

// IFC読み込み準備
const fragmentIfcLoader = new OBC.FragmentIfcLoader(viewer);
await fragmentIfcLoader.setup()

// IFCファイル読み込み処理
async function loadIfcAsFragments() {
  const file = await fetch('../assets/small.ifc');
  const data = await file.arrayBuffer();
  const buffer = new Uint8Array(data);
  const model = await fragmentIfcLoader.load(buffer);
  scene.add(model);
}

loadIfcAsFragments()

ドキュメント

https://docs.thatopen.com/Tutorials/SimpleScene

https://docs.thatopen.com/Tutorials/FragmentIfcLoader

kiyukakiyuka

fragmentIfcLoader.load(buffer)を詳しく見る。

https://github.com/ThatOpen/engine_components/blob/fc953a6fce8e2160b690a58333a65144a9ac1914/src/fragments/FragmentIfcLoader/index.ts#L82

いろいろやって入るけど、読み込みしてメッシュ作成自体はこれだけ。

  // const model = await fragmentIfcLoader.load(buffer);
  // scene.add(model);

  await fragmentIfcLoader.readIfcFile(buffer);
  const group = await fragmentIfcLoader.getAllGeometries();
  scene.add(group);

getAllGeometries が実際のThree.jsのメッシュ作成処理。

https://github.com/ThatOpen/engine_components/blob/fc953a6fce8e2160b690a58333a65144a9ac1914/src/fragments/FragmentIfcLoader/index.ts#L162

kiyukakiyuka

違うエンティティでも同じ形状の場合があるから、それをまとめることで、多重にメッシュを作成しないようにしているっていうことはわかった。

IfcOpenShellだと形状取得処理ifcopenshell.geom.create_shapeでそのあたりを判断できる要素が多分ないので、そういうことはできない。

Hidden comment
Hidden comment
kiyukakiyuka

なんでこんなメモリ効率いいんだ?
試しにBabylon.jsで同じ処理させようとするとメモリ使用量ぜんぜん違うんだけど?
いや、WebGLのパフォーマンスのこと全然詳しくないってのもあって、なにかしら実装に問題があるんだろうけど。