|
|
- which can be found in section 4.2.7 in the
POV-Ray documentation:
http://povray.org/documentation/view/116/
This macro is shown in the advanced SDL tutorial,
where a raytracer is implemented by using only
POV-script.
It is my belief that this macro does some
calulations of values that there is no need for.
Below is my explanation.
Tor Olav
Here is the original macro:
#macro calcRaySphereIntersection(P, D, sphereInd)
#local V = P-Coord[sphereInd][0];
#local R = Coord[sphereInd][1].x;
#local DV = vdot(D, V);
#local D2 = vdot(D, D);
#local SQ = DV*DV-D2*(vdot(V, V)-R*R);
#if(SQ < 0) #local Result = -1;
#else
#local SQ = sqrt(SQ);
#local T1 = (-DV+SQ)/D2;
#local T2 = (-DV-SQ)/D2;
#local Result = (T1<T2 ? T1 : T2);
#end
Result
#end
If I rewrite it slightly, it looks like this:
#macro calcRaySphereIntersection(pL, vL, pS, R)
#local vA = pL - pS;
#local AA = vdot(vA, vA);
#local AL = vdot(vA, vL);
#local LL = vdot(vL, vL); // LL > 0
#local Radicand = AL*AL - LL*(AA - R*R);
#if (Radicand < 0)
#local Result = -1;
#else
#local SquareRoot = sqrt(Radicand); // SquareRoot >= 0
#local T1 = (-AL + SquareRoot)/LL;
#local T2 = (-AL - SquareRoot)/LL;
#local Result = (T1 < T2 ? T1 : T2);
#end
Result
#end // macro calcRaySphereIntersection
Where the arguments to this macro are:
pL: Ray origin (or point on line)
vL: Ray direction (or vector parallel to line)
pS: Sphere centre
R: Sphere radius
Now, this expression:
(T1 < T2)
can be rewritten like this:
((-AL + SquareRoot)/LL < (-AL - SquareRoot)/LL)
Since LL is positive:
(-AL + SquareRoot < -AL - SquareRoot)
Adding AL to both sides:
(SquareRoot < -SquareRoot)
Since we know that SquareRoot is positive, the
value of this expression must always be false.
Therefore there is no need to calculate the T1
value. (Because it will never be used.)
This means that the macro above can be rewritten
like this:
#macro calcRaySphereIntersection(pL, vL, pS, R)
#local vA = pL - pS;
#local AA = vdot(vA, vA);
#local AL = vdot(vA, vL);
#local LL = vdot(vL, vL);
#local Radicand = AL*AL - LL*(AA - R*R);
#if (Radicand < 0)
#local Result = -1;
#else
#local Result = (-AL - sqrt(Radicand))/LL;
#end
Result
#end // macro calcRaySphereIntersection
or like this:
#macro calcRaySphereIntersection(P, D, sphereInd)
#local V = P-Coord[sphereInd][0];
#local R = Coord[sphereInd][1].x;
#local DV = vdot(D, V);
#local DD = vdot(D, D);
#local SQ = DV*DV-DD*(vdot(V, V)-R*R);
#if(SQ < 0)
#local Result = -1;
#else
#local Result = (-DV-sqrt(SQ))/DD;
#end
Result
#end
Post a reply to this message
|
|
|
|
Actually the whole macro can be replaced with a function (which calls
other functions). I tried this once, and by doing this the "rendering"
speeds up by about 30% (IIRC).
There are other (simple) optimizations that could be added to the code,
such as caching the last shadowing sphere for each light source, but I feel
that would be a bit out of the scope of the tutorial.
--
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -
Post a reply to this message
|
|