您的位置:首页 > 运维架构

[OpenGL] 二维游戏中的卷动地图

2016-07-26 20:17 316 查看
        卷动地图,也就是显示屏上只显示地图的一部分,随着玩家的走动,地图自动向走动方向卷动。在设计地图较大的二维游戏时,我们都不可避免地需要面对地图卷动这个问题。在切换场景方面,卷动地图和动态加载地图两者的结合,让整个游戏世界得以完整地呈现在玩家面前。

        在这一方面,比较高效的算法是卡马克卷轴算法,但是在这里,出于了解卷动地图的目的,我们只实现了最为朴素的卷动地图算法。也就是说,我们一次性绘制了整个地图,然后通过调整观察位置和视口大小,来实现卷动的效果。

        给出的样例中使用的地图是一张完整的图片。如果我们的地图不是一张完整的图片,而是网格布局的话,我们还可以考虑只绘制当前屏幕图片提高效率,这个优化会在之后的网格布局与碰撞检测中介绍。

    函数回顾

         首先,我们需要回顾一下OpenGL中几个重要函数的用法:

        1.glOrtho。该函数实现正投影。也就是,我们定义一个当前摄像机下的取景框大小,只有落在这个框里的物体才会显示。注意我们在glOrtho设置的参数非常重要,比如在这个例子中,我们设置的参数是glOrtho(-4, 4, -4, 4, -100, 100)。这也就意味着我们的屏幕坐标左下角是(-4.0,-4.0),右上角是(4.0,4.0),(注:正视时)我们需要利用这个数据来进行图形位置的摆放。

        2.glViewport。视口大小。在这里我们定义了视口的左下角坐标(一般为0,0)和视口长宽。可以这样理解,我们在此定义了取景框投影后的长与宽,然后屏幕也有长与宽,最终屏幕将截取屏幕大小的场景显示。一般而言,我们把这个视口大小设置的和窗体大小一样,就能恰好把所有物体包围。

        进一步而言,如果我们把视口大小设置的比窗体大,那么窗体只显示取景框中的一部分物体,利用这个,我们可以实现卷动地图效果:

       


        反言之,如果取景框大小比窗体小,那么就可以实现一个屏幕显示多个场景的效果:

       


      3.gluLookAt,定义了摄像机的位置以及朝向等。在卷动中,我们就是在不断移动这个摄像机的位置。

    自动卷动

        我们定义当人物走到屏幕3/4处时,触发卷动事件。在触发后,摄像机和人物一起向一个方向移动,注意移动速度最好相同。当场景快要走出视野后,我们限制摄像机不再移动。当然,人物还是可以继续走动的,直到它走到地图边缘。
        自动卷动的原理很简单,但是,问题在于,什么是屏幕的3/4处,什么又是场景快要走出视野的状态?我们只讨论水平方向的移动来解释这个问题,竖直方向的移动是同理的。

        首先,我们定义glOrtho参数为-size_x,  size_x,  -size_y,  size_y,-100,  100; 卷动缩小的水平比例是x,竖直比例是y,也就是说,glViewport的参数是0,0,x*width,y*height,它将物体按这样的比例相对于窗体大小放大。

    

  

          在上图中,x = 3,也就是说,对于一张地图的水平方向,窗口只显示了它的1/3大小。当人物移动到红线的时候,触发卷动事件。

          在这里,首先要指出,中心坐标点 x = 0。图中一个方块的大小是2*size_x / x, 那么3/4个方块的大小就是3 / 2 * size_x / x。由于中心坐标x = 0,所以红线的坐标x = -size + 1.5*size/x。

         那么,什么时候卷动结束呢?或者说,什么时候我们不能继续移动摄像机了?

         我们用一些具体的例子来解释。

        ① x = 2。

       

 

        整个场景占了两个格子,而屏幕只显示其中一个格子。

        一开始,我们的摄像机位于黄色的位置,它把整个场景都包在取景框内,但是,由于glViewport的参数,初始状态下,我们在屏幕上看到的只是第一块格子。

       那么,场景即将离开的时候,我们希望在屏幕上恰好显示完整的第二块格子。这个时候,摄像机应该处在绿色的位置。

        一个格子的大小为2*size_/2 = size_x, 黄色处坐标为0,所以,摄像机的临界x值为:size_x。

       

     ②x = 3

       


        整个场景占了3个格子,而屏幕只显示1个格子。

       一个格子的大小为2*size_x/3 , 黄色处坐标为0,所以,摄像机的临界x值为:2*2*size_x/3 = 4*size_x/3。

    ③x = 4

       


        整个场景占了4个格子,而屏幕只显示1个格子。

        一个格子的大小为2*size_x/4 = size_x/2,黄色处坐标为0,所以,摄像机的临界x值为:3*size_x/2 .

       

        ……

       最终,得到对于任意的x,摄像机的临界x值为 2 * size_x - 2 * size_x / x。

       分辨率也会影响临界x值,在给出的例子中,我们考虑了分辨率的影响,涉及到的函数语句为wHeight = wWidth = min(width, height); 在相应的判断语句中也乘上了w/h系数,如果不希望考虑这一因素,直接把所有出现的w,h(宽度和高度)以及和它相关的语句删掉即可。两个卷动函数也可以合并为一个。

       


    代码

  test.h

