update water waves
This commit is contained in:
@@ -118,8 +118,7 @@ pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width
|
||||
|
||||
create_tile_water_surface(
|
||||
tile_pos,
|
||||
height,
|
||||
chunk.min_height,
|
||||
chunk.distance_to_land[idx],
|
||||
&n,
|
||||
neighbor_has_land,
|
||||
&mut verts,
|
||||
@@ -142,9 +141,8 @@ pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width
|
||||
|
||||
fn create_tile_water_surface(
|
||||
pos: Vec3,
|
||||
height: f32,
|
||||
min_height: f32,
|
||||
neighbors: &[f32; 6],
|
||||
dist_to_land: f32,
|
||||
neighbors: &[(f32, Option<f32>); 6],
|
||||
neighbor_has_land: bool,
|
||||
verts: &mut Vec<Vec3>,
|
||||
uvs: &mut Vec<Vec2>,
|
||||
@@ -152,16 +150,16 @@ fn create_tile_water_surface(
|
||||
normals: &mut Vec<Vec3>,
|
||||
) {
|
||||
if !neighbor_has_land {
|
||||
crate_tile_water_inner_surface(pos, height, min_height, verts, uvs, indices, normals);
|
||||
crate_tile_water_inner_surface(pos, dist_to_land, neighbors, verts, uvs, indices, normals);
|
||||
return;
|
||||
}
|
||||
crate_tile_water_shore_surface(pos, height, min_height, neighbors, verts, uvs, indices, normals);
|
||||
crate_tile_water_shore_surface(pos, dist_to_land, neighbors, verts, uvs, indices, normals);
|
||||
}
|
||||
|
||||
fn crate_tile_water_inner_surface(
|
||||
pos: Vec3,
|
||||
height: f32,
|
||||
min_height: f32,
|
||||
dist_to_land: f32,
|
||||
neighbors: &[(f32, Option<f32>); 6],
|
||||
verts: &mut Vec<Vec3>,
|
||||
uvs: &mut Vec<Vec2>,
|
||||
indices: &mut Vec<u32>,
|
||||
@@ -172,7 +170,14 @@ fn crate_tile_water_inner_surface(
|
||||
for i in 0..6 {
|
||||
let p = pos + HEX_CORNERS[i];
|
||||
verts.push(p);
|
||||
uvs.push(Vec2::new(0.0, height.remap(min_height, pos.y, 0.0, 1.0)));
|
||||
let n1 = if let Some(v) = neighbors[i].1 { v } else { dist_to_land };
|
||||
let n2 = if let Some(v) = neighbors[(i + 5) % 6].1 {
|
||||
v
|
||||
} else {
|
||||
dist_to_land
|
||||
};
|
||||
let d = (n1 + n2 + dist_to_land) / 3.0;
|
||||
uvs.push(Vec2::new(0.0, d.remap(0., 4., 1.0, 0.0)));
|
||||
normals.push(Vec3::Y);
|
||||
}
|
||||
for i in 0..3 {
|
||||
@@ -188,9 +193,8 @@ fn crate_tile_water_inner_surface(
|
||||
|
||||
fn crate_tile_water_shore_surface(
|
||||
pos: Vec3,
|
||||
height: f32,
|
||||
min_height: f32,
|
||||
neighbors: &[f32; 6],
|
||||
dist_to_land: f32,
|
||||
neighbors: &[(f32, Option<f32>); 6],
|
||||
verts: &mut Vec<Vec3>,
|
||||
uvs: &mut Vec<Vec2>,
|
||||
indices: &mut Vec<u32>,
|
||||
@@ -199,23 +203,29 @@ fn crate_tile_water_shore_surface(
|
||||
let idx = verts.len() as u32;
|
||||
//todo: only use triangle fan when on shoreline
|
||||
verts.push(pos);
|
||||
uvs.push(Vec2::new(0.0, height.remap(min_height, pos.y, 0.0, 1.0)));
|
||||
uvs.push(Vec2::new(0.0, dist_to_land.remap(0., 4., 1.0, 0.0)));
|
||||
normals.push(Vec3::Y);
|
||||
for i in 0..12 {
|
||||
let p = pos + WATER_HEX_CORNERS[i];
|
||||
verts.push(p);
|
||||
let mut uv = Vec2::new(0.0, height.remap(min_height, pos.y, 0.0, 1.0));
|
||||
let ni = i / 2;
|
||||
let n = neighbors[ni];
|
||||
let nn = neighbors[(ni + 5) % 6];
|
||||
let mut uv = Vec2::new(0.0, dist_to_land.remap(0., 4., 1.0, 0.0));
|
||||
|
||||
if nn > pos.y || n > pos.y {
|
||||
if nn.0 > pos.y || n.0 > pos.y {
|
||||
uv.x = 1.0;
|
||||
}
|
||||
if ni * 2 != i {
|
||||
if n <= pos.y {
|
||||
if n.0 <= pos.y {
|
||||
uv.x = 0.0;
|
||||
}
|
||||
let d = if let Some(v) = n.1 { v } else { dist_to_land };
|
||||
uv.y = ((d + dist_to_land) / 2.0).remap(0., 4., 1.0, 0.0);
|
||||
} else {
|
||||
let d = if let Some(v) = n.1 { v } else { dist_to_land };
|
||||
let d2 = if let Some(v) = nn.1 { v } else { dist_to_land };
|
||||
uv.y = ((d + d2 + dist_to_land) / 3.0).remap(0., 4., 1.0, 0.0);
|
||||
}
|
||||
|
||||
indices.push(idx);
|
||||
|
||||
@@ -42,9 +42,47 @@ impl Map {
|
||||
sealevel: self.sealevel,
|
||||
heights: chunk.heights.clone(),
|
||||
textures: chunk.textures.clone(),
|
||||
distance_to_land: self.get_distance_from_land(chunk.chunk_offset, 4),
|
||||
};
|
||||
}
|
||||
|
||||
fn get_distance_from_land(&self, chunk_offset: IVec2, range: usize) -> [f32; Chunk::AREA] {
|
||||
#[cfg(feature = "tracing")]
|
||||
let _spawn_span = info_span!("Chunk Land Dist Data").entered();
|
||||
let mut dists = [0.0; Chunk::AREA];
|
||||
let cx = chunk_offset.x as usize * Chunk::SIZE;
|
||||
let cz = chunk_offset.y as usize * Chunk::SIZE;
|
||||
for z in 0..Chunk::SIZE {
|
||||
for x in 0..Chunk::SIZE {
|
||||
let coord = HexCoord::from_grid_pos(x + cx, z + cz);
|
||||
let index = coord.to_chunk_local_index();
|
||||
|
||||
if !self.is_in_bounds(&coord) {
|
||||
warn!("Coord is not in bounds!?");
|
||||
}
|
||||
|
||||
//Current tile is land tile
|
||||
if self.sample_height(&coord) > self.sealevel {
|
||||
dists[index] = 0.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Find closest land tile
|
||||
if let Some(d) = self.hex_select_first(&coord, range, false, |_t, h, r| {
|
||||
if h > self.sealevel {
|
||||
return Some(r as f32);
|
||||
}
|
||||
return None;
|
||||
}) {
|
||||
dists[index] = d;
|
||||
} else {
|
||||
dists[index] = range as f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dists;
|
||||
}
|
||||
|
||||
pub fn get_neighbors(&self, pos: &HexCoord) -> [Option<f32>; 6] {
|
||||
let mut results: [Option<f32>; 6] = [None; 6];
|
||||
let w = self.width * Chunk::SIZE;
|
||||
@@ -96,47 +134,6 @@ impl Map {
|
||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||
return chunk.biome_id[pos.to_chunk_local_index()];
|
||||
}
|
||||
/*
|
||||
pub fn get_biome_noise(&self, pos: &HexCoord) -> &BiomeData {
|
||||
assert!(
|
||||
self.is_in_bounds(pos),
|
||||
"The provided coordinate is not within the map bounds"
|
||||
);
|
||||
|
||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||
return &chunk.biome_data[pos.to_chunk_local_index()];
|
||||
}
|
||||
|
||||
pub fn get_moisture(&self, pos: &HexCoord) -> f32 {
|
||||
assert!(
|
||||
self.is_in_bounds(pos),
|
||||
"The provided coordinate is not within the map bounds"
|
||||
);
|
||||
|
||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||
return chunk.biome_data[pos.to_chunk_local_index()].moisture;
|
||||
}
|
||||
|
||||
pub fn get_tempurature(&self, pos: &HexCoord) -> f32 {
|
||||
assert!(
|
||||
self.is_in_bounds(pos),
|
||||
"The provided coordinate is not within the map bounds"
|
||||
);
|
||||
|
||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||
return chunk.biome_data[pos.to_chunk_local_index()].temperature;
|
||||
}
|
||||
|
||||
pub fn get_continentality(&self, pos: &HexCoord) -> f32 {
|
||||
assert!(
|
||||
self.is_in_bounds(pos),
|
||||
"The provided coordinate is not within the map bounds"
|
||||
);
|
||||
|
||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||
return chunk.biome_data[pos.to_chunk_local_index()].continentality;
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn get_center(&self) -> Vec3 {
|
||||
let w = self.get_world_width();
|
||||
@@ -206,6 +203,80 @@ impl Map {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn hex_select_first<OP, Ret>(
|
||||
&self,
|
||||
center: &HexCoord,
|
||||
radius: usize,
|
||||
include_center: bool,
|
||||
op: OP,
|
||||
) -> Option<Ret>
|
||||
where
|
||||
OP: (Fn(&HexCoord, f32, usize) -> Option<Ret>) + Sync + Send,
|
||||
{
|
||||
assert!(radius != 0, "Radius cannot be zero");
|
||||
|
||||
if include_center {
|
||||
let h = self.sample_height(¢er);
|
||||
let r = (op)(center, h, 0);
|
||||
if r.is_some() {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
for k in 0..(radius + 1) {
|
||||
let mut p = center.scale(4, k);
|
||||
for i in 0..6 {
|
||||
for _j in 0..k {
|
||||
p = p.get_neighbor(i);
|
||||
if self.is_in_bounds(&p) {
|
||||
let h = self.sample_height(&p);
|
||||
let r = (op)(&p, h, k);
|
||||
if r.is_some() {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn ring_select_first<OP, Ret>(
|
||||
&self,
|
||||
center: &HexCoord,
|
||||
start_radius: usize,
|
||||
end_radius: usize,
|
||||
op: OP,
|
||||
) -> Option<Ret>
|
||||
where
|
||||
OP: (Fn(&HexCoord, f32, usize) -> Option<Ret>) + Sync + Send,
|
||||
{
|
||||
assert!(start_radius != 0, "Start radius cannot be zero");
|
||||
assert!(
|
||||
start_radius > end_radius,
|
||||
"Start radius cannot be lower than end radius"
|
||||
);
|
||||
|
||||
for k in start_radius..(end_radius + 1) {
|
||||
let mut p = center.scale(4, k);
|
||||
for i in 0..6 {
|
||||
for _j in 0..k {
|
||||
p = p.get_neighbor(i);
|
||||
if self.is_in_bounds(&p) {
|
||||
let h = self.sample_height(&p);
|
||||
let r = (op)(&p, h, k);
|
||||
if r.is_some() {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn hex_select_mut<OP, Ret>(
|
||||
&mut self,
|
||||
center: &HexCoord,
|
||||
|
||||
@@ -7,6 +7,7 @@ pub struct MeshChunkData {
|
||||
pub textures: [[u32; 2]; Chunk::AREA],
|
||||
pub min_height: f32,
|
||||
pub sealevel: f32,
|
||||
pub distance_to_land: [f32; Chunk::AREA],
|
||||
}
|
||||
|
||||
impl MeshChunkData {
|
||||
@@ -24,17 +25,18 @@ impl MeshChunkData {
|
||||
return data;
|
||||
}
|
||||
|
||||
pub fn get_neighbors_with_water_info(&self, coord: &HexCoord) -> ([f32; 6], bool) {
|
||||
pub fn get_neighbors_with_water_info(&self, coord: &HexCoord) -> ([(f32, Option<f32>); 6], bool) {
|
||||
let mut has_land = false;
|
||||
let mut data = [self.min_height; 6];
|
||||
let mut data = [(self.min_height, None); 6];
|
||||
let n_tiles = coord.get_neighbors();
|
||||
for i in 0..6 {
|
||||
let n = n_tiles[i];
|
||||
if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) {
|
||||
continue;
|
||||
}
|
||||
data[i] = self.heights[n.to_index(Chunk::SIZE)];
|
||||
if data[i] > self.sealevel {
|
||||
let idx = n.to_index(Chunk::SIZE);
|
||||
data[i] = (self.heights[idx], Some(self.distance_to_land[idx]));
|
||||
if data[i].0 > self.sealevel {
|
||||
has_land = true;
|
||||
}
|
||||
}
|
||||
|
||||
Submodule game/main/assets updated: 939ce074e9...63384f1ef8
Reference in New Issue
Block a user