Ray Casting Problems

Discuss issues specific to the Flash/AS3 port of Box2D
Doughnuts
Posts: 5
Joined: Thu Aug 30, 2012 12:35 am

Ray Casting Problems

Postby Doughnuts » Thu Aug 30, 2012 1:39 am

Okay, so I may be relatively new to Box2D, but I A. have coded before and B. have gotten this far without too many problems... But I can't for the life of me figure out what is going wrong :lol:

Basically, I've started making a platform game for my dissertation next year - I've got dynamically creating levels, player movement, weapons and a lot of other stuff planned/sorted sorted so far - one of the weapons or utilities is a 'laser creator' type thing - you fire one pellet, it sticks to a surface, you fire another pellet, and it sticks to another surface, and a laser is created from the first to the second.
Image
It's literally done by getting the location of each of the bodys and doing a ray-cast from one to the other.

In the function specified into the raycast, it checks what type of object the hit item is, and at the moment, (I've cut all the code back to try and find the problem) it simply draws a circle where it hits (red - block, green - laser reciever, blue - sensor, white - player) and if the object is a block, it returns 0, if anything else, it returns 1. Afterwards it joins all of the points it hits with a line, stopping at a block it hits.

This works most of the time... but more than sometimes, stuff like this happens;
Image
the ray-cast travels from left to right, so it should hit the fist object, make a blue circle, continue, hit the second object, draw a red circle, stop.
instead, it doesn't hit the first two, hits the third, draws a red dot, CONTINUES (this is what confuses me the most) and hits the end.
I've put a trace in the function and it doesn't even recall the first two objects at all...
I recently made the raycast fire every frame (to check to see if the ray was fired the same place it would do the same thing, or whether it wouldn't) - it does the same thing while it's in the same position.

after testing (and testing) it seems to happen with certain objects, from certain positions, often when objects are next to each-other, but what happens don't seem to have too much of a patter (which seems to be no help to me).
more examples:
Image
Image

Here is the function for the raytrace, I can post more code, but you'll have to let me know what else you need to be of more help, because it is in all different places in different classes and whatnot

Code: Select all

private function MakeLaserReturn(fixture:b2Fixture,point:b2Vec2,normal:b2Vec2,fraction:Number):Number
      {
         var hititem:Object = fixture.GetBody().GetUserData();
         //trace(fixture.GetBody().GetUserData());
         if (hititem is PlayerActor)
         {
            temparray.push(point);
            drawCircle(point, 0xffffff);
            return 1;
         }else if (hititem is PlayerActorWheel)
         {
            temparray.push(point);
            drawCircle(point, 0xffffff);
            return 1;
         }else if (hititem is BulletActor)
         {
            temparray.push(point);
            drawCircle(point, 0x00ff00);
            return 1;
         }else if (hititem is LaserReceiver)
         {
            temparray.push(point);
            drawCircle(point, 0x0000ff);
            return 1;
         }else if (hititem is PlatTileActor)
         {
            temparray.push(point);
            drawCircle(point, 0xFF0000);
            return 0;
         }
         return 0;
      }


I was going to post the swf so you could have a little play with it, but it wouldn't let me attach it :cry:

It's probably something really stupid I've done on my part, but this time around, whether it is or isn't, I can't figure out what it is without somebody else's help. :?

Thanks in advance, hope you can help ;)

irresistible force
Posts: 1991
Joined: Tue Jun 24, 2008 8:25 pm
Location: Tokyo
Contact:

Re: Ray Casting Problems

Postby irresistible force » Thu Aug 30, 2012 3:55 am

The usual way to find the closest thing hit by the ray is to return the fraction value from the callback (not 1), and use the most recent intersection as the result. Returning the fraction is like cutting the ray off at that point so that the callback doesn't bother any more about things that are further away.

However since you have the exception of the sensor, you would want to return 1 for that case. Something like this I think:

Code: Select all

if ( it's a sensor ) {
    add sensor to list of sensors hit; //could be many
    return 1;
}
else {
    last hit thing = this thing; //only need one
    return fraction;
}

Doughnuts
Posts: 5
Joined: Thu Aug 30, 2012 12:35 am

Re: Ray Casting Problems

Postby Doughnuts » Thu Aug 30, 2012 4:42 am

irresistible force wrote:The usual way to find the closest thing hit by the ray is to return the fraction value from the callback (not 1), and use the most recent intersection as the result. Returning the fraction is like cutting the ray off at that point so that the callback doesn't bother any more about things that are further away.

However since you have the exception of the sensor, you would want to return 1 for that case. Something like this I think:

Code: Select all

if ( it's a sensor ) {
    add sensor to list of sensors hit; //could be many
    return 1;
}
else {
    last hit thing = this thing; //only need one
    return fraction;
}


Thankyou for your help :)

