![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Btw, I wonder if this kind of macro could be worth including in the
standard include files.
The only concern I have about it is that it uses the "trick" to calculate
the normal of the spline with the Spline(T+Epsilon)-Spline(T-Epsilon)
formula. What I'm not sure about is the value for 'Epsilon'. I used 1e-5,
but that might sometimes be either too big or too small (due to floating
point number inaccuracies).
The current macro is the following:
---------8<------------8<-------------8<------------8<-----------8<-----
#macro MeshLathe(Spline, VertSteps, HorSteps)
#ifndef(MeshLatheDebug) #local MeshLatheDebug=0; #end
#if(MeshLatheDebug=1 | MeshLatheDebug=2)
#ifndef(MeshLatheDebugRadius) #local MeshLatheDebugRadius=.05; #end
#ifndef(MeshLatheDebugNormalLength) #local MeshLatheDebugNormalLength=.2; #end
union
{ #local Ind1 = 0;
#while(Ind1 < VertSteps)
#local Time1 = Ind1/(VertSteps-1);
#local Coord1 = (Spline(Time1));
#local Tang = (Spline(Time1+1e-5)-Spline(Time1-1e-5));
#local Normal1 = vnormalize(<Tang.y, -Tang.x, 0>);
sphere { Coord1, MeshLatheDebugRadius }
sphere { Coord1*<-1,1,1>, MeshLatheDebugRadius }
#if(MeshLatheDebug=2)
cylinder
{ Coord1, Coord1+Normal1*MeshLatheDebugNormalLength,
MeshLatheDebugRadius*.5
#ifdef(MeshLatheDebugNormalColor)
pigment { rgb MeshLatheDebugNormalColor }
#end
}
#end
#if(Ind1>0)
cylinder { Coord1, oldCoord1, MeshLatheDebugRadius*.5 }
cylinder
{ Coord1*<-1,1,1>, oldCoord1*<-1,1,1>, MeshLatheDebugRadius*.5 }
#end
#local oldCoord1 = Coord1;
#local Ind1 = Ind1+1;
#end
}
#else
mesh
{ #local Ind1 = 0;
#while(Ind1 < VertSteps-1)
#local Time1 = Ind1/(VertSteps-1);
#local Time2 = (Ind1+1)/(VertSteps-1);
#local Coord1 = (Spline(Time1));
#local Tang = (Spline(Time1+1e-5)-Spline(Time1-1e-5));
#local Normal1 = vnormalize(<Tang.y, -Tang.x, 0>);
#local Coord2 = (Spline(Time2));
#local Tang = (Spline(Time2+1e-5)-Spline(Time2-1e-5));
#local Normal2 = vnormalize(<Tang.y, -Tang.x, 0>);
#local Ind2 = 0;
#while(Ind2 < HorSteps-1)
#local Angle1 = 360*Ind2/(HorSteps-1);
#local Angle2 = 360*(Ind2+1)/(HorSteps-1);
#local P1 = vrotate(Coord1, y*Angle1);
#local N1 = vrotate(Normal1, y*Angle1);
#local P2 = vrotate(Coord2, y*Angle1);
#local N2 = vrotate(Normal2, y*Angle1);
#local P3 = vrotate(Coord2, y*Angle2);
#local N3 = vrotate(Normal2, y*Angle2);
#local P4 = vrotate(Coord1, y*Angle2);
#local N4 = vrotate(Normal1, y*Angle2);
#if(MeshLatheDebug>2)
triangle { P1, P2, P3 }
triangle { P3, P4, P1 }
#else
smooth_triangle { P1,N1, P2,N2, P3,N3 }
smooth_triangle { P3,N3, P4,N4, P1,N1 }
#end
#local Ind2 = Ind2+1;
#end
#local Ind1 = Ind1+1;
#end
}
#end
#end
---------8<------------8<-------------8<------------8<-----------8<-----
--
#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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
"Warp" <war### [at] tag povray org> wrote in message
news:3c792e92@news.povray.org...
> Btw, I wonder if this kind of macro could be worth including in the
> standard include files.
>
> The only concern I have about it is that it uses the "trick" to
calculate
> the normal of the spline with the Spline(T+Epsilon)-Spline(T-Epsilon)
> formula. What I'm not sure about is the value for 'Epsilon'. I used 1e-5,
> but that might sometimes be either too big or too small (due to floating
> point number inaccuracies).
I remember from my Numerical Analysis courses, that some authors recommend
the optimal size for the epsilon as sqrt(EPS) where EPS is the distance from
1.0 to the next largest floating point number. In a traditional PC, I
believe EPS is approx 2.2e-16, so the optimal epsilon is approximately
1.4e-8
However, I'm recalling all this from my memory, so I can't guarantee that it
is correct :)
I hope you can make some tests for this and report your results...
Fernando.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> I remember from my Numerical Analysis courses, that some authors recommend
> the optimal size for the epsilon as sqrt(EPS) where EPS is the distance from
> 1.0 to the next largest floating point number. In a traditional PC, I
> believe EPS is approx 2.2e-16, so the optimal epsilon is approximately
> 1.4e-8
Note that we are not using an epsilon value for making comparisons, but
for making vector math which should be as accurate as possible.
The smaller the epsilon value we use for approximating the tangent of the
spline, the more error-prone it will become (due to inaccuracies with very
small values).
When we compare values a really small value is enough (as long as it's
bigger than 0) because we only need to see if two numbers are equal or not.
However in this case we are performing calculations which should not suffer
from inaccuracies.
On the other hand, using an epsilon value which is too big can result in
inaccurate results (because the result deviates too much from the real
tangent).
Thus a proper compromise has to be found.
In the case of splines, which are usually really smooth, we don't really
need a very small epsilon value. Even with rather big values (eg. 1e-3 or
something similar) we still get really acceptable results.
--
#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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <3c792e92@news.povray.org>, war### [at] tag povray org says...
> The only concern I have about it is that it uses the "trick" to calculate
> the normal of the spline with the Spline(T+Epsilon)-Spline(T-Epsilon)
> formula. What I'm not sure about is the value for 'Epsilon'.
Why not make it dependent on the distance between the previous and the
next control point?
If it is small (1/100 or so) compared to this distance it should work, no
matter what the absolute scale of the whole thing is.
Has the mesh-approach any advantage over using bicubic patches? The
documentation says bicubic patches are converted to a mesh internally, so
speed should be equal (but I didn't try yet), but parsing should be
faster with patches.
Lutz-Peter
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <MPG.16e362bd507e6d0b9896e1@news.povray.org>,
Lutz-Peter Hooge <lpv### [at] gmx de> wrote:
> Why not make it dependent on the distance between the previous and the
> next control point?
Better would be to make it dependant on the distance along the
spline...try an epsilon value and get the distance of the point from the
current point, if it is too small increase it.
But for this application, it isn't very critical...just use a large
enough sample to make errors extremely unlikely.
> Has the mesh-approach any advantage over using bicubic patches? The
> documentation says bicubic patches are converted to a mesh internally, so
> speed should be equal (but I didn't try yet), but parsing should be
> faster with patches.
Not really. Patches are converted to triangles for intersection testing,
but they can do adaptive subdivision on the fly, which slows rendering
but uses less memory and parse time. It is harder to connect them
smoothly, as well.
And a single mesh will have an advantage over a bunch of patches...a
mesh can be very efficient about which triangles it tests, and can use
tricks a union of patches can't. So a mesh will probably render faster.
Then you have the advantage that copies of meshes use very little extra
memory...
--
Christopher James Huff <chr### [at] mac com>
POV-Ray TAG e-mail: chr### [at] tag povray org
TAG web site: http://tag.povray.org/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
in news:3c792e92@news.povray.org Warp wrote:
> The only concern I have about it is that it uses the "trick" to
> calculate
> the normal of the spline with the Spline(T+Epsilon)-Spline(T-Epsilon)
> formula. What I'm not sure about is the value for 'Epsilon'.
Does it matter that much? While building my macro's I settled with half
the spline resolution as I didn't see any difference for smaller values.
Ingo
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <chr### [at] netplex aussie org>,
chr### [at] mac com says...
> Better would be to make it dependant on the distance along the
> spline...
Yes, but thats not as easy to calculate. And it will be alway bigger or
equal to distance between the points, so there isn't the danger of
accidently taking a too large epsilon.
> Not really. Patches are converted to triangles for intersection testing,
> but they can do adaptive subdivision on the fly,
I thought the subdivision is only perfomed once, when generating the
triangles (unless type 0 is used)
> It is harder to connect them smoothly, as well.
This may be true in general, but for just building a lathe shape it isn't
a problem.
Lutz-Peter
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
"Warp" <war### [at] tag povray org> wrote in message
news:3c7940df@news.povray.org...
> > I remember from my Numerical Analysis courses, that some authors
recommend
> > the optimal size for the epsilon as sqrt(EPS) where EPS is the distance
from
> > 1.0 to the next largest floating point number. In a traditional PC, I
> > believe EPS is approx 2.2e-16, so the optimal epsilon is approximately
> > 1.4e-8
>
> Note that we are not using an epsilon value for making comparisons, but
> for making vector math which should be as accurate as possible.
> The smaller the epsilon value we use for approximating the tangent of
the
> spline, the more error-prone it will become (due to inaccuracies with very
> small values).
Exactly, there are two type of errors:
* As the epsilon becomes larger, the approximation of the derivative will be
less accurate.
* As the epsilon becomes smaller, the errors due to the floating-point
arithmetic will worsen.
But both errors will affect directly the accuracy of the approximation.
That's why it's important to have a good size for the epsilon. However, for
your particular application, I think you don't need a very high accuracy for
the derivatives, so practically any reasonably small epsilon (1e-4?) will be
ok.
I searched for my Numerical Analysis notebook and didn't find it. But, I
just found a paper
(http://www.nek.uu.se/Utbildning/Foskarutbildning/MEnotes1.pdf) where the
optimal size for your epsilon, using central derivatives, is found out and
it is:
epsilon* = (3*EPS / M)^(1/3)
Where M is the highest value of the second derivative (in absolute value) of
the function in the interval (x-epsilon, x+epsilon) and it is often not
known and it is replaced by some estimate.
So, if you use a traditional PC, then EPS is approx. 2.2e1-6,
and if you ignore M, then you'll have:
epsilon* = (3*2.2e-16)^(1/3) = 8.7e-6
which is almost 1e-5, so I think 1e-5 is a pretty good size for your
epsilon.
I hope you can make some experiments and comment us your results.
Fernando.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Wasn't it Warp who wrote:
> I was experimenting with a small macro which creates a mesh shaped like
>a lathe from a spline. (The advantage of meshes over lathes is speed. Another
>one is that with lathes you sometimes get artifacts which you don't get with
>meshes.)
An alternative would be to consider that a spline function can also be
used in an isosurface. I've put a little example of this about halfway
down this page <http://www.econym.demon.co.uk/IsoTut/splines.htm>.
As it happens, this ends up being a ridiculously slow parametric
isosurface, so I use Ingo's macro to convert it to a mesh2 for the
actual rendering, so we end up doing the same thing.
This offers a little bit more flexibility. You can easily arrange for
the cross section to be something other than a circle and the axis to be
something other than a straight line as seen on that page. You can also
add other functions to the isosurface to achieve displacements.
#macro MakeEvenSplinePoints(Points)
#local Amnt = dimension_size(Points, 1)-1;
#local Ind = 0;
#while(Ind <= Amnt)
Ind/Amnt, Points[Ind]
#local Ind = Ind+1;
#end
#end
#declare Points = array[18]
{ <0,.1>,<1,0>,<1.2,.05>,<1,.1>,<.2,.3>,
<.25,.4>,<.1,.9>,<.1,2.5>,<.3,2.8>,<.3,3.1>,
<1,3.25>,<1.25,4>,<1,5>,<.9,5>,<1.1,4.5>,
<1.15,3.8>,<1,3.4>,<0,3.2>
}
#declare Spline = function {spline { cubic_spline
MakeEvenSplinePoints(Points) }}
camera { location -z*14 look_at 0 angle 35 orthographic translate y*2.5
}
light_source { <100,200,-300>, 1 }
light_source { <-100,20,-30>, <1,.5,0>*.5 }
plane { -z,0 pigment { checker rgb 1, rgb .5 } }
#declare Fx = function(x,y) {(Spline(u).x * sin(v))}
#declare Fy = function(x,y) {Spline(u).y}
#declare Fz = function(x,y) {(Spline(u).x * cos(v))}
#declare Umin = 0;
#declare Umax = 1;
#declare Vmin = -pi;
#declare Vmax = 1.001*pi;
#declare Iter_U = 80;
#declare Iter_V = 20;
#include "param.inc"
Parametric()
object {Surface
no_shadow
pigment { rgb 1 } finish { specular .5 }
}
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
>
> The only concern I have about it is that it uses the "trick" to calculate
> the normal of the spline with the Spline(T+Epsilon)-Spline(T-Epsilon)
> formula. What I'm not sure about is the value for 'Epsilon'. I used 1e-5,
> but that might sometimes be either too big or too small (due to floating
> point number inaccuracies).
No problem, just write a symbolic manipulation include that does
derivation and have it find the exact slope... ;)
--
David Fontaine <dav### [at] faricy net> ICQ 55354965
My raytracing gallery: http://davidf.faricy.net/
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |