ethereumdegen / bevy_mesh_terrain

MIT License
39 stars 5 forks source link

add collision using parry #3

Closed ethereumdegen closed 3 months ago

ethereumdegen commented 10 months ago

add collision using parry (should be simple since heightmap is already the exact same format of parry heightfield ! )

have some way to make Collider components be attached to the chunk entities... maybe just give some sample code..

mattdm commented 10 months ago

Would this make it Just Work™ with bevy_rapier?

Also: this is a cool project — thanks!

ethereumdegen commented 10 months ago

I am still trying to architect the best way to make that a reality. The way most packages handle this is by adding optional "features" which add the dependencies such as rapier or xpbd. So i think that is the best way to go about it without adding them as dependencies by default.

Here is some sample code of how i was able to get collision working with xpbd until then: https://gist.github.com/ethereumdegen/69c476d72053400feae37e88ca21fbd4

mattdm commented 10 months ago

Once I get the basics figured out here, I'll add a rapier3d example.

ethereumdegen commented 3 months ago

TLDR here is how i do it


#[sysfail]
pub(crate) fn load_colliders_for_terrain(
    mut commands: Commands,
   // _meshes: Res<Assets<Mesh>>,
    chunk_query: Query<&Chunk>,
    terrain_mesh_query: Query<
        (Entity, &Handle<Mesh>, &GlobalTransform, &Parent),
        (With<TerrainChunkMesh>, Without<Collider>),
    >,

     mut terrain_load_timer_resource: ResMut<TerrainLoadingTimerResource>,

    terrain_viewer: Query<&GlobalTransform, With<TerrainViewer>>,

     player_enter_level_data: Res<PlayerEnterLevelDataResource>,

)  {
    let viewer = terrain_viewer.iter().next();

    let _viewer_location: Vec3 = match viewer {

        Some(view) => view.translation(),
        // FIX: probably should log a warning if there are multiple (or no) viewers, rather than just setting to the origin
        None => {

            let   found_waypoint_xform:Option<Vec3> = player_enter_level_data.as_ref()
                                                         .player_is_entering_at_translation.clone();

            if let Some(found_waypoint_xform) = found_waypoint_xform {
               found_waypoint_xform
            }else {
                warn!("no terrain viewers");
            return Ok(())
            }

        } ,
    };

    for (entity, _mesh_handle, terrain_mesh_transform, parent_chunk) in terrain_mesh_query.iter() {
        let _chunk_world_location = terrain_mesh_transform.translation();

        println!("loading terrain collider  ");

        let chunk = chunk_query.get(parent_chunk.get()).unwrap();

        let chunk_id = chunk.chunk_id;

        let file_path = format!("assets/terrain/default_terrain/collision/{}.col", chunk_id);

        // Read the entire file into a string
        let mut file = fs::File::open(file_path)?;
        let mut contents = Vec::new();
        file.read_to_end(&mut contents)?;

        // Deserialize the JSON string back into a struct
        let collider: Collider = bincode::deserialize(&contents).unwrap();

        commands.entity(entity).insert(collider).insert((
            RigidBody::Static,
            CollisionLayers::new(
                [CollisionLayer::Terrain, CollisionLayer::CameraObstacle],
                [CollisionLayer::Character],
            ),

        ));

        println!("added terrain collider to {:?}", entity);

        terrain_load_timer_resource.terrain_loading_timer.reset();
    }

}