在表面上移动的球的旋转

我有一个球沿平台移动。 球的特点是具有半径和位置的球体。 该平台基本上是由两个顶点三角形组成的矩形。 它的类也存储平台的正常。

当移动球和应用重力物理学不会造成问题,我只是不能让球体正确旋转。 为了表示旋转,我使用了Qt的QQuaternion类。

这是我目前的轮换代码:

QVector3D right = QVector3D::crossProduct(tile->getSurfaceNormal(), step).normalized(); QVector3D forward = QVector3D::crossProduct(right, tile->getSurfaceNormal()).normalized(); float radian = QVector3D::dotProduct((ball - position), forward) / radius; angularRate = ((radian / interval) * 180.0f / M_PI) * right; QQuaternion rotation(angularRate.length() * interval, angularRate); orientation = rotation * orientation; 

方向四元数是这样初始化的:

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

绘制球时,我更新模型matrix(QMatrix4x4),像这样:

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

我在debugging时注意到,最终的模型matrix在前三列中获得了NAN值。 我的计算中是否有任何物理缺陷,或者与模型matrix本身有关系吗?

如果这很重要,下面是更新球属性的完整代码:

 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(); if (aBallLength <= radius || aNormalBallLength <= radius) { 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(); float radian = QVector3D::dotProduct((ball - position), forward) / radius; 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(); } }