bool RaySphereTest(const M3DVector3f point, const M3DVector3f ray, const M3DVector3f sphereCenter, float sphereRadius) { //m3dNormalizeVectorf(ray); // Make sure ray is unit length M3DVector3f rayToCenter; // Ray to center of sphere rayToCenter[0] = sphereCenter[0] - point[0]; rayToCenter[1] = sphereCenter[1] - point[1]; rayToCenter[2] = sphereCenter[2] - point[2]; // Project rayToCenter on ray to test float a = m3dDotProduct3(rayToCenter, ray); // Distance to center of sphere float distance2 = m3dDotProduct3(rayToCenter, rayToCenter); // Or length float dRet = (sphereRadius * sphereRadius) - distance2 + (a*a); if(dRet > 0.0) // Return distance to intersection return true; dRet = a - sqrtf(dRet); return false; }
/////////////////////////////////////////////////////////////////////////////// // Determine if the ray (starting at point) intersects the sphere centered at // sphereCenter with radius sphereRadius // Return value is < 0 if the ray does not intersect // Return value is 0.0 if ray is tangent // Positive value is distance to the intersection point // Algorithm from "3D Math Primer for Graphics and Game Development" double m3dRaySphereTest(const M3DVector3d point, const M3DVector3d ray, const M3DVector3d sphereCenter, double sphereRadius) { //m3dNormalizeVector(ray); // Make sure ray is unit length M3DVector3d rayToCenter; // Ray to center of sphere rayToCenter[0] = sphereCenter[0] - point[0]; rayToCenter[1] = sphereCenter[1] - point[1]; rayToCenter[2] = sphereCenter[2] - point[2]; // Project rayToCenter on ray to test double a = m3dDotProduct3(rayToCenter, ray); // Distance to center of sphere double distance2 = m3dDotProduct3(rayToCenter, rayToCenter); // Or length double dRet = (sphereRadius * sphereRadius) - distance2 + (a*a); if(dRet > 0.0) // Return distance to intersection dRet = a - sqrt(dRet); return dRet; }
// ditto above... but with floats float m3dClosestPointOnRay(M3DVector3f vPointOnRay, const M3DVector3f vRayOrigin, const M3DVector3f vUnitRayDir, const M3DVector3f vPointInSpace) { M3DVector3f v; m3dSubtractVectors3(v, vPointInSpace, vRayOrigin); float t = m3dDotProduct3(vUnitRayDir, v); // This is the point on the ray vPointOnRay[0] = vRayOrigin[0] + (t * vUnitRayDir[0]); vPointOnRay[1] = vRayOrigin[1] + (t * vUnitRayDir[1]); vPointOnRay[2] = vRayOrigin[2] + (t * vUnitRayDir[2]); return m3dGetDistanceSquared3(vPointOnRay, vPointInSpace); }
void MouseMoveEvent(int x, int y) { if (isStartTrackBall) { GLfloat theta; M3DVector3f p1, p2, n; int width = glutGet(GLUT_WINDOW_WIDTH); int height = glutGet(GLUT_WINDOW_HEIGHT); MousePtToSphereVec(p1, mMouseX, mMouseY, width, height); MousePtToSphereVec(p2, x, y, width, height); mMouseX = x; mMouseY = y; m3dNormalizeVector3(p1); m3dNormalizeVector3(p2); theta = acos(m3dDotProduct3(p1, p2)) ; //theta = m3dGetAngleBetweenVectors3(p1, p2); m3dCrossProduct3(n, p1, p2); m3dNormalizeVector3(n); M3DMatrix44f tempRotation; m3dLoadIdentity44(tempRotation); GLfloat dis = m3dGetDistance3(p1, p2); if (dis != 0.0f) { m3dRotationMatrix44(tempRotation, theta, m3dGetVectorX(n), m3dGetVectorY(n), m3dGetVectorZ(n)); } m3dMatrixMultiply44(mRotation, tempRotation, mRotation); glutPostRedisplay(); } }