WebGLに関する同様の質問:オブジェクトをワールド軸を中心に回転させます。
ユーザーがドラッグしているように、マウスでオブジェクトを移動できるようにオブジェクトを回転させる必要があります。問題はglRotatef
、オブジェクトの向きを考慮せずにオブジェクトを回転させるだけであるということです。WebGLの場合、解決策はクォータニオンを使用することでしたが、OpenGLにはクォータニオンがないようです。
これが私が今のところローテーションを達成する方法です:
// rotation 2D GLfloat C-vector, posX, posY GLfloat's
void mouse(int button, int state, int x, int y) {
if(button== GLUT_LEFT_BUTTON) {
if(state== GLUT_DOWN)
{
posX=x;
posY= y;
onEvent= true;
}
else if(state== GLUT_UP)
{
GLfloat dx= x-posX;
GLfloat dy= y-posY;
rotation[0]= -dy/5;
rotation[1]= dx/5;
onEvent= false;
glutPostRedisplay();
}
}
}
次に、表示機能で回転を処理します。
glPushMatrix();
glRotatef(rotation[0],1,0,0);
glRotatef(rotation[1],0,1,0);
// Draw the object
glPopMatrix();
それはちょっと動作しますが、私が言ったように、ユーザーがオブジェクトをドラッグして回転できるかどうかがいいはずです。代わりに、たとえばオブジェクトがX軸を中心に90度回転した場合、ユーザーがマウスを水平方向にドラッグしてY軸を中心に回転させると、オブジェクトは逆方向に回転します。私はここでアイデアが必要です、どうすればそれを行うことができますか?
編集
を使用しようとしましたglMultMatrixf
が、オブジェクトが正しく回転しません。回転する代わりにスケーリングされます。これは、マウス関数で編集したコードです。
// Global variables:
// GLfloat xRotationMatrix[4][4];
// GLfloat yRotationMatrix[4][4];
else if(state== GLUT_UP && onEvent)
{
GLfloat dx= (x-posX)/(180.0*5)*2.0*M_PI;
GLfloat dy= (y-posY)/(180.0*5)*2.0*M_PI;
// Computing rotations
double cosX= cos(dx);
double sinX= sin(dy);
double cosY= cos(dy);
double sinY= sin(dy);
// x axis rotation
xRotationMatrix[1][1]+= cosY;
xRotationMatrix[1][2]+=-sinY;
xRotationMatrix[2][2]+= sinY;
xRotationMatrix[2][2]+= cosY;
// y axis rotation
yRotationMatrix[0][0]+= cosX;
yRotationMatrix[0][2]+= sinX;
yRotationMatrix[2][0]+= -sinX;
yRotationMatrix[2][2]+= cosX;
onEvent= false;
glutPostRedisplay();
}
次に、表示機能で:
glPushMatrix();
glMultMatrixf((const GLfloat*)xRotationMatrix);
glMultMatrixf((const GLfloat*)yRotationMatrix);
glutSolidTeapot(10);
glPopMatrix();
これは回転していないティーポットです。
マウスを水平方向にドラッグしてティーポットをy軸を中心に回転させると、回転ではなく、次のようになります。
First of all a bit of algebra. Let v be a vector, M your current modelview matrix, and R the matrix associated with a glRotate
command. Then, if you use glRotate
, what you get is:
M * R * v
That means you are rotating around object axes. You want to rotate around the world axes, that is:
R * M * v
See the difference? Unfortunately GL doesn't have a MatrixPreMult
function.
In modern OpenGL we don't use the matrix stack anymore, in fact while working with shaders we manually pass the transformation matrices to the GL program. What (most) people do is write/use an external vector algebra library (like Eigen).
One possible (untested) workaround which uses only the old deprecated GL stuffs may be something like this:
void rotate(float dx, float dy)
{
//assuming that GL_MATRIX_MODE is GL_MODELVIEW
float oldMatrix[4][4];
glGetFloatv(GL_MODELVIEW_MATRIX,oldMatrix);
glLoadIdentity();
glRotatef(-dy,1,0,0);
glRotatef(dx,0,1,0);
glMultMatrixf(oldMatrix);
}
And you put this code in your mouse
function, not in the draw routine. You can use this trick by keeping the view matrix in the GL matrix stack, then pushing/popping everytime you have to draw an object. I wouldn't recommend something like that in a large project.
glRotate
上記のコードで2つの呼び出しの順序を逆にすると、特にdxとdyが小さくない場合に、わずかに異なる結果が得られる可能性があることにも注意してください。このコードは少し良いかもしれません:
float angle = sqrt(dx*dx+dy*dy)*scalingFactor;
glRotate(angle,-dy,dx,0);
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加