校正鱼眼效果后光线投射图像出现扭曲

问题描述 投票:0回答:1

我正在尝试制作一个光线投射引擎,我已经修复了鱼眼效果(或者至少我认为我做得很准确),但现在我遇到了一个我似乎无法找到解决方案的问题;它看起来像:

an inverse fisheye effect

这是我的代码(光线投射本身发生在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)

我在互联网上搜索过,但我似乎只找到解决鱼眼效果的解决方案,而不是我遇到的问题

c opengl glut raycasting
1个回答
0
投票

我现在没有太多时间来编译和查看代码(如果我记得的话,明天可能会这样做),但似乎在修复鱼眼错误的同时,您又将其逆转了。希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.