Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Ray casting in 2D (Not related to SFML)  (Read 5339 times)

0 Members and 1 Guest are viewing this topic.

awsumpwner27

  • Newbie
  • *
  • Posts: 27
    • View Profile
Ray casting in 2D (Not related to SFML)
« on: January 21, 2013, 03:28:16 am »
I have, for a long time, had a problem. I often found myself looking up how to do ray casting, I might find something, but it would never really help, and everything I had seen looked awfully limited. The environment where rays were being cast had to be a grid because it depended on checking every square on the grid the ray intersected with along the way, and that meant that it would be slower if things were far apart. I also noticed a bizarre pattern of people only wanting to know what ray casting was in the context of rendering a 3D-looking environment. This was weird for me, because people seemed to ONLY refer to it that way, when it had quite a few more applications. Needless to say the internet was useless, and I worked on and developed my own method independently to find if a ray would intersect with a line. No grids, no binary searches. Just rays and lines and math.

Something still bothered me though. I thought it was pretty efficient as compared to some other methods, but I didn't know how efficient it was. I've seen other things ray cast, but I never knew how the did it, and I never knew if my method was better or not.

So, today, I present the algorithm in the form of C++ to programmers I think will be able to judge it based on their experiences with such things. It isn't optimized. (It will still check if the ray is pointing directly away from the line.) Also, the code contains some variation of a class that represents a 2D vector, so there really is no relation to SFML here. I'm asking here because I trust you folks to answer the question:

Is there a more efficient way to do what I've done here? (Not in regards to programming, more in regards to the math.):
#include <iostream>
#include <math.h>
using std::cout;
using std::endl;

//Define the behaviour of a 2D vector (geometry). How this works is mostly irrelevant.
class vec2 {
public:
vec2(float X, float Y){
x = X;
y = Y;
}
vec2 operator = (vec2 arg){
x = arg.x;
y = arg.y;
return *this;
}
vec2 operator * (float arg){
vec2 temp(0,0);
temp.x = x * arg;
temp.y = y * arg;
return temp;
}
vec2 operator + (vec2 arg){
vec2 temp(0,0);
temp.x = x + arg.x;
temp.y = y + arg.y;
return temp;
}
vec2 operator - (vec2 arg){
vec2 temp(0,0);
temp.x = x - arg.x;
temp.y = y - arg.y;
return temp;
}
vec2 operator * (vec2 arg){
vec2 temp(0,0);
temp.x = x * arg.x;
temp.y = y * arg.y;
return temp;
}
vec2 operator / (vec2 arg){
vec2 temp(0,0);
temp.x = x / arg.x;
temp.y = y / arg.y;
return temp;
}
float magnitude(){
return sqrt(x*x + y*y);
}
vec2 normal(){
float mag = this->magnitude();
return vec2(x/mag, y/mag);
}
float x,y;
};
//That's what most of the code is, and I haven't even gotten into the important part.

//This is what makes it happen *IMPORTANT THINGS START HERE*
void raycast(bool * retBool, float * retDis, vec2 * retVec, float Angle, vec2 Origin, vec2 PointA, vec2 PointB){
float aA, bA;
float factor;
vec2 pos(0,0);
aA = atan2(PointA.y, PointA.x);
bA = atan2(PointB.y, PointB.x);
factor = (Angle - aA)/(bA - aA);
*retBool = factor >= 0 && factor <= 1;
*retVec = (PointB-PointA)*factor + PointA;
*retDis = sqrt((retVec->x)*(retVec->x)+(retVec->y)*(retVec->y));
}
//That's it


int main(){
float distance;
bool hit;
vec2 pos(0,0);

raycast(&hit, &distance, &pos, 45.0 / 180.0 * 3.14159, vec2(0,0), vec2(1, 3), vec2(3, 1));

cout<<hit<<endl;
cout<<distance<<endl;
cout<<pos.x<<", "<<pos.y<<endl;

return 0;
}

Of course, I doubt you'll just get it if I post the code, so I'll give a little explanation of how it works in the form of an image. I don't guarantee it'll help because I'm apparently bad at explanations.

That probably didn't help much.

Well, if you think you can help me, feel free to post about it, I'd love to hear it.

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Ray casting in 2D (Not related to SFML)
« Reply #1 on: January 21, 2013, 03:47:44 am »
That type of graph is common in linear algebra, I hadn't seen one in months after I won the course in my uni.

That aside your algorithm is pretty much complete in that aspect, you could try skipping the sqrt whenever possible (there are cases where it matters not whether you have the squared magnitude or not), but overall all it could possibly lack is inlining if you need your vector class very often.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Ray casting in 2D (Not related to SFML)
« Reply #2 on: January 21, 2013, 04:08:19 am »
So it seems you've gotten a working line to line intersection algorithm. I guess one can call it also ray casting, but as you've noticed on your own, people often use ray casting for 3D scenes. (Btw. Box2D has also a ray caster/line to line intersection test implemented in its test-bed.)

Since I'm a curious person, what applications for your algorithm are you think about here? Because depending on the task, there might be faster ways (e.g. scan line algorithms).

Ray casting is mostly referred to 3D, because it makes more sense to shoot rays into a 3D scene and 'watch' them bounce of objects that then give 2D image of the 3D scene, rather than letting rays bounce of lines.
Besides that a good ray-cast render produces very realistic images and being able to have a very good ray-cast render in real-time is sometimes held as the holy grail of 3D game programming, thus it's quite a popular topic.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/