#pragma once
#define GLUT_DISABLE_ATEXIT_HACK
#include "GL/GLUT.H"
void loadTex(int i, char *filename, GLuint* texture);//一般纹理
void loadTex(int i, char *filename, GLuint* texture, unsigned char* backgroundColor);//透明纹理

class sprite
{
public:
//精灵位置(中心位置)
float pos_x;
float pos_y;

//帧动画参数
int num = 96;//一共多少帧
int col = 12;//一行有多少帧

//精灵索引下标
//前、左、右、后
int index[4][3][2];

//步长
float step;

//用于计数
int count;
int count2;
int count3;

//精灵贴图
GLuint texture;

//行走方向(枚举量)
typedef enum { left, right, front, back }direction;

//是否停止
bool isStop = true;

//行走方向
direction dir = front;

sprite(int _col,int _num,float x,float y,GLuint _texture,int* index,float _step);

//快速索引绘制精灵
void drawRect(GLuint texture, int i, int j);

//绘制精灵
void drawSprite();
};


texture.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
#include"test.h"
#define BITMAP_ID 0x4D42

//读纹理图片
static unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{

FILE *filePtr;    // 文件指针
BITMAPFILEHEADER bitmapFileHeader;    // bitmap文件头
unsigned char    *bitmapImage;        // bitmap图像数据
int    imageIdx = 0;        // 图像位置索引
unsigned char    tempRGB;    // 交换变量

// 以“二进制+读”模式打开文件filename
filePtr = fopen(filename, "rb");
if (filePtr == NULL) {
printf("file not open\n");
return NULL;
}
// 读入bitmap文件图
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// 验证是否为bitmap文件
if (bitmapFileHeader.bfType != BITMAP_ID) {
fprintf(stderr, "Error in LoadBitmapFile: the file is not a bitmap file\n");
return NULL;
}
// 读入bitmap信息头
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// 将文件指针移至bitmap数据
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// 为装载图像数据创建足够的内存
bitmapImage = new unsigned char[bitmapInfoHeader->biSizeImage];
// 验证内存是否创建成功
if (!bitmapImage) {
fprintf(stderr, "Error in LoadBitmapFile: memory error\n");
return NULL;
}

// 读入bitmap图像数据
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// 确认读入成功
if (bitmapImage == NULL) {
fprintf(stderr, "Error in LoadBitmapFile: memory error\n");
return NULL;
}
//由于bitmap中保存的格式是BGR,下面交换R和B的值,得到RGB格式

for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx += 3) {
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// 关闭bitmap图像文件
fclose(filePtr);
return bitmapImage;
}

//读纹理图片
static unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader, unsigned char* backgroundColor)
{

FILE *filePtr;    // 文件指针
BITMAPFILEHEADER bitmapFileHeader;    // bitmap文件头
unsigned char    *bitmapImage;        // bitmap图像数据
int    imageIdx = 0;        // 图像位置索引

// 以“二进制+读”模式打开文件filename
filePtr = fopen(filename, "rb");
if (filePtr == NULL) {
printf("file not open\n");
return NULL;
}
// 读入bitmap文件图
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// 验证是否为bitmap文件
if (bitmapFileHeader.bfType != BITMAP_ID) {
fprintf(stderr, "Error in LoadBitmapFile: the file is not a bitmap file\n");
return NULL;
}
// 读入bitmap信息头
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// 将文件指针移至bitmap数据
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// 为装载图像数据创建足够的内存
bitmapImage = new unsigned char[bitmapInfoHeader->biSizeImage];
// 验证内存是否创建成功
if (!bitmapImage) {
fprintf(stderr, "Error in LoadBitmapFile: memory error\n");
return NULL;
}

// 读入bitmap图像数据
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// 确认读入成功
if (bitmapImage == NULL) {
fprintf(stderr, "Error in LoadBitmapFile: memory error\n");
return NULL;
}
unsigned char*   bitmapData;   // 纹理数据

bitmapData = new unsigned char[bitmapInfoHeader->biSizeImage / 3 * 4];

int count = 0;
//添加alpha通道
for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx += 3) {
bitmapData[count] = bitmapImage[imageIdx + 2];
bitmapData[count + 1] = bitmapImage[imageIdx + 1];
bitmapData[count + 2] = bitmapImage[imageIdx];
if (bitmapData[count] >= backgroundColor[0]
&& bitmapData[count + 1] >= backgroundColor[1]
&& bitmapData[count + 2] >= backgroundColor[2]) {
bitmapData[count + 3] = 0;
}
else bitmapData[count + 3] = 255;
count += 4;
}

// 关闭bitmap图像文件
fclose(filePtr);
return bitmapData;
}

//加载纹理的函数
void loadTex(int i, char *filename, GLuint* texture)
{

BITMAPINFOHEADER bitmapInfoHeader;                                 // bitmap信息头
unsigned char*   bitmapData;                                       // 纹理数据

bitmapData = LoadBitmapFile(filename, &bitmapInfoHeader);

glBindTexture(GL_TEXTURE_2D, texture[i]);
// 指定当前纹理的放大/缩小过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexImage2D(GL_TEXTURE_2D,
0,         //mipmap层次(通常为,表示最上层)
GL_RGB,    //我们希望该纹理有红、绿、蓝数据
bitmapInfoHeader.biWidth, //纹理宽带,必须是n,若有边框+2
bitmapInfoHeader.biHeight, //纹理高度,必须是n,若有边框+2
0, //边框(0=无边框, 1=有边框)
GL_RGB,    //bitmap数据的格式
GL_UNSIGNED_BYTE, //每个颜色数据的类型
bitmapData);    //bitmap数据指针

}

//加载纹理的函数
void loadTex(int i, char *filename, GLuint* texture, unsigned char* backgroundColor)
{

BITMAPINFOHEADER bitmapInfoHeader;                                 // bitmap信息头
unsigned char*   bitmapData;                                       // 纹理数据

bitmapData = LoadBitmapFile(filename, &bitmapInfoHeader, backgroundColor);

glBindTexture(GL_TEXTURE_2D, texture[i]);
// 指定当前纹理的放大/缩小过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexImage2D(GL_TEXTURE_2D,
0,         //mipmap层次(通常为,表示最上层)
GL_RGBA,    //我们希望该纹理有红、绿、蓝、alpha数据
bitmapInfoHeader.biWidth, //纹理宽带,必须是n,若有边框+2
bitmapInfoHeader.biHeight, //纹理高度,必须是n,若有边框+2
0, //边框(0=无边框, 1=有边框)
GL_RGBA,    //bitmap数据的格式
GL_UNSIGNED_BYTE, //每个颜色数据的类型
bitmapData);    //bitmap数据指针

}


sprite.cpp

