POV-Ray : Newsgroups : povray.bugreports : Normal scaling bug(s) Server Time
13 May 2024 21:36:46 EDT (-0400)
  Normal scaling bug(s) (Message 1 to 3 of 3)  
From: Rune
Subject: Normal scaling bug(s)
Date: 30 Oct 1999 01:35:00
Message: <381a8384@news.povray.org>
Sorry for the long post, but I'm not good at
making short and clear descriptions.

I consider it a bug that the depth of a normal
doesn't always proportionally follow the scaling
affecting the normal. It just isn't logic but
on the contrary strange and very inconvenient!

Whether this is a bug or not might be a matter
of opinions, but when I posted to povray.general
some time ago there was at least a few who
agreed that it is indeed a bug.

If you consider it a bug too I think it should be
fixed. I know it would break a whole lot of scenes,
but there ought to be a good solution.

Below the problem is described in details.

There are four basic types of normals:

o Block pattern normals (checker, hexagon, brick).
o Bump maps.
o Specialized normals (bumps, dents, ripples,
  waves, wrinkles).
o The rest is continuous pattern normals.

When working with normals you can modify both the
scale of the pattern and the depth of the pattern.

When you apply a *specialized normal* to an object
and afterwards scale the object smaller or larger,
the depth of the normal pattern follows the scale
of the pattern proportionally as you would expect.

However, when you apply a *continuous pattern
normal* to an object and scale the object smaller
or larger afterwards, the depth of the normal
pattern *doesn't* follow the scale of the pattern.
That is, if you scale the object smaller the
normal seems to be too deep and if you scale the
object larger the normal seems to be too flat.

If you want to have the depth of a *continuous
pattern normal* to follow the scale of the pattern
proportionally you must multiply the depth of the
normal pattern with the same amount you scale the
object with. However, for some reason that only
works when scaling the object larger, not when
scaling it smaller.

Just to confuse you even more: If you have an
*continuous pattern normal* inside a *normal_map*
it works as if it were a *specialized normal*,
that is, the depth of the normal pattern follows
the scale of the pattern proportionally. That's
what I just found out and that makes it all even
more confusing and inconvenient!

Here's an example of it all:

Left spheres:  Normal depth of 1.
Right spheres: Normal depth proportional to "Scale".
Upper spheres: A plain crackle normal.
Lower spheres: Same normal but inside a normal_map.

Change "Scale" to other values to see the effects.
*/

#declare Scale=1;

camera{location -8*z look_at 0 orthographic  scale Scale}
light_source{<1,1,-1>*100,color 1 shadowless scale Scale}
#default{pigment{color rgb 1}}

#declare N1a=normal{crackle 1    }
#declare N1b=normal{crackle Scale}

#declare N2a=normal{bozo normal_map{[0 N1a][1 N1a]}}
#declare N2b=normal{bozo normal_map{[0 N1b][1 N1b]}}

sphere{0,2 normal{N1a}translate <-2,+2,> scale Scale}
sphere{0,2 normal{N1b}translate <+2,+2,> scale Scale}
sphere{0,2 normal{N2a}translate <-2,-2,> scale Scale}
sphere{0,2 normal{N2b}translate <+2,-2,> scale Scale}

// Rune S. Johansen


Post a reply to this message

From: Nathan Kopp
Subject: Re: Normal scaling bug(s)
Date: 5 Dec 1999 19:18:16
Message: <384b00c8@news.povray.org>
There is a bug that affects the scaling of the 'amount' of slope_map
normals.  The bug also involves problems with rotating objects that have
patterned normals or patterned textures with surface normals.  I have found
a fix.  Note that this change will only work with UVPov, the SuperPatch, the
Mac Multipatch, and POV 3.5, since it requires the UV_Trans property of
objects.  UV_Trans contains all transformations that are applied to an
object.  This is necessary, since many objects (such as boxes and spheres)
optimize some transformations away (such as scaling a sphere by multiplying
its radius by a scalar or translating it by moving its center).  The full
set of transformations is very necessary to determine how the surface normal
has been rotated.

Ok, here is the bugfix (code examples might wrap funny):

