POV-Ray : Newsgroups : povray.newusers : macro argument help Server Time
2 Nov 2024 07:24:58 EDT (-0400)
  macro argument help (Message 1 to 6 of 6)  
From: Kaveh Bazargan
Subject: macro argument help
Date: 28 May 2004 06:36:36
Message: <40b71634@news.povray.org>
I am not a new user, but this must be a basic concept I am missing. I 
have the following file:

//---------------------- begin file ----------------------
camera {location <5,5,2>
        look_at 2*x
        angle 40
        right <-1.33,0,0>  //right-handed system
        sky z
        }

light_source {<0,3,3> 
              color rgb 2
              }


#macro cushion(size_x,size_y,size_z) 
  superellipsoid{<.2, .4 >
                 scale .5*<size_x,size_y,size_z>
                 translate .5*<size_x,size_y,size_z>
                }        
#end //macro cushion                

#macro sofa_seat(cushion_wd,segments)  //calls cushion
  union{
    #while (segments>0)
      object {cushion(cushion_wd,cushion_dp,cushion_ht) 
              translate (segments-1)*cushion_wd*x}
      #local segments = segments -1;
    #end //while
       }
#end //macro sofa_seat     

#macro sofa(sofa_wd,segments)  //calls sofa_seat
  union{ 
      object{sofa_seat(sofa_wd/segments,segments)} //the seat
      object{sofa_seat(sofa_wd/segments,segments) rotate 90*x} //the back
    texture{pigment{color rgb <1,0,0>}}
       }
#end //macro sofa                     


#declare cushion_dp = .6;
#declare cushion_ht = .2;
#declare sofa_width = 4;
#declare segments = 5;

sofa(sofa_width, segments)
//---------------------- end file ----------------------

It is meant to draw a sofa, with a seat and a back. "sofa()" calls 
sofa_seat() twice, once to create the seats, and once to create the 
back. The number of cushions (or segments) is passed via "segments".

Here is the problem. Running the program produces only the seat, not 
the back. Seems by the time the program gets to the line marked as 
"//the back", "segment" has been reset to zero, hence nothing is 
produced by that line. If you comment out the line before this one, 
marked "//the seat" you will see that the back is now produced, but not 
the seat obviously.

I think there is a fundamental point here about macro arguments which I 
need to learn. Why is segments zero in the line marked "//the back"? 
Any pointers welcome.


Post a reply to this message

From: Warp
Subject: Re: macro argument help
Date: 28 May 2004 08:13:44
Message: <40b72cf8@news.povray.org>
Kaveh Bazargan <kav### [at] delete_thisfocalimagecom> wrote:
> I think there is a fundamental point here about macro arguments which I 
> need to learn. Why is segments zero in the line marked "//the back"? 
> Any pointers welcome.

  I don't know how much you know about programming, but #macros take their
parameters by reference.
  That means that the macro does not get a copy of the thing you give it
as a parameter, but a reference, that is, a kind of "pointer" which points
to the original thing.
  This means that if you give it an identifier, any modification the macro
