writebsp.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #include "bsp5.h"
  2. // WriteClipNodes_r
  3. // WriteClipNodes
  4. // WriteDrawLeaf
  5. // WriteFace
  6. // WriteDrawNodes_r
  7. // FreeDrawNodes_r
  8. // WriteDrawNodes
  9. // BeginBSPFile
  10. // FinishBSPFile
  11. #include <map>
  12. typedef std::map<int,int> PlaneMap;
  13. static PlaneMap gPlaneMap;
  14. static int gNumMappedPlanes;
  15. static dplane_t gMappedPlanes[MAX_MAP_PLANES];
  16. extern bool g_noopt;
  17. // =====================================================================================
  18. // WritePlane
  19. // hook for plane optimization
  20. // =====================================================================================
  21. static int WritePlane(int planenum)
  22. {
  23. planenum = planenum & (~1);
  24. if(g_noopt)
  25. {
  26. return planenum;
  27. }
  28. PlaneMap::iterator item = gPlaneMap.find(planenum);
  29. if(item != gPlaneMap.end())
  30. {
  31. return item->second;
  32. }
  33. //add plane to BSP
  34. hlassume(gNumMappedPlanes < MAX_MAP_PLANES, assume_MAX_MAP_PLANES);
  35. gMappedPlanes[gNumMappedPlanes] = g_dplanes[planenum];
  36. gPlaneMap.insert(PlaneMap::value_type(planenum,gNumMappedPlanes));
  37. return gNumMappedPlanes++;
  38. }
  39. // =====================================================================================
  40. // WriteClipNodes_r
  41. // =====================================================================================
  42. static int WriteClipNodes_r(node_t* node)
  43. {
  44. int i, c;
  45. dclipnode_t* cn;
  46. int num;
  47. if (node->planenum == -1)
  48. {
  49. num = node->contents;
  50. free(node->markfaces);
  51. free(node);
  52. return num;
  53. }
  54. hlassume(g_numclipnodes < MAX_MAP_CLIPNODES, assume_MAX_MAP_CLIPNODES);
  55. // emit a clipnode
  56. c = g_numclipnodes;
  57. cn = &g_dclipnodes[g_numclipnodes];
  58. g_numclipnodes++;
  59. if (node->planenum & 1)
  60. {
  61. Error("WriteClipNodes_r: odd planenum");
  62. }
  63. cn->planenum = WritePlane(node->planenum);
  64. for (i = 0; i < 2; i++)
  65. {
  66. cn->children[i] = WriteClipNodes_r(node->children[i]);
  67. }
  68. free(node);
  69. return c;
  70. }
  71. // =====================================================================================
  72. // WriteClipNodes
  73. // Called after the clipping hull is completed. Generates a disk format
  74. // representation and frees the original memory.
  75. // =====================================================================================
  76. void WriteClipNodes(node_t* nodes)
  77. {
  78. WriteClipNodes_r(nodes);
  79. }
  80. // =====================================================================================
  81. // WriteDrawLeaf
  82. // =====================================================================================
  83. static void WriteDrawLeaf(const node_t* const node)
  84. {
  85. face_t** fp;
  86. face_t* f;
  87. dleaf_t* leaf_p;
  88. // emit a leaf
  89. leaf_p = &g_dleafs[g_numleafs];
  90. g_numleafs++;
  91. leaf_p->contents = node->contents;
  92. //
  93. // write bounding box info
  94. //
  95. VectorCopy(node->mins, leaf_p->mins);
  96. VectorCopy(node->maxs, leaf_p->maxs);
  97. leaf_p->visofs = -1; // no vis info yet
  98. //
  99. // write the marksurfaces
  100. //
  101. leaf_p->firstmarksurface = g_nummarksurfaces;
  102. hlassume(node->markfaces != NULL, assume_EmptySolid);
  103. for (fp = node->markfaces; *fp; fp++)
  104. {
  105. // emit a marksurface
  106. f = *fp;
  107. do
  108. {
  109. g_dmarksurfaces[g_nummarksurfaces] = f->outputnumber;
  110. hlassume(g_nummarksurfaces < MAX_MAP_MARKSURFACES, assume_MAX_MAP_MARKSURFACES);
  111. g_nummarksurfaces++;
  112. f = f->original; // grab tjunction split faces
  113. }
  114. while (f);
  115. }
  116. free(node->markfaces);
  117. leaf_p->nummarksurfaces = g_nummarksurfaces - leaf_p->firstmarksurface;
  118. }
  119. // =====================================================================================
  120. // WriteFace
  121. // =====================================================================================
  122. static void WriteFace(face_t* f)
  123. {
  124. dface_t* df;
  125. int i;
  126. int e;
  127. if ( CheckFaceForHint(f)
  128. || CheckFaceForSkip(f)
  129. #ifdef ZHLT_NULLTEX
  130. || CheckFaceForNull(f) // AJM
  131. #endif
  132. // =====================================================================================
  133. //Cpt_Andrew - Env_Sky Check
  134. // =====================================================================================
  135. || CheckFaceForEnv_Sky(f)
  136. // =====================================================================================
  137. )
  138. {
  139. return;
  140. }
  141. f->outputnumber = g_numfaces;
  142. df = &g_dfaces[g_numfaces];
  143. hlassume(g_numfaces < MAX_MAP_FACES, assume_MAX_MAP_FACES);
  144. g_numfaces++;
  145. df->planenum = WritePlane(f->planenum);
  146. df->side = f->planenum & 1;
  147. df->firstedge = g_numsurfedges;
  148. df->numedges = f->numpoints;
  149. df->texinfo = f->texturenum;
  150. for (i = 0; i < f->numpoints; i++)
  151. {
  152. e = GetEdge(f->pts[i], f->pts[(i + 1) % f->numpoints], f);
  153. hlassume(g_numsurfedges < MAX_MAP_SURFEDGES, assume_MAX_MAP_SURFEDGES);
  154. g_dsurfedges[g_numsurfedges] = e;
  155. g_numsurfedges++;
  156. }
  157. }
  158. // =====================================================================================
  159. // WriteDrawNodes_r
  160. // =====================================================================================
  161. static void WriteDrawNodes_r(const node_t* const node)
  162. {
  163. dnode_t* n;
  164. int i;
  165. face_t* f;
  166. // emit a node
  167. hlassume(g_numnodes < MAX_MAP_NODES, assume_MAX_MAP_NODES);
  168. n = &g_dnodes[g_numnodes];
  169. g_numnodes++;
  170. VectorCopy(node->mins, n->mins);
  171. VectorCopy(node->maxs, n->maxs);
  172. if (node->planenum & 1)
  173. {
  174. Error("WriteDrawNodes_r: odd planenum");
  175. }
  176. n->planenum = WritePlane(node->planenum);
  177. n->firstface = g_numfaces;
  178. for (f = node->faces; f; f = f->next)
  179. {
  180. WriteFace(f);
  181. }
  182. n->numfaces = g_numfaces - n->firstface;
  183. //
  184. // recursively output the other nodes
  185. //
  186. for (i = 0; i < 2; i++)
  187. {
  188. if (node->children[i]->planenum == -1)
  189. {
  190. if (node->children[i]->contents == CONTENTS_SOLID)
  191. {
  192. n->children[i] = -1;
  193. }
  194. else
  195. {
  196. n->children[i] = -(g_numleafs + 1);
  197. WriteDrawLeaf(node->children[i]);
  198. }
  199. }
  200. else
  201. {
  202. n->children[i] = g_numnodes;
  203. WriteDrawNodes_r(node->children[i]);
  204. }
  205. }
  206. }
  207. // =====================================================================================
  208. // FreeDrawNodes_r
  209. // =====================================================================================
  210. static void FreeDrawNodes_r(node_t* node)
  211. {
  212. int i;
  213. face_t* f;
  214. face_t* next;
  215. for (i = 0; i < 2; i++)
  216. {
  217. if (node->children[i]->planenum != -1)
  218. {
  219. FreeDrawNodes_r(node->children[i]);
  220. }
  221. }
  222. //
  223. // free the faces on the node
  224. //
  225. for (f = node->faces; f; f = next)
  226. {
  227. next = f->next;
  228. FreeFace(f);
  229. }
  230. free(node);
  231. }
  232. // =====================================================================================
  233. // WriteDrawNodes
  234. // Called after a drawing hull is completed
  235. // Frees all nodes and faces
  236. // =====================================================================================
  237. void WriteDrawNodes(node_t* headnode)
  238. {
  239. if (headnode->contents < 0)
  240. {
  241. WriteDrawLeaf(headnode);
  242. }
  243. else
  244. {
  245. WriteDrawNodes_r(headnode);
  246. FreeDrawNodes_r(headnode);
  247. }
  248. }
  249. // =====================================================================================
  250. // BeginBSPFile
  251. // =====================================================================================
  252. void BeginBSPFile()
  253. {
  254. // these values may actually be initialized
  255. // if the file existed when loaded, so clear them explicitly
  256. gNumMappedPlanes = 0;
  257. gPlaneMap.clear();
  258. g_nummodels = 0;
  259. g_numfaces = 0;
  260. g_numnodes = 0;
  261. g_numclipnodes = 0;
  262. g_numvertexes = 0;
  263. g_nummarksurfaces = 0;
  264. g_numsurfedges = 0;
  265. // edge 0 is not used, because 0 can't be negated
  266. g_numedges = 1;
  267. // leaf 0 is common solid with no faces
  268. g_numleafs = 1;
  269. g_dleafs[0].contents = CONTENTS_SOLID;
  270. }
  271. // =====================================================================================
  272. // FinishBSPFile
  273. // =====================================================================================
  274. void FinishBSPFile()
  275. {
  276. Verbose("--- FinishBSPFile ---\n");
  277. if(!g_noopt)
  278. {
  279. for(int counter = 0; counter < gNumMappedPlanes; counter++)
  280. {
  281. g_dplanes[counter] = gMappedPlanes[counter];
  282. }
  283. g_numplanes = gNumMappedPlanes;
  284. }
  285. if (g_chart)
  286. {
  287. PrintBSPFileSizes();
  288. }
  289. WriteBSPFile(g_bspfilename);
  290. }