Author Topic: Need Help with Prizm Raycaster  (Read 6224 times)

0 Members and 1 Guest are viewing this topic.

Offline Spenceboy98

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 547
  • Rating: +59/-2
    • View Profile
Need Help with Prizm Raycaster
« on: December 28, 2012, 01:21:11 pm »
I'm making a raycaster based off of this, and for some reason, it isn't working right. I came here to ask because I know there are some raycasting experts here. :P

My Code:
Code: [Select]
#include "keyboard.hpp"
#include "color.h"
#include "display.h"
#include "keyboard_syscalls.h"
#include "math.h"
#include "stdlib.h"

void plot(int x0, int y0, int color) {
   char* VRAM = (char*)0xA8000000;
   VRAM += 2*(y0*LCD_WIDTH_PX + x0);
   *(VRAM++) = (color&0x0000FF00)>>8;
   *(VRAM++) = (color&0x000000FF);
   return;
}

void drawLine(int x1, int y1, int x2, int y2, int color) {
    signed char ix;
    signed char iy;

    // if x1 == x2 or y1 == y2, then it does not matter what we set here
    int delta_x = (x2 > x1?(ix = 1, x2 - x1):(ix = -1, x1 - x2)) << 1;
    int delta_y = (y2 > y1?(iy = 1, y2 - y1):(iy = -1, y1 - y2)) << 1;

   plot(x1, y1, color);
    if (delta_x >= delta_y) {
        int error = delta_y - (delta_x >> 1);        // error may go below zero
        while (x1 != x2) {
            if (error >= 0) {
                if (error || (ix > 0)) {
                    y1 += iy;
                    error -= delta_x;
                }                           // else do nothing
         }                              // else do nothing
            x1 += ix;
            error += delta_y;
            plot(x1, y1, color);
        }
    } else {
        int error = delta_x - (delta_y >> 1);      // error may go below zero
        while (y1 != y2) {
            if (error >= 0) {
                if (error || (iy > 0)) {
                    x1 += ix;
                    error -= delta_y;
                }                           // else do nothing
            }                              // else do nothing
            y1 += iy;
            error += delta_x;
            plot(x1, y1, color);
        }
    }
}

int PRGM_GetKey(){
  unsigned char buffer[12];
  PRGM_GetKey_OS( buffer );
  return ( buffer[1] & 0x0F ) * 10 + ( ( buffer[2] & 0xF0 ) >> 4 );
}

int playerh = 32;
int fov = 60;
int viewingangle = 45;
int playergridx = 2;
int playergridy = 2;
int playerunitx;
int playerunity;
int projectionh = 200;
int projectionw = 320;
int distance = 160/tan(30);
int column = 60/320;
int planemx = 160;
int planemy = 100;
int AngleInc = 1;
int XDisplacement;
int YDisplacement;
int correctdistance;
int sliceheight;
int Ax;
int Ay;
int Cx;
int Cy;
int Dx;
int Dy;
int Bx;
int By;
int Xa;
int Ya;
int Xb;
int Yb;
int DxA;
int DyA;
int CyA;
int CxA;
int liney;

int MapData[10][10] = {
{1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1}
};

