Address review comments for MR 3679:

- Fix normal vectors/lighting for train tracks.
- Adjust chat command logging statement.
- Remove train tracks when their chunks get unloaded.
- Create a struct for the 6-tuple returned from `get_nearest_ways`.
- Move code that creates the train tracks into `layers::apply_trains_to`.
This commit is contained in:
Avi Weinstock 2022-11-03 14:22:37 -04:00
parent 2242f7245d
commit f5c1293e9f
8 changed files with 118 additions and 94 deletions

View File

@ -60,17 +60,20 @@ void main() {
float R_s = (f_pos.z < f_alt) ? mix(R_s2s1 * R_s1s0, R_s1s0, medium.x) : mix(R_s2s0, R_s1s2 * R_s2s0, medium.x);
vec3 k_a = vec3(1.0);
vec3 k_d = vec3(1.0);
vec3 k_d = vec3(0.8);
vec3 k_s = vec3(R_s);
float max_light = 0.0;
vec3 cam_attenuation = vec3(1);
float fluid_alt = max(f_pos.z + 1, floor(f_alt + 1));
vec3 mu = medium.x == MEDIUM_WATER ? MU_WATER : vec3(0.0);
vec3 emitted_light, reflected_light;
vec3 emitted_light = vec3(1);
vec3 reflected_light = vec3(1);
max_light += get_sun_diffuse2(sun_info, moon_info, f_norm, view_dir, f_pos, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
max_light += lights_at(f_pos, f_norm, view_dir, mu, cam_attenuation, fluid_alt, k_a, k_d, k_s, alpha, f_norm, 1.0, emitted_light, reflected_light);
surf_color = illuminate(max_light, view_dir, surf_color * emitted_light, surf_color * reflected_light * 1.0);
tgt_color = vec4(surf_color, 1.0);
//tgt_color = vec4(f_norm, 1.0);
}

View File

@ -530,4 +530,5 @@ void main() {
surf_color += f_select * (surf_color + 0.1) * vec3(0.5, 0.5, 0.5);
tgt_color = vec4(surf_color, f_alpha);
//tgt_color = vec4(f_norm, f_alpha);
}

View File

@ -226,7 +226,7 @@ impl<'a> Widget for Chat<'a> {
// Log the output of commands since the ingame terminal doesn't support copying
// the output to the clipboard
if let ChatType::CommandInfo = message.chat_type {
tracing::info!("{}", message.message);
tracing::info!("Chat command info: {}", message.message);
}
}
//new messages - update chat w/ them & scroll down if at bottom of chat

View File

@ -51,7 +51,7 @@ fn box_along_line(
) {
// dx is along b-a
// dz is along b-d
let dx = Vec3::unit_z().cross(line.end - line.start).normalized();
let dx = -Vec3::unit_z().cross(line.end - line.start).normalized();
let dz = dx.cross(line.end - line.start).normalized();
let w = width / 2.0;
let h = height / 2.0;
@ -66,7 +66,7 @@ fn box_along_line(
let h = r + w * dx - h * dz;
let quad = |x: Vec3<f32>, y: Vec3<f32>, z: Vec3<f32>, w: Vec3<f32>| {
let normal = x.cross(y);
let normal = (y - x).cross(z - y).normalized();
Quad::<DebugVertex>::new(
(x, color, normal).into(),
(y, color, normal).into(),
@ -228,8 +228,8 @@ impl DebugShape {
let end = path.evaluate((i + 1) as f32 * step_size);
let center = LineSegment3 { start, end };
let dx =
*rail_sep * Vec3::unit_z().cross(center.end - center.start).normalized();
let dz = -dx.cross(center.end - center.start).normalized();
*rail_sep * -Vec3::unit_z().cross(center.end - center.start).normalized();
let dz = dx.cross(center.end - center.start).normalized();
let left = LineSegment3 {
start: center.start + dx,
end: center.end + dx,

View File

@ -1305,8 +1305,10 @@ impl Scene {
) {
let ecs = client.state().ecs();
{
let mut current_chunks = hashbrown::HashSet::new();
let terrain_grid = ecs.read_resource::<TerrainGrid>();
for (key, chunk) in terrain_grid.iter() {
current_chunks.insert(key);
tracks.entry(key).or_insert_with(|| {
let mut ret = Vec::new();
for bezier in chunk.meta().tracks().iter() {
@ -1346,6 +1348,15 @@ impl Scene {
ret
});
}
tracks.retain(|k, v| {
let keep = current_chunks.contains(k);
if !keep {
for shape in v.iter() {
self.debug.remove_shape(*shape);
}
}
keep
});
}
let mut current_entities = hashbrown::HashSet::new();
if settings.interface.toggle_hitboxes {

View File

@ -14,6 +14,7 @@ pub use self::{
use crate::{
column::ColumnSample,
config::CONFIG,
sim,
util::{FastNoise, RandomField, RandomPerm, Sampler},
Canvas, CanvasInfo, IndexRef,
};
@ -148,6 +149,70 @@ pub fn apply_paths_to(canvas: &mut Canvas) {
});
}
pub fn apply_trains_to(
canvas: &mut Canvas,
sim: &sim::WorldSim,
sim_chunk: &sim::SimChunk,
chunk_center_wpos2d: Vec2<i32>,
) {
let mut splines = Vec::new();
let g = |v: Vec2<f32>| -> Vec3<f32> {
let path_nearest = sim
.get_nearest_path(v.as_::<i32>())
.map(|x| x.1)
.unwrap_or(v.as_::<f32>());
let alt = if let Some(c) = canvas.col_or_gen(v.as_::<i32>()) {
let pl = PathLocals::new(canvas, &c, path_nearest);
pl.riverless_alt + pl.bridge_offset + 0.75
} else {
sim_chunk.alt
};
v.with_z(alt)
};
fn hermite_to_bezier(
p0: Vec3<f32>,
m0: Vec3<f32>,
p3: Vec3<f32>,
m3: Vec3<f32>,
) -> CubicBezier3<f32> {
let hermite = Vec4::new(p0, p3, m0, m3);
let hermite = hermite.map(|v| v.with_w(0.0));
let hermite: [[f32; 4]; 4] = hermite.map(|v: Vec4<f32>| v.into_array()).into_array();
// https://courses.engr.illinois.edu/cs418/sp2009/notes/12-MoreSplines.pdf
let mut m = Mat4::from_row_arrays([
[1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
[-3.0, 3.0, 0.0, 0.0],
[0.0, 0.0, -3.0, 3.0],
]);
m.invert();
let bezier = m * Mat4::from_row_arrays(hermite);
let bezier: Vec4<Vec4<f32>> =
Vec4::<[f32; 4]>::from(bezier.into_row_arrays()).map(Vec4::from);
let bezier = bezier.map(Vec3::from);
CubicBezier3::from(bezier)
}
for sim::NearestWaysData { bezier: bez, .. } in
sim.get_nearest_ways(chunk_center_wpos2d, &|chunk| Some(chunk.path))
{
if bez.length_by_discretization(16) < 0.125 {
continue;
}
let a = 0.0;
let b = 1.0;
for bez in bez.split((a + b) / 2.0) {
let p0 = g(bez.evaluate(a));
let p1 = g(bez.evaluate(a + (b - a) / 3.0));
let p2 = g(bez.evaluate(a + 2.0 * (b - a) / 3.0));
let p3 = g(bez.evaluate(b));
splines.push(hermite_to_bezier(p0, 3.0 * (p1 - p0), p3, 3.0 * (p3 - p2)));
}
}
for spline in splines.into_iter() {
canvas.chunk.meta_mut().add_track(spline);
}
}
pub fn apply_caves_to(canvas: &mut Canvas, rng: &mut impl Rng) {
let info = canvas.info();
canvas.foreach_col(|canvas, wpos2d, col| {

View File

@ -360,65 +360,7 @@ impl World {
};
if index.features.train_tracks {
let mut splines = Vec::new();
let g = |v: Vec2<f32>| -> Vec3<f32> {
let path_nearest = self
.sim
.get_nearest_path(v.as_::<i32>())
.map(|x| x.1)
.unwrap_or(v.as_::<f32>());
let alt = if let Some(c) = canvas.col_or_gen(v.as_::<i32>()) {
let pl = PathLocals::new(&canvas, &c, path_nearest);
pl.riverless_alt + pl.bridge_offset + 0.75
} else {
sim_chunk.alt
};
v.with_z(alt)
};
fn hermite_to_bezier(
p0: Vec3<f32>,
m0: Vec3<f32>,
p3: Vec3<f32>,
m3: Vec3<f32>,
) -> CubicBezier3<f32> {
let hermite = Vec4::new(p0, p3, m0, m3);
let hermite = hermite.map(|v| v.with_w(0.0));
let hermite: [[f32; 4]; 4] =
hermite.map(|v: Vec4<f32>| v.into_array()).into_array();
// https://courses.engr.illinois.edu/cs418/sp2009/notes/12-MoreSplines.pdf
let mut m = Mat4::from_row_arrays([
[1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 1.0],
[-3.0, 3.0, 0.0, 0.0],
[0.0, 0.0, -3.0, 3.0],
]);
m.invert();
let bezier = m * Mat4::from_row_arrays(hermite);
let bezier: Vec4<Vec4<f32>> =
Vec4::<[f32; 4]>::from(bezier.into_row_arrays()).map(Vec4::from);
let bezier = bezier.map(Vec3::from);
CubicBezier3::from(bezier)
}
for (_, _, _, _, bez, _) in self
.sim
.get_nearest_ways(chunk_center_wpos2d, &|chunk| Some(chunk.path))
{
if bez.length_by_discretization(16) < 0.125 {
continue;
}
let a = 0.0;
let b = 1.0;
for bez in bez.split((a + b) / 2.0) {
let p0 = g(bez.evaluate(a));
let p1 = g(bez.evaluate(a + (b - a) / 3.0));
let p2 = g(bez.evaluate(a + 2.0 * (b - a) / 3.0));
let p3 = g(bez.evaluate(b));
splines.push(hermite_to_bezier(p0, 3.0 * (p1 - p0), p3, 3.0 * (p3 - p2)));
}
}
for spline in splines.into_iter() {
canvas.chunk.meta_mut().add_track(spline);
}
layer::apply_trains_to(&mut canvas, &self.sim, sim_chunk, chunk_center_wpos2d);
}
if index.features.caverns {

View File

@ -2137,16 +2137,7 @@ impl WorldSim {
&'a self,
wpos: Vec2<i32>,
get_way: &'a impl Fn(&SimChunk) -> Option<(Way, M)>,
) -> impl Iterator<
Item = (
usize,
f32,
Vec2<f32>,
M,
QuadraticBezier2<f32>,
impl FnOnce() -> Vec2<f32>,
),
> + 'a {
) -> impl Iterator<Item = NearestWaysData<M, impl FnOnce() -> Vec2<f32>>> + 'a {
let chunk_pos = wpos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| {
e.div_euclid(sz as i32)
});
@ -2216,9 +2207,16 @@ impl WorldSim {
} else {
Lerp::lerp(meta.clone(), end_meta, nearest_interval - 0.5)
};
Some((i, dist_sqrd, pos, meta, bez, move || {
bez.evaluate_derivative(nearest_interval).normalized()
}))
Some(NearestWaysData {
i,
dist_sqrd,
pos,
meta,
bezier: bez,
calc_tangent: move || {
bez.evaluate_derivative(nearest_interval).normalized()
},
})
}),
)
})
@ -2235,8 +2233,16 @@ impl WorldSim {
) -> Option<(f32, Vec2<f32>, M, Vec2<f32>)> {
let get_way = &get_way;
self.get_nearest_ways(wpos, get_way)
.min_by_key(|(_, dist_sqrd, _, _, _, _)| (dist_sqrd * 1024.0) as i32)
.map(|(_, dist, pos, meta, _, calc_tangent)| (dist.sqrt(), pos, meta, calc_tangent()))
.min_by_key(|NearestWaysData { dist_sqrd, .. }| (dist_sqrd * 1024.0) as i32)
.map(
|NearestWaysData {
dist_sqrd,
pos,
meta,
calc_tangent,
..
}| (dist_sqrd.sqrt(), pos, meta, calc_tangent()),
)
}
pub fn get_nearest_path(&self, wpos: Vec2<i32>) -> Option<(f32, Vec2<f32>, Path, Vec2<f32>)> {
@ -2247,19 +2253,6 @@ impl WorldSim {
self.get_nearest_way(wpos, |chunk| Some(chunk.cave))
}
pub fn get_nearest_path_for_direction(
&self,
wpos: Vec2<i32>,
dir: usize,
) -> Option<(f32, Vec2<f32>, Path, QuadraticBezier2<f32>, Vec2<f32>)> {
self.get_nearest_ways(wpos, &|chunk| Some(chunk.path))
.filter(|(i, _, _, _, _, _)| *i == dir)
.min_by_key(|(_, dist_sqrd, _, _, _, _)| (dist_sqrd * 1024.0) as i32)
.map(|(_, dist, pos, meta, bez, calc_tangent)| {
(dist.sqrt(), pos, meta, bez, calc_tangent())
})
}
/// Create a [`Lottery<Option<ForestKind>>`] that generates [`ForestKind`]s
/// according to the conditions at the given position. If no or fewer
/// trees are appropriate for the conditions, `None` may be generated.
@ -2366,6 +2359,15 @@ pub struct RegionInfo {
pub seed: u32,
}
pub struct NearestWaysData<M, F: FnOnce() -> Vec2<f32>> {
pub i: usize,
pub dist_sqrd: f32,
pub pos: Vec2<f32>,
pub meta: M,
pub bezier: QuadraticBezier2<f32>,
pub calc_tangent: F,
}
impl SimChunk {
fn generate(map_size_lg: MapSizeLg, posi: usize, gen_ctx: &GenCtx, gen_cdf: &GenCdf) -> Self {
let pos = uniform_idx_as_vec2(map_size_lg, posi);