POV-Ray : Newsgroups : povray.beta-test : Function weirdness Server Time
31 Jul 2024 02:26:25 EDT (-0400)
  Function weirdness (Message 1 to 8 of 8)  
From: Slime
Subject: Function weirdness
Date: 17 Sep 2001 21:01:30
Message: <3ba69cea$1@news.povray.org>
I have this simple function...

function {
     #local normvec = vnormalize(x,y,z);
     vlength(normvec)+f_noise3d(normvec.x,normvec.y,normvec.z)-1
}

I'm trying to get the normal vector of the current x,y,z coordinate being
tested, but it appears to think i'm referring to the variables x=<1,0,0>,
y=<0,1,0>, and z=<0,0,1>, so it gives me the error "Parse Error: Expected
')', , found instead" on the line with the "local" statement.

Is this a bug, or do I need to do this some other way? Trying
#local normlen = sqrt(x^2+y^2+z^2)
also caused an error.

- Slime
[ http://www.teja.nu/slime/ ]
[ http://www.teja.nu/slime/images ]


Post a reply to this message

From: Ron Parker
Subject: Re: Function weirdness
Date: 17 Sep 2001 21:59:34
Message: <slrn9qdak6.2hj.ron.parker@fwi.com>
On Mon, 17 Sep 2001 21:00:30 -0400, Slime wrote:
>I have this simple function...
>
>function {
>     #local normvec = vnormalize(x,y,z);
>     vlength(normvec)+f_noise3d(normvec.x,normvec.y,normvec.z)-1
>}
>
>I'm trying to get the normal vector of the current x,y,z coordinate being
>tested, but it appears to think i'm referring to the variables x=<1,0,0>,
>y=<0,1,0>, and z=<0,0,1>, so it gives me the error "Parse Error: Expected
>')', , found instead" on the line with the "local" statement.
>
>Is this a bug, or do I need to do this some other way? Trying
>#local normlen = sqrt(x^2+y^2+z^2)
>also caused an error.

#local doesn't do what you think it does in a function: it gets evaluated
when the scene file is parsed, not when the function is called.

--
#macro R(L P)sphere{L __}cylinder{L P __}#end#macro P(_1)union{R(z+_ z)R(-z _-z)
R(_-z*3_+z)torus{1__ clipped_by{plane{_ 0}}}translate z+_1}#end#macro S(_)9-(_1-
_)*(_1-_)#end#macro Z(_1 _ __)union{P(_)P(-_)R(y-z-1_)translate.1*_1-y*8pigment{
rgb<S(7)S(5)S(3)>}}#if(_1)Z(_1-__,_,__)#end#end Z(10x*-2,.2)camera{rotate x*90}


Post a reply to this message

From: Mike Williams
Subject: Re: Function weirdness
Date: 18 Sep 2001 01:45:19
Message: <1ItGvGAX4qp7Ew7n@econym.demon.co.uk>
Wasn't it Slime who wrote:
>I have this simple function...
>
>function {
>     #local normvec = vnormalize(x,y,z);
>     vlength(normvec)+f_noise3d(normvec.x,normvec.y,normvec.z)-1
>}
>
>I'm trying to get the normal vector of the current x,y,z coordinate being
>tested, but it appears to think i'm referring to the variables x=<1,0,0>,
>y=<0,1,0>, and z=<0,0,1>, so it gives me the error "Parse Error: Expected
>')', , found instead" on the line with the "local" statement.
>
>Is this a bug, or do I need to do this some other way? 


That all looks perfectly correct processing to me. x, y and z have
always meant the unit vectors when they appear in #declare and #local
statements, and I wouldn't expect that to change just because the
assignment happens inside a function block.

Unfortunately, you can't even do things like the following, because the
vlength() and vnormalize() are not supported in the syntax of user
defined functions (see 6.1.6)

function {
     vlength(vnormalize(x,y,z))
     + f_noise3d(vnormalize(x,y,z).x, vnormalize(x,y,z).y,
     vnormalize(x,y,z).z)-1
}


#declare F_normvec = function{vnormalize(x,y,z)}
function {
     vlength(F_normvec(x,y,z))
     + f_noise3d(F_normvec(x,y,z).x, F_normvec(x,y,z).y,       
     F_normvec(x,y,z).z)-1
}

You're allowed to do assignments within a function block, so that you
can do things like managing loops, but you can't use the assignments as
a sneaky way to perform operations that the function syntax itself
doesn't allow.



>Trying #local normlen = sqrt(x^2+y^2+z^2) also caused an error.

Try something like this:

#declare F_normlen=function{sqrt(x^2+y^2+z^2)}
function {F_normlen(x,y,z)}

You can also replace "vlength(vnormalize(x,y,z))" by "1", since a
normalized vector is always of unit length.

-- 
Mike Williams
Gentleman of Leisure


Post a reply to this message

From: Warp
Subject: Re: Function weirdness
Date: 18 Sep 2001 04:37:02
Message: <3ba707ad@news.povray.org>
Repeat after me: A function is not a macro.

  The difference might not be completely clear at first, but it's an important
difference.
  A #local-command is a parse-time command used mainly in macros. Functions
do not work this way.

-- 
#macro N(D,I)#if(I<6)cylinder{M()#local D[I]=div(D[I],104);M().5,2pigment{
rgb M()}}N(D,(D[I]>99?I:I+1))#end#end#macro M()<mod(D[I],13)-6,mod(div(D[I
],13),8)-3,10>#end blob{N(array[6]{11117333955,
7382340,3358,3900569407,970,4254934330},0)}//                     - Warp -


Post a reply to this message

