Created
July 29, 2020 16:55
-
-
Save pferreir/96c3a0f825187ba909ea5b717f9e84a3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use amethyst::{ | |
assets::{AssetLoaderSystemData, ProgressCounter}, | |
core::{Transform, TransformBundle}, | |
ecs::System, | |
prelude::*, | |
renderer::{ | |
bundle::RenderingBundle, | |
debug_drawing::DebugLines, | |
light::{Light, PointLight}, | |
palette::{LinSrgba, Srgb}, | |
plugins::{RenderDebugLines, RenderShaded3D, RenderSkybox}, | |
rendy::{ | |
mesh::{Indices, MeshBuilder, Normal, Position, TexCoord}, | |
texture::palette::load_from_linear_rgba, | |
}, | |
types::DefaultBackend, | |
types::{Mesh, MeshData}, | |
visibility::BoundingSphere, | |
ActiveCamera, Camera, Material, MaterialDefaults, RenderToWindow, Texture, | |
}, | |
utils::{ | |
auto_fov::{AutoFov, AutoFovSystem}, | |
fps_counter::FpsCounterBundle, | |
}, | |
}; | |
use bracket_noise::prelude::*; | |
use genmesh::{Neighbors, Normal as GMNormal, Triangle}; | |
struct PlayingState; | |
const SIZE_GRID: usize = 100; | |
const HEIGHT_SCALE: f32 = 10.0; | |
fn gen_mesh() -> MeshData { | |
let mut noise = FastNoise::seeded(1234); | |
noise.set_noise_type(NoiseType::SimplexFractal); | |
noise.set_fractal_type(FractalType::FBM); | |
noise.set_fractal_octaves(3); | |
noise.set_fractal_gain(0.5); | |
noise.set_fractal_lacunarity(2.0); | |
noise.set_frequency(0.05); | |
let mut vertices = Vec::new(); | |
let mut triangles = Vec::new(); | |
for z in 0..SIZE_GRID { | |
for x in 0..SIZE_GRID { | |
vertices.push(Position([ | |
x as f32, | |
noise.get_noise(x as f32, z as f32) * HEIGHT_SCALE, | |
z as f32, | |
])) | |
} | |
} | |
for z in 0..(SIZE_GRID - 1) { | |
for x in 0..(SIZE_GRID - 1) { | |
let n = z * SIZE_GRID + x; | |
triangles.push(n); | |
triangles.push(n + SIZE_GRID); | |
triangles.push(n + SIZE_GRID + 1); | |
triangles.push(n); | |
triangles.push(n + SIZE_GRID + 1); | |
triangles.push(n + 1); | |
} | |
} | |
let neighbors = Neighbors::new( | |
vertices.clone(), | |
triangles | |
.chunks(3) | |
.map(|c| Triangle::new(c[0], c[1], c[2])) | |
.collect(), | |
); | |
let normals = vertices | |
.iter() | |
.enumerate() | |
.map(|(n, _)| { | |
let norm = neighbors.normal_for_vertex(n, |p: &Position| GMNormal { | |
x: p.0[0], | |
y: p.0[1], | |
z: p.0[2], | |
}); | |
Normal([-norm.x, -norm.y, -norm.z]) | |
}) | |
.collect::<Vec<Normal>>(); | |
println!("{:?}", normals); | |
let builder = MeshBuilder::new() | |
.with_vertices::<Position, Vec<_>>(vertices.clone()) | |
.with_vertices::<Normal, Vec<_>>(normals) | |
.with_vertices::<TexCoord, Vec<_>>(vertices.iter().map(|_| TexCoord([0.0, 0.0])).collect()) | |
.with_indices(Indices::U16( | |
triangles | |
.iter() | |
.map(|t| *t as u16) | |
.collect::<Vec<_>>() | |
.into(), | |
)); | |
MeshData(builder) | |
} | |
impl SimpleState for PlayingState { | |
fn on_start(&mut self, data: StateData<'_, GameData<'_, '_>>) { | |
let world = data.world; | |
let mut progress = ProgressCounter::default(); | |
// load mesh from generated coords | |
let mesh = world.exec(|loader: AssetLoaderSystemData<'_, Mesh>| { | |
loader.load_from_data(gen_mesh(), &mut progress) | |
}); | |
// set earth-colored diffuse map | |
let albedo = world.exec(|loader: AssetLoaderSystemData<'_, Texture>| { | |
loader.load_from_data( | |
load_from_linear_rgba(LinSrgba::new(0.67, 0.0, 0.2, 1.0)).into(), | |
&mut progress, | |
) | |
}); | |
let mat_defaults = world.read_resource::<MaterialDefaults>().0.clone(); | |
let mtl = world.exec( | |
|(mtl_loader, tex_loader): ( | |
AssetLoaderSystemData<'_, Material>, | |
AssetLoaderSystemData<'_, Texture>, | |
)| { | |
let metallic_roughness = tex_loader.load_from_data( | |
load_from_linear_rgba(LinSrgba::new(0.0, 1.0, 0.1, 0.0)).into(), | |
&mut progress, | |
); | |
mtl_loader.load_from_data( | |
Material { | |
albedo, | |
metallic_roughness, | |
..mat_defaults | |
}, | |
&mut progress, | |
) | |
}, | |
); | |
// center terrain | |
let mut transform = Transform::default(); | |
transform.set_translation_xyz(-(SIZE_GRID as f32) / 2.0, 0.0, -(SIZE_GRID as f32) / 2.0); | |
// create mesh | |
world | |
.create_entity() | |
.with(transform) | |
.with(mesh.clone()) | |
.with(mtl.clone()) | |
.with(BoundingSphere::origin(1.0)) | |
.build(); | |
let mut camera_transform = Transform::default(); | |
camera_transform.set_rotation_x_axis(-std::f32::consts::FRAC_PI_4); | |
camera_transform.set_translation_xyz(0.0, 100.0, 100.0); | |
let mut auto_fov = AutoFov::default(); | |
auto_fov.set_base_fovx(std::f32::consts::FRAC_PI_3); | |
auto_fov.set_base_aspect_ratio(1, 1); | |
let camera = world | |
.create_entity() | |
.with(Camera::standard_3d(16.0, 9.0)) | |
.with(auto_fov) | |
.with(camera_transform) | |
.build(); | |
let mut light_transform = Transform::default(); | |
light_transform.set_translation_y(20.0); | |
let light: Light = PointLight { | |
intensity: 10.0, | |
..PointLight::default() | |
}.into(); | |
world | |
.create_entity() | |
.with(light_transform) | |
.with(light) | |
.build(); | |
world.insert(ActiveCamera { | |
entity: Some(camera), | |
}); | |
world.insert(DebugLines::new()); | |
} | |
fn update(&mut self, _data: &mut StateData<GameData>) -> SimpleTrans { | |
Trans::None | |
} | |
} | |
struct TerrainSystem; | |
impl<'s> System<'s> for TerrainSystem { | |
type SystemData = (); | |
fn run(&mut self, _data: Self::SystemData) {} | |
} | |
fn main() -> amethyst::Result<()> { | |
amethyst::start_logger(Default::default()); | |
let game_data = GameDataBuilder::default() | |
.with_bundle(TransformBundle::new())? | |
.with_bundle( | |
RenderingBundle::<DefaultBackend>::new() | |
.with_plugin(RenderToWindow::from_config_path("display.ron")?) | |
.with_plugin(RenderShaded3D::default()) | |
.with_plugin(RenderDebugLines::default()) | |
.with_plugin(RenderSkybox::with_colors( | |
Srgb::new(0.25, 0.51, 0.85), | |
Srgb::new(0.10, 0.11, 0.85), | |
)), | |
)? | |
.with(AutoFovSystem::default(), "auto_fov", &[]) | |
.with_bundle(FpsCounterBundle::default())? | |
.with(TerrainSystem, "terrain", &[]); | |
Application::build("assets/", PlayingState)? | |
.build(game_data)? | |
.run(); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment