OpenGLを触るきっかけがあったのでfreeglutで遊んでみた。
かわいい。
よく使ったオブジェクト
球
void gluSphere(
GLUquadric *qobj,
GLdouble radius,
GLint slices,
GLint stacks
);
GLquadric *qobj
quadricオブジェクトのポインタ。
初学者なのでquadricオブジェクトが何か知らない。
gluNewQuadric()で全て誤魔化した。
半径。
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と透過率(α値)で指定する。
GLfloat red[] = {1.0, 0.0, 0.0, 1.0};
まだこんな少数の関数しか覚えてないけど、誤魔化しながらホーマー描けたので満足。
参考文献
docs.microsoft.com
(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) {
glPushMatrix();
glTranslatef(0, 0.2, 2.2);
glScalef(0.8, 0.8, 0.8);
head();
glPopMatrix();
body();
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();
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();
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();
GLdouble eyePos[] = {0, 0.4, 0.60};
glPushMatrix();
glTranslated(eyePos[0], eyePos[1], eyePos[2]);
eyes();
glPopMatrix();
GLdouble mousePos[] = {0, 0.29, -0.08};
glPushMatrix();
glTranslated(mousePos[0], mousePos[1], mousePos[2]);
mouse();
glPopMatrix();
GLdouble nosePos[] = {0, 0.5, 0.36};
glPushMatrix();
glTranslated(nosePos[0], nosePos[1], nosePos[2]);
nose();
glPopMatrix();
GLdouble earPos[] = {0, 0, 0.27};
glPushMatrix();
glTranslated(earPos[0], earPos[1], earPos[2]);
ears();
glPopMatrix();
}
void body(void) {
GLdouble armPos[] = {0, 0, 1.55};
glPushMatrix();
glTranslated(armPos[0], armPos[1], armPos[2]);
arms();
glPopMatrix();
glPushMatrix();
glMaterialfv(GL_FRONT, GL_DIFFUSE, jeans);
gluSphere(gluNewQuadric(), 1.0, 30, 30);
glTranslatef(0, 0, -0.18);
glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
gluCylinder(gluNewQuadric(), 1.15, 0.4, 1.9, 30, 10);
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;
glPushMatrix();
glTranslated(pos[0], pos[1], pos[2]);
glRotatef(angle, 0, 1, 0);
sleeve_and_arm(sleeveRadius, sleeveLength, armLength, 1);
glPopMatrix();
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();
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);
glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
glTranslated(0, 0, -armLength);
gluCylinder(gluNewQuadric(), 0.3, 0.35, armLength+sleeveLength, 30, 30);
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();
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();
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();
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();
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);
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);
gluSphere(gluNewQuadric(), eyeSize, 30, 30);
glMaterialfv(GL_FRONT, GL_DIFFUSE, black);
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);
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);
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);
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;
}