2014-12-11 4 views
1

표준 아크볼 회전을 사용하여 원점을 기준으로 메쉬를 회전하려고합니다. 3D 오브젝트를 클릭 할 때마다 마우스에서 광선을 캐스팅하여 교차점을 찾습니다. 마우스를 놓을 때까지 회전에서 "아크볼"로 사용될 구체를 만들기 위해 3D 오브젝트 원점에서 교차점까지의 거리를 측정합니다. 매 회전 시작시이 작업을 수행하는 이유는 클릭 한 점이 마우스 아래에 있기를 원하기 때문입니다. 객체가 올바르게 회전합니다. 회전 각도가 작아서 클릭 한 점이 마우스 아래에 있지 않습니다. 다음 예제는 큐브를 회전하려고합니다. 처음에 클릭 한 점을 추적하기 위해 텍스처에 검은 색 사각형을 칠합니다. 여기에 문제의 동영상입니다 :GLM : 회전 할 때 어떻게 마우스를 클릭 한 상태로 유지할 수 있습니까?

http://youtu.be/x8rsqq1Qdfo

이 마우스의 위치와 클릭 계산 구 (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); 

어떻게 클릭 한 지점을 마우스 아래에 둘 수 있습니까?

답변

2

클릭 한 점과 대상의 중심 사이의 거리로 arcball 반경을 설정하십시오. 다시 말해 첫 번째 지점은 입방체에있는 레이 캐스트이며 그 다음 지점은 물체를 중심으로 한 가상 구 및 위에 언급 한 반경으로 레이 캐스트됩니다.

P .: .: 체크 아웃 내 arcball rotation code on codereview.SE. 그것은 acos 및 축 각도로 엉망이 아니며 두 번만 정상화됩니다.

+0

저는 이미 이것을하고 있습니다. 첫 번째 단계는 arcballRadius 변수 (교차점과 큐브 중심 사이의 거리)를 설정하는 레이 캐스트입니다. 링크 한 arcball 회전 코드는 클릭 한 점을 마우스 아래에 유지합니까? – Jubei

+0

@ Jubei 그것은 arcball 코드를 작동하고 있는데, 이는 축 각도 접근법보다 약간 효율적입니다 (나는 그것을 막고 싶습니다) –