planetkit 0.0.1

High-level toolkit for building games based around voxel globes.
Documentation
use super::*;

#[test]
fn find_spawn_points() {
    use rand;

    // Don't bother seeding it off the world spec/seed for now;
    // we just want to check that if we keep finding new points
    // then some of them will fail, because they are underwater.
    let mut rng = rand::thread_rng();
    const TRIALS: usize = 200;
    let successes = (0..TRIALS)
        .map(|_| {
            // TODO: move globe out of closure and "collect garbage" chunks
            // on each iteration? Need to get into the habit of doing this.
            // Maybe also make globe or something record stats on how many
            // chunks loaded over time.
            let mut globe = Globe::new_earth_scale_example();
            globe.air_above_random_surface_dry_land(
                &mut rng,
                5, // Min air cells above
                5, // Max distance from starting point
                3, // Max attempts
            )
        })
        .filter(|maybe_pos| maybe_pos.is_some())
        .count();
    // Some should eventually succeed, some should give up.
    assert!(successes > 5);
    assert!(successes < TRIALS - 5);
}

#[cfg(feature = "nightly")]
pub mod benches {
    use test::Bencher;

    use slog;

    use super::super::*;

    use globe::GridPoint3;

    #[bench]
    // # History for picking the "middle of the vector" chunk.
    //
    // - Original `cull_more_faces_impractically_slow` culling implementation:
    //     - 3,727,934 ns/iter (+/- 391,582
    // - After introducing `Cursor`:
    //     - 3,618,305 ns/iter (+/- 539,063)
    //     - No noticeable change; build_chunk_geometry already only operates
    //       directly on a single chunk. It's the implementation of `cull_cell`,
    //       and the underlying implementation of `Neighbors` that make it so
    //       horrendously slow at the moment.
    // - After using `Cursor` in `cull_cell`:
    //     - 861,702 ns/iter (+/- 170,677)
    //     - Substantially better, but there are many more gains to be had.
    // - After cleaning up implementation and use of `Neighbors`:
    //     - 565,896 ns/iter (+/- 237,193
    //     - A little bit better, but mostly by eliminating completely useless
    //       checks for diagonal neighbors. The next wins will come from implementing
    //       an "easy case" version of `Neighbors` that avoids most of the math.
    // - After implementing fast `Neighbors`:
    //     - 486,945 ns/iter (+/- 112,408)
    //     - Only a tiny speed-up. There's lots more room for improvement on this front,
    //       but given that my chunks at the moment are very small, I'm just going to
    //       leave it as is and move on to bigger fish.
    // - After replacing chunk vector with hash map:
    //     - 426,929 ns/iter (+/- 56,074)
    //     - Again, only a very small improvement. This change wasn't made to speed
    //       up generating chunk geometry; I'm just updating this history for completeness.
    //     - I believe this change would have been a lot more noticeable if I hadn't
    //       already implemented `Cursor`, because it speeds up looking up a chunk
    //       by its origin, which `Cursor` helps you avoid most of the time.
    fn bench_generate_chunk_geometry(b: &mut Bencher) {
        use render::Vertex;

        const ROOT_RESOLUTION: [GridCoord; 2] = [32, 64];
        const CHUNK_RESOLUTION: [GridCoord; 3] = [16, 16, 4];

        let drain = slog::Discard;
        let log = slog::Logger::root(drain, o!("pk_version" => env!("CARGO_PKG_VERSION")));
        let spec = Spec {
            seed: 13,
            floor_radius: 0.91,
            ocean_radius: 1.13,
            block_height: 0.02,
            root_resolution: ROOT_RESOLUTION,
            chunk_resolution: CHUNK_RESOLUTION,
        };
        let globe = Globe::new(spec);
        let spec = globe.spec();
        let globe_view = View::new(spec, &log);
        let mut vertex_data: Vec<Vertex> = Vec::new();
        let mut index_data: Vec<u32> = Vec::new();
        // Copied from output of old version of test to make sure
        // we're actually benchmarking the same thing.
        let middle_chunk_origin = ChunkOrigin::new(
            GridPoint3::new(2.into(), 16, 16, 8),
            ROOT_RESOLUTION,
            CHUNK_RESOLUTION,
        );
        b.iter(|| {
            vertex_data.clear();
            index_data.clear();
            globe_view.make_chunk_geometry(
                &globe,
                middle_chunk_origin,
                &mut vertex_data,
                &mut index_data,
            );
        });
    }
}