First:
The call to Warp_EPoint() needs to be removed from Evaluate_TPat().
All calls to Evaluate_TPat() will have to call Warp_EPoint() before they
call Evaluate_TPat().  There are not many calls to Evaluate_TPat(), so this
is easy to change.

Next:
At the end of Perturb_Normal() is the section that does slope_maps.  The end
of it should look like this:
// -------------- begin ----------------
    /* Note, even though DELTA and Pyramid_Vect are constants, we may later
   make DELTA a user-defined parameter.  Good optimising compilers
   should merge the constants anyway. */

    Amount=Tnormal->Amount * -5.0; /*fudge factor*/
    Amount*=0.02/DELTA;

    /* warp the center point first - this is the last warp */
    Warp_EPoint(TPoint,EPoint,(TPATTERN *)Tnormal,FALSE);

    for(i=0; i<=3; i++)
    {
      VAddScaled(P1,TPoint,DELTA,Pyramid_Vect[i]);  // change to TPoint
      value1 = Do_Slope_Map(Evaluate_TPat((TPATTERN
*)Tnormal,P1),Blend_Map);
      VAddScaledEq(Layer_Normal,value1*Amount,Pyramid_Vect[i]);
    }
// -------------- end ----------------

Finally:
Now, we have to compensate for rotations in the normal.  This is done with
EVERY non-recursive call to Perturb_Normal().  Note that we cannot do this
within Perturb_Normal() itself, since that function is called recursively.
However, a non-recursive wrapper could be used to call the recursive part of
Perturb_Normal() and the wrapper could contain this code.  Here is an
example from compute_lighted_texture() in lighting.c:  (this change is only
done in lighting.c)
// -------------- begin ----------------
      /*
         Because the transformation within Layer->Tnormal contains the
         object's transformation, we must make sure that LayNormal also
         gets inverse-transformed before we give it to PerturbNormal,
         then transform it back after the return.

         Remember that UV_Trans contains the object's full transformation
         stack, which is also contained in the root-level texture's warps.
      */
      if (Intersection->Object->UV_Trans)
      {
        MInvTransNormal(LayNormal,LayNormal,Intersection->Object->UV_Trans);
        VNormalizeEq(LayNormal);
      }

      Perturb_Normal(LayNormal, Layer->Tnormal, IPoint, Intersection);

      if (Intersection->Object->UV_Trans)
      {
        MTransNormal(LayNormal,LayNormal,Intersection->Object->UV_Trans);
        VNormalizeEq(LayNormal);
      }
// -------------- end ----------------

It is important to point out that Perturb_Normal has a VNormalizeEq() at the
end of it, and now we do a bunch more transforms and normalizes.  I think
they are all necessary, but that may not be the case.  In any case, there
are probably places we can optimize this to remove extraneous
normalizations.

-Nathan

