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

Add Box / Trimesh collisions #21

Open arpu opened 4 years ago

arpu commented 4 years ago

Hi, would be nice to get this Box Shape collide with a Trimesh

marcofugaro commented 4 years ago

Hello @arpu can you provide a more detailed explanation of what's the actual situation vs. how would you like it to work?

arpu commented 4 years ago

hi,

@codynova pointed me on Twitter to this cannon table Bildschirmfoto von 2020-04-20 12-47-08

in this Table a Trimesh can only be collade with a Sphere and a Plane, in some Situations it would be good to have a Box shape collide with the Trimesh

arpu commented 4 years ago

right now i am not sure if this needs much more work or its simple doable

marcofugaro commented 4 years ago

it's never simply doable my friend

arpu commented 3 years ago

still looking at this for https://vrland.io/dev/in if you grab the boxes and hit it again the house (trimesh) no physics the ball just works fine

maybe i should include a sphere inside the box? maybe this is the best and most performance optimized way?

NikLever commented 3 years ago

Any progress on this. It would be great for Car games, Snowboarding and Skiing.

IoIxD commented 2 years ago

It seems like, in the mean time, you will have to recreate your model with planes and boxes. I'd be interested in a more technical explanation as to why this is impossible.

WilliamBagel commented 2 years ago

For the people who really want to use trimeshes, I made a function that converts a trimesh to a body with convex polyhedron shapes added to it. However, it is probably very slow, (in my demo I got 44 fps while a few shapes were moving) and for some reason the body does not move, possibly because it contains lots of overlapping geometry? A way of implementing trimeshes could be segmenting the concave geometry into multiple convex shapes, this was also mentioned in this thread. Not sure how that could be implemented or where the javascript module for it is 😕 . image

function TrimeshToPolyhedron(trimesh,upvector){
      let p1 = new CANNON.Vec3(),p2 = new CANNON.Vec3(),p3 = new CANNON.Vec3(),p4 = new CANNON.Vec3(),mp = new CANNON.Vec3(),tmp = new CANNON.Vec3(),e1 = new CANNON.Vec3(),e2 = new CANNON.Vec3();
      const body = new CANNON.Body()
      for(let i = 0; i < trimesh.indices.length/3;i++){
          mp.set(0,0,0)
          trimesh.getTriangleVertices(i,p1,p2,p3)
          trimesh.getNormal(i,p4)
          if(upvector && p4.dot(upvector) < 0)p4.scale(-1,p4)
          p4.normalize()
          mp = mp.vadd(p1).vadd(p2).vadd(p3).scale(1/3)
          const vertices = [new CANNON.Vec3().copy(p1),new CANNON.Vec3().copy(p2),new CANNON.Vec3().copy(p3),mp.vadd(p4.scale(-1/2))];
          const faces = [[0,1,2],[0,3,1],[1,3,2],[2,3,0]];
          const normals = [new CANNON.Vec3().copy(p4)];
          for(let j = 0;j < 3;j++){
              vertices[j].vsub(vertices[(j+1)%3],e1);
              vertices[(j+1)%3].vsub(p4,e2);
              tmp.set(0,0,0)
              const points = faces[j+1]
              for(let p = 0;p < points.length;p++){
                  tmp.vadd(vertices[points[p]],tmp);
              }
              tmp.scale(1/points.length,tmp)
              const normal = e1.cross(e2)
              normal.normalize()
              normal.scale(-1,normal)
              const angle = normal.dot(tmp)

              if(angle < 0 )normal.scale(-1,normal)
              normals.push(normal)
          }
          const polyhedron = new CANNON.ConvexPolyhedron({vertices,faces,normals})
          body.addShape(polyhedron)
      }
      return body
    }

not the best written, but does the job :) EDIT: fixed the function after I realized it was making a sarlacc. There is still something messed up with the normals and 4th vertex(p4):confused: EDIT 2: fixed the function more and the problem with normals, I also tried not adding the extra faces, but either way, when testing with a torus, boxes glitch out when they fall inside the torus and end up flying away or getting stuck inside the torus. I also added an upvector parameter which helps when the trimesh does not have the correct normal orientation. Also the reason why it wasn't moving was because I had to set it's type to dynamic🤦‍♂️

rickythedeveloper commented 2 years ago

Have there been any updates on this? It would be super useful to be able to detect collisions between vehicles made of boxes and the ground made of trimeshes or vice versa.

arpu commented 7 months ago

for Box collide Trimesh i use now this:

if (shape.type === CANNON.Shape.types.BOX ) {

        const sphereShape = new CANNON.Sphere(0.1)
        const box = shape.halfExtents
        this.body.addShape(sphereShape, new CANNON.Vec3(-box.x, -box.y, box.z))
        this.body.addShape(sphereShape, new CANNON.Vec3(-box.x, box.y, box.z))
        this.body.addShape(sphereShape, new CANNON.Vec3(box.x, -box.y, box.z))
        this.body.addShape(sphereShape, new CANNON.Vec3(box.x, box.y, box.z))

        this.body.addShape(sphereShape, new CANNON.Vec3(-box.x, -box.y, -box.z))
        this.body.addShape(sphereShape, new CANNON.Vec3(-box.x, box.y, -box.z))
        this.body.addShape(sphereShape, new CANNON.Vec3(box.x, -box.y, -box.z))
        this.body.addShape(sphereShape, new CANNON.Vec3(box.x, box.y, -box.z))

        const minRadius = Math.min(box.x, box.y, box.z);
        this.body.addShape(new CANNON.Sphere(minRadius), new CANNON.Vec3(0, 0, 0))
        this.body.fixedRotation = true

 }

Bildschirmfoto vom 2024-01-12 13-16-57

kelvinkoko commented 3 months ago

Thanks for having a this maintained fork! i think other user also mentioned above, but just would like to have a +1 on supporting Box, it will help a lot in many applications like car racing etc