chunks generation (not tested)
This commit is contained in:
parent
00f75f2de6
commit
eb3742e21d
162
src/map.rs
162
src/map.rs
@ -7,6 +7,7 @@ use bevy::{
|
||||
picking::PickSet,
|
||||
prelude::*,
|
||||
render::mesh::{Indices, PrimitiveTopology},
|
||||
utils::HashMap,
|
||||
};
|
||||
use noise::{Fbm, MultiFractal, NoiseFn, Perlin};
|
||||
use rand::{thread_rng, Rng, SeedableRng};
|
||||
@ -45,8 +46,9 @@ pub const REAL_WIDTH: f32 = 8000.;
|
||||
pub const CELL_AREA: f32 = REAL_HEIGHT * REAL_WIDTH / CELLS as f32;
|
||||
pub const CELLS_TARGET_NUMBER: usize = 100_000;
|
||||
pub const CHUNKS_RESOLUTION: usize = 2;
|
||||
pub const CELLS_PER_CHUNK: usize = CELLS_TARGET_NUMBER / CHUNKS_RESOLUTION.pow(2);
|
||||
pub const CELLS: usize = CELLS_PER_CHUNK * CHUNKS_RESOLUTION.pow(2);
|
||||
pub const CHUNKS: usize = CHUNKS_RESOLUTION.pow(2);
|
||||
pub const CELLS_PER_CHUNK: usize = CELLS_TARGET_NUMBER / CHUNKS;
|
||||
pub const CELLS: usize = CELLS_PER_CHUNK * CHUNKS;
|
||||
|
||||
#[derive(Resource)]
|
||||
struct Seed(u32);
|
||||
@ -58,7 +60,7 @@ pub struct Voronoi(voronoice::Voronoi);
|
||||
pub struct MapMarker;
|
||||
|
||||
#[derive(Component)]
|
||||
struct MapMeshColors(Vec<[f32; 4]>);
|
||||
struct MeshColors(Vec<[f32; 4]>);
|
||||
|
||||
#[derive(Resource)]
|
||||
pub struct CellsEntities(Vec<Entity>);
|
||||
@ -105,10 +107,8 @@ fn setup(
|
||||
let mut cells = Vec::with_capacity(CELLS);
|
||||
let z_noise = Fbm::<Perlin>::new(seed.0);
|
||||
let moisture_noise = Fbm::<Perlin>::new(seed.0 + 1).set_frequency(2.);
|
||||
let mut res = 0;
|
||||
for i in 0..CELLS {
|
||||
let c = voronoi.cell(i);
|
||||
res += c.iter_neighbors().count();
|
||||
let site = c.site_position();
|
||||
let z = get_altitude(&z_noise, &[site.x as f32, site.y as f32]);
|
||||
let _m = (
|
||||
@ -131,17 +131,27 @@ fn setup(
|
||||
vertices: vec![],
|
||||
});
|
||||
}
|
||||
dbg!(res as f64 / CELLS as f64);
|
||||
|
||||
let mut poss = Vec::new();
|
||||
let mut indices = Vec::new();
|
||||
// let mut poss = [Vec::new(); CHUNKS];
|
||||
let mut indices: [Vec<u32>; CHUNKS] = std::array::from_fn(|_| Vec::new());
|
||||
// let mut normals = Vec::new();
|
||||
|
||||
for (i, pos) in voronoi.sites().iter().enumerate() {
|
||||
let z = get_altitude(&z_noise, &[pos.x as f32, pos.y as f32]);
|
||||
poss.push(Vec3::new(pos.x as f32, pos.y as f32, z));
|
||||
cells[i].vertices.push(i);
|
||||
}
|
||||
let mut poss = voronoi.sites().chunks_exact(CELLS_PER_CHUNK).map(|ch| {
|
||||
ch.iter()
|
||||
.map(|pos| {
|
||||
let z = get_altitude(&z_noise, &[pos.x as f32, pos.y as f32]);
|
||||
Vec3::new(pos.x as f32, pos.y as f32, z)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let mut poss: [Vec<Vec3>; CHUNKS] = std::array::from_fn(|_| poss.next().unwrap());
|
||||
|
||||
// for (i, pos) in voronoi.sites().iter().enumerate() {
|
||||
// let z = get_altitude(&z_noise, &[pos.x as f32, pos.y as f32]);
|
||||
// poss.push(Vec3::new(pos.x as f32, pos.y as f32, z));
|
||||
// cells[i].vertices.push(i);
|
||||
// }
|
||||
// let mut hybrid_cells: HashMap<usize, usize> = HashMap::new();
|
||||
for t in voronoi.triangulation().triangles.chunks_exact(3) {
|
||||
let on_hull = t
|
||||
.iter()
|
||||
@ -151,7 +161,53 @@ fn setup(
|
||||
if on_hull > 0 {
|
||||
continue;
|
||||
}
|
||||
indices.extend_from_slice(&[t[2] as u32, t[1] as u32, t[0] as u32]);
|
||||
let mut chs = t.iter().map(|c| Cell::chunk_from_id(*c));
|
||||
let chs: [usize; 3] = std::array::from_fn(|_| chs.next().unwrap());
|
||||
// Add vertex to chunk if it is from an external chunk but we need it for a triangle. Else, just make the triangle
|
||||
if chs[1] == chs[2] && chs[0] != chs[1] {
|
||||
poss[chs[1]].push(poss[chs[0]][t[0] % CELLS_PER_CHUNK]);
|
||||
// hybrid_cells.insert(chs[0], chs[1]);
|
||||
indices[chs[1]].push((poss[chs[1]].len() - 1) as u32);
|
||||
} else {
|
||||
indices[chs[0]].push((t[0] % CELLS_PER_CHUNK) as u32);
|
||||
}
|
||||
if chs[0] == chs[2] && chs[1] != chs[0] {
|
||||
poss[chs[0]].push(poss[chs[1]][t[1] % CELLS_PER_CHUNK]);
|
||||
// hybrid_cells.insert(chs[1], chs[0]);
|
||||
indices[chs[0]].push((poss[chs[0]].len() - 1) as u32);
|
||||
} else {
|
||||
indices[chs[1]].push((t[1] % CELLS_PER_CHUNK) as u32);
|
||||
}
|
||||
if chs[0] == chs[1] && chs[2] != chs[0] {
|
||||
poss[chs[0]].push(poss[chs[2]][t[2] % CELLS_PER_CHUNK]);
|
||||
// hybrid_cells.insert(chs[2], chs[0]);
|
||||
indices[chs[0]].push((poss[chs[0]].len() - 1) as u32);
|
||||
} else {
|
||||
indices[chs[2]].push((t[2] % CELLS_PER_CHUNK) as u32);
|
||||
}
|
||||
}
|
||||
let mut cells_entities = Vec::with_capacity(cells.len());
|
||||
for cell in cells {
|
||||
let kind = cell.kind;
|
||||
// let id = cell.voronoi_id;
|
||||
let mut cmd = cmds.spawn(cell);
|
||||
// if let Some(ch) = hybrid_cells.get(&id) {
|
||||
// cmd.insert(GhostCell(*ch));
|
||||
// }
|
||||
match kind {
|
||||
CellKind::Grass | CellKind::Forest => {
|
||||
cmd.insert((
|
||||
Wealth(0),
|
||||
Regeneration {
|
||||
last_update: Duration::ZERO,
|
||||
full_growth_duration: kind.regen_full_growth_duration(),
|
||||
},
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
cmd.observe(self::cells::on_click);
|
||||
cells_entities.push(cmd.id());
|
||||
}
|
||||
// indices.extend(voronoi.triangulation().triangles.iter().map(|t| *t as u32));
|
||||
|
||||
@ -176,63 +232,47 @@ fn setup(
|
||||
// cd.vertices.extend_from_slice(&[i, i + v, i + v + 1]);
|
||||
// }
|
||||
// }
|
||||
for (poss, indices) in poss.into_iter().zip(indices.into_iter()) {
|
||||
let colors = vec![[0.; 4]; poss.len()];
|
||||
let mut mesh = Mesh::new(
|
||||
PrimitiveTopology::TriangleList,
|
||||
RenderAssetUsages::default(),
|
||||
)
|
||||
// Add 4 vertices, each with its own position attribute (coordinate in
|
||||
// 3D space), for each of the corners of the parallelogram.
|
||||
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, poss)
|
||||
.with_inserted_attribute(Mesh::ATTRIBUTE_COLOR, colors.clone())
|
||||
// .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
|
||||
.with_inserted_indices(Indices::U32(indices));
|
||||
|
||||
let colors = vec![[0.; 4]; poss.len()];
|
||||
let mut mesh = Mesh::new(
|
||||
PrimitiveTopology::TriangleList,
|
||||
RenderAssetUsages::default(),
|
||||
)
|
||||
// Add 4 vertices, each with its own position attribute (coordinate in
|
||||
// 3D space), for each of the corners of the parallelogram.
|
||||
.with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, poss)
|
||||
.with_inserted_attribute(Mesh::ATTRIBUTE_COLOR, colors.clone())
|
||||
// .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
|
||||
.with_inserted_indices(Indices::U32(indices));
|
||||
mesh.compute_smooth_normals();
|
||||
|
||||
mesh.compute_smooth_normals();
|
||||
|
||||
let mut cells_entities = Vec::with_capacity(cells.len());
|
||||
|
||||
cmds.spawn((
|
||||
Mesh3d(meshes.add(mesh)),
|
||||
// StandardMaterial
|
||||
// MeshMaterial3d(materials.add(StandardMaterial::default())),
|
||||
MeshMaterial3d(materials.add(CellMaterial {
|
||||
base: StandardMaterial::default(),
|
||||
extension: CellMaterialExtension {},
|
||||
})),
|
||||
Transform::default(),
|
||||
MapMeshColors(colors),
|
||||
MeshNeedsUpdate(true),
|
||||
MapMarker,
|
||||
));
|
||||
|
||||
for cell in cells {
|
||||
let kind = cell.kind;
|
||||
let mut cmd = cmds.spawn(cell);
|
||||
match kind {
|
||||
CellKind::Grass | CellKind::Forest => {
|
||||
cmd.insert((
|
||||
Wealth(0),
|
||||
Regeneration {
|
||||
last_update: Duration::ZERO,
|
||||
full_growth_duration: kind.regen_full_growth_duration(),
|
||||
},
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
cmd.observe(self::cells::on_click);
|
||||
cells_entities.push(cmd.id());
|
||||
cmds.spawn((
|
||||
Mesh3d(meshes.add(mesh)),
|
||||
// StandardMaterial
|
||||
// MeshMaterial3d(materials.add(StandardMaterial::default())),
|
||||
MeshMaterial3d(materials.add(CellMaterial {
|
||||
base: StandardMaterial {
|
||||
alpha_mode: AlphaMode::Mask(0.5),
|
||||
..Default::default()
|
||||
},
|
||||
extension: CellMaterialExtension {},
|
||||
})),
|
||||
Transform::default(),
|
||||
MeshColors(colors),
|
||||
MeshNeedsUpdate(true),
|
||||
MapMarker,
|
||||
));
|
||||
}
|
||||
|
||||
cmds.insert_resource(Voronoi(voronoi));
|
||||
cmds.insert_resource(CellsEntities(cells_entities));
|
||||
}
|
||||
|
||||
// TODO: update this to take chunks into account
|
||||
fn update_map_mesh(
|
||||
cells: Query<(&Cell, Option<&Wealth>)>,
|
||||
mut map: Query<(&Mesh3d, &mut MapMeshColors, &mut MeshNeedsUpdate), With<MapMarker>>,
|
||||
mut map: Query<(&Mesh3d, &mut MeshColors, &mut MeshNeedsUpdate), With<MapMarker>>,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
) {
|
||||
let (mesh, mut cols, mut needs_update) = map.single_mut();
|
||||
|
@ -7,7 +7,7 @@ use crate::{time::GameTime, ui::CurrentAction};
|
||||
|
||||
use super::{
|
||||
animals::Animal, AnimalKind, CellsEntities, MapMarker, MeshNeedsUpdate, Voronoi,
|
||||
AVERAGE_NEIGHBORS_NUMBER, CELL_AREA,
|
||||
AVERAGE_NEIGHBORS_NUMBER, CELLS_PER_CHUNK, CELL_AREA,
|
||||
};
|
||||
|
||||
pub mod material;
|
||||
@ -59,7 +59,7 @@ pub struct Cell {
|
||||
pub vertices: Vec<usize>,
|
||||
}
|
||||
impl Cell {
|
||||
pub fn color(&self, wealth: u8) -> [f32; 4] {
|
||||
pub const fn color(&self, wealth: u8) -> [f32; 4] {
|
||||
match self.kind {
|
||||
CellKind::Sea => [0., 0., 1., 1.],
|
||||
CellKind::Beach => [0.82, 0.84, 0.51, 1.],
|
||||
@ -79,8 +79,20 @@ impl Cell {
|
||||
],
|
||||
}
|
||||
}
|
||||
pub const fn chunk_from_id(id: usize) -> usize {
|
||||
id / CELLS_PER_CHUNK
|
||||
}
|
||||
pub const fn chunk(&self) -> usize {
|
||||
Self::chunk_from_id(self.voronoi_id)
|
||||
}
|
||||
}
|
||||
|
||||
// #[derive(Component)]
|
||||
// /// Cell that's in another chunk but needs to be there to form a triangle
|
||||
// pub struct GhostCell {
|
||||
// pub chunk:
|
||||
// };
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct Wealth(pub u8);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user