l_poly.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412
  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 <malloc.h>
  19. #include "l_cmd.h"
  20. #include "l_math.h"
  21. #include "l_poly.h"
  22. #include "l_log.h"
  23. #include "l_mem.h"
  24. #define BOGUS_RANGE 65535
  25. extern int numthreads;
  26. // counters are only bumped when running single threaded,
  27. // because they are an awefull coherence problem
  28. int c_active_windings;
  29. int c_peak_windings;
  30. int c_winding_allocs;
  31. int c_winding_points;
  32. int c_windingmemory;
  33. int c_peak_windingmemory;
  34. char windingerror[1024];
  35. void pw(winding_t *w)
  36. {
  37. int i;
  38. for (i=0 ; i<w->numpoints ; i++)
  39. printf ("(%5.3f, %5.3f, %5.3f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
  40. }
  41. void ResetWindings(void)
  42. {
  43. c_active_windings = 0;
  44. c_peak_windings = 0;
  45. c_winding_allocs = 0;
  46. c_winding_points = 0;
  47. c_windingmemory = 0;
  48. c_peak_windingmemory = 0;
  49. strcpy(windingerror, "");
  50. } //end of the function ResetWindings
  51. /*
  52. =============
  53. AllocWinding
  54. =============
  55. */
  56. winding_t *AllocWinding (int points)
  57. {
  58. winding_t *w;
  59. int s;
  60. s = sizeof(vec_t)*3*points + sizeof(int);
  61. w = GetMemory(s);
  62. memset(w, 0, s);
  63. if (numthreads == 1)
  64. {
  65. c_winding_allocs++;
  66. c_winding_points += points;
  67. c_active_windings++;
  68. if (c_active_windings > c_peak_windings)
  69. c_peak_windings = c_active_windings;
  70. c_windingmemory += MemorySize(w);
  71. if (c_windingmemory > c_peak_windingmemory)
  72. c_peak_windingmemory = c_windingmemory;
  73. } //end if
  74. return w;
  75. } //end of the function AllocWinding
  76. void FreeWinding (winding_t *w)
  77. {
  78. if (*(unsigned *)w == 0xdeaddead)
  79. Error ("FreeWinding: freed a freed winding");
  80. if (numthreads == 1)
  81. {
  82. c_active_windings--;
  83. c_windingmemory -= MemorySize(w);
  84. } //end if
  85. *(unsigned *)w = 0xdeaddead;
  86. FreeMemory(w);
  87. } //end of the function FreeWinding
  88. int WindingMemory(void)
  89. {
  90. return c_windingmemory;
  91. } //end of the function WindingMemory
  92. int WindingPeakMemory(void)
  93. {
  94. return c_peak_windingmemory;
  95. } //end of the function WindingPeakMemory
  96. int ActiveWindings(void)
  97. {
  98. return c_active_windings;
  99. } //end of the function ActiveWindings
  100. /*
  101. ============
  102. RemoveColinearPoints
  103. ============
  104. */
  105. int c_removed;
  106. void RemoveColinearPoints (winding_t *w)
  107. {
  108. int i, j, k;
  109. vec3_t v1, v2;
  110. int nump;
  111. vec3_t p[MAX_POINTS_ON_WINDING];
  112. nump = 0;
  113. for (i=0 ; i<w->numpoints ; i++)
  114. {
  115. j = (i+1)%w->numpoints;
  116. k = (i+w->numpoints-1)%w->numpoints;
  117. VectorSubtract (w->p[j], w->p[i], v1);
  118. VectorSubtract (w->p[i], w->p[k], v2);
  119. VectorNormalize(v1);
  120. VectorNormalize(v2);
  121. if (DotProduct(v1, v2) < 0.999)
  122. {
  123. if (nump >= MAX_POINTS_ON_WINDING)
  124. Error("RemoveColinearPoints: MAX_POINTS_ON_WINDING");
  125. VectorCopy (w->p[i], p[nump]);
  126. nump++;
  127. }
  128. }
  129. if (nump == w->numpoints)
  130. return;
  131. if (numthreads == 1)
  132. c_removed += w->numpoints - nump;
  133. w->numpoints = nump;
  134. memcpy (w->p, p, nump*sizeof(p[0]));
  135. }
  136. /*
  137. ============
  138. WindingPlane
  139. ============
  140. */
  141. void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
  142. {
  143. vec3_t v1, v2;
  144. int i;
  145. //find two vectors each longer than 0.5 units
  146. for (i = 0; i < w->numpoints; i++)
  147. {
  148. VectorSubtract(w->p[(i+1) % w->numpoints], w->p[i], v1);
  149. VectorSubtract(w->p[(i+2) % w->numpoints], w->p[i], v2);
  150. if (VectorLength(v1) > 0.5 && VectorLength(v2) > 0.5) break;
  151. } //end for
  152. CrossProduct(v2, v1, normal);
  153. VectorNormalize(normal);
  154. *dist = DotProduct(w->p[0], normal);
  155. } //end of the function WindingPlane
  156. /*
  157. =============
  158. WindingArea
  159. =============
  160. */
  161. vec_t WindingArea (winding_t *w)
  162. {
  163. int i;
  164. vec3_t d1, d2, cross;
  165. vec_t total;
  166. total = 0;
  167. for (i=2 ; i<w->numpoints ; i++)
  168. {
  169. VectorSubtract (w->p[i-1], w->p[0], d1);
  170. VectorSubtract (w->p[i], w->p[0], d2);
  171. CrossProduct (d1, d2, cross);
  172. total += 0.5 * VectorLength ( cross );
  173. }
  174. return total;
  175. }
  176. void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
  177. {
  178. vec_t v;
  179. int i,j;
  180. mins[0] = mins[1] = mins[2] = 99999;
  181. maxs[0] = maxs[1] = maxs[2] = -99999;
  182. for (i=0 ; i<w->numpoints ; i++)
  183. {
  184. for (j=0 ; j<3 ; j++)
  185. {
  186. v = w->p[i][j];
  187. if (v < mins[j])
  188. mins[j] = v;
  189. if (v > maxs[j])
  190. maxs[j] = v;
  191. }
  192. }
  193. }
  194. /*
  195. =============
  196. WindingCenter
  197. =============
  198. */
  199. void WindingCenter (winding_t *w, vec3_t center)
  200. {
  201. int i;
  202. float scale;
  203. VectorCopy (vec3_origin, center);
  204. for (i=0 ; i<w->numpoints ; i++)
  205. VectorAdd (w->p[i], center, center);
  206. scale = 1.0/w->numpoints;
  207. VectorScale (center, scale, center);
  208. }
  209. /*
  210. =================
  211. BaseWindingForPlane
  212. =================
  213. */
  214. winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
  215. {
  216. int i, x;
  217. vec_t max, v;
  218. vec3_t org, vright, vup;
  219. winding_t *w;
  220. // find the major axis
  221. max = -BOGUS_RANGE;
  222. x = -1;
  223. for (i=0 ; i<3; i++)
  224. {
  225. v = fabs(normal[i]);
  226. if (v > max)
  227. {
  228. x = i;
  229. max = v;
  230. }
  231. }
  232. if (x==-1)
  233. Error ("BaseWindingForPlane: no axis found");
  234. VectorCopy (vec3_origin, vup);
  235. switch (x)
  236. {
  237. case 0:
  238. case 1:
  239. vup[2] = 1;
  240. break;
  241. case 2:
  242. vup[0] = 1;
  243. break;
  244. }
  245. v = DotProduct (vup, normal);
  246. VectorMA (vup, -v, normal, vup);
  247. VectorNormalize (vup);
  248. VectorScale (normal, dist, org);
  249. CrossProduct (vup, normal, vright);
  250. VectorScale (vup, BOGUS_RANGE, vup);
  251. VectorScale (vright, BOGUS_RANGE, vright);
  252. // project a really big axis aligned box onto the plane
  253. w = AllocWinding (4);
  254. VectorSubtract (org, vright, w->p[0]);
  255. VectorAdd (w->p[0], vup, w->p[0]);
  256. VectorAdd (org, vright, w->p[1]);
  257. VectorAdd (w->p[1], vup, w->p[1]);
  258. VectorAdd (org, vright, w->p[2]);
  259. VectorSubtract (w->p[2], vup, w->p[2]);
  260. VectorSubtract (org, vright, w->p[3]);
  261. VectorSubtract (w->p[3], vup, w->p[3]);
  262. w->numpoints = 4;
  263. return w;
  264. }
  265. /*
  266. ==================
  267. CopyWinding
  268. ==================
  269. */
  270. winding_t *CopyWinding (winding_t *w)
  271. {
  272. int size;
  273. winding_t *c;
  274. c = AllocWinding (w->numpoints);
  275. size = (int)((winding_t *)0)->p[w->numpoints];
  276. memcpy (c, w, size);
  277. return c;
  278. }
  279. /*
  280. ==================
  281. ReverseWinding
  282. ==================
  283. */
  284. winding_t *ReverseWinding (winding_t *w)
  285. {
  286. int i;
  287. winding_t *c;
  288. c = AllocWinding (w->numpoints);
  289. for (i=0 ; i<w->numpoints ; i++)
  290. {
  291. VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
  292. }
  293. c->numpoints = w->numpoints;
  294. return c;
  295. }
  296. /*
  297. =============
  298. ClipWindingEpsilon
  299. =============
  300. */
  301. void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
  302. vec_t epsilon, winding_t **front, winding_t **back)
  303. {
  304. vec_t dists[MAX_POINTS_ON_WINDING+4];
  305. int sides[MAX_POINTS_ON_WINDING+4];
  306. int counts[3];
  307. //MrElusive: DOH can't use statics when unsing multithreading!!!
  308. vec_t dot; // VC 4.2 optimizer bug if not static
  309. int i, j;
  310. vec_t *p1, *p2;
  311. vec3_t mid;
  312. winding_t *f, *b;
  313. int maxpts;
  314. counts[0] = counts[1] = counts[2] = 0;
  315. // determine sides for each point
  316. for (i=0 ; i<in->numpoints ; i++)
  317. {
  318. dot = DotProduct (in->p[i], normal);
  319. dot -= dist;
  320. dists[i] = dot;
  321. if (dot > epsilon)
  322. sides[i] = SIDE_FRONT;
  323. else if (dot < -epsilon)
  324. sides[i] = SIDE_BACK;
  325. else
  326. {
  327. sides[i] = SIDE_ON;
  328. }
  329. counts[sides[i]]++;
  330. }
  331. sides[i] = sides[0];
  332. dists[i] = dists[0];
  333. *front = *back = NULL;
  334. if (!counts[0])
  335. {
  336. *back = CopyWinding (in);
  337. return;
  338. }
  339. if (!counts[1])
  340. {
  341. *front = CopyWinding (in);
  342. return;
  343. }
  344. maxpts = in->numpoints+4; // cant use counts[0]+2 because
  345. // of fp grouping errors
  346. *front = f = AllocWinding (maxpts);
  347. *back = b = AllocWinding (maxpts);
  348. for (i=0 ; i<in->numpoints ; i++)
  349. {
  350. p1 = in->p[i];
  351. if (sides[i] == SIDE_ON)
  352. {
  353. VectorCopy (p1, f->p[f->numpoints]);
  354. f->numpoints++;
  355. VectorCopy (p1, b->p[b->numpoints]);
  356. b->numpoints++;
  357. continue;
  358. }
  359. if (sides[i] == SIDE_FRONT)
  360. {
  361. VectorCopy (p1, f->p[f->numpoints]);
  362. f->numpoints++;
  363. }
  364. if (sides[i] == SIDE_BACK)
  365. {
  366. VectorCopy (p1, b->p[b->numpoints]);
  367. b->numpoints++;
  368. }
  369. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  370. continue;
  371. // generate a split point
  372. p2 = in->p[(i+1)%in->numpoints];
  373. dot = dists[i] / (dists[i]-dists[i+1]);
  374. for (j=0 ; j<3 ; j++)
  375. { // avoid round off error when possible
  376. if (normal[j] == 1)
  377. mid[j] = dist;
  378. else if (normal[j] == -1)
  379. mid[j] = -dist;
  380. else
  381. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  382. }
  383. VectorCopy (mid, f->p[f->numpoints]);
  384. f->numpoints++;
  385. VectorCopy (mid, b->p[b->numpoints]);
  386. b->numpoints++;
  387. }
  388. if (f->numpoints > maxpts || b->numpoints > maxpts)
  389. Error ("ClipWinding: points exceeded estimate");
  390. if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
  391. Error ("ClipWinding: MAX_POINTS_ON_WINDING");
  392. }
  393. /*
  394. =============
  395. ChopWindingInPlace
  396. =============
  397. */
  398. void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
  399. {
  400. winding_t *in;
  401. vec_t dists[MAX_POINTS_ON_WINDING+4];
  402. int sides[MAX_POINTS_ON_WINDING+4];
  403. int counts[3];
  404. //MrElusive: DOH can't use statics when unsing multithreading!!!
  405. vec_t dot; // VC 4.2 optimizer bug if not static
  406. int i, j;
  407. vec_t *p1, *p2;
  408. vec3_t mid;
  409. winding_t *f;
  410. int maxpts;
  411. in = *inout;
  412. counts[0] = counts[1] = counts[2] = 0;
  413. // determine sides for each point
  414. for (i=0 ; i<in->numpoints ; i++)
  415. {
  416. dot = DotProduct (in->p[i], normal);
  417. dot -= dist;
  418. dists[i] = dot;
  419. if (dot > epsilon)
  420. sides[i] = SIDE_FRONT;
  421. else if (dot < -epsilon)
  422. sides[i] = SIDE_BACK;
  423. else
  424. {
  425. sides[i] = SIDE_ON;
  426. }
  427. counts[sides[i]]++;
  428. }
  429. sides[i] = sides[0];
  430. dists[i] = dists[0];
  431. if (!counts[0])
  432. {
  433. FreeWinding (in);
  434. *inout = NULL;
  435. return;
  436. }
  437. if (!counts[1])
  438. return; // inout stays the same
  439. maxpts = in->numpoints+4; // cant use counts[0]+2 because
  440. // of fp grouping errors
  441. f = AllocWinding (maxpts);
  442. for (i=0 ; i<in->numpoints ; i++)
  443. {
  444. p1 = in->p[i];
  445. if (sides[i] == SIDE_ON)
  446. {
  447. VectorCopy (p1, f->p[f->numpoints]);
  448. f->numpoints++;
  449. continue;
  450. }
  451. if (sides[i] == SIDE_FRONT)
  452. {
  453. VectorCopy (p1, f->p[f->numpoints]);
  454. f->numpoints++;
  455. }
  456. if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
  457. continue;
  458. // generate a split point
  459. p2 = in->p[(i+1)%in->numpoints];
  460. dot = dists[i] / (dists[i]-dists[i+1]);
  461. for (j=0 ; j<3 ; j++)
  462. { // avoid round off error when possible
  463. if (normal[j] == 1)
  464. mid[j] = dist;
  465. else if (normal[j] == -1)
  466. mid[j] = -dist;
  467. else
  468. mid[j] = p1[j] + dot*(p2[j]-p1[j]);
  469. }
  470. VectorCopy (mid, f->p[f->numpoints]);
  471. f->numpoints++;
  472. }
  473. if (f->numpoints > maxpts)
  474. Error ("ClipWinding: points exceeded estimate");
  475. if (f->numpoints > MAX_POINTS_ON_WINDING)
  476. Error ("ClipWinding: MAX_POINTS_ON_WINDING");
  477. FreeWinding (in);
  478. *inout = f;
  479. }
  480. /*
  481. =================
  482. ChopWinding
  483. Returns the fragment of in that is on the front side
  484. of the cliping plane. The original is freed.
  485. =================
  486. */
  487. winding_t *ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
  488. {
  489. winding_t *f, *b;
  490. ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
  491. FreeWinding (in);
  492. if (b)
  493. FreeWinding (b);
  494. return f;
  495. }
  496. /*
  497. =================
  498. CheckWinding
  499. =================
  500. */
  501. void CheckWinding (winding_t *w)
  502. {
  503. int i, j;
  504. vec_t *p1, *p2;
  505. vec_t d, edgedist;
  506. vec3_t dir, edgenormal, facenormal;
  507. vec_t area;
  508. vec_t facedist;
  509. if (w->numpoints < 3)
  510. Error ("CheckWinding: %i points",w->numpoints);
  511. area = WindingArea(w);
  512. if (area < 1)
  513. Error ("CheckWinding: %f area", area);
  514. WindingPlane (w, facenormal, &facedist);
  515. for (i=0 ; i<w->numpoints ; i++)
  516. {
  517. p1 = w->p[i];
  518. for (j=0 ; j<3 ; j++)
  519. if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
  520. Error ("CheckWinding: BUGUS_RANGE: %f",p1[j]);
  521. j = i+1 == w->numpoints ? 0 : i+1;
  522. // check the point is on the face plane
  523. d = DotProduct (p1, facenormal) - facedist;
  524. if (d < -ON_EPSILON || d > ON_EPSILON)
  525. Error ("CheckWinding: point off plane");
  526. // check the edge isnt degenerate
  527. p2 = w->p[j];
  528. VectorSubtract (p2, p1, dir);
  529. if (VectorLength (dir) < ON_EPSILON)
  530. Error ("CheckWinding: degenerate edge");
  531. CrossProduct (facenormal, dir, edgenormal);
  532. VectorNormalize (edgenormal);
  533. edgedist = DotProduct (p1, edgenormal);
  534. edgedist += ON_EPSILON;
  535. // all other points must be on front side
  536. for (j=0 ; j<w->numpoints ; j++)
  537. {
  538. if (j == i)
  539. continue;
  540. d = DotProduct (w->p[j], edgenormal);
  541. if (d > edgedist)
  542. Error ("CheckWinding: non-convex");
  543. }
  544. }
  545. }
  546. /*
  547. ============
  548. WindingOnPlaneSide
  549. ============
  550. */
  551. int WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
  552. {
  553. qboolean front, back;
  554. int i;
  555. vec_t d;
  556. front = false;
  557. back = false;
  558. for (i=0 ; i<w->numpoints ; i++)
  559. {
  560. d = DotProduct (w->p[i], normal) - dist;
  561. if (d < -ON_EPSILON)
  562. {
  563. if (front)
  564. return SIDE_CROSS;
  565. back = true;
  566. continue;
  567. }
  568. if (d > ON_EPSILON)
  569. {
  570. if (back)
  571. return SIDE_CROSS;
  572. front = true;
  573. continue;
  574. }
  575. }
  576. if (back)
  577. return SIDE_BACK;
  578. if (front)
  579. return SIDE_FRONT;
  580. return SIDE_ON;
  581. }
  582. //#ifdef ME
  583. #define CONTINUOUS_EPSILON 0.005
  584. //#else
  585. // #define CONTINUOUS_EPSILON 0.001
  586. //#endif
  587. /*
  588. =============
  589. TryMergeWinding
  590. If two polygons share a common edge and the edges that meet at the
  591. common points are both inside the other polygons, merge them
  592. Returns NULL if the faces couldn't be merged, or the new face.
  593. The originals will NOT be freed.
  594. =============
  595. */
  596. winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal)
  597. {
  598. vec_t *p1, *p2, *p3, *p4, *back;
  599. winding_t *newf;
  600. int i, j, k, l;
  601. vec3_t normal, delta;
  602. vec_t dot;
  603. qboolean keep1, keep2;
  604. //
  605. // find a common edge
  606. //
  607. p1 = p2 = NULL; // stop compiler warning
  608. j = 0; //
  609. for (i = 0; i < f1->numpoints; i++)
  610. {
  611. p1 = f1->p[i];
  612. p2 = f1->p[(i+1) % f1->numpoints];
  613. for (j = 0; j < f2->numpoints; j++)
  614. {
  615. p3 = f2->p[j];
  616. p4 = f2->p[(j+1) % f2->numpoints];
  617. for (k = 0; k < 3; k++)
  618. {
  619. if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
  620. break;
  621. if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
  622. break;
  623. } //end for
  624. if (k==3)
  625. break;
  626. } //end for
  627. if (j < f2->numpoints)
  628. break;
  629. } //end for
  630. if (i == f1->numpoints)
  631. return NULL; // no matching edges
  632. //
  633. // check slope of connected lines
  634. // if the slopes are colinear, the point can be removed
  635. //
  636. back = f1->p[(i+f1->numpoints-1)%f1->numpoints];
  637. VectorSubtract (p1, back, delta);
  638. CrossProduct (planenormal, delta, normal);
  639. VectorNormalize (normal);
  640. back = f2->p[(j+2)%f2->numpoints];
  641. VectorSubtract (back, p1, delta);
  642. dot = DotProduct (delta, normal);
  643. if (dot > CONTINUOUS_EPSILON)
  644. return NULL; // not a convex polygon
  645. keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
  646. back = f1->p[(i+2)%f1->numpoints];
  647. VectorSubtract (back, p2, delta);
  648. CrossProduct (planenormal, delta, normal);
  649. VectorNormalize (normal);
  650. back = f2->p[(j+f2->numpoints-1)%f2->numpoints];
  651. VectorSubtract (back, p2, delta);
  652. dot = DotProduct (delta, normal);
  653. if (dot > CONTINUOUS_EPSILON)
  654. return NULL; // not a convex polygon
  655. keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
  656. //
  657. // build the new polygon
  658. //
  659. newf = AllocWinding (f1->numpoints + f2->numpoints);
  660. // copy first polygon
  661. for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
  662. {
  663. if (k==(i+1)%f1->numpoints && !keep2)
  664. continue;
  665. VectorCopy (f1->p[k], newf->p[newf->numpoints]);
  666. newf->numpoints++;
  667. }
  668. // copy second polygon
  669. for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
  670. {
  671. if (l==(j+1)%f2->numpoints && !keep1)
  672. continue;
  673. VectorCopy (f2->p[l], newf->p[newf->numpoints]);
  674. newf->numpoints++;
  675. }
  676. return newf;
  677. }
  678. //#ifdef ME
  679. //===========================================================================
  680. //
  681. // Parameter: -
  682. // Returns: -
  683. // Changes Globals: -
  684. //===========================================================================
  685. winding_t *MergeWindings(winding_t *w1, winding_t *w2, vec3_t planenormal)
  686. {
  687. winding_t *neww;
  688. float dist;
  689. int i, j, n, found, insertafter;
  690. int sides[MAX_POINTS_ON_WINDING+4];
  691. vec3_t newp[MAX_POINTS_ON_WINDING+4];
  692. int numpoints;
  693. vec3_t edgevec, sepnormal, v;
  694. RemoveEqualPoints(w1, 0.2);
  695. numpoints = w1->numpoints;
  696. memcpy(newp, w1->p, w1->numpoints * sizeof(vec3_t));
  697. //
  698. for (i = 0; i < w2->numpoints; i++)
  699. {
  700. VectorCopy(w2->p[i], v);
  701. for (j = 0; j < numpoints; j++)
  702. {
  703. VectorSubtract(newp[(j+1)%numpoints],
  704. newp[(j)%numpoints], edgevec);
  705. CrossProduct(edgevec, planenormal, sepnormal);
  706. VectorNormalize(sepnormal);
  707. if (VectorLength(sepnormal) < 0.9)
  708. {
  709. //remove the point from the new winding
  710. for (n = j; n < numpoints-1; n++)
  711. {
  712. VectorCopy(newp[n+1], newp[n]);
  713. sides[n] = sides[n+1];
  714. } //end for
  715. numpoints--;
  716. j--;
  717. Log_Print("MergeWindings: degenerate edge on winding %f %f %f\n", sepnormal[0],
  718. sepnormal[1],
  719. sepnormal[2]);
  720. continue;
  721. } //end if
  722. dist = DotProduct(newp[(j)%numpoints], sepnormal);
  723. if (DotProduct(v, sepnormal) - dist < -0.1) sides[j] = SIDE_BACK;
  724. else sides[j] = SIDE_FRONT;
  725. } //end for
  726. //remove all unnecesary points
  727. for (j = 0; j < numpoints;)
  728. {
  729. if (sides[j] == SIDE_BACK
  730. && sides[(j+1)%numpoints] == SIDE_BACK)
  731. {
  732. //remove the point from the new winding
  733. for (n = (j+1)%numpoints; n < numpoints-1; n++)
  734. {
  735. VectorCopy(newp[n+1], newp[n]);
  736. sides[n] = sides[n+1];
  737. } //end for
  738. numpoints--;
  739. } //end if
  740. else
  741. {
  742. j++;
  743. } //end else
  744. } //end for
  745. //
  746. found = false;
  747. for (j = 0; j < numpoints; j++)
  748. {
  749. if (sides[j] == SIDE_FRONT
  750. && sides[(j+1)%numpoints] == SIDE_BACK)
  751. {
  752. if (found) Log_Print("Warning: MergeWindings: front to back found twice\n");
  753. found = true;
  754. } //end if
  755. } //end for
  756. //
  757. for (j = 0; j < numpoints; j++)
  758. {
  759. if (sides[j] == SIDE_FRONT
  760. && sides[(j+1)%numpoints] == SIDE_BACK)
  761. {
  762. insertafter = (j+1)%numpoints;
  763. //insert the new point after j+1
  764. for (n = numpoints-1; n > insertafter; n--)
  765. {
  766. VectorCopy(newp[n], newp[n+1]);
  767. } //end for
  768. numpoints++;
  769. VectorCopy(v, newp[(insertafter+1)%numpoints]);
  770. break;
  771. } //end if
  772. } //end for
  773. } //end for
  774. neww = AllocWinding(numpoints);
  775. neww->numpoints = numpoints;
  776. memcpy(neww->p, newp, numpoints * sizeof(vec3_t));
  777. RemoveColinearPoints(neww);
  778. return neww;
  779. } //end of the function MergeWindings
  780. //===========================================================================
  781. //
  782. // Parameter: -
  783. // Returns: -
  784. // Changes Globals: -
  785. //===========================================================================
  786. char *WindingErrorString(void)
  787. {
  788. return windingerror;
  789. } //end of the function WindingErrorString
  790. //===========================================================================
  791. //
  792. // Parameter: -
  793. // Returns: -
  794. // Changes Globals: -
  795. //===========================================================================
  796. int WindingError(winding_t *w)
  797. {
  798. int i, j;
  799. vec_t *p1, *p2;
  800. vec_t d, edgedist;
  801. vec3_t dir, edgenormal, facenormal;
  802. vec_t area;
  803. vec_t facedist;
  804. if (w->numpoints < 3)
  805. {
  806. sprintf(windingerror, "winding %i points", w->numpoints);
  807. return WE_NOTENOUGHPOINTS;
  808. } //end if
  809. area = WindingArea(w);
  810. if (area < 1)
  811. {
  812. sprintf(windingerror, "winding %f area", area);
  813. return WE_SMALLAREA;
  814. } //end if
  815. WindingPlane (w, facenormal, &facedist);
  816. for (i=0 ; i<w->numpoints ; i++)
  817. {
  818. p1 = w->p[i];
  819. for (j=0 ; j<3 ; j++)
  820. {
  821. if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
  822. {
  823. sprintf(windingerror, "winding point %d BUGUS_RANGE \'%f %f %f\'", j, p1[0], p1[1], p1[2]);
  824. return WE_POINTBOGUSRANGE;
  825. } //end if
  826. } //end for
  827. j = i+1 == w->numpoints ? 0 : i+1;
  828. // check the point is on the face plane
  829. d = DotProduct (p1, facenormal) - facedist;
  830. if (d < -ON_EPSILON || d > ON_EPSILON)
  831. {
  832. sprintf(windingerror, "winding point %d off plane", i);
  833. return WE_POINTOFFPLANE;
  834. } //end if
  835. // check the edge isnt degenerate
  836. p2 = w->p[j];
  837. VectorSubtract (p2, p1, dir);
  838. if (VectorLength (dir) < ON_EPSILON)
  839. {
  840. sprintf(windingerror, "winding degenerate edge %d-%d", i, j);
  841. return WE_DEGENERATEEDGE;
  842. } //end if
  843. CrossProduct (facenormal, dir, edgenormal);
  844. VectorNormalize (edgenormal);
  845. edgedist = DotProduct (p1, edgenormal);
  846. edgedist += ON_EPSILON;
  847. // all other points must be on front side
  848. for (j=0 ; j<w->numpoints ; j++)
  849. {
  850. if (j == i)
  851. continue;
  852. d = DotProduct (w->p[j], edgenormal);
  853. if (d > edgedist)
  854. {
  855. sprintf(windingerror, "winding non-convex");
  856. return WE_NONCONVEX;
  857. } //end if
  858. } //end for
  859. } //end for
  860. return WE_NONE;
  861. } //end of the function WindingError
  862. //===========================================================================
  863. //
  864. // Parameter: -
  865. // Returns: -
  866. // Changes Globals: -
  867. //===========================================================================
  868. void RemoveEqualPoints(winding_t *w, float epsilon)
  869. {
  870. int i, nump;
  871. vec3_t v;
  872. vec3_t p[MAX_POINTS_ON_WINDING];
  873. VectorCopy(w->p[0], p[0]);
  874. nump = 1;
  875. for (i = 1; i < w->numpoints; i++)
  876. {
  877. VectorSubtract(w->p[i], p[nump-1], v);
  878. if (VectorLength(v) > epsilon)
  879. {
  880. if (nump >= MAX_POINTS_ON_WINDING)
  881. Error("RemoveColinearPoints: MAX_POINTS_ON_WINDING");
  882. VectorCopy (w->p[i], p[nump]);
  883. nump++;
  884. } //end if
  885. } //end for
  886. if (nump == w->numpoints)
  887. return;
  888. w->numpoints = nump;
  889. memcpy(w->p, p, nump * sizeof(p[0]));
  890. } //end of the function RemoveEqualPoints
  891. //===========================================================================
  892. // adds the given point to a winding at the given spot
  893. // (for instance when spot is zero then the point is added at position zero)
  894. // the original winding is NOT freed
  895. //
  896. // Parameter: -
  897. // Returns: the new winding with the added point
  898. // Changes Globals: -
  899. //===========================================================================
  900. winding_t *AddWindingPoint(winding_t *w, vec3_t point, int spot)
  901. {
  902. int i, j;
  903. winding_t *neww;
  904. if (spot > w->numpoints)
  905. {
  906. Error("AddWindingPoint: num > w->numpoints");
  907. } //end if
  908. if (spot < 0)
  909. {
  910. Error("AddWindingPoint: num < 0");
  911. } //end if
  912. neww = AllocWinding(w->numpoints + 1);
  913. neww->numpoints = w->numpoints + 1;
  914. for (i = 0, j = 0; i < neww->numpoints; i++)
  915. {
  916. if (i == spot)
  917. {
  918. VectorCopy(point, neww->p[i]);
  919. } //end if
  920. else
  921. {
  922. VectorCopy(w->p[j], neww->p[i]);
  923. j++;
  924. } //end else
  925. } //end for
  926. return neww;
  927. } //end of the function AddWindingPoint
  928. //===========================================================================
  929. // the position where the new point should be added in the winding is
  930. // stored in *spot
  931. //
  932. // Parameter: -
  933. // Returns: true if the point is on the winding
  934. // Changes Globals: -
  935. //===========================================================================
  936. #define MELT_ON_EPSILON 0.2
  937. int PointOnWinding(winding_t *w, vec3_t normal, float dist, vec3_t point, int *spot)
  938. {
  939. int i, j;
  940. vec3_t v1, v2;
  941. vec3_t edgenormal, edgevec;
  942. float edgedist, dot;
  943. *spot = 0;
  944. //the point must be on the winding plane
  945. dot = DotProduct(point, normal) - dist;
  946. if (dot < -MELT_ON_EPSILON || dot > MELT_ON_EPSILON) return false;
  947. //
  948. for (i = 0; i < w->numpoints; i++)
  949. {
  950. j = (i+1) % w->numpoints;
  951. //get a plane orthogonal to the winding plane through the edge
  952. VectorSubtract(w->p[j], w->p[i], edgevec);
  953. CrossProduct(normal, edgevec, edgenormal);
  954. VectorNormalize(edgenormal);
  955. edgedist = DotProduct(edgenormal, w->p[i]);
  956. //point must be not too far from the plane
  957. dot = DotProduct(point, edgenormal) - edgedist;
  958. if (dot < -MELT_ON_EPSILON || dot > MELT_ON_EPSILON) continue;
  959. //vector from first point of winding to the point to test
  960. VectorSubtract(point, w->p[i], v1);
  961. //vector from second point of winding to the point to test
  962. VectorSubtract(point, w->p[j], v2);
  963. //if the length of the vector is not larger than 0.5 units then
  964. //the point is assumend to be the same as one of the winding points
  965. if (VectorNormalize(v1) < 0.5) return false;
  966. if (VectorNormalize(v2) < 0.5) return false;
  967. //point must be between the two winding points
  968. //(the two vectors must be directed towards each other, and on the
  969. //same straight line)
  970. if (DotProduct(v1, v2) < -0.99)
  971. {
  972. *spot = i + 1;
  973. return true;
  974. } //end if
  975. } //end for
  976. return false;
  977. } //end of the function PointOnWinding
  978. //===========================================================================
  979. //
  980. // Parameter: -
  981. // Returns: -
  982. // Changes Globals: -
  983. //===========================================================================
  984. int FindPlaneSeperatingWindings(winding_t *w1, winding_t *w2, vec3_t dir,
  985. vec3_t normal, float *dist)
  986. {
  987. int i, i2, j, j2, n;
  988. int sides1[3], sides2[3];
  989. float dist1, dist2, dot, diff;
  990. vec3_t normal1, normal2;
  991. vec3_t v1, v2;
  992. for (i = 0; i < w1->numpoints; i++)
  993. {
  994. i2 = (i+1) % w1->numpoints;
  995. //
  996. VectorSubtract(w1->p[i2], w1->p[i], v1);
  997. if (VectorLength(v1) < 0.1)
  998. {
  999. //Log_Write("FindPlaneSeperatingWindings: winding1 with degenerate edge\r\n");
  1000. continue;
  1001. } //end if
  1002. CrossProduct(v1, dir, normal1);
  1003. VectorNormalize(normal1);
  1004. dist1 = DotProduct(normal1, w1->p[i]);
  1005. //
  1006. for (j = 0; j < w2->numpoints; j++)
  1007. {
  1008. j2 = (j+1) % w2->numpoints;
  1009. //
  1010. VectorSubtract(w2->p[j2], w2->p[j], v2);
  1011. if (VectorLength(v2) < 0.1)
  1012. {
  1013. //Log_Write("FindPlaneSeperatingWindings: winding2 with degenerate edge\r\n");
  1014. continue;
  1015. } //end if
  1016. CrossProduct(v2, dir, normal2);
  1017. VectorNormalize(normal2);
  1018. dist2 = DotProduct(normal2, w2->p[j]);
  1019. //
  1020. diff = dist1 - dist2;
  1021. if (diff < -0.1 || diff > 0.1)
  1022. {
  1023. dist2 = -dist2;
  1024. VectorNegate(normal2, normal2);
  1025. diff = dist1 - dist2;
  1026. if (diff < -0.1 || diff > 0.1) continue;
  1027. } //end if
  1028. //check if the normal vectors are equal
  1029. for (n = 0; n < 3; n++)
  1030. {
  1031. diff = normal1[n] - normal2[n];
  1032. if (diff < -0.0001 || diff > 0.0001) break;
  1033. } //end for
  1034. if (n != 3) continue;
  1035. //check on which side of the seperating plane the points of
  1036. //the first winding are
  1037. sides1[0] = sides1[1] = sides1[2] = 0;
  1038. for (n = 0; n < w1->numpoints; n++)
  1039. {
  1040. dot = DotProduct(w1->p[n], normal1) - dist1;
  1041. if (dot > 0.1) sides1[0]++;
  1042. else if (dot < -0.1) sides1[1]++;
  1043. else sides1[2]++;
  1044. } //end for
  1045. //check on which side of the seperating plane the points of
  1046. //the second winding are
  1047. sides2[0] = sides2[1] = sides2[2] = 0;
  1048. for (n = 0; n < w2->numpoints; n++)
  1049. {
  1050. //used normal1 and dist1 (they are equal to normal2 and dist2)
  1051. dot = DotProduct(w2->p[n], normal1) - dist1;
  1052. if (dot > 0.1) sides2[0]++;
  1053. else if (dot < -0.1) sides2[1]++;
  1054. else sides2[2]++;
  1055. } //end for
  1056. //if the first winding has points at both sides
  1057. if (sides1[0] && sides1[1])
  1058. {
  1059. Log_Write("FindPlaneSeperatingWindings: winding1 non-convex\r\n");
  1060. continue;
  1061. } //end if
  1062. //if the second winding has points at both sides
  1063. if (sides2[0] && sides2[1])
  1064. {
  1065. Log_Write("FindPlaneSeperatingWindings: winding2 non-convex\r\n");
  1066. continue;
  1067. } //end if
  1068. //
  1069. if ((!sides1[0] && !sides1[1]) || (!sides2[0] && !sides2[1]))
  1070. {
  1071. //don't use one of the winding planes as the seperating plane
  1072. continue;
  1073. } //end if
  1074. //the windings must be at different sides of the seperating plane
  1075. if ((!sides1[0] && !sides2[1]) || (!sides1[1] && !sides2[0]))
  1076. {
  1077. VectorCopy(normal1, normal);
  1078. *dist = dist1;
  1079. return true;
  1080. } //end if
  1081. } //end for
  1082. } //end for
  1083. return false;
  1084. } //end of the function FindPlaneSeperatingWindings
  1085. //===========================================================================
  1086. //
  1087. // Parameter: -
  1088. // Returns: -
  1089. // Changes Globals: -
  1090. //===========================================================================
  1091. #define WCONVEX_EPSILON 0.2
  1092. int WindingsNonConvex(winding_t *w1, winding_t *w2,
  1093. vec3_t normal1, vec3_t normal2,
  1094. float dist1, float dist2)
  1095. {
  1096. int i;
  1097. if (!w1 || !w2) return false;
  1098. //check if one of the points of face1 is at the back of the plane of face2
  1099. for (i = 0; i < w1->numpoints; i++)
  1100. {
  1101. if (DotProduct(normal2, w1->p[i]) - dist2 > WCONVEX_EPSILON) return true;
  1102. } //end for
  1103. //check if one of the points of face2 is at the back of the plane of face1
  1104. for (i = 0; i < w2->numpoints; i++)
  1105. {
  1106. if (DotProduct(normal1, w2->p[i]) - dist1 > WCONVEX_EPSILON) return true;
  1107. } //end for
  1108. return false;
  1109. } //end of the function WindingsNonConvex
  1110. //===========================================================================
  1111. //
  1112. // Parameter: -
  1113. // Returns: -
  1114. // Changes Globals: -
  1115. //===========================================================================
  1116. /*
  1117. #define VERTEX_EPSILON 0.5
  1118. qboolean EqualVertexes(vec3_t v1, vec3_t v2)
  1119. {
  1120. float diff;
  1121. diff = v1[0] - v2[0];
  1122. if (diff > -VERTEX_EPSILON && diff < VERTEX_EPSILON)
  1123. {
  1124. diff = v1[1] - v2[1];
  1125. if (diff > -VERTEX_EPSILON && diff < VERTEX_EPSILON)
  1126. {
  1127. diff = v1[2] - v2[2];
  1128. if (diff > -VERTEX_EPSILON && diff < VERTEX_EPSILON)
  1129. {
  1130. return true;
  1131. } //end if
  1132. } //end if
  1133. } //end if
  1134. return false;
  1135. } //end of the function EqualVertexes
  1136. #define CONTINUOUS_EPSILON 0.001
  1137. winding_t *AAS_MergeWindings(winding_t *w1, winding_t *w2, vec3_t windingnormal)
  1138. {
  1139. int n, i, k;
  1140. vec3_t normal, delta;
  1141. winding_t *winding, *neww;
  1142. float dist, dot;
  1143. int p1, p2;
  1144. int points[2][64];
  1145. int numpoints[2] = {0, 0};
  1146. int newnumpoints;
  1147. int keep[2];
  1148. if (!FindPlaneSeperatingWindings(w1, w2, windingnormal, normal, &dist)) return NULL;
  1149. //for both windings
  1150. for (n = 0; n < 2; n++)
  1151. {
  1152. if (n == 0) winding = w1;
  1153. else winding = w2;
  1154. //get the points of the winding which are on the seperating plane
  1155. for (i = 0; i < winding->numpoints; i++)
  1156. {
  1157. dot = DotProduct(winding->p[i], normal) - dist;
  1158. if (dot > -ON_EPSILON && dot < ON_EPSILON)
  1159. {
  1160. //don't allow more than 64 points on the seperating plane
  1161. if (numpoints[n] >= 64) Error("AAS_MergeWindings: more than 64 points on seperating plane\n");
  1162. points[n][numpoints[n]++] = i;
  1163. } //end if
  1164. } //end for
  1165. //there must be at least two points of each winding on the seperating plane
  1166. if (numpoints[n] < 2) return NULL;
  1167. } //end for
  1168. //if the first point of winding1 (which is on the seperating plane) is unequal
  1169. //to the last point of winding2 (which is on the seperating plane)
  1170. if (!EqualVertexes(w1->p[points[0][0]], w2->p[points[1][numpoints[1]-1]]))
  1171. {
  1172. return NULL;
  1173. } //end if
  1174. //if the last point of winding1 (which is on the seperating plane) is unequal
  1175. //to the first point of winding2 (which is on the seperating plane)
  1176. if (!EqualVertexes(w1->p[points[0][numpoints[0]-1]], w2->p[points[1][0]]))
  1177. {
  1178. return NULL;
  1179. } //end if
  1180. //
  1181. // check slope of connected lines
  1182. // if the slopes are colinear, the point can be removed
  1183. //
  1184. //first point of winding1 which is on the seperating plane
  1185. p1 = points[0][0];
  1186. //point before p1
  1187. p2 = (p1 + w1->numpoints - 1) % w1->numpoints;
  1188. VectorSubtract(w1->p[p1], w1->p[p2], delta);
  1189. CrossProduct(windingnormal, delta, normal);
  1190. VectorNormalize(normal, normal);
  1191. //last point of winding2 which is on the seperating plane
  1192. p1 = points[1][numpoints[1]-1];
  1193. //point after p1
  1194. p2 = (p1 + 1) % w2->numpoints;
  1195. VectorSubtract(w2->p[p2], w2->p[p1], delta);
  1196. dot = DotProduct(delta, normal);
  1197. if (dot > CONTINUOUS_EPSILON) return NULL; //merging would create a non-convex polygon
  1198. keep[0] = (qboolean)(dot < -CONTINUOUS_EPSILON);
  1199. //first point of winding2 which is on the seperating plane
  1200. p1 = points[1][0];
  1201. //point before p1
  1202. p2 = (p1 + w2->numpoints - 1) % w2->numpoints;
  1203. VectorSubtract(w2->p[p1], w2->p[p2], delta);
  1204. CrossProduct(windingnormal, delta, normal);
  1205. VectorNormalize(normal, normal);
  1206. //last point of winding1 which is on the seperating plane
  1207. p1 = points[0][numpoints[0]-1];
  1208. //point after p1
  1209. p2 = (p1 + 1) % w1->numpoints;
  1210. VectorSubtract(w1->p[p2], w1->p[p1], delta);
  1211. dot = DotProduct(delta, normal);
  1212. if (dot > CONTINUOUS_EPSILON) return NULL; //merging would create a non-convex polygon
  1213. keep[1] = (qboolean)(dot < -CONTINUOUS_EPSILON);
  1214. //number of points on the new winding
  1215. newnumpoints = w1->numpoints - numpoints[0] + w2->numpoints - numpoints[1] + 2;
  1216. //allocate the winding
  1217. neww = AllocWinding(newnumpoints);
  1218. neww->numpoints = newnumpoints;
  1219. //copy all the points
  1220. k = 0;
  1221. //for both windings
  1222. for (n = 0; n < 2; n++)
  1223. {
  1224. if (n == 0) winding = w1;
  1225. else winding = w2;
  1226. //copy the points of the winding starting with the last point on the
  1227. //seperating plane and ending before the first point on the seperating plane
  1228. for (i = points[n][numpoints[n]-1]; i != points[n][0]; i = (i+1)%winding->numpoints)
  1229. {
  1230. if (k >= newnumpoints)
  1231. {
  1232. Log_Print("numpoints[0] = %d\n", numpoints[0]);
  1233. Log_Print("numpoints[1] = %d\n", numpoints[1]);
  1234. Error("AAS_MergeWindings: k = %d >= newnumpoints = %d\n", k, newnumpoints);
  1235. } //end if
  1236. VectorCopy(winding->p[i], neww->p[k]);
  1237. k++;
  1238. } //end for
  1239. } //end for
  1240. RemoveEqualPoints(neww);
  1241. if (!WindingIsOk(neww, 1))
  1242. {
  1243. Log_Print("AAS_MergeWindings: winding not ok after merging\n");
  1244. FreeWinding(neww);
  1245. return NULL;
  1246. } //end if
  1247. return neww;
  1248. } //end of the function AAS_MergeWindings*/
  1249. //#endif //ME