mirror of https://github.com/Leinnan/doppler.git
Cleanup
This commit is contained in:
parent
f30d198463
commit
dd6b42e55d
|
|
@ -0,0 +1,3 @@
|
|||
[](https://builds.sr.ht/~leinnan/doppler/commits/.build.yml?)
|
||||
|
||||
My OpenGL "engine". WIP
|
||||
|
|
@ -16,7 +16,7 @@ impl Default for BgInfo {
|
|||
BgInfo {
|
||||
r: 0.1,
|
||||
g: 0.2,
|
||||
b: 0.4
|
||||
b: 0.4,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ const ZOOM: f32 = 45.0;
|
|||
|
||||
pub struct Camera {
|
||||
// Camera Attributes
|
||||
pub Position: Point3,
|
||||
pub position: Point3,
|
||||
pub Front: Vector3,
|
||||
pub Up: Vector3,
|
||||
pub Right: Vector3,
|
||||
|
|
@ -46,7 +46,7 @@ pub struct Camera {
|
|||
impl Default for Camera {
|
||||
fn default() -> Camera {
|
||||
let mut camera = Camera {
|
||||
Position: Point3::new(0.0, 0.0, 0.0),
|
||||
position: Point3::new(0.0, 0.0, 0.0),
|
||||
Front: vec3(0.0, 0.0, -1.0),
|
||||
Up: Vector3::zero(), // initialized later
|
||||
Right: Vector3::zero(), // initialized later
|
||||
|
|
@ -65,23 +65,23 @@ impl Default for Camera {
|
|||
impl Camera {
|
||||
/// Returns the view matrix calculated using Eular Angles and the LookAt Matrix
|
||||
pub fn get_view_matrix(&self) -> Matrix4 {
|
||||
Matrix4::look_at(self.Position, self.Position + self.Front, self.Up)
|
||||
Matrix4::look_at(self.position, self.position + self.Front, self.Up)
|
||||
}
|
||||
|
||||
/// Processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
|
||||
pub fn process_keyboard(&mut self, direction: Camera_Movement, deltaTime: f32) {
|
||||
let velocity = self.MovementSpeed * deltaTime;
|
||||
if direction == FORWARD {
|
||||
self.Position += self.Front * velocity;
|
||||
self.position += self.Front * velocity;
|
||||
}
|
||||
if direction == BACKWARD {
|
||||
self.Position += -(self.Front * velocity);
|
||||
self.position += -(self.Front * velocity);
|
||||
}
|
||||
if direction == LEFT {
|
||||
self.Position += -(self.Right * velocity);
|
||||
self.position += -(self.Right * velocity);
|
||||
}
|
||||
if direction == RIGHT {
|
||||
self.Position += self.Right * velocity;
|
||||
self.position += self.Right * velocity;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,265 @@
|
|||
use crate::gaia::bg_info::BgInfo;
|
||||
use crate::gaia::camera::*;
|
||||
use crate::gaia::consts;
|
||||
use crate::gaia::*;
|
||||
use cgmath::{perspective, vec3, Deg, Matrix4, Point3, Rad, Vector3};
|
||||
use imgui_glfw_rs::glfw;
|
||||
use imgui_glfw_rs::glfw::{Action, Context, Key};
|
||||
use imgui_glfw_rs::imgui;
|
||||
use imgui_glfw_rs::ImguiGLFW;
|
||||
use imgui_inspect::InspectArgsStruct;
|
||||
|
||||
pub struct Engine {
|
||||
pub camera: Camera,
|
||||
pub bg_info: BgInfo,
|
||||
pub window: imgui_glfw_rs::glfw::Window,
|
||||
pub window_size: (f32, f32),
|
||||
pub events: std::sync::mpsc::Receiver<(f64, imgui_glfw_rs::glfw::WindowEvent)>,
|
||||
pub glfw: imgui_glfw_rs::glfw::Glfw,
|
||||
pub imgui: imgui::Context,
|
||||
pub imgui_glfw: ImguiGLFW,
|
||||
pub shader: shader::Shader,
|
||||
pub models: Vec<model::Model>,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn run(&mut self) {
|
||||
let mut first_mouse = true;
|
||||
let mut last_x: f32 = consts::SCR_WIDTH as f32 / 2.0;
|
||||
let mut last_y: f32 = consts::SCR_HEIGHT as f32 / 2.0;
|
||||
|
||||
// timing
|
||||
let mut delta_time: f32; // time between current frame and last frame
|
||||
let mut last_frame: f32 = 0.0;
|
||||
{
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
self.shader = shader::Shader::from_file(
|
||||
"resources/shaders/model_loading.vs",
|
||||
"resources/shaders/model_loading.fs",
|
||||
);
|
||||
|
||||
// load models
|
||||
// -----------
|
||||
for _ in 0..10 {
|
||||
self.models.push(model::Model::new("resources/objects/nanosuit/nanosuit.obj"));
|
||||
}
|
||||
};
|
||||
// render loop
|
||||
// -----------
|
||||
while !self.window.should_close() {
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
let cur_frame = self.glfw.get_time() as f32;
|
||||
delta_time = cur_frame - last_frame;
|
||||
last_frame = cur_frame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
let skip_input =
|
||||
self.imgui.io().want_capture_mouse || self.imgui.io().want_capture_keyboard;
|
||||
if !skip_input {
|
||||
self.process_input(delta_time);
|
||||
}
|
||||
|
||||
// render
|
||||
// ------
|
||||
unsafe {
|
||||
gl::ClearColor(self.bg_info.r, self.bg_info.g, self.bg_info.b, 1.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
|
||||
|
||||
// don't forget to enable shader before setting uniforms
|
||||
self.shader.useProgram();
|
||||
|
||||
// view/projection transformations
|
||||
let projection: Matrix4<f32> = perspective(
|
||||
Deg(self.camera.Zoom),
|
||||
self.window_size.0 / self.window_size.1,
|
||||
0.1,
|
||||
100.0,
|
||||
);
|
||||
let view = self.camera.get_view_matrix();
|
||||
self.shader.setMat4(c_str!("projection"), &projection);
|
||||
self.shader.setMat4(c_str!("view"), &view);
|
||||
|
||||
let mut i = 0;
|
||||
for m in &self.models {
|
||||
// render the loaded model
|
||||
let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -1.75, -1.25 * (i as f32))); // translate it down so it's at the center of the scene
|
||||
model = model * Matrix4::from_scale(0.2); // it's a bit too big for our scene, so scale it down
|
||||
self.shader.setMat4(c_str!("model"), &model);
|
||||
m.Draw(&self.shader);
|
||||
i = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
let ui = self.imgui_glfw.frame(&mut self.window, &mut self.imgui);
|
||||
|
||||
{
|
||||
use imgui::*;
|
||||
Window::new(im_str!("Hello world"))
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
.build(&ui, || {
|
||||
ui.text(im_str!("Hello world!"));
|
||||
ui.text(im_str!("こんにちは世界!"));
|
||||
ui.text(im_str!("This...is...imgui-rs!"));
|
||||
ui.separator();
|
||||
ui.text(format!("Mouse position: ({:.1},{:.1})", last_x, last_y));
|
||||
// let selected = vec![&self.bg_info];
|
||||
// <BgInfo as imgui_inspect::InspectRenderStruct<BgInfo>>::render(
|
||||
// &selected,
|
||||
// "Example Struct - Read Only",
|
||||
// &ui,
|
||||
// &InspectArgsStruct::default(),
|
||||
// );
|
||||
// let mut selected_mut = vec![&mut self.bg_info];
|
||||
// <BgInfo as imgui_inspect::InspectRenderStruct<BgInfo>>::render_mut(
|
||||
// &mut selected_mut,
|
||||
// "Example Struct - Writable",
|
||||
// &ui,
|
||||
// &InspectArgsStruct::default(),
|
||||
// );
|
||||
});
|
||||
}
|
||||
|
||||
self.imgui_glfw.draw(ui, &mut self.window);
|
||||
self.window.swap_buffers();
|
||||
self.glfw.poll_events();
|
||||
// events
|
||||
// -----
|
||||
self.process_events(&mut first_mouse, &mut last_x, &mut last_y, skip_input);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_input(&mut self, delta_time: f32) {
|
||||
if self.window.get_key(Key::Escape) == Action::Press {
|
||||
self.window.set_should_close(true)
|
||||
}
|
||||
if self.window.get_key(Key::W) == Action::Press {
|
||||
self.camera
|
||||
.process_keyboard(Camera_Movement::FORWARD, delta_time);
|
||||
}
|
||||
if self.window.get_key(Key::S) == Action::Press {
|
||||
self.camera
|
||||
.process_keyboard(Camera_Movement::BACKWARD, delta_time);
|
||||
}
|
||||
if self.window.get_key(Key::A) == Action::Press {
|
||||
self.camera
|
||||
.process_keyboard(Camera_Movement::LEFT, delta_time);
|
||||
}
|
||||
if self.window.get_key(Key::D) == Action::Press {
|
||||
self.camera
|
||||
.process_keyboard(Camera_Movement::RIGHT, delta_time);
|
||||
}
|
||||
self.camera
|
||||
.enable_mouse_movement(self.window.get_key(Key::LeftControl) != Action::Press);
|
||||
}
|
||||
|
||||
pub fn process_events(
|
||||
&mut self,
|
||||
first_mouse: &mut bool,
|
||||
last_x: &mut f32,
|
||||
last_y: &mut f32,
|
||||
skip_input: bool,
|
||||
) {
|
||||
for (_, event) in glfw::flush_messages(&self.events) {
|
||||
self.imgui_glfw.handle_event(&mut self.imgui, &event);
|
||||
match event {
|
||||
glfw::WindowEvent::FramebufferSize(width, height) => {
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
unsafe { gl::Viewport(0, 0, width, height) }
|
||||
self.window_size = (width as f32, height as f32);
|
||||
}
|
||||
glfw::WindowEvent::CursorPos(xpos, ypos) => {
|
||||
if skip_input {
|
||||
return;
|
||||
}
|
||||
let (xpos, ypos) = (xpos as f32, ypos as f32);
|
||||
if *first_mouse {
|
||||
*last_x = xpos;
|
||||
*last_y = ypos;
|
||||
*first_mouse = false;
|
||||
}
|
||||
|
||||
let xoffset = xpos - *last_x;
|
||||
let yoffset = *last_y - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
*last_x = xpos;
|
||||
*last_y = ypos;
|
||||
|
||||
self.camera.process_mouse_movement(xoffset, yoffset, true);
|
||||
}
|
||||
glfw::WindowEvent::Scroll(_xoffset, yoffset) => {
|
||||
if skip_input {
|
||||
return;
|
||||
}
|
||||
self.camera.process_mouse_scroll(yoffset as f32);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Engine {
|
||||
fn default() -> Self {
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
|
||||
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
|
||||
glfw::OpenGlProfileHint::Core,
|
||||
));
|
||||
#[cfg(target_os = "macos")]
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
let (mut window, events) = glfw
|
||||
.create_window(
|
||||
consts::SCR_WIDTH,
|
||||
consts::SCR_HEIGHT,
|
||||
"chRustedGL",
|
||||
glfw::WindowMode::Windowed,
|
||||
)
|
||||
.expect("Failed to create GLFW window");
|
||||
|
||||
window.make_current();
|
||||
window.set_all_polling(true);
|
||||
window.set_framebuffer_size_polling(true);
|
||||
window.set_cursor_pos_polling(true);
|
||||
window.set_scroll_polling(true);
|
||||
|
||||
// tell GLFW to capture our mouse
|
||||
window.set_cursor_mode(glfw::CursorMode::Disabled);
|
||||
// gl: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
|
||||
|
||||
let mut imgui = imgui::Context::create();
|
||||
let mut imgui_glfw = ImguiGLFW::new(&mut imgui, &mut window);
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
unsafe{gl::Enable(gl::DEPTH_TEST);}
|
||||
|
||||
Engine {
|
||||
camera: Camera {
|
||||
position: Point3::new(0.0, 0.0, 3.0),
|
||||
..Camera::default()
|
||||
},
|
||||
bg_info: BgInfo::default(),
|
||||
window: window,
|
||||
window_size: (consts::SCR_WIDTH as f32, consts::SCR_HEIGHT as f32),
|
||||
events: events,
|
||||
glfw: glfw,
|
||||
imgui: imgui,
|
||||
imgui_glfw: imgui_glfw,
|
||||
shader: shader::Shader::default(),
|
||||
models: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,11 +6,11 @@ use std::mem::size_of;
|
|||
use std::os::raw::c_void;
|
||||
use std::ptr;
|
||||
|
||||
use cgmath::{ Vector3, Vector2 };
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::{Vector2, Vector3};
|
||||
use gl;
|
||||
|
||||
use crate::shader::Shader;
|
||||
use crate::gaia::shader::Shader;
|
||||
|
||||
// NOTE: without repr(C) the compiler may reorder the fields or use different padding/alignment than C.
|
||||
// Depending on how you pass the data to OpenGL, this may be bad. In this case it's not strictly
|
||||
|
|
@ -18,7 +18,7 @@ use crate::shader::Shader;
|
|||
#[repr(C)]
|
||||
pub struct Vertex {
|
||||
// position
|
||||
pub Position: Vector3<f32>,
|
||||
pub position: Vector3<f32>,
|
||||
// normal
|
||||
pub Normal: Vector3<f32>,
|
||||
// texCoords
|
||||
|
|
@ -32,7 +32,7 @@ pub struct Vertex {
|
|||
impl Default for Vertex {
|
||||
fn default() -> Self {
|
||||
Vertex {
|
||||
Position: Vector3::zero(),
|
||||
position: Vector3::zero(),
|
||||
Normal: Vector3::zero(),
|
||||
TexCoords: Vector2::zero(),
|
||||
Tangent: Vector3::zero(),
|
||||
|
|
@ -63,8 +63,12 @@ pub struct Mesh {
|
|||
impl Mesh {
|
||||
pub fn new(vertices: Vec<Vertex>, indices: Vec<u32>, textures: Vec<Texture>) -> Mesh {
|
||||
let mut mesh = Mesh {
|
||||
vertices, indices, textures,
|
||||
VAO: 0, VBO: 0, EBO: 0
|
||||
vertices,
|
||||
indices,
|
||||
textures,
|
||||
VAO: 0,
|
||||
VBO: 0,
|
||||
EBO: 0,
|
||||
};
|
||||
|
||||
// now that we have all the required data, set the vertex buffers and its attribute pointers.
|
||||
|
|
@ -87,7 +91,7 @@ impl Mesh {
|
|||
"texture_diffuse" => {
|
||||
diffuseNr += 1;
|
||||
diffuseNr
|
||||
},
|
||||
}
|
||||
"texture_specular" => {
|
||||
specularNr += 1;
|
||||
specularNr
|
||||
|
|
@ -100,18 +104,26 @@ impl Mesh {
|
|||
heightNr += 1;
|
||||
heightNr
|
||||
}
|
||||
_ => panic!("unknown texture type")
|
||||
_ => panic!("unknown texture type"),
|
||||
};
|
||||
// now set the sampler to the correct texture unit
|
||||
let sampler = CString::new(format!("{}{}", name, number)).unwrap();
|
||||
gl::Uniform1i(gl::GetUniformLocation(shader.ID, sampler.as_ptr()), i as i32);
|
||||
gl::Uniform1i(
|
||||
gl::GetUniformLocation(shader.ID, sampler.as_ptr()),
|
||||
i as i32,
|
||||
);
|
||||
// and finally bind the texture
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture.id);
|
||||
}
|
||||
|
||||
// draw mesh
|
||||
gl::BindVertexArray(self.VAO);
|
||||
gl::DrawElements(gl::TRIANGLES, self.indices.len() as i32, gl::UNSIGNED_INT, ptr::null());
|
||||
gl::DrawElements(
|
||||
gl::TRIANGLES,
|
||||
self.indices.len() as i32,
|
||||
gl::UNSIGNED_INT,
|
||||
ptr::null(),
|
||||
);
|
||||
gl::BindVertexArray(0);
|
||||
|
||||
// always good practice to set everything back to defaults once configured.
|
||||
|
|
@ -143,19 +155,54 @@ impl Mesh {
|
|||
let size = size_of::<Vertex>() as i32;
|
||||
// vertex Positions
|
||||
gl::EnableVertexAttribArray(0);
|
||||
gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, Position) as *const c_void);
|
||||
gl::VertexAttribPointer(
|
||||
0,
|
||||
3,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
size,
|
||||
offset_of!(Vertex, position) as *const c_void,
|
||||
);
|
||||
// vertex normals
|
||||
gl::EnableVertexAttribArray(1);
|
||||
gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, Normal) as *const c_void);
|
||||
gl::VertexAttribPointer(
|
||||
1,
|
||||
3,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
size,
|
||||
offset_of!(Vertex, Normal) as *const c_void,
|
||||
);
|
||||
// vertex texture coords
|
||||
gl::EnableVertexAttribArray(2);
|
||||
gl::VertexAttribPointer(2, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, TexCoords) as *const c_void);
|
||||
gl::VertexAttribPointer(
|
||||
2,
|
||||
2,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
size,
|
||||
offset_of!(Vertex, TexCoords) as *const c_void,
|
||||
);
|
||||
// vertex tangent
|
||||
gl::EnableVertexAttribArray(3);
|
||||
gl::VertexAttribPointer(3, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, Tangent) as *const c_void);
|
||||
gl::VertexAttribPointer(
|
||||
3,
|
||||
3,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
size,
|
||||
offset_of!(Vertex, Tangent) as *const c_void,
|
||||
);
|
||||
// vertex bitangent
|
||||
gl::EnableVertexAttribArray(4);
|
||||
gl::VertexAttribPointer(4, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, Bitangent) as *const c_void);
|
||||
gl::VertexAttribPointer(
|
||||
4,
|
||||
3,
|
||||
gl::FLOAT,
|
||||
gl::FALSE,
|
||||
size,
|
||||
offset_of!(Vertex, Bitangent) as *const c_void,
|
||||
);
|
||||
|
||||
gl::BindVertexArray(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ pub mod consts;
|
|||
pub mod utils;
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod shader;
|
||||
pub mod model;
|
||||
pub mod mesh;
|
||||
pub mod bg_info;
|
||||
pub mod engine;
|
||||
pub mod mesh;
|
||||
pub mod model;
|
||||
pub mod shader;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ use image::DynamicImage::*;
|
|||
use image::GenericImage;
|
||||
use tobj;
|
||||
|
||||
use crate::mesh::{ Mesh, Texture, Vertex };
|
||||
use crate::shader::Shader;
|
||||
use crate::utils::*;
|
||||
use crate::gaia::mesh::{Mesh, Texture, Vertex};
|
||||
use crate::gaia::shader::Shader;
|
||||
use crate::gaia::utils::*;
|
||||
|
||||
// #[derive(Default)]
|
||||
pub struct Model {
|
||||
|
|
@ -30,7 +30,12 @@ impl Model {
|
|||
let mut model = Model {
|
||||
meshes: Vec::<Mesh>::new(),
|
||||
textures_loaded: Vec::<Texture>::new(),
|
||||
directory: pathObj.parent().unwrap_or_else(|| Path::new("")).to_str().unwrap().into()
|
||||
directory: pathObj
|
||||
.parent()
|
||||
.unwrap_or_else(|| Path::new(""))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into(),
|
||||
};
|
||||
model.loadModel(path);
|
||||
model
|
||||
|
|
@ -38,7 +43,9 @@ impl Model {
|
|||
|
||||
pub fn Draw(&self, shader: &Shader) {
|
||||
for mesh in &self.meshes {
|
||||
unsafe { mesh.Draw(shader); }
|
||||
unsafe {
|
||||
mesh.Draw(shader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +55,12 @@ impl Model {
|
|||
println!("Started loading model from path: {}", path.display());
|
||||
|
||||
// retrieve the directory path of the filepath
|
||||
self.directory = path.parent().unwrap_or_else(|| Path::new("")).to_str().unwrap().into();
|
||||
self.directory = path
|
||||
.parent()
|
||||
.unwrap_or_else(|| Path::new(""))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
let obj = tobj::load_obj(path, true);
|
||||
|
||||
let (models, materials) = obj.unwrap();
|
||||
|
|
@ -63,7 +75,7 @@ impl Model {
|
|||
let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords);
|
||||
for i in 0..num_vertices {
|
||||
vertices.push(Vertex {
|
||||
Position: vec3(p[i*3], p[i*3+1], p[i*3+2]),
|
||||
position: vec3(p[i * 3], p[i * 3 + 1], p[i * 3 + 2]),
|
||||
Normal: vec3(n[i * 3], n[i * 3 + 1], n[i * 3 + 2]),
|
||||
TexCoords: vec2(t[i * 2], t[i * 2 + 1]),
|
||||
..Vertex::default()
|
||||
|
|
@ -77,17 +89,20 @@ impl Model {
|
|||
|
||||
// 1. diffuse map
|
||||
if !material.diffuse_texture.is_empty() {
|
||||
let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse");
|
||||
let texture =
|
||||
self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse");
|
||||
textures.push(texture);
|
||||
}
|
||||
// 2. specular map
|
||||
if !material.specular_texture.is_empty() {
|
||||
let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular");
|
||||
let texture =
|
||||
self.loadMaterialTexture(&material.specular_texture, "texture_specular");
|
||||
textures.push(texture);
|
||||
}
|
||||
// 3. normal map
|
||||
if !material.normal_texture.is_empty() {
|
||||
let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal");
|
||||
let texture =
|
||||
self.loadMaterialTexture(&material.normal_texture, "texture_normal");
|
||||
textures.push(texture);
|
||||
}
|
||||
// NOTE: no height maps
|
||||
|
|
@ -96,7 +111,6 @@ impl Model {
|
|||
self.meshes.push(Mesh::new(vertices, indices, textures));
|
||||
}
|
||||
println!("Finished loading model from path: {}", path.display());
|
||||
|
||||
}
|
||||
|
||||
fn loadMaterialTexture(&mut self, path: &str, typeName: &str) -> Texture {
|
||||
|
|
@ -108,12 +122,11 @@ impl Model {
|
|||
}
|
||||
|
||||
let texture = Texture {
|
||||
id: unsafe { loadTextureFromDir(path, &self.directory) },
|
||||
id: unsafe { load_texture_from_dir(path, &self.directory) },
|
||||
type_: typeName.into(),
|
||||
path: path.into()
|
||||
path: path.into(),
|
||||
};
|
||||
self.textures_loaded.push(texture.clone());
|
||||
texture
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ use std::str;
|
|||
use gl;
|
||||
use gl::types::*;
|
||||
|
||||
use crate::gaia::consts;
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::{Matrix, Matrix4, Vector3};
|
||||
use crate::gaia::consts;
|
||||
|
||||
pub struct Shader {
|
||||
pub ID: u32,
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ use image::DynamicImage::*;
|
|||
use image::GenericImage;
|
||||
use image::*;
|
||||
|
||||
pub unsafe fn loadTexture(path: &str) -> u32 {
|
||||
pub unsafe fn load_texture(path: &str) -> u32 {
|
||||
println!("Loading texture from path: {}", path);
|
||||
let mut textureID = 0;
|
||||
let mut id = 0;
|
||||
|
||||
gl::GenTextures(1, &mut textureID);
|
||||
gl::GenTextures(1, &mut id);
|
||||
let img = image::open(&Path::new(path)).expect("Texture failed to load");
|
||||
let format = match img {
|
||||
ImageLuma8(_) => gl::RED,
|
||||
|
|
@ -26,7 +26,7 @@ pub unsafe fn loadTexture(path: &str) -> u32 {
|
|||
let data = img.raw_pixels();
|
||||
let dim = img.dimensions();
|
||||
|
||||
gl::BindTexture(gl::TEXTURE_2D, textureID);
|
||||
gl::BindTexture(gl::TEXTURE_2D, id);
|
||||
gl::TexImage2D(
|
||||
gl::TEXTURE_2D,
|
||||
0,
|
||||
|
|
@ -49,11 +49,11 @@ pub unsafe fn loadTexture(path: &str) -> u32 {
|
|||
);
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
|
||||
|
||||
textureID
|
||||
id
|
||||
}
|
||||
|
||||
pub unsafe fn loadTextureFromDir(filename: &str, directory: &str) -> u32 {
|
||||
pub unsafe fn load_texture_from_dir(filename: &str, directory: &str) -> u32 {
|
||||
let fullpath = format!("{}/{}", directory, filename);
|
||||
|
||||
loadTexture(&fullpath)
|
||||
load_texture(&fullpath)
|
||||
}
|
||||
252
src/main.rs
252
src/main.rs
|
|
@ -1,255 +1,15 @@
|
|||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
extern crate gl;
|
||||
extern crate imgui_glfw_rs;
|
||||
extern crate image;
|
||||
// Use the reexported glfw crate to avoid version conflicts.
|
||||
use imgui_glfw_rs::glfw;
|
||||
// Use the reexported imgui crate to avoid version conflicts.
|
||||
use imgui_glfw_rs::imgui;
|
||||
|
||||
use imgui_glfw_rs::ImguiGLFW;
|
||||
use imgui_inspect::InspectArgsStruct;
|
||||
use self::gl::types::*;
|
||||
use imgui_glfw_rs::glfw::{Action, Context, Key};
|
||||
use cgmath::prelude::*;
|
||||
use cgmath::{perspective, vec3, Deg, Matrix4, Point3, Rad, Vector3};
|
||||
extern crate imgui_glfw_rs;
|
||||
use human_panic::setup_panic;
|
||||
|
||||
#[macro_use]
|
||||
mod gaia;
|
||||
use crate::gaia::camera::*;
|
||||
use crate::gaia::*;
|
||||
use crate::gaia::bg_info::BgInfo;
|
||||
use crate::gaia::engine::Engine;
|
||||
|
||||
pub fn main() {
|
||||
setup_panic!();
|
||||
let mut camera = Camera {
|
||||
Position: Point3::new(0.0, 0.0, 3.0),
|
||||
..Camera::default()
|
||||
};
|
||||
let mut engine = Engine::default();
|
||||
|
||||
let mut first_mouse = true;
|
||||
let mut last_x: f32 = consts::SCR_WIDTH as f32 / 2.0;
|
||||
let mut last_y: f32 = consts::SCR_HEIGHT as f32 / 2.0;
|
||||
|
||||
// timing
|
||||
let mut delta_time: f32; // time between current frame and last frame
|
||||
let mut last_frame: f32 = 0.0;
|
||||
// glfw: initialize and configure
|
||||
// ------------------------------
|
||||
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
|
||||
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
|
||||
glfw::OpenGlProfileHint::Core,
|
||||
));
|
||||
#[cfg(target_os = "macos")]
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
||||
|
||||
// glfw window creation
|
||||
// --------------------
|
||||
let (mut window, events) = glfw
|
||||
.create_window(
|
||||
consts::SCR_WIDTH,
|
||||
consts::SCR_HEIGHT,
|
||||
"chRustedGL",
|
||||
glfw::WindowMode::Windowed,
|
||||
)
|
||||
.expect("Failed to create GLFW window");
|
||||
|
||||
window.make_current();
|
||||
window.set_all_polling(true);
|
||||
window.set_framebuffer_size_polling(true);
|
||||
window.set_cursor_pos_polling(true);
|
||||
window.set_scroll_polling(true);
|
||||
|
||||
// tell GLFW to capture our mouse
|
||||
window.set_cursor_mode(glfw::CursorMode::Disabled);
|
||||
|
||||
// gl: load all OpenGL function pointers
|
||||
// ---------------------------------------
|
||||
gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
|
||||
|
||||
|
||||
let (ourShader, ourModel) = unsafe {
|
||||
// configure global opengl state
|
||||
// -----------------------------
|
||||
gl::Enable(gl::DEPTH_TEST);
|
||||
|
||||
// build and compile shaders
|
||||
// -------------------------
|
||||
let ourShader = shader::Shader::from_file(
|
||||
"resources/shaders/model_loading.vs",
|
||||
"resources/shaders/model_loading.fs");
|
||||
|
||||
// load models
|
||||
// -----------
|
||||
let ourModel = model::Model::new("resources/objects/nanosuit/nanosuit.obj");
|
||||
|
||||
// draw in wireframe
|
||||
// gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
|
||||
|
||||
(ourShader, ourModel)
|
||||
};
|
||||
|
||||
|
||||
let mut imgui = imgui::Context::create();
|
||||
|
||||
let mut imgui_glfw = ImguiGLFW::new(&mut imgui, &mut window);
|
||||
|
||||
// render loop
|
||||
// -----------
|
||||
let mut bg = BgInfo::default();
|
||||
while !window.should_close() {
|
||||
// per-frame time logic
|
||||
// --------------------
|
||||
let cur_frame = glfw.get_time() as f32;
|
||||
delta_time = cur_frame - last_frame;
|
||||
last_frame = cur_frame;
|
||||
|
||||
// input
|
||||
// -----
|
||||
let skip_input = imgui.io().want_capture_mouse || imgui.io().want_capture_keyboard;
|
||||
if !skip_input {
|
||||
process_input(&mut window, delta_time, &mut camera);
|
||||
}
|
||||
|
||||
// render
|
||||
// ------
|
||||
unsafe {
|
||||
gl::ClearColor(bg.r, bg.g, bg.b, 1.0);
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
|
||||
|
||||
// don't forget to enable shader before setting uniforms
|
||||
ourShader.useProgram();
|
||||
|
||||
// view/projection transformations
|
||||
let projection: Matrix4<f32> = perspective(Deg(camera.Zoom), consts::SCR_WIDTH as f32 / consts::SCR_HEIGHT as f32, 0.1, 100.0);
|
||||
let view = camera.get_view_matrix();
|
||||
ourShader.setMat4(c_str!("projection"), &projection);
|
||||
ourShader.setMat4(c_str!("view"), &view);
|
||||
|
||||
// render the loaded model
|
||||
let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -1.75, 0.0)); // translate it down so it's at the center of the scene
|
||||
model = model * Matrix4::from_scale(0.2); // it's a bit too big for our scene, so scale it down
|
||||
ourShader.setMat4(c_str!("model"), &model);
|
||||
ourModel.Draw(&ourShader);
|
||||
}
|
||||
|
||||
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
|
||||
// -------------------------------------------------------------------------------
|
||||
|
||||
let ui = imgui_glfw.frame(&mut window, &mut imgui);
|
||||
|
||||
{
|
||||
use imgui::*;
|
||||
Window::new(im_str!("Hello world"))
|
||||
.size([300.0, 110.0], Condition::FirstUseEver)
|
||||
.build(&ui, || {
|
||||
ui.text(im_str!("Hello world!"));
|
||||
ui.text(im_str!("こんにちは世界!"));
|
||||
ui.text(im_str!("This...is...imgui-rs!"));
|
||||
ui.separator();
|
||||
ui.text(format!(
|
||||
"Mouse Position: ({:.1},{:.1})",
|
||||
last_x, last_y
|
||||
));
|
||||
let selected = vec![&bg];
|
||||
<BgInfo as imgui_inspect::InspectRenderStruct<
|
||||
BgInfo,
|
||||
>>::render(
|
||||
&selected,
|
||||
"Example Struct - Read Only",
|
||||
&ui,
|
||||
&InspectArgsStruct::default(),
|
||||
);
|
||||
let mut selected_mut = vec![&mut bg];
|
||||
<BgInfo as imgui_inspect::InspectRenderStruct<
|
||||
BgInfo,
|
||||
>>::render_mut(
|
||||
&mut selected_mut,
|
||||
"Example Struct - Writable",
|
||||
&ui,
|
||||
&InspectArgsStruct::default(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
imgui_glfw.draw(ui, &mut window);
|
||||
window.swap_buffers();
|
||||
glfw.poll_events();
|
||||
// events
|
||||
// -----
|
||||
|
||||
for (_, event) in glfw::flush_messages(&events) {
|
||||
imgui_glfw.handle_event(&mut imgui, &event);
|
||||
process_events(
|
||||
event,
|
||||
&mut first_mouse,
|
||||
&mut last_x,
|
||||
&mut last_y,
|
||||
&mut camera,
|
||||
skip_input
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_events(
|
||||
event: imgui_glfw_rs::glfw::WindowEvent,
|
||||
first_mouse: &mut bool,
|
||||
last_x: &mut f32,
|
||||
last_y: &mut f32,
|
||||
camera: &mut Camera,
|
||||
skip_input: bool
|
||||
) {
|
||||
match event {
|
||||
glfw::WindowEvent::FramebufferSize(width, height) => {
|
||||
// make sure the viewport matches the new window dimensions; note that width and
|
||||
// height will be significantly larger than specified on retina displays.
|
||||
unsafe { gl::Viewport(0, 0, width, height) }
|
||||
}
|
||||
glfw::WindowEvent::CursorPos(xpos, ypos) => {
|
||||
if skip_input { return; }
|
||||
let (xpos, ypos) = (xpos as f32, ypos as f32);
|
||||
if *first_mouse {
|
||||
*last_x = xpos;
|
||||
*last_y = ypos;
|
||||
*first_mouse = false;
|
||||
}
|
||||
|
||||
let xoffset = xpos - *last_x;
|
||||
let yoffset = *last_y - ypos; // reversed since y-coordinates go from bottom to top
|
||||
|
||||
*last_x = xpos;
|
||||
*last_y = ypos;
|
||||
|
||||
camera.process_mouse_movement(xoffset, yoffset, true);
|
||||
}
|
||||
glfw::WindowEvent::Scroll(_xoffset, yoffset) => {
|
||||
if skip_input { return; }
|
||||
camera.process_mouse_scroll(yoffset as f32);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Input processing function as introduced in 1.7.4 (Camera Class) and used in
|
||||
/// most later tutorials
|
||||
pub fn process_input(window: &mut glfw::Window, delta_time: f32, camera: &mut Camera) {
|
||||
if window.get_key(Key::Escape) == Action::Press {
|
||||
window.set_should_close(true)
|
||||
}
|
||||
|
||||
if window.get_key(Key::W) == Action::Press {
|
||||
camera.process_keyboard(Camera_Movement::FORWARD, delta_time);
|
||||
}
|
||||
if window.get_key(Key::S) == Action::Press {
|
||||
camera.process_keyboard(Camera_Movement::BACKWARD, delta_time);
|
||||
}
|
||||
if window.get_key(Key::A) == Action::Press {
|
||||
camera.process_keyboard(Camera_Movement::LEFT, delta_time);
|
||||
}
|
||||
if window.get_key(Key::D) == Action::Press {
|
||||
camera.process_keyboard(Camera_Movement::RIGHT, delta_time);
|
||||
}
|
||||
camera.enable_mouse_movement(window.get_key(Key::LeftControl) != Action::Press);
|
||||
engine.run();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue