Compare commits
6 Commits
98fbf892bc
...
a40ba66209
| Author | SHA1 | Date | |
|---|---|---|---|
| a40ba66209 | |||
| 9c29ccb8ec | |||
| 24b33f8146 | |||
| 1d9ff55163 | |||
| 3d150208e0 | |||
| 6012c480de |
18
.kateproject.build
Normal file
18
.kateproject.build
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"Auto_generated": "This file is auto-generated. Any extra tags or formatting will be lost",
|
||||||
|
"target_sets": [
|
||||||
|
{
|
||||||
|
"cmake_config": "",
|
||||||
|
"directory": "%B",
|
||||||
|
"loaded_via_cmake": false,
|
||||||
|
"name": "Cargo",
|
||||||
|
"targets": [
|
||||||
|
{
|
||||||
|
"build_cmd": "cargo build --bin wireframe",
|
||||||
|
"name": "wireframe",
|
||||||
|
"run_cmd": "cargo run --bin wireframe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
936
Cargo.lock
generated
936
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
|
@ -21,6 +21,8 @@ show-image = "0.14.0"
|
||||||
flo_draw = "0.3.1"
|
flo_draw = "0.3.1"
|
||||||
flo_canvas = "0.3.1"
|
flo_canvas = "0.3.1"
|
||||||
itertools-num = "0.1.3"
|
itertools-num = "0.1.3"
|
||||||
|
glium = "0.35.0"
|
||||||
|
winit = "0.30.5"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
approx = "0.5.1"
|
approx = "0.5.1"
|
||||||
|
|
|
||||||
200
src/bin/wireframe/main.rs
Normal file
200
src/bin/wireframe/main.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
use glam::{mat4, vec2, vec3, vec4, Mat4, Quat, Vec2, Vec3};
|
||||||
|
use glium::{
|
||||||
|
backend::glutin::SimpleWindowBuilder,
|
||||||
|
implement_vertex, uniform,
|
||||||
|
winit::event::{Event, WindowEvent},
|
||||||
|
Program, Surface, VertexBuffer,
|
||||||
|
};
|
||||||
|
use winit::{event::ElementState, event_loop::EventLoop};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct Vertex {
|
||||||
|
position: [f32; 3],
|
||||||
|
}
|
||||||
|
implement_vertex!(Vertex, position);
|
||||||
|
|
||||||
|
struct DragCtl<S> {
|
||||||
|
state: S,
|
||||||
|
ctl: Option<(Vec2, S)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Copy> DragCtl<S> {
|
||||||
|
pub fn new(state: S) -> Self {
|
||||||
|
Self { state, ctl: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state(&self) -> S {
|
||||||
|
self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_button(&mut self, pos: Vec2, state: ElementState) {
|
||||||
|
match state {
|
||||||
|
ElementState::Pressed => {
|
||||||
|
assert!(self.ctl.is_none());
|
||||||
|
self.ctl = Some((pos, self.state));
|
||||||
|
}
|
||||||
|
ElementState::Released => {
|
||||||
|
assert!(self.ctl.is_some());
|
||||||
|
self.ctl = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_move(&mut self, pos: Vec2, f: impl FnOnce(S, Vec2) -> S) {
|
||||||
|
if let Some((old_pos, old_state)) = self.ctl {
|
||||||
|
self.state = f(old_state, pos - old_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let event_loop = EventLoop::builder().build().unwrap();
|
||||||
|
let (window, display) = SimpleWindowBuilder::new()
|
||||||
|
.with_title("Refraction: Wireframe")
|
||||||
|
.build(&event_loop);
|
||||||
|
|
||||||
|
let vs_src = include_str!("ray.v.glsl");
|
||||||
|
let fs_src = include_str!("ray.f.glsl");
|
||||||
|
let program = Program::from_source(&display, vs_src, fs_src, None).unwrap();
|
||||||
|
|
||||||
|
let indices = glium::index::NoIndices(glium::index::PrimitiveType::LineLoop);
|
||||||
|
let shape = vec![
|
||||||
|
Vertex {
|
||||||
|
position: [-1., 0., 4.],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [0., -1., 4.],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [1., 0., 4.],
|
||||||
|
},
|
||||||
|
Vertex {
|
||||||
|
position: [0., 1., 4.],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let vertex_buffer = VertexBuffer::new(&display, &shape).unwrap();
|
||||||
|
|
||||||
|
let mut cur_pos = vec2(0., 0.);
|
||||||
|
let mut cam_pos = DragCtl::new(Vec3::ZERO);
|
||||||
|
let mut cam_rot = DragCtl::new(Quat::IDENTITY);
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
|
event_loop
|
||||||
|
.run(move |ev, window_target| match ev {
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
|
WindowEvent::RedrawRequested => {
|
||||||
|
let size = window.inner_size();
|
||||||
|
let size = vec2(size.width as f32, size.height as f32).normalize()
|
||||||
|
* std::f32::consts::SQRT_2;
|
||||||
|
let proj = make_proj_matrix(vec3(size.x, size.y, 2.), (0.125, 1024.125));
|
||||||
|
|
||||||
|
let view =
|
||||||
|
Mat4::from_quat(cam_rot.state()) * Mat4::from_translation(cam_pos.state());
|
||||||
|
|
||||||
|
let mut target = display.draw();
|
||||||
|
target.clear_color(0.0, 0.0, 0.2, 1.0);
|
||||||
|
|
||||||
|
let mvp = proj * view;
|
||||||
|
let uniforms = uniform! {
|
||||||
|
mvp: mvp.to_cols_array_2d(),
|
||||||
|
};
|
||||||
|
|
||||||
|
target
|
||||||
|
.draw(
|
||||||
|
&vertex_buffer,
|
||||||
|
&indices,
|
||||||
|
&program,
|
||||||
|
&uniforms,
|
||||||
|
&Default::default(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
target.finish().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowEvent::MouseInput {
|
||||||
|
device_id: _,
|
||||||
|
state,
|
||||||
|
button,
|
||||||
|
} => match button {
|
||||||
|
winit::event::MouseButton::Left => cam_pos.on_button(cur_pos, state),
|
||||||
|
winit::event::MouseButton::Right => cam_rot.on_button(cur_pos, state),
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
|
||||||
|
WindowEvent::CursorMoved {
|
||||||
|
device_id: _,
|
||||||
|
position,
|
||||||
|
} => {
|
||||||
|
let size = window.inner_size();
|
||||||
|
let size = vec2(size.width as f32, size.height as f32);
|
||||||
|
cur_pos = vec2(position.x as f32, position.y as f32) / size.length();
|
||||||
|
cam_pos.on_move(cur_pos, |init, off| {
|
||||||
|
window.request_redraw();
|
||||||
|
init + 4. * (cam_rot.state().inverse() * vec3(off.x, -off.y, 0.))
|
||||||
|
});
|
||||||
|
cam_rot.on_move(cur_pos, |init, off| {
|
||||||
|
window.request_redraw();
|
||||||
|
Quat::from_euler(glam::EulerRot::YXZ, 5. * off.x, 5. * off.y, 0.) * init
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowEvent::Resized(window_size) => {
|
||||||
|
display.resize(window_size.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowEvent::CloseRequested => {
|
||||||
|
window_target.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
|
||||||
|
Event::AboutToWait => {
|
||||||
|
window.request_redraw();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Make a projection matrix, assuming input coordinates are (right, up, forward).
|
||||||
|
///
|
||||||
|
/// `corner` is a vector that will be mapped to (x=1, y=1) after the perspective division.
|
||||||
|
/// `zrange` is the Z range that will be mapped to z∈[-1, 1]. It has no other effect. Both ends have to be positive though.
|
||||||
|
fn make_proj_matrix(corner: Vec3, zrange: (f32, f32)) -> Mat4 {
|
||||||
|
let scale = 1.0 / corner;
|
||||||
|
let zspan = zrange.1 - zrange.0;
|
||||||
|
mat4(
|
||||||
|
scale.x * vec4(1., 0., 0., 0.),
|
||||||
|
scale.y * vec4(0., 1., 0., 0.),
|
||||||
|
scale.z * vec4(0., 0., (zrange.0 + zrange.1) / zspan, 1.),
|
||||||
|
scale.z * vec4(0., 0., -2. * zrange.0 * zrange.1 / zspan, 0.),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use approx::assert_abs_diff_eq;
|
||||||
|
use glam::vec3;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_proj_matrix() {
|
||||||
|
let m = make_proj_matrix(vec3(2., 3., 4.), (0.5, 20.0));
|
||||||
|
|
||||||
|
let v = m * vec4(2., 3., 4., 1.);
|
||||||
|
assert_abs_diff_eq!(v.x / v.w, 1.0);
|
||||||
|
assert_abs_diff_eq!(v.y / v.w, 1.0);
|
||||||
|
assert!(-v.w < v.z && v.z < v.w, "z out of range in {v}");
|
||||||
|
|
||||||
|
let v = m * vec4(2., 3., 0.5, 1.);
|
||||||
|
assert_abs_diff_eq!(v.x / v.w, 8.0);
|
||||||
|
assert_abs_diff_eq!(v.y / v.w, 8.0);
|
||||||
|
assert_abs_diff_eq!(v.z / v.w, -1.0);
|
||||||
|
|
||||||
|
let v = m * vec4(2., 3., 20.0, 1.);
|
||||||
|
assert_abs_diff_eq!(v.x / v.w, 0.2);
|
||||||
|
assert_abs_diff_eq!(v.y / v.w, 0.2);
|
||||||
|
assert_abs_diff_eq!(v.z / v.w, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/bin/wireframe/ray.f.glsl
Normal file
9
src/bin/wireframe/ray.f.glsl
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
in vec3 vertex_color;
|
||||||
|
|
||||||
|
out vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
color = vec4(vertex_color, 1.0);
|
||||||
|
}
|
||||||
13
src/bin/wireframe/ray.v.glsl
Normal file
13
src/bin/wireframe/ray.v.glsl
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#version 330
|
||||||
|
|
||||||
|
uniform mat4 mvp;
|
||||||
|
uniform vec3 color;
|
||||||
|
|
||||||
|
in vec3 position;
|
||||||
|
|
||||||
|
out vec3 vertex_color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vertex_color = color;
|
||||||
|
gl_Position = mvp * vec4(position, 1.0);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user