adding texturing, getting sidetracked by config loading

master
mitchellhansen 4 years ago
parent 2b77153f10
commit da2c6a436a

@ -10,8 +10,21 @@ mesh = "ball.obj"
[entities.position] [entities.position]
x = 15.0 x = 15.0
y = 3.0 y = 15.0
z = 30.0 z = 15.0
[entities.position.rotation]
x = 0.0
y = 0.0
z = 0.0
[entities.physics]
body_status = "static"
[entities.physics.cuboid]
x = 1.0
y = 1.0
z = 1.0
[[entities]] [[entities]]
name = "camera.1" name = "camera.1"

@ -0,0 +1,12 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 323.999994
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.450000
d 1.000000
illum 2

@ -0,0 +1,46 @@
# Blender v2.91.2 OBJ File: ''
# www.blender.org
mtllib textured-cube.mtl
o Cube
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.875000 0.500000
vt 0.625000 0.750000
vt 0.625000 0.500000
vt 0.375000 1.000000
vt 0.375000 0.750000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.375000 0.500000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.625000 0.250000
vt 0.875000 0.750000
vt 0.625000 1.000000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
usemtl Material
s off
f 5/1/1 3/2/1 1/3/1
f 3/2/2 8/4/2 4/5/2
f 7/6/3 6/7/3 8/8/3
f 2/9/4 8/10/4 6/11/4
f 1/3/5 4/5/5 2/9/5
f 5/12/6 2/9/6 6/7/6
f 5/1/1 7/13/1 3/2/1
f 3/2/2 7/14/2 8/4/2
f 7/6/3 5/12/3 6/7/3
f 2/9/4 4/5/4 8/10/4
f 1/3/5 3/2/5 4/5/5
f 5/12/6 1/3/6 2/9/6

