Again an extremely unreadable title

The Ultimate Expression

magnum-sceneconverter \
    -P StbResizeImageConverter -p size="64 64" \
    -M MeshOptimizerSceneConverter -m simplify,simplifyTargetIndexCountThreshold=0.01 \
    -C GltfSceneConverter -c imageConverter=BasisKtxImageConverter \
    apartment_0_stage.glb apartment_0_stage.decimated.basis.glb

The Ultimate Expression

magnum-sceneconverter \
    -P StbResizeImageConverter -p size="64 64" \
    -M MeshOptimizerSceneConverter -m simplify,simplifyTargetIndexCountThreshold=0.01 \
    -C GltfSceneConverter -c imageConverter=BasisKtxImageConverter \
    apartment_0_stage.glb apartment_0_stage.decimated.basis.glb

Uhh…

The Ultimate Expression

magnum-sceneconverter \
    -P StbResizeImageConverter -p size="64 64" \
    -M MeshOptimizerSceneConverter -m simplify,simplifyTargetIndexCountThreshold=0.01 \
    -C GltfSceneConverter -c imageConverter=BasisKtxImageConverter \
    apartment_0_stage.glb apartment_0_stage.decimated.basis.glb

Uhh…

Well, let’s look at it piece by piece.

The Ultimate Expression

magnum-sceneconverter \
    -P StbResizeImageConverter -p size="64 64" \
    -M MeshOptimizerSceneConverter -m simplify,simplifyTargetIndexCountThreshold=0.01 \
    -C GltfSceneConverter -c imageConverter=BasisKtxImageConverter \
    apartment_0_stage.glb apartment_0_stage.decimated.basis.glb

Uhh…

Well, let’s look at it piece by piece.

No guarantee that it will be any less overwhelming.

Conversion between *.glb and *.gltf

For easier inspection or, conversely, making files self-contained. Supersedes the brittle old glbf2gltf.py scripts.

magnum-sceneconverter file.glb file.gltf
magnum-sceneconverter file.gltf file.glb

Images are implicitly bundled in a *.glb and external in a *.gltf, but don’t have to be:

magnum-sceneconverter file.gltf file.glb -c bundleImages=false

“One-click” Basis-ifying of glTF files

Encodes all images in the glTF as KTX2+Basis files referenced using the KHR_texture_basisu extension, with UASTC enabled:

magnum-sceneconverter file.glb file.basis.uastc.glb \
    -c imageConverter=BasisKtxImageConverter,imageConverter/uastc=true

De-Basis-ifying glTF files

A lossy operation, of course.

magnum-sceneconverter file.basis.uastc.glb file.glb \
    -c imageConverter=PngImageConverter

For when you need to inspect with a 3rd party tool that’s not as great as Magnum.

Producing Basis-encoded glTFs with a PNG fallback

… and having only Basis files in the *.glb and PNGs externally, so they’re not an implicit dead weight.

magnum-sceneconverter file.glb file.basis+fallback.glb \
    -c imageConverter=BasisKtxImageConverter,imageConverterFallback=PngImageConverter,bundleImageFallback=false

That’s where total control over the pipeline pays off.

Producing Basis-encoded glTFs with a PNG fallback

{
  
  "extensionsUsed": [
    "KHR_texture_basisu"
  ],
  "extensionsRequired": [],
  "textures": [
    {
      "extensions": {
        "KHR_texture_basisu": {
          "source": 0
        }
      },
      "source": 1
    }
  ],
  "images": [
    {
      "mimeType": "image/ktx2",
      "bufferView": 14
    },
    {
      "uri": "CesiumMilkTruck.basis+fallback.0.png"
    }
  ]
}


  • Magnum opens this and uses the Basis-compressed image
    • It won’t even load the external PNG file
  • Blender can open this as well
    • Ignores the Basis image and falls back to the PNG

Other possibilities

Yes.

Performing an operation on all images before saving them

The -P / --image-converter option allows to chain an image-to-image converter before all images are converted to files.

  • Such as a resize
  • Or a cheap DXT texture compression if Basis is too slow to encode, packed into a KTX2 container and referenced via the KHR_texture_ktx extension:
magnum-sceneconverter file.glb file.dxt.ktx.glb \
    -P StbResizeImageConverter -p size="512 512" \
    -P StbDxtImageConverter -p highQuality \
    -c imageConverter=KtxImageConverter,experimentalKhrTextureKtx

Yes, the image converters can be chained.

Performing an operation on all meshes before saving them

Remember MeshOptimizerSceneConverter?

  • Optimizes for GPU vertex cache
  • For overdraw and vertex fetch
  • And all that while capable of reducing the mesh to, for example, a 1/100th
