|
23 | 23 |
|
24 | 24 | #include <geode/mesh/helpers/convert_surface_mesh.hpp> |
25 | 25 |
|
| 26 | +#include <mapbox/earcut.hpp> |
| 27 | + |
26 | 28 | #include <geode/basic/attribute_manager.hpp> |
27 | 29 | #include <geode/basic/logger.hpp> |
28 | 30 |
|
29 | 31 | #include <geode/geometry/point.hpp> |
| 32 | +#include <geode/geometry/vector.hpp> |
30 | 33 |
|
31 | 34 | #include <geode/mesh/builder/polygonal_surface_builder.hpp> |
32 | 35 | #include <geode/mesh/builder/triangulated_surface_builder.hpp> |
|
39 | 42 | #include <geode/mesh/helpers/detail/surface_merger.hpp> |
40 | 43 | #include <geode/mesh/helpers/internal/copy.hpp> |
41 | 44 |
|
| 45 | +namespace mapbox |
| 46 | +{ |
| 47 | + namespace util |
| 48 | + { |
| 49 | + template < std::size_t coord, geode::index_t dimension > |
| 50 | + struct nth< coord, geode::Point< dimension > > |
| 51 | + { |
| 52 | + inline static auto get( const geode::Point< dimension >& point ) |
| 53 | + { |
| 54 | + return point.value( coord ); |
| 55 | + }; |
| 56 | + }; |
| 57 | + } // namespace util |
| 58 | +} // namespace mapbox |
| 59 | + |
42 | 60 | namespace |
43 | 61 | { |
44 | 62 | template < geode::index_t dimension > |
@@ -273,35 +291,47 @@ namespace |
273 | 291 | } |
274 | 292 |
|
275 | 293 | template < geode::index_t dimension > |
276 | | - void transfer_adjacents( geode::SurfaceMeshBuilder< dimension >& builder, |
277 | | - absl::Span< const std::optional< geode::PolygonEdge > > adjacents, |
278 | | - absl::Span< const geode::index_t > new_polygons ) |
| 294 | + std::array< absl::FixedArray< geode::Point2D >, 1 > polygon_points( |
| 295 | + const geode::SurfaceMesh< dimension >& surface, |
| 296 | + geode::index_t polygon_id, |
| 297 | + absl::Span< const geode::index_t > vertices ); |
| 298 | + |
| 299 | + template <> |
| 300 | + std::array< absl::FixedArray< geode::Point2D >, 1 > polygon_points( |
| 301 | + const geode::SurfaceMesh< 2 >& surface, |
| 302 | + geode::index_t /*unused*/, |
| 303 | + absl::Span< const geode::index_t > vertices ) |
279 | 304 | { |
280 | | - if( adjacents.front() ) |
281 | | - { |
282 | | - builder.set_polygon_adjacent( |
283 | | - { new_polygons.front(), 0 }, adjacents.front()->polygon_id ); |
284 | | - builder.set_polygon_adjacent( |
285 | | - adjacents.front().value(), new_polygons.front() ); |
286 | | - } |
287 | | - for( const auto v : geode::LRange{ 1, adjacents.size() - 1 } ) |
| 305 | + std::array< absl::FixedArray< geode::Point2D >, 1 > polygons{ |
| 306 | + absl::FixedArray< geode::Point2D >( vertices.size() ) |
| 307 | + }; |
| 308 | + auto& polygon = polygons[0]; |
| 309 | + for( const auto v : geode::LIndices{ vertices } ) |
288 | 310 | { |
289 | | - if( adjacents[v] ) |
290 | | - { |
291 | | - builder.set_polygon_adjacent( |
292 | | - { new_polygons[v - 1], 1 }, adjacents[v]->polygon_id ); |
293 | | - builder.set_polygon_adjacent( |
294 | | - adjacents[v].value(), new_polygons[v - 1] ); |
295 | | - } |
| 311 | + polygon[v] = surface.point( vertices[v] ); |
296 | 312 | } |
297 | | - if( adjacents.back() ) |
| 313 | + return polygons; |
| 314 | + } |
| 315 | + |
| 316 | + template <> |
| 317 | + std::array< absl::FixedArray< geode::Point2D >, 1 > polygon_points( |
| 318 | + const geode::SurfaceMesh< 3 >& surface, |
| 319 | + geode::index_t polygon_id, |
| 320 | + absl::Span< const geode::index_t > vertices ) |
| 321 | + { |
| 322 | + std::array< absl::FixedArray< geode::Point2D >, 1 > polygons{ |
| 323 | + absl::FixedArray< geode::Point2D >( vertices.size() ) |
| 324 | + }; |
| 325 | + auto& polygon = polygons[0]; |
| 326 | + const auto normal = surface.polygon_normal( polygon_id ) |
| 327 | + .value_or( geode::Vector3D{ { 0, 0, 1 } } ); |
| 328 | + const auto axis_to_remove = normal.most_meaningful_axis(); |
| 329 | + for( const auto v : geode::LIndices{ vertices } ) |
298 | 330 | { |
299 | | - builder.set_polygon_adjacent( |
300 | | - { new_polygons.back(), 2 }, adjacents.back()->polygon_id ); |
301 | | - builder.set_polygon_adjacent( |
302 | | - adjacents.back().value(), new_polygons.back() ); |
| 331 | + polygon[v] = |
| 332 | + surface.point( vertices[v] ).project_point( axis_to_remove ); |
303 | 333 | } |
304 | | - builder.compute_polygon_adjacencies( new_polygons ); |
| 334 | + return polygons; |
305 | 335 | } |
306 | 336 | } // namespace |
307 | 337 |
|
@@ -384,20 +414,50 @@ namespace geode |
384 | 414 | to_delete[p] = nb_vertices != 3; |
385 | 415 | if( nb_vertices > 3 ) |
386 | 416 | { |
387 | | - absl::FixedArray< std::optional< PolygonEdge > > adjacents( |
388 | | - nb_vertices, std::nullopt ); |
| 417 | + using Edge = std::array< index_t, 2 >; |
| 418 | + absl::flat_hash_map< Edge, PolygonEdge > adjacents; |
| 419 | + const auto vertices = surface.polygon_vertices( p ); |
389 | 420 | for( const auto e : LRange{ nb_vertices } ) |
390 | 421 | { |
391 | | - adjacents[e] = surface.polygon_adjacent_edge( { p, e } ); |
| 422 | + if( const auto adj = |
| 423 | + surface.polygon_adjacent_edge( { p, e } ) ) |
| 424 | + { |
| 425 | + adjacents.emplace( |
| 426 | + Edge{ vertices[e], |
| 427 | + vertices[e + 1 == nb_vertices ? 0 : e + 1] }, |
| 428 | + adj.value() ); |
| 429 | + } |
392 | 430 | } |
393 | | - absl::FixedArray< index_t > new_polygons( nb_vertices - 2 ); |
394 | | - const auto vertices = surface.polygon_vertices( p ); |
395 | | - for( const auto v : LRange{ 2, nb_vertices } ) |
| 431 | + const auto polygons = ::polygon_points( surface, p, vertices ); |
| 432 | + const auto new_triangles = |
| 433 | + mapbox::earcut< index_t >( polygons ); |
| 434 | + absl::FixedArray< index_t > new_polygons( |
| 435 | + new_triangles.size() / 3 ); |
| 436 | + for( const auto trgl : LIndices{ new_polygons } ) |
396 | 437 | { |
397 | | - new_polygons[v - 2] = builder.create_polygon( |
398 | | - { vertices[0], vertices[v - 1], vertices[v] } ); |
| 438 | + const std::array triangle{ |
| 439 | + vertices[new_triangles[3 * trgl]], |
| 440 | + vertices[new_triangles[3 * trgl + 1]], |
| 441 | + vertices[new_triangles[3 * trgl + 2]] |
| 442 | + }; |
| 443 | + new_polygons[trgl] = builder.create_polygon( triangle ); |
| 444 | + for( const auto e : LRange{ 3 } ) |
| 445 | + { |
| 446 | + const auto vertex0 = triangle[e]; |
| 447 | + const auto vertex1 = triangle[e == 2 ? 0 : e + 1]; |
| 448 | + const auto adj_it = |
| 449 | + adjacents.find( { vertex0, vertex1 } ); |
| 450 | + if( adj_it == adjacents.end() ) |
| 451 | + { |
| 452 | + continue; |
| 453 | + } |
| 454 | + builder.set_polygon_adjacent( |
| 455 | + adj_it->second, new_polygons[trgl] ); |
| 456 | + builder.set_polygon_adjacent( { new_polygons[trgl], e }, |
| 457 | + adj_it->second.polygon_id ); |
| 458 | + } |
399 | 459 | } |
400 | | - ::transfer_adjacents( builder, adjacents, new_polygons ); |
| 460 | + builder.compute_polygon_adjacencies( new_polygons ); |
401 | 461 | } |
402 | 462 | } |
403 | 463 | to_delete.resize( surface.nb_polygons(), false ); |
|
0 commit comments