





 
 




 
 


"Bald Eagle" <cre### [at] netscapenet> wrote:
> I figure I'll put this here, rather than embedding it in the midst of other
> threads.
>
> I'm currently working out some code to create some piecewise functions with
> very specific constraints.
>
> During development, I noticed some odd mismatches, seemingly resulting from the
> manner in which 3argument select () statements work.
>
> Using the 4argument form and (repeating the equation to evaluate after a comma)
> doesn't seem to correct this.
>
> Specifically, each section of the piecewise function never reaches the end of
> its domain, and instead, the next section of the nested select statement starts
> getting evaluated.
> I shifted the 2nd segment up a bit to illustrate the problem in the attached
> image. (disregard the file name)
I'm sorry Bill, but you have to provide some more information for us about
what you are doing here.
> https://wiki.povray.org/content/Reference:Numeric_Expressions
> select(A, B, C [,D])
> It can be used with three or four parameters Select compares the first argument
> with zero, depending on the outcome it will return B, C or D. A,B,C,D can be
> floats or fun(c)tions.
> When used with three parameters, if A < 0 it will return B, else C (A >= 0).
> When used with four parameters, if A < 0 it will return B. If A = 0 it will
> return C. Else it will return D (A > 0).
>
>
>
> Maybe that's something that I'm doing wrong, or maybe there's a hidden issue
> with select () that's never been uncovered yet.
>...
> But it did make me think that there ought to be a way to reverse which "side" of
> the evaluation A = 0 gets included in:
>...
There already is a way:
select(A, B, C)
A < 0: return B
A = 0: return C
A > 0: return C
select(A, C, B)
A < 0: return B
A = 0: return B
A > 0: return C
select(E  F, G, H)
E < F: return G
E = F: return H
E > F: return H
select(F  E, H, G)
E < F: return G
E = F: return G
E > F: return H

Tor Olav
http://subcube.com
https://github.com/tok
Post a reply to this message


 
 




 
 


"Bald Eagle" <cre### [at] netscapenet> wrote:
> William F Pokorny <ano### [at] anonymousorg> wrote:
>
> > Assuming you want access to the real internally generated >first rays,
>
> Nope.
> Just something like:
>
> #declare SFn_vdot = function (ax, ay, az, bx, by, bz) {ax*bx + ay*by + az*bz}
>
> #declare f_Reflectionx = function (Dx, Dy, Dz, Nx, Ny, Nz) {Dx  2 * SFn_vdot
> (Dx, Dy, Dz, Nx, Ny, Nz)* Nx}
> #declare f_Reflectiony = function (Dx, Dy, Dz, Nx, Ny, Nz) {Dy  2 * SFn_vdot
> (Dx, Dy, Dz, Nx, Ny, Nz)* Ny}
> #declare f_Reflectionz = function (Dx, Dy, Dz, Nx, Ny, Nz) {Dz  2 * SFn_vdot
> (Dx, Dy, Dz, Nx, Ny, Nz)* Nz}
>...
You are already thinking in the right ways...
To see how you can use that further, have a look here:
Subject: Source code for "With and without a light_source"
From: Tor Olav Kristensen
Date: 20030623 18:20:41
https://news.povray.org/povray.text.scenefiles/message/%3CXns93A54E262AE2torolavkhotmailcom%40204.213.191.226%3E
There's no vector cross expressions there. But that will require only 3 small
exressions.

Tor Olav
http://subcube.com
https://github.com/tok
Post a reply to this message


 
 




 
 


"Bald Eagle" <cre### [at] netscapenet> wrote:
>...
> With regard to the current shader, I've run into quite a number of stumbling
> blocks that highlight the deeply ingrained problems and limitations of the
> function parser. I'm not saying that Thorsten didn't do a good job  it's just
> that what we have isn't really adequate to the tasks I would (reasonably) like
> to accomplish, and isn't conducive to moving forward toward 4.0.
>
> When evaluating a pattern, things need to be coded in a certain "static" way.
> What one might do in a macro  declaring variables to store intermediate
> calculation results  isn't possible with functions.
>...
To not have variables in functions is not necessarily a showstopper.
It just requires you to rewire your brain to program in a more "functional" way.
;)
A lot of people struggle with this when they start programming in functional
languages.

