initial commit of headless i guess

This commit is contained in:
askiiart 2024-11-12 18:19:38 -06:00
parent ffb009b737
commit 2b647c3abc
Signed by untrusted user who does not match committer: askiiart
GPG key ID: EA85979611654C30
19 changed files with 2945 additions and 578 deletions

2275
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
[package]
name = "library-maths"
name = "testing"
version = "0.1.0"
edition = "2021"

3
README.md Normal file
View file

@ -0,0 +1,3 @@
A functional-enough regular polygon generator. Not really useful for anything currently, but it can make data.
This is deterministic, hence its used in [`askiiart/disk-read-benchmark`](https://git.askiiart.net/askiiart/disk-read-benchmark)

View file

@ -1,95 +0,0 @@
use std::vec;
use winit::{event::{self, ElementState, Event, KeyEvent, WindowEvent}, event_loop::{EventLoop, EventLoopWindowTarget}, keyboard::{KeyCode, PhysicalKey}, window::{self, WindowBuilder}};
use crate::{state::state::State, structure::{enums::{micellaneous::Shape, Resolution}, structs::Vertex, traits::Drawable}};
pub struct Canvas {
pub(crate) added: Vec<Box<dyn Drawable>>,
pub(crate) resolution: Resolution
}
impl Canvas {
pub fn new(resolution: Resolution) -> Self {
Canvas {
added: vec![],
resolution
}
}
pub fn add(&mut self, added: Shape) {
match added {
Shape::Regular(polygon) => self.added.push(Box::new(polygon)),
}
}
pub async fn run(&self) {
let event_loop = EventLoop::new().unwrap();
let window = WindowBuilder::new().with_title("ciao").build(&event_loop).unwrap();
let mut verts = vec![];
self.uniform(&mut verts);
let mut state = State::new(&window, Some(bytemuck::cast_slice(&verts)), self.resolution).await;
event_loop
.run(move |event, control_flow| match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
event:
KeyEvent {
state: ElementState::Pressed,
physical_key: PhysicalKey::Code(KeyCode::Escape),
..
},
..
} => control_flow.exit(),
WindowEvent::Resized(size) => {
state.resize(*size);
}
WindowEvent::RedrawRequested => {
state.window().request_redraw();
/*
if !surface_configured {
return;
} ??????
*/
state.update();
match state.render() {
Ok(_) => (),
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
state.resize(state.size);
}
Err(wgpu::SurfaceError::OutOfMemory) => {
log::error!("OutOfMemory");
control_flow.exit();
}
Err(wgpu::SurfaceError::Timeout) => {
log::warn!("Surface Timeout")
}
}
}
_ => (),
}
}
}
_ => {}
})
.unwrap();
}
fn uniform(&self, vector: &mut Vec<Vertex>) {
vector.extend(self.added.iter().flat_map(|d| d.uniform()));
}
}

5
src/front/enums.rs Normal file
View file

@ -0,0 +1,5 @@
pub enum Rotation{
HorizontalAlign,
VerticalAlign,
Custom(f32)
}

View file

@ -0,0 +1,6 @@
#[derive(Debug, Clone)]
pub enum PolyError {
NotEnoughSides,
SidesAndTriangleNumberArentConsistant,
}

3
src/front/mod.rs Normal file
View file

@ -0,0 +1,3 @@
pub mod structs;
pub mod front_errors;
pub mod enums;

229
src/front/old Normal file
View file

@ -0,0 +1,229 @@
use bytemuck::{Pod, Zeroable};
use rand::Rng;
use wgpu::{VertexAttribute, VertexBufferLayout};
use std::{default, vec::Vec};
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Pos([f32; 3]);
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Col([f32; 3]);
impl Pos {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self([x, y, z])
}
}
unsafe impl Zeroable for Pos {}
unsafe impl Pod for Pos {}
impl Col {
pub fn new(r: f32, g: f32, b: f32) -> Self {
Self([r, g, b])
}
pub fn random() -> Self {
Self::new(rand::thread_rng().gen_range(0.0..=1.0), rand::thread_rng().gen_range(0.0..=1.0), rand::thread_rng().gen_range(0.0..=1.0))
}
}
unsafe impl Zeroable for Col {}
unsafe impl Pod for Col {}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Vertex {
position: Pos,
color: Col,
}
impl Vertex {
pub fn new(position: Pos, color: Col) -> Self {
Vertex { position: position, color: color }
}
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: 0,
shader_location: 0,
},
VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: std::mem::size_of::<[f32; 3]>() as u64,
shader_location: 1,
}],
}
}
}
unsafe impl Zeroable for Vertex {}
unsafe impl Pod for Vertex {}
#[derive(Debug)]
pub enum PolyError {
NotEnoughSides,
SidesAndTriangeNumberArentConsistant
}
#[repr(C)]
pub struct Polygon{
triangles: Vec<Triangle>,
n_sides: usize,
}
impl Polygon {
pub fn new_from_center(center: Vertex, radius: f32, n_sides: usize) -> Self {
//let theta = (360.0 / n_sides as f32).to_radians();
let mut vec_tris: Vec<Triangle> = Vec::with_capacity(n_sides);
let center_x = center.position.0[0];
let center_y = center.position.0[1];
for v in 0..n_sides {
let theta_current = (v as f32 / n_sides as f32) * 2.0 * std::f32::consts::PI;
let theta_next = ((v+1) as f32 / n_sides as f32) * 2.0 * std::f32::consts::PI;
let triangle = Triangle::new(Vertex::new(Pos::new((theta_current.cos() * radius) + center_x, (theta_current.sin() * radius) + center_y, 0.0), Col::random()), Vertex::new(Pos::new((theta_next.cos() * radius) + center_x, (theta_next.sin() * radius) + center_y, 0.0), Col::random()), center);
vec_tris.push(triangle);
};
Self::new_from_tris(vec_tris, n_sides).unwrap()
}
pub fn new_from_side(len_side: f32, n_sides: usize, color: Option<Col>) -> Self {
todo!();
// let color = color.unwrap_or(Col::random());
// let theta = 360.0 / n_sides as f32;
// let center = Pos::new(
// // ((180.0 - theta) / 2.0).to_radians().cos() * radius,
// // ((180.0 - theta) / 2.0).to_radians().sin() * radius,
// (theta / 2.0).to_radians().cos() * radius,
// (theta / 2.0).to_radians().sin() * radius,
// 0.0
// );
// let nsides_poly = NSides::new(center, radius, n_sides, color).unwrap();
// nsides_poly.verts.polish_tris(nsides_poly.center, color)
}
fn new_from_tris(triangles: Vec<Triangle>, n_sides: usize) -> Result<Self, PolyError> {
if triangles.len() != n_sides {
return Err(PolyError::SidesAndTriangeNumberArentConsistant)
}
Ok(Self {
triangles,
n_sides
})
}
pub fn get_tris(&self) -> Vec<Triangle> {
self.triangles.clone()
}
pub fn uniform(&self) -> &[u8] {
self.get_tris();
todo!()
}
}
#[repr(C)]
#[derive(Debug, Clone)]
pub struct Triangle([Vertex; 3]);
impl Triangle {
pub fn new(vertex1: Vertex, vertex2: Vertex, vertex3: Vertex) -> Self {
Self([vertex1, vertex2, vertex3])
}
pub fn verts(&self) -> [Vertex; 3] {
self.0
}
}
pub type VertexVector = Vec<Vertex>;
trait VertexVectorMethods {
fn polish_tris(&self, center_position: Pos, center_color: Col) -> Polygon;
fn get_next(&self, index: usize) -> Vertex;
}
impl VertexVectorMethods for VertexVector {
fn polish_tris(&self, center_position: Pos, center_color: Col) -> Polygon {
let start_verts = self;
let mut vec_tris = Vec::with_capacity(self.len());
for (vx, indx) in self.iter().zip(0..self.len()) {
vec_tris.push(Triangle::new(vx.to_owned(), self.get_next(indx), Vertex { position: center_position, color: Col::random() }));
};
Polygon::new_from_tris(vec_tris, self.len()).unwrap()
}
fn get_next(&self, index: usize) -> Vertex {
if index != self.len()-1 {
return self[index+1];
} else {
return self[0];
}
}
}
#[repr(C)]
pub struct NSides {
center: Pos,
radius: f32,
n_sides: usize,
color: Col,
verts: VertexVector
}
impl NSides {
#[allow(private_interfaces)]
pub fn new(center: Pos, radius: f32, n_sides: usize, color: Col) -> Result<Self, PolyError> {
if n_sides < 3 {
return Err(PolyError::NotEnoughSides)
}
let verts = Self::calc_vertecies(n_sides, radius, color);
return Ok(Self {
center,
radius,
n_sides,
color,
verts,
})
}
pub fn get_verts(&self) -> VertexVector {
self.verts.clone()
}
#[allow(private_interfaces)]
fn calc_vertecies(n_sides: usize, radius: f32, color: Col) -> VertexVector{
let mut verts: Vec<Vertex> = Vec::with_capacity(n_sides);
let float_sides = n_sides as f32;
for x in 0..n_sides {
let x = x as f32;
let theta = (x / float_sides) * 2.0 * 3.14159265359;
verts.push(Vertex::new(Pos::new(theta.cos() * radius, theta.sin() * radius, 0.0), color));
}
verts
}
}

