aas_facemerging.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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 "qbsp.h"
  19. #include "../botlib/aasfile.h"
  20. #include "aas_create.h"
  21. //===========================================================================
  22. //
  23. // Parameter: -
  24. // Returns: -
  25. // Changes Globals: -
  26. //===========================================================================
  27. int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
  28. {
  29. winding_t *neww;
  30. #ifdef DEBUG
  31. if (!face1->winding) Error("face1 %d without winding", face1->num);
  32. if (!face2->winding) Error("face2 %d without winding", face2->num);
  33. #endif //DEBUG
  34. //
  35. if (face1->faceflags != face2->faceflags) return false;
  36. //NOTE: if the front or back area is zero this doesn't mean there's
  37. //a real area. It means there's solid at that side of the face
  38. //if both faces have the same front area
  39. if (face1->frontarea == face2->frontarea)
  40. {
  41. //if both faces have the same back area
  42. if (face1->backarea == face2->backarea)
  43. {
  44. //if the faces are in the same plane
  45. if (face1->planenum == face2->planenum)
  46. {
  47. //if they have both a front and a back area (no solid on either side)
  48. if (face1->frontarea && face1->backarea)
  49. {
  50. neww = MergeWindings(face1->winding, face2->winding,
  51. mapplanes[face1->planenum].normal);
  52. } //end if
  53. else
  54. {
  55. //this function is to be found in l_poly.c
  56. neww = TryMergeWinding(face1->winding, face2->winding,
  57. mapplanes[face1->planenum].normal);
  58. } //end else
  59. if (neww)
  60. {
  61. FreeWinding(face1->winding);
  62. face1->winding = neww;
  63. if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
  64. if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
  65. AAS_FreeTmpFace(face2);
  66. return true;
  67. } //end if
  68. } //end if
  69. else if ((face1->planenum & ~1) == (face2->planenum & ~1))
  70. {
  71. Log_Write("face %d and %d, same front and back area but flipped planes\r\n",
  72. face1->num, face2->num);
  73. } //end if
  74. } //end if
  75. } //end if
  76. return false;
  77. } //end of the function AAS_TryMergeFaces
  78. /*
  79. int AAS_TryMergeFaces(tmp_face_t *face1, tmp_face_t *face2)
  80. {
  81. winding_t *neww;
  82. #ifdef DEBUG
  83. if (!face1->winding) Error("face1 %d without winding", face1->num);
  84. if (!face2->winding) Error("face2 %d without winding", face2->num);
  85. #endif //DEBUG
  86. //if the faces are in the same plane
  87. if ((face1->planenum & ~1) != (face2->planenum & ~1)) return false;
  88. // if (face1->planenum != face2->planenum) return false;
  89. //NOTE: if the front or back area is zero this doesn't mean there's
  90. //a real area. It means there's solid at that side of the face
  91. //if both faces have the same front area
  92. if (face1->frontarea != face2->frontarea ||
  93. face1->backarea != face2->backarea)
  94. {
  95. if (!face1->frontarea || !face1->backarea ||
  96. !face2->frontarea || !face2->backarea) return false;
  97. else if (face1->frontarea != face2->backarea ||
  98. face1->backarea != face2->frontarea) return false;
  99. // return false;
  100. } //end if
  101. //this function is to be found in l_poly.c
  102. neww = TryMergeWinding(face1->winding, face2->winding,
  103. mapplanes[face1->planenum].normal);
  104. if (!neww) return false;
  105. //
  106. FreeWinding(face1->winding);
  107. face1->winding = neww;
  108. //remove face2
  109. if (face2->frontarea)
  110. AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->frontarea]);
  111. if (face2->backarea)
  112. AAS_RemoveFaceFromArea(face2, &tmpaasworld.areas[face2->backarea]);
  113. return true;
  114. } //end of the function AAS_TryMergeFaces*/
  115. //===========================================================================
  116. //
  117. // Parameter: -
  118. // Returns: -
  119. // Changes Globals: -
  120. //===========================================================================
  121. void AAS_MergeAreaFaces(void)
  122. {
  123. int num_facemerges = 0;
  124. int side1, side2, restart;
  125. tmp_area_t *tmparea, *lasttmparea;
  126. tmp_face_t *face1, *face2;
  127. Log_Write("AAS_MergeAreaFaces\r\n");
  128. qprintf("%6d face merges", num_facemerges);
  129. //NOTE: first convex area is a dummy
  130. lasttmparea = tmpaasworld.areas;
  131. for (tmparea = tmpaasworld.areas; tmparea; tmparea = tmparea->l_next)
  132. {
  133. restart = false;
  134. //
  135. if (tmparea->invalid) continue;
  136. //
  137. for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
  138. {
  139. side1 = face1->frontarea != tmparea;
  140. for (face2 = face1->next[side1]; face2; face2 = face2->next[side2])
  141. {
  142. side2 = face2->frontarea != tmparea;
  143. //if succesfully merged
  144. if (AAS_TryMergeFaces(face1, face2))
  145. {
  146. //start over again after merging two faces
  147. restart = true;
  148. num_facemerges++;
  149. qprintf("\r%6d", num_facemerges);
  150. AAS_CheckArea(tmparea);
  151. break;
  152. } //end if
  153. } //end for
  154. if (restart)
  155. {
  156. tmparea = lasttmparea;
  157. break;
  158. } //end if
  159. } //end for
  160. lasttmparea = tmparea;
  161. } //end for
  162. qprintf("\n");
  163. Log_Write("%6d face merges\r\n", num_facemerges);
  164. } //end of the function AAS_MergeAreaFaces
  165. //===========================================================================
  166. //
  167. // Parameter: -
  168. // Returns: -
  169. // Changes Globals: -
  170. //===========================================================================
  171. void AAS_MergePlaneFaces(tmp_area_t *tmparea, int planenum)
  172. {
  173. tmp_face_t *face1, *face2, *nextface2;
  174. winding_t *neww;
  175. int side1, side2;
  176. for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
  177. {
  178. side1 = face1->frontarea != tmparea;
  179. if (face1->planenum != planenum) continue;
  180. //
  181. for (face2 = face1->next[side1]; face2; face2 = nextface2)
  182. {
  183. side2 = face2->frontarea != tmparea;
  184. nextface2 = face2->next[side2];
  185. //
  186. if ((face2->planenum & ~1) != (planenum & ~1)) continue;
  187. //
  188. neww = MergeWindings(face1->winding, face2->winding,
  189. mapplanes[face1->planenum].normal);
  190. FreeWinding(face1->winding);
  191. face1->winding = neww;
  192. if (face2->frontarea) AAS_RemoveFaceFromArea(face2, face2->frontarea);
  193. if (face2->backarea) AAS_RemoveFaceFromArea(face2, face2->backarea);
  194. AAS_FreeTmpFace(face2);
  195. //
  196. nextface2 = face1->next[side1];
  197. } //end for
  198. } //end for
  199. } //end of the function AAS_MergePlaneFaces
  200. //===========================================================================
  201. //
  202. // Parameter: -
  203. // Returns: -
  204. // Changes Globals: -
  205. //===========================================================================
  206. int AAS_CanMergePlaneFaces(tmp_area_t *tmparea, int planenum)
  207. {
  208. tmp_area_t *frontarea, *backarea;
  209. tmp_face_t *face1;
  210. int side1, merge, faceflags;
  211. frontarea = backarea = NULL;
  212. merge = false;
  213. for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
  214. {
  215. side1 = face1->frontarea != tmparea;
  216. if ((face1->planenum & ~1) != (planenum & ~1)) continue;
  217. if (!frontarea && !backarea)
  218. {
  219. frontarea = face1->frontarea;
  220. backarea = face1->backarea;
  221. faceflags = face1->faceflags;
  222. } //end if
  223. else
  224. {
  225. if (frontarea != face1->frontarea) return false;
  226. if (backarea != face1->backarea) return false;
  227. if (faceflags != face1->faceflags) return false;
  228. merge = true;
  229. } //end else
  230. } //end for
  231. return merge;
  232. } //end of the function AAS_CanMergePlaneFaces
  233. //===========================================================================
  234. //
  235. // Parameter: -
  236. // Returns: -
  237. // Changes Globals: -
  238. //===========================================================================
  239. void AAS_MergeAreaPlaneFaces(void)
  240. {
  241. int num_facemerges = 0;
  242. int side1;
  243. tmp_area_t *tmparea, *nexttmparea;
  244. tmp_face_t *face1;
  245. Log_Write("AAS_MergePlaneFaces\r\n");
  246. qprintf("%6d plane face merges", num_facemerges);
  247. //NOTE: first convex area is a dummy
  248. for (tmparea = tmpaasworld.areas; tmparea; tmparea = nexttmparea)
  249. {
  250. nexttmparea = tmparea->l_next;
  251. //
  252. if (tmparea->invalid) continue;
  253. //
  254. for (face1 = tmparea->tmpfaces; face1; face1 = face1->next[side1])
  255. {
  256. side1 = face1->frontarea != tmparea;
  257. //
  258. if (AAS_CanMergePlaneFaces(tmparea, face1->planenum))
  259. {
  260. AAS_MergePlaneFaces(tmparea, face1->planenum);
  261. nexttmparea = tmparea;
  262. num_facemerges++;
  263. qprintf("\r%6d", num_facemerges);
  264. break;
  265. } //end if
  266. } //end for
  267. } //end for
  268. qprintf("\n");
  269. Log_Write("%6d plane face merges\r\n", num_facemerges);
  270. } //end of the function AAS_MergeAreaPlaneFaces