OpenGLでAABB

AABB

操作方法は昨日と同じです。
 
AABBは頂点の最小値と最大値を引っ張ってきて、
比較するだけなので、判定処理は簡単ですね。
 
むしろ、箱を表示するのに手間がかかりました…(´∀`;

#include <math.h>
#include <string>
#include <iostream>
#include <glut.h>
#include <ctype.h>

using namespace std;

/**
 * 3次元ベクトル構造体
 */
struct Vec3
{
	float x, y, z;
	Vec3(float x=0, float y=0, float z=0){this->x=x; this->y=y; this->z=z;}
	Vec3 operator +(Vec3 &vec)           {return Vec3(this->x+vec.x, this->y+vec.y, this->z+vec.z);}
	Vec3 operator -(Vec3 &vec)           {return Vec3(this->x-vec.x, this->y-vec.y, this->z-vec.z);}
	Vec3 operator *(float f)             {return Vec3(this->x*f, this->y*f, this->z*f);}
	Vec3 operator /(float f)             {return Vec3(this->x/f, this->y/f, this->z/f);}
	Vec3 operator =(Vec3 &vec)           {return Vec3(this->x=vec.x, this->y=vec.y, this->z=vec.z);}
	Vec3 operator ==(Vec3 &vec)          {return (this->x==vec.x && this->y==vec.y && this->z==vec.z);}
	Vec3 operator !=(Vec3 &vec)          {return (this->x!=vec.x || this->y!=vec.y || this->z!=vec.z);}
	void Set(float x, float y, float z)  {this->x=x; this->y=y; this->z=z;}
	// スカラの二乗を求める
	float LengthSq() {return x*x + y*y + z*z;}
	// スカラ
	float Length() {return sqrt(LengthSq());}
	// 正規化
	Vec3 Normalize() {
		float m = LengthSq();
		if (m > 0.0f) m = 1.0f / m;
		else          m = 0.0f;
		return Vec3(x*m, y*m, z*m);
	}
	// 内積
	float Dot(Vec3 &vec)
	{
		return (this->x*vec.x + this->y*vec.y + this->z*vec.z);
	}
	// 外積
	Vec3 Cross(Vec3 &vec)
	{
		return Vec3(
			this->y*vec.z - this->z*vec.y,
			this->z*vec.x - this->x*vec.z,
			this->x*vec.y - this->y*vec.x);
	}
	string Debug()
	{
		char tmp[256];
		sprintf(tmp, "(x,y,z)=(%f,%f,%f", x, y, z);
		string ret = tmp;
		return ret;
	}
};

/**
 * 箱構造体
 */
struct TCube
{
	Vec3 pos;    // 中心座標
	Vec3 radius; // 半径
	Vec3 rot;    // 回転角度
	Vec3 GetMinVec3()
	{
		return Vec3(
			pos.x-radius.x,
			pos.y-radius.y,
			pos.z-radius.z);
	}
	Vec3 GetMaxVec3()
	{
		return Vec3(
			pos.x+radius.x,
			pos.y+radius.y,
			pos.z+radius.z);
	}
};

// 境界箱(AABB)による当たり判定
bool IsCollideBoxAABB(Vec3 vMin1, Vec3 vMax1, Vec3 vMin2, Vec3 vMax2)
{
	if(    vMin1.x < vMax2.x && vMax1.x > vMin2.x
		&& vMin1.y < vMax2.y && vMax1.y > vMin2.y
		&& vMin1.z < vMax2.z && vMax1.z > vMin2.z)
	{
		return true;
	}
	return false;
}

/**
 * 箱の描画
 */
void DrawCube(Vec3 pos, Vec3 radius, Vec3 rot, int color)
{
	// シーンの描画
	static GLfloat red[]   = { 0.8, 0.2, 0.2, 1.0 };
	static GLfloat gleen[] = { 0.2, 0.8, 0.2, 1.0 };
	static GLfloat blue[]  = { 0.2, 0.2, 0.8, 1.0 };
	GLfloat *c;
	if(color == 0)      c = red;
	else if(color == 1) c = gleen;
	else                c = blue;

	// 陰影付けをONにする
	glEnable(GL_LIGHTING);
	// 球描画
	glPushMatrix();
	{
		glTranslatef(pos.x, pos.y, pos.z);
		glRotatef(rot.x, 1, 0, 0);
		glRotatef(rot.y, 0, 1, 0);
		glRotatef(rot.z, 0, 0, 1);
		glScaled(radius.x*2, radius.y*2, radius.z*2);
		glMaterialfv(GL_FRONT, GL_DIFFUSE, c);
		glutSolidCube(1);
	}
	glPopMatrix();
	// 陰影付けをOFFにする
	glDisable(GL_LIGHTING);
}

TCube self;   // 箱1(コイツが動く)
TCube target; // 箱2(コイツは動かない)

Vec3 vEye;    // カメラ座標

/**
 * 初期化
 */
void Init(void)
{
	// 初期設定
	glClearColor(0.0, 0.0, 1.0, 0.0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_LIGHT0);

	// 箱を作る
	self.pos      = Vec3(1, 0, 0);
	self.radius   = Vec3(0.5f, 0.5f*2, 0.5f);
	self.rot      = Vec3(0, 0, 0);
	target.pos    = Vec3(0, 0, 0);
	target.radius = Vec3(0.5f, 0.5f, 0.5f*2);
	target.rot    = Vec3(0, 0, 0);

	// カメラ座標初期化
	vEye    = Vec3(0, 0, -5);
}

/**
 * キーが押されたときの処理
 * @param key  押下キー
 * @param x, y 座標
 */
void InputKey(unsigned char key, int x, int y)
{
	// 動かす
	float mov = 0.1f;
	float rot = 1;
	switch(toupper(key))
	{
	case 'Z':
		self.pos.x -= mov;
		break;
	case 'X':
		self.pos.x += mov;
		break;
	case 'A':
		self.pos.y -= mov;
		break;
	case 'S':
		self.pos.y += mov;
		break;
	case 'Q':
		self.pos.z -= mov;
		break;
	case 'W':
		self.pos.z += mov;
		break;
	case 'C':
		self.rot.x -= rot;
		break;
	case 'V':
		self.rot.x += rot;
		break;
	case 'D':
		self.rot.y -= rot;
		break;
	case 'F':
		self.rot.y += rot;
		break;
	case 'E':
		self.rot.z -= rot;
		break;
	case 'R':
		self.rot.z += rot;
		break;
	case 0x1b:	// ESCキー
		// プログラムを終了
		exit(0);
		break;
	}

	// 当たり判定
	Vec3 vMin1 = self.GetMinVec3();
	Vec3 vMax1 = self.GetMaxVec3();
	Vec3 vMin2 = target.GetMinVec3();
	Vec3 vMax2 = target.GetMaxVec3();
	if(IsCollideBoxAABB(vMin1, vMax1, vMin2, vMax2))
	{
		cout << "隊長!当たってます!!" << endl;
	}
	else
	{
		cout << "当たってません。" << endl;
	}
}

/**
 * 特殊キーが押されたときの処理
 * @param key  押下キー
 * @param x, y 座標
 */
void InputKeySp(int key, int x, int y)
{
	// カメラ移動
	Vec3 vAxis;
	Vec3 vN;
	switch(key)
	{
	case GLUT_KEY_UP:
		// 上キー
		vAxis = Vec3(-1, 0, 0);
		break;
	case GLUT_KEY_DOWN:
		// 下キー
		vAxis = Vec3(1, 0, 0);
		break;
	case GLUT_KEY_LEFT:
		// 左キー
		vAxis = Vec3(0, 1, 0);
		break;
	case GLUT_KEY_RIGHT:
		// 右キー
		vAxis = Vec3(0, -1, 0);
		break;
	}
	vN = vEye.Normalize().Cross(vAxis);
	vEye = vEye + vN;
}

/**
 * 描画
 */
void Display(void)
{
	// 画面クリア
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// 視点の移動
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(vEye.x, vEye.y, vEye.z, 0, 0, 0, 0, 1, 0);

	// 箱の描画
	DrawCube(self.pos,   self.radius,   self.rot,   0);
	DrawCube(target.pos, target.radius, target.rot, 1);

	// 地面を線画で描く
	glColor3d(0.0, 0.0, 0.0);
	glBegin(GL_LINES);
	{
		for (int i = -10; i <= 10; i++)
		{
			glVertex3d((GLdouble)i, -0.5, -10.0);
			glVertex3d((GLdouble)i, -0.5,  10.0);
			glVertex3d(-10.0, -0.5, (GLdouble)i);
			glVertex3d( 10.0, -0.5, (GLdouble)i);
		}
	}
	glEnd();

	glutSwapBuffers();
}

/**
 * ウィンドウのリサイズ
 */
void Resize(int w, int h)
{
	// ウィンドウ全体をビューポートにする
	glViewport(0, 0, w, h);

	// 透視変換行列を設定する
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

	// モデルビュー変換行列を指定しておく
	glMatrixMode(GL_MODELVIEW);
}

/**
 * アイドル時
 */
void Idle()	
{
	glutPostRedisplay();
}

/**
 * メイン関数
 */
int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
	glutCreateWindow(argv[0]);
	glutDisplayFunc(Display);
	glutReshapeFunc(Resize);
	// キーボード入力用関数を登録
	glutKeyboardFunc(InputKey);
	glutSpecialFunc(InputKeySp);
	glutIdleFunc(Idle);
	Init();
	// メインループ
	glutMainLoop();
	return 0;
}

役に立つのかどうか分からない会話2

今作っているゲームを先生に見てもらいました。
 
以下は、その会話の抜粋。
 

先生「お、3Dか。一通りシーンのループして、、、マップもあるね。
   当たり判定はスフィアか、、。まあ、これだけやれば、(うちの学校の)賞は取れるよ」
kenmo「…あの、、、これ持って就職活動できますかね?」
先生「それは無理(あっさり)」
kenmo「ガーンΣ(゜Д゜) ど、どほすればいいですかね…。」
先生「うーん、この敵キャラ、アニメしないっしょ。メッシュのアニメーションは常識」
kenmo「…」
先生「あと、地味。
   頭飛ばしたときに、エフェクト。敵にぶつけて、エフェクト。
   敵にぶつかってもエフェクト、ぐらいしないと。
   『1アクションに1エフェクト』。基本だよ」
kenmo「…」
先生「地形に何もないよね。アイテムとか、破壊できるオブジェクトを置かないと、単調だよ」
kenmo「…あ、ありがとうございました…」
先生「いえいえ」

 
kenmoの課題がいっぺんに増えました…(´Д`;