POV-Ray : Newsgroups : povray.programming : cones.cpp: A typo and a question. : Re: cones.cpp: A typo and a question. Server Time
28 Jul 2024 06:13:09 EDT (-0400)
  Re: cones.cpp: A typo and a question.  
From: Massimo Valentini
Date: 7 Oct 2002 12:34:15
Message: <3da1b787@news.povray.org>
"Le Forgeron" ha scritto
:
: > An other one could be to avoid the normalization of the
: > direction of the ray, it appears to me useless.
:
: It is NOT useless. When CSG operation/object (union & merge, at least)
: will ask its component, it will orders the intersections by depth order
: before answering to the upper level. Thus, putting back the depth from
: object space to global space is mandatory (otherwise, strange things
: will happens).
:
: Same goes when more than a single cone/cylinder get intersected by the
: ray, the engine need to order them correctly, in the global space!
:

I try to show what I mean. You are first scaling the direction

<CODE src=cones.cpp lines=197-200>
MInvTransDirection(D, Ray->Direction, Cone->Trans);

VLength(len, D);
VInverseScaleEq(D, len);
</CODE>

This last line is a macro for a vector/scalar division:
D = D / len

Doing so results in a scaling of the coefficients (a & b)
of the 2nd order equation you are going to solve:

<CODE src=cones.cpp lines=206-213>
a = D[X] * D[X] + D[Y] * D[Y];

if (a > EPSILON)
{
  b = P[X] * D[X] + P[Y] * D[Y];

  c = P[X] * P[X] + P[Y] * P[Y] - 1.0;
</CODE>


And now you are required to scale the solution:

<CODE src= cones.cpp lines=220-228>
t1 = (-b + d) / a;
t2 = (-b - d) / a;

z = P[Z] + t1 * D[Z];

if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <=
1.0))
{
  Intersection[i].d   = t1 / len;
</CODE>


Suppose not to scale D, I name this not scaled direction D`
and D the direction that's actually used. It is:

D` = D * len

The resulting equation would be

a` * t`^2 + b` * t` + c = 0

where

a` = D`[X] * D`[X] + D`[Y] * D`[Y]
   = (D[X] * D[X] + D[Y] * D[Y]) * len ^ 2
   = a * len ^ 2

and b` = b * len

and whose solutions are t1,2` = t1,2 / len.

a` * t`^2 + b` * t` + c =
a * len^2 * (t / len)^2 + b * len * (t / len) + c =
a * t ^ 2 + b * t + c = 0

Exactly the previous solution only already scaled, so ready to
be used in global space sorting, testing, whatever necessary.

And

z` = P[Z] + t` * D`[Z]
   = P[Z] + (t / len) * (D[Z] * len)
   = P[Z] + t * D[Z] = z

The same z ready to be tested against 0 and 1.

So avoiding the normalization of the direction only saves a sqrt
(no need to calculate len) and some multiplications and divisions
but gives you the same result this function is returning.

The same reasoning is valid for the cone intersections.

If you want to try what I'm suggesting, assign 1.0 to len where this
is declared, and then comment out the computation of len.

<CODE lines=188-200>
  DBL a, b, c, z, t1, t2, len = 1.0;//<------
  DBL d;
  VECTOR P, D;

  Increase_Counter(stats[Ray_Cone_Tests]);

  /* Transform the ray into the cones space */

  MInvTransPoint(P, Ray->Initial, Cone->Trans);
  MInvTransDirection(D, Ray->Direction, Cone->Trans);

//  VLength(len, D);// <------------------------
//  VInverseScaleEq(D, len); //<----------------


HTH Massimo


Post a reply to this message

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