SEKKEIYA

SEKKEIYA

Gallery

Vision

About

Services

Products

Marketplace

Articles

Pricing

Download

Log in

DESIGN & 3D

空間をかたちにする

S.Model

S.Model

3Dモデルをブラウザ上で高速に共有し、ウォークスルーや注釈付けでレビューできるクラウド共有アプリ。

S.Layout

S.Layout

登録済みの3Dアセットを使い、ブラウザ上で直感的に空間レイアウトを組み立てる配置シミュレータ。

S.Create

S.Create

画像やテキストから独自の3Dアセットを素早く生成するAIモデリングジェネレーター。

S.Slide

S.Slide

BETA

シネマティックなスクロール型プレゼンテーションを自動構築・配信するPresentsビルダー。

S.Material

S.Material

IN DEVELOPMENT

木材・金属・ファブリックなどのマテリアルを在庫として管理し、家具や空間へワンクリックで適用する素材管理アプリ。

DRAWING & VISUAL

図面とビジュアル資料

S.Diagram

S.Diagram

ゾーニングや動線、システム構成などの設計ダイアグラムを作成・共有するドローイングツール。

S.Drawing

S.Drawing

平面図・立面図などの図面をセット単位でアップロード・管理し、チームと共有する図面管理アプリ。

S.Image

S.Image

パース・動画・AI生成画像などのビジュアル成果物を横断的に集約・管理するイメージライブラリ。

S.Movie

S.Movie

IN DEVELOPMENT

レンダリングしたクリップから、カット構成まで自動編集エンジンが組み立てる建築・インテリア向け動画ツール。

LEARNING & SHOWCASE

学び、貯め、発信する

S.Quest

S.Quest

BETA

建築・インテリア向けの学習プラットフォーム。動画講座やステップ式のコースでスキルを体系的に習得。

S.Portfolio

S.Portfolio

IN DEVELOPMENT

プロジェクトの成果物をまとめ、実績として発信できるポートフォリオ&ナレッジベース。

S.Library

S.Library

本・PDF・Web記事・メモといった知識資源をローカルで一元管理し、AIの知識源にもなるナレッジライブラリ。

S.Blog

S.Blog

AIと議論しながら記事を執筆し、自分の知識庫とSEOに強い公開サイトの両方へ同時配信するブログ執筆ハブ。

すべてのプロダクトを見る(Marketplace)

制作ワークフロー・連携

2025/12/22

Desktop版GLB変換パイプライン:Rhino連携を支える安定化設計の全記録

S

By SEKKEIYA

GLB生成のDesktop移行、rhino3dm環境差分への耐性、.mesh.3dmによる責務分離、Z-up/Y-up座標系の統一、ACK方式の非同期連携——Rhino連携を支えるGLB変換パイプライン安定化の全記録です。

導入

SEKKEIYA の S.Models(旧 3D Shape Share)Desktop版では、Rhino からアップロードした .3dm ファイルを Desktop 側で .glb に変換し、Web Viewer や Three.js 環境で扱える形にするローカル変換パイプラインを採用しています。

この GLB 生成は、Viewer 表示やデータ共有の要となる重要な工程です。本記事では、初期リリースに向けて積み重ねてきた GLB 変換パイプラインの安定化設計を、一連の改善としてまとめて記録します。具体的には、(1) 生成責務の Desktop 側への移行、(2) rhino3dm 環境差分への耐性、(3) Rhino と Desktop の役割分離、(4) 座標系(Z-up / Y-up)の統一、(5) 結果連携の非同期基盤化、の5点です。

1. GLB 生成を Desktop 側へ移行する

Rhino 側 GLB 出力が抱えていた課題

当初は UploadSelectionTo3DSS コマンド内で GLB を書き出していましたが、Rhino の Export ダイアログや内部挙動に依存するため、完全な自動化が困難でした。環境差や設定差によって出力に失敗し、glbPath が null になるケースが発生しやすく、運用上の不安定要因となっていました。

役割分担の再定義

そこで、Rhino は制作ツールとしての役割に集中し、Desktop は変換・最適化を担うという明確な分業構造へ切り替えました。Rhino から Desktop へ渡すジョブ情報 upload-selection-job.json には、次の要素を加えています。

  • requestGlb: true による GLB 生成リクエストの明示
  • unitSystem による単位系の正確な伝達
  • jobId による生成物の安定した紐付け
  • glbPath は Rhino 側では null 固定

Rhino 側は「3dm 書き出し・サムネイル生成・寸法/カテゴリ等のメタデータ生成」に専念し、Viewer では GLB を優先表示することで体感速度を向上させています。

2. rhino3dm の環境差分に耐えるメッシュ解釈

