c3dlas.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #ifndef __c3dlas_h__
  2. #define __c3dlas_h__
  3. #include <stdlib.h> // rand() et al.
  4. #include <math.h> // fmin/fmax
  5. #define F_PI ((float)3.1415926535897932384626433832795028841971693993751)
  6. #define D_PI ((double)3.1415926535897932384626433832795028841971693993751)
  7. #define F_2PI ((float)6.2831853071795864769252867665590057683943387987502)
  8. #define D_2PI ((double)6.2831853071795864769252867665590057683943387987502)
  9. #define F_1_PI ((float)0.3183098861837906715377675267450287240689192914809)
  10. #define D_1_PI ((double)0.3183098861837906715377675267450287240689192914809)
  11. #define F_PI_2 ((float)1.5707963267948966192313216916397514420985846996875)
  12. #define D_PI_2 ((double)1.5707963267948966192313216916397514420985846996875)
  13. #define F_3PI_2 ((float)4.7123889803846898576939650749192543262957540990626)
  14. #define D_3PI_2 ((double)4.7123889803846898576939650749192543262957540990626)
  15. #define F_GOLDEN ((float)1.61803398874989484820458683436563811772030917980576f)
  16. #define D_GOLDEN ((double)1.61803398874989484820458683436563811772030917980576)
  17. #define RAD2DEG (57.29577951308232087679815481410517033240547246656432154916024386)
  18. #define DEG2RAD (0.0174532925199432957692369076848861271344287188854172545609719144)
  19. #define FLT_CMP_EPSILON 0.000001
  20. #define C3DLAS_COPLANAR (0)
  21. #define C3DLAS_FRONT (1)
  22. #define C3DLAS_BACK (2)
  23. #define MAX(a,b) ({ \
  24. __typeof__ (a) _a = (a); \
  25. __typeof__ (b) _b = (b); \
  26. _a > _b ? _a : _b; \
  27. })
  28. #define MIN(a,b) ({ \
  29. __typeof__ (a) _a = (a); \
  30. __typeof__ (b) _b = (b); \
  31. _a < _b ? _a : _b; \
  32. })
  33. #define MAXE(a,b) ({ \
  34. __typeof__ (a) _a = (a); \
  35. __typeof__ (b) _b = (b); \
  36. _a >= _b ? _a : _b; \
  37. })
  38. #define MINE(a,b) ({ \
  39. __typeof__ (a) _a = (a); \
  40. __typeof__ (b) _b = (b); \
  41. _a <= _b ? _a : _b; \
  42. })
  43. typedef struct {
  44. float x,y;
  45. } Vector2;
  46. typedef struct {
  47. float x,y,z;
  48. } Vector;
  49. typedef struct {
  50. float x,y,z,w;
  51. } Vector4;
  52. typedef struct Vector2i {
  53. int x,y;
  54. } Vector2i;
  55. typedef struct {
  56. Vector o; // origin
  57. Vector d; // normalized direction
  58. Vector id; // inverse normalized direction (handy enough to keep around)
  59. } Ray;
  60. typedef struct {
  61. Vector start, end;
  62. } LineSegment;
  63. typedef struct BezierSplineSegment {
  64. Vector e, c; // end and control
  65. struct BezierSplineSegment* next;
  66. } BezierSplineSegment;
  67. typedef struct {
  68. int length;
  69. unsigned char isLoop;
  70. BezierSplineSegment* segments;
  71. } BezierSpline;
  72. typedef struct BezierSplineSegment2 {
  73. Vector2 e, c; // end and control
  74. struct BezierSplineSegment2* next;
  75. } BezierSplineSegment2;
  76. typedef struct {
  77. int length;
  78. unsigned char isLoop;
  79. BezierSplineSegment2* segments;
  80. } BezierSpline2;
  81. typedef struct {
  82. Vector n; // normal
  83. float d; // distance along normal to the origin
  84. } Plane;
  85. typedef struct { // does not have to be coplanar
  86. Vector v[4];
  87. } Quad;
  88. typedef struct {
  89. Vector2 v[4];
  90. } Quad2;
  91. typedef struct {
  92. Vector2i v[4];
  93. } Quad2i;
  94. typedef struct {
  95. float m[16];
  96. } Matrix;
  97. typedef struct MatrixStack {
  98. short size;
  99. short top;
  100. Matrix* stack;
  101. } MatrixStack;
  102. // axis-aligned bounding box
  103. typedef struct AABB {
  104. Vector min;
  105. Vector max;
  106. } AABB;
  107. typedef struct AABB2 {
  108. Vector2 min;
  109. Vector2 max;
  110. } AABB2;
  111. typedef struct AABB2i {
  112. Vector2i min;
  113. Vector2i max;
  114. } AABB2i;
  115. extern const Matrix IDENT_MATRIX;
  116. // utilities
  117. static inline float frand(float low, float high) {
  118. return low + ((high - low) * ((float)rand() / (float)RAND_MAX));
  119. }
  120. static inline float frandNorm() {
  121. return ((float)rand() / (float)RAND_MAX);
  122. }
  123. static inline double drand(double low, double high) {
  124. return low + ((high - low) * ((double)rand() / (double)RAND_MAX));
  125. }
  126. static inline double drandNorm() {
  127. return ((double)rand() / (double)RAND_MAX);
  128. }
  129. static inline float fclamp(float val, float min, float max) {
  130. return fmin(max, fmax(min, val));
  131. }
  132. static inline float fclampNorm(float val) {
  133. return fclamp(val, 0.0f, 1.0f);
  134. }
  135. static inline int iclamp(int val, int min, int max) {
  136. return MIN(max, MAX(min, val));
  137. }
  138. static inline float flerp(float a, float b, float t) {
  139. return a + ((b - a) * t);
  140. }
  141. // vectors
  142. int vEq(Vector* a, Vector* b); // safe equivalence, to FLT_CMP_EPSILON
  143. int vEqEp(Vector* a, Vector* b, float epsilon); // safe equivalence, to arbitrary epsilon
  144. void vCopy(const Vector* src, Vector* dst); // copy vector values
  145. void vSwap(Vector* a, Vector* b); // swap two vectors
  146. void vAdd(Vector* a, Vector* b, Vector* out); // add two vectors
  147. void vSub(Vector* from, Vector* what, Vector* diff); // diff = from - what
  148. void vScale(Vector* v, float scalar, Vector* out); // scalar muliplication
  149. void vLerp(Vector* a, Vector* b, float t, Vector* out); // Linear interpolation between two vectors
  150. void vInverse(Vector* v, Vector* out); // inverse
  151. float vMag(Vector* v); // return the magnitude
  152. float vDot(Vector* a, Vector* b); // dot product
  153. float vDist(Vector* from, Vector* to); // distance from one point to another
  154. void vNorm(Vector* v, Vector* out); // normalize the vector
  155. void vUnit(Vector* v, Vector* out); // normalise the vector, alternate name
  156. void vCross(Vector* a, Vector* b, Vector* out); // cross product: out = a x b
  157. float vScalarTriple(Vector* a, Vector* b, Vector* c); // scalar triple product: a . (b x c)
  158. void vProject(Vector* what, Vector* onto, Vector* out); // slower; onto may not be normalized
  159. void vProjectNorm(Vector* what, Vector* onto, Vector* out); // faster; onto must be normalized
  160. void vMin(Vector* a, Vector* b, Vector* out); // returns the minimum values of each component
  161. void vMax(Vector* a, Vector* b, Vector* out); // returns the maximum values of each component
  162. void vSet(float x, float y, float z, Vector* out);
  163. void vRandom(Vector* end1, Vector* end2, Vector* out);
  164. void vRandomNorm(Vector* out);
  165. void vLerp4(Vector4* a, Vector4* b, float t, Vector4* out); // Linear interpolation between two vectors
  166. // reflects the distance from v to pivot across pivot.
  167. // out, pivot, and v will form a straight line with pivot exactly in the middle.
  168. void vReflectAcross(Vector* v, Vector* pivot, Vector* out);
  169. void vTriFaceNormal(Vector* a, Vector* b, Vector* c, Vector* out); // returns a normalized face normal for the given triangle
  170. void vProjectOntoPlane(Vector* v, Plane* p, Vector* out);
  171. void vProjectOntoPlaneNormalized(Vector* v, Plane* p, Vector* out);
  172. void planeFromTriangle(Vector* v1, Vector* v2, Vector* v3, Plane* out); // calculates a plane form a triangle
  173. void planeCopy(Plane* in, Plane* out); // copy a plane
  174. void planeInverse(Plane* in, Plane* out); // flips the plane's direction
  175. int planeClassifyPoint(Plane* p, Vector* pt); // classifies a point by which side of the plane it's on, default espilon
  176. int planeClassifyPointEps(Plane* p, Vector* pt, float epsilon); // classifies a point by which side of the plane it's on, custom espilon
  177. // 2d vector stuff, same as 3d except one less d
  178. int vEq2(Vector2* a, Vector2* b); // safe equivalence, to FLT_CMP_EPSILON
  179. int vEqEp2(Vector2* a, Vector2* b, float epsilon); // safe equivalence, to arbitrary epsilon
  180. void vCopy2(const Vector2* src, Vector2* dst); // copy vector values
  181. void vSwap2(Vector2* a, Vector2* b); // swap two vectors
  182. void vAdd2(Vector2* a, Vector2* b, Vector2* out); // add two vectors
  183. void vSub2(Vector2* from, Vector2* what, Vector2* diff); // diff = from - what
  184. void vScale2(Vector2* v, float scalar, Vector2* out); // scalar muliplication
  185. float vDist2(Vector2* a, Vector2* b); // distance between points
  186. void vLerp2(Vector2* a, Vector2* b, float t, Vector2* out); // linear interpolation
  187. void vInverse2(Vector2* v, Vector2* out); // inverse
  188. float vMag2(Vector2* v); // return the magnitude
  189. float vDot2(Vector2* a, Vector2* b); // dot product
  190. void vNorm2(Vector2* v, Vector2* out); // normalize the vector
  191. void vUnit2(Vector2* v, Vector2* out); // normalise the vector, alternate name
  192. void vMin2(Vector2* a, Vector2* b, Vector2* out); // returns the minimum values of each component
  193. void vMax2(Vector2* a, Vector2* b, Vector2* out); // returns the maximum values of each component
  194. void vSet2(float x, float y, Vector2* out);
  195. // reflects the distance from v to pivot across pivot.
  196. // out, pivot, and v will form a straight line with pivot exactly in the middle.
  197. void vReflectAcross2(Vector2* v, Vector2* pivot, Vector2* out);
  198. // degenerate cases may not give desired results. GIGO.
  199. void vRoundAway2(const Vector2* in, const Vector2* center, Vector2i* out);
  200. void vRoundToward2(const Vector2* in, const Vector2* center, Vector2i* out);
  201. // returns the *signed* area of a triangle. useful for determining winding
  202. // positive values mean a clockwise triangle
  203. float triArea2(Vector2* a, Vector2* b, Vector2* c);
  204. // determines if a point is inside a triangle
  205. int triPointInside2(Vector2* p, Vector2* a, Vector2* b, Vector2* c);
  206. // 2d integer vector stuff
  207. int vEq2i(Vector2i* a, Vector2i* b);
  208. void vCopy2i(const Vector2i* src, Vector2i* dst); // copy vector values
  209. void vSwap2i(Vector2i* a, Vector2i* b); // swap two vectors
  210. void vAdd2i(Vector2i* a, Vector2i* b, Vector2i* out); // add two vectors
  211. void vSub2i(Vector2i* from, Vector2i* what, Vector2i* diff); // diff = from - what
  212. void vScale2i(Vector2i* v, int scalar, Vector2i* out); // scalar muliplication
  213. int vDot2i(Vector2i* a, Vector2i* b); // dot product
  214. void vMin2i(Vector2i* a, Vector2i* b, Vector2i* out); // returns the minimum values of each component
  215. void vMax2i(Vector2i* a, Vector2i* b, Vector2i* out); // returns the maximum values of each component
  216. void vSet2i(int x, int y, Vector2i* out);
  217. float vDist2i(Vector2i* a, Vector2i* b); // returns the absolute distance between two vectors
  218. float pvDist(Plane* p, Vector* v);
  219. void vMatrixMul(Vector* in, Matrix* m, Vector* out); // multiply a vector by a matrix
  220. void vMatrixMulf(float x, float y, float z, Matrix* m, Vector* out); // multiply a vector by a matrix
  221. void mIdent(Matrix* m); // set m to the identity matrix
  222. void mCopy(Matrix* in, Matrix* out);
  223. void mFastMul(Matrix* a, Matrix* b, Matrix* out); // a and b cannot also be out. mostly internal use.
  224. void mMul(Matrix* a, Matrix* out); // makes a copy of out before multiplying over it
  225. void mTransv(Vector* v, Matrix* out); // translation
  226. void mTrans3f(float x, float y, float z, Matrix* out); // translation
  227. void mScalev(Vector* v, Matrix* out);
  228. void mScale3f(float x, float y, float z, Matrix* out);
  229. void mRotv(Vector* v, float theta, Matrix* out); // rotate about a vector
  230. void mRot3f(float x, float y, float z, float theta, Matrix* out); // rotate about a vector
  231. void mRotX(float theta, Matrix* out); //
  232. void mRotY(float theta, Matrix* out); // rotate about axes
  233. void mRotZ(float theta, Matrix* out); //
  234. void mTranspose(Matrix* in, Matrix* out);
  235. void mTransposeFast(Matrix* in, Matrix* out); // in cannot be out
  236. float mDeterminate(Matrix* m);
  237. int mInverse(Matrix* in, Matrix* out); // returns 0 on success, 1 if there is no inverse; out remains unchanged
  238. // analogous to glFrustum
  239. // no div/0 checking here for right == left etc. just don't be an idiot.
  240. void mFrustum(float left, float right, float top, float bottom, float near, float far, Matrix* out);
  241. // analogous to gluPerspective
  242. // same div/0 warnings apply. if you get an FP exception you deserve it.
  243. // use a double for fov; the precision matters often.
  244. // https://www.opengl.org/archives/resources/faq/technical/transformations.htm
  245. // https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
  246. void mPerspective(double fov, float aspect, float near, float far, Matrix* out);
  247. // orthographic projection. use this for a "2D" look.
  248. // same div/0 warnings.
  249. void mOrtho(float left, float right, float top, float bottom, float near, float far, Matrix* out);
  250. // analgous to gluLookAt
  251. // https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml
  252. void mLookAt(Vector* eye, Vector* center, Vector* up, Matrix* out);
  253. void mPrint(Matrix* m, FILE* f);
  254. // matrix stack functions
  255. // make sure you allocate enough. when it's out, it's out. no surprise mallocs later on. (yet)
  256. void msAlloc(int size, MatrixStack* ms);
  257. void msFree(MatrixStack* ms);
  258. int msPush(MatrixStack* ms);
  259. void msPop(MatrixStack* ms);
  260. Matrix* msGetTop(MatrixStack* ms);
  261. void msPrintAll(MatrixStack* ms, FILE* f);
  262. // these are all wrappers around the functions listed above
  263. void msIdent(MatrixStack* ms); // set to the identity matrix
  264. void msCopy(Matrix* in, MatrixStack* ms);
  265. void msMul(Matrix* a, MatrixStack* ms); // makes a copy of out before multiplying over it
  266. void msTransv(Vector* v, MatrixStack* ms); // translation
  267. void msTrans3f(float x, float y, float z, MatrixStack* ms); // translation
  268. void msScalev(Vector* v, MatrixStack* ms);
  269. void msScale3f(float x, float y, float z, MatrixStack* ms);
  270. void msRotv(Vector* v, float theta, MatrixStack* ms); // rotate about a vector
  271. void msRot3f(float x, float y, float z, float theta, MatrixStack* ms); // rotate about a vector
  272. void msFrustum(float left, float right, float top, float bottom, float near, float far, MatrixStack* ms);
  273. void msPerspective(double fov, float aspect, float near, float far, MatrixStack* ms);
  274. void msOrtho(float left, float right, float top, float bottom, float near, float far, MatrixStack* ms);
  275. void msLookAt(Vector* eye, Vector* center, Vector* up, MatrixStack* ms);
  276. // cubic Bezier curves
  277. void evalBezier(Vector* e1, Vector* e2, Vector* c1, Vector* c2, float t, Vector* out);
  278. void evalBezierTangent(Vector* e1, Vector* e2, Vector* c1, Vector* c2, float t, Vector* out); // tangent vector; not normalized
  279. void evalBezierNorm(Vector* e1, Vector* e2, Vector* c1, Vector* c2, float t, Vector* out); // normal vector; not normalized
  280. float evalBezier1D(float e1, float e2, float c1, float c2, float t);
  281. float evalBezier1D_dt(float e1, float e2, float c1, float c2, float t); // first derivative with respect to t
  282. float evalBezier1D_ddt(float e1, float e2, float c1, float c2, float t); // second derivative with respect to t
  283. // quadratic Bezier curves
  284. float evalQBezier1D(float e1, float e2, float c1, float t);
  285. void evalQBezier2D(Vector2* e1, Vector2* e2, Vector2* c1, float t, Vector2* out);
  286. void evalQBezier(Vector* e1, Vector* e2, Vector* c1, float t, Vector* out);
  287. ///// bounding box functions
  288. // 3D versions
  289. int boxDisjoint(const AABB* a, const AABB* b);
  290. int boxOverlaps(const AABB* a, const AABB* b);
  291. int boxContainsPoint(const AABB* b, const Vector* p);
  292. void boxCenter(const AABB* b, Vector* out); // calculates the center of the box
  293. void boxSize(const AABB* b, Vector* out); // calculates the size of the box
  294. void makeRay(Vector* origin, Vector* direction, Ray* out);
  295. int boxRayIntersectFast(const AABB* b, const Ray* r);
  296. int boxRayIntersect(const AABB* b, const Ray* r, Vector* ipoint, float* idist);
  297. // 2D versions
  298. int boxDisjoint2(const AABB2* a, const AABB2* b);
  299. int boxOverlaps2(const AABB2* a, const AABB2* b);
  300. int boxContainsPoint2(const AABB2* b, const Vector2* p);
  301. void boxCenter2(const AABB2* b, Vector2* out); // calcuates the center of the box
  302. void boxSize2(const AABB2* b, Vector2* out); // calculates the size of the box
  303. void boxQuadrant2(const AABB2* in, char ix, char iy, AABB2* out);
  304. // 2D integer versions
  305. int boxDisjoint2i(const AABB2i* a, const AABB2i* b);
  306. int boxOverlaps2i(const AABB2i* a, const AABB2i* b);
  307. int boxContainsPoint2i(const AABB2i* b, const Vector2i* p);
  308. void boxCenter2i(const AABB2i* b, Vector2* out); // calcuates the center of the box
  309. void boxSize2i(const AABB2i* b, Vector2* out); // calculates the size of the box
  310. void boxQuadrant2i(const AABB2i* in, char ix, char iy, AABB2i* out);
  311. // find the center of a quad
  312. void quadCenter2(const Quad2* in, Vector2* out);
  313. void quadRoundOutward2(const Quad2* in, Quad2i* out);
  314. void quadRoundInward2(const Quad2* in, Quad2i* out);
  315. #endif // __c3dlas_h__