Skip to content

Instantly share code, notes, and snippets.

@pferreir
Created July 29, 2020 16:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pferreir/96c3a0f825187ba909ea5b717f9e84a3 to your computer and use it in GitHub Desktop.
Save pferreir/96c3a0f825187ba909ea5b717f9e84a3 to your computer and use it in GitHub Desktop.
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