/* vector.h: all about vectors */ #ifndef _VECTOR_H_ #define _VECTOR_H_ #ifdef __cplusplus extern "C" { #endif #include #include "Float.h" #include "mymath.h" #include "vectortype.h" /* fills in x, y, and z component of a vector */ #define VECTORSET(v, a, b, c) {(v).x = a; (v).y = b; (v).z = c;} /* copies the vector v to d: d = v. They may be different vector types. */ #define VECTORCOPY(v, d) {(d).x = (v).x; (d).y = (v).y; (d).z = (v).z;} /* tolerance value for e.g. a vertex position */ #define VECTORTOLERANCE(v) (EPSILON * (fabs((v).x) + fabs((v).y) + fabs((v).z))) /* two vectors are equal if their components are equal within the given tolerance. */ #define VECTOREQUAL(v, w, eps) (FLOATEQUAL((v).x, (w).x, (eps)) && \ FLOATEQUAL((v).y, (w).y, (eps)) && \ FLOATEQUAL((v).z, (w).z, (eps))) /* vector difference */ #define VECTORSUBTRACT VECTORDIFF #define VECTORDIFF(a, b, d) {(d).x = (a).x - (b).x; \ (d).y = (a).y - (b).y; \ (d).z = (a).z - (b).z;} /* scaled vector difference: d = a-s.b */ #define VECTORSUBTRACTSCALED VECTORDIFFSCALED #define VECTORDIFFSCALED(a, s, b, d){(d).x = (a).x - (s) * (b).x; \ (d).y = (a).y - (s) * (b).y; \ (d).z = (a).z - (s) * (b).z;} /* vector sum: d = a+b */ #define VECTORADD VECTORSUM #define VECTORSUM(a, b, d) {(d).x = (a).x + (b).x; \ (d).y = (a).y + (b).y; \ (d).z = (a).z + (b).z;} /* scaled vector sum: d = a+s.b */ #define VECTORADDSCALED VECTORSUMSCALED #define VECTORSUMSCALED(a, s, b, d) {(d).x = (a).x + (s) * (b).x; \ (d).y = (a).y + (s) * (b).y; \ (d).z = (a).z + (s) * (b).z;} /* scalar vector product: a.b */ #define VECTORDOTPRODUCT(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) /* square of vector norm: scalar product with itself */ #define VECTORNORM2(v) ((v).x * (v).x + (v).y * (v).y + (v).z * (v).z) /* norm of a vector: sqaure root of the sqaure norm */ #define VECTORNORM(v) (double)sqrt((double)VECTORNORM2(v)) /* scale a vector: d = s.v (s is a real number) */ #define VECTORSCALE(s, v, d) {(d).x = (s) * (v).x; \ (d).y = (s) * (v).y; \ (d).z = (s) * (v).z;} /* scales a vector with the inverse of the real number s if not zero: d = (1/s).v */ #define VECTORSCALEINVERSE(s, v, d) {double _is_ = ((s) < -EPSILON || (s) > EPSILON ? 1./(s) : 1.); \ (d).x = _is_ * (v).x; \ (d).y = _is_ * (v).y; \ (d).z = _is_ * (v).z;} /* normalizes a vector: scale it with the inverse of its norm */ #define VECTORNORMALISE VECTORNORMALIZE #define VECTORNORMALIZE(v) {double _norm_; _norm_ = VECTORNORM(v); \ VECTORSCALEINVERSE(_norm_, v, v);} /* inproduct of two vectors. */ #define VECTORCROSSPRODUCT(a, b, d) {DVECTOR _d; \ (_d).x = (a).y * (b).z - (a).z * (b).y; \ (_d).y = (a).z * (b).x - (a).x * (b).z; \ (_d).z = (a).x * (b).y - (a).y * (b).x; \ VECTORCOPY(_d, (d));} /* normal of the triangle defined by three non-colinear vectors: * n = (v2-v1) x (v3-v2) normalized */ #define NORMAL(v1, v2, v3, n) {DVECTOR _d1_, _d2_; \ VECTORSUBTRACT(v2, v1, _d1_); \ VECTORSUBTRACT(v3, v2, _d2_); \ VECTORCROSSPROD(_d1_, _d2_, n); \ VECTORNORMALIZE(n); } /* linear combination of two vectors: d = a.v + b.w */ #define VECTORCOMB2(a, v, b, w, d) {(d).x = (a) * (v).x + (b) * (w).x; \ (d).y = (a) * (v).y + (b) * (w).y; \ (d).z = (a) * (v).z + (b) * (w).z;} /* affine linear combination of two vectors: d = o + a.v + b.w */ #define VECTORCOMB3(o, a, v, b, w, d) {(d).x = (o).x + (a) * (v).x + (b) * (w).x; \ (d).y = (o).y + (a) * (v).y + (b) * (w).y; \ (d).z = (o).z + (a) * (v).z + (b) * (w).z;} /* linear combination of three vectors */ #define VECTORCOORD(a, X, b, Y, c, Z, d) {(d).x = (a) * (X).x + (b) * (Y).x + (c) * (Z).x; \ (d).y = (a) * (X).y + (b) * (Y).y + (c) * (Z).y; \ (d).z = (a) * (X).z + (b) * (Y).z + (c) * (Z).z;} /* triple (cross) product: d = (v3-v2) x (v1-v2) */ #define VECTORTRIPLECROSSPRODUCT(v1, v2, v3, d) {DVECTOR _D1, _D2; \ VECTORSUBTRACT(v3, v2, _D1); \ VECTORSUBTRACT(v1, v2, _D2); \ VECTORCROSSPRODUCT(_D1, _D2, d) \ } /* triple (dot) product: s = (v3-v2) . (v1-v2) */ #define VECTORTRIPLEDOTPRODUCT(v1, v2, v3, s) {DVECTOR _D1, _D2; \ VECTORSUBTRACT(v3, v2, _D1); \ VECTORSUBTRACT(v1, v2, _D2); \ s = VECTORDOTPRODUCT(_D1, _D2) \ } /* determinant s = (v1 x v2) . v3 = v1 . (v2 x v3) */ #define VECTORDETERMINANT(v1, v2, v3, s) {DVECTOR _D; \ VECTORCROSSPRODUCT(v1, v2, _D); \ s = VECTORDOTPRODUCT(_D, v3); \ } /* distance betwene two points in 3D space: s = |p2-p1| */ #define VECTORDIST(p1, p2, s) { DVECTOR _D; \ VECTORSUBTRACT(p2, p1, _D); \ s = VECTORNORM(_D); \ } /* orthogonal component of X with respect to Y. Result is stored in d */ #define VECTORORTHOCOMP(X, Y, d) {double _dotp_; \ _dotp_ = VECTORDOTPRODUCT(X, Y); \ VECTORSUMSCALED(X, -_dotp_, Y, d); \ } #define XNORMAL 0 #define YNORMAL 1 #define ZNORMAL 2 #define VECTORINDEXNAME(index) ((index) == XNORMAL ? "XNORMAL" : \ ((index) == YNORMAL ? "YNORMAL" : "ZNORMAL")) /* given a vector p in 3D space and an index i, which is * XNORMAL, YNORMAL or ZNORMAL, projects the vector on the YZ, XZ or XY plane * respectively. */ #define VECTORPROJECT(r, p, i) {switch(i) { \ case XNORMAL: \ r.u = (p).y; \ r.v = (p).z; \ break; \ case YNORMAL: \ r.u = (p).x; \ r.v = (p).z; \ break; \ case ZNORMAL: \ r.u = (p).x; \ r.v = (p).y; \ break; \ } } /* centre of two points */ #define MIDPOINT(p1, p2, m) { \ (m).x = 0.5 * ((p1).x + (p2).x); \ (m).y = 0.5 * ((p1).y + (p2).y); \ (m).z = 0.5 * ((p1).z + (p2).z); \ } /* centre of four points */ #define MIDPOINT4(p1, p2, p3, p4, m) { \ (m).x = 0.25 * ((p1).x + (p2).x + (p3).x + (p4).x); \ (m).y = 0.25 * ((p1).y + (p2).y + (p3).y + (p4).y); \ (m).z = 0.25 * ((p1).z + (p2).z + (p3).z + (p4).z); \ } /* sum of four vectors */ #define VECTORSUM4(v1, v2, v3, v4, s) { \ (s).x = (v1).x + (v2).x + (v3).x + (v4).x; \ (s).y = (v1).y + (v2).y + (v3).y + (v4).y; \ (s).z = (v1).z + (v2).z + (v3).z + (v4).z; \ } /* Point IN Triangle: barycentric parametrisation */ #define PINT(v0, v1, v2, u, v, p) { \ double _u = (u), _v = (v); \ (p).x = (v0).x + _u * ((v1).x - (v0).x) + _v * ((v2).x - (v0).x); \ (p).y = (v0).y + _u * ((v1).y - (v0).y) + _v * ((v2).y - (v0).y); \ (p).z = (v0).z + _u * ((v1).z - (v0).z) + _v * ((v2).z - (v0).z); \ } /* Point IN Quadrilateral: bilinear parametrisation */ #define PINQ(v0, v1 ,v2 ,v3, u, v, p) { \ double _c=(u)*(v), _b=(u)-_c, _d=(v)-_c; \ (p).x = (v0).x + (_b) * ((v1).x - (v0).x) + (_c) * ((v2).x - (v0).x)+ (_d) * ((v3).x - (v0).x); \ (p).y = (v0).y + (_b) * ((v1).y - (v0).y) + (_c) * ((v2).y - (v0).y)+ (_d) * ((v3).y - (v0).y); \ (p).z = (v0).z + (_b) * ((v1).z - (v0).z) + (_c) * ((v2).z - (v0).z)+ (_d) * ((v3).z - (v0).z); \ }; /* computes d = (1-s).p + s.q = p + s.(q-p) */ #define VECTORINTERPOLATE(p,q,s,d) {double _s = (s); \ (d).x = (p).x + _s * ((q).x - (p).x); \ (d).y = (p).y + _s * ((q).y - (p).y); \ (d).z = (p).z + _s * ((q).z - (p).z); \ } /* maximum of two vectors: d.x = max(v1.x,v2.x) etc ...*/ #define VECTORMAX(v1,v2,d) { \ (d).x = MAX((v1).x, (v2).x); \ (d).y = MAX((v1).y, (v2).y); \ (d).z = MAX((v1).z, (v2).z); \ } /* minimum of two vectors: d.x = min(v1.x,v2.x) etc ...*/ #define VECTORMIN(v1,v2,d) { \ (d).x = MIN((v1).x, (v2).x); \ (d).y = MIN((v1).y, (v2).y); \ (d).z = MIN((v1).z, (v2).z); \ } /* transforms a vector to the first quadrant by replacing its components * by their absolute value */ #define VECTORABS(v,d) { \ (d).x = fabs((v).x); \ (d).y = fabs((v).y); \ (d).z = fabs((v).z); \ } #include #define VectorPrint(fp, v) fprintf(fp, "%g %g %g", (v).x, (v).y, (v).z) #ifdef __cplusplus } #endif #endif /* _VECTOR_H_ */