style: rustfmt run
This commit is contained in:
1 parent
e7659ba387
commit
0661494b0f
17 files changed
+235
-203
No files matched your search
Generated
+3
-1
@@ -1,4 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise">
|
||||||
|
<file url="file://$PROJECT_DIR$/src/math/mod.rs" charset="US-ASCII" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
+127
-102
@@ -1,36 +1,45 @@
|
|||||||
use std::error::Error;
|
use crate::common::mesh::MeshRegistry;
|
||||||
|
use crate::gpu::vertex3::Vertex3;
|
||||||
|
use crate::triangle;
|
||||||
|
use std::error::Error;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
|
use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer};
|
||||||
use vulkano::command_buffer::allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo};
|
use vulkano::command_buffer::allocator::{
|
||||||
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, RenderPassBeginInfo, SubpassBeginInfo, SubpassContents, SubpassEndInfo};
|
StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo,
|
||||||
|
};
|
||||||
|
use vulkano::command_buffer::{
|
||||||
|
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, RenderPassBeginInfo,
|
||||||
|
SubpassBeginInfo, SubpassContents, SubpassEndInfo,
|
||||||
|
};
|
||||||
use vulkano::descriptor_set::allocator::{DescriptorSetAllocator, StandardDescriptorSetAllocator};
|
use vulkano::descriptor_set::allocator::{DescriptorSetAllocator, StandardDescriptorSetAllocator};
|
||||||
use vulkano::device::{Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags};
|
|
||||||
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
|
||||||
use vulkano::image::{Image, ImageUsage};
|
use vulkano::device::{
|
||||||
|
Device, DeviceCreateInfo, DeviceExtensions, Queue, QueueCreateInfo, QueueFlags,
|
||||||
|
};
|
||||||
use vulkano::image::view::ImageView;
|
use vulkano::image::view::ImageView;
|
||||||
|
use vulkano::image::{Image, ImageUsage};
|
||||||
use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions};
|
use vulkano::instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions};
|
||||||
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator};
|
use vulkano::memory::allocator::{
|
||||||
use vulkano::pipeline::{GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo};
|
AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator,
|
||||||
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
};
|
||||||
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo;
|
||||||
|
use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState};
|
||||||
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
use vulkano::pipeline::graphics::input_assembly::InputAssemblyState;
|
||||||
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
use vulkano::pipeline::graphics::multisample::MultisampleState;
|
||||||
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
use vulkano::pipeline::graphics::rasterization::RasterizationState;
|
||||||
use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition};
|
use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition};
|
||||||
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
|
||||||
use vulkano::pipeline::layout::PipelineDescriptorSetLayoutCreateInfo;
|
use vulkano::pipeline::layout::PipelineDescriptorSetLayoutCreateInfo;
|
||||||
|
use vulkano::pipeline::{GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo};
|
||||||
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
use vulkano::render_pass::{Framebuffer, FramebufferCreateInfo, RenderPass, Subpass};
|
||||||
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
|
|
||||||
use vulkano::{swapchain, sync, Validated, VulkanError, VulkanLibrary};
|
|
||||||
use vulkano::shader::ShaderModule;
|
use vulkano::shader::ShaderModule;
|
||||||
|
use vulkano::swapchain::{Surface, Swapchain, SwapchainCreateInfo, SwapchainPresentInfo};
|
||||||
use vulkano::sync::GpuFuture;
|
use vulkano::sync::GpuFuture;
|
||||||
|
use vulkano::{Validated, VulkanError, VulkanLibrary, swapchain, sync};
|
||||||
use winit::application::ApplicationHandler;
|
use winit::application::ApplicationHandler;
|
||||||
use winit::event::WindowEvent;
|
use winit::event::WindowEvent;
|
||||||
use winit::event_loop::ActiveEventLoop;
|
use winit::event_loop::ActiveEventLoop;
|
||||||
use winit::window::{Window, WindowAttributes, WindowId};
|
use winit::window::{Window, WindowAttributes, WindowId};
|
||||||
use crate::common::mesh::MeshRegistry;
|
|
||||||
use crate::gpu::vertex3::Vertex3;
|
|
||||||
use crate::triangle;
|
|
||||||
|
|
||||||
struct VulkanContext {
|
struct VulkanContext {
|
||||||
window: Arc<Window>,
|
window: Arc<Window>,
|
||||||
@@ -54,7 +63,10 @@ impl VulkanContext {
|
|||||||
/// Initializes and returns a new `VulkanContext`. It may fail in all cases where a Vulkan object
|
/// Initializes and returns a new `VulkanContext`. It may fail in all cases where a Vulkan object
|
||||||
/// may fail, specifically during initialization of shaders, devices, buffers, or any other such
|
/// may fail, specifically during initialization of shaders, devices, buffers, or any other such
|
||||||
/// structures.
|
/// structures.
|
||||||
pub fn init(instance: Arc<Instance>, event_loop: &ActiveEventLoop) -> Result<Self, Box<dyn Error>> {
|
pub fn init(
|
||||||
|
instance: Arc<Instance>,
|
||||||
|
event_loop: &ActiveEventLoop,
|
||||||
|
) -> Result<Self, Box<dyn Error>> {
|
||||||
let attributes = WindowAttributes::default()
|
let attributes = WindowAttributes::default()
|
||||||
.with_title("Vulkano Example")
|
.with_title("Vulkano Example")
|
||||||
.with_resizable(true);
|
.with_resizable(true);
|
||||||
@@ -70,41 +82,29 @@ impl VulkanContext {
|
|||||||
|
|
||||||
// Get a physical device. Fails if there is no suitable device found. The device must have a
|
// Get a physical device. Fails if there is no suitable device found. The device must have a
|
||||||
// graphics queue and swapchain capabilities.
|
// graphics queue and swapchain capabilities.
|
||||||
let (physical_device, queue_family_idx) = Self::get_physical_device(
|
let (physical_device, queue_family_idx) =
|
||||||
instance.clone(),
|
Self::get_physical_device(instance.clone(), surface.clone(), &dev_extensions)?;
|
||||||
surface.clone(),
|
|
||||||
&dev_extensions
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Create a Vulkan device. This is a handle to the connection between the program and the
|
// Create a Vulkan device. This is a handle to the connection between the program and the
|
||||||
// chosen physical device.
|
// chosen physical device.
|
||||||
let (device, mut queues) = Self::create_device(
|
let (device, mut queues) = Self::create_device(
|
||||||
physical_device.clone(),
|
physical_device.clone(),
|
||||||
&dev_extensions,
|
&dev_extensions,
|
||||||
queue_family_idx as usize
|
queue_family_idx as usize,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Get the first queue. This is what we'll use for drawing.
|
// Get the first queue. This is what we'll use for drawing.
|
||||||
let queue = queues.next()
|
let queue = queues.next().ok_or("Queues list was empty.")?;
|
||||||
.ok_or("Queues list was empty.")?;
|
|
||||||
|
|
||||||
let capabilities = physical_device
|
let capabilities = physical_device.surface_capabilities(&surface, Default::default())?;
|
||||||
.surface_capabilities(
|
|
||||||
&surface,
|
|
||||||
Default::default()
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let dimensions = window
|
let dimensions = window.inner_size();
|
||||||
.inner_size();
|
|
||||||
let composite_alpha = capabilities
|
let composite_alpha = capabilities
|
||||||
.supported_composite_alpha
|
.supported_composite_alpha
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.ok_or("No composite alpha supported")?;
|
.ok_or("No composite alpha supported")?;
|
||||||
let image_format = physical_device
|
let image_format = physical_device.surface_formats(&surface, Default::default())?[0].0;
|
||||||
.surface_formats(&surface, Default::default())?
|
|
||||||
[0]
|
|
||||||
.0;
|
|
||||||
|
|
||||||
// Swapchain needs to be easily changeable, since resizing the window creates a whole new
|
// Swapchain needs to be easily changeable, since resizing the window creates a whole new
|
||||||
// set of information. Putting this into a function would be good, but also the new
|
// set of information. Putting this into a function would be good, but also the new
|
||||||
@@ -119,7 +119,7 @@ impl VulkanContext {
|
|||||||
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
image_usage: ImageUsage::COLOR_ATTACHMENT,
|
||||||
composite_alpha,
|
composite_alpha,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mem_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
let mem_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
|
||||||
@@ -127,7 +127,10 @@ impl VulkanContext {
|
|||||||
device.clone(),
|
device.clone(),
|
||||||
StandardCommandBufferAllocatorCreateInfo::default(),
|
StandardCommandBufferAllocatorCreateInfo::default(),
|
||||||
));
|
));
|
||||||
let desc_allocator = Arc::new(StandardDescriptorSetAllocator::new(device.clone(), Default::default()));
|
let desc_allocator = Arc::new(StandardDescriptorSetAllocator::new(
|
||||||
|
device.clone(),
|
||||||
|
Default::default(),
|
||||||
|
));
|
||||||
|
|
||||||
let render_pass = vulkano::single_pass_renderpass!(
|
let render_pass = vulkano::single_pass_renderpass!(
|
||||||
device.clone(),
|
device.clone(),
|
||||||
@@ -158,7 +161,7 @@ impl VulkanContext {
|
|||||||
&vert_shader,
|
&vert_shader,
|
||||||
&frag_shader,
|
&frag_shader,
|
||||||
&render_pass,
|
&render_pass,
|
||||||
[image_extents[0] as f32, image_extents[1] as f32]
|
[image_extents[0] as f32, image_extents[1] as f32],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let vertex_buffer = Arc::new(Buffer::from_iter(
|
let vertex_buffer = Arc::new(Buffer::from_iter(
|
||||||
@@ -173,11 +176,19 @@ impl VulkanContext {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
Vertex3 { position: [0.5, 0.5, 0.0] },
|
Vertex3 {
|
||||||
Vertex3 { position: [-0.5, 0.5, 0.0] },
|
position: [0.5, 0.5, 0.0],
|
||||||
Vertex3 { position: [-0.5, -0.5, 0.0] },
|
},
|
||||||
Vertex3 { position: [0.5, -0.5, 0.0] },
|
Vertex3 {
|
||||||
]
|
position: [-0.5, 0.5, 0.0],
|
||||||
|
},
|
||||||
|
Vertex3 {
|
||||||
|
position: [-0.5, -0.5, 0.0],
|
||||||
|
},
|
||||||
|
Vertex3 {
|
||||||
|
position: [0.5, -0.5, 0.0],
|
||||||
|
},
|
||||||
|
],
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
let index_buffer = Arc::new(Buffer::from_iter(
|
let index_buffer = Arc::new(Buffer::from_iter(
|
||||||
@@ -191,10 +202,7 @@ impl VulkanContext {
|
|||||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
vec![
|
vec![0, 1, 2, 0, 2, 3],
|
||||||
0, 1, 2,
|
|
||||||
0, 2, 3,
|
|
||||||
]
|
|
||||||
)?);
|
)?);
|
||||||
|
|
||||||
let cmd_buffers = Self::get_command_buffers(
|
let cmd_buffers = Self::get_command_buffers(
|
||||||
@@ -203,12 +211,10 @@ impl VulkanContext {
|
|||||||
&pipeline,
|
&pipeline,
|
||||||
&framebuffers,
|
&framebuffers,
|
||||||
&vertex_buffer,
|
&vertex_buffer,
|
||||||
&index_buffer
|
&index_buffer,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mesh_registry = Arc::new(MeshRegistry::new(
|
let mesh_registry = Arc::new(MeshRegistry::new(mem_allocator.clone())?);
|
||||||
mem_allocator.clone(),
|
|
||||||
)?);
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
window,
|
window,
|
||||||
@@ -233,7 +239,8 @@ impl VulkanContext {
|
|||||||
pub fn draw_frame(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn draw_frame(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
let (image_idx, suboptimal, acquire_future) =
|
let (image_idx, suboptimal, acquire_future) =
|
||||||
match swapchain::acquire_next_image(self.swapchain.clone(), None)
|
match swapchain::acquire_next_image(self.swapchain.clone(), None)
|
||||||
.map_err(Validated::unwrap){
|
.map_err(Validated::unwrap)
|
||||||
|
{
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(VulkanError::OutOfDate) => {
|
Err(VulkanError::OutOfDate) => {
|
||||||
println!("Swapchain is out of date!");
|
println!("Swapchain is out of date!");
|
||||||
@@ -252,7 +259,10 @@ impl VulkanContext {
|
|||||||
|
|
||||||
let execution = sync::now(self.device.clone())
|
let execution = sync::now(self.device.clone())
|
||||||
.join(acquire_future)
|
.join(acquire_future)
|
||||||
.then_execute(self.queue.clone(), self.cmd_buffers[image_idx as usize].clone())?
|
.then_execute(
|
||||||
|
self.queue.clone(),
|
||||||
|
self.cmd_buffers[image_idx as usize].clone(),
|
||||||
|
)?
|
||||||
.then_swapchain_present(
|
.then_swapchain_present(
|
||||||
self.queue.clone(),
|
self.queue.clone(),
|
||||||
SwapchainPresentInfo::swapchain_image_index(self.swapchain.clone(), image_idx),
|
SwapchainPresentInfo::swapchain_image_index(self.swapchain.clone(), image_idx),
|
||||||
@@ -269,7 +279,7 @@ impl VulkanContext {
|
|||||||
fn get_physical_device(
|
fn get_physical_device(
|
||||||
instance: Arc<Instance>,
|
instance: Arc<Instance>,
|
||||||
surface: Arc<Surface>,
|
surface: Arc<Surface>,
|
||||||
extensions: &DeviceExtensions
|
extensions: &DeviceExtensions,
|
||||||
) -> Result<(Arc<PhysicalDevice>, u32), String> {
|
) -> Result<(Arc<PhysicalDevice>, u32), String> {
|
||||||
instance
|
instance
|
||||||
.enumerate_physical_devices()
|
.enumerate_physical_devices()
|
||||||
@@ -285,12 +295,10 @@ impl VulkanContext {
|
|||||||
})
|
})
|
||||||
.map(|q| (dev, q as u32))
|
.map(|q| (dev, q as u32))
|
||||||
})
|
})
|
||||||
.min_by_key(|(dev, _)| {
|
.min_by_key(|(dev, _)| match dev.properties().device_type {
|
||||||
match dev.properties().device_type {
|
|
||||||
PhysicalDeviceType::DiscreteGpu => 0,
|
PhysicalDeviceType::DiscreteGpu => 0,
|
||||||
PhysicalDeviceType::Cpu => 1,
|
PhysicalDeviceType::Cpu => 1,
|
||||||
_ => 2
|
_ => 2,
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.ok_or_else(|| "No physical devices found".to_string())
|
.ok_or_else(|| "No physical devices found".to_string())
|
||||||
}
|
}
|
||||||
@@ -299,7 +307,7 @@ impl VulkanContext {
|
|||||||
fn create_device(
|
fn create_device(
|
||||||
physical_device: Arc<PhysicalDevice>,
|
physical_device: Arc<PhysicalDevice>,
|
||||||
device_extensions: &DeviceExtensions,
|
device_extensions: &DeviceExtensions,
|
||||||
graphics_index: usize
|
graphics_index: usize,
|
||||||
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), String> {
|
) -> Result<(Arc<Device>, impl ExactSizeIterator<Item = Arc<Queue>>), String> {
|
||||||
Device::new(
|
Device::new(
|
||||||
physical_device.clone(),
|
physical_device.clone(),
|
||||||
@@ -310,7 +318,7 @@ impl VulkanContext {
|
|||||||
}],
|
}],
|
||||||
enabled_extensions: device_extensions.clone(),
|
enabled_extensions: device_extensions.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Failed to create device: {e}"))
|
.map_err(|e| format!("Failed to create device: {e}"))
|
||||||
}
|
}
|
||||||
@@ -318,9 +326,10 @@ impl VulkanContext {
|
|||||||
/// Creates a new [`Framebuffer`] for each swapchain image.
|
/// Creates a new [`Framebuffer`] for each swapchain image.
|
||||||
fn create_framebuffers(
|
fn create_framebuffers(
|
||||||
images: &Vec<Arc<Image>>,
|
images: &Vec<Arc<Image>>,
|
||||||
render_pass: &Arc<RenderPass>
|
render_pass: &Arc<RenderPass>,
|
||||||
) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> {
|
) -> Result<Vec<Arc<Framebuffer>>, Box<dyn Error>> {
|
||||||
let framebuffers = images.iter()
|
let framebuffers = images
|
||||||
|
.iter()
|
||||||
.map(|image| {
|
.map(|image| {
|
||||||
let view = ImageView::new_default(image.clone()).unwrap();
|
let view = ImageView::new_default(image.clone()).unwrap();
|
||||||
|
|
||||||
@@ -329,7 +338,7 @@ impl VulkanContext {
|
|||||||
FramebufferCreateInfo {
|
FramebufferCreateInfo {
|
||||||
attachments: vec![view],
|
attachments: vec![view],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
@@ -348,26 +357,27 @@ impl VulkanContext {
|
|||||||
extents: [f32; 2],
|
extents: [f32; 2],
|
||||||
) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> {
|
) -> Result<Arc<GraphicsPipeline>, Box<dyn Error>> {
|
||||||
// Get shader stages
|
// Get shader stages
|
||||||
let vs = vert_shader.entry_point("main")
|
let vs = vert_shader
|
||||||
|
.entry_point("main")
|
||||||
.ok_or("Failed to find vertex shader entry point")?;
|
.ok_or("Failed to find vertex shader entry point")?;
|
||||||
let fs = frag_shader.entry_point("main")
|
let fs = frag_shader
|
||||||
|
.entry_point("main")
|
||||||
.ok_or("Failed to find fragment shader entry point")?;
|
.ok_or("Failed to find fragment shader entry point")?;
|
||||||
|
|
||||||
let vertex_input_state = Vertex3::per_vertex()
|
let vertex_input_state = Vertex3::per_vertex().definition(&vs)?;
|
||||||
.definition(&vs)?;
|
|
||||||
|
|
||||||
let stages = vec![
|
let stages = vec![
|
||||||
PipelineShaderStageCreateInfo::new(vs),
|
PipelineShaderStageCreateInfo::new(vs),
|
||||||
PipelineShaderStageCreateInfo::new(fs),
|
PipelineShaderStageCreateInfo::new(fs),
|
||||||
];
|
];
|
||||||
|
|
||||||
let subpass = Subpass::from(render_pass.clone(), 0)
|
let subpass =
|
||||||
.ok_or("Failed to create pipeline subpass")?;
|
Subpass::from(render_pass.clone(), 0).ok_or("Failed to create pipeline subpass")?;
|
||||||
|
|
||||||
let layout = PipelineLayout::new(
|
let layout = PipelineLayout::new(
|
||||||
device.clone(),
|
device.clone(),
|
||||||
PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages)
|
PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages)
|
||||||
.into_pipeline_layout_create_info(device.clone())?
|
.into_pipeline_layout_create_info(device.clone())?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let viewport = Viewport {
|
let viewport = Viewport {
|
||||||
@@ -392,12 +402,12 @@ impl VulkanContext {
|
|||||||
multisample_state: Some(MultisampleState::default()),
|
multisample_state: Some(MultisampleState::default()),
|
||||||
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
color_blend_state: Some(ColorBlendState::with_attachment_states(
|
||||||
subpass.num_color_attachments(),
|
subpass.num_color_attachments(),
|
||||||
ColorBlendAttachmentState::default()
|
ColorBlendAttachmentState::default(),
|
||||||
)),
|
)),
|
||||||
dynamic_state: Default::default(),
|
dynamic_state: Default::default(),
|
||||||
subpass: Some(subpass.into()),
|
subpass: Some(subpass.into()),
|
||||||
..GraphicsPipelineCreateInfo::layout(layout)
|
..GraphicsPipelineCreateInfo::layout(layout)
|
||||||
}
|
},
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,15 +418,17 @@ impl VulkanContext {
|
|||||||
pipeline: &Arc<GraphicsPipeline>,
|
pipeline: &Arc<GraphicsPipeline>,
|
||||||
framebuffers: &Vec<Arc<Framebuffer>>,
|
framebuffers: &Vec<Arc<Framebuffer>>,
|
||||||
vertex_buffer: &Arc<Subbuffer<[Vertex3]>>,
|
vertex_buffer: &Arc<Subbuffer<[Vertex3]>>,
|
||||||
index_buffer: &Subbuffer<[u32]>
|
index_buffer: &Subbuffer<[u32]>,
|
||||||
) -> Result<Vec<Arc<PrimaryAutoCommandBuffer>>, Box<dyn Error>> {
|
) -> Result<Vec<Arc<PrimaryAutoCommandBuffer>>, Box<dyn Error>> {
|
||||||
let buffers = framebuffers.iter()
|
let buffers = framebuffers
|
||||||
|
.iter()
|
||||||
.filter_map(|framebuffer| {
|
.filter_map(|framebuffer| {
|
||||||
let mut builder = AutoCommandBufferBuilder::primary(
|
let mut builder = AutoCommandBufferBuilder::primary(
|
||||||
cmd_allocator.clone(),
|
cmd_allocator.clone(),
|
||||||
queue.queue_family_index(),
|
queue.queue_family_index(),
|
||||||
CommandBufferUsage::MultipleSubmit
|
CommandBufferUsage::MultipleSubmit,
|
||||||
).ok()?;
|
)
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
builder
|
builder
|
||||||
@@ -428,14 +440,20 @@ impl VulkanContext {
|
|||||||
SubpassBeginInfo {
|
SubpassBeginInfo {
|
||||||
contents: SubpassContents::Inline,
|
contents: SubpassContents::Inline,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
).ok()?
|
)
|
||||||
.bind_pipeline_graphics(pipeline.clone()).ok()?
|
.ok()?
|
||||||
.bind_vertex_buffers(0, vertex_buffer.as_ref().clone()).ok()?
|
.bind_pipeline_graphics(pipeline.clone())
|
||||||
.bind_index_buffer(index_buffer.clone()).ok()?
|
.ok()?
|
||||||
|
.bind_vertex_buffers(0, vertex_buffer.as_ref().clone())
|
||||||
|
.ok()?
|
||||||
|
.bind_index_buffer(index_buffer.clone())
|
||||||
|
.ok()?
|
||||||
// .draw(vertex_buffer.len() as u32, 1, 0, 0).ok()?
|
// .draw(vertex_buffer.len() as u32, 1, 0, 0).ok()?
|
||||||
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0).ok()?
|
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
|
||||||
.end_render_pass(SubpassEndInfo::default()).ok()?;
|
.ok()?
|
||||||
|
.end_render_pass(SubpassEndInfo::default())
|
||||||
|
.ok()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.build().ok()
|
builder.build().ok()
|
||||||
@@ -450,10 +468,11 @@ impl VulkanContext {
|
|||||||
/// specifically the [`GraphicsPipeline`] and [`PrimaryAutoCommandBuffer`]. All information is
|
/// specifically the [`GraphicsPipeline`] and [`PrimaryAutoCommandBuffer`]. All information is
|
||||||
/// automatically set within the `VulkanContext`.
|
/// automatically set within the `VulkanContext`.
|
||||||
pub fn recreate_swapchain(&mut self, resized: bool) -> Result<(), Box<dyn Error>> {
|
pub fn recreate_swapchain(&mut self, resized: bool) -> Result<(), Box<dyn Error>> {
|
||||||
unsafe { self.device.wait_idle()?; };
|
unsafe {
|
||||||
|
self.device.wait_idle()?;
|
||||||
|
};
|
||||||
|
|
||||||
let (new_swapchain, new_images) = self.swapchain
|
let (new_swapchain, new_images) = self.swapchain.recreate(SwapchainCreateInfo {
|
||||||
.recreate(SwapchainCreateInfo {
|
|
||||||
image_extent: self.window.inner_size().into(),
|
image_extent: self.window.inner_size().into(),
|
||||||
..self.swapchain.create_info()
|
..self.swapchain.create_info()
|
||||||
})?;
|
})?;
|
||||||
@@ -462,7 +481,8 @@ impl VulkanContext {
|
|||||||
self.swapchain_images = new_images;
|
self.swapchain_images = new_images;
|
||||||
|
|
||||||
// Recreate the framebuffers, which depend on the swapchain.
|
// Recreate the framebuffers, which depend on the swapchain.
|
||||||
let new_framebuffers = Self::create_framebuffers(&self.swapchain_images, &self.render_pass)?;
|
let new_framebuffers =
|
||||||
|
Self::create_framebuffers(&self.swapchain_images, &self.render_pass)?;
|
||||||
|
|
||||||
self.framebuffers = new_framebuffers;
|
self.framebuffers = new_framebuffers;
|
||||||
|
|
||||||
@@ -482,7 +502,7 @@ impl VulkanContext {
|
|||||||
&new_pipeline,
|
&new_pipeline,
|
||||||
&self.framebuffers,
|
&self.framebuffers,
|
||||||
&self.mesh_registry.vertex_buffer,
|
&self.mesh_registry.vertex_buffer,
|
||||||
&self.mesh_registry.index_buffer
|
&self.mesh_registry.index_buffer,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.pipeline = new_pipeline;
|
self.pipeline = new_pipeline;
|
||||||
@@ -517,11 +537,9 @@ impl MainApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the Vulkan instance.
|
/// Gets the Vulkan instance.
|
||||||
fn get_instance(
|
fn get_instance(required_extensions: InstanceExtensions) -> Result<Arc<Instance>, String> {
|
||||||
required_extensions: InstanceExtensions,
|
let library =
|
||||||
) -> Result<Arc<Instance>, String> {
|
VulkanLibrary::new().map_err(|e| format!("Failed to find Vulkan library: {e}"))?;
|
||||||
let library = VulkanLibrary::new()
|
|
||||||
.map_err(|e| format!("Failed to find Vulkan library: {e}"))?;
|
|
||||||
|
|
||||||
Instance::new(
|
Instance::new(
|
||||||
library,
|
library,
|
||||||
@@ -529,7 +547,7 @@ impl MainApplication {
|
|||||||
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
|
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
|
||||||
enabled_extensions: required_extensions,
|
enabled_extensions: required_extensions,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Failed to create instance: {e}"))
|
.map_err(|e| format!("Failed to create instance: {e}"))
|
||||||
}
|
}
|
||||||
@@ -537,28 +555,35 @@ impl MainApplication {
|
|||||||
|
|
||||||
impl ApplicationHandler for MainApplication {
|
impl ApplicationHandler for MainApplication {
|
||||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||||
self.context.is_none()
|
self.context.is_none().then(|| {
|
||||||
.then(|| {
|
|
||||||
// Initialization logic
|
// Initialization logic
|
||||||
let context = VulkanContext::init(
|
let context = VulkanContext::init(self.instance.clone(), event_loop)
|
||||||
self.instance.clone(),
|
.expect("Couldn't initialize VulkanContext");
|
||||||
event_loop
|
|
||||||
).expect("Couldn't initialize VulkanContext");
|
|
||||||
|
|
||||||
self.context = Some(context);
|
self.context = Some(context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) {
|
fn window_event(
|
||||||
|
&mut self,
|
||||||
|
event_loop: &ActiveEventLoop,
|
||||||
|
window_id: WindowId,
|
||||||
|
event: WindowEvent,
|
||||||
|
) {
|
||||||
match event {
|
match event {
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
println!("Closing window.");
|
println!("Closing window.");
|
||||||
event_loop.exit();
|
event_loop.exit();
|
||||||
}
|
}
|
||||||
WindowEvent::Resized(dimensions) => {
|
WindowEvent::Resized(dimensions) => {
|
||||||
println!("Window was resized, recreating swapchain. New dimensions: {:?}", dimensions);
|
println!(
|
||||||
|
"Window was resized, recreating swapchain. New dimensions: {:?}",
|
||||||
|
dimensions
|
||||||
|
);
|
||||||
if let Some(context) = self.context.as_mut() {
|
if let Some(context) = self.context.as_mut() {
|
||||||
context.recreate_swapchain(true).expect("Failed to recreate swapchain");
|
context
|
||||||
|
.recreate_swapchain(true)
|
||||||
|
.expect("Failed to recreate swapchain");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
@@ -569,7 +594,7 @@ impl ApplicationHandler for MainApplication {
|
|||||||
// Queue the next frame for drawing.
|
// Queue the next frame for drawing.
|
||||||
self.context.as_ref().unwrap().window.request_redraw();
|
self.context.as_ref().unwrap().window.request_redraw();
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use nalgebra::{Matrix4, Vector3, Vector4};
|
|
||||||
use crate::common::scene::SceneInstance;
|
use crate::common::scene::SceneInstance;
|
||||||
|
use nalgebra::{Matrix4, Vector3, Vector4};
|
||||||
|
|
||||||
/// Contains all information about an instance of a mesh, specifically its translation, rotation,
|
/// Contains all information about an instance of a mesh, specifically its translation, rotation,
|
||||||
/// and scale. Note that the rotation is a [`Vector4`], and not a `Quaternion`.
|
/// and scale. Note that the rotation is a [`Vector4`], and not a `Quaternion`.
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
|
pub mod instance;
|
||||||
pub mod mesh;
|
pub mod mesh;
|
||||||
pub mod scene;
|
pub mod scene;
|
||||||
pub mod instance;
|
|
||||||
+8
-7
@@ -1,7 +1,7 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
/// A scene, which holds all information required to render a world.
|
/// A scene, which holds all information required to render a world.
|
||||||
///
|
///
|
||||||
@@ -26,8 +26,7 @@ pub struct Scene {
|
|||||||
impl Scene {
|
impl Scene {
|
||||||
/// Converts this `Scene` into its byte representation.
|
/// Converts this `Scene` into its byte representation.
|
||||||
pub fn bytes(&self) -> Vec<u8> {
|
pub fn bytes(&self) -> Vec<u8> {
|
||||||
postcard::to_allocvec(self)
|
postcard::to_allocvec(self).expect("Couldn't serialize scene")
|
||||||
.expect("Couldn't serialize scene")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a `scene` from the given path. Automatically resolves all paths for the meshes that
|
/// Reads a `scene` from the given path. Automatically resolves all paths for the meshes that
|
||||||
@@ -43,18 +42,20 @@ impl Scene {
|
|||||||
let mut contents = Vec::new();
|
let mut contents = Vec::new();
|
||||||
let _ = file.read_to_end(&mut contents).unwrap();
|
let _ = file.read_to_end(&mut contents).unwrap();
|
||||||
|
|
||||||
let mut scene: Self = postcard::from_bytes(contents.as_slice())
|
let mut scene: Self =
|
||||||
.expect("Couldn't deserialize scene");
|
postcard::from_bytes(contents.as_slice()).expect("Couldn't deserialize scene");
|
||||||
|
|
||||||
let base = path.parent().unwrap_or(&Path::new("."));
|
let base = path.parent().unwrap_or(&Path::new("."));
|
||||||
scene.mesh_paths = scene.mesh_paths
|
scene.mesh_paths = scene
|
||||||
|
.mesh_paths
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(id, mesh_path)| {
|
.map(|(id, mesh_path)| {
|
||||||
let res = base.join(mesh_path);
|
let res = base.join(mesh_path);
|
||||||
let str = res.to_str().unwrap_or_default();
|
let str = res.to_str().unwrap_or_default();
|
||||||
|
|
||||||
(id, str.to_string())
|
(id, str.to_string())
|
||||||
}).collect::<HashMap<String, String>>();
|
})
|
||||||
|
.collect::<HashMap<String, String>>();
|
||||||
|
|
||||||
scene
|
scene
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
|
use crate::common::instance::MeshInstance;
|
||||||
use vulkano::buffer::BufferContents;
|
use vulkano::buffer::BufferContents;
|
||||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
||||||
use crate::common::instance::MeshInstance;
|
|
||||||
|
|
||||||
/// A transformation matrix for a mesh that can be passed into the shaders.
|
/// A transformation matrix for a mesh that can be passed into the shaders.
|
||||||
#[derive(BufferContents, Vertex)]
|
#[derive(BufferContents, Vertex)]
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
pub mod vertex3;
|
|
||||||
pub mod instance;
|
pub mod instance;
|
||||||
|
pub mod vertex3;
|
||||||
+6
-4
@@ -1,15 +1,17 @@
|
|||||||
use vulkano::buffer::BufferContents;
|
use vulkano::buffer::BufferContents;
|
||||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
||||||
|
|
||||||
#[derive(Debug, BufferContents, Vertex)]
|
#[derive(Debug, Clone, BufferContents, Vertex)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Vertex3 {
|
pub struct Vertex3 {
|
||||||
#[format(R32G32B32_SFLOAT)]
|
#[format(R32G32B32_SFLOAT)]
|
||||||
pub(crate) position: [f32; 3],
|
pub(crate) position: [f32; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[f32; 3]> for Vertex3 {
|
impl From<[f32; 3]> for Vertex3 {
|
||||||
fn from(v: &[f32; 3]) -> Self {
|
fn from(v: [f32; 3]) -> Self {
|
||||||
Self { position: v.clone() }
|
Self {
|
||||||
|
position: v.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-5
@@ -1,30 +1,30 @@
|
|||||||
mod app;
|
mod app;
|
||||||
pub mod math;
|
|
||||||
mod common;
|
mod common;
|
||||||
pub mod gpu;
|
pub mod gpu;
|
||||||
|
// pub mod math;
|
||||||
|
|
||||||
|
use crate::app::MainApplication;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use vulkano::swapchain::Surface;
|
use vulkano::swapchain::Surface;
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
use crate::app::MainApplication;
|
|
||||||
|
|
||||||
// Compute shader compilation. Happens at runtime, but file contents are included during compilation.
|
// Compute shader compilation. Happens at runtime, but file contents are included during compilation.
|
||||||
mod cs {
|
mod cs {
|
||||||
vulkano_shaders::shader!{
|
vulkano_shaders::shader! {
|
||||||
ty: "compute",
|
ty: "compute",
|
||||||
path: "src/shaders/comp.glsl",
|
path: "src/shaders/comp.glsl",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod mandelbrot_shader {
|
mod mandelbrot_shader {
|
||||||
vulkano_shaders::shader!{
|
vulkano_shaders::shader! {
|
||||||
ty: "compute",
|
ty: "compute",
|
||||||
path: "src/shaders/mandelbrot.glsl"
|
path: "src/shaders/mandelbrot.glsl"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod triangle {
|
mod triangle {
|
||||||
vulkano_shaders::shader!{
|
vulkano_shaders::shader! {
|
||||||
shaders: {
|
shaders: {
|
||||||
vertex: {
|
vertex: {
|
||||||
ty: "vertex",
|
ty: "vertex",
|
||||||
|
|||||||
+4
-10
@@ -1,6 +1,6 @@
|
|||||||
use std::ops::{Add, Index, IndexMut, Mul, Sub};
|
use crate::math::Vector2;
|
||||||
use crate::math::traits::{Matrix, Vector};
|
use crate::math::traits::{Matrix, Vector};
|
||||||
use crate::math::{Vector2};
|
use std::ops::{Add, Index, IndexMut, Mul, Sub};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Copy, Default)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Copy, Default)]
|
||||||
pub struct Matrix2 {
|
pub struct Matrix2 {
|
||||||
@@ -14,17 +14,11 @@ impl Matrix2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn row_vector(&self, row: usize) -> Vector2 {
|
pub fn row_vector(&self, row: usize) -> Vector2 {
|
||||||
Vector2::from([
|
Vector2::from([self[row][0], self[row][1]])
|
||||||
self[row][0],
|
|
||||||
self[row][1],
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn column_vector(&self, col: usize) -> Vector2 {
|
pub fn column_vector(&self, col: usize) -> Vector2 {
|
||||||
Vector2::from([
|
Vector2::from([self[0][col], self[1][col]])
|
||||||
self[0][col],
|
|
||||||
self[1][col],
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
+31
-8
@@ -1,6 +1,6 @@
|
|||||||
use std::ops::{Add, Div, Mul, Sub};
|
|
||||||
use crate::math::traits::{Matrix, Vector};
|
|
||||||
use crate::math::Vector4;
|
use crate::math::Vector4;
|
||||||
|
use crate::math::traits::{Matrix, Vector};
|
||||||
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Copy, PartialEq)]
|
#[derive(Debug, Clone, Default, Copy, PartialEq)]
|
||||||
pub struct Matrix4 {
|
pub struct Matrix4 {
|
||||||
@@ -10,8 +10,7 @@ pub struct Matrix4 {
|
|||||||
row4: Vector4,
|
row4: Vector4,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Matrix4 {
|
impl Matrix4 {}
|
||||||
}
|
|
||||||
|
|
||||||
impl Add for Matrix4 {
|
impl Add for Matrix4 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
@@ -68,10 +67,34 @@ impl Mul for Matrix4 {
|
|||||||
fn mul(self, rhs: Self) -> Self {
|
fn mul(self, rhs: Self) -> Self {
|
||||||
let rhs = rhs.transpose();
|
let rhs = rhs.transpose();
|
||||||
Self {
|
Self {
|
||||||
row1: [self.row1.dot(rhs.row1), self.row1.dot(rhs.row2), self.row1.dot(rhs.row3), self.row1.dot(rhs.row4)].into(),
|
row1: [
|
||||||
row2: [self.row2.dot(rhs.row1), self.row2.dot(rhs.row2), self.row2.dot(rhs.row3), self.row2.dot(rhs.row4)].into(),
|
self.row1.dot(rhs.row1),
|
||||||
row3: [self.row3.dot(rhs.row1), self.row3.dot(rhs.row2), self.row3.dot(rhs.row3), self.row3.dot(rhs.row4)].into(),
|
self.row1.dot(rhs.row2),
|
||||||
row4: [self.row4.dot(rhs.row1), self.row4.dot(rhs.row2), self.row4.dot(rhs.row3), self.row4.dot(rhs.row4)].into(),
|
self.row1.dot(rhs.row3),
|
||||||
|
self.row1.dot(rhs.row4),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
row2: [
|
||||||
|
self.row2.dot(rhs.row1),
|
||||||
|
self.row2.dot(rhs.row2),
|
||||||
|
self.row2.dot(rhs.row3),
|
||||||
|
self.row2.dot(rhs.row4),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
row3: [
|
||||||
|
self.row3.dot(rhs.row1),
|
||||||
|
self.row3.dot(rhs.row2),
|
||||||
|
self.row3.dot(rhs.row3),
|
||||||
|
self.row3.dot(rhs.row4),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
row4: [
|
||||||
|
self.row4.dot(rhs.row1),
|
||||||
|
self.row4.dot(rhs.row2),
|
||||||
|
self.row4.dot(rhs.row3),
|
||||||
|
self.row4.dot(rhs.row4),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -1,14 +1,14 @@
|
|||||||
mod matrix4;
|
|
||||||
mod vector3;
|
|
||||||
mod vector2;
|
|
||||||
mod traits;
|
|
||||||
mod matrix3;
|
|
||||||
mod matrix2;
|
mod matrix2;
|
||||||
|
mod matrix3;
|
||||||
|
mod matrix4;
|
||||||
|
mod traits;
|
||||||
|
mod vector2;
|
||||||
|
mod vector3;
|
||||||
mod vector4;
|
mod vector4;
|
||||||
|
|
||||||
pub use matrix4::*;
|
|
||||||
pub use matrix3::*;
|
|
||||||
pub use matrix2::*;
|
pub use matrix2::*;
|
||||||
pub use vector4::*;
|
pub use matrix3::*;
|
||||||
pub use vector3::*;
|
pub use matrix4::*;
|
||||||
pub use vector2::*;
|
pub use vector2::*;
|
||||||
|
pub use vector3::*;
|
||||||
|
pub use vector4::*;
|
||||||
+23
-6
@@ -1,8 +1,17 @@
|
|||||||
use std::ops::{Add, Div, Mul, Sub};
|
|
||||||
use crate::math::Vector4;
|
use crate::math::Vector4;
|
||||||
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
pub trait Vector: Clone + Copy + Default + PartialEq + Add + Sub + PartialOrd
|
pub trait Vector:
|
||||||
+ Div<f32, Output = Self> + Mul<f32, Output = Self> {
|
Clone
|
||||||
|
+ Copy
|
||||||
|
+ Default
|
||||||
|
+ PartialEq
|
||||||
|
+ Add
|
||||||
|
+ Sub
|
||||||
|
+ PartialOrd
|
||||||
|
+ Div<f32, Output = Self>
|
||||||
|
+ Mul<f32, Output = Self>
|
||||||
|
{
|
||||||
/// Gets the dot product of the two vectors.
|
/// Gets the dot product of the two vectors.
|
||||||
fn dot(self, other: Self) -> f32;
|
fn dot(self, other: Self) -> f32;
|
||||||
|
|
||||||
@@ -36,10 +45,18 @@ pub trait Vector: Clone + Copy + Default + PartialEq + Add + Sub + PartialOrd
|
|||||||
/// Note that this trait does not require implementation of the `Div` trait at all - this is because
|
/// Note that this trait does not require implementation of the `Div` trait at all - this is because
|
||||||
/// matrices do not have division, only multiplication by a scalar value. This doesn't mean that the
|
/// matrices do not have division, only multiplication by a scalar value. This doesn't mean that the
|
||||||
/// scalar cannot be a decimal value, however.
|
/// scalar cannot be a decimal value, however.
|
||||||
pub trait Matrix<TVec>: Clone + Copy + Default + PartialEq + Add + Sub
|
pub trait Matrix<TVec>:
|
||||||
+ Mul<f32, Output = Self> + Mul<TVec, Output = TVec>
|
Clone
|
||||||
|
+ Copy
|
||||||
|
+ Default
|
||||||
|
+ PartialEq
|
||||||
|
+ Add
|
||||||
|
+ Sub
|
||||||
|
+ Mul<f32, Output = Self>
|
||||||
|
+ Mul<TVec, Output = TVec>
|
||||||
+ Mul<Output = Self>
|
+ Mul<Output = Self>
|
||||||
where TVec: Vector
|
where
|
||||||
|
TVec: Vector,
|
||||||
{
|
{
|
||||||
/// Creates an identity matrix.
|
/// Creates an identity matrix.
|
||||||
fn identity() -> Self;
|
fn identity() -> Self;
|
||||||
|
|||||||
+3
-9
@@ -1,5 +1,5 @@
|
|||||||
use std::ops::{Add, Div, Mul, Sub, Index, IndexMut};
|
|
||||||
use crate::math::traits::Vector;
|
use crate::math::traits::Vector;
|
||||||
|
use std::ops::{Add, Div, Index, IndexMut, Mul, Sub};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
||||||
pub struct Vector2 {
|
pub struct Vector2 {
|
||||||
@@ -118,18 +118,12 @@ impl Vector for Vector2 {
|
|||||||
|
|
||||||
impl From<[f32; 2]> for Vector2 {
|
impl From<[f32; 2]> for Vector2 {
|
||||||
fn from(v: [f32; 2]) -> Self {
|
fn from(v: [f32; 2]) -> Self {
|
||||||
Self {
|
Self { x: v[0], y: v[1] }
|
||||||
x: v[0],
|
|
||||||
y: v[1],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<f32> for Vector2 {
|
impl From<f32> for Vector2 {
|
||||||
fn from(v: f32) -> Self {
|
fn from(v: f32) -> Self {
|
||||||
Self {
|
Self { x: v, y: 0.0 }
|
||||||
x: v,
|
|
||||||
y: 0.0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-17
@@ -1,6 +1,6 @@
|
|||||||
use std::ops::{Add, Div, Mul, Sub};
|
|
||||||
use crate::math::traits::Vector;
|
use crate::math::traits::Vector;
|
||||||
use crate::math::vector2::Vector2;
|
use crate::math::vector2::Vector2;
|
||||||
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
||||||
pub struct Vector3 {
|
pub struct Vector3 {
|
||||||
@@ -15,24 +15,15 @@ impl Vector3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn xy(&self) -> Vector2 {
|
pub fn xy(&self) -> Vector2 {
|
||||||
Vector2::from([
|
Vector2::from([self.x, self.y])
|
||||||
self.x,
|
|
||||||
self.y
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yz(&self) -> Vector2 {
|
pub fn yz(&self) -> Vector2 {
|
||||||
Vector2::from([
|
Vector2::from([self.y, self.z])
|
||||||
self.y,
|
|
||||||
self.z
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xz(&self) -> Vector2 {
|
pub fn xz(&self) -> Vector2 {
|
||||||
Vector2::from([
|
Vector2::from([self.x, self.z])
|
||||||
self.x,
|
|
||||||
self.z
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn xyz(&self) -> (f32, f32, f32) {
|
pub fn xyz(&self) -> (f32, f32, f32) {
|
||||||
@@ -144,9 +135,6 @@ impl From<[f32; 3]> for Vector3 {
|
|||||||
|
|
||||||
impl From<Vector2> for Vector3 {
|
impl From<Vector2> for Vector3 {
|
||||||
fn from(v: Vector2) -> Self {
|
fn from(v: Vector2) -> Self {
|
||||||
Self {
|
Self { z: 0.0, ..v.into() }
|
||||||
z: 0.0,
|
|
||||||
..v.into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-21
@@ -1,6 +1,6 @@
|
|||||||
use std::ops::{Add, Div, Mul, Sub};
|
|
||||||
use crate::math::traits::Vector;
|
use crate::math::traits::Vector;
|
||||||
use crate::math::{Vector2, Vector3};
|
use crate::math::{Vector2, Vector3};
|
||||||
|
use std::ops::{Add, Div, Mul, Sub};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
|
||||||
pub struct Vector4 {
|
pub struct Vector4 {
|
||||||
@@ -11,15 +11,8 @@ pub struct Vector4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Vector4 {
|
impl Vector4 {
|
||||||
pub fn new(
|
pub fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
|
||||||
x: f32,
|
Self { x, y, z, w }
|
||||||
y: f32,
|
|
||||||
z: f32,
|
|
||||||
w: f32,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
x, y, z, w
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn one() -> Self {
|
pub fn one() -> Self {
|
||||||
@@ -150,28 +143,20 @@ impl Vector for Vector4 {
|
|||||||
|
|
||||||
impl From<[f32; 4]> for Vector4 {
|
impl From<[f32; 4]> for Vector4 {
|
||||||
fn from([x, y, z, w]: [f32; 4]) -> Self {
|
fn from([x, y, z, w]: [f32; 4]) -> Self {
|
||||||
Self {
|
Self { x, y, z, w }
|
||||||
x, y, z, w,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<[f32; 3]> for Vector4 {
|
impl From<[f32; 3]> for Vector4 {
|
||||||
/// Creates a homogenous `Vector4` from a 3D positional vector.
|
/// Creates a homogenous `Vector4` from a 3D positional vector.
|
||||||
fn from([x, y, z]: [f32; 3]) -> Self {
|
fn from([x, y, z]: [f32; 3]) -> Self {
|
||||||
Self {
|
Self { x, y, z, w: 1.0 }
|
||||||
x, y, z,
|
|
||||||
w: 1.0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Vector3> for Vector4 {
|
impl From<Vector3> for Vector4 {
|
||||||
fn from(Vector3 { x, y, z }: Vector3) -> Self {
|
fn from(Vector3 { x, y, z }: Vector3) -> Self {
|
||||||
Self {
|
Self { x, y, z, w: 1.0 }
|
||||||
x, y, z,
|
|
||||||
w: 1.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user