bsp.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939
  1. #include "bsp.h"
  2. #include "atlas.h"
  3. #include "vbsp.h"
  4. #include "collection.h"
  5. #include "mempools.h"
  6. #include "vmfparser.h"
  7. #include "common.h"
  8. // DEBUG
  9. #include "texture.h"
  10. #define R2S(r) bspLoadResultString(r)
  11. const char *bspLoadResultString(enum BSPLoadResult result) {
  12. switch(result) {
  13. case BSPLoadResult_Success: return "BSPLoadResult_Success";
  14. case BSPLoadResult_ErrorFileOpen: return "BSPLoadResult_ErrorFileOpen";
  15. case BSPLoadResult_ErrorFileFormat: return "BSPLoadResult_ErrorFileFormat";
  16. case BSPLoadResult_ErrorMemory: return "BSPLoadResult_ErrorMemory";
  17. case BSPLoadResult_ErrorTempMemory: return "BSPLoadResult_ErrorTempMemory";
  18. case BSPLoadResult_ErrorCapabilities: return "BSPLoadResult_ErrorCapabilities";
  19. default: return "UNKNOWN";
  20. }
  21. }
  22. struct AnyLump {
  23. const void *p;
  24. uint32_t n;
  25. };
  26. struct Lumps {
  27. uint32_t version;
  28. #define LIST_LUMPS \
  29. BSPLUMP(Entity, char, entities); \
  30. BSPLUMP(Plane, struct VBSPLumpPlane, planes); \
  31. BSPLUMP(TexData, struct VBSPLumpTexData, texdata); \
  32. BSPLUMP(Vertex, struct VBSPLumpVertex, vertices); \
  33. \
  34. BSPLUMP(Node, struct VBSPLumpNode, nodes); \
  35. BSPLUMP(TexInfo, struct VBSPLumpTexInfo, texinfos); \
  36. BSPLUMP(Face, struct VBSPLumpFace, faces); \
  37. BSPLUMP(LightMap, struct VBSPLumpLightMap, lightmaps); \
  38. \
  39. BSPLUMP(Leaf, struct VBSPLumpLeaf, leaves); \
  40. \
  41. BSPLUMP(Edge, struct VBSPLumpEdge, edges); \
  42. BSPLUMP(Surfedge, int32_t, surfedges); \
  43. BSPLUMP(Model, struct VBSPLumpModel, models); \
  44. \
  45. BSPLUMP(LeafFace, uint16_t, leaffaces); \
  46. \
  47. BSPLUMP(DispInfo, struct VBSPLumpDispInfo, dispinfos); \
  48. \
  49. BSPLUMP(DispVerts, struct VBSPLumpDispVert, dispverts); \
  50. \
  51. BSPLUMP(PakFile, uint8_t, pakfile); \
  52. \
  53. BSPLUMP(TexDataStringData, char, texdatastringdata); \
  54. BSPLUMP(TexDataStringTable, int32_t, texdatastringtable); \
  55. \
  56. BSPLUMP(FaceHDR, struct VBSPLumpFace, faces_hdr); \
  57. \
  58. BSPLUMP(LightMapHDR, struct VBSPLumpLightMap, lightmaps_hdr); \
  59. #define BSPLUMP(name,type,field) struct{const type *p;uint32_t n;} field
  60. LIST_LUMPS
  61. #undef BSPLUMP
  62. };
  63. /* data needed for making lightmap atlas */
  64. struct Face {
  65. const struct VBSPLumpFace *vface;
  66. /* read directly from lumps */
  67. int vertices;
  68. int indices;
  69. int width, height;
  70. const struct VBSPLumpLightMap *samples;
  71. const struct VBSPLumpTexInfo *texinfo;
  72. const struct VBSPLumpTexData *texdata;
  73. const struct VBSPLumpDispInfo *dispinfo;
  74. int dispquadvtx[4]; // filled only when displaced
  75. int dispstartvtx;
  76. const struct Material *material;
  77. /* filled as a result of atlas allocation */
  78. int atlas_x, atlas_y;
  79. };
  80. struct LoadModelContext {
  81. struct Stack *tmp;
  82. struct ICollection *collection;
  83. const struct Lumps *lumps;
  84. const struct VBSPLumpModel *model;
  85. struct Face *faces;
  86. int faces_count;
  87. int vertices;
  88. int indices;
  89. int max_draw_vertices;
  90. struct {
  91. int pixels;
  92. int max_width;
  93. int max_height;
  94. RTexture texture;
  95. } lightmap;
  96. };
  97. /* TODO change this to Ok|Skip|Inconsistent,
  98. * print verbose errors for inconsistent */
  99. enum FacePreload {
  100. FacePreload_Ok,
  101. FacePreload_Skip,
  102. FacePreload_Inconsistent
  103. };
  104. static inline int shouldSkipFace(const struct VBSPLumpFace *face, const struct Lumps *lumps) {
  105. (void)(face); (void)(lumps);
  106. //const struct VBSPLumpTexInfo *tinfo = lumps->texinfos.p + face->texinfo;
  107. return /*(tinfo->flags & (VBSP_Surface_NoDraw | VBSP_Surface_NoLight)) ||*/ face->lightmap_offset == 0xffffffffu
  108. || face->lightmap_offset < 4;
  109. }
  110. static enum FacePreload bspFacePreloadMetadata(struct LoadModelContext *ctx,
  111. struct Face *face, unsigned index) {
  112. const struct Lumps * const lumps = ctx->lumps;
  113. #define FACE_CHECK(cond) \
  114. if (!(cond)) { PRINTF("F%d: check failed: (%s)", index, #cond); return FacePreload_Inconsistent; }
  115. FACE_CHECK(index < lumps->faces.n);
  116. const struct VBSPLumpFace * const vface = lumps->faces.p + index;
  117. face->vface = vface;
  118. if (vface->texinfo < 0) return FacePreload_Skip;
  119. FACE_CHECK((unsigned)vface->texinfo < lumps->texinfos.n);
  120. face->texinfo = lumps->texinfos.p + vface->texinfo;
  121. if (shouldSkipFace(vface, lumps)) return FacePreload_Skip;
  122. FACE_CHECK(face->texinfo->texdata < lumps->texdata.n);
  123. face->texdata = lumps->texdata.p + face->texinfo->texdata;
  124. FACE_CHECK(face->texdata->name_string_table_id < lumps->texdatastringtable.n);
  125. const int32_t texdatastringdata_offset = lumps->texdatastringtable.p[face->texdata->name_string_table_id];
  126. FACE_CHECK(texdatastringdata_offset >= 0 && (uint32_t)texdatastringdata_offset < lumps->texdatastringdata.n);
  127. /* FIXME validate string: has \0 earlier than end */
  128. const char *texture = lumps->texdatastringdata.p + texdatastringdata_offset;
  129. //PRINTF("F%u: texture %s", index, face->texture);
  130. face->material = materialGet(texture, ctx->collection, ctx->tmp);
  131. if (!face->material)
  132. return FacePreload_Skip;
  133. if (vface->dispinfo >= 0) {
  134. FACE_CHECK((unsigned)vface->dispinfo < lumps->dispinfos.n);
  135. face->dispinfo = lumps->dispinfos.p + vface->dispinfo;
  136. const int side = (1 << face->dispinfo->power) + 1;
  137. FACE_CHECK(vface->num_edges == 4);
  138. face->vertices = side * side;
  139. face->indices = (side - 1) * (side - 1) * 6; /* triangle list */
  140. if (face->dispinfo->min_tess != 0)
  141. PRINTF("Power: %d, min_tess: %d, vertices: %d",
  142. face->dispinfo->power, face->dispinfo->min_tess, face->vertices);
  143. face->dispstartvtx = 0;
  144. } else {
  145. face->dispinfo = 0;
  146. face->vertices = vface->num_edges;
  147. face->indices = (face->vertices - 2) * 3;
  148. }
  149. /* Check for basic reference consistency */
  150. FACE_CHECK(vface->plane < lumps->planes.n);
  151. FACE_CHECK(vface->num_edges > 2);
  152. FACE_CHECK(vface->first_edge < lumps->surfedges.n && lumps->surfedges.n - vface->first_edge >= (unsigned)vface->num_edges);
  153. FACE_CHECK(vface->lightmap_offset % sizeof(struct VBSPLumpLightMap) == 0);
  154. const int lm_width = vface->lightmap_size[0] + 1;
  155. const int lm_height = vface->lightmap_size[1] + 1;
  156. const unsigned lightmap_size = lm_width * lm_height;
  157. const unsigned sample_offset = vface->lightmap_offset / sizeof(struct VBSPLumpLightMap);
  158. FACE_CHECK(sample_offset < lumps->lightmaps.n && lumps->lightmaps.n - sample_offset >= lightmap_size);
  159. const int32_t *surfedges = lumps->surfedges.p + vface->first_edge;
  160. unsigned int prev_end = 0xffffffffu;
  161. for (int i = 0; i < vface->num_edges; ++i) {
  162. uint32_t edge_index;
  163. int istart;
  164. if (surfedges[i] >= 0) {
  165. edge_index = surfedges[i];
  166. istart = 0;
  167. } else {
  168. edge_index = -surfedges[i];
  169. istart = 1;
  170. }
  171. if (edge_index >= lumps->edges.n) {
  172. PRINTF("Error: face%u surfedge%u/%u references edge %u > max edges %u",
  173. index, i, vface->num_edges, edge_index, lumps->edges.n);
  174. return FacePreload_Inconsistent;
  175. }
  176. const unsigned int vstart = lumps->edges.p[edge_index].v[istart];
  177. const unsigned int vend = lumps->edges.p[edge_index].v[1^istart];
  178. if (face->dispinfo) {
  179. face->dispquadvtx[i] = vstart;
  180. if (fabs(lumps->vertices.p[vstart].x - face->dispinfo->start_pos.x) < .5f
  181. && fabs(lumps->vertices.p[vstart].y - face->dispinfo->start_pos.y) < .5f
  182. && fabs(lumps->vertices.p[vstart].z - face->dispinfo->start_pos.z) < .5f) {
  183. face->dispstartvtx = i;
  184. }
  185. }
  186. FACE_CHECK(vstart < lumps->vertices.n);
  187. FACE_CHECK(prev_end == 0xffffffffu || prev_end == vstart);
  188. prev_end = vend;
  189. }
  190. face->width = lm_width;
  191. face->height = lm_height;
  192. face->samples = lumps->lightmaps.p + sample_offset;
  193. if (lm_width > ctx->lightmap.max_width) ctx->lightmap.max_width = lm_width;
  194. if (lm_height > ctx->lightmap.max_height) ctx->lightmap.max_height = lm_height;
  195. ctx->lightmap.pixels += lightmap_size;
  196. ctx->vertices += face->vertices;
  197. ctx->indices += face->indices;
  198. ctx->faces_count++;
  199. return FacePreload_Ok;
  200. }
  201. const int c_max_draw_vertices = 65536;
  202. /*
  203. static float clamp(float x, float min, float max) {
  204. return x < min ? min : (x > max ? max : x);
  205. }
  206. */
  207. static int scaleLightmapColor(int c, int exp) {
  208. #if 0
  209. c = 255.f * pow(c * powf(2.f, exp) / 255.f, 1.0f / 2.2f) * .5f;
  210. #elif 0
  211. c = 255.f * sqrtf(c * powf(2.f, exp) / 255.f) * .5f;
  212. #elif 1
  213. c = (int)(255.f * sqrtf(c / 255.f) * powf(2.f, exp / 2.f - 1.f));
  214. #else
  215. c = sqrtf(c / 255.f) * 255.f;
  216. exp = exp / 2 - 1;
  217. c = (exp >= 0) ? c << exp : c >> -exp;
  218. #endif
  219. return c < 255 ? c : 255;
  220. }
  221. static enum BSPLoadResult bspLoadModelPreloadFaces(struct LoadModelContext *ctx) {
  222. ctx->faces = stackGetCursor(ctx->tmp);
  223. int current_draw_vertices = 0;
  224. for (int i = 0; i < ctx->model->num_faces; ++i) {
  225. struct Face face;
  226. const enum FacePreload result = bspFacePreloadMetadata(ctx, &face, ctx->model->first_face + i);
  227. if (result == FacePreload_Ok) {
  228. current_draw_vertices += face.vertices;
  229. struct Face *stored_face = stackAlloc(ctx->tmp, sizeof(struct Face));
  230. if (!stored_face) {
  231. PRINTF("Error: cannot allocate %zu temp bytes", sizeof(struct Face));
  232. return BSPLoadResult_ErrorTempMemory;
  233. }
  234. *stored_face = face;
  235. continue;
  236. }
  237. if (result != FacePreload_Skip)
  238. return BSPLoadResult_ErrorFileFormat;
  239. }
  240. if (!ctx->faces_count) {
  241. PRINTF("Error: no visible faces found%s", "");
  242. return BSPLoadResult_ErrorFileFormat; /* FIXME handle this */
  243. }
  244. if (ctx->max_draw_vertices < current_draw_vertices)
  245. ctx->max_draw_vertices = current_draw_vertices;
  246. return BSPLoadResult_Success;
  247. }
  248. static enum BSPLoadResult bspLoadModelLightmaps(struct LoadModelContext *ctx) {
  249. /* TODO optional sort lightmaps */
  250. struct AtlasContext atlas_context;
  251. atlas_context.temp_storage.ptr = stackGetCursor(ctx->tmp);
  252. atlas_context.temp_storage.size = stackGetFree(ctx->tmp);
  253. atlas_context.width = 16; /* TODO opengl caps */
  254. atlas_context.height = 16;
  255. atlas_context.rects = (void*)(&ctx->faces[0].width);
  256. atlas_context.rects_count = ctx->faces_count;
  257. atlas_context.rects_stride = sizeof(ctx->faces[0]);
  258. atlas_context.pos = (void*)(&ctx->faces[0].atlas_x);
  259. atlas_context.pos_stride = sizeof(ctx->faces[0]);
  260. while (atlas_context.width < (unsigned)ctx->lightmap.max_width) atlas_context.width <<= 1;
  261. while (atlas_context.height < (unsigned)ctx->lightmap.max_height) atlas_context.height <<= 1;
  262. while (atlas_context.width * atlas_context.height < (unsigned)ctx->lightmap.pixels)
  263. if (atlas_context.width < atlas_context.height) atlas_context.width <<= 1; else atlas_context.height <<= 1;
  264. for(;;) {
  265. const enum AtlasResult result = atlasCompute(&atlas_context);
  266. PRINTF("atlas: %u %u %u", atlas_context.width, atlas_context.height, result);
  267. if (result == Atlas_Success)
  268. break;
  269. if (result == Atlas_ErrorInsufficientTemp)
  270. return BSPLoadResult_ErrorTempMemory;
  271. if (atlas_context.width < atlas_context.height) atlas_context.width <<= 1; else atlas_context.height <<= 1;
  272. if (atlas_context.width > 2048 || atlas_context.height > 2048) /* TODO limit based on GL driver caps */
  273. return BSPLoadResult_ErrorCapabilities;
  274. }
  275. /* Build an atlas texture based on calculated fragment positions */
  276. const size_t atlas_size = sizeof(uint16_t) * atlas_context.width * atlas_context.height;
  277. uint16_t *const pixels = stackAlloc(ctx->tmp, atlas_size);
  278. if (!pixels) return BSPLoadResult_ErrorTempMemory;
  279. memset(pixels, 0x0f, atlas_size); /* TODO debug pattern */
  280. for (int i = 0; i < ctx->faces_count; ++i) {
  281. const struct Face *const face = ctx->faces + i;
  282. ASSERT((unsigned)face->atlas_x + face->width <= atlas_context.width);
  283. ASSERT((unsigned)face->atlas_y + face->height <= atlas_context.height);
  284. for (int y = 0; y < face->height; ++y) {
  285. for (int x = 0; x < face->width; ++x) {
  286. const struct VBSPLumpLightMap *const pixel = face->samples + x + y * face->width;
  287. const unsigned int
  288. r = scaleLightmapColor(pixel->r, pixel->exponent),
  289. g = scaleLightmapColor(pixel->g, pixel->exponent),
  290. b = scaleLightmapColor(pixel->b, pixel->exponent);
  291. pixels[face->atlas_x + x + (face->atlas_y + y) * atlas_context.width]
  292. = ((r&0xf8) << 8) | ((g&0xfc) << 3) | (b >> 3);
  293. } /* for x */
  294. } /* for y */
  295. } /* fot all visible faces */
  296. RTextureCreateParams upload;
  297. upload.width = atlas_context.width;
  298. upload.height = atlas_context.height;
  299. upload.format = RTexFormat_RGB565;
  300. upload.pixels = pixels;
  301. renderTextureCreate(&ctx->lightmap.texture, upload);
  302. //ctx->lightmap.texture.min_filter = RTmF_Nearest;
  303. /* pixels buffer is not needed anymore */
  304. stackFreeUpToPosition(ctx->tmp, pixels);
  305. return BSPLoadResult_Success;
  306. }
  307. static inline struct AVec3f aVec3fLumpVec(struct VBSPLumpVertex v) { return aVec3f(v.x, v.y, v.z); }
  308. #ifdef DEBUG_DISP_LIGHTMAP
  309. static int shouldSwapUV(struct AVec3f mapU, struct AVec3f mapV, const struct AVec3f *v) {
  310. float mappedU = 0.f, mappedV = 0.f;
  311. for (int i = 0; i < 4; ++i) {
  312. const float U = aVec3fDot(mapU, aVec3fSub(v[(i+1)%4], v[i]));
  313. if (U > mappedU) mappedU = U;
  314. const float V = aVec3fDot(mapV, aVec3fSub(v[(i+1)%4], v[i]));
  315. if (V > mappedV) mappedV = V;
  316. }
  317. const float dX1 = aVec3fLength2(aVec3fSub(v[3], v[0]));
  318. const float dX2 = aVec3fLength2(aVec3fSub(v[2], v[1]));
  319. const float dY1 = aVec3fLength2(aVec3fSub(v[1], v[0]));
  320. const float dY2 = aVec3fLength2(aVec3fSub(v[2], v[3]));
  321. const float maxDX = (dX1 > dX2) ? dX1 : dX2;
  322. const float maxDY = (dY1 > dY2) ? dY1 : dY2;
  323. //PRINTF("mappedU=%f mappedV=%f maxDX=%f, maxDY=%f", mappedU, mappedV, maxDX, maxDY);
  324. return (mappedU > mappedV) != (maxDX > maxDY);
  325. }
  326. #endif /* DEBUG_DISP_LIGHTMAP */
  327. static void bspLoadDisplacement(
  328. const struct LoadModelContext *ctx,
  329. const struct Face *face,
  330. struct BSPModelVertex *out_vertices, uint16_t *out_indices, int index_shift) {
  331. const int side = (1 << face->dispinfo->power) + 1;
  332. const struct VBSPLumpVertex *const vertices = ctx->lumps->vertices.p;
  333. const struct VBSPLumpTexInfo * const tinfo = face->texinfo;
  334. const struct VBSPLumpDispVert *const dispvert = ctx->lumps->dispverts.p + face->dispinfo->vtx_start;
  335. //if (face->dispstartvtx != 0) PRINTF("dispstartvtx = %d", face->dispstartvtx);
  336. const struct AVec3f vec[4] = { /* bl, tl, tr, br */
  337. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 0)%4]]),
  338. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 1)%4]]),
  339. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 2)%4]]),
  340. aVec3fLumpVec(vertices[face->dispquadvtx[(face->dispstartvtx + 3)%4]])};
  341. /*
  342. const struct AVec3f ovec[4] = {
  343. aVec3fAdd(vec[0], aVec3fMulf(aVec3f(dispvert[0].x, dispvert[0].y, dispvert[0].z), dispvert[0].dist)),
  344. 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)),
  345. 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)),
  346. aVec3fAdd(vec[3], aVec3fMulf(aVec3f(dispvert[side-1].x, dispvert[side-1].y, dispvert[side-1].z), dispvert[side-1].dist))};
  347. */
  348. const struct AVec3f lm_map_u = aVec3f(
  349. tinfo->lightmap_vecs[0][0], tinfo->lightmap_vecs[0][1], tinfo->lightmap_vecs[0][2]);
  350. const float luxels_per_unit = aVec3fLength(lm_map_u);
  351. float length_lm_u = luxels_per_unit * floatMax(
  352. aVec3fLength(aVec3fSub(vec[3], vec[0])),
  353. aVec3fLength(aVec3fSub(vec[2], vec[1])));
  354. float length_lm_v = luxels_per_unit * floatMax(
  355. aVec3fLength(aVec3fSub(vec[1], vec[0])),
  356. aVec3fLength(aVec3fSub(vec[2], vec[3])));
  357. const struct AVec4f tex_map_u = aVec4f(
  358. tinfo->texture_vecs[0][0], tinfo->texture_vecs[0][1],
  359. tinfo->texture_vecs[0][2], tinfo->texture_vecs[0][3]);
  360. const struct AVec4f tex_map_v = aVec4f(
  361. tinfo->texture_vecs[1][0], tinfo->texture_vecs[1][1],
  362. tinfo->texture_vecs[1][2], tinfo->texture_vecs[1][3]);
  363. #ifdef DEBUG_DISP_LIGHTMAP
  364. const int swap = shouldSwapUV(
  365. aVec3f(tinfo->lightmap_vecs[0][0], tinfo->lightmap_vecs[0][1], tinfo->lightmap_vecs[0][2]),
  366. aVec3f(tinfo->lightmap_vecs[1][0], tinfo->lightmap_vecs[1][1], tinfo->lightmap_vecs[1][2]), vec);
  367. #endif /*ifdef DEBUG_DISP_LIGHTMAP*/
  368. const struct AVec2f atlas_scale = aVec2f(1.f / ctx->lightmap.texture.width, 1.f / ctx->lightmap.texture.height);
  369. const struct AVec2f atlas_offset = aVec2f(
  370. .5f + face->atlas_x /*+ tinfo->lightmap_vecs[0][3] - face->face->lightmap_min[0]*/,
  371. .5f + face->atlas_y /*+ tinfo->lightmap_vecs[1][3] - face->face->lightmap_min[1]*/);
  372. if (length_lm_u < 0. || length_lm_u >= face->width
  373. || length_lm_v < 0. || length_lm_v >= face->height) {
  374. PRINTF("LM OOB: (%f, %f) (%d, %d)", length_lm_u, length_lm_v, face->width, face->height);
  375. if (length_lm_u >= face->width) length_lm_u = (float)(face->width - 1);
  376. if (length_lm_v >= face->height) length_lm_v = (float)(face->height - 1);
  377. }
  378. /*
  379. PRINTF("%f %f %f %f",
  380. tinfo->lightmap_vecs[0][3] * atlas_scale.x, face->face->lightmap_min[0] * atlas_scale.x,
  381. tinfo->lightmap_vecs[1][3] * atlas_scale.y, face->face->lightmap_min[1] * atlas_scale.y);
  382. */
  383. const float div_side = 1.f / (side - 1);
  384. for (int y = 0; y < side; ++y) {
  385. const float ty = (float)y * div_side;
  386. const struct AVec3f vl = aVec3fMix(vec[0], vec[1], ty);
  387. const struct AVec3f vr = aVec3fMix(vec[3], vec[2], ty);
  388. for (int x = 0; x < side; ++x) {
  389. const float tx = (float)x * div_side;
  390. struct BSPModelVertex * const v = out_vertices + y * side + x;
  391. const struct VBSPLumpDispVert * const dv = dispvert + y * side + x;
  392. v->vertex = aVec3fMix(vl, vr, tx);
  393. v->lightmap_uv = aVec2f(tx * length_lm_u, ty * length_lm_v);
  394. v->tex_uv = aVec2f(
  395. aVec4fDot(aVec4f3(v->vertex, 1.f), tex_map_u),
  396. aVec4fDot(aVec4f3(v->vertex, 1.f), tex_map_v));
  397. v->vertex = aVec3fAdd(aVec3fMix(vl, vr, tx), aVec3fMulf(aVec3f(dv->x, dv->y, dv->z), dv->dist));
  398. if (v->lightmap_uv.x < 0 || v->lightmap_uv.y < 0 || v->lightmap_uv.x > face->width || v->lightmap_uv.y > face->height)
  399. PRINTF("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",
  400. 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);
  401. v->lightmap_uv = aVec2fMul(aVec2fAdd(v->lightmap_uv, atlas_offset), atlas_scale);
  402. #ifdef DEBUG_DISP_LIGHTMAP
  403. v->normal = aVec3f(face->dispstartvtx/3.f, swap, dv->dist / 100.f);
  404. #else
  405. /* FIXME normal */
  406. v->normal = aVec3ff(0.f);
  407. #endif
  408. }
  409. }
  410. for (int y = 0; y < side - 1; ++y) {
  411. for (int x = 0; x < side - 1; ++x) {
  412. const int base = index_shift + y * side + x;
  413. *out_indices++ = base;
  414. *out_indices++ = base + side + 1;
  415. *out_indices++ = base + side;
  416. *out_indices++ = base;
  417. *out_indices++ = base + 1;
  418. *out_indices++ = base + side + 1;
  419. }
  420. }
  421. }
  422. static void bspLoadFace(
  423. const struct LoadModelContext *ctx,
  424. const struct Face *face,
  425. struct BSPModelVertex *out_vertices, uint16_t *out_indices, int index_shift) {
  426. const struct VBSPLumpFace *vface = face->vface;
  427. const struct VBSPLumpTexInfo * const tinfo = face->texinfo;
  428. struct AVec3f normal;
  429. normal.x = ctx->lumps->planes.p[vface->plane].x;
  430. normal.y = ctx->lumps->planes.p[vface->plane].y;
  431. normal.z = ctx->lumps->planes.p[vface->plane].z;
  432. if (vface->side) normal = aVec3fNeg(normal);
  433. const struct AVec4f lm_map_u = aVec4f(
  434. tinfo->lightmap_vecs[0][0], tinfo->lightmap_vecs[0][1],
  435. tinfo->lightmap_vecs[0][2], tinfo->lightmap_vecs[0][3] - vface->lightmap_min[0]);
  436. const struct AVec4f lm_map_v = aVec4f(
  437. tinfo->lightmap_vecs[1][0], tinfo->lightmap_vecs[1][1],
  438. tinfo->lightmap_vecs[1][2], tinfo->lightmap_vecs[1][3] - vface->lightmap_min[1]);
  439. const struct AVec4f tex_map_u = aVec4f(
  440. tinfo->texture_vecs[0][0], tinfo->texture_vecs[0][1],
  441. tinfo->texture_vecs[0][2], tinfo->texture_vecs[0][3]);
  442. const struct AVec4f tex_map_v = aVec4f(
  443. tinfo->texture_vecs[1][0], tinfo->texture_vecs[1][1],
  444. tinfo->texture_vecs[1][2], tinfo->texture_vecs[1][3]);
  445. const int32_t * const surfedges = ctx->lumps->surfedges.p + vface->first_edge;
  446. for (int iedge = 0; iedge < vface->num_edges; ++iedge) {
  447. const uint16_t vstart = (surfedges[iedge] >= 0)
  448. ? ctx->lumps->edges.p[surfedges[iedge]].v[0]
  449. : ctx->lumps->edges.p[-surfedges[iedge]].v[1];
  450. const struct VBSPLumpVertex * const lv = ctx->lumps->vertices.p + vstart;
  451. struct BSPModelVertex * const vertex = out_vertices + iedge;
  452. vertex->vertex = aVec3f(lv->x, lv->y, lv->z);
  453. vertex->normal = normal;
  454. vertex->lightmap_uv = aVec2f(
  455. aVec4fDot(aVec4f3(vertex->vertex, 1.f), lm_map_u),
  456. aVec4fDot(aVec4f3(vertex->vertex, 1.f), lm_map_v));
  457. vertex->tex_uv = aVec2f(
  458. aVec4fDot(aVec4f3(vertex->vertex, 1.f), tex_map_u),
  459. aVec4fDot(aVec4f3(vertex->vertex, 1.f), tex_map_v));
  460. if (vertex->lightmap_uv.x < 0 || vertex->lightmap_uv.y < 0 || vertex->lightmap_uv.x > face->width || vertex->lightmap_uv.y > face->height)
  461. PRINTF("Error: OOB LM F:V%u: x=%f y=%f z=%f u=%f v=%f w=%d h=%d", iedge, lv->x, lv->y, lv->z, vertex->lightmap_uv.x, vertex->lightmap_uv.y, face->width, face->height);
  462. vertex->lightmap_uv.x = (vertex->lightmap_uv.x + face->atlas_x + .5f) / ctx->lightmap.texture.width;
  463. vertex->lightmap_uv.y = (vertex->lightmap_uv.y + face->atlas_y + .5f) / ctx->lightmap.texture.height;
  464. if (iedge > 1) {
  465. out_indices[(iedge-2)*3+0] = index_shift + 0;
  466. out_indices[(iedge-2)*3+1] = index_shift + iedge;
  467. out_indices[(iedge-2)*3+2] = index_shift + iedge - 1;
  468. }
  469. }
  470. }
  471. static enum BSPLoadResult bspLoadModelDraws(const struct LoadModelContext *ctx, struct Stack *persistent,
  472. struct BSPModel *model) {
  473. struct BSPModelVertex * const vertices_buffer
  474. = stackAlloc(ctx->tmp, sizeof(struct BSPModelVertex) * ctx->max_draw_vertices);
  475. if (!vertices_buffer) return BSPLoadResult_ErrorTempMemory;
  476. /* each vertex after second in a vface is a new triangle */
  477. uint16_t * const indices_buffer = stackAlloc(ctx->tmp, sizeof(uint16_t) * ctx->indices);
  478. if (!indices_buffer) return BSPLoadResult_ErrorTempMemory;
  479. int vertex_pos = 0;
  480. int draw_indices_start = 0, indices_pos = 0;
  481. model->draws_count = ctx->faces_count;
  482. model->draws = stackAlloc(persistent, sizeof(struct BSPDraw) * model->draws_count);
  483. int vbo_offset = 0;
  484. int idraw = 0;
  485. for (int iface = 0; iface < ctx->faces_count/* + 1*/; ++iface) {
  486. const struct Face *face = ctx->faces + iface;
  487. if ((vertex_pos - vbo_offset) + face->vertices >= c_max_draw_vertices) {
  488. PRINTF("vbo_offset %d -> %d", vbo_offset, vertex_pos);
  489. vbo_offset = vertex_pos;
  490. }
  491. if (face->dispinfo) {
  492. bspLoadDisplacement(ctx, face, vertices_buffer + vertex_pos, indices_buffer + indices_pos, vertex_pos - vbo_offset);
  493. } else {
  494. bspLoadFace(ctx, face, vertices_buffer + vertex_pos, indices_buffer + indices_pos, vertex_pos - vbo_offset);
  495. }
  496. vertex_pos += face->vertices;
  497. indices_pos += face->indices;
  498. struct BSPDraw *draw = model->draws + idraw;
  499. memset(draw, 0, sizeof *draw);
  500. draw->count = indices_pos - draw_indices_start;
  501. draw->start = draw_indices_start;
  502. draw->vbo_offset = vbo_offset;
  503. //PRINTF("Adding draw=%u start=%u count=%u", idraw, draw->start, draw->count);
  504. draw->material = face->material;
  505. /*
  506. PRINTF("Got texture size %dx%d",
  507. draw->material->base_texture[0]->gltex.width,
  508. draw->material->base_texture[0]->gltex.height);
  509. */
  510. //vertex_pos = 0;
  511. draw_indices_start = indices_pos;
  512. ++idraw;
  513. ASSERT(idraw <= model->draws_count);
  514. }
  515. PRINTF("%d %d", idraw, model->draws_count);
  516. ASSERT(idraw == model->draws_count);
  517. renderModelOptimize(model);
  518. uint16_t *tmp_indices = stackAlloc(ctx->tmp, sizeof(uint16_t) * ctx->indices);
  519. if (!tmp_indices) {
  520. return BSPLoadResult_ErrorTempMemory;
  521. }
  522. int tmp_indices_offset = 0;
  523. for (int i = 0; i < model->draws_count; ++i) {
  524. struct BSPDraw *d = model->draws + i;
  525. memcpy(tmp_indices + tmp_indices_offset, indices_buffer + d->start, sizeof(uint16_t) * d->count);
  526. d->start = tmp_indices_offset;
  527. tmp_indices_offset += d->count;
  528. }
  529. ASSERT(tmp_indices_offset == ctx->indices);
  530. renderBufferCreate(&model->ibo, RBufferType_Index, sizeof(uint16_t) * ctx->indices, tmp_indices);
  531. renderBufferCreate(&model->vbo, RBufferType_Vertex, sizeof(struct BSPModelVertex) * vertex_pos, vertices_buffer);
  532. return BSPLoadResult_Success;
  533. }
  534. static enum BSPLoadResult bspLoadModel(
  535. struct ICollection *collection, struct BSPModel *model, struct Stack *persistent, struct Stack *temp,
  536. const struct Lumps *lumps, unsigned index) {
  537. struct LoadModelContext context;
  538. memset(&context, 0, sizeof context);
  539. ASSERT(index < lumps->models.n);
  540. context.tmp = temp;
  541. context.collection = collection;
  542. context.lumps = lumps;
  543. context.model = lumps->models.p + index;
  544. /* Step 1. Collect lightmaps for all faces */
  545. enum BSPLoadResult result = bspLoadModelPreloadFaces(&context);
  546. if (result != BSPLoadResult_Success) {
  547. PRINTF("Error: bspLoadModelPreloadFaces() => %s", R2S(result));
  548. return result;
  549. }
  550. /* Step 2. Build an atlas of all lightmaps */
  551. result = bspLoadModelLightmaps(&context);
  552. if (result != BSPLoadResult_Success) {
  553. PRINTF("Error: bspLoadModelLightmaps() => %s", R2S(result));
  554. return result;
  555. }
  556. /* Step 3. Generate draw operations data */
  557. result = bspLoadModelDraws(&context, persistent, model);
  558. if (result != BSPLoadResult_Success) {
  559. //aGLTextureDestroy(&context.lightmap.texture);
  560. return result;
  561. }
  562. model->lightmap = context.lightmap.texture;
  563. model->aabb.min.x = context.model->min.x;
  564. model->aabb.min.y = context.model->min.y;
  565. model->aabb.min.z = context.model->min.z;
  566. model->aabb.max.x = context.model->max.x;
  567. model->aabb.max.y = context.model->max.y;
  568. model->aabb.max.z = context.model->max.z;
  569. return BSPLoadResult_Success;
  570. } // bspLoadModel()
  571. struct EntityProp {
  572. const char *name;
  573. const char *value;
  574. int value_length;
  575. };
  576. enum BSPLoadResult bspReadEntityProps(struct TokenContext *tctx, struct EntityProp* props, int prop_count) {
  577. // TODO: what if this entity for some reason has nested entities
  578. // should count curlies then
  579. for (;;) {
  580. const enum TokenType type = getNextToken(tctx);
  581. switch (type) {
  582. case Token_String:
  583. /*if (!prop_count)
  584. PRINTF("%.*s", tctx->str_length, tctx->str_start);*/
  585. for (int i = 0; i < prop_count; ++i) {
  586. if (strncmp(props[i].name, tctx->str_start, tctx->str_length) == 0) {
  587. const enum TokenType type = getNextToken(tctx);
  588. if (type == Token_Error)
  589. return BSPLoadResult_ErrorFileFormat;
  590. if (type != Token_String) {
  591. PRINTF("Warning: expected string, got %d", type);
  592. continue;
  593. }
  594. props[i].value = tctx->str_start;
  595. props[i].value_length = tctx->str_length;
  596. break;
  597. } // if prop match found
  598. } // for all props
  599. break;
  600. case Token_CurlyClose:
  601. /*
  602. for (int i = 0; i < prop_count; ++i) {
  603. PRINTF("prop[%i] '%s' = '%.*s'", i,
  604. props[i].name, props[i].value_length, props[i].value);
  605. }
  606. */
  607. return BSPLoadResult_Success;
  608. default:
  609. PRINTF("Illegal token: %d", type);
  610. return BSPLoadResult_ErrorFileFormat;
  611. }
  612. } // forever
  613. }
  614. enum BSPLoadResult bspReadEntityInfoLandmark(struct BSPLoadModelContext *ctx, struct TokenContext* tctx) {
  615. struct EntityProp props[] = {
  616. {"targetname", NULL, 0},
  617. {"origin", NULL, 0}
  618. };
  619. const enum BSPLoadResult result = bspReadEntityProps(tctx, props, COUNTOF(props));
  620. if (result != BSPLoadResult_Success)
  621. return result;
  622. for (int i = 0; i < (int)COUNTOF(props); ++i)
  623. if (props[i].value == NULL || props[i].value_length == 0) {
  624. PRINTF("Property %s is empty, skipping this landmark", props[i].name);
  625. return BSPLoadResult_Success;
  626. }
  627. struct BSPModel *model = ctx->model;
  628. if (model->landmarks_count == BSP_MAX_LANDMARKS) {
  629. PRINT("Too many landmarks");
  630. return BSPLoadResult_ErrorMemory;
  631. }
  632. struct BSPLandmark *landmark = model->landmarks + model->landmarks_count;
  633. if (props[0].value_length >= (int)sizeof(landmark->name)) {
  634. PRINTF("Landmark name \"%.*s\" is too long",
  635. props[0].value_length, props[0].value);
  636. return BSPLoadResult_ErrorMemory;
  637. }
  638. memcpy(landmark->name, props[0].value, props[0].value_length);
  639. landmark->name[props[0].value_length] = '\0';
  640. // FIXME props[1].value is not null-terminated suman
  641. if (3 != sscanf(props[1].value, "%f %f %f",
  642. &landmark->origin.x,
  643. &landmark->origin.y,
  644. &landmark->origin.z))
  645. {
  646. PRINTF("Cannot read x, y, z from origin=\"%.*s\"",
  647. props[1].value_length, props[1].value);
  648. return BSPLoadResult_ErrorFileFormat;
  649. }
  650. ++model->landmarks_count;
  651. return BSPLoadResult_Success;
  652. }
  653. enum BSPLoadResult bspReadEntityTriggerChangelevel(struct BSPLoadModelContext *ctx, struct TokenContext* tctx) {
  654. (void)ctx;
  655. struct EntityProp props[] = {
  656. {"landmark", NULL, 0},
  657. {"map", NULL, 0}
  658. };
  659. const enum BSPLoadResult result = bspReadEntityProps(tctx, props, COUNTOF(props));
  660. if (result != BSPLoadResult_Success)
  661. return result;
  662. openSourceAddMap(props[1].value, props[1].value_length);
  663. return BSPLoadResult_Success;
  664. }
  665. enum BSPLoadResult bspReadEntityAndDumpProps(struct BSPLoadModelContext *ctx, struct TokenContext* tctx) {
  666. (void)ctx;
  667. return bspReadEntityProps(tctx, NULL, 0);
  668. }
  669. enum BSPLoadResult bspReadEntities(struct BSPLoadModelContext *ctx, const char *str, int length) {
  670. ctx->model->landmarks_count = 0;
  671. struct TokenContext tctx;
  672. tctx.cursor = str;
  673. tctx.end = str + length;
  674. int loop = 1;
  675. const char* curlyOpen = NULL;
  676. while(loop) {
  677. switch(getNextToken(&tctx)) {
  678. case Token_CurlyOpen:
  679. curlyOpen = tctx.cursor;
  680. break;
  681. case Token_String:
  682. //PRINTF("%.*s", (int)tctx.str_length, tctx.str_start);
  683. #define LOAD_ENTITY(name, func) \
  684. if (strncmp(name, tctx.str_start, tctx.str_length) == 0) { \
  685. tctx.cursor = curlyOpen; \
  686. const enum BSPLoadResult result = func(ctx, &tctx); \
  687. if (result != BSPLoadResult_Success) { \
  688. PRINTF("Failed at loading " name "@%d", (int)(tctx.cursor - str)); \
  689. return result; \
  690. } \
  691. continue; \
  692. }
  693. LOAD_ENTITY("info_landmark", bspReadEntityInfoLandmark);
  694. LOAD_ENTITY("trigger_changelevel", bspReadEntityTriggerChangelevel);
  695. LOAD_ENTITY("worldspawn", bspReadEntityAndDumpProps);
  696. LOAD_ENTITY("info_player_start", bspReadEntityAndDumpProps);
  697. break;
  698. case Token_Error:
  699. return BSPLoadResult_ErrorFileFormat;
  700. case Token_End:
  701. loop = 0;
  702. break;
  703. default:
  704. break;
  705. }
  706. }
  707. return BSPLoadResult_Success;
  708. }
  709. static int lumpRead(const char *name, const struct VBSPLumpHeader *header,
  710. struct IFile *file, struct Stack *tmp,
  711. struct AnyLump *out_ptr, uint32_t item_size) {
  712. out_ptr->p = stackAlloc(tmp, header->size);
  713. if (!out_ptr->p) {
  714. PRINTF("Not enough temp memory to allocate storage for lump %s; need: %d (%x)", name, header->size, header->size);
  715. return -1;
  716. }
  717. const size_t bytes = file->read(file, header->file_offset, header->size, (void*)out_ptr->p);
  718. if (bytes != header->size) {
  719. PRINTF("Cannot read full lump %s, read only %zu bytes out of %u", name, bytes, header->size);
  720. return -1;
  721. }
  722. PRINTF("Read lump %s, offset %u, size %u bytes / %u item = %u elements",
  723. name, header->file_offset, header->size, item_size, header->size / item_size);
  724. out_ptr->n = header->size / item_size;
  725. return 1;
  726. }
  727. enum BSPLoadResult bspLoadWorldspawn(struct BSPLoadModelContext context, const char *mapname) {
  728. enum BSPLoadResult result = BSPLoadResult_Success;
  729. struct IFile *file = 0;
  730. if (CollectionOpen_Success !=
  731. collectionChainOpen(context.collection, mapname, File_Map, &file)) {
  732. return BSPLoadResult_ErrorFileOpen;
  733. }
  734. void *tmp_cursor = stackGetCursor(context.tmp);
  735. struct ICollection *pakfile = NULL;
  736. struct VBSPHeader vbsp_header;
  737. size_t bytes = file->read(file, 0, sizeof vbsp_header, &vbsp_header);
  738. if (bytes < sizeof(vbsp_header)) {
  739. PRINTF("Size is too small: %zu <= %zu", bytes, sizeof(struct VBSPHeader));
  740. result = BSPLoadResult_ErrorFileFormat;
  741. goto exit;
  742. }
  743. if (vbsp_header.ident[0] != 'V' || vbsp_header.ident[1] != 'B' ||
  744. vbsp_header.ident[2] != 'S' || vbsp_header.ident[3] != 'P') {
  745. PRINTF("Error: invalid ident => %c%c%c%c != VBSP",
  746. vbsp_header.ident[0], vbsp_header.ident[1], vbsp_header.ident[2], vbsp_header.ident[3]);
  747. result = BSPLoadResult_ErrorFileFormat;
  748. goto exit;
  749. }
  750. if (vbsp_header.version != 19 && vbsp_header.version != 20) {
  751. PRINTF("Error: invalid version: %d != 19 or 20", vbsp_header.version);
  752. result = BSPLoadResult_ErrorFileFormat;
  753. goto exit;
  754. }
  755. PRINTF("VBSP version %u opened", vbsp_header.version);
  756. struct Lumps lumps;
  757. lumps.version = vbsp_header.version;
  758. #define BSPLUMP(name, type, field) \
  759. if (1 != lumpRead(#name, vbsp_header.lump_headers + VBSP_Lump_##name, file, context.tmp, \
  760. (struct AnyLump*)&lumps.field, sizeof(type))) { \
  761. result = BSPLoadResult_ErrorFileFormat; \
  762. goto exit; \
  763. }
  764. LIST_LUMPS
  765. #undef BSPLUMP
  766. if (lumps.lightmaps.n == 0) {
  767. memcpy(&lumps.lightmaps, &lumps.lightmaps_hdr, sizeof(lumps.lightmaps));
  768. memcpy(&lumps.faces, &lumps.faces_hdr, sizeof(lumps.faces));
  769. }
  770. if (lumps.pakfile.n > 0) {
  771. struct Memories memories = { context.tmp, context.tmp };
  772. pakfile = collectionCreatePakfile(&memories, lumps.pakfile.p, lumps.pakfile.n);
  773. if (pakfile)
  774. pakfile->next = context.collection;
  775. }
  776. result = bspLoadModel(pakfile ? pakfile : context.collection, context.model, context.persistent, context.tmp, &lumps, 0);
  777. if (result != BSPLoadResult_Success) {
  778. PRINTF("Error: bspLoadModel() => %s", R2S(result));
  779. goto exit;
  780. }
  781. result = bspReadEntities(&context, lumps.entities.p, lumps.entities.n);
  782. if (result != BSPLoadResult_Success)
  783. PRINTF("Error: bspReadEntities() => %s", R2S(result));
  784. exit:
  785. if (pakfile)
  786. pakfile->close(pakfile);
  787. stackFreeUpToPosition(context.tmp, tmp_cursor);
  788. if (file) file->close(file);
  789. return result;
  790. }