Reading sources of POV-Ray 3.5a I found that torus
object
has defined method for UV Mapping. But it was not mentioned in documentation so
I checked how it worked. Wrong! I have investigated sources and found that
there are two bugs. First: UV mapping is calculated for coordinates in scene space
instead of object space. Second: author assumed that torus
is
located on x-y plane while it is located on x-z plane. Therefore I made necessary changes.
No UV Mapping | 3.5a Torus UV Mapping | Correct Torus UV Mapping |
---|---|---|
#version 3.5;
#declare minor=1/3;
#declare major=minor*3;
torus{
major minor
uv_mapping
pigment{checker rgb 0 rgb 1 scale .1}
rotate x*90
rotate y*45
translate 3*z*major
}
light_source{-9-9*z 1}
background{1}
camera{up y right x}
Implementation was pretty easy. All I need was
open file torus.cpp
and find definition of
CalcUV
and replace content of it with:
/***************************************************************************** * * FUNCTION * * CalcUV * * INPUT * * OUTPUT * * RETURNS * * AUTHOR * * Alexander Enzmann * * DESCRIPTION * * - Calculate the u/v coordinate of a point on a torus * * CHANGES * * - 2002.08.08 by ABX (abx@abx.art.pl) * * Fix with correct placing for intersection point. It have to be * untransformed before further calculations. * Fix with correct space torus space. Change meaning of y and z. * ******************************************************************************/ static void CalcUV(TORUS *Torus, VECTOR IPoint, UV_VECT Result) { DBL len, v, u, x, y, z; VECTOR P; // Transform the ray into the torus space. MInvTransPoint(P, IPoint, Torus->Trans); x = P[X]; y = P[Y]; z = P[Z]; // Determine its angle from the y-axis. u = (1.0 - (atan2(z, x) + M_PI) / TWO_M_PI); len = sqrt(x * x + z * z); // Now rotate about the y-axis to get the point P into the x-z plane. x = len - Torus->R; v = (atan2(y, x) + M_PI) / TWO_M_PI; Result[U] = u; Result[V] = v; }
I noticed that UV coordinates are stored on intersection stack
while the same method was removed from parametric
object
(see my notes in UV Mapping for Parametric Object).
Additionally I'm not sure it is necessary to store UV coordinates anywhere. I
think method CalcUV
should be called directly from
Torus_UVCoord
method becouse it is necessary to have it there.
Of course the same can be also achived with toroidal mapping for texture but
I suppose method with UV coords is a little bit faster and use less memory.