16
Support / Code Snippet: Faking unlimited viewing distance
« on: December 29, 2013, 01:11:04 pm »
From time to time, I will post a few code snippets that proved useful while working on Armada. Maybe someone can use something for their own projects.
One problem that I ran into was the limited viewing distance. I thought that just setting the farplane value high enough would solve it, but there is actually a hard limit given by the hardware and/or OpenGl (not sure about that).
I wanted to have a planet that is far away but still visible (and approachable). While it would be possible to fake something with billboards, I found a solution that uses real geometry and actually pretty simple.
One problem that I ran into was the limited viewing distance. I thought that just setting the farplane value high enough would solve it, but there is actually a hard limit given by the hardware and/or OpenGl (not sure about that).
I wanted to have a planet that is far away but still visible (and approachable). While it would be possible to fake something with billboards, I found a solution that uses real geometry and actually pretty simple.
Code: [Select]
public class Planet extends Object3D { //It's better to not use Object3D directly for your game objects, but I do it here for simplicity
private SimpleVector realPosition, camPos = new SimpleVector();
private SimpleVector v = new SimpleVector; // temporary vector
private final static MAX_VIEWING_DISTANCE = 5000; //this should be a safe value for most devices; make sure your farplane value is higher than this
public Planet(SimpleVector position) {
... // init Object3D here
translate(position);
realPosition = new SimpleVector(position); //Save "real" position of planet in another vector as the object's physical position will change
}
// this is called in every frame update
public void update() {
world.getCamera().getPosition(camPos); //position of used camera
float dist = realPosition.distance(camPos); //calculate distance camera<->Planet
if (dist>MAX_VIEWING_DISTANCE) { //outside of the viewing distance -> do projection magic
setScale(MAX_VIEWING_DISTANCE / dist); //shrink the object
// Now that we made the object smaller, put it closer to the camera
v.set(realPosition); //Set helper vector to planet position
v.sub(camPos); //calculate direction vector from camera to planet
v.normalize(v); //and normalize it
v.scalarMul(MAX_VIEWING_DISTANCE); // Calculate new position within viewing distance
v.add(camPos); // add camera vector to get final object position
//Move it!
clearTranslation();
translate(v);
}
else { //planet is within viewing distance; reset size and position to real values
setScale(1);
clearTranslation();
translate(realPosition);
}