This is the code repository for Unifi3D, a unified framework for evaluating the reconstruction and generation performance of 3D representations. We compare these representations based on multiple criteria: quality, computational efficiency, and generalization performance. Beyond standard model benchmarking, our experiments aim to derive best practices over all steps involved in the 3D generation pipeline, including preprocessing, mesh reconstruction, compression with autoencoders, and generation. Our findings highlight that reconstruction errors significantly impact overall performance, underscoring the need to evaluate generation and reconstruction jointly.
Details (Click to expand)
The Unifi3D repository has the following structure:
Unifi3D # The top-level Unifi3D repository.
| #
├── unifi3d # Core module regrouping the main functionalities of Unifi3D
| | #
| ├── data # Torch dataset & sampler classes
| |
| ├── losses # Loss functions including method specific functions.
| | |
| │ ├── diffusion #
| | └── autoencoders #
| |
| ├── models # Relevant neural models and related submodules
| │ │ #
| │ ├── diffusion #
| │ ├── autoencoders #
| | └── modules # Representation, personalized network layers, or model componeents
| |
| ├── utils # Useful functions
| │ │ #
| │ ├── data #
| │ ├── evaluate #
| │ ├── logger #
| │ ├── rendering #
| │ ├── model #
| │ ├── triplane_utils #
| | └── scheduler #
|
├── configs # Hydra configs
| | #
| ├── data # Data configs
| ├── debug # Debugging configs
| ├── experiment # Experiment configs
| ├── extras # Extra utilities configs
| ├── hparams_search # Hyperparameter search configs
| ├── hydra # Hydra configs
| ├── local # Local configs
| ├── logger # Logger configs
| ├── model # Model configs
| ├── paths # Project paths configs
| ├── trainer # Trainer configs
| │ #
| ├── default.yaml # Config template
| ├── eval.yaml # Main config for evaluation
| ├── benchmark.yaml # Main config for benchmarking reconstruction
| ├── sample_diffusion.yaml # Main config for generation (inference)
| └── train.yaml # Main config for training
| #
├── checkpoints # Symbolic links to saved checkpoints in the format of *.safetensors.
| #
├── data # Torch dataset & sampler classes
│ ├── split_shapenet.csv # our train-test split of the ShapeNet dataset
│ ├── ShapeNetCore.v1 # original dataset (NOTE: to be downloaded)
│ └── shapenet_preprocessed # preprocessed dataset (NOTE: to be created)
|
├── docs # Additional documentation markdown files
| #
├── logs # Result of the training and evaluation runs
| #
├── media # Pictures and other relevant media resources of this repository
| #
├── scripts # Python scripts and Jupyter notebooks
| | #
| ├── accelerate # Main training scripts
| ├── data # Dataset preprocessing scripts
| ├── evaluate # Scripts for evaluation and creating tables and plots
| ├── diffusion # Diffusion inference script
| └── utils # Useful general scripts
│ #
├── tests # Unit tests
│ #
├── .project-root # File for inferring the position of project root directory
├── .python-version # Contains the exact version of python used in the project
│ #
├── requirements_<platform>.txt # File containing some of the main dependencies of the project by platform
├── LICENSE # License file
├── README.md # ReadMe file
└── setup.py # File for installing project as a package
Details (Click to expand)
We provide a bash script allowing users to automatically setup unifi3d and to create a suitable virtual environment for the project, connected to a specific and well tested version of python. This is the recommended way. Execute the script with:
chmod a+x setup_unifi3d.sh
./setup_unifi3d.sh
Note: Some components, such as dataset creation and user study scripts, require additional dependencies not installed by the setup script:
- Blender 4.1 (ensure it is available in your
PATH
)
For alternative installation methods (using venv, manual step-by-step setup, etc.), refer to our setup guide.
Details (Click to expand)
We use the ShapeNet dataset for our experiments. To enable different 3D generation approaches, we preprocess the data into point cloud, SDF etc. Details on generated datasets.
To preprocess the data, follow these steps:
- Download the ShapeNetCore.v1 dataset here.
- Once downloaded, place it in the
data
directory (there should be a folderdata/ShapeNetCore.v1
). - Install blender (if not already done) and add it to the
PATH
(see setup guide). - Run
python scripts/data/create_preprocessed_dataset.py --task_id 0 --num_tasks 1 data/shapenet_preprocessed
(Note: This can take a while. We recommend to distribute the work to multiple parallel jobs using a large number of CPU cores or multiple machines. Use the--task_id
and--num_tasks
to split the work for your parallel compute environment.)
This will save the preprocessed data in data/shapenet_preprocessed
.
Details (Click to expand)
-
Start by activating the
unifi3d
virtual environment:conda activate unifi3d
-
Setup an experiment parameter
.yaml
file in configs/experiment, for instancemy_great_experiment.yaml
. Within this file, set the parameters of your experiment. -
Run the trainer (used for both AE and diffusion training)
python scripts/accelerate/acc_train.py experiment=my_great_experiment
The training script should start automatically, instanciate a Trainer and a Logger based on the specifications of your experiment parameter file
my_great_experiment.yaml
. -
In case you are still in debug phase and with to see the crash logs, you may use the
HYDRA_FULL_ERROR=1
before your command::HYDRA_FULL_ERROR=1 python scripts/accelerate/acc_train.py experiment=my_great_experiment
-
For multi-GPU training, we rely on the hugging-face accelerate pipeline.
- You may start setting up your accelerate environment by creating an accelerate configuration file:
This will generate a
accelerate config
default_config.yaml
file in$HOME/.cache/huggingface/accelerate
which will be read byaccelerate
at the beginning of your training session. Simply follow the setup guide and set the number of GPUs according to your hardware. - Then on your multi-GPU mahcine or cluster session, you may run the distributed experiment using the following command:
accelerate launch scripts/accelerate/acc_train.py experiment=my_great_experiment
- Note that you can point to a specific config file to change the parameters of accelerate (e.g. for training on a different number of GPUs) using the
--config_file
flag:accelerate launch --config_file path/to/config/my_config_file.yaml scripts/accelerate/acc_train.py experiment=my_great_experiment
- You might also want to avoid using the
accelerate
config file for greater flexibility. In this case, you may simply use the--multi_gpu
flag:In this case, Accelerate will make some hyperparameter decisions for you, e.g., if GPUs are available, it will use all of them by default without the mixed precision.accelerate launch --multi_gpu scripts/accelerate/acc_train.py experiment=my_great_experiment
- For a complete list of parameters you can pass in, run:
Check the hugging-face documentation for more details.
accelerate launch -h
- You may start setting up your accelerate environment by creating an accelerate configuration file:
Currently, all config files for AE model training (i.e., using EncoderDecoderTrainer
) have the acc_
prefix, e.g. acc_shape2vecset_ae, while all diffusion models have the _diffuse
prefix, e.g. diffuse_sdf_ae_dit.
Most models were trained on 48 GB GPUs (e.g. single GPU with batch size 8 for SDF, Voxel, Triplane & Shap2vecset. DualOctree can be trained with larger batch sizes, Shap-E requires 80GB).
Example usage:
python scripts/accelerate/acc_train.py experiment=acc_triplane_ae
python scripts/accelerate/acc_train.py experiment=acc_shape2vecset_ae
python scripts/accelerate/acc_train.py experiment=acc_sdf_ae
python scripts/accelerate/acc_train.py experiment=acc_dualoctree_vae
python scripts/accelerate/acc_train.py experiment=acc_shap_e_ae
When training a diffusion model, you need to specify the checkpoint of the pretrained autoencoder. For example, train a DiT to denoise an encoded SDF with
python scripts/accelerate/acc_train.py experiment=diffuse_sdf_dit net_encode.ckpt_path=/path/to/ckpt/model.safetensors
Or for DualOctree with VAE and Unet:
python scripts/accelerate/acc_train.py experiment=diffuse_doctree_vae_unet net_encode.ckpt_path=/path/to/ckpt/model.safetensors
- Enable tunneling with your desired terminal and set the destination server to
127.0.0.1:43800
:cd ~/unifi3d/ aim up
Details (Click to expand)
Do not forget to activate the unifi3d
virtual environment before running any script:
conda activate unifi3d # if using miniforge
# OR
# source unifi3d_venv/bin/activate # if using pyenv/venv
Example usage (start from repository root):
python scripts/benchmarking.py benchmark=shape2vecset ae_id=ae # ae_id is one of ae, vae or vqvae
python scripts/benchmarking.py benchmark=sdf ae_id=ae
python scripts/benchmarking.py benchmark=voxel ae_id=vae
This command takes the preprocessed ShapeNet objects, encodes and decodes them with the model, and saves the result in the outputs
folder. The results include
results.csv
: Table with metric results and runtimes per samplemesh_comp.obj
: Obj file with two rows of objects, one row showing the ground truth meshes and the back row showing the reconstructed meshes (only the first few to avoid large files)
There is a checkpoint path specified in these benchmark
configs, but you can overwrite it to test your own checkpoint, e.g. with
python scripts/benchmarking.py benchmark=sdf ckpt_path=/path/to/checkpoint
python scripts/benchmarking.py benchmark=voxel ckpt_path=/path/to/checkpoint
If you used different arguments for training the model, you need to specify those as well:
python scripts/benchmarking.py benchmark=shape2vecset ckpt_path=/path/to/checkpoint net_encode.layer_norm_encoding=true
Quick testing mode
Some metrics take quite long to compute, and sometimes this script can be helpful to quickly check whether a trained model works. For testing, set the following parameters in the benchmark config:
- metrics: testing # will only compute two metrics (and sample less points to make them faster)
plot_mesh: True
limit: 10 # will only test on 10 meshes instead of the whole dataset
Collect all results and save latex tables
To collect all results from all representations, after running the benchmarking script for each of them, there is a script that load the result files and combines them:
python scripts/evaluate/make_reconstruction_table.py
This will directly print the latex code for the table. The output folders for each representation, and their name to display in the table, are currently hardcoded in the script.
Example usage (start from repo root):
python scripts/diffusion/benchmark_gen.py sample=sdf ae_id=ae diff_id=dit cat_id=Chair
python scripts/diffusion/benchmark_gen.py sample=voxel ae_id=ae diff_id=dit cat_id=Chair
python scripts/diffusion/benchmark_gen.py sample=shape2vecset ae_id=ae diff_id=dit cat_id=Chair
These sample
configs include paths to the currently best checkpoints. You can use your own AE and diffusion checkpoints by setting the corresponding arguments:
python scripts/diffusion/benchmark_gen.py sample=sdf_vqvae_dit ckpt_path=/change/to/your/diffusion/model.safetensors net_encode.ckpt_path=/change/to/your/ae/model.safetensors
Outputs are saved to the output_path
specified in the config file. The folder will contain the following outputs:
results.csv
: Table with runtimes and metrics per samplegenerated_samples
: Folder with all the obj files for the generated meshesmetrics.json
: Json file with the distributional metrics (Cov, MMD, 1-NNA)
Computing the metrics for data that was already generated
If you already have a folder with generated samples, and just want to run the generated metrics on it, there is a script that uses a config file and only computes the distribution metrics:
python scripts/evaluate/compute_uncond_gen_metrics.py sample=sdf_vqvae_dit
Again, the metrics are saved in output_path/metrics.json
Collect all results and save latex tables
To collect all results from all representations, after running the benchmarking script for each of them, there is a script that load the result files and combines them:
python scripts/evaluate/make_generation_table.py
This will directly print the latex code for the table. The output folders for each representation, and their name to display in the table, are currently hardcoded in the script.
We show in our paper that the metrics for unconditional generation require sufficient data to compute. This experiment computes these metrics on the test set of ShapeNet and compare to the train set as a reference, which should result in perfect scores. There are two scripts for computing the unconditional metrics on the train and test split of Shapenet.
scripts/evaluate/ground_truth_uncond_metrics_compute.py
scripts/evaluate/ground_truth_uncond_metrics_plot.py
You can get a description of the parameters by calling the scripts with --help
.
Details (Click to expand)
We use Hydra and Optuna to provide key-in-hand hyperparameter optimization capability.
-
As for the training and evaluation pipelines, make sure that the
unifi3d
virtual environment is activated:conda activate unifi3d
-
Setup an experiment parameter
.yaml
file in configs/experiment, for instanceacc_voxel_vqvae.yaml
. Within this file, set the parameters of your experiment. -
Setup an optuna sweeper parameter
.yaml
file in configs/hparams_search, for instanceacc_voxel_vqvae_optuna.yaml
. Within this file, set the hyperparameters you wish to optimize, for instance the learning rate or the batch size. You may use the provided template as a starting point. -
For multi-GPU hyperparameter optimisation, we rely on the hydra ray launcher pluggin to distribute the jobs -- with the parameters sampled by optuna -- to each GPU. In practice you may simply set the value of the
num_parallel_process
parameter to the number of available GPUs. You may use the provided parallel template as a starting point. -
Run the optuna hyperparameter optimizer:
python scripts/accelerate/acc_train.py hparams_search=acc_voxel_vqvae_optuna_parallel experiment=acc_voxel_vqvae
The training script should start automatically, instanciate a Trainer following the specifications of the Optuna parameter search algorithm, set in
acc_voxel_vqvae_optuna_parallel.yaml
. -
In case you are still in debug phase and with to see the crash logs, you may use the
HYDRA_FULL_ERROR=1
before your command:HYDRA_FULL_ERROR=1 python scripts/accelerate/acc_train.py hparams_search=acc_voxel_vqvae_optuna_parallel experiment=acc_voxel_vqvae
Details (Click to expand)
There are three steps:- Prepare the data
This requires blender 4.1 to be in the PATH
python scripts/user_study/prepare_user_study_data.py output_dir=/path/to/output_dir
- Collect data from users
Run
python scripts/user_study/user_study.py /path/to/output_dir
Share the link
- Compute scores
Open URL
this will generate user_results/csv_data/user_study_pairwise_prefs.csv
. Using the download button is not necessary.
Run
python scripts/evaluate/compute_elo_scores.py --data_dir user_results/csv_data/user_study_pairwise_prefs.csv --exp_dir XXXX --methods doctree_vae_unet_champion sdf_ae_dit voxel_ae_unet shape2vecset_ae_dit shap_e_ae_dit triplane_ae_unet
Details (Click to expand)
Please check the contribution guidelines.
Details (Click to expand)
As most research projects, Unifi3D stands on the shoulders of giants. Here are some of them:
Relevant Code Frameworks
Details (Click to expand)
Part of the code was inspired by the following repositories. We thank the authors of these projects for their great work.
@article{unifi3d,
title={{Unifi3D: A Study on 3D Representations for Generation and Reconstruction in a Common Framework}},
author={Wiedemann, Nina and Liu, Sainan and Leboutet, Quentin and Gao, Katelyn and Ummenhofer, Benjamin and Paulitsch, Michael and Yuan, Kai},
journal={Transactions on Machine Learning Research},
year={2025},
url={https://openreview.net/forum?id=GQpTWpXILA},
}