#include"test.h"

sprite::sprite(int _col, int _num, float x, float y, GLuint _texture, int* _index,float _step)
{
count = count2 = count3 = 0;
col = _col;
num = _num;
pos_x = x;
pos_y = y;
texture = _texture;
int cnt = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 2; k++) {
index[i][j][k] = _index[cnt++];
}
}
}
step = _step;
}
void sprite::drawRect(GLuint texture, int i, int j)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);  //选择纹理texture[status]

const GLfloat x1 = -0.5, x2 = 0.5;
const GLfloat y1 = -0.5, y2 = 0.5;
const GLfloat x = 1.0 / col, y = 1.0 / (num / col);
const GLfloat point[4][2] = { { x1,y1 },{ x2,y1 },{ x2,y2 },{ x1,y2 } };
const GLfloat dir[4][2] = { { j*x,1 - (i + 1)*y },{ (j + 1)*x,1 - (i + 1)*y },{ (j + 1)*x ,1 - i*y },{ j*x,1 - i*y } };
glBegin(GL_QUADS);

for (int k = 0; k < 4; k++) {
glTexCoord2fv(dir[k]);
glVertex2fv(point[k]);
}
glEnd();

glDisable(GL_TEXTURE_2D);
}

void sprite::drawSprite()
{
const int step = 50;
count++;

if (isStop) {
if (dir == front) {
drawRect(texture, index[0][1][0], index[0][1][1]);
}
else if (dir == back) {
drawRect(texture, index[3][1][0], index[3][1][1]);
}
else if (dir == left) {
drawRect(texture, index[1][1][0], index[1][1][1]);
}
else if (dir == right) {
drawRect(texture, index[2][1][0], index[2][1][1]);
}
}
else if (dir == front) {
if (count <= step) {
drawRect(texture, index[0][0][0], index[0][0][1]);
}
else if (count > step&&count <= step * 2) {
drawRect(texture, index[0][1][0], index[0][1][1]);
}
else if (count > step * 2 && count <= step * 3) {
drawRect(texture, index[0][2][0], index[0][2][1]);
}
}
else if (dir == back) {
if (count <= step) {
drawRect(texture, index[3][0][0], index[3][0][1]);
}
else if (count > step && count <= step * 2) {
drawRect(texture, index[3][1][0], index[3][1][1]);
}
else if (count > step * 2 && count <= step * 3) {
drawRect(texture, index[3][2][0], index[3][2][1]);
}
}
else if (dir == left) {
if (count <= step) {
drawRect(texture, index[1][0][0], index[1][0][1]);
}
else if (count > step && count <= step * 2) {
drawRect(texture, index[1][1][0], index[1][1][1]);
}
else if (count > step * 2 && count <= step * 3) {
drawRect(texture, index[1][2][0], index[1][2][1]);
}
}
else if (dir == right) {
if (count <= step) {
drawRect(texture, index[2][0][0], index[2][0][1]);
}
else if (count > step && count <= step * 2) {
drawRect(texture, index[2][1][0], index[2][1][1]);
}
else if (count > step * 2 && count <= step * 3) {
drawRect(texture, index[2][2][0], index[2][2][1]);
}
}
if (count%step == 0) {
if (count2 == count3) {
if (dir == front) {
drawRect(texture, index[0][1][0], index[0][1][1]);
}
else if (dir == back) {
drawRect(texture, index[3][1][0], index[3][1][1]);
}
else if (dir == left) {
drawRect(texture, index[1][1][0], index[1][1][1]);
}
else if (dir == right) {
drawRect(texture, index[2][1][0], index[2][1][1]);
}
isStop = true;

}
count3 = count2;
}
if (count == step * 3) {
count = 0;
}
}


main.cpp

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <string.h>
#include<time.h>
#include <stdlib.h>
#include"test.h"

#include <math.h>       /* for cos(), sin(), and sqrt() */

GLuint texture[2];
//视区
float whRatio;
int wHeight;
int wWidth;

//分辨率
float h=900, w=800;

