2012-10-17 1 views
0

OpenGL에서 피벗 위치를 고려하면서 Quaternion을 사용하여 행렬 회전을 수행하는 방법을 알아낼 수 없습니다. 현재 내가 얻는 것은 공간의 일부 지점을 중심으로 한 개체 회전입니다. 내가 원하는대로 로컬 피벗.쿼터니언 기반 회전 및 피벗 위치

public void rotateTo3(float xr, float yr, float zr) { 

    _rotation.x = xr; 
    _rotation.y = yr; 
    _rotation.z = zr; 

    Quaternion xrotQ = Glm.angleAxis((xr), Vec3.X_AXIS); 
    Quaternion yrotQ = Glm.angleAxis((yr), Vec3.Y_AXIS); 
    Quaternion zrotQ = Glm.angleAxis((zr), Vec3.Z_AXIS); 
    xrotQ = Glm.normalize(xrotQ); 
    yrotQ = Glm.normalize(yrotQ); 
    zrotQ = Glm.normalize(zrotQ); 

    Quaternion acumQuat; 
    acumQuat = Quaternion.mul(xrotQ, yrotQ); 
    acumQuat = Quaternion.mul(acumQuat, zrotQ); 



    Mat4 rotMat = Glm.matCast(acumQuat); 

    _model = new Mat4(1); 

    scaleTo(_scaleX, _scaleY, _scaleZ); 

    _model = Glm.translate(_model, new Vec3(_pivot.x, _pivot.y, 0)); 

    _model =rotMat.mul(_model);//_model.mul(rotMat); //rotMat.mul(_model); 

    _model = Glm.translate(_model, new Vec3(-_pivot.x, -_pivot.y, 0)); 


    translateTo(_x, _y, _z); 

    notifyTranformChange(); 
    } 

모델 매트릭스 스케일 방법 : 공개 공극이 scaleTo (플로트 X, Z 플로트, Y 플로트) {

_model.set(0, x); 
    _model.set(5, y); 
    _model.set(10, z); 

    _scaleX = x; 
    _scaleY = y; 
    _scaleZ = z; 

    notifyTranformChange(); 
    } 
여기 코드 [사용한 Java]

쿼터니언 회전 방법

번역 방법 : public void translateTo (float x, float y, float z) {

_x = x - _pivot.x; 
    _y = y - _pivot.y; 
    _z = z; 
    _position.x = _x; 
    _position.y = _y; 
    _position.z = _z; 

    _model.set(12, _x); 
    _model.set(13, _y); 
    _model.set(14, _z); 

    notifyTranformChange(); 
    } 

하지만 사원 수를 사용하지 않는 한이 방법은 잘 작동 :

public void rotate(Vec3 axis, float angleDegr) { 
    _rotation.add(axis.scale(angleDegr)); 
    // change to GLM: 
    Mat4 backTr = new Mat4(1.0f); 

    backTr = Glm.translate(backTr, new Vec3(_pivot.x, _pivot.y, 0)); 

    backTr = Glm.rotate(backTr, angleDegr, axis); 


    backTr = Glm.translate(backTr, new Vec3(-_pivot.x, -_pivot.y, 0)); 

    _model =_model.mul(backTr);///backTr.mul(_model); 
    notifyTranformChange(); 

    } 

답변

1

당신은 전과 회전 한 후 계정에 앞뒤로 번역을 이미. 왜 translateTo의 최종 호출?

또한 회전 할 때 순수 회전은 항상 원점을 의미합니다. 따라서 피벗 점을 중심으로 회전을 원한다면 피벗 포인트를 원점으로 변환 한 다음 회전 한 다음 피벗으로 다시 변환하는 것이 올바른 일일 것입니다. 따라서, 당신의 코드는 다음과 같이하는 기대 :

_model = Glm.translate(_model, new Vec3(-_pivot.x, -_pivot.y, 0)); 

_model =rotMat.mul(_model);//_model.mul(rotMat); //rotMat.mul(_model); 

_model = Glm.translate(_model, new Vec3(_pivot.x, _pivot.y, 0)); 

하고 통화 translateTo(_x, _y, _z);없이

합니다. 또한 회전 부분이 이미 예상 한대로 작동하는지 확인할 수 있습니까? rotMatGlm.rotate(new Mat4(1.0f), angleDegr, axis)을 비교하여 확인할 수 있습니다. 그들은 동일한 회전에 대해 동일해야합니다.

0

사원 수는 회전을 설명합니다. 결과적으로 쿼터니언 만 사용하여 어떻게 피벗 점을 중심으로 무언가를 회전 시키시겠습니까?

필요한 최소값은 R3 벡터와 쿼터니언입니다. 한 수준의 변형 만 있으면 먼저 객체를 roatate 한 다음 객체를 이동시킵니다.

매트릭스를 만들려면 우선 배급 매트릭스를 만든 다음 변형되지 않은 채 번역을 추가하십시오.

glTranslate와 glRotate (또는 glMultMatrix)를 호출하려면 먼저 glTranslate를 호출 한 다음 glRoatate를 호출해야합니다.

편집 :

당신은 렌더링 그냥 각 정점이 어디 있는지 알고 싶어하지 않는 경우 : 그것은 나에게 보인다

Vector3 newVertex = quat.transform(oldVertex) + translation; 
+0

나는 쿼터니온이 무엇인지 압니다. 또한 고정 파이프 라인을 사용하지 않습니다 :) –

+0

그러나 첫 번째 제안은 문제를 해결합니다. 내가 말했던 것처럼 변환 행렬을 계산하거나 각각의 모든 정점에 쿼터니온과 변환을 적용합니다. – rioki