Author Topic: Code Snippet: Faking unlimited viewing distance  (Read 3326 times)

Offline Irony

  • long
  • ***
  • Posts: 151
    • View Profile
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.

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);
  }
« Last Edit: December 29, 2013, 02:13:07 pm by Irony »

Offline Irony

  • long
  • ***
  • Posts: 151
    • View Profile
Re: Code Snippet: Faking unlimited viewing distance
« Reply #1 on: December 30, 2013, 09:35:55 am »
Added to the Wiki. I think we should still keep this thread open in case there any questions.

Offline Lobby

  • int
  • **
  • Posts: 66
    • View Profile
    • flowersoft
Re: Code Snippet: Faking unlimited viewing distance
« Reply #2 on: December 30, 2013, 10:56:14 am »
I think so. Could you also add a link there to this Topic? Then it would make a lot more sense ;) .

Nice code snippet, but don't forget that it is possible to determine a difference between a really far object and a not that far, scaled object. The really far object will look more flat than the other one (but I think nobody will ever notice that in a real program).

Offline Irony

  • long
  • ***
  • Posts: 151
    • View Profile
Re: Code Snippet: Faking unlimited viewing distance
« Reply #3 on: December 30, 2013, 11:22:09 am »
I think so. Could you also add a link there to this Topic? Then it would make a lot more sense ;) .

Nice code snippet, but don't forget that it is possible to determine a difference between a really far object and a not that far, scaled object. The really far object will look more flat than the other one (but I think nobody will ever notice that in a real program).

Thought it would be easy enough to find but here you go
http://www.jpct.net/wiki/index.php/Fake_unlimited_viewing_distance

About your objection: Are you sure this effect isn't only present in stereoscopic (real) 3D?

Offline Lobby

  • int
  • **
  • Posts: 66
    • View Profile
    • flowersoft
Re: Code Snippet: Faking unlimited viewing distance
« Reply #4 on: December 30, 2013, 12:26:14 pm »
I meant you could link from the wiki article to this Topic here ;) .

About your objection: Are you sure this effect isn't only present in stereoscopic (real) 3D?

I'm really sure. Look at this short sample:
Code: [Select]
world = new World();

piv = Object3D.createDummyObj();
camPiv = Object3D.createDummyObj();
camPiv.addParent(piv);
camPiv.translate(0, 0, -10);

Light light = new Light(world);
light.setPosition(new SimpleVector(-5, -5, -5));

TextureManager mgr = TextureManager.getInstance();
Resources res = getResources();
mgr.addTexture("texture", new Texture(res.openRawResource(R.raw.tex)));

SimpleVector vec;

Object3D sp1 = Primitives.getSphere(3.5f);
sp1.rotateY(0.4f);
sp1.rotateX(-0.1f);
vec = sp1.getZAxis();
vec.scalarMul(25f);
sp1.translate(vec);
sp1.calcTextureWrapSpherical();
sp1.setTexture("texture");
world.addObject(sp1);

Object3D sp2 = Primitives.getSphere(40f);
sp2.rotateY(-0.4f);
sp2.rotateX(-0.1f);
vec = sp2.getZAxis();
vec.scalarMul(400f);
sp2.translate(vec);
sp2.calcTextureWrapSpherical();
sp2.setTexture("texture");
world.addObject(sp2);

Which leads to this:


It's a really extreme sample, but I think it's visible that the left sphere seems to be more flat.

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 12295
    • View Profile
    • http://www.jpct.net
Re: Code Snippet: Faking unlimited viewing distance
« Reply #5 on: December 30, 2013, 03:56:41 pm »
It's different, because the scaling ignores the perspective projection. However, the farer away the object is, the less this counts. So for objects that are far away, this is a reasonable approach.

Offline Irony

  • long
  • ***
  • Posts: 151
    • View Profile
Re: Code Snippet: Faking unlimited viewing distance
« Reply #6 on: January 06, 2014, 03:46:10 pm »
Thanks for the feedback guys ;)