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::*;