0
\$\begingroup\$

I have developed a collision detector that return collision data, as collision normal, collision point, interpenetration, etc.

And now I am developing a collision solver. The collision solver compute correctly the linear motion after the collision but it is not able to compute the rotation after the collision.

This is an image ilustrating the problem

                                                     example

To compute the velocity after collision I apply a impulse to each body, this impulse is able to compute correctly linear motion.

Now, to compute the rotation change I need to apply the following formula

ImpulsiveTorque = RelativePoint.cross(Impulse);
RotationChange = InverseInertiaTensorWorld.transform(ImpulsiveTorque);

The problem is ImpulsiveTorque is very small to generate a visible rotation change.

The following correspond to my sphere-sphere collision detector

sphereAndSphere : function(one, two){
    var oneToTwo = one.position.sub(two.position);
    var oneToTwoLength = oneToTwo.length();
    if (oneToTwoLength < 0 || oneToTwoLength > one.radius + two.radius){
        return -1;
    }
    var normal = oneToTwo.divideByScalar(oneToTwoLength);
    var data = new Collision();
    data.normal = normal;
    data.point = one.position.add(oneToTwo.multiplyByScalar(0.5));
    data.depth = one.radius+two.radius - oneToTwoLength;
    data.body = [];
    data.body.push(one);
    data.body.push(two);
    data.restitution = Math.min(one.body.restitution, two.body.restitution);
    return data;
},

RelativePoint is the collision point relative to center of mass of each body in collision. It is computed as follow

this.relativePoint[0]=this.point.sub(this.body[0].position);
if (this.body[1] !== undefined){
    this.relativePoint[1]=this.point.sub(this.body[1].position);
}

The impulse should be applied in the normal direction.

If I am correct RelativePoint vector has the same direction that normal collision vector. So, the impulse has the same direction that RelativePoint so the cross product will return a very small result. As a result I can't get a visible rotation change.

I think calculations is ok, but it lead to no rotation between sphere-sphere collision and in the real world if sphere-sphere collide I can see a variation in rotation, so I think that I am forgetting something.

Can you give me some tip why I don't get a visible change in rotation?

P.D If you need more information please tell me.

Edit: This is the way how I compute the Impulse vector.

First I need to know how change the velocity for each unit of impulse. At this point I compute this quantity in the collision normal (For collision solver I work in collision coordinates). For that reason I use the dot product between normal and ChangeVelPerUnit

var changeVelPerUnit = RelativePoint[0].cross(normal);
changeVelPerUnit = body1.inverseInertiaTensorWorld.transform(changeVelPerUnit);
changeVelPerUnit = changeVelPerUnit.cross(RelativePoint[0]);
changeVelPerUnit = changeVelPerUnit.dot(normal);
changeVelPerUnit += body1.inverseMass;

Then I need to know the current closing velocity (or separating velocity) with the formula v = v' + (rotation x RelativePoint)

var sepVelocity = body1.rotation.cross(RelativePoint[0]);
sepVelocity = sepVelocity.add(body1.velocity);

This velocity is computed in world coordinates so I need to change it to Collision coordinates

var collisionVelocity = transform.getTranspose().transform(sepVelocity);

With this, now I compute the change in velocity that should be given to the body, taking into account the restitution coefficient. I use the x coordinates because I use the normal as X axis for matrix to change from collision coordinates to world coordinates and viceversa.

var changeInVel = -collisionVelocity.x * (1 + this.restitution);

and finally I compute the impulse in collision coordinates and then pass it to world coordinates

var impulseCollision = new ALMath.Vector3(changeInVel/changeVelPerUnit,0,0)
var impulse = transform.transform(impulseCollision);

P.S the impulse computation is doing only for one body, it should be necessary to do calculations for second body, but for simplicity I omitted it.

\$\endgroup\$
3
  • \$\begingroup\$ The vector (Impulse) passed to that cross product should be in the direction of the relative velocities of the objects. How do you calculate Impulse? \$\endgroup\$
    – Victor T.
    Apr 21, 2017 at 14:22
  • \$\begingroup\$ I have added a edit section where I explain how to compute impulse vector \$\endgroup\$
    – RdlP
    Apr 21, 2017 at 15:11
  • \$\begingroup\$ It looks to me like var changeVelPerUnit = RelativePoint[0].cross(normal); would always result in 0. As you note in your original post, the relative point and the normal are parallel and therefore should give a cross product of 0. \$\endgroup\$
    – Victor T.
    Apr 21, 2017 at 16:09

1 Answer 1

1
\$\begingroup\$

The direction of the collision normal between 2 spheres is calculated using the difference in their positions. This is the same direction as the vector pointing from either sphere to the contact point. The cross product of parallel vectors is zero, so your torque impulse is zero.

This is correct; the collision shouldn't induce any angular change absent friction.

\$\endgroup\$
4
  • \$\begingroup\$ So, without friction forces, two spheres in collision doesn't rotate, right? \$\endgroup\$
    – RdlP
    Apr 21, 2017 at 15:11
  • \$\begingroup\$ That is correct. \$\endgroup\$ Apr 21, 2017 at 15:27
  • \$\begingroup\$ Where can I find information about how to implement fiction? \$\endgroup\$
    – RdlP
    Apr 21, 2017 at 18:31
  • \$\begingroup\$ You can do a search for rigid body friction impulse. Basically you find the relative velocity at the contact point and project that onto the contact normal's tangent (a line in 2D, plane in 3D), and scale it by a coefficient of friction, µ. You also clamp the frictional impulse so that its magnitude doesn't exceed F µ, where F is the magnitude of the collision impulse. \$\endgroup\$ Apr 21, 2017 at 18:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .