www.jpct.net

jPCT-AE - a 3d engine for Android => Support => Topic started by: Irony on December 29, 2013, 01:11:04 pm

Title: Code Snippet: Faking unlimited viewing distance
Post by: Irony 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);
  }
Title: Re: Code Snippet: Faking unlimited viewing distance
Post by: Irony 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.
Title: Re: Code Snippet: Faking unlimited viewing distance
Post by: Lobby 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).
Title: Re: Code Snippet: Faking unlimited viewing distance
Post by: Irony 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 (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?
Title: Re: Code Snippet: Faking unlimited viewing distance
Post by: Lobby 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:
(https://dl.dropboxusercontent.com/u/1618711/web/Screenshot_2013-12-30-12-16-50.png)

It's a really extreme sample, but I think it's visible that the left sphere seems to be more flat.
Title: Re: Code Snippet: Faking unlimited viewing distance
Post by: EgonOlsen 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.
Title: Re: Code Snippet: Faking unlimited viewing distance
Post by: Irony on January 06, 2014, 03:46:10 pm
Thanks for the feedback guys ;)