# Rotation of a ball moving on a surface

I have a ball that moves along a platform. The ball is characterized as a sphere that has a radius and a position. The platform basically is a rectangle consisting of two vertex triangles. Its class also stores the normal of the platform.

While moving the ball and applying the physics of gravity doesn't pose a problem, I just can't get the sphere to rotate correctly. To represent the rotation(s) I'm using Qt's QQuaternion class.

Here's my current rotation code:

QVector3D right = QVector3D::crossProduct(tile->getSurfaceNormal(), step).normalized();
QVector3D forward = QVector3D::crossProduct(right, tile->getSurfaceNormal()).normalized();

angularRate = ((radian / interval) * 180.0f / M_PI) * right;

QQuaternion rotation(angularRate.length() * interval, angularRate);
orientation = rotation * orientation;


The orientation quaternion is initialized like this:

orientation = QQuaternion(0.0f, QVector3D(0.0f, 0.0f, 1.0f));

When drawing the ball I update the model matrix (QMatrix4x4) like this:

    modelMatrix.setToIdentity();
modelMatrix.translate(position.x(), position.y(), position.z());
modelMatrix.rotate(orientation);


What I noticed when debugging is that the final model matrix gets NAN values in the first three columns. Is there any physical flaw in my calculation or could it have to do with the model matrix itself?

If that's important, here's the full code for updating the ball's properties:

void Ball::update(float interval) {
collision = false;

// Calculate new velocity
velocity += (MOVE_FORCE / mass * interval) * pushDirection;
velocity.setY(velocity.y() - (GRAVITY * interval));

/* Collision detection */
QVector3D normal(0.0f, 0.0f, 0.0f);
QVector3D step = interval * velocity;
QVector3D ball = position + step;

// Check all tiles for collision with ball
for (unsigned int i = 0; i < tiles->length(); i++) {
Tile *tile = tiles->at(i);
QVector<QVector3D> mainVertices = tile->getVertices();

QVector3D a1 = VectorMath::closestPointOnTriangle(ball, mainVertices[0], mainVertices[1], mainVertices[2]);
QVector3D a2 = VectorMath::closestPointOnTriangle(ball, mainVertices[2], mainVertices[3], mainVertices[0]);

float d1 = (ball - a1).length();
float d2 = (ball - a2).length();

QVector3D a = (d1 <= d2) ? a1 : a2;
QVector3D aN = a - tile->getAdjustedSurfaceNormal();

float aBallLength = (a - ball).length();
float aNormalBallLength = (aN - ball).length();

QVector3D distance = (aBallLength <= aNormalBallLength) ? a - ball : aN - ball;
float l = distance.length();

QVector3D move = -((radius - l) / l) * distance;

// Rotation
QVector3D right = QVector3D::crossProduct(tile->getSurfaceNormal(), step).normalized();
QVector3D forward = QVector3D::crossProduct(right, tile->getSurfaceNormal()).normalized();

angularRate = ((radian / interval) * 180.0f / M_PI) * right;

ball += move;
normal += move;

collision = true;
}
}

// Set new ball position
position = ball;

normal.normalize();

// Applying rebound
if (collision) {
float velocityNormal = QVector3D::dotProduct(velocity, normal);
QVector3D rebound = (-(1 + ELASTICITY) * velocityNormal) * normal;

velocity += rebound;
}

// Damping
velocity *= DAMPING;

QQuaternion rotation(angularRate.length() * interval, angularRate);
orientation = orientation * rotation;

if (position.y() < -10.0f) {
reset();
}
}

• You should step through the code and see where the NaNs are coming from. My first guess would be a degenerate quaternion (aka all 0s), but there can be other ways to get it in there. If any of the values you're passing in are NaNs, that will cause NaNs to show up in the matrix. So if position, orientation, or scale contain a NaN, so will the matrix. – user1118321 Oct 18 '17 at 5:29