2019-01-13 20:53:55 +00:00
|
|
|
use crate::{
|
2019-04-28 21:34:58 +00:00
|
|
|
mesh::{vol, Meshable},
|
2019-08-19 20:09:35 +00:00
|
|
|
render::{self, FigurePipeline, Mesh, SpritePipeline},
|
2019-01-13 20:53:55 +00:00
|
|
|
};
|
2019-06-06 14:48:41 +00:00
|
|
|
use common::{
|
|
|
|
figure::Segment,
|
2019-08-04 19:54:08 +00:00
|
|
|
util::{linear_to_srgb, srgb_to_linear},
|
2019-09-24 06:03:40 +00:00
|
|
|
vol::{IntoFullVolIterator, ReadVol, Vox},
|
2019-06-06 14:48:41 +00:00
|
|
|
};
|
|
|
|
use vek::*;
|
2019-01-13 20:53:55 +00:00
|
|
|
|
|
|
|
type FigureVertex = <FigurePipeline as render::Pipeline>::Vertex;
|
2019-08-19 20:09:35 +00:00
|
|
|
type SpriteVertex = <SpritePipeline as render::Pipeline>::Vertex;
|
2019-01-13 20:53:55 +00:00
|
|
|
|
2019-08-19 20:09:35 +00:00
|
|
|
impl Meshable<FigurePipeline, FigurePipeline> for Segment {
|
2019-01-13 20:53:55 +00:00
|
|
|
type Pipeline = FigurePipeline;
|
2019-08-14 21:28:37 +00:00
|
|
|
type TranslucentPipeline = FigurePipeline;
|
2019-01-23 20:01:58 +00:00
|
|
|
type Supplement = Vec3<f32>;
|
2019-01-13 20:53:55 +00:00
|
|
|
|
2019-08-14 21:28:37 +00:00
|
|
|
fn generate_mesh(
|
|
|
|
&self,
|
|
|
|
offs: Self::Supplement,
|
|
|
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
2019-01-13 20:53:55 +00:00
|
|
|
let mut mesh = Mesh::new();
|
|
|
|
|
common: Rework volume API
See the doc comments in `common/src/vol.rs` for more information on
the API itself.
The changes include:
* Consistent `Err`/`Error` naming.
* Types are named `...Error`.
* `enum` variants are named `...Err`.
* Rename `VolMap{2d, 3d}` -> `VolGrid{2d, 3d}`. This is in preparation
to an upcoming change where a “map” in the game related sense will
be added.
* Add volume iterators. There are two types of them:
* _Position_ iterators obtained from the trait `IntoPosIterator`
using the method
`fn pos_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `Vec3<i32>`.
* _Volume_ iterators obtained from the trait `IntoVolIterator`
using the method
`fn vol_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `(Vec3<i32>, &Self::Vox)`.
Those traits will usually be implemented by references to volume
types (i.e. `impl IntoVolIterator<'a> for &'a T` where `T` is some
type which usually implements several volume traits, such as `Chunk`).
* _Position_ iterators iterate over the positions valid for that
volume.
* _Volume_ iterators do the same but return not only the position
but also the voxel at that position, in each iteration.
* Introduce trait `RectSizedVol` for the use case which we have with
`Chonk`: A `Chonk` is sized only in x and y direction.
* Introduce traits `RasterableVol`, `RectRasterableVol`
* `RasterableVol` represents a volume that is compile-time sized and has
its lower bound at `(0, 0, 0)`. The name `RasterableVol` was chosen
because such a volume can be used with `VolGrid3d`.
* `RectRasterableVol` represents a volume that is compile-time sized at
least in x and y direction and has its lower bound at `(0, 0, z)`.
There's no requirement on he lower bound or size in z direction.
The name `RectRasterableVol` was chosen because such a volume can be
used with `VolGrid2d`.
2019-09-03 22:23:29 +00:00
|
|
|
for (pos, vox) in self.full_vol_iter() {
|
|
|
|
if let Some(col) = vox.get_color() {
|
2019-04-28 21:34:58 +00:00
|
|
|
vol::push_vox_verts(
|
2019-04-28 17:12:45 +00:00
|
|
|
&mut mesh,
|
2019-10-25 00:02:29 +00:00
|
|
|
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
2019-04-28 17:12:45 +00:00
|
|
|
offs + pos.map(|e| e as f32),
|
2019-09-27 10:06:32 +00:00
|
|
|
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
2019-06-19 14:55:26 +00:00
|
|
|
|origin, norm, col, ao, light| {
|
2019-08-04 19:54:08 +00:00
|
|
|
FigureVertex::new(
|
|
|
|
origin,
|
|
|
|
norm,
|
2019-09-24 09:01:50 +00:00
|
|
|
linear_to_srgb(srgb_to_linear(col) * light.min(ao)),
|
2019-08-04 19:54:08 +00:00
|
|
|
0,
|
|
|
|
)
|
2019-06-19 14:55:26 +00:00
|
|
|
},
|
2019-09-24 06:03:40 +00:00
|
|
|
&{
|
|
|
|
let mut ls = [[[0.0; 3]; 3]; 3];
|
|
|
|
for x in 0..3 {
|
|
|
|
for y in 0..3 {
|
|
|
|
for z in 0..3 {
|
2019-09-24 09:01:50 +00:00
|
|
|
ls[z][y][x] = if self
|
2019-09-24 06:03:40 +00:00
|
|
|
.get(pos + Vec3::new(x as i32, y as i32, z as i32) - 1)
|
|
|
|
.map(|v| v.is_empty())
|
|
|
|
.unwrap_or(true)
|
|
|
|
{
|
|
|
|
1.0
|
|
|
|
} else {
|
|
|
|
0.0
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ls
|
|
|
|
},
|
2019-04-28 17:12:45 +00:00
|
|
|
);
|
2019-01-13 20:53:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-14 21:28:37 +00:00
|
|
|
(mesh, Mesh::new())
|
2019-01-13 20:53:55 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-19 20:09:35 +00:00
|
|
|
|
|
|
|
impl Meshable<SpritePipeline, SpritePipeline> for Segment {
|
|
|
|
type Pipeline = SpritePipeline;
|
|
|
|
type TranslucentPipeline = SpritePipeline;
|
|
|
|
type Supplement = Vec3<f32>;
|
|
|
|
|
|
|
|
fn generate_mesh(
|
|
|
|
&self,
|
|
|
|
offs: Self::Supplement,
|
|
|
|
) -> (Mesh<Self::Pipeline>, Mesh<Self::TranslucentPipeline>) {
|
|
|
|
let mut mesh = Mesh::new();
|
|
|
|
|
common: Rework volume API
See the doc comments in `common/src/vol.rs` for more information on
the API itself.
The changes include:
* Consistent `Err`/`Error` naming.
* Types are named `...Error`.
* `enum` variants are named `...Err`.
* Rename `VolMap{2d, 3d}` -> `VolGrid{2d, 3d}`. This is in preparation
to an upcoming change where a “map” in the game related sense will
be added.
* Add volume iterators. There are two types of them:
* _Position_ iterators obtained from the trait `IntoPosIterator`
using the method
`fn pos_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `Vec3<i32>`.
* _Volume_ iterators obtained from the trait `IntoVolIterator`
using the method
`fn vol_iter(self, lower_bound: Vec3<i32>, upper_bound: Vec3<i32>) -> ...`
which returns an iterator over `(Vec3<i32>, &Self::Vox)`.
Those traits will usually be implemented by references to volume
types (i.e. `impl IntoVolIterator<'a> for &'a T` where `T` is some
type which usually implements several volume traits, such as `Chunk`).
* _Position_ iterators iterate over the positions valid for that
volume.
* _Volume_ iterators do the same but return not only the position
but also the voxel at that position, in each iteration.
* Introduce trait `RectSizedVol` for the use case which we have with
`Chonk`: A `Chonk` is sized only in x and y direction.
* Introduce traits `RasterableVol`, `RectRasterableVol`
* `RasterableVol` represents a volume that is compile-time sized and has
its lower bound at `(0, 0, 0)`. The name `RasterableVol` was chosen
because such a volume can be used with `VolGrid3d`.
* `RectRasterableVol` represents a volume that is compile-time sized at
least in x and y direction and has its lower bound at `(0, 0, z)`.
There's no requirement on he lower bound or size in z direction.
The name `RectRasterableVol` was chosen because such a volume can be
used with `VolGrid2d`.
2019-09-03 22:23:29 +00:00
|
|
|
for (pos, vox) in self.full_vol_iter() {
|
|
|
|
if let Some(col) = vox.get_color() {
|
2019-08-19 20:09:35 +00:00
|
|
|
vol::push_vox_verts(
|
|
|
|
&mut mesh,
|
2019-10-25 00:02:29 +00:00
|
|
|
faces_to_make(self, pos, true, |vox| vox.is_empty()),
|
2019-08-19 20:09:35 +00:00
|
|
|
offs + pos.map(|e| e as f32),
|
2019-09-27 10:06:32 +00:00
|
|
|
&[[[Rgba::from_opaque(col); 3]; 3]; 3],
|
2019-08-19 20:09:35 +00:00
|
|
|
|origin, norm, col, ao, light| {
|
|
|
|
SpriteVertex::new(
|
|
|
|
origin,
|
|
|
|
norm,
|
|
|
|
linear_to_srgb(srgb_to_linear(col) * ao * light),
|
|
|
|
)
|
|
|
|
},
|
|
|
|
&[[[1.0; 3]; 3]; 3],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(mesh, Mesh::new())
|
|
|
|
}
|
|
|
|
}
|
2019-10-25 00:02:29 +00:00
|
|
|
|
|
|
|
/// Use the 6 voxels/blocks surrounding the one at the specified position
|
|
|
|
/// to detemine which faces should be drawn
|
|
|
|
fn faces_to_make<V: ReadVol>(
|
|
|
|
seg: &V,
|
|
|
|
pos: Vec3<i32>,
|
|
|
|
error_makes_face: bool,
|
|
|
|
should_add: impl Fn(&V::Vox) -> bool,
|
|
|
|
) -> [bool; 6] {
|
|
|
|
let (x, y, z) = (Vec3::unit_x(), Vec3::unit_y(), Vec3::unit_z());
|
|
|
|
let make_face = |offset| {
|
|
|
|
seg.get(pos + offset)
|
|
|
|
.map(|v| should_add(v))
|
|
|
|
.unwrap_or(error_makes_face)
|
|
|
|
};
|
|
|
|
[
|
|
|
|
make_face(-x),
|
|
|
|
make_face(x),
|
|
|
|
make_face(-y),
|
|
|
|
make_face(y),
|
|
|
|
make_face(-z),
|
|
|
|
make_face(z),
|
|
|
|
]
|
|
|
|
}
|