POV-Ray : Newsgroups : povray.binaries.images : Strange Result... Server Time
5 Nov 2024 09:22:54 EST (-0500)
  Strange Result... (Message 1 to 10 of 15)  
Goto Latest 10 Messages Next 5 Messages >>>
From: Jörg 'Yadgar' Bleimann
Subject: Strange Result...
Date: 17 Apr 2009 20:28:32
Message: <49e91eb0@news.povray.org>
High!

For my Solar System project (belated thanks, Lukas, for the hint about 
vrotate()!), I tried to generate a "spherical" mesh2 from a grayscale 
topographic map of the Martian moon Phobos (attached here) - but what I 
finally got the screen hasn't much in common with that potato-shaped 
little grey moon...

Here the code:

#declare PhobosRelief =
pigment
{
   image_map { png "solarsys/phobos_topo.png" }
}

mesh2 // Phobos
{
   vertex_vectors
   {
     320000
     #declare a=0;
     #while (a<400)
       #declare b=0;
       #while (b<800)
         ((8.1 + eval_pigment(PhobosRelief, <(0.5+b)*(1/800), 
(0.5+a)*(1/400), 0>).red * ((14-8.1)/255))
           * <sin(radians(b*(360/800)))*cos(radians(-90+a*(180/400))), 
sin(radians(-90+a*(180/400))), 
cos(radians(b*(360/800)))*cos(radians(-90+a*(180/400)))>)/sc,
         #declare b=b+1;
       #end
       #declare a=a+1;
     #end
   }
   face_indices
   {
     637602
     #declare a=0;
     #while (a<399)
       #declare b=0;
       #while (b<799)
         <a*400+b, a*400+b+1, (a+1)*400+b>,
         #if (b=798 & a=398)
           <319998, 319999, 319199>
         #else
           <(a+1)*400+b, (a+1)*400+b+1, a*400+b+1>,
         #end
         #declare b=b+1;
       #end
       #declare a=a+1;
     #end
   }
   texture
   {
     pigment { color rgb 0.3 }
     finish { F_Standard_Planetary_Surface }
   }
   rotate -y*100
   translate Pos_Phobos/sc

}

sc is currenty set to 13347, I tried it also with 500 and even 5, but 
that didn't change anything... what went wrong?

See you in Khyberspace!

Yadgar


Post a reply to this message


Attachments:
Download '2009-04-18 mars and phobos, take 2.jpg' (83 KB) Download 'phobos_topo.png' (72 KB)

Preview of image '2009-04-18 mars and phobos, take 2.jpg'
2009-04-18 mars and phobos, take 2.jpg

Preview of image 'phobos_topo.png'
phobos_topo.png


 

From: clipka
Subject: Re: Strange Result...
Date: 17 Apr 2009 21:00:00
Message: <web.49e925627f5031e4f88a27ab0@news.povray.org>
=?ISO-8859-15?Q?J=F6rg_=27Yadgar=27_Bleimann?= <yaz### [at] gmxde> wrote:
>    face_indices
>    {
>      637602
>      #declare a=0;
>      #while (a<399)
>        #declare b=0;
>        #while (b<799)
>          <a*400+b, a*400+b+1, (a+1)*400+b>,
>          #if (b=798 & a=398)
>            <319998, 319999, 319199>
>          #else
>            <(a+1)*400+b, (a+1)*400+b+1, a*400+b+1>,
> ...

I guess you want to multiply a and (a+1), respectively, with 800 here instead of
400, so that all b's fit "between the a's", if you got my meaning.


Post a reply to this message

From: Jörg 'Yadgar' Bleimann
Subject: Re: Strange Result...
Date: 17 Apr 2009 21:30:21
Message: <49e92d2d@news.povray.org>
clipka wrote:

> I guess you want to multiply a and (a+1), respectively, with 800 here instead of
> 400, so that all b's fit "between the a's", if you got my meaning.

Yes, of course... and also the difference between lowest and highest 
radius must not be divided through 255... finally I got my Phobos (see 
attached image)!

Danke, Christoph! Be prepared to find a "Lipka Montes" mountain range 
some day on a ficitious moon or planet designed by me...

See you in Khyberspace!

Yadgar


Post a reply to this message


Attachments:
Download '2009-04-18 mars and phobos, take 4.jpg' (87 KB)

Preview of image '2009-04-18 mars and phobos, take 4.jpg'
2009-04-18 mars and phobos, take 4.jpg


 

From: Kenneth
Subject: Re: Strange Result...
Date: 18 Apr 2009 06:15:00
Message: <web.49e9a7cb7f5031e4f50167bc0@news.povray.org>
That mesh 2 generation trick is quite interesting; I've never tried modeling
that way. I need to study your code (and Clipka's correction) to see if I can
understand the method.  Looks to be very useful!

Ken W.


Post a reply to this message

From: Jörg 'Yadgar' Bleimann
Subject: Re: Strange Result...
Date: 18 Apr 2009 15:32:28
Message: <49ea2acc$1@news.povray.org>
High!

Kenneth wrote:
> That mesh 2 generation trick is quite interesting; I've never tried modeling
> that way. I need to study your code (and Clipka's correction) to see if I can
> understand the method.  Looks to be very useful!
> 
> Ken W.
> 

O.k., here it is - Yadgar's Little Asteroid Modeling Tutorial:

I started with a color topographic map of Phobos, made in 1997 by A.
Tayfun Öner/Calvin J. Hamilton
(http://www.solarviews.org/cap/mars/phobos5.htm - there are many more
such maps on www.solarviews.org!). As the height levels of Phobos'
relief are coded according to hue values in the HSV/HSB color model
(with purple areas being lowest, red areas being highest), one can get a
greyscale bitmap easily interpretable by PoV-Ray when using a channel
separation function of a pixel-oriented graphics editor, for example the
GIMP.

So I cut out the map part of the image (which then is exactly 800 x 400
pixels) and started GIMP's separation function (Colors -> Components ->
Separate -> Color Mode: HSV). I found that the original image was not
exactly calibrated, so that the highest red parts were in fact already
slightly purplish, which made them stand out as white "islands" amidst
black regions in the hue value greyscale image, so I decided to adjust
the hue values of the original image.

In GIMP, this is done by Colors -> Hue/Saturation, in the dialog box
displayed then, press "All" (in the middle of six color fields in the
upper half), if not pre-selected yet, and then move the "hue" slide
control 5 units to the right and confirm with "Ok". After this, once
again separate the image channels.

For it is probably more convenient to assign the lowest grayscale values
to the lowest radius values rather than vice versa, you then should
invert the image (Colors -> Invert).

For some strange reasons, although the hue values of the original image
cover the full range of the HSV model (0 to 360), the gray values in the
separated image do not. So, to avoid complications when programming the
mesh2 reading routine, it's best to stretch the contrast to the maximum,
so that really the full grayscale range in fact shows up in the image.

Click on Colors -> Automatic -> Stretch Contrast; you can check the
result by using Colors -> Information -> Histogram (after stretching,
the black curve should span the entire width from 0 to 255).

Now you've got a POV-readable height bitmap! As the original image
already contained some compression artifacts, I recommend to store the
grayscale image in a lossless format, e. g. PNG.

Now to the programming in POV-Ray:

When used as a pigment, every bitmap, regardless of its actual
dimensions, is fit into a square of 1 x 1 POV units and (of course
unless rotated or translated) displayed on the x-y plane. The lower left
corner of the bitmap sits at the origin, the uper right corner sits at
<1, 1> (as all pigment patterns in POV-Ray are three-dimensional and
infinite, the bitmap pattern extends infinitely in both positive and
negative z direction).

In POV-Ray, a function (in the functions.inc file, which has to be 
included) exists to obtain the color value of any pigment
at any given point in 3-D space: eval_pigment(). As we want to model
elevations of an asteroidal body corresponding to grayscale values in a
bitmap, we now need to read out the gray value of every pixel.

The syntax for eval_pigment are: eval_pigment(<Name of pigment>, <Point 
at which color is to be read>), so we don't need to have the imagemap 
explicitly displayed in the scene, just defining it will do:

#declare PhobosRelief =
pigment
{
   image_map { png "solarsys/phobos_topo.png" }
}

According to the number of pixels in both dimensions (x and y), we read 
in the color data from a nested loop; to get reliable results, we pick 
the color from the center of each pixel, so that the loop will look like:

#declare a=0; // counter for rows
#while (a<400)
   #declare b=0; // counter for pixels in each row
   #while (b<800)
     #declare GrayValue = eval_pigment(PhobosRelief, <(0.5+b)*(1/800), 
0, (0.5+b)*(1/400)>.gray); // .gray as we just want one vector 
component, not the whole rgb vector itself
     #declare b=b+1;
   #end
   #declare a=a+1;
#end

As asteroid can be understood as an irregular spheroid, so that each 
point of the surface can be described by geographical coordinates and 
the distance to the center of the body, i. e. the local radius.
The radius for each surface point (= pixel of the grayscale bitmap) is 
calculated from the minimal radius, the difference between maximal 
radius und minimal radius and the respective gray value between 0 and 255.

As seen in the original topographic map image, the lowest radius is 8.1 
kms, while the highest radius is 14 km, so the radius for each pixel 
calculates as follows:

#declare rd = 8.1+GrayValue*(14-8.1);

Points on the surface of spheroids are defined by geographical 
coordinates (latitude and longitude), which are derived here from the 
two-dimensional coordinates of pixels in the greyscale map: the 800 
points per row equal 360 degrees of longitude, the 400 rows equal -90 to 
90 degrees of latitude. As the bitmap pigment spans <0, 0> to <1, 1>, we 
begin at the "south pole", i. e. -90 degrees.

#declare SurfacePoint = 
<sin(radians(long(b*(360/800)))*cos(radians(lat(a*(180/400))), 
sin(radians(lat(a*(360/800))), 
cos(radians(long(b*(360/800)))*cos(radians(lat(a*(180/400)))>;

The advantage of mesh2 object compared with the older mesh objects is 
that with a mesh2 object, each surface point (vertex) need to be 
declared and read into the internal calculation matrix only once, while 
the old mesh object consists of triangles as three-point triples, thus 
each triangle needed nine floating point values, which, with most points 
repeating, led to exponentially growing rendering times.

Contrary to this, mesh2 objects use index numbers of points in their 
triangle definition rather than actual points, so that each point needs 
to be defined only once.

So, we get the following code:

mesh2
{
   vertex_vectors
   {
   320000 // number of vertices: 800 x 400 pixels!
   #declare a=0; // counter for rows
   #while (a<400)
     #declare b=0; // counter for pixels in each row
     #while (b<800)
       #declare GrayValue = eval_pigment(PhobosRelief, <(0.5+b)*(1/800), 
0, (0.5+b)*(1/400)>.gray); // .gray as we just want one vector 
component, not the whole rgb vector itself
       #declare rd = 8.1+GrayValue*(14-8.1);
       #declare SurfacePoint = 
<sin(radians(long(b*(360/800)))*cos(radians(lat(a*(180/400))), 
sin(radians(lat(a*(360/800))), 
cos(radians(long(b*(360/800)))*cos(radians(lat(a*(180/400)))>;
       rd*SurfacePoint // the vertex must be generated explicitly, not 
just defined!
       #declare b=b+1;
     #end
     #declare a=a+1;
   #end
   }

/*
Here the vertices are generated and continuously assigned index numbers 
(here, from 0 to 319999); part 2 of a mesh2 is the definition of surface 
triangles from these vertices.

Starting with vertex 0(b) in row 0(a), all triangles are built according 
to the following scheme:

        <a*800+b, a*800+b+1, (a+1)*800+b>,
         #if (b=798 & a=398)
           <319998, 319999, 319199>
         #else
           <(a+1)*800+b, (a+1)*800+b+1, a*800+b+1>,
         #end

The #if clause is necessary because the last vector statement must not 
be followed by a comma.

Finally, we get this code:

mesh2 // Phobos
{
   vertex_vectors
   {
     320000
     #declare a=0;
     #while (a<400)
       #declare b=0;
       #while (b<800)
         ((8.1 + eval_pigment(PhobosRelief, <(0.5+b)*(1/800), 
(0.5+a)*(1/400), 0>).red * (14-8.1)) * 
<sin(radians(b*(360/800)))*cos(radians(-90+a*(180/400))), 
sin(radians(-90+a*(180/400))), 
cos(radians(b*(360/800)))*cos(radians(-90+a*(180/400)))>)/sc
         #declare b=b+1;
       #end
       #declare a=a+1;
     #end
   }
   face_indices
   {
     637602
     #declare a=0;
     #while (a<399)
       #declare b=0;
       #while (b<799)
         <a*800+b, a*800+b+1, (a+1)*800+b>,
         #if (b=798 & a=398)
           <319998, 319999, 319199>
         #else
           <(a+1)*800+b, (a+1)*800+b+1, a*800+b+1>,
         #end
         #declare b=b+1;
       #end
       #declare a=a+1;
     #end
   }
   texture
   {
     pigment { color rgb 0.3 }
     finish { F_Standard_Planetary_Surface }
   }
   rotate -y*100
   translate Pos_Phobos/sc

}

// end of code

This code renders in about one minute - an old-school mesh would have 
taken many hours even on a Athlon 64!

See you in Khyberspace!

Yadgar

*/


Post a reply to this message

From: Kenneth
Subject: Re: Strange Result...
Date: 19 Apr 2009 01:40:00
Message: <web.49eab7507f5031e4f50167bc0@news.povray.org>
>
> O.k., here it is - Yadgar's Little Asteroid Modeling Tutorial:

FASCINATING! I *very* much appreciate the time you took to explain this method
so clearly. Mesh 2 generation has been one of those 'mysterious' POV-Ray tools
that I've never understood before. And eval() is another tool I haven't yet
used, but am looking forward to experimenting with.

Since I'm familiar with Photoshop rather than the GIMP, I think I can extract a
grayscale image from the asteroid map (or I'll just make up my own!)

> Now to the programming in POV-Ray:
> [snip]
> According to the number of pixels in both dimensions (x and y), we read
> in the color data from a nested loop; to get reliable results, we pick
> the color from the center of each pixel...

That's a nice, subtle addition to your code.

> Points on the surface of spheroids are defined by geographical
> coordinates (latitude and longitude), which are derived here from the
> two-dimensional coordinates of pixels in the greyscale map: the 800
> points per row equal 360 degrees of longitude, the 400 rows equal -90 to
> 90 degrees of latitude.

Does this introduce any distortion into the way the asteroid map is applied to
the object? (I guess I need to read up on latitude and longitude!) I'm thinking
there might be, at the North and South 'poles.' Just guessing, out of ignorance.

> The advantage of mesh2 object compared with the older mesh objects is
> that with a mesh2 object, each surface point (vertex) need to be
> declared and read into the internal calculation matrix only once, while
> the old mesh object consists of triangles as three-point triples, thus
> each triangle needed nine floating point values, which, with most points
> repeating, led to exponentially growing rendering times.

I do see the intrinsic speedup. Though it appears to me that 'coding' a mesh 2
(vs. mesh) object is more complex--but that's only because I'm so new to the
idea. *Everything* seems strange and complicated when it's new!

> So, we get the following code:
>
> mesh2
[snip]

>        #declare rd = 8.1+GrayValue*(14-8.1);
>        #declare SurfacePoint =
> <sin(radians(long(b*(360/800)))*cos(radians(lat(a*(180/400))),
> sin(radians(lat(a*(360/800))),
> cos(radians(long(b*(360/800)))*cos(radians(lat(a*(180/400)))>;
>        rd*SurfacePoint // the vertex must be generated explicitly, not
> just defined!
[snip]

So  rd*SurfacePoint  doesn't need a #declare or anything, it's just used as
written?

>
> This code renders in about one minute - an old-school mesh would have
> taken many hours even on a Athlon 64!

Wow! Impressive. Yes, I'm used to *s-l-o-w* meshes.

Thanks again for your clear explanation! I need to take some time to digest it
all.

I have a question about eval(): If you were to actually evaluate a 3-D pigment
pattern (rather than a 2-D image), could those points in 3-D space be used with
your method to construct a mesh 2 object? I realize this is a non-detailed (and
rather naive) question; what I have in mind is producing something like your
asteroid, but with 'overhangs and undercuts' in the triangle mesh, similar to
what would be produced by an isosurface function, as opposed to a height_field.
In other words, the triangle vertices would not be 'restricted' to just height
values from a central radius point, but would be scattered in true 3-D space.
(For example, the various mesh-generation macros in shapes.inc can produce HFs
in the shape of a cylinder, sphere, etc.--but the resulting mesh doesn't have
overhangs or undercuts. Which is understandable, because that's what a
height_field is.)  But a method to produce an isosurface-like shape as a mesh 2
object would be VERY useful!  And much faster to render. (I can foresee problems
with this idea, though--triangles that might 'fold over' onto other ones,
possibly creating degenerate triangles or visible holes.  I *think*! But that
doesn't seem to me to be an insurmountable problem.)

Ken W.


Post a reply to this message

From: clipka
Subject: Re: Strange Result...
Date: 19 Apr 2009 06:25:00
Message: <web.49eafafe7f5031e4990f413d0@news.povray.org>
"Kenneth" <kdw### [at] earthlinknet> wrote:
> FASCINATING! I *very* much appreciate the time you took to explain this method
> so clearly. Mesh 2 generation has been one of those 'mysterious' POV-Ray tools
> that I've never understood before. And eval() is another tool I haven't yet
> used, but am looking forward to experimenting with.

Actually, if you are fine with generating mesh, then there is not much need to
go for mesh2: Both are compiled into the same internal data structures, with no
difference in memory or rendering speed efficiency whatsoever. Mesh2 is intended
for a more compact file format and easier generation by modeller software,
that's all.

Although it is not commonly known, POV-Ray does quite a good job at optimizing
mesh data, detecting identical vertices and normals and such.


Post a reply to this message

From: Jörg 'Yadgar' Bleimann
Subject: Re: Strange Result...
Date: 19 Apr 2009 07:01:01
Message: <49eb046d@news.povray.org>
High!

Kenneth wrote:

> Does this introduce any distortion into the way the asteroid map is applied to
> the object? (I guess I need to read up on latitude and longitude!) I'm thinking
> there might be, at the North and South 'poles.' Just guessing, out of ignorance.

The maps to use here are so-called "simple cylindrical projections" - 
this means that on the map, longitudes and latitudes form a rectangular 
grid, each parallel crosses each meridian at a 90 degree angle, unlike 
in most other map projections which are designed to avoid as much 
distortion as possible. Also, with the simple cylindrical projection, 
all distances between latitudes are equal, unlike Mercator's projection 
which stretches to infinity at the poles. When "re-projected" to a 
sphere, the 2D distortion of the simple cylindrical projection disappears!

> So  rd*SurfacePoint  doesn't need a #declare or anything, it's just used as
> written?

Yes, it is! With a mesh2 structure written by hand (without any loops), 
there also would be explicitly written vertex vectors, just like the 2D 
vectors you have to write when coding a prism!

> Wow! Impressive. Yes, I'm used to *s-l-o-w* meshes.

Back in 2002, I tried to render a mesh (not mesh2!) of the Moon's 
surface generated with John Beale's "OrbCyl" tool - the whole thing took 
three days and was, as original map, only 1000 x 500 pixels large!

> I have a question about eval(): If you were to actually evaluate a 3-D pigment
> pattern (rather than a 2-D image), could those points in 3-D space be used with
> your method to construct a mesh 2 object? I realize this is a non-detailed (and
> rather naive) question; what I have in mind is producing something like your
> asteroid, but with 'overhangs and undercuts' in the triangle mesh, similar to
> what would be produced by an isosurface function, as opposed to a height_field.
> In other words, the triangle vertices would not be 'restricted' to just height
> values from a central radius point, but would be scattered in true 3-D space.
> (For example, the various mesh-generation macros in shapes.inc can produce HFs
> in the shape of a cylinder, sphere, etc.--but the resulting mesh doesn't have
> overhangs or undercuts. Which is understandable, because that's what a
> height_field is.)  But a method to produce an isosurface-like shape as a mesh 2
> object would be VERY useful!  And much faster to render. (I can foresee problems
> with this idea, though--triangles that might 'fold over' onto other ones,
> possibly creating degenerate triangles or visible holes.  I *think*! But that
> doesn't seem to me to be an insurmountable problem.)

That would be pretty complicated to achieve with mathematic formulae... 
I think it would be much easier to do when modeling such surfaces 
intuitively with a graphical frontend, such as Wings3D, Hamapatch or 
Blender!

See you on www.khyberspace.de!

Yadgar

Now playing: Calling Your Name (Simple Minds)


Post a reply to this message

From: Slime
Subject: Re: Strange Result...
Date: 19 Apr 2009 07:34:33
Message: <49eb0c49$1@news.povray.org>
> The #if clause is necessary because the last vector statement must not be 
> followed by a comma.

In most cases in POV-Ray, an extra comma is permitted at the end of a list.

If that isn't the case for meshes, you can still go with the simpler

         <(a+1)*800+b, (a+1)*800+b+1, a*800+b+1>
         #if  ( b != 798 | a != 398 )
           ,
         #end

which doesn' t look like there's some crazy weird special case.

 - Slime
 [ http://www.slimeland.com/ ]


Post a reply to this message

From: clipka
Subject: Re: Strange Result...
Date: 19 Apr 2009 07:55:01
Message: <web.49eb10337f5031e4990f413d0@news.povray.org>
=?UTF-8?B?SsO2cmcgJ1lhZGdhcicgQmxlaW1hbm4=?= <yazdegird@gmx.de> wrote:
> > Does this introduce any distortion into the way the asteroid map is applied to
> > the object? (I guess I need to read up on latitude and longitude!) I'm thinking
> > there might be, at the North and South 'poles.' Just guessing, out of ignorance.
>
> The maps to use here are so-called "simple cylindrical projections" -
> this means that on the map, longitudes and latitudes form a rectangular
> grid, each parallel crosses each meridian at a 90 degree angle, unlike
> in most other map projections which are designed to avoid as much
> distortion as possible. Also, with the simple cylindrical projection,
> all distances between latitudes are equal, unlike Mercator's projection
> which stretches to infinity at the poles. When "re-projected" to a
> sphere, the 2D distortion of the simple cylindrical projection disappears!

The official cartographical term is "equidistant cylindrical projection" (aka
"plate carree projection").

Not to be confused with what POV-Ray calls a "cylindrical" projection - which
actually is an "equal-area cylindrical projection" (any subtype will do for
POV-Ray, e.g. Gall-Peters projection, Behrmann projection or Lambert
cylindrical equal-area projection, as they just differ in the way they are
"squeezed" to a certain aspect ratio, which is irrelevant for use in POV-Ray).

The "equidistant cylindrical projection" matches what POV-Ray calls "spherical
projection".


Post a reply to this message

Goto Latest 10 Messages Next 5 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.