博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用OpenGL实现跳跃的立体小球
阅读量:4654 次
发布时间:2019-06-09

本文共 5318 字,大约阅读时间需要 17 分钟。

一、目的

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

 

二、示例代码

#include "stdafx.h"#include 
#include
#include
#include
#include
//色彩全局常量GLfloat WHITE[] = { 1, 1, 1 }; //白色GLfloat RED[] = { 1, 0, 0 }; //红色GLfloat GREEN[] = { 0, 1, 0 }; //绿色GLfloat MAGENTA[] = { 1, 0, 1 }; //洋红//摄像机类:水平移动半径为10,按上下键则垂直移动class Camera {public: double theta; //确定x和z的位置 double y; //y位置 double dTheta; //角度增量 double dy; //上下y增量public: //类构造函数—默认初始化用法 Camera() : theta(0), y(3), dTheta(0.04), dy(0.2) {} //类方法 double getX() { return 10 * cos(theta); } double getY() { return y; } double getZ() { return 10 * 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(-1), y(h), x(x), z(z) { } //更新和绘制方法 void update() { //正反运动 y += direction * 0.05; if (y > maximumHeight) { y = maximumHeight; direction = -1; } else if (y < radius) { y = radius; direction = 1; } glPushMatrix(); //单独设置每个球的材质参数 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color); glTranslated(x, y, z); //创建球 glutSolidSphere(radius, 30, 30); 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 / 2; } //中心Y double centerz() { return depth / 2; } //创建方法 void create() { displayListId = glGenLists(1); //每个显示列表对应1个编号——关联起来 //新建操作表 glNewList(displayListId, GL_COMPILE); //把下述命令装入显示列表但不显示 //光源位置参数 GLfloat lightPosition[] = { 4, 3, 7, 1 }; //设置光源位置 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); //开始绘制四边形 glBegin(GL_QUADS); //法向量方向 glNormal3d(0, 1, 0); for (int x = 0; x < width - 1; x++) { for (int z = 0; z < depth - 1; z++) { //设置每个格子的材质属性 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, (x + z) % 2 == 0 ? RED : WHITE); //四边形的4个点坐标 glVertex3d(x, 0, z); glVertex3d(x + 1, 0, z); glVertex3d(x + 1, 0, z + 1); glVertex3d(x, 0, z + 1); } } glEnd(); glEndList(); } //按列表编号绘制棋盘格 void draw() { glCallList(displayListId); }};//全局变量:棋盘格、相机和3个球的数组Checkerboard checkerboard(8, 8);Camera camera;//创建3个小球的数组Ball balls[] = { Ball(1, GREEN, 7, 6, 1), Ball(1.5, MAGENTA, 6, 3, 4), Ball(0.4, WHITE, 5, 1, 7)};//自定义初始化方法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, 30); //允许灯光 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 = 0; i < sizeof balls / sizeof(Ball); i++) { //更新位置并绘图 balls[i].update(); } //glFlush(); glutSwapBuffers();}//窗口调整大小时调用的函数void reshape(GLint w, GLint h) { glViewport(0, 0, 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(1000 / 60, 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(80, 80); glutInitWindowSize(800, 600); glutCreateWindow("跳跃的球"); glutDisplayFunc(display); //设置显示函数 glutReshapeFunc(reshape); //设置窗口调整大小的函数 glutSpecialFunc(onKey); //设置按键处理函数 glutTimerFunc(100, timer, 0); //设置计时器函数--每100ms被调用1次 init();//自定义初始化函数 glutMainLoop();//进入opengl主循环 return 0;}

 

 

转载于:https://www.cnblogs.com/OctoptusLian/p/7367349.html

你可能感兴趣的文章
数字pid笔记(2)
查看>>
Visual Studio Code快速删除空行及几个常用快捷键总结
查看>>
STM32F103C8T6最小板搞定CMSIS-DAP和SWO功能
查看>>
一篇文章让您了解MQTT
查看>>
MQTT介绍与使用
查看>>
ESP8266—“ICACHE_FLASH_ATTR”宏
查看>>
Win10系统如何在防火墙里开放端口
查看>>
ESP8266常见问题汇总——转载自官网
查看>>
初识 MQTT——IBM
查看>>
快速开发MQTT(一)电子工程师眼中的MQTT
查看>>
MQTT 入门介绍——菜鸟教程
查看>>
重新学习ESP32(零)之环境搭建——转载——windows平台
查看>>
ESP8266—“ICACHE_FLASH_ATTR”宏——解释含义
查看>>
ESP8266在线视频网址
查看>>
ESP8266烧录选项中的QIO 和 DIO解释
查看>>
通俗的计算机网络通信的软文——转载知乎
查看>>
ESP8266乐鑫版本的(支持云端升级 (Boot 模式)烧写方法,(V1.5.4官方介绍如下)(BOOT模式)...
查看>>
stm32 cubemx hal dma uart参考例程,发送和接收
查看>>
linux编译esp8266
查看>>
freemodbus收藏学习网址
查看>>