No warns
This commit is contained in:
37
src/gui.rs
37
src/gui.rs
@@ -3,7 +3,7 @@ use crate::{
|
||||
light::Light,
|
||||
primitive::*,
|
||||
scene::{Node, Scene},
|
||||
state::INIT_FILE,
|
||||
state::{INIT_FILE, SAVE_FILE},
|
||||
UP_VECTOR_F32, ZERO_VECTOR_F32,
|
||||
};
|
||||
use imgui::*;
|
||||
@@ -12,13 +12,13 @@ use pixels::{wgpu, PixelsContext};
|
||||
use rhai::Engine;
|
||||
use std::time::Instant;
|
||||
|
||||
const BUFFER_PROPORTION_INIT: f32 = 1.0;
|
||||
const BUFFER_PROPORTION_MIN: f32 = 0.5;
|
||||
const BUFFER_PROPORTION_INIT: f32 = 0.2;
|
||||
const BUFFER_PROPORTION_MIN: f32 = 0.1;
|
||||
const BUFFER_PROPORTION_MAX: f32 = 1.0;
|
||||
|
||||
const RAYS_INIT: i32 = 1000;
|
||||
const RAYS_MIN: i32 = 100;
|
||||
const RAYS_MAX: i32 = 100000;
|
||||
const RAYS_MAX: i32 = 30000;
|
||||
|
||||
const CAMERA_MIN_FOV: f32 = 10.0;
|
||||
const CAMERA_MAX_FOV: f32 = 160.0;
|
||||
@@ -29,6 +29,7 @@ pub enum GuiEvent {
|
||||
BufferResize(f32, f32),
|
||||
CameraUpdate(Camera),
|
||||
SceneLoad(Scene),
|
||||
SaveImage(String),
|
||||
}
|
||||
|
||||
pub struct Gui {
|
||||
@@ -53,6 +54,8 @@ pub struct Gui {
|
||||
camera_target: [f32; 3],
|
||||
camera_up: [f32; 3],
|
||||
camera_fov: f32,
|
||||
|
||||
image_filename: String,
|
||||
}
|
||||
|
||||
impl Gui {
|
||||
@@ -115,6 +118,8 @@ impl Gui {
|
||||
camera_target: ZERO_VECTOR_F32.into(),
|
||||
camera_up: UP_VECTOR_F32.into(),
|
||||
camera_fov: 110.0,
|
||||
|
||||
image_filename: String::from(SAVE_FILE),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,11 +221,25 @@ impl Gui {
|
||||
Err(e) => println!("{e}"),
|
||||
}
|
||||
}
|
||||
if ui.button("Save script") {
|
||||
match std::fs::write(&self.script_filename, &self.script) {
|
||||
Ok(_) => println!("Script saved successfully"),
|
||||
Err(e) => println!("{}", e),
|
||||
}
|
||||
}
|
||||
//Script block
|
||||
ui.input_text_multiline("script", &mut self.script, [600., 1500.])
|
||||
.build();
|
||||
}
|
||||
|
||||
if CollapsingHeader::new("Image").build(ui) {
|
||||
ui.input_text("Image file", &mut self.image_filename)
|
||||
.build();
|
||||
if ui.button("Save Image") {
|
||||
self.event = Some(GuiEvent::SaveImage(self.image_filename.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
// Render Dear ImGui with WGPU
|
||||
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||
label: Some("imgui"),
|
||||
@@ -270,7 +289,9 @@ pub fn init_engine() -> Engine {
|
||||
.register_type::<Scene>()
|
||||
.register_fn("Scene", Scene::empty)
|
||||
.register_fn("addNode", Scene::add_node)
|
||||
.register_fn("addLight", Scene::add_light);
|
||||
.register_fn("addLight", Scene::add_light)
|
||||
.register_fn("addCamera", Scene::add_camera)
|
||||
.register_fn("addMaterial", Scene::add_material);
|
||||
|
||||
engine
|
||||
.register_type::<Node>()
|
||||
@@ -281,7 +302,8 @@ pub fn init_engine() -> Engine {
|
||||
.register_fn("child", Node::child);
|
||||
engine
|
||||
.register_type::<Light>()
|
||||
.register_fn("Light", Light::new);
|
||||
.register_fn("Light", Light::new)
|
||||
.register_fn("Ambient", Light::ambient);
|
||||
engine
|
||||
.register_type::<Material>()
|
||||
.register_fn("Material", Material::new)
|
||||
@@ -319,6 +341,9 @@ pub fn init_engine() -> Engine {
|
||||
engine
|
||||
.register_type::<Torus>()
|
||||
.register_fn("Torus", Torus::new);
|
||||
engine
|
||||
.register_type::<Mesh>()
|
||||
.register_fn("Mesh", Mesh::from_file);
|
||||
engine
|
||||
.register_type::<Gnonom>()
|
||||
.register_fn("Gnonom", Gnonom::new);
|
||||
|
||||
13
src/light.rs
13
src/light.rs
@@ -5,6 +5,7 @@ pub struct Light {
|
||||
pub position: Point3<f64>,
|
||||
pub colour: Vector3<f64>,
|
||||
pub falloff: Vector3<f64>,
|
||||
pub ambient: bool,
|
||||
}
|
||||
|
||||
impl Light {
|
||||
@@ -13,11 +14,15 @@ impl Light {
|
||||
position,
|
||||
colour,
|
||||
falloff,
|
||||
ambient: false,
|
||||
}
|
||||
}
|
||||
pub fn white(position: Point3<f64>) -> Self {
|
||||
let colour = Vector3::new(1.0, 1.0, 1.0);
|
||||
let falloff = Vector3::new(1.0, 0.0, 0.0);
|
||||
Light::new(position, colour, falloff)
|
||||
pub fn ambient(colour: Vector3<f64>) -> Self {
|
||||
Light {
|
||||
position: Point3::new(0.0, 0.0, 0.0),
|
||||
colour,
|
||||
falloff: Vector3::new(0.0, 0.0, 0.0),
|
||||
ambient: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ const EPSILON: f64 = 1e-6;
|
||||
const INFINITY: f64 = f64::MAX;
|
||||
const EPSILON_VECTOR: Vector3<f64> = Vector3::new(EPSILON, EPSILON, EPSILON);
|
||||
static ZERO_VECTOR: Vector3<f64> = Vector3::new(0.0, 0.0, 0.0);
|
||||
static UP_VECTOR: Vector3<f64> = Vector3::new(0.0, 1.0, 0.0);
|
||||
static ZERO_VECTOR_F32: Vector3<f32> = Vector3::new(0.0, 0.0, 0.0);
|
||||
static UP_VECTOR_F32: Vector3<f32> = Vector3::new(0.0, 1.0, 0.0);
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ impl Intersection {
|
||||
|
||||
// BOUNDING BOX -----------------------------------------------------------------
|
||||
#[derive(Clone)]
|
||||
|
||||
struct BoundingBox {
|
||||
bln: Point3<f64>,
|
||||
trf: Point3<f64>,
|
||||
@@ -97,6 +98,7 @@ impl BoundingBox {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
fn get_centroid(&self) -> Point3<f64> {
|
||||
self.bln + (self.trf - self.bln) / 2.0
|
||||
}
|
||||
@@ -689,7 +691,8 @@ impl Primitive for Cube {
|
||||
|
||||
// TRIANGLE -----------------------------------------------------------------
|
||||
#[derive(Clone)]
|
||||
struct Triangle {
|
||||
#[allow(dead_code)]
|
||||
pub struct Triangle {
|
||||
u: Point3<f64>,
|
||||
v: Point3<f64>,
|
||||
w: Point3<f64>,
|
||||
@@ -699,7 +702,7 @@ struct Triangle {
|
||||
}
|
||||
|
||||
impl Triangle {
|
||||
fn new(
|
||||
pub fn new(
|
||||
u: Point3<f64>,
|
||||
v: Point3<f64>,
|
||||
w: Point3<f64>,
|
||||
@@ -720,6 +723,7 @@ impl Triangle {
|
||||
bounding_box,
|
||||
})
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn unit(material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
let u = Point3::new(-1.0, 0.0, -1.0);
|
||||
let v = Point3::new(0.0, 0.0, 1.0);
|
||||
@@ -780,14 +784,15 @@ impl Primitive for Triangle {
|
||||
|
||||
// MESH -----------------------------------------------------------------
|
||||
#[derive(Clone)]
|
||||
struct Mesh {
|
||||
pub struct Mesh {
|
||||
triangles: Vec<Arc<Triangle>>,
|
||||
material: Arc<Material>,
|
||||
bounding_box: BoundingBox,
|
||||
}
|
||||
|
||||
impl Mesh {
|
||||
fn new(triangles: Vec<Arc<Triangle>>, material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(triangles: Vec<Arc<Triangle>>, material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
// Calculate the bounding box for the entire mesh based on the bounding boxes of individual triangles
|
||||
let bounding_box = Mesh::compute_bounding_box(&triangles);
|
||||
|
||||
@@ -798,6 +803,7 @@ impl Mesh {
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn compute_bounding_box(triangles: &Vec<Arc<Triangle>>) -> BoundingBox {
|
||||
let mut bln = Point3::new(INFINITY, INFINITY, INFINITY);
|
||||
let mut trf = -bln;
|
||||
@@ -813,7 +819,7 @@ impl Mesh {
|
||||
BoundingBox { bln, trf }
|
||||
}
|
||||
|
||||
fn from_file(filename: &str, material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
pub fn from_file(filename: &str, material: Arc<Material>) -> Arc<dyn Primitive> {
|
||||
let mut triangles: Vec<Arc<dyn Primitive>> = Vec::new();
|
||||
let mut vertices: Vec<Point3<f64>> = Vec::new();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
primitive::{self, Intersection},
|
||||
primitive::Intersection,
|
||||
raytracer::phong_shade_point,
|
||||
scene::{Node, Scene},
|
||||
EPSILON, INFINITY,
|
||||
INFINITY,
|
||||
};
|
||||
use nalgebra::{Matrix4, Point3, Vector3};
|
||||
|
||||
@@ -12,6 +12,7 @@ pub struct Ray {
|
||||
pub b: Vector3<f64>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl Ray {
|
||||
pub fn new(a: Point3<f64>, b: Vector3<f64>) -> Ray {
|
||||
Ray {
|
||||
@@ -45,7 +46,7 @@ impl Ray {
|
||||
for node in nodes {
|
||||
let primitive = node.primitive.clone();
|
||||
|
||||
//Transform ray to view coords
|
||||
//Transform ray from view coords
|
||||
let ray = self.transform(&node.inv_viewmodel);
|
||||
|
||||
if primitive.intersect_bounding_box(&ray).is_some() {
|
||||
@@ -54,6 +55,7 @@ impl Ray {
|
||||
closest_distance = intersect.distance;
|
||||
//Convert back to world coords
|
||||
let intersect = intersect.transform(&node.model, &node.inv_model);
|
||||
|
||||
closest_intersect = Some(intersect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,14 @@ pub fn phong_shade_point(scene: &Scene, intersect: &Intersection) -> Vector3<u8>
|
||||
position: light_position,
|
||||
colour: light_colour,
|
||||
falloff: light_falloff,
|
||||
ambient: light_ambient,
|
||||
} = light;
|
||||
|
||||
if *light_ambient {
|
||||
colour += light_colour;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Point to light
|
||||
let to_light = light_position - point;
|
||||
let light_distance = to_light.norm();
|
||||
|
||||
21
src/state.rs
21
src/state.rs
@@ -4,6 +4,7 @@ use crate::camera::Camera;
|
||||
use crate::ray::Ray;
|
||||
use crate::{gui::Gui, scene::Scene};
|
||||
use crate::{gui::GuiEvent, log_error};
|
||||
use std::path::Path;
|
||||
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
@@ -19,11 +20,12 @@ use winit::event::{Event, KeyboardInput, MouseButton, VirtualKeyCode, WindowEven
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{Window, WindowBuilder};
|
||||
|
||||
const START_WIDTH: i32 = 1400;
|
||||
const START_HEIGHT: i32 = 1000;
|
||||
const START_WIDTH: i32 = 1200;
|
||||
const START_HEIGHT: i32 = 1200;
|
||||
const COLOUR_CLEAR: [u8; 4] = [0x22, 0x00, 0x11, 0xff];
|
||||
|
||||
pub const INIT_FILE: &str = "scene.rhai";
|
||||
pub const SAVE_FILE: &str = "img.png";
|
||||
|
||||
pub struct State {
|
||||
scene: Scene,
|
||||
@@ -75,6 +77,17 @@ impl State {
|
||||
self.scene = scene;
|
||||
self.reset_queue();
|
||||
}
|
||||
GuiEvent::SaveImage(filename) => {
|
||||
let pixels = self.pixels.lock().unwrap();
|
||||
let frame = pixels.frame();
|
||||
image::save_buffer(
|
||||
Path::new(&filename),
|
||||
frame,
|
||||
self.buffer_width,
|
||||
self.buffer_height,
|
||||
image::ColorType::Rgba8,
|
||||
)?
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
@@ -93,13 +106,11 @@ impl State {
|
||||
|
||||
let mut pixels = self.pixels.lock().unwrap();
|
||||
pixels.resize_buffer(self.buffer_width, self.buffer_height)?;
|
||||
pixels.resize_surface(size.width, size.height)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resize(&mut self, size: &PhysicalSize<u32>) -> Result<(), Box<dyn Error>> {
|
||||
self.buffer_width = (size.width) as u32;
|
||||
self.buffer_height = (size.height) as u32;
|
||||
self.reset_queue();
|
||||
let mut pixels = self.pixels.lock().unwrap();
|
||||
pixels.resize_surface(size.width, size.height)?;
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user