Rune <run### [at] inamecom> wrote...
> Sorry for the long post, but I'm not good at
> making short and clear descriptions.
>
> I consider it a bug that the depth of a normal
> doesn't always proportionally follow the scaling
> affecting the normal. It just isn't logic but
> on the contrary strange and very inconvenient!
>
> Whether this is a bug or not might be a matter
> of opinions, but when I posted to povray.general
> some time ago there was at least a few who
> agreed that it is indeed a bug.
>
> If you consider it a bug too I think it should be
> fixed. I know it would break a whole lot of scenes,
> but there ought to be a good solution.
>
> Below the problem is described in details.
>
> There are four basic types of normals:
>
> o Block pattern normals (checker, hexagon, brick).
> o Bump maps.
> o Specialized normals (bumps, dents, ripples,
>   waves, wrinkles).
> o The rest is continuous pattern normals.
>
> When working with normals you can modify both the
> scale of the pattern and the depth of the pattern.
>
> When you apply a *specialized normal* to an object
> and afterwards scale the object smaller or larger,
> the depth of the normal pattern follows the scale
> of the pattern proportionally as you would expect.
>
> However, when you apply a *continuous pattern
> normal* to an object and scale the object smaller
> or larger afterwards, the depth of the normal
> pattern *doesn't* follow the scale of the pattern.
> That is, if you scale the object smaller the
> normal seems to be too deep and if you scale the
> object larger the normal seems to be too flat.
>
> If you want to have the depth of a *continuous
> pattern normal* to follow the scale of the pattern
> proportionally you must multiply the depth of the
> normal pattern with the same amount you scale the
> object with. However, for some reason that only
> works when scaling the object larger, not when
> scaling it smaller.
>
> Just to confuse you even more: If you have an
> *continuous pattern normal* inside a *normal_map*
> it works as if it were a *specialized normal*,
> that is, the depth of the normal pattern follows
> the scale of the pattern proportionally. That's
> what I just found out and that makes it all even
> more confusing and inconvenient!
>
> Here's an example of it all:
>
> Left spheres:  Normal depth of 1.
> Right spheres: Normal depth proportional to "Scale".
> Upper spheres: A plain crackle normal.
> Lower spheres: Same normal but inside a normal_map.
>
> Change "Scale" to other values to see the effects.
> */
>
> #declare Scale=1;
>
> camera{location -8*z look_at 0 orthographic  scale Scale}
> light_source{<1,1,-1>*100,color 1 shadowless scale Scale}
> #default{pigment{color rgb 1}}
>
> #declare N1a=normal{crackle 1    }
> #declare N1b=normal{crackle Scale}
>
> #declare N2a=normal{bozo normal_map{[0 N1a][1 N1a]}}
> #declare N2b=normal{bozo normal_map{[0 N1b][1 N1b]}}
>
> sphere{0,2 normal{N1a}translate <-2,+2,> scale Scale}
> sphere{0,2 normal{N1b}translate <+2,+2,> scale Scale}
> sphere{0,2 normal{N2a}translate <-2,-2,> scale Scale}
> sphere{0,2 normal{N2b}translate <+2,-2,> scale Scale}
>
> // Rune S. Johansen
>
>
>


Post a reply to this message

From: bugreports moderator
Subject: Re: Normal scaling bug(s)
Date: 16 Dec 1999 04:25:30
Message: <3858b00a@news.povray.org>
On Sun, 05 Dec 1999 17:29:50 -0500, Nathan Kopp <Nat### [at] Koppcom>
wrote:

Nathan Kopp <Nat### [at] Koppcom> wrote...
>       if (Intersection->Object->UV_Trans)
>       {
>
> MInvTransNormal(LayNormal,LayNormal,Intersection->Object->UV_Trans);
>         VNormalizeEq(LayNormal);
>       }
>
>       Perturb_Normal(LayNormal, Layer->Tnormal, IPoint, Intersection);
>
>       if (Intersection->Object->UV_Trans)
>       {
>         MTransNormal(LayNormal,LayNormal,Intersection->Object->UV_Trans);
>         VNormalizeEq(LayNormal);
>       }

This code is WRONG!

If you do this, than transformations prior to applying the surface
normal
will affect the surface normal.  This is BAD.

The code should look more like this (provides backwards compatibility,
too):

      if (opts.Language_Version>3.1 &&
          Layer->Tnormal->Warps &&
          Layer->Tnormal->Warps->Warp_Type==TRANSFORM_WARP)
      {
        TRANS *Tr;
        Tr=(TRANS *)(Layer->Tnormal->Warps);
        MInvTransNormal(LayNormal, LayNormal, &(Tr->Trans));
        VNormalizeEq(LayNormal);
      }

      Perturb_Normal(LayNormal, Layer->Tnormal, IPoint, Intersection);

      if (opts.Language_Version>3.1 &&
          Layer->Tnormal->Warps &&
          Layer->Tnormal->Warps->Warp_Type==TRANSFORM_WARP)
      {
        TRANS *Tr;
        Tr=(TRANS *)(Layer->Tnormal->Warps);
        MTransNormal(LayNormal, LayNormal, &(Tr->Trans));
        VNormalizeEq(LayNormal);
      }

Note that this no longer requires UVTrans (which means that it could
be
applied to the official 3.1... after much more testing, of course).

-Nathan


Post a reply to this message

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