int absolute(int n){
if(n < 0){
n = -n;
}
return n;
}
int main(){
XDisplacement = cos(viewingangle) * 10;
YDisplacement = sin(viewingangle) * 10;
playerunitx = 32 + (playergridx * 64);
playerunity = 32 + (playergridy * 64);
while(1){
int key = PRGM_GetKey();
if(key == KEY_PRGM_MENU) {  GetKey(&key); }
if(viewingangle <= 180 && viewingangle >= 0){
Ya = 64;
Ay = floor(playerunity / 64) * (64) - 1;
} else if(viewingangle <= 360 && viewingangle >= 181){
Ya = -64;
Ay = floor(playerunity / 64) * (64) + 64;
}
Ax = playerunitx + (playerunity - Ay) / tan(viewingangle);
Xa = 64 / tan(viewingangle);

Cx = Ax + Xa;
Cy = Ay + Ya;
CxA = floor(Cx / 64);
CyA = floor(Cy / 64);

playergridx = playerunitx/64;
playergridy = playerunity/64;

for(int w = 0; w < 10; w++){
if(MapData[CxA][CyA] == 1)
break;
CxA = floor(Cx / 64);
CyA = floor(Cy / 64);
Cx += Xa;
Cy += Ya;
}
Cx = floor(Cx / 64);
Cy = floor(Cy / 64);

if(viewingangle <= 270 && viewingangle >= 90){
Xb = 64;
Bx = floor(playerunity / 64) * (64) - 1;
} else if((viewingangle <= 89 && viewingangle >= 0) && (viewingangle <=360 && viewingangle >= 271)){
Xb = -64;
Bx = floor(playerunity / 64) * (64) + 64;
}
By = playerunity + (playerunitx - Bx) * tan(viewingangle);
Dx = Bx + Xb;
Dy = By + Yb;
DxA = floor(Dx / 64);
DyA = floor(Dy / 64);

for(int e = 0; e < 10; e++){
if(MapData[DyA][DxA] == 1)
break;
DxA = floor(Dx / 64);
DyA = floor(Dy / 64);
Dx += Xa;
Dy += Ya;
}
Dx = floor(Dx / 64);
Dy = floor(Dy / 64);
for(int i = 0; i < 320; i++){
if((absolute(playerunitx - Dx) / cos(viewingangle)) < (absolute(playerunitx - Cx) / cos(viewingangle))){
for(int j = -30; j < 30; j++){
correctdistance = (absolute(playerunitx - Dx) / cos(viewingangle)) * cos(j);
sliceheight = 64 / correctdistance * 277;
liney = 100 - (sliceheight / 2);
drawLine(i, liney, i, liney + correctdistance, COLOR_RED);
Bdisp_PutDisp_DD();
}
} else {
for(int j = -30; j < 30; j++){
correctdistance = (absolute(playerunitx - Cx) / cos(viewingangle)) * cos(j);
sliceheight = 64 / correctdistance * 277;
liney = 100 - (sliceheight / 2);
drawLine(i, liney, i, liney + correctdistance, COLOR_RED);
Bdisp_PutDisp_DD();
}
}
}
if(key == KEY_PRGM_UP){
playerunitx += XDisplacement;
playerunity += YDisplacement;
}
if(key == KEY_PRGM_DOWN){
playerunitx -= XDisplacement;
playerunity -= YDisplacement;
}
if(key == KEY_PRGM_LEFT){
viewingangle -= AngleInc;
}
if(key == KEY_PRGM_RIGHT){
viewingangle += AngleInc;
}
if(viewingangle > 360){
viewingangle = 0;
}
if(viewingangle < 0){
viewingangle = 360;
}
}
return 0;
}


The "for" loops used to be "while" loops, but the while loop would never break(something with that math is messed up if you can help), so I just changed it to a for loop, so that it would eventually break.

Another problem I am having is that when displaying the lines, it is going incredibly slow. Could anyone help with that?

I am using this raycaster as a learning example to myself, so that I will be able to make a raycaster in most any language. Any help would be appreciated.
« Last Edit: February 08, 2013, 08:55:00 pm by Spenceboy98 »
I like milk.

Offline Spenceboy98

  • LV7 Elite (Next: 700)
  • *******
  • Posts: 547
  • Rating: +59/-2
    • View Profile
Re: Need Help with Prizm Raycaster
« Reply #1 on: February 08, 2013, 09:03:44 pm »
*BUMP*
Can anyone help?
I like milk.

Offline fb39ca4

  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1749
  • Rating: +60/-3
    • View Profile
Re: Need Help with Prizm Raycaster
« Reply #2 on: February 08, 2013, 10:54:33 pm »
The reason your code might be going so slow is that you are calling the cosine function 64 (!) times per screen column (twice in line 176, and twice in the for loop starting at either line 177 or 186, times the 31 times the loop runs), or 20480 times per frame. Since viewingangle only changes once per frame, you can compute cos(viewingangle) once for the frame and store it in a variable. j does change throughout the frame, but cos(j) is only called for j from -30 to 30 so you can make a lookup table for those values.

You might want to take a look at this tutorial. The rendering is completely vector based, eliminating the need for trig functions during performance critical loops.

One last thing, in the future, you should put threads asking for programming help in the C language subforum.
« Last Edit: February 09, 2013, 12:33:18 am by t0xic_kitt3n »

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
Re: Need Help with Prizm Raycaster
« Reply #3 on: February 08, 2013, 11:04:59 pm »
*BUMP*
Can anyone help?
Runer112 might be able to help, but since he does TI-83 Plus stuff he might ignore the PRIZM section, so you might have to point him here. Likewise with the other raycaster experts here.

Offline fb39ca4

  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1749
  • Rating: +60/-3
    • View Profile
Re: Need Help with Prizm Raycaster
« Reply #4 on: February 09, 2013, 12:47:26 am »
You should avoid using short variables because it makes the code harder for others to understand. If you still wish to use them because they are easier to type, it would be great if you made a key with the meanings.

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
Re: Need Help with Prizm Raycaster
« Reply #5 on: February 09, 2013, 01:25:31 am »
One last thing, in the future, you should put threads asking for programming help in the C language subforum.

Actually the C section is TI-only. There is another one, but it's for computers.
« Last Edit: February 09, 2013, 01:26:05 am by DJ_O »