//正投影
float size_x = 4.0f;
float size_y = 4.0f;

//分辨率中,宽的值是否更大
bool isWidthLarger;

//水平、竖直方向的卷轴大小与窗口大小比例
int x = 3;
int y = 2;

//视点
float center[] = { 0, 0, 0 };
float eye[] = { 0, 0, 5 };

sprite *s;

inline float min(float x, float y)
{
if (x < y) {
isWidthLarger = false;
return x;
}
else {
isWidthLarger = true;
return y;
}
}
void drawRect(GLuint texture)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);  //选择纹理texture[status]
const GLfloat x1 = -0.5, x2 = 0.5;
const GLfloat y1 = -0.5, y2 = 0.5;
const GLfloat point[4][2] = { { x1,y1 },{ x2,y1 },{ x2,y2 },{ x1,y2 } };
int dir[4][2] = { { 0,0 },{ 1,0 },{ 1,1 },{ 0,1 } };
glBegin(GL_QUADS);

for (int i = 0; i < 4; i++) {
glTexCoord2iv(dir[i]);
glVertex2fv(point[i]);
}
glEnd();
glDisable(GL_TEXTURE_2D);
}

void drawScene()
{
glPushMatrix();
glScalef(size_x *2, size_y*2, 1);
drawRect(texture[1]);
glPopMatrix();

glPushMatrix();
glTranslatef(s->pos_x, s->pos_y, 2);
glScalef(0.3f,0.3f, 1);
s->drawSprite();
glPopMatrix();
}

void updateView(int height, int width)
{

glViewport(0, 0, width * x, height * y);
glMatrixMode(GL_PROJECTION);//设置矩阵模式为投影
glLoadIdentity();   //初始化矩阵为单位矩阵
whRatio = (GLfloat)width / (GLfloat)height;  //设置显示比例
glOrtho(-size_x, size_x,-size_y,size_y, -100, 100); //正投影
glMatrixMode(GL_MODELVIEW);  //设置矩阵模式为模型
}

void scroll_1()
{
if (s->dir == sprite::right || s->dir == sprite::left) {
if (s->dir == sprite::right&&s->pos_x>-size_x + 1.5*size_x / x*w/h&& s->pos_x<size_x) {
eye[0] += s->step;
center[0] += s->step;
if (eye[0]>2 * size_x - 2 * size_x / x*w / h) {
eye[0] = 2 * size_x - 2 * size_x / x*w / h;
center[0] = 2 * size_x - 2 * size_x / x*w / h;
}
}
else if (s->dir == sprite::left&&s->pos_x>-size_x&& s->pos_x<size_x - 1.5*size_x / x*w / h) {
eye[0] -= s->step;
center[0] -= s->step;
if (eye[0]<0) {
eye[0] = 0;
center[0] = 0;
}
}
}
if (s->dir == sprite::front || s->dir == sprite::back) {
if (s->dir == sprite::back&&s->pos_y>-size_y + 1.5*size_y /y && s->pos_y<size_y) {
eye[1] += s->step;
center[1] += s->step;
if (eye[1]>2 * size_y - 2 * size_y / y) {
eye[1] = 2 * size_y - 2 * size_y / y;
center[1] = 2 * size_y - 2 * size_y / y;
}
}
else if (s->dir == sprite::front&&s->pos_y>-size_y&&s->pos_y<size_y - 1.5*size_y / y) {
eye[1] -= s->step;
center[1] -= s->step;
if (eye[1]<0) {
eye[1] = 0;
center[1] = 0;
}
}
}
}

