写了个三维迷宫练练手 - 哆啦比猫的技术瞎扯 - Arch Linux · ドラえもん · 实时绘制

写了个三维迷宫练练手

哆啦比猫 posted @ 2011年8月17日 15:02 in C/C++ with tags maze , 2523 阅读

终于写了个像样点的 OpenGL 程序了

代码放在 https://github.com/cjxgm/clabs/blob/master/demo/Mine/opengl_learning/11_maze/

#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include "camera.h"

float spin = 0;
float pos_x = 0, pos_y = 0, pos_z = 0;
static const float no[] = { 0, 0, 0, 1 };
static char key[256] = {0};
static float fps = 1;

static GLuint lists;
#define LIST_SIZE		1
#define LIST_MAZE		lists

void draw_maze(void)
{
#define W 15
#define H 10
#define MAZE(X,Y)	maze[(((Y) * W) + X)]
	const char maze[H*W+1] = 
		"###############"
		"        #     #"
		"####  ### #####"
		"#  # #         "
		"#  #   * ###  #"
		"#  ##### # #  #"
		"#    # # # #  #"
		"# # *  ### #  #"
		"#             #"
		"###############";

	float ground_diffuse[] = { 0.6, 0.6, 0.6, 1 };
	float wall_diffuse[] = { 0.8, 0.8, 0.4, 1 };
	float danger_emission[] = { 1.0, 0.6, 0.2, 1 };

	int x, y;
	for (y=0; y<H; y++)
		for (x=0; x<W; x++) {
			glPushMatrix(); {
				glTranslatef(x, y, 0);
				switch (MAZE(x, y)) {
					case '#': // wall
						glMaterialfv(GL_FRONT, GL_DIFFUSE, wall_diffuse);
						glMaterialfv(GL_FRONT, GL_EMISSION, no);
						break;
					case ' ': // ground
						glMaterialfv(GL_FRONT, GL_DIFFUSE, ground_diffuse);
						glMaterialfv(GL_FRONT, GL_EMISSION, no);
						glScalef(1, 1, 0.1);
						break;
					case '*': // danger
						glMaterialfv(GL_FRONT, GL_DIFFUSE, no);
						glMaterialfv(GL_FRONT, GL_EMISSION,
										danger_emission);
						break;
				}
				glTranslatef(0, 0, 0.5);
				glutSolidCube(1.0);
			} glPopMatrix();
		}
#undef W
#undef H
#undef MAZE
}

void key_down(unsigned char k, int x, int y)
{
	key[k] = 1;
}

void key_up(unsigned char k, int x, int y)
{
	key[k] = 0;
}

void glWindowPos2i(int x, int y); // 奇怪,为什么没有这个会说没有声明,头文件里不是有么

void renderString(int x, int y,
		const char * string, void * font)
{
	if (font == NULL) font = GLUT_BITMAP_HELVETICA_18;
	glWindowPos2i(x, y);
	while (*string)
		glutBitmapCharacter(font, *string++);
}

void render(void)
{
	unsigned int time = glutGet(GLUT_ELAPSED_TIME);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushMatrix(); {
		camApply();

		glTranslatef(7.5, -2, -30);
		glScalef(4, 4, 4);
		glRotatef(-90, 0, 1, 0);
		glRotatef(-90, 1, 0, 0);
		glTranslatef(-7.5, -5, 0);
		glCallList(LIST_MAZE);
	} glPopMatrix();

	char buf[128];
	sprintf(buf, "fps: %.2f", fps);
	glColor3f(0.8, 0, 0);
	renderString(10, 10, buf, NULL);

	glutSwapBuffers();

	spin += 0.1;

	if (key[27]) exit(0);

	camBegin();
	if (key['w']) camForward(+4 / fps);
	if (key['s']) camForward(-4 / fps);
	if (key['d']) camTurn(+90 / fps);
	if (key['a']) camTurn(-90 / fps);
	if (key['q']) camPan(+4/ fps);
	if (key['e']) camPan(-4 / fps);
	camEnd();

	fps = 1000.0 / (glutGet(GLUT_ELAPSED_TIME) - time);
}

int main(int argc, char * argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(640, 480);
	glutCreateWindow("Maze");
	glutIdleFunc(&render);
	glutKeyboardFunc(&key_down);
	glutKeyboardUpFunc(&key_up);

	glMatrixMode(GL_PROJECTION);
	gluPerspective(45, 640.0 / 480.0, 1, 100);
	glMatrixMode(GL_MODELVIEW);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glEnable(GL_CULL_FACE);

	/* lighting */ {
		float light_pos[] = { 0, 0, 0, 1 };
		float white_light[] = { 1.1, 1.1, 1.1, 1 };
		float ambient[] = { 0.4, 0.4, 0.4, 1 };

		glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
		glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light);
		glLightfv(GL_LIGHT0, GL_SPECULAR, white_light);
		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
		glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);
	}

	glClearColor(0, 0, 0, 0);
	glEnable(GL_DEPTH_TEST);
	glClearDepth(1.0);

	lists = glGenLists(LIST_SIZE);
	glNewList(LIST_MAZE, GL_COMPILE);
	draw_maze();
	glEndList();

	camInit();

	glutMainLoop();

	return 0;
}

camera 的设计比较简洁,实现也很简单

#ifndef CAMERA_H
#define CAMERA_H

void camInit(void);
void camApply(void);
void camBegin(void);
void camEnd(void);
void camForward(float howmuch);
void camPan(float howmuch);
void camTurn(float howmuch);

#endif
#include "camera.h"
#include <GL/gl.h>

static float camera[16];

void camInit(void)
{
	glPushMatrix();
	glLoadIdentity();
	glGetFloatv(GL_MODELVIEW_MATRIX, camera);
	glPopMatrix();
}

void camApply(void)
{
	glLoadMatrixf(camera);
}

void camBegin(void)
{
	glPushMatrix();
}

void camEnd(void)
{
	glPopMatrix();
}

void camForward(float howmuch)
{
	glLoadIdentity();
	glTranslatef(0, 0, howmuch);
	glMultMatrixf(camera);
	glGetFloatv(GL_MODELVIEW_MATRIX, camera);
}

void camPan(float howmuch)
{
	glLoadIdentity();
	glTranslatef(howmuch, 0, 0);
	glMultMatrixf(camera);
	glGetFloatv(GL_MODELVIEW_MATRIX, camera);
}

void camTurn(float howmuch)
{
	glLoadIdentity();
	glRotatef(howmuch, 0, 1, 0);
	glMultMatrixf(camera);
	glGetFloatv(GL_MODELVIEW_MATRIX, camera);
}

然后就是 makefile 了

# Generated by ADSMGCS.

CC = gcc
CFLAGS = -Wall -s -O2 -lglut -lGL -lGLU

all: maze
clean:
	rm -f *.o
cleanall: clean
	rm -f maze
rebuild: clean all
debug: all
	./maze

maze: maze.o camera.o
	$(CC) $(CFLAGS) -o $@ $^
maze.o: maze.c camera.h
	$(CC) $(CFLAGS) -c -o $@ $<
camera.o: camera.c camera.h
	$(CC) $(CFLAGS) -c -o $@ $<

现在还不知道怎样取得当前位置,以及怎样“撞墙”


凡未特殊声明(转载/翻译),所有文章均为原创。
by Giumo Xavier Clanjor (哆啦比猫/兰威举), 2010-2019.
知识共享许可协议本作品采用知识共享署名·非商业性使用·相同方式共享 3.0 中国大陆许可协议进行许可。
文中凡未特殊声明且未声明为引用的代码均以 MIT 协议授权。

  • 无匹配
  • 无匹配
blog comments powered by Disqus
© 2010-2019 Giumo Xavier Clanjor (哆啦比猫/兰威举).
© 2013, 2014, 2015-2016 and 2017 The Dark Colorscheme Designed by Giumo Xavier Clanjor (哆啦比猫/兰威举).
知识共享署名·非商业性使用·相同方式共享 3.0 中国大陆许可协议
| © 2007 LinuxGem | Design by Matthew "Agent Spork" McGee