So, just so I understand this (as I've seen many different variations) and don't have to bother anyone again
returning the fraction stops the ray in its tracks
returning 0 stops it.. (somwhere?)
returning 1 lets it pass

After removing 0's and putting fractions & 1's it seems the ray likes to pass through solid objects when travelling to the right, but is fine going left;
Image
Image

Is there a reason for this? :lol:

irresistible force
Posts: 1991
Joined: Tue Jun 24, 2008 8:25 pm
Location: Tokyo
Contact:

Re: Ray Casting Problems

Postby irresistible force » Thu Aug 30, 2012 1:50 pm

How can you get two red dots there? Only one solid thing should be hit, which is why you do
last hit thing = this thing; //only need one
...instead of adding to a list.

oh... I notice in your first code that you are drawing every fixture the algorithm visits while it is running. How about not drawing any hits inside the ray cast, and just drawing only the last hit thing, after the raycast has finished.

Doughnuts
Posts: 5
Joined: Thu Aug 30, 2012 12:35 am

Re: Ray Casting Problems

Postby Doughnuts » Fri Aug 31, 2012 12:58 am

irresistible force wrote:How can you get two red dots there? Only one solid thing should be hit, which is why you do
last hit thing = this thing; //only need one
...instead of adding to a list.

oh... I notice in your first code that you are drawing every fixture the algorithm visits while it is running. How about not drawing any hits inside the ray cast, and just drawing only the last hit thing, after the raycast has finished.


All the array does is add a point to a list, and join all of the points that it has hit and clear the list... for that reason (and from tests) the line stops when the ray stops

I added another array, just so i could make sure that stuff was being hit along the way - as you can see it is, but the ray is continuing (I DON'T GET IT :shock: :o)

(only one of the trace lines in the picture below is actually what it hits, the others are dupes because it does it every frame, still)
Image

(the other way, hits one item and stops, like it should. :lol: )
Image

I shouldn't make out that it is just a left to right issue, it does some strange things in other orientations too - such as this;

Image

Yeah, that's right, it hit the first block.. CONTINUED, MISSED the next block, then HIT the one after it :lol:

Thanks for all the help so far :) it's really mystifying me why such a thing (which I thought was going to be relatively easy to start with) is harder to get working than the reflection trigonometry I have to do after :lol: I haven't seen anyone else with so many strange problems :D

irresistible force
Posts: 1991
Joined: Tue Jun 24, 2008 8:25 pm
Location: Tokyo
Contact:

Re: Ray Casting Problems

Postby irresistible force » Fri Aug 31, 2012 3:10 am

The engine has to look at all the fixtures along the ray one by one, and there is no guarantee what order the fixtures will be given to your MakeLaserReturn function, so it tells you each one as it is discovered in some (effectively) random order. As it reports them to you, you are supposed to REPLACE the one you have recorded as the closest, then when the algorithm is finished you will be left with ONE that is the closest.
If you draw stuff while the algorithm is running, or you collect all the points it found along the way, you will get something like this diagram which shows all the nodes of a graph that a search algorithm visited while it was running:
http://www.waxinlyrical.com/AStarPathFi ... shot01.png
It's kinda interesting to see how it works, but if you don't care about all the intermediate processing then you would only want the final outcome of the algorithm.

Doughnuts
Posts: 5
Joined: Thu Aug 30, 2012 12:35 am

Re: Ray Casting Problems

Postby Doughnuts » Fri Aug 31, 2012 4:54 am

irresistible force wrote:The engine has to look at all the fixtures along the ray one by one, and there is no guarantee what order the fixtures will be given to your MakeLaserReturn function, so it tells you each one as it is discovered in some (effectively) random order. As it reports them to you, you are supposed to REPLACE the one you have recorded as the closest, then when the algorithm is finished you will be left with ONE that is the closest.
If you draw stuff while the algorithm is running, or you collect all the points it found along the way, you will get something like this diagram which shows all the nodes of a graph that a search algorithm visited while it was running:
http://www.waxinlyrical.com/AStarPathFi ... shot01.png
It's kinda interesting to see how it works, but if you don't care about all the intermediate processing then you would only want the final outcome of the algorithm.


AHHHH! My mistake, that wasn't how I envisioned it carrying out that task at all :lol:

So basically (correct me if I'm wrong), I'll need a few variables (or an array or something) which stores all of the information I require for calculations to carry out after it has done its algorithm (the object, point, normal and such) and every time it passes through the "if (hititem is PlatTileActor)" section, I need to replace whatever values are already stored with what they are that time around. From what I gather those values remaining at the end of the algorithm will be the point/object (whatever) I need?

Sorry for messing you about all this time ;)

irresistible force
Posts: 1991
Joined: Tue Jun 24, 2008 8:25 pm
Location: Tokyo
Contact:

Re: Ray Casting Problems

Postby irresistible force » Fri Aug 31, 2012 9:26 pm

That's right.

For the sensors though, since the ray should continue through them you will actually have to collect them in a list if you want to know all the sensors the ray intersected.

Hmm... you will also need to go through the list of sensor hits after the algorithm has finished and remove all the ones that were further away than the point which eventually became the closest solid hit. Unfortunately you can't discard any sensors during the raycast because you don't yet know if they will be obscured until the closest solid hit has been decided.

Doughnuts
Posts: 5
Joined: Thu Aug 30, 2012 12:35 am

Re: Ray Casting Problems

Postby Doughnuts » Sat Sep 01, 2012 12:23 am

irresistible force wrote:That's right.

For the sensors though, since the ray should continue through them you will actually have to collect them in a list if you want to know all the sensors the ray intersected.

Hmm... you will also need to go through the list of sensor hits after the algorithm has finished and remove all the ones that were further away than the point which eventually became the closest solid hit. Unfortunately you can't discard any sensors during the raycast because you don't yet know if they will be obscured until the closest solid hit has been decided.


That's awesome! The ray works now :D Thankyou very much for this!

In that case, for the sensors I will have to collect the sensors, and their fractions, and check it against the last fraction of the last block it hit then.. right? or is there an easier way? =P


Return to “Flash”



Who is online

Users browsing this forum: Bing [Bot], Yahoo [Bot] and 3 guests