Skip to content

Instantly share code, notes, and snippets.

@kvark
Forked from LaylBongers/game_world.rs
Created June 6, 2017 15:04
Show Gist options
  • Save kvark/f781110f178ab3b5b270d65f9adf5197 to your computer and use it in GitHub Desktop.
Save kvark/f781110f178ab3b5b270d65f9adf5197 to your computer and use it in GitHub Desktop.
use cgmath::{Vector3};
use slog::{Logger};
use cobalt_rendering::{Target, Texture, TextureFormat};
use cobalt_rendering_world3d::{World, Model, Entity, Light, EntityId, LightId, Material};
use input::{InputState, FrameInput};
use player::{Player};
pub struct GameWorld {
pub player: Player,
devices: Vec<Device>,
light: LightId,
light_accum: f32,
}
impl GameWorld {
pub fn new(log: &Logger, target: &mut Target, world: &mut World) -> Self {
let player = Player::new();
// Create the floor
let floor_model = Model::load(log, target, "./assets/floor.obj", 0.1);
let floor_material = Material {
base_color: Texture::load(
log, target, "./assets/floor_base_color.png", TextureFormat::Srgb
),
normal_map: Texture::load(
log, target, "./assets/floor_normal.png", TextureFormat::Linear
),
metallic_map: Texture::load(
log, target, "./assets/floor_metallic.png", TextureFormat::LinearRed
),
roughness_map: Texture::load(
log, target, "./assets/floor_roughness.png", TextureFormat::LinearRed
),
};
world.add_entity(Entity {
position: Vector3::new(0.0, 0.0, 0.0),
mesh: floor_model.meshes[0].clone(),
material: floor_material.clone(),
});
// Create the 3 test devices
let device_model = Model::load(log, target, "./assets/device.obj", 0.1);
let flat_normal_map = Texture::load(
log, target, "./assets/texture_norm.png", TextureFormat::Linear
);
let flat_metallic_map = Texture::load(
log, target, "./assets/texture_metallic.png", TextureFormat::LinearRed
);
let flat_roughness_map = Texture::load(
log, target, "./assets/texture_roughness.png", TextureFormat::LinearRed
);
let material_device = Material {
base_color: Texture::load(log, target, "./assets/texture.png", TextureFormat::Srgb),
normal_map: flat_normal_map.clone(),
metallic_map: flat_metallic_map.clone(),
roughness_map: flat_roughness_map.clone(),
};
let material_working = Material {
base_color: Texture::load(
log, target, "./assets/texture_working.png", TextureFormat::Srgb
),
normal_map: flat_normal_map.clone(),
metallic_map: flat_metallic_map.clone(),
roughness_map: flat_roughness_map.clone(),
};
let material_broken = Material {
base_color: Texture::load(
log, target, "./assets/texture_broken.png", TextureFormat::Srgb
),
normal_map: flat_normal_map.clone(),
metallic_map: flat_metallic_map.clone(),
roughness_map: flat_roughness_map.clone(),
};
let d1 = Device::new(
world, Vector3::new(-2.0, 0.0, -4.0), &device_model,
&material_device, &material_working, &material_broken,
);
let d2 = Device::new(
world, Vector3::new( 0.0, 0.0, -4.0), &device_model,
&material_device, &material_working, &material_broken,
);
let d3 = Device::new(
world, Vector3::new( 2.0, 0.0, -4.0), &device_model,
&material_device, &material_working, &material_broken,
);
let devices = vec!(d1, d2, d3);
// Create a centered test light
let light = world.add_light(Light {
position: Vector3::new(0.0, 1.5, 0.0),
color: Vector3::new(1.0, 1.0, 1.0),
radius: 7.5,
});
world.set_ambient_light(Vector3::new(0.005, 0.005, 0.005));
// Add a test sphere just to be able to better see the effect of lighting
let sphere_model = Model::load(log, target, "./assets/sphere.obj", 0.5);
world.add_entity(Entity {
position: Vector3::new(0.0, 1.0, 0.0),
mesh: sphere_model.meshes[0].clone(),
material: material_device.clone(),
});
GameWorld {
player,
devices,
// TODO: Remove these two
light,
light_accum: 0.0,
}
}
pub fn update(
&mut self, time: f32, world: &mut World,
input_state: &InputState, frame_input: &FrameInput
) {
// Update the player based on the input we got so far
self.player.update(&input_state, &frame_input, time);
// Update the devices
for device in &mut self.devices {
device.update(time, world);
}
// Rotate the light around
self.light_accum += time;
let light = world.light_mut(self.light);
light.position.x = f32::sin(self.light_accum) * 4.0;
light.position.z = f32::cos(self.light_accum) * 4.0;
}
}
struct Device {
fixedness: f32,
status: bool,
light_entity: EntityId,
light_light: LightId,
material_working: Material,
material_broken: Material,
}
impl Device {
fn new(
world: &mut World, position: Vector3<f32>, model: &Model,
material_base: &Material, material_working: &Material, material_broken: &Material
) -> Self {
// Add the meshes for this device to the world
world.add_entity(Entity {
position,
mesh: model.meshes[0].clone(),
material: material_base.clone(),
});
let light_entity = world.add_entity(Entity {
position,
mesh: model.meshes[1].clone(),
material: material_working.clone(),
});
// Add a light to for device as well
let light_light = world.add_light(Light {
position: position + Vector3::new(-0.3, 1.2, 0.24),
color: Self::light_color_for(true),
radius: 2.0,
});
Device {
fixedness: 1.0,
status: true,
light_entity,
light_light,
material_working: material_working.clone(),
material_broken: material_broken.clone(),
}
}
fn set_status(&mut self, value: bool, world: &mut World) {
self.status = value;
// Switch the status light to what we need it to be
{
let entity = world.entity_mut(self.light_entity);
entity.material = self.material_for(self.status);
}
{
let light = world.light_mut(self.light_light);
light.color = Self::light_color_for(self.status);
}
}
fn material_for(&self, status: bool) -> Material {
if status {
self.material_working.clone()
} else {
self.material_broken.clone()
}
}
fn light_color_for(status: bool) -> Vector3<f32> {
if status {
Vector3::new(0.2, 1.0, 0.2)
} else {
Vector3::new(1.0, 0.2, 0.2)
}
}
fn update(&mut self, time: f32, world: &mut World) {
if self.status {
self.fixedness -= time;
} else {
self.fixedness += time;
}
if self.fixedness < 0.0 && self.status {
self.set_status(false, world);
}
if self.fixedness > 1.0 && !self.status {
self.set_status(true, world);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment