添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
0
1

Svelte で 3D 表示を行うライブラリ Threlte #3: glTF シーンを扱う

Last updated at Posted at 2024-01-22

  • Svelte で 3D 表示を行うライブラリ Threlte #1: パッケージの作成とライブラリ概要
  • Svelte で 3D 表示を行うライブラリ Threlte #2: エクストラパッケージを使用する
  • Svelte で 3D 表示を行うライブラリ Threlte #3: glTF シーンを扱う
  • Svelte で 3D 表示を行うライブラリ Threlte #4: シーンコントロールツールセット Theatre.js for Threlte
  • Svelte で3D表示を行うライブラリ Threlte #5: XR への対応
  • glTF について

    glTF は Khronos Group Inc. が提唱しているファイルフォーマット、シーンディスクリプタ。
    最初からストリーミング機構などをサポートしているため、Web 利用などと相性が良く、近年普及が進んできている。

    昨年の SIGGRAPH 2023 では glTF の今後のフォーマットに関してのセッションやフォーラムも数多くあった。
    参加者には、Khronos Group の人に加え、Meta、Adobe、NVIDIA、Autodesk、Epic Games などが参加しており、今後は、XR や 3D 広告での利用をもっと広めていく狙いもあるとみられる。

  • The State of 3D Asset Interoperability using USD and glTF
  • Geometry, Textures, and Workflow - Optimizing glTF
  • glTF Complex Scenes & Interactivity
  • Exploring the Artistic Frontier: Unleashing Creativity in 3D Models with glTF and PBR
  • Let's Get Moving: Adding Physics to glTF
  • glTF: Transforming 3D Asset Delivery for Real-Time Graphics
  • Khronos is holding our fourth invite-only glTF Ecosystem Forum at this year’s SIGGRAPH in Los Angeles, California.
  • animations : AnimationClip [], asset : { generator : string , version : number }, cameras : Camera [], materials : ' Materials ' [], nodes : ( Group | Mesh | SkkinedMesh )[], parser : GLTFParser , scenes : Group [] userData : {}
  • animations
  • アニメーション(クリップ)情報が保存されている
  • asset
  • glTF ファイル自体の情報
  • cameras
  • カメラ情報が保存されている
  • materials
  • マテリアル情報が保存されている
  • nodes
  • メッシュやスキンメッシュ(アニメーションする際に必要なメッシュタイプ)、内包シーン情報が保存される
  • parser
  • GLTF のパース情報。JSON 形式もこちら経由で取得できる。
  • scenes
  • シーン情報を保存
  • userData
  • ユーザー固有のデータの保存領域
  • useGltfAnimations
  • 通常のファイルロードに加えて、アニメーションやシーン周りのサポートもあるため、諸々を説明するより先に Threlte での glTF の扱い方を紹介した方がモノにしやすいというのもあり、この段階での glTF の扱い方についてまとめるに至った。

    では、まずは簡易ロードの仕方から。

    glTF 関連モジュールの使い方 <GLTF> - glTF ファイルの簡易ロード

    <GLTF> を使用すると、それ単体での glTF ファイルの簡易ロードが可能。

    Scene.svelte
    <script lang="ts">
    	import { T } from '@threlte/core';
    +	import { ContactShadows, GLTF, Grid, OrbitControls, Environment } from '@threlte/extras';
    </script>
    <T.PerspectiveCamera makeDefault position={[5, 2, 13]} fov={15}>
    	<OrbitControls enableZoom={true} enableDamping target.y={1.5} />
    </T.PerspectiveCamera>
    <Environment
    	files={'https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/equirectangular/venice_sunset_1k.hdr'}
    	isBackground={true}
    	position.y={-0.001}
    	cellColor="#ffffff"
    	sectionColor="#ffffff"
    	sectionThickness={0}
    	fadeDistance={30.0}
    	cellSize={2}
    <ContactShadows scale={10} blur={2} far={2.5} opacity={0.5} />
    <!-- 今回は glTF のサンプルモデルを直接 static 以下に配置して使用 -->
    <T.Mesh position={[0, 1.3, 0]}>
    +	<GLTF
    +		url="https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/main/2.0/DamagedHelmet/glTF/DamagedHelmet.gltf"
    </T.Mesh>
    useGltf - glTF ファイルの操作利用
    

    glTF シーンをロードして、そのシーンをコントロールしながら描画する場合は useGltf フックでロードして使用する。
    Web アプリとして実装する場合はこちらでの利用が多くなると思われる。

    useGltf を使用すると、glTF を取り回しができるインスタンスオブジェクトとして扱えるようになる。

    Scene.svelte
    <script lang="ts">
      import { T } from '@threlte/core'
    +  import { Grid, OrbitControls, useGltf, Environment } from '@threlte/extras'
      const gltf = useGltf("./models/DamagedHelmet.glb", { useDraco: true })
    </script>
    {#if $gltf}
    +  <T is={$gltf.nodes['node_damagedHelmet_-6514']} />
    {/if}
    

    glTF オブジェクトにすると、シーン内の詳細にもアクセスできる様になる。
    なので、例えばマテリアルを差し替えるなども可能。

    Scene.svelte
    <script lang="ts">
      import { T } from '@threlte/core'
      import { Grid, OrbitControls, useGltf, Environment } from '@threlte/extras'
    +  import { MeshStandardMaterial, Color } from 'three'
      const gltf = useGltf("./models/DamagedHelmet.glb", { useDraco: true })
    </script>
    {#if $gltf}
      <T.Mesh
    +    geometry={$gltf.nodes['node_damagedHelmet_-6514'].geometry}
    +    material={new MeshStandardMaterial({roughness: 0.0,
    +                                        color: new Color("rgb(255, 0, 0)")})}
        rotation={[1.5, 0, 0]}
    {/if}
    useGltfAnimations - glTF でのアニメーションを再生する
    

    Three.js の場合でもそうだが、大体の 3D フレームワーク同様、メッシュとアニメーションの処理は柔軟に扱えるよう、別々に取り扱うように設計されている。Mesh : Aimation = 1:1 ではないのである。
    なので、これらを取り扱う場合には、ワンステップ踏む必要がある。

    Threlte では、これを @threlte/extrasuseGltfAnimations などを使って実現する。

    Scene.svelte
    <script lang="ts">
      import { T } from '@threlte/core'
    +  import { useGltf, useGltfAnimations, GLTF } from '@threlte/extras'
    +  const { gltf, actions } = useGltfAnimations()
    +  $: $actions['Take 001']?.play()
    </script>
    <!-- その他シーンセットアップは省略 -->
    +<GLTF
    +  bind:gltf={$gltf}
    +  url="/models/LittlestTokyo.glb"
    +  useDraco={true}
    

    glTf のアニメーションは、一つの glTF ファイルに複数内包されいてる可能性がある。
    そのため、アニメーションを再生する際には、アニメーションのトラック名を指定して、再生してあげる必要がある。
    こういったところが、アニメーションを扱う上で意図手間かかる所以。

    @threlte/gltf - glTF コンポーネント出力ツール

    glTF の内部構造にアクセスする場合は名前解決が必要だったりする。
    それを上手く解析して表示するには、3D エディタ的な機能まで必要だったりするが、Threlte では、glTF ファイルを読み込むためのコンパクトな svelte コンポーネントを出力しくれるツールが提供されている。
    それが @threlte/gltf である。

    例えば、DamagedHelmet の場合、

    npx @threlte/gltf@latest DamagedHelmet.glb
    

    といったコマンドを実行することによって、以下のような Svelte コンポーネントを出力してくれる。

    DamagedHelmet.svelte
    <script>
      import { Group } from 'three'
      import { T, forwardEventHandlers } from '@threlte/core'
      import { useGltf } from '@threlte/extras'
      export const ref = new Group()
      const gltf = useGltf('/DamagedHelmet.glb')
      const component = forwardEventHandlers()
    </script>
    <T is={ref} dispose={false} {...$$restProps} bind:this={$component}>
      {#await gltf}
        <slot name="fallback" />
      {:then gltf}
        <T.Mesh
          geometry={gltf.nodes['node_damagedHelmet_-6514'].geometry}
          material={gltf.materials.Material_MR}
          rotation={[Math.PI / 2, 0, 0]}
      {:catch error}
        <slot name="error" {error} />
      {/await}
      <slot {ref} />
    

    あとは、これをコンポーネントとして再利用するだけ。

    Scene.svelte
    <script lang="ts">
      import Model from '$lib/models/DamagedHelmet.svelte';
    </script>
    <!-- シーン設定は省略 -->
    <Model />
    

    読み込むファイルが決まっていたり、コンパクトなローダーで収めたり、対象ハックする参考としてこれを利用するという手がある。

    glTF を扱う上での付随知識 DRACO ローダーの使用

    glTF は、際してコンパクトに取り回しが行える様に圧縮がかけられている事がままある。
    その圧縮形式は今のところ DRACO が頻繁に使われている(現状は、実質一択)。

    その DRACO 解凍 を行いつつロードしてくれる仕組みが DRACO ローダー として用意されている

    この Draco 圧縮がかかったものを、ローダーを通さずにロードしようとするとエラーを起こす。

    Error in asyncWritable: THREE.GLTFLoader: No DRACOLoader instance provided.
    

    そのため、エラー回避も含めてローダーを使用してロードしておく。
    以下の様に複数やり方があるので、状況に応じて選択する。

    Scene.svelte
    <script lang="ts">
      import { userGltf } from "@threlte/extras"
      const gltf = useGltf('/model.glb', { useDraco: true })
    </script>
    
    Scene.svelte
    url="/models/LittlestTokyo.glb" useDraco={true}

    また、true を渡すとライブラリ標準のものがロードされてくるが、ローダーを直接指定することも可能。
    特別、ローダーを変更したい場合に指定すると良い。

    Scene.svelte
    url="/models/LittlestTokyo.glb" useDraco="https://www.gstatic.com/draco/v1/decoders/"

    もう一つとしては Meshpot が存在する。
    ただ今のところ僕は使っているところを見たことがないので、要調査。

    使い方としては、DRACO と同じで、useMeshpot を指定する。

    url="/models/LittlestTokyo.glb" useMeshpot={true}

    :point_right:次のシリーズを読む
    Svelte で 3D 表示を行うライブラリ Threlte #4: シーンコントロールツールセット Theatre.js for Threlte

    0
    1
    0

    Register as a new user and use Qiita more conveniently

    1. You get articles that match your needs
    2. You can efficiently read back useful information
    3. You can use dark theme
    What you can do with signing up
    Sign up Login
    0
    1