OpenGL - サンプルコード
をテンプレートにして作成
[
トップ
|
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
必要なときにコピペするためのもの.
----
#contents
----
*描画関数 [#r8efd250]
***グリッド描画 [#xb859bb1]
#code(C){{
/*!
* グリッド描画(x-y軸平面)
* @param[in] d 分割数
* @param[in] x,y グリッド全体のside length
* @param[in] h グリッドの高さ
*/
static int DrawGroundGrid(int d, double x, double y, doub...
{
glPushMatrix();
glDisable(GL_LIGHTING);
glColor3f(1,0,0);
glLineWidth(6.0);
glBegin(GL_LINE_LOOP);
glVertex3d(-x, y, h);
glVertex3d( x, y, h);
glVertex3d( x, -y, h);
glVertex3d(-x, -y, h);
glEnd();
glLineWidth(3.0);
// x方向
float x0, x1, y0, y1;
float deltaX, deltaY;
x0 = -x; x1 = -x;
y0 = -y; y1 = y;
deltaX = (2*x)/d;
for(int i = 0; i < d; ++i){
x0 = x0 + deltaX;
glBegin(GL_LINES);
glVertex3f(x0, y0, h);
glVertex3f(x0, y1, h);
glEnd();
}
// y方向
x0 = -x; x1 = x;
deltaY = (2*y)/d;
for(int i = 0; i < d; ++i){
y0 = y0 + deltaY;
glBegin(GL_LINES);
glVertex3f(x0, y0, h);
glVertex3f(x1, y0, h);
glEnd();
}
glLineWidth(1.0);
glPopMatrix();
return 0;
}
}}
***ポリゴン描画 [#x93b90cd]
rxMaterialは下の材質クラスを参照.
#code(C){{
/*!
* 単一ポリゴンの描画
* @param[in] verts 頂点座標格納コンテナ
* @param[in] index 頂点位相
* @param[in] norm ポリゴン法線
* @param[in] color 描画色
*/
inline void DrawPolygon(const vector<Vec3> &verts, const ...
{
glBegin(GL_POLYGON);
glColor3f(color[0], color[1], color[2]);
for(int i = 0; i < (int)index.size(); ++i){
glVertex3dv(verts[index[i]-1].data);
}
glEnd();
}
/*!
* OpenGLによるグローシェーディングで単一ポリゴン描画
* @param[in] poly ポリゴン
* @param[in] color 描画色
*/
inline void DrawPolygonGouraud(const vector<Vec3> &verts,...
const vector<Vec3> &norms, const Vec3 &color)
{
Vec3 norm;
Vec3 vert;
glColor3f(color[0], color[1], color[2]);
glBegin(GL_POLYGON);
for(int i = 0; i < (int)index.size(); ++i){
glNormal3dv(norms[index[i]-1].data);
glVertex3dv(verts[index[i]-1].data);
}
glEnd();
}
/*!
* OpenGLによるグローシェーディングで複数ポリゴン描画(ポ...
* @param[in] polys ポリゴンを格納したコンテナ
* @param[in] gmat 全体の材質
*/
static void DrawPolygons(const vector<Vec3> &vrts, const ...
rxMaterial *gmat, bool select)
{
int i;
rxMaterial *mat;
for(i = 0; i < (int)idxs.size(); ++i){
if(gmat == NULL){
mat = &g_matDefault;
}
else{
mat = gmat;
}
if(select) glLoadName(i);
mat->SetGL();
glEnable(GL_LIGHTING);
DrawPolygon(vrts, idxs[i], mat->GetDiff3());
}
}
/*!
* OpenGLによるグローシェーディングで複数ポリゴン描画(頂...
* @param[in] polys ポリゴンを格納したコンテナ
* @param[in] gmat 全体の材質
*/
static void DrawPolygonsGouraud(const vector<Vec3> &vrts,...
const vector<Vec3> &nrms,
rxMaterial *gmat, bool select)
{
int i;
rxMaterial *mat;
for(i = 0; i < (int)idxs.size(); ++i){
if(gmat == NULL){
mat = &g_matDefault;
}
else{
mat = gmat;
}
if(select) glLoadName(i);
mat->SetGL();
glEnable(GL_LIGHTING);
DrawPolygonGouraud(vrts, idxs[i], nrms, mat->GetDiff3());
}
}
}}
***傾いた直方体描画 [#e72399ce]
glRotate使用版
#code(C){{
/*!
* cenを中心で辺の長さがlen,dirの方向を向いた直方体の描画
* @param[in] cen 直方体の中心
* @param[in] len 直方体の辺の長さ(x,y,z)
* @param[in] dir 直方体のx軸の向き
*/
inline void DrawSolidCuboid(Vec3 cen, Vec3 len, Vec3 dir)
{
Vec3 org_axis(1.0, 0.0, 0.0);
Vec3 tgt_axis = Unit(dir);
Vec3 rot_axis = Unit(cross(org_axis, tgt_axis));
double rot_angle = acos((double)(dot(org_axis, tgt_axis)...
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glRotatef(RX_TO_DEGREES(rot_angle), rot_axis[0], rot_axi...
DrawSolidCuboid(Vec3(0.0), len);
glPopMatrix();
}
}}
コーナー座標値算出版
#code(C){{
/*!
* cenを中心で辺の長さがlen,dirの方向を向いた直方体の描画
* @param[in] cen 直方体の中心
* @param[in] len 直方体の辺の長さ(x,y,z)
* @param[in] dir 直方体のx軸の向き
*/
inline void DrawSolidCuboid(Vec3 cen, Vec3 len, Vec3 dir)
{
len *= 0.5;
dir = Unit(dir);
Vec3 up(0.0, 1.0, 0.0);
Vec3 right = cross(dir, up);
Vec3 nc = cen-dir*len[0];
Vec3 fc = cen+dir*len[0];
right = Unit(right);
up = Unit(cross(right, dir));
Vec3 corner[8];
corner[0] = nc-up*len[1]-right*len[2];
corner[1] = nc+up*len[1]-right*len[2];
corner[2] = nc+up*len[1]+right*len[2];
corner[3] = nc-up*len[1]+right*len[2];
corner[4] = fc-up*len[1]-right*len[2];
corner[5] = fc+up*len[1]-right*len[2];
corner[6] = fc+up*len[1]+right*len[2];
corner[7] = fc-up*len[1]+right*len[2];
int index[6][4] = { { 3, 2, 1, 0 },
{ 4, 5, 6, 7 },
{ 3, 0, 4, 7 },
{ 1, 2, 6, 5 },
{ 0, 1, 5, 4 },
{ 2, 3, 7, 6 } };
glPushMatrix();
glBegin(GL_QUADS);
// 前後面
glNormal3dv((-dir).data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[0][i...
glNormal3dv(dir.data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[1][i...
// 上下側面
glNormal3dv((-up).data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[2][i...
glNormal3dv(up.data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[3][i...
// 左右側面
glNormal3dv((-right).data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[4][i...
glNormal3dv(right.data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[5][i...
glEnd();
glPopMatrix();
}
}}
***直方体描画 [#c7cf7534]
#code(C){{
/*!
* cenを中心で辺の長さがlenの直方体の描画
* @param[in] cen 直方体の中心
* @param[in] len 直方体の辺の長さ(x,y,z)
*/
inline void DrawSolidCuboid(Vec3 &cen, Vec3 len)
{
len *= 0.5;
Vec3 corner[8];
corner[0] = cen+Vec3(-len[0], -len[1], -len[2]);
corner[1] = cen+Vec3(-len[0], len[1], -len[2]);
corner[2] = cen+Vec3(-len[0], len[1], len[2]);
corner[3] = cen+Vec3(-len[0], -len[1], len[2]);
corner[4] = cen+Vec3( len[0], -len[1], -len[2]);
corner[5] = cen+Vec3( len[0], len[1], -len[2]);
corner[6] = cen+Vec3( len[0], len[1], len[2]);
corner[7] = cen+Vec3( len[0], -len[1], len[2]);
int index[6][4] = { { 3, 2, 1, 0 },
{ 4, 5, 6, 7 },
{ 3, 0, 4, 7 },
{ 1, 2, 6, 5 },
{ 0, 1, 5, 4 },
{ 2, 3, 7, 6 } };
glPushMatrix();
glBegin(GL_QUADS);
// x軸に垂直な面
glNormal3d(-1.0, 0.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[0][i...
glNormal3d( 1.0, 0.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[1][i...
// y軸に垂直な面
glNormal3d(0.0, -1.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[2][i...
glNormal3d(0.0, 1.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[3][i...
// z軸に垂直な面
glNormal3d(0.0, 0.0, -1.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[4][i...
glNormal3d(0.0, 0.0, 1.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[5][i...
glEnd();
glPopMatrix();
}
}}
***立方体描画(ディスプレイリスト使用) [#e72399ce]
vector<Vec3>は配列にした方が効率がよいかも.scaleやwireは...
#code(C){{
static void DrawCube(double scale = 0.5, bool wire = false)
{
using namespace boost::assign;
static GLuint polyList = 0;
vector<Vec3> vrts, cols;
vrts += Vec3( 1.0, 1.0, 1.0), \
Vec3( 1.0, -1.0, 1.0), \
Vec3(-1.0, -1.0, 1.0), \
Vec3(-1.0, 1.0, 1.0), \
Vec3( 1.0, 1.0, -1.0), \
Vec3( 1.0, -1.0, -1.0), \
Vec3(-1.0, -1.0, -1.0), \
Vec3(-1.0, 1.0, -1.0);
cols += Vec3(1.0, 1.0, 1.0), \
Vec3(1.0, 1.0, 0.0), \
Vec3(0.0, 1.0, 0.0), \
Vec3(0.0, 1.0, 1.0), \
Vec3(1.0, 0.0, 1.0), \
Vec3(1.0, 0.0, 0.0), \
Vec3(0.0, 0.0, 0.0), \
Vec3(0.0, 0.0, 1.0);
const short faces[6][4] = { {3, 2, 1, 0},
{2, 3, 7, 6},
{0, 1, 5, 4},
{3, 0, 4, 7},
{1, 2, 6, 5},
{4, 5, 6, 7} };
GLint num_faces = 6;
if(!polyList){
polyList = glGenLists(1);
glNewList(polyList, GL_COMPILE);
if(!wire){
glBegin(GL_QUADS);
for(int f = 0; f < num_faces; ++f){
for(int i = 0; i < 4; ++i){
glColor3dv(cols[faces[f][i]].data);
glVertex3dv((vrts[faces[f][i]]*scale).data);
}
}
glEnd();
}
glColor3f(0.0, 0.0, 0.0);
for(int f = 0; f < num_faces; ++f){
glBegin(GL_LINE_LOOP);
for(int i = 0; i < 4; ++i){
glVertex3dv((vrts[faces[f][i]]*scale).data);
}
glEnd();
}
glEndList();
}
glPushMatrix();
glCallList(polyList);
glPopMatrix();
}
}}
***円筒描画 [#e43fca86]
DrawCylinderは円筒,DrawCapsuleは両端が半球状の円筒.
#code(C){{
/*!
* 円筒描画
* @param[in] rad,len 半径と中心軸方向長さ
* @param[in] axis 軸方向
* @param[in] slices ポリゴン近似する際の分割数
*/
static void DrawCylinder(double rad, double len, int axis...
{
GLUquadricObj *qobj;
qobj = gluNewQuadric();
glPushMatrix();
switch(axis){
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 2:
glTranslatef(0.0, 0.0, -0.5*len);
break;
default:
glTranslatef(0.0, 0.0, -0.5*len);
}
gluQuadricDrawStyle(qobj, GLU_FILL);
gluQuadricNormals(qobj, GLU_SMOOTH);
gluCylinder(qobj, rad, rad, len, slices, slices);
glPushMatrix();
glRotatef(180.0, 1.0, 0.0, 0.0);
gluDisk(qobj, 0.0, rad, slices, slices);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, len);
gluDisk(qobj, 0.0, rad, slices, slices);
glPopMatrix();
glPopMatrix();
}
/*!
* カプセル描画(円筒の両端に半球をつけた形)
* @param[in] rad,len 半径と中心軸方向長さ
* @param[in] axis 軸方向
* @param[in] slices ポリゴン近似する際の分割数
*/
static void DrawCapsule(double rad, double len, int axis,...
{
GLUquadricObj *qobj;
qobj = gluNewQuadric();
glPushMatrix();
switch(axis){
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 2:
glTranslatef(0.0, 0.0, -0.5*len);
break;
default:
glTranslatef(0.0, 0.0, -0.5*len);
}
gluQuadricDrawStyle(qobj, GLU_FILL);
gluQuadricNormals(qobj, GLU_SMOOTH);
gluCylinder(qobj, rad, rad, len, slices, slices);
glPushMatrix();
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, len);
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glPopMatrix();
}
}}
ワイヤフレーム描画時に不自然にならないように両端の球をち...
#code(C){{
/*!
* カプセル描画(円筒の両端に半球をつけた形)
* - ワイヤフレーム描画時に不自然にならないように両端の...
* @param[in] rad,len 半径と中心軸方向長さ
* @param[in] axis 軸方向
* @param[in] slices ポリゴン近似する際の分割数
*/
void DrawCapsule(double rad, double len, int axis, int sl...
{
GLUquadricObj *qobj;
qobj = gluNewQuadric();
glPushMatrix();
switch(axis){
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 2:
glTranslatef(0.0, 0.0, -0.5*len);
break;
default:
glTranslatef(0.0, 0.0, -0.5*len);
}
gluQuadricDrawStyle(qobj, GLU_FILL);
gluQuadricNormals(qobj, GLU_SMOOTH);
gluCylinder(qobj, rad, rad, len, slices, slices);
double c_init[4] = {0, 0, 0, 0};
double c_bottom[4] = {0, 0, -1, 0};
double c_top[4] = {0, 0, 1, 0};
glEnable(GL_CLIP_PLANE0);
glPushMatrix();
glClipPlane(GL_CLIP_PLANE0, c_bottom);
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, len);
glClipPlane(GL_CLIP_PLANE0, c_top);
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glClipPlane(GL_CLIP_PLANE0, c_init);
glDisable(GL_CLIP_PLANE0);
glPopMatrix();
}
}}
GLUを使わないで円筒を描画する場合.
z軸平行で描画される.
#code(C){{
/*!
* 円筒形の描画(z軸平行,底面が原点)
* @param[in] r 円筒半径
* @param[in] h 返答長さ
* @param[in] slice 円の分割数
* @param[in] stack 長さ方向の分割数
*/
void DrawCylinder(double r, double h, int slice)
{
double theta = 2.0*RX_PI/(double)slice;
double n_norm;
Vec3 origin = Vec3(0.0);
vector<Vec3> vert;
vert.resize(slice);
Vec3 normal;
glPushMatrix();
// 天面の描画(y = cen[1]+h)
glNormal3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
for(int i = 0; i < slice; ++i){
vert[i][0] = origin[0]+r*sin(theta*(double)i);
vert[i][1] = origin[1]+r*cos(theta*(double)i);
vert[i][2] = origin[2]+h;
glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
}
glEnd();
// 底面の描画(y = cen[1])
glNormal3f(0.0, -1.0, 0.0);
glBegin(GL_POLYGON);
for(int i = 0; i < slice; ++i){
vert[i][2] = origin[2];
glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
}
glEnd();
// 側面の描画
glBegin(GL_QUAD_STRIP);
int j;
for(int i = 0; i < slice; ++i){
j = (i+1)%slice;
normal = 0.5*(vert[i]+vert[j]);
normal = origin-normal;
n_norm = norm(normal);
if(n_norm > RX_EPS) normal /= n_norm;
glNormal3f(normal[0], normal[1], normal[2]);
glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
glVertex3f(vert[i][0], vert[i][1], vert[i][2]+h);
}
glVertex3f(vert[j][0], vert[j][1], vert[j][2]);
glVertex3f(vert[j][0], vert[j][1], vert[j][2]+h);
glEnd();
glPopMatrix();
}
}}
***キューブマップ描画 [#j8bc13ff]
#code(C){{
/*!
* キューブマップテクスチャを内部に貼り付けた立方体の描画
* @param[in] cube_map キューブマップ
* @param[in] side 立方体の一辺の長さ
*/
void RxGLDraw::DrawCubeMap(GLuint cube_map, double side)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
// キューブマップテクスチャをバインド
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_map);
// GL_OBJECT_LINEARテクスチャ座標を設定
glPushMatrix();
GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_plane);
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_plane);
glTexGenfv(GL_R, GL_OBJECT_PLANE, r_plane);
glPopMatrix();
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
// シーンを覆う大きさの立方体を描画
glPushMatrix();
glutSolidCube(side);
glPopMatrix();
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glDisable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
}}
***矢印描画 [#j5da7c54]
2Dの場合
#code(C){{
/*!
* 矢印の描画
* @param[in] s 矢印の始点
* @param[in] e 矢印の始点
* @param[in] scale 傘の部分の大きさ(全体の長さに対する係...
*/
inline static void DrawArrow2D(const Vec2 &s, const Vec2 ...
{
// 始点,方向,長さ
Vec2 origin = s;
Vec2 dir = e-s;
double length = normalize(dir);
// ベクトル(1,0)との間の角度
double theta = 180.0/RX_PI*acos(dot(Vec2(1, 0), dir))*RX...
// 矢印の傘部分の設定
double arrow_x = scale*length; // 軸方向の長さ
//double arrow_y = arrow_x*0.174532925; // 軸に垂直...
double arrow_y = arrow_x*0.363970234; // 軸に垂直な...
glPushMatrix();
glTranslatef(origin[0], origin[1], 0.0); // 矢印原...
glRotatef(theta, 0.0, 0.0, 1.0); // 矢印方...
glBegin(GL_LINES);
// 軸
glVertex2d(0.0, 0.0);
glVertex2d(length, 0.0);
// 傘
glVertex2d(length, 0.0);
glVertex2d(length-arrow_x, arrow_y);
glVertex2d(length, 0.0);
glVertex2d(length-arrow_x, -arrow_y);
glEnd();
glPopMatrix();
}
}}
3Dの場合(3DベクトルクラスVec3と上の円筒描画,下の任意ベク...
#code(C){{
/*!
* ベクトルを矢印で描画
* @param[in] pos 原点座標
* @param[in] vec ベクトル
* @param[in] r 軸の半径
* @param[in] dr 矢印の傘部分の半径(軸の半径を1としたと...
* @param[in] dl 矢印の傘部分の長さ(全体の長さを1とした...
*/
void DrawArrow(Vec3 pos, Vec3 vec, double r, double dr = ...
{
double vlen = norm(vec);
Vec3 pos1 = pos+vec*(1.0-dl*0.5);
Vec3 init = Vec3(0.0, 0.0, 1.0); // 円筒と円錐描画はデフ...
// vecとz軸の間の回転角度と回転軸
double rot_ang = acos(dot(init, Unit(vec)))*57.295779513...
Vec3 rot_axis = Unit(cross(init, Unit(vec)));
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]); // 原点に移動
glRotatef(rot_ang, rot_axis[0], rot_axis[1], rot_axis[2]...
// ベクトルの軸部分
DrawCylinder(r, vlen*(1.0-dl*0.5), 16);
// ベクトルの傘部分
double alen = dl*vlen; // 円錐の高さ
double arad = dr*r; // 円錐の半径
pos1 = pos+vec;
glTranslatef(0.0, 0.0, vlen-alen);
glutSolidCone(arad, alen, 16, 16);
glPopMatrix();
}
}}
***文字描画 [#f4c43bc4]
#code{{
/*!
* 文字列描画
* @param[in] static_str 文字列
* @param[in] w,h ウィンドウサイズ
*/
static void DrawStrings(vector<string> &static_str, int w...
{
glDisable(GL_LIGHTING);
// 平行投影にする
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
float x0 = 5.0f;
float y0 = h-20.0f;
// 画面上部にテキスト描画
for(int j = 0; j < (int)static_str.size(); ++j){
glRasterPos2f(x0, y0);
int size = (int)static_str[j].size();
for(int i = 0; i < size; ++i){
char ic = static_str[j][i];
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
}
y0 -= 20;
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
}}
呼び出す前にglColorで色の設定をしておく.
boost::circular_bufferを使ってコマンドプロンプトのように...
#code(C){{
typedef boost::circular_buffer<string> CircularBuf;
// 循環バッファ
static CircularBuf g_cbDrawDef(5);
static vector<string> g_cbDrawStaticDef(3);
template<typename T>
inline CircularBuf &operator<<(CircularBuf &cb, const T &a)
{
string buf = boost::lexical_cast<std::string>(a);
if(buf == "\n"){
cb.push_back("");
}
else if(cb.empty()){
cb.push_back(buf);
}
else{
cb.back() += buf;
}
return cb;
}
template<typename T>
inline string &operator<<(string &cb, const T &a)
{
cb += boost::lexical_cast<std::string>(a);
return cb;
}
/*!
* 文字列描画
* @param[in] cir_str 文字列循環バッファ
* @param[in] static_str 静的な文字列バッファ
* @param[in] w,h ウィンドウサイズ
*/
static void DrawStrings(CircularBuf cir_str, vector<strin...
{
// MRK:PrintD
glDisable(GL_LIGHTING);
//glColor3f(0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
float x0 = 5;
float y0 = h-20;
// 画面上部にスタティックなテキスト
for(int j = 0; j < (int)static_str.size(); ++j){
glRasterPos2f(x0, y0);
int size = (int)static_str[j].size();
for(int i = 0; i < size; ++i){
char ic = static_str[j][i];
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
}
y0 -= 20;
}
// 画面下部に循環バッファを使ったテキスト
x0 = 5;
y0 = 20*cir_str.size();;
for(int j = 0; j < (int)cir_str.size(); ++j){
glRasterPos2f(x0, y0);
int size = (int)cir_str[j].size();
for(int i = 0; i < size; ++i){
char ic = cir_str[j][i];
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
}
y0 -= 20;
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
}}
***三角形メッシュ描画(法線計算付き) [#yee58253]
#code(C){{
/*!
* 三角形メッシュ描画
* @param[in] vrts 頂点列
* @param[in] idxes メッシュを構成する頂点インデックス(0...
* @param[in] normal 法線描画ON/OFF
*/
void DrawMesh(const vector<Vec3> &vrts, const vector< vec...
{
for(int i = 0; i < (int)idxes.size(); ++i){
vector<int> idx = idxes[i];
int nv = (int)idx.size();
// 法線
Vec3 nrm;
nrm = cross(vrts[idx[1]]-vrts[idx[0]], vrts[idx[nv-1]]-...
normalize(nrm);
if(normal){
// 重心を求める
Vec3 mc(0.0);
for(int j = 0; j < nv; ++j){
mc += vrts[idx[j]];
}
mc /= (double)nv;
int lighting = glIsEnabled(GL_LIGHTING);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glVertex3dv(mc.data);
glVertex3dv((mc+0.05*nrm).data);
glEnd();
lighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTI...
}
glNormal3dv(nrm.data);
// 面
glBegin(GL_POLYGON);
for(int j = 0; j < nv; ++j){
glVertex3dv(vrts[idx[j]].data);
}
glEnd();
}
}
}}
法線は面の重心に描画される.Vec3はオペレータ[]で各要素に...
***球の描画 [#sc7c38dc]
#code(C){{
/*!
* 球の描画
* @param[in] cen 球の中心
* @param[in] rad 球の半径
* @param[in] col 描画色(拡散反射色)
*/
inline void DrawSphere(const Vec3 &cen, const double &rad...
{
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glRotated(90, 1.0, 0.0, 0.0);
glutSolidSphere(rad, 20, 10);
glPopMatrix();
}
}}
***球の(滑らかな)ワイヤーフレーム描画 [#t159f84d]
#code(C){{
/*!
* 原点中心の円のワイヤーフレーム描画
* @param rad 円の半径
* @param n 分割数
*/
static void DrawWireCircle(const double &rad, const int &n)
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glBegin(GL_LINE_LOOP);
do{
glVertex3f(rad*cos(t), rad*sin(t), 0.0);
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
}
/*!
* 原点中心の円のワイヤーフレーム描画(XZ平面)
* @param rad 円の半径
* @param n 分割数
*/
static void DrawWireCircleXZ(const double &rad, const int...
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glBegin(GL_LINE_LOOP);
do{
glVertex3f(rad*cos(t), 0.0, rad*sin(t));
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
}
/*!
* 球のワイヤーフレーム描画
* @param cen 球の中心
* @param rad 球の半径
* @param col 描画色
*/
void DrawWireSphere(const Vec3 &cen, const float &rad, co...
{
glDisable(GL_LIGHTING);
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glRotatef(90, 1.0, 0.0, 0.0);
glColor3f(col[0], col[1], col[2]);
// 緯度(x-y平面に平行)
float z, dz;
dz = 2.0*rad/8.0f;
z = -(rad-dz);
do{
glPushMatrix();
glTranslatef(0.0, 0.0, z);
DrawWireCircle(sqrt(rad*rad-z*z), 32);
glPopMatrix();
z += dz;
}while(z < rad);
// 経度(z軸まわりに回転)
float t, dt;
t = 0.0f;
dt = 180.0/8.0;
do{
glPushMatrix();
glRotatef(t, 0.0, 0.0, 1.0);
DrawWireCircleXZ(rad, 32);
glPopMatrix();
t += dt;
}while(t < 180);
//glutWireSphere(rad, 10, 5);
glPopMatrix();
}
}}
***円の描画 [#w796138f]
x-y平面上に円を描画.
#code(C){{
/*!
* 円の描画
* @param cen 円の中心
* @param rad 円の半径
* @param n 分割数
*/
static void DrawCircle(Vec3 cen, double rad, int n)
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glBegin(GL_POLYGON);
do{
glVertex3f(rad*cos(t), rad*sin(t), 0.0);
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
glPopMatrix();
}
/*!
* 円のワイヤーフレーム描画
* @param cen 円の中心
* @param rad 円の半径
* @param n 分割数
*/
static void DrawWireCircle(Vec3 cen, double rad, int n)
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glBegin(GL_LINE_LOOP);
do{
glVertex3f(rad*cos(t), rad*sin(t), 0.0);
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
glPopMatrix();
}
}}
Vec3はオペレータ[]で各要素にアクセスできる3次元ベクトルク...
*アフィン変換 [#w6072353]
***回転 [#hc5f8f47]
#code(C){{
//! degree -> radian の変換係数(pi/180.0)
const double RX_DEGREES_TO_RADIANS = 0.017453292519943295...
//! degree -> radian の変換
template<class T>
inline T RX_TO_RADIANS(const T &x){ return static_cast<T>...
/*!
* 座標の回転
* @param[in] pos 回転したい座標値
* @param[in] rot_deg x,y,z軸周りの回転角(deg)
* @return 回転後の座標値
*/
inline Vec3 RxRotate(const Vec3 &pos, const Vec3 &rot_deg)
{
Vec3 pos1;
Vec3 rot = RX_TO_RADIANS(rot_deg);
Vec3 S(sin(rot[0]), sin(rot[1]), sin(rot[2]));
Vec3 C(cos(rot[0]), cos(rot[1]), cos(rot[2]));
pos1[0] = C[1]*C[2]*pos[0] ...
pos1[1] = (S[0]*S[1]*C[2]+C[0]*S[2])*pos[0] +(-S[0]*S[1...
pos1[2] = (-C[0]*S[1]*C[2]+S[0]*S[2])*pos[0] +(C[0]*S[1...
return pos1;
}
/*!
* 座標の回転(2D)
* @param[in] pos 回転したい座標値
* @param[in] rot_deg z軸周りの回転角(deg)
* @return 回転後の座標値
*/
inline Vec2 RxRotate2D(const Vec2 &pos, double rot_deg)
{
double rot = RX_TO_RADIANS(rot_deg);
return Vec2(pos[0]*cos(rot)-pos[1]*sin(rot), pos[0]*sin(...
}
}}
***任意ベクトル周りの回転 [#i46bfc4d]
#code(C){{
/*!
* 任意ベクトル周りの回転
* @param[in] pos 元の座標値
* @param[in] axis 回転軸
* @param[in] ang 回転角度(deg)
* @return 回転した座標値
*/
inline Vec3 Rotate(const Vec3 &pos, const Vec3 &axis, con...
{
Vec3 pos1; // 回転後の座標値
double ang = RX_TO_RADIANS(ang_deg);
double c = cos(ang);
double s = sin(ang);
double x, y, z;
x = axis[0]; y = axis[1]; z = axis[2];
// | xx(1-c)+c xy(1-c)-zs xz(1-c)+ys 0 |
// | yx(1-c)+zs yy(1-c)+c yz(1-c)-xs 0 |
// | xz(1-c)-ys yz(1-c)+xs zz(1-c)+c 0 |
// | 0 0 0 1 |
pos1[0] = (x*x*(1.0-c)+c)*pos[0] +(x*y*(1.0-c)-z*s)*po...
pos1[1] = (y*x*(1.0-c)+z*s)*pos[0] +(y*y*(1.0-c)+c)*po...
pos1[2] = (x*z*(1.0-c)-y*s)*pos[0] +(y*z*(1.0-c)+x*s)*po...
return pos1;
}
}}
***オイラー角から回転行列 [#dcb3ea9d]
#code(C){{
/*!
* オイラー角から回転行列(4x4)を生成
* @param[in]
* @param[out]
* @return
*/
inline void EulerToMatrix(double *m, double pitch, double...
{
yaw = RX_TO_RADIANS(yaw);
pitch = RX_TO_RADIANS(pitch);
roll = RX_TO_RADIANS(roll);
double cy = cos(yaw);
double sy = sin(yaw);
double cp = cos(pitch);
double sp = sin(pitch);
double cr = cos(roll);
double sr = sin(roll);
double cc = cy*cr;
double cs = cy*sr;
double sc = sy*cr;
double ss = sy*sr;
m[0] = cc+sp*ss;
m[1] = cs-sp*sc;
m[2] = -sy*cp;
m[3] = 0.0;
m[4] = -cp*sr;
m[5] = cp*cr;
m[6] = -sp;
m[7] = 0.0;
m[8] = sc-sp*cs;
m[9] = ss+sp*cc;
m[10] = cy*cp;
m[11] = 0.0;
m[12] = 0.0;
m[13] = 0.0;
m[14] = 0.0;
m[15] = 1.0;
}
}}
***射影 [#i5f51162]
#code(C){{
/*!
* 任意の平面へ影を射影する行列構築関数
* @param[out] m 作成する行列(4x4)m[16]へのポインタ
* @param[in] plane[4] 射影する表面の平面方程式
* @param[in] light[4] 光源の座標値(同次座標)
*/
inline void ProjectShadowMatrix(double *m, double plane[4...
{
double dot = plane[0]*light[0]+plane[1]*light[1]+plane[2...
m[0] = dot-light[0]*plane[0];
m[4] = -light[0]*plane[1];
m[8] = -light[0]*plane[2];
m[12] = -light[0]*plane[3];
m[1] = -light[1]*plane[0];
m[5] = dot-light[1]*plane[1];
m[9] = -light[1]*plane[2];
m[13] = -light[1]*plane[3];
m[2] = -light[2]*plane[0];
m[6] = -light[2]*plane[1];
m[10] = dot-light[2]*plane[2];
m[14] = -light[2]*plane[3];
m[3] = -light[3]*plane[0];
m[7] = -light[3]*plane[1];
m[11] = -light[3]*plane[2];
m[15] = dot-light[3]*plane[3];
}
}}
*その他関数 [#rdc4e1f5]
***球形状ポリゴン生成 [#k0cf6d98]
#code(C){{
/*!
* 球形状ポリゴン生成
* @param[in] rad 半径
* @param[in] slices z軸まわりの分割数(経線)
* @param[in] stacks z軸に沿ったの分割数(緯線)
* @param[out] vrts 頂点座標
* @param[out] nrms 法線座標
* @param[out] txcs テクスチャ座標
* @param[out] fces ポリゴン(頂点接続)
* @param[in] tri trueで三角形ポリゴン, falseで四角形(た...
* @return 生成頂点数
*/
int MakeSphere(double rad, int slices, int stacks,
vector<Vec3> &vrts, vector<Vec3> &nrms, vector<Vec2...
bool tri = true)
{
int vn = 2+(stacks-1)*slices; // 頂点数(極点2つ+経線・...
vrts.resize(vn, Vec3(0.0)); // 頂点座標
nrms.resize(vn, Vec3(0.0)); // 頂点法線
txcs.resize(vn, Vec2(0.0)); // テクスチャ座標
vrts[0] = Vec3(0.0, 0.0, rad); // 北極点
vrts[vn-1] = Vec3(0.0, 0.0, -rad); // 南極点
double dp = RX_PI/(double)stacks; // Φ(経線に沿った方向...
double dt = 2.0*RX_PI/(double)slices; // Θ(緯線に沿った...
double phi = dp; // 経線に沿った方向の角度(北極点で0)
double theta = 0.0; // 緯線に沿った方向の角度
// 球を構成する頂点の生成
for(int i = 0; i < stacks-1; ++i){
double z = rad*cos(phi);
theta = 0.0;
for(int j = 0; j < slices; ++j){
double rad_t = rad*sin(phi);
int idx = 1+i*slices+j;
vrts[idx] = Vec3(rad_t*cos(theta), rad_t*sin(theta), z);
nrms[idx] = Unit(vrts[idx]);
txcs[idx] = Vec2(theta/(2.0*RX_PI), phi/(RX_PI));
theta += dt;
}
phi += dp;
}
// ポリゴン数
int fn = 2*slices+(stacks-2)*slices*(tri ? 2 : 1);
fces.reserve(fn);
// ポリゴン生成
for(int i = 0; i < stacks; ++i){
if(i == 0){ // 北極点と最初の緯線を接続
vector<int> f(3);
for(int j = 0; j < slices; ++j){
int k0 = 1+i*slices+j;
int k1 = 1+i*slices+(j == slices-1 ? 0 : j+1);
f[0] = 0; f[1] = k0; f[2] = k1;
fces.push_back(f);
}
}
else if(i == stacks-1){ // 南極点と最後の緯線を接続
vector<int> f(3);
for(int j = 0; j < slices; ++j){
int k0 = 1+(i-1)*slices+j;
int k1 = 1+(i-1)*slices+(j == slices-1 ? 0 : j+1);
f[0] = vn-1; f[1] = k1; f[2] = k0;
fces.push_back(f);
}
}
else{
for(int j = 0; j < slices; ++j){
int k0 = 1+i*slices+j;
int k1 = 1+i*slices+(j == slices-1 ? 0 : j+1);
int k2 = 1+(i-1)*slices+j;
int k3 = 1+(i-1)*slices+(j == slices-1 ? 0 : j+1);
vector<int> f;
if(tri){
// 三角形ポリゴンを用いる場合
f.resize(3);
f[0] = k0; f[1] = k1; f[2] = k3;
fces.push_back(f);
f[0] = k0; f[1] = k3; f[2] = k2;
fces.push_back(f);
}
else{
// 四角形ポリゴンを用いる場合
f.resize(4);
f[0] = k0; f[1] = k1; f[2] = k3; f[3] = k2;
fces.push_back(f);
}
}
}
}
return 0;
}
/*!
* 球形状ポリゴン生成(極点,経度0degでの重複あり)
* @param[in] rad 半径
* @param[in] slices z軸まわりの分割数(経線)
* @param[in] stacks z軸に沿ったの分割数(緯線)
* @param[out] vrts 頂点座標
* @param[out] nrms 法線座標
* @param[out] txcs テクスチャ座標
* @param[out] fces ポリゴン(頂点接続)
* @param[in] tri trueで三角形ポリゴン, falseで四角形
* @return 生成頂点数
*/
int MakeSphereC(double rad, int slices, int stacks,
vector<Vec3> &vrts, vector<Vec3> &nrms, vector<Vec2> ...
bool tri = true)
{
int vn = (stacks+1)*(slices+1); // 頂点数(経線・緯線の...
vrts.resize(vn, Vec3(0.0)); // 頂点座標
nrms.resize(vn, Vec3(0.0)); // 頂点法線
txcs.resize(vn, Vec2(0.0)); // テクスチャ座標
double dp = RX_PI/(double)stacks; // Φ(経線に沿った方向...
double dt = 2.0*RX_PI/(double)slices; // Θ(緯線に沿った...
double phi = 0; // 経線に沿った方向の角度(北極点で0)
double theta = 0.0; // 緯線に沿った方向の角度
// 球を構成する頂点の生成
for(int i = 0; i < stacks+1; ++i){
double z = rad*cos(phi);
theta = 0.0;
for(int j = 0; j < slices+1; ++j){
double rad_t = rad*sin(phi);
int idx = i*(slices+1)+j;
vrts[idx] = Vec3(rad_t*cos(theta), rad_t*sin(theta), z);
nrms[idx] = Unit(vrts[idx]);
txcs[idx] = Vec2(theta/(2.0*RX_PI), phi/(RX_PI));
theta += dt;
}
phi += dp;
}
// ポリゴン数
int fn = stacks*slices*(tri ? 2 : 1);
fces.reserve(fn);
// ポリゴン生成
for(int i = 1; i < stacks+1; ++i){
for(int j = 0; j < slices; ++j){
int k0 = i*(slices+1)+j;
int k1 = i*(slices+1)+(j+1);
int k2 = (i-1)*(slices+1)+j;
int k3 = (i-1)*(slices+1)+(j+1);
vector<int> f;
if(tri){
// 三角形ポリゴンを用いる場合
f.resize(3);
f[0] = k0; f[1] = k1; f[2] = k3;
fces.push_back(f);
f[0] = k0; f[1] = k3; f[2] = k2;
fces.push_back(f);
}
else{
// 四角形ポリゴンを用いる場合
f.resize(4);
f[0] = k0; f[1] = k1; f[2] = k3; f[3] = k2;
fces.push_back(f);
}
}
}
return 0;
}
}}
***ミップマップテクスチャのサイズの計算 [#y1859c15]
#code(C){{
/*!
* ミップマップのサイズの計算
* @param[in] x 任意の整数(画像の大きさ)
* @param[out] d x以下の最大の2^d
* @return x以下の最大の2^dとなる解像度
*/
inline int CalMipmapSize(const int &x, int &d)
{
d = (int)(log((double)x)/log(2.0));
return (int)pow(2.0, (double)d);
}
}}
***グラデーション色の作成 [#m477d227]
#code(C){{
//! 値のクランプ(クランプした値を返す)
template<class T>
inline T RX_CLAMP(const T &x, const T &a, const T &b){ re...
//! 1次元線型補間
template<class T>
inline T RX_LERP(const T &a, const T &b, const T &t){ ret...
/*!
* 青->緑->赤->白と変化するサーモグラフ用の色生成
* @param[out] col 生成された色
* @param[in] x 値
* @param[in] xmin 最小値
* @param[in] xmax 最大値
*/
inline void CalThermograph(double col[3], double x, const...
{
double l = xmax-xmin;
if(fabs(l) < 1e-10) return;
const int ncolors = 7;
double base[ncolors][3] = { {0.0, 0.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 1.0, 1.0},
{0.0, 1.0, 0.0},
{1.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{1.0, 1.0, 1.0} };
x = RX_CLAMP(((x-xmin)/l), 0.0, 1.0)*(ncolors-1);
int i = (int)x;
double dx = x-floor(x);
col[0] = RX_LERP(base[i][0], base[i+1][0], dx);
col[1] = RX_LERP(base[i][1], base[i+1][1], dx);
col[2] = RX_LERP(base[i][2], base[i+1][2], dx);
}
/*!
* グラデーション色生成
* @param[out] col 生成された色
* @param[in] col1 x=xminのときの色
* @param[in] col2 x=xmaxのときの色
* @param[in] x 値
* @param[in] xmin 最小値
* @param[in] xmax 最大値
*/
inline void CalGradation(double col[3], const double col1...
double x, const double xmin = 0.0, const double xm...
{
double l = xmax-xmin;
if(fabs(l) < 1e-10) return;
double dx = RX_CLAMP(((x-xmin)/l), 0.0, 1.0);
col[0] = RX_LERP(col1[0], col2[0], dx);
col[1] = RX_LERP(col1[1], col2[1], dx);
col[2] = RX_LERP(col1[2], col2[2], dx);
}
}}
*クラス [#vb8f996e]
***テクスチャ管理クラス [#da4250ba]
#code(C){{
//-------------------------------------------------------...
// MARK:テクスチャデータの基底クラス
//-------------------------------------------------------...
class rxTexObj
{
protected:
GLenum m_iTarget;
bool m_bValid;
bool m_bManageObjects;
GLuint m_iTexName;
public:
// managed = true : デストラクタでオブジェクトを破棄した...
rxTexObj(GLenum tgt, bool managed) : m_iTarget(tgt), m_b...
~rxTexObj()
{
if(m_bManageObjects) Delete();
}
void Bind(void)
{
if(!m_bValid){
Generate();
}
glBindTexture(m_iTarget, m_iTexName);
}
void UnBind(void)
{
glBindTexture(m_iTarget, 0);
}
void SetParameter(GLenum pname, GLint i){ glTexParameter...
void SetParameter(GLenum pname, GLfloat f){ glTexParamet...
void SetParameter(GLenum pname, GLint *ip){ glTexParamet...
void SetParameter(GLenum pname, GLfloat *fp){ glTexParam...
void Enable(void){ glEnable(m_iTarget); }
void Disable(void){ glDisable(m_iTarget); }
GLuint GetTexName(void) const { return m_iTexName; }
GLenum GetTexTarget(void) const { return m_iTarget; }
void Delete()
{
if(m_bValid){
glDeleteTextures(1, &m_iTexName);
m_bValid = false;
}
}
void Generate()
{
glGenTextures(1, &m_iTexName);
m_bValid = true;
}
public:
bool IsValid() const { return m_bValid; }
};
//-------------------------------------------------------...
// MARK:2Dテクスチャデータ
//-------------------------------------------------------...
template <class T>
class rxTexObj2D_T : public rxTexObj
{
public:
T *m_pImage;
int m_iW, m_iH, m_iC;
GLenum m_iFormat;
public:
//! コンストラクタ
rxTexObj2D_T(bool managed = false) : rxTexObj(GL_TEXTURE...
{
m_pImage = NULL;
m_iW = 0;
m_iH = 0;
m_iC = 3;
m_iFormat = GL_RGB;
}
//! デストラクタ
~rxTexObj2D_T()
{
if(m_pImage != NULL) delete [] m_pImage;
}
/*!
* テクスチャサイズの設定
* @param[in] iW,iH テクスチャの縦横ピクセル数
* @param[in] iC テクスチャの1ピクセルごとのチャンネル数
*/
void SetSize(int iW, int iH, int iC = 3)
{
if(m_iW != iW || m_iH != iH || m_iC != iC){
m_iW = iW;
m_iH = iH;
m_iC = iC;
m_iFormat = (m_iC == 4) ? GL_RGBA : GL_RGB;
if(m_pImage != NULL) delete [] m_pImage;
m_pImage = new T[m_iW*m_iH*m_iC];
}
}
/*!
* テクスチャサイズの取得
* @param[out] iW,iH テクスチャの縦横ピクセル数
* @param[out] iC テクスチャの1ピクセルごとのチャンネル数
*/
void GetSize(int &iW, int &iH, int &iC)
{
iW = m_iW;
iH = m_iH;
iC = m_iC;
}
/*!
* ピクセルの色情報の取得
* @param[in] ic,jc ピクセル座標
* @param[out] r,g,b ピクセルの色
*/
void GetColor(int ic, int jc, T &r, T &g, T &b)
{
r = m_pImage[m_iC*(m_iW*jc+ic)+0];
g = m_pImage[m_iC*(m_iW*jc+ic)+1];
b = m_pImage[m_iC*(m_iW*jc+ic)+2];
}
/*!
* ピクセルの色情報の取得(4チャンネルRGBA)
* @param[in] ic,jc ピクセル座標
* @param[out] r,g,b,a ピクセルの色
*/
void GetColor4(int ic, int jc, T &r, T &g, T &b, T &a)
{
r = m_pImage[m_iC*(m_iW*jc+ic)+0];
g = m_pImage[m_iC*(m_iW*jc+ic)+1];
b = m_pImage[m_iC*(m_iW*jc+ic)+2];
if(m_iC == 4) a = m_pImage[m_iC*(m_iW*jc+ic)+3];
}
/*!
* ピクセルの色情報の設定
* @param[in] ic,jc ピクセル座標
* @param[in] r,g,b ピクセルの色
*/
void SetColor(int ic, int jc, const T &r, const T &g, co...
{
m_pImage[m_iC*(m_iW*jc+ic)+0] = r;
m_pImage[m_iC*(m_iW*jc+ic)+1] = g;
m_pImage[m_iC*(m_iW*jc+ic)+2] = b;
if(m_iC == 4) m_pImage[m_iC*(m_iW*jc+ic)+3] = 0;
}
/*!
* ピクセルの色情報の設定(4チャンネルRGBA)
* @param[in] ic,jc ピクセル座標
* @param[in] r,g,b,a ピクセルの色
*/
void SetColor(int ic, int jc, const T &r, const T &g, co...
{
m_pImage[m_iC*(m_iW*jc+ic)+0] = r;
m_pImage[m_iC*(m_iW*jc+ic)+1] = g;
m_pImage[m_iC*(m_iW*jc+ic)+2] = b;
if(m_iC == 4) m_pImage[m_iC*(m_iW*jc+ic)+3] = a;
}
/*!
* テクスチャメモリへ画像データを転送
*/
void SetTexture(void){
GLenum type = GL_UNSIGNED_BYTE;
if(sizeof(T) == 1){
type = GL_UNSIGNED_BYTE;
}
else if(sizeof(T) == 4){
type = GL_FLOAT;
}
glTexImage2D(m_iTarget, 0, GL_RGBA, m_iW, m_iH, 0, m_iF...
}
};
typedef rxTexObj2D_T<unsigned char> rxTexObj2D;
typedef rxTexObj2D_T<float> rxTexObj2Df;
}}
***材質クラス [#be975cfa]
OpenGLでの表面材質を管理するクラス.
g_matDefaultはデフォルトマテリアルを定義している.
#code(C){{
//-------------------------------------------------------...
// 材質データ
//-------------------------------------------------------...
class rxMaterial
{
public:
Vec4 m_vDiff, m_vSpec, m_vAmbi, m_vEmit;
double m_fDiffS, m_fSpecS, m_fAmbiS, m_fEmitS;
double m_fShin;
Vec4 m_vColor;
// 屈折,鏡面反射パラメータ
double m_fEta; //!< 屈折率
double m_fBias; //!< Fresnelバイアス
double m_fPower; //!< Fresnel指数
double m_fScale; //!< Fresnel倍率
string m_strName;
int m_iID;
int m_iIllum;
string m_strTexFile;
unsigned int m_uTexName;
public:
rxMaterial()
{
SetColor(Vec3(0.0, 0.0, 1.0), Vec3(1.0), Vec3(1.0), Vec...
SetScale(1.0, 0.75, 0.2, 0.0);
m_fEta = 0.9;
m_fBias = 1.0;
m_fPower = 0.98;
m_fScale = 5.0;
}
void SetColor(const Vec4 &diff, const Vec4 &spec, const ...
{
m_vDiff = diff;
m_vSpec = spec;
m_vAmbi = ambi;
m_vEmit = emit;
m_fShin = shin;
}
void SetColor(const GLfloat diff[4],
const GLfloat spec[4],
const GLfloat ambi[4],
const GLfloat emit[4],
const GLfloat shine)
{
m_vDiff = Vec4(diff[0], diff[1], diff[2], diff[3]);
m_vSpec = Vec4(spec[0], spec[1], spec[2], spec[3]);
m_vAmbi = Vec4(ambi[0], ambi[1], ambi[2], ambi[3]);
m_vEmit = Vec4(emit[0], emit[1], emit[2], emit[3]);
m_fShin = shine;
}
void SetColor(const Vec3 &diff, const Vec3 &spec, const ...
{
m_vDiff = diff; m_vDiff[3] = 1.0;
m_vSpec = spec; m_vSpec[3] = 1.0;
m_vAmbi = ambi; m_vAmbi[3] = 1.0;
m_vEmit = emit; m_vEmit[3] = 1.0;
m_fShin = shin;
}
void SetDiff(const Vec4 &col){ m_vDiff = col; }
void SetSpec(const Vec4 &col){ m_vSpec = col; }
void SetAmbi(const Vec4 &col){ m_vAmbi = col; }
void SetEmit(const Vec4 &col){ m_vEmit = col; }
void SetDiff3(const Vec3 &col){ m_vDiff = col; m_vDiff[3...
void SetSpec3(const Vec3 &col){ m_vSpec = col; m_vSpec[3...
void SetAmbi3(const Vec3 &col){ m_vAmbi = col; m_vAmbi[3...
void SetEmit3(const Vec3 &col){ m_vEmit = col; m_vEmit[3...
void SetScale(const double &sdiff, const double &sspec, ...
{
m_fDiffS = sdiff;
m_fSpecS = sspec;
m_fAmbiS = sambi;
m_fEmitS = semit;
}
void SetRefrac(const double &eta, const double &bias, co...
{
m_fEta = eta;
m_fBias = bias;
m_fPower = power;
m_fScale = scale;
}
void SetGL(void)
{
GLfloat mat_diff[] = { (float)(m_fDiffS*m_vDiff[0]), (f...
GLfloat mat_spec[] = { (float)(m_fSpecS*m_vSpec[0]), (f...
GLfloat mat_ambi[] = { (float)(m_fAmbiS*m_vAmbi[0]), (f...
GLfloat mat_shin[] = { (float)m_fShin };
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diff);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambi);
glMaterialfv(GL_FRONT, GL_SHININESS,mat_shin);
glColor3fv(mat_diff);
}
void SetGL(const Vec4 &diff, const Vec4 &spec, const Vec...
{
GLfloat mat_diff[] = { (float)(m_fDiffS*diff[0]), (floa...
GLfloat mat_spec[] = { (float)(m_fSpecS*spec[0]), (floa...
GLfloat mat_ambi[] = { (float)(m_fAmbiS*ambi[0]), (floa...
GLfloat mat_shin[] = { (float)m_fShin };
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diff);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambi);
glMaterialfv(GL_FRONT, GL_SHININESS,mat_shin);
glColor4fv(mat_diff);
}
// アクセスメソッド
Vec4 GetDiff(void) const { return m_vDiff*m_fDiffS; }
Vec4 GetSpec(void) const { return m_vSpec*m_fSpecS; }
Vec4 GetAmbi(void) const { return m_vAmbi*m_fAmbiS; }
Vec4 GetEmit(void) const { return m_vEmit*m_fEmitS; }
Vec3 GetDiff3(void) const { return Vec3(m_vDiff[0], m_vD...
Vec3 GetSpec3(void) const { return Vec3(m_vSpec[0], m_vS...
Vec3 GetAmbi3(void) const { return Vec3(m_vAmbi[0], m_vA...
Vec3 GetEmit3(void) const { return Vec3(m_vEmit[0], m_vE...
double GetShin(void) const { return m_fShin; }
Vec3 GetReflec(const Vec3 &irr, const Vec3 &nrm)
{
double ref_coef = m_fBias+m_fScale*pow((1.0+dot(irr, nr...
RXFunc::Clamp(ref_coef, 0.0, 1.0);
return ref_coef*GetSpec3();
}
Vec3 GetRefrac(const Vec3 &irr, const Vec3 &nrm)
{
double ref_coef = m_fBias+m_fScale*pow((1.0+dot(irr, nr...
RXFunc::Clamp(ref_coef, 0.0, 1.0);
return (1.0-ref_coef)*GetSpec3();
}
void Get(Vec3 &diff, Vec3 &spec, Vec3 &ambi, Vec3 &emit,...
{
diff = Vec3(m_vDiff[0], m_vDiff[1], m_vDiff[2]);
spec = Vec3(m_vSpec[0], m_vSpec[1], m_vSpec[2]);
ambi = Vec3(m_vAmbi[0], m_vAmbi[1], m_vAmbi[2]);
emit = Vec3(m_vEmit[0], m_vEmit[1], m_vEmit[2]);
shin = m_fShin;
}
};
static rxMaterial g_matDefault;
}}
***マウスピッククラス [#e411292a]
コンストラクタかSet関数で描画関数,投影変換関数を指定して,
Pick関数にマウス座標(スクリーン座標系)を渡すことで,ポリ...
クラスに渡す描画関数内ではglLoadNameで各オブジェクトのイ...
Pick関数はこのインデックスを返す.
#code(C){{
//-------------------------------------------------------...
// OpenGLによるオブジェクトピック
//-------------------------------------------------------...
class rxGLPick
{
boost::function<void (void)> m_fpDraw; //!< ピック用描画...
boost::function<void (void)> m_fpProj; //!< 投影変換関数
int m_pSelBufferSize;
public:
rxGLPick()
{
m_pSelBufferSize = 128;
}
rxGLPick(boost::function<void (void)> draw, boost::funct...
: m_fpDraw(draw), m_fpProj(proj)
{
m_pSelBufferSize = 128;
}
~rxGLPick(){}
void Set(boost::function<void (void)> draw, boost::funct...
{
m_fpDraw = draw;
m_fpProj = proj;
}
protected:
/*!
* OpenGLによるピックでヒットしたものから最小のデプス値...
* @param hits ヒット数
* @param buf 選択バッファ
* @return ヒットしたオブジェクト番号
*/
int selectHits(GLint hits, GLuint buf[])
{
GLuint hit_name;
float depth_min = 100.0f;
float depth1 = 1.0f;
float depth2 = 1.0f;
GLuint depth_name;
GLuint *ptr;
// ヒットしたデータなし
if(hits <= 0) return -1;
// ポインタを作業用ptrへ渡す.
ptr = (GLuint*)buf;
for(int i = 0; i < hits; ++i){
// 識別番号の階層の深さ
depth_name = *ptr;
ptr++;
depth1 = (float) *ptr/0x7fffffff;
ptr++;
depth2 = (float) *ptr/0x7fffffff;
ptr++;
// 最小デプスの確認
if(depth_min > depth1){
depth_min = depth1;
hit_name = *ptr;
}
ptr++;
}
return hit_name;
}
/*!
* マウス選択
* @param[in] x,y マウス座標
* @retval int ピックオブジェクト番号
*/
int pick(int x, int y)
{
// HCK:Pick
GLuint* selbuf = new GLuint[m_pSelBufferSize];
GLint hits;
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glSelectBuffer(m_pSelBufferSize, selbuf);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(x, viewport[3]-y, 10.0, 10.0, viewport);
m_fpProj();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
m_fpDraw();
glLoadName(0);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopName();
hits = glRenderMode(GL_RENDER);
int obj_number = selectHits(hits, selbuf);
glMatrixMode(GL_MODELVIEW);
return obj_number;
}
public:
/*!
* オブジェクトのマウス選択
* @param[in] x,y マウス座標
* @retval true ピック成功
* @retval false ピック失敗
*/
int Pick(int x, int y)
{
int obj_number;
if((obj_number = pick(x, y)) != -1){
return obj_number;
}
else{
return -1;
}
//Zバッファ値をゲット
// object_depth = PickDepth(x,y);
return -1;
}
};
}}
終了行:
必要なときにコピペするためのもの.
----
#contents
----
*描画関数 [#r8efd250]
***グリッド描画 [#xb859bb1]
#code(C){{
/*!
* グリッド描画(x-y軸平面)
* @param[in] d 分割数
* @param[in] x,y グリッド全体のside length
* @param[in] h グリッドの高さ
*/
static int DrawGroundGrid(int d, double x, double y, doub...
{
glPushMatrix();
glDisable(GL_LIGHTING);
glColor3f(1,0,0);
glLineWidth(6.0);
glBegin(GL_LINE_LOOP);
glVertex3d(-x, y, h);
glVertex3d( x, y, h);
glVertex3d( x, -y, h);
glVertex3d(-x, -y, h);
glEnd();
glLineWidth(3.0);
// x方向
float x0, x1, y0, y1;
float deltaX, deltaY;
x0 = -x; x1 = -x;
y0 = -y; y1 = y;
deltaX = (2*x)/d;
for(int i = 0; i < d; ++i){
x0 = x0 + deltaX;
glBegin(GL_LINES);
glVertex3f(x0, y0, h);
glVertex3f(x0, y1, h);
glEnd();
}
// y方向
x0 = -x; x1 = x;
deltaY = (2*y)/d;
for(int i = 0; i < d; ++i){
y0 = y0 + deltaY;
glBegin(GL_LINES);
glVertex3f(x0, y0, h);
glVertex3f(x1, y0, h);
glEnd();
}
glLineWidth(1.0);
glPopMatrix();
return 0;
}
}}
***ポリゴン描画 [#x93b90cd]
rxMaterialは下の材質クラスを参照.
#code(C){{
/*!
* 単一ポリゴンの描画
* @param[in] verts 頂点座標格納コンテナ
* @param[in] index 頂点位相
* @param[in] norm ポリゴン法線
* @param[in] color 描画色
*/
inline void DrawPolygon(const vector<Vec3> &verts, const ...
{
glBegin(GL_POLYGON);
glColor3f(color[0], color[1], color[2]);
for(int i = 0; i < (int)index.size(); ++i){
glVertex3dv(verts[index[i]-1].data);
}
glEnd();
}
/*!
* OpenGLによるグローシェーディングで単一ポリゴン描画
* @param[in] poly ポリゴン
* @param[in] color 描画色
*/
inline void DrawPolygonGouraud(const vector<Vec3> &verts,...
const vector<Vec3> &norms, const Vec3 &color)
{
Vec3 norm;
Vec3 vert;
glColor3f(color[0], color[1], color[2]);
glBegin(GL_POLYGON);
for(int i = 0; i < (int)index.size(); ++i){
glNormal3dv(norms[index[i]-1].data);
glVertex3dv(verts[index[i]-1].data);
}
glEnd();
}
/*!
* OpenGLによるグローシェーディングで複数ポリゴン描画(ポ...
* @param[in] polys ポリゴンを格納したコンテナ
* @param[in] gmat 全体の材質
*/
static void DrawPolygons(const vector<Vec3> &vrts, const ...
rxMaterial *gmat, bool select)
{
int i;
rxMaterial *mat;
for(i = 0; i < (int)idxs.size(); ++i){
if(gmat == NULL){
mat = &g_matDefault;
}
else{
mat = gmat;
}
if(select) glLoadName(i);
mat->SetGL();
glEnable(GL_LIGHTING);
DrawPolygon(vrts, idxs[i], mat->GetDiff3());
}
}
/*!
* OpenGLによるグローシェーディングで複数ポリゴン描画(頂...
* @param[in] polys ポリゴンを格納したコンテナ
* @param[in] gmat 全体の材質
*/
static void DrawPolygonsGouraud(const vector<Vec3> &vrts,...
const vector<Vec3> &nrms,
rxMaterial *gmat, bool select)
{
int i;
rxMaterial *mat;
for(i = 0; i < (int)idxs.size(); ++i){
if(gmat == NULL){
mat = &g_matDefault;
}
else{
mat = gmat;
}
if(select) glLoadName(i);
mat->SetGL();
glEnable(GL_LIGHTING);
DrawPolygonGouraud(vrts, idxs[i], nrms, mat->GetDiff3());
}
}
}}
***傾いた直方体描画 [#e72399ce]
glRotate使用版
#code(C){{
/*!
* cenを中心で辺の長さがlen,dirの方向を向いた直方体の描画
* @param[in] cen 直方体の中心
* @param[in] len 直方体の辺の長さ(x,y,z)
* @param[in] dir 直方体のx軸の向き
*/
inline void DrawSolidCuboid(Vec3 cen, Vec3 len, Vec3 dir)
{
Vec3 org_axis(1.0, 0.0, 0.0);
Vec3 tgt_axis = Unit(dir);
Vec3 rot_axis = Unit(cross(org_axis, tgt_axis));
double rot_angle = acos((double)(dot(org_axis, tgt_axis)...
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glRotatef(RX_TO_DEGREES(rot_angle), rot_axis[0], rot_axi...
DrawSolidCuboid(Vec3(0.0), len);
glPopMatrix();
}
}}
コーナー座標値算出版
#code(C){{
/*!
* cenを中心で辺の長さがlen,dirの方向を向いた直方体の描画
* @param[in] cen 直方体の中心
* @param[in] len 直方体の辺の長さ(x,y,z)
* @param[in] dir 直方体のx軸の向き
*/
inline void DrawSolidCuboid(Vec3 cen, Vec3 len, Vec3 dir)
{
len *= 0.5;
dir = Unit(dir);
Vec3 up(0.0, 1.0, 0.0);
Vec3 right = cross(dir, up);
Vec3 nc = cen-dir*len[0];
Vec3 fc = cen+dir*len[0];
right = Unit(right);
up = Unit(cross(right, dir));
Vec3 corner[8];
corner[0] = nc-up*len[1]-right*len[2];
corner[1] = nc+up*len[1]-right*len[2];
corner[2] = nc+up*len[1]+right*len[2];
corner[3] = nc-up*len[1]+right*len[2];
corner[4] = fc-up*len[1]-right*len[2];
corner[5] = fc+up*len[1]-right*len[2];
corner[6] = fc+up*len[1]+right*len[2];
corner[7] = fc-up*len[1]+right*len[2];
int index[6][4] = { { 3, 2, 1, 0 },
{ 4, 5, 6, 7 },
{ 3, 0, 4, 7 },
{ 1, 2, 6, 5 },
{ 0, 1, 5, 4 },
{ 2, 3, 7, 6 } };
glPushMatrix();
glBegin(GL_QUADS);
// 前後面
glNormal3dv((-dir).data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[0][i...
glNormal3dv(dir.data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[1][i...
// 上下側面
glNormal3dv((-up).data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[2][i...
glNormal3dv(up.data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[3][i...
// 左右側面
glNormal3dv((-right).data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[4][i...
glNormal3dv(right.data);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[5][i...
glEnd();
glPopMatrix();
}
}}
***直方体描画 [#c7cf7534]
#code(C){{
/*!
* cenを中心で辺の長さがlenの直方体の描画
* @param[in] cen 直方体の中心
* @param[in] len 直方体の辺の長さ(x,y,z)
*/
inline void DrawSolidCuboid(Vec3 &cen, Vec3 len)
{
len *= 0.5;
Vec3 corner[8];
corner[0] = cen+Vec3(-len[0], -len[1], -len[2]);
corner[1] = cen+Vec3(-len[0], len[1], -len[2]);
corner[2] = cen+Vec3(-len[0], len[1], len[2]);
corner[3] = cen+Vec3(-len[0], -len[1], len[2]);
corner[4] = cen+Vec3( len[0], -len[1], -len[2]);
corner[5] = cen+Vec3( len[0], len[1], -len[2]);
corner[6] = cen+Vec3( len[0], len[1], len[2]);
corner[7] = cen+Vec3( len[0], -len[1], len[2]);
int index[6][4] = { { 3, 2, 1, 0 },
{ 4, 5, 6, 7 },
{ 3, 0, 4, 7 },
{ 1, 2, 6, 5 },
{ 0, 1, 5, 4 },
{ 2, 3, 7, 6 } };
glPushMatrix();
glBegin(GL_QUADS);
// x軸に垂直な面
glNormal3d(-1.0, 0.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[0][i...
glNormal3d( 1.0, 0.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[1][i...
// y軸に垂直な面
glNormal3d(0.0, -1.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[2][i...
glNormal3d(0.0, 1.0, 0.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[3][i...
// z軸に垂直な面
glNormal3d(0.0, 0.0, -1.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[4][i...
glNormal3d(0.0, 0.0, 1.0);
for(int i = 0; i < 4; ++i) glVertex3dv(corner[index[5][i...
glEnd();
glPopMatrix();
}
}}
***立方体描画(ディスプレイリスト使用) [#e72399ce]
vector<Vec3>は配列にした方が効率がよいかも.scaleやwireは...
#code(C){{
static void DrawCube(double scale = 0.5, bool wire = false)
{
using namespace boost::assign;
static GLuint polyList = 0;
vector<Vec3> vrts, cols;
vrts += Vec3( 1.0, 1.0, 1.0), \
Vec3( 1.0, -1.0, 1.0), \
Vec3(-1.0, -1.0, 1.0), \
Vec3(-1.0, 1.0, 1.0), \
Vec3( 1.0, 1.0, -1.0), \
Vec3( 1.0, -1.0, -1.0), \
Vec3(-1.0, -1.0, -1.0), \
Vec3(-1.0, 1.0, -1.0);
cols += Vec3(1.0, 1.0, 1.0), \
Vec3(1.0, 1.0, 0.0), \
Vec3(0.0, 1.0, 0.0), \
Vec3(0.0, 1.0, 1.0), \
Vec3(1.0, 0.0, 1.0), \
Vec3(1.0, 0.0, 0.0), \
Vec3(0.0, 0.0, 0.0), \
Vec3(0.0, 0.0, 1.0);
const short faces[6][4] = { {3, 2, 1, 0},
{2, 3, 7, 6},
{0, 1, 5, 4},
{3, 0, 4, 7},
{1, 2, 6, 5},
{4, 5, 6, 7} };
GLint num_faces = 6;
if(!polyList){
polyList = glGenLists(1);
glNewList(polyList, GL_COMPILE);
if(!wire){
glBegin(GL_QUADS);
for(int f = 0; f < num_faces; ++f){
for(int i = 0; i < 4; ++i){
glColor3dv(cols[faces[f][i]].data);
glVertex3dv((vrts[faces[f][i]]*scale).data);
}
}
glEnd();
}
glColor3f(0.0, 0.0, 0.0);
for(int f = 0; f < num_faces; ++f){
glBegin(GL_LINE_LOOP);
for(int i = 0; i < 4; ++i){
glVertex3dv((vrts[faces[f][i]]*scale).data);
}
glEnd();
}
glEndList();
}
glPushMatrix();
glCallList(polyList);
glPopMatrix();
}
}}
***円筒描画 [#e43fca86]
DrawCylinderは円筒,DrawCapsuleは両端が半球状の円筒.
#code(C){{
/*!
* 円筒描画
* @param[in] rad,len 半径と中心軸方向長さ
* @param[in] axis 軸方向
* @param[in] slices ポリゴン近似する際の分割数
*/
static void DrawCylinder(double rad, double len, int axis...
{
GLUquadricObj *qobj;
qobj = gluNewQuadric();
glPushMatrix();
switch(axis){
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 2:
glTranslatef(0.0, 0.0, -0.5*len);
break;
default:
glTranslatef(0.0, 0.0, -0.5*len);
}
gluQuadricDrawStyle(qobj, GLU_FILL);
gluQuadricNormals(qobj, GLU_SMOOTH);
gluCylinder(qobj, rad, rad, len, slices, slices);
glPushMatrix();
glRotatef(180.0, 1.0, 0.0, 0.0);
gluDisk(qobj, 0.0, rad, slices, slices);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, len);
gluDisk(qobj, 0.0, rad, slices, slices);
glPopMatrix();
glPopMatrix();
}
/*!
* カプセル描画(円筒の両端に半球をつけた形)
* @param[in] rad,len 半径と中心軸方向長さ
* @param[in] axis 軸方向
* @param[in] slices ポリゴン近似する際の分割数
*/
static void DrawCapsule(double rad, double len, int axis,...
{
GLUquadricObj *qobj;
qobj = gluNewQuadric();
glPushMatrix();
switch(axis){
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 2:
glTranslatef(0.0, 0.0, -0.5*len);
break;
default:
glTranslatef(0.0, 0.0, -0.5*len);
}
gluQuadricDrawStyle(qobj, GLU_FILL);
gluQuadricNormals(qobj, GLU_SMOOTH);
gluCylinder(qobj, rad, rad, len, slices, slices);
glPushMatrix();
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, len);
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glPopMatrix();
}
}}
ワイヤフレーム描画時に不自然にならないように両端の球をち...
#code(C){{
/*!
* カプセル描画(円筒の両端に半球をつけた形)
* - ワイヤフレーム描画時に不自然にならないように両端の...
* @param[in] rad,len 半径と中心軸方向長さ
* @param[in] axis 軸方向
* @param[in] slices ポリゴン近似する際の分割数
*/
void DrawCapsule(double rad, double len, int axis, int sl...
{
GLUquadricObj *qobj;
qobj = gluNewQuadric();
glPushMatrix();
switch(axis){
case 0:
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 1:
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.0, -0.5*len);
break;
case 2:
glTranslatef(0.0, 0.0, -0.5*len);
break;
default:
glTranslatef(0.0, 0.0, -0.5*len);
}
gluQuadricDrawStyle(qobj, GLU_FILL);
gluQuadricNormals(qobj, GLU_SMOOTH);
gluCylinder(qobj, rad, rad, len, slices, slices);
double c_init[4] = {0, 0, 0, 0};
double c_bottom[4] = {0, 0, -1, 0};
double c_top[4] = {0, 0, 1, 0};
glEnable(GL_CLIP_PLANE0);
glPushMatrix();
glClipPlane(GL_CLIP_PLANE0, c_bottom);
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glPushMatrix();
glTranslatef(0.0, 0.0, len);
glClipPlane(GL_CLIP_PLANE0, c_top);
glutSolidSphere(rad, slices, slices);
glPopMatrix();
glClipPlane(GL_CLIP_PLANE0, c_init);
glDisable(GL_CLIP_PLANE0);
glPopMatrix();
}
}}
GLUを使わないで円筒を描画する場合.
z軸平行で描画される.
#code(C){{
/*!
* 円筒形の描画(z軸平行,底面が原点)
* @param[in] r 円筒半径
* @param[in] h 返答長さ
* @param[in] slice 円の分割数
* @param[in] stack 長さ方向の分割数
*/
void DrawCylinder(double r, double h, int slice)
{
double theta = 2.0*RX_PI/(double)slice;
double n_norm;
Vec3 origin = Vec3(0.0);
vector<Vec3> vert;
vert.resize(slice);
Vec3 normal;
glPushMatrix();
// 天面の描画(y = cen[1]+h)
glNormal3f(0.0, 1.0, 0.0);
glBegin(GL_POLYGON);
for(int i = 0; i < slice; ++i){
vert[i][0] = origin[0]+r*sin(theta*(double)i);
vert[i][1] = origin[1]+r*cos(theta*(double)i);
vert[i][2] = origin[2]+h;
glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
}
glEnd();
// 底面の描画(y = cen[1])
glNormal3f(0.0, -1.0, 0.0);
glBegin(GL_POLYGON);
for(int i = 0; i < slice; ++i){
vert[i][2] = origin[2];
glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
}
glEnd();
// 側面の描画
glBegin(GL_QUAD_STRIP);
int j;
for(int i = 0; i < slice; ++i){
j = (i+1)%slice;
normal = 0.5*(vert[i]+vert[j]);
normal = origin-normal;
n_norm = norm(normal);
if(n_norm > RX_EPS) normal /= n_norm;
glNormal3f(normal[0], normal[1], normal[2]);
glVertex3f(vert[i][0], vert[i][1], vert[i][2]);
glVertex3f(vert[i][0], vert[i][1], vert[i][2]+h);
}
glVertex3f(vert[j][0], vert[j][1], vert[j][2]);
glVertex3f(vert[j][0], vert[j][1], vert[j][2]+h);
glEnd();
glPopMatrix();
}
}}
***キューブマップ描画 [#j8bc13ff]
#code(C){{
/*!
* キューブマップテクスチャを内部に貼り付けた立方体の描画
* @param[in] cube_map キューブマップ
* @param[in] side 立方体の一辺の長さ
*/
void RxGLDraw::DrawCubeMap(GLuint cube_map, double side)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
// キューブマップテクスチャをバインド
glEnable(GL_TEXTURE_CUBE_MAP);
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_map);
// GL_OBJECT_LINEARテクスチャ座標を設定
glPushMatrix();
GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
glTexGenfv(GL_S, GL_OBJECT_PLANE, s_plane);
glTexGenfv(GL_T, GL_OBJECT_PLANE, t_plane);
glTexGenfv(GL_R, GL_OBJECT_PLANE, r_plane);
glPopMatrix();
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
// シーンを覆う大きさの立方体を描画
glPushMatrix();
glutSolidCube(side);
glPopMatrix();
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glDisable(GL_TEXTURE_CUBE_MAP);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
}}
***矢印描画 [#j5da7c54]
2Dの場合
#code(C){{
/*!
* 矢印の描画
* @param[in] s 矢印の始点
* @param[in] e 矢印の始点
* @param[in] scale 傘の部分の大きさ(全体の長さに対する係...
*/
inline static void DrawArrow2D(const Vec2 &s, const Vec2 ...
{
// 始点,方向,長さ
Vec2 origin = s;
Vec2 dir = e-s;
double length = normalize(dir);
// ベクトル(1,0)との間の角度
double theta = 180.0/RX_PI*acos(dot(Vec2(1, 0), dir))*RX...
// 矢印の傘部分の設定
double arrow_x = scale*length; // 軸方向の長さ
//double arrow_y = arrow_x*0.174532925; // 軸に垂直...
double arrow_y = arrow_x*0.363970234; // 軸に垂直な...
glPushMatrix();
glTranslatef(origin[0], origin[1], 0.0); // 矢印原...
glRotatef(theta, 0.0, 0.0, 1.0); // 矢印方...
glBegin(GL_LINES);
// 軸
glVertex2d(0.0, 0.0);
glVertex2d(length, 0.0);
// 傘
glVertex2d(length, 0.0);
glVertex2d(length-arrow_x, arrow_y);
glVertex2d(length, 0.0);
glVertex2d(length-arrow_x, -arrow_y);
glEnd();
glPopMatrix();
}
}}
3Dの場合(3DベクトルクラスVec3と上の円筒描画,下の任意ベク...
#code(C){{
/*!
* ベクトルを矢印で描画
* @param[in] pos 原点座標
* @param[in] vec ベクトル
* @param[in] r 軸の半径
* @param[in] dr 矢印の傘部分の半径(軸の半径を1としたと...
* @param[in] dl 矢印の傘部分の長さ(全体の長さを1とした...
*/
void DrawArrow(Vec3 pos, Vec3 vec, double r, double dr = ...
{
double vlen = norm(vec);
Vec3 pos1 = pos+vec*(1.0-dl*0.5);
Vec3 init = Vec3(0.0, 0.0, 1.0); // 円筒と円錐描画はデフ...
// vecとz軸の間の回転角度と回転軸
double rot_ang = acos(dot(init, Unit(vec)))*57.295779513...
Vec3 rot_axis = Unit(cross(init, Unit(vec)));
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]); // 原点に移動
glRotatef(rot_ang, rot_axis[0], rot_axis[1], rot_axis[2]...
// ベクトルの軸部分
DrawCylinder(r, vlen*(1.0-dl*0.5), 16);
// ベクトルの傘部分
double alen = dl*vlen; // 円錐の高さ
double arad = dr*r; // 円錐の半径
pos1 = pos+vec;
glTranslatef(0.0, 0.0, vlen-alen);
glutSolidCone(arad, alen, 16, 16);
glPopMatrix();
}
}}
***文字描画 [#f4c43bc4]
#code{{
/*!
* 文字列描画
* @param[in] static_str 文字列
* @param[in] w,h ウィンドウサイズ
*/
static void DrawStrings(vector<string> &static_str, int w...
{
glDisable(GL_LIGHTING);
// 平行投影にする
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
float x0 = 5.0f;
float y0 = h-20.0f;
// 画面上部にテキスト描画
for(int j = 0; j < (int)static_str.size(); ++j){
glRasterPos2f(x0, y0);
int size = (int)static_str[j].size();
for(int i = 0; i < size; ++i){
char ic = static_str[j][i];
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
}
y0 -= 20;
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
}}
呼び出す前にglColorで色の設定をしておく.
boost::circular_bufferを使ってコマンドプロンプトのように...
#code(C){{
typedef boost::circular_buffer<string> CircularBuf;
// 循環バッファ
static CircularBuf g_cbDrawDef(5);
static vector<string> g_cbDrawStaticDef(3);
template<typename T>
inline CircularBuf &operator<<(CircularBuf &cb, const T &a)
{
string buf = boost::lexical_cast<std::string>(a);
if(buf == "\n"){
cb.push_back("");
}
else if(cb.empty()){
cb.push_back(buf);
}
else{
cb.back() += buf;
}
return cb;
}
template<typename T>
inline string &operator<<(string &cb, const T &a)
{
cb += boost::lexical_cast<std::string>(a);
return cb;
}
/*!
* 文字列描画
* @param[in] cir_str 文字列循環バッファ
* @param[in] static_str 静的な文字列バッファ
* @param[in] w,h ウィンドウサイズ
*/
static void DrawStrings(CircularBuf cir_str, vector<strin...
{
// MRK:PrintD
glDisable(GL_LIGHTING);
//glColor3f(0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
float x0 = 5;
float y0 = h-20;
// 画面上部にスタティックなテキスト
for(int j = 0; j < (int)static_str.size(); ++j){
glRasterPos2f(x0, y0);
int size = (int)static_str[j].size();
for(int i = 0; i < size; ++i){
char ic = static_str[j][i];
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
}
y0 -= 20;
}
// 画面下部に循環バッファを使ったテキスト
x0 = 5;
y0 = 20*cir_str.size();;
for(int j = 0; j < (int)cir_str.size(); ++j){
glRasterPos2f(x0, y0);
int size = (int)cir_str[j].size();
for(int i = 0; i < size; ++i){
char ic = cir_str[j][i];
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, ic);
}
y0 -= 20;
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
}}
***三角形メッシュ描画(法線計算付き) [#yee58253]
#code(C){{
/*!
* 三角形メッシュ描画
* @param[in] vrts 頂点列
* @param[in] idxes メッシュを構成する頂点インデックス(0...
* @param[in] normal 法線描画ON/OFF
*/
void DrawMesh(const vector<Vec3> &vrts, const vector< vec...
{
for(int i = 0; i < (int)idxes.size(); ++i){
vector<int> idx = idxes[i];
int nv = (int)idx.size();
// 法線
Vec3 nrm;
nrm = cross(vrts[idx[1]]-vrts[idx[0]], vrts[idx[nv-1]]-...
normalize(nrm);
if(normal){
// 重心を求める
Vec3 mc(0.0);
for(int j = 0; j < nv; ++j){
mc += vrts[idx[j]];
}
mc /= (double)nv;
int lighting = glIsEnabled(GL_LIGHTING);
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glVertex3dv(mc.data);
glVertex3dv((mc+0.05*nrm).data);
glEnd();
lighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTI...
}
glNormal3dv(nrm.data);
// 面
glBegin(GL_POLYGON);
for(int j = 0; j < nv; ++j){
glVertex3dv(vrts[idx[j]].data);
}
glEnd();
}
}
}}
法線は面の重心に描画される.Vec3はオペレータ[]で各要素に...
***球の描画 [#sc7c38dc]
#code(C){{
/*!
* 球の描画
* @param[in] cen 球の中心
* @param[in] rad 球の半径
* @param[in] col 描画色(拡散反射色)
*/
inline void DrawSphere(const Vec3 &cen, const double &rad...
{
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glRotated(90, 1.0, 0.0, 0.0);
glutSolidSphere(rad, 20, 10);
glPopMatrix();
}
}}
***球の(滑らかな)ワイヤーフレーム描画 [#t159f84d]
#code(C){{
/*!
* 原点中心の円のワイヤーフレーム描画
* @param rad 円の半径
* @param n 分割数
*/
static void DrawWireCircle(const double &rad, const int &n)
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glBegin(GL_LINE_LOOP);
do{
glVertex3f(rad*cos(t), rad*sin(t), 0.0);
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
}
/*!
* 原点中心の円のワイヤーフレーム描画(XZ平面)
* @param rad 円の半径
* @param n 分割数
*/
static void DrawWireCircleXZ(const double &rad, const int...
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glBegin(GL_LINE_LOOP);
do{
glVertex3f(rad*cos(t), 0.0, rad*sin(t));
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
}
/*!
* 球のワイヤーフレーム描画
* @param cen 球の中心
* @param rad 球の半径
* @param col 描画色
*/
void DrawWireSphere(const Vec3 &cen, const float &rad, co...
{
glDisable(GL_LIGHTING);
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glRotatef(90, 1.0, 0.0, 0.0);
glColor3f(col[0], col[1], col[2]);
// 緯度(x-y平面に平行)
float z, dz;
dz = 2.0*rad/8.0f;
z = -(rad-dz);
do{
glPushMatrix();
glTranslatef(0.0, 0.0, z);
DrawWireCircle(sqrt(rad*rad-z*z), 32);
glPopMatrix();
z += dz;
}while(z < rad);
// 経度(z軸まわりに回転)
float t, dt;
t = 0.0f;
dt = 180.0/8.0;
do{
glPushMatrix();
glRotatef(t, 0.0, 0.0, 1.0);
DrawWireCircleXZ(rad, 32);
glPopMatrix();
t += dt;
}while(t < 180);
//glutWireSphere(rad, 10, 5);
glPopMatrix();
}
}}
***円の描画 [#w796138f]
x-y平面上に円を描画.
#code(C){{
/*!
* 円の描画
* @param cen 円の中心
* @param rad 円の半径
* @param n 分割数
*/
static void DrawCircle(Vec3 cen, double rad, int n)
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glBegin(GL_POLYGON);
do{
glVertex3f(rad*cos(t), rad*sin(t), 0.0);
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
glPopMatrix();
}
/*!
* 円のワイヤーフレーム描画
* @param cen 円の中心
* @param rad 円の半径
* @param n 分割数
*/
static void DrawWireCircle(Vec3 cen, double rad, int n)
{
double t = 0.0;
double dt = 2.0*RX_PI/(double)n;
glPushMatrix();
glTranslatef(cen[0], cen[1], cen[2]);
glBegin(GL_LINE_LOOP);
do{
glVertex3f(rad*cos(t), rad*sin(t), 0.0);
t += dt;
}while(t < 2.0*RX_PI);
glEnd();
glPopMatrix();
}
}}
Vec3はオペレータ[]で各要素にアクセスできる3次元ベクトルク...
*アフィン変換 [#w6072353]
***回転 [#hc5f8f47]
#code(C){{
//! degree -> radian の変換係数(pi/180.0)
const double RX_DEGREES_TO_RADIANS = 0.017453292519943295...
//! degree -> radian の変換
template<class T>
inline T RX_TO_RADIANS(const T &x){ return static_cast<T>...
/*!
* 座標の回転
* @param[in] pos 回転したい座標値
* @param[in] rot_deg x,y,z軸周りの回転角(deg)
* @return 回転後の座標値
*/
inline Vec3 RxRotate(const Vec3 &pos, const Vec3 &rot_deg)
{
Vec3 pos1;
Vec3 rot = RX_TO_RADIANS(rot_deg);
Vec3 S(sin(rot[0]), sin(rot[1]), sin(rot[2]));
Vec3 C(cos(rot[0]), cos(rot[1]), cos(rot[2]));
pos1[0] = C[1]*C[2]*pos[0] ...
pos1[1] = (S[0]*S[1]*C[2]+C[0]*S[2])*pos[0] +(-S[0]*S[1...
pos1[2] = (-C[0]*S[1]*C[2]+S[0]*S[2])*pos[0] +(C[0]*S[1...
return pos1;
}
/*!
* 座標の回転(2D)
* @param[in] pos 回転したい座標値
* @param[in] rot_deg z軸周りの回転角(deg)
* @return 回転後の座標値
*/
inline Vec2 RxRotate2D(const Vec2 &pos, double rot_deg)
{
double rot = RX_TO_RADIANS(rot_deg);
return Vec2(pos[0]*cos(rot)-pos[1]*sin(rot), pos[0]*sin(...
}
}}
***任意ベクトル周りの回転 [#i46bfc4d]
#code(C){{
/*!
* 任意ベクトル周りの回転
* @param[in] pos 元の座標値
* @param[in] axis 回転軸
* @param[in] ang 回転角度(deg)
* @return 回転した座標値
*/
inline Vec3 Rotate(const Vec3 &pos, const Vec3 &axis, con...
{
Vec3 pos1; // 回転後の座標値
double ang = RX_TO_RADIANS(ang_deg);
double c = cos(ang);
double s = sin(ang);
double x, y, z;
x = axis[0]; y = axis[1]; z = axis[2];
// | xx(1-c)+c xy(1-c)-zs xz(1-c)+ys 0 |
// | yx(1-c)+zs yy(1-c)+c yz(1-c)-xs 0 |
// | xz(1-c)-ys yz(1-c)+xs zz(1-c)+c 0 |
// | 0 0 0 1 |
pos1[0] = (x*x*(1.0-c)+c)*pos[0] +(x*y*(1.0-c)-z*s)*po...
pos1[1] = (y*x*(1.0-c)+z*s)*pos[0] +(y*y*(1.0-c)+c)*po...
pos1[2] = (x*z*(1.0-c)-y*s)*pos[0] +(y*z*(1.0-c)+x*s)*po...
return pos1;
}
}}
***オイラー角から回転行列 [#dcb3ea9d]
#code(C){{
/*!
* オイラー角から回転行列(4x4)を生成
* @param[in]
* @param[out]
* @return
*/
inline void EulerToMatrix(double *m, double pitch, double...
{
yaw = RX_TO_RADIANS(yaw);
pitch = RX_TO_RADIANS(pitch);
roll = RX_TO_RADIANS(roll);
double cy = cos(yaw);
double sy = sin(yaw);
double cp = cos(pitch);
double sp = sin(pitch);
double cr = cos(roll);
double sr = sin(roll);
double cc = cy*cr;
double cs = cy*sr;
double sc = sy*cr;
double ss = sy*sr;
m[0] = cc+sp*ss;
m[1] = cs-sp*sc;
m[2] = -sy*cp;
m[3] = 0.0;
m[4] = -cp*sr;
m[5] = cp*cr;
m[6] = -sp;
m[7] = 0.0;
m[8] = sc-sp*cs;
m[9] = ss+sp*cc;
m[10] = cy*cp;
m[11] = 0.0;
m[12] = 0.0;
m[13] = 0.0;
m[14] = 0.0;
m[15] = 1.0;
}
}}
***射影 [#i5f51162]
#code(C){{
/*!
* 任意の平面へ影を射影する行列構築関数
* @param[out] m 作成する行列(4x4)m[16]へのポインタ
* @param[in] plane[4] 射影する表面の平面方程式
* @param[in] light[4] 光源の座標値(同次座標)
*/
inline void ProjectShadowMatrix(double *m, double plane[4...
{
double dot = plane[0]*light[0]+plane[1]*light[1]+plane[2...
m[0] = dot-light[0]*plane[0];
m[4] = -light[0]*plane[1];
m[8] = -light[0]*plane[2];
m[12] = -light[0]*plane[3];
m[1] = -light[1]*plane[0];
m[5] = dot-light[1]*plane[1];
m[9] = -light[1]*plane[2];
m[13] = -light[1]*plane[3];
m[2] = -light[2]*plane[0];
m[6] = -light[2]*plane[1];
m[10] = dot-light[2]*plane[2];
m[14] = -light[2]*plane[3];
m[3] = -light[3]*plane[0];
m[7] = -light[3]*plane[1];
m[11] = -light[3]*plane[2];
m[15] = dot-light[3]*plane[3];
}
}}
*その他関数 [#rdc4e1f5]
***球形状ポリゴン生成 [#k0cf6d98]
#code(C){{
/*!
* 球形状ポリゴン生成
* @param[in] rad 半径
* @param[in] slices z軸まわりの分割数(経線)
* @param[in] stacks z軸に沿ったの分割数(緯線)
* @param[out] vrts 頂点座標
* @param[out] nrms 法線座標
* @param[out] txcs テクスチャ座標
* @param[out] fces ポリゴン(頂点接続)
* @param[in] tri trueで三角形ポリゴン, falseで四角形(た...
* @return 生成頂点数
*/
int MakeSphere(double rad, int slices, int stacks,
vector<Vec3> &vrts, vector<Vec3> &nrms, vector<Vec2...
bool tri = true)
{
int vn = 2+(stacks-1)*slices; // 頂点数(極点2つ+経線・...
vrts.resize(vn, Vec3(0.0)); // 頂点座標
nrms.resize(vn, Vec3(0.0)); // 頂点法線
txcs.resize(vn, Vec2(0.0)); // テクスチャ座標
vrts[0] = Vec3(0.0, 0.0, rad); // 北極点
vrts[vn-1] = Vec3(0.0, 0.0, -rad); // 南極点
double dp = RX_PI/(double)stacks; // Φ(経線に沿った方向...
double dt = 2.0*RX_PI/(double)slices; // Θ(緯線に沿った...
double phi = dp; // 経線に沿った方向の角度(北極点で0)
double theta = 0.0; // 緯線に沿った方向の角度
// 球を構成する頂点の生成
for(int i = 0; i < stacks-1; ++i){
double z = rad*cos(phi);
theta = 0.0;
for(int j = 0; j < slices; ++j){
double rad_t = rad*sin(phi);
int idx = 1+i*slices+j;
vrts[idx] = Vec3(rad_t*cos(theta), rad_t*sin(theta), z);
nrms[idx] = Unit(vrts[idx]);
txcs[idx] = Vec2(theta/(2.0*RX_PI), phi/(RX_PI));
theta += dt;
}
phi += dp;
}
// ポリゴン数
int fn = 2*slices+(stacks-2)*slices*(tri ? 2 : 1);
fces.reserve(fn);
// ポリゴン生成
for(int i = 0; i < stacks; ++i){
if(i == 0){ // 北極点と最初の緯線を接続
vector<int> f(3);
for(int j = 0; j < slices; ++j){
int k0 = 1+i*slices+j;
int k1 = 1+i*slices+(j == slices-1 ? 0 : j+1);
f[0] = 0; f[1] = k0; f[2] = k1;
fces.push_back(f);
}
}
else if(i == stacks-1){ // 南極点と最後の緯線を接続
vector<int> f(3);
for(int j = 0; j < slices; ++j){
int k0 = 1+(i-1)*slices+j;
int k1 = 1+(i-1)*slices+(j == slices-1 ? 0 : j+1);
f[0] = vn-1; f[1] = k1; f[2] = k0;
fces.push_back(f);
}
}
else{
for(int j = 0; j < slices; ++j){
int k0 = 1+i*slices+j;
int k1 = 1+i*slices+(j == slices-1 ? 0 : j+1);
int k2 = 1+(i-1)*slices+j;
int k3 = 1+(i-1)*slices+(j == slices-1 ? 0 : j+1);
vector<int> f;
if(tri){
// 三角形ポリゴンを用いる場合
f.resize(3);
f[0] = k0; f[1] = k1; f[2] = k3;
fces.push_back(f);
f[0] = k0; f[1] = k3; f[2] = k2;
fces.push_back(f);
}
else{
// 四角形ポリゴンを用いる場合
f.resize(4);
f[0] = k0; f[1] = k1; f[2] = k3; f[3] = k2;
fces.push_back(f);
}
}
}
}
return 0;
}
/*!
* 球形状ポリゴン生成(極点,経度0degでの重複あり)
* @param[in] rad 半径
* @param[in] slices z軸まわりの分割数(経線)
* @param[in] stacks z軸に沿ったの分割数(緯線)
* @param[out] vrts 頂点座標
* @param[out] nrms 法線座標
* @param[out] txcs テクスチャ座標
* @param[out] fces ポリゴン(頂点接続)
* @param[in] tri trueで三角形ポリゴン, falseで四角形
* @return 生成頂点数
*/
int MakeSphereC(double rad, int slices, int stacks,
vector<Vec3> &vrts, vector<Vec3> &nrms, vector<Vec2> ...
bool tri = true)
{
int vn = (stacks+1)*(slices+1); // 頂点数(経線・緯線の...
vrts.resize(vn, Vec3(0.0)); // 頂点座標
nrms.resize(vn, Vec3(0.0)); // 頂点法線
txcs.resize(vn, Vec2(0.0)); // テクスチャ座標
double dp = RX_PI/(double)stacks; // Φ(経線に沿った方向...
double dt = 2.0*RX_PI/(double)slices; // Θ(緯線に沿った...
double phi = 0; // 経線に沿った方向の角度(北極点で0)
double theta = 0.0; // 緯線に沿った方向の角度
// 球を構成する頂点の生成
for(int i = 0; i < stacks+1; ++i){
double z = rad*cos(phi);
theta = 0.0;
for(int j = 0; j < slices+1; ++j){
double rad_t = rad*sin(phi);
int idx = i*(slices+1)+j;
vrts[idx] = Vec3(rad_t*cos(theta), rad_t*sin(theta), z);
nrms[idx] = Unit(vrts[idx]);
txcs[idx] = Vec2(theta/(2.0*RX_PI), phi/(RX_PI));
theta += dt;
}
phi += dp;
}
// ポリゴン数
int fn = stacks*slices*(tri ? 2 : 1);
fces.reserve(fn);
// ポリゴン生成
for(int i = 1; i < stacks+1; ++i){
for(int j = 0; j < slices; ++j){
int k0 = i*(slices+1)+j;
int k1 = i*(slices+1)+(j+1);
int k2 = (i-1)*(slices+1)+j;
int k3 = (i-1)*(slices+1)+(j+1);
vector<int> f;
if(tri){
// 三角形ポリゴンを用いる場合
f.resize(3);
f[0] = k0; f[1] = k1; f[2] = k3;
fces.push_back(f);
f[0] = k0; f[1] = k3; f[2] = k2;
fces.push_back(f);
}
else{
// 四角形ポリゴンを用いる場合
f.resize(4);
f[0] = k0; f[1] = k1; f[2] = k3; f[3] = k2;
fces.push_back(f);
}
}
}
return 0;
}
}}
***ミップマップテクスチャのサイズの計算 [#y1859c15]
#code(C){{
/*!
* ミップマップのサイズの計算
* @param[in] x 任意の整数(画像の大きさ)
* @param[out] d x以下の最大の2^d
* @return x以下の最大の2^dとなる解像度
*/
inline int CalMipmapSize(const int &x, int &d)
{
d = (int)(log((double)x)/log(2.0));
return (int)pow(2.0, (double)d);
}
}}
***グラデーション色の作成 [#m477d227]
#code(C){{
//! 値のクランプ(クランプした値を返す)
template<class T>
inline T RX_CLAMP(const T &x, const T &a, const T &b){ re...
//! 1次元線型補間
template<class T>
inline T RX_LERP(const T &a, const T &b, const T &t){ ret...
/*!
* 青->緑->赤->白と変化するサーモグラフ用の色生成
* @param[out] col 生成された色
* @param[in] x 値
* @param[in] xmin 最小値
* @param[in] xmax 最大値
*/
inline void CalThermograph(double col[3], double x, const...
{
double l = xmax-xmin;
if(fabs(l) < 1e-10) return;
const int ncolors = 7;
double base[ncolors][3] = { {0.0, 0.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 1.0, 1.0},
{0.0, 1.0, 0.0},
{1.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{1.0, 1.0, 1.0} };
x = RX_CLAMP(((x-xmin)/l), 0.0, 1.0)*(ncolors-1);
int i = (int)x;
double dx = x-floor(x);
col[0] = RX_LERP(base[i][0], base[i+1][0], dx);
col[1] = RX_LERP(base[i][1], base[i+1][1], dx);
col[2] = RX_LERP(base[i][2], base[i+1][2], dx);
}
/*!
* グラデーション色生成
* @param[out] col 生成された色
* @param[in] col1 x=xminのときの色
* @param[in] col2 x=xmaxのときの色
* @param[in] x 値
* @param[in] xmin 最小値
* @param[in] xmax 最大値
*/
inline void CalGradation(double col[3], const double col1...
double x, const double xmin = 0.0, const double xm...
{
double l = xmax-xmin;
if(fabs(l) < 1e-10) return;
double dx = RX_CLAMP(((x-xmin)/l), 0.0, 1.0);
col[0] = RX_LERP(col1[0], col2[0], dx);
col[1] = RX_LERP(col1[1], col2[1], dx);
col[2] = RX_LERP(col1[2], col2[2], dx);
}
}}
*クラス [#vb8f996e]
***テクスチャ管理クラス [#da4250ba]
#code(C){{
//-------------------------------------------------------...
// MARK:テクスチャデータの基底クラス
//-------------------------------------------------------...
class rxTexObj
{
protected:
GLenum m_iTarget;
bool m_bValid;
bool m_bManageObjects;
GLuint m_iTexName;
public:
// managed = true : デストラクタでオブジェクトを破棄した...
rxTexObj(GLenum tgt, bool managed) : m_iTarget(tgt), m_b...
~rxTexObj()
{
if(m_bManageObjects) Delete();
}
void Bind(void)
{
if(!m_bValid){
Generate();
}
glBindTexture(m_iTarget, m_iTexName);
}
void UnBind(void)
{
glBindTexture(m_iTarget, 0);
}
void SetParameter(GLenum pname, GLint i){ glTexParameter...
void SetParameter(GLenum pname, GLfloat f){ glTexParamet...
void SetParameter(GLenum pname, GLint *ip){ glTexParamet...
void SetParameter(GLenum pname, GLfloat *fp){ glTexParam...
void Enable(void){ glEnable(m_iTarget); }
void Disable(void){ glDisable(m_iTarget); }
GLuint GetTexName(void) const { return m_iTexName; }
GLenum GetTexTarget(void) const { return m_iTarget; }
void Delete()
{
if(m_bValid){
glDeleteTextures(1, &m_iTexName);
m_bValid = false;
}
}
void Generate()
{
glGenTextures(1, &m_iTexName);
m_bValid = true;
}
public:
bool IsValid() const { return m_bValid; }
};
//-------------------------------------------------------...
// MARK:2Dテクスチャデータ
//-------------------------------------------------------...
template <class T>
class rxTexObj2D_T : public rxTexObj
{
public:
T *m_pImage;
int m_iW, m_iH, m_iC;
GLenum m_iFormat;
public:
//! コンストラクタ
rxTexObj2D_T(bool managed = false) : rxTexObj(GL_TEXTURE...
{
m_pImage = NULL;
m_iW = 0;
m_iH = 0;
m_iC = 3;
m_iFormat = GL_RGB;
}
//! デストラクタ
~rxTexObj2D_T()
{
if(m_pImage != NULL) delete [] m_pImage;
}
/*!
* テクスチャサイズの設定
* @param[in] iW,iH テクスチャの縦横ピクセル数
* @param[in] iC テクスチャの1ピクセルごとのチャンネル数
*/
void SetSize(int iW, int iH, int iC = 3)
{
if(m_iW != iW || m_iH != iH || m_iC != iC){
m_iW = iW;
m_iH = iH;
m_iC = iC;
m_iFormat = (m_iC == 4) ? GL_RGBA : GL_RGB;
if(m_pImage != NULL) delete [] m_pImage;
m_pImage = new T[m_iW*m_iH*m_iC];
}
}
/*!
* テクスチャサイズの取得
* @param[out] iW,iH テクスチャの縦横ピクセル数
* @param[out] iC テクスチャの1ピクセルごとのチャンネル数
*/
void GetSize(int &iW, int &iH, int &iC)
{
iW = m_iW;
iH = m_iH;
iC = m_iC;
}
/*!
* ピクセルの色情報の取得
* @param[in] ic,jc ピクセル座標
* @param[out] r,g,b ピクセルの色
*/
void GetColor(int ic, int jc, T &r, T &g, T &b)
{
r = m_pImage[m_iC*(m_iW*jc+ic)+0];
g = m_pImage[m_iC*(m_iW*jc+ic)+1];
b = m_pImage[m_iC*(m_iW*jc+ic)+2];
}
/*!
* ピクセルの色情報の取得(4チャンネルRGBA)
* @param[in] ic,jc ピクセル座標
* @param[out] r,g,b,a ピクセルの色
*/
void GetColor4(int ic, int jc, T &r, T &g, T &b, T &a)
{
r = m_pImage[m_iC*(m_iW*jc+ic)+0];
g = m_pImage[m_iC*(m_iW*jc+ic)+1];
b = m_pImage[m_iC*(m_iW*jc+ic)+2];
if(m_iC == 4) a = m_pImage[m_iC*(m_iW*jc+ic)+3];
}
/*!
* ピクセルの色情報の設定
* @param[in] ic,jc ピクセル座標
* @param[in] r,g,b ピクセルの色
*/
void SetColor(int ic, int jc, const T &r, const T &g, co...
{
m_pImage[m_iC*(m_iW*jc+ic)+0] = r;
m_pImage[m_iC*(m_iW*jc+ic)+1] = g;
m_pImage[m_iC*(m_iW*jc+ic)+2] = b;
if(m_iC == 4) m_pImage[m_iC*(m_iW*jc+ic)+3] = 0;
}
/*!
* ピクセルの色情報の設定(4チャンネルRGBA)
* @param[in] ic,jc ピクセル座標
* @param[in] r,g,b,a ピクセルの色
*/
void SetColor(int ic, int jc, const T &r, const T &g, co...
{
m_pImage[m_iC*(m_iW*jc+ic)+0] = r;
m_pImage[m_iC*(m_iW*jc+ic)+1] = g;
m_pImage[m_iC*(m_iW*jc+ic)+2] = b;
if(m_iC == 4) m_pImage[m_iC*(m_iW*jc+ic)+3] = a;
}
/*!
* テクスチャメモリへ画像データを転送
*/
void SetTexture(void){
GLenum type = GL_UNSIGNED_BYTE;
if(sizeof(T) == 1){
type = GL_UNSIGNED_BYTE;
}
else if(sizeof(T) == 4){
type = GL_FLOAT;
}
glTexImage2D(m_iTarget, 0, GL_RGBA, m_iW, m_iH, 0, m_iF...
}
};
typedef rxTexObj2D_T<unsigned char> rxTexObj2D;
typedef rxTexObj2D_T<float> rxTexObj2Df;
}}
***材質クラス [#be975cfa]
OpenGLでの表面材質を管理するクラス.
g_matDefaultはデフォルトマテリアルを定義している.
#code(C){{
//-------------------------------------------------------...
// 材質データ
//-------------------------------------------------------...
class rxMaterial
{
public:
Vec4 m_vDiff, m_vSpec, m_vAmbi, m_vEmit;
double m_fDiffS, m_fSpecS, m_fAmbiS, m_fEmitS;
double m_fShin;
Vec4 m_vColor;
// 屈折,鏡面反射パラメータ
double m_fEta; //!< 屈折率
double m_fBias; //!< Fresnelバイアス
double m_fPower; //!< Fresnel指数
double m_fScale; //!< Fresnel倍率
string m_strName;
int m_iID;
int m_iIllum;
string m_strTexFile;
unsigned int m_uTexName;
public:
rxMaterial()
{
SetColor(Vec3(0.0, 0.0, 1.0), Vec3(1.0), Vec3(1.0), Vec...
SetScale(1.0, 0.75, 0.2, 0.0);
m_fEta = 0.9;
m_fBias = 1.0;
m_fPower = 0.98;
m_fScale = 5.0;
}
void SetColor(const Vec4 &diff, const Vec4 &spec, const ...
{
m_vDiff = diff;
m_vSpec = spec;
m_vAmbi = ambi;
m_vEmit = emit;
m_fShin = shin;
}
void SetColor(const GLfloat diff[4],
const GLfloat spec[4],
const GLfloat ambi[4],
const GLfloat emit[4],
const GLfloat shine)
{
m_vDiff = Vec4(diff[0], diff[1], diff[2], diff[3]);
m_vSpec = Vec4(spec[0], spec[1], spec[2], spec[3]);
m_vAmbi = Vec4(ambi[0], ambi[1], ambi[2], ambi[3]);
m_vEmit = Vec4(emit[0], emit[1], emit[2], emit[3]);
m_fShin = shine;
}
void SetColor(const Vec3 &diff, const Vec3 &spec, const ...
{
m_vDiff = diff; m_vDiff[3] = 1.0;
m_vSpec = spec; m_vSpec[3] = 1.0;
m_vAmbi = ambi; m_vAmbi[3] = 1.0;
m_vEmit = emit; m_vEmit[3] = 1.0;
m_fShin = shin;
}
void SetDiff(const Vec4 &col){ m_vDiff = col; }
void SetSpec(const Vec4 &col){ m_vSpec = col; }
void SetAmbi(const Vec4 &col){ m_vAmbi = col; }
void SetEmit(const Vec4 &col){ m_vEmit = col; }
void SetDiff3(const Vec3 &col){ m_vDiff = col; m_vDiff[3...
void SetSpec3(const Vec3 &col){ m_vSpec = col; m_vSpec[3...
void SetAmbi3(const Vec3 &col){ m_vAmbi = col; m_vAmbi[3...
void SetEmit3(const Vec3 &col){ m_vEmit = col; m_vEmit[3...
void SetScale(const double &sdiff, const double &sspec, ...
{
m_fDiffS = sdiff;
m_fSpecS = sspec;
m_fAmbiS = sambi;
m_fEmitS = semit;
}
void SetRefrac(const double &eta, const double &bias, co...
{
m_fEta = eta;
m_fBias = bias;
m_fPower = power;
m_fScale = scale;
}
void SetGL(void)
{
GLfloat mat_diff[] = { (float)(m_fDiffS*m_vDiff[0]), (f...
GLfloat mat_spec[] = { (float)(m_fSpecS*m_vSpec[0]), (f...
GLfloat mat_ambi[] = { (float)(m_fAmbiS*m_vAmbi[0]), (f...
GLfloat mat_shin[] = { (float)m_fShin };
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diff);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambi);
glMaterialfv(GL_FRONT, GL_SHININESS,mat_shin);
glColor3fv(mat_diff);
}
void SetGL(const Vec4 &diff, const Vec4 &spec, const Vec...
{
GLfloat mat_diff[] = { (float)(m_fDiffS*diff[0]), (floa...
GLfloat mat_spec[] = { (float)(m_fSpecS*spec[0]), (floa...
GLfloat mat_ambi[] = { (float)(m_fAmbiS*ambi[0]), (floa...
GLfloat mat_shin[] = { (float)m_fShin };
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diff);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambi);
glMaterialfv(GL_FRONT, GL_SHININESS,mat_shin);
glColor4fv(mat_diff);
}
// アクセスメソッド
Vec4 GetDiff(void) const { return m_vDiff*m_fDiffS; }
Vec4 GetSpec(void) const { return m_vSpec*m_fSpecS; }
Vec4 GetAmbi(void) const { return m_vAmbi*m_fAmbiS; }
Vec4 GetEmit(void) const { return m_vEmit*m_fEmitS; }
Vec3 GetDiff3(void) const { return Vec3(m_vDiff[0], m_vD...
Vec3 GetSpec3(void) const { return Vec3(m_vSpec[0], m_vS...
Vec3 GetAmbi3(void) const { return Vec3(m_vAmbi[0], m_vA...
Vec3 GetEmit3(void) const { return Vec3(m_vEmit[0], m_vE...
double GetShin(void) const { return m_fShin; }
Vec3 GetReflec(const Vec3 &irr, const Vec3 &nrm)
{
double ref_coef = m_fBias+m_fScale*pow((1.0+dot(irr, nr...
RXFunc::Clamp(ref_coef, 0.0, 1.0);
return ref_coef*GetSpec3();
}
Vec3 GetRefrac(const Vec3 &irr, const Vec3 &nrm)
{
double ref_coef = m_fBias+m_fScale*pow((1.0+dot(irr, nr...
RXFunc::Clamp(ref_coef, 0.0, 1.0);
return (1.0-ref_coef)*GetSpec3();
}
void Get(Vec3 &diff, Vec3 &spec, Vec3 &ambi, Vec3 &emit,...
{
diff = Vec3(m_vDiff[0], m_vDiff[1], m_vDiff[2]);
spec = Vec3(m_vSpec[0], m_vSpec[1], m_vSpec[2]);
ambi = Vec3(m_vAmbi[0], m_vAmbi[1], m_vAmbi[2]);
emit = Vec3(m_vEmit[0], m_vEmit[1], m_vEmit[2]);
shin = m_fShin;
}
};
static rxMaterial g_matDefault;
}}
***マウスピッククラス [#e411292a]
コンストラクタかSet関数で描画関数,投影変換関数を指定して,
Pick関数にマウス座標(スクリーン座標系)を渡すことで,ポリ...
クラスに渡す描画関数内ではglLoadNameで各オブジェクトのイ...
Pick関数はこのインデックスを返す.
#code(C){{
//-------------------------------------------------------...
// OpenGLによるオブジェクトピック
//-------------------------------------------------------...
class rxGLPick
{
boost::function<void (void)> m_fpDraw; //!< ピック用描画...
boost::function<void (void)> m_fpProj; //!< 投影変換関数
int m_pSelBufferSize;
public:
rxGLPick()
{
m_pSelBufferSize = 128;
}
rxGLPick(boost::function<void (void)> draw, boost::funct...
: m_fpDraw(draw), m_fpProj(proj)
{
m_pSelBufferSize = 128;
}
~rxGLPick(){}
void Set(boost::function<void (void)> draw, boost::funct...
{
m_fpDraw = draw;
m_fpProj = proj;
}
protected:
/*!
* OpenGLによるピックでヒットしたものから最小のデプス値...
* @param hits ヒット数
* @param buf 選択バッファ
* @return ヒットしたオブジェクト番号
*/
int selectHits(GLint hits, GLuint buf[])
{
GLuint hit_name;
float depth_min = 100.0f;
float depth1 = 1.0f;
float depth2 = 1.0f;
GLuint depth_name;
GLuint *ptr;
// ヒットしたデータなし
if(hits <= 0) return -1;
// ポインタを作業用ptrへ渡す.
ptr = (GLuint*)buf;
for(int i = 0; i < hits; ++i){
// 識別番号の階層の深さ
depth_name = *ptr;
ptr++;
depth1 = (float) *ptr/0x7fffffff;
ptr++;
depth2 = (float) *ptr/0x7fffffff;
ptr++;
// 最小デプスの確認
if(depth_min > depth1){
depth_min = depth1;
hit_name = *ptr;
}
ptr++;
}
return hit_name;
}
/*!
* マウス選択
* @param[in] x,y マウス座標
* @retval int ピックオブジェクト番号
*/
int pick(int x, int y)
{
// HCK:Pick
GLuint* selbuf = new GLuint[m_pSelBufferSize];
GLint hits;
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glSelectBuffer(m_pSelBufferSize, selbuf);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(x, viewport[3]-y, 10.0, 10.0, viewport);
m_fpProj();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
m_fpDraw();
glLoadName(0);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopName();
hits = glRenderMode(GL_RENDER);
int obj_number = selectHits(hits, selbuf);
glMatrixMode(GL_MODELVIEW);
return obj_number;
}
public:
/*!
* オブジェクトのマウス選択
* @param[in] x,y マウス座標
* @retval true ピック成功
* @retval false ピック失敗
*/
int Pick(int x, int y)
{
int obj_number;
if((obj_number = pick(x, y)) != -1){
return obj_number;
}
else{
return -1;
}
//Zバッファ値をゲット
// object_depth = PickDepth(x,y);
return -1;
}
};
}}
ページ名: