VectorMath.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. ////////////////////////////////////////////////////////////////////////////////
  19. //
  20. // VectorMath.h
  21. // Project: RSPiX
  22. //
  23. // This module implements high speed manipulations of standard mathematical
  24. // vectors and matrices.
  25. //
  26. // History:
  27. // ??/??/?? JRD Started.
  28. //
  29. // 02/11/97 JMI Added Load() and Save() for compatability with RChannel,
  30. // RResMgr, and other such file-based thingers.
  31. //
  32. ////////////////////////////////////////////////////////////////////////////////
  33. #ifndef VECTOR_MATH_H
  34. #define VECTOR_MATH_H
  35. #include "System.h"
  36. #ifdef PATHS_IN_INCLUDES
  37. #include "ORANGE/File/file.h"
  38. #include "ORANGE/QuickMath/QuickMath.h"
  39. #else
  40. #include "file.h"
  41. #include "quickmath.h"
  42. #endif
  43. //===================================
  44. // This file contains data and operations
  45. // for high speed manipulations of standard
  46. // mathematical vectors and matrices.
  47. /*===================================
  48. RP3d; // This is a 3d point.
  49. inline void rspMakeHom(RP3d& p) // do if in question
  50. inline void rspCopy(RP3d& a,RP3d& b)
  51. inline void rspMakeUnit(RP3d& p)
  52. inline REAL rspDot(RP3d& a,RP3d& b)
  53. inline void rspCross(RP3d& a,RP3d& b,RP3d& c) // c = a x b
  54. RTransform
  55. { T[16],
  56. RTransform() // init to an identity transform
  57. RTransform(REAL* M) // init to a copy of another transform
  58. void Make1()
  59. void Make0()
  60. void PreMulBy(REAL* M)
  61. void Mul(REAL* A,REAL* B) // 4x4 transforms:
  62. void Transform(RP3d &p)
  63. void TransformInto(RP3d &XF, RP3d& p) XF = this x p
  64. void Trans(REAL x,REAL y,REAL z)
  65. void Scale(REAL a,REAL b, REAL c)
  66. void Rz(short sDeg) // CCW!
  67. void Rx(short sDeg) // CCW!
  68. void Ry(short sDeg) // CCW!
  69. void MakeScreenXF(
  70. REAL x1,REAL y1,REAL w1,REAL h1,
  71. REAL x2,REAL y2,REAL w2,REAL h2)
  72. void MakeRotTo(RP3d point,RP3d up)
  73. void MakeRotFrom(RP3d point,RP3d up)
  74. }
  75. //=================================*/
  76. #define REAL float // float conserves internal memory..
  77. // Note that if REAL is double, than it should somehow hook
  78. // double sized quick trig, so it doesn't have to do
  79. // conversions each time!
  80. // This is an aggregate type used with RTransform
  81. typedef union
  82. {
  83. // 06/30/97 MJR - For the metrowerks compiler, initializations don't
  84. // seem to work right unless the array comes before the struct!
  85. REAL v[4];
  86. struct
  87. {
  88. REAL x;
  89. REAL y;
  90. REAL z;
  91. REAL w;
  92. };
  93. short Load(RFile* pfile)
  94. { return pfile->Read(v, 4) != 4; }
  95. short Save(RFile* pfile)
  96. { return pfile->Write(v, 4) != 4; }
  97. } RP3d; // This is a 3d point.
  98. inline int operator==(const RP3d& lhs, const RP3d& rhs)
  99. {
  100. if (lhs.v == rhs.v)
  101. return 1;
  102. return 0;
  103. }
  104. // divides out the w component: (makes homogeneous)
  105. inline void rspMakeHom(RP3d& p)
  106. {
  107. #ifdef _DEBUG
  108. if (p.w == 0.0)
  109. {
  110. TRACE("FATAL ERROR - POINT AT INFINITY!");
  111. return;
  112. }
  113. #endif
  114. REAL w = p.w;
  115. p.x /= w;
  116. p.y /= w;
  117. p.z /= w;
  118. p.w = 1.00;
  119. }
  120. // Can be useful:
  121. // adjusts the length of a vector, ignoring w component
  122. inline void rspMakeUnit(RP3d& p)
  123. {
  124. REAL l = sqrt(SQR(p.x)+SQR(p.y)+SQR(p.z));
  125. #ifdef _DEBUG
  126. if (l == 0.0)
  127. {
  128. TRACE("FATAL ERROR - NULL VECTOR!");
  129. return;
  130. }
  131. #endif
  132. p.x /= l;
  133. p.y /= l;
  134. p.z /= l;
  135. }
  136. // returns a dot b
  137. inline REAL rspDot(RP3d& a,RP3d& b)
  138. {
  139. return a.x*b.x + a.y*b.y + a.z*b.z;
  140. }
  141. // a = b, does NOT deal with w!
  142. inline void rspCopy(RP3d& a,RP3d& b)
  143. {
  144. a.x = b.x;
  145. a.y = b.y;
  146. a.z = b.z;
  147. }
  148. // c = a x b
  149. inline void rspCross(RP3d& a,RP3d& b,RP3d& c)
  150. {
  151. c.x = a.y * b.z - a.z * b.y;
  152. c.z = a.x * b.y - a.y * b.x;
  153. c.y = a.z * b.x - a.x * b.z;
  154. }
  155. // a -= b;
  156. inline void rspSub(RP3d& a,RP3d& b)
  157. {
  158. a.x -= b.x;
  159. a.y -= b.y;
  160. a.z -= b.z;
  161. }
  162. // a += b;
  163. inline void rspAdd(RP3d& a,RP3d& b)
  164. {
  165. a.x += b.x;
  166. a.y += b.y;
  167. a.z += b.z;
  168. }
  169. // a += s;
  170. inline void rspScale(RP3d& a,REAL s)
  171. {
  172. a.x *= s;
  173. a.y *= s;
  174. a.z *= s;
  175. }
  176. // And some useful constants for manipulation:
  177. const short ROW[4] = {0,4,8,12};
  178. const short ROW0 = 0;
  179. const short ROW1 = 4;
  180. const short ROW2 = 8;
  181. const short ROW3 = 12;
  182. const REAL Identity[16] = {1.0,0.0,0.0,0.0,
  183. 0.0,1.0,0.0,0.0,
  184. 0.0,0.0,1.0,0.0,
  185. 0.0,0.0,0.0,1.0};
  186. // NOW, the class based transform allows matrix
  187. // multiplication to occur WITHOUT multiplying
  188. // 2 matrices together. This prevents a malloc
  189. // nightmare:
  190. //
  191. class RTransform
  192. {
  193. public:
  194. REAL T[16]; // This is compatible with the aggregate transform
  195. RTransform() // init to an identity transform
  196. {
  197. for (short i=0;i<16;i++)
  198. T[i]=Identity[i];
  199. }
  200. RTransform(REAL* M) // init to a copy of another transform
  201. {
  202. for (short i=0;i<16;i++)
  203. T[i]=M[i];
  204. }
  205. ~RTransform(){};
  206. int operator==(const RTransform& rhs) const
  207. {
  208. if (T == rhs.T)
  209. return 1;
  210. return 0;
  211. }
  212. void Make1() // identity matrix
  213. {
  214. for (short i=0;i<16;i++)
  215. T[i]=Identity[i];
  216. }
  217. void Make0() // null matrix
  218. {
  219. for (short i=0;i<15;i++)
  220. T[i]=(REAL)0;
  221. T[15] = (REAL)1;
  222. }
  223. //------------------------
  224. // ALL TRANSFORMATIONS ARE PRE-MULTIPLIES,
  225. // A Partial transform, assuming R3 = {0,0,0,1};
  226. //
  227. void PreMulBy(REAL* M)
  228. {
  229. //REAL* MLine = M;
  230. //REAL* TCol = T;
  231. //REAL tot;
  232. short r,c;
  233. // Unroll this puppy!
  234. // Much optimizing needed!
  235. for (r = 0;r<3;r++) // 3/4 XFORM!
  236. for (c=0;c<4;c++)
  237. {
  238. T[ ROW[r] + c] =
  239. M[ ROW[r]] * T[c] +
  240. M[ ROW[r] + 1] * T[ ROW1 + c] +
  241. M[ ROW[r] + 2] * T[ ROW2 + c] +
  242. M[ ROW[r] + 3] * T[ ROW3 + c];
  243. }
  244. }
  245. // Oversets the current Transform with the resultant!
  246. // = A * B
  247. void Mul(REAL* A,REAL* B) // 4x4 transforms:
  248. {
  249. short r,c;
  250. // Unroll this puppy!
  251. // Much optimizing needed!
  252. for (r = 0;r<3;r++) // 3/4 XFORM!
  253. for (c=0;c<4;c++)
  254. {
  255. T[ ROW[r] + c] =
  256. A[ ROW[r]] * B[c] +
  257. A[ ROW[r] + 1] * B[ ROW1 + c] +
  258. A[ ROW[r] + 2] * B[ ROW2 + c] +
  259. A[ ROW[r] + 3] * B[ ROW3 + c];
  260. }
  261. }
  262. // Transform an actual point ( overwrites old point )
  263. // Doex a premultiply!
  264. void Transform(RP3d &p)
  265. {
  266. RP3d temp = {0.0F,0.0F,0.0F,1.0F}; // asume 3 row form!
  267. REAL *pT = T,*pV;
  268. short i,j;
  269. for (j=0;j<3;j++) // asume 3 row form!
  270. for (i=0,pV = p.v;i<4;i++)
  271. {
  272. temp.v[j] += (*pV++) * (*pT++);
  273. }
  274. // overwrite original
  275. for (i=0;i<4;i++) p.v[i] = temp.v[i];
  276. }
  277. // Transform an actual point, and places the answer into a different pt
  278. // Doex a premultiply!
  279. void TransformInto(RP3d& vSrc, RP3d& vDst)
  280. {
  281. vDst.v[0] = vDst.v[1] = vDst.v[2] = REAL(0.);
  282. vDst.v[3] = REAL(1.);
  283. REAL *pT = T,*pV;
  284. short i,j;
  285. for (j=0;j<3;j++) // asume 3 row form!
  286. for (i=0,pV = vSrc.v;i<4;i++)
  287. {
  288. vDst.v[j] += (*pV++) * (*pT++);
  289. }
  290. }
  291. // Assumes R3 = {0,0,0,1}
  292. void Trans(REAL x,REAL y,REAL z)
  293. {
  294. T[ROW0+3] += x;
  295. T[ROW1+3] += y;
  296. T[ROW2+3] += z;
  297. }
  298. void Scale(REAL a,REAL b, REAL c)
  299. {
  300. for (short i=0;i<4;i++)
  301. {
  302. T[ ROW0 + i] *= a;
  303. T[ ROW1 + i] *= b;
  304. T[ ROW2 + i] *= c;
  305. }
  306. }
  307. void Rz(short sDeg) // CCW!
  308. {
  309. REAL S = rspfSin(sDeg);
  310. REAL C = rspfCos(sDeg);
  311. REAL NewVal; // two vertical numbers depend on each other
  312. for (short i=0;i<4;i++)
  313. {
  314. NewVal = T[ ROW0 + i] * C - T[ ROW1 + i] * S;
  315. T[ ROW1 + i] = T[ ROW0 + i] * S + T[ ROW1 + i] * C;
  316. T[ ROW0 + i] = NewVal;
  317. }
  318. }
  319. void Rx(short sDeg) // CCW!
  320. {
  321. REAL S = rspfSin(sDeg);
  322. REAL C = rspfCos(sDeg);
  323. REAL NewVal; // two vertical numbers depend on each other
  324. for (short i=0;i<4;i++)
  325. {
  326. NewVal = T[ ROW1 + i] * C - T[ ROW2 + i] * S;
  327. T[ ROW2 + i] = T[ ROW1 + i] * S + T[ ROW2 + i] * C;
  328. T[ ROW1 + i] = NewVal;
  329. }
  330. }
  331. void Ry(short sDeg) // CCW!
  332. {
  333. REAL S = rspfSin(sDeg);
  334. REAL C = rspfCos(sDeg);
  335. REAL NewVal; // two vertical numbers depend on each other
  336. for (short i=0;i<4;i++)
  337. {
  338. NewVal = T[ ROW0 + i] * C + T[ ROW2 + i] * S;
  339. T[ ROW2 + i] =-T[ ROW0 + i] * S + T[ ROW2 + i] * C;
  340. T[ ROW0 + i] = NewVal;
  341. }
  342. }
  343. // a 3d ORTHOGONAL mapping from REAL box1 to box2
  344. // useful in screen and orthogonal view xforms
  345. // Use rspSub to create w vertices (w,h,d)
  346. // x1 BECOMES x2. Note that w1 must NOT have any 0's.
  347. //
  348. void MakeBoxXF(RP3d &x1,RP3d &w1,RP3d &x2,RP3d &w2)
  349. {
  350. // NOT OF MAXIMUM SPEED!
  351. Make1();
  352. Trans(-x1.x,-x1.y,-x1.z);
  353. Scale(w2.x/w1.x,w2.y/w1.y,w2.z/w1.z);
  354. Trans(x2.x,x2.y,x2.z);
  355. }
  356. // This is NOT hyper fast, and the result IS a rotation matrix
  357. // For now, point is it's x-axis and up i s it's y-axis.
  358. void MakeRotTo(RP3d point,RP3d up)
  359. {
  360. RP3d third;
  361. rspMakeUnit(point);
  362. rspMakeUnit(up);
  363. rspCross(third,point,up);
  364. // store as columns
  365. Make0();
  366. T[0 + ROW[0] ] = point.x;
  367. T[0 + ROW[1] ] = point.y;
  368. T[0 + ROW[2] ] = point.z;
  369. T[1 + ROW[0] ] = up.x;
  370. T[1 + ROW[1] ] = up.y;
  371. T[1 + ROW[2] ] = up.z;
  372. T[2 + ROW[0] ] = third.x;
  373. T[2 + ROW[1] ] = third.y;
  374. T[2 + ROW[2] ] = third.z;
  375. }
  376. // This is NOT hyper fast, and the result IS a rotation matrix
  377. // For now, point is it's x-axis and up i s it's y-axis.
  378. void MakeRotFrom(RP3d point,RP3d up)
  379. {
  380. RP3d third;
  381. rspMakeUnit(point);
  382. rspMakeUnit(up);
  383. rspCross(third,point,up);
  384. // store as rows
  385. Make0();
  386. T[0 + ROW[0] ] = point.x;
  387. T[1 + ROW[0] ] = point.y;
  388. T[2 + ROW[0] ] = point.z;
  389. T[0 + ROW[1] ] = up.x;
  390. T[1 + ROW[1] ] = up.y;
  391. T[2 + ROW[1] ] = up.z;
  392. T[0 + ROW[2] ] = third.x;
  393. T[1 + ROW[2] ] = third.y;
  394. T[2 + ROW[2] ] = third.z;
  395. }
  396. // Loads instance data for this Transform from the specified
  397. // file.
  398. short Load( // Returns 0 on success.
  399. RFile* pfile) // In: Ptr to file to load from. Must be open with
  400. // read access.
  401. {
  402. // Read the entire matrix in one kerchunk. Bang! I mean Kerchunk!
  403. pfile->Read(T, sizeof(T) / sizeof(T[0]) );
  404. // Success can be measured in terms of I/O errors.
  405. // Also, we should not have read past the end yet.
  406. return pfile->Error() | pfile->IsEOF();
  407. }
  408. // Saves instance data for this Transform to the specified
  409. // file.
  410. short Save( // Returns 0 on success.
  411. RFile* pfile) // In: Ptr to file to save to. Must be open with
  412. // write access.
  413. {
  414. // Write the entire matrix in one kerchunk. Bang! I mean Kerchunk!
  415. pfile->Write(T, sizeof(T) / sizeof(T[0]) );
  416. // Success can be measured in terms of I/O errors.
  417. return pfile->Error();
  418. }
  419. };
  420. //===================================
  421. #endif