Rhino 7 / Rhino 8 / wasm build といった rhino3dm 実行環境ごとの差分により、従来の Mesh 判定・頂点取得・面取得ロジックが一部環境で正しく動作しないことが判明しました。これらを「例外」ではなく「最初からあり得る前提」として吸収する耐性設計へ刷新しています。

  • Mesh 判定を構造ベースへobjectType への依存を廃止し、constructor === "Mesh" かつ vertices / faces API が存在することを複合条件として判定。
  • 頂点取得の耐性化{x, y, z} 形式を前提とせず、配列形式 [x, y, z] も優先的に処理。
  • 面の正規化getFaceVertices(i) の返却(triangle / quad / d = -1 混在)を内部で吸収し、最終的に必ず三角形インデックスへ変換。

これにより、Mesh が1枚でも取得できれば GLB 生成を継続できる「失敗しないための多重安全設計」へと転換しました。あわせて、Node.js 実行環境で Three.js の GLTFExporter が要求する FileReader をポリフィルし、CLI・自動変換フローでも安定して GLB を生成できる基盤を整えています。

3. Rhino と Desktop の役割を分離する(.mesh.3dm と .3dm)

Brep・Extrusion・SubD は Rhino 内部で表示用 Mesh を保持していますが、必ずしも .3dm に明示的な Mesh として保存されているわけではありません。そのため Desktop 側で Mesh が解釈できず、GLB が 2KB 程度の空ファイルになる問題が起きていました。

そこで UploadSelectionTo3DSS を改修し、RhinoCommon を用いて Mesh を生成した状態で書き出す設計へ変更しました。

  • Mesh 取得は RenderMesh を最優先し、存在しない場合のみ Geometry からの Mesh 化をフォールバックとして実行
  • 生成した Mesh は headless な Rhino Document に集約し、Mesh のみを追加した .mesh.3dm として書き出す
  • Desktop 側は .mesh.3dm(Mesh 化済み)と .3dm(元データ)を明確に分離して扱う

「Rhino は正しい形状と Mesh を生成し、Desktop はそれを忠実に GLB 化する」という責務分離により、変換結果の再現性と信頼性が大きく向上しました。

4. 座標系(Z-up / Y-up)を統一する

Rhino は Z-up、glTF / Three.js は Y-up という仕様差により、GLB を Rhino で開くと向きが不正になる、Viewer 上で上下が逆に見える、といった問題が発生していました。

今回、GLB 出力前に座標系を正しく変換し、Rhino で再インポートしても Z-up が維持されることを確認しています。これにより、Web Viewer / Desktop Viewer / Rhino 再読み込みのすべてで、一貫した向きと形状を保てるようになりました。

5. 生成結果を非同期で安全に連携する(Result Watcher / ACK)

GLB 生成は計算量が大きく実行時間も不定なため、UI や Web 側の処理と密結合させると安定性に影響します。そこで「重い生成処理は Desktop、データ管理と共有は Web」という役割分担を明確にした非同期連携基盤を整備しました。

フロントエンド監視から Rust(Tauri)統合へ

従来は生成後の result ファイルをフロントエンド(JavaScript)側で監視していましたが、Node / Browser 環境差による fs API の制限などで不安定になりがちでした。ファイル監視の責務を OS に近い Rust(Tauri)側へ統合し、UI は Tauri Event を listen して結果を受け取るだけに整理しました(glbResultWatcher.js は廃止)。

ACK 方式による信頼性の確保

result ファイルを検知した時点で即削除する設計は、Firebase 更新が途中で失敗した際に再処理の手がかりを失います。そこで、Rust 側は「結果を通知する役割」に徹し、フロント側が Firebase Storage / Firestore の更新に成功したときだけ delete_glb_result_file を呼んで result ファイルを削除する ACK 方式を採用しました。

  • 二重処理の防止
  • 取りこぼしの回避
  • エラー時の再試行余地の確保(「安全に止まれる設計」)

結果として、責務は「Rhino:ジョブの起点 / Rust:ジョブ管理・Result 監視・イベント発行 / React:結果受信・Firebase 反映・ACK 送信」という一本の流れに整理されました。

まとめ

一連の改善により、「Rhino からアップロードすれば必ず Web で正しく表示できる」という Desktop 連携の基盤が完成しました。要点は次の5つです。

  1. GLB 生成責務を Desktop 側へ移行し、Viewer は GLB を優先表示
  2. rhino3dm の環境差分に耐える Mesh 判定・頂点/面取得ロジック
  3. .mesh.3dm.3dm の役割分離による変換パイプラインの明確化
  4. Z-up / Y-up 座標系の統一による表示の一貫性確保
  5. Result Watcher の Rust 統合と ACK 方式による安全な非同期連携

なお、本対応は Desktop 側のローカル変換処理の安定化を目的としたもので、Web 版のデータ構造や既存挙動には影響しません。引き続き、安定性と表現力の向上を進めていきます。