@ -1,13 +1,15 @@
use wgpu::{TextureView, Buffer, BindGroup};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant};
use cgmath::{Deg, Euler};
use rapier3d::dynamics::{RigidBody, RigidBodyHandle}; use rapier3d::dynamics::{RigidBody, RigidBodyHandle};
use rapier3d::geometry::ColliderHandle;
use rapier3d::geometry::Collider as r3dCollider; use rapier3d::geometry::Collider as r3dCollider;
use std::time::{Duration, Instant}; use rapier3d::geometry::ColliderHandle;
use cgmath::Deg; use wgpu::{BindGroup, Buffer, TextureView};
// a component is any type that is 'static, sized, send and sync use crate::runtime::state::{TomlPositionDescription, TomlRotationDescription};
// a component is any type that is 'static, sized, send and sync
pub struct ImguiWindow<'a> { pub struct ImguiWindow<'a> {
pub window: imgui::Window<'a>, pub window: imgui::Window<'a>,
@ -28,6 +30,47 @@ pub struct Position {
pub rot: cgmath::Euler<Deg<f32>>, pub rot: cgmath::Euler<Deg<f32>>,
} }
impl From<TomlPositionDescription> for Position {
fn from(pos: TomlPositionDescription) -> Self {
let euler = match pos.rot {
None => Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
Some(v) => Euler {
x: Deg(v.x),
y: Deg(v.y),
z: Deg(v.z),
},
};
Position {
x: pos.x,
y: pos.y,
z: pos.z,
rot: euler,
}
}
}
impl From<Option<TomlPositionDescription>> for Position {
fn from(pos: Option<TomlPositionDescription>) -> Self {
match pos {
None => Position {
x: 0.0,
y: 0.0,
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
},
Some(v) => Position::from(v),
}
}
}
#[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)] #[derive(Clone, Default, PartialEq, Eq, Hash, Copy, Debug)]
pub struct RangeCopy<Idx> { pub struct RangeCopy<Idx> {
pub start: Idx, pub start: Idx,
@ -55,4 +98,4 @@ pub struct Physics {
pub struct Collider { pub struct Collider {
pub collider: r3dCollider, pub collider: r3dCollider,
pub collider_handle: Option<ColliderHandle>, pub collider_handle: Option<ColliderHandle>,
} }

@ -92,12 +92,22 @@ https://github.com/amethyst/legion
ECS ECS
animation animation
config / save loading (sorta!)
render 3d (good!) render 3d (good!)
input/io (yep!) input/io (yep!)
collision / physics (yep!) collision / physics (yep!)
entities & behaviours (got the entities!) entities & behaviours (got the entities!)
scripting! scripting!
Todo:
Load scene imgui interface w/ toml files
FPS graph port from voxel raycaster
better imgui interface with components & systems
Figure out eventing, GameInput, passing all events, etc.
+ texturing
*/ */
//log::info!(""); //log::info!("");
@ -112,14 +122,6 @@ fn main() {
let logger = env_logger::builder().filter(Some("minimal_viable_game_engine"), LevelFilter::Info).init(); let logger = env_logger::builder().filter(Some("minimal_viable_game_engine"), LevelFilter::Info).init();
// for i in settings.get("entities") {
//
// }
let mut world = World::default(); let mut world = World::default();
let mut imgui_prepare_schedule = Schedule::builder() let mut imgui_prepare_schedule = Schedule::builder()

@ -17,50 +17,71 @@ use crate::components::{Collider, LoopState, Mesh, Physics, Position};
use crate::geometry::{load_obj, RawMesh}; use crate::geometry::{load_obj, RawMesh};
use std::io::Read; use std::io::Read;
pub struct EntityMeta {
pub name: String,
pub ent_type: String, #[derive(Deserialize, Clone)]
pub mesh: Option<String>, pub struct TomlBallPhysicsBodyDescription {
pub position: Option<Position> pub radius: String
} }
pub struct RuntimeState { #[derive(Deserialize, Clone)]
config_db: TomlEntityContainer, pub struct TomlCuboidPhysicsBodyDescription {
mesh_cache: HashMap<String, RawMesh>, pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Deserialize, Clone)]
pub struct TomlPhysicsDescription {
pub body_status: String,
pub ball: Option<TomlBallPhysicsBodyDescription>,
pub cuboid: Option<TomlCuboidPhysicsBodyDescription>,
} }
#[derive(Deserialize)] #[derive(Deserialize, Clone)]
pub struct TomlRotationDescription {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Deserialize, Clone)]
pub struct TomlPositionDescription { pub struct TomlPositionDescription {
pub x: f32, pub x: f32,
pub y: f32, pub y: f32,
pub z: f32, pub z: f32,
pub rot: Option<TomlRotationDescription>,
} }
#[derive(Deserialize)] #[derive(Deserialize, Clone)]
pub struct TomlEntityDescription { pub struct TomlEntityDescription {
pub name: String, pub name: String,
#[serde(rename = "type")] #[serde(rename = "type")]
pub type_name: String, pub type_name: String,
pub mesh: Option<String>, pub mesh: Option<String>,
pub position: Option<TomlPositionDescription>, pub position: Option<TomlPositionDescription>,
pub physics: Option<TomlPhysicsDescription>,
} }
#[derive(Deserialize)] #[derive(Deserialize, Clone)]
pub struct TomlEntityContainer { pub struct TomlEntityContainer {
pub entities: Vec<TomlEntityDescription>, pub entities: Vec<TomlEntityDescription>,
} }
pub struct RuntimeState {
config_db: TomlEntityContainer,
mesh_cache: HashMap<String, RawMesh>,
}
impl RuntimeState { impl RuntimeState {
pub fn new() -> RuntimeState { pub fn new() -> RuntimeState {
// TODO: Hook this file to the gui
let mut file = fs::File::open("./conf/entity_spawns.toml").unwrap(); let mut file = fs::File::open("./conf/entity_spawns.toml").unwrap();
let mut content = String::new(); let mut content = String::new();
file.read_to_string(&mut content).unwrap(); file.read_to_string(&mut content).unwrap();
// TODO: gracefully fail
let mut settings : TomlEntityContainer = toml::from_str(content.as_str()).unwrap(); let mut settings : TomlEntityContainer = toml::from_str(content.as_str()).unwrap();
// settings
// // File::with_name(..) is shorthand for File::from(Path::new(..))
// .merge(File::with_name("conf/entity_spawns.toml"))
// .unwrap();
RuntimeState { RuntimeState {
config_db: settings, config_db: settings,
@ -72,40 +93,8 @@ impl RuntimeState {
self.mesh_cache.get(mesh) self.mesh_cache.get(mesh)
} }
pub fn get_configured_entities(&mut self) -> Vec<EntityMeta> { pub fn get_entities(&mut self) -> Vec<TomlEntityDescription> {
let mut out = Vec::new(); self.config_db.entities.clone()
for entity in &self.config_db.entities {
let position = match &entity.position {
None => { None }
Some(pos) => {
Some(Position {
x: pos.x,
y: pos.y,
z: pos.z,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0)
}
})
}
};
// log::info!("{:?}", position);
// log::info!("{:?}", entity);
// log::info!("{:?}", entity.into_table());
// log::info!("{:?}", entity.into_array());
out.push(EntityMeta {
name: entity.name.clone(),
ent_type: entity.type_name.clone(),
mesh: entity.mesh.clone(),
position: position
});
}
out
} }
pub fn preload_meshes(&mut self, resources_path: PathBuf) { pub fn preload_meshes(&mut self, resources_path: PathBuf) {

@ -9,7 +9,9 @@ use legion::world::SubWorld;
use legion::IntoQuery; use legion::IntoQuery;
use legion::*; use legion::*;
use nalgebra::Quaternion as naQuaternion; use nalgebra::Quaternion as naQuaternion;
use rapier3d::dynamics::{IntegrationParameters, JointSet, RigidBodyBuilder, RigidBodySet, MassProperties}; use rapier3d::dynamics::{
IntegrationParameters, JointSet, MassProperties, RigidBodyBuilder, RigidBodySet,
};
use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase}; use rapier3d::geometry::{BroadPhase, ColliderBuilder, ColliderSet, NarrowPhase};
use rapier3d::na::{Isometry3, Vector, Vector3}; use rapier3d::na::{Isometry3, Vector, Vector3};
use rapier3d::pipeline::{ChannelEventCollector, PhysicsPipeline}; use rapier3d::pipeline::{ChannelEventCollector, PhysicsPipeline};
@ -35,10 +37,10 @@ pub fn runtime_spawn(
#[resource] runtime_state: &mut RuntimeState, #[resource] runtime_state: &mut RuntimeState,
#[resource] renderer: &mut RenderState, #[resource] renderer: &mut RenderState,
) { ) {
for entity in runtime_state.get_configured_entities() { for entity in &runtime_state.get_entities() {
match entity.ent_type.as_ref() { match entity.type_name.as_ref() {
"PhysicsEntity" => { "PhysicsEntity" => {
let mesh_name = entity.mesh.unwrap(); let mesh_name = entity.mesh.as_ref().unwrap();
let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) { let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
None => { None => {
log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name); log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
@ -47,14 +49,13 @@ pub fn runtime_spawn(
Some(mesh) => mesh, Some(mesh) => mesh,
}; };
let collider = ColliderBuilder::trimesh(
raw_mesh.vertices.iter().map(|v| v.position()).collect(),
raw_mesh.indices.clone(),
)
.build();
// let collider = ColliderBuilder::trimesh( let collider = ColliderBuilder::capsule_y(2.0, 1.0).build();
// raw_mesh.vertices.iter().map(|v| v.position()).collect(),
// raw_mesh.indices.clone(),
// ).density(1.0)
// .build();
let collider = ColliderBuilder::ball(2.0).build();
let gpu_mesh_buffer = renderer let gpu_mesh_buffer = renderer
.upload_mesh_to_buffer( .upload_mesh_to_buffer(
@ -68,19 +69,7 @@ pub fn runtime_spawn(
) )
.unwrap(); .unwrap();
let position = match entity.position { let position = Position::from(entity.position.clone());
None => Position {
x: 0.0,
y: rand::random::<f32>(),
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
},
Some(position) => position
};
let mut dynamic_body = RigidBodyBuilder::new_dynamic() let mut dynamic_body = RigidBodyBuilder::new_dynamic()
.can_sleep(false) .can_sleep(false)
@ -102,7 +91,7 @@ pub fn runtime_spawn(
)); ));
} }
"Terrain" => { "Terrain" => {
let mesh_name = entity.mesh.unwrap(); let mesh_name = entity.mesh.clone().unwrap();
let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) { let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
None => { None => {
log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name); log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
@ -111,8 +100,13 @@ pub fn runtime_spawn(
Some(mesh) => mesh, Some(mesh) => mesh,
}; };
let position = Position::from(entity.position.clone());
let mut static_body = RigidBodyBuilder::new_static() let mut static_body = RigidBodyBuilder::new_static()
.position(Isometry3::new(Vector3::new(0.0, -8.0, 0.0), Vector::y())) .position(Isometry3::new(
Vector3::new(position.x, position.y, position.z),
Vector::y(),
))
.build(); .build();
let mesh_collider = ColliderBuilder::trimesh( let mesh_collider = ColliderBuilder::trimesh(
@ -133,21 +127,6 @@ pub fn runtime_spawn(
) )
.unwrap(); .unwrap();
let position = match entity.position {
None => Position {
x: 0.0,
y: 0.0,
z: 0.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
},
Some(position) => position
};
let entity: Entity = cmd.push(( let entity: Entity = cmd.push((
position, position,
gpu_mesh_buffer, gpu_mesh_buffer,
@ -162,21 +141,22 @@ pub fn runtime_spawn(
)); ));
} }
"Camera" => { "Camera" => {
let position = Position::from(entity.position.clone());
let entity: Entity = cmd.push(( let entity: Entity = cmd.push((
Camera { Camera {
position: cgmath::Point3 { position: cgmath::Point3 {
x: 0.0, x: position.x,
y: 0.0, y: position.y,
z: 10.0, z: position.z,
}, },
yaw: Rad(-PI), yaw: Rad(-PI),
pitch: Rad(PI / 2.0), pitch: Rad(PI / 2.0),
}, },
CameraController::new(3.0, 1.0), CameraController::new(5.0, 1.0),
)); ));
} }
"Light" => { "Light" => {
let mesh_name = entity.mesh.unwrap(); let mesh_name = entity.mesh.clone().unwrap();
let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) { let raw_mesh = match runtime_state.get_mesh(mesh_name.as_str()) {
None => { None => {
log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name); log::warn!("Skipping entity with invalid mesh file {:?} ", mesh_name);
@ -185,19 +165,7 @@ pub fn runtime_spawn(
Some(mesh) => mesh, Some(mesh) => mesh,
}; };
let position = match entity.position { let position = Position::from(entity.position.clone());
None => Position {
x: 1.0,
y: 1.0,
z: 1.0,
rot: Euler {
x: Deg(0.0),
y: Deg(0.0),
z: Deg(0.0),
},
},
Some(position) => position
};
let gpu_mesh_buffer = renderer let gpu_mesh_buffer = renderer
.upload_mesh_to_buffer( .upload_mesh_to_buffer(
@ -211,11 +179,8 @@ pub fn runtime_spawn(
) )
.unwrap(); .unwrap();
let light_entity: Entity = cmd.push(( let light_entity: Entity =
position, cmd.push((position, gpu_mesh_buffer, renderer.create_light()));
gpu_mesh_buffer,
renderer.create_light(),
));
} }
_ => {} _ => {}

Loading…
Cancel
Save