Billboarding in Mario Kart style game..?

Started by
14 comments, last by robertgamble 20 years, 7 months ago
I''m working on a Mario Kart/"Mode 7" style game for the GP32 handheld, and &#106avascript (using &#106avascript as a "testbed" so that I don''t have to keep recompiling and uploading each time I change something). An old &#106avascript version is available here: http://www.elephantsneverforget.co.uk/mode7.asp (wasd to move around), it''s pretty slow but runs great &#111;n the GP32 (60fps at 40Mhz). At the moment you can drive around, the graphics look ok and there''s some collision detection. However I can''t work out how to draw cars/trackside objects etc.. At first I was drawing the car with raycasting.. E.g when I draw a pixel &#111;n the floor check if the ray coordinates match the car coordinates. But that was very slow, and didn''t seem like the <i>right </i> way of doing it... I was thinking that a better way would be to transform & project the coordinates and then draw the objects as point sprites. But I''m unsure of how to get this "in sync" with whats being drawn by the floorcaster. So what is the best way of doing this? Any help would be greatly appreciated.
Advertisement
Use the same perspective matrix you already use on the ''ground'' to transform the positions of the trackside objects.

Niko Suni

How do I actually work out the object coordinates though? Right now for the floor I''m just taking each pixel and then working out what should be drawn there...
Use the inverse of the matrix you''re using for the transformation between the screen-cordinates and the mode7-plane.

I suspect though that the current transformation isn''t in matrix form though so you have to translate it to that first.

good luck,
-claes
The said matrix consists from the perspective division, rotation in y-axis (camera direction in ground plane), and rotation in x-axis(the "camera height" angle).
You already have all this information when drawing the ground, just use the inverse to project any points from the "floor space" to screen space.

rgds Nik

PS. sorry for late reply

[edited by - Nik02 on September 4, 2003 3:15:05 PM]

Niko Suni

Just had a look at your algorithm. You''re doing it wrong, to get this fast you should only cast rays at the left and right sides of the screen, and then linearly interpolate texture coordinates across.
quote:Original post by Anonymous Poster
Just had a look at your algorithm. You''re doing it wrong, to get this fast you should only cast rays at the left and right sides of the screen, and then linearly interpolate texture coordinates across.


I''ve had a go at adding interpolation, for now I''m interpolating between the top of each column to the bottom like this:-

//get top of the floor areavar RAYX1 = (p.x + (FloorDist[100] * cos[angle]) - Sof)>>19;var RAYY1 = (p.y - (FloorDist[100] * sin[angle]) - Cof)>>19;//get bottom of the floor areavar RAYX2 = (p.x + (FloorDist[240] * cos[angle]) - Sof)>>19;var RAYY2 = (p.y - (FloorDist[240] * sin[angle]) - Cof)>>19;		//start drawing everythingdo{t=(i-100)/140;  //work out how the position in the lineRAYX=(RAYX1+ ((RAYX2-RAYX1) *t));   //get the interpolated coordsRAYY=(RAYY1+ ((RAYY2-RAYY1) *t));...carry on as normal 


...however it doesn''t seem to work too well. Take a look at http://www.elephantsneverforget.co.uk/mode7.htm, it''s very distorted. I think the line "t=(i-100)/140" might be wrong, but I''ve never done any interpolation before so I don''t know how to fix it..
Looks like you're interpolating top to bottom on screen coordinates, that's non-linear. Interpolation is linear left to right like this.

L-Ray       R-Ray \           /  ...........  <- Interpolated texture coordinates.   \       /     .......     \   /       .


Some dodgy old code of mine, it's setup for arbritrary size textures but changing it to a bit shift division is easy enough.

       for(int x=0; x<half_height;x++)        {            //far left floor ray              floor_dist = Math.abs(world_height/(Math.cos(floor_ray_ang              * radian_conv)));            sx = (floor_dist * Math.cos(left_ang));            sy = (floor_dist * Math.sin(left_ang));            //far right floor ray              floor_dist = Math.abs(world_height/(Math.cos(floor_ray_ang              * radian_conv)));            fx = (floor_dist * Math.cos(right_ang));            fy = (floor_dist * Math.sin(right_ang));            //interpolation values            dx = (fx-sx)/screen_width; dy = (fy-sy)/screen_width;            u = sx; v = sy;              //plot floor and ceiling              for (int j = 0; j<screen_width;j++)              {                  mu = (int)Math.abs((u+p1.getPlayerX()) % 200);                  mv = (int)Math.abs((v-p1.getPlayerY()) % 200);                  pixels[p_index++] = ((255<<24) | (Tex1[2][mu][mv]<<16) | (Tex1[2][mu][mv]<<8) | Tex1[0][mu][mv]<<0);                  pixels[p2_index++] = ((255<<24) | (Tex1[2][mu][mv]<<16) | (Tex1[2][mu][mv]<<8) | Tex1[0][mu][mv]<<0);                  u+=dx;v+=dy;              }             //increment angle             p2_index-=(screen_width*2); floor_ray_ang+=angstep;        }


Remember to keep divisions out of the innter loops.


[edited by - Neoteric on September 10, 2003 3:01:09 PM]
Neoteric, with that suggestion it''s interesting that you do in fact have two divisions in your inner loop. The % operator does a division. Use & and power-of-two sized maps instead
quote:Original post by Anonymous Poster
Neoteric, with that suggestion it's interesting that you do in fact have two divisions in your inner loop. The % operator does a division. Use & and power-of-two sized maps instead


Yeah I edited that in 5 seconds too late. The project needed any size textures for arrangements of tiling (which never got put in) so I was going to move the mods into a look up table, never got around to it.



[edited by - Neoteric on September 10, 2003 3:25:23 PM]

This topic is closed to new replies.

Advertisement