vibephysics 0.2.3__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.
Files changed (49) hide show
  1. {vibephysics-0.2.3/src/vibephysics.egg-info → vibephysics-0.2.4}/PKG-INFO +59 -73
  2. {vibephysics-0.2.3 → vibephysics-0.2.4}/README.md +58 -72
  3. {vibephysics-0.2.3 → vibephysics-0.2.4}/pyproject.toml +1 -1
  4. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/__init__.py +1 -1
  5. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/mapping/map_visual.py +77 -66
  6. {vibephysics-0.2.3 → vibephysics-0.2.4/src/vibephysics.egg-info}/PKG-INFO +59 -73
  7. {vibephysics-0.2.3 → vibephysics-0.2.4}/LICENSE +0 -0
  8. {vibephysics-0.2.3 → vibephysics-0.2.4}/MANIFEST.in +0 -0
  9. {vibephysics-0.2.3 → vibephysics-0.2.4}/setup.cfg +0 -0
  10. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/annotation/__init__.py +0 -0
  11. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/annotation/base.py +0 -0
  12. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/annotation/bbox.py +0 -0
  13. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/annotation/manager.py +0 -0
  14. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/annotation/motion_trail.py +0 -0
  15. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/annotation/point_tracking.py +0 -0
  16. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/camera/__init__.py +0 -0
  17. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/camera/base.py +0 -0
  18. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/camera/center.py +0 -0
  19. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/camera/following.py +0 -0
  20. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/camera/manager.py +0 -0
  21. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/camera/mounted.py +0 -0
  22. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/README.md +0 -0
  23. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/__init__.py +0 -0
  24. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/go2.py +0 -0
  25. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/ground.py +0 -0
  26. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/lighting.py +0 -0
  27. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/materials.py +0 -0
  28. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/objects.py +0 -0
  29. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/open_duck.py +0 -0
  30. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/physics.py +0 -0
  31. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/robot.py +0 -0
  32. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/trajectory.py +0 -0
  33. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/foundation/water.py +0 -0
  34. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/mapping/__init__.py +0 -0
  35. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/mapping/colmap.py +0 -0
  36. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/mapping/glomap.py +0 -0
  37. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/mapping/pipeline.py +0 -0
  38. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/mapping/utils.py +0 -0
  39. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/setup/__init__.py +0 -0
  40. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/setup/exporter.py +0 -0
  41. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/setup/gsplat.py +0 -0
  42. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/setup/importer.py +0 -0
  43. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/setup/scene.py +0 -0
  44. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics/setup/viewport.py +0 -0
  45. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics.egg-info/SOURCES.txt +0 -0
  46. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics.egg-info/dependency_links.txt +0 -0
  47. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics.egg-info/entry_points.txt +0 -0
  48. {vibephysics-0.2.3 → vibephysics-0.2.4}/src/vibephysics.egg-info/requires.txt +0 -0
  49. {vibephysics-0.2.3 → 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
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
@@ -74,7 +74,64 @@ export CFLAGS="$CFLAGS -fPIC"
74
74
  pip install git+https://github.com/shamangary/glomap.git
75
75
  ```
76
76
 
77
- ## 🎬 Example Results (`sh run_robot.sh`)
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`)
78
135
 
79
136
  ![Result Demo](assets/result_demo.gif)
80
137
 
@@ -293,77 +350,6 @@ exporter.export_fbx('output.fbx', selected_only=True)
293
350
  | USD/USDA/USDC | USD |
294
351
  | Blend (append) | |
295
352
 
296
- ## 🗺️ Mapping & Reconstruction
297
-
298
- VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
299
-
300
- - **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
301
- - **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
302
- - **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
303
-
304
- ### 💻 Usage (Command Line)
305
-
306
- ```bash
307
- # Run GLOMAP pipeline (Fastest - Default)
308
- ./run_glomap.sh --image_path path/to/images
309
-
310
- # Run COLMAP pipeline (Most Robust)
311
- ./run_glomap.sh --image_path path/to/images --engine colmap
312
-
313
- # Advanced options
314
- ./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
315
- ```
316
-
317
- ### 🐍 Usage (Python API)
318
-
319
- ```python
320
- from vibephysics import mapping
321
-
322
- # 1. Simple Usage (Only image_path is REQUIRED)
323
- # Defaults: glomap engine, exhaustive matcher, PINHOLE camera
324
- mapping.glomap_pipeline(image_path="path/to/images")
325
-
326
- # 2. COLMAP Incremental Pipeline
327
- mapping.colmap_pipeline(image_path="path/to/images")
328
-
329
- # 3. Full Configuration (All parameters except image_path are OPTIONAL)
330
- mapping.glomap_pipeline(
331
- image_path="path/to/images", # REQUIRED
332
- output_path="output/dir", # Optional: Defaults to image_path/../mapping_output/
333
- database_path="path/to/database.db", # Optional: Defaults to output_path/sparse/database.db
334
- matcher="exhaustive", # Optional: "exhaustive" (default) or "sequential"
335
- camera_model="PINHOLE", # Optional: "PINHOLE" (default), "SIMPLE_RADIAL", "OPENCV", etc.
336
- verbose=True # Optional: Set to False to suppress logs
337
- )
338
- ```
339
-
340
- | Parameter | Required | Default | Description |
341
- |-----------|----------|---------|-------------|
342
- | **`image_path`** | **Yes** | - | Path to the folder containing raw images. |
343
- | **`output_path`** | No | `mapping_output/` | Directory for results. Creates `sparse/0` and symlinked `images/`. |
344
- | **`database_path`** | No | `database.db` | Optional path to an existing COLMAP database. |
345
- | **`matcher`** | No | `exhaustive` | Matching algorithm: `exhaustive` or `sequential`. |
346
- | **`camera_model`** | No | `PINHOLE` | COLMAP camera model (e.g., `PINHOLE`, `OPENCV`). |
347
-
348
- ### 🎨 Visualization in Blender
349
-
350
- You can load your Colmap/GLOMAP reconstruction directly into Blender for inspection, featuring colored point clouds with high-visibility Geometry Node spheres and correct camera poses.
351
-
352
- ```python
353
- from vibephysics import mapping
354
-
355
- # Load a sparse model folder (containing cameras.bin, points3D.bin etc.)
356
- mapping.load_colmap_reconstruction(
357
- input_path="output/mapping_output/sparse/0",
358
- point_size=0.01 # Adjust point blob size for visibility
359
- )
360
- ```
361
-
362
- **Run the Demo:**
363
- ```bash
364
- # Visualize an existing reconstruction
365
- python examples/colmap_format/demo_glomap.py --sparse /path/to/sparse/0 --point-size 0.02
366
- ```
367
353
 
368
354
  ## Gaussian Splatting (3DGS) (BETA)
369
355
 
@@ -45,7 +45,64 @@ export CFLAGS="$CFLAGS -fPIC"
45
45
  pip install git+https://github.com/shamangary/glomap.git
46
46
  ```
47
47
 
48
- ## 🎬 Example Results (`sh run_robot.sh`)
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`)
49
106
 
50
107
  ![Result Demo](assets/result_demo.gif)
51
108
 
@@ -264,77 +321,6 @@ exporter.export_fbx('output.fbx', selected_only=True)
264
321
  | USD/USDA/USDC | USD |
265
322
  | Blend (append) | |
266
323
 
