4

I'm experimenting with procedural terrain generation of entire planets. This means I tend to render very big objects from very close up, and as a result I occasionally run into precision loss issues.

My latest terrain generator is producing images that look as follows. As you can see, there are lines in between some of the polygons.

Thing is, I'm reasonably sure that my terrain generator is outputting a correct mesh --- hand observation shows that the triangles seem to be sharing vertices, and the vertex:face ratio is about 2:1, which is correct. So I don't see how the polygons cannot precisely butt up against each other.

Does this look like it could be another precision loss issue? The camera is about 0.1 world units above the surface, which is about 1750 world units from the origin. This doesn't seem large enough to be an issue with Povray's double precision floats, but...

(If anyone feels like looking at the source code to the terrain generator, which is in C++, it's here: https://code.google.com/p/flooded-moon/source/browse/terrainmaker/sphericalroam.h)

Problematic image

Update: Here's a better image exhibiting the problem.

The camera's now 0.002 world units above the surface. The surface is about 1750 world units from the origin. My scale is 1 world unit to a kilometre; this means that the weird artifacting is on the order of centimetres, or about 0.00001. This is a difference of about 10^8. Is that enough for rounding errors to be significant?

Another problematic image

David Given
  • 13,277
  • 9
  • 76
  • 123

1 Answers1

2

I tried to reproduce the dimensions of your scenery with the POVRay code below. Here, I show surface elements of 10 cm (0.0001) width that have a varying elevation of z=(i+j)*0.000001 (i.e. 1 mm for every step). I would expect 2D stairs that gradually rise with distance from the origin (0.0,0.0,1750.0).

/* 
  display a planet's surface with real dimensions
 */
#include "colors.inc"

// dimensions
#declare Radius = 1750.0;   // planet radius in km
#declare nEl    = 100;      // nEl x nEl will be produced
#declare sEl    = 0.0001;   // size of one surface element
//
#declare camX = 0.0;
#declare camY = 0.0;
#declare camZ = Radius + 0.003

camera {
location <camX,camY,camZ>
look_at  <camX+1,camY+1,camZ-1>
angle 50
sky <0,1,0>
up <0,9,0>
right <16,0,0>  // up,right -> 16:9 
}
light_source { <camX,camY,camZ>
              color White
              fade_distance 2.0
              fade_power 1
}
#macro SElement(Xoff,Yoff,Zoff) 
#local cbase=<0.9,0.1,0.1>; // base color
#local hcolr=rand(hh)*0.1;  // color variation
#local hcolg=rand(hh)*0.1;
#local hcolb=rand(hh)*0.1;
#local OneElement = box { <0,0,0>, <1,1,1> 
     texture {
        pigment { color cbase+<hcolr,hcolg,hcolb> }
     } 
}
object{ OneElement
      scale sEl
      translate <Xoff,Yoff,Zoff> }
#end // macro SElement

// create surface from surface elements of varying elevation Zoff 
#local i=0;
#local j=0;
#while (i<nEl)
  #while (j<nEl)
    #local Xoff = i*(sEl);
    #local Yoff = j*(sEl);
    #local Zoff = Radius + (i+j)*0.000001; 
    SElement(Xoff,Yoff,Zoff)
    #local j=j+1;
  #end
  #local j=0;
  #local i=i+1;
#end 

To my surprise, this happens: Scene with camera angle 50

In regular intervals, there are large steps in the pattern that cannot be explained by the simple math of the scene description. When I change to Radius=1.0; the artefacts have disappeared: Same scene with Radius=1.0

So the conclusion (and the answer to your question, not to the problem in general) must be: Yes, POVRay has some issue when adding large and small numbers. Maybe there is a switch telling POVRay to use double precision. I don't know. I guess, there are experienced POVRay users who just smile when they read this.

I hope this helps. Anyway, I also learned something by answering your question.

Cheers, Marcus

Aziraphale
  • 337
  • 5
  • 15
  • Well, what I was _hoping_ was for someone to say, that's a common problem, to fix it do X... but I wasn't really expecting it. Thanks for the confirmation. I'll have to try and adjust the mesh so that the camera is at <0, 0, 0> and see if that helps. – David Given Dec 04 '13 at 18:39
  • [Here](http://news.povray.org/povray.pov4.discussion.general/thread/%3Cweb.4ad3b95a1e85221ac41e4df50@news.povray.org%3E/) the solution only involves a re-scaling of the scene to avoid very small increments. Maybe there is no other way around it. I can imagine every scene can be scaled to "reasonable" size. – Aziraphale Dec 04 '13 at 19:10
  • I've just tried adding some quick and dirty code to my mesh generated to subtract the camera position from each vertex, and then do a `translate ` afterwards. This means that vertices near the camera have relative mesh positions near <0, 0, 0>... and it works! My polygons are now all connected to each other. I don't think this would help with your example code, however, as you're doing something a bit different... – David Given Dec 06 '13 at 01:20
  • It DOES help as you can see in the second image. Removing the large number from the calculations seems to be the solution. When I removed the radius (1750. -> 1.), everything was fine. Obviously, the large range of significant digits causes trouble even with POVRay's double precision. – Aziraphale Dec 09 '13 at 13:46