|
|
|
|
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> Good idea; although in my case it's more of a visual result-- like the bumps
> pattern affecting an isosurface. I have no clue as to how debug might be used
> there.
Well, there are a number of ways that you can do these things.
you always do #declare A = function {pigment {bumps}}
and then use that to calculate numbers for your debug stream.
Another I do a lot is make a graph along one axis (usually x).
That way I can cycle through X with a loop, calculate the result, and make a
little sphere at <X, Result, 0> to see WTH is going on.
> That's really neat, and useful. I *still* struggle with understanding the finer
> points of function use. Your examples (here and through the years) have been a
> godsend...if I can only remember them!
Well, thanks - but remember, the only reason I got "this good" is because jr had
that media project, and Bill Pokorny walked me through a lot of the practical
details of using functions, and then I just practiced, practiced, practiced.
> In my current code project, many are the
> times that I came up with a workable solution only by sheer trial-and-error,
> discarding one failed attempt after another. It's like trying to discern the
> finer points of a 'foreign language' when I don't know or remember the subtle
> underlying rules, from lack of practice.
Absolutely. Don't think that I don't do exactly the same thing ALL THE TIME.
The key, really, is looking at any given function and asking "what do the things
inside the curly braces need to be fully evaluated"?
And often, that's a matter of going back one daisy-chained function and asking
the same thing. And then doing that again.
Because if you have A which needs X, and B which needs Y, and C which needs Z,
and D which needs W, then if you have A(B(C(D()))), your function A needs: A
(X, Y, Z, W) {}, and so on, as you go further down into the curly braces.
It can be mind-bending, and a real mess on the screen, but going through the
simpler functions and making the mistakes that are easier to track down because
there are fewer places for the error to be allows you to learn to "think ahead"
and keep a running tab of things that could/usually go wrong. Notes in the code
or on paper usually help me remember what the cryptic POV-Ray error heiroglyphs
actually MEAN in a practical sense.
The other thing that helps to work this all out in your head is to not delete
code that doesn't work. Otherwise you wind up coding the same mistakes over
and over again.
Do a #switch #case #break #end block, and copy-paste #case 1 into #case 2 and
then edit case 2. If that fails, work on case 3. That way you have a running
documentation of what you've tried, what the results look like, notes on why it
failed, what worked, etc.
You can then copy-paste the working code into a new scene that just works, but
retain that developmental test scene for your records. Heck, post it here, so
that people struggling with the same issues can follow along and really see how
one goes from fail to success. What doesn;t work is often more important to
know than what does, since there's so much more of it to go wading through.
Glad you're getting it all to work out.
- BW
Post a reply to this message
|
|
| |
| |
|
|
From: Alain Martel
Subject: Re: isosurface: Does the order of multiple functions matter?
Date: 28 Jan 2023 12:27:51
Message: <63d55b17$1@news.povray.org>
|
|
|
| |
| |
|
|
Le 2023-01-28 à 05:25, Kenneth a écrit :
> I have an isosuface made from multiple functions that is working quite nicely--
> but I want to rearrange the order of the functions to see the different(?)
> results. The code is complex, so I'll leave out the ugly function details and
> syntax. The following is just pseudo code.
>
> Right now, it is like this (very simplified):
> isosurface{
> function{A + B + C + D}
> ....
> }
>
> Only four, thankfully! :-)
>
> Does the order of the functions matter when POV-ray evaluates them? Or are they
> evaluated 'all at once' regardless of the order?
>
> If the ordering does matter, what would be the most efficient way to set up
> 'switches' at the beginning of the scene to easily change the order of A,B,C and
> D? Possibilities that occur to me would be some kind of combination of
> #switch/#case, or #if blocks, or select(?), or maybe an array; but I want the
> top-of-code selection process to be relatively easy-- something like
> #declare FUNCTION_ORDER= <C,A,D,B>;
> .... and without having to make multiple copies of the functions for all of the
> different permutations.
>
> Any ideas?
>
> (BTW: #if and #switch/#case do work well in the body of the isosurface, within
> the main function, to at least eliminate certain parts. Probably not good code
> practice, but it causes no problems AFAIK.)
>
The order should have no effect in this case. As long as you have all
additions or all multiplications, shuffling the terms won't change the
end result.
BUT, remember that A-B is different from B-A and A/B is also different
from B/A.
Post a reply to this message
|
|
| |
| |
|
|
From: Cousin Ricky
Subject: Re: isosurface: Does the order of multiple functions matter?
Date: 28 Jan 2023 12:40:02
Message: <63d55df2$1@news.povray.org>
|
|
|
| |
| |
|
|
On 2023-01-28 06:25 (-4), Kenneth wrote:
>
> isosurface{
> function{A + B + C + D}
> ....
> }
>
> Only four, thankfully! :-)
>
> Does the order of the functions matter when POV-ray evaluates them? Or are they
> evaluated 'all at once' regardless of the order?
<soapbox>
It is dangerous programming practice to rely on order of evaluation,
unless the language definition explicitly specifies it. POV-Ray has no
such specification.
</soapbox>
In your context, it does not appear that the order makes any difference,
because functions in POV-Ray cannot have side effects. Of course,
liberal use of parentheses will guarantee *precedence* of evaluation,
but this has limited effect on the *order* of evaluation.
> (BTW: #if and #switch/#case do work well in the body of the isosurface, within
> the main function, to at least eliminate certain parts. Probably not good code
> practice, but it causes no problems AFAIK.)
Directives (#if, #switch, etc.) in functions are parsed only once, when
the function is defined. Directives in functions that are coded in-line
in an isosurface will be observed each time the object is parsed, but
directives in any pre-defined functions used in the isosurface will not
be re-parsed.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Cousin Ricky <ric### [at] yahoocom> wrote:
> On 2023-01-28 06:25 (-4), Kenneth wrote:
> > (BTW: #if and #switch/#case do work well in the body of the isosurface, within
> > the main function, to at least eliminate certain parts. Probably not good code
> > practice, but it causes no problems AFAIK.)
>
> Directives (#if, #switch, etc.) in functions are parsed only once, when
> the function is defined. Directives in functions that are coded in-line
> in an isosurface will be observed each time the object is parsed, but
> directives in any pre-defined functions used in the isosurface will not
> be re-parsed.
Say what now?
I missed this in the first skim-through.
I'll be trying this out at some point - but I'd like to see a working code
example! (Considering that I had no idea this was possible)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
>
> The other thing that helps to work this all out in your head is to not delete
> code that doesn't work. Otherwise you wind up coding the same mistakes over
> and over again.
Absolutely! My current real scene code is full of commented-out sections that
failed, along with notes as to why (well, at least at my current level of
understanding, ha.) Unfortunately, much of my 'knowledge' is currently spread
through hundreds of my previous files, so I have to think hard as to *where* I
might have put a particularly useful note.
Your own method of adding accumulated tidbits of knowledge into a spreadsheet--
like a 'library' of known facts-- is the envy of the modern world. ;-) Alas, I
have not gotten around to implementing that major 'tuit.
>
> Do a #switch #case #break #end block, and copy-paste #case 1 into #case 2 and
> then edit case 2. If that fails, work on case 3. That way you have
> a running documentation of what you've tried, what the results look like,
> notes on why it failed, what worked, etc... What doesn't work is often more
> important to know than what does.
Exactly, Northern Cousin Walker. Excellent advice.
> If you have A which needs X, and B which needs Y, and C which needs Z,
> and D which needs W, then if you have A(B(C(D()))), your function A needs: A
> (X, Y, Z, W) {}, and so on, as you go further down into the curly braces.
This is the concept that I have the most trouble understanding...although I'm
making slow progress.
My apologies for going a bit off-topic here, but I was recently going through
someone else's old code that uses this idea brilliantly-- it's very complex,
with nested functions-- and I *think* I came across a particular section that I
don't fully understand.
Using your example: When A(X,Y,Z,W){} is the major function, I would imagine
that *all* of these variables (arguments?) in the body of the function would, at
some point in the code, have to be replaced with some actual value or other
pre-#declared variable. In almost all of the instances of X,Y,Z and W, that is
so. But in one section, there appears to be just W-- used as-is and not with any
substitution. (Sorry if I'm not describing this understandably.) AFAICT, there
is nowhere in the entire scene code that has *something* pre-declared for W. So
in this case, what does that 'naked' W represent? The code *works* of course--
and I've tried substituting actual float values for that one mysterious instance
of W, in my usual fumbling trial-and-error way...but with always-fatal results.
If indeed that one W is 'naked' so to speak, and I haven't made a stupid error
in detecting a substitution for it, then how does it work successfully? If I
could figure *that* out, it would certainly expand my understanding of POV-ray's
function use.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> "Bald Eagle" <cre### [at] netscapenet> wrote:
>
> > If you have A which needs X, and B which needs Y, and C which needs Z,
> > and D which needs W, then if you have A(B(C(D()))), your
> > function A needs: A(X, Y, Z, W) {}, and so on, as you go further down
> > into the curly braces.
>
> My apologies for going a bit off-topic here, but I was recently going through
> someone else's old code that uses this idea brilliantly-- it's very complex,
> with nested functions-- and I *think* I came across a particular section
> that I don't fully understand.
>
To be specific, it's in William Pokorny's "ObjectAslso" file from Sept. 19 2009,
if you would like to take a look (no pressure, of course.) In his file called
"ObjectAslso.inc", there is a function argument called 'S'. I have a hard time
following the code because of its complexity, but I can't see where one (or
more) of the instances of that argument are assigned a value of any kind. I
could be wrong *of course*; maybe I'm just not seeing the forest for the trees--
or vice-versa!
https://news.povray.org/povray.binaries.scene-files/thread/%3Cweb.4aae23151285f23f15ee2c550%40news.povray.org%3E/
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Cousin Ricky <ric### [at] yahoocom> wrote:
>
> <soapbox>
> It is dangerous programming practice to rely on order of evaluation,
> unless the language definition explicitly specifies it. POV-Ray has no
> such specification.
> </soapbox>
>
> In your context, it does not appear that the order makes any difference,
> because functions in POV-Ray cannot have side effects. Of course,
> liberal use of parentheses will guarantee *precedence* of evaluation,
> but this has limited effect on the *order* of evaluation.
>
I can't say that I really understand those distinctions, conceptually. In any
case, my attempts so far at sprinkling parentheses "here, there, and eveywhere"
in my simplistic example code has had no effect; the order of the isosurface's
inner functions still shows no visible difference when changed around.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
>
> The other thing that helps to work this all out in your head is to not delete
> code that doesn't work. Otherwise you wind up coding the same mistakes over
> and over again.
>
>..That way you have a running documentation of what you've tried, ..., why it
> failed, what worked, etc. Heck, post it here, so
> that people struggling with the same issues can follow along and really
> see how one goes from fail to success...
Well, since you mentioned it... :-)
[more off-topic stuff, sorry!]
In my current real scene, I'm using the 'object pattern' to make an isosurface
shape, necessarily using functions. Here is a somewhat simplified version of a
problem I had:
#declare OBJ_PATTERN_FUNC = function{pigment{object{MY_OBJECT rgb 0 rgb 1}}}
#declare PIG_DISTORTION_FUNC = function{pigment{bumps scale .2}}
#declare MAG = 1.5; // the magnitude of the bumps distortion to be added
This is how I originally wrote my main function:
isosurface{function{
1 - (OBJ_PATTERN_FUNC(
x + MAG*PIG_DISTORTION_FUNC (x,y,z).x - .5*MAG,
y + MAG*PIG_DISTORTION_FUNC (x,y,z).y - .5*MAG,
z + MAG*PIG_DISTORTION_FUNC (x,y,z).z - .5*MAG
).gray)
} ... }
This worked-- but the resulting bumps distortion had a spatial 'skew' aligned
along <1,1,1>, which *finally* became understandable because I was using full
(x,y,z) in all 3 inner functions. (I had to do that to solve other problems that
I ran into, up to this point.) But substituting 0.0 for the appropriate
'un-needed' x,y,z arguments resulted in *very* strange isosurface effects.
So I came up with this solution, which nicely fixed the skew--by subtracting the
'offending' arguments from 1.0. But I have NO idea why it works. I finally
arrived at it through pure chance and desperation:
isosurface{function{
1 - (OBJ_PATTERN_FUNC(
x + MAG*PIG_DISTORTION_FUNC (x,1-y,1-z).x - .5*MAG,
y + MAG*PIG_DISTORTION_FUNC (1-x,y,1-z).y - .5*MAG,
z + MAG*PIG_DISTORTION_FUNC (1-x,1-y,z).z - .5*MAG
).gray)
} ...}
Maybe this is a special-case solution because of the object pattern scheme? I
don't know.
Post a reply to this message
|
|
| |
| |
|
|
From: Thomas de Groot
Subject: Re: isosurface: Does the order of multiple functions matter?
Date: 29 Jan 2023 02:21:20
Message: <63d61e70$1@news.povray.org>
|
|
|
| |
| |
|
|
Op 28/01/2023 om 19:20 schreef Bald Eagle:
> Cousin Ricky <ric### [at] yahoocom> wrote:
>> On 2023-01-28 06:25 (-4), Kenneth wrote:
>
>>> (BTW: #if and #switch/#case do work well in the body of the isosurface, within
>>> the main function, to at least eliminate certain parts. Probably not good code
>>> practice, but it causes no problems AFAIK.)
>>
>> Directives (#if, #switch, etc.) in functions are parsed only once, when
>> the function is defined. Directives in functions that are coded in-line
>> in an isosurface will be observed each time the object is parsed, but
>> directives in any pre-defined functions used in the isosurface will not
>> be re-parsed.
>
> Say what now?
>
> I missed this in the first skim-through.
>
> I'll be trying this out at some point - but I'd like to see a working code
> example! (Considering that I had no idea this was possible)
>
Hmmmmm.... this makes sense, somehow, but I guess this behaviour could
produce unexpected results, with no clue of /where/ the diverging
behaviour would come from (if unaware of this behaviour).
--
Thomas
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
>...
> [more off-topic stuff, sorry!]
> In my current real scene, I'm using the 'object pattern' to make an isosurface
> shape, necessarily using functions. Here is a somewhat simplified version of a
> problem I had:
>...
> #declare OBJ_PATTERN_FUNC = function{pigment{object{MY_OBJECT rgb 0 rgb 1}}}
> #declare PIG_DISTORTION_FUNC = function{pigment{bumps scale .2}}
> #declare MAG = 1.5; // the magnitude of the bumps distortion to be added
>
> This is how I originally wrote my main function:
>
> isosurface{function{
> 1 - (OBJ_PATTERN_FUNC(
> x + MAG*PIG_DISTORTION_FUNC (x,y,z).x - .5*MAG,
> y + MAG*PIG_DISTORTION_FUNC (x,y,z).y - .5*MAG,
> z + MAG*PIG_DISTORTION_FUNC (x,y,z).z - .5*MAG
> ).gray)
> } ... }
>
> This worked-- but the resulting bumps distortion had a spatial 'skew' aligned
> along <1,1,1>, which *finally* became understandable because I was using full
> (x,y,z) in all 3 inner functions. (I had to do that to solve other problems that
> I ran into, up to this point.) But substituting 0.0 for the appropriate
> 'un-needed' x,y,z arguments resulted in *very* strange isosurface effects.
>
> So I came up with this solution, which nicely fixed the skew--by subtracting the
> 'offending' arguments from 1.0. But I have NO idea why it works. I finally
> arrived at it through pure chance and desperation:
>
> isosurface{function{
> 1 - (OBJ_PATTERN_FUNC(
> x + MAG*PIG_DISTORTION_FUNC (x,1-y,1-z).x - .5*MAG,
> y + MAG*PIG_DISTORTION_FUNC (1-x,y,1-z).y - .5*MAG,
> z + MAG*PIG_DISTORTION_FUNC (1-x,1-y,z).z - .5*MAG
> ).gray)
> } ...}
>
> Maybe this is a special-case solution because of the object pattern scheme? I
> don't know.
I recommend that you use pattern functions here instead of pigment
functions. That is because the pigments you use here always has the
same values for the red, green and blue components (extracted with
...red .green .blue or .x .y .z) The gray component will then also
have the same value as the red, green and blue components.
You can then write your declared functions like this:
#declare OBJECT_FUNC =
function {
pattern {
object { MY_OBJECT }
}
}
;
#declare DISTORTION_FUNC =
function {
pattern {
bumps
scale <0.2, 0.2, 0.2>
}
}
;
I suspect that the reason that the "skew" disappears when using your
"desperation" code is that there you are "sampling" the
PIG_DISTORTION_FUNC at different locations in 3D space for each of
the red, green and blue components (.x .y .z), This causes the 3
components to have different values. When you set some of the
arguments to the PIG_DISTORTION_FUNC function to zero, you where
either "sampling" this function in a plane, along a line or at a point.
With pattern functions you can rewrite your isosurface function like
this:
function {
1 -
OBJECT_FUNC(
x + MAG*(DISTORTION_FUNC( x, 1 - y, 1 - z) - 0.5),
y + MAG*(DISTORTION_FUNC(1 - x, y, 1 - z) - 0.5),
z + MAG*(DISTORTION_FUNC(1 - x, 1 - y, z) - 0.5)
)
}
--
Tor Olav
http://subcube.com
https://github.com/t-o-k
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|