Tom
Tom

Reputation: 135

Java Trying to raycast in 2D

I have a class Shape which just contains vertices and functions to draw itself, a class Ray which is just a Line2D with more functions (which are irrelevant in this case), and a RayCaster which casts rays to every vertex of every shape, checks for intersections of the current ray with every line, then takes those intersections, selects the one closest to the RayCaster and creates a new Ray using that intersection point, and then draw that ray.

I've tried doing this 3 times and it's never quite right, some rays don't even appear at certain positions. I've tested my code for calculating the intersection point position and it works:

public static Point2D getLineIntersection(Line2D ray, Line2D segment) {
    if(ray.intersectsLine(segment)){
        double rx1 = ray.getX1(),
                ry1 = ray.getY1(),
                rx2 = ray.getX2(),
                ry2 = ray.getY2(),
                sx1 = segment.getX1(),
                sy1 = segment.getY1(),
                sx2 = segment.getX2(),
                sy2 = segment.getY2(),
                rdx = Math.abs(rx2 - rx1),
                rdy = Math.abs(ry2 - ry1),
                sdx = Math.abs(sx2 - sx1),
                sdy = Math.abs(sy2 - sy1),
                t1, t2,
                ix, iy;

        t2 = (rdx * (sy1 - ry1) + rdy * (rx1 - sx1)) / (sdx * rdy - sdy * rdx);
        t1 = (sx1 + sdx * t2 - rx1) / rdx;

        if(t1 > 0 && 1 > t2 && t2 > 0){
            ix = rx1 + rdx * t1;
            iy = ry1 + rdy * t1;
            return new Point2D.Float((int) ix, (int) iy);
        }else
            return null;
    }else
        return null;
}

So I've narrowed it down to where I cast rays, but I don't know what's wrong:

public void castRays(Graphics g, ArrayList<Shape> map){
    ArrayList<Ray> rays = new ArrayList<>();
    ArrayList<Point2D> vertices = new ArrayList<>();
    ArrayList<Line2D> segments = new ArrayList<>();

    //populate vertices and segments
    for(Shape s : map){
        vertices.addAll(Arrays.asList(s.getPoints()));
        segments.addAll(s.getLines());
    }

    for(Point2D v : vertices){
        Ray ray = new Ray(x, y, (int) v.getX(), (int) v.getY());
        ArrayList<Point2D> rayIntersects = new ArrayList<>();
        Point2D closestIntersect = null;

        for(Line2D s : segments)
            if(Utils.getLineIntersection(ray.getLine(), s) != null)
                rayIntersects.add(Utils.getLineIntersection(ray.getLine(), s));

        if(rayIntersects.size() > 0){
            for(int i = 0; i < rayIntersects.size(); i++){
                if(i == 0)
                    closestIntersect = rayIntersects.get(0);
                else{
                    if(Utils.getLineLength(new Line2D.Float(x, y, (int) closestIntersect.getX(), (int) closestIntersect.getY()))
                            > Utils.getLineLength(new Line2D.Float(x, y, (int) rayIntersects.get(i).getX(), (int) rayIntersects.get(i).getY())))
                        closestIntersect = rayIntersects.get(i);
                }
            }
        }
        if(closestIntersect != null)
            rays.add(new Ray(x, y, (int) closestIntersect.getX(), (int) closestIntersect.getY()));
    }

    for(Ray r : rays)
        r.render(g, Color.WHITE);
}

public static double getLineLength(Line2D line){
    double dx = Math.abs(line.getX2() - line.getX1()),
            dy = Math.abs(line.getY2() - line.getY1());
    return Math.sqrt(dx * dx + dy * dy);
}

If you need any more code, just ask but I think the problem is in the castRays function

Upvotes: 3

Views: 2803

Answers (1)

Tom
Tom

Reputation: 135

Found my mistake. Turns out I was wrong:

public static Point2D getLineIntersection(Line2D ray, Line2D segment) {
    if(ray.intersectsLine(segment)){
        double rx1 = ray.getX1(),
                ry1 = ray.getY1(),
                rx2 = ray.getX2(),
                ry2 = ray.getY2(),
                sx1 = segment.getX1(),
                sy1 = segment.getY1(),
                sx2 = segment.getX2(),
                sy2 = segment.getY2(),
                rdx = rx2 - rx1,
                rdy = ry2 - ry1,
                sdx = sx2 - sx1,
                sdy = sy2 - sy1,
                t1, t2,
                ix, iy;

        t2 = (rdx * (sy1 - ry1) + rdy * (rx1 - sx1)) / (sdx * rdy - sdy * rdx);
        t1 = (sx1 + sdx * t2 - rx1) / rdx;

        if(t1 > 0/* && 1 > t2 && t2 > 0*/){
            ix = rx1 + rdx * t1;
            iy = ry1 + rdy * t1;
            return new Point2D.Float((int) ix, (int) iy);
        }else
            return null;
    }else
        return null;
}

Upvotes: 4

Related Questions