- 浏览: 915076 次
文章分类
最新评论
-
wmaizai163:
有源码文件么 可调试的那种 发我邮箱可以么 3906902 ...
java文件传输 -
shenselongge:
排版能否改改
Mina2.0框架源码剖析(一) -
grandry:
谢谢!这是一个困扰我多时的问题
delphi的tclientdataset的中文过滤使用注意事项 -
LongXiTianXia:
我不知道哪里下载那个组件
基于朴素贝叶斯分类器的文本分类算法(下) -
LongXiTianXia:
可以说一下分词组件怎么使用吗?
基于朴素贝叶斯分类器的文本分类算法(下)
代码分析
这是susu给我的一份关于glut的示例代码,里面涉及到的内容有:用glut来完成菜单管理,文本显示,显示列表,材质,光照,多窗口显示,鼠标事件处理,键盘事件处理,菜单事件处理,窗口创建,缩放,销毁,动画播放,定时器等功能,运行效果如图:
我分成几个部分来对代码进行分析:
1,命令行参数检查
{
intargp;
GLbooleanquit=GL_FALSE;
GLbooleanerror=GL_FALSE;
#defineAAargv[argp]
argp=1;
while(argp<argc)
{
if(match(AA,"-help"))
{
commandLineHelp();
quit=GL_TRUE;
}
elseif(match(AA,"-version"))
{
printf(VERSIONLONG"/n");
quit=GL_TRUE;
}
elseif(match(AA,"-auto"))
{//自动运行
demoMode=GL_TRUE;
}
elseif(match(AA,"-scale"))
{//放缩
argp++;
scaleFactor=atof(argv[argp]);//设置缩放因子
}
else
{//出错处理
fprintf(stderr,"Unknownarg:%s/n",AA);
error=GL_TRUE;
quit=GL_TRUE;
}
argp++;
}
GLbooleanmatch(char*arg,char*t)
{
if(strstr(t,arg))
returnGL_TRUE;
else
returnGL_FALSE;
}
if(error)
{
commandLineHelp();
exit(1);
}
if(quit)
exit(0);
}
这里match函数考虑到-help可能被输入为-h等形式,因此用的是strstr而不是strcmp来进行字符串的匹配。
2,窗口的缩放
通过对窗口原点和大小的调整就可以实现窗口的缩放。
{//各个窗口的左上角坐标
{50,150},/*win0*/
{450,150},/*win1*/
{50,600},/*win2*/
{450,600},/*win3*/
{10,10},/*subwin4(relativetoparentwin0)*/
{300,400},/*helpwin5*/
{850,150},/*cmapwin6*/
{850,600},/*cmapwin7*/
{250,450}/*textwin8*/
};
intsize[MAXWIN][2]=
{//各个窗口大小(宽度,高度)
{350,350},/*win0*/
{350,350},/*win1*/
{350,350},/*win2*/
{350,350},/*win3*/
{200,200},/*subwin4*/
{700,300},/*helpwin5*/
{350,350},/*cmapwin6*/
{350,350},/*cmapwin7*/
{800,450}/*textwin8*/
};
voidscaleWindows(floatscale)
{//放缩初始窗口大小和位置
inti;
for(i=0;i<MAXWIN;i++)
{
pos[i][0]=pos[i][0]*scale;//x坐标
pos[i][1]=pos[i][1]*scale;//y坐标
size[i][0]=size[i][0]*scale;//宽度
size[i][1]=size[i][1]*scale;//高度
}
}
3,设置显示模式、
Int型的数组modes用来记录各个模式位的值(0或者1),从而表明窗口是否支持这种模式。displayMode |= glutMode[i];通过这样的按位或运算最终获得窗口的显示模式。
modes[RGBA]=1;
modes[DOUBLEBUFFER]=1;
modes[DEPTH]=1;
setInitDisplayMode()
voidsetInitDisplayMode(void)
{//设置初始显示模式
inti;
displayMode=0;
for(i=0;i<MODES;i++){
if(modes[i]){
/*printf("Requesting%s/n",modeNames[i]);*/
displayMode|=glutMode[i];//进行按位或运行,
}
}
glutInitDisplayMode(displayMode);
createMenu6();
if(!glutGet(GLUT_DISPLAY_MODE_POSSIBLE))
warning("Thisdisplaymodenotsupported/n");
}
4,菜单管理
menu1到menu8这8个int型变量用来保存创建的菜单项,并且menu2到menu8都作为menu1的子菜单加入到menu1中。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
voidmakeMenus(void)
{//创建弹出菜单
/**//*Generalcontrol/debug*/
menu2=glutCreateMenu(menuFunc);
glutAddMenuEntry("toggleautodemomode(a)",312);
glutAddMenuEntry("togglefreezinginmenus",300);
glutAddMenuEntry("toggletextperwindow(t)",301);
glutAddMenuEntry("toggleglobaltimer",302);
glutAddMenuEntry("toggleglobalanimation",303);
glutAddMenuEntry("toggleperwindowanimation",304);
glutAddMenuEntry("toggledebugprints(D)",305);
glutAddMenuEntry("toggleshadedbackdrop",307);
glutAddMenuEntry("togglepassivemotioncallback",308);
glutAddMenuEntry("increaselinewidth(l)",310);
glutAddMenuEntry("decreaselinewidth(L)",311);
/**//*Shapes*/
menu3=glutCreateMenu(menuFunc);
glutAddMenuEntry("sphere",200);
glutAddMenuEntry("cube",201);
glutAddMenuEntry("cone",202);
glutAddMenuEntry("torus",203);
glutAddMenuEntry("dodecahedron",204);
glutAddMenuEntry("octahedron",205);
glutAddMenuEntry("tetrahedron",206);
glutAddMenuEntry("icosahedron",207);
glutAddMenuEntry("teapot",208);
/**//*Open/closewindows*/
menu4=glutCreateMenu(menuFunc);
glutAddMenuEntry("openallwindows",450);
glutAddMenuEntry("closeallwindows",451);
glutAddMenuEntry("",9999);
glutAddMenuEntry("createwin0",400);
glutAddMenuEntry("createwin1",401);
glutAddMenuEntry("createwin2",402);
glutAddMenuEntry("createwin3",403);
glutAddMenuEntry("createsubwindow",404);
glutAddMenuEntry("createcolorindexwin6",406);
glutAddMenuEntry("createcolorindexwin7",407);
glutAddMenuEntry("",9999);
glutAddMenuEntry("destroywin0",410);
glutAddMenuEntry("destroywin1",411);
glutAddMenuEntry("destroywin2",412);
glutAddMenuEntry("destroywin3",413);
glutAddMenuEntry("destroysubwindow",414);
glutAddMenuEntry("destroycolorindexwin6",416);
glutAddMenuEntry("destroycolorindexwin7",417);
/**//*Windowmanagerstuff*/
menu5=glutCreateMenu(menuFunc);
glutAddMenuEntry("movecurrentwin",430);
glutAddMenuEntry("resizecurrentwin",431);
glutAddMenuEntry("iconifycurrentwin",432);
glutAddMenuEntry("showcurrentwin",433);
glutAddMenuEntry("hidecurrentwin",434);
glutAddMenuEntry("pushcurrentwin",435);
glutAddMenuEntry("popcurrentwin",436);
glutAddMenuEntry("",9999);
glutAddMenuEntry("movewin1",420);
glutAddMenuEntry("resizewin1",421);
glutAddMenuEntry("iconifywin1",422);
glutAddMenuEntry("showwin1",423);
glutAddMenuEntry("hidewin1",424);
glutAddMenuEntry("pushwin1",425);
glutAddMenuEntry("popwin1",426);
/**//*Gfxmodes*/
createMenu6();/**//*builddynamically*/
/**//*Textyreports*/
menu7=glutCreateMenu(menuFunc);
glutAddMenuEntry("reportcurrentwinmodes",700);
glutAddMenuEntry("reportcurrentdevicedata",701);
glutAddMenuEntry("checkOpenGLextensions",702);
glutAddMenuEntry("dumpinternaldata(d)",703);
/**//*Playwithmenus*/
menu8=glutCreateMenu(menuFunc);
glutAddMenuEntry("togglemenusonleftbutton",805);
glutAddMenuEntry("togglemenusonmiddlebutton",806);
glutAddMenuEntry("togglemenusonrightbutton",807);
glutAddMenuEntry("---------------------------",9999);
glutAddMenuEntry("addplainitems",800);
glutAddMenuEntry("addsubmenuitems",801);
glutAddMenuEntry("changenewentriestoplainitems",802);
glutAddMenuEntry("changenewentriestosubmenus",803);
glutAddMenuEntry("removeallnewitems",804);
glutAddMenuEntry("---------------------------",9999);
/**//*Mainmenu*/
menu1=glutCreateMenu(menuFunc);
glutAddSubMenu("control",menu2);
glutAddSubMenu("shapes",menu3);
glutAddSubMenu("windows",menu4);
glutAddSubMenu("windowops",menu5);
glutAddSubMenu("gfxmodes",menu6);
glutAddSubMenu("reports",menu7);
glutAddSubMenu("menus",menu8);
glutAddMenuEntry("help(h)",101);
glutAddMenuEntry("quit(esc)",100);
}
5,创建窗口
本文中创建的窗口有4种类型,第1种是普通的RGB窗口,用来显示要绘制的图形,第2种是第1种窗口的子窗口(类似于“画中画”的效果),第3种是文本窗口和帮助窗口,第4种是颜色索引窗口。设置好窗口的显示模式,并根据保存的窗口大小和位置创建完窗口后,就可以对窗口进行OpenGL绘制的初始化工作,这是在gfxInit函数中完成的,最后就是为窗口加上各种事件处理函数。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voidmakeWindow(intindex)
{//建立窗口
charstr[99];
if(winId[index]!=0)
{//已经存在的窗口
/**//*warning("Attempttocreatewindowwhichisalready
created");*/
return;
}
switch(index)
{
//普通的RGB窗口
case0:/**//*ordinaryRGBwindows*/
case1:
case2:
case3:
setInitDisplayMode();
glutInitWindowPosition(pos[index][0],pos[index][1]);//窗口左上角位置
glutInitWindowSize(size[index][0],size[index][1]);//窗口大小
winId[index]=glutCreateWindow("");//保存窗口标识符
PR("Window%did=%d/n",index,winId[index]);
gfxInit(index);//初始化openGL
addCallbacks();
sprintf(str,"window%d(RGB)",index);
glutSetWindowTitle(str);
sprintf(str,"icon%d",index);
glutSetIconTitle(str);
glutSetMenu(menu1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
break;
case4:/**//*subwindow子窗口*/
setInitDisplayMode();
winId[index]=glutCreateSubWindow(winId[0],pos[index][0],pos[index]
[1],size[index][0],size[index][1]);
PR("Window%did=%d/n",index,winId[index]);
gfxInit(index);
glutDisplayFunc(drawScene);
glutVisibilityFunc(visible);
glutReshapeFunc(reshapeFunc);
break;
case5:/**//*helpwindow帮助窗口*/
case8:/**//*textwindow文本窗口*/
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowPosition(pos[index][0],pos[index][1]);
glutInitWindowSize(size[index][0],size[index][1]);
winId[index]=glutCreateWindow("");
PR("Window%did=%d/n",index,winId[index]);
/**//*addCallbacks();*/
glutKeyboardFunc(keyFunc);
glutSpecialFunc(specialFunc);
glClearColor(0.15,0.15,0.15,1.0);
glColor3f(1,1,1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,300,0,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if(index==5){
glutDisplayFunc(updateHelp);
glutSetWindowTitle("help(RGB)win5");
glutSetIconTitle("help");
}else{
glutDisplayFunc(updateText);
glutSetWindowTitle("text(RGB)win8");
glutSetIconTitle("text");
}
glutSetMenu(menu1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
break;
case6:/**//*colorindexwindow颜色索引窗口*/
case7:/**//*colorindexwindow*/
glutInitDisplayMode(GLUT_DOUBLE|GLUT_INDEX|GLUT_DEPTH);
glutInitWindowPosition(pos[index][0],pos[index][1]);
glutInitWindowSize(size[index][0],size[index][1]);
winId[index]=glutCreateWindow("");
PR("Window%did=%d/n",index,winId[index]);
gfxInit(index);
addCallbacks();
sprintf(str,"window%d(colorindex)",index);
glutSetWindowTitle(str);
sprintf(str,"icon%d",index);
glutSetIconTitle(str);
glutSetMenu(menu1);
glutAttachMenu(GLUT_RIGHT_BUTTON);
break;
}
}
为每个窗口初始化OpenGL时,首先通过redefineShapes为窗口建立其显示列表,然后渲染其背景矩阵,接着进行投影变换和视图变换,为了简单起见,作者采用了默认的白色光源来进行材质和光源位置的设置,最后就是启用光照并设置窗口的背景颜色。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voidgfxInit(intindex)
{//为每个窗口初始化OpenGL
GLfloatgrey10[]=
{0.10,0.10,0.10,1.0};
GLfloatgrey20[]=
{0.2,0.2,0.2,1.0};
GLfloatblack[]=
{0.0,0.0,0.0,0.0};
//光源位置
GLfloatdiffuse0[]=
{1.0,0.0,0.0,1.0};
GLfloatdiffuse1[]=
{0.0,1.0,0.0,1.0};
GLfloatdiffuse2[]=
{1.0,1.0,0.0,1.0};
GLfloatdiffuse3[]=
{0.0,1.0,1.0,1.0};
GLfloatdiffuse4[]=
{1.0,0.0,1.0,1.0};
#defineXX3
#defineYY3
#defineZZ-2.5
//背景的包围矩阵
floatvertex[][3]=
{
{-XX,-YY,ZZ},
{+XX,-YY,ZZ},
{+XX,+YY,ZZ},
{-XX,+YY,ZZ}
};
/*warning:ThisfuncmixesRGBAandCMAPcallsinanugly
fashion*/
redefineShapes(currentShape);/*setupdisplaylists建立显示列表*/
glutSetWindow(winId[index]);//设置为当前窗口
/*hack-redefineShapes
changesglutwin*/
/*Shadedbackdropsquare(RGBorCMAP)*/
//渲染背景矩阵
glNewList(100,GL_COMPILE);
glPushAttrib(GL_LIGHTING);
glDisable(GL_LIGHTING);
glBegin(GL_POLYGON);
glColor4fv(black);
glIndexi(0);
glVertex3fv(vertex[0]);
glColor4fv(grey10);
glIndexi(3);
glVertex3fv(vertex[1]);
glColor4fv(grey20);
glIndexi(4);
glVertex3fv(vertex[2]);
glColor4fv(grey10);
glIndexi(7);
glVertex3fv(vertex[3]);
glEnd();
glPopAttrib();
glIndexi(9);
glEndList();
/*Setproj+view*/
//投影变换和视图变换
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0,1.0,1.0,20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.);//gluLookAt前三个参数表示了观察点的位置,中间三个参数表示了观察目标的位置,最后三个参数代表从(0,0,0)到(x,y,z)的直线,它表示了观察者认为的“上”方向
glTranslatef(0.0,0.0,-1.0);//移入屏幕一个单位
if(index==6||index==7)//颜色索引模式
gotocolorindex;
/*Setbasicmaterial,lightingforRGBwindows*/
//材质和光源位置的设置(默认的白色光源)
if(index==0)
glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse0);
elseif(index==1)
glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse1);
elseif(index==2)
glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse2);
elseif(index==3)
glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse3);
elseif(index==4)
glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuse4);
//启用光源
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
if(index==4)
glClearColor(0.15,0.15,0.15,1);//设置子窗口的背景颜色
else
glClearColor(0.1,0.1,0.1,1.0);//其他窗口的背景颜色
return;
/*SetGLbasicsforCMAPwindows6,7*/
//颜色索引模式
colorindex:
glEnable(GL_DEPTH_TEST);
if(glutGet(GLUT_WINDOW_COLORMAP_SIZE)<16)
warning("Colormapsizetoosmallforcolorindexwindow");
/*Trytoreuseanexistingcolormap*/
if((index==6)&&(winId[7]!=0))
{
glutCopyColormap(winId[7]);
}elseif((index==7)&&(winId[6]!=0)){
glutCopyColormap(winId[6]);
}else{
glutSetColor(8,0.1,0.1,0.1);
glutSetColor(9,1.0,0.5,0.0);
glutSetColor(10,1.0,0.6,0.8);
}
glClearIndex(8);
glIndexi(index+3);
}
voidaddCallbacks(void)
{//为窗口增加回调函数
glutDisplayFunc(drawScene);
glutVisibilityFunc(visible);
glutReshapeFunc(reshapeFunc);
glutKeyboardFunc(keyFunc);
glutSpecialFunc(specialFunc);
glutMouseFunc(mouseFunc);
glutMotionFunc(motionFunc);
glutEntryFunc(entryFunc);
/*Callbacksforexoticinputdevices.Mustgetmydials&
buttonsback.*/
glutSpaceballMotionFunc(spaceballMotionCB);
glutSpaceballRotateFunc(spaceballRotateCB);
glutSpaceballButtonFunc(spaceballButtonCB);
glutButtonBoxFunc(buttonBoxCB);
glutDialsFunc(dialsCB);
glutTabletMotionFunc(tabletMotionCB);
glutTabletButtonFunc(tabletButtonCB);
}
6,动画效果
我在MFC中是通过设置一个定时器,并且在定时方法中修改旋转角度来刷新屏幕的,从而实现动画旋转的效果,在这里作者把这部分代码放到窗口的空闲事件处理函数中进行。每次执行时角度都进行了变换,并且通知窗口强制其重绘。
voididleFunc(void)
{
inti;
if(!leftDown&&!middleDown)//旋转角度加1
angle+=1;
angle=angle%360;
for(i=0;i<MAXWIN;i++)
{
if(winId[i]&&winVis[i]&&!winFreeze[i])
{
glutSetWindow(winId[i]);
glutPostRedisplay();//强制重画
}
}
}
7,自动演示
这里采用了一个小的技巧来实现多个窗口连续创建的自动演示功能。通过执行当前的动作后,为下一个应该接着发生的动作设置一个定时器,从而实现动作之间的接连发送效果。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voidautoDemo(intvalue)
{
staticintindex=0;
staticintcount=0;
staticintrestartValue=-2;
if(value==-999)
value=restartValue;
restartValue=value;
#defineAUTODELAY2(unsignedint)(AUTODELAY*0.66)
/*fprintf(stderr,"autoDemo:value%d/n",value);*/
if(!demoMode)
return;
if(menu_state==GLUT_MENU_IN_USE)
{
glutTimerFunc(AUTODELAY/2,autoDemo,value);
return;
}
switch(value)
{
/*Entrypoint;killoffexistingwindows.*/
case-2:
killAllWindows();
glutTimerFunc(AUTODELAY/2,autoDemo,1);
break;
/*Startmakingwindows*/
case-1:
makeWindow(0);
glutTimerFunc(AUTODELAY,autoDemo,0);/*skipcase0
firsttime*/
break;
/*Changeshape&backdrop*/
case0:
currentShape=(currentShape+1)%9;
redefineShapes(currentShape);
count+=1;
if(count%2)
backdrop=!backdrop;
glutTimerFunc(AUTODELAY,autoDemo,1);
break;
/*Keepmakingwindows*/
case1:
makeWindow(1);
glutTimerFunc(AUTODELAY,autoDemo,2);
break;
case2:
makeWindow(2);
glutTimerFunc(AUTODELAY,autoDemo,3);
break;
case3:
makeWindow(3);
glutTimerFunc(AUTODELAY,autoDemo,4);
break;
case4:
makeWindow(4);
glutTimerFunc(AUTODELAY,autoDemo,5);
break;
case5:
makeWindow(5);
glutTimerFunc(AUTODELAY*2,autoDemo,51);
break;
case51:
makeWindow(6);
glutTimerFunc(AUTODELAY*2,autoDemo,52);
break;
case52:
makeWindow(7);
glutTimerFunc(AUTODELAY*2,autoDemo,53);
break;
/*Killlast3windows,leave4up.*/
case53:
killWindow(7);
glutTimerFunc(AUTODELAY,autoDemo,54);
break;
case54:
killWindow(6);
glutTimerFunc(AUTODELAY,autoDemo,6);
break;
case6:
killWindow(5);
glutTimerFunc(AUTODELAY,autoDemo,7);
break;
case7:
killWindow(4);
glutTimerFunc(AUTODELAY,autoDemo,700);
break;
/*Changeshapeagain*/
case700:
currentShape=(currentShape+1)%9;
redefineShapes(currentShape);
glutTimerFunc(AUTODELAY,autoDemo,701);
break;
/*Cycle4mainwindowsthroughvariouswindowops.*/
case701:
positionWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?701:702);
break;
case702:
reshapeWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?702:703);
break;
case703:
iconifyWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?703:704);
break;
case704:
showWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?704:705);
break;
case705:
hideWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?705:706);
break;
case706:
showWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?706:707);
break;
case707:
pushWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?707:708);
break;
case708:
popWindow(index);
index=(index+1)%4;
glutTimerFunc(AUTODELAY2,autoDemo,index>0?708:8);
break;
/*Killallwindows*/
case8:
killWindow(3);
glutTimerFunc(AUTODELAY,autoDemo,9);
break;
case9:
killWindow(2);
glutTimerFunc(AUTODELAY,autoDemo,10);
break;
case10:
killWindow(1);
glutTimerFunc(AUTODELAY,autoDemo,11);
break;
case11:
killWindow(0);
glutTimerFunc(AUTODELAY,autoDemo,-1);/*backtostart*/
break;
}
}
8,图形绘制代码部分
所有窗口都使用drawScene来绘制其图形,只是各个窗口调用的显示列表不同而已,这通过各个窗口的标识符来进行区别,并且通过调用trackBall(APPLY, 0, 0, 0, 0);来绘制鼠标左键控制的结果(旋转后的角度或者平移后的距离),如果窗口还有文本要显示,则调用showText来显示文本信息。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voiddrawScene(void)
{
intwinIndex;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
winIndex=idToIndex(glutGetWindow());
/*printf("drawSceneforindex%d,id%d/n",winIndex,
glutGetWindow());*/
glPushMatrix();
glLineWidth(lineWidth);
if(backdrop)
glCallList(100);
/*Leftbuttonspinning*/
trackBall(APPLY,0,0,0,0);//鼠标左键控制结果的绘制
/*Applycontinuousspinning*/
glRotatef(angle,0,1,0);//绕y轴旋转
glCallList(winIndex+1);
glPopMatrix();
if(text[winIndex])
showText();//显示文本
glutSwapBuffers();
}
/*showText-RendersometextinthecurrentGLUTwindow*/
voidshowText(void)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0,100,0,100);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3f(1.0,1.0,1.0);
glIndexi(7);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glLineWidth(lineWidth);
textString(1,1,"GLUT_BITMAP_8_BY_13",GLUT_BITMAP_8_BY_13);
textString(1,5,"GLUT_BITMAP_9_BY_15",GLUT_BITMAP_9_BY_15);
textString(1,10,"GLUT_BITMAP_TIMES_ROMAN_10",GLUT_BITMAP_TIMES_ROMAN_10);
textString(1,15,"GLUT_BITMAP_TIMES_ROMAN_24",GLUT_BITMAP_TIMES_ROMAN_24);
strokeString(1,25,"GLUT_STROKE_ROMAN",GLUT_STROKE_ROMAN);
strokeString(1,35,"GLUT_STROKE_MONO_ROMAN",GLUT_STROKE_MONO_ROMAN);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
9.文本显示
这里有两种文本的显示方式,第一种采用位图字体来显示文本,第二种采用Stroke 字体来显示文本。
{//显示文本,x,y是起始坐标,msg:要显示的文本,font:显示的字体
glRasterPos2f(x,y);//定位位图字体
while(*msg)
{
glutBitmapCharacter(font,*msg);
msg++;
}
}
/*strokeString-Strokefontstring*/
voidstrokeString(intx,inty,char*msg,void*font)
{
glPushMatrix();
glTranslatef(x,y,0);
glScalef(.04,.04,.04);
while(*msg)
{
glutStrokeCharacter(font,*msg);
msg++;
}
glPopMatrix();
}
10,显示列表
显示列表由于是已经编译好的代码段,因此可以加快程序的速度。这里每种要绘制的图形(如球,茶壶等)都有实体和虚体两种模式可以选择。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voidredefineShapes(intshape)
{
inti;
//根据窗口号来绘制两种不同类型的图形
#defineC3/
switch(i)/
{/
case0:/
case3:/
C1;/
break;/
/
case1:/
case2:/
case4:/
case6:/
case7:/
C2;/
break;/
}/
currentShape=shape
for(i=0;i<MAXWIN;i++)
{//为每个要创建的窗口建立显示列表
if(winId[i])
{
glutSetWindow(winId[i]);
if(glIsList(i+1))
glDeleteLists(i+1,1);//若已经存在显示列表,就删除掉
glNewList(i+1,GL_COMPILE);//为当前窗口新建显示列表
switch(shape)
{
#undefC1
#defineC1glutSolidSphere(1.5,10,10)
#undefC2
#defineC2glutWireSphere(1.5,10,10)
case0:
C3;
break;
#undefC1
#defineC1glutSolidCube(2)
#undefC2
#defineC2glutWireCube(2)
case1:
C3;
break;
#undefC1
#defineC1glutSolidCone(1.5,1.75,10,10);
#undefC2
#defineC2glutWireCone(1.5,1.75,10,10);
case2:
C3;
break;
#undefC1
#defineC1glutSolidTorus(0.5,1.1,10,10)
#undefC2
#defineC2glutWireTorus(0.5,1.1,10,10)
case3:
C3;
break;
#undefC1
#defineC1glScalef(.8,.8,.8);glutSolidDodecahedron()
#undefC2
#defineC2glScalef(.8,.8,.8);glutWireDodecahedron()
case4:
C3;
break;
#undefC1
#defineC1glScalef(1.5,1.5,1.5);glutSolidOctahedron()
#undefC2
#defineC2glScalef(1.5,1.5,1.5);glutWireOctahedron()
case5:
C3;
break;
#undefC1
#defineC1glScalef(1.8,1.8,1.8);glutSolidTetrahedron()
#undefC2
#defineC2glScalef(1.8,1.8,1.8);glutWireTetrahedron()
case6:
C3;
break;
#undefC1
#defineC1glScalef(1.5,1.5,1.5);glutSolidIcosahedron()
#undefC2
#defineC2glScalef(1.5,1.5,1.5);glutWireIcosahedron()
case7:
C3;
break;
#undefC1
#defineC1glutSolidTeapot(1.5);
#undefC2
#defineC2glutWireTeapot(1.5);
case8:
C3;
break;
}
glEndList();
}
}
}
11,鼠标事件处理
这里鼠标有三种控制方式,1)左键进行旋转。2)中键进行xy平面的平移。3)左键+中键进行关于Z轴的平移(产生缩放的效果)。鼠标的事件模式这里有RESET,MOUSEBUTTON,APPLY, MOUSEMOTION四种,其中RESET是用来对清空以往的操作,让图形回到原点处。MOUSEBUTTON是鼠标按下激发的,用来记录下鼠标的位置,MOUSEMOTION是鼠标按下后并移动鼠标时,用来计算旋转的角度或者平移的距离,而最终这些变换后产生的效果的绘制是APPLY发生的,在这里进行了实际的旋转和平移动作。
<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->voidtrackBall(intmode,intbutton,intstate,intx,inty)
{//鼠标控制
staticintstartMX=0,startMY=0;/*initialmousepos*/
staticintdeltaMX=0,deltaMY=0;/*initialmousepos*/
staticfloatsteadyXangle=0.0,steadyYangle=0.0;//绕x,y轴旋转的角度
staticfloatvarXangle=0.0,varYangle=0.0;
staticfloatsteadyX=0.0,steadyY=0.0,steadyZ=0.0;//;沿坐标轴缩放的比例
staticfloatvarX=0.0,varY=0.0,varZ=0.0;
switch(mode)
{
caseRESET://重置
steadyXangle=steadyYangle=steadyX=steadyY=steadyZ=0.0;
break;
caseMOUSEBUTTON:
if(button==GLUT_LEFT_BUTTON&&state==GLUT_DOWN&&!middleDown)
{//左键按下
STARTROTATE(x,y);//开始旋转,记录起始点坐标
leftDown=GL_TRUE;
}
elseif(button==GLUT_LEFT_BUTTON&&state==GLUT_DOWN&&
middleDown)
{//原来中键已按下且未放开,这时按下左键,则停止移动,开始缩放
STOPPAN(x,y);
STARTZOOM(x,y);
leftDown=GL_TRUE;
}
elseif(button==GLUT_MIDDLE_BUTTON&&state==GLUT_DOWN&&
!leftDown)
{//中键按下,开始移动
STARTPAN(x,y);
middleDown=GL_TRUE;
}
elseif(button==GLUT_MIDDLE_BUTTON&&state==GLUT_DOWN&&
leftDown)
{//原来左键已按下且未放开,这时按下中键,则停止旋转,开始缩放
STOPROTATE(x,y);
STARTZOOM(x,y);
middleDown=GL_TRUE;
}
elseif(state==GLUT_UP&&button==GLUT_LEFT_BUTTON&&!middleDown)
{//左键放开且中键未按下,停止旋转
STOPROTATE(x,y);
leftDown=GL_FALSE;
}
elseif(state==GLUT_UP&&button==GLUT_LEFT_BUTTON&&middleDown)
{//原来左中键已按下且未放开,这时放开左键,则停止缩放,开始旋转
STOPZOOM(x,y);
STARTROTATE(x,y);
leftDown=GL_FALSE;
}
elseif(state==GLUT_UP&&button==GLUT_MIDDLE_BUTTON&&!leftDown)
{
STOPPAN(x,y);
middleDown=GL_FALSE;
}
elseif(state==GLUT_UP&&button==GLUT_MIDDLE_BUTTON&&leftDown)
{
STOPZOOM(x,y);
STARTROTATE(x,y);
middleDown=GL_FALSE;
}
break;
caseAPPLY://结果的绘制
if(leftDown&&!middleDown)
{//旋转
glTranslatef(steadyX,steadyY,steadyZ);
glRotatef(varXangle,0,1,0);//绕y轴旋转
glRotatef(varYangle,1,0,0);//绕x轴旋转
}
/*Middlebuttonpan*/
elseif(middleDown&&!leftDown)
{//平移
glTranslatef(varX,varY,steadyZ);//在xy平面内平移
glRotatef(steadyXangle,0,1,0);
glRotatef(steadyYangle,1,0,0);
}
/*Left+middlezoom.*/
elseif(leftDown&&middleDown)
{//缩放(其实不能说缩放,只是让z轴的距离变化,镜头推近推远产生缩放的感觉)
glTranslatef(steadyX,steadyY,varZ);
glRotatef(steadyXangle,0,1,0);
glRotatef(steadyYangle,1,0,0);
}
/*Nothingdown.*/
else
{
glTranslatef(steadyX,steadyY,steadyZ);
glRotatef(steadyXangle,0,1,0);
glRotatef(steadyYangle,1,0,0);
}
break;
caseMOUSEMOTION:
deltaMX=x-startMX;//计算x的偏移量
deltaMY=startMY-y;//y的偏移量
if(leftDown&&!middleDown)
{//旋转
varXangle=fixAngle(steadyXangle+deltaMX);//计算旋转后对于y轴的角度
varYangle=fixAngle(steadyYangle+deltaMY);//计算旋转后对于x轴的角度
}
elseif(middleDown&&!leftDown)
{//移动
varX=steadyX+deltaMX/100.0;//平移后相对于x轴的距离
varY=steadyY+deltaMY/100.0;//平移后相对于y轴的距离
}
elseif(leftDown&&middleDown)
{//缩放
varZ=steadyZ-deltaMY/50.0;//相对于z轴的缩放比例
}
break;
}
}
最后,代码中还加入了对空间球,图形板,拨号按键盒的事件处理支持。
相关推荐
关于图像标注的源码 值得收藏matlab 代码
CNC源代码分析,讲解每个环节的原理以及算法处理,代码比较强悍精炼,可以学习商用均可,适合所有行业人员
KVM 源代码分析-虚拟机创建和运行流程代码分析.pdf 学习资料 复习资料 教学资源
OSG核心源码解析,对核心源码进行详细解析与说明
《视觉几何三维重建-OpenMVS源码解析》课程手册9.28
dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.dubbo源码解析2.
zabbix server c语言源码分析 zabbix agent c语言源码分析 有助于理解zabbix运行流程,agent部分比较详细!
Spring源代码分析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器...
QuickJS架构及源代码分析. ⼀、 QuickJS项⽬介绍 1. JavaScript简介 2. QuickJS项⽬简介 3. QuickJS项⽬的⽬录结构 ⼆、 QuickJS架构介绍 1. 架构简介 2. 编译&优化过程 3. 解释执⾏过程 三、 QuickJS源码解读 1. ...
MTK系列WIFI驱动源码分析,有助于分析问题与优化驱动!
CAS源码分析图,
Minix3 源码的解析,没有繁琐,很快能看明白。 最重要是内容少而精!
本文档是qemu以及linux kernel中kvm模块代码解析,供参考
wireshark源码分析问题这几天在看wireshark(ethereal)源代码。看源代码的主要兴趣点是它的分析模块(dissect)。分析之后他的数据存在哪儿,怎么打印的(-V参数)。我想把分析后的数据,提取出来,存在自己定义的...
基于STM32的C语言编写的ESC32电机驱动(电调),本文档重点介绍整个程序架构,流程图,以及ad采样滤波过零换向,速度生力拟合,启动算法,恒力输出模式等。
Zookeeper源码分析.epub
GRUB源代码分析.pdf
讲述了GRBL的模块功能,主要介绍讲解了直线插补法和圆弧插补算法的原理,如何将脉冲转换为电机转动的频率。
h323源码分析
Spring源码分析.pdf