Skip to content

Commit d0a5c94

Browse files
authored
Add content pack system (#7)
* Refactor model loading * Move terrain data out of Renderer * Support multiple colliders * Content packs * Fix update problem * Cylinder gravity * cargo fmt * Prettify code * Assert level file ends with ".ron" * Rename "content_packs" to "content-packs" * Rename remove "vangers-ffi"
1 parent 3b39af7 commit d0a5c94

File tree

28 files changed

+1079
-453
lines changed

28 files changed

+1079
-453
lines changed

Cargo.lock

Lines changed: 21 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
resolver = "2"
3-
members = ["lib/ffi"]
3+
members = ["lib/content-packs"]
44

55
[workspace.dependencies]
66
blade-graphics = "0.6"

bin/game/main.rs

Lines changed: 94 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
use blade_graphics as gpu;
2-
use vandals_and_heroes::{config, Camera, ModelDesc, Object, Physics, Render, TerrainBody};
2+
use vandals_and_heroes::{
3+
config, Camera, Loader, ModelDesc, ModelInstance, Physics, PhysicsBodyHandle, Render, Terrain,
4+
TerrainBody,
5+
};
36

7+
use nalgebra::Matrix4;
48
use std::{f32, fs, path, sync::Arc, thread, time};
59

6-
struct Car {
7-
body: Object,
10+
pub struct Object {
11+
pub model_instance: ModelInstance,
12+
pub rigid_body: rapier3d::dynamics::RigidBodyHandle,
813
}
914

1015
pub struct Game {
@@ -22,7 +27,8 @@ pub struct Game {
2227
last_mouse_pos: [i32; 2],
2328
// game
2429
terrain_body: TerrainBody,
25-
car: Car,
30+
terrain: Terrain,
31+
car: Object,
2632
}
2733

2834
pub struct QuitEvent;
@@ -65,29 +71,15 @@ impl Game {
6571

6672
let mut loader = render.start_loading();
6773

68-
let car_body = {
69-
log::info!("Loading car: {}", config.car);
70-
let car_path = path::PathBuf::from("data/cars").join(config.car);
71-
let car_config: config::Car = ron::de::from_bytes(
72-
&fs::read(car_path.join("car.ron")).expect("Unable to open the car config"),
73-
)
74-
.expect("Unable to parse the car config");
75-
let desc = ModelDesc {
76-
scale: car_config.scale,
77-
density: car_config.density,
78-
};
79-
loader.load_gltf(&car_path.join("body.glb"), desc)
80-
};
81-
82-
let map_config = {
74+
let terrain = {
8375
log::info!("Loading map: {}", config.map);
8476
let map_path = path::PathBuf::from("data/maps").join(config.map);
8577
let mut map_config: config::Map = ron::de::from_bytes(
8678
&fs::read(map_path.join("map.ron")).expect("Unable to open the map config"),
8779
)
8880
.expect("Unable to parse the map config");
8981

90-
let (map_texture, map_extent) = loader.load_png(&map_path.join("map.png"));
82+
let (texture, map_extent) = loader.load_png(&map_path.join("map.png"));
9183

9284
if map_config.length == 0.0 {
9385
let circumference = 2.0 * f32::consts::PI * map_config.radius.start;
@@ -96,44 +88,50 @@ impl Game {
9688
log::info!("Derived map length to be {}", map_config.length);
9789
}
9890

99-
let submission = loader.finish();
100-
render.accept_submission(submission);
101-
render.set_map(map_texture, &map_config);
102-
103-
map_config
91+
Terrain {
92+
config: map_config,
93+
texture,
94+
}
10495
};
96+
let mut physics = Physics::default();
97+
let terrain_body = physics.create_terrain(&terrain.config);
98+
99+
let car = Self::load_car(
100+
&mut loader,
101+
&mut physics,
102+
&config.car,
103+
nalgebra::Isometry3 {
104+
translation: nalgebra::Vector3::new(
105+
0.0,
106+
0.35 * terrain.config.radius.start + 0.65 * terrain.config.radius.end,
107+
0.1 * terrain.config.length,
108+
)
109+
.into(),
110+
rotation: nalgebra::UnitQuaternion::from_axis_angle(
111+
&nalgebra::Vector3::y_axis(),
112+
0.5 * f32::consts::PI,
113+
),
114+
},
115+
);
116+
117+
let submission = loader.finish();
118+
render.accept_submission(submission);
119+
render.wait_for_gpu();
105120

106121
let camera = Camera {
107-
pos: nalgebra::Vector3::new(0.0, map_config.radius.end, 0.1 * map_config.length),
122+
pos: nalgebra::Vector3::new(
123+
0.0,
124+
terrain.config.radius.end,
125+
0.1 * terrain.config.length,
126+
),
108127
rot: nalgebra::UnitQuaternion::from_axis_angle(
109128
&nalgebra::Vector3::x_axis(),
110129
0.3 * f32::consts::PI,
111130
),
112-
clip: 1.0..map_config.length,
131+
clip: 1.0..terrain.config.length,
113132
..Default::default()
114133
};
115134

116-
let mut physics = Physics::default();
117-
let terrain_body = physics.create_terrain(&map_config);
118-
119-
let car = Car {
120-
body: physics.create_object(
121-
Arc::new(car_body),
122-
nalgebra::Isometry3 {
123-
translation: nalgebra::Vector3::new(
124-
0.0,
125-
0.35 * map_config.radius.start + 0.65 * map_config.radius.end,
126-
0.1 * map_config.length,
127-
)
128-
.into(),
129-
rotation: nalgebra::UnitQuaternion::from_axis_angle(
130-
&nalgebra::Vector3::y_axis(),
131-
0.5 * f32::consts::PI,
132-
),
133-
},
134-
),
135-
};
136-
137135
Self {
138136
choir,
139137
render,
@@ -144,28 +142,71 @@ impl Game {
144142
in_camera_drag: false,
145143
last_mouse_pos: [0; 2],
146144
terrain_body,
145+
terrain,
147146
car,
148147
}
149148
}
150149

150+
fn load_car(
151+
loader: &mut Loader,
152+
physics: &mut Physics,
153+
car_path: &str,
154+
transform: nalgebra::Isometry3<f32>,
155+
) -> Object {
156+
log::info!("Loading car: {}", car_path);
157+
let car_path = path::PathBuf::from("data/cars").join(car_path);
158+
let car_config: config::Car = ron::de::from_bytes(
159+
&fs::read(car_path.join("car.ron")).expect("Unable to open the car config"),
160+
)
161+
.expect("Unable to parse the car config");
162+
let model_desc = Loader::read_gltf(
163+
&car_path.join("body.glb"),
164+
Matrix4::identity().scale(car_config.scale),
165+
);
166+
let model = loader.load_model(&model_desc);
167+
let collider = Self::create_mesh_collider(model_desc, car_config.density);
168+
169+
let rigid_body = rapier3d::dynamics::RigidBodyBuilder::dynamic()
170+
.position(transform)
171+
.build();
172+
173+
let PhysicsBodyHandle {
174+
rigid_body_handle, ..
175+
} = physics.add_rigid_body(rigid_body, vec![collider]);
176+
Object {
177+
model_instance: ModelInstance {
178+
model: Arc::new(model),
179+
transform,
180+
},
181+
rigid_body: rigid_body_handle,
182+
}
183+
}
184+
185+
fn create_mesh_collider(model_desc: ModelDesc, density: f32) -> rapier3d::geometry::Collider {
186+
rapier3d::geometry::ColliderBuilder::trimesh(model_desc.positions(), model_desc.indices())
187+
.density(density)
188+
.build()
189+
}
190+
151191
fn update_physics(&mut self) {
152-
let mut objects = [&mut self.car.body];
192+
let mut objects = [&mut self.car];
153193
for object in objects.iter_mut() {
154194
self.physics
155195
.update_gravity(object.rigid_body, &self.terrain_body);
156196
}
157197
self.physics.step();
158198
for object in objects.iter_mut() {
159-
object.transform = self.physics.get_transform(object.rigid_body);
199+
object.model_instance.transform = self.physics.get_transform(object.rigid_body);
160200
}
161201
}
162202

163203
fn redraw(&mut self) -> time::Duration {
164204
//TODO: detach from rendering
165205
self.update_physics();
166206

167-
let objects = [&self.car.body];
168-
self.render.draw(&self.camera, &objects);
207+
let model_instances = vec![&self.car.model_instance];
208+
self.render
209+
.draw(&self.camera, &self.terrain, &model_instances);
169210

170211
time::Duration::from_millis(16)
171212
}
@@ -269,7 +310,7 @@ impl Drop for Game {
269310
}
270311
log::info!("Deinitializing");
271312
self.render.wait_for_gpu();
272-
self.car.body.model.free(self.render.context());
313+
self.car.model_instance.model.free(self.render.context());
273314
self.render.deinit();
274315
}
275316
}

data/packs/packs.ron

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[
2+
"root"
3+
]

data/packs/root/entities.ron

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[
2+
(
3+
id: "oxidize_monk",
4+
scene_path: Some("entities/oxidize_monk/body.glb"),
5+
),
6+
(
7+
id: "cube",
8+
scene_path: Some("entities/cube/cube.glb"),
9+
physics: Some((
10+
body: RigidBody(
11+
mass: 1
12+
),
13+
colliders: [(
14+
shape: Box(size: (0.1, 0.1, 0.1)),
15+
transform: ()
16+
)]
17+
))
18+
),
19+
(
20+
id: "floor",
21+
scene_path: Some("entities/floor/floor.glb"),
22+
physics: Some((
23+
body: StaticBody,
24+
colliders: [(
25+
shape: Box(size: (1.0, 0.02, 1.0)),
26+
transform: ()
27+
)]
28+
))
29+
),
30+
(
31+
id: "main_script",
32+
script_path: Some("entities/main/script.lua")
33+
)
34+
]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:c475d845c85cb171ee4be1b6aa82c010e79a86cf14f7114c6053280f563a55bf
3+
size 2008
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:baa52ef86b77a3b6faa0d4bbfbdb2db95717ef396e3c6b237f2f6c657e7732a4
3+
size 1972
13.4 MB
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
version https://git-lfs.github.com/spec/v1
2+
oid sha256:0d9d1557d54a35d39271cf148360c7464c0125a57dd6d4b7a204c508b533775c
3+
size 35660

0 commit comments

Comments
 (0)