mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Summary: - Added TriangulationMethod enum to MeshConverterConfig with two options: * Earcut (default): Robust algorithm for complex/concave polygons * TriangleFan: Fast algorithm for convex polygons (simple fan splitting) - Implemented triangle fan splitting for 5+ vertex polygons * Creates triangles from first vertex as pivot: (0,1,2), (0,2,3), etc. * Much simpler and faster than earcut for convex polygons - Updated TriangulatePolygon() function signature to accept triangulation method - Preserved backward compatibility with earcut as default method - Added triangulation_method_example.cc demonstrating usage of both methods Benefits: - Performance improvement for applications with convex polygon meshes - Flexible triangulation strategy based on polygon characteristics - Default behavior unchanged for backward compatibility Test plan: - Build successfully with no compilation errors - Example program demonstrates switching between triangulation methods - Can be tested with USD files containing 5+ vertex polygons 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
124 lines
4.1 KiB
C++
124 lines
4.1 KiB
C++
// Example demonstrating the new triangulation method option in TinyUSDZ Tydra
|
|
//
|
|
// This example shows how to use either:
|
|
// - Earcut algorithm (default): Robust for complex/concave polygons
|
|
// - Triangle Fan: Fast for simple convex polygons
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <string>
|
|
#include "tinyusdz.hh"
|
|
#include "tydra/render-data.hh"
|
|
#include "tydra/scene-access.hh"
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc < 2) {
|
|
std::cout << "Usage: " << argv[0] << " <input.usd> [fan|earcut]\n";
|
|
std::cout << "\nTriangulation methods:\n";
|
|
std::cout << " earcut (default): Robust algorithm for complex polygons\n";
|
|
std::cout << " fan: Fast triangle fan for convex polygons\n";
|
|
return 1;
|
|
}
|
|
|
|
std::string filename = argv[1];
|
|
bool use_fan = false;
|
|
|
|
if (argc >= 3) {
|
|
std::string method = argv[2];
|
|
if (method == "fan") {
|
|
use_fan = true;
|
|
std::cout << "Using triangle fan triangulation\n";
|
|
} else if (method == "earcut") {
|
|
std::cout << "Using earcut triangulation\n";
|
|
} else {
|
|
std::cerr << "Unknown triangulation method: " << method << "\n";
|
|
return 1;
|
|
}
|
|
} else {
|
|
std::cout << "Using default earcut triangulation\n";
|
|
}
|
|
|
|
// Load USD file
|
|
tinyusdz::Stage stage;
|
|
std::string warn, err;
|
|
bool ret = tinyusdz::LoadUSDFromFile(filename, &stage, &warn, &err);
|
|
|
|
if (!warn.empty()) {
|
|
std::cerr << "Warning: " << warn << "\n";
|
|
}
|
|
|
|
if (!ret) {
|
|
std::cerr << "Failed to load USD file: " << err << "\n";
|
|
return 1;
|
|
}
|
|
|
|
// Set up render scene converter with triangulation method
|
|
tinyusdz::tydra::RenderSceneConverterEnv env(stage);
|
|
|
|
// Configure mesh conversion
|
|
env.mesh_config.triangulate = true; // Enable triangulation
|
|
|
|
// Set the triangulation method
|
|
if (use_fan) {
|
|
env.mesh_config.triangulation_method =
|
|
tinyusdz::tydra::MeshConverterConfig::TriangulationMethod::TriangleFan;
|
|
} else {
|
|
env.mesh_config.triangulation_method =
|
|
tinyusdz::tydra::MeshConverterConfig::TriangulationMethod::Earcut;
|
|
}
|
|
|
|
// Convert to render scene
|
|
tinyusdz::tydra::RenderSceneConverter converter;
|
|
tinyusdz::tydra::RenderScene render_scene;
|
|
|
|
if (!converter.ConvertToRenderScene(env, &render_scene)) {
|
|
std::cerr << "Failed to convert to render scene: "
|
|
<< converter.GetError() << "\n";
|
|
return 1;
|
|
}
|
|
|
|
// Print statistics
|
|
std::cout << "\nConversion complete!\n";
|
|
std::cout << "Number of meshes: " << render_scene.meshes.size() << "\n";
|
|
|
|
size_t total_triangles = 0;
|
|
size_t total_original_faces = 0;
|
|
|
|
for (const auto& mesh : render_scene.meshes) {
|
|
if (!mesh.triangulatedFaceVertexIndices.empty()) {
|
|
size_t num_triangles = mesh.triangulatedFaceVertexIndices.size() / 3;
|
|
size_t num_original_faces = mesh.usdFaceVertexCounts.size();
|
|
|
|
total_triangles += num_triangles;
|
|
total_original_faces += num_original_faces;
|
|
|
|
std::cout << "\nMesh: " << mesh.prim_name << "\n";
|
|
std::cout << " Original faces: " << num_original_faces << "\n";
|
|
std::cout << " Triangulated faces: " << num_triangles << "\n";
|
|
|
|
// Count polygon types
|
|
std::map<uint32_t, size_t> poly_counts;
|
|
for (auto count : mesh.usdFaceVertexCounts) {
|
|
poly_counts[count]++;
|
|
}
|
|
|
|
std::cout << " Original polygon distribution:\n";
|
|
for (const auto& kv : poly_counts) {
|
|
std::cout << " " << kv.first << "-gons: " << kv.second << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
std::cout << "\nTotal original faces: " << total_original_faces << "\n";
|
|
std::cout << "Total triangles: " << total_triangles << "\n";
|
|
|
|
if (use_fan) {
|
|
std::cout << "\nNote: Triangle fan was used for 5+ vertex polygons.\n";
|
|
std::cout << "This is faster but assumes polygons are convex.\n";
|
|
} else {
|
|
std::cout << "\nNote: Earcut algorithm was used for 5+ vertex polygons.\n";
|
|
std::cout << "This handles complex polygons correctly.\n";
|
|
}
|
|
|
|
return 0;
|
|
} |