Skip to main content
gamedev.net
🔒 Locked

Raycasting Help ...

Started by fpsgamer May 28, 2006 at 12:03 PM 2 replies 900+ views
Original Post
fpsgamer
fpsgamer
I am following a raycasting tutorial and I have one slight confusion. In the first for-loop the author is scanning each vertical line in the camera plane. In the loop header he has the condition "x < w" but "w" is never defined. Is "w" supposed to be the magnitude of the camera plane? Here is the code from the tutorial:

/*
Copyright (c) 2004, Lode Vandevenne
All rights reserved.
*/

#include <cmath>
#include <cstdlib> //for random numbers rand();
#include <SDL/SDL.h>
#include "QuickCG.h"
#include "Q3Dmath.h"
using namespace std;
template <typename T0, typename T1>
inline T0 pow(T0 a, T1 b){return pow(a, T0(b));} 
////////////////////////////////////////////////////////////////////////////////
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//                           PUT CODE BELOW HERE                              //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
////////////////////////////////////////////////////////////////////////////////

#define mapWidth 24
#define mapHeight 24

int worldMap[mapWidth][mapHeight]=
{
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1,
    1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1,
    1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
};

Scalar posX = 22, posY = 12;  //x and y start position
Scalar dirX = -1, dirY = 0; //initial direction vector
Scalar planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane

Scalar time = 0; //time of current frame
Scalar oldTime = 0; //time of previous frame

int main(int argc, char *argv[])
{
    screen(512, 384, 0, "Raycaster");
    while(!done())
    {
        SDL_Delay(5); //sacrifice 5 milliseconds per frame to free some CPU time
        for(int x = 0; x < w; x++)
        {           
            //calculate ray position and direction 
            Scalar cameraX = 2 * x / Scalar(w) - 1; //x-coordinate in camera space         
            Scalar rayPosX = posX;
            Scalar rayPosY = posY;
            Scalar rayDirX = dirX + planeX * cameraX;
            Scalar rayDirY = dirY + planeY * cameraX;
            //which box of the map we're in  
            int mapX = int(rayPosX);
            int mapY = int(rayPosY);
           
            //length of ray from current position to next x or y-side
            Scalar sideDistX;
            Scalar sideDistY;
           
             //length of ray from one x or y-side to next x or y-side
            Scalar deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
            Scalar deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
            Scalar perpWallDist;
           
            //what direction to step in x or y-direction (either +1 or -1)
            int stepX;
            int stepY;
                      
            int hit = 0; //was there a wall hit?
            int side; //was a NS or a EW wall hit?
            //calculate step and initial sideDist                                 
            if (rayDirX < 0)
            {
                stepX = -1;
                sideDistX = (rayPosX - mapX) * deltaDistX;
            }
            else
            {
                stepX = 1;
                sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
            }          
            if (rayDirY < 0)
            {
                stepY = -1;
                sideDistY = (rayPosY - mapY) * deltaDistY;
            }
            else
            {
                stepY = 1;
                sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
            }
            //perform DDA       
            while (hit == 0)
            {                  
                //jump to next map square, OR in x-direction, OR in y-direction          
                if (sideDistX < sideDistY)
                {
                    sideDistX += deltaDistX;
                    mapX += stepX;
                    side = 0;
                }
                else
                {
                    sideDistY += deltaDistY;
                    mapY += stepY;
                    side = 1;
                }              
                //Check if ray has hit a wall           
                if (worldMap[mapX][mapY] > 0) hit = 1;             
            } 
            //Calculate distance projected on camera direction (oblique distance will give fisheye effect!)      
            if (side == 0)
            perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
            else
            perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
            
            //Calculate height of line to draw on screen           
            int lineHeight = abs(int(h / perpWallDist));       
           
            //calculate lowest and highest pixel to fill in current stripe
            int drawStart = -lineHeight / 2 + h / 2;
            if(drawStart < 0)drawStart = 0;
            int drawEnd = lineHeight / 2 + h / 2;
            if(drawEnd >= h)drawEnd = h - 1;  
                
            //choose wall color                     
            ColorRGB color;
            switch(worldMap[mapX][mapY])
            {
                case 1:  color = RGB_Red;    break; //red
                case 2:  color = RGB_Green;  break; //green
                case 3:  color = RGB_Blue;   break; //blue
                case 4:  color = RGB_White;  break; //white
                default: color = RGB_Yellow; break; //yellow
            }
             
            //give x and y sides different brightness
            if (side == 1) {color = color / 2;}           
           
            //draw the pixels of the stripe as a vertical line                                                                       
            verLine(x, drawStart, drawEnd, color);
        }    
        //timing for input and FPS counter
        oldTime = time;
        time = getTime();
        Scalar frameTime = (time - oldTime) / 1000.0; //frameTime is the time this frame has taken, in seconds       
        fprint(1.0 / frameTime); //FPS counter
        redraw();
        cls();

        //speed modifiers
        Scalar moveSpeed = frameTime * 5.0; //the constant value is in squares/second
        Scalar rotSpeed = frameTime * 3.0; //the constant value is in radians/second     
        readKeys();
        //move forward if no wall in front of you     
        if (inkeys[SDLK_UP])
        {
            if(worldMap[int(posX + dirX * moveSpeed)][int(posY)] == false) posX += dirX * moveSpeed;
            if(worldMap[int(posX)][int(posY + dirY * moveSpeed)] == false) posY += dirY * moveSpeed;
        }
        //move backwards if no wall behind you       
        if (inkeys[SDLK_DOWN])
        {
            if(worldMap[int(posX - dirX * moveSpeed)][int(posY)] == false) posX -= dirX * moveSpeed;
            if(worldMap[int(posX)][int(posY - dirY * moveSpeed)] == false) posY -= dirY * moveSpeed;
        }   
        //rotate to the right   
        if (inkeys[SDLK_RIGHT])
        {
            //both camera direction and camera plane must be rotated
            Scalar oldDirX = dirX;
            dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);
            dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);
            Scalar oldPlaneX = planeX;
            planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);
            planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);
        }
        //rotate to the left       
        if (inkeys[SDLK_LEFT])
        {
            //both camera direction and camera plane must be rotated         
            Scalar oldDirX = dirX;
            dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);
            dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);
            Scalar oldPlaneX = planeX;
            planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);
            planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);
        }       
    }      
}  

direct link: http://student.kuleuven.be/~m0216922/CG/code/raycaster_flat.cpp
Rockoon1
Rockoon1
My guess is that its the screen width :)
fpsgamer
fpsgamer
It seems you are correct. Must be defined somewhere in thoes SDL libraries. Thanks for making me feel silly :)
Rockoon1
Rockoon1
The code seems to enforce a 90 degree field of view. Its probably best to take control of it.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.