POV-Ray : Newsgroups : povray.binaries.images : Friday Afternoon Doodle : Re: Friday Afternoon Doodle Server Time
16 Apr 2024 19:00:13 EDT (-0400)
  Re: Friday Afternoon Doodle  
From: Chris R
Date: 8 Mar 2022 12:55:00
Message: <web.6227974915dda32b89a9c4065cc1b6e@news.povray.org>
"Kenneth" <kdw### [at] gmailcom> wrote:
> "Chris R" <car### [at] comcastnet> wrote:
> >
> > Here's a pretty simple example with linear tapering.  I did something similar
> > with the image above, but embedded the tapering in functions instead.
> > [code snip]
> > Sorry, transcription error, yScaleBase should have been zScaleBase in _zScaleFn
>
> Thanks! That's really interesting (and a bit more complex than I thought, ha.)
> Now I can play around, to see what I can muck up! :-O
>
> I had to make some minor changes to your code to get it to run-- replacing some
> z's with y's -- probably because the macro call uses two-part vectors, like
> <2,2> for the 'SizeBase' etc. So that would be like <x,y> (or even <u,v>)
> instead of <x,z>... which POV-ray chokes on ;-) At least in Windows.
>
> I've attached my own trial image... just as a sanity check, to make sure I'm
> seeing what you intended!
>
> BTW, there are a few interesting pieces of your code that I'm clueless about, as
> to what they mean and how they work. Example:
>       #local _xScaleFn = function(l)
>       _xScaleBase + _xSlope*l
>        }
>
> That's a lower-case 'L'. I'm familiar with the typical x (or y or z) use in a
> function-- which AFAIU usually represent spatial axes--  but I have never used
> just a 'generic' letter as a substitute. Could you briefly explain what that
> means, in the context of your code?
>
> Anyway, thanks again for the example!
>
> ---------
> #include "functions.inc"
>
> #macro TaperedBox(SizeBase,SizeTop,RoundingBase,RoundingTop,Height)
>    #local _xSlope = (SizeTop.x - SizeBase.x)/(2*Height);
>   // #local _zSlope = (SizeTop.z - SizeBase.z)/(2*Height); // [ORIGINAL]
>    #local _zSlope = (SizeTop.y - SizeBase.y)/(2*Height); // changed both to y
>    #local _rndSlope = (RoundingTop - RoundingBase)/Height;
>    #local _xScaleBase = SizeBase.x/2;
>   // #local _zScaleBase = SizeBase.z/2; // [ORIGINAL]
>    #local _zScaleBase = SizeBase.y/2; // changed to y
>    #local _xScaleFn = function(l) {
>       _xScaleBase + _xSlope*l
>    }
>    #local _zScaleFn = function(l) {
>     //  _yScaleBase + _ySlope*l   // [ORIGINAL]
>         _zScaleBase + _zSlope*l // [update]
>    }
>    #local _rndFn = function(l) {
>       RoundingBase + _rndSlope*l
>    }
>    #local _sy = Height/2;
>    #local _shapeFn = function(x,y,z) {
>       f_rounded_box(x, y, z, _rndFn(y+_sy), _xScaleFn(y+_sy), _sy,
> _zScaleFn(y+_sy))
>    }
>
>    #local _maxx = max(SizeBase.x,SizeTop.x)/2;
>   // #local _maxz = max(SizeBase.z,SizeTop.z)/2; // [ORIGINAL]
>    #local _maxz = max(SizeBase.y,SizeTop.y)/2; // changed both to y
>    #local _lbounds = -<_maxx, _sy, _maxz>;
>    #local _ubounds = <_maxx, _sy, _maxz>;
>
>    #local _shape = isosurface {
>       function {
>          _shapeFn(x,y,z)
>       }
>       threshold 0
>       contained_by { box { _lbounds, _ubounds } }
>    }
>
>    #undef _shapeFn
>    #undef _rndFn
>    #undef _zScaleFn
>    #undef _xScaleFn
>
>    _shape
>
> #end
>
> TaperedBox(<2,2>, <1,1>, 0.2, 0.1, 2)

Yes, that's exactly it.  And I apologize for the x/y/z errors.  I originally
wrote the macro to move along the Z axis and then rotated the object to stand it
upright for the image, and then didn't get all of the mental rotations right in
the text above.

By default, if you define a function, it takes three arguments (x,y,z).
However, you can declare it with any parameters you want; (hence
f_rounded_box(x,y,z,rnd,sx,sy,sz))

Since my scaling function only depends on the distance along the extrusion axis,
and I might want to reuse that function in some other object along a different
axis, I just declared it to be a function with one parameter, called "l".  When
it is actually called, I can give it any axis I want.

I have a computer programming background, and the C compiler flags unused
parameters as wasteful and confusing, so I tend to define my functions just to
include the parameters I need in the body, and give them meaningful names.


-- Chris R


Post a reply to this message

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