Addressing ThreeJS’s load time: smaller meshes = faster loader (OpenCTM 2?)

Description of the problem

The main issue with Three.JS these days I find is the slow mesh load time. This is caused primary by the size of the assets – meshes and images. We’ve recently done an analysis of the ThreeJS binary format and compared it with OpenCTM. We have found on average that OpenCTM meshes are 2x to 5x smaller than ThreeJS’s binary format gzipped (e.g. default browser compression) — which translates into huge improvements to start-up time.

The reason that OpenCTM produces smaller files is because it uses a novel compression method (data re-ordering, and data precision reduction, and other neat things) combined with the superior LZMA compression method (via LZMA.js). I have checked and LZMA is only responsible for about 1/2 to 1/3 of OpenCTM’s superior compression ratio, thus the data massaging that OpenCTM does is pretty valuable.

There are issues through with OpenCTM though that prevent it from being a replacement for ThreeJS’s binary format: it is no longer maintained (hasn’t been updated in 4 years), its index channel doesn’t support non-triangle index data (no support for non-indexed vertices, indexed triangle fans, indexed polygons, points, indexed lines), it doesn’t support submeshes (i.e. ranges for multi-materials), it doesn’t support arbitrary extra channels (only 4 x float channels.)

Arbitrary extra channels needed for minimum parity with ThreeJS’s binary format are:

  • skin weights (4x float) – supported
  • skin bone indices (4 x index)
  • morph positions (3 x float)
  • morph normals (3 x float)
  • colors (3 x float)
  • bones (16 x float)
  • point sizes (1 x float)
  • tangents/binormals (4 x float) – supported

I was wondering if it may be possible to write a new advanced compressed format that exposes the data transforms that improve compression (but maybe doesn’t require LZMA? so that one can use brotli, etc.) but doesn’t have extremely inflexible hard coded limitations that the current approach has.

My feeling is that one could create a new file format, one that isn’t based on any hard coding of the fields. Thus we do not have to anticipate its exact uses, rather we just have to make a flexible API.

Thus I wouldn’t hard code any particular fields (indices, vertices, normals, colors, etc.) but instead just allow for names and raw data types (Float32Array, UInt8Array, etc.) along with the stride and hints that enable optimal compression. These hints wouldn’t be perscriptive of the compression method (.e.g inflexible) but rather would be descriptive of the data (let the library make the best choice of compression method, if any) — and thus it is up to the library to figure out which compression and data transforms to use to achieve the high compression of OpenCTM. When reading, one would just read by name and you’d get the uncompressed data back – the data format will completely specify how to read the data and untransform it.

We could have a set of prebuild hints for the standard fields (normal, position, skin weights, indices, etc.), thus using it in a basic way would not require any real understanding of its details.

This would ensure we can save anything we want in this format, even if we do not anticipate it now. We could likely store animations in this file format in the future. I would write the compressor and decompressor in JavaScript but I would keep the compressor as simple and small as possible so that it can be easily ported to other languages like OpenCTM was.

Further details: At the bottom of this page is the specifications of the OpenCTM file format and its API: http://openctm.sourceforge.net/?page=about

If @tschw wanted a challenge that makes use of your skills that greatly moves this project forward, at least from my perspective (you’d have to check with @mrdoob), this would be it. I think that the design given above would have long-term viability and it really does address all of OpenCTM’s many current shortcomings. I would have wide usefulness outside of ThreeJS as well.

Three.js version
  • Dev
  • r76
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • Linux
  • Android
  • IOS
Hardware Requirements (graphics card, VR Device, …)

Author: Fantashit

4 thoughts on “Addressing ThreeJS’s load time: smaller meshes = faster loader (OpenCTM 2?)

  1. OBJ, JSON, DAE and all the other TEXT files are not suitable for online projects.
    One huge text file and dozens of image files used as textures is the last thing you want to download.
    The best option for THREE.js is SEA3D.
    https://github.com/sunag/sea3d
    Binary format and LZMA compression.

Comments are closed.