magnum-sceneconverter file.glb file.decimated.glb \
    -M MeshOptimizerSceneConverter \
    -m simplify,simplifyTargetIndexCountThreshold=0.01

The -M / --mesh-converter option can be chained too.

Sorry but all these the options are confusing

magnum-sceneconverter --info-converter \
    -C MeshOptimizerSceneConverter
Plugin name: MeshOptimizerSceneConverter
Features:
  ConvertMesh
  ConvertMeshInPlace
Configuration:
  # Mesh simplification, disabled by default as it's a destructive
  # operation. The simplifySloppy option is a variant without
  # preserving original mesh topology, enable either one or the other.
  simplify=false
  simplifySloppy=false
  simplifyTargetIndexCountThreshold=1.0
  simplifyTargetError=1.0e-2
  
  # Vertex cache optimization, operates on the index buffer only
  optimizeVertexCache=true
  
  # Overdraw optimization, operates on the index buffer and
  # additionally requires the mesh to provide (read-only) per-vertex
  # positions
  optimizeOverdraw=true
  optimizeOverdrawThreshold=1.05
magnum-imageconverter --info-converter \
    -C StbResizeImageConverter
Plugin name: StbResizeImageConverter
Features:
  Convert2D
  Convert3D
Configuration:
  # Target width and height, separated by a space. Required.
  size=
  
  # How neighboring pixel values are retrieved on image edges.
  # Valid values are:
  #  - clamp -- as if the edge pixels were extended
  #  - wrap -- as if the image was repeated
  #  - reflect -- as if the image was repeated and reflected
  #  - zero -- uses zero values for out-of-bounds pixels
  edge=clamp
  
  # Sampling filter. Valid values are:
  #  - box -- a trapezoid w/1-pixel wide ramps, same result as
  #    box for integer scale ratios
  #  - triangle -- on upsampling, produces same results as
  #    bilinear texture filtering

Don’t worry, I got you.

Reminder: inspecting asset contents

The --info options are still there, now including also total data sizes.

magnum-imageconverter --info apartment_0_stage.glb
Scene 0:
  Bound: 172 objects @ UnsignedInt (10.4 kB)
  Fields:
    Parent @ Int, 172 entries
    ImporterState @ Pointer, 172 entries
    Translation @ Vector3, 171 entries
    Rotation @ Quaternion, 171 entries
    Scaling @ Vector3, 171 entries
    Mesh @ UnsignedInt, 31 entries
    MeshMaterial @ Int, 31 entries
Total scene data size: 10.4 kB
…
Mesh 29 (referenced by 1 objects): doorFrame
  Level 0: 396 vertices @ Triangles (3405.2 kB)
    Normal @ Vector3, offset 1564056, stride 12
    Position @ Vector3, offset 1559304, stride 12
    Tangent @ Vector4, offset 2634984, stride 16
    TextureCoordinates @ Vector2, offset 3474840, stride 8
    396 indices @ UnsignedShort, offset 0, stride 2 (0.8 kB)
Mesh 30 (referenced by 1 objects): floor2_walls
  Level 0: 936 vertices @ Triangles (3405.2 kB)
    Normal @ Vector3, offset 33984, stride 12
    Position @ Vector3, offset 22752, stride 12
    Tangent @ Vector4, offset 1610616, stride 16
    TextureCoordinates @ Vector2, offset 2674248, stride 8
    TextureCoordinates @ Vector2, offset 2681736, stride 8
    936 indices @ UnsignedShort, offset 0, stride 2 (1.8 kB)
Total mesh data size: 105689.9 kB
…
2D image 41 (referenced by 1 textures):
  Level 0: {2048, 2048} @ RGBA8Unorm (16384.0 kB)
2D image 42 (referenced by 1 textures):
  Level 0: {2048, 2048} @ RGBA8Unorm (16384.0 kB)
2D image 43 (referenced by 1 textures):
  Level 0: {2048, 2048} @ RGB8Unorm (12288.0 kB)
2D image 44 (referenced by 1 textures):
  Level 0: {2048, 2048} @ RGB8Unorm (12288.0 kB)
Total image data size: 1386496.0 kB

GltfSceneConverter — implementation progress

  • Meshes shipped
    • “Native” mesh views not started useful for Blender export
  • 2D images and textures shipped
    • Multi-level, 2D array images and KHR_texture_ktx underway needed by batch renderer
  • Basic materials shipped
  • Basic scenes underway needed by batch renderer useful for Blender export
    • Custom scene fields underway needed by batch renderer
  • Lights and cameras not started useful for batch renderer useful for Blender export
  • Animations not started useful for Blender export
  • Integration into magnum-sceneconverter underway useful for everyone
  • Python scripting not started

Enough already