bsp.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. #include "bsp.h"
  2. #include "atlas.h"
  3. #include "vbsp.h"
  4. #include "collection.h"
  5. #include "mempools.h"
  6. #include <stdint.h>
  7. #include <string.h> /* memset */
  8. #include <stdio.h> /* printf */
  9. #define STR1(m) #m
  10. #define STR(m) STR1(m)
  11. #define PRINT(fmt, ...) fprintf(stderr, __FILE__ ":" STR(__LINE__) ": " fmt "\n", __VA_ARGS__)
  12. #define R2S(r) bspLoadResultString(r)
  13. const char *bspLoadResultString(enum BSPLoadResult result) {
  14. switch(result) {
  15. case BSPLoadResult_Success: return "BSPLoadResult_Success";
  16. case BSPLoadResult_ErrorFileOpen: return "BSPLoadResult_ErrorFileOpen";
  17. case BSPLoadResult_ErrorFileFormat: return "BSPLoadResult_ErrorFileFormat";
  18. case BSPLoadResult_ErrorMemory: return "BSPLoadResult_ErrorMemory";
  19. case BSPLoadResult_ErrorTempMemory: return "BSPLoadResult_ErrorTempMemory";
  20. case BSPLoadResult_ErrorCapabilities: return "BSPLoadResult_ErrorCapabilities";
  21. default: return "UNKNOWN";
  22. }
  23. }
  24. struct AnyLump {
  25. const void *p;
  26. uint32_t n;
  27. };
  28. struct Lumps {
  29. uint32_t version;
  30. #define LIST_LUMPS \
  31. BSPLUMP(Entity, char, entities); \
  32. BSPLUMP(Plane, struct VBSPLumpPlane, planes); \
  33. BSPLUMP(TexData, struct VBSPLumpTexData, texdata); \
  34. BSPLUMP(Vertex, struct VBSPLumpVertex, vertices); \
  35. \
  36. BSPLUMP(Node, struct VBSPLumpNode, nodes); \
  37. BSPLUMP(TexInfo, struct VBSPLumpTexInfo, texinfos); \
  38. BSPLUMP(Face, struct VBSPLumpFace, faces); \
  39. BSPLUMP(LightMap, struct VBSPLumpLightMap, lightmaps); \
  40. \
  41. BSPLUMP(Leaf, struct VBSPLumpLeaf, leaves); \
  42. \
  43. BSPLUMP(Edge, struct VBSPLumpEdge, edges); \
  44. BSPLUMP(Surfedge, int32_t, surfedges); \
  45. BSPLUMP(Model, struct VBSPLumpModel, models); \
  46. \
  47. BSPLUMP(LeafFace, uint16_t, leaffaces); \
  48. \
  49. BSPLUMP(DispInfo, struct VBSPLumpDispInfo, dispinfos); \
  50. \
  51. BSPLUMP(DispVerts, struct VBSPLumpDispVert, dispverts); \
  52. \
  53. BSPLUMP(PakFile, uint8_t, pakfile); \
  54. \
  55. BSPLUMP(TexDataStringData, char, texdatastringdata); \
  56. BSPLUMP(TexDataStringTable, int32_t, texdatastringtable);
  57. #define BSPLUMP(name,type,field) struct{const type *p;uint32_t n;} field
  58. LIST_LUMPS
  59. #undef BSPLUMP
  60. };
  61. /* data needed for making lightmap atlas */
  62. struct VisibleFace {
  63. const struct VBSPLumpFace *face;
  64. /* read directly from lumps */
  65. unsigned int vertices;
  66. int indices;
  67. unsigned int width, height;
  68. const struct VBSPLumpLightMap *samples;
  69. const struct VBSPLumpTexInfo *texinfo;
  70. const struct VBSPLumpTexData *texdata;
  71. const struct VBSPLumpDispInfo *dispinfo;
  72. int dispquadvtx[4]; // filled only when displaced
  73. int dispstartvtx;
  74. const char *texture;
  75. /* filled as a result of atlas allocation */
  76. unsigned int atlas_x, atlas_y;
  77. };
  78. struct LoadModelContext {
  79. struct TemporaryPool *tmp;
  80. const struct Lumps *lumps;
  81. const struct VBSPLumpModel *model;
  82. struct VisibleFace *faces;
  83. unsigned int faces_count;
  84. unsigned int vertices;
  85. int indices;
  86. unsigned int max_draw_vertices;
  87. struct {
  88. unsigned int pixels;
  89. unsigned int max_width;
  90. unsigned int max_height;
  91. AGLTexture texture;
  92. } lightmap;
  93. unsigned int draws_to_alloc;
  94. };
  95. /* TODO change this to Ok|Skip|Inconsistent,
  96. * print verbose errors for inconsistent */
  97. enum FaceProbe {
  98. FaceProbe_Ok,
  99. FaceProbe_Skip,
  100. FaceProbe_OOB,
  101. FaceProbe_Inconsistent,
  102. FaceProbe_PlaneOOB,
  103. FaceProbe_TooFewEdges,
  104. FaceProbe_SurfedgesOOB,
  105. FaceProbe_OutOfMemory,
  106. FaceProbe_EdgesOOB,
  107. FaceProbe_InconsistentEdge,
  108. FaceProbe_UnalignedLightmap,
  109. FaceProbe_LightmapOOB,
  110. FaceProbe_TexInfoOOB,
  111. FaceProbe_TexDataOOB,
  112. FaceProbe_TexDataStringTableOOB,
  113. FaceProbe_TexDataStringDataOOB,
  114. FaceProbe_VertexOOB,
  115. FaceProbe_DispInfoOOB
  116. };
  117. static const char *faceProbeError(enum FaceProbe code) {
  118. switch(code) {
  119. case FaceProbe_Ok: return "FaceProbe_Ok"; break;
  120. case FaceProbe_Skip: return "FaceProbe_Skip"; break;
  121. case FaceProbe_OOB: return "FaceProbe_OOB"; break;
  122. case FaceProbe_PlaneOOB: return "FaceProbe_PlaneOOB"; break;
  123. case FaceProbe_TooFewEdges: return "FaceProbe_TooFewEdges"; break;
  124. case FaceProbe_SurfedgesOOB: return "FaceProbe_SurfedgesOOB"; break;
  125. case FaceProbe_OutOfMemory: return "FaceProbe_OutOfMemory"; break;
  126. case FaceProbe_EdgesOOB: return "FaceProbe_EdgesOOB"; break;
  127. case FaceProbe_InconsistentEdge: return "FaceProbe_InconsistentEdge"; break;
  128. case FaceProbe_UnalignedLightmap: return "FaceProbe_UnalignedLightmap"; break;
  129. case FaceProbe_LightmapOOB: return "FaceProbe_LightmapOOB"; break;
  130. case FaceProbe_TexInfoOOB: return "FaceProbe_TexInfoOOB"; break;
  131. case FaceProbe_TexDataOOB: return "FaceProbe_TexDataOOB"; break;
  132. case FaceProbe_TexDataStringTableOOB: return "FaceProbe_TexDataStringTableOOB"; break;
  133. case FaceProbe_TexDataStringDataOOB: return "FaceProbe_TexDataStringDataOOB"; break;
  134. case FaceProbe_VertexOOB: return "FaceProbe_VertexOOB"; break;
  135. case FaceProbe_DispInfoOOB: return "FaceProbe_DispInfoOOB"; break;
  136. case FaceProbe_Inconsistent: return "FaceProbe_Inconsistent"; break;
  137. }
  138. return "UNKNOWN";
  139. }
  140. static inline int shouldSkipFace(const struct VBSPLumpFace *face, const struct Lumps *lumps) {
  141. (void)(face); (void)(lumps);
  142. //const struct VBSPLumpTexInfo *tinfo = lumps->texinfos.p + face->texinfo;
  143. return /*(tinfo->flags & (VBSP_Surface_NoDraw | VBSP_Surface_NoLight)) ||*/ face->lightmap_offset == 0xffffffffu
  144. || face->lightmap_offset < 4;
  145. }
  146. static enum FaceProbe bspFaceProbe(struct LoadModelContext *ctx,
  147. struct VisibleFace *vis_face, unsigned index) {
  148. const struct Lumps * const lumps = ctx->lumps;
  149. if (index >= lumps->faces.n) return FaceProbe_OOB;
  150. const struct VBSPLumpFace * const face = lumps->faces.p + index;
  151. vis_face->face = face;
  152. if (face->texinfo < 0)
  153. return FaceProbe_Skip;
  154. if ((unsigned)face->texinfo > lumps->texinfos.n)
  155. return FaceProbe_TexInfoOOB;
  156. vis_face->texinfo = lumps->texinfos.p + face->texinfo;
  157. if (shouldSkipFace(face, lumps))
  158. return FaceProbe_Skip;
  159. if (vis_face->texinfo->texdata >= lumps->texdata.n)
  160. return FaceProbe_TexDataOOB;
  161. vis_face->texdata = lumps->texdata.p + vis_face->texinfo->texdata;
  162. if (vis_face->texdata->name_string_table_id >= lumps->texdatastringtable.n)
  163. return FaceProbe_TexDataStringTableOOB;
  164. const int32_t texdatastringdata_offset = lumps->texdatastringtable.p[vis_face->texdata->name_string_table_id];
  165. if (texdatastringdata_offset < 0 || (uint32_t)texdatastringdata_offset >= lumps->texdatastringdata.n)
  166. return FaceProbe_TexDataStringDataOOB;
  167. /* FIXME validate string: has \0 earlier than end */
  168. vis_face->texture = lumps->texdatastringdata.p + texdatastringdata_offset;
  169. //PRINT("F%u: texture %s", index, vis_face->texture);
  170. if (face->dispinfo >= 0) {
  171. if ((unsigned)face->dispinfo >= lumps->dispinfos.n)
  172. return FaceProbe_DispInfoOOB;
  173. vis_face->dispinfo = lumps->dispinfos.p + face->dispinfo;
  174. const int side = (1 << vis_face->dispinfo->power) + 1;
  175. if (face->num_edges != 4) {
  176. PRINT("Displaced face has invalid num_edges %d", face->num_edges);
  177. return FaceProbe_Inconsistent;
  178. }
  179. vis_face->vertices = side * side;
  180. vis_face->indices = (side - 1) * (side - 1) * 6; /* triangle list */
  181. if (vis_face->dispinfo->min_tess != 0)
  182. PRINT("Power: %d, min_tess: %d, vertices: %d",
  183. vis_face->dispinfo->power, vis_face->dispinfo->min_tess, vis_face->vertices);
  184. vis_face->dispstartvtx = 0;
  185. } else {
  186. vis_face->dispinfo = 0;
  187. vis_face->vertices = face->num_edges;
  188. vis_face->indices = (vis_face->vertices - 2) * 3;
  189. }
  190. /* Check for basic reference consistency */
  191. if (face->plane >= lumps->planes.n) return FaceProbe_PlaneOOB;
  192. if (face->num_edges < 3) return FaceProbe_TooFewEdges;
  193. if (face->first_edge >= lumps->surfedges.n || lumps->surfedges.n - face->first_edge < (unsigned)face->num_edges)
  194. return FaceProbe_SurfedgesOOB;
  195. if (face->lightmap_offset % sizeof(struct VBSPLumpLightMap) != 0) {
  196. PRINT("Error: face%u references lightmap at unaligned offset %u: %zu",
  197. index, face->lightmap_offset, face->lightmap_offset % sizeof(struct VBSPLumpLightMap));
  198. return FaceProbe_UnalignedLightmap;
  199. }
  200. const unsigned int lm_width = face->lightmap_size[0] + 1;
  201. const unsigned int lm_height = face->lightmap_size[1] + 1;
  202. const size_t lightmap_size = lm_width * lm_height;
  203. const size_t sample_offset = face->lightmap_offset / sizeof(struct VBSPLumpLightMap);
  204. if (sample_offset >= lumps->lightmaps.n || lumps->lightmaps.n - sample_offset < lightmap_size)
  205. return FaceProbe_LightmapOOB;
  206. const int32_t *surfedges = lumps->surfedges.p + face->first_edge;
  207. unsigned int prev_end = 0xffffffffu;
  208. for (int i = 0; i < face->num_edges; ++i) {
  209. uint32_t edge_index;
  210. int istart;
  211. if (surfedges[i] >= 0) {
  212. edge_index = surfedges[i];
  213. istart = 0;
  214. } else {
  215. edge_index = -surfedges[i];
  216. istart = 1;
  217. }
  218. if (edge_index >= lumps->edges.n) {
  219. PRINT("Error: face%u surfedge%u/%u references edge %u > max edges %u",
  220. index, i, face->num_edges, edge_index, lumps->edges.n);
  221. return FaceProbe_EdgesOOB;
  222. }
  223. const unsigned int vstart = lumps->edges.p[edge_index].v[istart];
  224. const unsigned int vend = lumps->edges.p[edge_index].v[1^istart];
  225. if (vis_face->dispinfo) {
  226. vis_face->dispquadvtx[i] = vstart;
  227. if (fabs(lumps->vertices.p[vstart].x - vis_face->dispinfo->start_pos.x) < .5f
  228. && fabs(lumps->vertices.p[vstart].y - vis_face->dispinfo->start_pos.y) < .5f
  229. && fabs(lumps->vertices.p[vstart].z - vis_face->dispinfo->start_pos.z) < .5f) {
  230. vis_face->dispstartvtx = i;
  231. }
  232. }
  233. if (vstart > lumps->vertices.n)
  234. return FaceProbe_VertexOOB;
  235. if (prev_end != 0xffffffffu && prev_end != vstart) {
  236. return FaceProbe_InconsistentEdge;
  237. }
  238. prev_end = vend;
  239. }
  240. vis_face->width = lm_width;
  241. vis_face->height = lm_height;
  242. vis_face->samples = lumps->lightmaps.p + sample_offset;
  243. if (lm_width > ctx->lightmap.max_width) ctx->lightmap.max_width = lm_width;
  244. if (lm_height > ctx->lightmap.max_height) ctx->lightmap.max_height = lm_height;
  245. ctx->lightmap.pixels += lightmap_size;
  246. ctx->vertices += vis_face->vertices;
  247. ctx->indices += vis_face->indices;
  248. ctx->faces_count++;
  249. return FaceProbe_Ok;
  250. }
  251. const unsigned int c_max_draw_vertices = 65536;
  252. static enum BSPLoadResult bspLoadModelCollectFaces(struct LoadModelContext *ctx) {
  253. ctx->faces = tmpGetCursor(ctx->tmp);
  254. unsigned int current_draw_vertices = 0;
  255. for (int i = 0; i < ctx->model->num_faces; ++i) {
  256. struct VisibleFace face;
  257. const enum FaceProbe result = bspFaceProbe(ctx, &face, ctx->model->first_face + i);
  258. if (result == FaceProbe_Ok) {
  259. if (current_draw_vertices + face.vertices > c_max_draw_vertices) {
  260. if (ctx->max_draw_vertices < current_draw_vertices)
  261. ctx->max_draw_vertices = current_draw_vertices;
  262. ++ctx->draws_to_alloc;
  263. current_draw_vertices = 0;
  264. }
  265. current_draw_vertices += face.vertices;
  266. struct VisibleFace *stored_face = tmpAdvance(ctx->tmp, sizeof(struct VisibleFace));
  267. if (!stored_face) {
  268. PRINT("Error: cannot allocate %zu temp bytes", sizeof(struct VisibleFace));
  269. return BSPLoadResult_ErrorTempMemory;
  270. }
  271. *stored_face = face;
  272. continue;
  273. }
  274. if (result != FaceProbe_Skip) {
  275. PRINT("Error: bspFaceProbe returned %s (%d)", faceProbeError(result), result);
  276. return BSPLoadResult_ErrorFileFormat;
  277. }
  278. }
  279. if (!ctx->faces_count) {
  280. PRINT("Error: no visible faces found%s", "");
  281. return BSPLoadResult_ErrorFileFormat; /* FIXME handle this */
  282. }
  283. if (ctx->max_draw_vertices < current_draw_vertices)
  284. ctx->max_draw_vertices = current_draw_vertices;
  285. ++ctx->draws_to_alloc;
  286. return BSPLoadResult_Success;
  287. }
  288. static enum BSPLoadResult bspLoadModelLightmaps(struct LoadModelContext *ctx) {
  289. /* TODO optional sort lightmaps */
  290. struct AtlasContext atlas_context;
  291. atlas_context.temp_storage.ptr = tmpGetCursor(ctx->tmp);
  292. atlas_context.temp_storage.size = tmpGetLeft(ctx->tmp);
  293. atlas_context.width = 16; /* TODO opengl caps */
  294. atlas_context.height = 16;
  295. atlas_context.rects = (void*)(&ctx->faces[0].width);
  296. atlas_context.rects_count = ctx->faces_count;
  297. atlas_context.rects_stride = sizeof(ctx->faces[0]);
  298. atlas_context.pos = (void*)(&ctx->faces[0].atlas_x);
  299. atlas_context.pos_stride = sizeof(ctx->faces[0]);
  300. while (atlas_context.width < ctx->lightmap.max_width) atlas_context.width <<= 1;
  301. while (atlas_context.height < ctx->lightmap.max_height) atlas_context.height <<= 1;
  302. while (atlas_context.width * atlas_context.height < ctx->lightmap.pixels)
  303. if (atlas_context.width < atlas_context.height) atlas_context.width <<= 1; else atlas_context.height <<= 1;
  304. for(;;) {
  305. const enum AtlasResult result = atlasCompute(&atlas_context);
  306. PRINT("atlas: %u %u %u", atlas_context.width, atlas_context.height, result);
  307. if (result == Atlas_Success)
  308. break;
  309. if (result == Atlas_ErrorInsufficientTemp)
  310. return BSPLoadResult_ErrorTempMemory;
  311. if (atlas_context.width < atlas_context.height) atlas_context.width <<= 1; else atlas_context.height <<= 1;
  312. if (atlas_context.width > 2048 || atlas_context.height > 2048) /* TODO limit based on GL driver caps */
  313. return BSPLoadResult_ErrorCapabilities;
  314. }
  315. /* Build an atlas texture based on calculated fragment positions */
  316. const size_t atlas_size = sizeof(uint16_t) * atlas_context.width * atlas_context.height;
  317. uint16_t *const pixels = tmpAdvance(ctx->tmp, atlas_size);
  318. if (!pixels) return BSPLoadResult_ErrorTempMemory;
  319. memset(pixels, 0x0f, atlas_size); /* TODO debug pattern */
  320. for (unsigned int i = 0; i < ctx->faces_count; ++i) {
  321. const struct VisibleFace *const face = ctx->faces + i;
  322. ASSERT(face->atlas_x + face->width <= atlas_context.width);
  323. ASSERT(face->atlas_y + face->height <= atlas_context.height);
  324. for (unsigned int y = 0; y < face->height; ++y) {
  325. for (unsigned int x = 0; x < face->width; ++x) {
  326. const struct VBSPLumpLightMap *const pixel = face->samples + x + y * face->width;
  327. unsigned int
  328. r = pixel->r,
  329. g = pixel->g,
  330. b = pixel->b;
  331. if (pixel->exponent >= 0) {
  332. r <<= pixel->exponent;
  333. g <<= pixel->exponent;
  334. b <<= pixel->exponent;
  335. } else {
  336. r >>= -pixel->exponent;
  337. g >>= -pixel->exponent;
  338. b >>= -pixel->exponent;
  339. }
  340. (r > 255) ? r = 255 : 0;
  341. (g > 255) ? g = 255 : 0;
  342. (b > 255) ? b = 255 : 0;
  343. pixels[face->atlas_x + x + (face->atlas_y + y) * atlas_context.width]
  344. = ((r&0xf8) << 8) | ((g&0xfc) << 3) | (b >> 3);
  345. } /* for x */
  346. } /* for y */
  347. } /* fot all visible faces */
  348. ctx->lightmap.texture = aGLTextureCreate();
  349. AGLTextureUploadData upload;
  350. upload.x = upload.y = 0;
  351. upload.width = atlas_context.width;
  352. upload.height = atlas_context.height;
  353. upload.format = AGLTF_U565_RGB;
  354. upload.pixels = pixels;
  355. aGLTextureUpload(&ctx->lightmap.texture, &upload);
  356. /* pixels buffer is not needed anymore */
  357. tmpReturnToPosition(ctx->tmp, pixels);
  358. return BSPLoadResult_Success;
  359. }
  360. inline static struct AVec3f aVec3fLumpVec(struct VBSPLumpVertex v) { return aVec3f(v.x, v.y, v.z); }
  361. inline static struct AVec3f aVec3fMix(struct AVec3f a, struct AVec3f b, float t) {
  362. return aVec3fAdd(a, aVec3fMulf(aVec3fSub(b, a), t));
  363. }
  364. inline static struct AVec2f aVec2fMulf(struct AVec2f v, float f) { return aVec2f(v.x * f, v.y * f); }
  365. inline static struct AVec2f aVec2fMix(struct AVec2f a, struct AVec2f b, float t) {
  366. return aVec2fAdd(a, aVec2fMulf(aVec2fSub(b, a), t));
  367. }
  368. inline static struct AVec4f aVec4fNeg(struct AVec4f v) { return aVec4f(-v.x, -v.y, -v.z, -v.w); }
  369. inline static float aVec3fLength2(struct AVec3f v) { return aVec3fDot(v,v); }
  370. #define MAKE_MAX(type) \
  371. inline static type type##Max(type a, type b) { return (a > b) ? a : b; }
  372. MAKE_MAX(float)
  373. inline static float aVec2fLength(struct AVec2f v) { return sqrtf(aVec2fDot(v, v)); }
  374. static int shouldSwapUV(struct AVec3f mapU, struct AVec3f mapV, const struct AVec3f *v) {
  375. float mappedU = 0.f, mappedV = 0.f;
  376. for (int i = 0; i < 4; ++i) {
  377. const float U = aVec3fDot(mapU, aVec3fSub(v[(i+1)%4], v[i]));
  378. if (U > mappedU) mappedU = U;
  379. const float V = aVec3fDot(mapV, aVec3fSub(v[(i+1)%4], v[i]));
  380. if (V > mappedV) mappedV = V;
  381. }
  382. const float dX1 = aVec3fLength2(aVec3fSub(v[3], v[0]));
  383. const float dX2 = aVec3fLength2(aVec3fSub(v[2], v[1]));
  384. const float dY1 = aVec3fLength2(aVec3fSub(v[1], v[0]));
  385. const float dY2 = aVec3fLength2(aVec3fSub(v[2], v[3]));
  386. const float maxDX = (dX1 > dX2) ? dX1 : dX2;
  387. const float maxDY = (dY1 > dY2) ? dY1 : dY2;
  388. //PRINT("mappedU=%f mappedV=%f maxDX=%f, maxDY=%f", mappedU, mappedV, maxDX, maxDY);
  389. return (mappedU > mappedV) != (maxDX > maxDY);
  390. }
  391. static enum BSPLoadResult bspLoadDisplacement(const struct LoadModelContext *ctx,
  392. const struct VisibleFace *face,
  393. struct BSPModelVertex *out_vertices, uint16_t *out_indices, int index_shift) {
  394. const int side = (1 << face->dispinfo->power) + 1;
  395. const struct VBSPLumpVertex *const vertices = ctx->lumps->vertices.p;
  396. const struct VBSPLumpTexInfo * const tinfo = face->texinfo;
  397. const struct VBSPLumpDispVert *const dispvert = ctx->lumps->dispverts.p + face->dispinfo->vtx_start;
  398. //if (face->dispstartvtx != 0) PRINT("dispstartvtx = %d", face->dispstartvtx);
  399. const struct AVec3f vec[4] = { /* bl, tl, tr, br */
  400. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 0)%4]]),
  401. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 1)%4]]),
  402. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 2)%4]]),
  403. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 3)%4]])};
  404. /*
  405. const struct AVec3f ovec[4] = {
  406. aVec3fAdd(vec[0], aVec3fMulf(aVec3f(dispvert[0].x, dispvert[0].y, dispvert[0].z), dispvert[0].dist)),
  407. aVec3fAdd(vec[1], aVec3fMulf(aVec3f(dispvert[side*(side-1)].x, dispvert[side*(side-1)].y, dispvert[side*(side-1)].z), dispvert[side*(side-1)].dist)),
  408. aVec3fAdd(vec[2], aVec3fMulf(aVec3f(dispvert[side*side-1].x, dispvert[side*side-1].y, dispvert[side*side-1].z), dispvert[side*side-1].dist)),
  409. aVec3fAdd(vec[3], aVec3fMulf(aVec3f(dispvert[side-1].x, dispvert[side-1].y, dispvert[side-1].z), dispvert[side-1].dist))};
  410. */
  411. const struct AVec3f lm_map_u = aVec3f(
  412. tinfo->lightmap_vecs[0][0], tinfo->lightmap_vecs[0][1], tinfo->lightmap_vecs[0][2]);
  413. const float luxels_per_unit = aVec3fLength(lm_map_u);
  414. float length_lm_u = luxels_per_unit * floatMax(
  415. aVec3fLength(aVec3fSub(vec[3], vec[0])),
  416. aVec3fLength(aVec3fSub(vec[2], vec[1])));
  417. float length_lm_v = luxels_per_unit * floatMax(
  418. aVec3fLength(aVec3fSub(vec[1], vec[0])),
  419. aVec3fLength(aVec3fSub(vec[2], vec[3])));
  420. const int swap = shouldSwapUV(
  421. aVec3f(tinfo->lightmap_vecs[0][0],tinfo->lightmap_vecs[0][1],tinfo->lightmap_vecs[0][2]),
  422. aVec3f(tinfo->lightmap_vecs[1][0],tinfo->lightmap_vecs[1][1],tinfo->lightmap_vecs[1][2]), vec);
  423. const struct AVec2f atlas_scale = aVec2f(1.f / ctx->lightmap.texture.width, 1.f / ctx->lightmap.texture.height);
  424. const struct AVec2f atlas_offset = aVec2f(
  425. .5f + face->atlas_x + tinfo->lightmap_vecs[0][3]*0 - 0*face->face->lightmap_min[0],
  426. .5f + face->atlas_y + tinfo->lightmap_vecs[1][3]*0 - 0*face->face->lightmap_min[1]);
  427. if (length_lm_u < 0. || length_lm_u >= face->width
  428. || length_lm_v < 0. || length_lm_v >= face->height) {
  429. PRINT("LM OOB: (%f, %f) (%d, %d)", length_lm_u, length_lm_v, face->width, face->height);
  430. if (length_lm_u >= face->width) length_lm_u = face->width - 1;
  431. if (length_lm_v >= face->height) length_lm_v = face->height - 1;
  432. }
  433. /*
  434. PRINT("%f %f %f %f",
  435. tinfo->lightmap_vecs[0][3] * atlas_scale.x, face->face->lightmap_min[0] * atlas_scale.x,
  436. tinfo->lightmap_vecs[1][3] * atlas_scale.y, face->face->lightmap_min[1] * atlas_scale.y);
  437. */
  438. const float div_side = 1.f / (side - 1);
  439. for (int y = 0; y < side; ++y) {
  440. const float ty = (float)y * div_side;
  441. const struct AVec3f vl = aVec3fMix(vec[0], vec[1], ty);
  442. const struct AVec3f vr = aVec3fMix(vec[3], vec[2], ty);
  443. for (int x = 0; x < side; ++x) {
  444. const float tx = (float)x * div_side;
  445. struct BSPModelVertex * const v = out_vertices + y * side + x;
  446. const struct VBSPLumpDispVert * const dv = dispvert + y * side + x;
  447. v->vertex = aVec3fMix(vl, vr, tx);
  448. v->lightmap_uv = aVec2f(tx * length_lm_u, ty * length_lm_v);
  449. v->vertex = aVec3fAdd(aVec3fMix(vl, vr, tx), aVec3fMulf(aVec3f(dv->x, dv->y, dv->z), dv->dist));
  450. if (v->lightmap_uv.x < 0 || v->lightmap_uv.y < 0 || v->lightmap_uv.x > face->width || v->lightmap_uv.y > face->height)
  451. PRINT("Error: DISP OOB LM F:V%u: x=%f y=%f z=%f tx=%f, ty=%f u=%f v=%f w=%d h=%d",
  452. x + y * side, v->vertex.x, v->vertex.y, v->vertex.z, tx, ty, v->lightmap_uv.x, v->lightmap_uv.y, face->width, face->height);
  453. v->lightmap_uv = aVec2fMul(aVec2fAdd(v->lightmap_uv, atlas_offset), atlas_scale);
  454. /* FIXME normal */
  455. v->normal = aVec3f(face->dispstartvtx/3.f, swap, dv->dist / 100.f);
  456. }
  457. }
  458. for (int y = 0; y < side - 1; ++y) {
  459. for (int x = 0; x < side - 1; ++x) {
  460. const int base = index_shift + y * side + x;
  461. *out_indices++ = base;
  462. *out_indices++ = base + side + 1;
  463. *out_indices++ = base + side;
  464. *out_indices++ = base;
  465. *out_indices++ = base + 1;
  466. *out_indices++ = base + side + 1;
  467. }
  468. }
  469. return BSPLoadResult_Success;
  470. }
  471. static enum BSPLoadResult bspLoadModelDraws(const struct LoadModelContext *ctx, struct MemoryPool *pool,
  472. struct BSPModel *model) {
  473. struct BSPModelVertex * const vertices_buffer
  474. = tmpAdvance(ctx->tmp, sizeof(struct BSPModelVertex) * ctx->max_draw_vertices);
  475. if (!vertices_buffer) return BSPLoadResult_ErrorTempMemory;
  476. /* each vertex after second in a face is a new triangle */
  477. uint16_t * const indices_buffer = tmpAdvance(ctx->tmp, sizeof(uint16_t) * ctx->indices);
  478. if (!indices_buffer) return BSPLoadResult_ErrorTempMemory;
  479. size_t vertex_pos = 0;
  480. size_t draw_indices_start = 0, indices_pos = 0;
  481. model->draws_count = ctx->draws_to_alloc;
  482. model->draws = POOL_ALLOC(pool, sizeof(struct BSPDraw) * ctx->draws_to_alloc);
  483. unsigned int idraw = 0;
  484. for (unsigned int iface = 0; iface < ctx->faces_count + 1; ++iface) {
  485. const struct VisibleFace *vis_face = ctx->faces + iface;
  486. if (iface == ctx->faces_count || vis_face->vertices + vertex_pos >= c_max_draw_vertices) {
  487. struct BSPDraw *draw = model->draws + idraw;
  488. memset(draw, 0, sizeof *draw);
  489. draw->count = indices_pos - draw_indices_start;
  490. draw->start = draw_indices_start;
  491. PRINT("Adding draw=%u start=%u count=%u", idraw, draw->start, draw->count);
  492. draw->vbo = aGLBufferCreate(AGLBT_Vertex);
  493. aGLBufferUpload(&draw->vbo, sizeof(struct BSPModelVertex) * vertex_pos, vertices_buffer);
  494. if (iface == ctx->faces_count) break;
  495. vertex_pos = 0;
  496. draw_indices_start = indices_pos;
  497. ++idraw;
  498. ASSERT(idraw < ctx->draws_to_alloc);
  499. }
  500. if (vis_face->dispinfo) {
  501. bspLoadDisplacement(ctx, vis_face, vertices_buffer + vertex_pos, indices_buffer + indices_pos, vertex_pos);
  502. vertex_pos += vis_face->vertices;
  503. indices_pos += vis_face->indices;
  504. } else {
  505. const struct VBSPLumpFace *face = vis_face->face;
  506. const struct VBSPLumpTexInfo * const tinfo = vis_face->texinfo;
  507. struct AVec3f normal;
  508. normal.x = ctx->lumps->planes.p[face->plane].x;
  509. normal.y = ctx->lumps->planes.p[face->plane].y;
  510. normal.z = ctx->lumps->planes.p[face->plane].z;
  511. if (face->side) normal = aVec3fNeg(normal);
  512. const struct AVec4f lm_map_u = aVec4f(
  513. tinfo->lightmap_vecs[0][0], tinfo->lightmap_vecs[0][1],
  514. tinfo->lightmap_vecs[0][2], tinfo->lightmap_vecs[0][3] - face->lightmap_min[0]);
  515. const struct AVec4f lm_map_v = aVec4f(
  516. tinfo->lightmap_vecs[1][0], tinfo->lightmap_vecs[1][1],
  517. tinfo->lightmap_vecs[1][2], tinfo->lightmap_vecs[1][3] - face->lightmap_min[1]);
  518. const int32_t * const surfedges = ctx->lumps->surfedges.p + face->first_edge;
  519. const size_t indices_count = (face->num_edges - 2) * 3;
  520. ASSERT(indices_count + indices_pos <= (unsigned)ctx->indices);
  521. ASSERT(vertex_pos + face->num_edges <= ctx->max_draw_vertices);
  522. uint16_t * const indices = indices_buffer + indices_pos;
  523. struct BSPModelVertex * const vertices = vertices_buffer + vertex_pos;
  524. for (int iedge = 0; iedge < face->num_edges; ++iedge) {
  525. const uint16_t vstart = (surfedges[iedge] >= 0)
  526. ? ctx->lumps->edges.p[surfedges[iedge]].v[0]
  527. : ctx->lumps->edges.p[-surfedges[iedge]].v[1];
  528. const struct VBSPLumpVertex * const lv = ctx->lumps->vertices.p + vstart;
  529. struct BSPModelVertex * const vertex = vertices + iedge;
  530. vertex->vertex = aVec3f(lv->x, lv->y, lv->z);
  531. vertex->normal = aVec3f(0.f, 0.f, 0.f);// FIXME normal;
  532. vertex->lightmap_uv = aVec2f(
  533. aVec4fDot(aVec4f3(vertex->vertex, 1.f), lm_map_u),
  534. aVec4fDot(aVec4f3(vertex->vertex, 1.f), lm_map_v));
  535. if (vertex->lightmap_uv.x < 0 || vertex->lightmap_uv.y < 0 || vertex->lightmap_uv.x > vis_face->width || vertex->lightmap_uv.y > vis_face->height)
  536. PRINT("Error: OOB LM F%u:V%u: x=%f y=%f z=%f u=%f v=%f w=%d h=%d", iface, iedge, lv->x, lv->y, lv->z, vertex->lightmap_uv.x, vertex->lightmap_uv.y, vis_face->width, vis_face->height);
  537. vertex->lightmap_uv.x = (vertex->lightmap_uv.x + vis_face->atlas_x + .5f) / ctx->lightmap.texture.width;
  538. vertex->lightmap_uv.y = (vertex->lightmap_uv.y + vis_face->atlas_y + .5f) / ctx->lightmap.texture.height;
  539. if (iedge > 1) {
  540. indices[(iedge-2)*3+0] = vertex_pos + 0;
  541. indices[(iedge-2)*3+1] = vertex_pos + iedge;
  542. indices[(iedge-2)*3+2] = vertex_pos + iedge - 1;
  543. }
  544. }
  545. indices_pos += indices_count;
  546. vertex_pos += face->num_edges;
  547. }
  548. }
  549. model->ibo = aGLBufferCreate(AGLBT_Index);
  550. aGLBufferUpload(&model->ibo, sizeof(uint16_t) * ctx->indices, indices_buffer);
  551. /*for (unsigned int i = 0; i < (indices_buffer_count<256?indices_buffer_count:256); ++i)
  552. PRINT("%u: %u", i, indices_buffer[i]);
  553. */
  554. return BSPLoadResult_Success;
  555. }
  556. static enum BSPLoadResult bspLoadModel(struct BSPModel *model, struct MemoryPool *pool, struct TemporaryPool *temp,
  557. const struct Lumps *lumps, unsigned index) {
  558. struct LoadModelContext context;
  559. memset(&context, 0, sizeof context);
  560. ASSERT(index < lumps->models.n);
  561. context.tmp = temp;
  562. context.lumps = lumps;
  563. context.model = lumps->models.p + index;
  564. /* Step 1. Collect lightmaps for all faces */
  565. enum BSPLoadResult result = bspLoadModelCollectFaces(&context);
  566. if (result != BSPLoadResult_Success) {
  567. PRINT("Error: bspLoadModelCollectFaces() => %s", R2S(result));
  568. return result;
  569. }
  570. /* Step 2. Build an atlas of all lightmaps */
  571. result = bspLoadModelLightmaps(&context);
  572. if (result != BSPLoadResult_Success) {
  573. PRINT("Error: bspLoadModelLightmaps() => %s", R2S(result));
  574. return result;
  575. }
  576. /* Step 3. Generate draw operations data */
  577. result = bspLoadModelDraws(&context, pool, model);
  578. if (result != BSPLoadResult_Success) {
  579. aGLTextureDestroy(&context.lightmap.texture);
  580. return result;
  581. }
  582. model->lightmap = context.lightmap.texture;
  583. model->aabb.min.x = context.model->min.x;
  584. model->aabb.min.y = context.model->min.y;
  585. model->aabb.min.z = context.model->min.z;
  586. model->aabb.max.x = context.model->max.x;
  587. model->aabb.max.y = context.model->max.y;
  588. model->aabb.max.z = context.model->max.z;
  589. return BSPLoadResult_Success;
  590. }
  591. static int lumpRead(const char *name, const struct VBSPLumpHeader *header,
  592. struct IFile *file, struct TemporaryPool *pool,
  593. struct AnyLump *out_ptr, uint32_t item_size) {
  594. out_ptr->p = tmpAdvance(pool, header->size);
  595. if (!out_ptr->p) {
  596. PRINT("Not enough temp memory to allocate storage for lump %s", name);
  597. return -1;
  598. }
  599. const size_t bytes = file->read(file, header->file_offset, header->size, (void*)out_ptr->p);
  600. if (bytes != header->size) {
  601. PRINT("Cannot read full lump %s, read only %zu bytes out of %u", name, bytes, header->size);
  602. return -1;
  603. }
  604. PRINT("Read lump %s, offset %u, size %u bytes / %u item = %u elements",
  605. name, header->file_offset, header->size, item_size, header->size / item_size);
  606. out_ptr->n = header->size / item_size;
  607. return 1;
  608. }
  609. enum BSPLoadResult bspLoadWorldspawn(struct BSPLoadModelContext context, const char *mapname) {
  610. enum BSPLoadResult result = BSPLoadResult_Success;
  611. struct IFile *file = 0;
  612. if (CollectionOpen_Success !=
  613. collectionChainOpen(context.collection, mapname, File_Map, &file)) {
  614. return BSPLoadResult_ErrorFileOpen;
  615. }
  616. void *tmp_cursor = tmpGetCursor(context.tmp);
  617. struct VBSPHeader vbsp_header;
  618. size_t bytes = file->read(file, 0, sizeof vbsp_header, &vbsp_header);
  619. if (bytes < sizeof(vbsp_header)) {
  620. PRINT("Size is too small: %zu <= %zu", bytes, sizeof(struct VBSPHeader));
  621. result = BSPLoadResult_ErrorFileFormat;
  622. goto exit;
  623. }
  624. if (vbsp_header.ident[0] != 'V' || vbsp_header.ident[1] != 'B' ||
  625. vbsp_header.ident[2] != 'S' || vbsp_header.ident[3] != 'P') {
  626. PRINT("Error: invalid ident => %c%c%c%c != VBSP",
  627. vbsp_header.ident[0], vbsp_header.ident[1], vbsp_header.ident[2], vbsp_header.ident[3]);
  628. result = BSPLoadResult_ErrorFileFormat;
  629. goto exit;
  630. }
  631. if (vbsp_header.version != 19 && vbsp_header.version != 20) {
  632. PRINT("Error: invalid version: %d != 19 or 20", vbsp_header.version);
  633. result = BSPLoadResult_ErrorFileFormat;
  634. goto exit;
  635. }
  636. PRINT("VBSP version %u opened", vbsp_header.version);
  637. struct Lumps lumps;
  638. lumps.version = vbsp_header.version;
  639. #define BSPLUMP(name, type, field) \
  640. if (1 != lumpRead(#name, vbsp_header.lump_headers + VBSP_Lump_##name, file, context.tmp, \
  641. (struct AnyLump*)&lumps.field, sizeof(type))) { \
  642. result = BSPLoadResult_ErrorFileFormat; \
  643. goto exit; \
  644. }
  645. LIST_LUMPS
  646. #undef BSPLUMP
  647. result = bspLoadModel(context.model, context.pool, context.tmp, &lumps, 0);
  648. if (result != BSPLoadResult_Success)
  649. PRINT("Error: bspLoadModel() => %s", R2S(result));
  650. exit:
  651. tmpReturnToPosition(context.tmp, tmp_cursor);
  652. if (file) file->close(file);
  653. return result;
  654. }