OpenGL 和 GLUT: 强大的图形库和实用工具包





5.00/5 (19投票s)
解释如何使用此库的文章
开始前的一点说明
要使用 OpenGL 和 GLUT,请从 http://www.videotutorialsrock.com/opengl2.exe 下载 OpenGL。
然后从 http://www.xmission.com/~nate/glut/glut-3.7.6-src.zip 下载 GLUT。
只需安装 OpenGL 并将 GLUT 源代码解压到下述位置即可。这将使您能够编译提供的代码。请注意,如果您的头文件导致问题,请删除 GL 以使头文件变为 <glut.h>。那么,OpenGL、GLUT 是什么,我们为什么要使用它们?这些问题是本文的重点。
引言
OpenGL 是图形硬件的接口。GL 代表图形库。因此,它主要是一个低级图形库规范。GL 提供了用于在二维或三维中指定几何对象的命令,以及控制这些对象如何在显示器上绘制的命令。这里的对象是点、线、多边形、图像和位图。OpenGL 确实提供了用于执行窗口任务或获取用户输入的命令。这些命令由 OpenGL 实用工具包 (GLUT) 提供。GLUT 提供了创建窗口、子窗口和菜单的命令;以及通过回调函数处理各种设备的输入。安装 OpenGL 时,必须安装最新版本的 GLUT,它提供了四个文件:glut.h、glut.lib、glut.def 和 glut32.dll。在 Visual Studio 中使用 GLUT 时,必须将头文件和库文件分别放在 VC++ 的 include 和 library 目录中。定义文件与 DLL 有关,但 gllut32.dll 必须放在 %windir%\system32 目录中。
由于 OpenGL 的绘制命令仅限于生成简单几何图元(点、线和多边形)的命令,因此创建了 OpenGL 实用工具包 (GLUT) 来帮助开发更复杂的三维对象,例如球体、圆环体,甚至茶壶。GLUT 可能不适合功能齐全的 OpenGL 应用程序,但它是学习 OpenGL 的一个有用起点。
GLUT 旨在满足 OpenGL 程序对与窗口系统无关的编程接口的需求。该接口被设计得简单,但仍能满足有用 OpenGL 程序的需求。将窗口系统操作从 OpenGL 中移除是一个明智的决定,因为它允许 OpenGL 图形系统被重新定位到各种系统,包括功能强大但昂贵的图形工作站,以及大规模生产的图形系统,如视频游戏、交互式电视的机顶盒以及 PC。GLUT 简化了使用 OpenGL 渲染的程序的实现。GLUT 应用程序编程接口 (API) 需要很少的例程即可显示使用 OpenGL 渲染的图形场景。GLUT 例程的参数也相对较少。
那么,给我看些代码
虽然文章还很早,请查看此代码及其代码体的结构。然后查看输出,这是一个包含基本三角形的窗口。
#include <glut.h>
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0.0);
glVertex3f(0.5,0.0,0.0);
glVertex3f(0.0,0.5,0.0);
glEnd();
glFlush();
}
void main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("3D Tech- GLUT Tutorial");
glutDisplayFunc(renderScene);
glutMainLoop();
}
在 Visual Studio 或命令行上编译时,输出如下。但请注意 main 函数体之后发生的函数顺序。

初始化
以 glutInit
- 为前缀的例程用于初始化 GLUT 状态。主要的初始化例程是 glutInit
,它应该在 GLUT 程序中仅调用一次。在调用 glutInit
之前,不应调用任何不带 glutInit
- 前缀的 GLUT 或 OpenGL 例程。其他 glutInit
- 例程可以在 glutInit
之前调用。原因是这些例程可用于设置可能被 glutInit
中的命令处理修改的默认窗口初始化状态。例如,可以在 glutInit
之前调用 glutInitWindowSize(400, 400)
来指示 400x400 是程序的默认窗口大小。在 glutInit
之前设置初始窗口大小或位置允许 GLUT 程序用户使用命令行参数指定初始大小或位置。glutInit
用于初始化 GLUT 库。
void glutInit(int *argcp, char **argv);
rgcp
是指向 main
函数的程序的未修改的 argc
变量的指针。返回时,argcp
指向的值将被更新,因为 glutInit
会提取 GLUT 库的所有命令行选项。argv 是指 main 函数的程序的未修改的 argv 变量。与 argcp
一样,argv
的数据将被更新,因为 glutInit
会提取 GLUT 库理解的所有命令行选项。glutInit
将初始化 GLUT 库并与窗口系统协商会话。在此过程中,如果 GLUT 无法正确初始化,glutInit
可能会导致 GLUT 程序终止并向用户显示错误消息。这种情况的示例包括无法连接到窗口系统、缺少对 OpenGL 的窗口系统支持以及无效的命令行选项。glutInit
还会处理命令行选项,但解析的具体选项取决于窗口系统。
glutInitDisplayMode
:glutInitDisplayMode
设置初始显示模式。
void glutInitDisplayMode(unsigned int mode);
glutInitWindowPosition
,glutInitWindowSize
:glutInitWindowPosition
和 glutInitWindowSizeset
分别设置初始窗口位置和大小。
void glutInitWindowSize(int width, int height);
void glutInitWindowPosition(int x, int y);
width Width in pixels.
height Height in pixels.
x Window X location in pixels.
y Window Y location in pixels.
由 glutCreateWindow
创建的窗口将要求以当前的初始窗口位置和大小创建。初始窗口位置 GLUT 状态的初始值为 -1
和 -1
。如果初始窗口位置的 X 或 Y 分量为负值,则实际窗口位置将留给窗口系统确定。initialwindow
大小 GLUT 状态的初始值为 300x300。initialwindow
大小分量必须大于零。初始窗口位置和大小值的意图是为窗口的初始大小和位置向窗口系统提供建议。窗口系统没有义务使用此信息。因此,GLUT 程序不应假定窗口已按指定的大小或位置创建。GLUT 程序应使用窗口的 reshape 回调来确定窗口的实际大小。
int glutCreateWindow(char *name);
note: name ASCII character string for use as window name.
glutCreateWindow
创建一个顶层窗口。该名称将作为窗口的名称提供给窗口系统。意图是窗口系统将用该名称标记窗口。隐式地,当前窗口被设置为新创建的窗口。每个创建的窗口都有一个唯一的关联 OpenGL 上下文。窗口关联的 OpenGL 上下文的状态更改可以在窗口创建后立即完成。窗口的显示状态最初是让窗口显示。但直到进入 glutMainLoop
后,窗口的显示状态才真正生效。这意味着在调用 glutMainLoop
之前,渲染到创建的窗口是无效的,因为窗口还无法显示。返回值是窗口的唯一小整数标识符。分配的标识符范围从 1 开始。此窗口标识符可用于调用 glutSetWindow
。
void glutDisplayFunc(void (*func)(void));
func The new display callback function.
glutDisplayFunc
为当前窗口设置显示回调。当 GLUT 确定需要重新绘制窗口的正常平面时,将调用窗口的显示回调。在回调之前,当前窗口被设置为需要重新绘制的窗口,并且(如果没有注册 overlay 显示回调)使用的层被设置为正常平面。显示回调的调用不带参数。应在响应回调时重新绘制整个正常平面区域(包括辅助缓冲区,如果程序依赖于其状态)。GLUT 根据窗口的重新绘制状态确定何时触发显示回调。
窗口的重新绘制状态可以通过调用 glutPostRedisplay
显式设置,也可以通过窗口系统报告的窗口损坏隐式设置。窗口的多个已发布重新绘制请求会被 GLUT 合并,以最小化调用的显示回调次数。当为窗口建立 overlay 时,但没有注册 overlay 显示回调,则显示回调将用于重新绘制 overlay 和正常平面(即,如果设置了重新绘制状态或 overlay 重新绘制状态,则会调用它)。在这种情况下,在进入显示回调时,使用的层不会被隐式更改。当创建一个窗口时,该窗口不存在显示回调。程序员有责任在显示窗口之前为该窗口安装显示回调。任何显示的窗口都必须注册显示回调。如果一个窗口在未注册显示回调的情况下显示,则会发生致命错误。从 GLUT 3.0 开始,将 NULL
传递给 glutDisplayFunc
是非法的,没有办法“注销”显示回调(尽管总是可以注册另一个回调例程)。从显示回调返回后,窗口的正常损坏状态(通过调用 glutLayerGet(GLUT NORMAL DAMAGED)
返回)将被清除。如果没有注册 overlay 显示回调,窗口的 overlay 损坏状态(通过调用 glutLayerGet(GLUT OVERLAY DAMAGED)
返回)也将被清除。
开始事件处理
在 GLUT 程序完成初始设置(如创建窗口和菜单)后,GLUT 程序通过调用 glutMainLoop
进入 GLUT 事件处理循环。glutMainLoop
进入 GLUT 事件处理循环。请注意,这是上面基本程序中调用的最后一个 API。
void glutMainLoop(void);
glutMainLoop
进入 GLUT 事件处理循环。此例程在 GLUT 程序中最多应调用一次。一旦调用,此例程将永远不会返回。它会在必要时调用已注册的任何回调。GLUT 支持两种类型的窗口:顶层窗口和子窗口。这两种类型都支持 OpenGL 渲染和 GLUT 回调。这两种类型的窗口共享一个标识符空间。
现在让我们来检查动画
这是与上面类似的的代码。但是,当您使用 cl.exe VC++ 编译器驱动程序编译它时,该形状会旋转并改变大小。
#include <math.h><glut.h>
#include <glut.h><math.h>
float angle = 0.0;
float red=1.0, blue=1.0, green=1.0;
void changeSize(int w, int h) {
// Prevent a divide by zero, when window is too short
// (you cant make a window of zero width).
if(h == 0)
h = 1;
float ratio = 1.0* w / h;
// Reset the coordinate system before modifying
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set the viewport to be the entire window
glViewport(0, 0, w, h);
// Set the correct perspective.
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,
0.0,0.0,-1.0,
0.0f,1.0f,0.0f);
}
void renderScene(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(angle,0.0,1.0,0.0);
glColor3f(red,green,blue);
glBegin(GL_TRIANGLES);
glVertex3f(-0.5,-0.5,0.0);
glVertex3f(0.5,0.0,0.0);
glVertex3f(0.0,0.5,0.0);
glEnd();
glPopMatrix();
angle++;
glutSwapBuffers();
}
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
}
void processSpecialKeys(int key, int x, int y) {
switch(key) {
case GLUT_KEY_F1 : red = 1.0; green = 0.0; blue = 0.0; break;
case GLUT_KEY_F2 : red = 0.0; green = 1.0; blue = 0.0; break;
case GLUT_KEY_F3 : red = 0.0; green = 0.0; blue = 1.0; break;
}
}
void main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("Lighthouse 3D - GLUT Tutorial");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
//adding here the setting of keyboard processing
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(processSpecialKeys);
glutMainLoop();
}
输出如上所述。现在,让我们通过向代码添加一些功能来进一步检查这个图形库。
#include <math.h><math.h>
#include <glut.h><glut.h>
#include <stdio.h><stdio.h>
#include <string.h><string.h>
float angle=0.0,deltaAngle = 0.0,ratio;
float x=0.0f,y=1.75f,z=5.0f;
float lx=0.0f,ly=0.0f,lz=-1.0f;
int deltaMove = 0,h,w;
int font=(int)GLUT_BITMAP_8_BY_13;
static GLint snowman_display_list;
int bitmapHeight=13;
int frame,time,timebase=0;
char s[30];
void initWindow();
void changeSize(int w1, int h1)
{
if(h1 == 0)
h1 = 1;
w = w1;
h = h1;
ratio = 1.0f * w / h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45,ratio,0.1,1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void drawSnowMan() {
glColor3f(1.0f, 1.0f, 1.0f);
glTranslatef(0.0f ,0.75f, 0.0f);
glutSolidSphere(0.75f,20,20);
glTranslatef(0.0f, 1.0f, 0.0f);
glutSolidSphere(0.25f,20,20);
glPushMatrix();
glColor3f(0.0f,0.0f,0.0f);
glTranslatef(0.05f, 0.10f, 0.18f);
glutSolidSphere(0.05f,10,10);
glTranslatef(-0.1f, 0.0f, 0.0f);
glutSolidSphere(0.05f,10,10);
glPopMatrix();
glColor3f(1.0f, 0.5f , 0.5f);
glRotatef(0.0f,1.0f, 0.0f, 0.0f);
glutSolidCone(0.08f,0.5f,10,2);
}
GLuint createDL() {
GLuint snowManDL;
snowManDL = glGenLists(2);
glNewList(snowManDL+1,GL_COMPILE);
drawSnowMan();
glEndList();
glNewList(snowManDL,GL_COMPILE);
for(int i = -3; i < 3; i++)
for(int j=-3; j < 3; j++) {
glPushMatrix();
glTranslatef(i*10.0,0,j * 10.0);
glCallList(snowManDL+1);
glPopMatrix();
}
glEndList();
return(snowManDL);
}
void initScene() {
glEnable(GL_DEPTH_TEST);
snowman_display_list = createDL();
}
void orientMe(float ang) {
lx = sin(ang);
lz = -cos(ang);
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void moveMeFlat(int i) {
x = x + i*(lx)*0.1;
z = z + i*(lz)*0.1;
glLoadIdentity();
gluLookAt(x, y, z,
x + lx,y + ly,z + lz,
0.0f,1.0f,0.0f);
}
void setOrthographicProjection() {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, w, 0, h);
glScalef(1, -1, 1);
glTranslatef(0, -h, 0);
glMatrixMode(GL_MODELVIEW);
}
void resetPerspectiveProjection() {
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void renderBitmapString(float x, float y, void *font,char *string)
{
char *c;
glRasterPos2f(x, y);
for (c=string; *c != '\0'; c++) {
glutBitmapCharacter(font, *c);
}
}
void renderScene(void) {
if (deltaMove)
moveMeFlat(deltaMove);
if (deltaAngle) {
angle += deltaAngle;
orientMe(angle);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw ground
glColor3f(0.9f, 0.9f, 0.9f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, 0.0f, -100.0f);
glVertex3f(-100.0f, 0.0f, 100.0f);
glVertex3f( 100.0f, 0.0f, 100.0f);
glVertex3f( 100.0f, 0.0f, -100.0f);
glEnd();
// Draw 36 SnowMen
glCallList(snowman_display_list);
frame++;
time=glutGet(GLUT_ELAPSED_TIME);
if (time - timebase > 1000) {
sprintf(s,"FPS:%4.2f",frame*1000.0/(time-timebase));
timebase = time;
frame = 0;
}
glColor3f(0.0f,1.0f,1.0f);
setOrthographicProjection();
glPushMatrix();
glLoadIdentity();
renderBitmapString(30,15,(void *)font,"GLUT Tutorial @ 3D Tech");
renderBitmapString(30,35,(void *)font,s);
renderBitmapString(30,55,(void *)font,"Esc - Quit");
glPopMatrix();
resetPerspectiveProjection();
glutSwapBuffers();
}
void processNormalKeys(unsigned char key, int x, int y) {
if (key == 27)
exit(0);
}
void pressKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT : deltaAngle = -0.01f;break;
case GLUT_KEY_RIGHT : deltaAngle = 0.01f;break;
case GLUT_KEY_UP : deltaMove = 1;break;
case GLUT_KEY_DOWN : deltaMove = -1;break;
}
}
void releaseKey(int key, int x, int y) {
switch (key) {
case GLUT_KEY_LEFT : if (deltaAngle < 0.0f)
deltaAngle = 0.0f;
break;
case GLUT_KEY_RIGHT : if (deltaAngle > 0.0f)
deltaAngle = 0.0f;
break;
case GLUT_KEY_UP : if (deltaMove > 0)
deltaMove = 0;
break;
case GLUT_KEY_DOWN : if (deltaMove < 0)
deltaMove = 0;
break;
}
}
void initWindow() {
glutIgnoreKeyRepeat(1);
glutKeyboardFunc(processNormalKeys);
glutSpecialFunc(pressKey);
glutSpecialUpFunc(releaseKey);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
initScene();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(640,360);
glutCreateWindow("SnowMen from Lighthouse3D");
// register all callbacks
initWindow();
glutMainLoop();
return(0);
}
这是结果。

上面的代码包含更多函数和一个浮点数,用于指示我们正在绘制几何形状。但在我们深入研究这类函数和一些 3D 应用程序之前,我们将回顾迄今为止所采取的步骤。
您应该了解的关于 Windows 和 GLUT 的知识
void glutInit(int *argc, char **argv);
glutInit()
是应该首先调用的函数,它解析特定于窗口系统的参数,例如用于让 X11 导出到其他屏幕的 -display
参数。确保将其与 &argc
作为第一个参数一起调用,因为该函数需要一个指针而不是普通的 argc
。因此,您应该调用 glutInit(&argc, argv);
glutInitDisplayMode(unsigned int mode);
glutInitDisplayMode()
设置初始显示模式,您应该传入 OR 组合的模式链,有各种选项,如 GLUT_RGBA
、GLUT_RGB
、GLUT_INDEX
、GLUT_SINGLE
、GLUT_DOUBLE
、GLUT_ACCUM
、GLUT_ALPHA
、GLUT_DEPTH
、GLUT_STENCIL
、GLUT_MULTISAMPLE
、GLUT_STEREO
、GLUT_LUMINANCE
。我只想提一下 GLUT_RGBA
表示您想使用 RGBA 颜色模型(默认),GLUT_DOUBLE
表示您想使用双缓冲,这意味着您创建 2 个虚拟屏幕,一个可见,一个在后台,在后台屏幕上进行更改,然后使用 glutSwapBuffers()
函数交换缓冲区。GLUT_SINGLE
使用单缓冲,这对于动画来说并不是真正的推荐,但如果您不指定其他内容,则这是默认设置。如果您使用 GLUT_INDEX
(颜色索引模式),您应该手动使用 glutSetColor()
函数处理颜色映射,有关更多信息,请参阅 manpage。
glutInitWindowSize(int width, int height);
glutInitWindowSize() sets the initial size of the window.
glutInitWindowPosition(int x, int y);
glutInitWindowPosition();
设置窗口的初始位置,但这很容易被您的窗口管理器覆盖。
void glutFullScreen(void);
glutFullScreen();
requests that the window is made full screen
int glutCreateWindow(char *name)
glutCreateWindow()
为您创建窗口,您传入的 string
将是窗口的标题。窗口仅在进入 glutMainLoop()
时显示(有关实际启动程序和显示窗口的信息,请参阅“您应该了解的关于实际启动程序和显示窗口的信息”)。此函数返回一个整数,该整数是窗口标识符。某些函数需要此标识符来知道您指的是哪个窗口,例如 glutDestroyWindow
。
void glutDestroyWindow(int win)
glutDestroyWindow
销毁一个窗口,win
参数是上面提到的窗口标识符。当您销毁窗口时,程序不会终止,只有窗口被销毁。(请参阅下面的示例。)
您应该了解的关于事件和 GLUT 的知识
为了理解以下内容,我将首先解释什么是回调。当发生某个特定事件时,您希望程序执行某些操作。因此,在事件 E 发生时,调用方法/函数/过程 M。回调刚刚发生。在此部分中,您可以定义当事件发生时必须调用哪个函数。(事件是发生的事情:您移动鼠标、按下按键、调整窗口大小……主要由用户生成。)现在我将定义最常用的 GLUT 回调。
void glutDisplayFunc(void (*func)(void));
这指定了在重绘窗口时需要调用的函数。当窗口首次显示、弹出、内容损坏(例如被另一个窗口覆盖)时,都会调用此函数。还可以强制重绘,请参阅下面的 glutPostRedisplay()
。示例可能如下所示:
void doMagic(void){
// put everything on the screen
}
要将 doMagic()
设为您的显示函数,您将在源代码中添加以下行:
glutDisplayFunc(doMagic);
void glutPostRedisplay(void);
当您在代码中的某处放置 glutPostRedisplay();
时,这意味着使用 glutDisplayFunc()
定义的函数将在下一个合适的机会被调用。它将当前窗口标记为需要重绘。
void glutReshapeFunc(void (*func)(int width, int height));
每当窗口被移动和/或调整大小时,都会调用使用 glutReshapeFunc
定义的回调。参数是窗口的新宽度和新高度。
void glutTimerFunc(unsigned int msecs,void (*func)(int value), value);
定义一个定期调用的回调,您可以注册多个回调但不能注销它们,您应该通过将值设置为方法会忽略它的值来忽略这些回调。msecs
是以毫秒为单位的时间,在此时间内回调至少会被触发一次。
void glutKeyboardFunc(void (*func)(unsigned char key,int x, int y));
键盘事件的回调,key 是按下键的 ASCII 值,x 和 y 是按键时鼠标的坐标。
void glutMouseFunc(void (*func)(int button, int state, int x, int y));
鼠标单击时触发的回调。Button 可以是 GLUT_LEFT_BUTTON
、GLUT_MIDDLE_BUTTON
或 GLUT_RIGHT_BUTTON
。State 定义了您实际的操作,是按下按钮还是释放按钮,这些由 GLUT_UP
或 GLUT_DOWN
定义。x 和 y 是鼠标的坐标。
void glutMotionFunc(void (*func)(int x, int y));
鼠标移动(当一个或多个按钮被按下时)时触发的回调。x
和 y
是坐标。
void glutIdleFunc(void (*func)(void));
我们很快就会看到,程序在您进入等待事件的主循环时启动,这可以与以下内容进行比较:
while(true){
// let the world move
}
但是,并非每次发生需要处理的事件时都会调用此函数,这时空闲函数就派上用场了。这正是 glutIdleFunc()
的用武之地。当需要连续动画时,此函数非常有用。
重要提示:您可以通过将 NULL 作为函数名传递来撤销大多数回调。
您应该了解的关于在 GLUT 中创建 3D 对象的信息
glut 的另一个优点是 glut 提供了一些预定义的图元,您可以轻松地将它们放在屏幕上。我将在下面列出这些图元,大多数参数不言自明。每个图元都有实心或线框两种样式。
void glutSolidSphere(GLdouble radius, GLint slices, GLint stacks);
void glutWireSphere(GLdouble radius, GLint slices, GLint stacks);
在原点周围渲染一个球体,slices 是 Z 轴周围的细分数量,stacks 是 Z 轴上的细分数量。请注意,double
和 int
参数是 OpenGL 的一部分(请参阅 gl 前缀),而不是 GLUT 的一部分。
void glutSolidCube(GLdouble size);
void glutWireCube(GLdouble size);
Size 是边的长度。
void glutSolidCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
void glutWireCone(GLdouble base, GLdouble height, GLint slices, GLint stacks);
base 是底部的半径。
void glutSolidTorus
(GLdouble innerRadius, GLdouble outerRadius, GLint nsides, GLint rings);
void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
GLint nsides, GLint rings);void glutSolidDodecahedron(void);
void glutWireDodecahedron(void);
渲染一个实心或线框的 12 面正多面体。以原点为中心,半径为 3 的平方根。
void glutSolidTetrahedron(void);
void glutWiredTetrahedron(void);
渲染一个实心或线框的 4 面正多面体。以原点为中心,半径为 3 的平方根。
void glutSolidIcosahedron(void);
void glutWireIcosahedron(void);
渲染一个实心或线框的 20 面正多面体。以原点为中心,半径为 1.0。
void glutSolidOctahedron(void);
void glutWireOctahedron(void);
渲染一个实心或线框的 8 面正多面体。以原点为中心,半径为 1.0。
void glutSolidTeapot(GLdouble size);
void glutWireTeapot(GLdouble size);
您应该了解的关于在 GLUT 中创建菜单的信息
int glutCreateMenu(void (*func)(int value));
此函数定义了在菜单项被选中时必须调用的回调。此回调函数有一个参数,即 value。(程序员必须为他定义的每个菜单项定义一个值,有关更多信息,请参阅 blutAddMenuEntry()
)。此函数返回一个 int
,即菜单标识符。如果您想将此菜单作为子菜单附加,则需要此标识符。
void glutSetMenu(int menu);
您可以通过调用 glutSetMenu
并传递菜单标识符作为参数来设置当前菜单,使用 int glutGetMenu(void);
您可以查询当前菜单是哪个菜单。
void glutAddMenuEntry(char *name, int value);
这会将一个条目添加到具有 name 定义的标签的菜单中,第二个参数是要传递给回调函数的值。菜单正在添加到当前菜单中。添加的每个菜单项都添加到当前菜单的底部。
void glutAddSubMenu(char *name, int menu);
这会将标识为 menu identifier 的菜单添加为具有给定名称的子菜单到当前菜单中。如果菜单包含无限循环,程序将无法正常工作。
void glutAttachMenu(int button);
这会将当前菜单附加到特定的(鼠标)事件,您可以让菜单监听指定的鼠标按钮,button 可以是以下之一:GLUT_LEFT_BUTTON
、GLUT_MIDDLE_BUTTON
和 GLUT_RIGHT_BUTTON
。您还可以使用 void glutDetachMenu(int button);
来分离菜单。
最后但同样重要的一点是,它可以渲染一个茶壶。在重申了这些函数以及如何调用它们来渲染图形之后,请考虑这段代码。下面的源代码打开一个窗口,用黑色清除它,并绘制一个茶壶,它监听键盘按键并输出按下的键以及坐标。当用户按下“q
”时,程序终止。此程序仅使用 2 个 OpenGL 函数,第一个是 glClearColor()
,它将 Clearcolor
(背景)设置为黑色,第二个是 glClear()
,它实际清除窗口。在此示例中,未定义 idlefunction,并且我使用单缓冲(无双缓冲),因为不需要动画。
#include <iostream><iostream>
#include <glut.h><glut.h>
#include <cstdlib.h><cstdlib>
using namespace std;
void createMenu(void);
void menu(int value);
void disp(void);
static int win;
static int menid;
static int submenid;
static int primitive = 0;
int main(int argc, char **argv){
// normal initialisation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
win = glutCreateWindow("GLUT MENU");
// put all the menu functions in one nice procedure
createMenu();
// set the clearcolor and the callback
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(disp);
// enter the main loop
glutMainLoop();
}
void createMenu(void){
submenid = glutCreateMenu(menu);
// Add sub menu entry
glutAddMenuEntry("Teapot", 2);
glutAddMenuEntry("Cube", 3);
glutAddMenuEntry("Torus", 4);
// Create the menu, this menu becomes the current menu
menid = glutCreateMenu(menu);
// Create an entry
glutAddMenuEntry("Clear", 1);
glutAddSubMenu("Draw", submenid);
// Create an entry
glutAddMenuEntry("Quit", 0);
// Let the menu respond on the right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
void disp(void){
// Just clean the screen
glClear(GL_COLOR_BUFFER_BIT);
// draw what the user asked
if(primitive == 1){
glutPostRedisplay();
}else if(primitive == 2){
glutWireTeapot(0.5);
}else if(primitive == 3){
glutWireCube(0.5);
}else if(primitive == 4){
glutWireTorus(0.3,0.6,100,100);
}
glFlush();
}
void menu(int value){
if(value == 0){
glutDestroyWindow(win);
exit(0);
}else{
primitive=value;
}
// you would want to redraw now
glutPostRedisplay();
}
cl.exe tea.c 产生 tea.exe!

打造你自己的终结者
下一个示例实际上构建了一个机器人形象,当您右键单击表面图像并选择出现的选项之一时,它可以向您走来。运动和变换在很大程度上是三角学的。三角学分量的乘积形成角度和运动。请注意,机器人的形状是连接在一起的几何形状的总和:各部分的总和形成整体。由于代码是用 ANSI C 编写的,因此有很多宏预处理器指令。研究这段代码,因为它可以在此基础上扩展,并作为实际游戏编程的游标。
#define SPHERE
#define COLOR
#define LIGHT
#define TORSO
#define HIP
#define SHOULDER
#define UPPER_ARM
#define LOWER_ARM
#define ROCKET_POD
#define UPPER_LEG
#define LOWER_LEG
#define NO_NORM
#define ANIMATION
#define DRAW_MECH
#define DRAW_ENVIRO
#define MOVE_LIGHT
/* end of compilation conditions */
/* start various header files needed */
#include <stdlib.h><stdlib.h>
#include <math.h<math.h>
#define GLUT
#define GLUT_KEY
#define GLUT_SPEC
#include <glut.h><glut.h>
/* end of header files */
/* start of display list definitions */
#define SOLID_MECH_TORSO 1
#define SOLID_MECH_HIP 2
#define SOLID_MECH_SHOULDER 3
#define SOLID_MECH_UPPER_ARM 4
#define SOLID_MECH_FOREARM 5
#define SOLID_MECH_UPPER_LEG 6
#define SOLID_MECH_FOOT 7
#define SOLID_MECH_ROCKET 8
#define SOLID_MECH_VULCAN 9
#define SOLID_ENVIRO 10
/* end of display list definitions */
/* start of motion rate variables */
#define ANKLE_RATE 3
#define HEEL_RATE 3
#define ROTATE_RATE 10
#define TILT_RATE 10
#define ELBOW_RATE 2
#define SHOULDER_RATE 5
#define LAT_RATE 5
#define CANNON_RATE 40
#define UPPER_LEG_RATE 3
#define UPPER_LEG_RATE_GROIN 10
#define LIGHT_TURN_RATE 10
#define VIEW_TURN_RATE 10
/* end of motion rate variables */
/* start of motion variables */
/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
GLUquadricObj *qobj;
char leg = 0;
int shoulder1 = 0, shoulder2 = 0, shoulder3 = 0, shoulder4 = 0, lat1 = 20, lat2 = 20,
elbow1 = 0, elbow2 = 0, pivot = 0, tilt = 10, ankle1 = 0, ankle2 = 0, heel1 = 0,
heel2 = 0, hip11 = 0, hip12 = 10, hip21 = 0, hip22 = 10, fire = 0, solid_part = 0,
anim = 0, turn = 0, turn1 = 0, lightturn = 0, lightturn1 = 0;
float elevation = 0.0, distance = 0.0, frame = 3.0
/* foot1v[] = {} foot2v[] = {} */ ;
/* end of motion variables */
/* start of material definitions */
#ifdef LIGHT
GLfloat mat_specular[] =
{0.628281, 0.555802, 0.366065, 1.0};
GLfloat mat_ambient[] =
{0.24725, 0.1995, 0.0745, 1.0};
GLfloat mat_diffuse[] =
{0.75164, 0.60648, 0.22648, 1.0};
GLfloat mat_shininess[] =
{128.0 * 0.4};
GLfloat mat_specular2[] =
{0.508273, 0.508273, 0.508373};
GLfloat mat_ambient2[] =
{0.19225, 0.19225, 0.19225};
GLfloat mat_diffuse2[] =
{0.50754, 0.50754, 0.50754};
GLfloat mat_shininess2[] =
{128.0 * 0.6};
GLfloat mat_specular3[] =
{0.296648, 0.296648, 0.296648};
GLfloat mat_ambient3[] =
{0.25, 0.20725, 0.20725};
GLfloat mat_diffuse3[] =
{1, 0.829, 0.829};
GLfloat mat_shininess3[] =
{128.0 * 0.088};
GLfloat mat_specular4[] =
{0.633, 0.727811, 0.633};
GLfloat mat_ambient4[] =
{0.0215, 0.1745, 0.0215};
GLfloat mat_diffuse4[] =
{0.07568, 0.61424, 0.07568};
GLfloat mat_shininess4[] =
{128 * 0.6};
GLfloat mat_specular5[] =
{0.60, 0.60, 0.50};
GLfloat mat_ambient5[] =
{0.0, 0.0, 0.0};
GLfloat mat_diffuse5[] =
{0.5, 0.5, 0.0};
GLfloat mat_shininess5[] =
{128.0 * 0.25};
#endif
/* end of material definitions */
/* start of the body motion functions */
void
Heel1Add(void)
{
heel1 = (heel1 + HEEL_RATE) % 360;
}
void
Heel1Subtract(void)
{
heel1 = (heel1 - HEEL_RATE) % 360;
}
void
Heel2Add(void)
{
heel2 = (heel2 + HEEL_RATE) % 360;
}
void
Heel2Subtract(void)
{
heel2 = (heel2 - HEEL_RATE) % 360;
}
void
Ankle1Add(void)
{
ankle1 = (ankle1 + ANKLE_RATE) % 360;
}
void
Ankle1Subtract(void)
{
ankle1 = (ankle1 - ANKLE_RATE) % 360;
}
void
Ankle2Add(void)
{
ankle2 = (ankle2 + ANKLE_RATE) % 360;
}
void
Ankle2Subtract(void)
{
ankle2 = (ankle2 - ANKLE_RATE) % 360;
}
void
RotateAdd(void)
{
pivot = (pivot + ROTATE_RATE) % 360;
}
void
RotateSubtract(void)
{
pivot = (pivot - ROTATE_RATE) % 360;
}
void
MechTiltSubtract(void)
{
tilt = (tilt - TILT_RATE) % 360;
}
void
MechTiltAdd(void)
{
tilt = (tilt + TILT_RATE) % 360;
}
void
elbow1Add(void)
{
elbow1 = (elbow1 + ELBOW_RATE) % 360;
}
void
elbow1Subtract(void)
{
elbow1 = (elbow1 - ELBOW_RATE) % 360;
}
void
elbow2Add(void)
{
elbow2 = (elbow2 + ELBOW_RATE) % 360;
}
void
elbow2Subtract(void)
{
elbow2 = (elbow2 - ELBOW_RATE) % 360;
}
void
shoulder1Add(void)
{
shoulder1 = (shoulder1 + SHOULDER_RATE) % 360;
}
void
shoulder1Subtract(void)
{
shoulder1 = (shoulder1 - SHOULDER_RATE) % 360;
}
void
shoulder2Add(void)
{
shoulder2 = (shoulder2 + SHOULDER_RATE) % 360;
}
void
shoulder2Subtract(void)
{
shoulder2 = (shoulder2 - SHOULDER_RATE) % 360;
}
void
shoulder3Add(void)
{
shoulder3 = (shoulder3 + SHOULDER_RATE) % 360;
}
void
shoulder3Subtract(void)
{
shoulder3 = (shoulder3 - SHOULDER_RATE) % 360;
}
void
shoulder4Add(void)
{
shoulder4 = (shoulder4 + SHOULDER_RATE) % 360;
}
void
shoulder4Subtract(void)
{
shoulder4 = (shoulder4 - SHOULDER_RATE) % 360;
}
void
lat1Raise(void)
{
lat1 = (lat1 + LAT_RATE) % 360;
}
void
lat1Lower(void)
{
lat1 = (lat1 - LAT_RATE) % 360;
}
void
lat2Raise(void)
{
lat2 = (lat2 + LAT_RATE) % 360;
}
void
lat2Lower(void)
{
lat2 = (lat2 - LAT_RATE) % 360;
}
void
FireCannon(void)
{
fire = (fire + CANNON_RATE) % 360;
}
void
RaiseLeg1Forward(void)
{
hip11 = (hip11 + UPPER_LEG_RATE) % 360;
}
void
LowerLeg1Backwards(void)
{
hip11 = (hip11 - UPPER_LEG_RATE) % 360;
}
void
RaiseLeg1Outwards(void)
{
hip12 = (hip12 + UPPER_LEG_RATE_GROIN) % 360;
}
void
LowerLeg1Inwards(void)
{
hip12 = (hip12 - UPPER_LEG_RATE_GROIN) % 360;
}
void
RaiseLeg2Forward(void)
{
hip21 = (hip21 + UPPER_LEG_RATE) % 360;
}
void
LowerLeg2Backwards(void)
{
hip21 = (hip21 - UPPER_LEG_RATE) % 360;
}
void
RaiseLeg2Outwards(void)
{
hip22 = (hip22 + UPPER_LEG_RATE_GROIN) % 360;
}
void
LowerLeg2Inwards(void)
{
hip22 = (hip22 - UPPER_LEG_RATE_GROIN) % 360;
}
/* end of body motion functions */
/* start of light source position functions */
void
TurnRight(void)
{
turn = (turn - VIEW_TURN_RATE) % 360;
}
void
TurnLeft(void)
{
turn = (turn + VIEW_TURN_RATE) % 360;
}
void
TurnForwards(void)
{
turn1 = (turn1 - VIEW_TURN_RATE) % 360;
}
void
TurnBackwards(void)
{
turn1 = (turn1 + VIEW_TURN_RATE) % 360;
}
void
LightTurnRight(void)
{
lightturn = (lightturn + LIGHT_TURN_RATE) % 360;
}
void
LightTurnLeft(void)
{
lightturn = (lightturn - LIGHT_TURN_RATE) % 360;
}
void
LightForwards(void)
{
lightturn1 = (lightturn1 + LIGHT_TURN_RATE) % 360;
}
void
LightBackwards(void)
{
lightturn1 = (lightturn1 - LIGHT_TURN_RATE) % 360;
}
/* end of light source position functions */
/* start of geometric shape functions */
void
Box(float width, float height, float depth, char solid)
{
char i, j = 0;
float x = width / 2.0, y = height / 2.0, z = depth / 2.0;
for (i = 0; i < 4; i++) {
glRotatef(90.0, 0.0, 0.0, 1.0);
if (j) {
if (!solid)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_QUADS);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(-x, y, z);
glVertex3f(-x, -y, z);
glVertex3f(-x, -y, -z);
glVertex3f(-x, y, -z);
glEnd();
if (solid) {
glBegin(GL_TRIANGLES);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, z);
glVertex3f(-x, y, z);
glVertex3f(-x, -y, z);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -z);
glVertex3f(-x, -y, -z);
glVertex3f(-x, y, -z);
glEnd();
}
j = 0;
} else {
if (!solid)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_QUADS);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(-y, x, z);
glVertex3f(-y, -x, z);
glVertex3f(-y, -x, -z);
glVertex3f(-y, x, -z);
glEnd();
if (solid) {
glBegin(GL_TRIANGLES);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, z);
glVertex3f(-y, x, z);
glVertex3f(-y, -x, z);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -z);
glVertex3f(-y, -x, -z);
glVertex3f(-y, x, -z);
glEnd();
}
j = 1;
}
}
}
void
Octagon(float side, float height, char solid)
{
char j;
float x = sin(0.785398163) * side, y = side / 2.0, z = height / 2.0, c;
c = x + y;
for (j = 0; j < 8; j++) {
glTranslatef(-c, 0.0, 0.0);
if (!solid)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_QUADS);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(0.0, -y, z);
glVertex3f(0.0, y, z);
glVertex3f(0.0, y, -z);
glVertex3f(0.0, -y, -z);
glEnd();
glTranslatef(c, 0.0, 0.0);
if (solid) {
glBegin(GL_TRIANGLES);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, z);
glVertex3f(-c, -y, z);
glVertex3f(-c, y, z);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(0.0, 0.0, -z);
glVertex3f(-c, y, -z);
glVertex3f(-c, -y, -z);
glEnd();
}
glRotatef(45.0, 0.0, 0.0, 1.0);
}
}
/* end of geometric shape functions */
#ifdef NORM
void
Normalize(float v[3])
{
GLfloat d = sqrt(v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
if (d == 0.0) {
printf("zero length vector");
return;
}
v[1] /= d;
v[2] /= d;
v[3] /= d;
}
void
NormXprod(float v1[3], float v2[3], float v[3], float out[3])
{
GLint i, j;
GLfloat length;
out[0] = v1[1] * v2[2] - v1[2] * v2[1];
out[1] = v1[2] * v2[0] - v1[0] * v2[2];
out[2] = v1[0] * v2[1] - v1[1] * v2[0];
Normalize(out);
}
#endif
void
SetMaterial(GLfloat spec[], GLfloat amb[], GLfloat diff[], GLfloat shin[])
{
glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
glMaterialfv(GL_FRONT, GL_SHININESS, shin);
glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
}
void
MechTorso(char solid)
{
glNewList(SOLID_MECH_TORSO, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(1.0, 1.0, 3.0, solid);
glTranslatef(0.75, 0.0, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
Box(0.5, 0.6, 2.0, solid);
glTranslatef(-1.5, 0.0, 0.0);
Box(0.5, 0.6, 2.0, solid);
glTranslatef(0.75, 0.0, 0.0);
glEndList();
}
void
MechHip(char solid)
{
int i;
glNewList(SOLID_MECH_HIP, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Octagon(0.7, 0.5, solid);
#ifdef SPHERE
for (i = 0; i < 2; i++) {
if (i)
glScalef(-1.0, 1.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
gluSphere(qobj, 0.2, 16, 16);
glTranslatef(-1.0, 0.0, 0.0);
}
glScalef(-1.0, 1.0, 1.0);
#endif
glEndList();
}
void
Shoulder(char solid)
{
glNewList(SOLID_MECH_SHOULDER, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(1.0, 0.5, 0.5, solid);
glTranslatef(0.9, 0.0, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
#ifdef SPHERE
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
gluSphere(qobj, 0.6, 16, 16);
#endif
glTranslatef(-0.9, 0.0, 0.0);
glEndList();
}
void
UpperArm(char solid)
{
int i;
glNewList(SOLID_MECH_UPPER_ARM, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(1.0, 2.0, 1.0, solid);
glTranslatef(0.0, -0.95, 0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder(qobj, 0.4, 0.4, 1.5, 16, 10);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(-0.4, -1.85, 0.0);
glRotatef(90.0, 0.0, 1.0, 0.0);
for (i = 0; i < 2; i++) {
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
if (i)
gluCylinder(qobj, 0.5, 0.5, 0.8, 16, 10);
else
gluCylinder(qobj, 0.2, 0.2, 0.8, 16, 10);
}
for (i = 0; i < 2; i++) {
if (i)
glScalef(-1.0, 1.0, 1.0);
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
if (i)
glTranslatef(0.0, 0.0, 0.8);
gluDisk(qobj, 0.2, 0.5, 16, 10);
if (i)
glTranslatef(0.0, 0.0, -0.8);
}
glScalef(-1.0, 1.0, 1.0);
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.4, 2.9, 0.0);
glEndList();
}
void
VulcanGun(char solid)
{
int i;
glNewList(SOLID_MECH_VULCAN, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
if (!solid) {
gluQuadricDrawStyle(qobj, GLU_LINE);
}
gluCylinder(qobj, 0.5, 0.5, 0.5, 16, 10);
glTranslatef(0.0, 0.0, 0.5);
gluDisk(qobj, 0.0, 0.5, 16, 10);
for (i = 0; i < 5; i++) {
glRotatef(72.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.3, 0.0);
if (!solid) {
gluQuadricDrawStyle(qobj, GLU_LINE);
}
gluCylinder(qobj, 0.15, 0.15, 2.0, 16, 10);
gluCylinder(qobj, 0.06, 0.06, 2.0, 16, 10);
glTranslatef(0.0, 0.0, 2.0);
gluDisk(qobj, 0.1, 0.15, 16, 10);
gluCylinder(qobj, 0.1, 0.1, 0.1, 16, 5);
glTranslatef(0.0, 0.0, 0.1);
gluDisk(qobj, 0.06, 0.1, 16, 5);
glTranslatef(0.0, -0.3, -2.1);
}
glEndList();
}
void
ForeArm(char solid)
{
char i;
glNewList(SOLID_MECH_FOREARM, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
for (i = 0; i < 5; i++) {
glTranslatef(0.0, -0.1, -0.15);
Box(0.6, 0.8, 0.2, solid);
glTranslatef(0.0, 0.1, -0.15);
Box(0.4, 0.6, 0.1, solid);
}
glTranslatef(0.0, 0.0, 2.45);
Box(1.0, 1.0, 2.0, solid);
glTranslatef(0.0, 0.0, -1.0);
glEndList();
}
void
UpperLeg(char solid)
{
int i;
glNewList(SOLID_MECH_UPPER_LEG, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
if (!solid) {
gluQuadricDrawStyle(qobj, GLU_LINE);
}
glTranslatef(0.0, -1.0, 0.0);
Box(0.4, 1.0, 0.7, solid);
glTranslatef(0.0, -0.65, 0.0);
for (i = 0; i < 5; i++) {
Box(1.2, 0.3, 1.2, solid);
glTranslatef(0.0, -0.2, 0.0);
Box(1.0, 0.1, 1.0, solid);
glTranslatef(0.0, -0.2, 0.0);
}
glTranslatef(0.0, -0.15, -0.4);
Box(2.0, 0.5, 2.0, solid);
glTranslatef(0.0, -0.3, -0.2);
glRotatef(90.0, 1.0, 0.0, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
gluCylinder(qobj, 0.6, 0.6, 3.0, 16, 10);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, -1.5, 1.0);
Box(1.5, 3.0, 0.5, solid);
glTranslatef(0.0, -1.75, -0.8);
Box(2.0, 0.5, 2.0, solid);
glTranslatef(0.0, -0.9, -0.85);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
gluCylinder(qobj, 0.8, 0.8, 1.8, 16, 10);
for (i = 0; i < 2; i++) {
if (i)
glScalef(-1.0, 1.0, 1.0);
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
if (i)
glTranslatef(0.0, 0.0, 1.8);
gluDisk(qobj, 0.0, 0.8, 16, 10);
if (i)
glTranslatef(0.0, 0.0, -1.8);
}
glScalef(-1.0, 1.0, 1.0);
glEndList();
}
void
Foot(char solid)
{
glNewList(SOLID_MECH_FOOT, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
glRotatef(90.0, 1.0, 0.0, 0.0);
Octagon(1.5, 0.6, solid);
glRotatef(-90.0, 1.0, 0.0, 0.0);
glEndList();
}
void
LowerLeg(char solid)
{
float k, l;
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
for (k = 0.0; k < 2.0; k++) {
for (l = 0.0; l < 2.0; l++) {
glPushMatrix();
glTranslatef(k, 0.0, l);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(1.0, 0.5, 1.0, solid);
glTranslatef(0.0, -0.45, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
#ifdef SPHERE
if (!solid)
glutWireSphere(0.2, 16, 10);
else
glutSolidSphere(0.2, 16, 10);
#endif
if (leg)
glRotatef((GLfloat) heel1, 1.0, 0.0, 0.0);
else
glRotatef((GLfloat) heel2, 1.0, 0.0, 0.0);
/* glTranslatef(0.0, -0.2, 0.0); */
glTranslatef(0.0, -1.7, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(0.25, 3.0, 0.25, solid);
glTranslatef(0.0, -1.7, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
#ifdef SPHERE
if (!solid)
glutWireSphere(0.2, 16, 10);
else
glutSolidSphere(0.2, 16, 10);
#endif
if (leg)
glRotatef((GLfloat) - heel1, 1.0, 0.0, 0.0);
else
glRotatef((GLfloat) - heel2, 1.0, 0.0, 0.0);
glTranslatef(0.0, -0.45, 0.0);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(1.0, 0.5, 1.0, solid);
if (!k && !l) {
int j;
glTranslatef(-0.4, -0.8, 0.5);
if (leg)
glRotatef((GLfloat) ankle1, 1.0, 0.0, 0.0);
else
glRotatef((GLfloat) ankle2, 1.0, 0.0, 0.0);
glRotatef(90.0, 0.0, 1.0, 0.0);
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
gluCylinder(qobj, 0.8, 0.8, 1.8, 16, 10);
for (j = 0; j < 2; j++) {
if (!solid)
gluQuadricDrawStyle(qobj, GLU_LINE);
if (j) {
glScalef(-1.0, 1.0, 1.0);
glTranslatef(0.0, 0.0, 1.8);
}
gluDisk(qobj, 0.0, 0.8, 16, 10);
if (j)
glTranslatef(0.0, 0.0, -1.8);
}
glScalef(-1.0, 1.0, 1.0);
glRotatef(-90.0, 0.0, 1.0, 0.0);
glTranslatef(0.95, -0.8, 0.0);
glCallList(SOLID_MECH_FOOT);
}
glPopMatrix();
}
}
}
void
RocketPod(char solid)
{
int i, j, k = 0;
glNewList(SOLID_MECH_ROCKET, GL_COMPILE);
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glColor3f(0.5, 0.5, 0.5);
glScalef(0.4, 0.4, 0.4);
glRotatef(45.0, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
Box(2.0, 0.5, 3.0, solid);
glTranslatef(1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, 0.0, 1.0);
glTranslatef(0.5, 0.0, 0.0);
Box(1.2, 0.5, 3.0, solid);
glTranslatef(2.1, 0.0, 0.0);
glRotatef(-90.0, 0.0, 0.0, 1.0);
#ifdef LIGHT
SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
glColor3f(1.0, 1.0, 0.0);
Box(2.0, 3.0, 4.0, solid);
glTranslatef(-0.5, -1.0, 1.3);
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++) {
if (!solid) {
gluQuadricDrawStyle(qobj, GLU_LINE);
}
glTranslatef(i, j, 0.6);
#ifdef LIGHT
SetMaterial(mat_specular3, mat_ambient3, mat_diffuse3, mat_shininess3);
#endif
glColor3f(1.0, 1.0, 1.0);
gluCylinder(qobj, 0.4, 0.4, 0.3, 16, 10);
glTranslatef(0.0, 0.0, 0.3);
#ifdef LIGHT
SetMaterial(mat_specular4, mat_ambient4, mat_diffuse4, mat_shininess4);
#endif
glColor3f(0.0, 1.0, 0.0);
gluCylinder(qobj, 0.4, 0.0, 0.5, 16, 10);
k++;
glTranslatef(-i, -j, -0.9);
}
}
glEndList();
}
void
Enviro(char solid)
{
int i, j;
glNewList(SOLID_ENVIRO, GL_COMPILE);
SetMaterial(mat_specular4, mat_ambient4, mat_diffuse4, mat_shininess4);
glColor3f(0.0, 1.0, 0.0);
Box(20.0, 0.5, 30.0, solid);
SetMaterial(mat_specular4, mat_ambient3, mat_diffuse2, mat_shininess);
glColor3f(0.6, 0.6, 0.6);
glTranslatef(0.0, 0.0, -10.0);
for (j = 0; j < 6; j++) {
for (i = 0; i < 2; i++) {
if (i)
glScalef(-1.0, 1.0, 1.0);
glTranslatef(10.0, 4.0, 0.0);
Box(4.0, 8.0, 2.0, solid);
glTranslatef(0.0, -1.0, -3.0);
Box(4.0, 6.0, 2.0, solid);
glTranslatef(-10.0, -3.0, 3.0);
}
glScalef(-1.0, 1.0, 1.0);
glTranslatef(0.0, 0.0, 5.0);
}
glEndList();
}
void
Toggle(void)
{
if (solid_part)
solid_part = 0;
else
solid_part = 1;
}
void
disable(void)
{
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDisable(GL_NORMALIZE);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
void
lighting(void)
{
GLfloat position[] =
{0.0, 0.0, 2.0, 1.0};
#ifdef MOVE_LIGHT
glRotatef((GLfloat) lightturn1, 1.0, 0.0, 0.0);
glRotatef((GLfloat) lightturn, 0.0, 1.0, 0.0);
glRotatef(0.0, 1.0, 0.0, 0.0);
#endif
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glDepthFunc(GL_LESS);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 80.0);
glTranslatef(0.0, 0.0, 2.0);
glDisable(GL_LIGHTING);
Box(0.1, 0.1, 0.1, 0);
glEnable(GL_LIGHTING);
}
void
DrawMech(void)
{
int i, j;
glScalef(0.5, 0.5, 0.5);
glPushMatrix();
glTranslatef(0.0, -0.75, 0.0);
glRotatef((GLfloat) tilt, 1.0, 0.0, 0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
#ifdef HIP
glCallList(SOLID_MECH_HIP);
#endif
glRotatef(-90.0, 1.0, 0.0, 0.0);
glTranslatef(0.0, 0.75, 0.0);
glPushMatrix();
glRotatef((GLfloat) pivot, 0.0, 1.0, 0.0);
glPushMatrix();
#ifdef TORSO
glCallList(SOLID_MECH_TORSO);
#endif
glPopMatrix();
glPushMatrix();
glTranslatef(0.5, 0.5, 0.0);
#ifdef ROCKET_POD
glCallList(SOLID_MECH_ROCKET);
#endif
glPopMatrix();
for (i = 0; i < 2; i++) {
glPushMatrix();
if (i)
glScalef(-1.0, 1.0, 1.0);
glTranslatef(1.5, 0.0, 0.0);
#ifdef SHOULDER
glCallList(SOLID_MECH_SHOULDER);
#endif
glTranslatef(0.9, 0.0, 0.0);
if (i) {
glRotatef((GLfloat) lat1, 0.0, 0.0, 1.0);
glRotatef((GLfloat) shoulder1, 1.0, 0.0, 0.0);
glRotatef((GLfloat) shoulder3, 0.0, 1.0, 0.0);
} else {
glRotatef((GLfloat) lat2, 0.0, 0.0, 1.0);
glRotatef((GLfloat) shoulder2, 1.0, 0.0, 0.0);
glRotatef((GLfloat) shoulder4, 0.0, 1.0, 0.0);
}
glTranslatef(0.0, -1.4, 0.0);
#ifdef UPPER_ARM
glCallList(SOLID_MECH_UPPER_ARM);
#endif
glTranslatef(0.0, -2.9, 0.0);
if (i)
glRotatef((GLfloat) elbow1, 1.0, 0.0, 0.0);
else
glRotatef((GLfloat) elbow2, 1.0, 0.0, 0.0);
glTranslatef(0.0, -0.9, -0.2);
#ifdef LOWER_ARM
glCallList(SOLID_MECH_FOREARM);
glPushMatrix();
glTranslatef(0.0, 0.0, 2.0);
glRotatef((GLfloat) fire, 0.0, 0.0, 1.0);
glCallList(SOLID_MECH_VULCAN);
glPopMatrix();
#endif
glPopMatrix();
}
glPopMatrix();
glPopMatrix();
for (j = 0; j < 2; j++) {
glPushMatrix();
if (j) {
glScalef(-0.5, 0.5, 0.5);
leg = 1;
} else {
glScalef(0.5, 0.5, 0.5);
leg = 0;
}
glTranslatef(2.0, -1.5, 0.0);
if (j) {
glRotatef((GLfloat) hip11, 1.0, 0.0, 0.0);
glRotatef((GLfloat) hip12, 0.0, 0.0, 1.0);
} else {
glRotatef((GLfloat) hip21, 1.0, 0.0, 0.0);
glRotatef((GLfloat) hip22, 0.0, 0.0, 1.0);
}
glTranslatef(0.0, 0.3, 0.0);
#ifdef UPPER_LEG
glPushMatrix();
glCallList(SOLID_MECH_UPPER_LEG);
glPopMatrix();
#endif
glTranslatef(0.0, -8.3, -0.4);
if (j)
glRotatef((GLfloat) - hip12, 0.0, 0.0, 1.0);
else
glRotatef((GLfloat) - hip22, 0.0, 0.0, 1.0);
glTranslatef(-0.5, -0.85, -0.5);
#ifdef LOWER_LEG
LowerLeg(1);
#endif
glPopMatrix();
}
}
void
display(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glPushMatrix();
glRotatef((GLfloat) turn, 0.0, 1.0, 0.0);
glRotatef((GLfloat) turn1, 1.0, 0.0, 0.0);
#ifdef LIGHT
if (solid_part) {
glPushMatrix();
lighting();
glPopMatrix();
} else
disable();
#endif
#ifdef DRAW_MECH
glPushMatrix();
glTranslatef(0.0, elevation, 0.0);
DrawMech();
glPopMatrix();
#endif
#ifdef DRAW_ENVIRO
glPushMatrix();
if (distance >= 20.136)
distance = 0.0;
glTranslatef(0.0, -5.0, -distance);
glCallList(SOLID_ENVIRO);
glTranslatef(0.0, 0.0, 10.0);
glCallList(SOLID_ENVIRO);
glPopMatrix();
#endif
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void
myinit(void)
{
char i = 1;
qobj = gluNewQuadric();
#ifdef LIGHT
SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
glEnable(GL_DEPTH_TEST);
MechTorso(i);
MechHip(i);
Shoulder(i);
RocketPod(i);
UpperArm(i);
ForeArm(i);
UpperLeg(i);
Foot(i);
VulcanGun(i);
Enviro(i);
}
void
myReshape(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 1.2, -5.5); /* viewing transform */
}
#ifdef ANIMATION
void
animation_walk(void)
{
float angle;
static int step;
if (step == 0 || step == 2) {
/* for(frame=3.0; frame<=21.0; frame=frame+3.0){ */
if (frame >= 0.0 && frame <= 21.0) {
if (frame == 0.0)
frame = 3.0;
angle = (180 / M_PI) *
(acos(((cos((M_PI / 180) * frame) * 2.043) + 1.1625) / 3.2059));
if (frame > 0) {
elevation = -(3.2055 - (cos((M_PI / 180) * angle) * 3.2055));
} else
elevation = 0.0;
if (step == 0) {
hip11 = -(frame * 1.7);
if (1.7 * frame > 15)
heel1 = frame * 1.7;
heel2 = 0;
ankle1 = frame * 1.7;
if (frame > 0)
hip21 = angle;
else
hip21 = 0;
ankle2 = -hip21;
shoulder1 = frame * 1.5;
shoulder2 = -frame * 1.5;
elbow1 = frame;
elbow2 = -frame;
} else {
hip21 = -(frame * 1.7);
if (1.7 * frame > 15)
heel2 = frame * 1.7;
heel1 = 0;
ankle2 = frame * 1.7;
if (frame > 0)
hip11 = angle;
else
hip11 = 0;
ankle1 = -hip11;
shoulder1 = -frame * 1.5;
shoulder2 = frame * 1.5;
elbow1 = -frame;
elbow2 = frame;
}
if (frame == 21)
step++;
if (frame < 21)
frame = frame + 3.0;
}
}
if (step == 1 || step == 3) {
/* for(x=21.0; x>=0.0; x=x-3.0){ */
if (frame <= 21.0 && frame >= 0.0) {
angle = (180 / M_PI) *
(acos(((cos((M_PI / 180) * frame) * 2.043) + 1.1625) / 3.2029));
if (frame > 0)
elevation = -(3.2055 - (cos((M_PI / 180) * angle) * 3.2055));
else
elevation = 0.0;
if (step == 1) {
elbow2 = hip11 = -frame;
elbow1 = heel1 = frame;
heel2 = 15;
ankle1 = frame;
if (frame > 0)
hip21 = angle;
else
hip21 = 0;
ankle2 = -hip21;
shoulder1 = 1.5 * frame;
shoulder2 = -frame * 1.5;
} else {
elbow1 = hip21 = -frame;
elbow2 = heel2 = frame;
heel1 = 15;
ankle2 = frame;
if (frame > 0)
hip11 = angle;
else
hip11 = 0;
ankle1 = -hip11;
shoulder1 = -frame * 1.5;
shoulder2 = frame * 1.5;
}
if (frame == 0.0)
step++;
if (frame > 0)
frame = frame - 3.0;
}
}
if (step == 4)
step = 0;
distance += 0.1678;
glutPostRedisplay();
}
void
animation(void)
{
animation_walk();
}
#endif
#ifdef GLUT
#ifdef GLUT_KEY
/* ARGSUSED1 */
void
keyboard(unsigned char key, int x, int y)
{
int i = 0;
switch (key) {
/* start arm control functions */
case 'q':{
shoulder2Subtract();
i++;
}
break;
case 'a':{
shoulder2Add();
i++;
}
break;
case 'w':{
shoulder1Subtract();
i++;
}
break;
case 's':{
shoulder1Add();
i++;
}
break;
case '2':{
shoulder3Add();
i++;
}
break;
case '1':{
shoulder4Add();
i++;
}
break;
case '4':{
shoulder3Subtract();
i++;
}
break;
case '3':{
shoulder4Subtract();
i++;
}
break;
case 'z':{
lat2Raise();
i++;
}
break;
case 'Z':{
lat2Lower();
i++;
}
break;
case 'x':{
lat1Raise();
i++;
}
break;
case 'X':{
lat1Lower();
i++;
}
break;
case 'A':{
elbow2Add();
i++;
}
break;
case 'Q':{
elbow2Subtract();
i++;
}
break;
case 'S':{
elbow1Add();
i++;
}
break;
case 'W':{
elbow1Subtract();
i++;
}
break;
/* end of arm control functions */
/* start of torso control functions */
case 'd':{
RotateAdd();
i++;
}
break;
case 'g':{
RotateSubtract();
i++;
}
break;
case 'r':{
MechTiltAdd();
i++;
}
break;
case 'f':{
MechTiltSubtract();
i++;
}
break;
/* end of torso control functions */
/* start of leg control functions */
case 'h':{
RaiseLeg2Forward();
i++;
}
break;
case 'y':{
LowerLeg2Backwards();
i++;
}
break;
case 'Y':{
RaiseLeg2Outwards();
i++;
}
break;
case 'H':{
LowerLeg2Inwards();
i++;
}
break;
case 'j':{
RaiseLeg1Forward();
i++;
}
break;
case 'u':{
LowerLeg1Backwards();
i++;
}
break;
case 'U':{
RaiseLeg1Outwards();
i++;
}
break;
case 'J':{
LowerLeg1Inwards();
i++;
}
break;
case 'N':{
Heel2Add();
i++;
}
break;
case 'n':{
Heel2Subtract();
i++;
}
break;
case 'M':{
Heel1Add();
i++;
}
break;
case 'm':{
Heel1Subtract();
i++;
}
break;
case 'k':{
Ankle2Add();
i++;
}
break;
case 'K':{
Ankle2Subtract();
i++;
}
break;
case 'l':{
Ankle1Add();
i++;
}
break;
case 'L':{
Ankle1Subtract();
i++;
}
break;
/* end of leg control functions */
/* start of light source position functions */
case 'p':{
LightTurnRight();
i++;
}
break;
case 'i':{
LightTurnLeft();
i++;
}
break;
case 'o':{
LightForwards();
i++;
}
break;
case '9':{
LightBackwards();
i++;
}
break;
/* end of light source position functions */
}
if (i)
glutPostRedisplay();
}
#endif
#ifdef GLUT_SPEC
/* ARGSUSED1 */
void
special(int key, int x, int y)
{
int i = 0;
switch (key) {
/* start of view position functions */
case GLUT_KEY_RIGHT:{
TurnRight();
i++;
}
break;
case GLUT_KEY_LEFT:{
TurnLeft();
i++;
}
break;
case GLUT_KEY_DOWN:{
TurnForwards();
i++;
}
break;
case GLUT_KEY_UP:{
TurnBackwards();
i++;
}
break;
/* end of view positions functions */
/* start of miscellaneous functions */
case GLUT_KEY_PAGE_UP:{
FireCannon();
i++;
}
break;
/* end of miscellaneous functions */
}
if (i)
glutPostRedisplay();
}
#endif
#endif
void
menu_select(int mode)
{
switch (mode) {
#ifdef ANIMATION
case 1:
glutIdleFunc(animation);
break;
#endif
case 2:
glutIdleFunc(NULL);
break;
case 3:
Toggle();
glutPostRedisplay();
break;
case 4:
exit(EXIT_SUCCESS);
}
}
/* ARGSUSED */
void
null_select(int mode)
{
}
void
glutMenu(void)
{
int glut_menu[13];
glut_menu[5] = glutCreateMenu(null_select);
glutAddMenuEntry("forward : q,w", 0);
glutAddMenuEntry("backwards : a,s", 0);
glutAddMenuEntry("outwards : z,x", 0);
glutAddMenuEntry("inwards : Z,X", 0);
glut_menu[6] = glutCreateMenu(null_select);
glutAddMenuEntry("upwards : Q,W", 0);
glutAddMenuEntry("downwards : A,S", 0);
glutAddMenuEntry("outwards : 1,2", 0);
glutAddMenuEntry("inwards : 3,4", 0);
glut_menu[1] = glutCreateMenu(null_select);
glutAddMenuEntry(" : Page_up", 0);
glut_menu[8] = glutCreateMenu(null_select);
glutAddMenuEntry("forward : y,u", 0);
glutAddMenuEntry("backwards : h.j", 0);
glutAddMenuEntry("outwards : Y,U", 0);
glutAddMenuEntry("inwards : H,J", 0);
glut_menu[9] = glutCreateMenu(null_select);
glutAddMenuEntry("forward : n,m", 0);
glutAddMenuEntry("backwards : N,M", 0);
glut_menu[9] = glutCreateMenu(null_select);
glutAddMenuEntry("forward : n,m", 0);
glutAddMenuEntry("backwards : N,M", 0);
glut_menu[10] = glutCreateMenu(null_select);
glutAddMenuEntry("toes up : K,L", 0);
glutAddMenuEntry("toes down : k,l", 0);
glut_menu[11] = glutCreateMenu(null_select);
glutAddMenuEntry("right : right arrow", 0);
glutAddMenuEntry("left : left arrow", 0);
glutAddMenuEntry("down : up arrow", 0);
glutAddMenuEntry("up : down arrow", 0);
glut_menu[12] = glutCreateMenu(null_select);
glutAddMenuEntry("right : p", 0);
glutAddMenuEntry("left : i", 0);
glutAddMenuEntry("up : 9", 0);
glutAddMenuEntry("down : o", 0);
glut_menu[4] = glutCreateMenu(NULL);
glutAddSubMenu("at the shoulders? ", glut_menu[5]);
glutAddSubMenu("at the elbows?", glut_menu[6]);
glut_menu[7] = glutCreateMenu(NULL);
glutAddSubMenu("at the hip? ", glut_menu[8]);
glutAddSubMenu("at the knees?", glut_menu[9]);
glutAddSubMenu("at the ankles? ", glut_menu[10]);
glut_menu[2] = glutCreateMenu(null_select);
glutAddMenuEntry("turn left : d", 0);
glutAddMenuEntry("turn right : g", 0);
glut_menu[3] = glutCreateMenu(null_select);
glutAddMenuEntry("tilt backwards : f", 0);
glutAddMenuEntry("tilt forwards : r", 0);
glut_menu[0] = glutCreateMenu(NULL);
glutAddSubMenu("move the arms.. ", glut_menu[4]);
glutAddSubMenu("fire the vulcan guns?", glut_menu[1]);
glutAddSubMenu("move the legs.. ", glut_menu[7]);
glutAddSubMenu("move the torso?", glut_menu[2]);
glutAddSubMenu("move the hip?", glut_menu[3]);
glutAddSubMenu("rotate the scene..", glut_menu[11]);
#ifdef MOVE_LIGHT
glutAddSubMenu("rotate the light source..", glut_menu[12]);
#endif
glutCreateMenu(menu_select);
#ifdef ANIMATION
glutAddMenuEntry("Start Walk", 1);
glutAddMenuEntry("Stop Walk", 2);
#endif
glutAddMenuEntry("Toggle Wireframe", 3);
glutAddSubMenu("How do I ..", glut_menu[0]);
glutAddMenuEntry("Quit", 4);
glutAttachMenu(GLUT_LEFT_BUTTON);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
int
main(int argc, char **argv)
{
#ifdef GLUT
/* start of glut windowing and control functions */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("glutmech: Vulcan Gunner");
myinit();
glutDisplayFunc(display);
glutReshapeFunc(myReshape);
#ifdef GLUT_KEY
glutKeyboardFunc(keyboard);
#endif
#ifdef GLUT_SPEC
glutSpecialFunc(special);
#endif
glutMenu();
glutMainLoop();
/* end of glut windowing and control functions */
#endif
return 0;
}
将此代码编译为空 C++ 控制台应用程序,其中您添加一个新项(即代码文件)并将此代码粘贴进去。我在 VC++ 命令行上编译它没有任何问题。请记住,您处于 bin 目录中,必须键入 vcvars32.bat 来设置环境。键入 'type con > robot.c
',您的光标将向下移动一行并移到最左侧,没有提示符。在此控制台空间中粘贴代码,并使用 cl.exe 编译器进行编译。

参考文献
- www.openGL.org 和 OpenGL 规范 PDF