Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/arithb.c')
-rw-r--r--source/blender/blenlib/intern/arithb.c560
1 files changed, 555 insertions, 5 deletions
diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c
index 2888a684af1..15ea647361f 100644
--- a/source/blender/blenlib/intern/arithb.c
+++ b/source/blender/blenlib/intern/arithb.c
@@ -2421,6 +2421,98 @@ short IsectLL2Df(float *v1, float *v2, float *v3, float *v4)
return 0;
}
+/*
+-1: colliniar
+ 1: intersection
+
+*/
+short IsectLLPt2Df(float x0,float y0,float x1,float y1,
+ float x2,float y2,float x3,float y3, float *xi,float *yi)
+
+{
+ /*
+ this function computes the intersection of the sent lines
+ and returns the intersection point, note that the function assumes
+ the lines intersect. the function can handle vertical as well
+ as horizontal lines. note the function isn't very clever, it simply
+ applies the math, but we don't need speed since this is a
+ pre-processing step
+ */
+ float c1,c2, // constants of linear equations
+ det_inv, // the inverse of the determinant of the coefficient
+ m1,m2; // the slopes of each line
+ /*
+ compute slopes, note the cludge for infinity, however, this will
+ be close enough
+ */
+ if ( fabs( x1-x0 ) > 0.000001 )
+ m1 = ( y1-y0 ) / ( x1-x0 );
+ else
+ return -1; /*m1 = ( float ) 1e+10;*/ // close enough to infinity
+
+ if ( fabs( x3-x2 ) > 0.000001 )
+ m2 = ( y3-y2 ) / ( x3-x2 );
+ else
+ return -1; /*m2 = ( float ) 1e+10;*/ // close enough to infinity
+
+ if (fabs(m1-m2) < 0.000001)
+ return -1; /* paralelle lines */
+
+// compute constants
+
+ c1 = ( y0-m1*x0 );
+ c2 = ( y2-m2*x2 );
+
+// compute the inverse of the determinate
+
+ det_inv = 1.0f / ( -m1 + m2 );
+
+// use Kramers rule to compute xi and yi
+
+ *xi= ( ( -c2 + c1 ) *det_inv );
+ *yi= ( ( m2*c1 - m1*c2 ) *det_inv );
+
+ return 1;
+} // end Intersect_Lines
+
+#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
+#define ISECT_EPSILON 1e-6
+
+/* point in tri */
+int IsectPT2Df(float pt[2], float v1[2], float v2[2], float v3[2])
+{
+ if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) &&
+ (SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) &&
+ (SIDE_OF_LINE(v3,v1,pt)>=-ISECT_EPSILON))
+ return 1;
+ else {
+ return 0;
+ }
+}
+/* point in quad - only convex quads */
+int IsectPQ2Df(float pt[2], float v1[2], float v2[2], float v3[2], float v4[2])
+{
+ if ((SIDE_OF_LINE(v1,v2,pt)>=-ISECT_EPSILON) &&
+ (SIDE_OF_LINE(v2,v3,pt)>=-ISECT_EPSILON) &&
+ (SIDE_OF_LINE(v3,v4,pt)>=-ISECT_EPSILON) &&
+ (SIDE_OF_LINE(v4,v1,pt)>=-ISECT_EPSILON))
+ return 1;
+ else
+ return 0;
+}
+
+
+
+ /* copied from Geometry.c - todo - move to arithb.c or some other generic place we can reuse */
+#define SIDE_OF_LINE(pa,pb,pp) ((pa[0]-pp[0])*(pb[1]-pp[1]))-((pb[0]-pp[0])*(pa[1]-pp[1]))
+#define POINT_IN_TRI(p0,p1,p2,p3) ((SIDE_OF_LINE(p1,p2,p0)>=0) && (SIDE_OF_LINE(p2,p3,p0)>=0) && (SIDE_OF_LINE(p3,p1,p0)>=0))
+
+/**
+ *
+ * @param min
+ * @param max
+ * @param vec
+ */
void MinMax3(float *min, float *max, float *vec)
{
if(min[0]>vec[0]) min[0]= vec[0];
@@ -3035,6 +3127,11 @@ float Vec2Lenf(float *v1, float *v2)
return (float)sqrt(x*x+y*y);
}
+float Vec2Length(float *v)
+{
+ return (float)sqrt(v[0]*v[0] + v[1]*v[1]);
+}
+
void Vec2Mulf(float *v1, float f)
{
v1[0]*= f;
@@ -3501,7 +3598,7 @@ void mul_v3_v3m4(float *v1, float *v2, float mat[][4])
test if the line starting at p1 ending at p2 intersects the triangle v0..v2
return non zero if it does
*/
-int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda)
+int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda, float *uv)
{
float p[3], s[3], d[3], e1[3], e2[3], q[3];
@@ -3527,15 +3624,318 @@ int LineIntersectsTriangle(float p1[3], float p2[3], float v0[3], float v1[3], f
v = f * Inpf(d, q);
if ((v < 0.0)||((u + v) > 1.0)) return 0;
+
+ if(uv) {
+ uv[0]= u;
+ uv[1]= v;
+ }
return 1;
}
+/* Adapted from the paper by Kasper Fauerby */
+/* "Improved Collision detection and Response" */
+int SweepingSphereIntersectsTriangleUV(float p1[3], float p2[3], float radius, float v0[3], float v1[3], float v2[3], float *lambda, float *ipoint)
+{
+ float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3];
+ float a, b, c, d, e, x, y, z, t, t0, t1, radius2=radius*radius;
+ float elen2,edotv,edotbv,nordotv,vel2;
+ int embedded_in_plane=0, found_by_sweep=0;
-/*
-find closest point to p on line through l1,l2
-and return lambda, where (0 <= lambda <= 1) when cp is in the line segement l1,l2
-*/
+ VecSubf(e1,v1,v0);
+ VecSubf(e2,v2,v0);
+ VecSubf(vel,p2,p1);
+
+/*---test plane of tri---*/
+ Crossf(nor,e1,e2);
+ Normalize(nor);
+ /* flip normal */
+ if(Inpf(nor,vel)>0.0f) VecMulf(nor,-1.0f);
+
+ a=Inpf(p1,nor)-Inpf(v0,nor);
+
+ nordotv=Inpf(nor,vel);
+
+ if ((nordotv > -0.000001) && (nordotv < 0.000001)) {
+ if(fabs(a)>=1.0f)
+ return 0;
+ else{
+ embedded_in_plane=1;
+ t0=0.0f;
+ t1=1.0f;
+ }
+ }
+ else{
+ t0=(radius-a)/nordotv;
+ t1=(-radius-a)/nordotv;
+ /* make t0<t1 */
+ if(t0>t1){b=t1; t1=t0; t0=b;}
+
+ if(t0>1.0f || t1<0.0f) return 0;
+
+ /* clamp to [0,1] */
+ t0=(t0<0.0f)?0.0f:((t0>1.0f)?1.0:t0);
+ t1=(t1<0.0f)?0.0f:((t1>1.0f)?1.0:t1);
+ }
+
+/*---test inside of tri---*/
+ if(embedded_in_plane==0){
+ /* plane intersection point */
+ VecCopyf(point,vel);
+ VecMulf(point,t0);
+ VecAddf(point,point,p1);
+ VecCopyf(temp,nor);
+ VecMulf(temp,radius);
+ VecSubf(point,point,temp);
+
+ /* is the point in the tri? */
+ a=Inpf(e1,e1);
+ b=Inpf(e1,e2);
+ c=Inpf(e2,e2);
+
+ VecSubf(temp,point,v0);
+ d=Inpf(temp,e1);
+ e=Inpf(temp,e2);
+
+ x=d*c-e*b;
+ y=e*a-d*b;
+ z=x+y-(a*c-b*b);
+
+ if(( ((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y)) ) & 0x80000000){
+ *lambda=t0;
+ VecCopyf(ipoint,point);
+ return 1;
+ }
+ }
+
+ *lambda=1.0f;
+/*---test points---*/
+ a=vel2=Inpf(vel,vel);
+
+ /*v0*/
+ VecSubf(temp,p1,v0);
+ b=2.0f*Inpf(vel,temp);
+ c=Inpf(temp,temp)-radius2;
+ d=b*b-4*a*c;
+
+ if(d>=0.0f){
+ if(d==0.0f)
+ t=-b/2*a;
+ else{
+ z=sqrt(d);
+ x=(-b-z)*0.5/a;
+ y=(-b+z)*0.5/a;
+ t=x<y?x:y;
+ }
+
+ if(t>0.0 && t < *lambda){
+ *lambda=t;
+ VecCopyf(ipoint,v0);
+ found_by_sweep=1;
+ }
+ }
+
+ /*v1*/
+ VecSubf(temp,p1,v1);
+ b=2.0f*Inpf(vel,temp);
+ c=Inpf(temp,temp)-radius2;
+ d=b*b-4*a*c;
+
+ if(d>=0.0f){
+ if(d==0.0f)
+ t=-b/2*a;
+ else{
+ z=sqrt(d);
+ x=(-b-z)*0.5/a;
+ y=(-b+z)*0.5/a;
+ t=x<y?x:y;
+ }
+
+ if(t>0.0 && t < *lambda){
+ *lambda=t;
+ VecCopyf(ipoint,v1);
+ found_by_sweep=1;
+ }
+ }
+ /*v2*/
+ VecSubf(temp,p1,v2);
+ b=2.0f*Inpf(vel,temp);
+ c=Inpf(temp,temp)-radius2;
+ d=b*b-4*a*c;
+
+ if(d>=0.0f){
+ if(d==0.0f)
+ t=-b/2*a;
+ else{
+ z=sqrt(d);
+ x=(-b-z)*0.5/a;
+ y=(-b+z)*0.5/a;
+ t=x<y?x:y;
+ }
+
+ if(t>0.0 && t < *lambda){
+ *lambda=t;
+ VecCopyf(ipoint,v2);
+ found_by_sweep=1;
+ }
+ }
+
+/*---test edges---*/
+ /*e1*/
+ VecSubf(bv,v0,p1);
+ elen2 = Inpf(e1,e1);
+ edotv = Inpf(e1,vel);
+ edotbv = Inpf(e1,bv);
+
+ a=elen2*(-Inpf(vel,vel))+edotv*edotv;
+ b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv);
+ c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv;
+ d=b*b-4*a*c;
+ if(d>=0.0f){
+ if(d==0.0f)
+ t=-b/2*a;
+ else{
+ z=sqrt(d);
+ x=(-b-z)*0.5/a;
+ y=(-b+z)*0.5/a;
+ t=x<y?x:y;
+ }
+
+ e=(edotv*t-edotbv)/elen2;
+
+ if((e>=0.0f) && (e<=1.0f)){
+ if(t>0.0 && t < *lambda){
+ *lambda=t;
+ VecCopyf(ipoint,e1);
+ VecMulf(ipoint,e);
+ VecAddf(ipoint,ipoint,v0);
+ found_by_sweep=1;
+ }
+ }
+ }
+
+ /*e2*/
+ /*bv is same*/
+ elen2 = Inpf(e2,e2);
+ edotv = Inpf(e2,vel);
+ edotbv = Inpf(e2,bv);
+
+ a=elen2*(-Inpf(vel,vel))+edotv*edotv;
+ b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv);
+ c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv;
+ d=b*b-4*a*c;
+ if(d>=0.0f){
+ if(d==0.0f)
+ t=-b/2*a;
+ else{
+ z=sqrt(d);
+ x=(-b-z)*0.5/a;
+ y=(-b+z)*0.5/a;
+ t=x<y?x:y;
+ }
+
+ e=(edotv*t-edotbv)/elen2;
+
+ if((e>=0.0f) && (e<=1.0f)){
+ if(t>0.0 && t < *lambda){
+ *lambda=t;
+ VecCopyf(ipoint,e2);
+ VecMulf(ipoint,e);
+ VecAddf(ipoint,ipoint,v0);
+ found_by_sweep=1;
+ }
+ }
+ }
+
+ /*e3*/
+ VecSubf(e3,v2,v1);
+ VecSubf(bv,v1,p1);
+ elen2 = Inpf(e3,e3);
+ edotv = Inpf(e3,vel);
+ edotbv = Inpf(e3,bv);
+
+ a=elen2*(-Inpf(vel,vel))+edotv*edotv;
+ b=2.0f*(elen2*Inpf(vel,bv)-edotv*edotbv);
+ c=elen2*(radius2-Inpf(bv,bv))+edotbv*edotbv;
+ d=b*b-4*a*c;
+ if(d>=0.0f){
+ if(d==0.0f)
+ t=-b/2*a;
+ else{
+ z=sqrt(d);
+ x=(-b-z)*0.5/a;
+ y=(-b+z)*0.5/a;
+ t=x<y?x:y;
+ }
+
+ e=(edotv*t-edotbv)/elen2;
+
+ if((e>=0.0f) && (e<=1.0f)){
+ if(t>0.0 && t < *lambda){
+ *lambda=t;
+ VecCopyf(ipoint,e3);
+ VecMulf(ipoint,e);
+ VecAddf(ipoint,ipoint,v1);
+ found_by_sweep=1;
+ }
+ }
+ }
+
+ return found_by_sweep;
+}
+int AxialLineIntersectsTriangle(int axis, float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *lambda)
+{
+ float p[3], e1[3], e2[3];
+ float u, v, f;
+ int a0=axis, a1=(axis+1)%3, a2=(axis+2)%3;
+
+ //return LineIntersectsTriangle(p1,p2,v0,v1,v2,lambda);
+
+ ///* first a simple bounding box test */
+ //if(MIN3(v0[a1],v1[a1],v2[a1]) > p1[a1]) return 0;
+ //if(MIN3(v0[a2],v1[a2],v2[a2]) > p1[a2]) return 0;
+ //if(MAX3(v0[a1],v1[a1],v2[a1]) < p1[a1]) return 0;
+ //if(MAX3(v0[a2],v1[a2],v2[a2]) < p1[a2]) return 0;
+
+ ///* then a full intersection test */
+
+ VecSubf(e1,v1,v0);
+ VecSubf(e2,v2,v0);
+ VecSubf(p,v0,p1);
+
+ f= (e2[a1]*e1[a2]-e2[a2]*e1[a1]);
+ if ((f > -0.000001) && (f < 0.000001)) return 0;
+
+ v= (p[a2]*e1[a1]-p[a1]*e1[a2])/f;
+ if ((v < 0.0)||(v > 1.0)) return 0;
+
+ f= e1[a1];
+ if((f > -0.000001) && (f < 0.000001)){
+ f= e1[a2];
+ if((f > -0.000001) && (f < 0.000001)) return 0;
+ u= (-p[a2]-v*e2[a2])/f;
+ }
+ else
+ u= (-p[a1]-v*e2[a1])/f;
+
+ if ((u < 0.0)||((u + v) > 1.0)) return 0;
+
+ *lambda = (p[a0]+u*e1[a0]+v*e2[a0])/(p2[a0]-p1[a0]);
+
+ if ((*lambda < 0.0)||(*lambda > 1.0)) return 0;
+
+ return 1;
+}
+
+int AabbIntersectAabb(float min1[3], float max1[3], float min2[3], float max2[3])
+{
+ return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&
+ min2[0]<max1[0] && min2[1]<max1[1] && min2[2]<max1[2]);
+}
+
+/* find closest point to p on line through l1,l2 and return lambda,
+ * where (0 <= lambda <= 1) when cp is in the line segement l1,l2
+ */
float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3])
{
float h[3],u[3],lambda;
@@ -3547,6 +3947,7 @@ float lambda_cp_line_ex(float p[3], float l1[3], float l2[3], float cp[3])
cp[2] = l1[2] + u[2] * lambda;
return lambda;
}
+
/* little sister we only need to know lambda */
float lambda_cp_line(float p[3], float l1[3], float l2[3])
{
@@ -3556,7 +3957,156 @@ float lambda_cp_line(float p[3], float l1[3], float l2[3])
return(Inpf(u,h)/Inpf(u,u));
}
+/* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */
+void PointInQuad2DUV(float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv)
+{
+ float x0,y0, x1,y1, wtot, v2d[2], w1, w2;
+
+ /* used for paralelle lines */
+ float pt3d[3], l1[3], l2[3], pt_on_line[3];
+
+ /* compute 2 edges of the quad intersection point */
+ if (IsectLLPt2Df(v0[0],v0[1],v1[0],v1[1], v2[0],v2[1],v3[0],v3[1], &x0,&y0) == 1) {
+ /* the intersection point between the quad-edge intersection and the point in the quad we want the uv's for */
+ /* should never be paralle !! */
+ /*printf("\tnot paralelle 1\n");*/
+ IsectLLPt2Df(pt[0],pt[1],x0,y0, v0[0],v0[1],v3[0],v3[1], &x1,&y1);
+
+ /* Get the weights from the new intersection point, to each edge */
+ v2d[0] = x1-v0[0];
+ v2d[1] = y1-v0[1];
+ w1 = Vec2Length(v2d);
+
+ v2d[0] = x1-v3[0]; /* some but for the other vert */
+ v2d[1] = y1-v3[1];
+ w2 = Vec2Length(v2d);
+ wtot = w1+w2;
+ /*w1 = w1/wtot;*/
+ /*w2 = w2/wtot;*/
+ uv[0] = w1/wtot;
+ } else {
+ /* lines are paralelle, lambda_cp_line_ex is 3d grrr */
+ /*printf("\tparalelle1\n");*/
+ pt3d[0] = pt[0];
+ pt3d[1] = pt[1];
+ pt3d[2] = l1[2] = l2[2] = 0.0f;
+
+ l1[0] = v0[0]; l1[1] = v0[1];
+ l2[0] = v1[0]; l2[1] = v1[1];
+ lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
+ v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */
+ v2d[1] = pt[1]-pt_on_line[1];
+ w1 = Vec2Length(v2d);
+
+ l1[0] = v2[0]; l1[1] = v2[1];
+ l2[0] = v3[0]; l2[1] = v3[1];
+ lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
+ v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */
+ v2d[1] = pt[1]-pt_on_line[1];
+ w2 = Vec2Length(v2d);
+ wtot = w1+w2;
+ uv[0] = w1/wtot;
+ }
+
+ /* Same as above to calc the uv[1] value, alternate calculation */
+
+ if (IsectLLPt2Df(v0[0],v0[1],v3[0],v3[1], v1[0],v1[1],v2[0],v2[1], &x0,&y0) == 1) { /* was v0,v1 v2,v3 now v0,v3 v1,v2*/
+ /* never paralle if above was not */
+ /*printf("\tnot paralelle2\n");*/
+ IsectLLPt2Df(pt[0],pt[1],x0,y0, v0[0],v0[1],v1[0],v1[1], &x1,&y1);/* was v0,v3 now v0,v1*/
+
+ v2d[0] = x1-v0[0];
+ v2d[1] = y1-v0[1];
+ w1 = Vec2Length(v2d);
+
+ v2d[0] = x1-v1[0];
+ v2d[1] = y1-v1[1];
+ w2 = Vec2Length(v2d);
+ wtot = w1+w2;
+ uv[1] = w1/wtot;
+ } else {
+ /* lines are paralelle, lambda_cp_line_ex is 3d grrr */
+ /*printf("\tparalelle2\n");*/
+ pt3d[0] = pt[0];
+ pt3d[1] = pt[1];
+ pt3d[2] = l1[2] = l2[2] = 0.0f;
+
+
+ l1[0] = v0[0]; l1[1] = v0[1];
+ l2[0] = v3[0]; l2[1] = v3[1];
+ lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
+ v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */
+ v2d[1] = pt[1]-pt_on_line[1];
+ w1 = Vec2Length(v2d);
+
+ l1[0] = v1[0]; l1[1] = v1[1];
+ l2[0] = v2[0]; l2[1] = v2[1];
+ lambda_cp_line_ex(pt3d, l1, l2, pt_on_line);
+ v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */
+ v2d[1] = pt[1]-pt_on_line[1];
+ w2 = Vec2Length(v2d);
+ wtot = w1+w2;
+ uv[1] = w1/wtot;
+ }
+ /* may need to flip UV's here */
+}
+
+/* same as above but does tri's and quads, tri's are a bit of a hack */
+void PointInFace2DUV(int isquad, float v0[2], float v1[2], float v2[2], float v3[2], float pt[2], float *uv)
+{
+ if (isquad) {
+ PointInQuad2DUV(v0, v1, v2, v3, pt, uv);
+ }
+ else {
+ /* not for quads, use for our abuse of LineIntersectsTriangleUV */
+ float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3], lambda;
+
+ p1_3d[0] = p2_3d[0] = uv[0];
+ p1_3d[1] = p2_3d[1] = uv[1];
+ p1_3d[2] = 1.0f;
+ p2_3d[2] = -1.0f;
+ v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0;
+
+ /* generate a new fuv, (this is possibly a non optimal solution,
+ * since we only need 2d calculation but use 3d func's)
+ *
+ * this method makes an imaginary triangle in 2d space using the UV's from the derived mesh face
+ * Then find new uv coords using the fuv and this face with LineIntersectsTriangleUV.
+ * This means the new values will be correct in relation to the derived meshes face.
+ */
+ Vec2Copyf(v0_3d, v0);
+ Vec2Copyf(v1_3d, v1);
+ Vec2Copyf(v2_3d, v2);
+
+ /* Doing this in 3D is not nice */
+ LineIntersectsTriangle(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, uv);
+ }
+}
+
+/* (x1,v1)(t1=0)------(x2,v2)(t2=1), 0<t<1 --> (x,v)(t) */
+void VecfCubicInterpol(float *x1, float *v1, float *x2, float *v2, float t, float *x, float *v)
+{
+ float a[3],b[3];
+ float t2= t*t;
+ float t3= t2*t;
+ /* cubic interpolation */
+ a[0]= v1[0] + v2[0] + 2*(x1[0] - x2[0]);
+ a[1]= v1[1] + v2[1] + 2*(x1[1] - x2[1]);
+ a[2]= v1[2] + v2[2] + 2*(x1[2] - x2[2]);
+
+ b[0]= -2*v1[0] - v2[0] - 3*(x1[0] - x2[0]);
+ b[1]= -2*v1[1] - v2[1] - 3*(x1[1] - x2[1]);
+ b[2]= -2*v1[2] - v2[2] - 3*(x1[2] - x2[2]);
+
+ x[0]= a[0]*t3 + b[0]*t2 + v1[0]*t + x1[0];
+ x[1]= a[1]*t3 + b[1]*t2 + v1[1]*t + x1[1];
+ x[2]= a[2]*t3 + b[2]*t2 + v1[2]*t + x1[2];
+
+ v[0]= 3*a[0]*t2 + 2*b[0]*t + v1[0];
+ v[1]= 3*a[1]*t2 + 2*b[1]*t + v1[1];
+ v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2];
+}
int point_in_slice(float p[3], float v1[3], float l1[3], float l2[3])
{