267
- ## 🗺️ Mapping & Reconstruction
268
-
269
- VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
270
-
271
- - **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
272
- - **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
273
- - **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
274
-
275
- ### 💻 Usage (Command Line)
276
-
277
- ```bash
278
- # Run GLOMAP pipeline (Fastest - Default)
279
- ./run_glomap.sh --image_path path/to/images
280
-
281
- # Run COLMAP pipeline (Most Robust)
282
- ./run_glomap.sh --image_path path/to/images --engine colmap
283
-
284
- # Advanced options
285
- ./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
286
- ```
287
-
288
- ### 🐍 Usage (Python API)
289
-
290
- ```python
291
- from vibephysics import mapping
292
-
293
- # 1. Simple Usage (Only image_path is REQUIRED)
294
- # Defaults: glomap engine, exhaustive matcher, PINHOLE camera
295
- mapping.glomap_pipeline(image_path="path/to/images")
296
-
297
- # 2. COLMAP Incremental Pipeline
298
- mapping.colmap_pipeline(image_path="path/to/images")
299
-
300
- # 3. Full Configuration (All parameters except image_path are OPTIONAL)
301
- mapping.glomap_pipeline(
302
- image_path="path/to/images", # REQUIRED
303
- output_path="output/dir", # Optional: Defaults to image_path/../mapping_output/
304
- database_path="path/to/database.db", # Optional: Defaults to output_path/sparse/database.db
305
- matcher="exhaustive", # Optional: "exhaustive" (default) or "sequential"
306
- camera_model="PINHOLE", # Optional: "PINHOLE" (default), "SIMPLE_RADIAL", "OPENCV", etc.
307
- verbose=True # Optional: Set to False to suppress logs
308
- )
309
- ```
310
-
311
- | Parameter | Required | Default | Description |
312
- |-----------|----------|---------|-------------|
313
- | **`image_path`** | **Yes** | - | Path to the folder containing raw images. |
314
- | **`output_path`** | No | `mapping_output/` | Directory for results. Creates `sparse/0` and symlinked `images/`. |
315
- | **`database_path`** | No | `database.db` | Optional path to an existing COLMAP database. |
316
- | **`matcher`** | No | `exhaustive` | Matching algorithm: `exhaustive` or `sequential`. |
317
- | **`camera_model`** | No | `PINHOLE` | COLMAP camera model (e.g., `PINHOLE`, `OPENCV`). |
318
-
319
- ### 🎨 Visualization in Blender
320
-
321
- You can load your Colmap/GLOMAP reconstruction directly into Blender for inspection, featuring colored point clouds with high-visibility Geometry Node spheres and correct camera poses.
322
-
323
- ```python
324
- from vibephysics import mapping
325
-
326
- # Load a sparse model folder (containing cameras.bin, points3D.bin etc.)
327
- mapping.load_colmap_reconstruction(
328
- input_path="output/mapping_output/sparse/0",
329
- point_size=0.01 # Adjust point blob size for visibility
330
- )
331
- ```
332
-
333
- **Run the Demo:**
334
- ```bash
335
- # Visualize an existing reconstruction
336
- python examples/colmap_format/demo_glomap.py --sparse /path/to/sparse/0 --point-size 0.02
337
- ```
338
324
 
339
325
  ## Gaussian Splatting (3DGS) (BETA)
340
326
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vibephysics"
7
- version = "0.2.3"
7
+ version = "0.2.4"
8
8
  description = "Physics simulation and annotation tools for Blender"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -16,7 +16,7 @@ Usage:
16
16
  Note: This package requires Blender 5.0's Python environment (bpy) for simulation.
17
17
  """
18
18
 
19
- __version__ = "0.2.3"
19
+ __version__ = "0.2.4"
20
20
  __author__ = "Tsun-Yi Yang"
21
21
 
22
22
  # Core modules (non-Blender)
@@ -1,8 +1,9 @@
1
1
  import bpy
2
2
  import pycolmap
3
3
  import numpy as np
4
- from pathlib import Path
5
4
  import math
5
+ import mathutils
6
+ from pathlib import Path
6
7
 
7
8
  def create_camera_object(image, camera, collection, scale=0.1):
8
9
  """
