一、目的

掌握OpenGL中显示列表对象的使用方法。

二、示例代码

Github地址

#include "stdafx.h"
#include <GL/glut.h>
#include <cmath>
#include <stdlib.h>
#include <GL/glut.h>
#include <math.h> //色彩全局常量
GLfloat WHITE[] = { , , }; //白色
GLfloat RED[] = { , , }; //红色
GLfloat GREEN[] = { , , }; //绿色
GLfloat MAGENTA[] = { , , }; //洋红 //摄像机类:水平移动半径为10,按上下键则垂直移动
class Camera {
public:
double theta; //确定x和z的位置
double y; //y位置
double dTheta; //角度增量
double dy; //上下y增量
public:
//类构造函数—默认初始化用法
Camera() : theta(), y(), dTheta(0.04), dy(0.2) {}
//类方法
double getX() { return * cos(theta); }
double getY() { return y; }
double getZ() { return * sin(theta); }
void moveRight() { theta += dTheta; }
void moveLeft() { theta -= dTheta; }
void moveUp() { y += dy; }
void moveDown() { if (y > dy) y -= dy; }
}; //球类定义
//半径、颜色、最大高度
//x和z固定
//用lame bouncing algorithm
//每帧上下移动0.05单位
class Ball {
//类的属性
double radius;
GLfloat* color;
double maximumHeight;
double x;
double y;
double z;
int direction; //方向
public:
//构造函数
Ball(double r, GLfloat* c, double h, double x, double z) :
radius(r), color(c), maximumHeight(h), direction(-),
y(h), x(x), z(z) {
} //更新和绘制方法
void update() {
//正反运动
y += direction * 0.05;
if (y > maximumHeight) {
y = maximumHeight;
direction = -;
}
else if (y < radius) {
y = radius;
direction = ;
}
glPushMatrix();
//单独设置每个球的材质参数
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
glTranslated(x, y, z);
//创建球
glutSolidSphere(radius, , );
glPopMatrix();
}
}; //棋盘格:沿x和z平面分布
//点光源位置设置为(4, 3, 7).
class Checkerboard {
int displayListId;
int width;
int depth;
public:
//构造函数
Checkerboard(int width, int depth) : width(width), depth(depth) {} //中心X
double centerx() { return width / ; } //中心Y
double centerz() { return depth / ; } //创建方法
void create() {
displayListId = glGenLists(); //每个显示列表对应1个编号——关联起来
//新建操作表
glNewList(displayListId, GL_COMPILE); //把下述命令装入显示列表但不显示
//光源位置参数
GLfloat lightPosition[] = { , , , };
//设置光源位置
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
//开始绘制四边形
glBegin(GL_QUADS);
//法向量方向
glNormal3d(, , );
for (int x = ; x < width - ; x++) {
for (int z = ; z < depth - ; z++) {
//设置每个格子的材质属性
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE,
(x + z) % == ? RED : WHITE);
//四边形的4个点坐标
glVertex3d(x, , z);
glVertex3d(x + , , z);
glVertex3d(x + , , z + );
glVertex3d(x, , z + );
}
}
glEnd();
glEndList();
}
//按列表编号绘制棋盘格
void draw() {
glCallList(displayListId);
}
}; //全局变量:棋盘格、相机和3个球的数组
Checkerboard checkerboard(, );
Camera camera;
//创建3个小球的数组
Ball balls[] = {
Ball(, GREEN, , , ),
Ball(1.5, MAGENTA, , , ),
Ball(0.4, WHITE, , , )
}; //自定义初始化方法
void init() {
//允许深度测试
glEnable(GL_DEPTH_TEST);
//设置散射和镜像反射为白光
glLightfv(GL_LIGHT0, GL_DIFFUSE, WHITE);
glLightfv(GL_LIGHT0, GL_SPECULAR, WHITE);
//设置前表面的高光镜像反射为白光
glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE);
//设置前表面散射光反光系数
glMaterialf(GL_FRONT, GL_SHININESS, );
//允许灯光
glEnable(GL_LIGHTING);
//打开0#灯
glEnable(GL_LIGHT0);
//创建棋盘格
checkerboard.create();
} //自定义绘制函数
//通过类绘制各对象,display函数代码得以简化
void display() {
//清除前一帧绘图结果
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//装入单位阵
glLoadIdentity();
//设置视角——摄像机参数
gluLookAt(camera.getX(), camera.getY(), camera.getZ(), //摄像机位置
checkerboard.centerx(), 0.0, checkerboard.centerz(), //焦点坐标
0.0, 1.0, 0.0); //摄像机机顶方向矢量
//绘制棋盘
checkerboard.draw();
//绘制小球
for (int i = ; i < sizeof balls / sizeof(Ball); i++) {
//更新位置并绘图
balls[i].update();
}
//glFlush();
glutSwapBuffers();
} //窗口调整大小时调用的函数
void reshape(GLint w, GLint h) {
glViewport(, , w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0, GLfloat(w) / GLfloat(h), 1.0, 150.0);
glMatrixMode(GL_MODELVIEW);
} //自定义计时器函数
void timer(int v) {
//当计时器唤醒时所调用的函数
glutPostRedisplay();
//设置下一次计时器的参数
glutTimerFunc( / , timer/*函数名*/, v);
} //键盘处理函数
void onKey(int key, int, int) {
//按键:上下左右
switch (key) {
case GLUT_KEY_LEFT: camera.moveLeft(); break;
case GLUT_KEY_RIGHT: camera.moveRight(); break;
case GLUT_KEY_UP: camera.moveUp(); break;
case GLUT_KEY_DOWN: camera.moveDown(); break;
}
glutPostRedisplay();
} int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowPosition(, );
glutInitWindowSize(, );
glutCreateWindow("跳跃的球");
glutDisplayFunc(display); //设置显示函数
glutReshapeFunc(reshape); //设置窗口调整大小的函数
glutSpecialFunc(onKey); //设置按键处理函数
glutTimerFunc(, timer, ); //设置计时器函数--每100ms被调用1次
init();//自定义初始化函数
glutMainLoop();//进入opengl主循环 return ;
}

用OpenGL实现跳跃的立体小球的更多相关文章

  1. 用OpenGL实现动态的立体时钟

    (在学期末做的图形学课程设计,特将学习心得整理如下) 一.设计思路 1,设计一个平面的时钟: 按照 钟面——>中心点——>刻度——>时针——>分针——>秒针 的顺序绘制. ...

  2. Libgls 1.0.1 发布,OpenGL 立体渲染

    Libgls 1.0.1 只是修复了一些小问题,更新了 FindGLS.cmake 脚本. Libgls 允许 OpenGL 立体渲染,不需要硬件支持四缓冲立体.支持许多立体显示模式,从立体眼镜的3D ...

  3. OpenGL绘制自由落体小球

    OpenGL绘制自由落体小球 一.    程序运行的软硬件环境 本次设计在window10系统下进行,运用C++进行编写,在CodeBlocks环境下使用OpenGL进行设计. 所需环境配置分为2部分 ...

  4. OpenGL蓝宝书第七章:立体天空和纹理折射、双纹理(下)

    对照了蓝宝书,才知道红宝书的长处. reflect函数的原理在红宝书中有说明,仅仅有对照了红宝书,才知道红宝书的定位:高级工具书. 蓝宝书作为入门级书籍,以较快的速度让读者敲到代码去思考,总遗留了须要 ...

  5. OpenGL ES 渲染立体图形

    一.理解 顶点数据存储在申请的缓冲区中,其由数据总线传递给着色器(如果是片元着色器,还须将顶点转换成片元),再由着色器最终渲染到涂层上: 二.思路 1.设置涂层: 2.创建上下文: 3.清空缓存区: ...

  6. opengl 笔记(1)

    参考<opengl入门教程>.<OpenGL之坐标转换>.<OpenGL绘制管线操作细节>等资料. 复习下留个备忘:) /*- * Opengl Demo Test ...

  7. openGL实现二维图形和三维图形

    openGL是一个强大的底层图形库,其命令最初的时候使用C语言实现的.openGL定义了一个图形程序接口,常用于制作处理三维图像,功能强大,调用方便,在图像处理十分受欢迎. 实现图形主要使用的是ope ...

  8. CSharpGL(6)在OpenGL中绘制UI元素

    CSharpGL(6)在OpenGL中绘制UI元素 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo,更适合入 ...

  9. OpenGL顶点数组

    概述 作为在立即模式(glBegin()与glEnd()之间)下指定单个顶点数据的替代,你可以保存顶点数据在一组列表中,包括顶点位置.法线.纹理坐标与颜色信息.并且你可以通过索引数组解引用数组元素绘制 ...

随机推荐

  1. git for windows 无法提交修改的处理

    在git for windows里面不能commit修改,提示open shell open shell以后,使用git add [filename],会报错: fatal: Unable to cr ...

  2. 每日英语:The best time for coffee is 10:30 a.m.

    For many of us, it is the rocket fuel that gets us going first thing in the morning. But one expert ...

  3. 每日英语:The Risks of Big Data for Companies

    Big data. It's the latest IT buzzword, and it isn't hard to see why. The ability to parse more infor ...

  4. visio直线交叉相交跨线修改

    在使用visio画流程图时,经常会遇到两条直线相交.下面讲如何修改使得相交点变成我们想要的方式. 可以设置如下: (1)  全局直线相交,设置跨线标志. (2)  对每条线进行相交跨线设置. (一) ...

  5. 2017年研究生数学建模竞赛-E题 MATLAB 作战区域道路示意图

    MATLAB 画区域作战图 clear load('output_path1.mat') k = 1:130; gplot(edge(k,k),loc(k,:),'c-') title('作战区域道路 ...

  6. HTTP请求与响应报文详解

    如图所示,这是客户端往服务器发送请求时的报文: 一般来说,将报文分成三个部分,请求行.请求头.请求体 如图,请求行包括三部分内容 1.请求方法,在HTTP里的请求方法种类较多,但就移动端开发来说,常用 ...

  7. Android Studio占用C盘内存

    使用Android Studio的时候,会发现,在各种下载导入的时候,C盘内存耗费的非常的快,于是我看了下配置.

  8. [转]MySQL函数大全 及用法示例

    原文地址:http://blog.sina.com.cn/s/blog_4586764e0100h5ct.html 1.字符串函数ascii(str)   返回字符串str的第一个字符的ascii值( ...

  9. Git做代码增量发布的重要用法 - --diff-filter

    你以为有 bash git diff --name-only 就够了,NO! 对于PHP开发的系统来说,增量发布,一般只需部署新增的文件和有变动的文件,但很多时候,文件是删除的或重构成其它文件名或重构 ...

  10. backlight 子系统(转载)

    http://blog.csdn.net/weiqing1981127/article/details/8511676   Linux下的Backlight子系统(一) http://blog.csd ...