This guide shows how to add Solidean to a C++17 project and run your first exact boolean.
(Example uses the no-dependency C++17 binding. Other languages follow the same concepts.)
Add Solidean to your build (CMake)
Create or update your CMakeLists.txt:
# Point this to the Solidean SDK you received
add_subdirectory(path/to/solidean/lang/cpp17)
# Link the C++17 binding target
target_link_libraries(YourProject PRIVATE Solidean::Cpp17)
Ensure the Solidean dynamic library (solidean.dll on Windows / libsolidean.so on Linux) is discoverable at runtime (same folder as your binary or on the system path).
Minimal Solidean example (C++17)
#include <solidean.hh>
// Triangle3D is your app's POD of 9 floats (3 x pos3)
struct Triangle3D { float x0,y0,z0, x1,y1,z1, x2,y2,z2; };
int main() {
// 1) Create a context (thread pools, license check, scratch)
auto ctx = solidean::Context::create();
// 2) Choose exact arithmetic (absolute bounding box)
// All coordinates during computation must lie within [-maxCoord, +maxCoord]
float maxCoord = 1000.0f; // ~7 decimal digits within this box for Fixed256Pos26
auto arithmetic = ctx->createExactArithmetic(maxCoord);
// 3) Execute an operation: import -> boolean -> export
auto resultBlob = ctx->execute(*arithmetic, [&](solidean::Operation& op) {
// Import float triangle soups as exact mesh operands
auto meshA = op.importFromTrianglesF32(/* std::span<Triangle3D> or equivalent */);
auto meshB = op.importFromTrianglesF32(/* ... */);
// Compute A \ B as an exact temporary result
auto resultMesh = op.difference(meshA, meshB);
// Export unrolled float32 triangles (choose indexed/half-edge if you need topology)
return op.exportToTrianglesF32(resultMesh);
});
// 4) Read back the triangles
auto triangles = resultBlob->getTrianglesF32<Triangle3D>();
// ... use your triangles
return 0;
}
What just happened?
- Exact arithmetic converts floats to an internal exact representation (no robustness loss).
- Operation records work (imports, booleans, exports).
Context::executeoptimizes and runs it (multi-threaded by default). - Export materializes results in your chosen format (unrolled triangles above).
Choosing the right export
For connected output and de-duplication, prefer indexed or half-edge exports:
- Indexed triangles
return op.exportToIndexedTrianglesF32(resultMesh); - Topology-rich (half-edge)
return op.exportMesh(resultMesh, ExportFormat::HalfedgeExplicit, ExportOption::VertexPositionF32 | ExportOption::HalfedgeToFace | ExportOption::HalfedgeToNextHalfedge | ExportOption::HalfedgeToOppositeHalfedge); - Guarantee manifoldness (for any input):
AddExportOption::Manifold(and optionallyPreferLargerManifoldsand/orRemoveSpuriousVertices).
See the API Reference for all ExportFormat / ExportOption combinations.
Messy real-world meshes
If inputs can have holes or non-manifold bits:
- Import with the right guarantees (
MeshType::NonSupersolid/AllowNonSupersolid). - Run
Operation::Heal(upgrades to supersolid robustly). - If you need a strict solid, follow with
Operation::SelfUnion. - Perform booleans and export.
Performance & correctness tips
Default execution is multithreaded (ExecuteMode::Multithreaded).
- Use
Singlethreadedfor deterministic debugging orDebugfor extra validation. - Only enable
AllowSelfIntersections/AllowSurfaceIntersections/AllowNestedComponentswhen needed. They cost performance. - For iterative CSG chains, output only what you need; the scheduler avoids materializing throwaway intermediates.
- Use tracking IDs via
SurfaceBuilder::TrackID(...)and export withExportOption::PrimitiveIDto map inputs → outputs.
If performance is still not where you want it, contact support. Optimizing common pipelines is an ongoing priority.
Next steps
- Browse the API Reference (search functions, classes, and types).
- Scan All Symbols (A–Z) for quick symbol lookup.
- See FAQ for developer-focused questions.
- Check Troubleshooting for common issues and fixes.
- Track changes in the Changelog.