我正在尝试制作一个光线投射引擎,我已经修复了鱼眼效果(或者至少我认为我做得很准确),但现在我遇到了一个我似乎无法找到解决方案的问题;它看起来像:
这是我的代码(光线投射本身发生在drawRays2D函数中):
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <math.h>
typedef struct {
int z, q, d, s;
}ButtonKeys; ButtonKeys Keys;
#define RES_MULT 8.5
#define PI 3.141592653589
#define P2 PI/2
#define P3 3*PI/2
#define DR 0.0174533 //one degree in radians
float FixAng(float a){ if(a>359){ a-=360;} if(a<0){ a+=360;} return a;}
float degToRad(float a) { return a*PI/180.0;}
float px,py,pdx,pdy,pa;
void drawPlayer()
{
glColor3f(1.0, 1.0, 0.0);
glPointSize(8.0);
glBegin(GL_POINTS);
glVertex2i(px, py);
glEnd();
glLineWidth(3.0);
glBegin(GL_LINES);
glVertex2i(px, py);
glVertex2i(px+pdx*5, py+pdy*5);
glEnd();
}
int mapX = 8, mapY = 8, mapS = 64;
int map[]=
{
1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1,
1, 0, 0, 1, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 0, 0, 0, 0, 1, 0, 1,
1, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1,
};
void drawMap2D()
{
int x, y, xo, yo;
for (y = 0; y < mapY; y++) {
for (x = 0; x < mapX; x++) {
if (map[y * mapX + x] == 1) {
glColor3f(1.0, 1.0, 1.0);
} else {
glColor3f(0.0, 0.0, 0.0);
}
xo=x*mapS; yo=y*mapS;
glBegin(GL_QUADS);
glVertex2i( 0 +xo+1, 0 +yo+1);
glVertex2i( 0 +xo+1, mapS+yo-1);
glVertex2i( mapS+xo-1, mapS+yo-1);
glVertex2i( mapS+xo-1, 0 +yo+1);
glEnd();
}
}
}
float dist(float ax, float ay, float bx, float by, float ang)
{
return (sqrt((bx-ax)*(bx-ax) + (by-ay)*(by-ay)));
}
void drawRays2D()
{
int r, mx, my, mp, dof; float rx, ry, ra, xo, yo, disT;
ra = pa - DR*64; if (ra < 0) { ra += 2*PI; } if (ra > 2*PI) { ra -= 2*PI; }
for (r = 0; r < 128*RES_MULT; r++) {
// check horizontal lines
dof = 0;
float disH = 1000000, hx = px, hy = py;
float aTan = -1/tan(ra);
if (ra > PI) { ry = (((int)py>>6)<<6)-0.0001; rx = (py-ry)*aTan+px; yo = -64; xo = -yo*aTan; }
if (ra < PI) { ry = (((int)py>>6)<<6)+64; rx = (py-ry)*aTan+px; yo = 64; xo = -yo*aTan; }
if (ra == 0 || ra == PI) { rx = px; ry = py; dof = 8; }
while (dof < 8) {
mx = (int)(rx)>>6; my = (int)(ry)>>6; mp = my*mapX+mx;
if (mp > 0 && mp < mapX*mapY && map[mp] == 1) { hx=rx; hy=ry; disH=dist(px, py, hx, hy, ra); dof = 8; }
else { rx += xo; ry += yo; dof += 1; }
}
// check vertical lines
dof = 0;
float disV = 1000000, vx = px, vy = py;
float nTan = -tan(ra);
if (ra > P2 && ra < P3) { rx = (((int)px>>6)<<6)-0.0001; ry = (px-rx)*nTan+py; xo = -64; yo = -xo*nTan; }
if (ra < P2 || ra > P3) { rx = (((int)px>>6)<<6)+64; ry = (px-rx)*nTan+py; xo = 64; yo = -xo*nTan; }
if (ra == 0 || ra == PI) { rx = px; ry = py; dof = 8; }
while (dof < 8) {
mx = (int)(rx)>>6; my = (int)(ry)>>6; mp = my*mapX+mx;
if (mp > 0 && mp < mapX*mapY && map[mp] == 1) { vx=rx; vy=ry; disV=dist(px, py, vx, vy, ra); dof = 8; }
else { rx += xo; ry += yo; dof += 1; }
}
if (disV < disH) { rx = vx; ry = vy; disT = disV; glColor3f(0.9, 0.0, 0.0); }
if (disH < disV) { rx = hx; ry = hy; disT = disH; glColor3f(0.7, 0.0, 0.0); }
// glLineWidth(1.0); glBegin(GL_LINES); glVertex2i(px, py); glVertex2i(rx, ry); glEnd();
// draw 3D walls
float ca = pa - ra; if (ca < 0) { ca += 2*PI; } if (ca > 2*PI) { ca -= 2*PI; } disT = disT*cos(ca); // fix fisheye
float lineH = (mapS*500)/disT; if (lineH > 500) { lineH = 500; } // line height
float lineO = 160 - lineH/3.25; // line offset
glLineWidth(8/RES_MULT); glBegin(GL_LINES); glVertex2i(r*(8/RES_MULT), lineO); glVertex2i(r*(8/RES_MULT), lineH+lineO); glEnd();
ra+=(DR/RES_MULT); if (ra < 0) { ra += 2*PI; } if (ra > 2*PI) { ra -= 2*PI; }
}
}
float frame1, frame2, fps;
void display()
{
frame2 = glutGet(GLUT_ELAPSED_TIME); fps = (frame2-frame1); frame1 = glutGet(GLUT_ELAPSED_TIME);
if (Keys.q == 1) {pa -= .005*fps; if (pa < 0) { pa += 2*PI; } pdx = cos(pa)*5; pdy = sin(pa)*5;}
if (Keys.d == 1) {pa += .005*fps; if (pa > 2*PI) { pa -= 2*PI; } pdx = cos(pa)*5; pdy = sin(pa)*5;}
int xo=0; if (pdx<0) {xo=-20;} else {xo=20;}
int yo=0; if (pdy<0) {yo=-20;} else {yo=20;}
int ipx=px/64.0, ipx_add_xo=(px+xo)/64.0, ipx_sub_xo=(px-xo)/64.0;
int ipy=py/64.0, ipx_add_yo=(py+yo)/64.0, ipy_sub_yo=(py-yo)/64.0;
if (Keys.z==1) {
if (map[ipy*mapX + ipx_add_xo] == 0) {px+=pdx*.04*fps;}
if (map[ipx_add_yo*mapX + ipx] == 0) {py+=pdy*.04*fps;}
}
if (Keys.s==1) {
if (map[ipy*mapX + ipx_sub_xo] == 0) {px-=pdx*.04*fps;}
if (map[ipy_sub_yo*mapX + ipx] == 0) {py-=pdy*.04*fps;}
}
glutPostRedisplay();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// drawMap2D();
drawRays2D();
// drawPlayer();
glutSwapBuffers();
}
void ButtonDown(unsigned char key, int x, int y)
{
if (key == 'q') {Keys.q = 1;}
if (key == 'd') {Keys.d = 1;}
if (key == 'z') {Keys.z = 1;}
if (key == 's') {Keys.s = 1;}
glutPostRedisplay();
}
void ButtonUp(unsigned char key, int x, int y)
{
if (key == 'q') {Keys.q = 0;}
if (key == 'd') {Keys.d = 0;}
if (key == 'z') {Keys.z = 0;}
if (key == 's') {Keys.s = 0;}
glutPostRedisplay();
}
void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
gluOrtho2D(0, 1024, 512, 0);
px=300; py=300; pdx = cos(pa)*5; pdy = sin(pa)*5;
}
void resize(int w, int h)
{
glutReshapeWindow(1024, 512);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(1024, 510);
glutInitWindowPosition(200, 200);
glutCreateWindow("New Window");
init();
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutKeyboardFunc(ButtonDown);
glutKeyboardUpFunc(ButtonUp);
glutMainLoop();
return 0;
}
makefile 非常简单
CC = gcc
CFLAGS = -Wall -Wextra -std=c99
LDFLAGS = -lglfw -lGL -lm -lglut -lGL -lGLU
SRCS = raycaster.c
OBJDIR = OBJs
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
EXEC = raycaster
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) $(OBJS) $(LDFLAGS) -o $(EXEC)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(EXEC)
我在互联网上搜索过,但我似乎只找到解决鱼眼效果的解决方案,而不是我遇到的问题
我现在没有太多时间来编译和查看代码(如果我记得的话,明天可能会这样做),但似乎在修复鱼眼错误的同时,您又将其逆转了。希望这有帮助。