POV-Ray : Newsgroups : povray.general : Weirdnesses with function patterns Server Time
25 Dec 2024 20:38:01 EST (-0500)
  Weirdnesses with function patterns (Message 1 to 7 of 7)  
From: David Given
Subject: Weirdnesses with function patterns
Date: 8 Dec 2013 13:17:47
Message: <52a4b7cb$1@news.povray.org>
Yes, me again, I'm afraid. I've found two issues where function patterns
are behaving really strangely.

Consider this texture:

texture {
	function { x }
	texture_map {
		[-0.5 pigment { Red } ]
		[0.5 pigment { Yellow } ]
	}
}

I'd expect this to be solid red in the -x direction, fading smoothly to
yellow as it passes x=0, and then solid yellow in the +x direction.

Instead what happens is the return value of the function is clipped into
the [0..1] range.

This could be intentional; however, if it is, then this behaviour isn't
documented, and the actual implementation that makes it happen seems a
little confused, which makes me suspect that's it's not intended.

The code comes in two parts: this in function_pattern:

	return ((value > 1.0) ? fmod(value, 1.0) : value);

...which wraps *positive* values, and this in Evaluate_TPat, which wraps
*negative* values.

	if(TPat->Frequency != 0.0)
		value = fmod(value * TPat->Frequency + TPat->Phase, 1.00001); // TODO
FIXME - magic number! Should be 1.0+SOME_EPSILON (or maybe actually 1.0?)

	/* allow negative Frequency */
	if(value < 0.0)
		value -= floor(value);

Because positive values are only wrapped in function_pattern, then this
means that positive values returned by non-function patterns aren't
wrapped at all! Also that TODO makes me sad.

So I think there's definitely something wrong here, but I'm not entirely
sure what. What's *supposed* to happen in this situation?

-- 
┌─── dg@cowlark.com ─────
http://www.cowlark.com ─────
│ "There does not now, nor will there ever, exist a programming
│ language in which it is the least bit hard to write bad programs." ---
│ Flon's Axiom


Post a reply to this message

From: Christian Froeschlin
Subject: Re: Weirdnesses with function patterns
Date: 8 Dec 2013 13:28:05
Message: <52a4ba35$1@news.povray.org>
David Given wrote:

> Instead what happens is the return value of the function is clipped into
> the [0..1] range.

at least for the maps itself it is documented that the value are
supposed to be in the range 0.0 to 1.0. Regarding the function wrap
I found that unexpected too when I encountered it (would have expected
value > 1.0 to be treated same as 1.0).

But it is easy to work around that using "select" statement.


Post a reply to this message

From: clipka
Subject: Re: Weirdnesses with function patterns
Date: 8 Dec 2013 15:02:12
Message: <52a4d044$1@news.povray.org>
Am 08.12.2013 19:17, schrieb David Given:

> Instead what happens is the return value of the function is clipped into
> the [0..1] range.

This is consistent with each and every other pattern, and entirely 
intentional.

> This could be intentional; however, if it is, then this behaviour isn't
> documented, and the actual implementation that makes it happen seems a
> little confused, which makes me suspect that's it's not intended.
>
> The code comes in two parts: this in function_pattern:
>
> 	return ((value > 1.0) ? fmod(value, 1.0) : value);
>
> ....which wraps *positive* values, and this in Evaluate_TPat, which wraps
> *negative* values.
>
> 	if(TPat->Frequency != 0.0)
> 		value = fmod(value * TPat->Frequency + TPat->Phase, 1.00001); // TODO
> FIXME - magic number! Should be 1.0+SOME_EPSILON (or maybe actually 1.0?)
>
> 	/* allow negative Frequency */
> 	if(value < 0.0)
> 		value -= floor(value);
>
> Because positive values are only wrapped in function_pattern, then this
> means that positive values returned by non-function patterns aren't
> wrapped at all!

