OPENGL カメラの回転でうまくいきません
Posted: 2014年7月21日(月) 23:26
私はVS2013のC++で開発しているのですが、
FPSゲームのようにカメラの回転をするべく、様々なサンプルを参考にコードを組みました。
しかし、下記のコードでは、高速に回転し、マウスを動かした方向に回転していないように見えます。
どのように改善すれば、適当な速さで、マウスを動かした方向に回転するコードが出来るでしょうか。
ヒントを教えてください。私は中学生で行列やベクトル、三角関数への理解が足らない部分もあるので、おかしい部分があれば指摘して頂きたいです。
FPSゲームのようにカメラの回転をするべく、様々なサンプルを参考にコードを組みました。
しかし、下記のコードでは、高速に回転し、マウスを動かした方向に回転していないように見えます。
どのように改善すれば、適当な速さで、マウスを動かした方向に回転するコードが出来るでしょうか。
ヒントを教えてください。私は中学生で行列やベクトル、三角関数への理解が足らない部分もあるので、おかしい部分があれば指摘して頂きたいです。
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <Windows.h>
#include <GL/freeglut.h>
#define DISP_X glutGet(GLUT_SCREEN_WIDTH)
#define DISP_Y glutGet(GLUT_SCREEN_HEIGHT)
#define WND_X glutGet(GLUT_WINDOW_WIDTH)
#define WND_Y glutGet(GLUT_WINDOW_HEIGHT)
#define M_PI 3.14159265359
static int distX = 0;
static int distY = 0;
typedef struct {
float x, y, z, w;
} VECTOR4;
typedef struct{
double m[16];
}MATRIX;
MATRIX rotmat,xmat,ymat;
static VECTOR4 POS = { 0.0, 0.0, 0.0, 1.0 };
static VECTOR4 LOOKAT = { 0.0, 0.0, 100.0, 1.0 };
static VECTOR4 UP = { 0.0, 1.0, 0.0, 1.0 };
void getRotMatX(double radian, MATRIX mat[])
{
mat->m[5] = cos(radian);
mat->m[6] = sin(radian);
mat->m[9] = -sin(radian);
mat->m[10] = cos(radian);
}
void getRotMatY(double radian, MATRIX mat[])
{
mat->m[0] = cos(radian);
mat->m[2] = -sin(radian);
mat->m[8] = sin(radian);
mat->m[10] = cos(radian);
}
void mulMatrix(MATRIX *r, MATRIX *a, MATRIX *b)
{
float a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15;
float b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15;
a0 = a->m[0]; a1 = a->m[1]; a2 = a->m[2]; a3 = a->m[3];
a4 = a->m[4]; a5 = a->m[5]; a6 = a->m[6]; a7 = a->m[7];
a8 = a->m[8]; a9 = a->m[9]; a10 = a->m[10]; a11 = a->m[11];
a12 = a->m[12]; a13 = a->m[13]; a14 = a->m[14]; a15 = a->m[15];
b0 = b->m[0]; b1 = b->m[1]; b2 = b->m[2]; b3 = b->m[3];
b4 = b->m[4]; b5 = b->m[5]; b6 = b->m[6]; b7 = b->m[7];
b8 = b->m[8]; b9 = b->m[9]; b10 = b->m[10]; b11 = b->m[11];
b12 = b->m[12]; b13 = b->m[13]; b14 = b->m[14]; b15 = b->m[15];
r->m[0] = a0 * b0 + a4 * b1 + a8 * b2 + a12 * b3;
r->m[1] = a1 * b0 + a5 * b1 + a9 * b2 + a13 * b3;
r->m[2] = a2 * b0 + a6 * b1 + a10 * b2 + a14 * b3;
r->m[3] = a3 * b0 + a7 * b1 + a11 * b2 + a15 * b3;
r->m[4] = a0 * b4 + a4 * b5 + a8 * b6 + a12 * b7;
r->m[5] = a1 * b4 + a5 * b5 + a9 * b6 + a13 * b7;
r->m[6] = a2 * b4 + a6 * b5 + a10 * b6 + a14 * b7;
r->m[7] = a3 * b4 + a7 * b5 + a11 * b6 + a15 * b7;
r->m[8] = a0 * b8 + a4 * b9 + a8 * b10 + a12 * b11;
r->m[9] = a1 * b8 + a5 * b9 + a9 * b10 + a13 * b11;
r->m[10] = a2 * b8 + a6 * b9 + a10 * b10 + a14 * b11;
r->m[11] = a3 * b8 + a7 * b9 + a11 * b10 + a15 * b11;
r->m[12] = a0 * b12 + a4 * b13 + a8 * b14 + a12 * b15;
r->m[13] = a1 * b12 + a5 * b13 + a9 * b14 + a13 * b15;
r->m[14] = a2 * b12 + a6 * b13 + a10 * b14 + a14 * b15;
r->m[15] = a3 * b12 + a7 * b13 + a11 * b14 + a15 * b15;
}
void mulMatrixVec(VECTOR4 *r, MATRIX *a, VECTOR4 *b)
{
float b0, b1, b2, b3;
b0 = b->x; b1 = b->y; b2 = b->z; b3 = b->w;
r->x = a->m[0] * b0 + a->m[4] * b1 + a->m[8] * b2 + a->m[12] * b3;
r->y = a->m[1] * b0 + a->m[5] * b1 + a->m[9] * b2 + a->m[13] * b3;
r->z = a->m[2] * b0 + a->m[6] * b1 + a->m[10] * b2 + a->m[14] * b3;
r->w = a->m[3] * b0 + a->m[7] * b1 + a->m[11] * b2 + a->m[15] * b3;
}
void GetIdentity(MATRIX *mat)
{
for (int i = 0; i < 16; i++)
{
switch (i)
{
case 0:
case 5:
case 10:
case 15:
mat->m[i] = 1.0;
break;
default:
mat->m[i]= 0.0;
}
}
}
void disp(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glutWireCube(2.0);
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key){
case '\033':
exit(0);
default:
break;
}
}
void motion(int xPos, int yPos)
{
static VECTOR4 lookat = LOOKAT;
static VECTOR4 up = UP;
static bool wrap = false;
if (!wrap) {
distX += (xPos - WND_X / 2) / 2 ;
distY += (yPos - WND_Y / 2) / 2 ;
if (distY <-250) distY = -250;
if (distY > 250) distY = 250;
getRotMatX(distY * M_PI * 2 / 1000, &xmat);
mulMatrix(&rotmat, &rotmat, &xmat);
getRotMatY(distX * M_PI * 2 / 1000, &ymat);
mulMatrix(&rotmat, &rotmat, &ymat);
mulMatrixVec(&LOOKAT, &rotmat, &lookat);
mulMatrixVec(&UP, &rotmat, &up);
gluLookAt(.0, 0.0, 0.0,
LOOKAT.x, LOOKAT.y, LOOKAT.y,
UP.x, UP.y, UP.y);
std::cout << distX << std::endl;
std::cout << distY << std::endl;
std::cout << LOOKAT.z << std::endl;
glutPostRedisplay();
glutWarpPointer(WND_X / 2, WND_Y / 2);
wrap = true;
}
else {
wrap = false;
}
}
void init(void)
{
HWND hWnd;
LONG lStyle;
glutInitWindowPosition(DISP_X / 2, DISP_Y / 2);
glutInitWindowSize(640, 480);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutCreateWindow("OpenGL test");
hWnd = FindWindow(NULL, "OpenGL test");
lStyle = GetWindowLong(hWnd, GWL_STYLE);
lStyle &= ~WS_THICKFRAME & ~WS_MAXIMIZEBOX;
lStyle = SetWindowLong(hWnd, GWL_STYLE, lStyle);
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED));
GetIdentity(&rotmat);
GetIdentity(&xmat);
GetIdentity(&ymat);
gluPerspective(80.0, 640.0 / 480.0, 0.0, 10000.0);
glutDisplayFunc(disp);
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(motion);
glutMainLoop();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
init();
return 0;
}