Jump to content
  • Advertisement
Sign in to follow this  
JNT

Non-tile based raycasting problems

This topic is 3607 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there! I'm currently working on a more advanced form of raycasting that is free from the restrictions of the grid based map. Basically the renderer works with lines and intersections, where a wall only consists of two arbitrary points in a coordinate system. Anyhow, I've run into problems. Some walls do not get drawn properly (they tear). Some of you have more experience than I do in this field, so I figured that someone might know what this problem is caused by? The code below is the full code for the renderer:
float32 ray_angle = camera->GetViewAngle() -(camera->GetFOV() /2),
  ray_angle_increment = camera->GetFOV() /i2Screen.GetWidth() *quality_loss,
  screen_distance = camera->GetScreenDistance(),
  x1 = camera->GetPosition().x,
  y1 = camera->GetPosition().y; //camera coordinates
  
for (uint32 x = 0; x < i2Screen.GetWidth(); x += quality_loss, ray_angle += ray_angle_increment){
  
  ray_angle = i2::ForceInterval(ray_angle, 0, 360);
  float32 x2 = (cos(i2::DegreesToRadians(ray_angle)) *screen_distance) +x1,
    y2 = (sin(i2::DegreesToRadians(ray_angle)) *screen_distance) +y1; //screen-ray intersection coordinates
  
  for (uint64 i = 0; i < map->GetSize(); ++i){
    
    i2::MapRC::Wall * wall = &map->GetWall(i);
    float32	x3 = wall->a.x,
      y3 = wall->a.y,
      x4 = wall->b.x,
      y4 = wall->b.y; //wall coordinates
      
    float32 div = ((x1-x2)*(y3-y4) - (y1-y2)*(x3-x4));
    float32 wix = ((x1*y2 - y1*x2)*(x3-x4) - (x1-x2)*(x3*y4-y3*x4)) / div,
      wiy = ((x1*y2 - y1*x2)*(y3-y4) - (y1-y2)*(x3*y4-y3*x4)) / div; //wall-ray intersection coordinates
      
    if (wix >= x3 && wix <= x4 && wiy >= y3 && wiy <= y4){ //intersection is in wall interval
      
      uint8 rq = 0; //ray quadrant
      if (ray_angle >= 0.f && ray_angle < 90.f) { rq = 1; }
      else if (ray_angle >= 90.f && ray_angle < 180.f) { rq = 2; }
      else if (ray_angle >= 180.f && ray_angle < 270.f) { rq = 3; }
      else if (ray_angle >= 270.f && ray_angle < 360.f) { rq = 4; }
      
      float32 a = wix -x1,
        b = wiy -y1;
      
      uint8 wiq = rq; //wall intersection quadrant
      if (a > 0.f){
        if (b > 0.f) { wiq = 1; }
        else if (b < 0.f) { wiq = 4; }
      } else if (a < 0.f){
        if (b > 0.f) { wiq = 2; }
        else if (b < 0.f) { wiq = 3; }
      } else if (a == 0.f){
        if (b > 0.f) { wiq = 2; }
        else if (b < 0.f) { wiq = 4; }
      } else if (b == 0.f) {
        if (a > 0.f) { wiq = 1; }
        else if (a < 0.f) { wiq = 3; }
      }
      
      if (rq == wiq){ //ray quadrant must be same as wall intersection quadrant
        float32 c = sqrt((a*a) +(b*b)) *cos(i2::DegreesToRadians(camera->GetViewAngle() -ray_angle)); //distance to intersection
        uint32 h = static_cast<uint32>(wall->height /c); // wall height on-screen
        byte color = static_cast<byte>(BYTE_MAX /(c +1.f)); //shade pixels
    
        i2Screen.Fill(i2::Rectangle(x, (i2Screen.GetHeight() -h) /2, quality_loss, h), pixel32(i2::Color(color, color, color))); //draw pixels on screen
      }
    }
  }
}
I should add that I suspect that the problem occurs in the section where I'm determining what quadrant (relative to the player/camera) the ray and the intersection are located in, i.e. somewhere between
uint8 rq = 0; //ray quadrant
and
if (rq == wiq){ //ray quadrant must be same as wall intersection quadrant
As you can see, I'm using a few user defined types, but I think they're named clearly enough for you to understand what they are. If not, don't hesitate to ask. Thank you for your time! /Jonathan [Edited by - JNT on July 18, 2008 3:58:05 PM]

Share this post


Link to post
Share on other sites
Advertisement
Sounds like you are doing something like doom but a little bit different.
Doom wasn't restricted to grid too. It used arbitary shaped sectors built of lines (polygons).
It might be worth for you to look at the doom source codes!

Share this post


Link to post
Share on other sites
Correct me if I'm wrong, but I don't think that the Doom engine is a raycaster at all, so Carmack's way of solving this problem probably won't apply to my situation.

I wish I could submit images on this forum (can you? am I missing something?), since I think it would clearly show what I mean by "tearing".

Share this post


Link to post
Share on other sites
Doom was using raycasting !
It sent rays through each screen column and calculated the intersection between rays and sectors/lines. Its advantage over wolfenstein was that it wasnt restricted to a grid and could produce arbitary looking levels (but with no room over room).

Share this post


Link to post
Share on other sites
Huh. I distinctly remember reading that the Doom engine wasn't a raycaster, but of course, I haven't read the source code until recently so I really couldn't tell one way or the other.

I just checked Wikipedia about the Doom engine and it seems like it checks intersections the same principal way my renderer does, just as you guys stated earlier. I looked around a bit in the Doom source but I didn't really find anything useful for my particular problem. It seems that the intersection problem is solved differently, circumventing my predicament all together. Then again, I only skimmed through the Doom code...

Share this post


Link to post
Share on other sites
To anyone interested, I found what was causing the walls to tear:


if (wix >= x3 && wix <= x4 && wiy >= y3 && wiy <= y4){ //intersection is in wall interval


The problem concerned inaccuracies in the floating-point values wix and wiy. I solved the problem by adding or subracting a small, near zero value to the floating-point variables, like so:


static const float32 ROUND = 0.000001f;
if (wix +ROUND >= x3 && wix -ROUND <= x4 && wiy +ROUND >= y3 && wiy -ROUND <= y4){


Still, thanks for your time and help!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!