mod3d_base/
buffer_data.rs

1//a Imports
2use std::cell::RefCell;
3
4use crate::{ByteBuffer, Renderable};
5
6//a BufferData
7//tp BufferData
8/// A data buffer for use with vertex data. It may be indices
9/// or vertex coordinates etc.
10///
11/// A data buffer may contain a lot of data per vertex, such as
12/// position, normal, tangent, color etc.  a `BufferView` on the data is
13/// then a subset of this data - perhaps picking out just the
14/// position, for example, for a set of vertices
15///
16/// The data buffer may, indeed, contain data for more than one object
17/// - and the objects may have different data per vertex. The data
18/// buffer is pretty free-form, it is a `BufferView` on the [BufferData] which
19/// identifies the object it applies to, and the vertex attributes
20/// required.
21///
22/// A data buffer may then be used by many `BufferView`s. Each `BufferView` may be
23/// used by many primitives for a single model; alternatively,
24/// primitives may have their own individual `BufferViews`.
25///
26/// A client may have one copy of the data for all the primitives and models.
27pub struct BufferData<'a, R: Renderable> {
28    /// Data buffer itself
29    data: &'a [u8],
30    /// Offset in to the data buffer for the first byte
31    pub byte_offset: u32,
32    /// Length of data used in the buffer
33    pub byte_length: u32,
34    /// The client bound to data\[byte_offset\] .. + byte_length
35    ///
36    /// This must be held as a [RefCell] as the [BufferData] is
37    /// created early in the process, prior to any `BufferView`s using
38    /// it - which then have shared references to the data - but the
39    /// client is created afterwards
40    rc_client: RefCell<R::Buffer>,
41}
42
43//ip Debug for BufferData
44impl<'a, R: Renderable> std::fmt::Debug for BufferData<'a, R> {
45    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
46        let (data, cont) = {
47            if self.data.len() < 8 {
48                (self.data, "")
49            } else {
50                (&self.data[0..8], "...")
51            }
52        };
53        write!(
54            fmt,
55            "BufferData {{{0:?}{cont}#{4}, byte_offset:{1}, byte_length:{2}, client:{3:?}}}",
56            data,
57            self.byte_offset,
58            self.byte_length,
59            self.rc_client,
60            self.data.len(),
61        )
62    }
63}
64
65//ip BufferData
66impl<'a, R: Renderable> BufferData<'a, R> {
67    //fp new
68    /// Create a new [BufferData] given a buffer, offset and length; if the
69    /// length is zero then the whole of the data buffer post offset
70    /// is used
71    ///
72    /// If offset and length are both zero, then all the data is used
73    pub fn new<B: ByteBuffer + ?Sized>(data: &'a B, byte_offset: u32, byte_length: u32) -> Self {
74        let byte_length = {
75            if byte_length == 0 {
76                (data.byte_length() as u32) - byte_offset
77            } else {
78                byte_length
79            }
80        };
81        let rc_client = RefCell::new(R::Buffer::default());
82        let data = data.borrow_bytes();
83        assert!(
84            byte_offset + byte_length <= data.len() as u32,
85            "Buffer is not large enough for data {} + #{} [ got {}]",
86            byte_offset,
87            byte_length,
88            data.len()
89        );
90        Self {
91            data,
92            byte_offset,
93            byte_length,
94            rc_client,
95        }
96    }
97
98    //mp create_client
99    /// Replace the client data with one of this data
100    pub fn create_client(&self, renderable: &mut R) {
101        use std::ops::DerefMut;
102        renderable.init_buffer_data_client(self.rc_client.borrow_mut().deref_mut(), self);
103    }
104
105    //ap borrow_client
106    /// Borrow the client
107    pub fn borrow_client(&self) -> std::cell::Ref<R::Buffer> {
108        self.rc_client.borrow()
109    }
110
111    //mp as_ptr
112    /// Get a const u8 ptr to the data itself
113    pub fn as_ptr(&self) -> *const u8 {
114        unsafe { self.data.as_ptr().add(self.byte_offset as usize) }
115    }
116
117    //mp as_slice
118    /// Get the slice that is the data itself
119    pub fn as_slice(&self) -> &[u8] {
120        let start = self.byte_offset as usize;
121        let end = (self.byte_offset + self.byte_length) as usize;
122        self.data.get(start..end).unwrap()
123    }
124
125    //zz All done
126}
127
128//ip Display for BufferData
129impl<'a, R: Renderable + ?Sized> std::fmt::Display for BufferData<'a, R> {
130    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
131        let data_ptr = self.data.as_ptr();
132        write!(
133            f,
134            "BufferData[{:?}+{}#{}]:GL({})",
135            data_ptr,
136            self.byte_offset,
137            self.byte_length,
138            self.rc_client.borrow()
139        )
140    }
141}
142
143//ip DefaultIndentedDisplay for BufferData
144impl<'a, R: Renderable + ?Sized> indent_display::DefaultIndentedDisplay for BufferData<'a, R> {}