Works
This commit is contained in:
+166
-25
@@ -2,11 +2,12 @@ use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use glam::Vec3;
|
||||
use indicatif::ProgressIterator;
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::voxel::gpu::ExplicitNTreeNode;
|
||||
use crate::voxel::gpu::StructurePointer;
|
||||
use crate::voxel::sparse::Color;
|
||||
use crate::voxel_cache::gpu::ExplicitNTreeNode;
|
||||
use crate::voxel_cache::gpu::StructurePointer;
|
||||
use crate::voxel_cache::sparse::Color;
|
||||
|
||||
pub struct BallGenerator<const N: usize>
|
||||
{
|
||||
@@ -15,7 +16,13 @@ pub struct BallGenerator<const N: usize>
|
||||
|
||||
pub fn map(x: f32, x_min: f32, x_max: f32, y_min: f32, y_max: f32) -> f32
|
||||
{
|
||||
((x - x_min) / (x_max - x_min)) * (y_max - y_min) + y_min
|
||||
//((x - x_min) / (x_max - x_min)) * (y_max - y_min) + y_min
|
||||
let input_range = x_max.algebraic_sub(x_min);
|
||||
let output_range = y_max.algebraic_sub(y_min);
|
||||
|
||||
(x.algebraic_sub(x_min).algebraic_div(input_range))
|
||||
.algebraic_mul(output_range)
|
||||
.algebraic_add(y_min)
|
||||
}
|
||||
|
||||
pub trait Producer<const N: usize>
|
||||
@@ -240,6 +247,14 @@ where
|
||||
heightmap: Vec<f32>,
|
||||
colormap: Vec<u8>,
|
||||
|
||||
heightmap_low_width: usize,
|
||||
heightmap_low_height: usize,
|
||||
heightmap_low: Vec<(f32, f32)>,
|
||||
|
||||
colormap_low_width: usize,
|
||||
colormap_low_height: usize,
|
||||
colormap_mip: Vec<u8>,
|
||||
|
||||
pub chunk_width: usize,
|
||||
pub chunk_height: usize,
|
||||
pub chunk_alt: usize,
|
||||
@@ -256,29 +271,50 @@ where
|
||||
color_path: P,
|
||||
) -> Self
|
||||
{
|
||||
println!("Starting terrain producer");
|
||||
println!("Loading height map.");
|
||||
let mut tiff_dec = tiff::decoder::Decoder::new(File::open(height_path).unwrap()).unwrap();
|
||||
let (heightmap_width, heightmap_height) = tiff_dec.dimensions().unwrap();
|
||||
let (heightmap_width, heightmap_height) =
|
||||
(heightmap_width as usize, heightmap_height as usize);
|
||||
|
||||
let heightmap = match tiff_dec.read_image().unwrap()
|
||||
let mut heightmap = match tiff_dec.read_image().unwrap()
|
||||
{
|
||||
tiff::decoder::DecodingResult::F32(vec) => vec,
|
||||
_ => panic!("Unsupported format"),
|
||||
};
|
||||
|
||||
println!("Loading color map.");
|
||||
let mut color = image::ImageReader::open(color_path).unwrap();
|
||||
color.no_limits();
|
||||
|
||||
let color = color.decode().unwrap();
|
||||
let colormap = color.as_rgb8().unwrap().to_vec();
|
||||
let mut colormap = color.as_rgb8().unwrap().to_vec();
|
||||
|
||||
println!("Converting color spaces");
|
||||
colormap.iter_mut().for_each(|x| {
|
||||
let normalized = map(*x as f32, 0., 255., 0., 1.);
|
||||
let maped = normalized.powf(2.4);
|
||||
*x = map(maped, 0., 1., 0., 255.) as u8;
|
||||
});
|
||||
|
||||
let terrain_width = color.width() as usize;
|
||||
let terrain_height = color.height() as usize;
|
||||
|
||||
let heightmap_min = heightmap.iter().copied().reduce(f32::min).unwrap();
|
||||
println!("Computing heightmap min/max");
|
||||
let heightmap_min = heightmap
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|x| *x != -9999.)
|
||||
.reduce(f32::min)
|
||||
.unwrap();
|
||||
let heightmap_max = heightmap.iter().copied().reduce(f32::max).unwrap();
|
||||
|
||||
heightmap
|
||||
.iter_mut()
|
||||
.filter(|x| **x == -9999.)
|
||||
.for_each(|x| *x = heightmap_min);
|
||||
|
||||
// Decide size in chunks
|
||||
let height_amplitude = heightmap_max - heightmap_min;
|
||||
let chunk_size = N.pow(chunk_power as u32);
|
||||
@@ -286,6 +322,65 @@ where
|
||||
let chunk_height = terrain_height.div_ceil(chunk_size);
|
||||
let chunk_alt = ((height_amplitude / height_factor) as usize).div_ceil(chunk_size);
|
||||
|
||||
// build the low heightmap
|
||||
println!("Computing low res height/color maps");
|
||||
let heightmap_low_width = heightmap_width / 8;
|
||||
let heightmap_low_height = heightmap_height / 8;
|
||||
|
||||
let mut heightmap_low = vec![(0., 0.); heightmap_low_height * heightmap_low_width];
|
||||
|
||||
for y in 0..heightmap_low_height
|
||||
{
|
||||
for x in 0..heightmap_low_width
|
||||
{
|
||||
let mut min = heightmap_max;
|
||||
let mut max = heightmap_min;
|
||||
for sy in (y * 8)..(y * 8 + 8)
|
||||
{
|
||||
for sx in (x * 8)..(x * 8 + 8)
|
||||
{
|
||||
min = min.min(heightmap[sx + sy * heightmap_width]);
|
||||
max = max.max(heightmap[sx + sy * heightmap_width]);
|
||||
}
|
||||
}
|
||||
|
||||
heightmap_low[x + y * heightmap_low_width] = (min, max);
|
||||
}
|
||||
}
|
||||
|
||||
// build the color map mip
|
||||
let colormap_low_width = terrain_width / 8;
|
||||
let colormap_low_height = terrain_height / 8;
|
||||
|
||||
let mut colormap_mip = vec![0u8; colormap_low_width * colormap_low_height * 3];
|
||||
|
||||
for y in 0..colormap_low_height
|
||||
{
|
||||
for x in 0..colormap_low_width
|
||||
{
|
||||
let mut r = 0u32;
|
||||
let mut g = 0u32;
|
||||
let mut b = 0u32;
|
||||
for sy in (y * 8)..(y * 8 + 8)
|
||||
{
|
||||
for sx in (x * 8)..(x * 8 + 8)
|
||||
{
|
||||
r += colormap[(sx + sy * terrain_width) * 3] as u32;
|
||||
g += colormap[(sx + sy * terrain_width) * 3 + 1] as u32;
|
||||
b += colormap[(sx + sy * terrain_width) * 3 + 2] as u32;
|
||||
}
|
||||
}
|
||||
|
||||
colormap_mip[(x + y * colormap_low_width) * 3] =
|
||||
((r as f32) / (8 * 8) as f32).clamp(0., 255.) as u8;
|
||||
colormap_mip[(x + y * colormap_low_width) * 3 + 1] =
|
||||
((g as f32) / (8 * 8) as f32).clamp(0., 255.) as u8;
|
||||
colormap_mip[(x + y * colormap_low_width) * 3 + 2] =
|
||||
((b as f32) / (8 * 8) as f32).clamp(0., 255.) as u8;
|
||||
}
|
||||
}
|
||||
|
||||
println!("Producer ready");
|
||||
Self {
|
||||
chunk_power,
|
||||
heightmap_width,
|
||||
@@ -297,6 +392,14 @@ where
|
||||
heightmap,
|
||||
colormap,
|
||||
|
||||
heightmap_low_width,
|
||||
heightmap_low_height,
|
||||
heightmap_low,
|
||||
|
||||
colormap_low_width,
|
||||
colormap_low_height,
|
||||
colormap_mip,
|
||||
|
||||
chunk_width,
|
||||
chunk_height,
|
||||
chunk_alt,
|
||||
@@ -340,30 +443,68 @@ where
|
||||
let mut sample_min = self.heightmap_max;
|
||||
let mut color_avg = Color(0., 0., 0., 0.);
|
||||
let mut count = 0;
|
||||
for (x, z) in (0..child_size).cartesian_product(0..child_size)
|
||||
|
||||
if depth <= 2
|
||||
{
|
||||
let gvx = gcx + x;
|
||||
let gvz = gcz + z;
|
||||
if gvx < self.terrain_width && gvz < self.terrain_height
|
||||
for (z, x) in (0..(child_size / 8)).cartesian_product(0..(child_size / 8))
|
||||
{
|
||||
// Height sample
|
||||
let height_x = (gvx * self.heightmap_width) / self.terrain_width;
|
||||
let height_z = (gvz * self.heightmap_height) / self.terrain_height;
|
||||
let gvx = (gcx + x * 8) / 8;
|
||||
let gvz = (gcz + z * 8) / 8;
|
||||
if gvx < self.colormap_low_width && gvz < self.colormap_low_height
|
||||
{
|
||||
// Height sample
|
||||
let height_x = (gvx * self.heightmap_low_width) / self.colormap_low_width;
|
||||
let height_z = (gvz * self.heightmap_low_height) / self.colormap_low_height;
|
||||
|
||||
let sample = self.heightmap[height_x + height_z * self.heightmap_width];
|
||||
sample_max = sample_max.max(sample);
|
||||
sample_min = sample_min.min(sample);
|
||||
let sample =
|
||||
self.heightmap_low[height_x + height_z * self.heightmap_low_width];
|
||||
sample_min = sample_min.min(sample.0);
|
||||
sample_max = sample_max.max(sample.1);
|
||||
|
||||
let sample_color_r = self.colormap[(gvx + gvz * self.terrain_width) * 3];
|
||||
let sample_color_g = self.colormap[(gvx + gvz * self.terrain_width) * 3 + 1];
|
||||
let sample_color_b = self.colormap[(gvx + gvz * self.terrain_width) * 3 + 2];
|
||||
let sample_color_r =
|
||||
self.colormap_mip[(gvx + gvz * self.colormap_low_width) * 3];
|
||||
let sample_color_g =
|
||||
self.colormap_mip[(gvx + gvz * self.colormap_low_width) * 3 + 1];
|
||||
let sample_color_b =
|
||||
self.colormap_mip[(gvx + gvz * self.colormap_low_width) * 3 + 2];
|
||||
|
||||
color_avg.0 += map(sample_color_r as f32, 0., 256., 0., 1.);
|
||||
color_avg.1 += map(sample_color_g as f32, 0., 256., 0., 1.);
|
||||
color_avg.2 += map(sample_color_b as f32, 0., 256., 0., 1.);
|
||||
count += 1;
|
||||
color_avg.0 += map(sample_color_r as f32, 0., 256., 0., 1.);
|
||||
color_avg.1 += map(sample_color_g as f32, 0., 256., 0., 1.);
|
||||
color_avg.2 += map(sample_color_b as f32, 0., 256., 0., 1.);
|
||||
count += 1;
|
||||
}
|
||||
//let gvy = gcy;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (z, x) in (0..child_size).cartesian_product(0..child_size)
|
||||
{
|
||||
let gvx = gcx + x;
|
||||
let gvz = gcz + z;
|
||||
if gvx < self.terrain_width && gvz < self.terrain_height
|
||||
{
|
||||
// Height sample
|
||||
let height_x = (gvx * self.heightmap_width) / self.terrain_width;
|
||||
let height_z = (gvz * self.heightmap_height) / self.terrain_height;
|
||||
|
||||
let sample = self.heightmap[height_x + height_z * self.heightmap_width];
|
||||
sample_max = sample_max.max(sample);
|
||||
sample_min = sample_min.min(sample);
|
||||
|
||||
let sample_color_r = self.colormap[(gvx + gvz * self.terrain_width) * 3];
|
||||
let sample_color_g =
|
||||
self.colormap[(gvx + gvz * self.terrain_width) * 3 + 1];
|
||||
let sample_color_b =
|
||||
self.colormap[(gvx + gvz * self.terrain_width) * 3 + 2];
|
||||
|
||||
color_avg.0 += map(sample_color_r as f32, 0., 256., 0., 1.);
|
||||
color_avg.1 += map(sample_color_g as f32, 0., 256., 0., 1.);
|
||||
color_avg.2 += map(sample_color_b as f32, 0., 256., 0., 1.);
|
||||
count += 1;
|
||||
}
|
||||
//let gvy = gcy;
|
||||
}
|
||||
//let gvy = gcy;
|
||||
}
|
||||
|
||||
color_avg.0 /= count as f32;
|
||||
|
||||
Reference in New Issue
Block a user