Draco-Compressed gltf escape character handling

Hi guys, I’m new to three.js and testing it with an building scenario, and my gltf node names might contain escape characters such as inches (e.g 1"-pipe). Since the model might be relatively large, I’ve thought to compress it with draco. However, the draco-compressed model seems to be corrupted and failed to load with three.js loader.

Given that I can’t share the original file, I tried to reproduce it with other models.

As shown below, I’ve modified a model node with " character and three.js editor can load it and parse the node name correctly.

However, after compressing the model with draco_transcoder, three.js editor can’t load it and returned with the following error message.

image

Which seems to me that it’s due to unescaped node name.
image

I have zero knowledge with C++ and wondering if this is and Draco issue or am I missing something here?

Or, escape characters should be avoided by all cost for gltf assets? If not, what’s the proper way to handle it?

Thanks in advance

node_with_special_char.zip (96.8 KB)
draco_compressed_node_with_special_char.rar (26.8 KB)

It sounds like this must be a bug in their transcoding tool. I’d recommend using something else to Draco-compress the file, like any of these:

Hi @donmccurdy, thanks for the quick reply and fantastic package glTF-Transform.

Both gltf-pipeline and glTF-Transform worked and can be properly loaded.

Based on you reply, please bear with me with a few questions just to make sure i’ve correct knowledge on draco and gltf assets:

  1. Characters such as \, " can be used in gltf assets as long as it is properly escaped and shouldn’t be a problem?

  2. Draco is merely an compression algorithm and both gltf-Transform/gltf-pipeline are just reimplementation of it in ts/js, is that correct? Yet I’ve noticed that the gltf-transform has less compression rate (result in 35kb) compared to gltf-pipeline(29kb, closer to the result of draco_transcoder). I’m wondering what might be the rationale?

Characters such as \, " can be used in gltf assets as long as it is properly escaped and shouldn’t be a problem?

Right! The glTF specification definitely allows these characters, and we’ve made sure to support that and more in the three.js implementation. I’m inclined to guess that maybe the Draco library authors didn’t use a very robust JSON serialization library here, their glTF transcoder is a newer feature that I haven’t tried myself yet.

Draco is merely an compression algorithm and both gltf-Transform/gltf-pipeline are just reimplementation of it in ts/js, is that correct?

Yes — both of these tools are using the official Draco compression library (there’s only one implementation of that), but they’re handling the glTF container themselves. The Draco-compressed geometry gets embedded in the glTF container alongside glTF’s materials and other definitions.

I’m not sure why the compression rate would differ between the two; there are some parameters you can adjust on both tools. I’d say 6kb is a pretty small difference here, by comparison the Draco decoder itself is 100–200 kb, and that 6kb might just come down to something minor like internal formatting, I haven’t seen 20% differences on larger files. Happy to take a closer look if you want to post the files too.

Yes — both of these tools are using the official Draco compression library (there’s only one implementation of that), but they’re handling the glTF container themselves.

If I’ve understand correctly, the implementation you’re referring to is the official released draco3d/draco3dgltf in npm, where gltf-transform used draco3dgltf, and gltf-pipeline used draco3d, then both tools implement their own gltf container to work with draco? Thanks for helping me clarifying the concept.

As for the conversion rate issue, I’m using model as attached. I’ve compressed the model with both tools without manipulating any parameters. And the benchmark is as follows:

  • Source: .gltf (5kb) + .bin (100kb) + .png (16kb)
  • gltf-transform compressed: .glb(35kb)
  • gltf-pipeline compressed: .glb(29kb)

I’ve tried with other larger models(but I’m not allowed to share them, sorry for that):

  • Source: .gltf (11mb) + .bin (109mb)
  • gltf-transform compressed: .glb(15.4mb)
  • gltf-pipeline compressed: .glb(10.9mb)

Looks like as the gltf file size grows, such gap might increase, not sure what caused that.
Definitely will find time to look into it myself as well.

Thanks again for your massive help.

gltf.zip (96.8 KB)
compressed_with_gltf_pipeline.glb (28.2 KB)
compressed_with_gltf_transform.glb (34.4 KB)

UPDATE:

I’ve reported the issue to the draco repo, and has been resolved by the draco team.

It looks like the difference between the two is in the default values for the Draco compression options. You can get the same results from glTF Transform by overriding the quantization precision and encoding speed/quality settings:

gltf-transform draco input.gltf output.glb \
  --quantize-position 11 \
  --quantize-normal 8 \
  --quantize-texcoord 10 \
  --encode-speed 0 \
  --decode-speed 0

I’m not fully sure how the encode/decode speeds map to glTF Pipeline’s options, but the quantization bit choices above are copied from their defaults.

You can knock another 10-15 kilobytes off by welding, simplifying, WebP-compressing, etc. Usually the Draco compression step should happen last.

gltf-transform weld input.glb output.glb
gltf-transform simplify input.glb output.glb --ratio 0.1 --error 0.001
gltf-transform webp input.glb output.glb 

Duck-weld-simplify-webp-draco.glb (15.1 KB)