Import Oxide engine (Stages 0–10) under MIT license
Full project snapshot migrated to new Gitea remote without history: engine, editor, physics, script, examples, tests, docs, and assets. Relicensed from GPLv3 to MIT and updated repo URLs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
//! Stage 4 example: load primitive meshes and render them lit, in 3D.
|
||||
//!
|
||||
//! Run with:
|
||||
//! cargo run -p oxide-examples --bin hello_mesh
|
||||
//!
|
||||
//! Shows a spinning cube, a sphere, and a ground plane drawn through the
|
||||
//! [`ForwardRenderer`] with a single directional light. Esc quits.
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
use oxide_engine::math::Quat;
|
||||
use oxide_engine::prelude::*;
|
||||
use oxide_engine::window::event::{ElementState, Key, NamedKey, WindowEvent};
|
||||
use oxide_engine::window::RenderCtx;
|
||||
|
||||
/// GPU resources, built lazily on the first frame (once the surface format is
|
||||
/// known) and reused thereafter.
|
||||
struct Gpu3d {
|
||||
pipeline: RenderPipeline,
|
||||
cube: GpuMesh,
|
||||
sphere: GpuMesh,
|
||||
plane: GpuMesh,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct HelloMesh {
|
||||
angle: f32,
|
||||
gpu: Option<Gpu3d>,
|
||||
}
|
||||
|
||||
impl WindowApp for HelloMesh {
|
||||
fn init(&mut self, ctx: &mut AppCtx<'_>) {
|
||||
ctx.set_clear_color(Color::rgb(0.05, 0.06, 0.09));
|
||||
log::info!("hello_mesh: spinning cube + sphere + ground plane (Esc quits)");
|
||||
}
|
||||
|
||||
fn event(&mut self, ctx: &mut AppCtx<'_>, event: &WindowEvent) {
|
||||
if let WindowEvent::KeyboardInput { event: key, .. } = event {
|
||||
if key.state == ElementState::Pressed && key.logical_key == Key::Named(NamedKey::Escape)
|
||||
{
|
||||
ctx.request_exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut AppCtx<'_>) {
|
||||
self.angle += ctx.dt;
|
||||
}
|
||||
|
||||
fn render(&mut self, ctx: &RenderCtx<'_>) {
|
||||
let device = ctx.gpu.device();
|
||||
let queue = ctx.gpu.queue();
|
||||
|
||||
let gpu = self.gpu.get_or_insert_with(|| {
|
||||
// The window runner already clears the surface to the configured
|
||||
// clear color before `render`, so the viewport pipeline is just the
|
||||
// forward pass (no clear pass needed here).
|
||||
let mut pipeline = RenderPipeline::new();
|
||||
pipeline.add_pass("forward", ForwardPass::new(device, ctx.surface_format));
|
||||
Gpu3d {
|
||||
pipeline,
|
||||
cube: Mesh::cube().upload(device, "cube"),
|
||||
sphere: Mesh::uv_sphere(0.8, 32, 16).upload(device, "sphere"),
|
||||
plane: Mesh::plane(12.0).upload(device, "plane"),
|
||||
}
|
||||
});
|
||||
|
||||
// Orbit the camera slowly around the scene.
|
||||
let eye = Vec3::new(
|
||||
4.0 * (self.angle * 0.3).cos(),
|
||||
2.6,
|
||||
4.0 * (self.angle * 0.3).sin(),
|
||||
);
|
||||
let view = Transform::looking_at(eye, Vec3::new(0.0, 0.2, 0.0), Vec3::Y);
|
||||
let camera = Camera::default();
|
||||
|
||||
let objects = [
|
||||
RenderObject {
|
||||
mesh: &gpu.plane,
|
||||
material: Material::diffuse(Color::rgb(0.25, 0.27, 0.30)),
|
||||
transform: Transform::from_translation(Vec3::new(0.0, -1.0, 0.0)),
|
||||
},
|
||||
RenderObject {
|
||||
mesh: &gpu.cube,
|
||||
material: Material::diffuse(Color::rgb(0.85, 0.20, 0.15)),
|
||||
transform: Transform::from_trs(
|
||||
Vec3::new(-1.3, 0.0, 0.0),
|
||||
Quat::from_euler(oxide_engine::math::EulerRot::YXZ, self.angle, 0.4, 0.0),
|
||||
Vec3::ONE,
|
||||
),
|
||||
},
|
||||
RenderObject {
|
||||
mesh: &gpu.sphere,
|
||||
material: Material::metal(Color::rgb(0.55, 0.65, 0.95), 0.35),
|
||||
transform: Transform::from_translation(Vec3::new(1.3, 0.2, 0.0)),
|
||||
},
|
||||
];
|
||||
|
||||
let lighting = Lighting::default();
|
||||
gpu.pipeline.render(&mut FrameContext {
|
||||
device,
|
||||
queue,
|
||||
color: ctx.view,
|
||||
size: ctx.size,
|
||||
viewport_rect: None,
|
||||
clear_color: Color::rgb(0.05, 0.06, 0.09),
|
||||
camera: &camera,
|
||||
view_transform: &view,
|
||||
lighting: &lighting,
|
||||
objects: &objects,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
|
||||
let config = WindowConfig {
|
||||
title: "Oxide — hello_mesh".to_string(),
|
||||
width: 960,
|
||||
height: 540,
|
||||
..Default::default()
|
||||
};
|
||||
run(config, HelloMesh::default())
|
||||
}
|
||||
Reference in New Issue
Block a user