233
src/front/structs.rs Normal file
View file

@ -0,0 +1,233 @@
use bytemuck::{Pod, Zeroable};
use core::f32;
use rand::Rng;
use std::vec::Vec;
use wgpu::VertexAttribute;
use super::{enums::Rotation, front_errors::PolyError};
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Pos([f32; 3]);
impl Pos {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self([x, y, z])
}
}
unsafe impl Zeroable for Pos {}
unsafe impl Pod for Pos {}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Col([f32; 3]);
impl Col {
pub fn new(r: f32, g: f32, b: f32) -> Self {
Self([r, g, b])
}
pub fn random() -> Self {
Self::new(
rand::thread_rng().gen_range(0.0..=1.0),
rand::thread_rng().gen_range(0.0..=1.0),
rand::thread_rng().gen_range(0.0..=1.0),
)
}
}
unsafe impl Zeroable for Col {}
unsafe impl Pod for Col {}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Vertex {
position: Pos,
color: Col,
}
unsafe impl Zeroable for Vertex {}
unsafe impl Pod for Vertex {}
impl Vertex {
pub fn new(position: Pos, color: Col) -> Self {
Vertex {
position: position,
color: color,
}
}
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: 0,
shader_location: 0,
},
VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: std::mem::size_of::<[f32; 3]>() as u64,
shader_location: 1,
},
],
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Triangle([Vertex; 3]);
impl Triangle {
pub fn new(vertices: [Vertex; 3]) -> Self {
Triangle(vertices)
}
pub fn verts(&self) -> [Vertex; 3] {
self.0
}
}
pub struct Polygon {
triangles: Vec<Triangle>,
center: Vertex,
radius: f32,
n_sides: usize,
rotation: Rotation,
}
impl Polygon {
/// # USAGE
/// quality of life method, alias [Polygon::new_from_radius_with_rotation()] with `rotation == 0.0`
pub fn new_from_radius(center: Vertex, radius: f32, n_sides: usize) -> Result<Self, PolyError> {
Self::new_from_radius_with_rotation(center, radius, n_sides, Rotation::HorizontalAlign)
}
/// # USAGE
/// creates a [Polygon] from a center and radius with a rotation.
///
/// # WARNING
/// - the rotation must be given in radiants.
pub fn new_from_radius_with_rotation(
center: Vertex,
radius: f32,
n_sides: usize,
rotation: Rotation,
) -> Result<Self, PolyError> {
if n_sides < 3 {
return Err(PolyError::NotEnoughSides);
}
let rotation_rad = match rotation {
Rotation::HorizontalAlign => {
if n_sides % 6 == 0 {
0.0
} else if n_sides % 4 == 0 {
(f32::consts::PI * 2.0 / n_sides as f32) / 2.0
} else if n_sides % 3 == 0 {
match ((n_sides-3)/6)%2 {
1 => (f32::consts::PI * 2.0 / n_sides as f32) / 4.0,
0 => (f32::consts::PI * 2.0)- ((f32::consts::PI * 2.0 / n_sides as f32) / 4.0),
_ => panic!(), // should never happen, it's a module. ( % 2)
}
} else {
0.0
} //TODO: add other n_sides
},
Rotation::VerticalAlign => (f32::consts::PI * 2.0 / n_sides as f32) / 2.0, // TODO
Rotation::Custom(rad) => rad,
};
let mut vec_tris: Vec<Triangle> = Vec::with_capacity(n_sides); // TODO: add space 4 morph
let center_x = center.position.0[0];
let center_y = center.position.0[1];
for v in 0..n_sides {
let theta_current =
((v as f32 / n_sides as f32) * 2.0 * std::f32::consts::PI) + rotation_rad;
let theta_next =
(((v + 1) as f32 / n_sides as f32) * 2.0 * std::f32::consts::PI) + rotation_rad;
let triangle = Triangle::new([
Vertex::new(
Pos::new(
(theta_current.cos() * radius) + center_x,
(theta_current.sin() * radius) + center_y,
0.0,
),
Col::random(),
),
Vertex::new(
Pos::new(
(theta_next.cos() * radius) + center_x,
(theta_next.sin() * radius) + center_y,
0.0,
),
Col::random(),
),
center,
]);
vec_tris.push(triangle);
}
Self::new_from_everything_with_rotation(vec_tris, center, radius, n_sides, rotation)
}
/// # USAGE
/// quality of life method, alias [Polygon::new_from_everything_with_rotation()] with `rotation == Rotation::HorizontalAlign`
fn new_from_everything(
triangles: Vec<Triangle>,
center: Vertex,
radius: f32,
n_sides: usize,
) -> Result<Self, PolyError> {
Self::new_from_everything_with_rotation(
triangles,
center,
radius,
n_sides,
Rotation::HorizontalAlign,
)
}
/// # USAGE
/// creates a [Polygon] from a center and radius with a rotation.
///
/// # WARNING
/// - the rotation must be given in radiants.
fn new_from_everything_with_rotation(
triangles: Vec<Triangle>,
center: Vertex,
radius: f32,
n_sides: usize,
rotation: Rotation,
) -> Result<Self, PolyError> {
if n_sides < 3 {
return Err(PolyError::NotEnoughSides);
}
if triangles.len() != n_sides {
return Err(PolyError::SidesAndTriangleNumberArentConsistant);
}
Ok(Polygon {
triangles,
center,
radius,
n_sides,
rotation,
})
}
fn get_triangles(&self) -> Vec<Triangle> {
self.triangles.clone()
}
pub fn uniform(&self) -> Vec<Vertex> {
self.get_triangles()
.iter()
.flat_map(|t| t.verts().to_vec())
.collect::<Vec<Vertex>>()
}
}

36
src/learn_shading.wgsl Normal file
View file

@ -0,0 +1,36 @@
// Vertex shader
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
};
@vertex
fn vs_main(
@builtin(vertex_index) vertex_index: u32,
) -> VertexOutput {
var out: VertexOutput;
var x: f32;
var y: f32;
if vertex_index == 0 || vertex_index == 4 {
x = 0.5 * (10.0/16.0);
y = 0.5;
} else if vertex_index == 1 {
x = -0.5* (10.0/16.0);
y = 0.5;
} else if vertex_index == 2 {
x= -0.5* (10.0/16.0);
y= -0.5;
} else if vertex_index == 3 {
x= 0.5* (10.0/16.0);
y= -0.5;
}
out.clip_position = vec4<f32>(x, y, 0.0, 1.0);
return out;
}
// Fragment shader
@fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return vec4<f32>(0.67, 0.47, 0.72, 1.0);
}

View file

@ -1,21 +1,32 @@
use state::state::State;
use winit::{event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, keyboard::{KeyCode, PhysicalKey}, window::WindowBuilder};
pub mod front;
pub mod state;
mod state;
mod structure;
mod canvas;
use bytemuck::{Pod, Zeroable};
use state::State;
use wgpu::VertexAttribute;
use winit::{
dpi::Size,
event::*,
event_loop::EventLoop,
keyboard::{KeyCode, PhysicalKey},
window::WindowBuilder,
};
// * re-exports
pub use canvas::Canvas;
pub use structure::enums::Resolution;
pub use structure::enums::micellaneous::Shape;
pub use structure::structs::baseline::polygon::Polygon;
pub use structure::structs::Vertex;
pub use structure::structs::{Col, Pos};
// * re-exports
// const VERTS: &[Vertex] = &[
// Vertex { position: [-0.0868241, 0.49240386, 0.0], color: [0.5, 0.0, 0.5] }, // A
// Vertex { position: [-0.49513406, 0.06958647, 0.0], color: [0.5, 0.0, 0.5] }, // B
// Vertex { position: [-0.21918549, -0.44939706, 0.0], color: [0.5, 0.0, 0.5] }, // C
// Vertex { position: [0.35966998, -0.3473291, 0.0], color: [0.5, 0.0, 0.5] }, // D
// Vertex { position: [0.44147372, 0.2347359, 0.0], color: [0.5, 0.0, 0.5] }, // E
// ];
impl State<'_> {
pub fn run(&mut self) {
// const INDICES: &[u16] = &[
// 0, 1, 4,
// 1, 2, 4,
// 2, 3, 4,
// ];
pub async fn run() {
env_logger::init();
let event_loop = EventLoop::new().unwrap();
let window = WindowBuilder::new()
@ -23,13 +34,15 @@ impl State<'_> {
.build(&event_loop)
.unwrap();
let mut state = State::new(&window).await;
event_loop
.run(move |event, control_flow| match event {
Event::WindowEvent {
ref event,
window_id,
} if window_id == self.window().id() => {
if !self.input(event) {
} if window_id == state.window().id() => {
if !state.input(event) {
match event {
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
@ -43,25 +56,23 @@ impl State<'_> {
} => control_flow.exit(),
WindowEvent::Resized(size) => {
self.resize(*size);
state.resize(*size);
}
WindowEvent::RedrawRequested => {
self.window().request_redraw();
state.window().request_redraw();
/*
if !surface_configured {
return;
} ??????
*/
self.update();
state.update();
match self.render() {
match state.render() {
Ok(_) => (),
Err(
wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated,
) => {
self.resize(self.size);
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
state.resize(state.size);
}
Err(wgpu::SurfaceError::OutOfMemory) => {
log::error!("OutOfMemory");
@ -81,4 +92,3 @@ impl State<'_> {
})
.unwrap();
}
}

11
src/main.rs Normal file
View file

@ -0,0 +1,11 @@
use tokio;
use testing::front::{structs::*, enums::*};
#[tokio::main]
async fn main() {
// the number of sides for the regular polygon; must be >= 3
// ~25M sides = 8 GB of RAM usage
let sides = 100_000_000;
let verts = Polygon::new_from_radius_with_rotation(Vertex::new(Pos::new(0.0, 0.0, 0.0), Col::new(0.1, 0.2, 0.3)), 0.5, sides, Rotation::Custom(0.0)).unwrap().uniform();
std::fs::write("output", format!("{:?}", verts)).unwrap();
}

View file

@ -1,41 +1,32 @@
use super::super::structure::{enums::Resolution, structs::Vertex};
use std::fmt::Debug;
use wgpu::{
util::{BufferInitDescriptor, DeviceExt},
BufferUsages, Color, PipelineLayout, PipelineLayoutDescriptor, RenderPassColorAttachment,
RenderPipelineDescriptor, ShaderModuleDescriptor, VertexBufferLayout, VertexState,
};
use winit::{
event::WindowEvent,
event_loop::{self, EventLoop},
window::{Window, WindowBuilder},
naga::back::INDENT, util::DeviceExt, Buffer, BufferUsages, Color, PipelineLayout, PipelineLayoutDescriptor, RenderPassColorAttachment, RenderPipelineDescriptor, ShaderModuleDescriptor, VertexState
};
use winit::{event::WindowEvent, window::Window};
use crate::front::structs::{Col, Polygon, Pos, Vertex};
pub struct State<'a> {
pub clear_color: wgpu::Color,
pub(crate) config: wgpu::SurfaceConfiguration,
pub(crate) device: wgpu::Device,
//pub index_buffer: wgpu::Buffer,
pub num_index: u32,
pub(crate) queue: wgpu::Queue,
pub(crate) render_pipeline: wgpu::RenderPipeline,
pub resolution: Resolution,
pub(crate) size: winit::dpi::PhysicalSize<u32>,
pub(crate) surface: wgpu::Surface<'a>,
pub(crate) vertex_buffer: wgpu::Buffer,
pub surface: wgpu::Surface<'a>,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
pub config: wgpu::SurfaceConfiguration,
pub size: winit::dpi::PhysicalSize<u32>,
// The window must be declared after the surface so
// it gets dropped after it as the surface contains
// unsafe references to the window's resources.
pub(crate) window: &'a Window
pub window: &'a Window,
pub clear_color: wgpu::Color,
pub render_pipeline: wgpu::RenderPipeline,
pub vertex_buffer: wgpu::Buffer,
//pub index_buffer: wgpu::Buffer,
pub num_index: u32,
}
impl<'a> State<'a> {
// Creating some of the wgpu types requires async code
pub async fn new(
window: &'a Window,
verts: Option<&[u8]>,
resolution: Resolution,
) -> State<'a> {
pub async fn new(window: &'a Window) -> State<'a> {
// * ---------- SIZE ----------
let size = window.inner_size();
// * ---------- SIZE ----------
@ -119,25 +110,25 @@ impl<'a> State<'a> {
let shader: wgpu::ShaderModule = device.create_shader_module(ShaderModuleDescriptor {
label: Some("shader"),
// source: wgpu::ShaderSource::Wgsl(include_str!("learn_shading.wgsl").into()),
source: wgpu::ShaderSource::Wgsl(include_str!("../shaders/shader.wgsl").into()),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
let render_pipeline_layout: PipelineLayout =
device.create_pipeline_layout(&PipelineLayoutDescriptor {
let render_pipeline_layout: PipelineLayout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
label: Some("Render Pipeline Layout"),
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let render_pipeline: wgpu::RenderPipeline =
device.create_render_pipeline(&RenderPipelineDescriptor {
let render_pipeline: wgpu::RenderPipeline = device.create_render_pipeline(&RenderPipelineDescriptor {
label: Some("Pipeline"),
layout: Some(&render_pipeline_layout),
vertex: VertexState {
module: &shader,
entry_point: "vs_main",
compilation_options: Default::default(),
buffers: &[Vertex::desc()],
buffers: &[
Vertex::desc(),
],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
@ -149,38 +140,29 @@ impl<'a> State<'a> {
write_mask: wgpu::ColorWrites::ALL,
})],
}),
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleStrip,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: Some(wgpu::Face::Back),
unclipped_depth: false,
polygon_mode: wgpu::PolygonMode::Fill,
conservative: false,
},
primitive: wgpu::PrimitiveState { topology: wgpu::PrimitiveTopology::TriangleStrip, strip_index_format: None, front_face: wgpu::FrontFace::Ccw, cull_mode: Some(wgpu::Face::Back), unclipped_depth: false, polygon_mode: wgpu::PolygonMode::Fill, conservative: false },
depth_stencil: None,
multisample: wgpu::MultisampleState {
count: 1,
mask: !0,
alpha_to_coverage_enabled: false,
},
multisample: wgpu::MultisampleState { count: 1, mask: !0, alpha_to_coverage_enabled: false },
multiview: None,
cache: None,
cache: None
});
// * ---------- PIPELINE ----------
let verts_final = match verts {
Some(v) => v,
None => &[],
};
let verts = Polygon::new_from_radius_with_rotation(Vertex::new(Pos::new(0.0, 0.0, 0.0), Col::new(0.2, 0.4, 0.6)), 0.5, 268435456, crate::front::enums::Rotation::HorizontalAlign).unwrap().uniform();
let something: &[u8] = bytemuck::cast_slice(&verts);
//println!("{:?}", verts);
std::fs::write("stuff", format!("{:?}", verts)).unwrap();
// ! ---------- VERT BUFFER ----------
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
label: Some("Vertex Buffer"),
contents: verts_final,
// contents: bytemuck::cast_slice(&VERTS),
contents: something,
usage: BufferUsages::VERTEX,
});
let num_index = (verts_final.len() / std::mem::size_of::<Vertex>()) as u32;
let num_index = verts.len() as u32;
// ! ---------- VERT BUFFER ----------
// // ! ---------- INDEX BUFFER ----------
@ -194,7 +176,6 @@ impl<'a> State<'a> {
let clear_color = Color::WHITE;
Self {
resolution,
window,
surface,
device,
@ -302,14 +283,4 @@ impl<'a> State<'a> {
output.present();
Ok(())
}
pub(crate) fn modify_vert_buffer(&mut self, verts: Vec<Vertex>) {
self.vertex_buffer = self.device.create_buffer_init(&BufferInitDescriptor {
label: Some("Vertex Buffer"),
// contents: bytemuck::cast_slice(&VERTS),
contents: bytemuck::cast_slice(&verts),
usage: BufferUsages::VERTEX,
});
self.num_index = verts.len() as u32;
}
}

View file

@ -1 +0,0 @@
pub mod state;

View file

@ -1,39 +0,0 @@
pub use micellaneous::Resolution;
pub mod micellaneous {
use crate::structure::structs::baseline::polygon::Polygon;
#[derive(Debug, Clone, Copy)]
pub enum Resolution {
Res_16_10,
Res_16_9,
Res_4_3,
Res_21_9,
Res_32_9,
Res_5_4,
Custom((u16, u16)),
}
#[derive(Debug, Clone, Copy)]
pub enum Rotation {
HorizontalAlign,
VerticalAlign,
Custom(f32),
}
#[derive(Debug, Clone)]
pub enum Shape {
Regular(Polygon),
}
}
pub mod errors {
#[derive(Debug, Clone, Copy)]
pub enum PolyError {
NotEnoughSides,
SidesAndTriangleNumberArentConsistant,
}
}

View file

@ -1,3 +0,0 @@
pub mod structs;
pub mod enums;
pub mod traits;

View file

@ -1,270 +0,0 @@
pub use baseline::color::Col;
pub use baseline::position::Pos;
pub use baseline::vertex::Vertex;
pub mod baseline {
pub mod position {
use bytemuck::{bytes_of, Pod, Zeroable};
use crate::structure::traits::Drawable;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Pos(pub(crate) [f32; 3]);
impl Pos {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self([x, y, z])
}
}
unsafe impl Zeroable for Pos {}
unsafe impl Pod for Pos {}
}
pub mod color {
use bytemuck::{Pod, Zeroable};
use rand::Rng;
use crate::structure::traits::Drawable;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Col(pub(crate) [f32; 3]);
impl Col {
pub fn new(r: f32, g: f32, b: f32) -> Self {
Self([r, g, b])
}
pub fn random() -> Self {
Self::new(
rand::thread_rng().gen_range(0.0..=1.0),
rand::thread_rng().gen_range(0.0..=1.0),
rand::thread_rng().gen_range(0.0..=1.0),
)
}
}
unsafe impl Zeroable for Col {}
unsafe impl Pod for Col {}
}
pub mod vertex {
use crate::structure::traits::Drawable;
use bytemuck::{NoUninit, Pod, Zeroable};
use wgpu::VertexAttribute;
use super::super::*;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct Vertex {
pub(crate) position: Pos,
pub(crate) color: Col,
}
unsafe impl Zeroable for Vertex {}
unsafe impl Pod for Vertex {}
impl Vertex {
pub fn new(position: Pos, color: Col) -> Self {
Vertex {
position: position,
color: color,
}
}
pub fn desc() -> wgpu::VertexBufferLayout<'static> {
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Self>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &[
VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: 0,
shader_location: 0,
},
VertexAttribute {
format: wgpu::VertexFormat::Float32x3,
offset: std::mem::size_of::<[f32; 3]>() as u64,
shader_location: 1,
},
],
}
}
}
}
pub mod triangle {
use super::vertex::Vertex;
#[derive(Debug, Clone, Copy)]
pub struct Triangle([Vertex; 3]);
impl Triangle {
pub fn new(vertices: [Vertex; 3]) -> Self {
Triangle(vertices)
}
pub fn verts(&self) -> [Vertex; 3] {
self.0
}
}
}
pub mod polygon {
use crate::structure::{enums::{errors::PolyError, micellaneous::Rotation}, traits::Drawable};
use super::{color::Col, position::Pos, triangle::Triangle, vertex::Vertex};
#[derive(Debug, Clone)]
pub struct Polygon {
triangles: Vec<Triangle>,
center: Vertex,
radius: f32,
n_sides: usize,
rotation: Rotation,
}
impl Polygon {
/// # USAGE
/// quality of life method, alias [Polygon::new_from_radius_with_rotation()] with `rotation == 0.0`
pub fn new_from_radius(center: Vertex, radius: f32, n_sides: usize) -> Result<Self, PolyError> {
Self::new_from_radius_with_rotation(center, radius, n_sides, Rotation::HorizontalAlign)
}
/// # USAGE
/// creates a [Polygon] from a center and radius with a rotation.
///
/// # WARNING
/// - the rotation must be given in radiants.
pub fn new_from_radius_with_rotation(
center: Vertex,
radius: f32,
n_sides: usize,
rotation: Rotation,
) -> Result<Self, PolyError> {
if n_sides < 3 {
return Err(PolyError::NotEnoughSides);
}
let rotation_rad = match rotation {
Rotation::HorizontalAlign => {
if n_sides % 6 == 0 {
0.0
} else if n_sides % 4 == 0 {
(std::f32::consts::PI * 2.0 / n_sides as f32) / 2.0
} else if n_sides % 3 == 0 {
match ((n_sides-3)/6)%2 {
1 => (std::f32::consts::PI * 2.0 / n_sides as f32) / 4.0,
0 => (std::f32::consts::PI * 2.0)- ((std::f32::consts::PI * 2.0 / n_sides as f32) / 4.0),
_ => panic!(), // should never happen, it's a module. ( % 2)
}
} else {
0.0
} //TODO: add other n_sides
},
Rotation::VerticalAlign => (std::f32::consts::PI * 2.0 / n_sides as f32) / 2.0, // TODO
Rotation::Custom(rad) => rad,
};
let mut vec_tris: Vec<Triangle> = Vec::with_capacity(n_sides); // TODO: add space 4 morph
let center_x = center.position.0[0];
let center_y = center.position.0[1];
for v in 0..n_sides {
let theta_current =
((v as f32 / n_sides as f32) * 2.0 * std::f32::consts::PI) + rotation_rad;
let theta_next =
(((v + 1) as f32 / n_sides as f32) * 2.0 * std::f32::consts::PI) + rotation_rad;
let triangle = Triangle::new([
Vertex::new(
Pos::new(
(theta_current.cos() * radius) + center_x,
(theta_current.sin() * radius) + center_y,
0.0,
),
Col::random(),
),
Vertex::new(
Pos::new(
(theta_next.cos() * radius) + center_x,
(theta_next.sin() * radius) + center_y,
0.0,
),
Col::random(),
),
center,
]);
vec_tris.push(triangle);
}
Self::new_from_everything_with_rotation(vec_tris, center, radius, n_sides, rotation)
}
/// # USAGE
/// quality of life method, alias [Polygon::new_from_everything_with_rotation()] with `rotation == Rotation::HorizontalAlign`
fn new_from_everything(
triangles: Vec<Triangle>,
center: Vertex,
radius: f32,
n_sides: usize,
) -> Result<Self, PolyError> {
Self::new_from_everything_with_rotation(
triangles,
center,
radius,
n_sides,
Rotation::HorizontalAlign,
)
}
/// # USAGE
/// creates a [Polygon] from a center and radius with a rotation.
///
/// # WARNING
/// - the rotation must be given in radiants.
fn new_from_everything_with_rotation(
triangles: Vec<Triangle>,
center: Vertex,
radius: f32,
n_sides: usize,
rotation: Rotation,
) -> Result<Self, PolyError> {
if n_sides < 3 {
return Err(PolyError::NotEnoughSides);
}
if triangles.len() != n_sides {
return Err(PolyError::SidesAndTriangleNumberArentConsistant);
}
Ok(Polygon {
triangles,
center,
radius,
n_sides,
rotation,
})
}
fn get_triangles(&self) -> Vec<Triangle> {
self.triangles.clone()
}
pub fn uniform(&self) -> Vec<Vertex> {
self.get_triangles()
.iter()
.flat_map(|t| t.verts().to_vec())
.collect::<Vec<Vertex>>()
}
}
impl Drawable for Polygon {
fn uniform(&self) -> Vec<Vertex> {
self.uniform()
}
}
}
}

View file

@ -1,7 +0,0 @@
use bytemuck::NoUninit;
use super::structs::Vertex;
pub trait Drawable {
fn uniform(&self) -> Vec<Vertex>;
}