1extern crate pretty_env_logger;
2extern crate gl;
3
4use std::collections::HashMap;
5use std::vec::Vec;
6
7use interface::i_renderobj;
8use implement::render::util_gl;
9
10#[derive(Debug)]
11#[derive(Clone)]
12#[derive(Copy)]
13pub struct BufferFormat {
14 pub _buff_data_type: i_renderobj::BuffDataType,
15 pub _index: u64,
16 pub _num_data: u64,
17 pub _stride_bytes: u64,
18 pub _offset_bytes: u64,
19}
20
21#[derive(Debug)]
23pub struct RenderDrawGroup {
24 pub _group_handle: u64,pub _buffer_handle: u64, pub _buffer_draw: Vec< f32 >,
27 pub _format: Vec< BufferFormat >,
28 pub _stride: u64,
29 pub _primitive_type: i_renderobj::RenderObjType,
30}
31
32impl RenderDrawGroup {
33 pub fn init( internal_group_handle: u64, buffer_handle: u64, format: Vec< BufferFormat >, stride: u64, primitive_type: i_renderobj::RenderObjType ) -> RenderDrawGroup {
34 RenderDrawGroup {
35 _group_handle: internal_group_handle,
36 _buffer_handle: buffer_handle,
37 _buffer_draw: vec![],
38 _format: format,
39 _stride: stride,
40 _primitive_type: primitive_type,
41 }
42 }
43 pub fn init_with_default_format_triangle( internal_group_handle: u64, buffer_handle: u64 ) -> RenderDrawGroup {
44 let stride = 8 * ::std::mem::size_of::<f32>();
45 let format = vec![ BufferFormat { _buff_data_type: i_renderobj::BuffDataType::POS, _index: 0, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: 0 },
46 BufferFormat { _buff_data_type: i_renderobj::BuffDataType::NORMAL, _index: 1, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: (3 * ::std::mem::size_of::<f32>()) as _ },
47 BufferFormat { _buff_data_type: i_renderobj::BuffDataType::TC, _index: 2, _num_data: 2, _stride_bytes: stride as _, _offset_bytes: (6 * ::std::mem::size_of::<f32>()) as _ },
48 ];
49 RenderDrawGroup {
50 _group_handle: internal_group_handle,
51 _buffer_handle: buffer_handle,
52 _buffer_draw: vec![],
53 _format: format,
54 _stride: stride as _,
55 _primitive_type: i_renderobj::RenderObjType::TRI,
56 }
58 }
59 pub fn init_with_default_format_point( internal_group_handle: u64, buffer_handle: u64 ) -> RenderDrawGroup {
60 let stride = 8 * ::std::mem::size_of::<f32>();
62 let format = vec![ BufferFormat { _buff_data_type: i_renderobj::BuffDataType::POS, _index: 0, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: 0 },
63 BufferFormat { _buff_data_type: i_renderobj::BuffDataType::NORMAL, _index: 1, _num_data: 3, _stride_bytes: stride as _, _offset_bytes: (3 * ::std::mem::size_of::<f32>()) as _ },
64 BufferFormat { _buff_data_type: i_renderobj::BuffDataType::TC, _index: 2, _num_data: 2, _stride_bytes: stride as _, _offset_bytes: (6 * ::std::mem::size_of::<f32>()) as _ },
65 ];
66 RenderDrawGroup {
67 _group_handle: internal_group_handle,
68 _buffer_handle: buffer_handle,
69 _buffer_draw: vec![],
70 _format: format,
71 _stride: stride as _,
72 _primitive_type: i_renderobj::RenderObjType::POINT,
73 }
74 }
75}
76
77impl i_renderobj::RenderDevice for RenderDrawGroup{
78 fn bind_buffer( & mut self ) -> Result< (), & 'static str > {
79 let data_len = self._buffer_draw.len() * ::std::mem::size_of::<f32>();
80 unsafe {
81 gl::BindVertexArray( self._group_handle as _ );
82 gl::BindBuffer( gl::ARRAY_BUFFER, self._buffer_handle as _ );
83 gl::BufferData( gl::ARRAY_BUFFER, data_len as isize, self._buffer_draw.as_ptr() as _, gl::STATIC_DRAW );
84 util_gl::check_last_op();
85
86 for &i in self._format.iter() {
87 gl::VertexAttribPointer( i._index as _, i._num_data as _, gl::FLOAT, gl::FALSE, i._stride_bytes as i32, i._offset_bytes as _ );
88 gl::EnableVertexAttribArray( i._index as _ );
89 util_gl::check_last_op();
90 }
91 gl::BindBuffer( gl::ARRAY_BUFFER, 0 );
92 gl::BindVertexArray( 0 );
93 }
94 Ok( () )
95 }
96 fn draw_buffer_all( & mut self) -> Result< (), & 'static str > {
97 unsafe {
98 gl::BindVertexArray( self._group_handle as _ );
99 let num_elements = self._buffer_draw.len() / (self._stride as usize / ::std::mem::size_of::<f32>());
100 match self._primitive_type {
101 i_renderobj::RenderObjType::TRI => {
102 trace!("draw buffer all: num verts: {}", num_elements );
103 gl::DrawArrays(gl::TRIANGLES, 0, num_elements as _ );
104 },
105 i_renderobj::RenderObjType::POINT => {
106 trace!("draw buffer all: num points: {}", num_elements );
107 gl::PointSize(3f32);
109 gl::DrawArrays(gl::POINTS, 0, num_elements as _ );
110 },
111 _=> return Err( "unsupported primite type for drawing detected" )
112 }
113 gl::BindVertexArray( 0 );
114 }
115 Ok( () )
116 }
117 fn draw_buffer_range( & mut self) -> Result< (), & 'static str > {
118 unimplemented!();
119 }
120 fn clear_buff_data( & mut self ){
121 self._buffer_draw.clear();
122 }
123 fn store_buff_data( & mut self, data: & HashMap< i_renderobj::BuffDataType, Vec< f32 > > ) -> Result< (), & 'static str > {
124 let mut data_pos : Vec< f32 > = vec![];
125 let mut data_normal : Vec< f32 > = vec![];
126 let mut data_tc : Vec< f32 > = vec![];
127 for i in self._format.iter() {
128 match i._buff_data_type {
129 i_renderobj::BuffDataType::POS => {
130 match data.get( &i_renderobj::BuffDataType::POS ) {
131 None => return Err( "render buffer data expected data not found: pos" ),
132 Some( ref pos ) => {
133 data_pos.extend_from_slice( &pos[..] );
134 }
135 }
136 },
137 i_renderobj::BuffDataType::NORMAL => {
138 match data.get( &i_renderobj::BuffDataType::NORMAL ) {
139 None => return Err( "render buffer data expected data not found: normal" ),
140 Some( ref normal ) => {
141 data_normal.extend_from_slice( &normal[..] );
142 }
143 }
144 },
145 i_renderobj::BuffDataType::TC => {
146 match data.get( &i_renderobj::BuffDataType::TC ) {
147 None => return Err( "render buffer data expected data not found: tc" ),
148 Some( ref tc ) => {
149 data_tc.extend_from_slice( &tc[..] );
150 }
151 }
152 },
153 }
154 }
155 match self._primitive_type {
156 i_renderobj::RenderObjType::TRI => {
157 if data_pos.len() != data_normal.len() {
158 return Err( "render buffer data length not equal" )
159 }
160 if data_pos.len() % 3 != 0 {
161 return Err( "render buffer data length not divisible by 3" )
162 }
163 if data_tc.len() % 2 != 0 {
164 return Err( "render buffer data length not divisible by 2" )
165 }
166 let count_data = data_pos.len() / 3;
167 if count_data != data_tc.len() / 2 {
168 return Err( "render buffer data length not equal" )
169 }
170 for i in 0..count_data {
171 self._buffer_draw.push( data_pos[i*3] );
172 self._buffer_draw.push( data_pos[i*3+1] );
173 self._buffer_draw.push( data_pos[i*3+2] );
174
175 self._buffer_draw.push( data_normal[i*3] );
176 self._buffer_draw.push( data_normal[i*3+1] );
177 self._buffer_draw.push( data_normal[i*3+2] );
178
179 self._buffer_draw.push( data_tc[i*2] );
180 self._buffer_draw.push( data_tc[i*2+1] );
181 }
182 },
183 i_renderobj::RenderObjType::POINT => {
184 if data_pos.len() != data_normal.len() {
186 return Err( "render buffer data length not equal" )
187 }
188 if data_pos.len() % 3 != 0 {
189 return Err( "render buffer data length not divisible by 3" )
190 }
191 if data_tc.len() % 2 != 0 {
192 return Err( "render buffer data length not divisible by 2" )
193 }
194 let count_data = data_pos.len() / 3;
195 if count_data != data_tc.len() / 2 {
196 return Err( "render buffer data length not equal" )
197 }
198 for i in 0..count_data {
199 self._buffer_draw.push( data_pos[i*3] );
200 self._buffer_draw.push( data_pos[i*3+1] );
201 self._buffer_draw.push( data_pos[i*3+2] );
202
203 self._buffer_draw.push( data_normal[i*3] );
204 self._buffer_draw.push( data_normal[i*3+1] );
205 self._buffer_draw.push( data_normal[i*3+2] );
206
207 self._buffer_draw.push( data_tc[i*2] );
208 self._buffer_draw.push( data_tc[i*2+1] );
209 }
210 },
211 i_renderobj::RenderObjType::LINE => {
212 },
214 _ => { unimplemented!(); }
215 }
216 Ok( () )
217 }
218}
219
220#[derive(Debug)]
221#[derive(Clone)]
222#[derive(Copy)]
223pub enum UniformType {
224 VEC,
225 MAT4,
226 MAT4X1,
227 MAT4X2,
228 MAT4X3,
229 MAT3,
230 MAT3X1,
231 MAT3X2,
232 MAT2,
233 MAT2X1,
234}
235
236pub struct RenderUniformCollection {
239 pub _uniforms_f: HashMap< (u64, String), ( UniformType, Vec<f32> ) >,
241 pub _uniforms_groups: HashMap< u64, (u64, Vec<String>) >,
243}
244
245impl Default for RenderUniformCollection {
246 fn default() -> RenderUniformCollection {
247 RenderUniformCollection {
248 _uniforms_f: HashMap::new(),
249 _uniforms_groups: HashMap::new(),
250 }
251 }
252}
253
254impl RenderUniformCollection {
255 pub fn set_uniform_f( & mut self, shader_program: u64, name: &str, val_type: UniformType, vals: &[f32] ) {
257 self._uniforms_f.insert( (shader_program, String::from( name ) ), ( val_type, vals.to_vec() ) );
258 }
259 pub fn set_group( & mut self, shader_program: u64, group_id: u64, names: Vec< String > ) -> Result< (), & 'static str > {
261 for i in names.iter() {
262 match self._uniforms_f.get( &( shader_program, i.clone() ) ) {
263 None => return Err( &"unfound uniform name" ),
264 _ => (),
265 }
266 }
267 self._uniforms_groups.insert( group_id, ( shader_program, names ) );
268 Ok( () )
269 }
270 pub fn get_group( & self, group_id: u64 ) -> Result< Vec< (String, UniformType, Vec<f32> )>, & 'static str > {
271 let mut ret = vec![];
272 match self._uniforms_groups.get( &group_id ) {
273 None => return Err( &"unfound uniform group id" ),
274 Some( &( ref program, ref v ) ) => {
275 for name in v.iter() {
276 match self._uniforms_f.get( &( *program, name.clone()) ) {
277 None => return Err( &"unfound uniform name" ),
278 Some( &( ref uniform_type , ref vals) ) => {
279 ret.push( ( name.clone(), uniform_type.clone(), vals.clone() ) );
280 }
281 }
282 }
283 }
284 }
285 Ok( ret )
286 }
287 pub fn send_uniform_group( & self, group_id: u64 ) -> Result< (), & 'static str > {
289 match self._uniforms_groups.get( &group_id ) {
290 None => return Err( &"unfound uniform group id" ),
291 Some( &( ref program, ref v ) ) => {
292 for name in v.iter() {
293 match self._uniforms_f.get( &( *program, name.clone()) ) {
294 None => return Err( &"unfound uniform name" ),
295 Some( &( ref uniform_type , ref vals) ) => {
296 match *uniform_type {
297 UniformType::VEC => {
298 unsafe {
299 match vals.len() {
300 1 => gl::Uniform1f( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), vals[0] ),
301 2 => gl::Uniform2fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, vals.as_ptr() as _ ),
302 3 => gl::Uniform3fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, vals.as_ptr() as _ ),
303 4 => gl::Uniform4fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, vals.as_ptr() as _ ),
304 _ => return Err( &"unsupported uniform data length" ),
305 }
306 }
307 },
308 UniformType::MAT4 => {
309 if vals.len() != 16 {
310 return Err( &"unmatched uniform length for MAT4" )
311 }
312 unsafe {
313 gl::UniformMatrix4fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, gl::TRUE, vals.as_ptr() as _ );
315 }
316 },
317 UniformType::MAT3 => {
318 if vals.len() != 9 {
319 return Err( &"unmatched uniform length for MAT3" )
320 }
321 unsafe {
322 gl::UniformMatrix3fv( gl::GetUniformLocation( *program as _, name.as_ptr() as * const i8 ), 1, gl::TRUE, vals.as_ptr() as _ );
324 }
325 },
326 _ => { unimplemented!(); },
327 }
328 }
329 }
330 }
331 }
332 }
333 Ok( () )
334 }
335}