Tor Olav
http://subcube.com
https://github.com/tok
Post a reply to this message


 
 




 
 


On 12/27/23 19:13, Tor Olav Kristensen wrote:
> "Bald Eagle" <cre### [at] netscapenet> wrote:
>> William F Pokorny <ano### [at] anonymousorg> wrote:
>>
>>> Assuming you want access to the real internally generated >first rays,
>>
>> Nope.
>> Just something like:
>>
>> #declare SFn_vdot = function (ax, ay, az, bx, by, bz) {ax*bx + ay*by + az*bz}
>>
>> #declare f_Reflectionx = function (Dx, Dy, Dz, Nx, Ny, Nz) {Dx  2 * SFn_vdot
>> (Dx, Dy, Dz, Nx, Ny, Nz)* Nx}
>> #declare f_Reflectiony = function (Dx, Dy, Dz, Nx, Ny, Nz) {Dy  2 * SFn_vdot
>> (Dx, Dy, Dz, Nx, Ny, Nz)* Ny}
>> #declare f_Reflectionz = function (Dx, Dy, Dz, Nx, Ny, Nz) {Dz  2 * SFn_vdot
>> (Dx, Dy, Dz, Nx, Ny, Nz)* Nz}
>> ...
>
> You are already thinking in the right ways...
> To see how you can use that further, have a look here:
>
> Subject: Source code for "With and without a light_source"
> From: Tor Olav Kristensen
> Date: 20030623 18:20:41
>
https://news.povray.org/povray.text.scenefiles/message/%3CXns93A54E262AE2torolavkhotmailcom%40204.213.191.226%3E
>
> There's no vector cross expressions there. But that will require only 3 small
> exressions.
>
> 
> Tor Olav
> http://subcube.com
> https://github.com/tok
>
>
OK. When I get to implementing 21 bit float dot, cross functions for
yuqk, I'll think about reflection / refraction functions too. I already
implemented a f_normal() function and have had thoughts on perhaps
implementing some sort of prerange, bounded, f_trace() 'trace()'
equivalent too, but we'll see...
Bill P.
Post a reply to this message


 
 


From: William F Pokorny
Subject: Re: yuqk feature requests / suggestions
Date: 28 Dec 2023 13:07:38
Message: <658db96a@news.povray.org>



 
 


On 12/27/23 18:44, Tor Olav Kristensen wrote:
> I'm sorry Bill, but you have to provide some more information for us about
> what you are doing here.
Bill posted a test scene here:
http://news.povray.org/povray.bugreports/thread/%3Cweb.654c1b56f53b6bed1f9dae3025979125%40news.povray.org%3E/
I've not gotten around to looking at it myself, but it is on my to do
list somewhere.

FYI. With credit, I've added the bottom part of your response  on the
zero bucketing adjustments  to yuqk's select keyword documentation.
Bill P.
Post a reply to this message


 
 




 
 


William F Pokorny <ano### [at] anonymousorg> wrote:
> On 12/27/23 18:44, Tor Olav Kristensen wrote:
> > I'm sorry Bill, but you have to provide some more information for us about
> > what you are doing here.
https://arxiv.org/pdf/1511.04224.pdf
I was working on figuring out Stephen Marschner's procedural wood texture, and
part of the paper uses triangular waves and rectangular waves with specific
properties, as he states:
6.1.3 Seasonal growth
We turn the r coordinate volume into a time volume by scal
ing its value and adding a smoothed triangular wave w (r)
to it. Each cycle of the smoothed triangle wave consists of
two linear segments connected by quadratic segments so as
to make the wave C1 continuous. The parameters are the
lengths of the two linear segments and the two quadratic
segments.
We scale the triangle wave so that when added to the radius,
half of the time the wood grows faster than the mean and
half of the time the wood grows more slowly. Then we add
1D noise n to generate variation in growth rate. All in all,
we have
tpre = r + w (r) (23)
t = tpre + n (tpre) (24)
This gives us the time at which any point in the wood was
laid down.
6.1.4 Growth rings
We can then create growth rings from the time volume. By
using a smoothed rectangular wave g = w (t), we can vary
the absorption of the wood according to the season. Simi
larly to the triangle wave used to determine the growth rate,
each cycle of the smoothed rectangular wave consists of two
constant segments and two cubic segements so as to make
the wave C2 continuous, and the parameters are the relative
lengths of the two linear segments and the two quadratic
segments, plus the minimum and maximum values.
 BW
