2019-04-29 15:40:36 +00:00
|
|
|
use vek::*;
|
|
|
|
|
2019-08-15 01:35:56 +00:00
|
|
|
use common::vol::ReadVol;
|
2019-04-29 15:40:36 +00:00
|
|
|
|
|
|
|
use crate::render::{
|
|
|
|
mesh::{Mesh, Quad},
|
|
|
|
Pipeline,
|
|
|
|
};
|
|
|
|
|
2019-05-17 09:22:32 +00:00
|
|
|
/// Given volume, position, and cardinal directions, compute each vertex's AO value.
|
2019-04-29 15:40:36 +00:00
|
|
|
/// `dirs` should be a slice of length 5 so that the sliding window of size 2 over the slice
|
|
|
|
/// yields each vertex' adjacent positions.
|
2019-06-19 14:55:26 +00:00
|
|
|
fn get_ao_quad<V: ReadVol>(
|
|
|
|
vol: &V,
|
|
|
|
pos: Vec3<i32>,
|
|
|
|
shift: Vec3<i32>,
|
|
|
|
dirs: &[Vec3<i32>],
|
|
|
|
darknesses: &[[[f32; 3]; 3]; 3],
|
2019-08-15 01:35:56 +00:00
|
|
|
is_opaque: impl Fn(&V::Vox) -> bool,
|
2019-06-19 14:55:26 +00:00
|
|
|
) -> Vec4<(f32, f32)> {
|
2019-04-29 15:40:36 +00:00
|
|
|
dirs.windows(2)
|
2019-07-04 12:02:26 +00:00
|
|
|
.map(|offs| {
|
2019-09-24 09:01:50 +00:00
|
|
|
let (s1, s2) = (
|
|
|
|
vol.get(pos + shift + offs[0])
|
|
|
|
.map(&is_opaque)
|
|
|
|
.unwrap_or(false),
|
|
|
|
vol.get(pos + shift + offs[1])
|
|
|
|
.map(&is_opaque)
|
|
|
|
.unwrap_or(false),
|
|
|
|
);
|
|
|
|
|
2019-09-24 00:15:38 +00:00
|
|
|
let mut darkness = 0.0;
|
|
|
|
for x in 0..2 {
|
|
|
|
for y in 0..2 {
|
|
|
|
let dark_pos = shift + offs[0] * x + offs[1] * y + 1;
|
2019-09-24 09:01:50 +00:00
|
|
|
darkness += darknesses[dark_pos.z as usize][dark_pos.y as usize]
|
|
|
|
[dark_pos.x as usize]
|
2019-09-24 00:15:38 +00:00
|
|
|
/ 4.0;
|
|
|
|
}
|
|
|
|
}
|
2019-06-18 11:33:18 +00:00
|
|
|
|
2019-09-24 09:01:50 +00:00
|
|
|
(
|
|
|
|
darkness,
|
|
|
|
if s1 && s2 {
|
|
|
|
0.0
|
|
|
|
} else {
|
|
|
|
let corner = vol
|
|
|
|
.get(pos + shift + offs[0] + offs[1])
|
|
|
|
.map(&is_opaque)
|
|
|
|
.unwrap_or(false);
|
|
|
|
// Map both 1 and 2 neighbors to 0.5 occlusion.
|
|
|
|
if s1 || s2 || corner {
|
|
|
|
0.5
|
|
|
|
} else {
|
|
|
|
1.0
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
2019-04-29 15:40:36 +00:00
|
|
|
})
|
2019-06-18 21:37:48 +00:00
|
|
|
.collect::<Vec4<(f32, f32)>>()
|
2019-04-29 15:40:36 +00:00
|
|
|
}
|
|
|
|
|
2019-09-24 10:28:40 +00:00
|
|
|
#[allow(unsafe_code)]
|
2019-09-24 06:42:09 +00:00
|
|
|
fn get_col_quad<V: ReadVol>(
|
2019-09-26 12:34:15 +00:00
|
|
|
_vol: &V,
|
|
|
|
_pos: Vec3<i32>,
|
|
|
|
_shift: Vec3<i32>,
|
2019-09-24 06:42:09 +00:00
|
|
|
dirs: &[Vec3<i32>],
|
|
|
|
cols: &[[[Option<Rgb<f32>>; 3]; 3]; 3],
|
2019-09-26 12:34:15 +00:00
|
|
|
_is_opaque: impl Fn(&V::Vox) -> bool,
|
2019-09-24 06:42:09 +00:00
|
|
|
) -> Vec4<Rgb<f32>> {
|
|
|
|
dirs.windows(2)
|
|
|
|
.map(|offs| {
|
2019-09-24 09:01:50 +00:00
|
|
|
let primary_col = cols[1][1][1].unwrap_or(Rgb::zero());
|
2019-09-24 06:42:09 +00:00
|
|
|
let mut color = Rgb::zero();
|
|
|
|
let mut total = 0.0;
|
|
|
|
for x in 0..2 {
|
|
|
|
for y in 0..2 {
|
2019-09-24 10:28:40 +00:00
|
|
|
let col_pos = offs[0] * x + offs[1] * y + 1;
|
|
|
|
if let Some(col) = unsafe {
|
|
|
|
cols.get_unchecked(col_pos.z as usize)
|
|
|
|
.get_unchecked(col_pos.y as usize)
|
|
|
|
.get_unchecked(col_pos.x as usize)
|
|
|
|
} {
|
|
|
|
if Vec3::<f32>::from(primary_col).distance_squared(Vec3::from(*col))
|
|
|
|
< 0.25 * 0.25
|
2019-09-24 06:42:09 +00:00
|
|
|
{
|
2019-09-24 10:28:40 +00:00
|
|
|
color += *col;
|
|
|
|
total += 1.0;
|
2019-09-24 06:42:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-24 10:28:40 +00:00
|
|
|
color / total
|
2019-09-24 06:42:09 +00:00
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
}
|
|
|
|
|
2019-04-29 15:40:36 +00:00
|
|
|
// Utility function
|
2019-06-18 21:37:48 +00:00
|
|
|
fn create_quad<P: Pipeline, F: Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P::Vertex>(
|
2019-04-29 15:40:36 +00:00
|
|
|
origin: Vec3<f32>,
|
|
|
|
unit_x: Vec3<f32>,
|
|
|
|
unit_y: Vec3<f32>,
|
|
|
|
norm: Vec3<f32>,
|
2019-09-24 06:42:09 +00:00
|
|
|
cols: Vec4<Rgb<f32>>,
|
2019-06-18 21:37:48 +00:00
|
|
|
darkness_ao: Vec4<(f32, f32)>,
|
2019-04-29 15:40:36 +00:00
|
|
|
vcons: &F,
|
|
|
|
) -> Quad<P> {
|
2019-06-18 21:37:48 +00:00
|
|
|
let darkness = darkness_ao.map(|e| e.0);
|
|
|
|
let ao = darkness_ao.map(|e| e.1);
|
|
|
|
|
2019-09-24 09:01:50 +00:00
|
|
|
let ao_map = ao.map(|e| e); //0.05 + e.powf(1.2) * 0.95);
|
2019-05-21 12:28:53 +00:00
|
|
|
|
2019-09-24 17:56:51 +00:00
|
|
|
if ao[0].min(ao[2]).min(darkness[0]).min(darkness[2])
|
|
|
|
< ao[1].min(ao[3]).min(darkness[1]).min(darkness[3])
|
|
|
|
{
|
2019-04-29 15:40:36 +00:00
|
|
|
Quad::new(
|
2019-09-24 06:42:09 +00:00
|
|
|
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3]),
|
|
|
|
vcons(origin, norm, cols[0], darkness[0], ao_map[0]),
|
|
|
|
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1]),
|
|
|
|
vcons(
|
|
|
|
origin + unit_x + unit_y,
|
|
|
|
norm,
|
|
|
|
cols[2],
|
|
|
|
darkness[2],
|
|
|
|
ao_map[2],
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
)
|
|
|
|
} else {
|
|
|
|
Quad::new(
|
2019-09-24 06:42:09 +00:00
|
|
|
vcons(origin, norm, cols[0], darkness[0], ao_map[0]),
|
|
|
|
vcons(origin + unit_x, norm, cols[1], darkness[1], ao_map[1]),
|
|
|
|
vcons(
|
|
|
|
origin + unit_x + unit_y,
|
|
|
|
norm,
|
|
|
|
cols[2],
|
|
|
|
darkness[2],
|
|
|
|
ao_map[2],
|
|
|
|
),
|
|
|
|
vcons(origin + unit_y, norm, cols[3], darkness[3], ao_map[3]),
|
2019-04-29 15:40:36 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-14 21:28:37 +00:00
|
|
|
pub fn push_vox_verts<V: ReadVol, P: Pipeline>(
|
2019-04-29 15:40:36 +00:00
|
|
|
mesh: &mut Mesh<P>,
|
|
|
|
vol: &V,
|
|
|
|
pos: Vec3<i32>,
|
|
|
|
offs: Vec3<f32>,
|
2019-09-24 06:42:09 +00:00
|
|
|
cols: &[[[Option<Rgb<f32>>; 3]; 3]; 3],
|
2019-08-14 21:28:37 +00:00
|
|
|
vcons: impl Fn(Vec3<f32>, Vec3<f32>, Rgb<f32>, f32, f32) -> P::Vertex,
|
2019-05-13 12:08:17 +00:00
|
|
|
error_makes_face: bool,
|
2019-06-18 11:33:18 +00:00
|
|
|
darknesses: &[[[f32; 3]; 3]; 3],
|
2019-08-14 21:28:37 +00:00
|
|
|
should_add: impl Fn(&V::Vox) -> bool,
|
2019-08-15 01:35:56 +00:00
|
|
|
is_opaque: impl Fn(&V::Vox) -> bool,
|
2019-04-29 15:40:36 +00:00
|
|
|
) {
|
|
|
|
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
|
|
|
|
|
|
|
// -x
|
|
|
|
if vol
|
|
|
|
.get(pos - Vec3::unit_x())
|
2019-08-14 21:28:37 +00:00
|
|
|
.map(|v| should_add(v))
|
2019-05-13 12:08:17 +00:00
|
|
|
.unwrap_or(error_makes_face)
|
2019-04-29 15:40:36 +00:00
|
|
|
{
|
|
|
|
mesh.push_quad(create_quad(
|
|
|
|
offs,
|
|
|
|
Vec3::unit_z(),
|
|
|
|
Vec3::unit_y(),
|
|
|
|
-Vec3::unit_x(),
|
2019-09-24 06:42:09 +00:00
|
|
|
get_col_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
-Vec3::unit_x(),
|
|
|
|
&[-z, -y, z, y, -z],
|
|
|
|
cols,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-08-15 01:35:56 +00:00
|
|
|
get_ao_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
-Vec3::unit_x(),
|
|
|
|
&[-z, -y, z, y, -z],
|
|
|
|
darknesses,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
&vcons,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
// +x
|
|
|
|
if vol
|
|
|
|
.get(pos + Vec3::unit_x())
|
2019-08-14 21:28:37 +00:00
|
|
|
.map(|v| should_add(v))
|
2019-05-13 12:08:17 +00:00
|
|
|
.unwrap_or(error_makes_face)
|
2019-04-29 15:40:36 +00:00
|
|
|
{
|
|
|
|
mesh.push_quad(create_quad(
|
|
|
|
offs + Vec3::unit_x(),
|
|
|
|
Vec3::unit_y(),
|
|
|
|
Vec3::unit_z(),
|
|
|
|
Vec3::unit_x(),
|
2019-09-24 06:42:09 +00:00
|
|
|
get_col_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
Vec3::unit_x(),
|
|
|
|
&[-y, -z, y, z, -y],
|
|
|
|
cols,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-08-15 01:35:56 +00:00
|
|
|
get_ao_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
Vec3::unit_x(),
|
|
|
|
&[-y, -z, y, z, -y],
|
|
|
|
darknesses,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
&vcons,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
// -y
|
|
|
|
if vol
|
|
|
|
.get(pos - Vec3::unit_y())
|
2019-08-14 21:28:37 +00:00
|
|
|
.map(|v| should_add(v))
|
2019-05-13 12:08:17 +00:00
|
|
|
.unwrap_or(error_makes_face)
|
2019-04-29 15:40:36 +00:00
|
|
|
{
|
|
|
|
mesh.push_quad(create_quad(
|
|
|
|
offs,
|
|
|
|
Vec3::unit_x(),
|
|
|
|
Vec3::unit_z(),
|
|
|
|
-Vec3::unit_y(),
|
2019-09-24 06:42:09 +00:00
|
|
|
get_col_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
-Vec3::unit_y(),
|
|
|
|
&[-x, -z, x, z, -x],
|
|
|
|
cols,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-08-15 01:35:56 +00:00
|
|
|
get_ao_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
-Vec3::unit_y(),
|
|
|
|
&[-x, -z, x, z, -x],
|
|
|
|
darknesses,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
&vcons,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
// +y
|
|
|
|
if vol
|
|
|
|
.get(pos + Vec3::unit_y())
|
2019-08-14 21:28:37 +00:00
|
|
|
.map(|v| should_add(v))
|
2019-05-13 12:08:17 +00:00
|
|
|
.unwrap_or(error_makes_face)
|
2019-04-29 15:40:36 +00:00
|
|
|
{
|
|
|
|
mesh.push_quad(create_quad(
|
|
|
|
offs + Vec3::unit_y(),
|
|
|
|
Vec3::unit_z(),
|
|
|
|
Vec3::unit_x(),
|
|
|
|
Vec3::unit_y(),
|
2019-09-24 06:42:09 +00:00
|
|
|
get_col_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
Vec3::unit_y(),
|
|
|
|
&[-z, -x, z, x, -z],
|
|
|
|
cols,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-08-15 01:35:56 +00:00
|
|
|
get_ao_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
Vec3::unit_y(),
|
|
|
|
&[-z, -x, z, x, -z],
|
|
|
|
darknesses,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
&vcons,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
// -z
|
|
|
|
if vol
|
|
|
|
.get(pos - Vec3::unit_z())
|
2019-08-14 21:28:37 +00:00
|
|
|
.map(|v| should_add(v))
|
2019-05-13 12:08:17 +00:00
|
|
|
.unwrap_or(error_makes_face)
|
2019-04-29 15:40:36 +00:00
|
|
|
{
|
|
|
|
mesh.push_quad(create_quad(
|
|
|
|
offs,
|
|
|
|
Vec3::unit_y(),
|
|
|
|
Vec3::unit_x(),
|
|
|
|
-Vec3::unit_z(),
|
2019-09-24 06:42:09 +00:00
|
|
|
get_col_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
-Vec3::unit_z(),
|
|
|
|
&[-y, -x, y, x, -y],
|
|
|
|
cols,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-08-15 01:35:56 +00:00
|
|
|
get_ao_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
-Vec3::unit_z(),
|
|
|
|
&[-y, -x, y, x, -y],
|
|
|
|
darknesses,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
&vcons,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
// +z
|
|
|
|
if vol
|
|
|
|
.get(pos + Vec3::unit_z())
|
2019-08-14 21:28:37 +00:00
|
|
|
.map(|v| should_add(v))
|
2019-05-13 12:08:17 +00:00
|
|
|
.unwrap_or(error_makes_face)
|
2019-04-29 15:40:36 +00:00
|
|
|
{
|
|
|
|
mesh.push_quad(create_quad(
|
|
|
|
offs + Vec3::unit_z(),
|
|
|
|
Vec3::unit_x(),
|
|
|
|
Vec3::unit_y(),
|
|
|
|
Vec3::unit_z(),
|
2019-09-24 06:42:09 +00:00
|
|
|
get_col_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
Vec3::unit_z(),
|
|
|
|
&[-x, -y, x, y, -x],
|
|
|
|
cols,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-08-15 01:35:56 +00:00
|
|
|
get_ao_quad(
|
|
|
|
vol,
|
|
|
|
pos,
|
|
|
|
Vec3::unit_z(),
|
|
|
|
&[-x, -y, x, y, -x],
|
|
|
|
darknesses,
|
|
|
|
&is_opaque,
|
|
|
|
),
|
2019-04-29 15:40:36 +00:00
|
|
|
&vcons,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|