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> {}