327 lines
7.6 KiB
C
327 lines
7.6 KiB
C
/***
|
|
* libccd
|
|
* ---------------------------------
|
|
* Copyright (c)2010,2011 Daniel Fiser <danfis@danfis.cz>
|
|
*
|
|
*
|
|
* This file is part of libccd.
|
|
*
|
|
* Distributed under the OSI-approved BSD License (the "License");
|
|
* see accompanying file BDS-LICENSE for details or see
|
|
* <http://www.opensource.org/licenses/bsd-license.php>.
|
|
*
|
|
* This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the License for more information.
|
|
*/
|
|
|
|
#ifndef __CCD_VEC3_H__
|
|
#define __CCD_VEC3_H__
|
|
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include <stdlib.h>
|
|
#include <ccd/compiler.h>
|
|
#include <ccd/ccd_config.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
#ifndef CCD_SINGLE
|
|
# ifndef CCD_DOUBLE
|
|
# error You must define CCD_SINGLE or CCD_DOUBLE
|
|
# endif /* CCD_DOUBLE */
|
|
#endif /* CCD_SINGLE */
|
|
|
|
|
|
#ifdef CCD_SINGLE
|
|
# ifdef CCD_DOUBLE
|
|
# error You can define either CCD_SINGLE or CCD_DOUBLE, not both!
|
|
# endif /* CCD_DOUBLE */
|
|
|
|
typedef float ccd_real_t;
|
|
|
|
/*# define CCD_EPS 1E-6*/
|
|
# define CCD_EPS FLT_EPSILON
|
|
|
|
# define CCD_REAL_MAX FLT_MAX
|
|
|
|
# define CCD_REAL(x) (x ## f) /*!< form a constant */
|
|
# define CCD_SQRT(x) (sqrtf(x)) /*!< square root */
|
|
# define CCD_FABS(x) (fabsf(x)) /*!< absolute value */
|
|
# define CCD_FMAX(x, y) (fmaxf((x), (y))) /*!< maximum of two floats */
|
|
# define CCD_FMIN(x, y) (fminf((x), (y))) /*!< minimum of two floats */
|
|
#endif /* CCD_SINGLE */
|
|
|
|
#ifdef CCD_DOUBLE
|
|
typedef double ccd_real_t;
|
|
|
|
/*# define CCD_EPS 1E-10*/
|
|
# define CCD_EPS DBL_EPSILON
|
|
|
|
# define CCD_REAL_MAX DBL_MAX
|
|
|
|
# define CCD_REAL(x) (x) /*!< form a constant */
|
|
# define CCD_SQRT(x) (sqrt(x)) /*!< square root */
|
|
# define CCD_FABS(x) (fabs(x)) /*!< absolute value */
|
|
# define CCD_FMAX(x, y) (fmax((x), (y))) /*!< maximum of two floats */
|
|
# define CCD_FMIN(x, y) (fmin((x), (y))) /*!< minimum of two floats */
|
|
#endif /* CCD_DOUBLE */
|
|
|
|
#define CCD_ONE CCD_REAL(1.)
|
|
#define CCD_ZERO CCD_REAL(0.)
|
|
|
|
struct _ccd_vec3_t {
|
|
ccd_real_t v[3];
|
|
};
|
|
typedef struct _ccd_vec3_t ccd_vec3_t;
|
|
|
|
|
|
/**
|
|
* Holds origin (0,0,0) - this variable is meant to be read-only!
|
|
*/
|
|
extern ccd_vec3_t *ccd_vec3_origin;
|
|
|
|
/**
|
|
* Array of points uniformly distributed on unit sphere.
|
|
*/
|
|
extern ccd_vec3_t *ccd_points_on_sphere;
|
|
extern size_t ccd_points_on_sphere_len;
|
|
|
|
/** Returns sign of value. */
|
|
_ccd_inline int ccdSign(ccd_real_t val);
|
|
/** Returns true if val is zero. **/
|
|
_ccd_inline int ccdIsZero(ccd_real_t val);
|
|
/** Returns true if a and b equal. **/
|
|
_ccd_inline int ccdEq(ccd_real_t a, ccd_real_t b);
|
|
|
|
|
|
#define CCD_VEC3_STATIC(x, y, z) \
|
|
{ { (x), (y), (z) } }
|
|
|
|
#define CCD_VEC3(name, x, y, z) \
|
|
ccd_vec3_t name = CCD_VEC3_STATIC((x), (y), (z))
|
|
|
|
_ccd_inline ccd_real_t ccdVec3X(const ccd_vec3_t *v);
|
|
_ccd_inline ccd_real_t ccdVec3Y(const ccd_vec3_t *v);
|
|
_ccd_inline ccd_real_t ccdVec3Z(const ccd_vec3_t *v);
|
|
|
|
/**
|
|
* Returns true if a and b equal.
|
|
*/
|
|
_ccd_inline int ccdVec3Eq(const ccd_vec3_t *a, const ccd_vec3_t *b);
|
|
|
|
/**
|
|
* Returns squared length of vector.
|
|
*/
|
|
_ccd_inline ccd_real_t ccdVec3Len2(const ccd_vec3_t *v);
|
|
|
|
/**
|
|
* Returns distance between a and b.
|
|
*/
|
|
_ccd_inline ccd_real_t ccdVec3Dist2(const ccd_vec3_t *a, const ccd_vec3_t *b);
|
|
|
|
|
|
_ccd_inline void ccdVec3Set(ccd_vec3_t *v, ccd_real_t x, ccd_real_t y, ccd_real_t z);
|
|
|
|
/**
|
|
* v = w
|
|
*/
|
|
_ccd_inline void ccdVec3Copy(ccd_vec3_t *v, const ccd_vec3_t *w);
|
|
|
|
/**
|
|
* Substracts coordinates of vector w from vector v. v = v - w
|
|
*/
|
|
_ccd_inline void ccdVec3Sub(ccd_vec3_t *v, const ccd_vec3_t *w);
|
|
|
|
/**
|
|
* Adds coordinates of vector w to vector v. v = v + w
|
|
*/
|
|
_ccd_inline void ccdVec3Add(ccd_vec3_t *v, const ccd_vec3_t *w);
|
|
|
|
/**
|
|
* d = v - w
|
|
*/
|
|
_ccd_inline void ccdVec3Sub2(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *w);
|
|
|
|
/**
|
|
* d = d * k;
|
|
*/
|
|
_ccd_inline void ccdVec3Scale(ccd_vec3_t *d, ccd_real_t k);
|
|
|
|
/**
|
|
* Normalizes given vector to unit length.
|
|
*/
|
|
_ccd_inline void ccdVec3Normalize(ccd_vec3_t *d);
|
|
|
|
|
|
/**
|
|
* Dot product of two vectors.
|
|
*/
|
|
_ccd_inline ccd_real_t ccdVec3Dot(const ccd_vec3_t *a, const ccd_vec3_t *b);
|
|
|
|
/**
|
|
* Cross product: d = a x b.
|
|
*/
|
|
_ccd_inline void ccdVec3Cross(ccd_vec3_t *d, const ccd_vec3_t *a, const ccd_vec3_t *b);
|
|
|
|
|
|
/**
|
|
* Returns distance2 of point P to segment ab.
|
|
* If witness is non-NULL it is filled with coordinates of point from which
|
|
* was computaed distance to point P.
|
|
*/
|
|
ccd_real_t ccdVec3PointSegmentDist2(const ccd_vec3_t *P,
|
|
const ccd_vec3_t *a, const ccd_vec3_t *b,
|
|
ccd_vec3_t *witness);
|
|
|
|
/**
|
|
* Returns distance2 of point P from triangle formed by triplet a, b, c.
|
|
* If witness vector is provided it is filled with coordinates of point
|
|
* from which was computed distance to point P.
|
|
*/
|
|
ccd_real_t ccdVec3PointTriDist2(const ccd_vec3_t *P,
|
|
const ccd_vec3_t *a, const ccd_vec3_t *b,
|
|
const ccd_vec3_t *c,
|
|
ccd_vec3_t *witness);
|
|
|
|
|
|
/**** INLINES ****/
|
|
_ccd_inline int ccdSign(ccd_real_t val)
|
|
{
|
|
if (ccdIsZero(val)){
|
|
return 0;
|
|
}else if (val < CCD_ZERO){
|
|
return -1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
_ccd_inline int ccdIsZero(ccd_real_t val)
|
|
{
|
|
return CCD_FABS(val) < CCD_EPS;
|
|
}
|
|
|
|
_ccd_inline int ccdEq(ccd_real_t _a, ccd_real_t _b)
|
|
{
|
|
ccd_real_t ab;
|
|
ccd_real_t a, b;
|
|
|
|
ab = CCD_FABS(_a - _b);
|
|
if (CCD_FABS(ab) < CCD_EPS)
|
|
return 1;
|
|
|
|
a = CCD_FABS(_a);
|
|
b = CCD_FABS(_b);
|
|
if (b > a){
|
|
return ab < CCD_EPS * b;
|
|
}else{
|
|
return ab < CCD_EPS * a;
|
|
}
|
|
}
|
|
|
|
|
|
_ccd_inline ccd_real_t ccdVec3X(const ccd_vec3_t *v)
|
|
{
|
|
return v->v[0];
|
|
}
|
|
|
|
_ccd_inline ccd_real_t ccdVec3Y(const ccd_vec3_t *v)
|
|
{
|
|
return v->v[1];
|
|
}
|
|
|
|
_ccd_inline ccd_real_t ccdVec3Z(const ccd_vec3_t *v)
|
|
{
|
|
return v->v[2];
|
|
}
|
|
|
|
_ccd_inline int ccdVec3Eq(const ccd_vec3_t *a, const ccd_vec3_t *b)
|
|
{
|
|
return ccdEq(ccdVec3X(a), ccdVec3X(b))
|
|
&& ccdEq(ccdVec3Y(a), ccdVec3Y(b))
|
|
&& ccdEq(ccdVec3Z(a), ccdVec3Z(b));
|
|
}
|
|
|
|
_ccd_inline ccd_real_t ccdVec3Len2(const ccd_vec3_t *v)
|
|
{
|
|
return ccdVec3Dot(v, v);
|
|
}
|
|
|
|
_ccd_inline ccd_real_t ccdVec3Dist2(const ccd_vec3_t *a, const ccd_vec3_t *b)
|
|
{
|
|
ccd_vec3_t ab;
|
|
ccdVec3Sub2(&ab, a, b);
|
|
return ccdVec3Len2(&ab);
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Set(ccd_vec3_t *v, ccd_real_t x, ccd_real_t y, ccd_real_t z)
|
|
{
|
|
v->v[0] = x;
|
|
v->v[1] = y;
|
|
v->v[2] = z;
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Copy(ccd_vec3_t *v, const ccd_vec3_t *w)
|
|
{
|
|
*v = *w;
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Sub(ccd_vec3_t *v, const ccd_vec3_t *w)
|
|
{
|
|
v->v[0] -= w->v[0];
|
|
v->v[1] -= w->v[1];
|
|
v->v[2] -= w->v[2];
|
|
}
|
|
_ccd_inline void ccdVec3Sub2(ccd_vec3_t *d, const ccd_vec3_t *v, const ccd_vec3_t *w)
|
|
{
|
|
d->v[0] = v->v[0] - w->v[0];
|
|
d->v[1] = v->v[1] - w->v[1];
|
|
d->v[2] = v->v[2] - w->v[2];
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Add(ccd_vec3_t *v, const ccd_vec3_t *w)
|
|
{
|
|
v->v[0] += w->v[0];
|
|
v->v[1] += w->v[1];
|
|
v->v[2] += w->v[2];
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Scale(ccd_vec3_t *d, ccd_real_t k)
|
|
{
|
|
d->v[0] *= k;
|
|
d->v[1] *= k;
|
|
d->v[2] *= k;
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Normalize(ccd_vec3_t *d)
|
|
{
|
|
ccd_real_t k = CCD_ONE / CCD_SQRT(ccdVec3Len2(d));
|
|
ccdVec3Scale(d, k);
|
|
}
|
|
|
|
_ccd_inline ccd_real_t ccdVec3Dot(const ccd_vec3_t *a, const ccd_vec3_t *b)
|
|
{
|
|
ccd_real_t dot;
|
|
|
|
dot = a->v[0] * b->v[0];
|
|
dot += a->v[1] * b->v[1];
|
|
dot += a->v[2] * b->v[2];
|
|
return dot;
|
|
}
|
|
|
|
_ccd_inline void ccdVec3Cross(ccd_vec3_t *d, const ccd_vec3_t *a, const ccd_vec3_t *b)
|
|
{
|
|
d->v[0] = (a->v[1] * b->v[2]) - (a->v[2] * b->v[1]);
|
|
d->v[1] = (a->v[2] * b->v[0]) - (a->v[0] * b->v[2]);
|
|
d->v[2] = (a->v[0] * b->v[1]) - (a->v[1] * b->v[0]);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif /* __cplusplus */
|
|
|
|
#endif /* __CCD_VEC3_H__ */
|