vibephysics 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vibephysics-0.2.2/src/vibephysics.egg-info → vibephysics-0.2.4}/PKG-INFO +100 -84
- {vibephysics-0.2.2 → vibephysics-0.2.4}/README.md +99 -83
- {vibephysics-0.2.2 → vibephysics-0.2.4}/pyproject.toml +1 -1
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/__init__.py +1 -1
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/mapping/__init__.py +2 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/mapping/colmap.py +2 -2
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/mapping/glomap.py +1 -1
- vibephysics-0.2.4/src/vibephysics/mapping/map_visual.py +285 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4/src/vibephysics.egg-info}/PKG-INFO +100 -84
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics.egg-info/SOURCES.txt +1 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/LICENSE +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/MANIFEST.in +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/setup.cfg +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/annotation/__init__.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/annotation/base.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/annotation/bbox.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/annotation/manager.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/annotation/motion_trail.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/annotation/point_tracking.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/camera/__init__.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/camera/base.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/camera/center.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/camera/following.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/camera/manager.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/camera/mounted.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/README.md +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/__init__.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/go2.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/ground.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/lighting.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/materials.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/objects.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/open_duck.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/physics.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/robot.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/trajectory.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/foundation/water.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/mapping/pipeline.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/mapping/utils.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/setup/__init__.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/setup/exporter.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/setup/gsplat.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/setup/importer.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/setup/scene.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics/setup/viewport.py +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics.egg-info/dependency_links.txt +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics.egg-info/entry_points.txt +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics.egg-info/requires.txt +0 -0
- {vibephysics-0.2.2 → vibephysics-0.2.4}/src/vibephysics.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vibephysics
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Physics simulation and annotation tools for Blender
|
|
5
5
|
Author-email: tsunyi <tsunyi@mimiaigen.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/yourusername/vibephysics
|
|
@@ -33,7 +33,105 @@ Requires-Dist: ruff; extra == "dev"
|
|
|
33
33
|
|
|
34
34
|
**A lightweight Blender physics simulation framework for creating realistic robot animations, rigid body physics, water dynamics, and comprehensive annotation tools — all running efficiently on CPU.**
|
|
35
35
|
|
|
36
|
-
##
|
|
36
|
+
## ⚙️ Installation (MacOS)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. Create environment
|
|
40
|
+
conda create -n vibephysics python=3.11
|
|
41
|
+
conda activate vibephysics
|
|
42
|
+
|
|
43
|
+
# 2. Install core package (includes COLMAP mapping & Blender simulation)
|
|
44
|
+
pip install vibephysics
|
|
45
|
+
|
|
46
|
+
# 3. (Optional) Install GLOMAP backend
|
|
47
|
+
# Linux users: refer to "Linux System Dependencies" below first
|
|
48
|
+
pip install git+https://github.com/shamangary/glomap.git
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 🐧 Linux (Ubuntu) System Dependencies
|
|
52
|
+
If you are on Linux and want to use the **GLOMAP** or **COLMAP** backends, you must install the following C++ development libraries to enable successful compilation:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
sudo apt-get update
|
|
56
|
+
sudo apt-get install -y \
|
|
57
|
+
libeigen3-dev \
|
|
58
|
+
libceres-dev \
|
|
59
|
+
libgoogle-glog-dev \
|
|
60
|
+
libboost-all-dev \
|
|
61
|
+
libsuitesparse-dev \
|
|
62
|
+
libsqlite3-dev \
|
|
63
|
+
libgflags-dev \
|
|
64
|
+
libfreeimage-dev \
|
|
65
|
+
libmetis-dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## ⚠️ Troubleshooting (Linker Errors)
|
|
69
|
+
If you are using **Anaconda** on Linux and see an error like `relocation R_X86_64_TPOFF32 ... can not be used when making a shared object`, it is due to a conflict with the Anaconda linker. Fix it by forcing the compiler to use the global-dynamic TLS model:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
export CXXFLAGS="$CXXFLAGS -fPIC -ftls-model=global-dynamic"
|
|
73
|
+
export CFLAGS="$CFLAGS -fPIC"
|
|
74
|
+
pip install git+https://github.com/shamangary/glomap.git
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 🗺️ Mapping & Reconstruction
|
|
78
|
+
|
|
79
|
+
VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
|
|
80
|
+
|
|
81
|
+
- **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
|
|
82
|
+
- **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
|
|
83
|
+
- **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
|
|
84
|
+
|
|
85
|
+
### 💻 1. Run Reconstruction (SfM)
|
|
86
|
+
|
|
87
|
+
You can run the SfM pipeline via shell script or Python API:
|
|
88
|
+
|
|
89
|
+
**Command Line:**
|
|
90
|
+
```bash
|
|
91
|
+
# Run GLOMAP pipeline (Fastest - Default)
|
|
92
|
+
./run_glomap.sh --image_path path/to/images
|
|
93
|
+
|
|
94
|
+
# Run COLMAP pipeline (Most Robust)
|
|
95
|
+
./run_glomap.sh --image_path path/to/images --engine colmap
|
|
96
|
+
|
|
97
|
+
# Advanced options
|
|
98
|
+
./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Python API:**
|
|
102
|
+
```python
|
|
103
|
+
from vibephysics import mapping
|
|
104
|
+
|
|
105
|
+
# Simple Usage (Directly run GLOMAP on a folder of images)
|
|
106
|
+
mapping.glomap_pipeline(image_path="path/to/images")
|
|
107
|
+
|
|
108
|
+
# COLMAP Incremental Pipeline
|
|
109
|
+
mapping.colmap_pipeline(image_path="path/to/images")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 🎨 2. Visualize in Blender
|
|
113
|
+
|
|
114
|
+
Load your reconstruction into Blender for inspection with colored point clouds and correct camera poses.
|
|
115
|
+
|
|
116
|
+
**Command Line:**
|
|
117
|
+
```bash
|
|
118
|
+
# Visualize a sparse model folder (containing cameras.bin, points3D.bin etc.)
|
|
119
|
+
./run_glomap_visual.sh --sparse path/to/sparse/0 --output result.blend
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Python API:**
|
|
123
|
+
```python
|
|
124
|
+
from vibephysics import mapping
|
|
125
|
+
|
|
126
|
+
# Load reconstruction directly into active Blender scene
|
|
127
|
+
mapping.load_colmap_reconstruction(
|
|
128
|
+
input_path="output/mapping_output/sparse/0",
|
|
129
|
+
point_size=0.03,
|
|
130
|
+
rotation=(-90, 0, 0) # Optional: global rotation
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 🎬 Simulation Results (`sh run_robot.sh`)
|
|
37
135
|
|
|
38
136
|

|
|
39
137
|
|
|
@@ -93,37 +191,6 @@ Perfect for researchers, animators, and robotics engineers who need physics simu
|
|
|
93
191
|
- **Open Duck**: We use the [Open Duck blender model](https://github.com/pollen-robotics/Open_Duck_Blender) as demo. We do not own the model. Please refer to the original github repo.
|
|
94
192
|
- **Unitree Go2**: We use the [Unitree Go2 USD model](https://huggingface.co/datasets/unitreerobotics/unitree_model). The model is auto-downloaded when running Go2 examples. We do not own the model.
|
|
95
193
|
|
|
96
|
-
## ⚙️ Installation
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
# Create and activate environment
|
|
100
|
-
conda create -n vibephysics python=3.11
|
|
101
|
-
conda activate vibephysics
|
|
102
|
-
|
|
103
|
-
# Install vibephysics
|
|
104
|
-
pip install vibephysics
|
|
105
|
-
|
|
106
|
-
# Or install from source
|
|
107
|
-
git clone https://github.com/mimiaigen/vibephysics
|
|
108
|
-
cd vibephysics
|
|
109
|
-
pip install -e .
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 🗺️ Mapping & Reconstruction
|
|
113
|
-
The core mapping tools are now built-in!
|
|
114
|
-
|
|
115
|
-
1. **Incremental COLMAP**: Available immediately after `pip install vibephysics`.
|
|
116
|
-
2. **Global GLOMAP**: Just run your first mapping task! `vibephysics` will automatically prompt and install the optimized GLOMAP backend from GitHub.
|
|
117
|
-
*(Note: This requires a one-time C++ build which takes a few minutes).*
|
|
118
|
-
|
|
119
|
-
### Requirements for Simulations
|
|
120
|
-
If you intend to run physics simulations, you also need to install Blender's Python module:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
# Install Blender module
|
|
124
|
-
pip install bpy
|
|
125
|
-
```
|
|
126
|
-
|
|
127
194
|
## Quick Start
|
|
128
195
|
|
|
129
196
|
```bash
|
|
@@ -283,57 +350,6 @@ exporter.export_fbx('output.fbx', selected_only=True)
|
|
|
283
350
|
| USD/USDA/USDC | USD |
|
|
284
351
|
| Blend (append) | |
|
|
285
352
|
|
|
286
|
-
## 🗺️ Mapping & Reconstruction
|
|
287
|
-
|
|
288
|
-
VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
|
|
289
|
-
|
|
290
|
-
- **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
|
|
291
|
-
- **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
|
|
292
|
-
- **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
|
|
293
|
-
|
|
294
|
-
### 💻 Usage (Command Line)
|
|
295
|
-
|
|
296
|
-
```bash
|
|
297
|
-
# Run GLOMAP pipeline (Fastest - Default)
|
|
298
|
-
./run_glomap.sh --image_path path/to/images
|
|
299
|
-
|
|
300
|
-
# Run COLMAP pipeline (Most Robust)
|
|
301
|
-
./run_glomap.sh --image_path path/to/images --engine colmap
|
|
302
|
-
|
|
303
|
-
# Advanced options
|
|
304
|
-
./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### 🐍 Usage (Python API)
|
|
308
|
-
|
|
309
|
-
```python
|
|
310
|
-
from vibephysics import mapping
|
|
311
|
-
|
|
312
|
-
# 1. Simple Usage (Only image_path is REQUIRED)
|
|
313
|
-
# Defaults: glomap engine, exhaustive matcher, SIMPLE_RADIAL camera
|
|
314
|
-
mapping.glomap_pipeline(image_path="path/to/images")
|
|
315
|
-
|
|
316
|
-
# 2. COLMAP Incremental Pipeline
|
|
317
|
-
mapping.colmap_pipeline(image_path="path/to/images")
|
|
318
|
-
|
|
319
|
-
# 3. Full Configuration (All parameters except image_path are OPTIONAL)
|
|
320
|
-
mapping.glomap_pipeline(
|
|
321
|
-
image_path="path/to/images", # REQUIRED
|
|
322
|
-
output_path="output/dir", # Optional: Defaults to image_path/../mapping_output/
|
|
323
|
-
database_path="path/to/database.db", # Optional: Defaults to output_path/sparse/database.db
|
|
324
|
-
matcher="exhaustive", # Optional: "exhaustive" (default) or "sequential"
|
|
325
|
-
camera_model="SIMPLE_RADIAL", # Optional: "PINHOLE", "SIMPLE_RADIAL" (default), "OPENCV", etc.
|
|
326
|
-
verbose=True # Optional: Set to False to suppress logs
|
|
327
|
-
)
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
| Parameter | Required | Default | Description |
|
|
331
|
-
|-----------|----------|---------|-------------|
|
|
332
|
-
| **`image_path`** | **Yes** | - | Path to the folder containing raw images. |
|
|
333
|
-
| **`output_path`** | No | `mapping_output/` | Directory for results. Creates `sparse/0` and symlinked `images/`. |
|
|
334
|
-
| **`database_path`** | No | `database.db` | Optional path to an existing COLMAP database. |
|
|
335
|
-
| **`matcher`** | No | `exhaustive` | Matching algorithm: `exhaustive` or `sequential`. |
|
|
336
|
-
| **`camera_model`** | No | `SIMPLE_RADIAL` | COLMAP camera model (e.g., `PINHOLE`, `OPENCV`). |
|
|
337
353
|
|
|
338
354
|
## Gaussian Splatting (3DGS) (BETA)
|
|
339
355
|
|
|
@@ -4,7 +4,105 @@
|
|
|
4
4
|
|
|
5
5
|
**A lightweight Blender physics simulation framework for creating realistic robot animations, rigid body physics, water dynamics, and comprehensive annotation tools — all running efficiently on CPU.**
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## ⚙️ Installation (MacOS)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# 1. Create environment
|
|
11
|
+
conda create -n vibephysics python=3.11
|
|
12
|
+
conda activate vibephysics
|
|
13
|
+
|
|
14
|
+
# 2. Install core package (includes COLMAP mapping & Blender simulation)
|
|
15
|
+
pip install vibephysics
|
|
16
|
+
|
|
17
|
+
# 3. (Optional) Install GLOMAP backend
|
|
18
|
+
# Linux users: refer to "Linux System Dependencies" below first
|
|
19
|
+
pip install git+https://github.com/shamangary/glomap.git
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 🐧 Linux (Ubuntu) System Dependencies
|
|
23
|
+
If you are on Linux and want to use the **GLOMAP** or **COLMAP** backends, you must install the following C++ development libraries to enable successful compilation:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
sudo apt-get update
|
|
27
|
+
sudo apt-get install -y \
|
|
28
|
+
libeigen3-dev \
|
|
29
|
+
libceres-dev \
|
|
30
|
+
libgoogle-glog-dev \
|
|
31
|
+
libboost-all-dev \
|
|
32
|
+
libsuitesparse-dev \
|
|
33
|
+
libsqlite3-dev \
|
|
34
|
+
libgflags-dev \
|
|
35
|
+
libfreeimage-dev \
|
|
36
|
+
libmetis-dev
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## ⚠️ Troubleshooting (Linker Errors)
|
|
40
|
+
If you are using **Anaconda** on Linux and see an error like `relocation R_X86_64_TPOFF32 ... can not be used when making a shared object`, it is due to a conflict with the Anaconda linker. Fix it by forcing the compiler to use the global-dynamic TLS model:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export CXXFLAGS="$CXXFLAGS -fPIC -ftls-model=global-dynamic"
|
|
44
|
+
export CFLAGS="$CFLAGS -fPIC"
|
|
45
|
+
pip install git+https://github.com/shamangary/glomap.git
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 🗺️ Mapping & Reconstruction
|
|
49
|
+
|
|
50
|
+
VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
|
|
51
|
+
|
|
52
|
+
- **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
|
|
53
|
+
- **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
|
|
54
|
+
- **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
|
|
55
|
+
|
|
56
|
+
### 💻 1. Run Reconstruction (SfM)
|
|
57
|
+
|
|
58
|
+
You can run the SfM pipeline via shell script or Python API:
|
|
59
|
+
|
|
60
|
+
**Command Line:**
|
|
61
|
+
```bash
|
|
62
|
+
# Run GLOMAP pipeline (Fastest - Default)
|
|
63
|
+
./run_glomap.sh --image_path path/to/images
|
|
64
|
+
|
|
65
|
+
# Run COLMAP pipeline (Most Robust)
|
|
66
|
+
./run_glomap.sh --image_path path/to/images --engine colmap
|
|
67
|
+
|
|
68
|
+
# Advanced options
|
|
69
|
+
./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Python API:**
|
|
73
|
+
```python
|
|
74
|
+
from vibephysics import mapping
|
|
75
|
+
|
|
76
|
+
# Simple Usage (Directly run GLOMAP on a folder of images)
|
|
77
|
+
mapping.glomap_pipeline(image_path="path/to/images")
|
|
78
|
+
|
|
79
|
+
# COLMAP Incremental Pipeline
|
|
80
|
+
mapping.colmap_pipeline(image_path="path/to/images")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 🎨 2. Visualize in Blender
|
|
84
|
+
|
|
85
|
+
Load your reconstruction into Blender for inspection with colored point clouds and correct camera poses.
|
|
86
|
+
|
|
87
|
+
**Command Line:**
|
|
88
|
+
```bash
|
|
89
|
+
# Visualize a sparse model folder (containing cameras.bin, points3D.bin etc.)
|
|
90
|
+
./run_glomap_visual.sh --sparse path/to/sparse/0 --output result.blend
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Python API:**
|
|
94
|
+
```python
|
|
95
|
+
from vibephysics import mapping
|
|
96
|
+
|
|
97
|
+
# Load reconstruction directly into active Blender scene
|
|
98
|
+
mapping.load_colmap_reconstruction(
|
|
99
|
+
input_path="output/mapping_output/sparse/0",
|
|
100
|
+
point_size=0.03,
|
|
101
|
+
rotation=(-90, 0, 0) # Optional: global rotation
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 🎬 Simulation Results (`sh run_robot.sh`)
|
|
8
106
|
|
|
9
107
|

|
|
10
108
|
|
|
@@ -64,37 +162,6 @@ Perfect for researchers, animators, and robotics engineers who need physics simu
|
|
|
64
162
|
- **Open Duck**: We use the [Open Duck blender model](https://github.com/pollen-robotics/Open_Duck_Blender) as demo. We do not own the model. Please refer to the original github repo.
|
|
65
163
|
- **Unitree Go2**: We use the [Unitree Go2 USD model](https://huggingface.co/datasets/unitreerobotics/unitree_model). The model is auto-downloaded when running Go2 examples. We do not own the model.
|
|
66
164
|
|
|
67
|
-
## ⚙️ Installation
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# Create and activate environment
|
|
71
|
-
conda create -n vibephysics python=3.11
|
|
72
|
-
conda activate vibephysics
|
|
73
|
-
|
|
74
|
-
# Install vibephysics
|
|
75
|
-
pip install vibephysics
|
|
76
|
-
|
|
77
|
-
# Or install from source
|
|
78
|
-
git clone https://github.com/mimiaigen/vibephysics
|
|
79
|
-
cd vibephysics
|
|
80
|
-
pip install -e .
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### 🗺️ Mapping & Reconstruction
|
|
84
|
-
The core mapping tools are now built-in!
|
|
85
|
-
|
|
86
|
-
1. **Incremental COLMAP**: Available immediately after `pip install vibephysics`.
|
|
87
|
-
2. **Global GLOMAP**: Just run your first mapping task! `vibephysics` will automatically prompt and install the optimized GLOMAP backend from GitHub.
|
|
88
|
-
*(Note: This requires a one-time C++ build which takes a few minutes).*
|
|
89
|
-
|
|
90
|
-
### Requirements for Simulations
|
|
91
|
-
If you intend to run physics simulations, you also need to install Blender's Python module:
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
# Install Blender module
|
|
95
|
-
pip install bpy
|
|
96
|
-
```
|
|
97
|
-
|
|
98
165
|
## Quick Start
|
|
99
166
|
|
|
100
167
|
```bash
|
|
@@ -254,57 +321,6 @@ exporter.export_fbx('output.fbx', selected_only=True)
|
|
|
254
321
|
| USD/USDA/USDC | USD |
|
|
255
322
|
| Blend (append) | |
|
|
256
323
|
|
|
257
|
-
## 🗺️ Mapping & Reconstruction
|
|
258
|
-
|
|
259
|
-
VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
|
|
260
|
-
|
|
261
|
-
- **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
|
|
262
|
-
- **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
|
|
263
|
-
- **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
|
|
264
|
-
|
|
265
|
-
### 💻 Usage (Command Line)
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
# Run GLOMAP pipeline (Fastest - Default)
|
|
269
|
-
./run_glomap.sh --image_path path/to/images
|
|
270
|
-
|
|
271
|
-
# Run COLMAP pipeline (Most Robust)
|
|
272
|
-
./run_glomap.sh --image_path path/to/images --engine colmap
|
|
273
|
-
|
|
274
|
-
# Advanced options
|
|
275
|
-
./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
### 🐍 Usage (Python API)
|
|
279
|
-
|
|
280
|
-
```python
|
|
281
|
-
from vibephysics import mapping
|
|
282
|
-
|
|
283
|
-
# 1. Simple Usage (Only image_path is REQUIRED)
|
|
284
|
-
# Defaults: glomap engine, exhaustive matcher, SIMPLE_RADIAL camera
|
|
285
|
-
mapping.glomap_pipeline(image_path="path/to/images")
|
|
286
|
-
|
|
287
|
-
# 2. COLMAP Incremental Pipeline
|
|
288
|
-
mapping.colmap_pipeline(image_path="path/to/images")
|
|
289
|
-
|
|
290
|
-
# 3. Full Configuration (All parameters except image_path are OPTIONAL)
|
|
291
|
-
mapping.glomap_pipeline(
|
|
292
|
-
image_path="path/to/images", # REQUIRED
|
|
293
|
-
output_path="output/dir", # Optional: Defaults to image_path/../mapping_output/
|
|
294
|
-
database_path="path/to/database.db", # Optional: Defaults to output_path/sparse/database.db
|
|
295
|
-
matcher="exhaustive", # Optional: "exhaustive" (default) or "sequential"
|
|
296
|
-
camera_model="SIMPLE_RADIAL", # Optional: "PINHOLE", "SIMPLE_RADIAL" (default), "OPENCV", etc.
|
|
297
|
-
verbose=True # Optional: Set to False to suppress logs
|
|
298
|
-
)
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
| Parameter | Required | Default | Description |
|
|
302
|
-
|-----------|----------|---------|-------------|
|
|
303
|
-
| **`image_path`** | **Yes** | - | Path to the folder containing raw images. |
|
|
304
|
-
| **`output_path`** | No | `mapping_output/` | Directory for results. Creates `sparse/0` and symlinked `images/`. |
|
|
305
|
-
| **`database_path`** | No | `database.db` | Optional path to an existing COLMAP database. |
|
|
306
|
-
| **`matcher`** | No | `exhaustive` | Matching algorithm: `exhaustive` or `sequential`. |
|
|
307
|
-
| **`camera_model`** | No | `SIMPLE_RADIAL` | COLMAP camera model (e.g., `PINHOLE`, `OPENCV`). |
|
|
308
324
|
|
|
309
325
|
## Gaussian Splatting (3DGS) (BETA)
|
|
310
326
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .colmap import colmap_pipeline, run_colmap_stage, run_incremental_mapping_stage
|
|
2
2
|
from .glomap import glomap_pipeline, run_glomap_stage
|
|
3
|
+
from .map_visual import load_colmap_reconstruction
|
|
3
4
|
from .utils import prepare_output_directory
|
|
4
5
|
|
|
5
6
|
__all__ = [
|
|
@@ -8,5 +9,6 @@ __all__ = [
|
|
|
8
9
|
"run_colmap_stage",
|
|
9
10
|
"run_incremental_mapping_stage",
|
|
10
11
|
"run_glomap_stage",
|
|
12
|
+
"load_colmap_reconstruction",
|
|
11
13
|
"prepare_output_directory"
|
|
12
14
|
]
|
|
@@ -7,7 +7,7 @@ from .utils import prepare_output_directory
|
|
|
7
7
|
def run_colmap_stage(
|
|
8
8
|
image_path: Path,
|
|
9
9
|
database_path: Path,
|
|
10
|
-
camera_model: str = "
|
|
10
|
+
camera_model: str = "PINHOLE",
|
|
11
11
|
matcher: str = "exhaustive",
|
|
12
12
|
verbose: bool = True
|
|
13
13
|
) -> int:
|
|
@@ -86,7 +86,7 @@ def colmap_pipeline(
|
|
|
86
86
|
output_path: str | Path | None = None,
|
|
87
87
|
database_path: str | Path | None = None,
|
|
88
88
|
matcher: str = "exhaustive",
|
|
89
|
-
camera_model: str = "
|
|
89
|
+
camera_model: str = "PINHOLE",
|
|
90
90
|
verbose: bool = True
|
|
91
91
|
) -> int:
|
|
92
92
|
"""
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import bpy
|
|
2
|
+
import pycolmap
|
|
3
|
+
import numpy as np
|
|
4
|
+
import math
|
|
5
|
+
import mathutils
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
def create_camera_object(image, camera, collection, scale=0.1):
|
|
9
|
+
"""
|
|
10
|
+
Create a Blender camera object from a Colmap image and camera.
|
|
11
|
+
"""
|
|
12
|
+
name = image.name
|
|
13
|
+
|
|
14
|
+
# 1. Pose: World-to-Camera (SfM) -> Camera-to-World (Blender)
|
|
15
|
+
if hasattr(image, "cam_from_world") and callable(image.cam_from_world):
|
|
16
|
+
pose = image.cam_from_world()
|
|
17
|
+
rot_mat = pose.rotation.matrix()
|
|
18
|
+
tvec = pose.translation
|
|
19
|
+
else:
|
|
20
|
+
# Fallback for older pycolmap (World-to-Camera)
|
|
21
|
+
qvec = getattr(image, "qvec", np.array([1, 0, 0, 0]))
|
|
22
|
+
tvec = getattr(image, "tvec", np.zeros(3))
|
|
23
|
+
w, x, y, z = qvec
|
|
24
|
+
rot_mat = np.array([
|
|
25
|
+
[1 - 2*y**2 - 2*z**2, 2*x*y - 2*z*w, 2*x*z + 2*y*w],
|
|
26
|
+
[2*x*y + 2*z*w, 1 - 2*x**2 - 2*z**2, 2*y*z - 2*x*w],
|
|
27
|
+
[2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x**2 - 2*y**2]
|
|
28
|
+
])
|
|
29
|
+
|
|
30
|
+
# Camera-to-World matrix in OpenCV frame (X-right, Y-down, Z-forward)
|
|
31
|
+
rot_mat_inv = rot_mat.T
|
|
32
|
+
tvec_inv = -rot_mat_inv @ tvec
|
|
33
|
+
|
|
34
|
+
# Construct 4x4 matrix in mathutils
|
|
35
|
+
mat_world_cv = mathutils.Matrix.Identity(4)
|
|
36
|
+
for i in range(3):
|
|
37
|
+
for j in range(3):
|
|
38
|
+
mat_world_cv[i][j] = rot_mat_inv[i, j]
|
|
39
|
+
mat_world_cv[i][3] = tvec_inv[i]
|
|
40
|
+
|
|
41
|
+
# Convert from OpenCV (X-right, Y-down, Z-forward)
|
|
42
|
+
# to Blender (X-right, Y-up, Z-back / points -Z)
|
|
43
|
+
# This is a 180-degree rotation around the X-axis
|
|
44
|
+
flip_mat = mathutils.Matrix.Rotation(math.pi, 4, 'X')
|
|
45
|
+
final_matrix = mat_world_cv @ flip_mat
|
|
46
|
+
|
|
47
|
+
# 2. Create Camera Data and Object
|
|
48
|
+
# We use the native bpy camera object
|
|
49
|
+
cam_data = bpy.data.cameras.new(name=f"CamData_{name}")
|
|
50
|
+
cam_obj = bpy.data.objects.new(name=name, object_data=cam_data)
|
|
51
|
+
collection.objects.link(cam_obj)
|
|
52
|
+
|
|
53
|
+
cam_obj.matrix_world = final_matrix
|
|
54
|
+
|
|
55
|
+
# 3. Intrinsics: Focal length and Principal Point (Image x, y)
|
|
56
|
+
width = camera.width
|
|
57
|
+
height = camera.height
|
|
58
|
+
params = camera.params
|
|
59
|
+
model = camera.model_name if hasattr(camera, "model_name") else "PINHOLE"
|
|
60
|
+
|
|
61
|
+
# Standard Blender sensor width (36mm)
|
|
62
|
+
cam_data.sensor_fit = 'HORIZONTAL'
|
|
63
|
+
cam_data.sensor_width = 36.0
|
|
64
|
+
cam_data.sensor_height = 36.0 * height / width
|
|
65
|
+
|
|
66
|
+
# Extract params based on model
|
|
67
|
+
if model == "SIMPLE_PINHOLE":
|
|
68
|
+
f, cx, cy = params
|
|
69
|
+
fx = fy = f
|
|
70
|
+
elif model == "PINHOLE":
|
|
71
|
+
fx, fy, cx, cy = params
|
|
72
|
+
elif model in ["SIMPLE_RADIAL", "RADIAL"]:
|
|
73
|
+
f, cx, cy = params[:3]
|
|
74
|
+
fx = fy = f
|
|
75
|
+
elif model in ["OPENCV", "FULL_OPENCV"]:
|
|
76
|
+
fx, fy, cx, cy = params[:4]
|
|
77
|
+
else:
|
|
78
|
+
# Fallback
|
|
79
|
+
fx = fy = params[0] if len(params) > 0 else 1000.0
|
|
80
|
+
cx = width / 2.0
|
|
81
|
+
cy = height / 2.0
|
|
82
|
+
|
|
83
|
+
# Focal length: f_mm = f_px * sensor_width / width_px
|
|
84
|
+
cam_data.lens = fx * cam_data.sensor_width / width
|
|
85
|
+
|
|
86
|
+
# Principal Point Shift (consider image x and y offsets)
|
|
87
|
+
# shift_x/y are ratios of the larger dimension (if fit is AUTO) or the fit dimension
|
|
88
|
+
# Since we use 'HORIZONTAL', both are relative to width.
|
|
89
|
+
cam_data.shift_x = (cx / width) - 0.5
|
|
90
|
+
cam_data.shift_y = (height / 2.0 - cy) / width
|
|
91
|
+
|
|
92
|
+
# Set display size for the camera gizmo in viewport
|
|
93
|
+
cam_data.display_size = scale
|
|
94
|
+
|
|
95
|
+
return cam_obj
|
|
96
|
+
|
|
97
|
+
def create_point_cloud(points3D, collection, name="PointCloud", point_size=0.03):
|
|
98
|
+
"""
|
|
99
|
+
Create a point cloud visualization using a mesh with vertices and colors.
|
|
100
|
+
Uses Geometry Nodes to make points visible as spheres.
|
|
101
|
+
"""
|
|
102
|
+
mesh = bpy.data.meshes.new(name=name)
|
|
103
|
+
obj = bpy.data.objects.new(name=name, object_data=mesh)
|
|
104
|
+
collection.objects.link(obj)
|
|
105
|
+
|
|
106
|
+
# Extract points and colors
|
|
107
|
+
xyz = []
|
|
108
|
+
rgb = []
|
|
109
|
+
|
|
110
|
+
for p_id, p in points3D.items():
|
|
111
|
+
xyz.append(p.xyz)
|
|
112
|
+
rgb.append(p.color / 255.0) # Normalize to 0-1
|
|
113
|
+
|
|
114
|
+
if not xyz:
|
|
115
|
+
print("No points found in reconstruction.")
|
|
116
|
+
return obj
|
|
117
|
+
|
|
118
|
+
# Create mesh
|
|
119
|
+
mesh.from_pydata(xyz, [], [])
|
|
120
|
+
mesh.update()
|
|
121
|
+
|
|
122
|
+
# Add colors as a generic attribute
|
|
123
|
+
if rgb:
|
|
124
|
+
# Check Blender version for attribute creation
|
|
125
|
+
if hasattr(mesh.attributes, "new"):
|
|
126
|
+
color_attr = mesh.attributes.new(name="Color", type='FLOAT_COLOR', domain='POINT')
|
|
127
|
+
color_attr.data.foreach_set("color", [c for color in rgb for c in (*color, 1.0)]) # RGBA
|
|
128
|
+
|
|
129
|
+
# Simple Geometry Nodes setup to render points as spheres
|
|
130
|
+
modifier = obj.modifiers.new(name="PointVisualizer", type='NODES')
|
|
131
|
+
|
|
132
|
+
# Setup node tree
|
|
133
|
+
node_tree = bpy.data.node_groups.new(name="PointVisualizerTree", type='GeometryNodeTree')
|
|
134
|
+
|
|
135
|
+
# In Blender 4.0+, we use interface to add sockets
|
|
136
|
+
if hasattr(node_tree, "interface"):
|
|
137
|
+
if not any(item.name == "Geometry" for item in node_tree.interface.items_tree if item.item_type == 'SOCKET'):
|
|
138
|
+
node_tree.interface.new_socket(name="Geometry", in_out='INPUT', socket_type='NodeSocketGeometry')
|
|
139
|
+
node_tree.interface.new_socket(name="Geometry", in_out='OUTPUT', socket_type='NodeSocketGeometry')
|
|
140
|
+
else:
|
|
141
|
+
# Older Blender fallback
|
|
142
|
+
if "Geometry" not in node_tree.inputs:
|
|
143
|
+
node_tree.inputs.new('NodeSocketGeometry', "Geometry")
|
|
144
|
+
if "Geometry" not in node_tree.outputs:
|
|
145
|
+
node_tree.outputs.new('NodeSocketGeometry', "Geometry")
|
|
146
|
+
|
|
147
|
+
links = node_tree.links
|
|
148
|
+
nodes = node_tree.nodes
|
|
149
|
+
|
|
150
|
+
# Clear default nodes
|
|
151
|
+
nodes.clear()
|
|
152
|
+
|
|
153
|
+
# Input/Output
|
|
154
|
+
node_in = nodes.new('NodeGroupInput')
|
|
155
|
+
node_out = nodes.new('NodeGroupOutput')
|
|
156
|
+
|
|
157
|
+
# Point to Volume / Instances
|
|
158
|
+
node_m2p = nodes.new('GeometryNodeMeshToPoints')
|
|
159
|
+
node_inst = nodes.new('GeometryNodeInstanceOnPoints')
|
|
160
|
+
node_sph = nodes.new('GeometryNodeMeshIcoSphere')
|
|
161
|
+
node_sph.inputs['Radius'].default_value = point_size
|
|
162
|
+
node_sph.inputs['Subdivisions'].default_value = 1
|
|
163
|
+
|
|
164
|
+
# Realize Instances to propagate attributes (like Color)
|
|
165
|
+
node_realize = nodes.new('GeometryNodeRealizeInstances')
|
|
166
|
+
|
|
167
|
+
# Material
|
|
168
|
+
node_mat = nodes.new('GeometryNodeSetMaterial')
|
|
169
|
+
|
|
170
|
+
# Material setup
|
|
171
|
+
mat_name = "PointCloudMaterial"
|
|
172
|
+
if mat_name not in bpy.data.materials:
|
|
173
|
+
mat = bpy.data.materials.new(name=mat_name)
|
|
174
|
+
mat.use_nodes = True
|
|
175
|
+
nodes_mat = mat.node_tree.nodes
|
|
176
|
+
links_mat = mat.node_tree.links
|
|
177
|
+
nodes_mat.clear()
|
|
178
|
+
|
|
179
|
+
node_out_mat = nodes_mat.new('ShaderNodeOutputMaterial')
|
|
180
|
+
node_principled = nodes_mat.new('ShaderNodeBsdfPrincipled')
|
|
181
|
+
# Use Attribute node to get the vertex color
|
|
182
|
+
node_attr = nodes_mat.new('ShaderNodeAttribute')
|
|
183
|
+
node_attr.attribute_name = "Color"
|
|
184
|
+
node_attr.attribute_type = 'GEOMETRY'
|
|
185
|
+
|
|
186
|
+
links_mat.new(node_attr.outputs['Color'], node_principled.inputs['Base Color'])
|
|
187
|
+
links_mat.new(node_principled.outputs['BSDF'], node_out_mat.inputs['Surface'])
|
|
188
|
+
else:
|
|
189
|
+
mat = bpy.data.materials[mat_name]
|
|
190
|
+
|
|
191
|
+
# Assign material to object slots (important for some Blender versions to see attributes)
|
|
192
|
+
if mat.name not in obj.data.materials:
|
|
193
|
+
obj.data.materials.append(mat)
|
|
194
|
+
|
|
195
|
+
node_mat.inputs['Material'].default_value = mat
|
|
196
|
+
|
|
197
|
+
# Link nodes
|
|
198
|
+
links.new(node_in.outputs[0], node_m2p.inputs['Mesh'])
|
|
199
|
+
links.new(node_m2p.outputs['Points'], node_inst.inputs['Points'])
|
|
200
|
+
links.new(node_sph.outputs['Mesh'], node_inst.inputs['Instance'])
|
|
201
|
+
links.new(node_inst.outputs['Instances'], node_realize.inputs['Geometry'])
|
|
202
|
+
links.new(node_realize.outputs['Geometry'], node_mat.inputs['Geometry'])
|
|
203
|
+
links.new(node_mat.outputs['Geometry'], node_out.inputs[0])
|
|
204
|
+
|
|
205
|
+
modifier.node_group = node_tree
|
|
206
|
+
|
|
207
|
+
# Attempt to set viewport shading to MATERIAL for better UX
|
|
208
|
+
if bpy.context.screen:
|
|
209
|
+
for area in bpy.context.screen.areas:
|
|
210
|
+
if area.type == 'VIEW_3D':
|
|
211
|
+
for space in area.spaces:
|
|
212
|
+
if space.type == 'VIEW_3D':
|
|
213
|
+
space.shading.type = 'MATERIAL'
|
|
214
|
+
|
|
215
|
+
return obj
|
|
216
|
+
|
|
217
|
+
def load_colmap_reconstruction(
|
|
218
|
+
input_path: str, # Path to sparse/0 folder
|
|
219
|
+
collection_name: str = "Reconstruction",
|
|
220
|
+
import_cameras: bool = True,
|
|
221
|
+
import_points: bool = True,
|
|
222
|
+
camera_scale: float = 0.1,
|
|
223
|
+
point_size: float = 0.03,
|
|
224
|
+
rotation: tuple = (-90, 0, 0) # Global rotation in degrees (Euler XYZ)
|
|
225
|
+
):
|
|
226
|
+
"""
|
|
227
|
+
Load Colmap reconstruction output (sparse folder) into Blender.
|
|
228
|
+
"""
|
|
229
|
+
input_dir = Path(input_path)
|
|
230
|
+
if not input_dir.exists():
|
|
231
|
+
print(f"Error: Path {input_dir} does not exist.")
|
|
232
|
+
return
|
|
233
|
+
|
|
234
|
+
print(f"Loading Colmap reconstruction from {input_dir}...")
|
|
235
|
+
recon = pycolmap.Reconstruction(input_dir)
|
|
236
|
+
|
|
237
|
+
# Create collection
|
|
238
|
+
if collection_name in bpy.data.collections:
|
|
239
|
+
col = bpy.data.collections[collection_name]
|
|
240
|
+
else:
|
|
241
|
+
col = bpy.data.collections.new(collection_name)
|
|
242
|
+
bpy.context.scene.collection.children.link(col)
|
|
243
|
+
|
|
244
|
+
# Create a root object for the whole reconstruction to allow global manipulation
|
|
245
|
+
root_name = f"{collection_name}_Root"
|
|
246
|
+
if root_name in bpy.data.objects:
|
|
247
|
+
root_obj = bpy.data.objects[root_name]
|
|
248
|
+
else:
|
|
249
|
+
root_obj = bpy.data.objects.new(root_name, None)
|
|
250
|
+
col.objects.link(root_obj)
|
|
251
|
+
|
|
252
|
+
# Apply global rotation to the root
|
|
253
|
+
root_obj.rotation_mode = 'XYZ'
|
|
254
|
+
root_obj.rotation_euler = [math.radians(a) for a in rotation]
|
|
255
|
+
|
|
256
|
+
# Set scene resolution from the first camera to correctly reflect aspect ratio (e.g. 9:16)
|
|
257
|
+
if import_cameras and recon.cameras:
|
|
258
|
+
first_cam = next(iter(recon.cameras.values()))
|
|
259
|
+
bpy.context.scene.render.resolution_x = first_cam.width
|
|
260
|
+
bpy.context.scene.render.resolution_y = first_cam.height
|
|
261
|
+
bpy.context.scene.render.pixel_aspect_x = 1.0
|
|
262
|
+
bpy.context.scene.render.pixel_aspect_y = 1.0
|
|
263
|
+
|
|
264
|
+
if import_points:
|
|
265
|
+
print(f"Importing {len(recon.points3D)} points...")
|
|
266
|
+
pc_obj = create_point_cloud(recon.points3D, col, point_size=point_size)
|
|
267
|
+
pc_obj.parent = root_obj
|
|
268
|
+
|
|
269
|
+
if import_cameras:
|
|
270
|
+
print(f"Importing {len(recon.images)} cameras...")
|
|
271
|
+
first_cam_obj = None
|
|
272
|
+
for img_id, image in recon.images.items():
|
|
273
|
+
if image.camera_id in recon.cameras:
|
|
274
|
+
cam = recon.cameras[image.camera_id]
|
|
275
|
+
cam_obj = create_camera_object(image, cam, col, scale=camera_scale)
|
|
276
|
+
cam_obj.parent = root_obj
|
|
277
|
+
if first_cam_obj is None:
|
|
278
|
+
first_cam_obj = cam_obj
|
|
279
|
+
|
|
280
|
+
# Set the first camera as active for the scene
|
|
281
|
+
if first_cam_obj:
|
|
282
|
+
bpy.context.scene.camera = first_cam_obj
|
|
283
|
+
|
|
284
|
+
print("Done.")
|
|
285
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vibephysics
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Physics simulation and annotation tools for Blender
|
|
5
5
|
Author-email: tsunyi <tsunyi@mimiaigen.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/yourusername/vibephysics
|
|
@@ -33,7 +33,105 @@ Requires-Dist: ruff; extra == "dev"
|
|
|
33
33
|
|
|
34
34
|
**A lightweight Blender physics simulation framework for creating realistic robot animations, rigid body physics, water dynamics, and comprehensive annotation tools — all running efficiently on CPU.**
|
|
35
35
|
|
|
36
|
-
##
|
|
36
|
+
## ⚙️ Installation (MacOS)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. Create environment
|
|
40
|
+
conda create -n vibephysics python=3.11
|
|
41
|
+
conda activate vibephysics
|
|
42
|
+
|
|
43
|
+
# 2. Install core package (includes COLMAP mapping & Blender simulation)
|
|
44
|
+
pip install vibephysics
|
|
45
|
+
|
|
46
|
+
# 3. (Optional) Install GLOMAP backend
|
|
47
|
+
# Linux users: refer to "Linux System Dependencies" below first
|
|
48
|
+
pip install git+https://github.com/shamangary/glomap.git
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 🐧 Linux (Ubuntu) System Dependencies
|
|
52
|
+
If you are on Linux and want to use the **GLOMAP** or **COLMAP** backends, you must install the following C++ development libraries to enable successful compilation:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
sudo apt-get update
|
|
56
|
+
sudo apt-get install -y \
|
|
57
|
+
libeigen3-dev \
|
|
58
|
+
libceres-dev \
|
|
59
|
+
libgoogle-glog-dev \
|
|
60
|
+
libboost-all-dev \
|
|
61
|
+
libsuitesparse-dev \
|
|
62
|
+
libsqlite3-dev \
|
|
63
|
+
libgflags-dev \
|
|
64
|
+
libfreeimage-dev \
|
|
65
|
+
libmetis-dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## ⚠️ Troubleshooting (Linker Errors)
|
|
69
|
+
If you are using **Anaconda** on Linux and see an error like `relocation R_X86_64_TPOFF32 ... can not be used when making a shared object`, it is due to a conflict with the Anaconda linker. Fix it by forcing the compiler to use the global-dynamic TLS model:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
export CXXFLAGS="$CXXFLAGS -fPIC -ftls-model=global-dynamic"
|
|
73
|
+
export CFLAGS="$CFLAGS -fPIC"
|
|
74
|
+
pip install git+https://github.com/shamangary/glomap.git
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 🗺️ Mapping & Reconstruction
|
|
78
|
+
|
|
79
|
+
VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
|
|
80
|
+
|
|
81
|
+
- **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
|
|
82
|
+
- **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
|
|
83
|
+
- **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
|
|
84
|
+
|
|
85
|
+
### 💻 1. Run Reconstruction (SfM)
|
|
86
|
+
|
|
87
|
+
You can run the SfM pipeline via shell script or Python API:
|
|
88
|
+
|
|
89
|
+
**Command Line:**
|
|
90
|
+
```bash
|
|
91
|
+
# Run GLOMAP pipeline (Fastest - Default)
|
|
92
|
+
./run_glomap.sh --image_path path/to/images
|
|
93
|
+
|
|
94
|
+
# Run COLMAP pipeline (Most Robust)
|
|
95
|
+
./run_glomap.sh --image_path path/to/images --engine colmap
|
|
96
|
+
|
|
97
|
+
# Advanced options
|
|
98
|
+
./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Python API:**
|
|
102
|
+
```python
|
|
103
|
+
from vibephysics import mapping
|
|
104
|
+
|
|
105
|
+
# Simple Usage (Directly run GLOMAP on a folder of images)
|
|
106
|
+
mapping.glomap_pipeline(image_path="path/to/images")
|
|
107
|
+
|
|
108
|
+
# COLMAP Incremental Pipeline
|
|
109
|
+
mapping.colmap_pipeline(image_path="path/to/images")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 🎨 2. Visualize in Blender
|
|
113
|
+
|
|
114
|
+
Load your reconstruction into Blender for inspection with colored point clouds and correct camera poses.
|
|
115
|
+
|
|
116
|
+
**Command Line:**
|
|
117
|
+
```bash
|
|
118
|
+
# Visualize a sparse model folder (containing cameras.bin, points3D.bin etc.)
|
|
119
|
+
./run_glomap_visual.sh --sparse path/to/sparse/0 --output result.blend
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Python API:**
|
|
123
|
+
```python
|
|
124
|
+
from vibephysics import mapping
|
|
125
|
+
|
|
126
|
+
# Load reconstruction directly into active Blender scene
|
|
127
|
+
mapping.load_colmap_reconstruction(
|
|
128
|
+
input_path="output/mapping_output/sparse/0",
|
|
129
|
+
point_size=0.03,
|
|
130
|
+
rotation=(-90, 0, 0) # Optional: global rotation
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## 🎬 Simulation Results (`sh run_robot.sh`)
|
|
37
135
|
|
|
38
136
|

|
|
39
137
|
|
|
@@ -93,37 +191,6 @@ Perfect for researchers, animators, and robotics engineers who need physics simu
|
|
|
93
191
|
- **Open Duck**: We use the [Open Duck blender model](https://github.com/pollen-robotics/Open_Duck_Blender) as demo. We do not own the model. Please refer to the original github repo.
|
|
94
192
|
- **Unitree Go2**: We use the [Unitree Go2 USD model](https://huggingface.co/datasets/unitreerobotics/unitree_model). The model is auto-downloaded when running Go2 examples. We do not own the model.
|
|
95
193
|
|
|
96
|
-
## ⚙️ Installation
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
# Create and activate environment
|
|
100
|
-
conda create -n vibephysics python=3.11
|
|
101
|
-
conda activate vibephysics
|
|
102
|
-
|
|
103
|
-
# Install vibephysics
|
|
104
|
-
pip install vibephysics
|
|
105
|
-
|
|
106
|
-
# Or install from source
|
|
107
|
-
git clone https://github.com/mimiaigen/vibephysics
|
|
108
|
-
cd vibephysics
|
|
109
|
-
pip install -e .
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 🗺️ Mapping & Reconstruction
|
|
113
|
-
The core mapping tools are now built-in!
|
|
114
|
-
|
|
115
|
-
1. **Incremental COLMAP**: Available immediately after `pip install vibephysics`.
|
|
116
|
-
2. **Global GLOMAP**: Just run your first mapping task! `vibephysics` will automatically prompt and install the optimized GLOMAP backend from GitHub.
|
|
117
|
-
*(Note: This requires a one-time C++ build which takes a few minutes).*
|
|
118
|
-
|
|
119
|
-
### Requirements for Simulations
|
|
120
|
-
If you intend to run physics simulations, you also need to install Blender's Python module:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
# Install Blender module
|
|
124
|
-
pip install bpy
|
|
125
|
-
```
|
|
126
|
-
|
|
127
194
|
## Quick Start
|
|
128
195
|
|
|
129
196
|
```bash
|
|
@@ -283,57 +350,6 @@ exporter.export_fbx('output.fbx', selected_only=True)
|
|
|
283
350
|
| USD/USDA/USDC | USD |
|
|
284
351
|
| Blend (append) | |
|
|
285
352
|
|
|
286
|
-
## 🗺️ Mapping & Reconstruction
|
|
287
|
-
|
|
288
|
-
VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
|
|
289
|
-
|
|
290
|
-
- **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
|
|
291
|
-
- **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
|
|
292
|
-
- **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
|
|
293
|
-
|
|
294
|
-
### 💻 Usage (Command Line)
|
|
295
|
-
|
|
296
|
-
```bash
|
|
297
|
-
# Run GLOMAP pipeline (Fastest - Default)
|
|
298
|
-
./run_glomap.sh --image_path path/to/images
|
|
299
|
-
|
|
300
|
-
# Run COLMAP pipeline (Most Robust)
|
|
301
|
-
./run_glomap.sh --image_path path/to/images --engine colmap
|
|
302
|
-
|
|
303
|
-
# Advanced options
|
|
304
|
-
./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### 🐍 Usage (Python API)
|
|
308
|
-
|
|
309
|
-
```python
|
|
310
|
-
from vibephysics import mapping
|
|
311
|
-
|
|
312
|
-
# 1. Simple Usage (Only image_path is REQUIRED)
|
|
313
|
-
# Defaults: glomap engine, exhaustive matcher, SIMPLE_RADIAL camera
|
|
314
|
-
mapping.glomap_pipeline(image_path="path/to/images")
|
|
315
|
-
|
|
316
|
-
# 2. COLMAP Incremental Pipeline
|
|
317
|
-
mapping.colmap_pipeline(image_path="path/to/images")
|
|
318
|
-
|
|
319
|
-
# 3. Full Configuration (All parameters except image_path are OPTIONAL)
|
|
320
|
-
mapping.glomap_pipeline(
|
|
321
|
-
image_path="path/to/images", # REQUIRED
|
|
322
|
-
output_path="output/dir", # Optional: Defaults to image_path/../mapping_output/
|
|
323
|
-
database_path="path/to/database.db", # Optional: Defaults to output_path/sparse/database.db
|
|
324
|
-
matcher="exhaustive", # Optional: "exhaustive" (default) or "sequential"
|
|
325
|
-
camera_model="SIMPLE_RADIAL", # Optional: "PINHOLE", "SIMPLE_RADIAL" (default), "OPENCV", etc.
|
|
326
|
-
verbose=True # Optional: Set to False to suppress logs
|
|
327
|
-
)
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
| Parameter | Required | Default | Description |
|
|
331
|
-
|-----------|----------|---------|-------------|
|
|
332
|
-
| **`image_path`** | **Yes** | - | Path to the folder containing raw images. |
|
|
333
|
-
| **`output_path`** | No | `mapping_output/` | Directory for results. Creates `sparse/0` and symlinked `images/`. |
|
|
334
|
-
| **`database_path`** | No | `database.db` | Optional path to an existing COLMAP database. |
|
|
335
|
-
| **`matcher`** | No | `exhaustive` | Matching algorithm: `exhaustive` or `sequential`. |
|
|
336
|
-
| **`camera_model`** | No | `SIMPLE_RADIAL` | COLMAP camera model (e.g., `PINHOLE`, `OPENCV`). |
|
|
337
353
|
|
|
338
354
|
## Gaussian Splatting (3DGS) (BETA)
|
|
339
355
|
|
|
@@ -36,6 +36,7 @@ src/vibephysics/foundation/water.py
|
|
|
36
36
|
src/vibephysics/mapping/__init__.py
|
|
37
37
|
src/vibephysics/mapping/colmap.py
|
|
38
38
|
src/vibephysics/mapping/glomap.py
|
|
39
|
+
src/vibephysics/mapping/map_visual.py
|
|
39
40
|
src/vibephysics/mapping/pipeline.py
|
|
40
41
|
src/vibephysics/mapping/utils.py
|
|
41
42
|
src/vibephysics/setup/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|