Omnimaga

Calculator Community => Casio Calculators => Topic started by: Spenceboy98 on December 28, 2012, 01:21:11 pm

Title: Need Help with Prizm Raycaster
Post by: Spenceboy98 on December 28, 2012, 01:21:11 pm
I'm making a raycaster based off of this (http://www.permadi.com/tutorial/raycast/index.html), 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.
Title: Re: Need Help with Prizm Raycaster
Post by: Spenceboy98 on February 08, 2013, 09:03:44 pm
*BUMP*
Can anyone help?
Title: Re: Need Help with Prizm Raycaster
Post by: fb39ca4 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 (http://lodev.org/cgtutor/raycasting.html). 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.
Title: Re: Need Help with Prizm Raycaster
Post by: DJ Omnimaga 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.
Title: Re: Need Help with Prizm Raycaster
Post by: fb39ca4 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.
Title: Re: Need Help with Prizm Raycaster
Post by: DJ Omnimaga 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.