All other patterns take care of the wrapping by themselves. The wrapping 
of negative values is only there (or so the comment implies) because the 
value could be transformed into the negative domain by multiplying with 
TPat->Frequency. (Like the % operator, fmod preserves the sign of the 
first operand.)

The only inconsistency here is that the function pattern does not handle 
negative values itself, and instead apparently relies on the 
Evaluate_TPat code to take care of that.


Post a reply to this message

From: David Given
Subject: Re: Weirdnesses with function patterns
Date: 8 Dec 2013 17:13:21
Message: <52a4ef01@news.povray.org>
On 08/12/13 20:02, clipka wrote:
[...]
>> Instead what happens is the return value of the function is clipped into
>> the [0..1] range.
> 
> This is consistent with each and every other pattern, and entirely
> intentional.

In which case can this be made explicit? It's really not obvious from
either the documentation or the code.

In addition, I've just discovered this:

#version 3.7;
#local f = function { pigment { rgb <10, 10, 10> }}
#warning str(f(0, 0, 0).red, 0, 1)

...prints 10.

Also I note that some of the internal pattern functions that drive
things like cubic, hexagon etc will return values outside [0..1]. But I
think these are all safely isolated from the user, unless there's a code
path to Evaluate_TPat which I haven't found yet.

-- 
┌─── dg@cowlark.com ─────
http://www.cowlark.com ─────
│ "There does not now, nor will there ever, exist a programming
│ language in which it is the least bit hard to write bad programs." ---
│ Flon's Axiom


Post a reply to this message

From: clipka
Subject: Re: Weirdnesses with function patterns
Date: 8 Dec 2013 18:00:20
Message: <52a4fa04$1@news.povray.org>
Am 08.12.2013 23:13, schrieb David Given:

> In addition, I've just discovered this:
>
> #version 3.7;
> #local f = function { pigment { rgb <10, 10, 10> }}
> #warning str(f(0, 0, 0).red, 0, 1)
>
> ....prints 10.

Yes, of course. There's no pattern involved here, so why should there be 
any clipping or wrapping?


Post a reply to this message

From: David Given
Subject: Re: Weirdnesses with function patterns
Date: 8 Dec 2013 19:24:44
Message: <52a50dcc$1@news.povray.org>
On 08/12/13 23:00, clipka wrote:
[...]
> Yes, of course. There's no pattern involved here, so why should there be
> any clipping or wrapping?

Oh, yes, my bad. What I should have said was that this:

	pigment {
		pigment_pattern {
			rgb <100, 100, 100>
		}
		frequency 0
		pigment_map {
			[0.0 rgb <0, 0, 0>]
		}
	}

...results in an out-of-bound value (of 100) being passed to
Search_Blend_Func() --- pigment_pattern() doesn't clip the greyscale
value before returning it.

As the default frequency is 1, which causes the value to be wrapped, I
can't imagine this every actually happening in real life, but I still
noticed it when I was looking at the code.

That's not really related to my earlier comment, though. Can I reiterate
my plea for more visible documentation that function patterns should
only return values from 0 to 1? As you might have gathered, this wasn't
obvious!

-- 
┌─── dg@cowlark.com ─────
http://www.cowlark.com ─────
│ "There does not now, nor will there ever, exist a programming
│ language in which it is the least bit hard to write bad programs." ---
│ Flon's Axiom


Post a reply to this message

From: James Holsenback
Subject: Re: Weirdnesses with function patterns
Date: 9 Dec 2013 07:40:13
Message: <52a5ba2d@news.povray.org>
On 12/08/2013 07:24 PM, David Given wrote:
> That's not really related to my earlier comment, though. Can I reiterate
> my plea for more visible documentation that function patterns should
> only return values from 0 to 1? As you might have gathered, this wasn't
> obvious!

Well ... I'm not going to jump on this one as fast as mesh2 issue. Does 
anyone else feel this needs to be addressed?


Post a reply to this message

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