POV-Ray : Newsgroups : povray.pov4.discussion.general : POV-Ray 4 SDL: Some concrete proposal : Re: POV-Ray 4 SDL: Some concrete proposal Server Time
23 Feb 2024 18:06:04 EST (-0500)
  Re: POV-Ray 4 SDL: Some concrete proposal  
From: clipka
Date: 13 Apr 2009 19:00:00
Message: <web.49e3c2da3a7e550e2dae03a10@news.povray.org>
Lukas Winter <web### [at] geloeschtremovethisandthedotbeforenet> wrote:
> Prototyping is a great concept and I'd love to see it in POV 4.

Yes, I think it's a powerful thing. It doesn't allow for as good a type checking
as class or interface based concepts, but it has the tremendous advantage of
coming at very low overhead and very high flexibility.

> > - "rotate(...) and translate()" are functions both returning a
> > transformation; as an expression-only statement, these transformations
> > are applied to the current object (which hopefully knows what to do with
> > them).
>
> I find this inconsistent. Why is rotate a function and sphere is not a
> function? I think rotate and translate should be expressions returning a
> transformation and use curly brackets as well. They could return identity
> transformations as a default.

Well, both approaches would be ok in this language framework; it would be a
matter of definition.

I think however that the function-based approach is better, because it would
define transformations as basically property-less. So nobody tries to do things
like:

  sphere {
    rotate { axis: <1,0,0>; angle: 30 deg; } as myRotate;
    translate { vector: <1,2,3>; };
  }
  myRotate.angle = 60 deg;

Otherwise, POV-Ray would need to keep track of a stack of transformations
applied to the object (and similarly all the texture patterns and such as
well), just in case someone would want to modify one of the steps later.

> Ultimately I dream of foing something like this:

> /*let's define the prototype of a rotation around a certain axis...*/
> rotate_around_axis = rotate
> {
>   input axis = #<1, 0, 0>; /*default value*/
>   input amount = 0; /*default value*/
>   rotation_vector = /*whatever it takes to calculate this rotation*/;
> };
>
> /*let's use it!*/
> sphere
> {
>   radius = 20;
>   center = <100, 0, 0>;
>   transformation *= rotate_around_axis
>     {
>       axis = <.5, .5, .5>;
>       amount = 30;
>       /*the actual transformation is automagically performed according to
> the calculations made in the definition of rotate_around_axis.*/
>     };
> };
>
> Which means: lazy evaluation of prototype definitions!

This is definitely something we would want - but isn't lazy evaluation the
domain of functions?

Maybe we could get a consensus by allowing for named parameters in functions.

There should be, however, *some* distinction between the two in syntax (not only
in defining them, but also in using them), so it is clear to the user that it
makes no sense to try to manipulate the parameters of the function.

> I chose = instead
> of : because of consistency

> and *= means composition of two
> transformation and writing the result back to the lhs. Simply putting a
> transformation inside a modification block does not work for me (it works
> in POV 3 because it does not use object properties). There should be
> something to signify that you are _applying_ this transformation.

In the language concept I have in mind, it would simply be (taking the freedom
to make this a function again, albeit with named parameters):

sphere
{
  radius = 20;
  center = <100, 0, 0>;
  rotate_around_axis
  (
    axis = <.5, .5, .5>;
    amount = 30;
  );
};

because, as already mentioned in the original post, expressions by themselves
(whether they be from prototype-cloning or function-calling) are always
*applied*. Note that a sphere would "know what to do" with a transformation
being applied to it. Most importantly, it would know that it would have to
update its children accordingly, too. Which a simple tampering with the spere's
*own* transformation matrix wouldn't do.

(Granted, we'd probably want a way to allow for getter/setter methods anyway...)

> > - "modify MainSphere{...}" is a statement taking a "modification block"
> > as well, in this case describing how the object itself is to be changed.
> >
> I'm pretty sure we don't need modify. Just use
>
> MainSphere = MainSphere
> {
>   radius = NewRadiusForMainSphere
> };
>
> This should be the same. We're just using a variable as the prototype for
> itself, clever, huh? ;)

Duh. I've just started laying out the basics of the language, and people already
start exploiting its details :P

Note however that this might be slower on a non-optimizing interpreter: It would
have to copy the object first, then discard the original one.

It would also make a difference in case of:

MySphere = sphere {...};
MySphereAlias = MySphere; // no prototype instantiation here, just an alias!
modify MySphere {...};

(Then again, disallowing "modify" would prevent any misconception about how this
case would work out.)

> > - adding "as <Name>" to an expression stores the value of that
> > expression for later use, serving as an "on-the-fly assignment"
>
> I agree with Warp here, a = would be more consistent.

So how would you express such an "on-the-fly assignment" then?

> You mean "<Name> : <Value>" is shorthand for ".<Name> = <Value>"? I'd
> rather make "::<Name>" access a global variable and "<Name>" always
> access the most local one, like in C++. So we'd get rid of all those
> different notations for assigning variables.

The thing is, I don't like those interpunctuation prefixes: When you start lots
of statements with these, it messes up the indentation, optically speaking.

>
> So, here's my version of your example ;)
>
> include "colors.inc";
>
> SphereCenter = <0,1,0>;
>
> MainSphere = sphere {
>   center = SphereCenter;
>   radius = 1;
>   ::SphereRadius = radius; //if you _really_ want to create this global
> variable
>   texture = texture
>   {
>     /*Local texture overrides global texture but that's no problem because
>     the prototype already has a default texture.*/
>     pigment { color = <1,0,0> }
>   };
> };

> scene += MainSphere; /*or whatever symbol is reserved for "append"*/

I'd prefer to avoid this "scene +=" - I think it's unnecessary bulk. Similarly
with the "texture = texture" above.

> /*I'm not sure whether I like this syntax or not...*/

You mean the "for" loop? I find nothing wrong with it.
The remainder of the syntax, that's what you came up with yourself :P

> MainSphere = MainSphere {
>   radius = 0.9;
> };
> /*Do we modify what was already added to the scene? Then we can't clone
> objects this way!

Hm, yeah - you're making the point why I originally added the "modify" statement
in the first place, but I forgot about it :}

> If we don't, we can't change objects that are already
> in the scene! Note that the "modify" keyword is no solution to that
> problem.*/

Why isn't it? If the POV-Ray internals can cope with an object being modified,
then this shouldn't be an issue.

> scene += MainSphere {
>   center = center + y*0.5;
> };
>
> /*Here I think the intention here was to clone MainSphere.*/
>
> debug(MainSphere.center);
> debug(MainSphere["center"]);
>
> Ah, sorry for taking your nice syntax apart and transforming it to
> something completely different. I just couldn't resist. I think you're on
> the right track, though!

Yeah, basically. I'm quite sure about the underlying idea. I'm still struggling
with the details, like how to get a syntax that is both perfectly consistent
*and* looks good. Mostly the "center:..." vs. alternatives like "center=...",
".center=..." or some such doesn't yet satisfy me.

That, and your and Warp's objection against the "as" statement. I actually like
it, but your complaint regarding inconsistency has some justification, too.


Post a reply to this message

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