pmndrs / cannon-es

💣 A lightweight 3D physics engine written in JavaScript.
https://pmndrs.github.io/cannon-es/
MIT License
1.75k stars 130 forks source link

CANNON.Ray(...).intersectBody doesn't update direction itself #15

Open nestarz opened 4 years ago

nestarz commented 4 years ago

new CANNON.Ray(vFrom, vTo).intersectBody(body) method doesn't work without using ray.updateDirection method (which was private in cannon.js).

body.addEventListener("collide", ({ contact }) => {
  if (!grounded) {
    const vFrom = body.position;
    const vTo = new CANNON.Vec3(0, -1, 0);
    const ray = new CANNON.Ray(vFrom, vTo);
    ray.updateDirection(); // <------ I shouldnt need to update the direction 
                            //         manually before using intersectBody
    ray.intersectBody(contact.bi);
    grounded = ray.result.hasHit;
  }
});

A bug also encountered here but you should dig into the code.

Also, thanks for your port and fork !

codynova commented 4 years ago

Try providing a RaycastResult when calling intersectBody:

body.addEventListener('collide', ({ contact: { bi } }) => {
  if (!grounded) {
    const vTo = new CANNON.Vec3(0, -1, 0)
    const ray = new CANNON.Ray(body.position, vTo)
    const result = new CANNON.RaycastResult()
    ray.intersectBody(bi, result)
    grounded = result.hasHit
  }
})
nestarz commented 4 years ago

Thanks for your fast reply, but should I do this even if its a deprecated method ? https://github.com/react-spring/cannon-es/blob/dda84a95bd1812050b4338c3b71ae3093e351d6f/src/collision/Ray.ts#L127

Also, what about the use without a RaycastResult, if it's optional then how to make this work?

codynova commented 4 years ago

The problem I see is that we don't want to call updateDirection in any intersection method unless it's truly necessary (it is not insignificant to performance) - and the way in which it's consumed by the World does not require calling updateDirection.

~I'll remove the optional result param, and instead add an optional doSkipUpdateDirection param that defaults to false, and is set to true by the World.~

EDIT: Not a good idea, see https://github.com/react-spring/cannon-es/issues/15#issuecomment-609564601

codynova commented 4 years ago

This does not work:

Your destructuring isn't correct:

body.addEventListener("collide", ({ contact: bi }) => {

should be

body.addEventListener("collide", ({ contact: { bi } }) => {
codynova commented 4 years ago

After doing more digging I will need to consider this further. Updating the intersect methods API as I suggested above would cause undesirable behavior when initializing the Ray with a RayOptions that contains a result prop - and I believe this pattern may be useful for memory sharing.

The Ray intersect methods were not initially intended for manually raycasting against individual bodies, but they are suitable for it. Maybe be could develop another layer of abstraction for user-facing raycasts.