|
|
|
|
|
|
| |
| |
|
|
From: Jörg 'Yadgar' Bleimann
Subject: Problem: Finding the elevation range of an isosurface relief
Date: 6 Aug 2007 17:43:32
Message: <46b79604@news.povray.org>
|
|
|
| |
| |
|
|
High!
During the last months, I experimented with various isosurface (and
pattern) functions to generate realistic-looking landscapes. To
"navigate" around these landscapes (e. g. for placing cameras or, in the
future, trees or buildings) I found it necessary to have an orthographic
map view of the terrain at different scales.
But at very large scales such as 1 by 1 kilometres (whis equals to 1
metre/pixel at my favourite rendering resolution - see last attachment)
a problem occurs: as the human eye's ability to discern hues is limited,
I have to adapt the color_map for the original 200 by 200 kilometres
physical map to the height range of the respective large-scale section.
To do this, I would have to know the highest and lowest point of the relief.
How could this be achieved? The highest point could be tested for by
shooting a series of parallel horizontal trace() rays from one edge of
the map section, starting at a height well above the highest mountains
in the whole isosurface (for example 15 kilometres), going lower each
iteration until the first mountain peak is hit. But how to this for the
lowest point?
And, after all, I'm sure that this method would be outstandingly
time-consuming - is there any way to do it faster?
See you in Khyberspace!
Post a reply to this message
Attachments:
Download 'ghurghusht_flat_0103b_wrinkles_oblique_view.jpg' (126 KB)
Download 'ghurghusht_flat_0103c_wrinkles_physical_map.jpg' (259 KB)
Download 'ghurghusht_flat_0105a_wrinkles_regional_map.jpg' (93 KB)
Download 'ghurghusht_flat_0105b_wrinkles_local_map.jpg' (33 KB)
Download 'ghurghusht_flat_0105c_wrinkles_microlocal_map.jpg' (12 KB)
Preview of image 'ghurghusht_flat_0103b_wrinkles_oblique_view.jpg'
Preview of image 'ghurghusht_flat_0103c_wrinkles_physical_map.jpg'
Preview of image 'ghurghusht_flat_0105a_wrinkles_regional_map.jpg'
Preview of image 'ghurghusht_flat_0105b_wrinkles_local_map.jpg'
Preview of image 'ghurghusht_flat_0105c_wrinkles_microlocal_map.jpg'
|
|
| |
| |
|
|
|
|
| |
| |
|
|
A faster(?) trace option could be to shoot vertical rays in a grid pattern
over the entire landscape, keeping track of only the current highest &
lowest points.
This wouldn't find the *exact* highest point, but unless there are some very
sharp gradient changes it would be close enough.
Alternatively you could add a second layer to your colour map, say with some
narrow black lines like isobars on a weather map.
Post a reply to this message
|
|
| |
| |
|
|
From: Tim Attwood
Subject: Re: Problem: Finding the elevation range of an isosurface relief
Date: 8 Aug 2007 03:11:14
Message: <46b96c92$1@news.povray.org>
|
|
|
| |
| |
|
|
You could give it a b/w gradient pigment (ambient 1)
with a scale range that is sure to fit, then render an
overhead view without lights, load the image in an
editor and check what the brightest pixel is, and
then use that and the range to figure the ballpark
height.
Or you could use this collision macro with a
box overhead and lower it until the box hits.
// check if object A collides with object B
// Example: #local isHit = collision(A, B, 1000);
#macro collision(A B rez)
#local result = false;
#if (((min_extent(A).x > max_extent(B).x ) |
(min_extent(B).x > max_extent(A).x ) |
(min_extent(A).y > max_extent(B).y ) |
(min_extent(B).y > max_extent(A).y ) |
(min_extent(A).z > max_extent(B).z ) |
(min_extent(B).z > max_extent(A).z ))=false)
#local AB = intersection{object{A} object{B}};
#local Mn = min_extent(AB);
#local Mx = max_extent(AB);
#local S1 = seed(1);
#local Pt = VRand_In_Box(Mn, Mx, S1);
#local cnt = 0;
#while ((result = false) & (cnt < rez))
#local Pt = VRand_In_Box(Mn, Mx, S1);
#if (inside(AB, Pt))
#local result = true;
#end
#local cnt = cnt + 1;
#end
#end
result
#end
Post a reply to this message
|
|
| |
| |
|
|
From: Ray Bellis
Subject: Re: Problem: Finding the elevation range of an isosurface relief
Date: 8 Aug 2007 03:52:16
Message: <46b97630$1@news.povray.org>
|
|
|
| |
| |
|
|
> How could this be achieved? The highest point could be
> tested for by shooting a series of parallel horizontal
> trace() rays from one edge of the map section, starting
> at a height well above the highest mountains in the whole
> isosurface (for example 15 kilometres), going lower each
> iteration until the first mountain peak is hit. But how
> to this for the lowest point?
>
> And, after all, I'm sure that this method would be
> outstandingly time-consuming - is there any way to do it faster?
It needn't be particular slow at all - you can use an O(LogN) binary
sub-division algorithm:
In pseudo code:
int height = 16384;
int step = height / 2;
while (step >= 0) {
if (hit_object_at_height(height)) {
height += step;
} else {
height -= step;
}
step /= 2;
}
With just 15 trace calls you'd have the maximum height between 0 and 65535m
to 1m resolution.
Ray
Post a reply to this message
|
|
| |
| |
|
|
From: Ray Bellis
Subject: Re: Problem: Finding the elevation range of an isosurface relief
Date: 8 Aug 2007 03:54:31
Message: <46b976b7@news.povray.org>
|
|
|
| |
| |
|
|
Ray Bellis wrote:
>
> int height = 16384;
> int step = height / 2;
> while (step >= 0) {
> if (hit_object_at_height(height)) {
> height += step;
> } else {
> height -= step;
> }
> step /= 2;
> }
Oops - small bug - that (step >= 0) check should be (step > 0)
Ray
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Wasn't it Tim Attwood who wrote:
>You could give it a b/w gradient pigment (ambient 1)
>with a scale range that is sure to fit, then render an
>overhead view without lights, load the image in an
>editor and check what the brightest pixel is, and
>then use that and the range to figure the ballpark
>height.
If your isosurface is independent of z (which is probably a good idea
for landscapes, since you don't want to risk disconnected fragments
floating above the main surface) then you could do the equivalent inside
POV-Ray.
Use the function that generates the isosurface as a pigment function,
apply it to a plane, then use eval_pigment on each resulting "pixel" to
obtain the brightness of the pigment. It should run a lot faster than
using trace on the isosurface. You can use eval_pigment to sample at
different separations, you're not limited by the pixel size of the
render.
Or, equivalently, use the function that generates the isosurface as a
heightfield function and use max_extents and min_extents of that
heightfield. See http://www.econym.demon.co.uk/isotut/patterns.htm#hf
You have to switch the y and -z axes and translate by <-0.5,0,-0.5> to
get the heightfield to match the isosurface. The accuracy and speed of
this method depends on the size of the heightfield grid.
In both those cases, you can gain a little bit of extra time by not
actually rendering the plane or heightfield. Just #declare them and
perform the eval_pigment or max_extents on the undisplayed object.
--
Mike Williams
Gentleman of Leisure
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |