OPENGL カメラの回転でうまくいきません

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
matrix

OPENGL カメラの回転でうまくいきません

#1

投稿記事 by matrix » 11年前

私はVS2013のC++で開発しているのですが、
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;

}

旅路のきのこ

Re: OPENGL カメラの回転でうまくいきません

#2

投稿記事 by 旅路のきのこ » 11年前

よく分かりませんが、何となく気になって色々やっているとできました。

motionのところで考えて欲しいのですが、マウスが結構外側寄りにあるときdistXはどう変化するでしょうか?
プログラムの流れからいくと、distXの値は、motionが新たに呼ばれたときも前回更新されたままです。
そこで実行されるのがdistX += ...です。
+1とかならいいのですが、増える量はマウスの座標なので結構な量です。
一フレーム後にはたとえば90度回転した視野が広がっていることになってしまいます。つまり、そのためにもの凄い高速回転をしてしまうということです。
distX = ...に直すといいんじゃないでしょうか。

こういう間違いがいくつかありました。
distX , distY , rotmat , xmat , ymat , lookat , up
この辺は、motionが呼ばれるたびに、正しい値になるように書いてください。

3D座標をディスプレイの座標に変換する行列も、どうやら保存されっぱなしになるようです。(これは仕様?)
ということでmotionの中で変換行列を改めて設定するようにしました。
glLoadIdentity() ; gluPerspective(80.0 , 640.0/480.0 , 0.0 , 10000.0);
こんな風に。

その他、ケアレスミスのようなものだとは思いますが、gluLookAtの中で、x , y , zと並べるべきところがx , y , yとなっていますよ。



いやー、でも中学生で行列なんて偉いですね。
頑張ってください。

matrix

Re: OPENGL カメラの回転でうまくいきません

#3

投稿記事 by matrix » 11年前

旅路のきのこさん、返信ありがとうございます。
アドバイスの元、コードを下記のように修正したところ、良い動きができました。
ありがとうございます。
ですが、またもう一つの問題に気づいてしまいました。カメラの回転の事ですのでこのトピックで質問させていただきます。
distYをdistY = のような形に変えると、真上、真下を見れないように(ぐるぐる回転しないように)133,134行で制限をかけていたのですが、distYの値は小さいためぐるぐる回れるようになってしまいます。
図々しいことですが、ぐるぐる回転しないようにするためのアドバイスを、教えて頂きたいです。

コード:

#include <iostream>
#define _USE_MATH_DEFINES
#include <math.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)

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(0.5);
	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);
		distY = (yPos - WND_Y / 2);

		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);

		glLoadIdentity(); gluPerspective(80.0, 640.0 / 480.0, 0.0, 10000.0);
		gluLookAt(0.0, 0.0, 0.0,
			LOOKAT.x, LOOKAT.y, LOOKAT.z,
			0.0, UP.y, UP.z);

		std::cout << UP.x << std::endl;
		std::cout << UP.y << std::endl;
		std::cout << UP.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;

}

旅路のきのこ

Re: OPENGL カメラの回転でうまくいきません

#4

投稿記事 by 旅路のきのこ » 11年前

ちょっと何か手違いでもあったんでしょうか、新しいコードも神速で動いてしまいます。
GetIdentity(&rotmat) ; GetIdentity(&xmat) ; GetIdentity(&ymat) ;
これを134行目の前にでも入れてくれれば動くと思います。
というか僕の方も、lookat , upに関して勝手な勘違いをしてしまっていたようですね。

matrix さんが書きました:distYをdistY = のような形に変えると、真上、真下を見れないように(ぐるぐる回転しないように)133,134行で制限をかけていたのですが、distYの値は小さいためぐるぐる回れるようになってしまいます。
その133,134行というのは、前のコードのこれでしょうか?

コード:

     distX += (xPos - WND_X / 2) / 2 ;
     distY += (yPos - WND_Y / 2) / 2 ; 
 
新しいコードでは最後の"/2"がないので変化が大きくなって困っているということですか?

コード:

// 新しいコード
     distX = -(xPos - WND_X / 2);
     distY = (yPos - WND_Y / 2); 
 
まあ、前と同じように適当な数値で割ったらいいのかもしれません。
また勘違いしてたらごめんなさい。

matrix

Re: OPENGL カメラの回転でうまくいきません

#5

投稿記事 by matrix » 11年前

すいません、行の指定が間違っていました。
正しくは一番最初のコードの136,137行目です。

コード:

        if (distY <-250) distY = -250;
        if (distY > 250) distY = 250;
↑の事です。
何ででしょうか、2つめのコードで動かしても普通に動くようです。
↑のコードはXの回転軸が真上、真下から後ろには動かないように、としたコードでした。
DXLibから移植したものだったので、どこかで手違いが生じたんだと思いますが・・

matrix

Re: OPENGL カメラの回転でうまくいきません

#6

投稿記事 by matrix » 11年前

ちなみに、視点の回転の部分について参考にしたのはこのサイトのこのトピックです。
http://dixq.net/forum/viewtopic.php?f=3&t=12461#p100187

旅路のきのこ

Re: OPENGL カメラの回転でうまくいきません

#7

投稿記事 by 旅路のきのこ » 11年前

ああ、そっちでしたか。
まあ、そういう場合はあえて奇天烈な数値で試してみると、ああこういうことか、と納得できることもありますよ。
if (distY <-50) distY = -50;// こんな風に


ただ、どういうことかというと、これです、これ。これを見てください。

コード:

 getRotMatX(distY * M_PI * 2 / 1000, &xmat);
これでどれだけ回転するかというのを決める行列を設定しているわけですよね。
で、現在数学がどれくらいまで進んでいるのかわからないので、一応書いて見ます。

円をぐるっと一周したら、中心の周りを360度回転したことになりますが、同じことを別のやり方で表現できます。
その一つがラジアン単位を使うというもので、360度とは2π、つまり円周率の二倍にあたります。
360度 = 2 * 3.1415...なわけです。

上の関数の引数にdistY * M_PI * 2 / 1000とあります。
これはつまり(distY / 1000.0) * (2 * M_PI)なので、(2*M_PI)が一周であることを考えれば(distY / 1000.0)周するということを意味すると分かります。
distYというのはスクリーンの中央からの距離を表していたと思うので、つまり中心から1000ピクセル離れると一周することになります。
今回のように250までで制限していれば四分の一周。つまり真上と真下までです。

ところで、このプログラムだと、ウィンドウの高さは480しかありません。
ということはウィンドウの一番外側までやってきても240にしかならないので動作には変わりがないのだと思います。
(振り返ってみれば、そうするように仕向けたのは僕自身のような気もします。)

matrix

Re: OPENGL カメラの回転でうまくいきません

#8

投稿記事 by matrix » 11年前

解説ありがとうございました。
ですが、また1つ問題がありました。
横を向いて上を向こうとすると、視点が傾き向けません。
また、後ろを向いて上下を向こうとすると、上下が逆になっています。
夜分遅くに申し訳ないのですが、この件についてアドバイス願えませんか。

・・・と質問しようと思ったのですが、行列の計算順を変えたところ、正常に動作しました。
旅路のきのこさん、本当にありがとうございました。
↓は完成したコードです。

コード:

#include <iostream>
#define _USE_MATH_DEFINES
#include <math.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)

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 pos = POS;
	static VECTOR4 lookat = LOOKAT;
	static VECTOR4 up = UP;

	static bool wrap = false;
	if (!wrap) {

		distX += -(xPos - WND_X / 2);
		distY += (yPos - WND_Y / 2);

		if (distY <-250) distY = -250;
		if (distY > 250) distY = 250;

		GetIdentity(&rotmat); GetIdentity(&xmat); GetIdentity(&ymat);
		getRotMatX(distY * M_PI * 2 / 1000, &xmat);
		mulMatrix(&rotmat,&xmat, &rotmat);
		getRotMatY(distX * M_PI * 2 / 1000, &ymat);
		mulMatrix(&rotmat, &ymat, &rotmat);

		mulMatrixVec(&POS, &rotmat, &pos);
		mulMatrixVec(&LOOKAT, &rotmat, &lookat);
		mulMatrixVec(&UP, &rotmat, &up);

		glLoadIdentity(); gluPerspective(80.0, 640.0 / 480.0, 0.0, 10000.0);
		gluLookAt(0.0, 0.0, 0.0,
			LOOKAT.x, LOOKAT.y, LOOKAT.z,
			UP.x, UP.y, UP.z
		);

		std::cout << UP.x << std::endl;
		std::cout << UP.y << std::endl;
		std::cout << UP.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;

}
これにて解決とさせていただきます。

閉鎖

“C言語何でも質問掲示板” へ戻る