|
- use std::mem::swap;
- use std::rc::Rc;
-
- use glc::{
- buffer::Buffer,
- misc::BindGuard,
- transform_feedback::TransformFeedback,
- vertex_array::{BindingBuilder, DataType, Pointer, VertexArray},
- };
- use space_crush_common::return_if_none;
-
- use crate::Error;
-
- type VertexArrayBuilder = BindingBuilder<Rc<Buffer>>;
-
- /* Particles */
-
- pub struct Particles {
- input: Buffers,
- output: Buffers,
- }
-
- impl Particles {
- pub fn builder() -> Builder {
- Builder::default()
- }
-
- pub fn update(&mut self) {
- let update_array = return_if_none!(&self.input.update_array);
-
- gl::enable(gl::RASTERIZER_DISCARD);
-
- let guard_buffer = BindGuard::new(update_array);
- let guard_transform_feedback = BindGuard::new(&self.output.transform_feedback);
-
- gl::begin_transform_feedback(gl::POINTS);
-
- // TODO gl::draw_arrays(mode, 0, count as _);
-
- gl::end_transform_feedback();
-
- gl::disable(gl::RASTERIZER_DISCARD);
-
- drop(guard_buffer);
- drop(guard_transform_feedback);
-
- swap(&mut self.input, &mut self.output);
- }
- }
-
- /* Buffer */
-
- struct Buffers {
- transform_feedback: TransformFeedback<Rc<Buffer>>,
- update_array: Option<VertexArray<Rc<Buffer>>>,
- render_array: Option<VertexArray<Rc<Buffer>>>,
- }
-
- impl Buffers {
- fn from_builder(builder: &Builder) -> Result<Self, Error> {
- let mut transform_feedback = TransformFeedback::builder();
- let mut update_array: Option<VertexArrayBuilder> = None;
- let mut render_array: Option<VertexArrayBuilder> = None;
-
- let mut index = 0;
- for b in &builder.buffers {
- if b.render_pointers.is_empty() && b.update_pointers.is_empty() {
- continue;
- }
-
- let buffer = Rc::new(Buffer::new()?);
- transform_feedback = transform_feedback.bind_buffer(index, buffer.clone())?;
- update_array = update_vertex_array(update_array, &buffer, &b.update_pointers)?;
- render_array = update_vertex_array(render_array, &buffer, &b.render_pointers)?;
-
- index += 1;
- }
-
- let transform_feedback = transform_feedback.build()?;
- let update_array = match update_array {
- Some(update_array) => Some(update_array.build()?),
- None => None,
- };
- let render_array = match render_array {
- Some(render_array) => Some(render_array.build()?),
- None => None,
- };
-
- Ok(Self {
- transform_feedback,
- update_array,
- render_array,
- })
- }
- }
-
- fn update_vertex_array(
- mut builder: Option<VertexArrayBuilder>,
- buffer: &Rc<Buffer>,
- pointers: &[Pointer],
- ) -> Result<Option<VertexArrayBuilder>, Error> {
- if !pointers.is_empty() {
- builder = match builder {
- Some(builder) => Some(builder.bind_buffer(buffer.clone())),
- None => Some(VertexArray::builder().bind_buffer(buffer.clone())),
- };
-
- for p in pointers {
- builder = Some(builder.unwrap().vertex_attrib_pointer(
- p.index,
- p.size,
- p.type_,
- p.normalize,
- p.stride,
- p.offset,
- )?);
- }
- }
-
- Ok(builder)
- }
-
- /* Builder */
-
- #[derive(Default)]
- pub struct Builder {
- buffers: Vec<BufferData>,
- }
-
- impl Builder {
- pub fn add_buffer(mut self) -> BufferBuilder {
- self.buffers.push(BufferData::default());
-
- BufferBuilder { builder: self }
- }
-
- fn build(self) -> Result<Particles, Error> {
- let input = Buffers::from_builder(&self)?;
- let output = Buffers::from_builder(&self)?;
-
- Ok(Particles { input, output })
- }
- }
-
- /* BufferBuilder */
-
- #[derive(Default)]
- pub struct BufferBuilder {
- builder: Builder,
- }
-
- impl BufferBuilder {
- pub fn add_buffer(self) -> BufferBuilder {
- self.builder.add_buffer()
- }
-
- pub fn update_attrib_pointer(
- mut self,
- index: gl::GLuint,
- size: gl::GLint,
- type_: DataType,
- normalize: bool,
- stride: gl::GLsizei,
- offset: gl::GLsizei,
- ) -> Result<Self, Error> {
- self.builder
- .buffers
- .last_mut()
- .unwrap()
- .update_pointers
- .push(Pointer {
- index,
- size,
- type_,
- normalize,
- stride,
- offset,
- divisor: None,
- });
-
- Ok(self)
- }
-
- pub fn render_attrib_pointer(
- mut self,
- index: gl::GLuint,
- size: gl::GLint,
- type_: DataType,
- normalize: bool,
- stride: gl::GLsizei,
- offset: gl::GLsizei,
- ) -> Result<Self, Error> {
- self.builder
- .buffers
- .last_mut()
- .unwrap()
- .render_pointers
- .push(Pointer {
- index,
- size,
- type_,
- normalize,
- stride,
- offset,
- divisor: None,
- });
-
- Ok(self)
- }
-
- pub fn build(self) -> Result<Particles, Error> {
- self.builder.build()
- }
- }
-
- /* BufferData */
-
- #[derive(Default)]
- struct BufferData {
- update_pointers: Vec<Pointer>,
- render_pointers: Vec<Pointer>,
- }
|