POV-Ray : Newsgroups : povray.binaries.images : Mesh vs mesh2 Server Time
26 Apr 2024 16:10:04 EDT (-0400)
  Mesh vs mesh2 (Message 1 to 5 of 5)  
From: Bill Pragnell
Subject: Mesh vs mesh2
Date: 25 May 2006 08:00:01
Message: <web.44759ba38c28dbe6731f01d10@news.povray.org>
Following a problem I had with slow mesh parsing (see povray.general), here
is my solution, with an example pic, using an optimized mesh2 object.

My goal was to create a fairly good mountain landscape for use in
backgrounds, etc, without resorting to fiddling with image heightfields or
waiting for isosurfaces. So this is a heightfield generated using only SDL,
using an 'envelope' function to control the height of mountains generated
from pigment functions. I've included the complete scene, with some brief
comments - hopefully someone will find it useful! I'm using 1 pov-unit = 1
metre, approximately, so by all means have a play with the numbers.

Bill

/* code starts */
#include "colors.inc"
#include "shapes.inc"

global_settings {
  assumed_gamma 1
  max_trace_level 10 }

camera {
  location <0, 100, 0>
  right <4/3, 0, 0>
  up <0, 1, 0>
  direction <0, 0, FoV_90>
  look_at <100, 100, 150> }

light_source { <10000, 100000, -50000> color White }

// define basic pigment functions for mountains
// agate for large-scale features, wrinkles for
// fine detail
#declare land1 = function {
  pigment {
    agate
    color_map {
      [0 color rgb 1]
      [1 color rgb 0] } } }
#declare land2 = function {
  pigment {
    wrinkles
    color_map {
      [0 color rgb 1]
      [1 color rgb 0] } } }

// global scaling parameters for pigment functions
#declare sc1 = 20;
#declare sc2 = 5;
#declare hilloff = 12;

// macro function to return a sinusoidal edge, so
// that mountains can rise smoothly from a plain without
// cut-off edges
#macro SineEdge(xp,yp,zp)
  #if (xp >= 0)
    #local Result = 1;
  #end
  #if (xp < 0 & xp >= -pi)
    #local Result = 0.5*cos(xp)+0.5;
  #end
  #if (xp < -pi)
    #local Result = 0;
  #end
  (Result)
#end

// height macro function to return a mountain height value
// given a point in the x-y plane. vary the hilloff parameter defined
// above to move the pigment function around without changing the envelope.
#macro LandHeight(xp, yp)
  #local Result = SineEdge(xp+6,0,yp)
   *(0.5*land1((xp+hilloff)/sc1, 0, yp/sc1).x +
     0.5*land2((xp+hilloff)/sc2, 0, yp/sc2).x);
  (Result)
#end

// texture definitions
#declare p1 = pigment { color Clear }
#declare p2 = pigment {
  slope { <0, 1, 0> }
  color_map {
    [0 color Clear]
    [0.75 color Clear]
    [0.77 color White]
    [1 color White] } }
#declare t1 = texture {
  pigment {
    slope { <0, 1, 0> }
    color_map {
      [0 color Gray70]
      [0.7 color Gray70]
      [0.75 color Tan]
      [0.85 color LightWood]
      [0.94 color rgb <0.3, 0.6, 0.3>]
      [1 color rgb <0.3, 0.6, 0.3>] } }
  finish { ambient 0 } }
#declare t2 = texture {
  pigment {
    gradient y
    pigment_map {
      [0 p1]
      [0.6 p1]
      [0.605 p2]
      [1 p2] } }
  finish { ambient 0.35 } }

// mountain macro to build the mesh2 heightfield
// xs, ys are extent of field in each direction
// (i.e. width = 2*xs etc)
// maxh is maximum altitude of mountains
// dx is grid spacing of heightfield (must divide into
// xs and ys exactly)
#macro Region(xs, ys, maxh, dx)
  #local nx = 2*xs/dx + 1;
  #local ny = 2*ys/dx + 1;
  #local Vertices = nx*ny;
  #local Faces = (nx-1)*(ny-1)*2;
  mesh2 {
  vertex_vectors {
    Vertices,
    #local xp = -xs;
    #local yp = -ys;
    #local n = 0;
    #while (n < Vertices-1)
      <xp, maxh*LandHeight(xp,yp), yp>,
      #local n = n + 1;
      #local xp = xp + dx;
      #if (xp = xs+dx)
        #local xp = -xs;
        #local yp = yp + dx;
      #end
    #end
    <xp, maxh*LandHeight(xp,yp), yp> }
  face_indices {
    Faces,
    #local n = 0;
    #while (n < Vertices-nx-2)
      <n, n+1, n+nx>,
      <n+1, n+nx+1, n+nx>,
      #local n = n + 1;
      #if (mod(n-(nx-1), nx) = 0)
        #local n = n + 1;
      #end
    #end
    <n, n+1, n+nx>,
    <n+1, n+nx+1, n+nx> }
  texture { t1 scale maxh }
  texture { t2 scale maxh } }
#end

// make mountains.
// they were originally created small during testing and
// then scaled up later using transformations. alter the last
// parameter to change the heightfield resolution.
object {
  Region(12, 30, 5, 0.05)
  translate <12, 0, 30>
  scale 500
  translate <1000, 0, 0> }

// ground plane
plane {
  <0, 1, 0>, 0.2
  pigment { color rgb <0.3, 0.6, 0.3> }
  finish { ambient 0 } }

// background & some ground mist
fog {
  color rgb <0.9, 0.975, 1>
  distance 10000
  fog_type 2
  fog_offset 0
  fog_alt 300 }
background { color NavyBlue }

/* code ends */


Post a reply to this message


Attachments:
Download 'hills.jpg' (36 KB)

Preview of image 'hills.jpg'
hills.jpg


 

From: Roman Reiner
Subject: Re: Mesh vs mesh2
Date: 25 May 2006 11:05:00
Message: <web.4475c701f14cf419c4bd4e7a0@news.povray.org>
Maybe i'm overlooking something, but where's the difference to a
heightfield?

Your approach could however be easily expanded to become capable of doing
overhangs which a heightfield isn't capable of.

Regards Roman


Post a reply to this message

From: Bill Pragnell
Subject: Re: Mesh vs mesh2
Date: 25 May 2006 12:30:00
Message: <web.4475dadef14cf419731f01d10@news.povray.org>
"Roman Reiner" <lim### [at] gmxde> wrote:
> Maybe i'm overlooking something, but where's the difference to a
> heightfield?
The main reason I knocked it together was simply to make the landscape
tinkering process easier and faster; resolution, shape, functions can all
be changed in a single render. If I want a really high-res landscape, I
don't have to wait for it to churn out the image and then import it back
again. It seemed like a good excuse to learn how to use mesh2, too.

> Your approach could however be easily expanded to become capable of doing
> overhangs which a heightfield isn't capable of.
And there's that, of course... :-)

I'll have a think, and see what else I could do with it!

Bill


Post a reply to this message

From: Trevor G Quayle
Subject: Re: Mesh vs mesh2
Date: 25 May 2006 20:07:29
Message: <447646c1$1@news.povray.org>
"Bill Pragnell" <bil### [at] hotmailcom> wrote in message 
news:web.44759ba38c28dbe6731f01d10@news.povray.org...
> Following a problem I had with slow mesh parsing (see povray.general), 
> here
> is my solution, with an example pic, using an optimized mesh2 object.
>
> My goal was to create a fairly good mountain landscape for use in
> backgrounds, etc, without resorting to fiddling with image heightfields or
> waiting for isosurfaces. So this is a heightfield generated using only 
> SDL,
> using an 'envelope' function to control the height of mountains generated
> from pigment functions. I've included the complete scene, with some brief
> comments - hopefully someone will find it useful! I'm using 1 pov-unit = 1
> metre, approximately, so by all means have a play with the numbers.
>
> Bill
>

It's always a good exercise to write a mesh2 generator in POV SDL to better 
understand both the programming and mesh2 formats.  Good work.  A couple 
hints for you here:

1) changing both SineEdge and LandHeight to functions rather than macros 
adds speed.  Parse time dropped from about 90secs to 60secs for me:

#declare SineEdge2 = function 
(xp){select(xp,select(xp+pi,0,0.5*cos(xp)+0.5),1)}
#declare LandHeight2=function 
(xp,yp){SineEdge2(xp+6)*(0.5*land1((xp+hilloff)/sc1, 0, yp/sc1).x + 
0.5*land2((xp+hilloff)/sc2, 0, yp/sc2).x)}

2) There is the function pattern for height_fields which does pretty much 
what you did by hand only much faster (drops down to a mere 6sec parse time, 
plus smoothing can be added):

#macro Region2(xs, ys, maxh, dx)
height_field {
  #local m=(2*xs/dx+2);
  #local n=(2*ys/dx+2);
  function m,n {pattern{function{LandHeight2( (x)*2*xs-xs 
, -((y-1/n)*2*ys-ys) )}}}
  //smooth
  translate <-1/2,0,-1/2>
  scale <2*xs,maxh,2*ys>
  texture { t1 scale maxh }
  texture { t2 scale maxh }
}
#end

Good work on weeding through the math involved in mesh creation though.  I 
did it once for a moebius generator and it was quite educational.  (You 
forgot the smoothing normals though! And uv mapping support!)

-tgq


Post a reply to this message

From: Bill Pragnell
Subject: Re: Mesh vs mesh2
Date: 26 May 2006 05:50:00
Message: <web.4476ce9ef14cf419731f01d10@news.povray.org>
"Trevor G Quayle" <Tin### [at] hotmailcom> wrote:
> 1) changing both SineEdge and LandHeight to functions rather than macros
> adds speed.  Parse time dropped from about 90secs to 60secs for me:
>
> #declare SineEdge2 = function
> (xp){select(xp,select(xp+pi,0,0.5*cos(xp)+0.5),1)}
> #declare LandHeight2=function
> (xp,yp){SineEdge2(xp+6)*(0.5*land1((xp+hilloff)/sc1, 0, yp/sc1).x +
> 0.5*land2((xp+hilloff)/sc2, 0, yp/sc2).x)}
Well, crikey. I never even knew the select() function existed. Very useful!

> height_field {
>   #local m=(2*xs/dx+2);
>   #local n=(2*ys/dx+2);
>   function m,n {pattern{function{LandHeight2( (x)*2*xs-xs
> , -((y-1/n)*2*ys-ys) )}}}
>   //smooth
>   translate <-1/2,0,-1/2>
>   scale <2*xs,maxh,2*ys>
>   texture { t1 scale maxh }
>   texture { t2 scale maxh }
> }
That's *very* interesting. Is that feature in 3.6.1? I can't find it
anywhere in the documentation. As you say, it completely does away with the
intermediate image generation / import step which used to be so
time-consuming when I've tried using heightfields in the past.

Anyway, at least I have a nice modifiable rectangular mesh2 generator now.

Cheers for the pointers!
Bill


Post a reply to this message

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