OpenGLを触るきっかけがあったのでfreeglutで遊んでみた。
かわいい。
よく使ったオブジェクト
球
void gluSphere(
GLUquadric *qobj,
GLdouble radius,
GLint slices,
GLint stacks
);
GLquadric *qobj
quadricオブジェクトのポインタ。 初学者なのでquadricオブジェクトが何か知らない。 gluNewQuadric()で全て誤魔化した。
GLdouble radius
半径。
GLint slices
経度の分割数。 数が大きいほど滑らか。
GLint stacks
緯度の分割数。
円筒
void gluCylinder(
GLUquadric *qobj,
GLdouble baseRadius,
GLdouble topRadius,
GLdouble height,
GLint slices,
GLint stacks
);
GLquadric *qobj
quadricオブジェクトのポインタ。
GLdouble baseRadiius
底面の半径。
GLdouble topRadius
上面の半径。
GLdouble height
円筒の高さ
GLint slices
経度の分割数。
GLint stacks
緯度の分割数。
座標の平行移動
void glTranslated(
GLdouble x,
GLdouble y,
GLdouble z
);
GLdouble x, y, z
平行移動するベクトル。
座標の回転
void glRotated(
GLdouble angle,
GLdouble x,
GLdouble y,
GLdouble z
);
GLdouble angle
回転する角度。
GLdouble x, y, z
回転軸ベクトル。
拡大・縮小
void glScaled(
GLdouble x,
GLdouble y,
GLdouble z
);
GLdouble x, y, z
それぞれの方向に対する拡大率。
座標系の一時的な変更
void glPushMatrix(void);
座標系の保存。
void glPopMatrix(void);
座標系の元に戻す。
e.g.
glPushMatrix(); /* 座標系を変更する処理 */ glTranslated(1.0, 0.0, 0.0); // ... (#) glSphere(glNewQuadric(), 1.0, 1.0, 3.0, 30, 30); glPopMatrix(); /* ここでは(#)の処理が反映されない */ glSphere(glNewQuadric(), 1.0, 1.0, 3.0, 30, 30);
C言語だから仕方ないけど、Pythonなら絶対with
ステートメント使う。
色付け
void glMaterialfv( GLenum face, GLenum pname, const GLfloat *params );
GLenum face
GL_FRONT: 表 GL_BACK: 裏 GL_FRONT_AND_BACK: 表と裏
GLenum pname
GL_DIFFUSE: 拡散反射 GL_SPECULAR: 鏡面反射 GL_AMBIENT: 環境光
const GLfloat *params
色を指定する。 (0.0, 1.0)のRGBと透過率(α値)で指定する。
// e.g. GLfloat red[] = {1.0, 0.0, 0.0, 1.0};
まだこんな少数の関数しか覚えてないけど、誤魔化しながらホーマー描けたので満足。
参考文献
(accessed on 2021/05/23)
#include <GL/glut.h> #include <math.h> #define PI2 (3.1415*2) GLfloat white[] = {1.0, 1.0, 1.0, 1.0}; GLfloat jeans[] = {0, 0.5, 0.7, 1.0}; GLfloat yellow[] = {1.0, 0.9, 0.0, 1.0}; GLfloat stubble[] = {0.596, 0.486, 0.165, 1.0}; GLfloat grey[] = {0.4, 0.4, 0.4, 1.0}; GLfloat black[] = {0, 0, 0, 1.0}; void Homer(); void head(); void body(); void arms(); void legs(); void eyes(); void mouse(); void nose(); void ears(); void hand(int isRight); void Homer(void) { /* head */ glPushMatrix(); glTranslatef(0, 0.2, 2.2); glScalef(0.8, 0.8, 0.8); head(); glPopMatrix(); /* body */ body(); /* legs */ glPushMatrix(); glTranslated(0.0, 0.0, -2.5); legs(); glPopMatrix(); } void head(void) { GLdouble headHeight = 1.05; GLdouble headRadius = 0.63; glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); glPushMatrix(); glRotatef(20, 1, 0, 0); glPushMatrix(); gluCylinder(gluNewQuadric(), headRadius+0.02, headRadius, headHeight, 30, 10); glPushMatrix(); glTranslated(0, 0.0, 0.01); glScalef(1, 1, 0.9); gluSphere(gluNewQuadric(), headRadius+0.02, 30, 30); glPopMatrix(); glPushMatrix(); glTranslated(0, 0, headHeight); glScalef(1, 1, 0.8); gluSphere(gluNewQuadric(), headRadius, 30, 30); glPopMatrix(); glPopMatrix(); /* hear side */ glMaterialfv(GL_FRONT, GL_DIFFUSE, black); int numSpike = 30; double step = PI2 / numSpike; GLdouble sideHearHeight = 0.45; GLdouble sideHearRadius = headRadius + 0.01; GLdouble sideHearWidth = 2.0; int start = 5, end = 23; glLineWidth(sideHearWidth); glBegin(GL_LINE_STRIP); for (int i = 0; i < numSpike; i++) { if (i < start) continue; if (i > end) continue; glVertex3d(sideHearRadius * sin(i * step), sideHearRadius * cos(i * step), sideHearHeight); glVertex3d(sideHearRadius * sin((i+0.5) * step), sideHearRadius * cos((i+0.5) * step), sideHearHeight+0.3); } glVertex3d(sideHearRadius * sin((end+1) * step), sideHearRadius * cos((end+1) * step), sideHearHeight); glEnd(); /* hear top */ GLdouble topHearHeight = headHeight + 0.3; GLdouble between = 0.1; for (int i = 0; i < 2; i++) { glPushMatrix(); glTranslated(0, (i == 0)? between : -between, topHearHeight); hear(); glPopMatrix(); } glPopMatrix(); /* eyes */ GLdouble eyePos[] = {0, 0.4, 0.60}; glPushMatrix(); glTranslated(eyePos[0], eyePos[1], eyePos[2]); eyes(); glPopMatrix(); /* mouse */ GLdouble mousePos[] = {0, 0.29, -0.08}; glPushMatrix(); glTranslated(mousePos[0], mousePos[1], mousePos[2]); mouse(); glPopMatrix(); /* nose */ GLdouble nosePos[] = {0, 0.5, 0.36}; glPushMatrix(); glTranslated(nosePos[0], nosePos[1], nosePos[2]); nose(); glPopMatrix(); /* ears */ GLdouble earPos[] = {0, 0, 0.27}; glPushMatrix(); glTranslated(earPos[0], earPos[1], earPos[2]); ears(); glPopMatrix(); } void body(void) { /* arms */ GLdouble armPos[] = {0, 0, 1.55}; glPushMatrix(); glTranslated(armPos[0], armPos[1], armPos[2]); arms(); glPopMatrix(); glPushMatrix(); /* waist */ glMaterialfv(GL_FRONT, GL_DIFFUSE, jeans); gluSphere(gluNewQuadric(), 1.0, 30, 30); /* chest */ glTranslatef(0, 0, -0.18); glMaterialfv(GL_FRONT, GL_DIFFUSE, white); gluCylinder(gluNewQuadric(), 1.15, 0.4, 1.9, 30, 10); /* neck */ glTranslated(0, 0, 1.7); glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); gluCylinder(gluNewQuadric(), 0.4, 0.4, 0.6, 30, 10); glPopMatrix(); } void arms(void) { GLdouble sleeveLength = 0.5; GLdouble sleeveRadius = 0.4; GLdouble armLength = 1.0; GLdouble pos[3] = {0.4, 0, 0}; GLfloat angle = -30; /* right arm */ glPushMatrix(); glTranslated(pos[0], pos[1], pos[2]); glRotatef(angle, 0, 1, 0); sleeve_and_arm(sleeveRadius, sleeveLength, armLength, 1); glPopMatrix(); /* left arm */ glPushMatrix(); glTranslated(-pos[0], pos[1], pos[2]); glRotatef(-angle, 0, 1, 0); sleeve_and_arm(sleeveRadius, sleeveLength, armLength, 0); glPopMatrix(); } void sleeve_and_arm(GLdouble sleeveRadius, GLdouble sleeveLength, GLdouble armLength, int isRight) { glPushMatrix(); /* sleeve */ glMaterialfv(GL_FRONT, GL_DIFFUSE, white); glTranslated(0, 0, -sleeveRadius); gluSphere(gluNewQuadric(), sleeveRadius, 30, 30); glTranslated(0, 0, -sleeveLength); gluCylinder(gluNewQuadric(), 0.4, 0.4, sleeveLength, 30, 30); /* arm */ glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); glTranslated(0, 0, -armLength); gluCylinder(gluNewQuadric(), 0.3, 0.35, armLength+sleeveLength, 30, 30); /* hand */ hand(isRight); glPopMatrix(); } void hand(int isRight) { GLdouble thumbLength = 0.25; GLdouble indexLength = 0.36; GLdouble middleLength = 0.36; GLdouble pinkieLength = 0.35; double t = (isRight)? 1.0 : -1.0; glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); glPushMatrix(); glScalef(1, 1, 0.6); gluSphere(gluNewQuadric(), 0.3, 30, 30); glPopMatrix(); /* thumb */ glPushMatrix(); glRotatef(20*t, 0, 1, 0); glTranslated(-0.11*t, 0.16, -thumbLength); gluCylinder(gluNewQuadric(), 0.1, 0.11, thumbLength, 30, 30); gluSphere(gluNewQuadric(), 0.1, 30, 30); glPopMatrix(); /* index */ glPushMatrix(); glRotatef(10*t, 0, 1, 0); glTranslated(0.13*t, 0.12, -indexLength); gluCylinder(gluNewQuadric(), 0.1, 0.12, indexLength, 30, 30); gluSphere(gluNewQuadric(), 0.1, 30, 30); glPopMatrix(); /* middle */ glPushMatrix(); glRotatef(10*t, 0, 1, 0); glTranslated(0.17*t, -0.03, -middleLength); gluCylinder(gluNewQuadric(), 0.1, 0.12, middleLength, 30, 30); gluSphere(gluNewQuadric(), 0.1, 30, 30); glPopMatrix(); /* pinlie */ glPushMatrix(); glRotatef(10*t, 0, 1, 0); glTranslated(0.13*t, -0.14, -pinkieLength); gluCylinder(gluNewQuadric(), 0.09, 0.11, pinkieLength, 30, 30); gluSphere(gluNewQuadric(), 0.09, 30, 30); glPopMatrix(); } void legs(void) { GLdouble legLength = 2.3; GLfloat pos[3] = {0.37, 0, 0}; GLdouble legRadius = 0.5; for (int i = 0; i < 2; i++) { glPushMatrix(); glMaterialfv(GL_FRONT, GL_DIFFUSE, jeans); glTranslatef((i==0)? pos[0] : -pos[0], pos[1], pos[2]); gluCylinder(gluNewQuadric(), legRadius, legRadius, legLength, 30, 10); /* shoe */ glMaterialfv(GL_FRONT, GL_DIFFUSE, grey); glScalef(1, 1.4, 0.45); glTranslated(0, 0.1, -0.2); gluSphere(gluNewQuadric(), legRadius, 30, 30); glPopMatrix(); } } void eyes(void) { GLdouble pos[3] = {0.24, 0, 0}; GLdouble eyeSize = 0.24; glPushMatrix(); glScalef(1, 0.8, 1); for (int i = 0; i < 2; i++) { glPushMatrix(); glTranslated((i==0)? pos[0] : -pos[0], pos[1], pos[2]); glMaterialfv(GL_FRONT, GL_DIFFUSE, white); // color gluSphere(gluNewQuadric(), eyeSize, 30, 30); glMaterialfv(GL_FRONT, GL_DIFFUSE, black); // color glTranslated(0, eyeSize-0.01, 0); glScalef(1, 0.6, 1); gluSphere(gluNewQuadric(), 0.06, 30, 30); glPopMatrix(); } glPopMatrix(); } void mouse(void) { glMaterialfv(GL_FRONT, GL_DIFFUSE, stubble); // color glPushMatrix(); glScalef(1, 1, 0.68); glTranslated(0, -0.12, 0.10); gluSphere(gluNewQuadric(), 0.6, 20, 20); glPopMatrix(); glPushMatrix(); glTranslated(0, -0.06, -0.04); glScalef(1, 1, 0.6); gluSphere(gluNewQuadric(), 0.5, 20, 20); glPopMatrix(); } void nose(void) { GLdouble noseSize = 0.12; GLdouble noseHeight = 0.15; glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); // color glPushMatrix(); glRotatef(90, -1, 0, 0); glPushMatrix(); gluCylinder(gluNewQuadric(), noseSize, noseSize, noseHeight, 20, 20); glTranslated(0, 0, noseHeight); gluSphere(gluNewQuadric(), noseSize, 20, 20); glPopMatrix(); glPopMatrix(); } void ears(void) { GLdouble pos[3] = {0.61, -0.2, 0}; glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow); // color for (int i = 0; i < 2; i++) { glPushMatrix(); glTranslated((i==0)? pos[0] : -pos[0], pos[1], pos[2]); glRotatef(100, 0, (i==0)? 1 : -1, 0); glRotatef(30, -1, 0, 0); glutSolidTorus(0.089, 0.08, 30, 30); glPopMatrix(); } } void hear() { int n = 30; double step = PI2 / n; GLdouble hearRadius = 0.4; GLdouble hearWidth = 2.0; glLineWidth(hearWidth); glBegin(GL_LINE_LOOP); for (int i = 0; i < n; i++) { glVertex3d(hearRadius * cos(i * step), 0, hearRadius * sin(i * step)); } glEnd(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Homer(); glutSwapBuffers(); } void init(void) { glClearColor(1.0, 1.0, 1.0, 0.0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloat lightPos0[] = {-5, 15, 10, 1}; glLightfv(GL_LIGHT0, GL_POSITION, lightPos0); glEnable(GL_LIGHT1); GLfloat lightPos1[] = {5, 15, 10, 1}; glLightfv(GL_LIGHT1, GL_POSITION, lightPos1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(30.0, 1, 1.0, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(8, 15, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(600, 600); glutCreateWindow("Homer Simpson"); glutDisplayFunc(display); init(); glutMainLoop(); return 0; }