Awesome
Draco 3D Data Compression Unity Package
Unity package that integrates the Draco 3D data compression library within Unity.
Following build targets are supported
- WebGL
- iOS (arm64 and armv7a)
- Android (x86, arm64 and armv7a)
- Windows (64 and 32 bit)
- Universal Windows Platform (x64,x86,ARM,ARM64)
- macOS (Apple Silicon an Intel)
- Linux (64 bit)
- Lumin / Magic Leap
Note: Burst support is broken on iOS builds at the moment. Please deactivate Burst AOT in the project settings until this is resolved.
Installing
The easiest way to install is to download and open the Installer Package
It runs a script that installs the Draco 3D Data Compression Unity Package via a scoped registry. After that it is listed in the Package Manager and can be updated from there.
<details><summary>Alternative: Install via GIT URL</summary>You have to manually add the package's URL into your project manifest
Inside your Unity project there's the folder Packages
containing a file called manifest.json
. You have to open it and add the following line inside the dependencies
category:
"com.atteneder.draco": "https://github.com/atteneder/DracoUnity.git",
It should look something like this:
{
"dependencies": {
"com.atteneder.draco": "https://github.com/atteneder/DracoUnity.git",
"com.unity.package-manager-ui": "2.1.2",
"com.unity.modules.unitywebrequest": "1.0.0"
...
}
}
Next time you open your project in Unity, it will download the package automatically. You have to have a GIT LFS client (large file support) installed on your system. Otherwise you will get an error that the native library file (dll on Windows) is corrupt. There's more detail about how to add packages via GIT URLs in the Unity documentation.
</details>Using
Mesh result
Minimalistic way of loading a draco file (source):
public class DracoDemo : MonoBehaviour {
public string filePath;
async void Start() {
// Load file into memory
var fullPath = Path.Combine(Application.streamingAssetsPath, filePath);
var data = File.ReadAllBytes(fullPath);
// Convert data to Unity mesh
var draco = new DracoMeshLoader();
// Async decoding has to start on the main thread and spawns multiple C# jobs.
var mesh = await draco.ConvertDracoMeshToUnity(data);
if (mesh != null) {
// Use the resulting mesh
GetComponent<MeshFilter>().mesh= mesh;
}
}
}
Using MeshDataArray
Starting with Unity 2020.2 you can create Meshes efficiently via MeshDataArray
.
The important difference is that instead of returning a Mesh
directly, it just configures the MeshData
properly and fills its buffers. It's up to the user to:
- Create the
Mesh
instance(s) - Apply the data via
Mesh.ApplyAndDisposeWritableMeshData
- In case the mesh had bone weight data, apply and dispose those as well (optional extra step)
Here's an examply how to do this (source):
public class DracoDemoMeshData : MonoBehaviour {
public string filePath;
public bool requireNormals;
public bool requireTangents;
async void Start() {
// Load file into memory
var fullPath = Path.Combine(Application.streamingAssetsPath, filePath);
var data = File.ReadAllBytes(fullPath);
// Convert data to Unity mesh
var draco = new DracoMeshLoader();
// Allocate single mesh data (you can/should bulk allocate multiple at once, if you're loading multiple draco meshes)
var meshDataArray = Mesh.AllocateWritableMeshData(1);
// Async decoding has to start on the main thread and spawns multiple C# jobs.
var result = await draco.ConvertDracoMeshToUnity(
meshDataArray[0],
data,
requireNormals, // Set to true if you require normals. If Draco data does not contain them, they are allocated and we have to calculate them below
requireTangents // Retrieve tangents is not supported, but this will ensure they are allocated and can be calculated later (see below)
);
if (result.success) {
// Apply onto new Mesh
var mesh = new Mesh();
Mesh.ApplyAndDisposeWritableMeshData(meshDataArray,mesh);
// If Draco mesh has bone weigths, apply them now.
// To get these, you have to supply the correct attribute IDs
// to `ConvertDracoMeshToUnity` above (optional paramters).
if (result.boneWeightData != null) {
result.boneWeightData.ApplyOnMesh(mesh);
result.boneWeightData.Dispose();
}
if (result.calculateNormals) {
// If draco didn't contain normals, calculate them.
mesh.RecalculateNormals();
}
if (requireTangents) {
// If required (e.g. for consistent specular shading), calculate tangents
mesh.RecalculateTangents();
}
// Use the resulting mesh
GetComponent<MeshFilter>().mesh = mesh;
}
}
}
Details and where to go next
See the signatures of all DracoMeshLoader.ConvertDracoMeshToUnity
variants to see all options available.
The examples above and more can be found in the DracoUnityDemo project.
Troubleshooting - Missing code signing
The binary libraries used in this package are not code-signed. macOS in particular will not let you load the ktx_unity.bundle
for that reason (see issue).
Here's the steps to make it work on macOS
- When you first open a project with DracoUnity (or add the package), you get prompted to remove the "broken" ktx_unity.bundle. Don't do it and click "cancel" instead.
- Open the macOS "System Preferencess" and go to "Security & Privacy". At the bottom of the "General" tab you should see a warning about ktx_unity.bundle. Click the "Allow anyways" button besides it.
- Restart Unity
- Now you get another, similar prompt (see step 1) with the third option "Open". Click it
- Now it should work (at least for development on your machine)
If you want to deploy your software using DracoUnity you either have to
- Wait until there is proper code-sign setup (watch this project or subscribe to the corresponding issue).
- Build your own library from the source draco repository (note that it's not the original Google repository) and sign it with your own credentials/Apple profile.
Origin
This project is a fork of the existing Unity integration
Differences
- Encoding support
- Can be integrated into Projects easily via Package Manager
- Is magnitudes faster due to
- Bulk memory copies instead of per vertex/index data copy
- Multi-threaded via C# Job system
- Burst compiler
- Using Unity's Advanced Mesh API
- Supports coordinate space conversion (from right-handed Y-up to Unity's left-handed Y-up by flipping the Z-axis; optional; required in glTF context)
- Supports single meshes with more than 65536 vertices (old split algorithm was broken)
- Supports loading joint index and joint weights for skinning
- Corrects tangents by re-calculating them if necessary
- Point cloud support
- Additional native libs and support for platforms
- WebGL
- iOS armv7(s) and arm64
- Windows 32-bit
- Linux 64-bit
- Android x86
- Universal Windows Platform (x64,x86,ARM,ARM64)
- macOS Apple Silicon
Support
Like this demo? You can show your appreciation and ...
Develop
To develop this package, check out the repository and add it as local repository in the Unity Package Manager.
Build Draco library
The native libraries are built via CI in this GitHub action
Look into the YAML file to see how the project is built with CMake.
License
Copyright (c) 2019 Andreas Atteneder, All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use files in this repository except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Third party notice
Builds upon and includes builds of Google's Draco 3D data compression library (released under the terms of Apache License 2.0).