@@ -10,84 +11,86 @@ def create_camera_object(image, camera, collection, scale=0.1):
10
11
  """
11
12
  name = image.name
12
13
 
13
- # Colmap pose is World-to-Camera (R, t)
14
- # pycolmap 3.x uses image.cam_from_world() method
14
+ # 1. Pose: World-to-Camera (SfM) -> Camera-to-World (Blender)
15
15
  if hasattr(image, "cam_from_world") and callable(image.cam_from_world):
16
16
  pose = image.cam_from_world()
17
17
  rot_mat = pose.rotation.matrix()
18
18
  tvec = pose.translation
19
19
  else:
20
- # Fallback for older pycolmap
20
+ # Fallback for older pycolmap (World-to-Camera)
21
21
  qvec = getattr(image, "qvec", np.array([1, 0, 0, 0]))
22
22
  tvec = getattr(image, "tvec", np.zeros(3))
23
- # Manual qvec to rotmat if function is missing
24
- if hasattr(pycolmap, "qvec_to_rotmat"):
25
- rot_mat = pycolmap.qvec_to_rotmat(qvec)
26
- else:
27
- # Standard Hamilton quaternion to rotation matrix
28
- w, x, y, z = qvec
29
- rot_mat = np.array([
30
- [1 - 2*y**2 - 2*z**2, 2*x*y - 2*z*w, 2*x*z + 2*y*w],
31
- [2*x*y + 2*z*w, 1 - 2*x**2 - 2*z**2, 2*y*z - 2*x*w],
32
- [2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x**2 - 2*y**2]
33
- ])
34
-
35
- # Inverse rotation and translation to get Camera-to-World
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)
36
31
  rot_mat_inv = rot_mat.T
37
32
  tvec_inv = -rot_mat_inv @ tvec
38
33
 
39
- # Create Camera Data
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
40
49
  cam_data = bpy.data.cameras.new(name=f"CamData_{name}")
41
50
  cam_obj = bpy.data.objects.new(name=name, object_data=cam_data)
42
51
  collection.objects.link(cam_obj)
43
52
 
44
- # Construct 4x4 matrix in OpenCV frame (X-right, Y-down, Z-forward)
45
- mat_world_cv = np.eye(4)
46
- mat_world_cv[:3, :3] = rot_mat_inv
47
- mat_world_cv[:3, 3] = tvec_inv
48
-
49
- # Convert from OpenCV to Blender coordinate system
50
- # Blender camera looks down -Z, Y is up.
51
- # We rotate 180 degrees around X to flip Y and Z.
52
- transform_matrix = np.array([
53
- [1, 0, 0, 0],
54
- [0, -1, 0, 0],
55
- [0, 0, -1, 0],
56
- [0, 0, 0, 1]
57
- ])
53
+ cam_obj.matrix_world = final_matrix
58
54
 
59
- final_matrix = mat_world_cv @ transform_matrix
60
-
61
- # Assign to object
62
- import mathutils
63
- m = mathutils.Matrix(final_matrix.tolist())
64
- cam_obj.matrix_world = m
65
-
66
- # Set camera intrinsics
67
- # Params mapping depends on camera model
55
+ # 3. Intrinsics: Focal length and Principal Point (Image x, y)
68
56
  width = camera.width
69
57
  height = camera.height
70
- cam_data.sensor_width = 36.0 # standard 36mm sensor
71
-
72
- # f_mm = f_px * sensor_width / width_px
73
- f_px = 1000.0 # fallback
74
-
75
- # Get camera model name
76
- if hasattr(camera, "model") and hasattr(camera.model, "name"):
77
- model = camera.model.name
78
- else:
79
- model = getattr(camera, "model_name", "UNKNOWN")
80
-
81
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
82
85
 
83
- if model in ["SIMPLE_PINHOLE", "SIMPLE_RADIAL"]:
84
- # f, cx, cy
85
- f_px = params[0]
86
- elif model in ["PINHOLE", "OPENCV", "FULL_OPENCV"]:
87
- # fx, fy, cx, cy
88
- f_px = (params[0] + params[1]) / 2.0
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
89
91
 
90
- cam_data.lens = f_px * cam_data.sensor_width / width
92
+ # Set display size for the camera gizmo in viewport
93
+ cam_data.display_size = scale
91
94
 
92
95
  return cam_obj
93
96
 
@@ -249,6 +252,14 @@ def load_colmap_reconstruction(
249
252
  # Apply global rotation to the root
250
253
  root_obj.rotation_mode = 'XYZ'
251
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
252
263
 
253
264
  if import_points:
254
265
  print(f"Importing {len(recon.points3D)} points...")
@@ -257,18 +268,18 @@ def load_colmap_reconstruction(
257
268
 
258
269
  if import_cameras:
259
270
  print(f"Importing {len(recon.images)} cameras...")
271
+ first_cam_obj = None
260
272
  for img_id, image in recon.images.items():
261
273
  if image.camera_id in recon.cameras:
262
274
  cam = recon.cameras[image.camera_id]
263
275
  cam_obj = create_camera_object(image, cam, col, scale=camera_scale)
264
276
  cam_obj.parent = root_obj
265
- # Keep the same world matrix when parenting if the root has no rotation yet
266
- # or just set it relative to parent.
267
- # Since we set root rotation ABOVE, we should set matrix_world AFTER parenting
268
- # or use matrix_local if we want it to be relative.
269
- # The create_camera_object returns an object with matrix_world set for the SfM space.
270
- # If we parent it to root_obj, and then set matrix_world again,
271
- # it will stay in the correct spot while being a child.
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
272
283
 
273
284
  print("Done.")
274
285
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibephysics
3
- Version: 0.2.3
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
@@ -74,7 +74,64 @@ export CFLAGS="$CFLAGS -fPIC"
74
74
  pip install git+https://github.com/shamangary/glomap.git
75
75
  ```
76
76
 
77
- ## 🎬 Example Results (`sh run_robot.sh`)
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`)
78
135
 
79
136
  ![Result Demo](assets/result_demo.gif)
80
137
 
@@ -293,77 +350,6 @@ exporter.export_fbx('output.fbx', selected_only=True)
293
350
  | USD/USDA/USDC | USD |
294
351
  | Blend (append) | |
295
352
 
296
- ## 🗺️ Mapping & Reconstruction
297
-
298
- VibePhysics integrates high-performance Structure-from-Motion (SfM) engines to convert image sequences into 3D reconstructions.
299
-
300
- - **GLOMAP Engine** – Global SfM that is 1-2 orders of magnitude faster than traditional methods.
301
- - **COLMAP Engine** – Industry-standard incremental SfM for robust reconstruction.
302
- - **GSplat Ready** – Automatically generates standard output structures (`sparse/0` and `images/` symlink) ready for instant GSplat training.
303
-
304
- ### 💻 Usage (Command Line)
305
-
306
- ```bash
307
- # Run GLOMAP pipeline (Fastest - Default)
308
- ./run_glomap.sh --image_path path/to/images
309
-
310
- # Run COLMAP pipeline (Most Robust)
311
- ./run_glomap.sh --image_path path/to/images --engine colmap
312
-
313
- # Advanced options
314
- ./run_glomap.sh --image_path path/to/images --matcher sequential --camera_model PINHOLE
315
- ```
316
-
317
- ### 🐍 Usage (Python API)
318
-
319
- ```python
320
- from vibephysics import mapping
321
-
322
- # 1. Simple Usage (Only image_path is REQUIRED)
323
- # Defaults: glomap engine, exhaustive matcher, PINHOLE camera
324
- mapping.glomap_pipeline(image_path="path/to/images")
325
-
326
- # 2. COLMAP Incremental Pipeline
327
- mapping.colmap_pipeline(image_path="path/to/images")
328
-
329
- # 3. Full Configuration (All parameters except image_path are OPTIONAL)
330
- mapping.glomap_pipeline(
331
- image_path="path/to/images", # REQUIRED
332
- output_path="output/dir", # Optional: Defaults to image_path/../mapping_output/
333
- database_path="path/to/database.db", # Optional: Defaults to output_path/sparse/database.db
334
- matcher="exhaustive", # Optional: "exhaustive" (default) or "sequential"
335
- camera_model="PINHOLE", # Optional: "PINHOLE" (default), "SIMPLE_RADIAL", "OPENCV", etc.
336
- verbose=True # Optional: Set to False to suppress logs
337
- )
338
- ```
339
-
340
- | Parameter | Required | Default | Description |
341
- |-----------|----------|---------|-------------|
342
- | **`image_path`** | **Yes** | - | Path to the folder containing raw images. |
343
- | **`output_path`** | No | `mapping_output/` | Directory for results. Creates `sparse/0` and symlinked `images/`. |
344
- | **`database_path`** | No | `database.db` | Optional path to an existing COLMAP database. |
345
- | **`matcher`** | No | `exhaustive` | Matching algorithm: `exhaustive` or `sequential`. |
346
- | **`camera_model`** | No | `PINHOLE` | COLMAP camera model (e.g., `PINHOLE`, `OPENCV`). |
347
-
348
- ### 🎨 Visualization in Blender
349
-
350
- You can load your Colmap/GLOMAP reconstruction directly into Blender for inspection, featuring colored point clouds with high-visibility Geometry Node spheres and correct camera poses.
351
-
352
- ```python
353
- from vibephysics import mapping
354
-
355
- # Load a sparse model folder (containing cameras.bin, points3D.bin etc.)
356
- mapping.load_colmap_reconstruction(
357
- input_path="output/mapping_output/sparse/0",
358
- point_size=0.01 # Adjust point blob size for visibility
359
- )
360
- ```
361
-
362
- **Run the Demo:**
363
- ```bash
364
- # Visualize an existing reconstruction
365
- python examples/colmap_format/demo_glomap.py --sparse /path/to/sparse/0 --point-size 0.02
366
- ```
367
353
 
368
354
  ## Gaussian Splatting (3DGS) (BETA)
369
355
 
File without changes
File without changes
File without changes