ncollide icon indicating copy to clipboard operation
ncollide copied to clipboard

Use a general transformation type for certain operations such as ray-object queries

Open expenses opened this issue 5 years ago • 3 comments

toi_with_ray takes an isometry which is the transformation to apply to the object. Unfortunately, isometrys do not involve scaling, so if I wanted to query rays against a objects of various sizes, I would have to do various transformations to either the ray or the object. I think it would be better to use a general transformation type for this sort of thing that did incorporate scaling.

expenses avatar Nov 01 '18 09:11 expenses

Scaling generally complicates significantly geometric algorithms. In particular non-uniform scaling is almost always impossible to handle efficiently.

To some extents uniform scaling can be handled for some shapes and geometric operations so that might be possible to consider.

sebcrozet avatar Nov 01 '18 10:11 sebcrozet

Oh, yeah, I can see how non-uniform scaling could be problematic. I'll see what I can do with uniform scaling though.

expenses avatar Nov 01 '18 10:11 expenses

For example, I've got this code to check for collisions:

fn get_mesh_at_size(&self, model: context::Model, size: f32) -> TriMesh<f32> {
    let mut vertices = self.get_mesh(model).vertices().clone();
    vertices.iter_mut().for_each(|vertex| *vertex *= size);

    let indices = self.get_mesh(model).indices().clone();

    TriMesh::new(vertices, indices, None)
}

pub fn intersects(
    &self,
    model_a: context::Model, pos_a: Vector3<f32>, rot_a: Quaternion<f32>, size_a: f32,
    model_b: context::Model, pos_b: Vector3<f32>, rot_b: Quaternion<f32>, size_b: f32
) -> bool {

    let bb_a = self.get_bbox(model_a, pos_a, rot_a, size_a);
    let bb_b = self.get_bbox(model_b, pos_b, rot_b, size_b);

    if !bb_a.intersects(&bb_b) {
        return false;
    }

    ncollide3d::query::distance(
        &make_isometry(pos_a, rot_a),
        &self.get_mesh_at_size(model_a, size_a),
        &make_isometry(pos_b, rot_b),
        &self.get_mesh_at_size(model_b, size_b)
    ) == 0.0
}

Unfortunately, cloning the trimesh is fairly expensive. There are a few solutions that might work such as only scaling one of the meshes or caching meshes by size, but it would be a lot easier to have a variantof ncollide3d::query::distance or something that takes size into acount.

expenses avatar Nov 03 '18 00:11 expenses