Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
bfops committed Jan 1, 2018
1 parent 9bad61d commit 6b5722b
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 62 deletions.
41 changes: 24 additions & 17 deletions client/lib/src/terrain_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use common::voxel;
use chunk;
use chunk_stats;
use lod;
use terrain_mesh;

use view;
use view::chunked_terrain;
Expand Down Expand Up @@ -130,10 +129,7 @@ pub fn generate<Rng: rand::Rng>(
let lg_edge_samples = lod.lg_edge_samples();
let lg_sample_size = lod.lg_sample_size();

let mut vertex_coordinates = Vec::new();
let mut normals = Vec::new();
let mut materials = Vec::new();
let mut grass = terrain_mesh::Grass::new();
let chunked_terrain = chunked_terrain::empty();

let low = *chunk_position.as_pnt();
let high = low + (&Vector3::new(1, 1, 1));
Expand Down Expand Up @@ -171,16 +167,27 @@ pub fn generate<Rng: rand::Rng>(
&mut voxel_storage::T { voxels: voxels },
&edge,
&mut |polygon: dual_contouring::polygon::T<voxel::Material>| {
let polygon_offset = vertex_coordinates.len();
vertex_coordinates.push(tri(polygon.vertices[0], polygon.vertices[1], polygon.vertices[2]));
normals.push(tri(polygon.normals[0], polygon.normals[1], polygon.normals[2]));
materials.push(polygon.material as i32);

if polygon.material == voxel::Material::Terrain && lod <= lod::MAX_GRASS_LOD {
grass.tex_ids.push(rng.gen_range(0, 9));
grass.ids.push(grass_allocator.lock().unwrap().allocate());
grass.polygon_offsets.push(polygon_offset);
}
let vertices = tri(polygon.vertices[0], polygon.vertices[1], polygon.vertices[2]);
let normals = tri(polygon.normals[0], polygon.normals[1], polygon.normals[2]);
let material = polygon.material as i32;

let grass =
if polygon.material == voxel::Material::Terrain && lod <= lod::MAX_GRASS_LOD {
Some(chunked_terrain::PushGrass {
tex_id : rng.gen_range(0, 9),
id : grass_allocator.lock().unwrap().allocate(),
})
} else {
None
};

chunked_terrain.push(
&mut *chunk_allocator.lock().unwrap(),
vertices,
normals,
material,
grass,
);
}
);
}}}
Expand All @@ -207,8 +214,8 @@ pub fn generate<Rng: rand::Rng>(
}

let chunk_allocator = &mut *chunk_allocator.lock().unwrap();
chunk_stats.add(vertex_coordinates.len());
chunked_terrain::of_parts(chunk_allocator, vertex_coordinates, normals, materials, grass)
chunk_stats.add(chunked_terrain.polygon_count());
chunked_terrain
})
}

Expand Down
114 changes: 71 additions & 43 deletions client/lib/src/view/chunked_terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use super::terrain_buffers::Chunk;
use super::entity;

/// Information required to load a grass tuft into vram, transformed to refer to vram terrain chunks.
// TODO: Consider making fields non-pub and exposing read-only accessors.
pub struct Grass {
/// subtexture indices
pub tex_ids : Vec<u32>,
Expand All @@ -25,13 +26,23 @@ pub struct Grass {
}

impl Grass {
fn empty() -> Self {
Grass {
tex_ids : Vec::new(),
ids : Vec::new(),
polygon_chunk_ids : Vec::new(),
polygon_offsets : Vec::new(),
}
}

#[allow(missing_docs)]
pub fn len(&self) -> usize {
self.ids.len()
}
}

#[allow(missing_docs)]
// TODO: Consider making fields non-pub and exposing read-only accessors.
pub struct T {
// Every vector should be the same length

Expand All @@ -44,17 +55,67 @@ pub struct T {
/// per-chunk ids
pub ids: Vec<entity::id::Terrain>,
pub grass : Grass,

/// The index within each `Chunk` that we should write to next when pushing new data.
next_idx_inside_chunks: usize,
}

pub struct PushGrass {
tex_id : u32,
id : entity::id::Grass,
}

impl T {
/// is there nothing to be loaded in this chunk?
pub fn len(&self) -> usize {
pub fn polygon_count(&self) -> usize {
if self.next_idx_inside_chunks > 0 {
terrain_buffers::CHUNK_LENGTH * (self.ids.len() - 1) + self.next_idx_inside_chunks
} else {
terrain_buffers::CHUNK_LENGTH * self.ids.len()
}
}

pub fn chunk_count(&self) -> usize {
self.ids.len()
}

/// is there nothing to be loaded in this chunk?
pub fn is_empty(&self) -> bool {
self.len() == 0
self.chunk_count() == 0
}

#[allow(missing_docs)]
pub fn push(
&mut self,
id_allocator : &mut id_allocator::T<entity::id::Terrain>,
vertices : terrain_mesh::Triangle<Point3<GLfloat>>,
normals : terrain_mesh::Triangle<Vector3<GLfloat>>,
material : GLint,
grass : Option<PushGrass>,
) {
// After this block executes, then it is unconditionally true that we write to the last chunk in every `Vec` at this index.
// We only allocate a new chunk when we know we will actually write data to it, to avoid conceptual ambiguity between the
// lack of a pushed chunk vs an empty pushed chunk (e.g. for the return value of `len`)
if self.next_idx_inside_chunks == 0 {
let zero = Point3::new(0.0, 0.0, 0.0);
self.vertex_coordinates.push(terrain_buffers::Chunk([terrain_mesh::tri(zero, zero, zero); terrain_buffers::CHUNK_LENGTH]));
let zero = Vector3::new(0.0, 0.0, 0.0);
self.normals.push(terrain_buffers::Chunk([terrain_mesh::tri(zero, zero, zero); terrain_buffers::CHUNK_LENGTH]));
self.materials.push(terrain_buffers::Chunk([0; terrain_buffers::CHUNK_LENGTH]));
}

self.vertex_coordinates.last_mut().unwrap().0[self.next_idx_inside_chunks] = vertices;
self.normals.last_mut().unwrap().0[self.next_idx_inside_chunks] = normals;
self.materials.last_mut().unwrap().0[self.next_idx_inside_chunks] = material;

let id = id_allocator.allocate();
grass.map(|grass| {
self.grass.polygon_chunk_ids.push(id);
self.grass.polygon_offsets.push(index::of_u32(self.next_idx_inside_chunks));
self.grass.tex_ids.push(grass.tex_id);
self.grass.ids.push(grass.id);
});

self.next_idx_inside_chunks += 1;
}
}

Expand All @@ -73,46 +134,13 @@ fn zero_pad_to<T>(v: &mut Vec<T>, len: usize) {
}

#[allow(missing_docs)]
pub fn of_parts(
id_allocator : &mut id_allocator::T<entity::id::Terrain>,
mut vertices : Vec<terrain_mesh::Triangle<Point3<GLfloat>>>,
mut normals : Vec<terrain_mesh::Triangle<Vector3<GLfloat>>>,
mut materials : Vec<GLint>,
grass : terrain_mesh::Grass,
) -> T {
assert_eq!(vertices.len(), normals.len());
assert_eq!(vertices.len(), materials.len());
let len = round_up(vertices.len(), terrain_buffers::CHUNK_LENGTH);
zero_pad_to(&mut vertices, len);
zero_pad_to(&mut normals, len);
zero_pad_to(&mut materials, len);
let vec_len = len / terrain_buffers::CHUNK_LENGTH;
let vertices_ptr = vertices.as_mut_ptr();
let normals_ptr = normals.as_mut_ptr();
let materials_ptr = materials.as_mut_ptr();
std::mem::forget(vertices);
std::mem::forget(normals);
std::mem::forget(materials);
let ids: Vec<_> = (0..vec_len).map(|_| id_allocator.allocate()).collect();
let grass = {
let mut polygon_chunk_ids = Vec::with_capacity(grass.len());
let mut polygon_offsets = Vec::with_capacity(grass.len());
for i in grass.polygon_offsets {
polygon_chunk_ids.push(ids[i / terrain_buffers::CHUNK_LENGTH]);
polygon_offsets.push(index::of_u32((i % terrain_buffers::CHUNK_LENGTH) as u32));
}
Grass {
tex_ids : grass.tex_ids,
ids : grass.ids,
polygon_offsets : polygon_offsets,
polygon_chunk_ids : polygon_chunk_ids,
}
};
pub fn empty() -> T {
T {
vertex_coordinates : unsafe { Vec::from_raw_parts(vertices_ptr as *mut _, vec_len, vec_len) },
normals : unsafe { Vec::from_raw_parts(normals_ptr as *mut _, vec_len, vec_len) },
materials : unsafe { Vec::from_raw_parts(materials_ptr as *mut _, vec_len, vec_len) },
ids : ids,
grass : grass,
vertex_coordinates : Vec::new(),
normals : Vec::new(),
materials : Vec::new(),
ids : Vec::new(),
grass : Grass::empty(),
next_idx_inside_chunks : 0
}
}
2 changes: 1 addition & 1 deletion client/lib/src/view/terrain_buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub const CHUNK_LENGTH: usize = 1 << 5;
const CHUNK_BUDGET: usize = POLYGON_BUDGET / CHUNK_LENGTH;
/// Instead of storing individual vertices, normals, etc. in VRAM, store them in chunks.
/// This makes it much faster to unload things.
pub struct Chunk<V>([V; CHUNK_LENGTH]);
pub struct Chunk<V>(pub [V; CHUNK_LENGTH]);

impl<V> Chunk<V> {
#[allow(missing_docs)]
Expand Down
2 changes: 1 addition & 1 deletion client/lib/src/view/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn apply_client_to_view(view: &mut view::T, up: T) {
T::LoadMesh(mesh) => {
stopwatch::time("add_chunk", move || {
let mesh = *mesh;
for i in 0 .. mesh.len() {
for i in 0 .. mesh.chunk_count() {
view.terrain_buffers.push(
&mut view.gl,
mesh.ids[i],
Expand Down

0 comments on commit 6b5722b

Please sign in to comment.