Closed ethereumdegen closed 3 months ago
Would this make it Just Work™ with bevy_rapier?
Also: this is a cool project — thanks!
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
Once I get the basics figured out here, I'll add a rapier3d example.
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();
}
}
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..