Post a reply to this message


 
 




 
 


With regard to recent work by Jonathan Bush,
It occurred to me that a fairly typical and frequently used operation in
constructing scene code is the remapping of a value in one domain to a value in
another domain (typically 0 to 1).
Rather than puzzling out singleuse formulas for doing such a conversion, it
would be extremely convenient, especially to new users, to have a set if inbuilt
functions specifically for this purpose.
A basic set of formulas, proposed by Freya Holmer
https://www.youtube.com/watch?v=NzjF1pdlK7Y
is suggested for use below:
//
// Freya Holmer
#declare Lerp = function (Start, End, Value) {(1  Value) * Start + (End *
Value)}
#declare InvLerp = function (Start, End, Value) {(Value  Start) / (End 
Start)}
#declare ReMap = function (OldMin, OldMax, NewMin, NewMax, Value) {Lerp
(NewMin, NewMax, InvLerp (OldMin, OldMax, Value) )}
//
While hunting down this code, I found a functions.inc file by WFP that had some
internal remapping functions (presumably for use in isosurfaces in povr/yuqk)
but the accompanying documentation was pretty complex, dense and hard to follow,
but it suggests that there are other remapping schemes may be desirable.
Similarly, an example scene to demonstrate/illustrate how <u, v> values get
remapped to <x, y, z> values on a parametric surface would likely be of interest
and use to those trying to understand how uvmapping works.
Also, IIRC, there is some splinebased animation code, perhaps written by Rune
Johansen that employs some extensive remapping functions.
The point of this thread being that certain operations widely considered to be
basic operations in computer graphics should be inbuilt in yuqk / 4.0 rather
than require an awareness of multiple include files and other external libraries
by users as part of the rather steep learning curve.
Also, the power and speed of compiled source code, and the algorithmic nature of
sourcecode "functions" would reduce significant frustration in trying to write
complex scene code, and make POVRay more attractive and competetive in the
larger computer graphics community.
 BW
Post a reply to this message


 
 




 
 


On 1/2/24 07:34, Bald Eagle wrote:
> Rather than puzzling out singleuse formulas for doing such a conversion, it
> would be extremely convenient, especially to new users, to have a set if inbuilt
> functions specifically for this purpose.
>
> A basic set of formulas, proposed by Freya Holmer
> https://www.youtube.com/watch?v=NzjF1pdlK7Y
> is suggested for use below:
> //
>
> // Freya Holmer
> #declare Lerp = function (Start, End, Value) {(1  Value) * Start + (End *
> Value)}
>
> #declare InvLerp = function (Start, End, Value) {(Value  Start) / (End 
> Start)}
>
> #declare ReMap = function (OldMin, OldMax, NewMin, NewMax, Value) {Lerp
> (NewMin, NewMax, InvLerp (OldMin, OldMax, Value) )}
>
> //
>
> While hunting down this code, I found a functions.inc file by WFP that had some
> internal remapping functions (presumably for use in isosurfaces in povr/yuqk)
> but the accompanying documentation was pretty complex, dense and hard to follow,
> but it suggests that there are other remapping schemes may be desirable.
Yuqk's functions.inc documents a f_range2range() inbuilt which is likely
equivalent to the the 'Remap' function above  though the value is the
first parameter rather than the last.
Yes, yuqk's f_remap() is somewhat complicated. It could be used for one
range to range pair, but it's aimed more at creating multiple roots
(more particularly, isosurface shells) at particular value locations
within an existing functions value's overall range. For example,
multiple shells within f_sphere()'s return values where we'd normally be
able to create only one shell about f_sphere()'s radius value / single
root.
Providing inbuilt function(s?) for common interpolation methods is a
good idea. Some time ago Ingo coded up an include with a largish set of
gradients / interpolation methods. My aim is to someday create a
f_interpolation() inbuilt which encapsulated most (or all?) of those and
probably others. Maybe I'll at least create an initial version when I go
after those additional 3x, 21 bit float functions...
I have started a directory of examples for the inbuilt functions which
is shipped in the examples tar ball. Overall progress is admittedly slow.
Aside: I have large collection of scene files for playing with / testing
the inbuilt functions, but those are mostly not good examples as coded.
Plus, quite a few no longer work because of later yuqk changes...
Aside: The functions.inc file has a self test section at the bottom with
the functions coded up for sanity testing purposes. That testing code
sometimes works as decent example code.
Anyhow. In general, I agree with the suggestions in your post! :)
Bill P.
Post a reply to this message


 
 




 
 


William F Pokorny <ano### [at] anonymousorg> wrote:
> Anyhow. In general, I agree with the suggestions in your post! :)
I had a bit of time to wind down after work, and got sucked back into playing
with pigment function {}} patterns.
There are certain functions that we already have and that can be used in clever
ways (Thanks TOK) such as f_r and select ();
If I don't get to it at some point in the near future, I'd suggest an include
file that allows users to employ these in a somewhat more "code readable"
fashion. By that I mean that f_r should have an alias function declared such as
#declare vector_length = function {f_r (x, y, z)}
and TOK's various select () permutations might be confusing to employ without a
little cheat sheet.
I'm considering writing some "help functions" that store the valid domains of
various functions, such that it's easy to output to the debug stream, use as a
protective wrapper / sanity check for avoiding parse errors, graphing the valid
domains of the functions, and probably an insertmenu cheat sheet would be a
simple but useful idea as well.
Anyway, that was a longwinded leadin to the fact that I often find myself
needing to use some of the odder trigonometric functions and their inverses, and
the following ought to be inbuilt functions.
#declare fmod = function (Value, Modulo) {select (Value, 1  mod (abs (Value),
Modulo), mod (abs (Value), Modulo))} // this gives a mod function that remains
consistant across the origin
// trigonometric functions
#declare csc = function (N) {1/sin(N)}
#declare sec = function (N) {1/cos(N)}
#declare cot = function (N) {1/tan(N)}
// inverse trigonometric functions
#declare acsc = function (N) {asin(1 / N)}
#declare asec = function (N) {acos(1 / N)}
#declare acot = function (N) {atan(1 / N)}
This reminds me to look into hyperbolic and spherical functions as well...
With regard to interesting functions that (barring TOKlevel functional coding)
likely can "only" be coded as algorithms in source, or would likely only be
useful if leverage the speed of being a compiled internal "function" (algorithm)
are:
GCD (HCF)
LCM
https://www.geeksforgeeks.org/mathematicalalgorithms/mathematicalalgorithmsgcdlcm/
! factorial
Strangely, sgn (N) is not inbuilt.
And I guess until I run into something else, that's it for today's installment.
:)
 BW
Post a reply to this message


 
 




 
 


On 1/4/24 13:29, Bald Eagle wrote:
> If I don't get to it at some point in the near future, I'd suggest an include
> file that allows users to employ these in a somewhat more "code readable"
> fashion. By that I mean that f_r should have an alias function declared such as
>
> #declare vector_length = function {f_r (x, y, z)}
Thanks for the input!

The yuqk fork already has inbuilt f_length() and f_length_sqr()
functions. The former added in part as a clearer alternative to f_r(),
but it and f_length_sqr() also wrap POVRay's internal vector template
functions called length() and length_sqr(), respectively. The f_r()
implementation is hard coded c++ math.
The f_r() and f_length() results should be identical for sane inputs,
but pulling that internal code out to something SDL/VM accessible gives
us a way to sanity test the both the internal template functionality and
that equivalence as part of the include's self testing code.
Aside: The yuqk fork has too an f_hypot() function for two inputs (2D
vectors). Initially it wrapped C++'s std:hypot() as being safer with
respect to internal overflows, but I found the std::hypot performance
slow. Today it's just sqrt(x*x + y*y) as the main reason to have the two
input form over just f_length() with one input at zero, is performance.
As for sgn(), the yuqk fork has the inbuilt functions: f_sign(),
f_sign0(), f_signpow() and f_signsqrt().
Bill P.
Post a reply to this message


 
 




 

