lip.cpp
//g++ lip.cpp -framework OpenGL -framework GLUT -Wno-deprecated (左記のコードをターミナルにコピーしてコンパイル)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GLUT/glut.h>
#define SPEED 3//リップシンク速度
#define TIME 13//リップシンク移行時間
//関数名の宣言
void initGL();
void display();
void resize(int w, int h);
void timer(int value);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);
void keyboard(unsigned char key, int x, int y);
//グローバル変数
double eDist, eDegX, eDegY;
int winW, winH; //ウィンドウサイズ
int mButton, mState, mX, mY;
int si=0;//動作フラグ
double px=0,py=0.5,pz=0.5;//唇上部座標
double px2=-5.0,py2=0,pz2=-1;//唇左部座標
double px3=5.0,py3=0,pz3=-1;//唇右部座標
double px4=0,py4=0.5,pz4=0.5;//唇下部座標
double lips[30]={};//リップシンク配列(30音まで)
int l_num=0;//リップシンク配列保存用
int l_num2=0;//リップシンク配列呼び出し用
int move=0;//現在の経過時間
int main(int argc, char *argv[])
{
glutInit(&argc, argv); //OpenGL,GLUTの初期化
initGL();
glutMainLoop();
return 0;
}
//初期設定関数
void initGL()
{
//チュートリアル
printf("a,i,u,e,o,nを自由に入力した後、1キーを入力すると動作を開始します\n");
printf("動作途中で2キーを入力すると動作を強制終了します\n");
printf("一度に発声できるのは30音までです\n");
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow("CG");
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutTimerFunc(33, timer, 0);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutKeyboardFunc(keyboard);
//各種設定
glClearColor(1.0, 0.95, 0.9, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_NORMALIZE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glAlphaFunc(GL_GREATER, 0.6);
//光源
GLfloat col[4];
col[0] = 0.9; col[1] = 0.9; col[2] = 0.9; col[3] = 1.0;
glEnable(GL_LIGHTING);
//0
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, col);
glLightfv(GL_LIGHT0, GL_SPECULAR, col);
col[0] = 0.1; col[1] = 0.1; col[2] = 0.1; col[3] = 1.0;
glLightfv(GL_LIGHT0, GL_AMBIENT, col);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.001);
//1
glEnable(GL_LIGHT1);
col[0] = 0.9; col[1] = 0.9; col[2] = 0.9; col[3] = 1.0;
glLightfv(GL_LIGHT1, GL_DIFFUSE, col);
glLightfv(GL_LIGHT1, GL_SPECULAR, col);
col[0] = 0.1; col[1] = 0.1; col[2] = 0.1; col[3] = 1.0;
glLightfv(GL_LIGHT1, GL_AMBIENT, col);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.001);
eDist = 120.0;
eDegX = 20.0; eDegY = 0.0;
}
void resize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, (double)w/(double)h, 1.0, 1000.0);
winW = w; winH = h;
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
double ex = eDist*cos(eDegX*M_PI/180.0)*sin(eDegY*M_PI/180.0);
double ey = eDist*sin(eDegX*M_PI/180.0);
double ez = eDist*cos(eDegX*M_PI/180.0)*cos(eDegY*M_PI/180.0);
gluLookAt(ex, ey, ez, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
GLfloat lightPos0[] = {10.0, 40.0, 30.0, 1.0};
glLightfv(GL_LIGHT0, GL_POSITION, lightPos0);
GLfloat lightPos1[] = {15.0, 10.0, 15.0, 1.0};
glLightfv(GL_LIGHT1, GL_POSITION, lightPos1);
GLfloat col[4], spe[4], shi[1];
glPushMatrix();//唇
col[0] = 1.0; col[1] = 0.0; col[2] = 0.0; col[3] = 1.0;
spe[0] = 0.7; spe[1] = 0.7; spe[2] = 0.7; spe[3] = 1.0;
shi[0] = 100;
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, col);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spe);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shi);
glScaled(4,4,4);
if(si==1){
if(lips[l_num2]==1){//a
py+=(3.0-py)/SPEED;
px2+=(-5-px2)/SPEED;
px3+=(5-px3)/SPEED;
py4+=(-1.5-py4)/SPEED;
move++;
if(move==TIME){
l_num2++;
move=0;
}
}
if(lips[l_num2]==2){//i
py+=(2-py)/SPEED;
px2+=(-6.0-px2)/SPEED;
px3+=(6.0-px3)/SPEED;
py4+=(-0.5-py4)/SPEED;
move++;
if(move==TIME){
l_num2++;
move=0;
}
}
if(lips[l_num2]==3){//u
py+=(2-py)/SPEED;
px2+=(-2.5-px2)/SPEED;
px3+=(2.5-px3)/SPEED;
py4+=(-1.0-py4)/SPEED;
move++;
if(move==TIME){
l_num2++;
move=0;
}
}
if(lips[l_num2]==4){//e
py+=(2-py)/SPEED;
px2+=(-5.5-px2)/SPEED;
px3+=(5.5-px3)/SPEED;
py4+=(-1.0-py4)/SPEED;
move++;
if(move==TIME){
l_num2++;
move=0;
}
}
if(lips[l_num2]==5){//o
py+=(3.0-py)/SPEED;
px2+=(-4.0-px2)/SPEED;
px3+=(4.0-px3)/SPEED;
py4+=(-1.5-py4)/SPEED;
move++;
if(move==TIME){
l_num2++;
move=0;
}
}
if(lips[l_num2]==6){//n
py+=(0.5-py)/SPEED;
px2+=(-5-px2)/SPEED;
px3+=(5-px3)/SPEED;
py4+=(0.5-py4)/SPEED;
move++;
if(move==TIME){
l_num2++;
move=0;
}
}
if(l_num2==l_num){//終了
py+=(0.5-py)/SPEED;
px2+=(-5-px2)/SPEED;
px3+=(5-px3)/SPEED;
py4+=(0.5-py4)/SPEED;
move++;
if(move==TIME){
l_num=0;
l_num2=0;
move=0;
si=0;
for(int i=0;i<30;i++){
lips[i]=9;
}
}
}
}
glBegin(GL_QUADS);
glNormal3d(0.4, 0.2, 0.7);
glVertex3d(px-2,py+1.5,pz+0.5);
glVertex3d(px+2,py+1.5,pz+0.5);
glVertex3d(px+1,py,pz);
glVertex3d(px-1,py,pz);
glEnd();
glBegin(GL_TRIANGLES);
glNormal3d(0.7, 0.1, 0.9);
glVertex3d(px-2,py+1.5,pz+0.5);
glVertex3d(px-1,py,pz);
glVertex3d(px2,py2,pz2);
glEnd();
glBegin(GL_TRIANGLES);
glNormal3d(0.1, 0.1, 0.5);
glVertex3d(px+2,py+1.5,pz+0.5);
glVertex3d(px+1,py,pz);
glVertex3d(px3,py3,pz3);
glEnd();
glBegin(GL_QUADS);
glNormal3d(0.3, 0.2, 0.5);
glVertex3d(px4,py4,pz4);
glVertex3d(px2,py2,pz2);
glVertex3d(px2+2,py2-1,pz2+0.5);
glVertex3d(px4,py4-2,pz+0.5);
glEnd();
glBegin(GL_QUADS);
glNormal3d(-0.1, 0.2, 0.5);
glVertex3d(px4,py4,pz4);
glVertex3d(px3,py3,pz3);
glVertex3d(px3-2,py3-1,pz3+0.5);
glVertex3d(px4,py4-2,pz4+0.5);
glEnd();
col[0] = 0.0; col[1] = 0.0; col[2] = 0.0; col[3] = 1.0;
spe[0] = 0.0; spe[1] = 0.0; spe[2] = 0.0; spe[3] = 1.0;
shi[0] = 0;
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, col);
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, col);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spe);
glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, shi);
glBegin(GL_QUADS);
glVertex3d(px-2,py+1.5,pz+0.5);
glVertex3d(px+2,py+1.5,pz+0.5);
glVertex3d(px3,py3,pz3);
glVertex3d(px2,py2,pz2);
glEnd();
glBegin(GL_POLYGON);
glVertex3d(px3,py3,pz3);
glVertex3d(px2,py2,pz2);
glVertex3d(px2+2,py2-1,pz2+0.5);
glVertex3d(px4,py4-2,pz4+0.5);
glVertex3d(px3-2,py3-1,pz3+0.5);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void timer(int value)
{
glutPostRedisplay();
glutTimerFunc(33, timer, 0);
}
void mouse(int button, int state, int x, int y)
{
mButton = button; mState = state; mX = x; mY = y;
}
void motion(int x, int y)
{
if (mButton==GLUT_RIGHT_BUTTON){
eDegY += (mX-x)*0.1;
eDegX += (y-mY)*0.1;
}
else if (mButton==GLUT_LEFT_BUTTON){
GLfloat winX, winY, winZ;
GLdouble objX, objY, objZ;
GLdouble model[16], proj[16];
GLint view[4];
winX = x;
winY = winH-y;
glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
glGetDoublev(GL_MODELVIEW_MATRIX, model);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetIntegerv(GL_VIEWPORT, view);
gluUnProject(winX, winY, winZ, model, proj, view, &objX, &objY, &objZ);
}
mX = x; mY = y;
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27: //ESC
exit(0);
break;
case '1':
if(si==0){
si=1;
}
break;
case '2':
if(si==1){
l_num2=l_num;
move=0;
}
break;
case 'a':
if(si==0&&l_num<30){
lips[l_num]=1;
l_num++;
}else if(si==0&&l_num>=30){
printf("\n発音は30回までです\n");
}
break;
case 'i':
if(si==0&&l_num<30){
lips[l_num]=2;
l_num++;
}else if(si==0&&l_num>=30){
printf("\n発音は30回までです\n");
}
break;
case 'u':
if(si==0&&l_num<30){
lips[l_num]=3;
l_num++;
}else if(si==0&&l_num>=30){
printf("\n発音は30回までです\n");
}
break;
case 'e':
if(si==0&&l_num<30){
lips[l_num]=4;
l_num++;
}else if(si==0&&l_num>=30){
printf("\n発音は30回までです\n");
}
break;
case 'o':
if(si==0&&l_num<30){
lips[l_num]=5;
l_num++;
}else if(si==0&&l_num>=30){
printf("\n発音は30回までです\n");
}
break;
case 'n':
if(si==0&&l_num<30){
lips[l_num]=6;
l_num++;
}else if(si==0&&l_num>=30){
printf("\n発音は30回までです\n");
}
break;
default:
break;
}
}