Got some weird behavior here. Let me explain, I’ll try to be brief.
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(){
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.