ptex_sys/lib.rs
1/// cxx FFI bindings to the Ptex C++ API.
2
3/// The ffi module provides raw access to the underlying C++ APIs.
4#[cxx::bridge(namespace = "Ptex")]
5pub mod ffi {
6 /// How to handle mesh border when filtering.
7 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
8 #[repr(u32)]
9 enum BorderMode {
10 /// texel access is clamped to border
11 #[cxx_name = "m_clamp"]
12 Clamp,
13 /// texel beyond border are assumed to be black
14 #[cxx_name = "m_black"]
15 Black,
16 /// texel access wraps to other side of face
17 #[cxx_name = "m_periodic"]
18 Periodic,
19 }
20
21 /// Type of data stored in texture file.
22 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
23 #[repr(u32)]
24 enum DataType {
25 /// Unsigned, 8-bit integer.
26 #[cxx_name = "dt_uint8"]
27 UInt8,
28 /// Unsigned, 16-bit integer.
29 #[cxx_name = "dt_uint16"]
30 UInt16,
31 /// Half-precision (16-bit) floating point.
32 #[cxx_name = "dt_half"]
33 Float16,
34 /// Single-precision (32-bit) floating point.
35 #[cxx_name = "dt_float"]
36 Float32,
37 }
38
39 /// How to handle transformation across edges when filtering.
40 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
41 #[repr(u32)]
42 enum EdgeFilterMode {
43 /// Don't do anything with the values.
44 #[cxx_name = "efm_none"]
45 None,
46 /// Values are vectors in tangent space; rotate values.
47 #[cxx_name = "efm_tanvec"]
48 TangentVector,
49 }
50
51 /// Edge IDs used in adjacency data in the Ptex::FaceInfo struct.
52 /// Edge ID usage for triangle meshes is TBD.
53 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
54 #[repr(u32)]
55 enum EdgeId {
56 /// Bottom edge, from UV (0,0) to (1,0)
57 #[cxx_name = "e_bottom"]
58 Bottom,
59 /// Right edge, from UV (1,0) to (1,1)
60 #[cxx_name = "e_right"]
61 Right,
62 /// Top edge, from UV (1,1) to (0,1)
63 #[cxx_name = "e_top"]
64 Top,
65 /// Left edge, from UV (0,1) to (0,0)
66 #[cxx_name = "e_left"]
67 Left,
68 }
69
70 /// Type of meta data entry.
71 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
72 #[repr(u32)]
73 enum MetaDataType {
74 /// Null-terminated string.
75 #[cxx_name = "mdt_string"]
76 String,
77 // Signed 8-bit integer.
78 #[cxx_name = "mdt_int8"]
79 Int8,
80 /// Signed 16-bit integer.
81 #[cxx_name = "mdt_int16"]
82 Int16,
83 /// Signed 32-bit integer.
84 #[cxx_name = "mdt_int32"]
85 Int32,
86 /// Single-precision (32-bit) floating point.
87 #[cxx_name = "mdt_float"]
88 Float,
89 /// Double-precision (32-bit) floating point.
90 #[cxx_name = "mdt_double"]
91 Double,
92 }
93
94 /// Type of base mesh for which the textures are defined. A mesh
95 /// can be triangle-based (with triangular textures) or quad-based
96 /// (with rectangular textures). */
97 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
98 #[repr(u32)]
99 enum MeshType {
100 /// Mesh is triangle-based.
101 #[cxx_name = "mt_triangle"]
102 Triangle,
103 /// Mesh is quad-based.
104 #[cxx_name = "mt_quad"]
105 Quad,
106 }
107
108 /// Pixel resolution of a given texture.
109 /// The resolution is stored in log form: ulog2 = log2(ures), vlog2 = log2(vres)).
110 /// Note: negative ulog2 or vlog2 values are reserved for internal use.
111 #[derive(Copy, Clone, Debug)]
112 struct Res {
113 /// log2 of u resolution, in texels
114 ulog2: i8,
115 /// log2 of v resolution, in texels
116 vlog2: i8,
117 }
118
119 /// Information about a face, as stored in the Ptex file header.
120 #[derive(Clone, Copy, Debug)]
121 struct FaceInfo {
122 /// Resolution of face.
123 res: Res,
124 ///< Adjacent edges, 2 bits per edge.
125 adjedges: u8,
126 /// Flags.
127 flags: u8,
128 /// Adjacent faces (-1 == no adjacent face).
129 adjfaces: [u32; 4],
130 }
131
132 unsafe extern "C++" {
133 include!("Ptexture.h");
134 include!("ptex-sys.h");
135
136 /// How to handle mesh border when filtering.
137 type BorderMode;
138
139 /// Type of data stored in texture file.
140 type DataType;
141
142 /// How to handle transformation across edges when filtering.
143 type EdgeFilterMode;
144
145 /// Type of base mesh for which the textures are defined. A mesh
146 /// can be triangle-based (with triangular textures) or quad-based
147 /// (with rectangular textures). */
148 type MeshType;
149
150 /// Type of meta data entry.
151 type MetaDataType;
152
153 /// File-handle and memory cache for reading ptex files.
154 type PtexCache;
155
156 /// Interface for reading data from a ptex file
157 type PtexTexture;
158
159 /// Interface for writing data to a ptex file.
160 type PtexWriter;
161
162 // struct Res
163
164 /// Create a default-constructed Res.
165 #[namespace = "Ptex::sys"]
166 fn res_default() -> Res;
167
168 /// Create a Res from u and v log2 sizes.
169 #[namespace = "Ptex::sys"]
170 fn res_from_uv(u: i8, v: i8) -> Res;
171
172 /// Create a Res from a packed u16 value.
173 #[namespace = "Ptex::sys"]
174 fn res_from_value(value: u16) -> Res;
175
176 /// Return the log2 resolution in the u direction.
177 #[namespace = "Ptex::sys"]
178 fn res_u(res: &Res) -> i32;
179
180 /// Return the log2 resolution in the v direction.
181 #[namespace = "Ptex::sys"]
182 fn res_v(res: &Res) -> i32;
183
184 /// Return the size for a Res object.
185 #[namespace = "Ptex::sys"]
186 fn res_size(res: &Res) -> i32;
187
188 fn val(self: &Res) -> u16;
189
190 /// Return a Res object with swapped u, v values
191 #[namespace = "Ptex::sys"]
192 fn res_swappeduv(res: &Res) -> Res;
193
194 /// Swap the u, v values in-place on a Res.
195 #[namespace = "Ptex::sys"]
196 fn res_swapuv(res: &mut Res);
197
198 /// Clamp the resolution value against the given value.
199 #[namespace = "Ptex::sys"]
200 fn res_clamp(res: &mut Res, clamp_res: &Res);
201
202 /// Determine the number of tiles in the u direction for the given tile res.
203 #[namespace = "Ptex::sys"]
204 fn res_ntilesu(res: &Res, tileres: Res) -> i32;
205
206 /// Determine the number of tiles in the v direction for the given tile res.
207 #[namespace = "Ptex::sys"]
208 fn res_ntilesv(res: &Res, tileres: Res) -> i32;
209
210 /// Determine the total number of tiles for the given tile res.
211 #[namespace = "Ptex::sys"]
212 fn res_ntiles(res: &Res, tileres: Res) -> i32;
213
214 // struct FaceInfo
215
216 /// Create a default-constructed FaceInfo.
217 #[namespace = "Ptex::sys"]
218 fn faceinfo_default() -> FaceInfo;
219
220 /// Create a FaceInfo from a Res.
221 #[namespace = "Ptex::sys"]
222 fn faceinfo_from_res(res: Res) -> FaceInfo;
223
224 /// Create a FaceInfo from a Res and adjacency information.
225 #[namespace = "Ptex::sys"]
226 fn faceinfo_from_res_and_adjacency(
227 res: Res,
228 adjacent_faces: &[i32; 4],
229 adjacent_edges: &[i32; 4],
230 is_subface: bool,
231 ) -> FaceInfo;
232
233 /// Return true if the FaceInfo contains edits.
234 #[namespace = "Ptex::sys"]
235 fn faceinfo_has_edits(face_info: &FaceInfo) -> bool;
236
237 /// Return true if the FaceInfo contains constant data.
238 #[namespace = "Ptex::sys"]
239 fn faceinfo_is_constant(face_info: &FaceInfo) -> bool;
240
241 /// Return true if the FaceInfo is in a neighborhood of constant faces.
242 #[namespace = "Ptex::sys"]
243 fn faceinfo_is_neighborhood_constant(face_info: &FaceInfo) -> bool;
244
245 /// Return true if the FaceInfo is a subface.
246 #[namespace = "Ptex::sys"]
247 fn faceinfo_is_subface(face_info: &FaceInfo) -> bool;
248
249 /// Return the adjacent edge for this face.
250 #[namespace = "Ptex::sys"]
251 fn faceinfo_adjacent_edge(face_info: &FaceInfo, edge_id: i32) -> EdgeId;
252
253 /// Get the adjacent face for the specified face ID.
254 #[namespace = "Ptex::sys"]
255 fn faceinfo_adjacent_face(face_info: &FaceInfo, edge_id: i32) -> i32;
256
257 /// Set the adjacent faces.
258 #[namespace = "Ptex::sys"]
259 fn faceinfo_set_adjacent_faces(
260 face_info: &mut FaceInfo,
261 f1: i32,
262 f2: i32,
263 f3: i32,
264 f4: i32,
265 );
266
267 /// Set the adjacent edges.
268 #[namespace = "Ptex::sys"]
269 fn faceinfo_set_adjacent_edges(
270 face_info: &mut FaceInfo,
271 e1: EdgeId,
272 e2: EdgeId,
273 e3: EdgeId,
274 e4: EdgeId,
275 );
276
277 /// Return the value of "1.0" for the specified DataType (1.0 (float), 255.0 (8bit), ...).
278 #[cxx_name = "OneValue"]
279 fn one_value(data_type: DataType) -> f32;
280
281 /// Return the 1.0/value of "1.0" for the specified DataType (1/1.0 (float), 1/255.0 (8bit), ...).
282 #[cxx_name = "OneValueInv"]
283 fn one_value_inverse(data_type: DataType) -> f32;
284
285 /// Return the size in bytes of the specified DataType.
286 #[cxx_name = "DataSize"]
287 fn data_size(data_type: DataType) -> i32;
288
289 /// Create a cache with the specified limits.
290 /// # Safety
291 /// The value returned must be released using ptexcache_release.
292 #[namespace = "Ptex::sys"]
293 unsafe fn ptexcache_create(
294 max_files: i32,
295 max_mem: usize,
296 premultiply: bool,
297 ) -> *mut PtexCache;
298
299 // class PtexCache
300
301 /// Release a PtexCache
302 /// Cache will be immediately destroyed and all resources will be released.
303 /// # Safety
304 /// This function must be called with a valid PtexCache pointer.
305 #[namespace = "Ptex::sys"]
306 unsafe fn ptexcache_release(cache: *mut PtexCache);
307
308 /// Set a search path for finding textures.
309 /// Parameters:
310 /// - path: colon-delimited search path.
311 /// # Safety
312 /// This function must be called with a valid PtexCache pointer.
313 #[namespace = "Ptex::sys"]
314 unsafe fn ptexcache_set_search_path(cache: *mut PtexCache, path: &str);
315
316 /// Query the search path. Returns string set via `ptexcache_set_search_path`.
317 /// # Safety
318 /// This function must be called with a valid PtexCache pointer.
319 #[namespace = "Ptex::sys"]
320 unsafe fn ptexcache_get_search_path(cache: *const PtexCache) -> String;
321
322 // class PtexTexture
323
324 /// Release a PtexTexture instance.
325 /// # Safety
326 /// This function must be called with a valid PtexTexture pointer.
327 #[namespace = "Ptex::sys"]
328 unsafe fn ptextexture_release(cache: *mut PtexTexture);
329
330 /// Return true if the PtexTexture contains edits.
331 /// # Safety
332 /// This function must be called with a valid PtexTexture pointer.
333 #[namespace = "Ptex::sys"]
334 unsafe fn ptextexture_has_edits(cache: *const PtexTexture) -> bool;
335
336 /// Return true if the PtexTexture has mip maps.
337 /// # Safety
338 /// This function must be called with a valid PtexTexture pointer.
339 #[namespace = "Ptex::sys"]
340 unsafe fn ptextexture_has_mipmaps(cache: *const PtexTexture) -> bool;
341
342 /// Get the alpha channel for the specified PtexTexture.
343 /// # Safety
344 /// This function must be called with a valid PtexTexture pointer.
345 #[namespace = "Ptex::sys"]
346 unsafe fn ptextexture_get_alpha_channel(cache: *const PtexTexture) -> i32;
347
348 /// Get the number of channels for the specified PtexTexture.
349 /// # Safety
350 /// This function must be called with a valid PtexTexture pointer.
351 #[namespace = "Ptex::sys"]
352 unsafe fn ptextexture_get_num_channels(cache: *const PtexTexture) -> i32;
353
354 /// Get the number of faces for the specified PtexTexture.
355 /// # Safety
356 /// This function must be called with a valid PtexTexture pointer.
357 #[namespace = "Ptex::sys"]
358 unsafe fn ptextexture_get_num_faces(cache: *const PtexTexture) -> i32;
359
360 /// Get the path for the specified PtexCache.
361 /// # Safety
362 /// This function must be called with a valid PtexTexture pointer.
363 #[namespace = "Ptex::sys"]
364 unsafe fn ptextexture_get_path(cache: *const PtexTexture) -> String;
365
366 /// Get the MeshType for the specified PtexCache.
367 /// # Safety
368 /// This function must be called with a valid PtexTexture pointer.
369 #[namespace = "Ptex::sys"]
370 unsafe fn ptextexture_get_meshtype(cache: *const PtexTexture) -> MeshType;
371
372 /// Get the DataType for the specified PtexCache.
373 /// # Safety
374 /// This function must be called with a valid PtexTexture pointer.
375 #[namespace = "Ptex::sys"]
376 unsafe fn ptextexture_get_datatype(cache: *const PtexTexture) -> DataType;
377
378 /// Get the BorderMode for the specified PtexCache and direction.
379 /// # Safety
380 /// This function must be called with a valid PtexTexture pointer.
381 #[namespace = "Ptex::sys"]
382 unsafe fn ptextexture_get_border_mode_u(cache: *const PtexTexture) -> BorderMode;
383
384 /// Get the BorderMode for the specified PtexCache and direction.
385 /// # Safety
386 /// This function must be called with a valid PtexTexture pointer.
387 #[namespace = "Ptex::sys"]
388 unsafe fn ptextexture_get_border_mode_v(cache: *const PtexTexture) -> BorderMode;
389
390 /// Get the EdgeFilterMode for the specified PtexCache.
391 /// # Safety
392 /// This function must be called with a valid PtexTexture pointer.
393 #[namespace = "Ptex::sys"]
394 unsafe fn ptextexture_get_edge_filter_mode(cache: *const PtexTexture) -> EdgeFilterMode;
395
396 /// Get the FaceInfo for the specified PtexTexture and faceid.
397 /// # Safety
398 /// This function must be called with a valid PtexTexture pointer.
399 #[namespace = "Ptex::sys"]
400 unsafe fn ptextexture_get_face_info<'a>(
401 cache: *const PtexTexture,
402 faceid: i32,
403 ) -> &'a FaceInfo;
404
405 /// Get the pixel value for the specified PtexCache.
406 /// # Safety
407 /// This function must be called with a valid PtexTexture pointer.
408 #[namespace = "Ptex::sys"]
409 unsafe fn ptextexture_get_pixel(
410 cache: *const PtexTexture,
411 faceid: i32,
412 u: i32,
413 v: i32,
414 first_channel: i32,
415 num_channels: i32,
416 ) -> f32;
417
418 /// Access a texture. If the specified path was previously accessed
419 /// from the cache, then a pointer to the cached texture will be
420 /// returned.
421 ///
422 /// If the specified path hasn't been opened yet or was purged
423 /// from the cache (via the purge or purgeAll methods) then the
424 /// file will be opened. If the path is relative (i.e. doesn't
425 /// begin with a '/') then the search path will be used to locate
426 /// the file.
427 ///
428 /// The texture will be accessible until the PtexTexture::release
429 /// method is called, at which point the texture will be returned
430 /// to the cache. Once released, the texture may have it's data
431 /// pruned (immediately or some time later) to stay within the
432 /// maximum cache size.
433 ///
434 /// If the texture could not be opened, null will be returned and
435 /// an error string will be set. If an error were previously
436 /// encountered with the file (include the file not being found),
437 /// null will be returned and no error string will be set.
438 ///
439 /// Parameters:
440 /// - filename: File path. If path is relative, search path will
441 /// be used to find the file.
442 /// - error_str: Error string to set if texture could not be opened.
443 ///
444 /// # Safety
445 /// The Texture must not outlive its owning Cache.
446 #[namespace = "Ptex::sys"]
447 unsafe fn ptexcache_get(
448 cache: *mut PtexCache,
449 filename: &str,
450 error_str: *mut CxxString,
451 ) -> *mut PtexTexture;
452
453 /// Create a PtexWriter.
454 ///
455 /// # Safety
456 /// Should not be called outside of the ptex::ffi::sys crate.
457 #[allow(clippy::too_many_arguments)]
458 #[namespace = "Ptex::sys"]
459 unsafe fn ptexwriter_open(
460 filename: &str,
461 meshtype: MeshType,
462 datatype: DataType,
463 num_channels: i32,
464 alpha_channel: i32,
465 num_faces: i32,
466 genmipmaps: bool,
467 error_str: *mut CxxString,
468 ) -> *mut PtexWriter;
469
470 /// Release a PtexWriter.
471 ///
472 /// # Safety
473 /// Must only be called on pointers returned from ptexwriter_open().
474 #[namespace = "Ptex::sys"]
475 unsafe fn ptexwriter_release(writer: *mut PtexWriter);
476
477 /// Close an open PtexWriter.
478 ///
479 /// # Safety
480 /// Must only be called on valid PtexWriter pointers.
481 #[namespace = "Ptex::sys"]
482 unsafe fn ptexwriter_close(writer: *mut PtexWriter) -> String;
483
484 /// Writer a face to a PtexWriter
485 ///
486 /// # Safety
487 /// Must only be called on valid PtexWriter pointers.
488 #[namespace = "Ptex::sys"]
489 unsafe fn ptexwriter_write_face(
490 writer: *mut PtexWriter,
491 face_id: i32,
492 face_info: &FaceInfo,
493 data: *const u8,
494 stride: i32,
495 ) -> bool;
496 }
497}
498
499impl Default for Res {
500 /// Default constructor, sets res to 0 (1x1 texel).
501 fn default() -> Self {
502 ffi::res_default()
503 }
504}
505
506impl Eq for Res {}
507
508impl PartialEq for Res {
509 fn eq(&self, res: &ffi::Res) -> bool {
510 self.ulog2 == res.ulog2 && self.vlog2 == res.vlog2
511 }
512}
513
514impl Res {
515 /// Return the log2 resolution in the u direction.
516 pub fn u(&self) -> i32 {
517 ffi::res_u(self)
518 }
519
520 /// Return the log2 resolution in the v direction.
521 pub fn v(&self) -> i32 {
522 ffi::res_v(self)
523 }
524
525 /// Return the size of the FaceInfo.
526 pub fn size(&self) -> i32 {
527 ffi::res_size(self)
528 }
529
530 /// Return a Res instance with swapped u, v values.
531 pub fn swapped_uv(&self) -> i32 {
532 ffi::res_size(self)
533 }
534}
535
536impl Default for FaceInfo {
537 fn default() -> Self {
538 ffi::faceinfo_default()
539 }
540}
541
542impl FaceInfo {
543 pub fn from_res_and_adjacency<T: Into<Res>>(
544 res: T,
545 adjacent_faces: &[i32; 4],
546 adjacent_edges: &[i32; 4],
547 is_subface: bool,
548 ) -> Self {
549 ffi::faceinfo_from_res_and_adjacency(res.into(), adjacent_faces, adjacent_edges, is_subface)
550 }
551
552 /// Return a Res resolution struct.
553 pub fn resolution(&self) -> Res {
554 self.res
555 }
556
557 /// Set the resolution for this face.
558 pub fn set_resolution<T: Into<Res>>(&mut self, res: T) {
559 self.res = res.into();
560 }
561
562 /// Return the adjacent edge for this face.
563 pub fn adjacent_edge(&self, edge_id: i32) -> EdgeId {
564 ffi::faceinfo_adjacent_edge(self, edge_id)
565 }
566
567 /// Set the adjacent edges.
568 pub fn set_adjacent_edges(&mut self, e1: EdgeId, e2: EdgeId, e3: EdgeId, e4: EdgeId) {
569 ffi::faceinfo_set_adjacent_edges(self, e1, e2, e3, e4);
570 }
571
572 /// Get the adjacent face for the specified face ID.
573 pub fn adjacent_face(&self, face_id: i32) -> i32 {
574 ffi::faceinfo_adjacent_face(self, face_id)
575 }
576
577 /// Set the adjacent faces.
578 pub fn set_adjacent_faces(&mut self, f1: i32, f2: i32, f3: i32, f4: i32) {
579 ffi::faceinfo_set_adjacent_faces(self, f1, f2, f3, f4);
580 }
581
582 /// Return true if the FaceInfo contains edits.
583 pub fn has_edits(&self) -> bool {
584 ffi::faceinfo_has_edits(self)
585 }
586
587 /// Return true if the FaceInfo contains constant data.
588 pub fn is_constant(&self) -> bool {
589 ffi::faceinfo_is_constant(self)
590 }
591
592 /// Return true if the FaceInfo is in a neighborhood of constant faces.
593 pub fn is_neighborhood_constant(&self) -> bool {
594 ffi::faceinfo_is_neighborhood_constant(self)
595 }
596
597 /// Return true if the FaceInfo represents a subface.
598 pub fn is_subface(&self) -> bool {
599 ffi::faceinfo_is_subface(self)
600 }
601}
602
603pub use ffi::*;