3dmath.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /*
  2. 3D matematicke funkce
  3. */
  4. #include "3d_all.h"
  5. GLMATRIX *calc_reflex_matrix(GLMATRIX * p_mat, BOD * p_a, BOD * p_b,
  6. BOD * p_c)
  7. {
  8. float e;
  9. QUAT q;
  10. q.x =
  11. (p_b->y - p_a->y) * (p_c->z - p_a->z) - (p_c->y - p_a->y) * (p_b->z -
  12. p_a->z);
  13. q.y =
  14. (p_b->z - p_a->z) * (p_c->x - p_a->x) - (p_c->z - p_a->z) * (p_b->x -
  15. p_a->x);
  16. q.z =
  17. (p_b->x - p_a->x) * (p_c->y - p_a->y) - (p_c->x - p_a->x) * (p_b->y -
  18. p_a->y);
  19. norm_vect(&q.x, &q.y, &q.z);
  20. q.w = 0.0f;
  21. e = 2 * (q.x * p_a->x + q.y * p_a->y + q.z * p_a->z);
  22. /*
  23. Init na standartni kartezskou souradnou soustavu
  24. */
  25. init_matrix(p_mat);
  26. /*
  27. Natoceni souradnic dle vektoru q
  28. */
  29. quat_to_matrix(p_mat, &q);
  30. /*
  31. Posun souradnic do pozadovane roviny
  32. */
  33. translate_matrix(p_mat, q.x * e, q.y * e, q.z * e);
  34. /*
  35. Reflexivituj souradnice
  36. */
  37. scale_matrix(p_mat, -1.0f, -1.0f, -1.0f);
  38. return (p_mat);
  39. }
  40. /*
  41. prusek s rovninou r (paprsek A->B) se ulozi do bodu p
  42. */
  43. int calc_prusek(ROVINA * r, OBJ_VERTEX * a, OBJ_VERTEX * b, OBJ_VERTEX * p)
  44. {
  45. #define TOL 0.001
  46. float t;
  47. float c, j;
  48. float qx, qy, qz;
  49. // q = B-A
  50. qx = b->x - a->x;
  51. qy = b->y - a->y;
  52. qz = b->z - a->z;
  53. c = -(r->x * a->x + r->y * a->y + r->z * a->z + r->e);
  54. j = r->x * qx + r->y * qy + r->z * qz;
  55. if ((j < TOL) && (j > -TOL)) {
  56. return (0); // printf("Paprsek je rovnobezny z rovinou !");
  57. }
  58. t = c / j;
  59. // P = A - qt
  60. p->x = a->x + qx * t;
  61. p->y = a->y + qy * t;
  62. p->z = a->z + qz * t;
  63. return (1);
  64. }
  65. int calc_prusek_bod(ROVINA * r, BOD * a, BOD * b, BOD * p)
  66. {
  67. #define TOL 0.001
  68. float t;
  69. float c, j;
  70. float qx, qy, qz;
  71. // q = B-A
  72. qx = b->x - a->x;
  73. qy = b->y - a->y;
  74. qz = b->z - a->z;
  75. c = -(r->x * a->x + r->y * a->y + r->z * a->z + r->e);
  76. j = r->x * qx + r->y * qy + r->z * qz;
  77. if ((j < TOL) && (j > -TOL)) {
  78. return (0); // printf("Paprsek je rovnobezny z rovinou !");
  79. }
  80. t = c / j;
  81. // P = A - qt
  82. p->x = a->x + qx * t;
  83. p->y = a->y + qy * t;
  84. p->z = a->z + qz * t;
  85. return (1);
  86. }
  87. /*
  88. Opravit pruseky !!!!!!!!!!!!!!!!!
  89. */
  90. int prusek_face(OBJ_VERTEX * a, OBJ_VERTEX * b, OBJ_VERTEX * p, ROVINA * p_r,
  91. OBJ_VERTEX * _1, OBJ_VERTEX * _2, OBJ_VERTEX * _3)
  92. {
  93. if (calc_prusek(p_r, a, b, p)) {
  94. if (((p_r->x > p_r->z) && (p_r->x > p_r->y)) || (p_r->z == p_r->y))
  95. return (je_uvnitr(_1->y, _1->z, _2->y, _2->z, _3->y, _3->z, p->y,
  96. p->z));
  97. else if (((p_r->y > p_r->z) && (p_r->y > p_r->x)) || (p_r->z == p_r->x))
  98. return (je_uvnitr(_1->x, _1->z, _2->x, _2->z, _3->x, _3->z, p->x,
  99. p->z));
  100. else if (((p_r->z > p_r->x) && (p_r->z > p_r->y)) || (p_r->x == p_r->y))
  101. return (je_uvnitr(_1->x, _1->y, _2->x, _2->y, _3->x, _3->y, p->x,
  102. p->y));
  103. else
  104. return (FALSE);
  105. }
  106. else
  107. return (FALSE);
  108. }
  109. int prusek_face_editor(OBJ_VERTEX * a, OBJ_VERTEX * b, OBJ_VERTEX * p,
  110. OBJ_VERTEX * _1, OBJ_VERTEX * _2, OBJ_VERTEX * _3)
  111. {
  112. ROVINA r;
  113. calc_rovinu(_1, _2, _3, &r);
  114. if (calc_prusek(&r, a, b, p)) {
  115. r.x = (float) fabs(r.x);
  116. r.y = (float) fabs(r.y);
  117. r.z = (float) fabs(r.z);
  118. if (((r.x > r.z) && (r.x > r.y)) || (r.z == r.y))
  119. return (je_uvnitr(_1->y, _1->z, _2->y, _2->z, _3->y, _3->z, p->y,
  120. p->z));
  121. else if (((r.y > r.z) && (r.y > r.x)) || (r.z == r.x))
  122. return (je_uvnitr(_1->x, _1->z, _2->x, _2->z, _3->x, _3->z, p->x,
  123. p->z));
  124. else if (((r.z > r.x) && (r.z > r.y)) || (r.x == r.y))
  125. return (je_uvnitr(_1->x, _1->y, _2->x, _2->y, _3->x, _3->y, p->x,
  126. p->y));
  127. else
  128. return (FALSE);
  129. }
  130. else
  131. return (FALSE);
  132. }
  133. int intersect_triangle_point(OBJ_VERTEX * _1, OBJ_VERTEX * _2,
  134. OBJ_VERTEX * _3, BOD * p)
  135. {
  136. ROVINA r;
  137. calc_rovinu(_1, _2, _3, &r);
  138. r.x = (float) fabs(r.x);
  139. r.y = (float) fabs(r.y);
  140. r.z = (float) fabs(r.z);
  141. if (((r.x > r.z) && (r.x > r.y)) || (r.y == r.z)) // prumet do z/y
  142. return (je_uvnitr(_1->y, _1->z, _2->y, _2->z, _3->y, _3->z, p->y, p->z));
  143. else if (((r.y > r.z) && (r.y > r.x)) || (r.x == r.z)) //prumet do x/z
  144. return (je_uvnitr(_1->x, _1->z, _2->x, _2->z, _3->x, _3->z, p->x, p->z));
  145. else if (((r.z > r.x) && (r.z > r.y)) || (r.y == r.x)) // prumet do x/y
  146. return (je_uvnitr(_1->x, _1->y, _2->x, _2->y, _3->x, _3->y, p->x, p->y));
  147. else {
  148. ddw("Velka chyba vrhani savle !");
  149. return (FALSE);
  150. }
  151. }
  152. #define MAX_HRANOVA_VZDAL 0.0001f
  153. #define frvn(x,y,presnost) (fabs(x-y) < presnost)
  154. int je_uvnitr(float ax, float ay, float bx, float by, float cx, float cy,
  155. float px, float py)
  156. {
  157. float sp;
  158. int v = 0;
  159. int hrana = 0;
  160. #define calc_sp(a0,a1,b0,b1,p0,p1) ((b0 - a0)*(p1 - a1) - (b1 - a1)*(p0 - a0))
  161. // Face je z a->b, b->c, c->a
  162. // Pod musi lezet nalevo (napravo) od vsech techto primek
  163. if (frvn(ax, px, MAX_HRANOVA_VZDAL) && frvn(ay, py, MAX_HRANOVA_VZDAL))
  164. return (1);
  165. if (frvn(bx, px, MAX_HRANOVA_VZDAL) && frvn(by, py, MAX_HRANOVA_VZDAL))
  166. return (1);
  167. if (frvn(cx, px, MAX_HRANOVA_VZDAL) && frvn(cy, py, MAX_HRANOVA_VZDAL))
  168. return (1);
  169. //a->b
  170. sp = calc_sp(ax, ay, bx, by, px, py);
  171. if (MAX_HRANOVA_VZDAL > fabs(sp))
  172. hrana = 1;
  173. else if (sp > 0)
  174. v += 1;
  175. else
  176. v -= 1;
  177. //b->c .. a = b, b = c
  178. sp = calc_sp(bx, by, cx, cy, px, py);
  179. if (MAX_HRANOVA_VZDAL > fabs(sp))
  180. hrana = 1;
  181. else if (sp > 0)
  182. v += 1;
  183. else
  184. v -= 1;
  185. sp = calc_sp(cx, cy, ax, ay, px, py);
  186. if (MAX_HRANOVA_VZDAL > fabs(sp))
  187. hrana = 1;
  188. else if (sp > 0)
  189. v += 1;
  190. else
  191. v -= 1;
  192. if (abs(v) == 3)
  193. return (1);
  194. else {
  195. if (abs(v) == 2 && hrana)
  196. return (1);
  197. else
  198. return (0);
  199. }
  200. }
  201. int intersect_triangle(BOD * p_orig, BOD * p_dir, BOD * p_v0, BOD * p_v1,
  202. BOD * p_v2, FLOAT * p_t, FLOAT * p_u, FLOAT * p_v)
  203. {
  204. BOD edge1, edge2, tvec, pvec, qvec;
  205. float det, inv_det;
  206. // spocitam ramena trojuhelnika
  207. edge1.x = p_v1->x - p_v0->x;
  208. edge1.y = p_v1->y - p_v0->y;
  209. edge1.z = p_v1->z - p_v0->z;
  210. edge2.x = p_v2->x - p_v0->x;
  211. edge2.y = p_v2->y - p_v0->y;
  212. edge2.z = p_v2->z - p_v0->z;
  213. // determinant - uhel mezi plochou dir&edge2 a vektorem edge1
  214. // spocitam rovinu mezi dir&edge2
  215. pvec.x = p_dir->y * edge2.z - p_dir->z * edge2.y;
  216. pvec.y = p_dir->z * edge2.x - p_dir->x * edge2.z;
  217. pvec.z = p_dir->x * edge2.y - p_dir->y * edge2.x;
  218. // uhel mezi normalovym vektorem plochy dir&edge2 a edge1
  219. det = edge1.x * pvec.x + edge1.y * pvec.y + edge1.z * pvec.z;
  220. // lezi paprsek v rovine plosky (je rovnobezny s ploskou ?)
  221. // uhel mezi paprskem a ploskou je det
  222. // culling off
  223. if (det > -EPSILON && det < EPSILON)
  224. return (FALSE);
  225. // t = 0->orig
  226. tvec.x = p_orig->x - p_v0->x;
  227. tvec.y = p_orig->y - p_v0->y;
  228. tvec.z = p_orig->z - p_v0->z;
  229. // uhel mezi t a p
  230. *p_u = tvec.x * pvec.x + tvec.y * pvec.y + tvec.z * pvec.z;
  231. if (*p_u < 0.0f || *p_u > det)
  232. return (FALSE);
  233. // plocha mezi tvec a edge1
  234. qvec.x = tvec.y * edge1.z - tvec.z * edge1.y;
  235. qvec.y = tvec.z * edge1.x - tvec.x * edge1.z;
  236. qvec.z = tvec.x * edge1.y - tvec.y * edge1.x;
  237. // uhel mezi p_dir a qvec
  238. *p_v = (p_dir->x * qvec.x + p_dir->y * qvec.y + p_dir->z * qvec.z);
  239. // test hranic s = u, t = v
  240. if (*p_v < 0.0f || *p_u + *p_v > det)
  241. return (FALSE);
  242. // spocitani t parametru
  243. *p_t = (edge2.x * qvec.x + edge2.y * qvec.y + edge2.z * qvec.z);
  244. inv_det = 1.0f / det;
  245. *p_u *= inv_det;
  246. *p_v *= inv_det;
  247. *p_t *= inv_det;
  248. return (TRUE);
  249. }
  250. int intersect_triangle_ncull(BOD * p_orig, BOD * p_dir, BOD * p_v0,
  251. BOD * p_v1, BOD * p_v2, FLOAT * p_t, FLOAT * p_u, FLOAT * p_v)
  252. {
  253. BOD edge1, edge2, tvec, pvec, qvec;
  254. float det, inv_det;
  255. // spocitam ramena trojuhelnika
  256. edge1.x = p_v1->x - p_v0->x;
  257. edge1.y = p_v1->y - p_v0->y;
  258. edge1.z = p_v1->z - p_v0->z;
  259. edge2.x = p_v2->x - p_v0->x;
  260. edge2.y = p_v2->y - p_v0->y;
  261. edge2.z = p_v2->z - p_v0->z;
  262. // determinant - uhel mezi plochou dir&edge2 a vektorem edge1
  263. // spocitam rovinu mezi dir&edge2
  264. pvec.x = p_dir->y * edge2.z - p_dir->z * edge2.y;
  265. pvec.y = p_dir->z * edge2.x - p_dir->x * edge2.z;
  266. pvec.z = p_dir->x * edge2.y - p_dir->y * edge2.x;
  267. // uhel mezi normalovym vektorem plochy dir&edge2 a edge1
  268. det = edge1.x * pvec.x + edge1.y * pvec.y + edge1.z * pvec.z;
  269. // lezi paprsek v rovine plosky (je rovnobezny s ploskou ?)
  270. // uhel mezi paprskem a ploskou je det
  271. // culling off
  272. if (det > -EPSILON && det < EPSILON)
  273. return (FALSE);
  274. inv_det = 1.0f / det;
  275. // t = 0->orig
  276. tvec.x = p_orig->x - p_v0->x;
  277. tvec.y = p_orig->y - p_v0->y;
  278. tvec.z = p_orig->z - p_v0->z;
  279. // uhel mezi t a p
  280. *p_u = (tvec.x * pvec.x + tvec.y * pvec.y + tvec.z * pvec.z) * inv_det;
  281. if (*p_u < 0.0f || *p_u > 1.0f)
  282. return (FALSE);
  283. // plocha mezi tvec a edge1
  284. qvec.x = tvec.y * edge1.z - tvec.z * edge1.y;
  285. qvec.y = tvec.z * edge1.x - tvec.x * edge1.z;
  286. qvec.z = tvec.x * edge1.y - tvec.y * edge1.x;
  287. // uhel mezi p_dir a qvec
  288. *p_v =
  289. (p_dir->x * qvec.x + p_dir->y * qvec.y + p_dir->z * qvec.z) * inv_det;
  290. // test hranic s = u, t = v
  291. if (*p_v < 0.0f || *p_u + *p_v > 1.0f)
  292. return (FALSE);
  293. // spocitani t parametru
  294. *p_t = (edge2.x * qvec.x + edge2.y * qvec.y + edge2.z * qvec.z) * inv_det;
  295. return (TRUE);
  296. }
  297. /* Spocita kamerovou matici
  298. */
  299. GLMATRIX *calc_camera_3ds(GLMATRIX * p_cam, GLMATRIX * p_invcam, BOD * p_p,
  300. BOD * p_t, float roll)
  301. {
  302. GLMATRIX m;
  303. BOD x, y, z;
  304. vektor_norm(vektor_sub(p_t, p_p, &z));
  305. y.x = y.z = 0.0f;
  306. y.y = 1.0f;
  307. vektor_norm(vektor_soucin(&y, &z, &x));
  308. vektor_norm(vektor_soucin(&z, &x, &y));
  309. p_cam->_14 = p_cam->_24 = p_cam->_34 = 0.0f;
  310. p_cam->_44 = 1.0f;
  311. p_cam->_41 = p_cam->_42 = p_cam->_43 = 0.0f;
  312. p_cam->_11 = x.x;
  313. p_cam->_21 = x.y;
  314. p_cam->_31 = x.z;
  315. p_cam->_12 = y.x;
  316. p_cam->_22 = y.y;
  317. p_cam->_32 = y.z;
  318. p_cam->_13 = z.x;
  319. p_cam->_23 = z.y;
  320. p_cam->_33 = z.z;
  321. translate_matrix(p_cam, -p_p->x, -p_p->y, -p_p->z);
  322. if (roll != 0.0f) {
  323. rotation_matrix_z(&m, roll);
  324. mat_mult(p_cam, &m, p_cam);
  325. }
  326. return (invert_matrix(p_cam, p_invcam));
  327. }
  328. GLMATRIX *calc_camera_polar(GLMATRIX * p_cam, GLMATRIX * p_invcam, BOD * p_p,
  329. QUAT * p_quat, float vzdal)
  330. {
  331. p_invcam->_14 = p_invcam->_24 = p_invcam->_34 = 0.0f;
  332. p_invcam->_44 = 1.0f;
  333. p_invcam->_41 = p_p->x;
  334. p_invcam->_42 = p_p->y;
  335. p_invcam->_43 = p_p->z;
  336. quat_to_matrix(p_invcam, p_quat); // jednotkove vektory do kamery
  337. translate_matrix(p_invcam, 0, 0, -vzdal); //+posun
  338. return (invert_matrix(p_invcam, p_cam));
  339. }
  340. void calc_camera(GLMATRIX * p_cmatrix, GLMATRIX * r_bod_matrix, float vzdal,
  341. float fi)
  342. {
  343. GLMATRIX m;
  344. m = *r_bod_matrix;
  345. rotate_matrix_x(&m, fi);
  346. translate_matrix(&m, 0, 0, -vzdal);
  347. invert_matrix(&m, p_cmatrix);
  348. }
  349. void calc_camera_bod(GLMATRIX * p_cmatrix, GLMATRIX * p_inv, BOD * p_p,
  350. float vzdal, float fi, float rfi)
  351. {
  352. init_matrix(p_inv);
  353. p_inv->_41 = p_p->x;
  354. p_inv->_42 = p_p->y;
  355. p_inv->_43 = p_p->z;
  356. rotate_matrix_y(p_inv, rfi);
  357. rotate_matrix_x(p_inv, fi);
  358. translate_matrix(p_inv, 0, 0, -vzdal);
  359. invert_matrix(p_inv, p_cmatrix);
  360. }
  361. void calc_r_bod(GLMATRIX * p_cmatrix, GLMATRIX * r_bod_matrix, float vzdal,
  362. float fi)
  363. {
  364. *r_bod_matrix = *p_cmatrix;
  365. translate_matrix(r_bod_matrix, 0, 0, vzdal);
  366. rotate_matrix_x(r_bod_matrix, -fi);
  367. }
  368. // prusecik primky a,b a bodu p
  369. void prusecik(BOD * p_a, BOD * p_b, BOD * p_p, BOD * p_I)
  370. {
  371. float t_i, vz;
  372. t_i =
  373. (p_b->x - p_a->x) * (p_p->x - p_a->x) + (p_b->y - p_a->y) * (p_p->y -
  374. p_a->y) + (p_b->z - p_a->z) * (p_p->z - p_a->z);
  375. vz = (float) vzdal_bodu_xy(p_a->x, p_a->y, p_a->z, p_b->x, p_b->y, p_b->z);
  376. t_i /= (vz * vz);
  377. p_I->x = p_a->x + (p_b->x - p_a->x) * t_i;
  378. p_I->y = p_a->y + (p_b->y - p_a->y) * t_i;
  379. p_I->z = p_a->z + (p_b->z - p_a->z) * t_i;
  380. }
  381. void prusecik_mujbod(MUJ_BOD * p_a, MUJ_BOD * p_b, MUJ_BOD * p_p,
  382. MUJ_BOD * p_I)
  383. {
  384. float t_i, vz;
  385. BOD q;
  386. t_i =
  387. (p_b->x - p_a->x) * (p_p->x - p_a->x) + (p_b->y - p_a->y) * (p_p->y -
  388. p_a->y) + (p_b->z - p_a->z) * (p_p->z - p_a->z);
  389. vz = (float) vzdal_bodu_xy(p_a->x, p_a->y, p_a->z, p_b->x, p_b->y, p_b->z);
  390. t_i /= (vz * vz);
  391. q.x = p_b->x - p_a->x;
  392. q.y = p_b->y - p_a->y;
  393. q.z = p_b->z - p_a->z;
  394. p_I->x = p_a->x + q.x * t_i;
  395. p_I->y = p_a->y + q.y * t_i;
  396. p_I->z = p_a->z + q.z * t_i;
  397. }