Skip to content

Commit 19013e3

Browse files
authored
Merge pull request #2140 from Idclip/m2v_interrupt
Improved the interruptibility of tools::meshToVolume
2 parents 8ca4ac8 + 3733f2c commit 19013e3

File tree

3 files changed

+95
-2
lines changed

3 files changed

+95
-2
lines changed

openvdb/openvdb/tools/MeshToVolume.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,20 +2169,23 @@ class VoxelizePolygons
21692169
unsigned char primId = data.getNewPrimId();
21702170
data.primIdAcc.setValueOnly(ijk, primId);
21712171

2172+
// iteration number to check for an interrupt
2173+
constexpr Int32 freq = 2<<12;
2174+
21722175
while (!coordList.empty()) {
21732176
if (interrupter && interrupter->wasInterrupted()) {
21742177
thread::cancelGroupExecution();
21752178
break;
21762179
}
2177-
for (Int32 pass = 0; pass < 1048576 && !coordList.empty(); ++pass) {
2180+
for (Int32 pass = 0; pass < freq && !coordList.empty(); ++pass) {
21782181
ijk = coordList.back();
21792182
coordList.pop_back();
21802183

21812184
for (Int32 i = 0; i < 26; ++i) {
21822185
nijk = ijk + util::COORD_OFFSETS[i];
21832186
if (primId != data.primIdAcc.getValue(nijk)) {
21842187
data.primIdAcc.setValueOnly(nijk, primId);
2185-
if(updateDistance(nijk, prim, data)) coordList.push_back(nijk);
2188+
if (updateDistance(nijk, prim, data)) coordList.push_back(nijk);
21862189
}
21872190
}
21882191
}

openvdb/openvdb/unittest/TestMeshToVolume.cc

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
#include <openvdb/Exceptions.h>
66
#include <openvdb/tools/MeshToVolume.h>
77
#include <openvdb/util/Util.h>
8+
#include <openvdb/util/NullInterrupter.h>
89

910
#include <gtest/gtest.h>
1011
#include <vector>
12+
#include <thread>
13+
#include <chrono>
1114

1215
class TestMeshToVolume: public ::testing::Test
1316
{
@@ -129,3 +132,87 @@ TEST_F(TestMeshToVolume, testCreateLevelSetBox)
129132
EXPECT_TRUE(grid->tree().getValue(ijk) > 0.0f);
130133
}
131134

135+
136+
TEST_F(TestMeshToVolume, testInterrupt)
137+
{
138+
using namespace openvdb;
139+
140+
///////////////////////////////////////////////////////////////////////////
141+
142+
struct Interrupter final : util::NullInterrupter
143+
{
144+
bool wasInterrupted(int percent = -1) override { (void)percent; return interrupted.load(); }
145+
void interrupt() { interrupted.store(true); }
146+
std::atomic<bool> interrupted = false;
147+
};
148+
149+
struct MeshAdapter
150+
{
151+
MeshAdapter(const std::vector<Vec3d>& vertices, const std::vector<Vec3d>& triangles)
152+
: vertices(vertices), triangles(triangles), positionsRequested(false) {}
153+
size_t polygonCount() const { return triangles.size(); }
154+
size_t pointCount() const { return vertices.size(); }
155+
size_t vertexCount(size_t) const { return 3; }
156+
void getIndexSpacePoint(size_t n, size_t v, Vec3d &pos) const
157+
{
158+
// Mark that positions have been accessed
159+
positionsRequested = true;
160+
pos = vertices[size_t(triangles[n][v])];
161+
}
162+
const std::vector<Vec3d>& vertices;
163+
const std::vector<Vec3d>& triangles;
164+
// Flag to check that meshToVolume has started accessing positions
165+
mutable std::atomic<bool> positionsRequested;
166+
};
167+
168+
///////////////////////////////////////////////////////////////////////////
169+
170+
Interrupter interrupter;
171+
172+
// define geo for a box
173+
const Vec3d size = {100000, 100000, 100000};
174+
const double hx = size.x() / 2.0;
175+
const double hy = size.y() / 2.0;
176+
const double z = size.z();
177+
178+
const std::vector<Vec3d> vertices = {
179+
{-hx, -hy, 0.0}, {+hx, -hy, 0.0}, {+hx, -hy, z}, {-hx, -hy, z},
180+
{-hx, +hy, 0.0}, {+hx, +hy, 0.0}, {+hx, +hy, z}, {-hx, +hy, z},
181+
};
182+
183+
const std::vector<Vec3d> triangles = {
184+
{0, 1, 2}, {0, 2, 3}, {1, 0, 4}, {1, 4, 5}, {1, 5, 6}, {1, 6, 2},
185+
{3, 2, 6}, {3, 6, 7}, {4, 0, 3}, {4, 3, 7}, {4, 6, 5}, {4, 7, 6},
186+
};
187+
188+
const MeshAdapter adapter(vertices, triangles);
189+
const auto transform = math::Transform::createLinearTransform(1.0);
190+
FloatGrid::Ptr grid;
191+
192+
std::chrono::steady_clock::time_point start, end;
193+
194+
// Start volume generation
195+
std::thread m2vThread([&]() {
196+
grid = tools::meshToVolume<FloatGrid>(interrupter, adapter, *transform);
197+
// assign end here to avoid waiting for thread sync (we only care about
198+
// meshToVolume returning).
199+
end = std::chrono::steady_clock::now();
200+
});
201+
202+
// Wait for method to start before interrupting
203+
while (!adapter.positionsRequested) {} // loop until positions have been accessed
204+
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for a bit longer
205+
206+
start = std::chrono::steady_clock::now();
207+
// interrupt
208+
interrupter.interrupt();
209+
m2vThread.join();
210+
211+
// Should have returned _something_
212+
EXPECT_TRUE(grid);
213+
214+
// Expect to interrupt in under a second
215+
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
216+
EXPECT_LT(duration.count(), 1000);
217+
}
218+

pendingchanges/m2vinterrupt.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
OpenVDB:
2+
Improvements:
3+
- Improved the interruptibility of tools::meshToVolume [Reported by @RustyLooks]

0 commit comments

Comments
 (0)