PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/quakeforge/branches/release_0_5_2/tools/qfbsp/source/surfaces.c

#
C | 462 lines | 320 code | 84 blank | 58 comment | 74 complexity | 0b7ea9061031d52bdc566edd675653b8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, AGPL-3.0, AGPL-1.0, Unlicense
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. See file, 'COPYING', for details.
  15. */
  16. static const char rcsid[] =
  17. "$Id: surfaces.c 8629 2002-09-25 21:35:49Z taniwha $";
  18. #ifdef HAVE_CONFIG_H
  19. # include "config.h"
  20. #endif
  21. #ifdef HAVE_STRING_H
  22. # include "string.h"
  23. #endif
  24. #include <stdlib.h>
  25. #include "QF/sys.h"
  26. #include "bsp5.h"
  27. #include "options.h"
  28. /*
  29. a surface has all of the faces that could be drawn on a given plane
  30. the outside filling stage can remove some of them so a better bsp can be
  31. generated
  32. */
  33. surface_t newcopy_t;
  34. int subdivides;
  35. /*
  36. SubdivideFace
  37. If the face is >256 in either texture direction, carve a valid sized
  38. piece off and insert the remainder in the next link
  39. */
  40. void
  41. SubdivideFace (face_t *f, face_t **prevptr)
  42. {
  43. face_t *front, *back, *next;
  44. float mins, maxs;
  45. int axis, i;
  46. plane_t plane;
  47. texinfo_t *tex;
  48. vec_t v;
  49. // special (non-surface cached) faces don't need subdivision
  50. tex = &bsp->texinfo[f->texturenum];
  51. if (tex->flags & TEX_SPECIAL)
  52. return;
  53. for (axis = 0; axis < 2; axis++) {
  54. while (1) {
  55. mins = 9999;
  56. maxs = -9999;
  57. for (i = 0; i < f->numpoints; i++) {
  58. v = DotProduct (f->pts[i], tex->vecs[axis]);
  59. if (v < mins)
  60. mins = v;
  61. if (v > maxs)
  62. maxs = v;
  63. }
  64. if (maxs - mins <= options.subdivide_size)
  65. break;
  66. // split it
  67. subdivides++;
  68. VectorCopy (tex->vecs[axis], plane.normal);
  69. v = VectorLength (plane.normal);
  70. _VectorNormalize (plane.normal);
  71. plane.dist = (mins + options.subdivide_size - 16) / v;
  72. next = f->next;
  73. SplitFace (f, &plane, &front, &back);
  74. if (!front || !back)
  75. Sys_Error ("SubdivideFace: didn't split the polygon");
  76. *prevptr = back;
  77. back->next = front;
  78. front->next = next;
  79. f = back;
  80. }
  81. }
  82. }
  83. void
  84. SubdivideFaces (surface_t *surfhead)
  85. {
  86. face_t *f, **prevptr;
  87. surface_t *surf;
  88. qprintf ("--- SubdivideFaces ---\n");
  89. subdivides = 0;
  90. for (surf = surfhead; surf; surf = surf->next) {
  91. prevptr = &surf->faces;
  92. while (1) {
  93. f = *prevptr;
  94. if (!f)
  95. break;
  96. SubdivideFace (f, prevptr);
  97. f = *prevptr;
  98. prevptr = &f->next;
  99. }
  100. }
  101. qprintf ("%i faces added by subdivision\n", subdivides);
  102. }
  103. /*
  104. GatherNodeFaces
  105. Frees the current node tree and returns a new chain of the surfaces that
  106. have inside faces.
  107. */
  108. void
  109. GatherNodeFaces_r (node_t *node)
  110. {
  111. face_t *next, *f;
  112. if (node->planenum != PLANENUM_LEAF) {
  113. // decision node
  114. for (f = node->faces; f; f = next) {
  115. next = f->next;
  116. if (!f->numpoints) { // face was removed outside
  117. FreeFace (f);
  118. } else {
  119. f->next = validfaces[f->planenum];
  120. validfaces[f->planenum] = f;
  121. }
  122. }
  123. GatherNodeFaces_r (node->children[0]);
  124. GatherNodeFaces_r (node->children[1]);
  125. free (node);
  126. } else {
  127. // leaf node
  128. free (node);
  129. }
  130. }
  131. surface_t *
  132. GatherNodeFaces (node_t *headnode)
  133. {
  134. memset (validfaces, 0, sizeof (validfaces));
  135. GatherNodeFaces_r (headnode);
  136. return BuildSurfaces ();
  137. }
  138. //===========================================================================
  139. typedef struct hashvert_s {
  140. struct hashvert_s *next;
  141. vec3_t point;
  142. int num;
  143. int numplanes; // for corner determination
  144. int planenums[2];
  145. int numedges;
  146. } hashvert_t;
  147. #define POINT_EPSILON 0.01
  148. int c_cornerverts;
  149. hashvert_t hvertex[MAX_MAP_VERTS];
  150. hashvert_t *hvert_p;
  151. face_t *edgefaces[MAX_MAP_EDGES][2];
  152. int firstmodeledge = 1;
  153. int firstmodelface;
  154. //============================================================================
  155. #define NUM_HASH 4096
  156. hashvert_t *hashverts[NUM_HASH];
  157. static vec3_t hash_min, hash_scale;
  158. static void
  159. InitHash (void)
  160. {
  161. int i;
  162. int newsize[2];
  163. vec3_t size;
  164. vec_t scale, volume;
  165. memset (hashverts, 0, sizeof (hashverts));
  166. for (i = 0; i < 3; i++) {
  167. hash_min[i] = -8000;
  168. size[i] = 16000;
  169. }
  170. volume = size[0] * size[1];
  171. scale = sqrt (volume / NUM_HASH);
  172. newsize[0] = size[0] / scale;
  173. newsize[1] = size[1] / scale;
  174. hash_scale[0] = newsize[0] / size[0];
  175. hash_scale[1] = newsize[1] / size[1];
  176. hash_scale[2] = newsize[1];
  177. hvert_p = hvertex;
  178. }
  179. static unsigned
  180. HashVec (vec3_t vec)
  181. {
  182. unsigned h;
  183. h = hash_scale[0] * (vec[0] - hash_min[0]) * hash_scale[2]
  184. + hash_scale[1] * (vec[1] - hash_min[1]);
  185. if (h >= NUM_HASH)
  186. return NUM_HASH - 1;
  187. return h;
  188. }
  189. int
  190. GetVertex (vec3_t in, int planenum)
  191. {
  192. hashvert_t *hv;
  193. int h, i;
  194. vec3_t vert;
  195. dvertex_t v;
  196. for (i = 0; i < 3; i++) {
  197. if (fabs (in[i] - RINT (in[i])) < 0.001)
  198. vert[i] = RINT (in[i]);
  199. else
  200. vert[i] = in[i];
  201. }
  202. h = HashVec (vert);
  203. for (hv = hashverts[h]; hv; hv = hv->next) {
  204. if (fabs (hv->point[0] - vert[0]) < POINT_EPSILON
  205. && fabs (hv->point[1] - vert[1]) < POINT_EPSILON
  206. && fabs (hv->point[2] - vert[2]) < POINT_EPSILON) {
  207. hv->numedges++;
  208. if (hv->numplanes == 3)
  209. return hv->num; // already known to be a corner
  210. for (i = 0; i < hv->numplanes; i++)
  211. if (hv->planenums[i] == planenum)
  212. return hv->num; // already know this plane
  213. if (hv->numplanes == 2)
  214. c_cornerverts++;
  215. else
  216. hv->planenums[hv->numplanes] = planenum;
  217. hv->numplanes++;
  218. return hv->num;
  219. }
  220. }
  221. hv = hvert_p;
  222. hv->numedges = 1;
  223. hv->numplanes = 1;
  224. hv->planenums[0] = planenum;
  225. hv->next = hashverts[h];
  226. hashverts[h] = hv;
  227. VectorCopy (vert, hv->point);
  228. hv->num = bsp->numvertexes;
  229. if (hv->num == MAX_MAP_VERTS)
  230. Sys_Error ("GetVertex: MAX_MAP_VERTS");
  231. hvert_p++;
  232. // emit a vertex
  233. if (bsp->numvertexes == MAX_MAP_VERTS)
  234. Sys_Error ("numvertexes == MAX_MAP_VERTS");
  235. v.point[0] = vert[0];
  236. v.point[1] = vert[1];
  237. v.point[2] = vert[2];
  238. BSP_AddVertex (bsp, &v);
  239. return hv->num;
  240. }
  241. //===========================================================================
  242. int c_tryedges;
  243. /*
  244. GetEdge
  245. Don't allow four way edges
  246. */
  247. int
  248. GetEdge (vec3_t p1, vec3_t p2, face_t *f)
  249. {
  250. dedge_t edge;
  251. int v1, v2, i;
  252. if (!f->contents[0])
  253. Sys_Error ("GetEdge: 0 contents");
  254. c_tryedges++;
  255. v1 = GetVertex (p1, f->planenum);
  256. v2 = GetVertex (p2, f->planenum);
  257. for (i = firstmodeledge; i < bsp->numedges; i++) {
  258. if (v1 == bsp->edges[i].v[1] && v2 == bsp->edges[i].v[0]
  259. && !edgefaces[i][1]
  260. && edgefaces[i][0]->contents[0] == f->contents[0]) {
  261. edgefaces[i][1] = f;
  262. return -i;
  263. }
  264. }
  265. // emit an edge
  266. if (bsp->numedges == MAX_MAP_EDGES)
  267. Sys_Error ("numedges == MAX_MAP_EDGES");
  268. edge.v[0] = v1;
  269. edge.v[1] = v2;
  270. BSP_AddEdge (bsp, &edge);
  271. edgefaces[i][0] = f;
  272. return i;
  273. }
  274. void
  275. FindFaceEdges (face_t *face)
  276. {
  277. int i;
  278. face->outputnumber = -1;
  279. if (face->numpoints > MAXEDGES)
  280. Sys_Error ("WriteFace: %i points", face->numpoints);
  281. for (i = 0; i < face->numpoints; i++)
  282. face->edges[i] = GetEdge
  283. (face->pts[i], face->pts[(i + 1) % face->numpoints], face);
  284. }
  285. void
  286. CheckVertexes (void)
  287. {
  288. hashvert_t *hv;
  289. int cb, c0, c1, c2, c3;
  290. cb = c0 = c1 = c2 = c3 = 0;
  291. for (hv = hvertex; hv != hvert_p; hv++) {
  292. if (hv->numedges < 0 || hv->numedges & 1)
  293. cb++;
  294. else if (!hv->numedges)
  295. c0++;
  296. else if (hv->numedges == 2)
  297. c1++;
  298. else if (hv->numedges == 4)
  299. c2++;
  300. else
  301. c3++;
  302. }
  303. qprintf ("%5i bad edge points\n", cb);
  304. qprintf ("%5i 0 edge points\n", c0);
  305. qprintf ("%5i 2 edge points\n", c1);
  306. qprintf ("%5i 4 edge points\n", c2);
  307. qprintf ("%5i 6+ edge points\n", c3);
  308. }
  309. void
  310. CheckEdges (void)
  311. {
  312. dedge_t *edge;
  313. dvertex_t *d1, *d2;
  314. face_t *f1, *f2;
  315. int c_multitexture, c_nonconvex, i;
  316. c_nonconvex = c_multitexture = 0;
  317. // CheckVertexes ();
  318. for (i = 1; i < bsp->numedges; i++) {
  319. edge = &bsp->edges[i];
  320. if (!edgefaces[i][1]) {
  321. d1 = &bsp->vertexes[edge->v[0]];
  322. d2 = &bsp->vertexes[edge->v[1]];
  323. qprintf ("unshared edge at: (%8.2f, %8.2f, %8.2f) (%8.2f, %8.2f, "
  324. "%8.2f)\n", d1->point[0], d1->point[1], d1->point[2],
  325. d2->point[0], d2->point[1], d2->point[2]);
  326. } else {
  327. f1 = edgefaces[i][0];
  328. f2 = edgefaces[i][1];
  329. if (f1->planeside != f2->planeside)
  330. continue;
  331. if (f1->planenum != f2->planenum)
  332. continue;
  333. // on the same plane, might be discardable
  334. if (f1->texturenum == f2->texturenum) {
  335. hvertex[edge->v[0]].numedges -= 2;
  336. hvertex[edge->v[1]].numedges -= 2;
  337. c_nonconvex++;
  338. } else
  339. c_multitexture++;
  340. }
  341. }
  342. // qprintf ("%5i edges\n", i);
  343. // qprintf ("%5i c_nonconvex\n", c_nonconvex);
  344. // qprintf ("%5i c_multitexture\n", c_multitexture);
  345. // CheckVertexes ();
  346. }
  347. void
  348. MakeFaceEdges_r (node_t *node)
  349. {
  350. face_t *f;
  351. if (node->planenum == PLANENUM_LEAF)
  352. return;
  353. for (f = node->faces; f; f = f->next)
  354. FindFaceEdges (f);
  355. MakeFaceEdges_r (node->children[0]);
  356. MakeFaceEdges_r (node->children[1]);
  357. }
  358. void
  359. MakeFaceEdges (node_t *headnode)
  360. {
  361. qprintf ("----- MakeFaceEdges -----\n");
  362. InitHash ();
  363. c_tryedges = 0;
  364. c_cornerverts = 0;
  365. MakeFaceEdges_r (headnode);
  366. // CheckEdges ();
  367. GrowNodeRegions (headnode);
  368. firstmodeledge = bsp->numedges;
  369. firstmodelface = bsp->numfaces;
  370. }