Winding.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, 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. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "stdafx.h"
  19. #include <assert.h>
  20. #include "qe3.h"
  21. #include "winding.h"
  22. #define BOGUS_RANGE 18000
  23. /*
  24. =============
  25. Plane_Equal
  26. =============
  27. */
  28. #define NORMAL_EPSILON 0.0001
  29. #define DIST_EPSILON 0.02
  30. int Plane_Equal(plane_t *a, plane_t *b, int flip)
  31. {
  32. vec3_t normal;
  33. float dist;
  34. if (flip) {
  35. normal[0] = - b->normal[0];
  36. normal[1] = - b->normal[1];
  37. normal[2] = - b->normal[2];
  38. dist = - b->dist;
  39. }
  40. else {
  41. normal[0] = b->normal[0];
  42. normal[1] = b->normal[1];
  43. normal[2] = b->normal[2];
  44. dist = b->dist;
  45. }
  46. if (
  47. fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON
  48. && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON
  49. && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON
  50. && fabs(a->dist - dist) < DIST_EPSILON )
  51. return true;
  52. return false;
  53. }
  54. /*
  55. ============
  56. Plane_FromPoints
  57. ============
  58. */
  59. int Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane)
  60. {
  61. vec3_t v1, v2;
  62. VectorSubtract(p2, p1, v1);
  63. VectorSubtract(p3, p1, v2);
  64. //CrossProduct(v2, v1, plane->normal);
  65. CrossProduct(v1, v2, plane->normal);
  66. if (VectorNormalize(plane->normal) < 0.1) return false;
  67. plane->dist = DotProduct(p1, plane->normal);
  68. return true;
  69. }
  70. /*
  71. =================
  72. Point_Equal
  73. =================
  74. */
  75. int Point_Equal(vec3_t p1, vec3_t p2, float epsilon)
  76. {
  77. int i;
  78. for (i = 0; i < 3; i++)
  79. {
  80. if (fabs(p1[i] - p2[i]) > epsilon) return false;
  81. }
  82. return true;
  83. }
  84. /*
  85. =================
  86. Winding_BaseForPlane
  87. =================
  88. */
  89. winding_t *Winding_BaseForPlane (plane_t *p)
  90. {
  91. int i, x;
  92. vec_t max, v;
  93. vec3_t org, vright, vup;
  94. winding_t *w;
  95. // find the major axis
  96. max = -BOGUS_RANGE;
  97. x = -1;
  98. for (i=0 ; i<3; i++)
  99. {
  100. v = fabs(p->normal[i]);
  101. if (v > max)
  102. {
  103. x = i;
  104. max = v;
  105. }
  106. }
  107. if (x==-1)
  108. Error ("Winding_BaseForPlane: no axis found");
  109. VectorCopy (vec3_origin, vup);
  110. switch (x)
  111. {
  112. case 0:
  113. case 1:
  114. vup[2] = 1;
  115. break;
  116. case 2:
  117. vup[0] = 1;
  118. break;
  119. }
  120. v = DotProduct (vup, p->normal);
  121. VectorMA (vup, -v, p->normal, vup);
  122. VectorNormalize (vup);
  123. VectorScale (p->normal, p->dist, org);
  124. CrossProduct (vup, p->normal, vright);
  125. VectorScale (vup, BOGUS_RANGE, vup);
  126. VectorScale (vright, BOGUS_RANGE, vright);
  127. // project a really big axis aligned box onto the plane
  128. w = Winding_Alloc (4);
  129. VectorSubtract (org, vright, w->points[0]);
  130. VectorAdd (w->points[0], vup, w->points[0]);
  131. VectorAdd (org, vright, w->points[1]);
  132. VectorAdd (w->points[1], vup, w->points[1]);
  133. VectorAdd (org, vright, w->points[2]);
  134. VectorSubtract (w->points[2], vup, w->points[2]);
  135. VectorSubtract (org, vright, w->points[3]);
  136. VectorSubtract (w->points[3], vup, w->points[3]);
  137. w->numpoints = 4;
  138. return w;
  139. }
  140. /*
  141. ==================
  142. Winding_Alloc
  143. ==================
  144. */
  145. winding_t *Winding_Alloc (int points)
  146. {
  147. winding_t *w;
  148. int size;
  149. if (points > MAX_POINTS_ON_WINDING)
  150. Error ("Winding_Alloc: %i points", points);
  151. size = (int)((winding_t *)0)->points[points];
  152. w = (winding_t*) malloc (size);
  153. memset (w, 0, size);
  154. w->maxpoints = points;
  155. return w;
  156. }
  157. void Winding_Free (winding_t *w)
  158. {
  159. free(w);
  160. }
  161. /*
  162. ==================
  163. Winding_Clone
  164. ==================
  165. */
  166. winding_t *Winding_Clone(winding_t *w)
  167. {
  168. int size;
  169. winding_t *c;
  170. size = (int)((winding_t *)0)->points[w->numpoints];
  171. c = (winding_t*)qmalloc (size);
  172. memcpy (c, w, size);
  173. return c;
  174. }
  175. /*
  176. ==================
  177. ReverseWinding
  178. ==================
  179. */
  180. winding_t *Winding_Reverse(winding_t *w)
  181. {
  182. int i;
  183. winding_t *c;
  184. c = Winding_Alloc(w->numpoints);
  185. for (i = 0; i < w->numpoints; i++)
  186. {
  187. VectorCopy (w->points[w->numpoints-1-i], c->points[i]);
  188. }
  189. c->numpoints = w->numpoints;
  190. return c;
  191. }
  192. /*
  193. ==============
  194. Winding_RemovePoint
  195. ==============
  196. */
  197. void Winding_RemovePoint(winding_t *w, int point)
  198. {
  199. if (point < 0 || point >= w->numpoints)
  200. Error("Winding_RemovePoint: point out of range");
  201. if (point < w->numpoints-1)
  202. {
  203. memmove(&w->points[point], &w->points[point+1], (int)((winding_t *)0)->points[w->numpoints - point - 1]);
  204. }
  205. w->numpoints--;
  206. }
  207. /*
  208. =============
  209. Winding_InsertPoint
  210. =============
  211. */
  212. winding_t *Winding_InsertPoint(winding_t *w, vec3_t point, int spot)
  213. {
  214. int i, j;
  215. winding_t *neww;
  216. if (spot > w->numpoints)
  217. {
  218. Error("Winding_InsertPoint: spot > w->numpoints");
  219. } //end if
  220. if (spot < 0)
  221. {
  222. Error("Winding_InsertPoint: spot < 0");
  223. } //end if
  224. neww = Winding_Alloc(w->numpoints + 1);
  225. neww->numpoints = w->numpoints + 1;
  226. for (i = 0, j = 0; i < neww->numpoints; i++)
  227. {
  228. if (i == spot)
  229. {
  230. VectorCopy(point, neww->points[i]);
  231. }
  232. else
  233. {
  234. VectorCopy(w->points[j], neww->points[i]);
  235. j++;
  236. }
  237. }
  238. return neww;
  239. }
  240. /*
  241. ==============
  242. Winding_IsTiny
  243. ==============
  244. */
  245. #define EDGE_LENGTH 0.2
  246. int Winding_IsTiny (winding_t *w)
  247. {
  248. int i, j;
  249. vec_t len;
  250. vec3_t delta;
  251. int edges;
  252. edges = 0;
  253. for (i=0 ; i<w->numpoints ; i++)
  254. {
  255. j = i == w->numpoints - 1 ? 0 : i+1;
  256. VectorSubtract (w->points[j], w->points[i], delta);
  257. len = VectorLength (delta);
  258. if (len > EDGE_LENGTH)
  259. {
  260. if (++edges == 3)
  261. return false;
  262. }
  263. }
  264. return true;
  265. }
  266. /*
  267. ==============
  268. Winding_IsHuge
  269. ==============
  270. */
  271. int Winding_IsHuge(winding_t *w)
  272. {
  273. int i, j;
  274. for (i=0 ; i<w->numpoints ; i++)
  275. {
  276. for (j=0 ; j<3 ; j++)
  277. if (w->points[i][j] < -BOGUS_RANGE+1 || w->points[i][j] > BOGUS_RANGE-1)
  278. return true;
  279. }
  280. return false;
  281. }
  282. /*
  283. =============
  284. Winding_PlanesConcave
  285. =============
  286. */
  287. #define WCONVEX_EPSILON 0.2
  288. int Winding_PlanesConcave(winding_t *w1, winding_t *w2,
  289. vec3_t normal1, vec3_t normal2,
  290. float dist1, float dist2)
  291. {
  292. int i;
  293. if (!w1 || !w2) return false;
  294. // check if one of the points of winding 1 is at the back of the plane of winding 2
  295. for (i = 0; i < w1->numpoints; i++)
  296. {
  297. if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return true;
  298. }
  299. // check if one of the points of winding 2 is at the back of the plane of winding 1
  300. for (i = 0; i < w2->numpoints; i++)
  301. {
  302. if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return true;
  303. }
  304. return false;
  305. }
  306. /*
  307. ==================
  308. Winding_Clip
  309. Clips the winding to the plane, returning the new winding on the positive side
  310. Frees the input winding.
  311. If keepon is true, an exactly on-plane winding will be saved, otherwise
  312. it will be clipped away.
  313. ==================
  314. */
  315. winding_t *Winding_Clip (winding_t *in, plane_t *split, qboolean keepon)
  316. {
  317. vec_t dists[MAX_POINTS_ON_WINDING];
  318. int sides[MAX_POINTS_ON_WINDING];
  319. int counts[3];
  320. vec_t dot;
  321. int i, j;
  322. vec_t *p1, *p2;
  323. vec3_t mid;
  324. winding_t *neww;
  325. int maxpts;
  326. counts[0] = counts[1] = counts[2] = 0;
  327. // determine sides for each point
  328. for (i=0 ; i<in->numpoints ; i++)
  329. {
  330. dot = DotProduct (in->points[i], split->normal);
  331. dot -= split->dist;
  332. dists[i] = dot;
  333. if (dot > ON_EPSILON)
  334. sides[i] = SIDE_FRONT;
  335. else if (dot < -ON_EPSILON)
  336. sides[i] = SIDE_BACK;
  337. else
  338. {
  339. sides[i] = SIDE_ON;
  340. }
  341. counts[sides[i]]++;
  342. }
  343. sides[i] = sides[0];
  344. dists[i] = dists[0];
  345. if (keepon && !counts[0] && !counts[1])
  346. return in;
  347. if (!counts[0])
  348. {
  349. Winding_Free (in);
  350. return NULL;
  351. }
  352. if (!counts[1])
  353. return in;
  354. maxpts = in->numpoints+4; // can't use counts[0]+2 because
  355. // of fp grouping errors
  356. neww = Winding_Alloc (maxpts);
  357. for (i=0 ; i<in->numpoints ; i++)
  358. {
  359. p1 = in->points[i];
  360. if (sides[i] == SIDE_ON)
  361. {
  362. VectorCopy (p1, neww->points[neww->numpoints]);
  363. neww->numpoints++;
  364. continue;
  365. }
  366. if (sides[i] == SIDE_FRONT)
  367. {
  368. VectorCopy (p1, neww->points[neww->numpoints]);
  369. neww->numpoints++;
  370. }
  371. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  372. continue;
  373. // generate a split point
  374. p2 = in->points[(i+1)%in->numpoints];
  375. dot = dists[i] / (dists[i]-dists[i+1]);
  376. for (j=0 ; j<3 ; j++)
  377. { // avoid round off error when possible
  378. if (split->normal[j] == 1)
  379. mid[j] = split->dist;
  380. else if (split->normal[j] == -1)
  381. mid[j] = -split->dist;
  382. else
  383. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  384. }
  385. VectorCopy (mid, neww->points[neww->numpoints]);
  386. neww->numpoints++;
  387. }
  388. if (neww->numpoints > maxpts)
  389. Error ("Winding_Clip: points exceeded estimate");
  390. // free the original winding
  391. Winding_Free (in);
  392. return neww;
  393. }
  394. /*
  395. =============
  396. Winding_SplitEpsilon
  397. split the input winding with the plane
  398. the input winding stays untouched
  399. =============
  400. */
  401. void Winding_SplitEpsilon (winding_t *in, vec3_t normal, double dist,
  402. vec_t epsilon, winding_t **front, winding_t **back)
  403. {
  404. vec_t dists[MAX_POINTS_ON_WINDING+4];
  405. int sides[MAX_POINTS_ON_WINDING+4];
  406. int counts[3];
  407. vec_t dot;
  408. int i, j;
  409. vec_t *p1, *p2;
  410. vec3_t mid;
  411. winding_t *f, *b;
  412. int maxpts;
  413. counts[0] = counts[1] = counts[2] = 0;
  414. // determine sides for each point
  415. for (i = 0; i < in->numpoints; i++)
  416. {
  417. dot = DotProduct (in->points[i], normal);
  418. dot -= dist;
  419. dists[i] = dot;
  420. if (dot > epsilon)
  421. sides[i] = SIDE_FRONT;
  422. else if (dot < -epsilon)
  423. sides[i] = SIDE_BACK;
  424. else
  425. {
  426. sides[i] = SIDE_ON;
  427. }
  428. counts[sides[i]]++;
  429. }
  430. sides[i] = sides[0];
  431. dists[i] = dists[0];
  432. *front = *back = NULL;
  433. if (!counts[0])
  434. {
  435. *back = Winding_Clone(in);
  436. return;
  437. }
  438. if (!counts[1])
  439. {
  440. *front = Winding_Clone(in);
  441. return;
  442. }
  443. maxpts = in->numpoints+4; // cant use counts[0]+2 because
  444. // of fp grouping errors
  445. *front = f = Winding_Alloc (maxpts);
  446. *back = b = Winding_Alloc (maxpts);
  447. for (i = 0; i < in->numpoints; i++)
  448. {
  449. p1 = in->points[i];
  450. if (sides[i] == SIDE_ON)
  451. {
  452. VectorCopy (p1, f->points[f->numpoints]);
  453. f->numpoints++;
  454. VectorCopy (p1, b->points[b->numpoints]);
  455. b->numpoints++;
  456. continue;
  457. }
  458. if (sides[i] == SIDE_FRONT)
  459. {
  460. VectorCopy (p1, f->points[f->numpoints]);
  461. f->numpoints++;
  462. }
  463. if (sides[i] == SIDE_BACK)
  464. {
  465. VectorCopy (p1, b->points[b->numpoints]);
  466. b->numpoints++;
  467. }
  468. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  469. continue;
  470. // generate a split point
  471. p2 = in->points[(i+1)%in->numpoints];
  472. dot = dists[i] / (dists[i]-dists[i+1]);
  473. for (j = 0; j < 3; j++)
  474. {
  475. // avoid round off error when possible
  476. if (normal[j] == 1)
  477. mid[j] = dist;
  478. else if (normal[j] == -1)
  479. mid[j] = -dist;
  480. else
  481. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  482. }
  483. VectorCopy (mid, f->points[f->numpoints]);
  484. f->numpoints++;
  485. VectorCopy (mid, b->points[b->numpoints]);
  486. b->numpoints++;
  487. }
  488. if (f->numpoints > maxpts || b->numpoints > maxpts)
  489. Error ("Winding_Clip: points exceeded estimate");
  490. if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
  491. Error ("Winding_Clip: MAX_POINTS_ON_WINDING");
  492. }
  493. /*
  494. =============
  495. Winding_TryMerge
  496. If two windings share a common edge and the edges that meet at the
  497. common points are both inside the other polygons, merge them
  498. Returns NULL if the windings couldn't be merged, or the new winding.
  499. The originals will NOT be freed.
  500. if keep is true no points are ever removed
  501. =============
  502. */
  503. #define CONTINUOUS_EPSILON 0.005
  504. winding_t *Winding_TryMerge(winding_t *f1, winding_t *f2, vec3_t planenormal, int keep)
  505. {
  506. vec_t *p1, *p2, *p3, *p4, *back;
  507. winding_t *newf;
  508. int i, j, k, l;
  509. vec3_t normal, delta;
  510. vec_t dot;
  511. qboolean keep1, keep2;
  512. //
  513. // find a common edge
  514. //
  515. p1 = p2 = NULL; // stop compiler warning
  516. j = 0; //
  517. for (i = 0; i < f1->numpoints; i++)
  518. {
  519. p1 = f1->points[i];
  520. p2 = f1->points[(i+1) % f1->numpoints];
  521. for (j = 0; j < f2->numpoints; j++)
  522. {
  523. p3 = f2->points[j];
  524. p4 = f2->points[(j+1) % f2->numpoints];
  525. for (k = 0; k < 3; k++)
  526. {
  527. if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
  528. break;
  529. if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
  530. break;
  531. } //end for
  532. if (k==3)
  533. break;
  534. } //end for
  535. if (j < f2->numpoints)
  536. break;
  537. } //end for
  538. if (i == f1->numpoints)
  539. return NULL; // no matching edges
  540. //
  541. // check slope of connected lines
  542. // if the slopes are colinear, the point can be removed
  543. //
  544. back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
  545. VectorSubtract (p1, back, delta);
  546. CrossProduct (planenormal, delta, normal);
  547. VectorNormalize (normal);
  548. back = f2->points[(j+2)%f2->numpoints];
  549. VectorSubtract (back, p1, delta);
  550. dot = DotProduct (delta, normal);
  551. if (dot > CONTINUOUS_EPSILON)
  552. return NULL; // not a convex polygon
  553. keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
  554. back = f1->points[(i+2)%f1->numpoints];
  555. VectorSubtract (back, p2, delta);
  556. CrossProduct (planenormal, delta, normal);
  557. VectorNormalize (normal);
  558. back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
  559. VectorSubtract (back, p2, delta);
  560. dot = DotProduct (delta, normal);
  561. if (dot > CONTINUOUS_EPSILON)
  562. return NULL; // not a convex polygon
  563. keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
  564. //
  565. // build the new polygon
  566. //
  567. newf = Winding_Alloc (f1->numpoints + f2->numpoints);
  568. // copy first polygon
  569. for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
  570. {
  571. if (!keep && k==(i+1)%f1->numpoints && !keep2)
  572. continue;
  573. VectorCopy (f1->points[k], newf->points[newf->numpoints]);
  574. newf->numpoints++;
  575. }
  576. // copy second polygon
  577. for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
  578. {
  579. if (!keep && l==(j+1)%f2->numpoints && !keep1)
  580. continue;
  581. VectorCopy (f2->points[l], newf->points[newf->numpoints]);
  582. newf->numpoints++;
  583. }
  584. return newf;
  585. }
  586. /*
  587. ============
  588. Winding_Plane
  589. ============
  590. */
  591. void Winding_Plane (winding_t *w, vec3_t normal, double *dist)
  592. {
  593. vec3_t v1, v2;
  594. int i;
  595. //find two vectors each longer than 0.5 units
  596. for (i = 0; i < w->numpoints; i++)
  597. {
  598. VectorSubtract(w->points[(i+1) % w->numpoints], w->points[i], v1);
  599. VectorSubtract(w->points[(i+2) % w->numpoints], w->points[i], v2);
  600. if (VectorLength(v1) > 0.5 && VectorLength(v2) > 0.5) break;
  601. }
  602. CrossProduct(v2, v1, normal);
  603. VectorNormalize(normal);
  604. *dist = DotProduct(w->points[0], normal);
  605. }
  606. /*
  607. =============
  608. Winding_Area
  609. =============
  610. */
  611. float Winding_Area (winding_t *w)
  612. {
  613. int i;
  614. vec3_t d1, d2, cross;
  615. float total;
  616. total = 0;
  617. for (i=2 ; i<w->numpoints ; i++)
  618. {
  619. VectorSubtract (w->points[i-1], w->points[0], d1);
  620. VectorSubtract (w->points[i], w->points[0], d2);
  621. CrossProduct (d1, d2, cross);
  622. total += 0.5 * VectorLength ( cross );
  623. }
  624. return total;
  625. }
  626. /*
  627. =============
  628. Winding_Bounds
  629. =============
  630. */
  631. void Winding_Bounds (winding_t *w, vec3_t mins, vec3_t maxs)
  632. {
  633. vec_t v;
  634. int i,j;
  635. mins[0] = mins[1] = mins[2] = 99999;
  636. maxs[0] = maxs[1] = maxs[2] = -99999;
  637. for (i=0 ; i<w->numpoints ; i++)
  638. {
  639. for (j=0 ; j<3 ; j++)
  640. {
  641. v = w->points[i][j];
  642. if (v < mins[j])
  643. mins[j] = v;
  644. if (v > maxs[j])
  645. maxs[j] = v;
  646. }
  647. }
  648. }
  649. /*
  650. =================
  651. Winding_PointInside
  652. =================
  653. */
  654. int Winding_PointInside(winding_t *w, plane_t *plane, vec3_t point, float epsilon)
  655. {
  656. int i;
  657. vec3_t dir, normal, pointvec;
  658. for (i = 0; i < w->numpoints; i++)
  659. {
  660. VectorSubtract(w->points[(i+1) % w->numpoints], w->points[i], dir);
  661. VectorSubtract(point, w->points[i], pointvec);
  662. //
  663. CrossProduct(dir, plane->normal, normal);
  664. //
  665. if (DotProduct(pointvec, normal) < -epsilon) return false;
  666. }
  667. return true;
  668. }
  669. /*
  670. =================
  671. Winding_VectorIntersect
  672. =================
  673. */
  674. int Winding_VectorIntersect(winding_t *w, plane_t *plane, vec3_t p1, vec3_t p2, float epsilon)
  675. {
  676. float front, back, frac;
  677. vec3_t mid;
  678. front = DotProduct(p1, plane->normal) - plane->dist;
  679. back = DotProduct(p2, plane->normal) - plane->dist;
  680. //if both points at the same side of the plane
  681. if (front < -epsilon && back < -epsilon) return false;
  682. if (front > epsilon && back > epsilon) return false;
  683. //get point of intersection with winding plane
  684. if (fabs(front-back) < 0.001)
  685. {
  686. VectorCopy(p2, mid);
  687. }
  688. else
  689. {
  690. frac = front/(front-back);
  691. mid[0] = p1[0] + (p2[0] - p1[0]) * frac;
  692. mid[1] = p1[1] + (p2[1] - p1[1]) * frac;
  693. mid[2] = p1[2] + (p2[2] - p1[2]) * frac;
  694. }
  695. return Winding_PointInside(w, plane, mid, epsilon);
  696. }