|
5 | 5 | #include <openvdb/Exceptions.h> |
6 | 6 | #include <openvdb/tools/MeshToVolume.h> |
7 | 7 | #include <openvdb/util/Util.h> |
| 8 | +#include <openvdb/util/NullInterrupter.h> |
8 | 9 |
|
9 | 10 | #include <gtest/gtest.h> |
10 | 11 | #include <vector> |
| 12 | +#include <thread> |
| 13 | +#include <chrono> |
11 | 14 |
|
12 | 15 | class TestMeshToVolume: public ::testing::Test |
13 | 16 | { |
@@ -129,3 +132,87 @@ TEST_F(TestMeshToVolume, testCreateLevelSetBox) |
129 | 132 | EXPECT_TRUE(grid->tree().getValue(ijk) > 0.0f); |
130 | 133 | } |
131 | 134 |
|
| 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 | + |
0 commit comments