home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Graphics
/
Graphics.zip
/
povsrc31.zip
/
bezier2.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-11-26
|
22KB
|
912 lines
#include "frame.h"
#include "vector.h"
#include "povproto.h"
#include "bezier.h"
#include "matrices.h"
#include "objects.h"
#include "povray.h"
#ifdef RBezierPatch
/* following magical constant serves to detection of multiple intesections.
according do NSK (Nishita, Sederberg,Kakimoto) set to 20% */
#define MAGICAL_CONSTANT (1.0 - 0.2)
/*YS*/
#ifndef INFINITY
#define INFINITY 1.0e100
#endif
/*YS*/
#define VERY_SMALL_EPSILON 1.0e-20
/*YS*/
#ifndef MACOS
/* just for debugging */
#define FIXME { printf("FIXME: file %s: line %d", \
__FILE__, \
__LINE__); exit(0); }
#else
#define FIXME
#endif
/*YS*/
static RAY *Current_Ray;
static BICUBIC_PATCH *Current_Shape;
static ISTACK *Current_Depth_Stack;
static int bezier_compute_plane_points_distances(DBL p[4][4],VECTOR n,DBL d, VECTOR cp[4][4]);
static int rbezier_compute_plane_points_distances(DBL p[4][4], VECTOR n, DBL d, VECTOR cp[4][4], WEIGHTS w);
static void compute_line_points_distance( DISTANCES d, DBL vec[2], DISTANCES points[2]);
static int new_line0(DISTANCES p[2], DBL Line[2]);
static int new_line1(DISTANCES p[2], DBL Line[2]);
static int bezier_bounds(DISTANCES p[2], DBL interval[2][2]);
static void split_patch_0(DISTANCES p[2], DBL where, DISTANCES first[2],DISTANCES second[2] );
static void split_patch_1(DISTANCES p[2], DBL where, DISTANCES first[2],DISTANCES second[2] ) ;
static int bezier_get_minmax_0(DISTANCES d,DBL *min,DBL *max);
static int bezier_get_minmax_1(DISTANCES d,DBL *min,DBL *max);
static void decasteljau (VECTOR cpoints[4][4], DBL u, DBL v, VECTOR point, VECTOR normal);
static void rb_decasteljau (VECTOR cpoints[4][4], WEIGHTS w, DBL u, DBL v, VECTOR point, VECTOR normal);
static int add_solution(DBL u,DBL v);
static int find_solution( DISTANCES p[2], DBL interval[2][2], DBL bounds[2][2]);
void find_planes (VECTOR point,VECTOR dir,VECTOR n1,DBL * d1,VECTOR n2,DBL * d2)
{
DBL tmp1, tmp2;
if ( fabs(dir[X] < 0.5 ))
{
n1[X]= 0.0;
tmp1= n1[Y]= dir[Z];
tmp2= n1[Z]= -dir[Y];
tmp1= sqrt(tmp1*tmp1+tmp2*tmp2);
n1[Y]/= tmp1;
n1[Z]/= tmp1;
}
else
{
tmp1= n1[X]= -dir[Z];
n1[Y]= 0.0;
tmp2= n1[Z]= dir[X];
tmp1= sqrt(tmp1*tmp1+tmp2*tmp2);
n1[X]/= tmp1;
n1[Z]/= tmp1;
}
VCross(n2, dir, n1);
VDot( *d1, point, n1);
*d1= - *d1;
VDot( *d2, point, n2);
*d2= - *d2;
}
/*
this funciton computes distace between control points (cp) and plane (normal n, distance d)
if there can not be intersection between simple convex hul and ray (ie all distances are greater than 0 or less than 0)
returns 0
*/
static int bezier_compute_plane_points_distances(DBL p[4][4],VECTOR n,DBL d, VECTOR cp[4][4])
{
int i,j;
VECTOR *cptmp;
DBL *ptmp;
DBL a,b,c;
DBL min,max;
ptmp= *p;
cptmp= *cp;
a= n[X]; b= n[Y]; c= n[Z];
min= INFINITY;
max= - INFINITY;
for (i=0; i<4; i++)
for (j=0; j<4; j++, ptmp++, cptmp++)
{
*ptmp= (*cptmp)[X]*a + (*cptmp)[Y]*b + (*cptmp)[Z]*c +d;
if (*ptmp < min) min=*ptmp;
if (*ptmp > max) max=*ptmp;
}
if ((min>0.0)||(max<0.0))
return 0;
else
return 1;
}
static int rbezier_compute_plane_points_distances(DBL p[4][4], VECTOR n, DBL d, VECTOR cp[4][4], WEIGHTS w)
{
int i,j;
VECTOR *cptmp;
DBL *ptmp;
DBL *wptr;
DBL a,b,c;
DBL min,max;
ptmp= *p;
cptmp= *cp;
wptr= *w;
a= n[X]; b= n[Y]; c= n[Z];
min= INFINITY;
max= - INFINITY;
for (i=0; i<4; i++)
for (j=0; j<4; j++, ptmp++, cptmp++, wptr++)
{
*ptmp= (*wptr) * ((*cptmp)[X]*a + (*cptmp)[Y]*b + (*cptmp)[Z]*c +d );
if (*ptmp < min) min=*ptmp;
if (*ptmp > max) max=*ptmp;
}
if ((min>0.0)||(max<0.0))
return 0;
else
return 1;
}
static void compute_line_points_distance( DISTANCES d, DBL vec[2], DISTANCES points[2])
{
int i,j;
DBL a,b;
DBL *ptmp, *xtmp, *ytmp;
a=vec[0];
b=vec[1];
ptmp= *d;
xtmp= **points;
ytmp= *(points[1]);
for (i=0; i<4;i++)
for (j=0; j<4; j++, ptmp++, xtmp++, ytmp++)
*ptmp= (*xtmp)*a + (*ytmp)*b;
}
static int new_line0(DISTANCES p[2], DBL Line[2])
{
DBL tmp;
Line[0]= p[1][3][0] - p[1][0][0] + p[1][3][3] - p[1][0][3];
Line[1]= - (p[0][3][0] - p[0][0][0] + p[0][3][3] - p[0][0][3]);
tmp= Line[0]*Line[0]+Line[1]*Line[1];
if (tmp < VERY_SMALL_EPSILON)
return 0;
tmp= sqrt(tmp);
Line[0]/= tmp;
Line[1]/= tmp;
return 1;
}
static int new_line1(DISTANCES p[2], DBL Line[2])
{
DBL tmp;
Line[0]= p[1][0][3] - p[1][0][0] + p[1][3][3] - p[1][3][0];
Line[1]= -( p[0][0][3] - p[0][0][0] + p[0][3][3] - p[0][3][0] );
tmp= Line[0]*Line[0]+Line[1]*Line[1];
if (tmp < VERY_SMALL_EPSILON)
return 0;
tmp= sqrt (tmp);
Line[0]/= tmp;
Line[1]/= tmp;
return 1;
}
/* conv. hull does not contain [0,0] */
static int bezier_bounds(DISTANCES p[2], DBL interval[2][2])
{
int i,j;
DBL *itmp;
DBL *min, *max;
int ret=0;
for (i=0; i<2; i++)
{
itmp = &(p[i][0][0]);
min= & (interval[i][0]);
max= & (interval[i][1]);
*min=*max= *(itmp++);
for(j=15; j ; j--, itmp++ )
{
if ( *itmp < *min )
*min= *itmp;
else
if ( *itmp > *max )
*max= *itmp;
}
ret|= (*min > EPSILON) || (*max < -EPSILON);
}
return !ret;
}
static void split_patch_0(DISTANCES p[2], DBL where, DISTANCES first[2],DISTANCES second[2] )
{
int i,l;
DISTANCES tmp;
DBL *p_i;
DBL *fi_i;
DBL *se_i;
DBL where2;
where2= 1.0 - where;
for (l=0; l<2; l++)
{
p_i= & (p[l][0][0]);
fi_i= & (first[l][0][0]);
se_i= & (second[l][0][0]);
se_i+= 3;
for (i=0;
i<4;
i++
)
{
tmp[1][0]= where2 * (* fi_i= * p_i); p_i++; fi_i++;
*fi_i= tmp[1][0]+= where * (* p_i);
fi_i++;
tmp[1][1]= where2 * (* p_i); p_i+= 1; tmp[1][1]+= where * (* p_i);
tmp[1][2]= where2 * (* p_i); p_i+= 1; tmp[1][2]+= where * (*se_i = * p_i);
se_i--;
p_i++;
*fi_i= tmp[2][0]= where2 * tmp[1][0] + where * tmp[1][1];
fi_i++;
tmp[2][1]= where2 * tmp[1][1] + where * (*se_i= tmp[1][2]);
se_i--;
*fi_i= where2 * tmp[2][0] + where * (*se_i= tmp[2][1]);
se_i--;
*se_i= *fi_i;
fi_i++;
se_i+= 7;
}
}
}
static void split_patch_1(DISTANCES p[2], DBL where, DISTANCES first[2],DISTANCES second[2] )
{
int i,l;
DISTANCES tmp;
DBL *p_i;
DBL *fi_i;
DBL *se_i;
DBL where2;
where2= 1.0 - where;
for (l=0; l<2; l++)
{
p_i= & (p[l][0][0]);
fi_i= & (first[l][0][0]);
se_i= & (second[l][0][0]);
se_i+= 3* 4;
for (i=0;
i<4;
i++
)
{
tmp[1][0]= where2 * (* fi_i= * p_i); p_i+= 4; fi_i+= 4;
*fi_i= tmp[1][0]+= where * (* p_i);
fi_i+= 4;
tmp[1][1]= where2 * (* p_i); p_i+= 4; tmp[1][1]+= where * (* p_i);
tmp[1][2]= where2 * (* p_i); p_i+= 4; tmp[1][2]+= where * (*se_i = * p_i);
se_i-= 4;
*fi_i= tmp[2][0]= where2 * tmp[1][0] + where * tmp[1][1];
fi_i+= 4;
tmp[2][1]= where2 * tmp[1][1] + where * (*se_i= tmp[1][2]);
se_i-= 4;
*fi_i= where2 * tmp[2][0] + where * (*se_i= tmp[2][1]);
se_i-= 4;
*se_i= *fi_i;
fi_i-= 3*4 - 1;
p_i -= 3*4 - 1;
se_i+= 1 + 3* 4;
}
}
}
static void (*split_patch[2])(DISTANCES *, DBL, DISTANCES *, DISTANCES *) =
{ split_patch_0, split_patch_1 };
static int bezier_get_minmax_0(DISTANCES d,DBL *min,DBL *max)
{
DBL *p, *n, *pp, tmp;
int f,l;
int i;
*min = 2.0;
*max = -2.0;
f=l= 0;
for (i=0; i<4; i++)
{
n= 1 + (p= pp= &(d[i][0]) );
if ( *p < 0.0 ) f++;
if ( (*p <= 0.0) ^ (*n <= 0.0) ) /* 0,1 */
{
tmp= /* 0.0 / 3.0 + */ (1.0 / 3.0) * (*p) / ( (*p) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
p++; n++;
if ( (*p <= 0.0) ^ (*n <= 0.0) ) /* 1,2 */
{
tmp= 1.0 / 3.0 + (1.0 / 3.0) * (*p) / ( (*p) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
if ( (*pp <= 0.0) ^ (*n <= 0.0) ) /* 0,2 */
{
tmp= /* 0.0 / 3.0 + */ (2.0 / 3.0) * (*pp) / ( (*pp) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
p++; n++;
if ( (*p <= 0.0) ^ (*n <= 0.0) ) /* 2,3 */
{
tmp= 2.0 / 3.0 + (1.0 / 3.0) * (*p) / ( (*p) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
if ( (*pp <= 0.0) ^ (*n <= 0.0) ) /* 0,3 */
{
tmp= /* 0.0 / 3.0 + (3.0 / 3.0) */ (*pp) / ( (*pp) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
pp++;
if ( (*pp <= 0.0) ^ (*n <= 0.0) ) /* 1,3 */
{
tmp= 1.0 / 3.0 + (2.0 / 3.0) * (*pp) / ( (*pp) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
if ( *n < 0.0 ) l++;
}
if ( (f & 3) != 0) *min = 0.0;
if ( (l & 3) != 0) *max = 1.0;
if (*min > *max) return 0; /* no solution found */
else return 1;
}
static int bezier_get_minmax_1(DISTANCES d,DBL *min,DBL *max)
{
DBL *p, *n, *pp, tmp;
int f,l;
int i;
f=l= 0;
*min = 2.0;
*max = -2.0;
for (i=0; i<4; i++)
{
n= 4 + (p= pp= &(d[0][i]) );
if ( *p < 0.0) f++;
if ( (*p <= 0.0) ^ (*n <= 0.0) ) /* 0,1 */
{
tmp= /* 0.0 / 3.0 + */ (1.0 / 3.0) * (*p) / ( (*p) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
p+= 4; n+= 4;
if ( (*p <= 0.0) ^ (*n <= 0.0) ) /* 1,2 */
{
tmp= 1.0 / 3.0 + (1.0 / 3.0) * (*p) / ( (*p) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
if ( (*pp <= 0.0) ^ (*n <= 0.0) ) /* 0,2 */
{
tmp= /* 0.0 / 3.0 */ + (2.0 / 3.0) * (*pp) / ( (*pp) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
p+= 4; n+= 4;
if ( (*p <= 0.0) ^ (*n <= 0.0) ) /* 2,3 */
{
tmp= 2.0 / 3.0 + (1.0 / 3.0) * (*p) / ( (*p) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
if ( (*pp <= 0.0) ^ (*n <= 0.0) ) /* 0,3 */
{
tmp= /* 0.0 / 3.0 + (3.0 / 3.0) */ (*pp) / ( (*pp) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
pp+=4;
if ( (*pp <= 0.0) ^ (*n <= 0.0) ) /* 1,3 */
{
tmp= 1.0 / 3.0 + (2.0 / 3.0) * (*pp) / ( (*pp) - (*n) );
if (tmp < *min) *min= tmp;
if (tmp > *max) *max= tmp;
}
if ( *n < 0.0 ) l++;
}
if ( (f & 3) != 0) *min = 0.0;
if ( (l & 3) != 0) *max = 1.0;
if (*min > *max) return 0; /* no solution found */
else return 1;
}
static int (*bezier_get_minmax[2])(DISTANCES ,DBL *, DBL *) =
{ bezier_get_minmax_0, bezier_get_minmax_1 };
/*
static void
solve_as_curve(p, iii, where)
DISTANCES p[2];
int iii;
DBL where;
{
FIXME;
}
*/
static void decasteljau (VECTOR cpoints[4][4], DBL u, DBL v, VECTOR point, VECTOR normal)
{
int i,j;
DBL m, n;
VECTOR v0, v1;
DBL *pp, *nn;
DBL q[4];
DBL ftmp;
DISTANCES tmp;
m= 1.0 - u;
n= 1.0 - v;
for (i=0; i<3; i++)
{
nn= 3 + (pp= &(cpoints [0][0][i]) );
for (j=0; j < 4; j++)
{
tmp[0][0]= m * (*pp) + u * (*nn); pp+=3; nn+=3;
tmp[0][1]= m * (*pp) + u * (*nn); pp+=3; nn+=3;
tmp[0][2]= m * (*pp) + u * (*nn); pp+=6; nn+=6;
tmp[1][0]= m * tmp[0][0] + u * tmp[0][1];
tmp[1][1]= m * tmp[0][1] + u * tmp[0][2];
q[j]= m * tmp[1][0] + u * tmp[1][1];
}
tmp[0][0]= n * q[0] + v * q[1];
tmp[0][1]= n * q[1] + v * q[2];
tmp[0][2]= n * q[2] + v * q[3];
tmp[1][0] = n * tmp[0][0] + v * tmp[0][1];
tmp[1][1] = n * tmp[0][1] + v * tmp[0][2];
v0[i]= tmp[1][1] - tmp[1][0];
point[i]= n * tmp[1][0] + v * tmp[1][1];
}
for (i=0; i<3; i++)
{
nn= 3 * 4 + ( pp= &( cpoints [0][0][i] ));
for (j=0; j < 4; j++)
{
tmp[0][0]= n * (*pp) + v * (*nn); pp+=3*4; nn+=3*4;
tmp[0][1]= n * (*pp) + v * (*nn); pp+=3*4; nn+=3*4;
tmp[0][2]= n * (*pp) + v * (*nn); pp-=2*3*4-3; nn-=2*3*4-3;
tmp[1][0]= n * tmp[0][0] + v * tmp[0][1];
tmp[1][1]= n * tmp[0][1] + v * tmp[0][2];
q[j]= n * tmp[1][0] + v * tmp[1][1];
}
tmp[0][0]= m * q[0] + u * q[1];
tmp[0][1]= m * q[1] + u * q[2];
tmp[0][2]= m * q[2] + u * q[3];
tmp[1][0] = m * tmp[0][0] + u * tmp[0][1];
tmp[1][1] = m * tmp[0][1] + u * tmp[0][2];
v1[i]= tmp[1][1] - tmp[1][0];
}
VCross(normal,v0,v1);
VLength(ftmp, normal);
if (ftmp < VERY_SMALL_EPSILON)
{ normal[X]=normal[Y]=0.0; normal[Z]=1.0; }
else
{ normal[X]/= ftmp; normal[Y]/= ftmp; normal[Z]/= ftmp; }
}
static void rb_decasteljau (VECTOR cpoints[4][4], WEIGHTS w, DBL u, DBL v, VECTOR point, VECTOR normal)
{
int i,j;
DBL m, n;
VECTOR v0, v1;
DBL *pp, *nn, *wptr;
DBL q[4];
DBL ftmp;
DBL wpoints[4][4][4];
DBL w0,w1,w00;
DBL tmp[2][4];
wptr= & ( w[0][0] );
pp= & ( cpoints[0][0][0] );
nn= & ( wpoints[0][0][0] ) ;
for (i=0; i<16; i++)
{
*nn= (*pp) * (*wptr); nn++; pp++;
*nn= (*pp) * (*wptr); nn++; pp++;
*nn= (*pp) * (*wptr); nn++; pp++;
*nn= (*wptr); nn++; wptr++;
}
m= 1.0 - u;
n= 1.0 - v;
for (i=3; i>=0; i--)
{
nn= 4 + (pp= &(wpoints [0][0][i]) );
for (j=0; j < 4; j++)
{
tmp[0][0]= m * (*pp) + u * (*nn); pp+=4; nn+=4;
tmp[0][1]= m * (*pp) + u * (*nn); pp+=4; nn+=4;
tmp[0][2]= m * (*pp) + u * (*nn); pp+=8; nn+=8;
tmp[1][0]= m * tmp[0][0] + u * tmp[0][1];
tmp[1][1]= m * tmp[0][1] + u * tmp[0][2];
q[j]= m * tmp[1][0] + u * tmp[1][1];
}
tmp[0][0]= n * q[0] + v * q[1];
tmp[0][1]= n * q[1] + v * q[2];
tmp[0][2]= n * q[2] + v * q[3];
tmp[1][0] = n * tmp[0][0] + v * tmp[0][1];
tmp[1][1] = n * tmp[0][1] + v * tmp[0][2];
if (i!=3)
{
v0[i]= tmp[1][1] / w1 - tmp[1][0] / w0;
point[i]= (n * tmp[1][0] + v * tmp[1][1]) / w00;
}
else
{
w00= (n * (w0= tmp[1][0]) + v * (w1= tmp[1][1]) );
}
}
for (i=3; i>=0; i--)
{
nn= 4 * 4 + ( pp= &( wpoints [0][0][i] ));
for (j=0; j < 4; j++)
{
tmp[0][0]= n * (*pp) + v * (*nn); pp+=4*4; nn+=4*4;
tmp[0][1]= n * (*pp) + v * (*nn); pp+=4*4; nn+=4*4;
tmp[0][2]= n * (*pp) + v * (*nn); pp-=2*4*4-4; nn-=2*4*4-4;
tmp[1][0]= n * tmp[0][0] + v * tmp[0][1];
tmp[1][1]= n * tmp[0][1] + v * tmp[0][2];
q[j]= n * tmp[1][0] + v * tmp[1][1];
}
tmp[0][0]= m * q[0] + u * q[1];
tmp[0][1]= m * q[1] + u * q[2];
tmp[0][2]= m * q[2] + u * q[3];
tmp[1][0] = m * tmp[0][0] + u * tmp[0][1];
tmp[1][1] = m * tmp[0][1] + u * tmp[0][2];
if (i!=3)
{
v1[i]= tmp[1][1] / w1 - tmp[1][0] / w0;
}
else
{
w0= tmp[1][0]; w1= tmp[1][1];
}
}
VCross(normal,v0,v1);
VLength(ftmp, normal);
if (ftmp < VERY_SMALL_EPSILON)
{ normal[X]=normal[Y]=0.0; normal[Z]=1.0; }
else
{ normal[X]/= ftmp; normal[Y]/= ftmp; normal[Z]/= ftmp; }
}
static int add_solution(DBL u,DBL v)
{
VECTOR point, normal;
DBL depth;
#ifdef UpdatedUVMappingPatch
UV_VECT UV; /* MH */
double uv_point[2], tpoint[3]; /*MH */
#endif
if ((u<0.0) || (u> 1.0) || (v < 0.0) || ( v > 1.0)) return 0;
if ( Current_Shape -> Patch_Type == RATIONAL_BEZIER_NSK)
rb_decasteljau( Current_Shape -> Control_Points,*Current_Shape -> Weights,
u, v, point, normal );
else
decasteljau( Current_Shape -> Control_Points, u, v, point, normal );
if (fabs(Current_Ray->Direction[X]) > 0.5 )
depth= (point[X]- Current_Ray->Initial[X]) / Current_Ray->Direction[X];
else
if (fabs(Current_Ray->Direction[Y]) > 0.5 )
depth= (point[Y]- Current_Ray->Initial[Y]) / Current_Ray->Direction[Y];
else
depth= (point[Z]- Current_Ray->Initial[Z]) / Current_Ray->Direction[Z];
if ( depth < 4.0 * Current_Shape-> accuracy)
return 0;
#ifndef UpdatedUVMappingPatch
push_normal_entry(depth, point, normal, (OBJECT *)Current_Shape, Current_Depth_Stack);
#else
/* MH */
/* transform current point from uv space to texture space */
uv_point[0] = u;
uv_point[1] = v;
MTransUVPoint(uv_point, Current_Shape->Mapping, tpoint);
UV[U] = tpoint[0];
UV[V] = tpoint[1];
push_normal_uv_entry(depth, point, normal, UV, (OBJECT *)Current_Shape, Current_Depth_Stack);
/* MH */
#endif
return 1;
}
static int find_solution( DISTANCES p[2],
DBL interval[2][2],/* attention, this is strange interval, first is begin, second is length */
DBL bounds[2][2] /* this is bounding box in trans. coordinates */
)
{
int iii;
DBL Line[2];
DBL tmp;
int in_half=0;
DISTANCES d;
DBL min,max;
if ( (bounds[1][1]-bounds[1][0] < Current_Shape->accuracy)
&& (bounds[0][1]-bounds[0][0] < Current_Shape->accuracy))
{ /* end of iteration ...*/
return add_solution( interval[0][0]+ interval[0][1]/2.0, interval[1][0] + interval[1][1]/2.0 );
FIXME /* soupni sem presnejsi resitko ...!!! */
}
if ( interval[0][1] > interval[1][1] )
{
iii=0;
if ( new_line0(p, Line) == 0)
if ( new_line1(p, Line) == 0)
in_half=1; /* degenerated patch -=> split in half */
else
{
tmp= -Line[0];
Line[0]= Line[1];
Line[1]= tmp;
}
}
else
{
iii=1;
if ( new_line1(p, Line) == 0)
if ( new_line0(p, Line) == 0)
in_half=1; /* degenerated patch -=> split in half */
else
{
tmp= -Line[0];
Line[0]= Line[1];
Line[1]= tmp;
}
}
/* FIXME */
/* in_half=1; */
if (in_half == 0)
{
compute_line_points_distance( d, Line, p );
if (bezier_get_minmax[iii](d, &min, &max)==0) return 0;
if ( (tmp= max-min) > MAGICAL_CONSTANT )
in_half= 1;
else
{
/*
if (tmp < EPSILON)
solve_as_surve(p,iii,min);
FIXME
*/
{
DISTANCES ptmp1[2],ptmp2[2];
/* is seems that this "speed-up" is "slow-down" :-)
if (min == 0.0)
{
split_patch[iii]( p, max, ptmp1, ptmp2);
if (bezier_bounds(ptmp1, bounds ) == 0) return 0;
interval[iii][1] = interval[iii][1]*max;
return find_solution(ptmp1, interval, bounds);
}
if (max == 1.0)
{
split_patch[iii]( p, min, ptmp1, ptmp2);
if (bezier_bounds(ptmp2, bounds ) == 0) return 0;
interval[iii][0]+= interval[iii][1]*min;
interval[iii][1] = interval[iii][1]*tmp;
return find_solution(ptmp2, interval, bounds);
}
*/
if (min < 0.5)
{
split_patch[iii]( p,min, ptmp1, ptmp2);
split_patch[iii]( ptmp2, (max-min) / (1.0 - min), p, ptmp1);
}
else
{
split_patch[iii]( p,max,ptmp1, ptmp2);
split_patch[iii]( ptmp1,min/max, ptmp2, p);
}
}
if (bezier_bounds(p, bounds ) == 0) return 0;
interval[iii][0]+= interval[iii][1]*min;
interval[iii][1] = interval[iii][1]*tmp;
return find_solution(p, interval, bounds);
}
}
if (in_half == 1)
{
DISTANCES ld[2], rd[2];
DBL ni[2][2];
int ret=0;
split_patch[iii](p, 0.5, ld, rd);
tmp= interval[iii][1]/= 2.0;
memcpy( &(ni[0][0]), &(interval[0][0]), 4 * sizeof(DBL));
ni[iii][0]+= tmp;
if (bezier_bounds(ld,bounds) != 0)
ret|= find_solution(ld, interval, bounds);
if (bezier_bounds(rd, bounds) != 0)
ret|= find_solution(rd, ni, bounds);
return ret;
}
printf("Bezier 2: This should never ever happend :-)\n");
return 0;
}
int intersect_bicubic_patch_nsk (RAY * Ray,BICUBIC_PATCH *Shape,ISTACK * Depth_Stack)
{
VECTOR n0,n1;
DBL d0,d1; /* two perpendicular planes. intersection( pl1, pl2 ) == Ray */
DISTANCES p[2];
DBL interval[2][2];
DBL sti[2][2];
find_planes( Ray->Initial, Ray->Direction, n0, &d0, n1, &d1 );
if ( Shape -> Patch_Type == BEZIER_NSK )
{
if (bezier_compute_plane_points_distances(p[0], n0, d0, Shape->Control_Points) == 0)
return 0;
if (bezier_compute_plane_points_distances(p[1], n1, d1, Shape->Control_Points) == 0)
return 0;
}
else
{
if (rbezier_compute_plane_points_distances(p[0], n0, d0, Shape->Control_Points, *Shape-> Weights) == 0)
return 0;
if (rbezier_compute_plane_points_distances(p[1], n1, d1, Shape->Control_Points, *Shape-> Weights) == 0)
return 0;
}
Current_Ray=Ray;
Current_Shape=Shape;
Current_Depth_Stack= Depth_Stack;
interval[0][0]=interval[1][0]= 0.0;
interval[0][1]=interval[1][1]= 1.0;
sti[1][1]= sti[0][1]= INFINITY;
sti[1][0]= sti[0][0]=-INFINITY;
return find_solution( p, interval, sti );
}
#else
static char dummy[2];
#endif