Skip to main content

opencsg_sys/
lib.rs

1//! FFI bindings to OpenCSG (image-based CSG rendering for OpenGL).
2//!
3//! OpenCSG renders CSG (Constructive Solid Geometry) results directly into
4//! the OpenGL depth buffer using the Goldfeather or SCS algorithms. After
5//! calling [`render`], re-render the primitives with `GL_EQUAL` depth
6//! test to shade them.
7
8use std::ffi::c_void;
9use std::os::raw::{c_int, c_uint};
10
11/// Operation: the primitive is intersected into the CSG product.
12pub const INTERSECTION: c_int = 0;
13/// Operation: the primitive is subtracted from the CSG product.
14pub const SUBTRACTION: c_int = 1;
15
16/// Algorithm: automatic selection based on primitive properties.
17pub const ALGORITHM_AUTOMATIC: c_int = 0;
18/// Algorithm: Goldfeather (robust, handles concave primitives).
19pub const ALGORITHM_GOLDFEATHER: c_int = 1;
20/// Algorithm: SCS (fast, convex primitives only).
21pub const ALGORITHM_SCS: c_int = 2;
22
23/// Option: which CSG algorithm to use.
24pub const OPTION_ALGORITHM: c_int = 0;
25/// Option: depth complexity sampling strategy.
26pub const OPTION_DEPTH_COMPLEXITY: c_int = 1;
27/// Option: offscreen buffer type.
28pub const OPTION_OFFSCREEN: c_int = 2;
29
30/// C callback type for rendering a primitive's geometry.
31pub type RenderFn = unsafe extern "C" fn(*mut c_void);
32
33/// Opaque handle to an OpenCSG primitive.
34#[repr(C)]
35pub struct OcsgPrimitive {
36  _opaque: [u8; 0],
37}
38
39unsafe extern "C" {
40  pub safe fn opencsg_init_gl();
41
42  pub fn opencsg_primitive_new(
43    operation: c_int,
44    convexity: c_uint,
45    callback: RenderFn,
46    user_data: *mut c_void,
47  ) -> *mut OcsgPrimitive;
48
49  pub fn opencsg_primitive_free(prim: *mut OcsgPrimitive);
50
51  pub fn opencsg_primitive_set_bounding_box(
52    prim: *mut OcsgPrimitive,
53    minx: f32,
54    miny: f32,
55    minz: f32,
56    maxx: f32,
57    maxy: f32,
58    maxz: f32,
59  );
60
61  pub fn opencsg_render_primitives(
62    primitives: *mut *mut OcsgPrimitive,
63    count: c_int,
64  );
65
66  pub safe fn opencsg_set_option(option_type: c_int, setting: c_int);
67
68  pub safe fn opencsg_free_resources();
69}
70
71// --- Safe wrappers ---
72
73/// Initialize OpenCSG's internal GL loader. Call once after GL context is current.
74pub fn init_gl() {
75  opencsg_init_gl();
76}
77
78/// Set an OpenCSG option (algorithm, depth complexity, offscreen type).
79pub fn set_option(option_type: c_int, setting: c_int) {
80  opencsg_set_option(option_type, setting);
81}
82
83/// Release OpenGL resources allocated by OpenCSG for the current context.
84pub fn free_resources() {
85  opencsg_free_resources();
86}
87
88/// Perform CSG rendering on a list of primitive pointers.
89///
90/// # Safety
91/// All pointers in `primitives` must be valid `OcsgPrimitive` handles.
92/// The render callbacks must only issue valid GL calls.
93pub unsafe fn render(primitives: &mut [*mut OcsgPrimitive]) {
94  if primitives.is_empty() {
95    return;
96  }
97  unsafe {
98    opencsg_render_primitives(
99      primitives.as_mut_ptr(),
100      primitives.len() as c_int,
101    );
102  }
103}
104
105/// Create a new OpenCSG primitive.
106///
107/// # Safety
108/// `callback` will be invoked by OpenCSG during rendering passes.
109/// `user_data` must remain valid for the lifetime of the primitive.
110pub unsafe fn primitive_new(
111  operation: c_int,
112  convexity: u32,
113  callback: RenderFn,
114  user_data: *mut c_void,
115) -> *mut OcsgPrimitive {
116  unsafe {
117    opencsg_primitive_new(operation, convexity as c_uint, callback, user_data)
118  }
119}
120
121/// Free an OpenCSG primitive.
122///
123/// # Safety
124/// `prim` must be a valid handle returned by `primitive_new`.
125pub unsafe fn primitive_free(prim: *mut OcsgPrimitive) {
126  unsafe {
127    opencsg_primitive_free(prim);
128  }
129}
130
131/// Set the bounding box on a primitive (normalized device coordinates).
132///
133/// # Safety
134/// `prim` must be a valid handle.
135pub unsafe fn primitive_set_bbox(
136  prim: *mut OcsgPrimitive,
137  minx: f32,
138  miny: f32,
139  minz: f32,
140  maxx: f32,
141  maxy: f32,
142  maxz: f32,
143) {
144  unsafe {
145    opencsg_primitive_set_bounding_box(
146      prim, minx, miny, minz, maxx, maxy, maxz,
147    );
148  }
149}