Can anyone give me a working example of raycasting in C++ using SDL2. I have tried different tutorials but none of them work. Example in below is my latest try. Expected result is that all the points(screen and obstacles) are static and dont move around, but the reality is the vision polygon that comes from calculating the intersections is weird shape and covers maximum 1/4 of the entire visible area. Oddly enough best result currently comes when i just add all the points(without intersection test) in correct order to the polygon point list. It almost is perfect, but the obvious comes out when at some point the polygon does some weird jumps it shouldnt. Can someone tell me where my math goes wrong?
typedef struct point{
float x;
float y;
float angle;
float T;
}Point;
typedef struct ray{
float x;
float y;
float angle;
}RAY;
Point* getIntesection(RAY ray, LINE segment){
float r_px = ray.x;
float r_py = ray.y;
float r_dx = cos(ray.angle);
float r_dy = sin(ray.angle);
// SEGMENT in parametric: Point + Delta*T2
float s_px = segment.a.x;
float s_py = segment.a.y;
float s_dx = segment.b.x - segment.a.x;
float s_dy = segment.b.y - segment.a.y;
// Are they parallel? If so, no intersect
float r_mag = sqrt(r_dx*r_dx + r_dy*r_dy);
float s_mag = sqrt(s_dx*s_dx + s_dy*s_dy);
if (r_dx / r_mag == s_dx / s_mag && r_dy / r_mag == s_dy / s_mag){
// Unit vectors are the same.
return NULL;
}
float T2 = (r_dx*(s_py - r_py) + r_dy*(r_px - s_px)) / (s_dx*r_dy - s_dy*r_dx);
float T1 = (s_px + s_dx*T2 - r_px) / r_dx;
// Must be within parametic whatevers for RAY/SEGMENT
if (T1<0) return NULL;
if (T2<0 || T2>1) return NULL;
Point* p = new Point;
p->x = r_px + r_dx*T1;
p->y = r_py + r_dy*T1;
p->T = T1;
return p;
}
void render_polygon(std::vector<Point*> polygon){
std::vector<Point*>::iterator it = polygon.begin();
Point* p = *it;
SDL_SetRenderDrawColor(gRenderer, 255, 0, 0, 255);
it++;
Point* t = p;
for (; it != polygon.end(); it++){
SDL_RenderDrawLine(gRenderer, t->x, t->y, (*it)->x, (*it)->y);
t = *it;
}
SDL_RenderDrawLine(gRenderer, t->x, t->y, p->x, p->y);
}
struct PointerCompare {
bool operator()(const Point* l, const Point* r) {
return l->angle < r->angle;
}
};
void raycast(Circle* c, std::set<SDL_Point*>* points, std::set<LINE*>* lines){
float centerX = (c->getCenterX());
float centerY = (c->getCenterY());
std::vector<Point*> polygon;
for (std::set<SDL_Point*>::iterator it = points->begin(); it != points->end(); ++it){
float angle = 0;
float tempdx = (*it)->x - centerX;
float tempdy = (*it)->y - centerY;
angle = atan2(tempdy,tempdx);
float dx = cos(angle);
float dy = sin(angle);
RAY r{ centerX, centerY ,angle};
Point* closest = NULL;
for (std::set<LINE*>::iterator it2 = lines->begin(); it2 != lines->end(); ++it2){
Point* D = getIntesection(r, *(*it2));
if (D == NULL) continue;
if (closest == NULL || D->T < closest->T) closest = D;
}
// if (closest == NULL){
// std::cout << "End" << std::endl;
// Point* t = new Point;
// t->x = p2.x;
// t->y = p2.y;
// t->angle = angle;
// polygon.push_back(t);
// }
// else{
if (closest == NULL) continue;
// std::cout << closest->x << " " << closest->y << std::endl;
closest->angle = angle;
polygon.push_back(closest);
// }
}
std::sort(polygon.begin(), polygon.end(), PointerCompare());
render_polygon(polygon);
}