gltf-rs / gltf

A crate for loading glTF 2.0
Apache License 2.0
517 stars 118 forks source link

Draco Compression #242

Open zicklag opened 5 years ago

zicklag commented 5 years ago

I'm using this crate for the Arsenal game engine I'm building and Draco compression is something that I'm going to want to support in the future. @bwasty suggested that I open an issue over here to discuss it.

My thought was that we could create Rust bindings for the C++ Draco library and then use that, but I'm not sure how difficult that would be. I haven't done any investigation into the API or what that would involve.

bwasty commented 5 years ago

I see 3 things to discuss:

  1. Wrap C++ library or implement spec We could either wrap draco like we did with mikktspace originally (separate crate+repo), or implement the Draco Bitstream Specification in Rust. The latter looks like way more work though... The draco library only offers a C++ interface, so binding might be a bit more complicated - rust-bindgen seems like the standard way to do it -> Generating Bindings to C++
  2. Importing The support for Draco should be a non-default Cargo feature (at least if we wrap the C++ library - looks like a big dependency and needs a C++ compiler). For decoding there are several cases to consider (see also extension specification):

    • KHR_draco_mesh_compression in extensionsUsed: use draco if feature is active, otherwise use uncompressed data
    • KHR_draco_mesh_compression in extensionsRequired: use draco if feature is active, otherwise fail the import

    Ideally it should be transparent to the user - just activate the feature and the decompression happens automatically.

  3. Exporting Do we need it? It's less important since there are tools that can apply Draco compression afterwards (e.g. gltf-to-glb). Not sure how much more effort it would be...
alteous commented 5 years ago

My understanding of this extension is that it's designed to reduce the size of geometry so that there is less data to transmit over slow networks. Outside of this context I'm sceptical of its usefulness. We ought to support this extension eventually though. @bwasty summarises the discussion points well above.

Implementing the decompression algorithm in Rust sounds fun but probably not a good use of time. :smile:

zicklag commented 5 years ago

@bwasty, my thoughts:

  1. It seems like wrapping it would be the best option as long as it didn't turn into a mess somehow with the C++ bindings. That is unless there is just somebody that is motivated to implement it in Rust as that would obviously be nicer to have.
  2. That sounds good to me.
  3. It would be nice to be able to export, but I don't know that is something that the gltf crate would handle specifically. Right now exporters are kind of implemented manually, with the gltf crate handling the JSON while the application handles organizing the buffers, which makes sense. Maybe the app would just use a draco-rs crate to encode and decode the buffers and that would be handled separately from the gltf crate?

@alteous My take on it is that if I'm writing a game that will have hundreds of assets large and small, having Draco compression would be a reasonable step in reducing the packaged size of the game. If I can shave a large percentage of the size of the game off without suffering a loss of quality or performance, than that is definitely something I would want to do. Downloading mods for the game would also be a place that it might come in handy.

Granted, this is not something that I need very quickly as there are a lot of other things that are more important to get working first. It isn't absolutely critical, but I think it would be nice to have.

bwasty commented 4 years ago

I've played a bit with rust-bindgen since I was curious if C++ binding really works - result so far: https://github.com/bwasty/google-draco-rs/compare/master...develop Quite annoying to setup and get to link successfully and now I'm getting weird segfaults on cargo test (the pointer to the buffer is suddenly 0x0 on the C++ side). I guess writing a minimal C-wrapper might help... (I don't know how passing a pointer can fail like that except that the bindings are somehow wrong).

Veykril commented 4 years ago

I wouldn't mind looking into porting draco to rust, ive got some free time on my hands and this seems like a nice project idea.

Veykril commented 4 years ago

So I looked a bit into it and started working on it in this repo but it's gonna be a tough job given that the spec and the C++ implementation both arent too easy to understand for me at least(and they arent even completely equal it seems). So it'll take a lot of time problaby and I wont be able to promise that im gonna finish this 😄

alteous commented 4 years ago

@bwasty: I wouldn't publish as google-draco because of the trademark. I suggest draco-compression instead.

zellski commented 4 years ago

Hey all, just starting to take a closer look at this very interesting project. Came across this issue and wanted to drop in a comment on the fundamental usefulness of Draco. Apologies in advance if it's all kind of obvious!

One caveat, though –– check out meshoptimizer and its bundled tool, gltfpack. It also exists as a crate. Here's a relevant quote from the documentation:

While several mesh compression libraries, like Google Draco, are available, they typically are designed to maximize the compression ratio at the cost of preserving the vertex/index order (which makes the meshes inefficient to render on GPU) or decompression performance. Additionally they frequently don't support custom game-ready quantized vertex formats and thus require to re-quantize the data after loading it, introducing extra quantization errors and making decoding slower.

zicklag commented 4 years ago

@zellski thanks for the input! I looked at meshoptimizer and it looks like it is more suited to the needs that I have. I was planning on using it for a game's built-in assets, not necessarily ones sent over the network, so while transfer size is still important, the graphics performance is more important. The fact that meshoptimizer focuses on the graphics performance while still providing storage/transfer size optimizations seems perfect. And it already has Rust bindings which is a huge bonus. It seems like its a win over Draco for my purposes.