我是决定做跳舞的人,但是,我不会maya,怎么办?
很简单,去http://tf3dm.com/3d-models/maya这样网站找别人做的模型,然后download,之后的模型材料上色可以自己百度简单步骤哦。(如果有空的话我在po图)
打开devC++,opencv和glut都要安装哦~~~
基本的是
#include<GL/glut.h>
int main()
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(500,500);
glutCreateWindow("Berry homework");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
objLoad();//load maya data加载maya模型所用
mylight();打光
glutMainLoop();
}
然后你会发现你需要些两个函数就是display和keyboard,
display是用来显示图形的,keyboard是用来控制键盘,顺带配合滑鼠
void keyboard(unsigned char key, int x,int y)
{
if(key =='a') moveX-=0.1;//控制整体的左移
if(key =='d') moveX+=0.1;//控制整体的右移
if(key =='w') moveY+=0.1;//控制整体的上移
if(key =='x') moveY-=0.1;//控制整体的下移
glutPostRedisplay();
}
如下是控制滑鼠的
void mouse(int button,int state,int x,int y)
{
OldX=x;
OldY=y;
}
void motion(int x,int y)
{
angleX=x-OldX;OldX=x;
angle[angleID]+=angleX;//angleID是用来选择所要旋转的关节
glutPostRedisplay();
}
这里还要在main函数里面写入打光的函数mylight()
(老师说可以直接复制贴上,因为只有控制position[]这个坐标来改变打光方向而已)
void mylight()
{
const GLfloat light_position[] = { -2.0f, 5.0f, 5.0f, 0.0f };
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
}
这里先来把图案画出来~~运用导入.obj格式的模型
基本准备:
GLMmodel * pmodel[9];有九个关节
char filename[9][50]={"data/man/newbody.obj", "data/man/newhead.obj",
"data/man/lefthand.obj", "data/man/lefthand1.obj","data/man/righthand.obj", "data/man/righthand1.obj","data/man/leftleg.obj", "data/man/rightleg.obj","data/man/ball.obj"};
我用函数来写,以阵列的方式将模型放入相应的pmodel中
void objLoad()
{
for(int i=0;i<9;i++)
{
pmodel[i] = glmReadOBJ(filename[i]);
glmUnitize(pmodel[i]);
glmFacetNormals(pmodel[i]);
glmVertexNormals(pmodel[i], 90.0);
}
}
接下来就进入紧张的画的阶段了
void display()
{
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();//start draw
//gluLookAt(eyeX,eyeY,eyeZ,objX,objY,objZ,upX,upY,upZ);
glRotatef(angle[7],0,1,0);
glScalef(theSize,theSize,theSize);
glTranslatef(moveX,moveY,0);
glmDraw(pmodel[0], GLM_SMOOTH | GLM_MATERIAL);//body
glTranslatef(0, 0, 0.12);
glScalef(1,1.2,1);
glPushMatrix();//head
glTranslatef(0, 0.5, 0);
glRotatef(angle[0], 0,1,0);
glTranslatef(0, -0.2, 0);
glmDraw(pmodel[1], GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
glPushMatrix();//left hand
glTranslatef(-0.1, 0.1, -0.06);
glRotatef(angle[1], 0,0,1);
glRotatef(angle[12], 0,1,0);
glTranslatef(-0.04, 0, 0);
glmDraw(pmodel[2], GLM_SMOOTH | GLM_MATERIAL);
glPushMatrix();//left lowerarm
glTranslatef(-0.02, 0, 0);
glRotatef(angle[2], 0,0,1);
glRotatef(angle[10], 1,0,0);
glTranslatef(-0.2, 0, 0);
glmDraw(pmodel[3], GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
glPopMatrix();
glPushMatrix();//ball
glScalef(ballSize,ballSize,ballSize);
glRotatef(angle[14],0,1,0);
glTranslatef(-0.5,0.05,-0.05);
glTranslatef(ballX,ballY,ballZ);
glmDraw(pmodel[8], GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
glPushMatrix();//right hand
glTranslatef(0.1, 0.1, -0.06);
glRotatef(angle[3], 0,0,1);
glRotatef(angle[13], 0,1,0);
glTranslatef(0.04, 0, 0);
glmDraw(pmodel[4], GLM_SMOOTH | GLM_MATERIAL);
glPushMatrix();//right lowerarm
glTranslatef(0.02, 0, 0);
glRotatef(angle[4], 0,0,1);
glRotatef(angle[11], 1,0,0);
glTranslatef(0.2, 0, 0);
glmDraw(pmodel[5], GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
glPopMatrix();
glPushMatrix();//left foot
glScalef(0.2,0.4,0.2);
glTranslatef( -0.3, -0.5, -0.2);
glRotatef(angle[5], 1,0,0);
glRotatef(angle[8],0,0,1);
glTranslatef(0, -0.8, 0);
glmDraw(pmodel[6], GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
glPushMatrix();//right foot
glScalef(0.2,0.4,0.2);
glTranslatef( 0.3, -0.5, 0);
glRotatef(-angle[6], 1,0,0);
glRotatef(angle[9],0,0,1);
glTranslatef(0, -0.8, 0);
glmDraw(pmodel[7], GLM_SMOOTH | GLM_MATERIAL);
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
如上的display需要注意glTranslatef和glRotatef的位置~~,(关于自转和公转)老师上课讲过了哦~~(好好复习笔记)
其中重点语句就是glmDraw(pmodel[i], GLM_SMOOTH | GLM_MATERIAL);这就是画出模型了(好开心~~)
你以为很简单吗?其实你还需要做一些额外的工作,
1.在你电脑的devC++下的bin的opencv下找到
然后放在你档案里面,还有就是glm.o,glm.h,glm.c这三个文件也要在档案里(具体的干啥我忘了,但是好像很重要),然后在工程里导入glm.c,还有就是在工程属性下加入参数咒语-lcv -lcxcore -lhighgui (这里的空格等以下列要看清楚哦~~)
还有开头的#include "glm.h"
#include<opencv/highgui.h>
#include<opencv/cv.h>
在键盘keyboard事件中,我用了如下
if(key=='s')保存文件txt在专案里,我每次都漏写了.txt,然后找BUG找的快疯了
{
if(fout==NULL) fout=fopen("my_action.txt","w+");
for(int i=0;i<20;i++)
{
printf("%f ",angle[i]);
fprintf(fout, "%f ", angle[i]);
}
printf("%f ",moveX);
printf("%f ",moveY);
fprintf(fout,"%f ",moveX);
fprintf(fout,"%f ",moveY);
printf("%f ",ballX);
printf("%f ",ballY);
printf("%f ",ballZ);
fprintf(fout,"%f ",ballX);
fprintf(fout,"%f ",ballY);
fprintf(fout,"%f ",ballZ);
printf("%f ",ballSize);
fprintf(fout,"%f ",ballSize);
printf("\n");
fprintf(fout,"\n");
}
然后我要加入音乐~~~这里要在文档里加入一个文件CMP3_MCI.h,然后同样导入专案里面和前面的glm.c一样哦~~~
#include <windows.h>
#include <mmsystem.h>
#include "CMP3_MCI.h"
然后在main函数中写入 myMP3.Load("action_baofeng.mp3");这是加载音乐啦~~
然后同样在键盘事件中写入
if(key =='p')
{
myMP3.Play();音乐开始播放了哦,巴拉拉巴拉
glutTimerFunc(0,timer,0);在0秒后执行timer函数
}
又出现glutTimerFunc函数,这是个计时器哦~~就是一定时间下执行事件~~
我的事件是这样的哦~~~
void timer(int t)
{
glutTimerFunc(40,timer,0);
readNext();
glutPostRedisplay();
}在timer函数中又出现了计时器,那就是嵌套喽,没事,你只要设置好时间就可以一定时间执行事件,如我是40ms下执行timer.
你还需要写一个readNext()函数,这是用于读档案的,这里运用了内插~~~
FILE *fout=NULL,*fin=NULL;
float a=0;
float angleOld[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
float angleNew[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void readNext()
{
if(fin==NULL){fin=fopen("my_action.txt","r");}
a+=0.1;
for(int i=0;i<20;i++)
{ angle[i]=angleOld[i]*(1-a)+angleNew[i]*a;}
moveX=moveOldX*(1-a)+moveNewX*a;
moveY=moveOldY*(1-a)+moveNewY*a;
ballX=ballOldX*(1-a)+ballNewX*a;
ballY=ballOldY*(1-a)+ballNewY*a;
ballZ=ballOldZ*(1-a)+ballNewZ*a;
ballSize=ballSizeOld*(1-a)+ballSizeNew*a;
if(a>=1.0)
{
a=0.0;
for(int i=0;i<20;i++)
{
angleOld[i]=angleNew[i];
fscanf(fin,"%f ",&angleNew[i]);
}
moveOldX=moveNewX;
fscanf(fin,"%f ",&moveNewX);
moveOldY=moveNewY;
fscanf(fin,"%f ",&moveNewY);
ballOldX=ballNewX;
fscanf(fin,"%f ",&ballNewX);
ballOldY=ballNewY;
fscanf(fin,"%f ",&ballNewY);
ballOldZ=ballNewZ;
fscanf(fin,"%f ",&ballNewZ);
ballSizeOld=ballSizeNew;
fscanf(fin,"%f ",&ballSizeNew);
}
}
依葫芦画瓢吧~~
然后我想做背景贴图
代码如下:
GLuint id;
void mytexture()
{
glEnable(GL_TEXTURE_2D);
IplImage *img = cvLoadImage("3.jpg");自己的图片名称
cvCvtColor(img,img,CV_BGR2RGB);
glGenTextures(1,&id);
glBindTexture(GL_TEXTURE_2D,id);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,img->width,img->height,0,GL_RGB,GL_UNSIGNED_BYTE,img->imageData);
}
贴图的准备如上面
在display中的glutSwapBuffers()前写入
这里要解释为什么这么多,因为考虑到打光和贴图的影响,所以先关闭打光,开启贴图,然后画贴图,再关闭贴图,画打光,这样打光和贴图就能分开不会影响到~~
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
drawbackground();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
这里的drawbackground是来画背景的
void drawbackground()
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D,id);
glBegin(GL_POLYGON);
glTexCoord2f(0,0);glVertex3f(-2,2,-1.8);这里的-1.8根据不同情况哦
glTexCoord2f(1,0);glVertex3f(2,2,-1.8);
glTexCoord2f(1,1);glVertex3f(2,-2,-1.8);
glTexCoord2f(0,1);glVertex3f(-2,-2,-1.8);
glEnd();
}
最后可以在main中写入
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2,2,-2,2,-10,10);
glMatrixMode(GL_MODELVIEW);
这是用于扩大界面的,不至于移动或旋转会超出空间
下面是我的影片播放效果~~~
第一版很弱,我有稍稍改进,但还是不眨地。。希望这篇文章对你们有用!!!!!
謝謝分享 非常有用
回覆刪除