Calculating ceiling and floor textures in a raycaster
StevenVI

Well, I decided to start working on my raycaster idea again. I remember a little while after I started working on mine there was some sort of craze around here with them, so I figure by now everyone's written their own Duke3D clone and I'm way behind the times...

But anyways, I was wondering if anyone would share the math involved for texturing the floor and ceiling. I can't seem to figure out the math on this one. I have some triangles written down on paper with two similar triangles ... but I'm not sure if they're related or what and I'm babbling now.

So if anyone could explain the formulas (or just tell them to me :P) I'd appreciate it.

Thanks!

23yrold3yrold

I never actually implemented it in mine, but the tutorial we were all referencing during the craze (this one) shows how to do it. Most of what I learnt about the raycasting implementation I got from there ...

StevenVI

233yrold3yrold: Thanks, I do have that tutorial in my reference list. I looked over the pages on texturing the floors, and it was pretty vague and I couldn't quite understand it. I have an "almost-working" implementation at the moment. It moves left and right with the camera properly, but not forward or backwards (the product of a couple guesses in math and stealing code from another program which I wasn't up to disecting in it's entirety.)

This is what I have (the decimal function returns the decimal portion of a floating point number):

for(row=bot+1; row<SCREEN_H; row++) {
  // get ratio of viewer height to pixel height
  float ratio = player_height/(row-(SCREEN_H/2));

  // get distance to visible pixel
  float distance = ratio*VIEWPLANE_DISTANCE/my_cos(i*ANGLE_BETWEEN_RAYS-FOV2);

  // rotate distance to ray angle
  float x = decimal((-distance * my_sin(ray<i>.angle))+player_x)*floor_texture->w;
  float y = decimal((distance * my_cos(ray<i>.angle))+player_y)*floor_texture->h;

  putpixel(buffer,i,row,getpixel(floor_texture,(int)x,(int)y));
}

(And please no kiddies commenting on the fact that it's not optimised. That's for once it works properly.) The x/sin and y/cos is from the other program I looked at. I tried a bunch of combinations on the x= and y= lines and none of them worked (and understanding the math would most definitely make this baby work for me, maybe if I just sat here and thought for another few minutes...)

Roman Tech.

This is how I do my floor casting:

1 
2/* this is how to find rayangle */
3float column_angle = atan( (float) ( column - (SCREEN_WIDTH/2) ) / SCREEN_HEIGHT);
4float rayangle = player.angle+column_angle;
5/**/
6 
7for (int row=bot; row<=SCREEN_H-1; ++row)
8{
9distance = ((float)PLAYER_HEIGHT / (row-SCREEN_H/2) )* PROJ_PLANE * cos_column_angle;
10
11x = -distance * (sin_rayangle);
12y = distance * (cos_rayangle);
13 
14x+=player.x;
15y+=player.y;
16
17tile = map.floor[x>>6][y>>6].tile;
18 
19/* Might need this - it will crash if 'tile' is out of bounds
20if(x>=MAP_WIDTH*64 || x<0) tile = 2;
21if(y>=MAP_HEIGHT*64 || y<0) tile = 2;
22*/
23
24 putpixel(buf,column,row,getpixel(tex,x&63,y&63);
25 
26
27}

Krzysztof Kluczek

I'm rendering floors the same way as in code posted above, but still this is really bad approach to rendering floors. Most FPPs (Doom, Duke3d) were rendering floors in horizontal lines. This will spare you per-pixel division since it's essentially the same as rendering vertical walls then. Anyway, mixing column and row rendering doesn't seem to be easy.

Kitty Cat

You should actually draw all your floors first (far to near), then walls (near to far with some kind of per-ray z-buffer, or far to near without).

Thread #374305. Printed from Allegro.cc