initial commit of headless i guess
This commit is contained in:
parent
ffb009b737
commit
2b647c3abc
19 changed files with 2945 additions and 578 deletions
2275
Cargo.lock
generated
Normal file
2275
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "library-maths"
|
||||
name = "testing"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
|
@ -16,4 +16,4 @@ rand = "*"
|
|||
opt-level = 3
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 2
|
||||
opt-level = 2
|
||||
|
|
3
README.md
Normal file
3
README.md
Normal 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)
|
|
@ -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
5
src/front/enums.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub enum Rotation{
|
||||
HorizontalAlign,
|
||||
VerticalAlign,
|
||||
Custom(f32)
|
||||
}
|
6
src/front/front_errors.rs
Normal file
6
src/front/front_errors.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum PolyError {
|
||||
NotEnoughSides,
|
||||
SidesAndTriangleNumberArentConsistant,
|
||||
}
|
3
src/front/mod.rs
Normal file
3
src/front/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub mod structs;
|
||||
pub mod front_errors;
|
||||
pub mod enums;
|
229
src/front/old
Normal file
229
src/front/old
Normal 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
233
src/front/structs.rs
Normal 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
36
src/learn_shading.wgsl
Normal 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);
|
||||
}
|
150
src/lib.rs
150
src/lib.rs
|
@ -1,84 +1,94 @@
|
|||
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) {
|
||||
env_logger::init();
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
let window = WindowBuilder::new()
|
||||
.with_title("uhhhhh")
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
// const INDICES: &[u16] = &[
|
||||
// 0, 1, 4,
|
||||
// 1, 2, 4,
|
||||
// 2, 3, 4,
|
||||
// ];
|
||||
|
||||
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) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested
|
||||
| WindowEvent::KeyboardInput {
|
||||
event:
|
||||
KeyEvent {
|
||||
state: ElementState::Pressed,
|
||||
physical_key: PhysicalKey::Code(KeyCode::Escape),
|
||||
..
|
||||
},
|
||||
..
|
||||
} => control_flow.exit(),
|
||||
pub async fn run() {
|
||||
env_logger::init();
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
let window = WindowBuilder::new()
|
||||
.with_title("uhhhhh")
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
WindowEvent::Resized(size) => {
|
||||
self.resize(*size);
|
||||
}
|
||||
let mut state = State::new(&window).await;
|
||||
|
||||
WindowEvent::RedrawRequested => {
|
||||
self.window().request_redraw();
|
||||
/*
|
||||
if !surface_configured {
|
||||
return;
|
||||
} ??????
|
||||
*/
|
||||
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(),
|
||||
|
||||
self.update();
|
||||
WindowEvent::Resized(size) => {
|
||||
state.resize(*size);
|
||||
}
|
||||
|
||||
match self.render() {
|
||||
Ok(_) => (),
|
||||
Err(
|
||||
wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated,
|
||||
) => {
|
||||
self.resize(self.size);
|
||||
}
|
||||
Err(wgpu::SurfaceError::OutOfMemory) => {
|
||||
log::error!("OutOfMemory");
|
||||
control_flow.exit();
|
||||
}
|
||||
Err(wgpu::SurfaceError::Timeout) => {
|
||||
log::warn!("Surface Timeout")
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
|
11
src/main.rs
Normal file
11
src/main.rs
Normal 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();
|
||||
}
|
|
@ -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,68 +110,59 @@ 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 {
|
||||
label: Some("Render Pipeline Layout"),
|
||||
bind_group_layouts: &[],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
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 {
|
||||
label: Some("Pipeline"),
|
||||
layout: Some(&render_pipeline_layout),
|
||||
vertex: VertexState {
|
||||
module: &shader,
|
||||
entry_point: "vs_main",
|
||||
compilation_options: Default::default(),
|
||||
buffers: &[Vertex::desc()],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
compilation_options: Default::default(),
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: config.format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
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,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState {
|
||||
count: 1,
|
||||
mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
},
|
||||
multiview: None,
|
||||
cache: None,
|
||||
});
|
||||
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(),
|
||||
],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
compilation_options: Default::default(),
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: config.format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
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 },
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState { count: 1, mask: !0, alpha_to_coverage_enabled: false },
|
||||
multiview: 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 {
|
||||
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,
|
||||
|
@ -274,7 +255,7 @@ impl<'a> State<'a> {
|
|||
label: Some("encoder"),
|
||||
});
|
||||
|
||||
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
let mut render_pass= encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("Render Pass"),
|
||||
color_attachments: &[Some(RenderPassColorAttachment {
|
||||
view: &view,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
pub mod state;
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
pub mod structs;
|
||||
pub mod enums;
|
||||
pub mod traits;
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
use bytemuck::NoUninit;
|
||||
|
||||
use super::structs::Vertex;
|
||||
|
||||
pub trait Drawable {
|
||||
fn uniform(&self) -> Vec<Vertex>;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue