conquer3d 0.3.4__tar.gz → 0.3.9__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.3.4/conquer3d.egg-info → conquer3d-0.3.9}/PKG-INFO +3 -1
- {conquer3d-0.3.4 → conquer3d-0.3.9}/README.md +1 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/_C.so +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/creation/triangle_creation.py +16 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/creation/triangle_creation.cpp +11 -0
- conquer3d-0.3.9/conquer3d/csrc/binds/data_structure/zcurve.cpp +32 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/creation/triangle_creation.h +25 -0
- conquer3d-0.3.9/conquer3d/csrc/data_structure/zcurve.cu +27 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/zcurve.h +10 -5
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/pybind.cpp +2 -0
- conquer3d-0.3.9/conquer3d/data/assets/__init__.py +2 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/assets/common.py +7 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/assets/iphigenia.py +7 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/dataset/digit3d.py +29 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data_structure/__init__.py +3 -1
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data_structure/grid.py +18 -1
- conquer3d-0.3.9/conquer3d/data_structure/sort.py +37 -0
- conquer3d-0.3.9/conquer3d/io/__init__.py +2 -0
- conquer3d-0.3.9/conquer3d/io/obj.py +38 -0
- conquer3d-0.3.9/conquer3d/io/off.py +20 -0
- conquer3d-0.3.9/conquer3d/ops/__init__.py +19 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/ops/delaunay_triangulation.py +0 -1
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/ops/distance.py +27 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9/conquer3d.egg-info}/PKG-INFO +3 -1
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d.egg-info/SOURCES.txt +3 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d.egg-info/requires.txt +1 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/pyproject.toml +2 -1
- conquer3d-0.3.4/conquer3d/data/transform/__init__.py +0 -0
- conquer3d-0.3.4/conquer3d/io/__init__.py +0 -0
- conquer3d-0.3.4/conquer3d/io/obj.py +0 -46
- conquer3d-0.3.4/conquer3d/io/off.py +0 -84
- conquer3d-0.3.4/conquer3d/ops/__init__.py +0 -10
- {conquer3d-0.3.4 → conquer3d-0.3.9}/LICENSE +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/MANIFEST.in +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/_C.pyi +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/conversion/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/conversion/grid.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/conversion/mesh.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/creation/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/bvh.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/grid.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/gs_bvh.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/kdtree.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/mesh_bvh.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/pgs_bvh.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/data_structure/triangle_mesh.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/ops/chamfer.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/ops/mc.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/primitive/gs.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/primitive/pgs.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/primitive/ray.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/binds/primitive/triangle.cpp +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/check.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/constants.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/bvh.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/bvh.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/gs_bvh.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/kdtree.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/kdtree.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/mesh_bvh.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/mesh_bvh.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/pgs_bvh.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/triangle_mesh.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/data_structure/triangle_mesh.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/f2x2.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/f3x1.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/f3x3.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/f3x4.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/f4x1.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/f4x4.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/maths.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/maths/ops.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/ops/chamfer.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/ops/chamfer.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/ops/mc.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/ops/mc.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/ops/mc_data.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/aabb.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/edge.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/gs.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/gs.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/gs_aabb.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/gs_math.cuh +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/pgs.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/pgs.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/pgs_aabb.cu +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/pgs_math.cuh +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/ray.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/csrc/primitive/triangle.h +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/__init__.py +0 -0
- {conquer3d-0.3.4/conquer3d/data/assets → conquer3d-0.3.9/conquer3d/data/collate}/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/collate/mesh.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/collate/sparse_tensor.py +0 -0
- {conquer3d-0.3.4/conquer3d/data/collate → conquer3d-0.3.9/conquer3d/data/dataset}/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/dataset/base_mesh.py +0 -0
- {conquer3d-0.3.4/conquer3d/data/dataset → conquer3d-0.3.9/conquer3d/data/transform}/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/transform/base.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/transform/ops.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data/transform/vertex.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/data_structure/bmesh.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/ops/diff_marching_cubes.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/ops/marching_cubes.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/ops/marching_tetrahedra.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/primitive/__init__.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/primitive/gs.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d/primitive/pgs.py +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d.egg-info/dependency_links.txt +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d.egg-info/not-zip-safe +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/conquer3d.egg-info/top_level.txt +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/setup.cfg +0 -0
- {conquer3d-0.3.4 → conquer3d-0.3.9}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conquer3d
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
4
4
|
Summary: Geometric Cuda Tool Box
|
|
5
5
|
Author-email: Do Hoang Khoi <khoido8899@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.9
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: torch>=2.0.0
|
|
16
|
+
Requires-Dist: meshio>=5.3.5
|
|
16
17
|
Requires-Dist: gdown
|
|
17
18
|
Provides-Extra: cuda
|
|
18
19
|
Requires-Dist: cuda-toolkit==12.8.2; extra == "cuda"
|
|
@@ -49,6 +50,7 @@ pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
|
49
50
|
```bash
|
|
50
51
|
conda create -c conda-forge -n geocutool python=3.10 gxx_linux-64=13 gcc_linux-64=13 -y
|
|
51
52
|
conda activate geocutool
|
|
53
|
+
conda install -c conda-forge sparsehash -y
|
|
52
54
|
|
|
53
55
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
54
56
|
|
|
@@ -20,6 +20,7 @@ pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
|
20
20
|
```bash
|
|
21
21
|
conda create -c conda-forge -n geocutool python=3.10 gxx_linux-64=13 gcc_linux-64=13 -y
|
|
22
22
|
conda activate geocutool
|
|
23
|
+
conda install -c conda-forge sparsehash -y
|
|
23
24
|
|
|
24
25
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
25
26
|
|
|
Binary file
|
|
@@ -2,6 +2,7 @@ import torch
|
|
|
2
2
|
from typing import Tuple
|
|
3
3
|
|
|
4
4
|
from .._C import create_sphere as create_sphere_c
|
|
5
|
+
from .._C import create_tetrahedra as create_tetrahedra_c
|
|
5
6
|
|
|
6
7
|
def create_sphere(
|
|
7
8
|
sectors: int = 32,
|
|
@@ -21,3 +22,18 @@ def create_sphere(
|
|
|
21
22
|
triangles: (M, 3) int32 tensor of triangle indices.
|
|
22
23
|
"""
|
|
23
24
|
return create_sphere_c(sectors, stacks, radius)
|
|
25
|
+
|
|
26
|
+
def create_tetrahedra(
|
|
27
|
+
radius: float = 1.0
|
|
28
|
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
|
29
|
+
"""
|
|
30
|
+
Creates a regular tetrahedron returning (vertices, triangles) tensors on the CPU.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
radius (float, optional): Circumscribed radius of the tetrahedron. Defaults to 1.0.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
vertices: (4, 3) float32 tensor of vertex positions.
|
|
37
|
+
triangles: (4, 3) int32 tensor of triangle indices.
|
|
38
|
+
"""
|
|
39
|
+
return create_tetrahedra_c(radius)
|
|
@@ -17,6 +17,17 @@ Args:
|
|
|
17
17
|
stacks (int): The number of latitudinal stacks. Defaults to 16.
|
|
18
18
|
radius (float): The radius of the sphere. Defaults to 1.0.
|
|
19
19
|
|
|
20
|
+
Returns:
|
|
21
|
+
tuple: A tuple containing the vertices tensor and the triangles tensor.
|
|
22
|
+
)doc");
|
|
23
|
+
|
|
24
|
+
m.def("create_tetrahedra", &triangle_creation::create_tetrahedra,
|
|
25
|
+
py::arg("radius") = 1.0f,
|
|
26
|
+
R"doc(Creates a regular tetrahedron returning (vertices, triangles) tensors on the CPU.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
radius (float): The circumscribed radius of the tetrahedron. Defaults to 1.0.
|
|
30
|
+
|
|
20
31
|
Returns:
|
|
21
32
|
tuple: A tuple containing the vertices tensor and the triangles tensor.
|
|
22
33
|
)doc");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#include <torch/extension.h>
|
|
2
|
+
#include <pybind11/pybind11.h>
|
|
3
|
+
#include "../../data_structure/zcurve.h"
|
|
4
|
+
#include "../../check.h"
|
|
5
|
+
|
|
6
|
+
namespace py = pybind11;
|
|
7
|
+
|
|
8
|
+
torch::Tensor compute_zcurve_wrapper(torch::Tensor points)
|
|
9
|
+
{
|
|
10
|
+
CHECK_INPUT(points);
|
|
11
|
+
|
|
12
|
+
// We expect points to be [..., 3]
|
|
13
|
+
auto num_points = points.numel() / 3;
|
|
14
|
+
const float *p_points = points.data_ptr<float>();
|
|
15
|
+
|
|
16
|
+
// Output is same shape as points but without the last dim
|
|
17
|
+
auto sizes = points.sizes().vec();
|
|
18
|
+
sizes.pop_back();
|
|
19
|
+
|
|
20
|
+
torch::Tensor codes = torch::empty(sizes, points.options().dtype(torch::kInt64));
|
|
21
|
+
int64_t *p_codes = codes.data_ptr<int64_t>();
|
|
22
|
+
|
|
23
|
+
zcurve::compute_zcurve(p_points, num_points, p_codes);
|
|
24
|
+
|
|
25
|
+
return codes;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
void bind_ds_zcurve(py::module_ &m)
|
|
29
|
+
{
|
|
30
|
+
m.def("compute_zcurve", &compute_zcurve_wrapper, "Compute Z-curve codes for a batch of points",
|
|
31
|
+
py::arg("points"));
|
|
32
|
+
}
|
|
@@ -92,6 +92,31 @@ namespace triangle_creation
|
|
|
92
92
|
return {V, F};
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
inline std::tuple<torch::Tensor, torch::Tensor> create_tetrahedra(float radius = 1.0f) {
|
|
96
|
+
float a = radius / std::sqrt(3.0f);
|
|
97
|
+
std::vector<float> vertices = {
|
|
98
|
+
a, a, a,
|
|
99
|
+
-a, -a, a,
|
|
100
|
+
-a, a, -a,
|
|
101
|
+
a, -a, -a
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
std::vector<int> triangles = {
|
|
105
|
+
0, 2, 1,
|
|
106
|
+
0, 1, 3,
|
|
107
|
+
0, 3, 2,
|
|
108
|
+
1, 2, 3
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
auto opts_f32 = torch::TensorOptions().dtype(torch::kFloat32);
|
|
112
|
+
auto opts_i32 = torch::TensorOptions().dtype(torch::kInt32);
|
|
113
|
+
|
|
114
|
+
torch::Tensor V = torch::from_blob(vertices.data(), {4, 3}, opts_f32).clone();
|
|
115
|
+
torch::Tensor F = torch::from_blob(triangles.data(), {4, 3}, opts_i32).clone();
|
|
116
|
+
|
|
117
|
+
return {V, F};
|
|
118
|
+
}
|
|
119
|
+
|
|
95
120
|
}
|
|
96
121
|
|
|
97
122
|
#endif // TRIANGLE_CREATION_H
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#include "zcurve.h"
|
|
2
|
+
#include "../constants.h"
|
|
3
|
+
#include <cuda_runtime.h>
|
|
4
|
+
|
|
5
|
+
namespace zcurve
|
|
6
|
+
{
|
|
7
|
+
|
|
8
|
+
__global__ void compute_zcurve_kernel(const float3 *__restrict__ points, uint32_t num_points, int64_t *__restrict__ codes)
|
|
9
|
+
{
|
|
10
|
+
uint32_t idx = blockIdx.x * blockDim.x + threadIdx.x;
|
|
11
|
+
if (idx >= num_points)
|
|
12
|
+
return;
|
|
13
|
+
|
|
14
|
+
float3 p = points[idx];
|
|
15
|
+
unsigned int code = morton3D(p.x, p.y, p.z);
|
|
16
|
+
codes[idx] = (int64_t)code;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void compute_zcurve(const float *points, uint32_t num_points, int64_t *codes)
|
|
20
|
+
{
|
|
21
|
+
uint32_t threads = NTHREADS;
|
|
22
|
+
uint32_t blocks = (num_points + threads - 1) / threads;
|
|
23
|
+
|
|
24
|
+
compute_zcurve_kernel<<<blocks, threads>>>((const float3 *)points, num_points, codes);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
namespace zcurve
|
|
8
8
|
{
|
|
9
|
-
__device__ unsigned int expandBits(unsigned int v)
|
|
9
|
+
inline __device__ unsigned int expandBits(unsigned int v)
|
|
10
10
|
{
|
|
11
11
|
v = (v * 0x00010001u) & 0xFF0000FFu;
|
|
12
12
|
v = (v * 0x00000101u) & 0x0F00F00Fu;
|
|
@@ -15,16 +15,21 @@ namespace zcurve
|
|
|
15
15
|
return v;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
__device__ unsigned int morton3D(float x, float y, float z)
|
|
18
|
+
inline __device__ unsigned int morton3D(float x, float y, float z)
|
|
19
19
|
{
|
|
20
|
-
x =
|
|
21
|
-
y =
|
|
22
|
-
z =
|
|
20
|
+
x = x * 1024.0f;
|
|
21
|
+
y = y * 1024.0f;
|
|
22
|
+
z = z * 1024.0f;
|
|
23
|
+
x = x < 0.0f ? 0.0f : (x > 1023.0f ? 1023.0f : x);
|
|
24
|
+
y = y < 0.0f ? 0.0f : (y > 1023.0f ? 1023.0f : y);
|
|
25
|
+
z = z < 0.0f ? 0.0f : (z > 1023.0f ? 1023.0f : z);
|
|
23
26
|
unsigned int xx = expandBits((unsigned int)x);
|
|
24
27
|
unsigned int yy = expandBits((unsigned int)y);
|
|
25
28
|
unsigned int zz = expandBits((unsigned int)z);
|
|
26
29
|
return xx * 4 + yy * 2 + zz;
|
|
27
30
|
}
|
|
31
|
+
|
|
32
|
+
void compute_zcurve(const float *points, uint32_t num_points, int64_t *codes);
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
#endif // ZCURVE_H
|
|
@@ -15,6 +15,7 @@ void bind_ds_pgs_bvh(py::module_& m);
|
|
|
15
15
|
void bind_ds_mesh_bvh(py::module_& m);
|
|
16
16
|
void bind_ds_triangle_mesh(py::module_& m);
|
|
17
17
|
void bind_ds_grid(py::module_& m);
|
|
18
|
+
void bind_ds_zcurve(py::module_& m);
|
|
18
19
|
|
|
19
20
|
void bind_creation_triangle_creation(py::module_& m);
|
|
20
21
|
|
|
@@ -36,6 +37,7 @@ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
|
|
|
36
37
|
bind_ds_mesh_bvh(m);
|
|
37
38
|
bind_ds_triangle_mesh(m);
|
|
38
39
|
bind_ds_grid(m);
|
|
40
|
+
bind_ds_zcurve(m);
|
|
39
41
|
|
|
40
42
|
bind_creation_triangle_creation(m);
|
|
41
43
|
|
|
@@ -33,6 +33,13 @@ class Common3D:
|
|
|
33
33
|
print(f"Reading {self.filename}...")
|
|
34
34
|
self.vertices, self.faces, self.colors = read_obj(obj_path)
|
|
35
35
|
|
|
36
|
+
def get(self):
|
|
37
|
+
return (
|
|
38
|
+
self.vertices.clone(),
|
|
39
|
+
self.faces.clone(),
|
|
40
|
+
self.colors.clone() if self.colors is not None else None
|
|
41
|
+
)
|
|
42
|
+
|
|
36
43
|
# --- Child Classes ---
|
|
37
44
|
|
|
38
45
|
class Alligator(Common3D):
|
|
@@ -15,6 +15,7 @@ class Iphiagenia:
|
|
|
15
15
|
self.download_dir = os.path.expanduser(download_dir)
|
|
16
16
|
self.vertices = None
|
|
17
17
|
self.faces = None
|
|
18
|
+
self.colors = None
|
|
18
19
|
|
|
19
20
|
self._load()
|
|
20
21
|
|
|
@@ -41,3 +42,9 @@ class Iphiagenia:
|
|
|
41
42
|
# off_file is a file-like object of bytes.
|
|
42
43
|
# read_off will automatically decode and parse it.
|
|
43
44
|
self.vertices, self.faces = read_off(off_file)
|
|
45
|
+
def get(self):
|
|
46
|
+
return (
|
|
47
|
+
self.vertices.clone(),
|
|
48
|
+
self.faces.clone(),
|
|
49
|
+
self.colors.clone() if self.colors is not None else None
|
|
50
|
+
)
|
|
@@ -130,3 +130,32 @@ class SparseDigit3D(Digit3D):
|
|
|
130
130
|
sparse_idx_grids = sparse_coords[:, 1:]
|
|
131
131
|
|
|
132
132
|
return sparse_idx_grids, sparse_sdfs, label
|
|
133
|
+
|
|
134
|
+
class PointDigit3D(Digit3D):
|
|
135
|
+
"""
|
|
136
|
+
Digit3D Dataset that constructs a point cloud by sampling on the mesh.
|
|
137
|
+
"""
|
|
138
|
+
def __init__(self, root: str = "~/.conquer3d/", train: bool = True, transform=None, download: bool = False,
|
|
139
|
+
cached: bool = False, num_points: int = 512):
|
|
140
|
+
super().__init__(root, train, transform, download, cached=cached)
|
|
141
|
+
self.num_points = num_points
|
|
142
|
+
|
|
143
|
+
def __getitem__(self, idx: int):
|
|
144
|
+
# 1. Obtain vertices, faces, and label from Digit3D
|
|
145
|
+
vertices, faces, label = super().__getitem__(idx)
|
|
146
|
+
|
|
147
|
+
import trimesh
|
|
148
|
+
# 2. Construct trimesh object (CPU safe for DataLoader workers)
|
|
149
|
+
mesh = trimesh.Trimesh(vertices=vertices.numpy(), faces=faces.numpy(), process=False)
|
|
150
|
+
|
|
151
|
+
# 3. Sample points uniformly over the surface
|
|
152
|
+
points_np, face_indices = trimesh.sample.sample_surface(mesh, self.num_points)
|
|
153
|
+
normals_np = mesh.face_normals[face_indices]
|
|
154
|
+
|
|
155
|
+
points = torch.tensor(points_np, dtype=torch.float32)
|
|
156
|
+
normals = torch.tensor(normals_np, dtype=torch.float32)
|
|
157
|
+
|
|
158
|
+
# 4. Combine into features
|
|
159
|
+
features = torch.cat([points, normals], dim=-1)
|
|
160
|
+
|
|
161
|
+
return points, features, label
|
|
@@ -11,6 +11,7 @@ from .grid import (
|
|
|
11
11
|
compute_grid_normal,
|
|
12
12
|
compute_active_voxels,
|
|
13
13
|
)
|
|
14
|
+
from .sort import z_curve_sort
|
|
14
15
|
|
|
15
16
|
spatial_data_structures = ['KDTree', 'BVH', 'GSBVH', 'PGSBVH', 'MeshBVH']
|
|
16
17
|
mesh_data_structures = ['TriangleMesh']
|
|
@@ -19,5 +20,6 @@ grid_data_structures = [
|
|
|
19
20
|
'compute_grid_normal',
|
|
20
21
|
'compute_active_voxels',
|
|
21
22
|
]
|
|
23
|
+
sort_data_structures = ['z_curve_sort']
|
|
22
24
|
|
|
23
|
-
__all__ = spatial_data_structures + mesh_data_structures + grid_data_structures
|
|
25
|
+
__all__ = spatial_data_structures + mesh_data_structures + grid_data_structures + sort_data_structures
|
|
@@ -62,4 +62,21 @@ def compute_active_voxels(
|
|
|
62
62
|
Returns:
|
|
63
63
|
torch.Tensor: An int64 tensor containing the indices of the active voxels.
|
|
64
64
|
"""
|
|
65
|
-
return _C.compute_active_voxels(voxels.contiguous(), sdf.contiguous(), iso)
|
|
65
|
+
return _C.compute_active_voxels(voxels.contiguous(), sdf.contiguous(), iso)
|
|
66
|
+
|
|
67
|
+
def create_random_points_ball(n_points: int, radius: float = 1.0, device: str = 'cuda') -> torch.Tensor:
|
|
68
|
+
"""
|
|
69
|
+
Creates a set of random points uniformly distributed inside a sphere.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
n_points (int): Number of points to sample.
|
|
73
|
+
radius (float): Radius of the sphere. Defaults to 1.0.
|
|
74
|
+
device (str): Device to place the tensor on. Defaults to 'cuda'.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
torch.Tensor: Random points of shape (n_points, 3).
|
|
78
|
+
"""
|
|
79
|
+
points = torch.randn(n_points, 3, device=device)
|
|
80
|
+
radii = torch.rand(n_points, 1, device=device) ** (1/3) * radius
|
|
81
|
+
points = (points / points.norm(dim=-1, keepdim=True)) * radii
|
|
82
|
+
return points
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import conquer3d._C as _C
|
|
3
|
+
|
|
4
|
+
def z_curve_sort(points: torch.Tensor):
|
|
5
|
+
"""
|
|
6
|
+
Computes the Z-curve (Morton code) for a batch of points and sorts them.
|
|
7
|
+
Assumes points are normalized between [0, 1]. The function will clamp points outside this range.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
points (torch.Tensor): Tensor of shape (..., 3) containing the point coordinates.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
sorted_points (torch.Tensor): Points sorted by their Z-curve value.
|
|
14
|
+
sorted_indices (torch.Tensor): The indices used to sort the points.
|
|
15
|
+
inverse_indices (torch.Tensor): The indices to reverse the sorting.
|
|
16
|
+
"""
|
|
17
|
+
assert points.is_cuda, "Points must be on CUDA"
|
|
18
|
+
assert points.dtype == torch.float32, "Points must be float32"
|
|
19
|
+
assert points.shape[-1] == 3, "Points must be 3D"
|
|
20
|
+
|
|
21
|
+
# Compute the Morton codes for each point
|
|
22
|
+
codes = _C.compute_zcurve(points.contiguous())
|
|
23
|
+
|
|
24
|
+
# codes has shape (..., N). We always sort along the last dimension (dim=-1)
|
|
25
|
+
|
|
26
|
+
sorted_codes, sorted_indices = torch.sort(codes, dim=-1)
|
|
27
|
+
|
|
28
|
+
# Gather the points using the sorted indices
|
|
29
|
+
# We need to expand sorted_indices to match points: (..., N, 3)
|
|
30
|
+
dim = -2 if points.dim() > 1 else -1
|
|
31
|
+
expanded_indices = sorted_indices.unsqueeze(-1).expand_as(points)
|
|
32
|
+
sorted_points = torch.gather(points, dim=dim, index=expanded_indices)
|
|
33
|
+
|
|
34
|
+
# Compute the inverse indices (scatter)
|
|
35
|
+
inverse_indices = torch.argsort(sorted_indices, dim=-1)
|
|
36
|
+
|
|
37
|
+
return sorted_points, sorted_indices, inverse_indices
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import trimesh
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
def read_obj(file_obj):
|
|
6
|
+
"""
|
|
7
|
+
Reads an OBJ file and returns vertices, faces, and optional vertex colors using trimesh.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
file_obj: A file-like object or a string path.
|
|
11
|
+
"""
|
|
12
|
+
# trimesh safely handles UV seams and mismatched v/vt counts
|
|
13
|
+
mesh = trimesh.load(file_obj, process=False, force='mesh', skip_materials=True)
|
|
14
|
+
|
|
15
|
+
vertices = torch.tensor(mesh.vertices, dtype=torch.float32)
|
|
16
|
+
faces = torch.tensor(mesh.faces, dtype=torch.long)
|
|
17
|
+
|
|
18
|
+
colors = None
|
|
19
|
+
if hasattr(mesh.visual, 'vertex_colors') and mesh.visual.vertex_colors is not None and len(mesh.visual.vertex_colors) > 0:
|
|
20
|
+
colors = torch.tensor(mesh.visual.vertex_colors[:, :3], dtype=torch.float32) / 255.0
|
|
21
|
+
|
|
22
|
+
return vertices, faces, colors
|
|
23
|
+
|
|
24
|
+
def write_obj(filepath, vertices, faces, colors=None):
|
|
25
|
+
"""
|
|
26
|
+
Writes vertices, faces, and optional vertex colors to an OBJ file using trimesh.
|
|
27
|
+
"""
|
|
28
|
+
v = vertices.detach().cpu().numpy()
|
|
29
|
+
f = faces.detach().cpu().numpy()
|
|
30
|
+
|
|
31
|
+
vc = None
|
|
32
|
+
if colors is not None:
|
|
33
|
+
vc = (colors.detach().cpu().numpy() * 255.0).clip(0, 255).astype(np.uint8)
|
|
34
|
+
|
|
35
|
+
mesh = trimesh.Trimesh(vertices=v, faces=f, vertex_colors=vc, process=False)
|
|
36
|
+
mesh.export(filepath)
|
|
37
|
+
|
|
38
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
import trimesh
|
|
3
|
+
|
|
4
|
+
def read_off(filepath_or_filelike):
|
|
5
|
+
"""
|
|
6
|
+
Read an OFF (Object File Format) file and return vertices and faces as PyTorch tensors using trimesh.
|
|
7
|
+
|
|
8
|
+
Args:
|
|
9
|
+
filepath_or_filelike: A string path or a file-like object (including binary streams).
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
tuple: (vertices, faces) as torch.Tensor
|
|
13
|
+
"""
|
|
14
|
+
# trimesh handles both string paths and binary file streams natively
|
|
15
|
+
mesh = trimesh.load(filepath_or_filelike, file_type='off', process=False, force='mesh')
|
|
16
|
+
|
|
17
|
+
vertices = torch.tensor(mesh.vertices, dtype=torch.float32)
|
|
18
|
+
faces = torch.tensor(mesh.faces, dtype=torch.long)
|
|
19
|
+
|
|
20
|
+
return vertices, faces
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .marching_cubes import marching_cubes
|
|
2
|
+
from .diff_marching_cubes import diff_marching_cubes
|
|
3
|
+
|
|
4
|
+
from .delaunay_triangulation import tetrahedralize, get_edges
|
|
5
|
+
from .marching_tetrahedra import marching_tetrahedra
|
|
6
|
+
|
|
7
|
+
from .distance import one_sided_chamfer_distance, chamfer_distance, one_sided_hausdorff_distance, hausdorff_distance
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"marching_cubes",
|
|
11
|
+
"diff_marching_cubes",
|
|
12
|
+
"one_sided_chamfer_distance",
|
|
13
|
+
"chamfer_distance",
|
|
14
|
+
"one_sided_hausdorff_distance",
|
|
15
|
+
"hausdorff_distance",
|
|
16
|
+
"tetrahedralize",
|
|
17
|
+
"get_edges",
|
|
18
|
+
"marching_tetrahedra"
|
|
19
|
+
]
|
|
@@ -26,3 +26,30 @@ def chamfer_distance(x: torch.Tensor, y: torch.Tensor, squared: bool = True, ret
|
|
|
26
26
|
if return_indices:
|
|
27
27
|
return loss, idx_x_to_y, idx_y_to_x
|
|
28
28
|
return loss
|
|
29
|
+
|
|
30
|
+
def one_sided_hausdorff_distance(query_points: torch.Tensor, reference_points: torch.Tensor, squared: bool = True, return_indices: bool = False):
|
|
31
|
+
distances, indices = one_sided_chamfer_distance(query_points, reference_points, squared=squared)
|
|
32
|
+
|
|
33
|
+
max_dist, max_idx = torch.max(distances, dim=0)
|
|
34
|
+
|
|
35
|
+
if return_indices:
|
|
36
|
+
return max_dist, max_idx, indices[max_idx]
|
|
37
|
+
return max_dist
|
|
38
|
+
|
|
39
|
+
def hausdorff_distance(x: torch.Tensor, y: torch.Tensor, squared: bool = True, return_indices: bool = False):
|
|
40
|
+
if return_indices:
|
|
41
|
+
dist_x_to_y, idx_x1, idx_y1 = one_sided_hausdorff_distance(x, y, squared=squared, return_indices=True)
|
|
42
|
+
dist_y_to_x, idx_y2, idx_x2 = one_sided_hausdorff_distance(y, x, squared=squared, return_indices=True)
|
|
43
|
+
|
|
44
|
+
if dist_x_to_y > dist_y_to_x:
|
|
45
|
+
return dist_x_to_y, idx_x1, idx_y1
|
|
46
|
+
else:
|
|
47
|
+
return dist_y_to_x, idx_x2, idx_y2
|
|
48
|
+
else:
|
|
49
|
+
dist_x_to_y = one_sided_hausdorff_distance(x, y, squared=squared, return_indices=False)
|
|
50
|
+
dist_y_to_x = one_sided_hausdorff_distance(y, x, squared=squared, return_indices=False)
|
|
51
|
+
|
|
52
|
+
if dist_x_to_y > dist_y_to_x:
|
|
53
|
+
return dist_x_to_y
|
|
54
|
+
else:
|
|
55
|
+
return dist_y_to_x
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conquer3d
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
4
4
|
Summary: Geometric Cuda Tool Box
|
|
5
5
|
Author-email: Do Hoang Khoi <khoido8899@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.9
|
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
15
|
Requires-Dist: torch>=2.0.0
|
|
16
|
+
Requires-Dist: meshio>=5.3.5
|
|
16
17
|
Requires-Dist: gdown
|
|
17
18
|
Provides-Extra: cuda
|
|
18
19
|
Requires-Dist: cuda-toolkit==12.8.2; extra == "cuda"
|
|
@@ -49,6 +50,7 @@ pip install git+https://github.com/KhoiDOO/geocutool.git --no-build-isolation
|
|
|
49
50
|
```bash
|
|
50
51
|
conda create -c conda-forge -n geocutool python=3.10 gxx_linux-64=13 gcc_linux-64=13 -y
|
|
51
52
|
conda activate geocutool
|
|
53
|
+
conda install -c conda-forge sparsehash -y
|
|
52
54
|
|
|
53
55
|
conda install nvidia::cuda-toolkit==12.8.2 -y
|
|
54
56
|
|
|
@@ -28,6 +28,7 @@ conquer3d/csrc/binds/data_structure/kdtree.cpp
|
|
|
28
28
|
conquer3d/csrc/binds/data_structure/mesh_bvh.cpp
|
|
29
29
|
conquer3d/csrc/binds/data_structure/pgs_bvh.cpp
|
|
30
30
|
conquer3d/csrc/binds/data_structure/triangle_mesh.cpp
|
|
31
|
+
conquer3d/csrc/binds/data_structure/zcurve.cpp
|
|
31
32
|
conquer3d/csrc/binds/ops/chamfer.cpp
|
|
32
33
|
conquer3d/csrc/binds/ops/mc.cpp
|
|
33
34
|
conquer3d/csrc/binds/primitive/gs.cpp
|
|
@@ -45,6 +46,7 @@ conquer3d/csrc/data_structure/mesh_bvh.h
|
|
|
45
46
|
conquer3d/csrc/data_structure/pgs_bvh.h
|
|
46
47
|
conquer3d/csrc/data_structure/triangle_mesh.cu
|
|
47
48
|
conquer3d/csrc/data_structure/triangle_mesh.h
|
|
49
|
+
conquer3d/csrc/data_structure/zcurve.cu
|
|
48
50
|
conquer3d/csrc/data_structure/zcurve.h
|
|
49
51
|
conquer3d/csrc/maths/f2x2.h
|
|
50
52
|
conquer3d/csrc/maths/f3x1.h
|
|
@@ -88,6 +90,7 @@ conquer3d/data/transform/vertex.py
|
|
|
88
90
|
conquer3d/data_structure/__init__.py
|
|
89
91
|
conquer3d/data_structure/bmesh.py
|
|
90
92
|
conquer3d/data_structure/grid.py
|
|
93
|
+
conquer3d/data_structure/sort.py
|
|
91
94
|
conquer3d/io/__init__.py
|
|
92
95
|
conquer3d/io/obj.py
|
|
93
96
|
conquer3d/io/off.py
|
|
@@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta"
|
|
|
9
9
|
|
|
10
10
|
[project]
|
|
11
11
|
name = "conquer3d"
|
|
12
|
-
version = "0.3.
|
|
12
|
+
version = "0.3.9"
|
|
13
13
|
description = "Geometric Cuda Tool Box"
|
|
14
14
|
readme = "README.md"
|
|
15
15
|
license = "MIT"
|
|
@@ -20,6 +20,7 @@ requires-python = ">=3.9"
|
|
|
20
20
|
keywords = ["geometry"]
|
|
21
21
|
dependencies = [
|
|
22
22
|
"torch>=2.0.0",
|
|
23
|
+
"meshio>=5.3.5",
|
|
23
24
|
"gdown",
|
|
24
25
|
]
|
|
25
26
|
|
|
File without changes
|
|
File without changes
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import torch
|
|
2
|
-
|
|
3
|
-
def read_obj(file_obj):
|
|
4
|
-
"""
|
|
5
|
-
Reads an OBJ file and returns vertices, faces, and optional vertex colors.
|
|
6
|
-
|
|
7
|
-
Args:
|
|
8
|
-
file_obj: A file-like object or a string path.
|
|
9
|
-
"""
|
|
10
|
-
vertices = []
|
|
11
|
-
faces = []
|
|
12
|
-
colors = []
|
|
13
|
-
|
|
14
|
-
close_file = False
|
|
15
|
-
if isinstance(file_obj, str):
|
|
16
|
-
file_obj = open(file_obj, 'r', encoding='utf-8')
|
|
17
|
-
close_file = True
|
|
18
|
-
|
|
19
|
-
try:
|
|
20
|
-
for line in file_obj:
|
|
21
|
-
if isinstance(line, bytes):
|
|
22
|
-
line = line.decode('utf-8', errors='ignore')
|
|
23
|
-
line = line.strip()
|
|
24
|
-
if line.startswith('v '):
|
|
25
|
-
parts = line.split()
|
|
26
|
-
vertices.append([float(parts[1]), float(parts[2]), float(parts[3])])
|
|
27
|
-
if len(parts) >= 7:
|
|
28
|
-
colors.append([float(parts[4]), float(parts[5]), float(parts[6])])
|
|
29
|
-
elif line.startswith('f '):
|
|
30
|
-
parts = line.split()
|
|
31
|
-
# Face elements can be v, v/vt, or v/vt/vn. We just want the first index (v).
|
|
32
|
-
face = [int(p.split('/')[0]) - 1 for p in parts[1:4]]
|
|
33
|
-
faces.append(face)
|
|
34
|
-
finally:
|
|
35
|
-
if close_file:
|
|
36
|
-
file_obj.close()
|
|
37
|
-
|
|
38
|
-
vertices = torch.tensor(vertices, dtype=torch.float32)
|
|
39
|
-
faces = torch.tensor(faces, dtype=torch.long)
|
|
40
|
-
|
|
41
|
-
if len(colors) == len(vertices):
|
|
42
|
-
colors = torch.tensor(colors, dtype=torch.float32)
|
|
43
|
-
else:
|
|
44
|
-
colors = None
|
|
45
|
-
|
|
46
|
-
return vertices, faces, colors
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import torch
|
|
2
|
-
import numpy as np
|
|
3
|
-
import io
|
|
4
|
-
|
|
5
|
-
def read_off(filepath_or_filelike):
|
|
6
|
-
"""
|
|
7
|
-
Read an OFF (Object File Format) file and return vertices and faces as PyTorch tensors.
|
|
8
|
-
Supports reading from a file path or a file-like object.
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
filepath_or_filelike: A string path or a file-like object.
|
|
12
|
-
|
|
13
|
-
Returns:
|
|
14
|
-
tuple: (vertices, faces) as torch.Tensor
|
|
15
|
-
"""
|
|
16
|
-
if isinstance(filepath_or_filelike, str):
|
|
17
|
-
with open(filepath_or_filelike, "r") as f:
|
|
18
|
-
lines = f.readlines()
|
|
19
|
-
else:
|
|
20
|
-
# Assuming text-based or bytes file-like object
|
|
21
|
-
lines = filepath_or_filelike.readlines()
|
|
22
|
-
if len(lines) > 0 and isinstance(lines[0], bytes):
|
|
23
|
-
lines = [line.decode('utf-8') for line in lines]
|
|
24
|
-
|
|
25
|
-
# Clean up empty lines and comments
|
|
26
|
-
lines = [line.strip() for line in lines if line.strip() and not line.startswith('#')]
|
|
27
|
-
|
|
28
|
-
if not lines:
|
|
29
|
-
raise ValueError("Empty OFF file.")
|
|
30
|
-
|
|
31
|
-
first_line = lines[0].strip()
|
|
32
|
-
if first_line.upper().startswith("OFF"):
|
|
33
|
-
if len(first_line) > 3:
|
|
34
|
-
# Format: 'OFF 123 456 0'
|
|
35
|
-
parts = first_line[3:].strip().split()
|
|
36
|
-
# If the rest of the line doesn't contain counts, maybe they are on the next line
|
|
37
|
-
if parts:
|
|
38
|
-
lines = [parts] + lines[1:]
|
|
39
|
-
else:
|
|
40
|
-
lines = lines[1:]
|
|
41
|
-
else:
|
|
42
|
-
lines = lines[1:]
|
|
43
|
-
|
|
44
|
-
# If the format parsing above resulted in a list of parts at index 0, handle it
|
|
45
|
-
if isinstance(lines[0], list):
|
|
46
|
-
counts = lines[0]
|
|
47
|
-
else:
|
|
48
|
-
counts = lines[0].split()
|
|
49
|
-
|
|
50
|
-
num_verts, num_faces, num_edges = map(int, counts[:3])
|
|
51
|
-
|
|
52
|
-
# Fast parsing with numpy
|
|
53
|
-
verts_lines = lines[1:num_verts + 1]
|
|
54
|
-
verts_str = '\n'.join(verts_lines)
|
|
55
|
-
verts = np.fromstring(verts_str, sep=' ').reshape(num_verts, -1)[:, :3]
|
|
56
|
-
|
|
57
|
-
faces_lines = lines[num_verts + 1 : num_verts + 1 + num_faces]
|
|
58
|
-
faces_str = '\n'.join(faces_lines)
|
|
59
|
-
|
|
60
|
-
# In an OFF file, face lines look like: `3 v1 v2 v3` for triangles.
|
|
61
|
-
# We parse the flat array and reshape based on the number of elements per line
|
|
62
|
-
faces_raw = np.fromstring(faces_str, sep=' ', dtype=int)
|
|
63
|
-
|
|
64
|
-
# We assume all faces are triangles!
|
|
65
|
-
# The first element of each chunk will be 3, followed by 3 indices.
|
|
66
|
-
# Total length should be num_faces * 4
|
|
67
|
-
if len(faces_raw) == num_faces * 4:
|
|
68
|
-
faces = faces_raw.reshape(num_faces, 4)[:, 1:4]
|
|
69
|
-
else:
|
|
70
|
-
# If faces are mixed (e.g. some quads), we fall back to a slower parsing
|
|
71
|
-
faces_list = []
|
|
72
|
-
idx = 0
|
|
73
|
-
for _ in range(num_faces):
|
|
74
|
-
n_v = faces_raw[idx]
|
|
75
|
-
if n_v == 3:
|
|
76
|
-
faces_list.append([faces_raw[idx+1], faces_raw[idx+2], faces_raw[idx+3]])
|
|
77
|
-
else:
|
|
78
|
-
# Naive triangulation for ngons (fan triangulation)
|
|
79
|
-
for i in range(1, n_v - 1):
|
|
80
|
-
faces_list.append([faces_raw[idx+1], faces_raw[idx+i+1], faces_raw[idx+i+2]])
|
|
81
|
-
idx += n_v + 1
|
|
82
|
-
faces = np.array(faces_list, dtype=int)
|
|
83
|
-
|
|
84
|
-
return torch.from_numpy(verts).float(), torch.from_numpy(faces).long()
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
from .marching_cubes import marching_cubes
|
|
2
|
-
from .diff_marching_cubes import diff_marching_cubes
|
|
3
|
-
from .distance import one_sided_chamfer_distance, chamfer_distance
|
|
4
|
-
|
|
5
|
-
__all__ = [
|
|
6
|
-
"marching_cubes",
|
|
7
|
-
"diff_marching_cubes",
|
|
8
|
-
"one_sided_chamfer_distance",
|
|
9
|
-
"chamfer_distance"
|
|
10
|
-
]
|
|
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
|
{conquer3d-0.3.4/conquer3d/data/assets → conquer3d-0.3.9/conquer3d/data/collate}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{conquer3d-0.3.4/conquer3d/data/collate → conquer3d-0.3.9/conquer3d/data/dataset}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{conquer3d-0.3.4/conquer3d/data/dataset → conquer3d-0.3.9/conquer3d/data/transform}/__init__.py
RENAMED
|
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
|