conquer3d 0.7.3__tar.gz → 0.7.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.
- {conquer3d-0.7.3/conquer3d.egg-info → conquer3d-0.7.4}/PKG-INFO +21 -10
- {conquer3d-0.7.3 → conquer3d-0.7.4}/README.md +20 -9
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/_C.so +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/dc_data.h +9 -2
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/dmc_data.h +2 -2
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mc.cu +13 -4
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mca.cu +2 -2
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mt_data.h +7 -7
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mtg_data.h +9 -9
- {conquer3d-0.7.3 → conquer3d-0.7.4/conquer3d.egg-info}/PKG-INFO +21 -10
- {conquer3d-0.7.3 → conquer3d-0.7.4}/pyproject.toml +1 -1
- {conquer3d-0.7.3 → conquer3d-0.7.4}/LICENSE +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/MANIFEST.in +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/_C.pyi +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/conversion/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/conversion/grid.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/conversion/mesh.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/conversion/tmesh.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/creation/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/creation/triangle_creation.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/creation/triangle_creation.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/grid.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/data_structure/zcurve.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/chamfer.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/dc.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/dmc.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/flood_fill.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/flood_fill_cf.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/mc.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/mca.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/mt.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/mtg.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/ops/volint.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/primitive/ray.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/binds/primitive/triangle.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/check.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/constants.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/creation/triangle_creation.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/bvh.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/bvh.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/grid.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/grid.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/kdtree.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/zcurve.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/data_structure/zcurve.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/f2x2.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/f3x1.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/f3x3.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/f3x4.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/f4x1.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/f4x4.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/maths.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/ops.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/maths/qef.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/chamfer.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/chamfer.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/dc.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/dc.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/dmc.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/dmc.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/flood_fill.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/flood_fill.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/flood_fill_cf.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/flood_fill_cf.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mc.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mc_data.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mca.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mca_data.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mt.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mt.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mtg.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/mtg.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/volint.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/ops/volint.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/aabb.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/edge.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/gs.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/gs.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/pgs.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/pgs.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/ray.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/primitive/triangle.h +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/csrc/pybind.cpp +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/assets/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/assets/common.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/assets/iphigenia.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/collate/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/collate/mesh.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/collate/sparse_tensor.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/dataset/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/dataset/base_mesh.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/dataset/digit3d.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/dataset/digit3dmv.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/dataset/mesh.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/dataset/redwood.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/transform/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/transform/base.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/transform/ops.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data/transform/vertex.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data_structure/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data_structure/bmesh.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data_structure/grid.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/data_structure/sort.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/io/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/io/obj.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/io/off.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/io/ply.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/delaunay_triangulation.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/diff_marching_cubes.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/diff_marching_tetrahedra_grid.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/distance.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/dpsr.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/dual_contouring.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/dual_marching_cubes.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/marching_cubes.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/marching_cubes_asymptotic.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/marching_tetrahedra.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/marching_tetrahedra_grid.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/ops/volint.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/primitive/__init__.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/primitive/gs.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d/primitive/pgs.py +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d.egg-info/SOURCES.txt +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d.egg-info/dependency_links.txt +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d.egg-info/not-zip-safe +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d.egg-info/requires.txt +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/conquer3d.egg-info/top_level.txt +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/setup.cfg +0 -0
- {conquer3d-0.7.3 → conquer3d-0.7.4}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conquer3d
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Geometric Cuda Tool Box
|
|
5
5
|
Author-email: Do Hoang Khoi <khoido8899@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -60,9 +60,16 @@ Dynamic: license-file
|
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
+
> [!NOTE]
|
|
64
|
+
> The API documentation and the [documentation website](https://khoidoo.github.io/conquer3d/)
|
|
65
|
+
> were written with [Claude](https://claude.ai/code). The library itself — every CUDA kernel,
|
|
66
|
+
> data structure and operator — is the author's own work.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
63
70
|
## 🌟 Overview
|
|
64
71
|
|
|
65
|
-
**Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.
|
|
72
|
+
**Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.3 Billion faces/second** isosurface extraction, exact CAD sharp crease preservation, and memory-efficient spatial acceleration structures.
|
|
66
73
|
|
|
67
74
|
Every operator consumes and produces PyTorch tensors **in place** — no host round-trip, no format conversion — so meshing a field is an operation *inside* a training step rather than a preprocessing stage around it.
|
|
68
75
|
|
|
@@ -115,14 +122,18 @@ The API reference does not stop at the Python surface. It descends through the p
|
|
|
115
122
|
|
|
116
123
|
## ⚡ Benchmarks
|
|
117
124
|
|
|
118
|
-
*
|
|
125
|
+
*Measured on **NVIDIA GeForce RTX 4090** (torch 2.8.0+cu128, CUDA 12.8) on the **Fandisk CAD model** at **$1024^3$ resolution** (5.15M active cells). Timed with CUDA events around the operator alone, median of 7 runs after 2 warm-ups:*
|
|
126
|
+
|
|
127
|
+
| Algorithm | Mesh Output | Extracted Vertices | Extracted Faces / Quads | Latency (ms) | Throughput |
|
|
128
|
+
| :--- | :--- | ---: | ---: | ---: | ---: |
|
|
129
|
+
| **DMC (pure quads)** | Pure Quads | 1,716,384 | 1,716,382 | **2.51 ms** | **684M faces/s** |
|
|
130
|
+
| **Dual Marching Cubes** | Triangles | 1,716,384 | 3,432,764 | **2.62 ms** | **1,311M faces/s** |
|
|
131
|
+
| MC Asymptotic | Triangles | 1,716,382 | 3,432,760 | 2.71 ms | 1,267M faces/s |
|
|
132
|
+
| Dual Contouring | Triangles | 1,716,384 | 3,432,764 | 3.88 ms | 884M faces/s |
|
|
133
|
+
| Marching Cubes | Triangles | 1,716,382 | 3,432,760 | 7.90 ms | 434M faces/s |
|
|
134
|
+
| Marching Tetrahedra | Triangles | 6,113,918 | 12,227,832 | 44.90 ms | 272M faces/s |
|
|
119
135
|
|
|
120
|
-
|
|
121
|
-
| :--- | :--- | :--- | :--- | :---: | :---: | :---: |
|
|
122
|
-
| **Dual Marching Cubes (DMC)** | Triangles | **1,716,386** | **3,432,768** | **3.44 ms** | **~1.0B faces/s** | **Yes** |
|
|
123
|
-
| **Dual Marching Cubes (DMC)** | Pure Quads | **1,716,386** | **1,716,384** | **3.22 ms** | **533M quads/s** | **Yes** |
|
|
124
|
-
| **Dual Contouring (DC + Normals)** | Triangles | 1,716,386 | 3,432,768 | **4.79 ms** | **717M faces/s** | **Yes** |
|
|
125
|
-
| **Marching Cubes Asymptotic (MCA)** | Triangles | 1,716,384 | 3,432,764 | 16.42 ms | **209M faces/s** | **Yes** |
|
|
136
|
+
All figures are produced by `docs/_figures/make_benchmarks.py` and can be reproduced. Sign-mode costs, pipeline setup breakdown and memory scaling are on the **[benchmarks page](https://khoidoo.github.io/conquer3d/benchmarks.html)**.
|
|
126
137
|
|
|
127
138
|
---
|
|
128
139
|
|
|
@@ -132,7 +143,7 @@ The API reference does not stop at the Python surface. It descends through the p
|
|
|
132
143
|
<summary><b>🔷 1. Isosurface Extraction & Meshing</b></summary>
|
|
133
144
|
<br>
|
|
134
145
|
|
|
135
|
-
- **Dual Marching Cubes (`dmc`)**: High-throughput manifold surface extraction with pure quad $(Q, 4)$ or triangle $(F, 3)$ outputs (~1.
|
|
146
|
+
- **Dual Marching Cubes (`dmc`)**: High-throughput manifold surface extraction with pure quad $(Q, 4)$ or triangle $(F, 3)$ outputs (~1.3B faces/s measured).
|
|
136
147
|
- **Dual Contouring (`dc`)**: Sharp CAD crease and mechanical corner preservation via GPU Quadratic Error Function (QEF) solving.
|
|
137
148
|
- **Marching Cubes Asymptotic (`mca`)**: Decider-enhanced Marching Cubes resolving topological face ambiguities on-the-fly.
|
|
138
149
|
- **Differentiable Poisson Surface Reconstruction (`dpsr`, `DPSR`)**: Differentiable spectral Fourier Poisson indicator field solving directly from oriented point clouds.
|
|
@@ -27,9 +27,16 @@
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
> [!NOTE]
|
|
31
|
+
> The API documentation and the [documentation website](https://khoidoo.github.io/conquer3d/)
|
|
32
|
+
> were written with [Claude](https://claude.ai/code). The library itself — every CUDA kernel,
|
|
33
|
+
> data structure and operator — is the author's own work.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
30
37
|
## 🌟 Overview
|
|
31
38
|
|
|
32
|
-
**Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.
|
|
39
|
+
**Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.3 Billion faces/second** isosurface extraction, exact CAD sharp crease preservation, and memory-efficient spatial acceleration structures.
|
|
33
40
|
|
|
34
41
|
Every operator consumes and produces PyTorch tensors **in place** — no host round-trip, no format conversion — so meshing a field is an operation *inside* a training step rather than a preprocessing stage around it.
|
|
35
42
|
|
|
@@ -82,14 +89,18 @@ The API reference does not stop at the Python surface. It descends through the p
|
|
|
82
89
|
|
|
83
90
|
## ⚡ Benchmarks
|
|
84
91
|
|
|
85
|
-
*
|
|
92
|
+
*Measured on **NVIDIA GeForce RTX 4090** (torch 2.8.0+cu128, CUDA 12.8) on the **Fandisk CAD model** at **$1024^3$ resolution** (5.15M active cells). Timed with CUDA events around the operator alone, median of 7 runs after 2 warm-ups:*
|
|
93
|
+
|
|
94
|
+
| Algorithm | Mesh Output | Extracted Vertices | Extracted Faces / Quads | Latency (ms) | Throughput |
|
|
95
|
+
| :--- | :--- | ---: | ---: | ---: | ---: |
|
|
96
|
+
| **DMC (pure quads)** | Pure Quads | 1,716,384 | 1,716,382 | **2.51 ms** | **684M faces/s** |
|
|
97
|
+
| **Dual Marching Cubes** | Triangles | 1,716,384 | 3,432,764 | **2.62 ms** | **1,311M faces/s** |
|
|
98
|
+
| MC Asymptotic | Triangles | 1,716,382 | 3,432,760 | 2.71 ms | 1,267M faces/s |
|
|
99
|
+
| Dual Contouring | Triangles | 1,716,384 | 3,432,764 | 3.88 ms | 884M faces/s |
|
|
100
|
+
| Marching Cubes | Triangles | 1,716,382 | 3,432,760 | 7.90 ms | 434M faces/s |
|
|
101
|
+
| Marching Tetrahedra | Triangles | 6,113,918 | 12,227,832 | 44.90 ms | 272M faces/s |
|
|
86
102
|
|
|
87
|
-
|
|
88
|
-
| :--- | :--- | :--- | :--- | :---: | :---: | :---: |
|
|
89
|
-
| **Dual Marching Cubes (DMC)** | Triangles | **1,716,386** | **3,432,768** | **3.44 ms** | **~1.0B faces/s** | **Yes** |
|
|
90
|
-
| **Dual Marching Cubes (DMC)** | Pure Quads | **1,716,386** | **1,716,384** | **3.22 ms** | **533M quads/s** | **Yes** |
|
|
91
|
-
| **Dual Contouring (DC + Normals)** | Triangles | 1,716,386 | 3,432,768 | **4.79 ms** | **717M faces/s** | **Yes** |
|
|
92
|
-
| **Marching Cubes Asymptotic (MCA)** | Triangles | 1,716,384 | 3,432,764 | 16.42 ms | **209M faces/s** | **Yes** |
|
|
103
|
+
All figures are produced by `docs/_figures/make_benchmarks.py` and can be reproduced. Sign-mode costs, pipeline setup breakdown and memory scaling are on the **[benchmarks page](https://khoidoo.github.io/conquer3d/benchmarks.html)**.
|
|
93
104
|
|
|
94
105
|
---
|
|
95
106
|
|
|
@@ -99,7 +110,7 @@ The API reference does not stop at the Python surface. It descends through the p
|
|
|
99
110
|
<summary><b>🔷 1. Isosurface Extraction & Meshing</b></summary>
|
|
100
111
|
<br>
|
|
101
112
|
|
|
102
|
-
- **Dual Marching Cubes (`dmc`)**: High-throughput manifold surface extraction with pure quad $(Q, 4)$ or triangle $(F, 3)$ outputs (~1.
|
|
113
|
+
- **Dual Marching Cubes (`dmc`)**: High-throughput manifold surface extraction with pure quad $(Q, 4)$ or triangle $(F, 3)$ outputs (~1.3B faces/s measured).
|
|
103
114
|
- **Dual Contouring (`dc`)**: Sharp CAD crease and mechanical corner preservation via GPU Quadratic Error Function (QEF) solving.
|
|
104
115
|
- **Marching Cubes Asymptotic (`mca`)**: Decider-enhanced Marching Cubes resolving topological face ambiguities on-the-fly.
|
|
105
116
|
- **Differentiable Poisson Surface Reconstruction (`dpsr`, `DPSR`)**: Differentiable spectral Fourier Poisson indicator field solving directly from oriented point clouds.
|
|
Binary file
|
|
@@ -59,13 +59,20 @@ static __constant__ float dc_corner_uvw[8][3] = {
|
|
|
59
59
|
* deterministically to one of four quadrant slots. Because adjacent cells agree on this
|
|
60
60
|
* mapping, the dual quad around a shared edge is assembled consistently from all four
|
|
61
61
|
* incident cells.
|
|
62
|
+
*
|
|
63
|
+
* Slots 0-3 must walk the four incident cells **counter-clockwise about the edge's own
|
|
64
|
+
* positive axis**, and all three edge families must agree on that handedness -- otherwise
|
|
65
|
+
* the faces of one family are wound backwards relative to the rest and the extracted mesh
|
|
66
|
+
* has inconsistent normals. The right-handed plane perpendicular to each axis is $(Y, Z)$
|
|
67
|
+
* for $+X$, $(Z, X)$ for $+Y$ and $(X, Y)$ for $+Z$; note that $+Y$ pairs with $(Z, X)$ and
|
|
68
|
+
* not $(X, Z)$, which is the easy mistake here.
|
|
62
69
|
*/
|
|
63
70
|
static __constant__ int dc_edge_quadrant[12] = {
|
|
64
71
|
0, // e=0 (+X) -> slot 0
|
|
65
72
|
3, // e=1 (+Y) -> slot 3
|
|
66
|
-
|
|
73
|
+
1, // e=2 (+X) -> slot 1
|
|
67
74
|
0, // e=3 (+Y) -> slot 0
|
|
68
|
-
|
|
75
|
+
3, // e=4 (+X) -> slot 3
|
|
69
76
|
2, // e=5 (+Y) -> slot 2
|
|
70
77
|
2, // e=6 (+X) -> slot 2
|
|
71
78
|
1, // e=7 (+Y) -> slot 1
|
|
@@ -79,9 +79,9 @@ static __constant__ float dmc_corner_uvw[8][3] = {
|
|
|
79
79
|
static __constant__ int dmc_edge_quadrant[12] = {
|
|
80
80
|
0, // e=0 (+X) -> slot 0
|
|
81
81
|
3, // e=1 (+Y) -> slot 3
|
|
82
|
-
|
|
82
|
+
1, // e=2 (+X) -> slot 1
|
|
83
83
|
0, // e=3 (+Y) -> slot 0
|
|
84
|
-
|
|
84
|
+
3, // e=4 (+X) -> slot 3
|
|
85
85
|
2, // e=5 (+Y) -> slot 2
|
|
86
86
|
2, // e=6 (+X) -> slot 2
|
|
87
87
|
1, // e=7 (+Y) -> slot 1
|
|
@@ -616,8 +616,15 @@ __global__ void interpolate_vertices_kernel(
|
|
|
616
616
|
* @param[in] voxel_triangle_prefix_sums Device array of per-voxel output offsets.
|
|
617
617
|
* @param[out] out_triangles Device array receiving triangle vertex index triples.
|
|
618
618
|
* @note Launched with `NTHREADS` threads per block over a 1D grid.
|
|
619
|
-
* @note
|
|
620
|
-
*
|
|
619
|
+
* @note The implementation is based on Bourke implementation at http://paulbourke.net/geometry/polygonise/.
|
|
620
|
+
* @note The adatation to CUDA at first is normal inconsistent where all normals are facing inwards.
|
|
621
|
+
* @note The canonical Lorensen-Cline / Bourke ::triTable is written for the convention
|
|
622
|
+
* that a corner bit is set when the corner is *below* the isolevel, and it winds each
|
|
623
|
+
* triangle so the right-hand normal points towards that below-isolevel region. For a
|
|
624
|
+
* signed distance field, below-isolevel is the *interior*, so emitting the table row
|
|
625
|
+
* verbatim yields inward-facing normals. The last two indices are therefore swapped on
|
|
626
|
+
* write, which reverses the winding and gives outward-facing normals for a field that is
|
|
627
|
+
* negative inside -- matching Dual Contouring and the rest of the library.
|
|
621
628
|
*/
|
|
622
629
|
__global__ void assemble_triangles_kernel(
|
|
623
630
|
const uint32_t num_active_voxels,
|
|
@@ -648,9 +655,11 @@ __global__ void assemble_triangles_kernel(
|
|
|
648
655
|
uint32_t v1 = voxel_edge_to_vert_idx[active_voxel_idx * 12 + edge1];
|
|
649
656
|
uint32_t v2 = voxel_edge_to_vert_idx[active_voxel_idx * 12 + edge2];
|
|
650
657
|
|
|
658
|
+
// Reversed winding: see the note above. The table's own order points the
|
|
659
|
+
// normal into the solid for a negative-inside field.
|
|
651
660
|
out_triangles[(start_tri_idx + tri_count) * 3 + 0] = v0;
|
|
652
|
-
out_triangles[(start_tri_idx + tri_count) * 3 + 1] =
|
|
653
|
-
out_triangles[(start_tri_idx + tri_count) * 3 + 2] =
|
|
661
|
+
out_triangles[(start_tri_idx + tri_count) * 3 + 1] = v2;
|
|
662
|
+
out_triangles[(start_tri_idx + tri_count) * 3 + 2] = v1;
|
|
654
663
|
|
|
655
664
|
tri_count++;
|
|
656
665
|
}
|
|
@@ -310,8 +310,8 @@ __global__ void generate_edges_and_triangles_mca_kernel(
|
|
|
310
310
|
for (int t = 0; t < 5 && tri_edges[t * 3] != -1; ++t) {
|
|
311
311
|
int local_edges[3] = {
|
|
312
312
|
tri_edges[t * 3 + 0],
|
|
313
|
-
tri_edges[t * 3 +
|
|
314
|
-
tri_edges[t * 3 +
|
|
313
|
+
tri_edges[t * 3 + 2],
|
|
314
|
+
tri_edges[t * 3 + 1]
|
|
315
315
|
};
|
|
316
316
|
#pragma unroll
|
|
317
317
|
for (int e_idx = 0; e_idx < 3; ++e_idx) {
|
|
@@ -85,16 +85,16 @@ __constant__ int tetTriTable[16][7] = {
|
|
|
85
85
|
{-1, -1, -1, -1, -1, -1, -1}, // 0x00
|
|
86
86
|
{ 0, 1, 2, -1, -1, -1, -1}, // 0x01
|
|
87
87
|
{ 0, 4, 3, -1, -1, -1, -1}, // 0x02
|
|
88
|
-
{
|
|
88
|
+
{ 1, 2, 4, 1, 4, 3, -1}, // 0x03
|
|
89
89
|
{ 1, 3, 5, -1, -1, -1, -1}, // 0x04
|
|
90
90
|
{ 0, 5, 2, 0, 3, 5, -1}, // 0x05
|
|
91
|
-
{ 0, 4, 5, 0,
|
|
92
|
-
{ 2,
|
|
93
|
-
{ 2,
|
|
94
|
-
{ 0,
|
|
95
|
-
{ 0,
|
|
91
|
+
{ 0, 4, 5, 0, 5, 1, -1}, // 0x06
|
|
92
|
+
{ 2, 4, 5, -1, -1, -1, -1}, // 0x07
|
|
93
|
+
{ 2, 5, 4, -1, -1, -1, -1}, // 0x08
|
|
94
|
+
{ 0, 1, 5, 0, 5, 4, -1}, // 0x09
|
|
95
|
+
{ 0, 5, 3, 0, 2, 5, -1}, // 0x0A
|
|
96
96
|
{ 1, 5, 3, -1, -1, -1, -1}, // 0x0B
|
|
97
|
-
{
|
|
97
|
+
{ 1, 3, 4, 1, 4, 2, -1}, // 0x0C
|
|
98
98
|
{ 0, 3, 4, -1, -1, -1, -1}, // 0x0D
|
|
99
99
|
{ 0, 2, 1, -1, -1, -1, -1}, // 0x0E
|
|
100
100
|
{-1, -1, -1, -1, -1, -1, -1} // 0x0F
|
|
@@ -25,10 +25,10 @@ namespace mtg {
|
|
|
25
25
|
*/
|
|
26
26
|
__constant__ int mtg_tets[6][4] = {
|
|
27
27
|
{0, 2, 3, 7},
|
|
28
|
-
{0, 2,
|
|
28
|
+
{0, 2, 7, 6},
|
|
29
29
|
{0, 4, 6, 7},
|
|
30
30
|
{0, 6, 1, 2},
|
|
31
|
-
{0, 6,
|
|
31
|
+
{0, 6, 4, 1},
|
|
32
32
|
{5, 6, 1, 4}
|
|
33
33
|
};
|
|
34
34
|
|
|
@@ -60,16 +60,16 @@ __constant__ int mtg_triTable[16][7] = {
|
|
|
60
60
|
{-1, -1, -1, -1, -1, -1, -1}, // 0x00
|
|
61
61
|
{ 0, 1, 2, -1, -1, -1, -1}, // 0x01
|
|
62
62
|
{ 0, 4, 3, -1, -1, -1, -1}, // 0x02
|
|
63
|
-
{
|
|
63
|
+
{ 1, 2, 4, 1, 4, 3, -1}, // 0x03
|
|
64
64
|
{ 1, 3, 5, -1, -1, -1, -1}, // 0x04
|
|
65
65
|
{ 0, 5, 2, 0, 3, 5, -1}, // 0x05
|
|
66
|
-
{ 0, 4, 5, 0,
|
|
67
|
-
{ 2,
|
|
68
|
-
{ 2,
|
|
69
|
-
{ 0,
|
|
70
|
-
{ 0,
|
|
66
|
+
{ 0, 4, 5, 0, 5, 1, -1}, // 0x06
|
|
67
|
+
{ 2, 4, 5, -1, -1, -1, -1}, // 0x07
|
|
68
|
+
{ 2, 5, 4, -1, -1, -1, -1}, // 0x08
|
|
69
|
+
{ 0, 1, 5, 0, 5, 4, -1}, // 0x09
|
|
70
|
+
{ 0, 5, 3, 0, 2, 5, -1}, // 0x0A
|
|
71
71
|
{ 1, 5, 3, -1, -1, -1, -1}, // 0x0B
|
|
72
|
-
{
|
|
72
|
+
{ 1, 3, 4, 1, 4, 2, -1}, // 0x0C
|
|
73
73
|
{ 0, 3, 4, -1, -1, -1, -1}, // 0x0D
|
|
74
74
|
{ 0, 2, 1, -1, -1, -1, -1}, // 0x0E
|
|
75
75
|
{-1, -1, -1, -1, -1, -1, -1} // 0x0F
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conquer3d
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Geometric Cuda Tool Box
|
|
5
5
|
Author-email: Do Hoang Khoi <khoido8899@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -60,9 +60,16 @@ Dynamic: license-file
|
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
+
> [!NOTE]
|
|
64
|
+
> The API documentation and the [documentation website](https://khoidoo.github.io/conquer3d/)
|
|
65
|
+
> were written with [Claude](https://claude.ai/code). The library itself — every CUDA kernel,
|
|
66
|
+
> data structure and operator — is the author's own work.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
63
70
|
## 🌟 Overview
|
|
64
71
|
|
|
65
|
-
**Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.
|
|
72
|
+
**Conquer3D** is an ultra-fast, GPU-native computational geometry and differentiable spatial computing library engineered in **PyTorch and CUDA**. Designed from the ground up for 3D computer vision, generative AI, neural surface reconstruction, and differentiable rendering, **Conquer3D** delivers up to **~1.3 Billion faces/second** isosurface extraction, exact CAD sharp crease preservation, and memory-efficient spatial acceleration structures.
|
|
66
73
|
|
|
67
74
|
Every operator consumes and produces PyTorch tensors **in place** — no host round-trip, no format conversion — so meshing a field is an operation *inside* a training step rather than a preprocessing stage around it.
|
|
68
75
|
|
|
@@ -115,14 +122,18 @@ The API reference does not stop at the Python surface. It descends through the p
|
|
|
115
122
|
|
|
116
123
|
## ⚡ Benchmarks
|
|
117
124
|
|
|
118
|
-
*
|
|
125
|
+
*Measured on **NVIDIA GeForce RTX 4090** (torch 2.8.0+cu128, CUDA 12.8) on the **Fandisk CAD model** at **$1024^3$ resolution** (5.15M active cells). Timed with CUDA events around the operator alone, median of 7 runs after 2 warm-ups:*
|
|
126
|
+
|
|
127
|
+
| Algorithm | Mesh Output | Extracted Vertices | Extracted Faces / Quads | Latency (ms) | Throughput |
|
|
128
|
+
| :--- | :--- | ---: | ---: | ---: | ---: |
|
|
129
|
+
| **DMC (pure quads)** | Pure Quads | 1,716,384 | 1,716,382 | **2.51 ms** | **684M faces/s** |
|
|
130
|
+
| **Dual Marching Cubes** | Triangles | 1,716,384 | 3,432,764 | **2.62 ms** | **1,311M faces/s** |
|
|
131
|
+
| MC Asymptotic | Triangles | 1,716,382 | 3,432,760 | 2.71 ms | 1,267M faces/s |
|
|
132
|
+
| Dual Contouring | Triangles | 1,716,384 | 3,432,764 | 3.88 ms | 884M faces/s |
|
|
133
|
+
| Marching Cubes | Triangles | 1,716,382 | 3,432,760 | 7.90 ms | 434M faces/s |
|
|
134
|
+
| Marching Tetrahedra | Triangles | 6,113,918 | 12,227,832 | 44.90 ms | 272M faces/s |
|
|
119
135
|
|
|
120
|
-
|
|
121
|
-
| :--- | :--- | :--- | :--- | :---: | :---: | :---: |
|
|
122
|
-
| **Dual Marching Cubes (DMC)** | Triangles | **1,716,386** | **3,432,768** | **3.44 ms** | **~1.0B faces/s** | **Yes** |
|
|
123
|
-
| **Dual Marching Cubes (DMC)** | Pure Quads | **1,716,386** | **1,716,384** | **3.22 ms** | **533M quads/s** | **Yes** |
|
|
124
|
-
| **Dual Contouring (DC + Normals)** | Triangles | 1,716,386 | 3,432,768 | **4.79 ms** | **717M faces/s** | **Yes** |
|
|
125
|
-
| **Marching Cubes Asymptotic (MCA)** | Triangles | 1,716,384 | 3,432,764 | 16.42 ms | **209M faces/s** | **Yes** |
|
|
136
|
+
All figures are produced by `docs/_figures/make_benchmarks.py` and can be reproduced. Sign-mode costs, pipeline setup breakdown and memory scaling are on the **[benchmarks page](https://khoidoo.github.io/conquer3d/benchmarks.html)**.
|
|
126
137
|
|
|
127
138
|
---
|
|
128
139
|
|
|
@@ -132,7 +143,7 @@ The API reference does not stop at the Python surface. It descends through the p
|
|
|
132
143
|
<summary><b>🔷 1. Isosurface Extraction & Meshing</b></summary>
|
|
133
144
|
<br>
|
|
134
145
|
|
|
135
|
-
- **Dual Marching Cubes (`dmc`)**: High-throughput manifold surface extraction with pure quad $(Q, 4)$ or triangle $(F, 3)$ outputs (~1.
|
|
146
|
+
- **Dual Marching Cubes (`dmc`)**: High-throughput manifold surface extraction with pure quad $(Q, 4)$ or triangle $(F, 3)$ outputs (~1.3B faces/s measured).
|
|
136
147
|
- **Dual Contouring (`dc`)**: Sharp CAD crease and mechanical corner preservation via GPU Quadratic Error Function (QEF) solving.
|
|
137
148
|
- **Marching Cubes Asymptotic (`mca`)**: Decider-enhanced Marching Cubes resolving topological face ambiguities on-the-fly.
|
|
138
149
|
- **Differentiable Poisson Surface Reconstruction (`dpsr`, `DPSR`)**: Differentiable spectral Fourier Poisson indicator field solving directly from oriented point clouds.
|
|
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
|
|
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
|
|
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
|
|
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
|