wip: engine enhancements and fixes
This commit is contained in:
parent
9816f14f53
commit
cc7921a5fe
27 changed files with 347 additions and 32 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
|
@ -75,9 +75,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.98"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
|
|
@ -1258,10 +1258,19 @@ dependencies = [
|
|||
"winit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raidillon_ecs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"raidillon_assets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raidillon_game"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"raidillon_core",
|
||||
"raidillon_glium",
|
||||
"raidillon_platform",
|
||||
|
|
@ -1278,6 +1287,7 @@ dependencies = [
|
|||
"indexmap",
|
||||
"raidillon_assets",
|
||||
"raidillon_core",
|
||||
"raidillon_ecs",
|
||||
"raidillon_platform",
|
||||
"winit",
|
||||
]
|
||||
|
|
@ -1286,6 +1296,7 @@ dependencies = [
|
|||
name = "raidillon_platform"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"glam",
|
||||
"raidillon_assets",
|
||||
"raidillon_core",
|
||||
"winit",
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@ members = [
|
|||
"glium_platform",
|
||||
"platform",
|
||||
"asset",
|
||||
"game"
|
||||
"game",
|
||||
"ecs"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,5 +2,3 @@
|
|||
name = "raidillon_assets"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
pub mod model_manager;
|
||||
|
||||
pub use crate::model_manager::{ModelManager, ModelManagerRef};
|
||||
|
||||
pub use crate::model_manager::ModelID;
|
||||
#[macro_export]
|
||||
macro_rules! include_shader {
|
||||
($path:expr) => {
|
||||
include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/shaders/", $path))
|
||||
};
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
use std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
|
||||
pub type ModelManagerRef = Rc<RefCell<Box<dyn ModelManager>>>;
|
||||
|
||||
pub type ModelID = PathBuf;
|
||||
|
||||
/// The asset manager trait of Raidillon.
|
||||
pub trait ModelManager {
|
||||
pub trait ModelManager: Any {
|
||||
/// Loads a gltf model to VRAM.
|
||||
fn load_gltf(&mut self, path: &Path);
|
||||
/// Unloads the loaded model from VRAM.
|
||||
fn unload_model(&mut self, path: &Path);
|
||||
|
||||
fn get_model(&self, id: &ModelID) -> Option<&dyn Any>;
|
||||
}
|
||||
|
|
|
|||
34
assets/shaders/gl_textured.frag
Normal file
34
assets/shaders/gl_textured.frag
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#version 330 core
|
||||
|
||||
in vec3 v_normal;
|
||||
in vec2 v_tex;
|
||||
in vec3 v_position;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
uniform vec3 u_light;
|
||||
uniform sampler2D tex;
|
||||
uniform vec3 color; // base colour factor (acts as solid colour when no texture)
|
||||
|
||||
void main() {
|
||||
// Combine base texture (or constant white) with colour factor supplied by CPU.
|
||||
vec3 base_col = texture(tex, v_tex).rgb * color;
|
||||
|
||||
vec3 ambient_color = base_col * 0.2;
|
||||
vec3 diffuse_color = base_col * 0.6;
|
||||
vec3 specular_color = vec3(1.0);
|
||||
|
||||
// u_light is the direction **from the light towards the fragment**.
|
||||
float diffuse = max(dot(normalize(v_normal), normalize(u_light)), 0.0);
|
||||
|
||||
vec3 camera_dir = normalize(-v_position);
|
||||
vec3 half_dir = normalize(normalize(u_light) + camera_dir);
|
||||
float specular = pow(max(dot(half_dir, normalize(v_normal)), 0.0), 16.0);
|
||||
|
||||
vec3 result = ambient_color + diffuse * diffuse_color + specular * specular_color;
|
||||
|
||||
// Convert from linear to sRGB for display (approximate γ-correction)
|
||||
result = pow(result, vec3(1.0 / 2.2));
|
||||
|
||||
frag_color = vec4(result, 1.0);
|
||||
}
|
||||
23
assets/shaders/gl_textured.vert
Normal file
23
assets/shaders/gl_textured.vert
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#version 330 core
|
||||
|
||||
in vec3 position;
|
||||
in vec3 normal;
|
||||
in vec2 tex_coords;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
uniform vec2 uv_offset;
|
||||
uniform vec2 uv_scale;
|
||||
|
||||
out vec3 v_normal;
|
||||
out vec2 v_tex;
|
||||
out vec3 v_position;
|
||||
|
||||
void main() {
|
||||
mat4 modelview = view * model;
|
||||
v_normal = transpose(inverse(mat3(modelview))) * normal;
|
||||
v_tex = tex_coords * uv_scale + uv_offset;
|
||||
v_position = (modelview * vec4(position, 1.0)).xyz;
|
||||
gl_Position = projection * modelview * vec4(position, 1.0);
|
||||
}
|
||||
22
assets/shaders/skybox.frag
Normal file
22
assets/shaders/skybox.frag
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#version 330 core
|
||||
|
||||
in vec3 direction;
|
||||
|
||||
out vec4 frag_color;
|
||||
|
||||
uniform sampler2D equirect;
|
||||
|
||||
const vec2 inv_atan = vec2(0.15915494309, 0.31830988618);
|
||||
|
||||
vec2 sample_spherical_map(vec3 v) {
|
||||
vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
|
||||
uv *= inv_atan;
|
||||
uv += 0.5;
|
||||
return uv;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = sample_spherical_map(normalize(direction));
|
||||
vec3 color = texture(equirect, uv).rgb;
|
||||
frag_color = vec4(color, 1.0);
|
||||
}
|
||||
15
assets/shaders/skybox.vert
Normal file
15
assets/shaders/skybox.vert
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#version 330 core
|
||||
|
||||
in vec3 position;
|
||||
|
||||
uniform mat4 view;
|
||||
|
||||
uniform mat4 projection;
|
||||
|
||||
out vec3 direction;
|
||||
|
||||
void main() {
|
||||
direction = position;
|
||||
vec4 pos = projection * view * vec4(position, 1.0);
|
||||
gl_Position = pos.xyww;
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ use std::collections::HashMap;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub struct Scene {
|
||||
title: String,
|
||||
world: hecs::World,
|
||||
skybox_texture_path: Option<PathBuf>,
|
||||
pub title: String,
|
||||
pub world: hecs::World,
|
||||
pub skybox_texture_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Scene {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub trait System {
|
|||
fn update(&mut self, ctx: &mut SystemContext);
|
||||
}
|
||||
|
||||
pub type SystemID = String;
|
||||
pub type SystemID = &'static str;
|
||||
pub struct SystemManager {
|
||||
pub systems: IndexMap<SystemID, Box<dyn System>>,
|
||||
}
|
||||
|
|
|
|||
8
ecs/Cargo.toml
Normal file
8
ecs/Cargo.toml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
[package]
|
||||
name = "raidillon_ecs"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
glam = "0.30.5"
|
||||
raidillon_assets = { path = "../asset" }
|
||||
15
ecs/src/components.rs
Normal file
15
ecs/src/components.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use glam::{Vec3, Quat, Mat4};
|
||||
pub use raidillon_assets::ModelID;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Transform {
|
||||
pub translation: Vec3,
|
||||
pub rotation: Quat,
|
||||
pub scale: Vec3,
|
||||
}
|
||||
|
||||
impl Transform {
|
||||
pub fn matrix(&self) -> Mat4 {
|
||||
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
|
||||
}
|
||||
}
|
||||
3
ecs/src/lib.rs
Normal file
3
ecs/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub mod components;
|
||||
|
||||
pub use components::{Transform, ModelID};
|
||||
|
|
@ -11,3 +11,4 @@ glium = ["raidillon_glium"]
|
|||
raidillon_core = { path = "../core" }
|
||||
raidillon_platform = { path = "../platform" }
|
||||
raidillon_glium = { path = "../glium_platform", optional = true }
|
||||
glam = "0.30.5"
|
||||
|
|
@ -1,14 +1,39 @@
|
|||
use raidillon_core::{Engine, Scene};
|
||||
use raidillon_platform::Platform;
|
||||
use glam::Vec3;
|
||||
use raidillon_core::{Engine, Scene, System};
|
||||
use raidillon_core::system::SystemContext;
|
||||
use raidillon_platform::{Platform, Camera};
|
||||
|
||||
#[cfg(feature = "glium")]
|
||||
use raidillon_glium::GliumPlatform;
|
||||
|
||||
const RENDERING_TEST_SYSTEM: &str = "rendering_test_system";
|
||||
struct RenderingTestSystem;
|
||||
|
||||
impl System for RenderingTestSystem {
|
||||
fn initialize(&mut self) {}
|
||||
fn load_world(&mut self, ctx: &mut SystemContext) {
|
||||
ctx.scene.world.spawn((Camera {
|
||||
eye: Vec3::new(0.0, 0.0, 2.0),
|
||||
center: Vec3::ZERO,
|
||||
up: Vec3::Y,
|
||||
fovy: 60_f32.to_radians(),
|
||||
aspect: 1920 as f32 / 1080 as f32, // FIXME
|
||||
znear: 0.1,
|
||||
zfar: 100.0,
|
||||
},));
|
||||
|
||||
// TODO: Load a sample glTF file
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut SystemContext) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut engine = Engine::new();
|
||||
// Define systems
|
||||
// engine.system_manager.add_system("spawn_chunks".to_string(), ChunkSystem);
|
||||
// engine.system_manager.add_system("movement".to_string(), MovementSystem);
|
||||
engine.system_manager.add_system(RENDERING_TEST_SYSTEM, Box::new(RenderingTestSystem));
|
||||
|
||||
// Set up the scene
|
||||
let main_scene_id = "Main".to_owned();
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ gltf = { version = "1.4.1", features = ["import", "utils", "KHR_texture_transfor
|
|||
raidillon_platform = { path = "../platform" }
|
||||
raidillon_core = { path = "../core" }
|
||||
raidillon_assets = { path = "../asset" }
|
||||
raidillon_ecs = { path = "../ecs" }
|
||||
winit = "0.30.12"
|
||||
indexmap = "2.10.0"
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
use std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use raidillon_assets::{ModelManagerRef, ModelManager};
|
||||
use crate::model::Model;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
|
@ -5,10 +7,12 @@ use crate::gltf_loader::load_gltf;
|
|||
use glium::backend::Facade;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::rc::Rc;
|
||||
use raidillon_assets::model_manager::ModelID;
|
||||
|
||||
/// Glium platform asset manager implementation.
|
||||
pub struct GliumAssetManager {
|
||||
models: HashMap<PathBuf, Model>,
|
||||
pub models: HashMap<PathBuf, Model>,
|
||||
facade: Box<dyn Facade>,
|
||||
}
|
||||
|
||||
|
|
@ -42,4 +46,8 @@ impl ModelManager for GliumAssetManager {
|
|||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
fn get_model(&self, id: &ModelID) -> Option<&dyn Any> {
|
||||
self.models.get(id).map(|model| model as &dyn Any)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@ pub mod gltf_loader;
|
|||
pub mod system;
|
||||
mod render;
|
||||
|
||||
pub use assets::GliumAssetManager;
|
||||
pub use assets::{GliumAssetManager};
|
||||
pub use platform::GliumPlatform;
|
||||
pub use system::RenderingSystem;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::any::{Any, TypeId};
|
||||
use glium::{IndexBuffer, VertexBuffer, implement_vertex};
|
||||
use glium::texture::{SrgbTexture2d, Texture2d};
|
||||
use glium::uniforms::SamplerBehavior;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use raidillon_platform::Platform;
|
||||
use glium::winit::event_loop::EventLoop;
|
||||
|
|
@ -8,12 +9,14 @@ use glium::backend::glutin::Display;
|
|||
use glium::glutin::surface::WindowSurface;
|
||||
use glium::backend::glutin::SimpleWindowBuilder;
|
||||
use glium::Surface;
|
||||
use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext};
|
||||
use crate::system::{RenderingSystemManager, RenderingSystem, RenderingContext, SystemID};
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use raidillon_assets::{ModelManager, ModelManagerRef};
|
||||
use raidillon_core::Engine;
|
||||
use crate::GliumAssetManager;
|
||||
use crate::render::BasicRenderingSystem;
|
||||
use crate::{GliumAssetManager};
|
||||
use crate::render::BasicMeshRenderingSystem;
|
||||
|
||||
pub const MESH_RENDERER: &str = "mesh_renderer";
|
||||
|
||||
pub struct GliumPlatform {
|
||||
event_loop: EventLoop<()>,
|
||||
|
|
@ -36,8 +39,15 @@ impl Platform for GliumPlatform {
|
|||
.build(&event_loop);
|
||||
|
||||
let asset_manager: ModelManagerRef = Rc::new(RefCell::new(Box::new(GliumAssetManager::new(Box::new(display.clone())))));
|
||||
let rendering_system_manager = RenderingSystemManager::new();
|
||||
let mut rendering_system_manager = RenderingSystemManager::new();
|
||||
engine.set_model_manager(asset_manager.clone());
|
||||
|
||||
// Install rendering systems
|
||||
rendering_system_manager.add_system(
|
||||
MESH_RENDERER,
|
||||
Box::new(BasicMeshRenderingSystem::initialize(&display))
|
||||
);
|
||||
|
||||
Self {
|
||||
event_loop,
|
||||
window,
|
||||
|
|
@ -49,6 +59,7 @@ impl Platform for GliumPlatform {
|
|||
}
|
||||
|
||||
fn run(mut self) {
|
||||
self.engine.initialize();
|
||||
let _ = &self.event_loop.run(move |event, el| {
|
||||
match event {
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,111 @@
|
|||
use crate::RenderingSystem;
|
||||
use std::any::Any;
|
||||
use glium::{uniform, Display, Program, Surface};
|
||||
use glium::glutin::surface::WindowSurface;
|
||||
use glium::texture::{RawImage2d, SrgbTexture2d};
|
||||
use crate::{GliumAssetManager, RenderingSystem};
|
||||
use crate::system::RenderingContext;
|
||||
use raidillon_assets::include_shader;
|
||||
pub use raidillon_platform::Camera;
|
||||
use glam::Vec3;
|
||||
use glium::uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction};
|
||||
use raidillon_ecs::{Transform, ModelID};
|
||||
use crate::model::Model;
|
||||
|
||||
/// A basic renderer pipeline step.
|
||||
pub struct BasicRenderingSystem;
|
||||
pub struct BasicMeshRenderingSystem {
|
||||
program: Program,
|
||||
white_tex: SrgbTexture2d,
|
||||
params: glium::DrawParameters<'static>,
|
||||
}
|
||||
|
||||
impl RenderingSystem for BasicMeshRenderingSystem {
|
||||
fn initialize(display: &Display<WindowSurface>) -> Self {
|
||||
const VERT_SRC: &str = include_shader!("gl_textured.vert");
|
||||
const FRAG_SRC: &str = include_shader!("gl_textured.frag");
|
||||
|
||||
let program = Program::from_source(display, VERT_SRC, FRAG_SRC, None).unwrap();
|
||||
|
||||
let white_tex = {
|
||||
let data = vec![255u8, 255u8, 255u8, 255u8];
|
||||
let raw = RawImage2d::from_raw_rgba(data, (1, 1));
|
||||
SrgbTexture2d::new(display, raw).unwrap()
|
||||
};
|
||||
|
||||
let params = glium::DrawParameters {
|
||||
depth: glium::Depth {
|
||||
test: glium::draw_parameters::DepthTest::IfLess,
|
||||
write: true,
|
||||
.. Default::default()
|
||||
},
|
||||
.. Default::default()
|
||||
};
|
||||
|
||||
Self {
|
||||
program, white_tex, params
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderingSystem for BasicRenderingSystem {
|
||||
fn render(&mut self, ctx: &mut RenderingContext) {
|
||||
todo!()
|
||||
let cam = match ctx.scene.world.query::<&Camera>().iter().next() {
|
||||
Some((_, cam)) => *cam,
|
||||
None => {
|
||||
eprintln!("[renderer] No camera component found. Skipping frame");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Direction from the light source (0,+Y) towards the scene.
|
||||
let light_dir: Vec3 = Vec3::new(0.0, -1.0, 0.0).normalize();
|
||||
|
||||
// let asset_manager = ctx.asset_manager.borrow();
|
||||
// let any_ref: &dyn Any = &**asset_manager;
|
||||
// if let Some(glium_manager) = any_ref.downcast_ref::<GliumAssetManager>() {
|
||||
// &glium_manager.models;
|
||||
// }
|
||||
|
||||
let asset_manager = ctx.asset_manager.borrow();
|
||||
|
||||
for (_, (tr, mh)) in ctx.scene.world.query::<(&Transform, &ModelID)>().iter() {
|
||||
let model = match asset_manager.get_model(mh) {
|
||||
Some(model) => model,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let model = match model.downcast_ref::<Model>() {
|
||||
Some(model) => model,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let mesh = &model.mesh;
|
||||
let mat = &model.material;
|
||||
|
||||
let tex_ref: &SrgbTexture2d = mat.base_color.as_ref().unwrap_or(&self.white_tex);
|
||||
|
||||
let mut sampler = tex_ref.sampled();
|
||||
sampler = sampler.wrap_function(SamplerWrapFunction::Repeat);
|
||||
sampler = sampler.minify_filter(MinifySamplerFilter::Linear);
|
||||
sampler = sampler.magnify_filter(MagnifySamplerFilter::Linear);
|
||||
|
||||
let c = mat.base_color_factor;
|
||||
|
||||
let uniforms = uniform! {
|
||||
model: tr.matrix().to_cols_array_2d(),
|
||||
view: cam.view().to_cols_array_2d(),
|
||||
projection: cam.projection().to_cols_array_2d(),
|
||||
u_light: [light_dir.x, light_dir.y, light_dir.z],
|
||||
tex: sampler,
|
||||
color: [c[0], c[1], c[2]],
|
||||
uv_offset: [mat.uv_offset.x, mat.uv_offset.y],
|
||||
uv_scale: [mat.uv_scale.x, mat.uv_scale.y],
|
||||
};
|
||||
|
||||
ctx.target.draw(
|
||||
&mesh.vbuf,
|
||||
&mesh.ibuf,
|
||||
&self.program,
|
||||
&uniforms,
|
||||
&self.params,
|
||||
).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
mod basic;
|
||||
pub use basic::BasicRenderingSystem;
|
||||
pub use basic::BasicMeshRenderingSystem;
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use raidillon_core::Scene;
|
||||
use glium::Frame;
|
||||
use crate::GliumAssetManager;
|
||||
use glium::{Display, Frame};
|
||||
use glium::glutin::surface::WindowSurface;
|
||||
use indexmap::IndexMap;
|
||||
use raidillon_assets::ModelManagerRef;
|
||||
use crate::GliumAssetManager;
|
||||
|
||||
pub struct RenderingContext<'a> {
|
||||
pub scene: &'a Scene,
|
||||
|
|
@ -14,10 +17,10 @@ pub struct RenderingContext<'a> {
|
|||
/// This is unrelated to the main System trait in core.
|
||||
pub trait RenderingSystem {
|
||||
fn render(&mut self, ctx: &mut RenderingContext);
|
||||
fn compile_shaders(&mut self) {}
|
||||
fn initialize(display: &Display<WindowSurface>) -> Self where Self: Sized;
|
||||
}
|
||||
|
||||
type SystemID = String;
|
||||
pub type SystemID = &'static str;
|
||||
|
||||
pub struct RenderingSystemManager {
|
||||
pub systems: IndexMap<SystemID, Box<dyn RenderingSystem>>,
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@ edition = "2024"
|
|||
winit = "0.30.12"
|
||||
raidillon_core = { path = "../core" }
|
||||
raidillon_assets = { path = "../asset" }
|
||||
glam = "0.30.5"
|
||||
|
|
|
|||
24
platform/src/camera.rs
Normal file
24
platform/src/camera.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use glam::{Mat4, Vec3};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Camera {
|
||||
pub eye: Vec3,
|
||||
pub center: Vec3,
|
||||
pub up: Vec3,
|
||||
pub fovy: f32,
|
||||
pub aspect: f32,
|
||||
pub znear: f32,
|
||||
pub zfar: f32,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
pub fn view(&self) -> Mat4 {
|
||||
Mat4::look_at_rh(self.eye, self.center, self.up)
|
||||
}
|
||||
pub fn projection(&self) -> Mat4 {
|
||||
Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar)
|
||||
}
|
||||
pub fn view_proj(&self) -> Mat4 {
|
||||
self.projection() * self.view()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
pub mod platform;
|
||||
pub mod context;
|
||||
mod camera;
|
||||
|
||||
pub use context::PlatformContext;
|
||||
pub use platform::Platform;
|
||||
pub use camera::Camera;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue