一、目的

掌握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. PLSA及EM算法

    前言:本文主要介绍PLSA及EM算法,首先给出LSA(隐性语义分析)的早期方法SVD,然后引入基于概率的PLSA模型,其参数学习采用EM算法.接着我们分析如何运用EM算法估计一个简单的mixture ...

  2. zipkin微服务调用链分析

    1.zipkin的作用 在微服务架构下,一个http请求从发出到响应,中间可能经过了N多服务的调用,或者N多逻辑操作, 如何监控某个服务,或者某个逻辑操作的执行情况,对分析耗时操作,性能瓶颈具有很大价 ...

  3. 【Socket】linux套接字技术之tcp

      1.mystery引入      1)UDP也可以编写出C/S程序 ,另外TCP也可以编写点对点通信.    2)网络的本质就是资源共享,当前流行的P2P应用正好暗合了这种精神.    3)当前流 ...

  4. FFmpeg Basics学习笔记(2)

    帧率 fps的概念 帧率,单位FPS(frame per second), 用于衡量视频每秒的处理帧数,对于编码器而言说明编码器在1s的编码的速度,通常可以使用一帧的编码时间倒数简单计算:对于解码器而 ...

  5. Nginx作为反向代理服务器

    前言:Nginx通过proxy模块实现反向代理功能.在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI.客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream ...

  6. JIRA python篇之统计产品尚未解决的bugs

    [本文出自天外归云的博客园] 通过python中的jira类我们可以方便的操作jira,获取一些我们想要再加工的信息. 一些通过JIRA的JTL查询语句不方便直接搜索的过滤条件可以通过JIRA的pyt ...

  7. UDP服务器

    用c#开发的一个UDP服务器.可以接收UDP的连接请求.给予响应. 代码已经上传至 GitHub,功能还会不断完善. 界面很丑.我很奇怪的是很少(到现在为止,我都没有见到过),所以界面一直做的不够酷炫 ...

  8. 解决hibernate向mysql插入中文乱码问题(转)

    转载自:http://blog.csdn.net/peditable/article/details/7047573 1.首先需要修改MySQL数据库的配置文件my.ini,此文件放在mysql根目录 ...

  9. C#中使用Buffer.BlockCopy()方法将string转换为byte array的方法:

    public static void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count); 将指定数目的字 ...

  10. Linux 下编译出现 undefined reference to `pthread_create'

    这是由于没有链接线程库的原因,只要在编译的时候加入: -lpthread 参数即可. arm-linux-gcc serial.c -o serial -lpthread 查看 ubuntu 版本的命 ...