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(
|
create_tile_water_surface(
|
||||||
tile_pos,
|
tile_pos,
|
||||||
height,
|
chunk.distance_to_land[idx],
|
||||||
chunk.min_height,
|
|
||||||
&n,
|
&n,
|
||||||
neighbor_has_land,
|
neighbor_has_land,
|
||||||
&mut verts,
|
&mut verts,
|
||||||
@@ -142,9 +141,8 @@ pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width
|
|||||||
|
|
||||||
fn create_tile_water_surface(
|
fn create_tile_water_surface(
|
||||||
pos: Vec3,
|
pos: Vec3,
|
||||||
height: f32,
|
dist_to_land: f32,
|
||||||
min_height: f32,
|
neighbors: &[(f32, Option<f32>); 6],
|
||||||
neighbors: &[f32; 6],
|
|
||||||
neighbor_has_land: bool,
|
neighbor_has_land: bool,
|
||||||
verts: &mut Vec<Vec3>,
|
verts: &mut Vec<Vec3>,
|
||||||
uvs: &mut Vec<Vec2>,
|
uvs: &mut Vec<Vec2>,
|
||||||
@@ -152,16 +150,16 @@ fn create_tile_water_surface(
|
|||||||
normals: &mut Vec<Vec3>,
|
normals: &mut Vec<Vec3>,
|
||||||
) {
|
) {
|
||||||
if !neighbor_has_land {
|
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;
|
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(
|
fn crate_tile_water_inner_surface(
|
||||||
pos: Vec3,
|
pos: Vec3,
|
||||||
height: f32,
|
dist_to_land: f32,
|
||||||
min_height: f32,
|
neighbors: &[(f32, Option<f32>); 6],
|
||||||
verts: &mut Vec<Vec3>,
|
verts: &mut Vec<Vec3>,
|
||||||
uvs: &mut Vec<Vec2>,
|
uvs: &mut Vec<Vec2>,
|
||||||
indices: &mut Vec<u32>,
|
indices: &mut Vec<u32>,
|
||||||
@@ -172,7 +170,14 @@ fn crate_tile_water_inner_surface(
|
|||||||
for i in 0..6 {
|
for i in 0..6 {
|
||||||
let p = pos + HEX_CORNERS[i];
|
let p = pos + HEX_CORNERS[i];
|
||||||
verts.push(p);
|
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);
|
normals.push(Vec3::Y);
|
||||||
}
|
}
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
@@ -188,9 +193,8 @@ fn crate_tile_water_inner_surface(
|
|||||||
|
|
||||||
fn crate_tile_water_shore_surface(
|
fn crate_tile_water_shore_surface(
|
||||||
pos: Vec3,
|
pos: Vec3,
|
||||||
height: f32,
|
dist_to_land: f32,
|
||||||
min_height: f32,
|
neighbors: &[(f32, Option<f32>); 6],
|
||||||
neighbors: &[f32; 6],
|
|
||||||
verts: &mut Vec<Vec3>,
|
verts: &mut Vec<Vec3>,
|
||||||
uvs: &mut Vec<Vec2>,
|
uvs: &mut Vec<Vec2>,
|
||||||
indices: &mut Vec<u32>,
|
indices: &mut Vec<u32>,
|
||||||
@@ -199,23 +203,29 @@ fn crate_tile_water_shore_surface(
|
|||||||
let idx = verts.len() as u32;
|
let idx = verts.len() as u32;
|
||||||
//todo: only use triangle fan when on shoreline
|
//todo: only use triangle fan when on shoreline
|
||||||
verts.push(pos);
|
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);
|
normals.push(Vec3::Y);
|
||||||
for i in 0..12 {
|
for i in 0..12 {
|
||||||
let p = pos + WATER_HEX_CORNERS[i];
|
let p = pos + WATER_HEX_CORNERS[i];
|
||||||
verts.push(p);
|
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 ni = i / 2;
|
||||||
let n = neighbors[ni];
|
let n = neighbors[ni];
|
||||||
let nn = neighbors[(ni + 5) % 6];
|
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;
|
uv.x = 1.0;
|
||||||
}
|
}
|
||||||
if ni * 2 != i {
|
if ni * 2 != i {
|
||||||
if n <= pos.y {
|
if n.0 <= pos.y {
|
||||||
uv.x = 0.0;
|
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);
|
indices.push(idx);
|
||||||
|
|||||||
@@ -42,9 +42,47 @@ impl Map {
|
|||||||
sealevel: self.sealevel,
|
sealevel: self.sealevel,
|
||||||
heights: chunk.heights.clone(),
|
heights: chunk.heights.clone(),
|
||||||
textures: chunk.textures.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] {
|
pub fn get_neighbors(&self, pos: &HexCoord) -> [Option<f32>; 6] {
|
||||||
let mut results: [Option<f32>; 6] = [None; 6];
|
let mut results: [Option<f32>; 6] = [None; 6];
|
||||||
let w = self.width * Chunk::SIZE;
|
let w = self.width * Chunk::SIZE;
|
||||||
@@ -96,47 +134,6 @@ impl Map {
|
|||||||
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||||
return chunk.biome_id[pos.to_chunk_local_index()];
|
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 {
|
pub fn get_center(&self) -> Vec3 {
|
||||||
let w = self.get_world_width();
|
let w = self.get_world_width();
|
||||||
@@ -206,6 +203,80 @@ impl Map {
|
|||||||
return result;
|
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>(
|
pub fn hex_select_mut<OP, Ret>(
|
||||||
&mut self,
|
&mut self,
|
||||||
center: &HexCoord,
|
center: &HexCoord,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ pub struct MeshChunkData {
|
|||||||
pub textures: [[u32; 2]; Chunk::AREA],
|
pub textures: [[u32; 2]; Chunk::AREA],
|
||||||
pub min_height: f32,
|
pub min_height: f32,
|
||||||
pub sealevel: f32,
|
pub sealevel: f32,
|
||||||
|
pub distance_to_land: [f32; Chunk::AREA],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MeshChunkData {
|
impl MeshChunkData {
|
||||||
@@ -24,17 +25,18 @@ impl MeshChunkData {
|
|||||||
return data;
|
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 has_land = false;
|
||||||
let mut data = [self.min_height; 6];
|
let mut data = [(self.min_height, None); 6];
|
||||||
let n_tiles = coord.get_neighbors();
|
let n_tiles = coord.get_neighbors();
|
||||||
for i in 0..6 {
|
for i in 0..6 {
|
||||||
let n = n_tiles[i];
|
let n = n_tiles[i];
|
||||||
if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) {
|
if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
data[i] = self.heights[n.to_index(Chunk::SIZE)];
|
let idx = n.to_index(Chunk::SIZE);
|
||||||
if data[i] > self.sealevel {
|
data[i] = (self.heights[idx], Some(self.distance_to_land[idx]));
|
||||||
|
if data[i].0 > self.sealevel {
|
||||||
has_land = true;
|
has_land = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule game/main/assets updated: 939ce074e9...63384f1ef8
Reference in New Issue
Block a user