use super::{
FrameIDType,
ObjectIDType,
ElementIndexType,
frame_size,
SimpleVertex2D,
HeapObject,
StackObject,
ObjectAllocation,
DrawParameters,
HeapDrawType,
StackDrawType,
};
use cat_engine_basement::graphics::{
GCore,
core::{
drawing::PrimitiveType,
buffer::BufferUsage,
},
level0::VertexArray,
level1::{
VertexBuffer,
IndexBuffer,
VertexShader,
FragmentShader
},
level2::Program,
};
pub struct SimpleGraphics{
vertex_buffer:VertexBuffer<SimpleVertex2D>,
index_buffer:IndexBuffer<ElementIndexType>,
vertex_array:VertexArray<SimpleVertex2D>,
object_allocation:ObjectAllocation<SimpleVertex2D>,
draw:Program,
}
impl SimpleGraphics{
pub fn new(
stack_vertices:ElementIndexType,
stack_indices:i32,
stack_objects:ObjectIDType,
heap_vertex_frames:FrameIDType,
heap_index_frames:FrameIDType,
heap_objects:ObjectIDType
)->SimpleGraphics{
let vertex_shader=VertexShader::new(&include_str!("shaders/simple/vertex_shader.glsl")).unwrap();
let fragment_shader=FragmentShader::new(&include_str!("shaders/simple/fragment_shader.glsl")).unwrap();
let program=Program::new(&vertex_shader,&fragment_shader).unwrap();
program.bind_uniform_block("DrawParameters",0u32);
let heap_vertex_buffer_size=heap_vertex_frames as ElementIndexType*frame_size as ElementIndexType;
let heap_index_buffer_size=heap_index_frames as ElementIndexType*frame_size as ElementIndexType;
let vertex_buffer_size=heap_vertex_buffer_size+stack_vertices;
let index_buffer_size=heap_index_buffer_size+stack_indices as ElementIndexType;
let vertex_buffer=VertexBuffer::empty(vertex_buffer_size as isize,BufferUsage::DynamicDraw);
let index_buffer=IndexBuffer::empty(index_buffer_size as isize,BufferUsage::DynamicDraw);
let vertex_array=VertexArray::new(vertex_buffer.raw());
Self{
vertex_buffer,
index_buffer,
vertex_array,
object_allocation:ObjectAllocation::new(
stack_vertices,
stack_indices,
stack_objects,
heap_vertex_frames,
heap_index_frames,
heap_objects,
),
draw:program,
}
}
}
impl SimpleGraphics{
pub fn add_object_raw(
&mut self,
vertices:&[SimpleVertex2D],
indices:&[ElementIndexType],
primitive_type:PrimitiveType
)->Option<ObjectIDType>{
self.object_allocation.heap_system.add_object(
&self.vertex_buffer,
&self.index_buffer,
vertices,
indices,
primitive_type
)
}
pub fn remove_object(&mut self,index:ObjectIDType){
self.object_allocation.heap_system.remove_object(index)
}
pub fn get_heap_object(&self,id:ObjectIDType)->Option<&HeapObject>{
self.object_allocation.heap_system.get_object(id)
}
pub fn write_heap_object_vertices(&mut self,id:ObjectIDType,vertices:&[SimpleVertex2D]){
self.object_allocation.heap_system.write_object_vertices(&self.vertex_buffer,id,vertices)
}
pub fn write_heap_object_indices(&mut self,id:ObjectIDType,indices:&[ElementIndexType]){
self.object_allocation.heap_system.write_object_indices(&self.index_buffer,id,indices)
}
pub fn draw_heap_object(&self,index:ObjectIDType,draw_parameters:&DrawParameters){
if let Some(object)=self.object_allocation.heap_system.get_drawable_object(index){
self.draw.bind();
self.vertex_array.bind();
self.index_buffer.bind();
self.vertex_buffer.bind();
let _=self.draw.set_uniform_value("viewport",draw_parameters.viewport());
let _=self.draw.set_uniform_value("draw_mode",draw_parameters.flag());
if let Some(shift)=draw_parameters.shift(){
let _=self.draw.set_uniform_value("vertex_shift",shift);
}
if let Some(rotation)=draw_parameters.rotation(){
let _=self.draw.set_uniform_value("vertex_rotation",rotation);
}
match object.draw_type{
HeapDrawType::Vertices(first)=>unsafe{
GCore.drawing.multi_draw_arrays(&first,&object.count,object.primitive_type)
}
HeapDrawType::Indices(indices)=>unsafe{
GCore.drawing.multi_draw_elements_typed::<ElementIndexType>(
&indices,
&object.count,
object.primitive_type
)
}
}
self.vertex_array.unbind();
}
}
}
impl SimpleGraphics{
pub fn push_object_raw(
&mut self,
vertices:&[SimpleVertex2D],
indices:&[ElementIndexType],
primitive_type:PrimitiveType
)->Option<ObjectIDType>{
self.object_allocation.stack_system.push_object_raw(
&self.vertex_buffer,
&self.index_buffer,
vertices,
indices,
primitive_type
)
}
pub fn get_stack_object(&self,id:ObjectIDType)->Option<&StackObject>{
self.object_allocation.stack_system.get_object(id)
}
pub fn pop_object(&mut self){
self.object_allocation.stack_system.pop_object()
}
pub fn clear_stack(&mut self){
self.object_allocation.stack_system.clear()
}
pub fn write_stack_object_vertices(&mut self,id:ObjectIDType,vertices:&[SimpleVertex2D]){
self.object_allocation.stack_system.write_object_vertices(&self.vertex_buffer,id,vertices)
}
pub fn write_stack_object_indices(&mut self,id:ObjectIDType,indices:&[ElementIndexType]){
self.object_allocation.stack_system.write_object_indices(&self.index_buffer,id,indices)
}
pub fn draw_stack_object(&self,index:ObjectIDType,draw_parameters:&DrawParameters){
if let Some(object)=&self.object_allocation.stack_system.get_drawable_object(index){
self.draw.bind();
self.vertex_array.bind();
self.vertex_buffer.bind();
self.index_buffer.bind();
let _=self.draw.set_uniform_value("viewport",draw_parameters.viewport());
let _=self.draw.set_uniform_value("draw_mode",draw_parameters.flag());
if let Some(shift)=draw_parameters.shift(){
let _=self.draw.set_uniform_value("vertex_shift",shift);
}
if let Some(rotation)=draw_parameters.rotation(){
let _=self.draw.set_uniform_value("vertex_rotation",rotation);
}
match object.draw_type{
StackDrawType::Vertices(first)=>unsafe{
GCore.drawing.draw_arrays(first,object.count,object.primitive_type)
}
StackDrawType::Indices(first)=>unsafe{
GCore.drawing.draw_elements_typed::<ElementIndexType>(
first,
object.count,
object.primitive_type
)
}
}
self.vertex_array.unbind();
}
}
}