From: Slime
Subject: Re: Function weirdness
Date: 19 Sep 2001 00:21:40
Message: <3ba81d54$1@news.povray.org>
Yeah, it makes sense now... I wish there were some way to force the function
to store a value just so that the same value doesn't have to be calculated
multiple times. That could speed up rendering, probably. I ended up doing
this for my function:

    function { sqrt((x/scalex)^2+(y/scaley)^2+(z/scalez)^2)/baseradius +
     f_noise3d(x/sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)*noisedetail
+ rndx,
         y/sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)*noisedetail +
rndy,
         z/sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)*noisedetail +
rndz
     )*noiseamnt-1
    }

This created the intended effect. Its just that
sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2) is calculated three times in
the whole thing, and I'd imagine with all the division, exponentation, and
square-rooting, it's slowing down the render significantly. I guess there's
no real other way though.

(note that all the variables in that like scalex, scalenx, noisedetail,
rndx, noiseamnt, and others are all predefined elsewhere in my code.)

- Slime
[ http://www.teja.nu/slime/ ]
[ http://www.teja.nu/slime/images/ ]

"Warp" <war### [at] tagpovrayorg> wrote in message
news:3ba707ad@news.povray.org...
>   Repeat after me: A function is not a macro.
>
>   The difference might not be completely clear at first, but it's an
important
> difference.
>   A #local-command is a parse-time command used mainly in macros.
Functions
> do not work this way.
>
> --
> #macro N(D,I)#if(I<6)cylinder{M()#local D[I]=div(D[I],104);M().5,2pigment{
> rgb M()}}N(D,(D[I]>99?I:I+1))#end#end#macro M()<mod(D[I],13)-6,mod(div(D[I
> ],13),8)-3,10>#end blob{N(array[6]{11117333955,
> 7382340,3358,3900569407,970,4254934330},0)}//                     - Warp -


Post a reply to this message

From: Mike Williams
Subject: Re: Function weirdness
Date: 19 Sep 2001 02:43:43
Message: <$hFUlAA7zDq7EwRs@econym.demon.co.uk>
Wasn't it Slime who wrote:
>Yeah, it makes sense now... I wish there were some way to force the function
>to store a value just so that the same value doesn't have to be calculated
>multiple times. That could speed up rendering, probably. I ended up doing
>this for my function:
>
>    function { sqrt((x/scalex)^2+(y/scaley)^2+(z/scalez)^2)/baseradius +
>     f_noise3d(x/sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)*noisedetail
>+ rndx,
>         y/sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)*noisedetail +
>rndy,
>         z/sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)*noisedetail +
>rndz
>     )*noiseamnt-1
>    }

You can certainly write it more clearly as 

#declare F = function{sqrt((x/scalenx)^2+(y/scaleny)^2+(z/scalenz)^2)}
#declare G = function{sqrt((x/scalex)^2 +(y/scaley)^2 +(z/scalez)^2)}

function { G(x,y,z)/baseradius 
   + f_noise3d(x/F(x,y,z)*noisedetail + rndx,         
               y/F(x,y,z)*noisedetail + rndy,
               z/F(x,y,z)*noisedetail + rndz
   )*noiseamnt-1
}

This way it's easier to read, takes just about the same amount of time,
produces exactly the same output, and crashes in exactly the same place
when you try to divide by zero at the origin.

-- 
Mike Williams
Gentleman of Leisure


Post a reply to this message

From:
Subject: Re: Function weirdness
Date: 19 Sep 2001 04:41:56
Message: <5ulgqtgutqlojtjetl847g1r4s3rven3tn@4ax.com>
On Wed, 19 Sep 2001 00:20:42 -0400, "Slime" <noo### [at] hotmailcom>
wrote:

> Yeah, it makes sense now... I wish there were some way to force the function
> to store a value just so that the same value doesn't have to be calculated
> multiple times.

but you can do that !
just take another level of function

imagine - you want something like (in your expected notation)

#declare MyFunc=function(x,y,z){
  #local A=x+y+z;
  #local B=max3(x,y,z);
  (A*x/B)+(A*y/B)+(A*z/B)
} // I don't know what's this expression feel free to test

this can't work, but you can replace this with two declarations

#declare WithLocals=function(x,y,z,A,B){
  (A*x/B)+(A*y/B)+(A*z/B)
}
#declare MyFunc=function(x,y,z){WithLocals(x,y,z,x+y+z,max3(x,y,z))}

I don't know 3.5 engine yet but I think it causes one calculation of
such local variables.

ABX


Post a reply to this message

From: Thorsten Froehlich
Subject: Re: Function weirdness
Date: 19 Sep 2001 11:45:39
Message: <3ba8bda3@news.povray.org>

Skiba <abx### [at] babilonorg>  wrote:

> #declare MyFunc=function(x,y,z){
>   #local A=x+y+z;
>   #local B=max3(x,y,z);
>   (A*x/B)+(A*y/B)+(A*z/B)
> } // I don't know what's this expression feel free to test
>
> this can't work, but you can replace this with two declarations
>
> #declare WithLocals=function(x,y,z,A,B){
>   (A*x/B)+(A*y/B)+(A*z/B)
> }
> #declare MyFunc=function(x,y,z){WithLocals(x,y,z,x+y+z,max3(x,y,z))}
>
> I don't know 3.5 engine yet but I think it causes one calculation of
> such local variables.

While this should work, I would only recommend it for really complex cases
(more than 20 or so operators) because function calls are in many cases more
"expensive" than just calculating the value over and over again (which can
be optimised, btw).

    Thorsten

____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde

Visit POV-Ray on the web: http://mac.povray.org


Post a reply to this message

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