diff --git a/gladius/documentation/3MF_SUPPORT.md b/gladius/documentation/3MF_SUPPORT.md new file mode 100644 index 00000000..247de2c5 --- /dev/null +++ b/gladius/documentation/3MF_SUPPORT.md @@ -0,0 +1,663 @@ +# 3MF Import/Export System Documentation + +## Overview + +Gladius provides comprehensive support for the 3MF file format with the Volumetric Extension, enabling import and export of implicit geometries defined through function graphs. The system bridges between the 3MF XML representation and Gladius's internal node graph structure. + +## 3MF Volumetric Extension + +The 3MF Volumetric Extension defines two main approaches for representing implicit geometries: + +1. **Implicit Namespace**: Function graphs defined as node networks +2. **Image3D**: Volumetric data stored as 3D textures + +Gladius supports both approaches for maximum compatibility. + +## Architecture + +```mermaid +graph TB + subgraph "Import Flow" + File3MF[3MF File] --> Reader[lib3mf Reader] + Reader --> Parser[XML Parser] + Parser --> ImplicitNS{Implicit
Namespace?} + ImplicitNS -->|Yes| GraphImport[Import Graph] + ImplicitNS -->|No| Image3D{Image3D?} + Image3D -->|Yes| TextureImport[Import Texture] + Image3D -->|No| MeshImport[Import Mesh] + GraphImport --> Model[Node Model] + TextureImport --> Resource[Image Resource] + MeshImport --> MeshRes[Mesh Resource] + end + + subgraph "Export Flow" + Model2[Node Model] --> Visitor[Writer Visitor] + Visitor --> GraphExport[Export Graph] + Resource2[Resources] --> ResourceExport[Export Resources] + GraphExport --> XML[XML Generation] + ResourceExport --> XML + XML --> Writer[lib3mf Writer] + Writer --> Output3MF[3MF File] + end +``` + +## Import System + +### Importer3mf Class + +The main entry point for importing 3MF files: + +```cpp +class Importer3mf { +public: + Importer3mf(const std::filesystem::path& filename); + + // Import entire assembly + nodes::SharedAssembly import(); + + // Import specific model + nodes::Model importModel(lib3mf::CModel& model); + + // Import resources + void importResources(lib3mf::CModel& model, + nodes::Assembly& assembly); +}; +``` + +### Import Process + +```mermaid +sequenceDiagram + participant App as Application + participant Imp as Importer3mf + participant Lib as lib3mf + participant Graph as GraphBuilder + participant Res as ResourceManager + + App->>Imp: import(filename) + Imp->>Lib: Read 3MF File + Lib-->>Imp: Model Data + + Imp->>Imp: Parse Build Items + Imp->>Imp: Parse Components + + loop For Each Object + Imp->>Graph: Extract Implicit Function + Graph->>Graph: Create Nodes + Graph->>Graph: Create Connections + Graph-->>Imp: Node Model + end + + loop For Each Resource + Imp->>Res: Load Resource + Res->>Res: Parse Data + Res-->>Imp: Resource Handle + end + + Imp-->>App: Complete Assembly +``` + +### Implicit Function Graph Import + +The system translates 3MF implicit function definitions to node graphs: + +**3MF XML Example:** +```xml + + + + + + + + + + + + + + + + 0 0 0 + + + + + 1.0 + + + + + + + + + + + + + + + + + +``` + +**Corresponding Node Graph:** +```mermaid +graph LR + Begin[Begin Node
id: 1] -->|cs| Sphere[Sphere Node
id: 2
radius: 1.0] + Begin -->|p| Sphere + Sphere -->|distance| End[End Node
id: 3] +``` + +### Node Type Mapping + +The importer maps 3MF node types to Gladius node types: + +| 3MF Type | Gladius Node | Description | +|----------|--------------|-------------| +| `impl:begin` | Begin | Function entry point | +| `impl:end` | End | Function exit point | +| `impl:sphere` | Sphere | Sphere primitive | +| `impl:box` | Box | Box primitive | +| `impl:cylinder` | Cylinder | Cylinder primitive | +| `impl:union` | Union | Boolean union | +| `impl:intersection` | Intersection | Boolean intersection | +| `impl:difference` | Difference | Boolean difference | +| `impl:add` | Add | Scalar addition | +| `impl:multiply` | Multiply | Scalar multiplication | +| `impl:mesh` | MeshResource | Mesh-based SDF | +| `impl:image3d` | ImageStackResource | 3D texture sampling | + +### Resource Import + +Resources are loaded and registered with the ResourceManager: + +```mermaid +flowchart TD + Start[Detect Resource Type] --> CheckMesh{Mesh?} + CheckMesh -->|Yes| LoadMesh[Load Mesh Data] + CheckMesh -->|No| CheckImage{Image3D?} + CheckImage -->|Yes| LoadImage[Load Image Data] + CheckImage -->|No| CheckVDB{VDB?} + CheckVDB -->|Yes| LoadVDB[Load VDB Data] + CheckVDB -->|No| Skip[Skip Unknown] + + LoadMesh --> ConvertMesh[Convert to Internal Format] + LoadImage --> ConvertImage[Convert to OCL Image] + LoadVDB --> ConvertVDB[Convert to Grid] + + ConvertMesh --> Register[Register with ResourceManager] + ConvertImage --> Register + ConvertVDB --> Register + Register --> Complete[Resource Available] +``` + +### Image3D Import + +Image3D resources store volumetric data as 3D textures: + +```xml + + + + + +``` + +Import process: +1. Decode base64 data +2. Parse according to format (float32, uint8, etc.) +3. Upload to OpenCL image buffer +4. Create ImageStackResource reference + +## Export System + +### Writer3mf Class + +The main entry point for exporting to 3MF: + +```cpp +class Writer3mf { +public: + Writer3mf(const std::filesystem::path& filename); + + // Export assembly to 3MF + void write(const nodes::Assembly& assembly); + + // Export with options + void write(const nodes::Assembly& assembly, + const ExportOptions& options); + +private: + void writeModel(lib3mf::CModel& model, + const nodes::Model& nodeModel); + void writeResources(lib3mf::CModel& model, + const nodes::Assembly& assembly); +}; +``` + +### Export Process + +```mermaid +sequenceDiagram + participant App as Application + participant Exp as Writer3mf + participant Visit as Visitor + participant Lib as lib3mf + participant File as File System + + App->>Exp: write(assembly) + Exp->>Lib: Create Model + + loop For Each Component + Exp->>Visit: Visit Node Graph + Visit->>Visit: Generate XML Structure + Visit-->>Exp: XML Nodes + Exp->>Lib: Add Object + end + + loop For Each Resource + Exp->>Exp: Serialize Resource + Exp->>Lib: Add Attachment + end + + Exp->>Lib: Add Build Items + Exp->>Lib: Add Metadata + Exp->>Lib: Write to File + Lib->>File: Write 3MF Package + File-->>App: Complete +``` + +### Node Graph Export + +The export system traverses the node graph and generates 3MF XML: + +```cpp +class ToXMLVisitor : public Visitor { +public: + void visit(NodeBase& node) override { + // Generate XML for this node + auto xmlNode = createXMLNode(node); + + // Export parameters + for (const auto& param : node.getParameters()) { + xmlNode.addParameter(param); + } + + // Export connections + for (const auto& input : node.getInputs()) { + if (input.isConnected()) { + xmlNode.addConnection(input.getConnectedPort()); + } + } + + m_xmlNodes.push_back(xmlNode); + } + +private: + std::vector m_xmlNodes; +}; +``` + +### Export Options + +Various options control the export process: + +```cpp +struct ExportOptions { + bool embedResources{true}; // Embed or reference externally + bool optimizeGraph{true}; // Remove unused nodes + bool includeMetadata{true}; // Export metadata + ImageFormat imageFormat{Float32}; // Format for Image3D + int imageResolution{256}; // Resolution for Image3D +}; +``` + +### Mesh Export from Implicit Functions + +Gladius can generate explicit meshes from implicit functions: + +```mermaid +flowchart LR + subgraph "Conversion Process" + Implicit[Implicit Function] --> Sample[Sample SDF] + Sample --> MC[Marching Cubes] + MC --> Mesh[Triangle Mesh] + Mesh --> Optimize[Optimize Topology] + Optimize --> Output[3MF Mesh] + end +``` + +**Process:** +1. **Sample SDF**: Evaluate implicit function on regular grid +2. **Marching Cubes**: Extract isosurface at distance = 0 +3. **Optimize**: Remove duplicate vertices, fix topology +4. **Export**: Write as standard 3MF mesh + +### Resource Dependencies + +The exporter tracks resource dependencies to ensure all required resources are included: + +```mermaid +graph TD + Assembly[Assembly] --> Comp1[Component 1] + Assembly --> Comp2[Component 2] + Comp1 --> Mesh1[Mesh Resource] + Comp1 --> Image1[Image Resource] + Comp2 --> Mesh1 + Comp2 --> VDB1[VDB Resource] + + style Mesh1 fill:#FFE4B5 + style Image1 fill:#FFE4B5 + style VDB1 fill:#FFE4B5 +``` + +**Dependency Resolution:** +```cpp +class ResourceDependencyGraph { +public: + // Add resource dependency + void addDependency(ResourceId source, ResourceId target); + + // Get all dependencies + std::vector getAllDependencies(ResourceId root); + + // Topologically sort resources + std::vector getExportOrder(); +}; +``` + +## Function Comparator + +When exporting, the system can detect identical functions and share them: + +```cpp +class FunctionComparator { +public: + // Compare two node graphs for equality + bool areEqual(const nodes::Model& a, const nodes::Model& b); + + // Compute hash for quick comparison + size_t computeHash(const nodes::Model& model); + +private: + bool compareNodes(const NodeBase& a, const NodeBase& b); + bool compareConnections(const Model& a, const Model& b); +}; +``` + +**Benefits:** +- Reduced file size +- Faster loading +- Better memory usage + +## Metadata Handling + +### Standard Metadata + +Gladius supports standard 3MF metadata: + +```xml +My Part +John Doe +Example part with implicit geometry +2024-01-15T10:30:00Z +Gladius +1.2.0 +``` + +### Custom Metadata + +Gladius-specific metadata for preserving application state: + +```xml + + 0 0 10 + 0 0 0 + 0 1 0 + +Rendered + + + +``` + +## Error Handling + +### Import Errors + +Common import errors and their handling: + +| Error | Cause | Resolution | +|-------|-------|------------| +| Invalid XML | Malformed 3MF file | Report parse error with line number | +| Unknown node type | Unsupported node type | Skip node or use fallback | +| Missing resource | Referenced resource not found | Create placeholder or report error | +| Cyclic graph | Invalid node connections | Reject import, show error | +| Version mismatch | Incompatible 3MF version | Attempt compatibility mode | + +### Export Errors + +Common export errors and their handling: + +| Error | Cause | Resolution | +|-------|-------|------------| +| Unsupported feature | Node type not in 3MF spec | Convert to supported equivalent | +| Resource too large | Image/mesh exceeds size limit | Downsample or split | +| Invalid graph | Begin/End missing | Validate before export | +| Write failure | Disk full, permissions | Report I/O error | + +## Validation + +### Import Validation + +The importer validates imported data: + +```cpp +class GraphValidator { +public: + struct ValidationResult { + bool valid; + std::vector errors; + std::vector warnings; + }; + + ValidationResult validate(const nodes::Model& model); + +private: + bool checkBeginEnd(const Model& model); + bool checkConnections(const Model& model); + bool checkCycles(const Model& model); + bool checkTypes(const Model& model); +}; +``` + +**Validation Checks:** +- Begin and End nodes present +- All required inputs connected +- No cycles in graph +- Type compatibility of connections +- Valid parameter values + +### Export Validation + +Before exporting, the system validates: +- Graph is complete and valid +- All resources are available +- No unsupported features used +- File can be written to destination + +## Performance Considerations + +### Large Files + +For large 3MF files with embedded resources: + +1. **Streaming**: Read resources on-demand rather than loading all at once +2. **Compression**: Use ZIP compression within 3MF package +3. **Progress Reporting**: Show progress for long operations +4. **Chunking**: Process resources in chunks + +### Memory Usage + +```mermaid +flowchart TD + Start[Begin Import] --> CheckSize{File Size?} + CheckSize -->|Small| LoadAll[Load Entirely] + CheckSize -->|Large| Stream[Stream Resources] + LoadAll --> Parse[Parse All Data] + Stream --> OnDemand[Load On Demand] + Parse --> Complete[Import Complete] + OnDemand --> Complete +``` + +## Compatibility + +### 3MF Specification Versions + +Gladius supports: +- **3MF Core 1.3**: Base specification +- **Volumetric Extension Draft**: Implicit functions +- **Materials and Properties**: Basic material support + +### Backward Compatibility + +When exporting, Gladius can target different specification versions: + +```cpp +enum class SpecVersion { + Core_1_0, + Core_1_3, + Volumetric_Draft +}; + +ExportOptions options; +options.targetVersion = SpecVersion::Core_1_3; +``` + +## Example Workflows + +### Import and Modify + +```cpp +// Import 3MF file +Importer3mf importer("input.3mf"); +auto assembly = importer.import(); + +// Modify node graph +auto& model = assembly->getModel(); +auto sphereNode = model.getNode(nodeId); +sphereNode->setParameter("radius", 2.0f); + +// Export modified version +Writer3mf writer("output.3mf"); +writer.write(*assembly); +``` + +### Batch Conversion + +```cpp +// Convert multiple 3MF files +for (const auto& file : inputFiles) { + Importer3mf importer(file); + auto assembly = importer.import(); + + // Apply transformations + processAssembly(*assembly); + + // Export as STL + MeshExporter exporter(file.replace_extension(".stl")); + exporter.exportMesh(*assembly); +} +``` + +### Resource Extraction + +```cpp +// Extract resources from 3MF +Importer3mf importer("model.3mf"); +auto assembly = importer.import(); + +// Save resources separately +for (const auto& resource : assembly->getResources()) { + if (auto mesh = dynamic_cast(resource)) { + mesh->save(mesh->getName() + ".stl"); + } + if (auto image = dynamic_cast(resource)) { + image->save(image->getName() + ".raw"); + } +} +``` + +## Testing + +### Unit Tests + +Test individual import/export operations: + +```cpp +TEST(Writer3mf_Tests, ExportSimpleSphere) { + // Create model with sphere + nodes::Model model; + model.createBeginEnd(); + auto sphere = model.addNode(std::make_unique()); + model.connect(/* ... */); + + // Export + Writer3mf writer("test_sphere.3mf"); + writer.write(model); + + // Verify file exists and is valid + ASSERT_TRUE(std::filesystem::exists("test_sphere.3mf")); +} +``` + +### Integration Tests + +Test round-trip import/export: + +```cpp +TEST(Importer3mf_tests, RoundTripEquality) { + // Export original + Writer3mf writer1("original.3mf"); + writer1.write(originalAssembly); + + // Import + Importer3mf importer("original.3mf"); + auto imported = importer.import(); + + // Export again + Writer3mf writer2("reimported.3mf"); + writer2.write(*imported); + + // Compare models + FunctionComparator comparator; + ASSERT_TRUE(comparator.areEqual( + originalAssembly.getModel(), + imported->getModel() + )); +} +``` + +## Future Enhancements + +- **Streaming Import**: Support for extremely large files +- **Incremental Export**: Update existing 3MF files without full rewrite +- **Parallel Processing**: Multi-threaded resource loading +- **Advanced Compression**: Better compression for volumetric data +- **Cloud Integration**: Direct import/export from cloud storage +- **Version Control**: Track changes between 3MF file versions + +## Related Documentation + +- [Architecture Overview](ARCHITECTURE.md) +- [Node System Documentation](NODE_SYSTEM.md) +- [Resource Management](RESOURCE_MANAGEMENT.md) +- [API Reference](API_REFERENCE.md) diff --git a/gladius/documentation/API_REFERENCE.md b/gladius/documentation/API_REFERENCE.md new file mode 100644 index 00000000..9a4ba38d --- /dev/null +++ b/gladius/documentation/API_REFERENCE.md @@ -0,0 +1,833 @@ +# API Reference Documentation + +## Overview + +Gladius provides a comprehensive API for programmatic access to its functionality. The API is generated using the Automatic Component Toolkit (ACT), enabling bindings for multiple programming languages including C++, C#, and Python. + +## Language Bindings + +The API is available in multiple languages: + +- **C++**: Native C++ interface with modern C++17 features +- **C**: Dynamic C interface for maximum compatibility +- **C#**: .NET bindings with C# conventions +- **Python**: Python 3.x bindings with Pythonic interface + +```mermaid +graph TB + subgraph "API Definition" + XML[Gladius.xml
ACT Definition] + end + + subgraph "Generated Bindings" + CPP[C++ API] + C[C Dynamic API] + CS[C# API] + PY[Python API] + end + + subgraph "Implementation" + Impl[C++ Implementation] + end + + XML -->|ACT Generate| CPP + XML -->|ACT Generate| C + XML -->|ACT Generate| CS + XML -->|ACT Generate| PY + + CPP --> Impl + C --> Impl + CS --> Impl + PY --> Impl +``` + +## Core API Structure + +### Class Hierarchy + +```mermaid +classDiagram + class Base { + <> + +GetLastError() bool + +AcquireInstance() + +ReleaseInstance() + } + + class Gladius { + +LoadModel(filename) Model + +CreateModel() Model + +GetVersion() string + } + + class Model { + +AddBuildItem(item) void + +GetBuildItemCount() int + +GetBuildItem(index) BuildItem + +AddComponent(component) void + +GenerateSlice(z, resolution) Slice + +ExportMesh(filename) void + +ExportContours(filename) void + } + + class BuildItem { + +GetObjectID() int + +GetTransform() Matrix4x4 + +SetTransform(transform) void + +GetBoundingBox() BoundingBox + } + + class Component { + +GetName() string + +SetName(name) void + +GetNodeGraph() NodeGraph + } + + class Slice { + +GetContourCount() int + +GetContour(index) Contour + +GetZHeight() float + +GetBoundingBox() BoundingBox + } + + class Contour { + +GetPointCount() int + +GetPoint(index) Vector2f + +GetClosed() bool + } + + class Mesh { + +GetFaceCount() int + +GetFace(index) Face + +GetBoundingBox() BoundingBox + } + + class Face { + +GetVertexA() Vector3f + +GetVertexB() Vector3f + +GetVertexC() Vector3f + +GetNormal() Vector3f + } + + Base <|-- Gladius + Base <|-- Model + Base <|-- BuildItem + Base <|-- Component + Base <|-- Slice + Base <|-- Contour + Base <|-- Mesh + Base <|-- Face + + Gladius --> Model + Model --> BuildItem + Model --> Component + Model --> Slice + Slice --> Contour + Model --> Mesh + Mesh --> Face +``` + +## API Methods + +### Gladius Class + +The main entry point for the API. + +#### CreateGladius() +```cpp +// C++ +Gladius* gladius = CreateGladius(); + +// C# +var gladius = new Gladius(); + +// Python +gladius = gladiuslib.CreateGladius() +``` + +Creates a new Gladius instance. + +**Returns:** Pointer/reference to Gladius instance + +#### GetVersion() +```cpp +// C++ +uint32_t major, minor, micro; +gladius->GetVersion(major, minor, micro); + +// C# +gladius.GetVersion(out uint major, out uint minor, out uint micro); + +// Python +major, minor, micro = gladius.GetVersion() +``` + +Retrieves the library version. + +**Parameters:** +- `major` (out): Major version number +- `minor` (out): Minor version number +- `micro` (out): Micro version number + +#### LoadModel() +```cpp +// C++ +Model* model = gladius->LoadModel("model.3mf"); + +// C# +var model = gladius.LoadModel("model.3mf"); + +// Python +model = gladius.LoadModel("model.3mf") +``` + +Loads a 3MF model from file. + +**Parameters:** +- `filename` (string): Path to 3MF file + +**Returns:** Model instance + +**Throws:** Exception if file not found or invalid + +#### CreateModel() +```cpp +// C++ +Model* model = gladius->CreateModel(); + +// C# +var model = gladius.CreateModel(); + +// Python +model = gladius.CreateModel() +``` + +Creates an empty model. + +**Returns:** New Model instance + +### Model Class + +Represents a 3D model with implicit geometry. + +#### AddBuildItem() +```cpp +// C++ +model->AddBuildItem(objectID, transform); + +// C# +model.AddBuildItem(objectID, transform); + +// Python +model.AddBuildItem(objectID, transform) +``` + +Adds a build item to the model. + +**Parameters:** +- `objectID` (int): ID of the object to build +- `transform` (Matrix4x4): Transformation matrix + +#### GetBuildItemCount() +```cpp +// C++ +uint32_t count = model->GetBuildItemCount(); + +// C# +uint count = model.GetBuildItemCount(); + +// Python +count = model.GetBuildItemCount() +``` + +Gets the number of build items. + +**Returns:** Number of build items + +#### GetBuildItem() +```cpp +// C++ +BuildItem* item = model->GetBuildItem(0); + +// C# +var item = model.GetBuildItem(0); + +// Python +item = model.GetBuildItem(0) +``` + +Gets a build item by index. + +**Parameters:** +- `index` (int): Build item index (0-based) + +**Returns:** BuildItem instance + +#### GenerateSlice() +```cpp +// C++ +Slice* slice = model->GenerateSlice(5.0f, 1024); + +// C# +var slice = model.GenerateSlice(5.0f, 1024); + +// Python +slice = model.GenerateSlice(5.0, 1024) +``` + +Generates a 2D slice at specified Z-height. + +**Parameters:** +- `zHeight` (float): Z-coordinate of the slice plane +- `resolution` (int): Resolution of the slice image + +**Returns:** Slice instance containing contours + +#### ExportMesh() +```cpp +// C++ +model->ExportMesh("output.stl"); + +// C# +model.ExportMesh("output.stl"); + +// Python +model.ExportMesh("output.stl") +``` + +Exports the model as a triangle mesh. + +**Parameters:** +- `filename` (string): Output file path +- Supported formats: STL, 3MF + +**Throws:** Exception if export fails + +#### ExportContours() +```cpp +// C++ +model->ExportContours("output.svg", 0.0f, 10.0f, 0.1f); + +// C# +model.ExportContours("output.svg", 0.0f, 10.0f, 0.1f); + +// Python +model.ExportContours("output.svg", 0.0, 10.0, 0.1) +``` + +Exports contours for a range of Z-heights. + +**Parameters:** +- `filename` (string): Output file path (SVG or CLI format) +- `zMin` (float): Minimum Z-height +- `zMax` (float): Maximum Z-height +- `zStep` (float): Z-height increment + +#### GetBoundingBox() +```cpp +// C++ +BoundingBox* bbox = model->GetBoundingBox(); +Vector3f min = bbox->GetMin(); +Vector3f max = bbox->GetMax(); + +// C# +var bbox = model.GetBoundingBox(); +var min = bbox.GetMin(); +var max = bbox.GetMax(); + +// Python +bbox = model.GetBoundingBox() +min_pt = bbox.GetMin() +max_pt = bbox.GetMax() +``` + +Gets the axis-aligned bounding box. + +**Returns:** BoundingBox instance + +### BuildItem Class + +Represents an instance of an object in the build volume. + +#### GetObjectID() +```cpp +// C++ +uint32_t objectID = buildItem->GetObjectID(); + +// C# +uint objectID = buildItem.GetObjectID(); + +// Python +object_id = buildItem.GetObjectID() +``` + +Gets the ID of the referenced object. + +**Returns:** Object ID + +#### GetTransform() +```cpp +// C++ +Matrix4x4 transform = buildItem->GetTransform(); + +// C# +var transform = buildItem.GetTransform(); + +// Python +transform = buildItem.GetTransform() +``` + +Gets the transformation matrix. + +**Returns:** 4x4 transformation matrix + +#### SetTransform() +```cpp +// C++ +Matrix4x4 transform = /* ... */; +buildItem->SetTransform(transform); + +// C# +var transform = /* ... */; +buildItem.SetTransform(transform); + +// Python +transform = # ... +buildItem.SetTransform(transform) +``` + +Sets the transformation matrix. + +**Parameters:** +- `transform` (Matrix4x4): New transformation + +### Slice Class + +Represents a 2D slice of the model. + +#### GetContourCount() +```cpp +// C++ +uint32_t count = slice->GetContourCount(); + +// C# +uint count = slice.GetContourCount(); + +// Python +count = slice.GetContourCount() +``` + +Gets the number of contours in the slice. + +**Returns:** Number of contours + +#### GetContour() +```cpp +// C++ +Contour* contour = slice->GetContour(0); + +// C# +var contour = slice.GetContour(0); + +// Python +contour = slice.GetContour(0) +``` + +Gets a contour by index. + +**Parameters:** +- `index` (int): Contour index (0-based) + +**Returns:** Contour instance + +#### GetZHeight() +```cpp +// C++ +float z = slice->GetZHeight(); + +// C# +float z = slice.GetZHeight(); + +// Python +z = slice.GetZHeight() +``` + +Gets the Z-height of the slice. + +**Returns:** Z-coordinate + +### Contour Class + +Represents a closed or open 2D contour. + +#### GetPointCount() +```cpp +// C++ +uint32_t count = contour->GetPointCount(); + +// C# +uint count = contour.GetPointCount(); + +// Python +count = contour.GetPointCount() +``` + +Gets the number of points in the contour. + +**Returns:** Number of points + +#### GetPoint() +```cpp +// C++ +Vector2f point = contour->GetPoint(0); + +// C# +var point = contour.GetPoint(0); + +// Python +point = contour.GetPoint(0) +``` + +Gets a point by index. + +**Parameters:** +- `index` (int): Point index (0-based) + +**Returns:** 2D point coordinates + +#### GetClosed() +```cpp +// C++ +bool closed = contour->GetClosed(); + +// C# +bool closed = contour.GetClosed(); + +// Python +closed = contour.GetClosed() +``` + +Checks if the contour is closed. + +**Returns:** True if closed, false if open + +### Mesh Class + +Represents a triangle mesh (for mesh export). + +#### GetFaceCount() +```cpp +// C++ +uint32_t count = mesh->GetFaceCount(); + +// C# +uint count = mesh.GetFaceCount(); + +// Python +count = mesh.GetFaceCount() +``` + +Gets the number of triangular faces. + +**Returns:** Number of faces + +#### GetFace() +```cpp +// C++ +Face* face = mesh->GetFace(0); + +// C# +var face = mesh.GetFace(0); + +// Python +face = mesh.GetFace(0) +``` + +Gets a face by index. + +**Parameters:** +- `index` (int): Face index (0-based) + +**Returns:** Face instance + +### Face Class + +Represents a triangular face. + +#### GetVertexA/B/C() +```cpp +// C++ +Vector3f va = face->GetVertexA(); +Vector3f vb = face->GetVertexB(); +Vector3f vc = face->GetVertexC(); + +// C# +var va = face.GetVertexA(); +var vb = face.GetVertexB(); +var vc = face.GetVertexC(); + +// Python +va = face.GetVertexA() +vb = face.GetVertexB() +vc = face.GetVertexC() +``` + +Gets the three vertices of the triangle. + +**Returns:** 3D vertex coordinates + +#### GetNormal() +```cpp +// C++ +Vector3f normal = face->GetNormal(); + +// C# +var normal = face.GetNormal(); + +// Python +normal = face.GetNormal() +``` + +Gets the face normal. + +**Returns:** 3D normal vector + +## Data Types + +### Vector2f +```cpp +struct Vector2f { + float x, y; +}; +``` + +### Vector3f +```cpp +struct Vector3f { + float x, y, z; +}; +``` + +### Matrix4x4 +```cpp +struct Matrix4x4 { + float m[16]; // Column-major order +}; +``` + +## Error Handling + +All API methods can throw exceptions. Always use appropriate error handling: + +### C++ +```cpp +try { + Model* model = gladius->LoadModel("model.3mf"); + // Use model +} catch (const GladiusException& e) { + std::cerr << "Error: " << e.what() << std::endl; +} +``` + +### C# +```cpp +try { + var model = gladius.LoadModel("model.3mf"); + // Use model +} catch (GladiusException e) { + Console.WriteLine($"Error: {e.Message}"); +} +``` + +### Python +```python +try: + model = gladius.LoadModel("model.3mf") + # Use model +except gladiuslib.GladiusException as e: + print(f"Error: {e}") +``` + +## Usage Examples + +### Load and Slice + +```cpp +// C++ +auto gladius = CreateGladius(); +auto model = gladius->LoadModel("input.3mf"); + +// Generate slices +for (float z = 0.0f; z < 10.0f; z += 0.1f) { + auto slice = model->GenerateSlice(z, 2048); + + // Process each contour + for (uint32_t i = 0; i < slice->GetContourCount(); i++) { + auto contour = slice->GetContour(i); + // Process contour points + } +} +``` + +```python +# Python +gladius = gladiuslib.CreateGladius() +model = gladius.LoadModel("input.3mf") + +# Generate slices +for z in range(0, 100, 1): # 0 to 10mm in 0.1mm steps + slice_obj = model.GenerateSlice(z / 10.0, 2048) + + # Process each contour + for i in range(slice_obj.GetContourCount()): + contour = slice_obj.GetContour(i) + # Process contour points +``` + +### Export Mesh + +```cpp +// C++ +auto gladius = CreateGladius(); +auto model = gladius->LoadModel("input.3mf"); + +// Export as STL +model->ExportMesh("output.stl"); +``` + +```csharp +// C# +var gladius = new Gladius(); +var model = gladius.LoadModel("input.3mf"); + +// Export as STL +model.ExportMesh("output.stl"); +``` + +### Batch Processing + +```python +# Python +import gladiuslib +import os + +gladius = gladiuslib.CreateGladius() + +# Process all 3MF files in directory +for filename in os.listdir("input"): + if filename.endswith(".3mf"): + model = gladius.LoadModel(f"input/{filename}") + + # Export as STL + output_name = filename.replace(".3mf", ".stl") + model.ExportMesh(f"output/{output_name}") + + print(f"Processed {filename}") +``` + +### Integration with Slicer + +```cpp +// C++ slicer integration +class GladiusSlicer { +public: + void sliceModel(const std::string& filename) { + auto gladius = CreateGladius(); + auto model = gladius->LoadModel(filename); + + // Get bounding box + auto bbox = model->GetBoundingBox(); + auto min = bbox->GetMin(); + auto max = bbox->GetMax(); + + // Generate slices + float layerHeight = 0.2f; // 0.2mm layers + for (float z = min.z; z <= max.z; z += layerHeight) { + auto slice = model->GenerateSlice(z, 4096); + + // Convert to toolpaths + generateToolpaths(slice); + } + } + +private: + void generateToolpaths(Slice* slice) { + for (uint32_t i = 0; i < slice->GetContourCount(); i++) { + auto contour = slice->GetContour(i); + + // Generate G-code for this contour + for (uint32_t j = 0; j < contour->GetPointCount(); j++) { + auto point = contour->GetPoint(j); + // Generate G-code + } + } + } +}; +``` + +## Thread Safety + +The API is **not thread-safe** by default. Each thread should: +1. Create its own Gladius instance, or +2. Use external synchronization (mutexes) + +```cpp +// Multiple threads - separate instances +void threadFunction(const std::string& filename) { + auto gladius = CreateGladius(); // Thread-local instance + auto model = gladius->LoadModel(filename); + // Process model +} +``` + +## Memory Management + +### C++ +- Use RAII and smart pointers +- Objects are reference counted +- Call `ReleaseInstance()` when done (or use smart pointer wrapper) + +### C# +- Automatic garbage collection +- Implements `IDisposable` +- Use `using` statements for automatic cleanup + +```csharp +using (var gladius = new Gladius()) { + var model = gladius.LoadModel("input.3mf"); + // Use model +} // Automatic cleanup +``` + +### Python +- Automatic reference counting +- Objects are cleaned up when out of scope +- Can manually call `del` if needed + +## Performance Tips + +1. **Reuse instances**: Create Gladius instance once, load multiple models +2. **Cache slices**: Store frequently used slices rather than regenerating +3. **Appropriate resolution**: Use lower resolution for preview, higher for export +4. **Batch operations**: Process multiple items in one session + +## Building API Bindings + +The API bindings are generated from `Gladius.xml` using ACT: + +```bash +# Generate all bindings +act Gladius.xml + +# Generate specific language +act Gladius.xml --binding cpp +act Gladius.xml --binding csharp +act Gladius.xml --binding python +``` + +## Related Documentation + +- [Architecture Overview](ARCHITECTURE.md) +- [Developer Guide](DEVELOPER_GUIDE.md) +- [3MF Support](3MF_SUPPORT.md) +- [Examples and Tutorials](EXAMPLES.md) diff --git a/gladius/documentation/ARCHITECTURE.md b/gladius/documentation/ARCHITECTURE.md new file mode 100644 index 00000000..42bafe98 --- /dev/null +++ b/gladius/documentation/ARCHITECTURE.md @@ -0,0 +1,403 @@ +# Gladius Architecture Overview + +## Introduction + +Gladius is a development tool for processing implicit geometries, specifically designed as a playground for the 3MF Volumetric Extension. The software combines a graphical programming interface with a high-performance rendering engine to enable the design and visualization of complex 3D parts using Constructive Solid Geometry (CSG) principles. + +## System Architecture + +```mermaid +graph TB + subgraph "User Interface Layer" + UI[MainWindow
ImGUI-based UI] + NodeEditor[Node Editor
Graph Editing] + RenderWindow[Render Window
3D Visualization] + Dialogs[Export/Import
Dialogs] + end + + subgraph "Application Layer" + App[Application
Main Controller] + Config[ConfigManager
Settings] + Document[Document
State Management] + Backup[BackupManager
Auto-save] + end + + subgraph "Node System" + Model[Model
Node Graph] + Nodes[Node Types
Functions/Operations] + Assembly[Assembly
Component Container] + Visitor[Visitors
Graph Traversal] + end + + subgraph "Compute Pipeline" + ComputeCore[ComputeCore
Execution Engine] + ComputeCtx[ComputeContext
OpenCL Context] + Programs[CL Programs
Kernels] + Resources[Resource Manager
Buffers/Textures] + end + + subgraph "I/O System" + Import[Importers
3MF, VDB] + Export[Exporters
3MF, STL, SVG] + FileIO[File System Utils
Path Management] + end + + UI --> App + NodeEditor --> Model + RenderWindow --> ComputeCore + App --> Document + App --> Config + Document --> Model + Model --> Visitor + Visitor --> ComputeCore + ComputeCore --> ComputeCtx + ComputeCore --> Programs + ComputeCore --> Resources + Import --> Model + Export --> Model + Model --> Assembly + Assembly --> Nodes +``` + +## Core Components + +### 1. Application Layer + +The application layer manages the overall lifecycle and provides coordination between major subsystems. + +- **Application**: Main entry point that initializes the UI and configuration +- **ConfigManager**: Manages application settings and preferences +- **Document**: Maintains the current working document state +- **BackupManager**: Provides auto-save functionality for crash recovery + +### 2. Node System + +The node system implements a dataflow graph for defining implicit functions using CSG operations. + +```mermaid +classDiagram + class Model { + +NodeRegistry nodes + +PortRegistry ports + +addNode() + +removeNode() + +connect() + +disconnect() + } + + class NodeBase { + +NodeId id + +NodeName name + +Category category + +Ports inputs + +Ports outputs + +evaluate() + } + + class Assembly { + +Model model + +Components components + +BuildItems buildItems + } + + class Visitor { + <> + +visit(NodeBase) + +traverse(Model) + } + + class ToOCLVisitor { + +generateKernelCode() + } + + class ToCommandStreamVisitor { + +generateCommandStream() + } + + Model o-- NodeBase + Model --> Assembly + Visitor <|-- ToOCLVisitor + Visitor <|-- ToCommandStreamVisitor + Visitor --> Model +``` + +**Key Node Types:** +- **Begin/End**: Entry and exit points for function graphs +- **Primitives**: Basic shapes (sphere, box, cylinder, etc.) +- **Operations**: Boolean operations (union, intersection, difference) +- **Functions**: Mathematical functions (sin, cos, smoothstep, etc.) +- **Resources**: External data (meshes, images, VDB volumes) + +### 3. Compute Pipeline + +The compute pipeline uses OpenCL for GPU-accelerated evaluation of implicit functions. + +```mermaid +sequenceDiagram + participant App as Application + participant Core as ComputeCore + participant Ctx as ComputeContext + participant OCL as OpenCL Device + participant Render as RenderProgram + + App->>Core: Initialize with Model + Core->>Ctx: Create OpenCL Context + Ctx->>OCL: Select Device + Core->>Render: Compile Kernels + Render->>OCL: Upload Kernel Code + + loop Render Frame + App->>Core: Update Camera + Core->>Render: Execute Kernel + Render->>OCL: Enqueue Kernel + OCL-->>Render: Return Image Buffer + Render-->>App: Display Result + end +``` + +**Key Components:** +- **ComputeCore**: Orchestrates compute operations and manages programs +- **ComputeContext**: Manages OpenCL context, devices, and command queues +- **RenderProgram**: Ray marching renderer for implicit surfaces +- **SlicerProgram**: Generates slices and contours at specified Z-heights +- **CLProgram**: Base class for OpenCL program management + +### 4. Resource Management + +Resources (meshes, images, VDB volumes) are managed centrally to enable sharing and efficient memory usage. + +```mermaid +graph LR + subgraph "Resource System" + RM[ResourceManager] + RC[ResourceContext] + + subgraph "Resource Types" + Mesh[MeshResource] + Image[ImageStackResource] + VDB[VdbResource] + end + + subgraph "Buffers" + OCL[OpenCL Buffers] + GL[OpenGL Buffers] + CPU[CPU Memory] + end + end + + RM --> RC + RM --> Mesh + RM --> Image + RM --> VDB + Mesh --> OCL + Image --> OCL + VDB --> OCL + OCL <--> GL + OCL <--> CPU +``` + +### 5. I/O System + +The I/O system handles import and export of various file formats, with special focus on 3MF with volumetric extension. + +**Import Formats:** +- 3MF with volumetric extension (implicit namespace and Image3D) +- OpenVDB volumes + +**Export Formats:** +- 3MF with volumetric extension +- STL (mesh export) +- SVG (contour export) +- CLI (contour export) +- OpenVDB + +### 6. User Interface + +The UI is built with ImGUI and provides an immediate-mode interface for editing and visualization. + +**Main Components:** +- **MainWindow**: Primary application window and menu system +- **NodeView**: Visual node graph editor with drag-and-drop +- **RenderWindow**: 3D viewport with orbital camera controls +- **SliceView**: 2D slice visualization and contour inspection +- **Various Dialogs**: Export configuration, settings, about dialog + +## Data Flow + +### Node Graph Execution Flow + +```mermaid +flowchart TD + Start[User Edits Graph] --> Validate{Valid Graph?} + Validate -->|No| Error[Show Error] + Validate -->|Yes| Flatten[Flatten Graph] + Flatten --> TopoSort[Topological Sort] + TopoSort --> CodeGen[Generate OpenCL Code] + CodeGen --> Compile[Compile Kernels] + Compile --> Execute[Execute on GPU] + Execute --> Display[Display Results] + Display --> Start + + Error --> Start +``` + +### Rendering Pipeline + +```mermaid +flowchart LR + subgraph "Input" + Camera[Camera Position] + Model[Node Model] + Params[Build Parameters] + end + + subgraph "Processing" + KernelGen[Kernel Generation] + RayMarch[Ray Marching] + Shading[Surface Shading] + end + + subgraph "Output" + FrameBuffer[Frame Buffer] + Display[Display] + end + + Camera --> RayMarch + Model --> KernelGen + Params --> KernelGen + KernelGen --> RayMarch + RayMarch --> Shading + Shading --> FrameBuffer + FrameBuffer --> Display +``` + +### Contour Extraction Pipeline + +```mermaid +flowchart TD + Input[Input: Node Model + Z-Height] --> Slice[Generate Slice Image] + Slice --> Extract[Extract Contour Points] + Extract --> Validate[Validate Contours] + Validate --> Connect[Connect Points to Contours] + Connect --> Simplify[Simplify Geometry] + Simplify --> Output[Output: Contour Data] +``` + +## Technology Stack + +### Core Technologies +- **C++17/20**: Primary programming language +- **OpenCL 1.2+**: GPU compute acceleration +- **OpenGL 3.3+**: Graphics rendering +- **ImGUI**: Immediate-mode user interface + +### Key Libraries +- **lib3mf**: 3MF file format support +- **OpenVDB**: Volumetric data structures +- **fmt**: String formatting +- **GTest/GMock**: Unit testing framework + +### Build System +- **CMake**: Cross-platform build configuration +- **vcpkg**: Dependency management + +## Design Patterns + +### Visitor Pattern +Used extensively for traversing the node graph and generating different representations: +- `ToOCLVisitor`: Generates OpenCL kernel code +- `ToCommandStreamVisitor`: Generates command streams for evaluation + +### Resource Acquisition Is Initialization (RAII) +All OpenCL and OpenGL resources use RAII for automatic cleanup: +- Smart pointers for memory management +- Scoped guards for state management + +### Factory Pattern +Node creation uses factory functions for type-safe instantiation: +```cpp +NodeBase* createNodeFromName(const std::string& name, Model& nodes); +``` + +### Observer Pattern +Event logging system for propagating messages throughout the application: +```cpp +class EventLogger { + void logInfo(const std::string& message); + void logWarning(const std::string& message); + void logError(const std::string& message); +}; +``` + +## Threading Model + +Gladius uses a single-threaded architecture with asynchronous GPU execution: + +1. **Main Thread**: UI, event handling, graph editing +2. **OpenCL Command Queues**: Asynchronous GPU kernel execution +3. **Resource Loading**: May use background threads for large files + +## Memory Management + +### CPU Memory +- Smart pointers (`std::unique_ptr`, `std::shared_ptr`) for automatic cleanup +- RAII wrappers for system resources + +### GPU Memory +- OpenCL buffers managed through RAII wrappers +- Shared memory between OpenCL and OpenGL via interop +- Resource pooling to minimize allocation overhead + +## Performance Considerations + +### Optimization Strategies +1. **GPU Acceleration**: All heavy computations run on OpenCL devices +2. **Lazy Evaluation**: Nodes only recompute when dependencies change +3. **Memory Pooling**: Resources are cached and reused when possible +4. **Incremental Updates**: UI updates only affected regions + +### Bottlenecks +- Kernel compilation can be slow on first execution +- Large contour extraction on high-resolution slices +- File I/O for large 3MF files with embedded data + +## Extensibility + +### Adding New Node Types +1. Derive from `NodeBase` or use `ClonableNode` template +2. Define input/output ports and parameters +3. Implement OpenCL kernel code generation +4. Register node type in node factory + +### Adding New File Formats +1. Implement importer/exporter interface +2. Add to file dialog filters +3. Handle resource conversion + +### Adding New UI Components +1. Create new dialog or view class +2. Integrate with MainWindow menu system +3. Use ImGUI immediate-mode API + +## Security Considerations + +- Input validation for all file formats +- Bounds checking in kernel code +- Safe string handling with modern C++ practices +- No unsafe casts or pointer arithmetic in user-facing code + +## Future Directions + +- Multi-GPU support for improved performance +- Network rendering for distributed computation +- Plugin system for third-party extensions +- Python scripting integration +- Advanced optimization passes for graph compilation + +## Related Documentation + +- [Node System Documentation](NODE_SYSTEM.md) +- [Compute Pipeline Documentation](COMPUTE_PIPELINE.md) +- [3MF Import/Export Documentation](3MF_SUPPORT.md) +- [API Reference](API_REFERENCE.md) +- [Developer Guide](DEVELOPER_GUIDE.md) diff --git a/gladius/documentation/COMPUTE_PIPELINE.md b/gladius/documentation/COMPUTE_PIPELINE.md new file mode 100644 index 00000000..586e154d --- /dev/null +++ b/gladius/documentation/COMPUTE_PIPELINE.md @@ -0,0 +1,669 @@ +# Compute Pipeline Documentation + +## Overview + +The Compute Pipeline is the high-performance execution engine of Gladius, utilizing OpenCL for GPU-accelerated evaluation of implicit functions. The pipeline handles kernel compilation, resource management, and execution coordination between the CPU and GPU. + +## Architecture + +```mermaid +graph TB + subgraph "Application Layer" + App[Application] + UI[User Interface] + end + + subgraph "Compute Layer" + Core[ComputeCore
Orchestration] + Manager[ProgramManager
Kernel Management] + Render[RenderProgram
Ray Marching] + Slicer[SlicerProgram
Contour Generation] + end + + subgraph "OpenCL Layer" + Context[ComputeContext
Device Context] + Queue[Command Queues] + Kernels[Compiled Kernels] + end + + subgraph "Resource Layer" + ResCtx[ResourceContext
Memory Management] + Buffers[OpenCL Buffers] + Textures[OpenCL Images] + GLInterop[OpenGL Interop] + end + + subgraph "Hardware" + GPU[GPU Device] + end + + App --> Core + UI --> Core + Core --> Manager + Core --> Render + Core --> Slicer + Manager --> Context + Render --> Context + Slicer --> Context + Context --> Queue + Context --> Kernels + Core --> ResCtx + ResCtx --> Buffers + ResCtx --> Textures + ResCtx --> GLInterop + Queue --> GPU + Kernels --> GPU + Buffers --> GPU + Textures --> GPU +``` + +## Core Components + +### ComputeContext + +The `ComputeContext` manages the OpenCL environment, including device selection, context creation, and command queue management. + +```mermaid +classDiagram + class ComputeContext { + -cl::Device m_device + -cl::Platform m_platform + -cl::Context m_context + -QueuePerThread m_queues + -Capabilities m_capabilities + +initialize() + +getDevice() Device + +getContext() Context + +getQueue() CommandQueue + +getCapabilities() Capabilities + } + + class Capabilities { + +bool fp64 + +bool correctlyRoundedDivedSqrt + +bool cpu + +bool gpu + +double performanceEstimation + +OpenCLVersion openCLVersion + } + + class Accelerator { + +Device device + +Platform platform + +Capabilities capabilities + } + + ComputeContext --> Capabilities + ComputeContext --> Accelerator +``` + +**Device Selection Strategy:** + +```mermaid +flowchart TD + Start[Initialize] --> Enumerate[Enumerate Devices] + Enumerate --> FilterGPU{GPU Devices?} + FilterGPU -->|Yes| SelectBestGPU[Select Best GPU] + FilterGPU -->|No| CheckCPU{CPU Devices?} + CheckCPU -->|Yes| SelectCPU[Select CPU] + CheckCPU -->|No| Error[Error: No Devices] + SelectBestGPU --> Estimate[Estimate Performance] + Estimate --> Choose[Choose Highest Performance] + Choose --> CreateContext[Create OpenCL Context] + SelectCPU --> CreateContext + CreateContext --> Success[Ready] +``` + +**Key Features:** +- Automatic device selection based on performance estimation +- Multi-threaded command queue management (one queue per thread) +- Capability detection (FP64, CPU/GPU, OpenCL version) +- Fallback to CPU if no GPU available + +### ComputeCore + +The `ComputeCore` orchestrates all compute operations, managing the lifecycle of programs and coordinating execution. + +```cpp +class ComputeCore { +public: + ComputeCore(SharedComputeContext context, + SharedResourceContext resources); + + // Program management + SharedRenderProgram getRenderProgram(); + SharedSlicerProgram getSlicerProgram(); + + // Execution + void updateModel(const nodes::Model& model); + void render(const Camera& camera, ImageBuffer& output); + void generateSlice(float zHeight, BitmapLayer& output); + +private: + SharedComputeContext m_context; + SharedResourceContext m_resources; + SharedProgramManager m_programManager; +}; +``` + +**Responsibilities:** +- Initialize and manage compute programs +- Coordinate between different execution modes (render, slice, export) +- Handle model updates and kernel recompilation +- Manage resource allocation and cleanup + +### ProgramManager + +The `ProgramManager` handles compilation and caching of OpenCL programs. + +```mermaid +stateDiagram-v2 + [*] --> Uncompiled + Uncompiled --> Compiling: compile() + Compiling --> Compiled: success + Compiling --> Failed: error + Compiled --> Executing: execute() + Executing --> Compiled: complete + Failed --> Uncompiled: retry() +``` + +**Features:** +- Incremental compilation (only recompile when source changes) +- Build error reporting with line numbers +- Kernel parameter caching +- Multi-kernel program support + +## Execution Modes + +### Rendering Pipeline + +The rendering pipeline uses ray marching to visualize implicit surfaces in real-time. + +```mermaid +sequenceDiagram + participant App + participant Core as ComputeCore + participant Render as RenderProgram + participant OCL as OpenCL + participant GPU + + App->>Core: render(camera, output) + Core->>Render: setCamera(camera) + Core->>Render: execute() + Render->>OCL: enqueueNDRangeKernel + OCL->>GPU: Launch Kernel + + Note over GPU: Ray March
For Each Pixel + + GPU-->>OCL: Complete + OCL-->>Render: Image Buffer + Render-->>Core: Result + Core-->>App: Display +``` + +**Ray Marching Algorithm:** + +```mermaid +flowchart TD + Start[For Each Pixel] --> GenRay[Generate Camera Ray] + GenRay --> InitDist[distance = 0] + InitDist --> March{distance < maxDist?} + March -->|Yes| EvalSDF[Evaluate SDF] + EvalSDF --> CheckHit{sdf < threshold?} + CheckHit -->|Yes| CalcShading[Calculate Shading] + CheckHit -->|No| Step[distance += sdf] + Step --> March + March -->|No| Background[Return Background] + CalcShading --> Return[Return Color] + Background --> Return +``` + +**Kernel Structure:** +```c +__kernel void render( + __write_only image2d_t output, + float16 camera, + float4 viewport, + // ... model parameters +) { + int2 pixel = (int2)(get_global_id(0), get_global_id(1)); + + // Generate ray + float3 rayOrigin = camera.s012; + float3 rayDir = calculateRayDirection(pixel, camera, viewport); + + // Ray march + float dist = 0.0f; + for (int i = 0; i < MAX_STEPS && dist < MAX_DIST; i++) { + float3 pos = rayOrigin + rayDir * dist; + float sdf = evaluateModel(pos); + + if (sdf < THRESHOLD) { + // Hit surface - calculate shading + float3 normal = calculateNormal(pos); + float4 color = calculateShading(pos, normal, rayDir); + write_imagef(output, pixel, color); + return; + } + + dist += sdf; + } + + // No hit - background + write_imagef(output, pixel, BACKGROUND_COLOR); +} +``` + +### Slicing Pipeline + +The slicing pipeline generates 2D slices and contours at specified Z-heights. + +```mermaid +flowchart LR + subgraph "Input" + Model[Node Model] + ZHeight[Z Height] + Resolution[Resolution] + end + + subgraph "Processing" + GenKernel[Generate Kernel] + Rasterize[Rasterize SDF] + Extract[Extract Contours] + end + + subgraph "Output" + Bitmap[Bitmap Layer] + Contours[Contour Data] + end + + Model --> GenKernel + ZHeight --> GenKernel + Resolution --> Rasterize + GenKernel --> Rasterize + Rasterize --> Bitmap + Bitmap --> Extract + Extract --> Contours +``` + +**Slice Generation Kernel:** +```c +__kernel void generateSlice( + __write_only image2d_t output, + float zHeight, + float2 bounds_min, + float2 bounds_max + // ... model parameters +) { + int2 pixel = (int2)(get_global_id(0), get_global_id(1)); + int2 size = get_image_dim(output); + + // Calculate world position + float2 uv = (float2)(pixel.x, pixel.y) / (float2)(size.x, size.y); + float2 worldXY = mix(bounds_min, bounds_max, uv); + float3 worldPos = (float3)(worldXY.x, worldXY.y, zHeight); + + // Evaluate SDF at this position + float sdf = evaluateModel(worldPos); + + // Write distance value + write_imagef(output, pixel, (float4)(sdf, 0, 0, 0)); +} +``` + +## Kernel Generation + +### From Node Graph to OpenCL Code + +The system converts node graphs to executable OpenCL kernels using the Visitor pattern: + +```mermaid +flowchart TD + Model[Node Model] --> Flatten[Flatten Graph] + Flatten --> TopoSort[Topological Sort] + TopoSort --> Visitor[ToOCLVisitor] + Visitor --> GenFunc[Generate Functions] + GenFunc --> GenMain[Generate Main Eval] + GenMain --> Header[Add Headers/Helpers] + Header --> Complete[Complete Kernel Code] + Complete --> Compile[Compile with OpenCL] + Compile --> Execute[Ready to Execute] +``` + +**Example Translation:** + +Node Graph: +``` +Begin → Sphere(radius=1.0) → Union → End + → Box(size=0.5) ↗ +``` + +Generated OpenCL: +```c +// Helper function for sphere +float sdSphere(float3 p, float radius) { + return length(p) - radius; +} + +// Helper function for box +float sdBox(float3 p, float3 size) { + float3 d = fabs(p) - size; + return length(max(d, 0.0f)) + min(max(d.x, max(d.y, d.z)), 0.0f); +} + +// Boolean operation +float opUnion(float a, float b) { + return min(a, b); +} + +// Main evaluation function +float evaluateModel(float3 p, float16 cs) { + // Sphere evaluation + float dist1 = sdSphere(p, 1.0f); + + // Box evaluation + float dist2 = sdBox(p, (float3)(0.5f)); + + // Union operation + float result = opUnion(dist1, dist2); + + return result; +} +``` + +### Kernel Library + +Pre-defined helper functions for common operations: + +**SDF Primitives:** +- `sdSphere`, `sdBox`, `sdCylinder`, `sdTorus`, `sdCone`, `sdCapsule`, `sdPlane` + +**Boolean Operations:** +- `opUnion`, `opIntersection`, `opDifference` +- `opSmoothUnion`, `opSmoothIntersection`, `opSmoothDifference` + +**Domain Operations:** +- `opRepeat`, `opSymmetry`, `opDisplace`, `opTwist`, `opBend` + +**Utility Functions:** +- `rotate`, `translate`, `scale` +- `calculateNormal` (gradient-based) +- `calculateAO` (ambient occlusion) + +## Resource Management + +### Memory Hierarchy + +```mermaid +graph TB + subgraph "CPU Side" + CPUMem[CPU Memory] + Staging[Staging Buffers] + end + + subgraph "GPU Side" + GlobalMem[Global Memory] + LocalMem[Local Memory] + PrivateMem[Private Memory] + Texture[Texture Memory] + end + + subgraph "OpenGL" + GLBuffer[GL Buffers] + GLTexture[GL Textures] + end + + CPUMem <-->|Copy| Staging + Staging <-->|Transfer| GlobalMem + GlobalMem --> LocalMem + LocalMem --> PrivateMem + GlobalMem --> Texture + GLBuffer <-->|Interop| GlobalMem + GLTexture <-->|Interop| Texture +``` + +### Buffer Management + +Buffers are allocated and managed through the `ResourceContext`: + +```cpp +class ResourceContext { +public: + // Buffer creation + cl::Buffer createBuffer(size_t size, cl_mem_flags flags); + cl::Image2D createImage2D(int width, int height, cl::ImageFormat format); + cl::Image3D createImage3D(int width, int height, int depth, cl::ImageFormat format); + + // OpenGL interop + cl::BufferGL createBufferGL(GLuint glBuffer, cl_mem_flags flags); + cl::Image2DGL createImage2DGL(GLuint glTexture, cl_mem_flags flags); + + // Memory transfer + void writeBuffer(cl::Buffer& buffer, const void* data, size_t size); + void readBuffer(cl::Buffer& buffer, void* data, size_t size); +}; +``` + +### OpenGL Interoperability + +For efficient rendering, OpenCL can share memory with OpenGL: + +```mermaid +sequenceDiagram + participant App + participant GL as OpenGL + participant CL as OpenCL + participant GPU + + App->>GL: Create Texture + GL->>GPU: Allocate Memory + App->>CL: Create Image from GL Texture + CL->>GPU: Map GL Memory + + loop Render Loop + App->>CL: Acquire GL Objects + App->>CL: Execute Kernel (write to texture) + CL->>GPU: Compute + App->>CL: Release GL Objects + App->>GL: Display Texture + end +``` + +**Synchronization:** +```cpp +// Acquire GL objects for OpenCL use +std::vector glObjects = {clImage}; +queue.enqueueAcquireGLObjects(&glObjects); + +// Execute OpenCL kernel +queue.enqueueNDRangeKernel(kernel, ...); + +// Release back to OpenGL +queue.enqueueReleaseGLObjects(&glObjects); +queue.finish(); + +// Now OpenGL can render the result +``` + +## Performance Optimization + +### Work Group Size Selection + +Optimal work group size depends on the device: + +```cpp +// Query device capabilities +size_t maxWorkGroupSize = device.getInfo(); +size_t maxWorkItemDims[3]; +device.getInfo(CL_DEVICE_MAX_WORK_ITEM_SIZES, &maxWorkItemDims); + +// Choose appropriate size +cl::NDRange localSize(16, 16); // 256 threads per work group +cl::NDRange globalSize( + roundUp(width, 16), + roundUp(height, 16) +); +``` + +### Memory Access Patterns + +Optimizing for coalesced memory access: + +```c +// BAD: Non-coalesced access +__kernel void bad_example(__global float* data) { + int idx = get_global_id(0); + float value = data[idx * 1000]; // Stride of 1000 +} + +// GOOD: Coalesced access +__kernel void good_example(__global float* data) { + int idx = get_global_id(0); + float value = data[idx]; // Consecutive access +} +``` + +### Local Memory Usage + +Using local memory for shared data: + +```c +__kernel void optimized_kernel( + __global float* input, + __global float* output, + __local float* shared +) { + int gid = get_global_id(0); + int lid = get_local_id(0); + + // Load to local memory + shared[lid] = input[gid]; + barrier(CLK_LOCAL_MEM_FENCE); + + // Compute using shared memory + float result = 0.0f; + for (int i = 0; i < get_local_size(0); i++) { + result += shared[i]; + } + + output[gid] = result; +} +``` + +### Kernel Compilation Caching + +Compiled binaries are cached to avoid recompilation: + +```cpp +// Check cache +std::string cacheKey = computeHash(kernelSource); +if (m_kernelCache.contains(cacheKey)) { + return m_kernelCache[cacheKey]; +} + +// Compile and cache +cl::Program program(context, kernelSource); +program.build(devices); +m_kernelCache[cacheKey] = program; +``` + +## Error Handling + +### OpenCL Error Checking + +All OpenCL calls are wrapped with error checking: + +```cpp +#define CL_ERROR(X) gladius::checkError(X, LOCATION) + +void checkError(cl_int err, const std::string& description) { + if (err != CL_SUCCESS) { + std::string errorName = getErrorString(err); + throw ComputeException( + fmt::format("OpenCL Error: {} at {}: {}", + errorName, description, err) + ); + } +} +``` + +### Kernel Build Errors + +Build errors are captured and reported with line numbers: + +```cpp +try { + program.build(devices); +} catch (cl::Error& e) { + if (e.err() == CL_BUILD_PROGRAM_FAILURE) { + std::string buildLog = program.getBuildInfo(device); + throw ComputeException( + fmt::format("Kernel compilation failed:\n{}", buildLog) + ); + } + throw; +} +``` + +## Profiling and Debugging + +### Event-Based Profiling + +OpenCL events can be used to measure kernel execution time: + +```cpp +cl::Event event; +queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize, nullptr, &event); +event.wait(); + +cl_ulong start = event.getProfilingInfo(); +cl_ulong end = event.getProfilingInfo(); +double duration = (end - start) * 1.0e-6; // Convert to milliseconds +``` + +### Debugging Strategies + +1. **CPU Fallback**: Test kernels on CPU with printf debugging +2. **Incremental Complexity**: Start simple and add features gradually +3. **Validation**: Compare GPU results with CPU reference implementation +4. **Bounds Checking**: Add assertions in kernels (development builds) + +## Platform-Specific Considerations + +### Windows + +- Use NVIDIA/AMD/Intel OpenCL SDKs +- TDR (Timeout Detection and Recovery) can interrupt long-running kernels +- May need to adjust registry settings for longer kernel execution + +### Linux + +- OpenCL via Mesa or vendor drivers +- More relaxed kernel execution timeouts +- Better support for CPU fallback implementations + +### Multi-GPU Systems + +Currently uses default device, but can be extended: + +```cpp +// Select specific GPU +std::vector devices; +platform.getDevices(CL_DEVICE_TYPE_GPU, &devices); +cl::Device selectedDevice = devices[1]; // Choose second GPU +``` + +## Future Enhancements + +- **Multi-GPU Rendering**: Split workload across multiple GPUs +- **Vulkan Compute**: Alternative to OpenCL for better performance +- **Persistent Kernels**: Keep kernels running for lower latency +- **Adaptive Work Size**: Dynamically adjust based on load +- **Advanced Caching**: Store compiled binaries on disk + +## Related Documentation + +- [Architecture Overview](ARCHITECTURE.md) +- [Node System Documentation](NODE_SYSTEM.md) +- [Resource Management](RESOURCE_MANAGEMENT.md) +- [Performance Tuning Guide](PERFORMANCE_TUNING.md) diff --git a/gladius/documentation/DATA_FLOW.md b/gladius/documentation/DATA_FLOW.md new file mode 100644 index 00000000..37bb0128 --- /dev/null +++ b/gladius/documentation/DATA_FLOW.md @@ -0,0 +1,589 @@ +# Data Flow Documentation + +## Overview + +This document describes the major data flows through the Gladius system, from user input through processing to output. Understanding these flows is essential for debugging, optimization, and extending the system. + +## Core Data Flows + +### 1. Model Loading and Display + +The complete flow from loading a 3MF file to rendering it on screen. + +```mermaid +sequenceDiagram + participant User + participant UI as User Interface + participant App as Application + participant Importer as Importer3mf + participant Model as Node Model + participant Core as ComputeCore + participant OCL as OpenCL + participant Display as Display + + User->>UI: Open File + UI->>App: loadFile("model.3mf") + App->>Importer: import() + Importer->>Importer: Parse 3MF XML + Importer->>Model: Build Node Graph + Model-->>Importer: Validated Model + Importer-->>App: Assembly + App->>Core: updateModel(model) + Core->>OCL: Compile Kernels + OCL-->>Core: Compiled Programs + Core->>OCL: Execute Render Kernel + OCL-->>Core: Rendered Image + Core-->>Display: Frame Buffer + Display-->>User: Visual Output +``` + +**Key Steps:** + +1. **File Selection**: User selects 3MF file via file dialog +2. **XML Parsing**: lib3mf parses 3MF structure +3. **Graph Construction**: Nodes and connections created from XML +4. **Validation**: Graph checked for completeness and validity +5. **Kernel Generation**: OpenCL code generated from node graph +6. **Compilation**: Kernels compiled for target device +7. **Execution**: Rendering kernel executed on GPU +8. **Display**: Result shown in viewport + +**Data Transformations:** + +``` +3MF XML → Node Graph → OpenCL Source → Compiled Kernel → Image Buffer → Screen +``` + +### 2. Interactive Editing Flow + +How changes to the node graph propagate through the system. + +```mermaid +flowchart TD + User[User Edit] --> NodeGraph[Update Node Graph] + NodeGraph --> Validate{Valid?} + Validate -->|No| Error[Show Error] + Validate -->|Yes| Dirty[Mark Dirty] + Dirty --> Background[Background Thread] + Background --> CodeGen[Generate OpenCL Code] + CodeGen --> Compare{Code Changed?} + Compare -->|No| UseCache[Use Cached Kernel] + Compare -->|Yes| Compile[Compile Kernel] + Compile --> NewKernel[Store New Kernel] + UseCache --> Render[Render Frame] + NewKernel --> Render + Render --> Display[Update Display] + Display --> User + Error --> User +``` + +**Optimization: Incremental Updates** + +The system only recompiles when necessary: + +1. **Change Detection**: Hash of node graph tracked +2. **Cache Lookup**: Check if kernel already compiled +3. **Selective Compilation**: Only compile if code changed +4. **Progressive Rendering**: Show preview while compiling + +**Timing Example:** +- Node parameter change: ~1ms (no recompile) +- Add new node: ~50-200ms (recompile) +- Cached render: ~16ms (60 FPS) + +### 3. Slicing Pipeline Flow + +From 3D model to 2D contours for manufacturing. + +```mermaid +flowchart LR + subgraph "Input" + Model3D[3D Model] + Params[Slice Parameters
Z-height, Resolution] + end + + subgraph "GPU Processing" + GenKernel[Generate Slice Kernel] + Rasterize[Rasterize SDF
2D Grid Sampling] + Buffer[Distance Field Buffer] + end + + subgraph "Contour Extraction" + MarchSq[Marching Squares] + Points[Contour Points] + Connect[Connect Points] + Validate[Validate Topology] + Simplify[Simplify Geometry] + end + + subgraph "Output" + Contours[Final Contours] + Export[Export to File
SVG/CLI/etc] + end + + Model3D --> GenKernel + Params --> GenKernel + GenKernel --> Rasterize + Rasterize --> Buffer + Buffer --> MarchSq + MarchSq --> Points + Points --> Connect + Connect --> Validate + Validate --> Simplify + Simplify --> Contours + Contours --> Export +``` + +**Detailed Steps:** + +**Phase 1: GPU Rasterization** +```c +// For each pixel in slice +for (x, y in resolution) { + worldPos = pixelToWorld(x, y, zHeight); + distance = evaluateSDF(worldPos); + buffer[x, y] = distance; +} +``` + +**Phase 2: Marching Squares** +``` +For each grid cell: + Check four corners + Determine crossing configuration (0-15) + Generate edge intersections + Create line segments +``` + +**Phase 3: Contour Connection** +``` +Start from any edge point: + Follow to next connected point + Continue until loop closes or boundary reached + Mark visited points +Repeat for all unvisited points +``` + +**Phase 4: Simplification** +``` +For each contour: + Apply Douglas-Peucker algorithm + Remove redundant points + Maintain topology +``` + +### 4. Mesh Export Flow + +Converting implicit geometry to explicit triangle mesh. + +```mermaid +sequenceDiagram + participant User + participant Dialog as Export Dialog + participant Exporter as MeshExporter + participant Sampler as SDF Sampler + participant MC as Marching Cubes + participant Mesh as Triangle Mesh + participant Writer as File Writer + + User->>Dialog: Export as STL + Dialog->>Exporter: export(settings) + Exporter->>Sampler: Sample SDF Grid + + loop For each voxel + Sampler->>Sampler: Evaluate SDF + end + + Sampler-->>MC: Distance Field + MC->>MC: Extract Isosurface + MC->>Mesh: Generate Triangles + Mesh->>Mesh: Optimize Topology + Mesh->>Mesh: Calculate Normals + Mesh-->>Writer: Triangle Data + Writer->>Writer: Write STL File + Writer-->>User: Export Complete +``` + +**Grid Sampling:** +```cpp +// Determine grid resolution +Vector3f bounds = getBoundingBox(); +int resolution = 256; // Voxels per axis + +// Sample SDF +std::vector grid(resolution * resolution * resolution); +for (int z = 0; z < resolution; z++) { + for (int y = 0; y < resolution; y++) { + for (int x = 0; x < resolution; x++) { + Vector3f pos = gridToWorld(x, y, z); + grid[index(x,y,z)] = evaluateSDF(pos); + } + } +} +``` + +**Marching Cubes:** +``` +For each cube (8 voxels): + 1. Calculate cube index from corner signs + 2. Look up edge table + 3. Interpolate edge intersections + 4. Generate 0-5 triangles per cube +``` + +### 5. Resource Loading Flow + +How external resources (meshes, images, VDB) are loaded and cached. + +```mermaid +stateDiagram-v2 + [*] --> Requested: Reference Found + Requested --> CheckCache: Look Up + CheckCache --> Cached: Found in Cache + CheckCache --> Loading: Not Cached + Loading --> Parsing: Load File + Parsing --> Converting: Parse Format + Converting --> Uploading: Convert to Internal + Uploading --> Ready: Upload to GPU + Cached --> Ready: Use Cached + Ready --> InUse: Provide to Node + InUse --> [*] +``` + +**Cache Management:** + +```cpp +class ResourceCache { + std::unordered_map m_cache; + +public: + ResourcePtr get(const ResourceKey& key) { + // Check cache + auto it = m_cache.find(key); + if (it != m_cache.end()) { + return it->second; // Cache hit + } + + // Load resource + auto resource = loadResource(key); + + // Add to cache + m_cache[key] = resource; + + return resource; + } +}; +``` + +**Resource Pipeline:** +``` +File Path → File Load → Format Parse → Internal Representation → GPU Upload → Ready +``` + +### 6. Camera and View Updates + +Real-time interaction and rendering updates. + +```mermaid +flowchart TD + Input[Mouse/Keyboard Input] --> Camera[Update Camera] + Camera --> ViewMatrix[Calculate View Matrix] + ViewMatrix --> Frustum[Calculate Frustum] + Frustum --> Cull{Frustum Culling} + Cull -->|Visible| Render[Queue Render] + Cull -->|Hidden| Skip[Skip] + Render --> Kernel[Execute Render Kernel] + Kernel --> PostProcess[Post Processing] + PostProcess --> Swap[Swap Buffers] + Swap --> Display[Display Frame] + Display --> Input +``` + +**Frame Timing:** +``` +Input (1ms) → Camera Update (0.5ms) → Render (14ms) → Display (0.5ms) = 16ms (60 FPS) +``` + +**Optimization: Dirty Flags** +```cpp +class Viewport { + bool m_cameraDirty = true; + bool m_modelDirty = true; + + void render() { + if (!m_cameraDirty && !m_modelDirty) { + return; // No update needed + } + + if (m_cameraDirty) { + updateCameraUniforms(); + m_cameraDirty = false; + } + + if (m_modelDirty) { + recompileKernels(); + m_modelDirty = false; + } + + executeRenderKernel(); + } +}; +``` + +## Data Structures + +### Node Graph Representation + +```mermaid +graph TB + Model[Model Container] + Model --> NodeReg[Node Registry
map: ID → Node*] + Model --> PortReg[Port Registry
map: ID → Port*] + Model --> AdjList[Adjacency List
Graph Structure] + + NodeReg --> Node1[Node 1] + NodeReg --> Node2[Node 2] + NodeReg --> NodeN[Node N] + + Node1 --> Inputs[Input Ports] + Node1 --> Outputs[Output Ports] + Node1 --> Params[Parameters] + + Inputs --> Port1[Port 1] + Inputs --> Port2[Port 2] + + Port1 -.Connection.-> Port3[Other Port] +``` + +### Buffer Management + +```mermaid +graph LR + subgraph "CPU Side" + CPUData[CPU Data] + Staging[Staging Buffer] + end + + subgraph "GPU Side" + GPUBuffer[GPU Buffer] + Kernel[Kernel Access] + end + + subgraph "GL Side" + GLBuffer[OpenGL Buffer] + Render[Rendering] + end + + CPUData -->|Write| Staging + Staging -->|Transfer| GPUBuffer + GPUBuffer <-->|Interop| GLBuffer + GPUBuffer -->|Read/Write| Kernel + GLBuffer -->|Display| Render +``` + +**Memory Copy Patterns:** +```cpp +// CPU to GPU +void uploadData(const std::vector& cpuData, cl::Buffer& gpuBuffer) { + queue.enqueueWriteBuffer(gpuBuffer, CL_TRUE, 0, + cpuData.size() * sizeof(float), + cpuData.data()); +} + +// GPU to CPU +void downloadData(cl::Buffer& gpuBuffer, std::vector& cpuData) { + queue.enqueueReadBuffer(gpuBuffer, CL_TRUE, 0, + cpuData.size() * sizeof(float), + cpuData.data()); +} + +// GPU to GPU (fastest) +void copyBuffer(cl::Buffer& src, cl::Buffer& dst, size_t size) { + queue.enqueueCopyBuffer(src, dst, 0, 0, size); +} +``` + +## Performance Characteristics + +### Operation Timings (Typical) + +| Operation | Time | Notes | +|-----------|------|-------| +| Parameter update | ~1ms | No recompile | +| Add/remove node | 50-200ms | Requires recompile | +| Render frame (GPU) | 5-16ms | Depends on complexity | +| Generate slice | 10-50ms | Depends on resolution | +| Extract contours | 20-100ms | Depends on complexity | +| Load 3MF file | 100-2000ms | Depends on file size | +| Export STL mesh | 500-5000ms | Depends on resolution | + +### Memory Usage (Typical) + +| Component | Memory | Notes | +|-----------|--------|-------| +| Node graph | 1-10 MB | Depends on complexity | +| Render buffer (1920x1080) | 8 MB | RGBA float | +| Slice buffer (4096x4096) | 16 MB | Single channel float | +| VDB resource | 10-500 MB | Depends on resolution | +| Compiled kernels | 1-5 MB | Cached binaries | + +### Bottleneck Analysis + +```mermaid +pie title "Typical Frame Time Breakdown" + "Kernel Execution" : 70 + "Memory Transfer" : 15 + "CPU Processing" : 10 + "Overhead" : 5 +``` + +**Optimization Priorities:** +1. **Kernel Optimization**: 70% of time + - Reduce operations per pixel + - Optimize memory access patterns + - Use local memory effectively + +2. **Memory Transfer**: 15% of time + - Use interop for GPU↔GPU transfers + - Minimize CPU↔GPU transfers + - Batch transfers when possible + +3. **CPU Processing**: 10% of time + - Cache expensive computations + - Use parallel algorithms + - Profile hot paths + +## Debugging Data Flows + +### Instrumentation Points + +```cpp +// Add timing measurements +class ScopedTimer { + std::string m_name; + TimePoint m_start; + +public: + ScopedTimer(const std::string& name) + : m_name(name), m_start(Clock::now()) {} + + ~ScopedTimer() { + auto duration = Clock::now() - m_start; + log("Timer '{}': {} ms", m_name, duration.count()); + } +}; + +void renderFrame() { + ScopedTimer timer("renderFrame"); + + { + ScopedTimer timer("updateCamera"); + updateCamera(); + } + + { + ScopedTimer timer("executeKernel"); + executeKernel(); + } +} +``` + +### Data Validation + +```cpp +// Validate intermediate results +void validateSliceData(const BitmapLayer& slice) { + // Check for NaN/Inf + for (const auto& value : slice.data()) { + assert(std::isfinite(value)); + } + + // Check bounds + auto [min, max] = std::minmax_element( + slice.data().begin(), + slice.data().end() + ); + assert(*min >= -1000.0f && *max <= 1000.0f); +} +``` + +### Logging Data Flow + +```cpp +// Log major data flow events +EventLogger& log = EventLogger::instance(); + +log.info("Starting model import"); +auto model = importer.import(); +log.info("Model imported: {} nodes", model.getNodeCount()); + +log.info("Compiling kernels"); +compiler.compile(model); +log.info("Compilation complete"); + +log.info("Executing render"); +auto result = renderer.render(camera); +log.info("Render complete: {}x{}", result.width, result.height); +``` + +## Data Flow Optimization + +### Lazy Evaluation + +```cpp +class LazyResource { + mutable std::optional m_cache; + +public: + const Data& get() const { + if (!m_cache) { + m_cache = loadData(); // Load on first access + } + return *m_cache; + } + + void invalidate() { + m_cache.reset(); // Clear cache + } +}; +``` + +### Asynchronous Loading + +```cpp +class AsyncLoader { + std::future m_future; + +public: + void startLoad(const std::string& path) { + m_future = std::async(std::launch::async, [path]() { + return loadResource(path); + }); + } + + bool isReady() const { + return m_future.wait_for(0s) == std::future_status::ready; + } + + Resource get() { + return m_future.get(); + } +}; +``` + +### Pipeline Parallelism + +``` +[Load File] → [Parse] → [Validate] → [Compile] → [Execute] + ↓ ↓ ↓ ↓ ↓ + File 1 File 2 File 3 File 4 File 5 +``` + +Multiple files can be in different pipeline stages simultaneously. + +## Related Documentation + +- [Architecture Overview](ARCHITECTURE.md) +- [Compute Pipeline](COMPUTE_PIPELINE.md) +- [Node System](NODE_SYSTEM.md) +- [Performance Tuning](PERFORMANCE_TUNING.md) diff --git a/gladius/documentation/DEVELOPER_GUIDE.md b/gladius/documentation/DEVELOPER_GUIDE.md new file mode 100644 index 00000000..18c4e308 --- /dev/null +++ b/gladius/documentation/DEVELOPER_GUIDE.md @@ -0,0 +1,700 @@ +# Developer Guide + +## Welcome + +This guide will help you get started with developing Gladius, whether you're fixing bugs, adding features, or integrating Gladius into your own applications. + +## Prerequisites + +### Required Tools + +- **C++ Compiler**: MSVC 2019+ (Windows), GCC 9+ or Clang 10+ (Linux) +- **CMake**: Version 3.20 or higher +- **vcpkg**: For dependency management +- **Git**: For version control +- **OpenCL SDK**: From your GPU vendor (NVIDIA, AMD, or Intel) + +### Optional Tools + +- **Visual Studio Code**: Recommended IDE with C++ extensions +- **Visual Studio 2022**: Full IDE with integrated debugging +- **CLion**: JetBrains C++ IDE +- **Ninja**: Fast build system + +## Getting Started + +### 1. Clone the Repository + +```bash +git clone https://github.com/3MFConsortium/gladius.git +cd gladius +git submodule update --init --recursive +``` + +### 2. Set Up vcpkg + +#### Windows +```powershell +# Set environment variables +$env:VCPKG_ROOT = "C:\path\to\vcpkg" +$env:VCPKG_DEFAULT_TRIPLET = "x64-windows" + +# Install vcpkg if not already installed +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +.\bootstrap-vcpkg.bat +``` + +#### Linux +```bash +# Set environment variables +export VCPKG_ROOT=/path/to/vcpkg + +# Install vcpkg +git clone https://github.com/Microsoft/vcpkg.git +cd vcpkg +./bootstrap-vcpkg.sh +``` + +### 3. Build the Project + +#### Using CMake Presets (Recommended) + +**Windows:** +```bash +cd gladius +cmake --preset x64-debug +cmake --build --preset x64-debug +``` + +**Linux:** +```bash +cd gladius +cmake --preset linux-debug +cmake --build --preset linux-debug +``` + +#### Manual CMake Configuration + +```bash +mkdir build +cd build +cmake .. -DCMAKE_BUILD_TYPE=Debug +cmake --build . +``` + +### 4. Run Tests + +```bash +# Run all tests +ctest --output-on-failure + +# Run specific test suite +./gladius_tests +``` + +## Project Structure + +``` +gladius/ +├── gladius/ # Main source directory +│ ├── src/ # Source code +│ │ ├── api/ # API definitions (ACT) +│ │ ├── compute/ # Compute pipeline +│ │ ├── contour/ # Contour extraction +│ │ ├── io/ # Import/Export +│ │ ├── kernel/ # OpenCL kernels +│ │ ├── nodes/ # Node system +│ │ └── ui/ # User interface +│ ├── tests/ # Test suites +│ │ ├── unittests/ # Unit tests +│ │ └── integrationtests/ # Integration tests +│ ├── library/ # Reusable libraries +│ ├── examples/ # Example code +│ └── documentation/ # Documentation (this!) +├── scripts/ # Build and utility scripts +└── CMakeLists.txt # Root CMake configuration +``` + +## Development Workflow + +### Using Visual Studio Code + +1. **Install Extensions:** + - C/C++ (Microsoft) + - CMake Tools + - GitLens + +2. **Open Project:** + ```bash + code . + ``` + +3. **Configure CMake:** + - Press `Ctrl+Shift+P` + - Type "CMake: Configure" + - Select appropriate preset + +4. **Build:** + - Press `F7` or use CMake Tools panel + +5. **Debug:** + - Set breakpoints + - Press `F5` to start debugging + +### Using Visual Studio + +1. **Open Project:** + - File → Open → CMake + - Select `CMakeLists.txt` + +2. **Select Configuration:** + - Use configuration dropdown + - Choose Debug or Release + +3. **Build:** + - Build → Build All (`Ctrl+Shift+B`) + +4. **Run:** + - Select gladius.exe as startup item + - Press `F5` to debug + +### Command Line Development + +```bash +# Build in debug mode +cmake --preset x64-debug +cmake --build --preset x64-debug + +# Run application +./out/build/x64-debug/gladius + +# Run tests +cd out/build/x64-debug +ctest --output-on-failure + +# Build in release mode +cmake --preset x64-release +cmake --build --preset x64-release +``` + +## Coding Guidelines + +### C++ Style + +Follow the project's C++ coding guidelines (see project README): + +```cpp +// Class names: PascalCase +class MyClassName { +public: + // Method names: camelCase + void myMethodName(); + + // Boolean methods: is/has/are prefix + bool isValid() const; + bool hasConnection() const; + +private: + // Member variables: m_ prefix, camelCase + int m_memberVariable; + + // Static members: s_ prefix + static int s_staticMember; +}; + +// Constants: UPPER_SNAKE_CASE +const int MAX_ITERATIONS = 100; + +// Namespaces: lower_snake_case +namespace gladius::nodes { + // ... +} +``` + +### Formatting + +Use `.clang-format` for consistent formatting: + +```bash +# Format all changed files +git diff --name-only | grep -E '\.(cpp|h)$' | xargs clang-format -i + +# Format specific file +clang-format -i src/MyFile.cpp +``` + +### Documentation + +Use Doxygen-style comments for public APIs: + +```cpp +/** + * @brief Evaluates the signed distance field at a given point + * + * @param point The 3D point in world space + * @param context The evaluation context with parameters + * @return The signed distance value (negative inside, positive outside) + * + * @throws ComputeException if evaluation fails + */ +float evaluate(const Vector3f& point, const Context& context); +``` + +## Adding New Features + +### Adding a New Node Type + +1. **Define the Node Class:** + +```cpp +// In src/nodes/DerivedNodes.h +class MyCustomNode : public ClonableNode { +public: + MyCustomNode() + : ClonableNode("MyCustomNode", {}, Category::Function) + { + // Define inputs + addInput("input", PortType::Scalar); + + // Define outputs + addOutput("output", PortType::Scalar); + + // Define parameters + addParameter("factor", 2.0f); + } + + std::string getDescription() const override { + return "Multiplies input by factor"; + } +}; +``` + +2. **Implement OpenCL Code Generation:** + +```cpp +// In ToOCLVisitor.cpp +void ToOCLVisitor::visit(MyCustomNode& node) { + float factor = node.getParameter("factor").get(); + + std::string code = fmt::format( + "float {} = {} * {};", + outputVar, + inputVar, + factor + ); + + m_code += code; +} +``` + +3. **Register the Node:** + +```cpp +// In nodes factory +NodeBase* createNodeFromName(const std::string& name, Model& model) { + if (name == "MyCustomNode") { + return new MyCustomNode(); + } + // ... other nodes +} +``` + +4. **Add Tests:** + +```cpp +// In tests/unittests/MyCustomNode_tests.cpp +TEST(MyCustomNode_Tests, BasicMultiplication) { + nodes::Model model; + auto node = std::make_unique(); + + node->setParameter("factor", 3.0f); + + // Test evaluation + // ... + + ASSERT_FLOAT_EQ(result, expected); +} +``` + +### Adding a New Export Format + +1. **Create Exporter Class:** + +```cpp +// In src/io/MyFormatExporter.h +class MyFormatExporter : public IExporter { +public: + MyFormatExporter(const std::filesystem::path& filename); + + void exportModel(const nodes::Assembly& assembly) override; + +private: + void writeHeader(); + void writeGeometry(); + void writeFooter(); + + std::filesystem::path m_filename; +}; +``` + +2. **Implement Export Logic:** + +```cpp +// In src/io/MyFormatExporter.cpp +void MyFormatExporter::exportModel(const nodes::Assembly& assembly) { + std::ofstream file(m_filename); + + writeHeader(); + + // Convert model to format + auto& model = assembly.getModel(); + // ... export logic + + writeFooter(); +} +``` + +3. **Register in Export Dialog:** + +```cpp +// In ui/ExportDialog.cpp +void ExportDialog::show() { + if (ImGui::MenuItem("My Format (.myf)")) { + exportToMyFormat(); + } +} +``` + +### Adding an OpenCL Kernel + +1. **Create Kernel File:** + +```c +// In src/kernel/my_kernel.cl +__kernel void my_kernel( + __global float* input, + __global float* output, + const int count +) { + int gid = get_global_id(0); + if (gid < count) { + output[gid] = input[gid] * 2.0f; + } +} +``` + +2. **Create Program Wrapper:** + +```cpp +// In src/MyProgram.h +class MyProgram : public CLProgram { +public: + MyProgram(SharedComputeContext context); + + void execute(cl::Buffer& input, cl::Buffer& output, int count); + +private: + cl::Kernel m_kernel; +}; +``` + +3. **Implement Execution:** + +```cpp +// In src/MyProgram.cpp +void MyProgram::execute(cl::Buffer& input, cl::Buffer& output, int count) { + m_kernel.setArg(0, input); + m_kernel.setArg(1, output); + m_kernel.setArg(2, count); + + auto& queue = m_context->getQueue(); + queue.enqueueNDRangeKernel( + m_kernel, + cl::NullRange, + cl::NDRange(count), + cl::NullRange + ); +} +``` + +## Debugging + +### Debugging C++ Code + +**Visual Studio / VS Code:** +1. Set breakpoints by clicking in the margin +2. Press F5 to start debugging +3. Use Debug Console for expressions + +**GDB (Linux):** +```bash +gdb ./gladius +(gdb) break Application.cpp:42 +(gdb) run input.3mf +(gdb) print variableName +(gdb) continue +``` + +### Debugging OpenCL Kernels + +1. **Use CPU Device:** + ```cpp + // Force CPU execution for debugging + ComputeContext context; + context.selectDevice(DeviceType::CPU); + ``` + +2. **Add Printf Debugging:** + ```c + __kernel void debug_kernel(...) { + int gid = get_global_id(0); + printf("Thread %d: value = %f\n", gid, someValue); + } + ``` + +3. **Validate Results on CPU:** + ```cpp + // Compare GPU results with CPU reference + std::vector gpuResult = /* ... */; + std::vector cpuResult = computeReferenceCPU(); + + for (size_t i = 0; i < gpuResult.size(); i++) { + ASSERT_NEAR(gpuResult[i], cpuResult[i], 1e-5); + } + ``` + +### Memory Debugging + +**Valgrind (Linux):** +```bash +valgrind --leak-check=full ./gladius +``` + +**Visual Studio Memory Profiler:** +1. Debug → Performance Profiler +2. Select "Memory Usage" +3. Start profiling + +## Testing + +### Writing Unit Tests + +Use GTest framework: + +```cpp +#include + +namespace gladius::tests { + +TEST(ComponentName_Tests, MethodName_Condition_ExpectedBehavior) { + // Arrange + ComponentName component; + component.setup(); + + // Act + auto result = component.methodName(); + + // Assert + ASSERT_EQ(result, expectedValue); +} + +TEST(ComponentName_Tests, MethodName_WithNullInput_ThrowsException) { + ComponentName component; + + ASSERT_THROW(component.methodName(nullptr), std::invalid_argument); +} + +} // namespace gladius::tests +``` + +### Running Tests + +```bash +# Run all tests +ctest + +# Run with verbose output +ctest --output-on-failure + +# Run specific test +./gladius_tests --gtest_filter=NodeSystem_Tests.* + +# Run with debugging +gdb ./gladius_tests +``` + +### Integration Tests + +```cpp +TEST(Integration_Tests, LoadAndExport_CompleteWorkflow) { + // Load model + Importer3mf importer("test_data/model.3mf"); + auto assembly = importer.import(); + + // Process + auto& model = assembly->getModel(); + ASSERT_TRUE(model.isValid()); + + // Export + Writer3mf writer("output.3mf"); + writer.write(*assembly); + + // Verify + ASSERT_TRUE(std::filesystem::exists("output.3mf")); +} +``` + +## Performance Profiling + +### Using Built-in Profiling + +```cpp +#include "Profiling.h" + +void myFunction() { + PROFILE_SCOPE("MyFunction"); + + // Code to profile + + PROFILE_SCOPE("SubSection"); + // More code +} +``` + +### External Profilers + +**Visual Studio Profiler:** +1. Debug → Performance Profiler +2. Select "CPU Usage" +3. Start profiling + +**perf (Linux):** +```bash +perf record ./gladius +perf report +``` + +**Intel VTune:** +```bash +vtune -collect hotspots ./gladius +vtune -report hotspots +``` + +## Common Issues + +### Build Issues + +**Issue:** vcpkg dependencies fail to build +**Solution:** +```bash +# Clear vcpkg cache +rm -rf $VCPKG_ROOT/buildtrees +rm -rf $VCPKG_ROOT/packages + +# Rebuild +vcpkg install +``` + +**Issue:** OpenCL not found +**Solution:** Install OpenCL SDK for your platform and set environment variables + +**Issue:** CMake cache issues +**Solution:** +```bash +rm -rf build/ +rm CMakeCache.txt +cmake --preset x64-debug +``` + +### Runtime Issues + +**Issue:** "Device not found" error +**Solution:** +- Install GPU drivers with OpenCL support +- Install CPU OpenCL runtime as fallback + +**Issue:** Kernel compilation fails +**Solution:** +- Check kernel syntax +- Enable build log output +- Test on CPU device first + +**Issue:** Out of memory errors +**Solution:** +- Reduce image resolution +- Use smaller models +- Monitor GPU memory usage + +## Contributing + +### Pull Request Process + +1. **Create a Branch:** + ```bash + git checkout -b feature/my-new-feature + ``` + +2. **Make Changes:** + - Follow coding guidelines + - Add tests + - Update documentation + +3. **Test:** + ```bash + cmake --build . --target all + ctest --output-on-failure + ``` + +4. **Commit:** + ```bash + git add . + git commit -m "Add my new feature" + ``` + +5. **Push:** + ```bash + git push origin feature/my-new-feature + ``` + +6. **Create Pull Request:** + - Go to GitHub + - Create PR with clear description + - Link related issues + +### Code Review + +- Address all review comments +- Keep commits focused and atomic +- Squash commits if requested +- Ensure CI passes + +## Resources + +### Documentation +- [Architecture Overview](ARCHITECTURE.md) +- [Node System](NODE_SYSTEM.md) +- [Compute Pipeline](COMPUTE_PIPELINE.md) +- [API Reference](API_REFERENCE.md) + +### External Resources +- [OpenCL Documentation](https://www.khronos.org/opencl/) +- [3MF Specification](https://3mf.io/specification/) +- [ImGUI Documentation](https://github.com/ocornut/imgui) +- [CMake Documentation](https://cmake.org/documentation/) + +### Community +- GitHub Issues for bug reports +- GitHub Discussions for questions +- Pull Requests for contributions + +## Next Steps + +1. Build the project successfully +2. Run the test suite +3. Explore the example code +4. Try adding a simple feature +5. Read the architecture documentation +6. Join the community discussions + +Happy coding! 🚀 diff --git a/gladius/documentation/NODE_SYSTEM.md b/gladius/documentation/NODE_SYSTEM.md new file mode 100644 index 00000000..a3cc9448 --- /dev/null +++ b/gladius/documentation/NODE_SYSTEM.md @@ -0,0 +1,543 @@ +# Node System Documentation + +## Overview + +The Node System is the core of Gladius, implementing a dataflow graph architecture for defining implicit functions using Constructive Solid Geometry (CSG) operations. The system allows users to build complex 3D geometries by connecting nodes that represent primitives, operations, and mathematical functions. + +## Architecture + +```mermaid +classDiagram + class Model { + -NodeRegistry m_nodes + -PortRegistry m_ports + -InputParameterRegistry m_inputParameters + -AdjacencyListDirectedGraph m_graph + +addNode(NodeBase) NodeId + +removeNode(NodeId) + +connect(PortId, PortId) bool + +disconnect(PortId) + +getNode(NodeId) NodeBase* + +topologicalSort() vector~NodeId~ + } + + class NodeBase { + <> + #NodeId m_id + #NodeName m_name + #Category m_category + #Ports m_inputs + #Ports m_outputs + #ParameterMap m_parameters + +evaluate()* + +getInputs() Ports + +getOutputs() Ports + +clone()* NodeBase* + } + + class Port { + -PortId m_id + -PortName m_name + -PortType m_type + -NodeId m_nodeId + -PortId m_connectedPort + +connect(PortId) bool + +disconnect() + +isConnected() bool + } + + class Parameter { + <> + #ParameterId m_id + #ParameterName m_name + +getValue()* + +setValue()* + } + + class TypedParameter~T~ { + -T m_value + +getValue() T + +setValue(T) + } + + class Assembly { + -Model m_model + -Components m_components + -BuildItems m_buildItems + -MetaData m_metaData + +addComponent(Component) + +addBuildItem(BuildItem) + +getModel() Model + } + + Model o-- NodeBase + Model --> Port + NodeBase o-- Port + NodeBase o-- Parameter + Parameter <|-- TypedParameter + Assembly --> Model + + class Begin { + +getDescription() string + } + + class End { + +getDescription() string + } + + class PrimitiveNode { + +getDescription() string + } + + class OperationNode { + +getDescription() string + } + + NodeBase <|-- Begin + NodeBase <|-- End + NodeBase <|-- PrimitiveNode + NodeBase <|-- OperationNode +``` + +## Core Classes + +### Model + +The `Model` class represents a complete node graph. It maintains: +- A registry of all nodes in the graph +- A registry of all ports for quick lookup +- An adjacency list representing connections between nodes +- Input parameters for the entire graph + +**Key Methods:** +```cpp +// Node management +NodeId addNode(std::unique_ptr node); +void removeNode(NodeId nodeId); +NodeBase* getNode(NodeId nodeId); + +// Connection management +bool connect(PortId outputPort, PortId inputPort); +void disconnect(PortId port); + +// Graph operations +std::vector topologicalSort() const; +bool isAcyclic() const; +std::vector getNodesInExecutionOrder() const; +``` + +### NodeBase + +The abstract base class for all nodes. Every node has: +- **Unique ID**: For identification in the graph +- **Name**: Human-readable name +- **Category**: Classification (Primitive, Operation, Function, etc.) +- **Input Ports**: Connections to other nodes +- **Output Ports**: Connections to other nodes +- **Parameters**: Configuration values + +**Node Categories:** +```cpp +enum class Category { + Primitive, // Basic shapes (sphere, box, cylinder) + Operation, // Boolean ops (union, intersection, difference) + Function, // Math functions (sin, cos, abs) + Resource, // External data (mesh, image, VDB) + Internal, // Begin/End nodes + Utility, // Helper nodes (constant, variable) + Transform, // Spatial transformations + Material // Surface properties +}; +``` + +### Port + +Ports define the inputs and outputs of nodes. Each port has: +- **Type**: Data type (Scalar, Vector3, Matrix4x4, etc.) +- **Direction**: Input or Output +- **Connection**: Reference to connected port (if any) + +**Port Types:** +```cpp +enum class PortType { + Scalar, // Single floating-point value + Vector2, // 2D vector + Vector3, // 3D vector + Vector4, // 4D vector + Matrix3x3, // 3x3 transformation matrix + Matrix4x4, // 4x4 transformation matrix + Resource, // Resource reference + Any // Type to be inferred +}; +``` + +### Parameter + +Parameters are configurable values within nodes. They differ from ports in that they have fixed values set by the user, rather than connections to other nodes. + +**Parameter Types:** +- `ScalarParameter`: Single floating-point value +- `Vector2Parameter`: 2D vector +- `Vector3Parameter`: 3D vector +- `BoolParameter`: Boolean value +- `IntParameter`: Integer value +- `StringParameter`: Text value +- `EnumParameter`: Selection from predefined options + +## Node Types + +### Begin Node + +The Begin node is the entry point of a function graph. It provides: +- **cs (Coordinate System)**: The transformation matrix for the current evaluation +- **p (Position)**: The 3D point in space being evaluated +- **Additional Inputs**: User-defined function arguments + +```mermaid +graph LR + Begin[Begin Node] --> cs[cs: Matrix4x4] + Begin --> p[p: Vector3] + Begin --> arg1[arg1: User Defined] + Begin --> argN[argN: User Defined] +``` + +### End Node + +The End node is the exit point of a function graph. It typically has: +- **Input**: The signed distance field value or composite result +- **Output**: The final function result + +```mermaid +graph LR + result[Result: Scalar] --> End[End Node] + End --> output[Output] +``` + +### Primitive Nodes + +Primitive nodes generate signed distance fields for basic shapes. + +**Available Primitives:** +- **Sphere**: Distance from sphere surface +- **Box**: Distance from box surface +- **Cylinder**: Distance from cylinder surface +- **Capsule**: Distance from capsule surface +- **Torus**: Distance from torus surface +- **Cone**: Distance from cone surface +- **Plane**: Distance from plane + +**Example: Sphere Node** +``` +Inputs: + - cs: Matrix4x4 (coordinate system) + - radius: Scalar (sphere radius) +Outputs: + - distance: Scalar (signed distance) +``` + +### Operation Nodes + +Operation nodes combine multiple signed distance fields using CSG operations. + +```mermaid +graph TD + subgraph "Boolean Operations" + A[SDF A] --> Union[Union] + B[SDF B] --> Union + Union --> Result1[Combined SDF] + + C[SDF A] --> Intersect[Intersection] + D[SDF B] --> Intersect + Intersect --> Result2[Intersected SDF] + + E[SDF A] --> Diff[Difference] + F[SDF B] --> Diff + Diff --> Result3[Difference SDF] + end +``` + +**Boolean Operations:** +- **Union (min)**: Combines shapes (A ∪ B) +- **Intersection (max)**: Keeps only overlap (A ∩ B) +- **Difference**: Subtracts B from A (A - B) +- **Smooth Union**: Blended union with smooth transition +- **Smooth Intersection**: Blended intersection +- **Smooth Difference**: Blended subtraction + +### Function Nodes + +Function nodes perform mathematical operations on scalar, vector, or matrix values. + +**Categories:** +1. **Arithmetic**: Add, Subtract, Multiply, Divide, Power +2. **Trigonometric**: Sin, Cos, Tan, Asin, Acos, Atan +3. **Comparison**: Less, Greater, Equal, Min, Max +4. **Vector Operations**: Dot, Cross, Normalize, Length +5. **Interpolation**: Mix, Smoothstep, Step, Clamp +6. **Noise**: Perlin, Simplex, Voronoi + +### Resource Nodes + +Resource nodes reference external data like meshes, images, or VDB volumes. + +**Types:** +- **MeshResource**: Signed distance from mesh surface +- **ImageStackResource**: 3D texture sampling +- **VdbResource**: OpenVDB volume sampling + +## Type System + +The node system uses a flexible type system with automatic type inference and conversion. + +### Type Rules + +Each node defines type rules that determine output types based on input types: + +```cpp +struct TypeRule { + RuleType type; // Default, Scalar, Vector, Matrix + InputTypeMap input; // Expected input types + OutputTypeMap output; // Resulting output types +}; +``` + +### Type Inference + +When nodes are connected, the system: +1. Checks if connection types are compatible +2. Applies type rules to determine output types +3. Propagates type changes through the graph +4. Validates that all connections are type-safe + +```mermaid +flowchart LR + Connect[Connect Ports] --> Check{Types Compatible?} + Check -->|No| Error[Connection Failed] + Check -->|Yes| Infer[Infer Types] + Infer --> Propagate[Propagate Types] + Propagate --> Validate{Graph Valid?} + Validate -->|No| Error + Validate -->|Yes| Success[Connection Successful] +``` + +## Graph Operations + +### Topological Sort + +The graph is topologically sorted to determine execution order: + +```mermaid +graph TD + Begin[Begin] --> A[Node A] + Begin --> B[Node B] + A --> C[Node C] + B --> C + C --> End[End] + + style Begin fill:#90EE90 + style End fill:#FFB6C1 +``` + +Execution order: Begin → A, B → C → End + +### Cycle Detection + +The system validates that the graph is acyclic (no loops): + +```cpp +bool Model::isAcyclic() const { + return !m_graph.hasCycle(); +} +``` + +### Graph Flattening + +When assemblies reference other assemblies, the graph is flattened to a single level: + +```mermaid +flowchart TD + subgraph "Original" + A1[Assembly A] --> A2[Assembly B] + A2 --> A3[Assembly C] + end + + subgraph "Flattened" + F1[All Nodes] --> F2[In Single Graph] + end + + A3 --> F1 +``` + +## Visitor Pattern + +Visitors traverse the node graph to generate different representations: + +### ToOCLVisitor + +Generates OpenCL kernel code from the node graph: + +```cpp +class ToOCLVisitor : public Visitor { +public: + void visit(NodeBase& node) override; + std::string getGeneratedCode() const; +}; +``` + +**Generated Code Structure:** +```c +// Helper functions +float sdSphere(float3 p, float radius) { ... } +float opUnion(float a, float b) { ... } + +// Main evaluation function +float evaluate(float3 p, float4x4 cs) { + // Node evaluation in topological order + float dist1 = sdSphere(p, 1.0f); + float dist2 = sdBox(p, (float3)(0.5f)); + float result = opUnion(dist1, dist2); + return result; +} +``` + +### ToCommandStreamVisitor + +Generates a command stream for CPU evaluation: + +```cpp +class ToCommandStreamVisitor : public Visitor { +public: + void visit(NodeBase& node) override; + CommandStream getCommandStream() const; +}; +``` + +## Example Workflows + +### Creating a Simple CSG Object + +```mermaid +flowchart LR + Begin[Begin] --> Sphere[Sphere
radius: 1.0] + Begin --> Box[Box
size: 0.8] + Sphere --> Union[Smooth Union
blend: 0.1] + Box --> Union + Union --> End[End] +``` + +**Steps:** +1. Create Begin and End nodes +2. Add Sphere primitive with radius 1.0 +3. Add Box primitive with size 0.8 +4. Add Smooth Union operation +5. Connect: Begin → Sphere → Union → End +6. Connect: Begin → Box → Union + +### Using Resources + +```mermaid +flowchart LR + Begin[Begin] --> Mesh[Mesh Resource
bunny.stl] + Begin --> Transform[Transform
rotate, scale] + Transform --> Sphere[Sphere
radius: 2.0] + Mesh --> Diff[Difference] + Sphere --> Diff + Diff --> End[End] +``` + +## Performance Considerations + +### Optimization Strategies + +1. **Node Caching**: Results are cached when inputs haven't changed +2. **Dead Code Elimination**: Unused nodes are not evaluated +3. **Constant Folding**: Compile-time evaluation of constant expressions +4. **Common Subexpression Elimination**: Shared computations are reused + +### Best Practices + +- Keep graphs shallow when possible (fewer levels) +- Use smooth operations sparingly (more expensive) +- Avoid unnecessary coordinate transformations +- Minimize resource node usage in tight loops + +## Serialization + +Nodes can be serialized to 3MF format using the implicit namespace: + +```xml + + + + + + + + + 1.0 + + + + + + + + + +``` + +## Error Handling + +The node system validates graphs and reports errors: + +- **Type Mismatch**: Connecting incompatible port types +- **Cyclic Graph**: Loops in the graph +- **Missing Connections**: Required inputs not connected +- **Invalid Parameters**: Out-of-range parameter values +- **Missing Resources**: Referenced files not found + +## Extension Points + +### Creating Custom Nodes + +```cpp +class CustomNode : public ClonableNode { +public: + CustomNode() : ClonableNode("CustomNode", {}, Category::Function) { + // Define ports + addInput("input", PortType::Scalar); + addOutput("output", PortType::Scalar); + + // Define parameters + addParameter("factor", 1.0f); + } + + std::string getDescription() const override { + return "Custom node description"; + } + + // OpenCL code generation + std::string generateKernelCode() const override { + return "output = input * factor;"; + } +}; +``` + +### Registering Custom Nodes + +```cpp +// In node factory +NodeBase* createNodeFromName(const std::string& name, Model& model) { + if (name == "CustomNode") { + return new CustomNode(); + } + // ... other nodes +} +``` + +## Related Documentation + +- [Architecture Overview](ARCHITECTURE.md) +- [Compute Pipeline Documentation](COMPUTE_PIPELINE.md) +- [Graph Algorithms](GRAPH_ALGORITHMS.md) +- [API Reference](API_REFERENCE.md) diff --git a/gladius/documentation/QUICK_REFERENCE.md b/gladius/documentation/QUICK_REFERENCE.md new file mode 100644 index 00000000..0e02ba18 --- /dev/null +++ b/gladius/documentation/QUICK_REFERENCE.md @@ -0,0 +1,542 @@ +# Quick Reference Guide + +A handy reference for common tasks, APIs, and patterns in Gladius. + +## 📌 Build Commands + +### Windows +```bash +# Configure +cmake --preset x64-debug +cmake --preset x64-release + +# Build +cmake --build --preset x64-debug +cmake --build --preset x64-release + +# Test +cd out/build/x64-debug +ctest --output-on-failure +``` + +### Linux +```bash +# Configure +cmake --preset linux-debug +cmake --preset linux-release + +# Build +cmake --build out/build/linux-debug +cmake --build out/build/linux-release + +# Test +cd out/build/linux-debug +ctest --output-on-failure +``` + +## 🔧 Common Development Tasks + +### Running the Application +```bash +# Debug build +./out/build/x64-debug/gladius + +# With a file +./out/build/x64-debug/gladius model.3mf + +# Release build +./out/build/x64-release/gladius +``` + +### Formatting Code +```bash +# Format all changed files +git diff --name-only | grep -E '\.(cpp|h)$' | xargs clang-format -i + +# Format specific file +clang-format -i src/MyFile.cpp +``` + +### Running Specific Tests +```bash +# Run all tests +./gladius_tests + +# Run specific test suite +./gladius_tests --gtest_filter=NodeSystem_Tests.* + +# Run single test +./gladius_tests --gtest_filter=NodeSystem_Tests.CreateBasicGraph +``` + +## 🎯 Common Coding Patterns + +### Creating a Node Graph +```cpp +#include +#include + +nodes::Model model; +model.createBeginEnd(); + +// Add a sphere +auto sphereId = model.addNode(std::make_unique()); +auto sphereNode = model.getNode(sphereId); +sphereNode->setParameter("radius", 1.0f); + +// Add a box +auto boxId = model.addNode(std::make_unique()); + +// Add union operation +auto unionId = model.addNode(std::make_unique()); + +// Connect nodes +auto beginId = model.getBeginNode(); +auto endId = model.getEndNode(); + +model.connect(beginId, "cs", sphereId, "cs"); +model.connect(sphereId, "distance", unionId, "a"); +model.connect(boxId, "distance", unionId, "b"); +model.connect(unionId, "result", endId, "input"); +``` + +### Loading and Rendering a Model +```cpp +#include +#include + +// Load model +Importer3mf importer("model.3mf"); +auto assembly = importer.import(); + +// Set up compute +auto computeContext = std::make_shared(); +auto resourceContext = std::make_shared(computeContext); +ComputeCore computeCore(computeContext, resourceContext); + +// Update with model +computeCore.updateModel(assembly->getModel()); + +// Render +Camera camera; +ImageBuffer output(1920, 1080); +computeCore.render(camera, output); +``` + +### Generating Slices +```cpp +#include +#include + +// Generate single slice +float zHeight = 5.0f; +int resolution = 2048; +BitmapLayer slice; +computeCore.generateSlice(zHeight, resolution, slice); + +// Extract contours +ContourExtractor extractor; +auto contours = extractor.extract(slice); + +// Process contours +for (const auto& contour : contours) { + for (const auto& point : contour.points) { + // Process point + } +} +``` + +### Exporting to Different Formats +```cpp +#include +#include +#include + +// Export as 3MF +Writer3mf writer3mf("output.3mf"); +writer3mf.write(*assembly); + +// Export as STL mesh +MeshExporter meshExporter("output.stl"); +meshExporter.exportMesh(*assembly); + +// Export contours as SVG +SvgWriter svgWriter("output.svg"); +for (float z = 0; z < 10.0f; z += 0.1f) { + auto slice = computeCore.generateSlice(z, 2048); + svgWriter.addSlice(slice, z); +} +svgWriter.write(); +``` + +### Using the API (C++) +```cpp +#include + +// Create Gladius instance +auto gladius = GladiusLib::CreateGladius(); + +// Load model +auto model = gladius->LoadModel("input.3mf"); + +// Generate slice +auto slice = model->GenerateSlice(5.0f, 2048); + +// Process contours +for (uint32_t i = 0; i < slice->GetContourCount(); i++) { + auto contour = slice->GetContour(i); + for (uint32_t j = 0; j < contour->GetPointCount(); j++) { + auto point = contour->GetPoint(j); + // Process point + } +} + +// Export +model->ExportMesh("output.stl"); +``` + +## 🔍 Useful Debugging Commands + +### GDB (Linux) +```bash +# Start debugging +gdb ./gladius + +# Set breakpoint +(gdb) break Application.cpp:42 +(gdb) break ComputeCore::render + +# Run with arguments +(gdb) run model.3mf + +# Print variable +(gdb) print variableName +(gdb) print *this + +# Continue execution +(gdb) continue +(gdb) next +(gdb) step + +# Backtrace +(gdb) backtrace +(gdb) frame 2 +``` + +### LLDB (macOS/Linux) +```bash +# Start debugging +lldb ./gladius + +# Set breakpoint +(lldb) breakpoint set --file Application.cpp --line 42 +(lldb) breakpoint set --name ComputeCore::render + +# Run with arguments +(lldb) run model.3mf + +# Print variable +(lldb) print variableName +(lldb) expr this + +# Continue execution +(lldb) continue +(lldb) next +(lldb) step +``` + +### Visual Studio Debugger +``` +F9 - Toggle breakpoint +F5 - Start debugging +F10 - Step over +F11 - Step into +Shift+F11 - Step out +F5 - Continue +Shift+F5 - Stop debugging +``` + +## 📊 Common OpenCL Patterns + +### Creating a Kernel +```cpp +#include + +class MyProgram : public CLProgram { +public: + MyProgram(SharedComputeContext context) + : CLProgram(context) { + // Load kernel source + std::string source = loadKernelSource("my_kernel.cl"); + + // Compile + compile(source); + + // Get kernel + m_kernel = cl::Kernel(m_program, "my_kernel"); + } + + void execute(cl::Buffer& input, cl::Buffer& output, int count) { + m_kernel.setArg(0, input); + m_kernel.setArg(1, output); + m_kernel.setArg(2, count); + + auto& queue = m_context->getQueue(); + queue.enqueueNDRangeKernel( + m_kernel, + cl::NullRange, + cl::NDRange(count), + cl::NullRange + ); + } + +private: + cl::Kernel m_kernel; +}; +``` + +### Buffer Operations +```cpp +// Create buffer +cl::Buffer buffer = context->createBuffer( + size * sizeof(float), + CL_MEM_READ_WRITE +); + +// Write to buffer +std::vector data = {1.0f, 2.0f, 3.0f}; +queue.enqueueWriteBuffer(buffer, CL_TRUE, 0, + data.size() * sizeof(float), + data.data()); + +// Read from buffer +std::vector result(size); +queue.enqueueReadBuffer(buffer, CL_TRUE, 0, + result.size() * sizeof(float), + result.data()); + +// Copy buffer +cl::Buffer buffer2 = context->createBuffer(size * sizeof(float)); +queue.enqueueCopyBuffer(buffer, buffer2, 0, 0, size * sizeof(float)); +``` + +## 🧪 Testing Patterns + +### Basic Unit Test +```cpp +#include + +TEST(ComponentName_Tests, MethodName_Condition_ExpectedBehavior) { + // Arrange + ComponentName component; + component.setup(); + + // Act + auto result = component.methodName(); + + // Assert + ASSERT_EQ(result, expectedValue); +} +``` + +### Testing with Fixtures +```cpp +class MyTestFixture : public ::testing::Test { +protected: + void SetUp() override { + // Setup code + m_model.createBeginEnd(); + } + + void TearDown() override { + // Cleanup code + } + + nodes::Model m_model; +}; + +TEST_F(MyTestFixture, TestSomething) { + // Test uses m_model from fixture + ASSERT_TRUE(m_model.isValid()); +} +``` + +### Testing Exceptions +```cpp +TEST(MyTest, ThrowsException) { + MyClass obj; + ASSERT_THROW(obj.methodThatThrows(), std::runtime_error); +} + +TEST(MyTest, NoThrow) { + MyClass obj; + ASSERT_NO_THROW(obj.methodThatDoesntThrow()); +} +``` + +## 📝 Node Types Quick Reference + +| Category | Node Types | +|----------|-----------| +| **Primitives** | Sphere, Box, Cylinder, Cone, Torus, Capsule, Plane | +| **Boolean Ops** | Union, Intersection, Difference, SmoothUnion, SmoothIntersection | +| **Math Functions** | Add, Subtract, Multiply, Divide, Power, Sqrt, Abs, Min, Max | +| **Trigonometry** | Sin, Cos, Tan, Asin, Acos, Atan, Atan2 | +| **Vector Ops** | Dot, Cross, Normalize, Length, Distance | +| **Interpolation** | Mix, Smoothstep, Step, Clamp | +| **Resources** | MeshResource, ImageStackResource, VdbResource | +| **Transforms** | Translate, Rotate, Scale, Matrix | + +## 🎨 ImGUI Patterns + +### Basic Window +```cpp +void MyWindow::render() { + if (ImGui::Begin("My Window")) { + ImGui::Text("Hello, World!"); + + if (ImGui::Button("Click Me")) { + // Handle click + } + + ImGui::End(); + } +} +``` + +### Input Widgets +```cpp +// Float input +float value = 1.0f; +ImGui::InputFloat("Value", &value); + +// Slider +ImGui::SliderFloat("Radius", &radius, 0.0f, 10.0f); + +// Color picker +ImVec4 color = ImVec4(1.0f, 0.0f, 0.0f, 1.0f); +ImGui::ColorEdit4("Color", (float*)&color); + +// Checkbox +bool enabled = true; +ImGui::Checkbox("Enabled", &enabled); + +// Combo box +const char* items[] = {"Item 1", "Item 2", "Item 3"}; +static int currentItem = 0; +ImGui::Combo("Select", ¤tItem, items, IM_ARRAYSIZE(items)); +``` + +## 🔐 Error Handling Patterns + +### Exception Handling +```cpp +try { + auto model = importer.import(); + // Use model +} catch (const ImportException& e) { + EventLogger::instance().error("Import failed: {}", e.what()); +} catch (const std::exception& e) { + EventLogger::instance().error("Unexpected error: {}", e.what()); +} +``` + +### OpenCL Error Checking +```cpp +#include "ComputeContext.h" + +cl_int err; +cl::Buffer buffer(context, CL_MEM_READ_WRITE, size, nullptr, &err); +CL_ERROR(err); // Throws if error +``` + +### Validation +```cpp +bool validate(const Model& model) { + if (!model.hasBeginNode()) { + EventLogger::instance().error("Model missing begin node"); + return false; + } + + if (!model.hasEndNode()) { + EventLogger::instance().error("Model missing end node"); + return false; + } + + if (model.hasCycle()) { + EventLogger::instance().error("Model contains cycle"); + return false; + } + + return true; +} +``` + +## 📚 Common Includes + +```cpp +// Core +#include +#include +#include + +// Compute +#include +#include +#include + +// I/O +#include +#include +#include + +// Resources +#include +#include +#include + +// Utilities +#include +#include +#include +``` + +## 🌐 File Format Extensions + +| Extension | Format | Use Case | +|-----------|--------|----------| +| `.3mf` | 3MF with volumetric | Import/Export models | +| `.stl` | STL mesh | Export meshes | +| `.obj` | Wavefront OBJ | Export meshes | +| `.svg` | SVG vector | Export contours | +| `.cli` | CLI format | Export contours for manufacturing | +| `.vdb` | OpenVDB | Import/Export volumetric data | +| `.raw` | Raw binary | Image stack data | + +## 🎯 Performance Tips + +### DO +- ✅ Cache compiled kernels +- ✅ Use local memory in kernels +- ✅ Batch GPU operations +- ✅ Use OpenGL interop for rendering +- ✅ Profile before optimizing + +### DON'T +- ❌ Copy between CPU/GPU unnecessarily +- ❌ Recompile kernels on every frame +- ❌ Use printf in production kernels +- ❌ Allocate in hot loops +- ❌ Use global state + +## 🔗 Useful Links + +- [Main Documentation](README.md) +- [Developer Guide](DEVELOPER_GUIDE.md) +- [Architecture Overview](ARCHITECTURE.md) +- [API Reference](API_REFERENCE.md) +- [GitHub Repository](https://github.com/3MFConsortium/gladius) + +--- + +**Tip**: Bookmark this page for quick reference during development! diff --git a/gladius/documentation/README.md b/gladius/documentation/README.md new file mode 100644 index 00000000..17bd93a5 --- /dev/null +++ b/gladius/documentation/README.md @@ -0,0 +1,250 @@ +# Gladius Documentation + +Welcome to the comprehensive documentation for Gladius - a development tool for processing implicit geometries with the 3MF Volumetric Extension. + +## 📚 Documentation Index + +### Getting Started + +- **[Developer Guide](DEVELOPER_GUIDE.md)** - Start here! Complete guide to setting up your development environment, building, and contributing +- **[Architecture Overview](ARCHITECTURE.md)** - High-level system architecture and component overview +- **[Quick Reference](QUICK_REFERENCE.md)** - Handy reference for common tasks and APIs + +### Core Systems + +- **[Node System](NODE_SYSTEM.md)** - Detailed documentation of the node graph system + - Node types and categories + - Type system and validation + - Graph operations and visitors + - Creating custom nodes + +- **[Compute Pipeline](COMPUTE_PIPELINE.md)** - GPU acceleration and OpenCL execution + - ComputeContext and device management + - Kernel generation and compilation + - Rendering and slicing pipelines + - Performance optimization + +- **[Data Flow](DATA_FLOW.md)** - How data moves through the system + - Model loading and display + - Interactive editing + - Slicing and export workflows + - Performance characteristics + +### Integration and I/O + +- **[3MF Support](3MF_SUPPORT.md)** - Import/Export of 3MF with Volumetric Extension + - Implicit function graphs + - Image3D volumetric data + - Resource management + - Format compatibility + +- **[API Reference](API_REFERENCE.md)** - Public API for C++, C#, and Python + - Class hierarchy + - Method documentation + - Usage examples + - Language bindings + +## 🎯 Documentation by Use Case + +### I want to... + +#### Use Gladius in My Application +→ Start with [API Reference](API_REFERENCE.md) for programmatic access + +#### Add a New Feature +→ Read [Developer Guide](DEVELOPER_GUIDE.md) → [Architecture Overview](ARCHITECTURE.md) → relevant system doc + +#### Fix a Bug +→ Check [Data Flow](DATA_FLOW.md) to understand the code path → [Developer Guide](DEVELOPER_GUIDE.md) for debugging + +#### Add a New Node Type +→ See "Adding New Node Types" in [Node System](NODE_SYSTEM.md) → [Developer Guide](DEVELOPER_GUIDE.md) + +#### Optimize Performance +→ Review performance sections in [Compute Pipeline](COMPUTE_PIPELINE.md) and [Data Flow](DATA_FLOW.md) + +#### Support a New File Format +→ Study [3MF Support](3MF_SUPPORT.md) as a reference → implement similar patterns + +#### Understand How Something Works +→ Start with [Architecture Overview](ARCHITECTURE.md) → dive into specific system docs + +## 🗺️ System Overview + +```mermaid +graph TB + subgraph "User Layer" + UI[User Interface
ImGUI-based] + end + + subgraph "Application Layer" + App[Application Core
Coordination & State] + end + + subgraph "Processing Layer" + Nodes[Node System
Graph Definition] + Compute[Compute Pipeline
GPU Execution] + end + + subgraph "I/O Layer" + Import[Import
3MF, VDB] + Export[Export
STL, SVG, CLI] + end + + UI --> App + App --> Nodes + App --> Compute + Nodes --> Compute + Import --> Nodes + Nodes --> Export +``` + +## 🔑 Key Concepts + +### Implicit Geometry +Gladius uses signed distance fields (SDFs) to represent 3D geometry implicitly as mathematical functions rather than explicit meshes. This enables: +- Exact CSG operations +- Infinite resolution +- Compact representation +- Efficient ray marching + +### Node Graphs +Complex shapes are built by connecting nodes in a dataflow graph: +- **Primitive nodes**: Basic shapes (sphere, box, cylinder) +- **Operation nodes**: Combine shapes (union, intersection, difference) +- **Function nodes**: Mathematical transformations +- **Resource nodes**: External data (meshes, images, volumes) + +### GPU Acceleration +All heavy computations run on the GPU via OpenCL: +- Real-time rendering using ray marching +- Fast slice generation for manufacturing +- Parallel contour extraction + +### 3MF Volumetric Extension +Native support for the 3MF format with implicit geometry: +- Import/export function graphs +- Embed volumetric data +- Preserve design intent + +## 📖 Documentation Structure + +Each documentation file follows a consistent structure: + +1. **Overview** - What the system does and why it exists +2. **Architecture** - High-level design with diagrams +3. **Core Components** - Detailed class and interface documentation +4. **Usage Examples** - Practical code examples +5. **Common Patterns** - Best practices and idioms +6. **Troubleshooting** - Common issues and solutions +7. **Related Documentation** - Links to related topics + +## 🎨 Diagram Legend + +Throughout the documentation, you'll find Mermaid diagrams with these conventions: + +- **Rectangles**: Components or classes +- **Rounded rectangles**: Processes or operations +- **Diamonds**: Decisions or conditions +- **Cylinders**: Data storage +- **Arrows**: Data flow or dependencies +- **Colors**: + - Green: Entry points + - Blue: Core components + - Orange: External systems + - Red: Error states + +## 🔧 Tools Used + +- **Language**: C++17/20 +- **GPU Compute**: OpenCL 1.2+ +- **Graphics**: OpenGL 3.3+ +- **UI Framework**: Dear ImGUI +- **Build System**: CMake + vcpkg +- **Testing**: Google Test / Google Mock +- **File Format**: 3MF (lib3mf), OpenVDB + +## 🤝 Contributing to Documentation + +Documentation improvements are always welcome! When contributing: + +1. **Follow the structure** - Match the existing format +2. **Add diagrams** - Use Mermaid for visual explanations +3. **Include examples** - Code samples help understanding +4. **Cross-reference** - Link to related documentation +5. **Test code** - Ensure examples actually work +6. **Update index** - Add new documents to this README + +## 📝 Documentation Standards + +- Use GitHub-flavored Markdown +- Include Mermaid diagrams for complex concepts +- Provide code examples in C++ (primary language) +- Keep paragraphs concise and scannable +- Use tables for reference information +- Include links to related sections + +## 🚀 Quick Start Path + +**New Developer? Follow this path:** + +1. [Developer Guide](DEVELOPER_GUIDE.md) - Set up environment and build +2. [Architecture Overview](ARCHITECTURE.md) - Understand the big picture +3. [Node System](NODE_SYSTEM.md) - Learn the core abstraction +4. [Quick Reference](QUICK_REFERENCE.md) - Bookmark for daily use +5. Pick a specific topic based on your work + +**New User of the API? Follow this path:** + +1. [API Reference](API_REFERENCE.md) - Learn the public interface +2. [3MF Support](3MF_SUPPORT.md) - Understand the file format +3. [Quick Reference](QUICK_REFERENCE.md) - Common API patterns +4. Start coding! + +## 🔍 Finding Information + +- **Search by topic**: Use GitHub's file search (`Ctrl+K` or `Cmd+K`) +- **Search within file**: Use your editor's search (`Ctrl+F`) +- **Browse code**: Links to source files are provided where relevant +- **Check examples**: Many docs include working code examples + +## 💡 Tips for Reading + +- Diagrams are clickable - you can zoom and inspect +- Code blocks are syntax highlighted +- Links are blue and underlined +- Important notes are in **bold** or > blockquotes +- Examples show multiple languages where applicable + +## 📦 Additional Resources + +### External Documentation +- [3MF Specification](https://3mf.io/specification/) +- [OpenCL Documentation](https://www.khronos.org/opencl/) +- [ImGUI Documentation](https://github.com/ocornut/imgui) +- [CMake Documentation](https://cmake.org/documentation/) + +### Community +- [GitHub Repository](https://github.com/3MFConsortium/gladius) +- [Issue Tracker](https://github.com/3MFConsortium/gladius/issues) +- [Discussions](https://github.com/3MFConsortium/gladius/discussions) + +## 📅 Documentation Versions + +This documentation corresponds to Gladius version 1.2.0 and above. If you're using an older version, some features may not be available. + +## ❓ Questions? + +- **Found an error?** Open an issue on GitHub +- **Need clarification?** Start a discussion +- **Want to contribute?** Submit a pull request + +## 🏆 Credits + +Documentation created and maintained by the Gladius development team and community contributors. + +--- + +**Last Updated**: December 2024 +**Documentation Version**: 1.0 +**Gladius Version**: 1.2.0+