標準のアークボール回転を使用して、メッシュをその原点を中心に回転させようとしています。3D オブジェクトをクリックするたびに、マウスからレイをキャストして交点を見つけます。3D オブジェクトの原点から交点までの距離を測定して、その回転で「アークボール」として使用される球を作成します (マウスが離されるまで)。すべての回転の開始時にこれを行う理由は、クリックしたポイントをマウスの下に残しておきたいからです。オブジェクトは正しく回転します。回転の大きさが小さくなり、その結果、クリックしたポイントがマウスの下に残りません。次の例では、立方体を回転させようとしています。最初にクリックしたポイントを追跡するために、テクスチャに黒い四角形をペイントします。問題のビデオは次のとおりです。
これは、マウスの位置とクリック時に計算された球の半径 (arcballRadius) に基づいてアークボール ベクトルを取得する関数です (立方体オブジェクトの位置が考慮されていないのが心配です。オブジェクトは (0,0,z) にあります:
/**
* Get a normalized vector from the center of the virtual ball O to a
* point P on the virtual ball surface, such that P is aligned on
* screen's (X,Y) coordinates. If (X,Y) is too far away from the
* sphere, return the nearest point on the virtual ball surface.
*/
glm::vec3 get_arcball_vector(double x, double y) {
glm::vec3 P = glm::vec3(x,y,0);
float OP_squared = P.x * P.x + P.y * P.y;
if (OP_squared <= arcballRadius*arcballRadius)
P.z = sqrt(arcballRadius*arcballRadius - OP_squared); // Pythagore
else
{
static int i;
std::cout << i++ << "Nearest point" << std::endl;
P = glm::normalize(P); // nearest point
}
return P;
}
マウスを動かすたびに
//get two vectors, one for the previous point and one for the current point
glm::vec3 va = glm::normalize(get_arcball_vector(prevMousePos.x, prevMousePos.y)); //previous point
glm::vec3 vb = glm::normalize(get_arcball_vector(mousePos.x, mousePos.y)); //current point
float angle = acos(glm::dot(va, vb)); //angle between those two vectors based on dot product
//since these axes are in camera coordinates they must be converted before applied to the object
glm::vec3 axis_in_camera_coord = glm::cross(va, vb);
glm::mat3 camera2object = glm::inverse(glm::mat3(viewMatrix) * glm::mat3(cube.modelMatrix));
glm::vec3 axis_in_object_coord = camera2object * axis_in_camera_coord;
//apply rotation to cube's matrix
cube.modelMatrix = glm::rotate(cube.modelMatrix, angle, axis_in_object_coord);
クリックしたポイントをマウスの下に残すにはどうすればよいですか?