void scroll_2()
{
if (s->dir == sprite::right || s->dir == sprite::left) {
if (s->dir == sprite::right&&s->pos_x>-size_x + 1.5*size_x / x&& s->pos_x<size_x) {
eye[0] += s->step;
center[0] += s->step;
if (eye[0]>2 * size_x - 2 * size_x / x) {
eye[0] = 2 * size_x - 2 * size_x / x;
center[0] = 2 * size_x - 2 * size_x / x;
}
}
else if (s->dir == sprite::left&&s->pos_x>-size_x&& s->pos_x<size_x - 1.5*size_x / x) {
eye[0] -= s->step;
center[0] -= s->step;
if (eye[0]<0) {
eye[0] = 0;
center[0] = 0;
}
}
}
if (s->dir == sprite::front || s->dir == sprite::back) {
if (s->dir == sprite::back&&s->pos_y>-size_y + 1.5*size_y / y*w/h && s->pos_y<size_y) {
eye[1] += s->step;
center[1] += s->step;
if (eye[1]>2 * size_y - 2 * size_y / y*w / h) {
eye[1] = 2 * size_y - 2 * size_y / y*w / h;
center[1] = 2 * size_y - 2 * size_y / y*w / h;
}
}
else if (s->dir == sprite::front&&s->pos_y>-size_y&&s->pos_y<size_y - 1.5*size_y / y*w / h) {
eye[1] -= s->step;
center[1] -= s->step;
if (eye[1]<0) {
eye[1] = 0;
center[1] = 0;
}
}
}
}

void key(unsigned char k, int _x, int _y)
{
s->count2++;
switch (k)
{
case 'a': {
s->dir = sprite::left;
s->isStop = false;
s->pos_x -= s->step;
if (s->pos_x < -size_x)s->pos_x = -size_x;
break;
}
case 'd': {
s->dir = sprite::right;
s->isStop = false;
s->pos_x += s->step;
if (s->pos_x > size_x)s->pos_x = size_x;
break;
}
case 'w': {
s->dir = sprite::back;
s->isStop = false;
s->pos_y += s->step;
if (s->pos_y > size_y)s->pos_y = size_y;
break;
}
case 's': {
s->dir = sprite::front;
s->isStop = false;
s->pos_y -= s->step;
if (s->pos_y < -size_y)s->pos_y = -size_y;
break;
}
}
if(isWidthLarger)scroll_1();
else scroll_2();
updateView(wHeight, wWidth); //更新视角
}

void reshape(int width, int height)
{
if (height == 0)      //如果高度为0
{
height = 1;   //让高度为1(避免出现分母为0的现象)
}
h = height;
w = width;
wHeight = height;
wWidth = width;
wHeight = wWidth = min(width, height);
updateView(wHeight, wWidth); //更新视角

}

void idle()
{
glutPostRedisplay();
}

void init()
{
srand(unsigned(time(NULL)));
glEnable(GL_DEPTH_TEST);//开启深度测试
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5);
unsigned char color[3] = { 255,255,255 };
glGenTextures(2, texture);
loadTex(0, "1.bmp", texture,color);
loadTex(1, "2.bmp", texture);
if (w > h)isWidthLarger = true;
else isWidthLarger = false;
int index[] = {0,0,0,1,0,2,1,0,1,1,1,2,2,0,2,1,2,2,3,0,3,1,3,2};
s = new sprite(12, 96, -1.5f, -1.5f, texture[0], index,0.06f);
}

void redraw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除颜色和深度缓存
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();   //初始化矩阵为单位矩阵
gluLookAt(eye[0], eye[1], eye[2], center[0], center[1], center[2], 0, 1, 0);                // 场景(0,0,0)的视点中心 (0,5,50),Y轴向上
glPolygonMode(GL_FRONT, GL_FILL);
drawScene();//绘制场景
glutSwapBuffers();//交换缓冲区
}

int main(int argc, char *argv[])
{

glutInit(&argc, argv);//对glut的初始化
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
//初始化显示模式:RGB颜色模型,深度测试,双缓冲
glutInitWindowSize(w,h);//设置窗口大小
int windowHandle = glutCreateWindow("Simple GLUT App");//设置窗口标题
glutDisplayFunc(redraw); //注册绘制回调函数
glutReshapeFunc(reshape);   //注册重绘回调函数
glutKeyboardFunc(key); //注册按键回调函数
glutIdleFunc(idle);//注册全局回调函数:空闲时调用

init();
glutMainLoop();  // glut事件处理循环
return 0;
}

图片资源来自网络:



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: