Fix occlusion culling.
It's slow now, but I'm pretty sure it can be optimized.
This commit is contained in:
parent
6b0087f1a2
commit
6c8e4de739
|
@ -50,7 +50,7 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
||||||
const SCALE_FACTOR: f32 = 1.0;
|
const SCALE_FACTOR: f32 = 1.0;
|
||||||
|
|
||||||
// TODO(pcwalton): Make this configurable.
|
// TODO(pcwalton): Make this configurable.
|
||||||
const FLATTENING_TOLERANCE: f32 = 3.0;
|
const FLATTENING_TOLERANCE: f32 = 0.333;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let matches =
|
let matches =
|
||||||
|
@ -1238,22 +1238,53 @@ impl BuiltScene {
|
||||||
fn from_objects(view_box: &Rect<f32>, objects: &[BuiltObject]) -> BuiltScene {
|
fn from_objects(view_box: &Rect<f32>, objects: &[BuiltObject]) -> BuiltScene {
|
||||||
let mut scene = BuiltScene::new(view_box, objects.len() as u32);
|
let mut scene = BuiltScene::new(view_box, objects.len() as u32);
|
||||||
|
|
||||||
let mut z_buffer = FixedBitSet::with_capacity(scene.tile_rect.size.width as usize *
|
let tile_area = scene.tile_rect.size.width as usize * scene.tile_rect.size.height as usize;
|
||||||
scene.tile_rect.size.height as usize);
|
let mut z_buffer = vec![0; tile_area];
|
||||||
|
|
||||||
|
// Initialize z-buffer, and fill solid tiles.
|
||||||
|
for (object_index, object) in objects.iter().enumerate().rev() {
|
||||||
|
for solid_tile_index in object.solid_tiles.ones() {
|
||||||
|
let tile = &object.tiles[solid_tile_index];
|
||||||
|
if tile.backdrop == 0 {
|
||||||
|
// Tile is transparent and can't be solid.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
let scene_tile_index = scene.scene_tile_index(tile.tile_x, tile.tile_y);
|
||||||
|
if z_buffer[scene_tile_index as usize] > object_index {
|
||||||
|
// Occluded.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
z_buffer[scene_tile_index as usize] = object_index;
|
||||||
|
|
||||||
|
scene.solid_tiles.push(SolidTileScenePrimitive {
|
||||||
|
tile_x: tile.tile_x,
|
||||||
|
tile_y: tile.tile_y,
|
||||||
|
object_index: object_index as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut object_tile_index_to_scene_mask_tile_index = vec![];
|
let mut object_tile_index_to_scene_mask_tile_index = vec![];
|
||||||
|
for (object_index, object) in objects.iter().enumerate() {
|
||||||
for (object_index, object) in objects.iter().enumerate().rev() {
|
|
||||||
object_tile_index_to_scene_mask_tile_index.clear();
|
object_tile_index_to_scene_mask_tile_index.clear();
|
||||||
object_tile_index_to_scene_mask_tile_index.reserve(object.tiles.len());
|
object_tile_index_to_scene_mask_tile_index.reserve(object.tiles.len());
|
||||||
|
|
||||||
// Copy tiles.
|
// Copy mask tiles.
|
||||||
for (tile_index, tile) in object.tiles.iter().enumerate() {
|
for (tile_index, tile) in object.tiles.iter().enumerate() {
|
||||||
let scene_tile_index = scene.scene_tile_index(tile.tile_x, tile.tile_y);
|
// Skip solid tiles, since we handled them above already.
|
||||||
if z_buffer[scene_tile_index as usize] {
|
if object.solid_tiles[tile_index] {
|
||||||
// Occluded.
|
|
||||||
object_tile_index_to_scene_mask_tile_index.push(u32::MAX);
|
object_tile_index_to_scene_mask_tile_index.push(u32::MAX);
|
||||||
} else if object.mask_tiles[tile_index] {
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cull occluded tiles.
|
||||||
|
let scene_tile_index = scene.scene_tile_index(tile.tile_x, tile.tile_y);
|
||||||
|
if z_buffer[scene_tile_index as usize] > object_index {
|
||||||
|
object_tile_index_to_scene_mask_tile_index.push(u32::MAX);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Visible mask tile.
|
// Visible mask tile.
|
||||||
let scene_mask_tile_index = scene.mask_tiles.len() as u32;
|
let scene_mask_tile_index = scene.mask_tiles.len() as u32;
|
||||||
object_tile_index_to_scene_mask_tile_index.push(scene_mask_tile_index);
|
object_tile_index_to_scene_mask_tile_index.push(scene_mask_tile_index);
|
||||||
|
@ -1261,18 +1292,6 @@ impl BuiltScene {
|
||||||
tile: *tile,
|
tile: *tile,
|
||||||
object_index: object_index as u32,
|
object_index: object_index as u32,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
// Visible transparent or solid tile.
|
|
||||||
object_tile_index_to_scene_mask_tile_index.push(u32::MAX);
|
|
||||||
if tile.backdrop != 0 {
|
|
||||||
scene.solid_tiles.push(SolidTileScenePrimitive {
|
|
||||||
tile_x: tile.tile_x,
|
|
||||||
tile_y: tile.tile_y,
|
|
||||||
object_index: object_index as u32,
|
|
||||||
});
|
|
||||||
z_buffer.insert(scene_tile_index as usize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remap and copy fills, culling as necessary.
|
// Remap and copy fills, culling as necessary.
|
||||||
|
@ -1311,7 +1330,7 @@ struct BuiltObject {
|
||||||
tile_rect: Rect<i16>,
|
tile_rect: Rect<i16>,
|
||||||
tiles: Vec<TileObjectPrimitive>,
|
tiles: Vec<TileObjectPrimitive>,
|
||||||
fills: Vec<FillObjectPrimitive>,
|
fills: Vec<FillObjectPrimitive>,
|
||||||
mask_tiles: FixedBitSet,
|
solid_tiles: FixedBitSet,
|
||||||
shader: ObjectShader,
|
shader: ObjectShader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1390,12 +1409,15 @@ impl BuiltObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut solid_tiles = FixedBitSet::with_capacity(tile_count);
|
||||||
|
solid_tiles.insert_range(..);
|
||||||
|
|
||||||
BuiltObject {
|
BuiltObject {
|
||||||
bounds: *bounds,
|
bounds: *bounds,
|
||||||
tile_rect,
|
tile_rect,
|
||||||
tiles,
|
tiles,
|
||||||
fills: vec![],
|
fills: vec![],
|
||||||
mask_tiles: FixedBitSet::with_capacity(tile_count),
|
solid_tiles,
|
||||||
shader: *shader,
|
shader: *shader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1409,7 +1431,7 @@ impl BuiltObject {
|
||||||
tile_x,
|
tile_x,
|
||||||
tile_y,
|
tile_y,
|
||||||
});
|
});
|
||||||
self.mask_tiles.insert(tile_index as usize);
|
self.solid_tiles.set(tile_index as usize, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(pcwalton): Use a `Point2D<i16>` instead?
|
// FIXME(pcwalton): Use a `Point2D<i16>` instead?
|
||||||
|
|
Loading…
Reference in New Issue