This page summarizes the retained DDS/CHDOP composition layer built on top of the normal drawing primitives.
Object operations do not delete the original primitive objects from the DDS graph. Instead, they create new retained DDS nodes that reference existing object IDs. The composed result is serializable, hideable, labelable, recolorable, and reusable in later compositions.
Overview
The current retained object-operation API in wx_bgi_dds.h is:
| Function | Purpose |
wxbgi_dds_translate(id, dx, dy, dz) | Create a retained affine-transform node that replays id with a translation offset |
wxbgi_dds_rotate_x/y/z_deg(id, angleDeg) | Create retained affine-transform nodes for axis-aligned rotation in degrees |
wxbgi_dds_rotate_x/y/z_rad(id, angleRad) | Create retained affine-transform nodes for axis-aligned rotation in radians |
wxbgi_dds_rotate_axis_deg/rad(id, ax, ay, az, angle) | Create retained affine-transform nodes for arbitrary-axis rotation |
wxbgi_dds_scale_uniform(id, factor) / wxbgi_dds_scale_xyz(id, sx, sy, sz) | Create retained affine-transform nodes for uniform or per-axis scaling |
wxbgi_dds_skew(id, xy, xz, yx, yz, zx, zy) | Create a retained affine-transform node from 3D shear factors |
wxbgi_dds_union(count, ids) | Create a retained set-union node over existing DDS object IDs |
wxbgi_dds_intersection(count, ids) | Create a retained set-intersection node over existing DDS object IDs |
wxbgi_dds_difference(count, ids) | Create a retained ordered set-difference node over existing DDS object IDs |
wxbgi_object_set_face_color(id, color) | Change the rendered face color of an existing retained solid or set-operation blob |
wxbgi_dds_get_child_count(id) | Return the number of direct referenced child IDs |
wxbgi_dds_get_child_at(id, index) | Return one direct child ID from a retained operation node |
All of these return or operate on normal DDS object IDs, so the results participate in:
C/C++ note: DDS ID getter functions return borrowed const char * buffers. Copy them into std::string before making later DDS API calls.
</blockquote>
Set Operations
Three retained set operations are available:
- Union combines multiple referenced DDS objects into one composed result.
- Intersection keeps only the common overlapping part of the referenced DDS objects.
- Difference subtracts later operands from the first operand in order.
Current status
- Translate, rotate, scale, and skew are implemented as retained affine helpers over the same
Transform node type.
Transform nodes carry a full 4x4 matrix internally, and retained replay / exact 3D set operations now evaluate the full accumulated matrix chain instead of translation alone.
Union, Intersection, and Difference are first-class retained DDS node types with their own draw mode, colour, label, visibility, and serialisation state.
- During retained rendering, operands referenced by transform/set-operation nodes are no longer replayed as standalone roots. The composed node owns the visible result.
- For supported 3D solids the retained set-operation path evaluates closed Manifold volumes and caches the resulting display mesh per DDS scene revision.
How they are used
The input objects must already exist in the active DDS scene. A set-operation node stores only their IDs; it does not duplicate the leaf geometry.
const char *ids[2] = { idA.c_str(), idB.c_str() };
BGI_API const char *BGI_CALL wxbgi_dds_difference(int count, const char *const *ids)
Creates a retained SetDifference node over count operand IDs.
BGI_API const char *BGI_CALL wxbgi_dds_union(int count, const char *const *ids)
Creates a retained SetUnion node over count operand IDs.
BGI_API const char *BGI_CALL wxbgi_dds_intersection(int count, const char *const *ids)
Creates a retained SetIntersection node over count operand IDs.
Typical workflow:
- Draw or create the source objects normally.
- Capture or look up their DDS IDs and copy them to stable storage in C++.
- Create a retained union, intersection, or difference node.
- Optionally label or recolor the composed node.
- Re-render the scene with
wxbgi_render_dds(...).
You no longer need to manually hide operands just to prevent double-drawing during retained replay. DDS render-root traversal handles that ownership automatically.
You can recolor a retained composed blob after it has been created:
BGI_API int BGI_CALL wxbgi_object_set_face_color(const char *id, int color)
Sets the face fill colour for an existing DDS object identified by id.
Current behavior
- For supported 3D solid DDS objects (
Box, Sphere, Cylinder, Cone, Torus, HeightMap, ParamSurface, Extrusion), Union, Intersection, and Difference currently use the exact Manifold-based boolean path during retained rendering.
- Difference follows OpenSCAD-style ordered subtraction: operand 0 is the base solid and operands 1..N are subtracted from it in sequence, producing the remaining solid volume.
- For other retained DDS content, the composed result still behaves as a first-class retained DDS object and re-renders through the normal DDS traversal path.
Volume semantics
Retained 3D set operations are evaluated as solid volumes for supported DDS solid primitives. The rendered triangles are only the display/export form of that volumetric result, not the boolean model itself.
Notes
- Set-operation nodes are stored as their own CHDOP/DDS object types:
WXBGI_DDS_SET_UNION
WXBGI_DDS_SET_INTERSECTION
WXBGI_DDS_SET_DIFFERENCE
- Child IDs can point to leaf primitives, transform nodes, or other set-operation nodes.
- Invalid or missing child references are ignored by traversal; exact 3D evaluation requires valid operands and a supported closed-volume conversion path.
- Difference is ordered: operand 0 is the base, operands 1..N are subtracted in sequence.
Affine Transformations
The retained transform path is intentionally modeled as an affine transformation layer.
The public helpers are:
const std::string skewId =
wxbgi_dds_skew(
id.c_str(), 0.35f, 0.f, 0.f, 0.f, 0.f, 0.f);
BGI_API const char *BGI_CALL wxbgi_dds_rotate_z_deg(const char *id, float angleDeg)
BGI_API const char *BGI_CALL wxbgi_dds_translate(const char *id, float dx, float dy, float dz)
Creates a retained transform node that translates the object/subtree identified by id by (dx,...
BGI_API const char *BGI_CALL wxbgi_dds_scale_uniform(const char *id, float factor)
Creates a retained transform node that scales id by the given factor(s).
BGI_API const char *BGI_CALL wxbgi_dds_skew(const char *id, float xy, float xz, float yx, float yz, float zx, float zy)
Creates a retained transform node with a 3D shear/skew matrix.
Each call creates a new retained transform node that references the original object and replays it through the requested matrix. The original object remains unchanged.
Implemented today
- Translate
- Rotate on X/Y/Z and arbitrary axes, in both degrees and radians
- Scale with uniform or per-axis factors
- Skew / shear with six independent factors
Why this is an affine path
Internally, the transform node carries a 4x4 matrix so the same retained-node model covers:
- translation
- rotation
- scaling
- skew / shear
- future general matrix (
multmatrix) transforms
That keeps the API consistent and lets transforms compose naturally with union and intersection nodes.
High-level implementation design
- Source primitives are appended to the DDS as normal leaf nodes.
wxbgi_dds_translate(...), wxbgi_dds_rotate_*(), wxbgi_dds_scale_*(), and wxbgi_dds_skew(...) wrap one existing ID in a retained Transform node that stores the requested affine matrix.
wxbgi_dds_union(...), wxbgi_dds_intersection(...), and wxbgi_dds_difference(...) create retained set-operation nodes that store operand IDs only.
wxbgi_render_dds(...) starts from DDS render roots only. Any operand that is referenced by a transform or set-operation node is replayed through that owner instead of as an independent root.
- Retained traversal accumulates the full 4x4 matrix chain while replaying leaves and while evaluating exact 3D Manifold booleans.
- For supported 3D solids the set-operation node renders an exact closed-volume boolean result; for non-exact cases the node still participates in the same retained traversal and masking path.
Minimal Example
const char *ops[2] = { boxA.c_str(), movedB.c_str() };
BGI_API void BGI_CALL cleardevice(void)
Clears the full active drawing page to background color.
Public classic BGI-compatible C API exported by the library.
Public C API for the Drawing Description Data Structure (DDS).
BGI_API const char *BGI_CALL wxbgi_dds_get_id_at(int index)
Returns the auto-assigned ID string of the object at position index (0-based insertion order,...
BGI_API void BGI_CALL wxbgi_render_dds(const char *camName)
Renders all visible DDS drawing objects through the named camera into the BGI pixel buffer.
BGI_API void BGI_CALL wxbgi_dds_set_label(const char *id, const char *label)
Sets the user label of the object identified by id.
BGI_API int BGI_CALL wxbgi_dds_object_count(void)
Returns the total number of non-deleted, visible + hidden objects in the DDS (cameras,...
Public C API for Phase 4 (3D Solid Primitives), Phase 5 (3D Surfaces), and Phase 6 (2Dā3D Extrusion) ...
BGI_API void BGI_CALL wxbgi_solid_box(float cx, float cy, float cz, float width, float depth, float height)
Draw an axis-aligned box centred at (cx, cy, cz).
Compound-solid screenshots
These screenshots come from the current wxbgi_set_operations_demo_cpp scene and show retained translation + set-operation results rendered as compound solids:
Compound solids shaded mode
Compound solids wireframe mode
Related Pages
- DDS.md ā retained scene graph, serialization, and CHDOP type list
- Camera3D_Map.md ā camera projection and world/screen mapping
- Tests.md ā current automated coverage for retained transform and set operations