makes to the parameter (even if it's done with #local) will be made to
the original identifier.
  If you want to avoid a macro modifying its parameter, make a copy of it.
That is, instead of:

#macro Foo(param)
  #while(param)
    ...
    #local param = param-1;
  #end
#end

do this:

#macro Foo(param)
  #local index = param;
  #while(index)
    #local index = index-1;
  #end
#end

  (Btw, if you give an expression as parameter to a macro, a temporary
variable will be created and the reference will point to that, and
the temporary variable is destroyed after the macro call is over. That's
why it's ok to use expressions as parameters, eg Foo(a+b-1).
  This has a curious side-effect that if you make a call like Foo((identifier))
that's an expression and not the identifier directly and thus the value of
the identifier will be copied to a temporary variable and the macro will not
modify the original identifier. However, it's better to make the macro
itself safe and not trust that the caller takes care.)

-- 
plane{-x+y,-1pigment{bozo color_map{[0rgb x][1rgb x+y]}turbulence 1}}
sphere{0,2pigment{rgbt 1}interior{media{emission 1density{spherical
density_map{[0rgb 0][.5rgb<1,.5>][1rgb 1]}turbulence.9}}}scale
<1,1,3>hollow}text{ttf"timrom""Warp".1,0translate<-1,-.1,2>}//  - Warp -


Post a reply to this message

From: Kaveh Bazargan
Subject: Re: macro argument help
Date: 28 May 2004 08:27:16
Message: <40b73024@news.povray.org>
On 2004-05-28 13:13:44 +0100, Warp <war### [at] tagpovrayorg> said:

[...]


>   This means that if you give it an identifier, any modification the macro
> makes to the parameter (even if it's done with #local) will be made to
> the original identifier.

This is completely new to me. I will try and read up on this, as it is 
a fundamental point. Thanks for the lucid explanation.

The solution worked by the way. :-)


Post a reply to this message

From: Christopher James Huff
Subject: Re: macro argument help
Date: 28 May 2004 08:28:26
Message: <cjameshuff-141A45.07285928052004@news.povray.org>
In article <40b71634@news.povray.org>,
 Kaveh Bazargan <kav### [at] delete_thisfocalimagecom> wrote:

> I think there is a fundamental point here about macro arguments which I 
> need to learn. Why is segments zero in the line marked "//the back"? 
> Any pointers welcome.

Because you set it to 0 in the loop in sofa_seat(). Variables are passed 
"by reference", the macro can modify its parameters. Use something more 
like this:
#macro Sofa_Seat(Cushion_wd, Segments)  //calls Cushion
  union{
    #local Segs = Segments;
    #while (Segs > 0)
      object {Cushion(Cushion_wd, Cushion_dp, Cushion_ht) 
              translate (Segs-1)*Cushion_wd*x}
      #local Segs = Segs - 1;
    #end //while
  }
#end //macro Sofa_Seat 

Notice I made some naming changes...you should always use at least one 
capitalized letter in variable names in POV. Unlike other programming 
languages, the POV-Ray language has frequent additions, and doing so 
will avoid any problems with name conflicts. For example, a POV 3.1 
scene using the word "size" for a variable will not work with current 
versions, which use that word in the facets pattern. Keywords can be 
relied on to always be lower case.

-- 
Christopher James Huff <cja### [at] earthlinknet>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: <chr### [at] tagpovrayorg>
http://tag.povray.org/


Post a reply to this message

From: Kaveh Bazargan
Subject: Re: macro argument help
Date: 28 May 2004 11:26:20
Message: <40b75a1b@news.povray.org>
On 2004-05-28 13:28:59 +0100, Christopher James Huff 
<cja### [at] earthlinknet> said:

> 
> [...]
> 
> Notice I made some naming changes...you should always use at least one 
> capitalized letter in variable names in POV. Unlike other programming 
> [...]
> 
> 

I appreciate the time you both took to reply. I have learnt a 
fundamental point about programming!! And I didn't know about the 
capital letter hint. I'll do that henceforth.


Post a reply to this message

From: Stephen
Subject: Re: macro argument help
Date: 28 May 2004 16:21:45
Message: <40b79f59$1@news.povray.org>
I learned this the hard way after lots of testing. And I discovered the
trick for ...

>> This has a curious side-effect that if you make a call like
Foo((identifier))

where I used Foo( +param) instead.  I feel like an expert now (although soon
to be challenged yet again).
So it really is in the documentation, but sometimes a quick nudge in the
right direction helps a lot.

Thanks for the clear explanation.

Stephen


"Warp" <war### [at] tagpovrayorg> wrote in message
news:40b72cf8@news.povray.org...
> Kaveh Bazargan <kav### [at] delete_thisfocalimagecom> wrote:
> > I think there is a fundamental point here about macro arguments which I
> > need to learn. Why is segments zero in the line marked "//the back"?
> > Any pointers welcome.
>
>   I don't know how much you know about programming, but #macros take their
> parameters by reference.
>   That means that the macro does not get a copy of the thing you give it
> as a parameter, but a reference, that is, a kind of "pointer" which points
> to the original thing.
>   This means that if you give it an identifier, any modification the macro
> makes to the parameter (even if it's done with #local) will be made to
> the original identifier.
>   If you want to avoid a macro modifying its parameter, make a copy of it.
> That is, instead of:
>
> #macro Foo(param)
>   #while(param)
>     ...
>     #local param = param-1;
>   #end
> #end
>
> do this:
>
> #macro Foo(param)
>   #local index = param;
>   #while(index)
>     #local index = index-1;
>   #end
> #end
>
>   (Btw, if you give an expression as parameter to a macro, a temporary
> variable will be created and the reference will point to that, and
> the temporary variable is destroyed after the macro call is over. That's
> why it's ok to use expressions as parameters, eg Foo(a+b-1).
>   This has a curious side-effect that if you make a call like
Foo((identifier))
> that's an expression and not the identifier directly and thus the value of
> the identifier will be copied to a temporary variable and the macro will
not
> modify the original identifier. However, it's better to make the macro
> itself safe and not trust that the caller takes care.)
>
> -- 
> plane{-x+y,-1pigment{bozo color_map{[0rgb x][1rgb x+y]}turbulence 1}}
> sphere{0,2pigment{rgbt 1}interior{media{emission 1density{spherical
> density_map{[0rgb 0][.5rgb<1,.5>][1rgb 1]}turbulence.9}}}scale
> <1,1,3>hollow}text{ttf"timrom""Warp".1,0translate<-1,-.1,2>}//  - Warp -


Post a reply to this message

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