Occlusion result, or lack thereof. [Solved]

Got some weird behavior here. Let me explain, I’ll try to be brief. :wink:



In the solar systems I have in my game I have a lens flare for each sun and there’s a check made if the sun is occluded by planets or the player’s ship.



It works perfect with solar systems with only one sun.



In binary systems, it goes out of whack. Each sun correctly occludes the other, as expected, but not so for the planets or the player’s ship. The code is the same. The method take a geometry (the sun with the flare attached to it) and, using a Ray, I iterate through “System Body” geometries contained in the scene node. At the first collision it returns true, else false.



Sometimes there is a collision between a sun and a planet but when that happens it’s never right. It’s like the planet geometry was much, much smaller and at the wrong place. :s



In the update of the scene:

[java]

// Check flare occlusion.

if (gMgrs.getGameSettings().isUseLensFlare()) {

if (checkFlareOccluded(primaryStarGeo)) {

flarePrimary.turnOff();

} else {

flarePrimary.update();

}

if (star.hasCompanion()) {

if (checkFlareOccluded(companionStarGeo)) {

flareCompanion.turnOff();

} else {

flareCompanion.update();

}

}

}

[/java]



The occlusion check method:

[java]

/**

  • Checks if given geometry is occluded by a “System Body” or the player’s ship.
  • @param geo The geometry to verify the occlusion of.
  • @return True if occluded, false if not.

    */

    private boolean checkFlareOccluded(Geometry geo) {

    Ray shooter = new Ray(geo.getWorldTranslation(), getViewport().getCamera().getLocation().normalize());

    shooter.setLimit(geo.getWorldTranslation().distance(getViewport().getCamera().getLocation()) * 2);

    CollisionResults colRes = new CollisionResults();

    for (Geometry g : sceneNode.getGeometryNamed(“System Body”)) {

    if (g == geo) {

    continue;

    }

    g.collideWith(shooter, colRes);

    if (colRes.size() > 0)

    break;

    }

    if (colRes.size() == 0) {

    playerShip.collideWith(shooter, colRes);

    }

    if (colRes.size() > 0) {

    System.out.println(“Collision FROM” +

    " sun ID : " + geo.getUserData(“ID”) + " TO ");

    for (Iterator i = colRes.iterator() ; i.hasNext():wink: {

    CollisionResult cr = (CollisionResult) i.next();

    System.out.println(cr.getGeometry().getUserData(“Class”) + " ID " + cr.getGeometry().getUserData(“ID”) + “n”);

    if (cr.getGeometry().getUserData(“Class”).equals(“Planet”)) {

    continue;

    }

    // System.out.println(colRes.getCollision(0).getGeometry().getUserData(“Class”) + " ID " + colRes.getCollision(0).getGeometry().getUserData(“ID”));

    }

    return true;

    } else {

    return false;

    }

    }

    [/java]



    Planet geometry location is based on the radius of the sun (or the sum of orbits + the radius of the suns for binary systems). Except for that, the geometry scaling is the same.



    Based on camera angle and occlusion of the suns toward each other the Ray casting is right. As soon as a sun goes behind the other its lens flare is turned off.



    The code looks sound, but I’m thinking I’m overlooking something.



    Help appreciated.



    Thanks. :smiley:

This looks very strange to me:

Ray shooter = new Ray(geo.getWorldTranslation(), getViewport().getCamera().getLocation().normalize());



How is the location of the camera related to ray direction? I presumed from other code that your camera actually flies around in which case getLocation().normalize() isn’t going to have anything to do with direction.

I had the same thought too and I changed it to getViewport.getCamera().getDirection() but after doing that there we no collision at all in any kind of solar system.



I’ll revisit this…

Given that you start at the body in question, you probably want the direction of object → camera. Or start at camera and go camera->object… either way, I think the Ray isn’t correct.

Changed the ray casting to:

[java]

Ray shooter = new Ray(geo.getWorldTranslation(), getCamera().getWorldCoordinates(new Vector2f(gMgrs.getScreenWidth() * .5f, gMgrs.getScreenHeight() * .5f), 0));

[/java]



Getting the same behavior. Works fine in unary systems, but no collision with planets in binary systems. :S



Edit: It’s actually the same as the OP. The collided geometry seems “tiny” compared to the planet geometry sphere.

@pspeed said:
Given that you _start_ at the body in question, you probably want the direction of object -> camera. Or start at camera and go camera->object... either way, I think the Ray isn't correct.

It has to be from geometry to camera. Order is important.

Either way, your direction is wrong. You direction should be (camera.location - obj.location) normalized.

1 Like

Ah goddamn it. That was dumb of me actually. You’re completely right. That vector is totally wrong.



To my defense I had that method made before I actually understood how vector addition/subtraction worked… I’ll repost in a bit w/ results. :wink:

As expected, it works flawlessly. :smiley:



Thanks Paul.