Welcome to mirror list, hosted at ThFree Co, Russian Federation.

OpenVDBUtils.cpp « libslic3r « src - github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 31ae203ddf4c224e83133a16a5299bd5a5facc6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#define NOMINMAX
#include "OpenVDBUtils.hpp"
#include <openvdb/tools/MeshToVolume.h>
#include <openvdb/tools/VolumeToMesh.h>
#include <openvdb/tools/Composite.h>
#include <openvdb/tools/LevelSetRebuild.h>

//#include "MTUtils.hpp"

namespace Slic3r {

class TriangleMeshDataAdapter {
public:
    const TriangleMesh &mesh;
    
    size_t polygonCount() const { return mesh.its.indices.size(); }
    size_t pointCount() const   { return mesh.its.vertices.size(); }
    size_t vertexCount(size_t) const { return 3; }
    
    // Return position pos in local grid index space for polygon n and vertex v
    void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const;
};

class Contour3DDataAdapter {
public:
    const sla::Contour3D &mesh;
    
    size_t polygonCount() const { return mesh.faces3.size() + mesh.faces4.size(); }
    size_t pointCount() const   { return mesh.points.size(); }
    size_t vertexCount(size_t n) const { return n < mesh.faces3.size() ? 3 : 4; }
    
    // Return position pos in local grid index space for polygon n and vertex v
    void getIndexSpacePoint(size_t n, size_t v, openvdb::Vec3d& pos) const;
};

void TriangleMeshDataAdapter::getIndexSpacePoint(size_t          n,
                                                 size_t          v,
                                                 openvdb::Vec3d &pos) const
{
    auto vidx = size_t(mesh.its.indices[n](Eigen::Index(v)));
    Slic3r::Vec3d p = mesh.its.vertices[vidx].cast<double>();
    pos = {p.x(), p.y(), p.z()};
}

void Contour3DDataAdapter::getIndexSpacePoint(size_t          n,
                                              size_t          v,
                                              openvdb::Vec3d &pos) const
{
    size_t vidx = 0;
    if (n < mesh.faces3.size()) vidx = size_t(mesh.faces3[n](Eigen::Index(v)));
    else vidx = size_t(mesh.faces4[n - mesh.faces3.size()](Eigen::Index(v)));
    
    Slic3r::Vec3d p = mesh.points[vidx];
    pos = {p.x(), p.y(), p.z()};
}


// TODO: Do I need to call initialize? Seems to work without it as well but the
// docs say it should be called ones. It does a mutex lock-unlock sequence all
// even if was called previously.
openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh &mesh,
                                     const openvdb::math::Transform &tr,
                                     float               exteriorBandWidth,
                                     float               interiorBandWidth,
                                     int                 flags)
{
    openvdb::initialize();

    TriangleMeshPtrs meshparts = mesh.split();

    auto it = std::remove_if(meshparts.begin(), meshparts.end(),
    [](TriangleMesh *m){
        m->require_shared_vertices();
        return !m->is_manifold() || m->volume() < EPSILON;
    });

    meshparts.erase(it, meshparts.end());

    openvdb::FloatGrid::Ptr grid;
    for (TriangleMesh *m : meshparts) {
        auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
            TriangleMeshDataAdapter{*m}, tr, exteriorBandWidth,
            interiorBandWidth, flags);

        if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
        else if (subgrid) grid = std::move(subgrid);
    }

    if (grid) {
        grid = openvdb::tools::levelSetRebuild(*grid, 0., exteriorBandWidth,
                                               interiorBandWidth);
    } else if(meshparts.empty()) {
        // Splitting failed, fall back to hollow the original mesh
        grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
            TriangleMeshDataAdapter{mesh}, tr, exteriorBandWidth,
            interiorBandWidth, flags);
    }

    return grid;
}

openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D &mesh,
                                     const openvdb::math::Transform &tr,
                                     float exteriorBandWidth,
                                     float interiorBandWidth,
                                     int flags)
{
    openvdb::initialize();
    return openvdb::tools::meshToVolume<openvdb::FloatGrid>(
        Contour3DDataAdapter{mesh}, tr, exteriorBandWidth, interiorBandWidth,
        flags);
}

template<class Grid>
sla::Contour3D _volumeToMesh(const Grid &grid,
                             double      isovalue,
                             double      adaptivity,
                             bool        relaxDisorientedTriangles)
{
    openvdb::initialize();
    
    std::vector<openvdb::Vec3s> points;
    std::vector<openvdb::Vec3I> triangles;
    std::vector<openvdb::Vec4I> quads;
    
    openvdb::tools::volumeToMesh(grid, points, triangles, quads, isovalue,
                                 adaptivity, relaxDisorientedTriangles);
    
    sla::Contour3D ret;
    ret.points.reserve(points.size());
    ret.faces3.reserve(triangles.size());
    ret.faces4.reserve(quads.size());

    for (auto &v : points) ret.points.emplace_back(to_vec3d(v));
    for (auto &v : triangles) ret.faces3.emplace_back(to_vec3i(v));
    for (auto &v : quads) ret.faces4.emplace_back(to_vec4i(v));

    return ret;
}

TriangleMesh grid_to_mesh(const openvdb::FloatGrid &grid,
                          double                    isovalue,
                          double                    adaptivity,
                          bool                      relaxDisorientedTriangles)
{
    return to_triangle_mesh(
        _volumeToMesh(grid, isovalue, adaptivity, relaxDisorientedTriangles));
}

sla::Contour3D grid_to_contour3d(const openvdb::FloatGrid &grid,
                                 double                    isovalue,
                                 double                    adaptivity,
                                 bool relaxDisorientedTriangles)
{
    return _volumeToMesh(grid, isovalue, adaptivity,
                         relaxDisorientedTriangles);
}

openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, double iso, double er, double ir)
{
    return openvdb::tools::levelSetRebuild(grid, float(iso), float(er), float(ir));
}

} // namespace Slic3r