2019-06-05 15:22:06 +00:00
|
|
|
use crate::{
|
|
|
|
mesh::{vol, Meshable},
|
2019-08-14 21:28:37 +00:00
|
|
|
render::{self, FluidPipeline, Mesh, TerrainPipeline},
|
2019-06-05 15:22:06 +00:00
|
|
|
};
|
2019-01-23 20:01:58 +00:00
|
|
|
use common::{
|
2019-08-14 21:28:37 +00:00
|
|
|
terrain::{Block, BlockKind},
|
2019-06-06 14:48:41 +00:00
|
|
|
vol::{BaseVol, ReadVol, VolSize},
|
|
|
|
volumes::vol_map_2d::VolMap2d,
|
2019-01-23 20:01:58 +00:00
|
|
|
};
|
2019-06-05 15:22:06 +00:00
|
|
|
use std::fmt::Debug;
|
|
|
|
use vek::*;
|
2019-01-23 20:01:58 +00:00
|
|
|
|
|
|
|
type TerrainVertex = <TerrainPipeline as render::Pipeline>::Vertex;
|
2019-08-14 21:28:37 +00:00
|
|
|
type FluidVertex = <FluidPipeline as render::Pipeline>::Vertex;
|
|
|
|
|
2019-08-16 11:38:59 +00:00
|
|
|
fn block_shadow_density(kind: BlockKind) -> (f32, f32) {
|
2019-08-19 20:09:35 +00:00
|
|
|
// (density, cap)
|
2019-08-14 21:28:37 +00:00
|
|
|
match kind {
|
2019-08-16 11:38:59 +00:00
|
|
|
BlockKind::Normal => (0.085, 0.3),
|
|
|
|
BlockKind::Dense => (0.3, 0.0),
|
2019-08-16 14:58:14 +00:00
|
|
|
BlockKind::Water => (0.15, 0.0),
|
2019-08-19 20:09:35 +00:00
|
|
|
kind if kind.is_air() => (0.0, 0.0),
|
|
|
|
_ => (1.0, 0.0),
|
2019-01-23 20:01:58 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-12 18:33:39 +00:00
|
|
|
|
2019-08-19 20:09:35 +00:00
|
|
|
impl<V: BaseVol<Vox = Block> + ReadVol + Debug, S: VolSize + Clone>
|
|
|
|
Meshable<TerrainPipeline, FluidPipeline> for VolMap2d<V, S>
|
|
|
|
{
|
2019-05-17 17:44:30 +00:00
|
|
|
type Pipeline = TerrainPipeline;
|
2019-08-14 21:28:37 +00:00
|
|
|
type TranslucentPipeline = FluidPipeline;
|
2019-05-17 17:44:30 +00:00
|
|
|
type Supplement = Aabb<i32>;
|
|
|
|
|
2019-08-14 21:28:37 +00:00
|
|
|
fn generate_mesh(
|
|
|
|
&self,
|
|
|
|
range: Self::Supplement,
|
|
|
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
|
|
|
let mut opaque_mesh = Mesh::new();
|
|
|
|
let mut fluid_mesh = Mesh::new();
|
2019-05-17 17:44:30 +00:00
|
|
|
|
2019-05-17 21:19:32 +00:00
|
|
|
for x in range.min.x + 1..range.max.x - 1 {
|
|
|
|
for y in range.min.y + 1..range.max.y - 1 {
|
2019-06-18 11:33:18 +00:00
|
|
|
let mut neighbour_light = [[[1.0f32; 3]; 3]; 3];
|
2019-05-29 11:01:02 +00:00
|
|
|
|
|
|
|
for z in (range.min.z..range.max.z).rev() {
|
2019-05-17 17:44:30 +00:00
|
|
|
let pos = Vec3::new(x, y, z);
|
2019-08-14 21:28:37 +00:00
|
|
|
let offs = (pos - (range.min + 1) * Vec3::new(1, 1, 0)).map(|e| e as f32);
|
|
|
|
|
|
|
|
let block = self.get(pos).ok();
|
2019-05-17 17:44:30 +00:00
|
|
|
|
2019-05-29 11:01:02 +00:00
|
|
|
// Create mesh polygons
|
2019-08-14 21:28:37 +00:00
|
|
|
if let Some(col) = block
|
|
|
|
.filter(|vox| vox.is_opaque())
|
|
|
|
.and_then(|vox| vox.get_color())
|
|
|
|
{
|
2019-05-31 20:37:11 +00:00
|
|
|
let col = col.map(|e| e as f32 / 255.0);
|
2019-05-29 11:01:02 +00:00
|
|
|
|
2019-05-21 22:31:38 +00:00
|
|
|
vol::push_vox_verts(
|
2019-08-14 21:28:37 +00:00
|
|
|
&mut opaque_mesh,
|
2019-05-21 22:31:38 +00:00
|
|
|
self,
|
|
|
|
pos,
|
|
|
|
offs,
|
|
|
|
col,
|
2019-06-19 14:55:26 +00:00
|
|
|
|pos, norm, col, ao, light| {
|
2019-07-04 12:02:26 +00:00
|
|
|
TerrainVertex::new(pos, norm, col, light * ao)
|
2019-06-19 14:55:26 +00:00
|
|
|
},
|
2019-05-21 22:31:38 +00:00
|
|
|
false,
|
2019-06-18 11:33:18 +00:00
|
|
|
&neighbour_light,
|
2019-08-14 21:28:37 +00:00
|
|
|
|vox| !vox.is_opaque(),
|
2019-08-15 01:35:56 +00:00
|
|
|
|vox| vox.is_opaque(),
|
2019-08-14 21:28:37 +00:00
|
|
|
);
|
|
|
|
} else if let Some(col) = block
|
|
|
|
.filter(|vox| vox.is_fluid())
|
|
|
|
.and_then(|vox| vox.get_color())
|
|
|
|
{
|
|
|
|
let col = col.map(|e| e as f32 / 255.0);
|
|
|
|
|
|
|
|
vol::push_vox_verts(
|
|
|
|
&mut fluid_mesh,
|
|
|
|
self,
|
|
|
|
pos,
|
|
|
|
offs,
|
|
|
|
col,
|
|
|
|
|pos, norm, col, ao, light| {
|
|
|
|
FluidVertex::new(pos, norm, col, light * ao, 0.3)
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
&neighbour_light,
|
|
|
|
|vox| vox.is_air(),
|
2019-08-15 01:35:56 +00:00
|
|
|
|vox| vox.is_opaque(),
|
2019-05-21 22:31:38 +00:00
|
|
|
);
|
2019-05-17 17:44:30 +00:00
|
|
|
}
|
2019-06-18 23:59:40 +00:00
|
|
|
|
|
|
|
// Shift lighting
|
|
|
|
neighbour_light[2] = neighbour_light[1];
|
|
|
|
neighbour_light[1] = neighbour_light[0];
|
|
|
|
|
|
|
|
// Accumulate shade under opaque blocks
|
|
|
|
for i in 0..3 {
|
|
|
|
for j in 0..3 {
|
2019-08-16 11:38:59 +00:00
|
|
|
let (density, cap) = self
|
2019-06-18 23:59:40 +00:00
|
|
|
.get(pos + Vec3::new(i as i32 - 1, j as i32 - 1, -1))
|
|
|
|
.ok()
|
2019-08-16 11:38:59 +00:00
|
|
|
.map(|vox| block_shadow_density(vox.kind()))
|
|
|
|
.unwrap_or((0.0, 0.0));
|
|
|
|
|
2019-08-23 19:56:21 +00:00
|
|
|
neighbour_light[0][i][j] = (neighbour_light[0][i][j] * (1.0 - density))
|
|
|
|
.max(cap.min(neighbour_light[1][i][j]));
|
2019-06-18 23:59:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Spread light
|
|
|
|
neighbour_light[0] = [[neighbour_light[0]
|
|
|
|
.iter()
|
|
|
|
.map(|col| col.iter())
|
|
|
|
.flatten()
|
|
|
|
.copied()
|
2019-06-19 14:55:26 +00:00
|
|
|
.fold(0.0, |a, x| a + x)
|
|
|
|
/ 9.0; 3]; 3];
|
2019-05-17 17:44:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-14 21:28:37 +00:00
|
|
|
|
|
|
|
(opaque_mesh, fluid_mesh)
|
2019-05-17 17:44:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-31 20:37:11 +00:00
|
|
|
/*
|
2019-06-05 15:22:06 +00:00
|
|
|
impl<V: BaseVol<Vox = Block> + ReadVol + Debug, S: VolSize + Clone> Meshable for VolMap3d<V, S> {
|
2019-05-12 18:33:39 +00:00
|
|
|
type Pipeline = TerrainPipeline;
|
|
|
|
type Supplement = Aabb<i32>;
|
|
|
|
|
|
|
|
fn generate_mesh(&self, range: Self::Supplement) -> Mesh<Self::Pipeline> {
|
|
|
|
let mut mesh = Mesh::new();
|
|
|
|
|
|
|
|
let mut last_chunk_pos = self.pos_key(range.min);
|
|
|
|
let mut last_chunk = self.get_key(last_chunk_pos);
|
|
|
|
|
|
|
|
let size = range.max - range.min;
|
2019-05-13 12:08:17 +00:00
|
|
|
for x in 1..size.x - 1 {
|
|
|
|
for y in 1..size.y - 1 {
|
|
|
|
for z in 1..size.z - 1 {
|
2019-05-12 18:33:39 +00:00
|
|
|
let pos = Vec3::new(x, y, z);
|
|
|
|
|
|
|
|
let new_chunk_pos = self.pos_key(range.min + pos);
|
|
|
|
if last_chunk_pos != new_chunk_pos {
|
|
|
|
last_chunk = self.get_key(new_chunk_pos);
|
|
|
|
last_chunk_pos = new_chunk_pos;
|
|
|
|
}
|
|
|
|
let offs = pos.map(|e| e as f32 - 1.0);
|
2019-05-12 20:58:37 +00:00
|
|
|
if let Some(chunk) = last_chunk {
|
|
|
|
let chunk_pos = Self::chunk_offs(range.min + pos);
|
|
|
|
if let Some(col) = chunk.get(chunk_pos).ok().and_then(|vox| vox.get_color())
|
|
|
|
{
|
|
|
|
let col = col.map(|e| e as f32 / 255.0);
|
|
|
|
|
|
|
|
vol::push_vox_verts(
|
|
|
|
&mut mesh,
|
|
|
|
self,
|
2019-05-12 22:46:36 +00:00
|
|
|
range.min + pos,
|
2019-05-12 20:58:37 +00:00
|
|
|
offs,
|
|
|
|
col,
|
|
|
|
TerrainVertex::new,
|
2019-05-13 12:08:17 +00:00
|
|
|
false,
|
2019-05-12 20:58:37 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if let Some(col) = self
|
|
|
|
.get(range.min + pos)
|
|
|
|
.ok()
|
|
|
|
.and_then(|vox| vox.get_color())
|
|
|
|
{
|
|
|
|
let col = col.map(|e| e as f32 / 255.0);
|
|
|
|
|
|
|
|
vol::push_vox_verts(
|
|
|
|
&mut mesh,
|
|
|
|
self,
|
2019-05-12 22:46:36 +00:00
|
|
|
range.min + pos,
|
2019-05-12 20:58:37 +00:00
|
|
|
offs,
|
|
|
|
col,
|
|
|
|
TerrainVertex::new,
|
2019-05-13 12:08:17 +00:00
|
|
|
false,
|
2019-05-12 20:58:37 +00:00
|
|
|
);
|
|
|
|
}
|
2019-05-12 18:33:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mesh
|
|
|
|
}
|
|
|
|
}
|
2019-05-31 20:37:11 +00:00
|
|
|
*/
|