/src/utils.c

https://gitlab.com/flypig/knot3d · C · 334 lines · 227 code · 80 blank · 27 comment · 17 complexity · c255f58ed3008cbf4b6627208124b09e MD5 · raw file

  1. ///////////////////////////////////////////////////////////////////
  2. // Utils
  3. // Generally useful definitions, structures, functions, etc.
  4. //
  5. // David Llewellyn-Jones
  6. // Liverpool John Moores University
  7. //
  8. // Spring 2008
  9. ///////////////////////////////////////////////////////////////////
  10. ///////////////////////////////////////////////////////////////////
  11. // Includes
  12. #include "utils.h"
  13. ///////////////////////////////////////////////////////////////////
  14. // Defines
  15. ///////////////////////////////////////////////////////////////////
  16. // Structures and enumerations
  17. ///////////////////////////////////////////////////////////////////
  18. // Global variables
  19. static Matrix3 mId0 = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
  20. ///////////////////////////////////////////////////////////////////
  21. // Function prototypes
  22. ///////////////////////////////////////////////////////////////////
  23. // Function definitions
  24. float absf (float fValue) {
  25. if (fValue < 0.0f) fValue = -fValue;
  26. return fValue;
  27. }
  28. Vector3 Normal (Vector3 * v1, Vector3 * v2) {
  29. Vector3 vReturn;
  30. vReturn.fX = (v1->fY * v2->fZ) - (v1->fZ * v2->fY);
  31. vReturn.fY = (v1->fZ * v2->fX) - (v1->fX * v2->fZ);
  32. vReturn.fZ = (v1->fX * v2->fY) - (v1->fY * v2->fX);
  33. Normalise (& vReturn);
  34. return vReturn;
  35. }
  36. Vector3 AddVectors (Vector3 const * v1, Vector3 const * v2) {
  37. Vector3 vReturn;
  38. vReturn.fX = (v1->fX + v2->fX);
  39. vReturn.fY = (v1->fY + v2->fY);
  40. vReturn.fZ = (v1->fZ + v2->fZ);
  41. return vReturn;
  42. }
  43. Vector3 SubtractVectors (Vector3 const * v1, Vector3 const * v2) {
  44. Vector3 vReturn;
  45. vReturn.fX = (v1->fX - v2->fX);
  46. vReturn.fY = (v1->fY - v2->fY);
  47. vReturn.fZ = (v1->fZ - v2->fZ);
  48. return vReturn;
  49. }
  50. Vector3 MultiplyVectors (Vector3 const * v1, Vector3 const * v2) {
  51. Vector3 vReturn;
  52. vReturn.fX = (v1->fX * v2->fX);
  53. vReturn.fY = (v1->fY * v2->fY);
  54. vReturn.fZ = (v1->fZ * v2->fZ);
  55. return vReturn;
  56. }
  57. Vector3 ScaleVector (Vector3 const * v1, float fScale) {
  58. Vector3 vReturn;
  59. vReturn.fX = (v1->fX * fScale);
  60. vReturn.fY = (v1->fY * fScale);
  61. vReturn.fZ = (v1->fZ * fScale);
  62. return vReturn;
  63. }
  64. void Normalise (Vector3 * v1) {
  65. float fLength;
  66. fLength = sqrt ((v1->fX * v1->fX) + (v1->fY * v1->fY) + (v1->fZ * v1->fZ));
  67. v1->fX /= fLength;
  68. v1->fY /= fLength;
  69. v1->fZ /= fLength;
  70. }
  71. void Normalise3f (float * pfX, float * pfY, float * pfZ) {
  72. float fLength;
  73. fLength = sqrt (((*pfX) * (*pfX)) + ((*pfY) * (*pfY)) + ((*pfZ) * (*pfZ)));
  74. *pfX /= fLength;
  75. *pfY /= fLength;
  76. *pfZ /= fLength;
  77. }
  78. float Length (Vector3 * v1) {
  79. return sqrt ((v1->fX * v1->fX) + (v1->fY * v1->fY) + (v1->fZ * v1->fZ));
  80. }
  81. Matrix3 Invert (Matrix3 * m1) {
  82. Matrix3 vReturn;
  83. float fDet;
  84. fDet = Determinant (m1);
  85. if (fDet != 0.0f) {
  86. fDet = 1 / fDet;
  87. vReturn.fA1 = fDet * ((m1->fB2 * m1->fC3) - (m1->fC2 * m1->fB3));
  88. vReturn.fA2 = - fDet * ((m1->fA2 * m1->fC3) - (m1->fC2 * m1->fA3));
  89. vReturn.fA3 = fDet * ((m1->fA2 * m1->fB3) - (m1->fB2 * m1->fA3));
  90. vReturn.fB1 = - fDet * ((m1->fB1 * m1->fC3) - (m1->fC1 * m1->fB3));
  91. vReturn.fB2 = fDet * ((m1->fA1 * m1->fC3) - (m1->fC1 * m1->fA3));
  92. vReturn.fB3 = - fDet * ((m1->fA1 * m1->fB3) - (m1->fB1 * m1->fA3));
  93. vReturn.fC1 = fDet * ((m1->fB1 * m1->fC2) - (m1->fC1 * m1->fB2));
  94. vReturn.fC2 = - fDet * ((m1->fA1 * m1->fC2) - (m1->fC1 * m1->fA2));
  95. vReturn.fC3 = fDet * ((m1->fA1 * m1->fB2) - (m1->fB1 * m1->fA2));
  96. }
  97. else {
  98. vReturn = mId0;
  99. }
  100. return vReturn;
  101. }
  102. float Determinant (Matrix3 * m1) {
  103. return (m1->fA1 * ((m1->fB2 * m1->fC3) - (m1->fB3 * m1->fC2)))
  104. - (m1->fA2 * ((m1->fB1 * m1->fC3) - (m1->fB3 * m1->fC1)))
  105. + (m1->fA3 * ((m1->fB1 * m1->fC2) - (m1->fB2 * m1->fC1)));
  106. }
  107. float DotProdAngle (float fX1, float fY1, float fX2, float fY2) {
  108. float fAngle;
  109. float fScaler;
  110. float fY;
  111. float fRot;
  112. fRot = atan2 (fY1, fX1);
  113. fY = - (fX2 * sin (fRot)) + (fY2 * cos (fRot));
  114. fScaler = sqrt ((fX1 * fX1) + (fY1 * fY1)) * sqrt ((fX2 * fX2) + (fY2 * fY2));
  115. fAngle = acos (((fX1 * fX2) + (fY1 * fY2)) / fScaler);
  116. if (fY < 0) fAngle = -fAngle;
  117. return fAngle;
  118. }
  119. float DotProdAngleVector (Vector3 * v1, Vector3 * v2) {
  120. float fAngle;
  121. float fScaler;
  122. float fDotProduct;
  123. float fQuotient;
  124. fScaler = Length (v1) * Length (v2);
  125. fDotProduct = ((v1->fX * v2->fX) + (v1->fY * v2->fY) + (v1->fZ * v2->fZ));
  126. fQuotient = (fDotProduct / fScaler);
  127. fQuotient = CLAMP (fQuotient, -1.0f, 1.0f);
  128. fAngle = acos (fQuotient);
  129. return fAngle;
  130. }
  131. // Useful for calculating the result of simultaneous equations
  132. // and therefore where the normal to a plane passes through a point
  133. // [ a1 b1 c1 ] [ v1 ] [ r1 ] [ (a1*v1) + (b1*v2) + (c1*v3) ]
  134. // [ a2 b2 c2 ] [ v2 ] = [ r3 ] = [ (a2*v1) + (b2*v2) + (c2*v3) ]
  135. // [ a3 b3 c3 ] [ v3 ] [ r3 ] [ (a3*v1) + (b3*v2) + (c3*v3) ]
  136. Vector3 MultMatrixVector (Matrix3 * m1, Vector3 * v1) {
  137. Vector3 vReturn;
  138. vReturn.fX = (m1->fA1 * v1->fX) + (m1->fB1 * v1->fY) + (m1->fC1 * v1->fZ);
  139. vReturn.fY = (m1->fA2 * v1->fX) + (m1->fB2 * v1->fY) + (m1->fC2 * v1->fZ);
  140. vReturn.fZ = (m1->fA3 * v1->fX) + (m1->fB3 * v1->fY) + (m1->fC3 * v1->fZ);
  141. return vReturn;
  142. }
  143. void PrintMatrix (Matrix3 * m1) {
  144. printf ("[ %f, \t%f, \t%f \t]\n", m1->fA1, m1->fB1, m1->fC1);
  145. printf ("[ %f, \t%f, \t%f \t]\n", m1->fA2, m1->fB2, m1->fC2);
  146. printf ("[ %f, \t%f, \t%f \t]\n", m1->fA3, m1->fB3, m1->fC3);
  147. }
  148. void PrintVector (Vector3 * v1) {
  149. printf ("[ %f, \t%f, \t%f \t]\n", v1->fX, v1->fY, v1->fZ);
  150. }
  151. Vector3 CrossProduct (Vector3 * v1, Vector3 * v2) {
  152. Vector3 vResult;
  153. vResult.fX = (v1->fY * v2->fZ) - (v1->fZ * v2->fY);
  154. vResult.fY = (v1->fZ * v2->fX) - (v1->fX * v2->fZ);
  155. vResult.fZ = (v1->fX * v2->fY) - (v1->fY * v2->fX);
  156. return vResult;
  157. }
  158. Matrix3 MultMatrixMatrix (Matrix3 * m1, Matrix3 * m2) {
  159. Matrix3 mResult;
  160. mResult.fA1 = (m1->fA1 * m2->fA1) + (m1->fA2 * m2->fB1) + (m1->fA3 * m2->fC1);
  161. mResult.fA2 = (m1->fA1 * m2->fA2) + (m1->fA2 * m2->fB2) + (m1->fA3 * m2->fC2);
  162. mResult.fA3 = (m1->fA1 * m2->fA3) + (m1->fA2 * m2->fB3) + (m1->fA3 * m2->fC3);
  163. mResult.fB1 = (m1->fB1 * m2->fA1) + (m1->fB2 * m2->fB1) + (m1->fB3 * m2->fC1);
  164. mResult.fB2 = (m1->fB1 * m2->fA2) + (m1->fB2 * m2->fB2) + (m1->fB3 * m2->fC2);
  165. mResult.fB3 = (m1->fB1 * m2->fA3) + (m1->fB2 * m2->fB3) + (m1->fB3 * m2->fC3);
  166. mResult.fC1 = (m1->fC1 * m2->fA1) + (m1->fC2 * m2->fB1) + (m1->fC3 * m2->fC1);
  167. mResult.fC2 = (m1->fC1 * m2->fA2) + (m1->fC2 * m2->fB2) + (m1->fC3 * m2->fC2);
  168. mResult.fC3 = (m1->fC1 * m2->fA3) + (m1->fC2 * m2->fB3) + (m1->fC3 * m2->fC3);
  169. return mResult;
  170. }
  171. void SetIdentity (Matrix3 * m1) {
  172. m1->fA1 = 1.0f;
  173. m1->fA2 = 0.0f;
  174. m1->fA3 = 0.0f;
  175. m1->fB1 = 0.0f;
  176. m1->fB2 = 1.0f;
  177. m1->fB3 = 0.0f;
  178. m1->fC1 = 0.0f;
  179. m1->fC2 = 0.0f;
  180. m1->fC3 = 1.0f;
  181. }
  182. Matrix3 RotationBetweenVectors (Vector3 * v1, Vector3 * v2) {
  183. Matrix3 mReturn;
  184. float fAngle;
  185. Vector3 vAxis;
  186. Vector3 v1normal;
  187. Vector3 v2normal;
  188. v1normal = *v1;
  189. v2normal = *v2;
  190. if ((Length (v1) == 0.0) || (Length (v2) == 0.0)) {
  191. SetIdentity (& mReturn);
  192. }
  193. else {
  194. Normalise (& v1normal);
  195. Normalise (& v2normal);
  196. fAngle = DotProdAngleVector (& v1normal, & v2normal);
  197. if (fAngle < 0.001f) {
  198. SetIdentity (& mReturn);
  199. }
  200. else {
  201. if (fAngle >= M_PI) {
  202. vAxis = PerpendicularVector (& v1normal);
  203. mReturn = RotationAngleAxis (& vAxis, fAngle);
  204. }
  205. else {
  206. vAxis = CrossProduct (& v1normal, & v2normal);
  207. Normalise (& vAxis);
  208. mReturn = RotationAngleAxis (& vAxis, fAngle);
  209. }
  210. }
  211. }
  212. return mReturn;
  213. }
  214. Matrix3 RotationAngleAxis (Vector3 * vAxis, float fAngle) {
  215. Matrix3 mReturn;
  216. mReturn.fA1 = 1.0 + (1.0 - cos (fAngle)) * (vAxis->fX * vAxis->fX - 1.0);
  217. mReturn.fB1 = -vAxis->fZ * sin (fAngle) + (1.0 - cos (fAngle)) * vAxis->fX * vAxis->fY;
  218. mReturn.fC1 = vAxis->fY * sin (fAngle) + (1.0 - cos (fAngle)) * vAxis->fX * vAxis->fZ;
  219. mReturn.fA2 = vAxis->fZ * sin (fAngle) + (1.0 - cos (fAngle)) * vAxis->fX * vAxis->fY;
  220. mReturn.fB2 = 1.0 + (1.0 - cos (fAngle)) * (vAxis->fY * vAxis->fY - 1.0);
  221. mReturn.fC2 = -vAxis->fX * sin (fAngle) + (1.0 - cos (fAngle)) * vAxis->fY * vAxis->fZ;
  222. mReturn.fA3 = -vAxis->fY * sin (fAngle) + (1.0 - cos (fAngle)) * vAxis->fX * vAxis->fZ;
  223. mReturn.fB3 = vAxis->fX * sin (fAngle) + (1.0 - cos (fAngle)) * vAxis->fY * vAxis->fZ;
  224. mReturn.fC3 = 1.0 + (1.0 - cos (fAngle)) * (vAxis->fZ * vAxis->fZ - 1.0);
  225. return mReturn;
  226. }
  227. Vector3 PerpendicularVector (Vector3 * pvVector) {
  228. Vector3 vVector;
  229. Vector3 vOrth;
  230. int nDim;
  231. int nDimMin;
  232. GLfloat fMin;
  233. vVector = * pvVector;
  234. Normalise (& vVector);
  235. // Choose the dimension vector that's smallest
  236. nDimMin = 0;
  237. fMin = ((GLfloat *)& vVector)[nDimMin];
  238. for (nDim = 1; nDim < 3; nDim++) {
  239. if (absf(((GLfloat *)& vVector)[nDim]) < fMin) {
  240. nDimMin = nDim;
  241. fMin = absf(((GLfloat *)& vVector)[nDim]);
  242. }
  243. }
  244. fMin = ((GLfloat *)& vVector)[nDimMin];
  245. vOrth.fX = 0.0f;
  246. vOrth.fY = 0.0f;
  247. vOrth.fZ = 0.0f;
  248. ((GLfloat *)& vOrth)[nDimMin] = 1.0f;
  249. for (nDim = 0; nDim < 3; nDim++) {
  250. ((GLfloat *)& vOrth)[nDim] -= fMin * ((GLfloat *)& vVector)[nDim];
  251. }
  252. Normalise (& vOrth);
  253. return vOrth;
  254. }