Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

933 lines
28 KiB

  1. // This file takes minecraft chunks (decoded by cave_parse) and
  2. // uses stb_voxel_render to turn them into vertex buffers.
  3. #define STB_GLEXT_DECLARE "glext_list.h"
  4. #include "stb_gl.h"
  5. #include "stb_image.h"
  6. #include "stb_glprog.h"
  7. #include "caveview.h"
  8. #include "cave_parse.h"
  9. #include "stb.h"
  10. #include "sdl.h"
  11. #include "sdl_thread.h"
  12. #include <math.h>
  13. //#define VHEIGHT_TEST
  14. //#define STBVOX_OPTIMIZED_VHEIGHT
  15. #define STBVOX_CONFIG_MODE 1
  16. #define STBVOX_CONFIG_OPENGL_MODELVIEW
  17. #define STBVOX_CONFIG_PREFER_TEXBUFFER
  18. //#define STBVOX_CONFIG_LIGHTING_SIMPLE
  19. #define STBVOX_CONFIG_FOG_SMOOTHSTEP
  20. //#define STBVOX_CONFIG_PREMULTIPLIED_ALPHA // this doesn't work properly alpha test without next #define
  21. //#define STBVOX_CONFIG_UNPREMULTIPLY // slower, fixes alpha test makes windows & fancy leaves look better
  22. //#define STBVOX_CONFIG_TEX1_EDGE_CLAMP
  23. #define STBVOX_CONFIG_DISABLE_TEX2
  24. //#define STBVOX_CONFIG_DOWN_TEXLERP_PACKED
  25. #define STBVOX_CONFIG_ROTATION_IN_LIGHTING
  26. #define STB_VOXEL_RENDER_IMPLEMENTATION
  27. #include "stb_voxel_render.h"
  28. extern void ods(char *fmt, ...);
  29. //#define FANCY_LEAVES // nearly 2x the triangles when enabled (if underground is filled)
  30. #define FAST_CHUNK
  31. #define IN_PLACE
  32. #define SKIP_TERRAIN 0
  33. //#define SKIP_TERRAIN 48 // use to avoid building underground stuff
  34. // allows you to see what perf would be like if underground was efficiently culled,
  35. // or if you were making a game without underground
  36. enum
  37. {
  38. C_empty,
  39. C_solid,
  40. C_trans,
  41. C_cross,
  42. C_water,
  43. C_slab,
  44. C_stair,
  45. C_force,
  46. };
  47. unsigned char geom_map[] =
  48. {
  49. STBVOX_GEOM_empty,
  50. STBVOX_GEOM_solid,
  51. STBVOX_GEOM_transp,
  52. STBVOX_GEOM_crossed_pair,
  53. STBVOX_GEOM_solid,
  54. STBVOX_GEOM_slab_lower,
  55. STBVOX_GEOM_floor_slope_north_is_top,
  56. STBVOX_GEOM_force,
  57. };
  58. unsigned char minecraft_info[256][7] =
  59. {
  60. { C_empty, 0,0,0,0,0,0 },
  61. { C_solid, 1,1,1,1,1,1 },
  62. { C_solid, 3,3,3,3,40,2 },
  63. { C_solid, 2,2,2,2,2,2 },
  64. { C_solid, 16,16,16,16,16,16 },
  65. { C_solid, 4,4,4,4,4,4 },
  66. { C_cross, 15,15,15,15 },
  67. { C_solid, 17,17,17,17,17,17 },
  68. // 8
  69. { C_water, 223,223,223,223,223,223 },
  70. { C_water, 223,223,223,223,223,223 },
  71. { C_solid, 255,255,255,255,255,255 },
  72. { C_solid, 255,255,255,255,255,255 },
  73. { C_solid, 18,18,18,18,18,18 },
  74. { C_solid, 19,19,19,19,19,19 },
  75. { C_solid, 32,32,32,32,32,32 },
  76. { C_solid, 33,33,33,33,33,33 },
  77. // 16
  78. { C_solid, 34,34,34,34,34,34 },
  79. { C_solid, 20,20,20,20,21,21 },
  80. #ifdef FANCY_LEAVES
  81. { C_force, 52,52,52,52,52,52 }, // leaves
  82. #else
  83. { C_solid, 53,53,53,53,53,53 }, // leaves
  84. #endif
  85. { C_solid, 24,24,24,24,24,24 },
  86. { C_trans, 49,49,49,49,49,49 }, // glass
  87. { C_solid, 160,160,160,160,160,160 },
  88. { C_solid, 144,144,144,144,144,144 },
  89. { C_solid, 46,45,45,45,62,62 },
  90. // 24
  91. { C_solid, 192,192,192,192, 176,176 },
  92. { C_solid, 74,74,74,74,74,74 },
  93. { C_empty }, // bed
  94. { C_empty }, // powered rail
  95. { C_empty }, // detector rail
  96. { C_solid, 106,108,109,108,108,108 },
  97. { C_empty }, // cobweb=11
  98. { C_cross, 39,39,39,39 },
  99. // 32
  100. { C_cross, 55,55,55,55,0,0 },
  101. { C_solid, 107,108,109,108,108,108 },
  102. { C_empty }, // piston head
  103. { C_solid, 64,64,64,64,64,64 }, // various colors
  104. { C_empty }, // unused
  105. { C_cross, 13,13,13,13,0,0 },
  106. { C_cross, 12,12,12,12,0,0 },
  107. { C_cross, 29,29,29,29,0,0 },
  108. // 40
  109. { C_cross, 28,28,28,28,0,0 },
  110. { C_solid, 23,23,23,23,23,23 },
  111. { C_solid, 22,22,22,22,22,22 },
  112. { C_solid, 5,5,5,5,6,6, },
  113. { C_slab , 5,5,5,5,6,6, },
  114. { C_solid, 7,7,7,7,7,7, },
  115. { C_solid, 8,8,8,8,9,10 },
  116. { C_solid, 35,35,35,35,4,4, },
  117. // 48
  118. //{ C_solid, 36,36,36,36,36,36 },
  119. { C_force, 36,36,36,36,36,36 },
  120. { C_solid, 37,37,37,37,37,37 },
  121. { C_cross, 80,80,80,80,80,80 }, // torch
  122. { C_empty }, // fire
  123. { C_trans, 65,65,65,65,65,65 },
  124. { C_stair, 4,4,4,4,4,4 },
  125. { C_solid, 26,26,26,27,25,25 },
  126. { C_empty }, // redstone
  127. // 56
  128. { C_solid, 50,50,50,50,50,50 },
  129. //{ C_force, 50,50,50,50,50,50 },
  130. { C_solid, 26,26,26,26,26,26 },
  131. { C_solid, 60,59,59,59,43,43 },
  132. { C_cross, 95,95,95,95 },
  133. { C_solid, 2,2,2,2,86,2 },
  134. { C_solid, 44,45,45,45,62,62 },
  135. { C_solid, 61,45,45,45,62,62 },
  136. { C_empty }, // sign
  137. // 64
  138. { C_empty }, // door
  139. { C_empty }, // ladder
  140. { C_empty }, // rail
  141. { C_stair, 16,16,16,16,16,16 }, // cobblestone stairs
  142. { C_empty }, // sign
  143. { C_empty }, // lever
  144. { C_empty }, // stone pressure plate
  145. { C_empty }, // iron door
  146. // 72
  147. { C_empty }, // wooden pressure
  148. { C_solid, 51,51,51,51,51,51 },
  149. { C_solid, 51,51,51,51,51,51 },
  150. { C_empty },
  151. { C_empty },
  152. { C_empty },
  153. { C_empty }, // snow on block below, do as half slab?
  154. { C_solid, 67,67,67,67,67,67 },
  155. // 80
  156. { C_solid, 66,66,66,66,66,66 },
  157. { C_solid, 70,70,70,70,69,71 },
  158. { C_solid, 72,72,72,72,72,72 },
  159. { C_cross, 73,73,73,73,73,73 },
  160. { C_solid, 74,74,74,74,75,74 },
  161. { C_empty }, // fence
  162. { C_solid,119,118,118,118,102,102 },
  163. { C_solid,103,103,103,103,103,103 },
  164. // 88
  165. { C_solid, 104,104,104,104,104,104 },
  166. { C_solid, 105,105,105,105,105,105 },
  167. { C_solid, 167,167,167,167,167,167 },
  168. { C_solid, 120,118,118,118,102,102 },
  169. { C_empty }, // cake
  170. { C_empty }, // repeater
  171. { C_empty }, // repeater
  172. { C_solid, 49,49,49,49,49,49 }, // colored glass
  173. // 96
  174. { C_empty },
  175. { C_empty },
  176. { C_solid, 54,54,54,54,54,54 },
  177. { C_solid, 125,125,125,125,125,125 },
  178. { C_solid, 126,126,126,126,126,126 },
  179. { C_empty }, // bars
  180. { C_trans, 49,49,49,49,49,49 }, // glass pane
  181. { C_solid, 136,136,136,136,137,137 }, // melon
  182. // 104
  183. { C_empty }, // pumpkin stem
  184. { C_empty }, // melon stem
  185. { C_empty }, // vines
  186. { C_empty }, // gate
  187. { C_stair, 7,7,7,7,7,7, }, // brick stairs
  188. { C_stair, 54,54,54,54,54,54 }, // stone brick stairs
  189. { C_empty }, // mycelium
  190. { C_empty }, // lily pad
  191. // 112
  192. { C_solid, 224,224,224,224,224,224 },
  193. { C_empty }, // nether brick fence
  194. { C_stair, 224,224,224,224,224,224 }, // nether brick stairs
  195. { C_empty }, // nether wart
  196. { C_solid, 182,182,182,182,166,183 },
  197. { C_empty }, // brewing stand
  198. { C_empty }, // cauldron
  199. { C_empty }, // end portal
  200. // 120
  201. { C_solid, 159,159,159,159,158,158 },
  202. { C_solid, 175,175,175,175,175,175 },
  203. { C_empty }, // dragon egg
  204. { C_solid, 211,211,211,211,211,211 },
  205. { C_solid, 212,212,212,212,212,212 },
  206. { C_solid, 4,4,4,4,4,4, }, // wood double-slab
  207. { C_slab , 4,4,4,4,4,4, }, // wood slab
  208. { C_empty }, // cocoa
  209. // 128
  210. { C_solid, 192,192,192,192,176,176 }, // sandstone stairs
  211. { C_solid, 32,32,32,32,32,32 }, // emerald ore
  212. { C_solid, 26,26,26,27,25,25 }, // ender chest
  213. { C_empty },
  214. { C_empty },
  215. { C_solid, 23,23,23,23,23,23 }, // emerald block
  216. { C_solid, 198,198,198,198,198,198 }, // spruce stairs
  217. { C_solid, 214,214,214,214,214,214 }, // birch stairs
  218. // 136
  219. { C_stair, 199,199,199,199,199,199 }, // jungle stairs
  220. { C_empty }, // command block
  221. { C_empty }, // beacon
  222. { C_slab, 16,16,16,16,16,16 }, // cobblestone wall
  223. { C_empty }, // flower pot
  224. { C_empty }, // carrot
  225. { C_empty }, // potatoes
  226. { C_empty }, // wooden button
  227. // 144
  228. { C_empty }, // mob head
  229. { C_empty }, // anvil
  230. { C_solid, 26,26,26,27,25,25 }, // trapped chest
  231. { C_empty }, // weighted pressure plate light
  232. { C_empty }, // weighted pressure plat eheavy
  233. { C_empty }, // comparator inactive
  234. { C_empty }, // comparator active
  235. { C_empty }, // daylight sensor
  236. // 152
  237. { C_solid, 135,135,135,135,135,135 }, // redstone block
  238. { C_solid, 0,0,0,0,0,0, }, // nether quartz ore
  239. { C_empty }, // hopper
  240. { C_solid, 22,22,22,22,22,22 }, // quartz block
  241. { C_stair, 22,22,22,22,22,22 }, // quartz stairs
  242. { C_empty }, // activator rail
  243. { C_solid, 46,45,45,45,62,62 }, // dropper
  244. { C_solid, 72,72,72,72,72,72 }, // stained clay
  245. // 160
  246. { C_trans, 49,49,49,49,49,49 }, // stained glass pane
  247. #ifdef FANCY_LEAVES
  248. { C_force, 52,52,52,52,52,52 }, // leaves
  249. #else
  250. { C_solid, 53,53,53,53,53,53 }, // acacia leaves
  251. #endif
  252. { C_solid, 20,20,20,20,21,21 }, // acacia tree
  253. { C_solid, 199,199,199,199,199,199 }, // acacia wood stairs
  254. { C_solid, 198,198,198,198,198,198 }, // dark oak stairs
  255. { C_solid, 146,146,146,146,146,146 }, // slime block
  256. { C_solid, 176,176,176,176,176,176 }, // red sandstone
  257. { C_solid, 176,176,176,176,176,176 }, // red sandstone
  258. // 168
  259. { C_empty },
  260. { C_empty },
  261. { C_empty },
  262. { C_empty },
  263. { C_solid, 72,72,72,72,72,72 }, // hardened clay
  264. { C_empty },
  265. { C_empty },
  266. { C_empty },
  267. // 176
  268. { C_empty },
  269. { C_empty },
  270. { C_solid, 176,176,176,176,176,176 }, // red sandstone
  271. };
  272. unsigned char minecraft_tex1_for_blocktype[256][6];
  273. unsigned char effective_blocktype[256];
  274. unsigned char minecraft_color_for_blocktype[256][6];
  275. unsigned char minecraft_geom_for_blocktype[256];
  276. uint8 build_buffer[BUILD_BUFFER_SIZE];
  277. uint8 face_buffer[FACE_BUFFER_SIZE];
  278. //GLuint vbuf, fbuf, fbuf_tex;
  279. //unsigned char tex1_for_blocktype[256][6];
  280. //unsigned char blocktype[34][34][257];
  281. //unsigned char lighting[34][34][257];
  282. // a superchunk is 64x64x256, with the border blocks computed as well,
  283. // which means we need 4x4 chunks plus 16 border chunks plus 4 corner chunks
  284. #define SUPERCHUNK_X 4
  285. #define SUPERCHUNK_Y 4
  286. unsigned char remap_data[16][16];
  287. unsigned char remap[256];
  288. unsigned char rotate_data[4] = { 1,3,2,0 };
  289. void convert_fastchunk_inplace(fast_chunk *fc)
  290. {
  291. int i;
  292. int num_blocks=0, step=0;
  293. unsigned char rot[4096];
  294. #ifndef IN_PLACE
  295. unsigned char *storage;
  296. #endif
  297. memset(rot, 0, 4096);
  298. for (i=0; i < 16; ++i)
  299. num_blocks += fc->blockdata[i] != NULL;
  300. #ifndef IN_PLACE
  301. storage = malloc(16*16*16*2 * num_blocks);
  302. #endif
  303. for (i=0; i < 16; ++i) {
  304. if (fc->blockdata[i]) {
  305. int o=0;
  306. unsigned char *bd,*dd,*lt,*sky;
  307. unsigned char *out, *outb;
  308. // this ordering allows us to determine which data we can safely overwrite for in-place processing
  309. bd = fc->blockdata[i];
  310. dd = fc->data[i];
  311. lt = fc->light[i];
  312. sky = fc->skylight[i];
  313. #ifdef IN_PLACE
  314. out = bd;
  315. #else
  316. out = storage + 16*16*16*2*step;
  317. #endif
  318. // bd is written in place, but also reads from dd
  319. for (o=0; o < 16*16*16/2; o += 1) {
  320. unsigned char v1,v2;
  321. unsigned char d = dd[o];
  322. v1 = bd[o*2+0];
  323. v2 = bd[o*2+1];
  324. if (remap[v1])
  325. {
  326. //unsigned char d = bd[o] & 15;
  327. v1 = remap_data[remap[v1]][d&15];
  328. rot[o*2+0] = rotate_data[d&3];
  329. } else
  330. v1 = effective_blocktype[v1];
  331. if (remap[v2])
  332. {
  333. //unsigned char d = bd[o] >> 4;
  334. v2 = remap_data[remap[v2]][d>>4];
  335. rot[o*2+1] = rotate_data[(d>>4)&3];
  336. } else
  337. v2 = effective_blocktype[v2];
  338. out[o*2+0] = v1;
  339. out[o*2+1] = v2;
  340. }
  341. // this reads from lt & sky
  342. #ifndef IN_PLACE
  343. outb = out + 16*16*16;
  344. ++step;
  345. #endif
  346. // MC used to write in this order and it makes it possible to compute in-place
  347. if (dd < sky && sky < lt) {
  348. // @TODO go this path always if !IN_PLACE
  349. #ifdef IN_PLACE
  350. outb = dd;
  351. #endif
  352. for (o=0; o < 16*16*16/2; ++o) {
  353. int bright;
  354. bright = (lt[o]&15)*12 + 15 + (sky[o]&15)*16;
  355. if (bright > 255) bright = 255;
  356. if (bright < 32) bright = 32;
  357. outb[o*2+0] = STBVOX_MAKE_LIGHTING_EXT((unsigned char) bright, (rot[o*2+0]&3));
  358. bright = (lt[o]>>4)*12 + 15 + (sky[o]>>4)*16;
  359. if (bright > 255) bright = 255;
  360. if (bright < 32) bright = 32;
  361. outb[o*2+1] = STBVOX_MAKE_LIGHTING_EXT((unsigned char) bright, (rot[o*2+1]&3));
  362. }
  363. } else {
  364. // @TODO: if blocktype is in between others, this breaks; need to find which side has two pointers, and use that
  365. // overwrite rot[] array, then copy out
  366. #ifdef IN_PLACE
  367. outb = (dd < sky) ? dd : sky;
  368. if (lt < outb) lt = outb;
  369. #endif
  370. for (o=0; o < 16*16*16/2; ++o) {
  371. int bright;
  372. bright = (lt[o]&15)*12 + 15 + (sky[o]&15)*16;
  373. if (bright > 255) bright = 255;
  374. if (bright < 32) bright = 32;
  375. rot[o*2+0] = STBVOX_MAKE_LIGHTING_EXT((unsigned char) bright, (rot[o*2+0]&3));
  376. bright = (lt[o]>>4)*12 + 15 + (sky[o]>>4)*16;
  377. if (bright > 255) bright = 255;
  378. if (bright < 32) bright = 32;
  379. rot[o*2+1] = STBVOX_MAKE_LIGHTING_EXT((unsigned char) bright, (rot[o*2+1]&3));
  380. }
  381. memcpy(outb, rot, 4096);
  382. fc->data[i] = outb;
  383. }
  384. #ifndef IN_PLACE
  385. fc->blockdata[i] = out;
  386. fc->data[i] = outb;
  387. #endif
  388. }
  389. }
  390. #ifndef IN_PLACE
  391. free(fc->pointer_to_free);
  392. fc->pointer_to_free = storage;
  393. #endif
  394. }
  395. void make_converted_fastchunk(fast_chunk *fc, int x, int y, int segment, uint8 *sv_blocktype, uint8 *sv_lighting)
  396. {
  397. int z;
  398. assert(fc == NULL || (fc->refcount > 0 && fc->refcount < 64));
  399. if (fc == NULL || fc->blockdata[segment] == NULL) {
  400. for (z=0; z < 16; ++z) {
  401. sv_blocktype[z] = C_empty;
  402. sv_lighting[z] = 255;
  403. }
  404. } else {
  405. unsigned char *block = fc->blockdata[segment];
  406. unsigned char *data = fc->data[segment];
  407. y = 15-y;
  408. for (z=0; z < 16; ++z) {
  409. sv_blocktype[z] = block[z*256 + y*16 + x];
  410. sv_lighting [z] = data [z*256 + y*16 + x];
  411. }
  412. }
  413. }
  414. #define CHUNK_CACHE 64
  415. typedef struct
  416. {
  417. int valid;
  418. int chunk_x, chunk_y;
  419. fast_chunk *fc;
  420. } cached_converted_chunk;
  421. cached_converted_chunk chunk_cache[CHUNK_CACHE][CHUNK_CACHE];
  422. int cache_size = CHUNK_CACHE;
  423. void reset_cache_size(int size)
  424. {
  425. int i,j;
  426. for (j=size; j < cache_size; ++j) {
  427. for (i=size; i < cache_size; ++i) {
  428. cached_converted_chunk *ccc = &chunk_cache[j][i];
  429. if (ccc->valid) {
  430. if (ccc->fc) {
  431. free(ccc->fc->pointer_to_free);
  432. free(ccc->fc);
  433. ccc->fc = NULL;
  434. }
  435. ccc->valid = 0;
  436. }
  437. }
  438. }
  439. cache_size = size;
  440. }
  441. // this must be called inside mutex
  442. void deref_fastchunk(fast_chunk *fc)
  443. {
  444. if (fc) {
  445. assert(fc->refcount > 0);
  446. --fc->refcount;
  447. if (fc->refcount == 0) {
  448. free(fc->pointer_to_free);
  449. free(fc);
  450. }
  451. }
  452. }
  453. SDL_mutex * chunk_cache_mutex;
  454. SDL_mutex * chunk_get_mutex;
  455. void lock_chunk_get_mutex(void)
  456. {
  457. SDL_LockMutex(chunk_get_mutex);
  458. }
  459. void unlock_chunk_get_mutex(void)
  460. {
  461. SDL_UnlockMutex(chunk_get_mutex);
  462. }
  463. fast_chunk *get_converted_fastchunk(int chunk_x, int chunk_y)
  464. {
  465. int slot_x = (chunk_x & (cache_size-1));
  466. int slot_y = (chunk_y & (cache_size-1));
  467. fast_chunk *fc;
  468. cached_converted_chunk *ccc;
  469. SDL_LockMutex(chunk_cache_mutex);
  470. ccc = &chunk_cache[slot_y][slot_x];
  471. if (ccc->valid) {
  472. if (ccc->chunk_x == chunk_x && ccc->chunk_y == chunk_y) {
  473. fast_chunk *fc = ccc->fc;
  474. if (fc)
  475. ++fc->refcount;
  476. SDL_UnlockMutex(chunk_cache_mutex);
  477. return fc;
  478. }
  479. if (ccc->fc) {
  480. deref_fastchunk(ccc->fc);
  481. ccc->fc = NULL;
  482. ccc->valid = 0;
  483. }
  484. }
  485. SDL_UnlockMutex(chunk_cache_mutex);
  486. fc = get_decoded_fastchunk_uncached(chunk_x, -chunk_y);
  487. if (fc)
  488. convert_fastchunk_inplace(fc);
  489. SDL_LockMutex(chunk_cache_mutex);
  490. // another thread might have updated it, so before we overwrite it...
  491. if (ccc->fc) {
  492. deref_fastchunk(ccc->fc);
  493. ccc->fc = NULL;
  494. }
  495. if (fc)
  496. fc->refcount = 1; // 1 in the cache
  497. ccc->chunk_x = chunk_x;
  498. ccc->chunk_y = chunk_y;
  499. ccc->valid = 1;
  500. if (fc)
  501. ++fc->refcount;
  502. ccc->fc = fc;
  503. SDL_UnlockMutex(chunk_cache_mutex);
  504. return fc;
  505. }
  506. void make_map_segment_for_superchunk_preconvert(int chunk_x, int chunk_y, int segment, fast_chunk *fc_table[4][4], uint8 sv_blocktype[34][34][18], uint8 sv_lighting[34][34][18])
  507. {
  508. int a,b;
  509. assert((chunk_x & 1) == 0);
  510. assert((chunk_y & 1) == 0);
  511. for (b=-1; b < 3; ++b) {
  512. for (a=-1; a < 3; ++a) {
  513. int xo = a*16+1;
  514. int yo = b*16+1;
  515. int x,y;
  516. fast_chunk *fc = fc_table[b+1][a+1];
  517. for (y=0; y < 16; ++y)
  518. for (x=0; x < 16; ++x)
  519. if (xo+x >= 0 && xo+x < 34 && yo+y >= 0 && yo+y < 34)
  520. make_converted_fastchunk(fc,x,y, segment, sv_blocktype[xo+x][yo+y], sv_lighting[xo+x][yo+y]);
  521. }
  522. }
  523. }
  524. // build 1 mesh covering 2x2 chunks
  525. void build_chunk(int chunk_x, int chunk_y, fast_chunk *fc_table[4][4], raw_mesh *rm)
  526. {
  527. int a,b,z;
  528. stbvox_input_description *map;
  529. #ifdef VHEIGHT_TEST
  530. unsigned char vheight[34][34][18];
  531. #endif
  532. #ifndef STBVOX_CONFIG_DISABLE_TEX2
  533. unsigned char tex2_choice[34][34][18];
  534. #endif
  535. assert((chunk_x & 1) == 0);
  536. assert((chunk_y & 1) == 0);
  537. rm->cx = chunk_x;
  538. rm->cy = chunk_y;
  539. stbvox_set_input_stride(&rm->mm, 34*18, 18);
  540. assert(rm->mm.input.geometry == NULL);
  541. map = stbvox_get_input_description(&rm->mm);
  542. map->block_tex1_face = minecraft_tex1_for_blocktype;
  543. map->block_color_face = minecraft_color_for_blocktype;
  544. map->block_geometry = minecraft_geom_for_blocktype;
  545. stbvox_reset_buffers(&rm->mm);
  546. stbvox_set_buffer(&rm->mm, 0, 0, rm->build_buffer, BUILD_BUFFER_SIZE);
  547. stbvox_set_buffer(&rm->mm, 0, 1, rm->face_buffer , FACE_BUFFER_SIZE);
  548. map->blocktype = &rm->sv_blocktype[1][1][1]; // this is (0,0,0), but we need to be able to query off the edges
  549. map->lighting = &rm->sv_lighting[1][1][1];
  550. // fill in the top two rows of the buffer
  551. for (a=0; a < 34; ++a) {
  552. for (b=0; b < 34; ++b) {
  553. rm->sv_blocktype[a][b][16] = 0;
  554. rm->sv_lighting [a][b][16] = 255;
  555. rm->sv_blocktype[a][b][17] = 0;
  556. rm->sv_lighting [a][b][17] = 255;
  557. }
  558. }
  559. #ifndef STBVOX_CONFIG_DISABLE_TEX2
  560. for (a=0; a < 34; ++a) {
  561. for (b=0; b < 34; ++b) {
  562. int px = chunk_x*16 + a - 1;
  563. int py = chunk_y*16 + b - 1;
  564. float dist = (float) sqrt(px*px + py*py);
  565. float s1 = (float) sin(dist / 16), s2, s3;
  566. dist = (float) sqrt((px-80)*(px-80) + (py-50)*(py-50));
  567. s2 = (float) sin(dist / 11);
  568. for (z=0; z < 18; ++z) {
  569. s3 = (float) sin(z * 3.141592 / 8);
  570. s3 = s1*s2*s3;
  571. tex2_choice[a][b][z] = 63 & (int) stb_linear_remap(s3,-1,1, -20,83);
  572. }
  573. }
  574. }
  575. #endif
  576. for (z=256-16; z >= SKIP_TERRAIN; z -= 16)
  577. {
  578. int z0 = z;
  579. int z1 = z+16;
  580. if (z1 == 256) z1 = 255;
  581. make_map_segment_for_superchunk_preconvert(chunk_x, chunk_y, z >> 4, fc_table, rm->sv_blocktype, rm->sv_lighting);
  582. map->blocktype = &rm->sv_blocktype[1][1][1-z]; // specify location of 0,0,0 so that accessing z0..z1 gets right data
  583. map->lighting = &rm->sv_lighting[1][1][1-z];
  584. #ifndef STBVOX_CONFIG_DISABLE_TEX2
  585. map->tex2 = &tex2_choice[1][1][1-z];
  586. #endif
  587. #ifdef VHEIGHT_TEST
  588. // hacky test of vheight
  589. for (a=0; a < 34; ++a) {
  590. for (b=0; b < 34; ++b) {
  591. int c;
  592. for (c=0; c < 17; ++c) {
  593. if (rm->sv_blocktype[a][b][c] != 0 && rm->sv_blocktype[a][b][c+1] == 0) {
  594. // topmost block
  595. vheight[a][b][c] = rand() & 255;
  596. rm->sv_blocktype[a][b][c] = 168;
  597. } else if (c > 0 && rm->sv_blocktype[a][b][c] != 0 && rm->sv_blocktype[a][b][c-1] == 0) {
  598. // bottommost block
  599. vheight[a][b][c] = ((rand() % 3) << 6) + ((rand() % 3) << 4) + ((rand() % 3) << 2) + (rand() % 3);
  600. rm->sv_blocktype[a][b][c] = 169;
  601. }
  602. }
  603. vheight[a][b][c] = STBVOX_MAKE_VHEIGHT(2,2,2,2); // flat top
  604. }
  605. }
  606. map->vheight = &vheight[1][1][1-z];
  607. #endif
  608. {
  609. stbvox_set_input_range(&rm->mm, 0,0,z0, 32,32,z1);
  610. stbvox_set_default_mesh(&rm->mm, 0);
  611. stbvox_make_mesh(&rm->mm);
  612. }
  613. // copy the bottom two rows of data up to the top
  614. for (a=0; a < 34; ++a) {
  615. for (b=0; b < 34; ++b) {
  616. rm->sv_blocktype[a][b][16] = rm->sv_blocktype[a][b][0];
  617. rm->sv_blocktype[a][b][17] = rm->sv_blocktype[a][b][1];
  618. rm->sv_lighting [a][b][16] = rm->sv_lighting [a][b][0];
  619. rm->sv_lighting [a][b][17] = rm->sv_lighting [a][b][1];
  620. }
  621. }
  622. }
  623. stbvox_set_mesh_coordinates(&rm->mm, chunk_x*16, chunk_y*16, 0);
  624. stbvox_get_transform(&rm->mm, rm->transform);
  625. stbvox_set_input_range(&rm->mm, 0,0,0, 32,32,255);
  626. stbvox_get_bounds(&rm->mm, rm->bounds);
  627. rm->num_quads = stbvox_get_quad_count(&rm->mm, 0);
  628. }
  629. int next_blocktype = 255;
  630. unsigned char mc_rot[4] = { 1,3,2,0 };
  631. // create blocktypes with rotation baked into type...
  632. // @TODO we no longer need this now that we store rotations
  633. // in lighting
  634. void build_stair_rotations(int blocktype, unsigned char *map)
  635. {
  636. int i;
  637. // use the existing block type for floor stairs; allocate a new type for ceil stairs
  638. for (i=0; i < 6; ++i) {
  639. minecraft_color_for_blocktype[next_blocktype][i] = minecraft_color_for_blocktype[blocktype][i];
  640. minecraft_tex1_for_blocktype [next_blocktype][i] = minecraft_tex1_for_blocktype [blocktype][i];
  641. }
  642. minecraft_geom_for_blocktype[next_blocktype] = (unsigned char) STBVOX_MAKE_GEOMETRY(STBVOX_GEOM_ceil_slope_north_is_bottom, 0, 0);
  643. minecraft_geom_for_blocktype[ blocktype] = (unsigned char) STBVOX_MAKE_GEOMETRY(STBVOX_GEOM_floor_slope_north_is_top, 0, 0);
  644. for (i=0; i < 4; ++i) {
  645. map[0+i+8] = map[0+i] = blocktype;
  646. map[4+i+8] = map[4+i] = next_blocktype;
  647. }
  648. --next_blocktype;
  649. }
  650. void build_wool_variations(int bt, unsigned char *map)
  651. {
  652. int i,k;
  653. unsigned char tex[16] = { 64, 210, 194, 178, 162, 146, 130, 114, 225, 209, 193, 177, 161, 145, 129, 113 };
  654. for (i=0; i < 16; ++i) {
  655. if (i == 0)
  656. map[i] = bt;
  657. else {
  658. map[i] = next_blocktype;
  659. for (k=0; k < 6; ++k) {
  660. minecraft_tex1_for_blocktype[next_blocktype][k] = tex[i];
  661. }
  662. minecraft_geom_for_blocktype[next_blocktype] = minecraft_geom_for_blocktype[bt];
  663. --next_blocktype;
  664. }
  665. }
  666. }
  667. void build_wood_variations(int bt, unsigned char *map)
  668. {
  669. int i,k;
  670. unsigned char tex[4] = { 5, 198, 214, 199 };
  671. for (i=0; i < 4; ++i) {
  672. if (i == 0)
  673. map[i] = bt;
  674. else {
  675. map[i] = next_blocktype;
  676. for (k=0; k < 6; ++k) {
  677. minecraft_tex1_for_blocktype[next_blocktype][k] = tex[i];
  678. }
  679. minecraft_geom_for_blocktype[next_blocktype] = minecraft_geom_for_blocktype[bt];
  680. --next_blocktype;
  681. }
  682. }
  683. map[i] = map[i-1];
  684. ++i;
  685. for (; i < 16; ++i)
  686. map[i] = bt;
  687. }
  688. void remap_in_place(int bt, int rm)
  689. {
  690. int i;
  691. remap[bt] = rm;
  692. for (i=0; i < 16; ++i)
  693. remap_data[rm][i] = bt;
  694. }
  695. void mesh_init(void)
  696. {
  697. int i;
  698. chunk_cache_mutex = SDL_CreateMutex();
  699. chunk_get_mutex = SDL_CreateMutex();
  700. for (i=0; i < 256; ++i) {
  701. memcpy(minecraft_tex1_for_blocktype[i], minecraft_info[i]+1, 6);
  702. effective_blocktype[i] = (minecraft_info[i][0] == C_empty ? 0 : i);
  703. minecraft_geom_for_blocktype[i] = geom_map[minecraft_info[i][0]];
  704. }
  705. //effective_blocktype[50] = 0; // delete torches
  706. for (i=0; i < 6*256; ++i) {
  707. if (minecraft_tex1_for_blocktype[0][i] == 40)
  708. minecraft_color_for_blocktype[0][i] = 38 | 64; // apply to tex1
  709. if (minecraft_tex1_for_blocktype[0][i] == 39)
  710. minecraft_color_for_blocktype[0][i] = 39 | 64; // apply to tex1
  711. if (minecraft_tex1_for_blocktype[0][i] == 105)
  712. minecraft_color_for_blocktype[0][i] = 63; // emissive
  713. if (minecraft_tex1_for_blocktype[0][i] == 212)
  714. minecraft_color_for_blocktype[0][i] = 63; // emissive
  715. if (minecraft_tex1_for_blocktype[0][i] == 80)
  716. minecraft_color_for_blocktype[0][i] = 63; // emissive
  717. }
  718. for (i=0; i < 6; ++i) {
  719. minecraft_color_for_blocktype[172][i] = 47 | 64; // apply to tex1
  720. minecraft_color_for_blocktype[178][i] = 47 | 64; // apply to tex1
  721. minecraft_color_for_blocktype[18][i] = 39 | 64; // green
  722. minecraft_color_for_blocktype[161][i] = 37 | 64; // green
  723. minecraft_color_for_blocktype[10][i] = 63; // emissive lava
  724. minecraft_color_for_blocktype[11][i] = 63; // emissive
  725. //minecraft_color_for_blocktype[56][i] = 63; // emissive diamond
  726. minecraft_color_for_blocktype[48][i] = 63; // emissive dungeon
  727. }
  728. #ifdef VHEIGHT_TEST
  729. effective_blocktype[168] = 168;
  730. minecraft_tex1_for_blocktype[168][0] = 1;
  731. minecraft_tex1_for_blocktype[168][1] = 1;
  732. minecraft_tex1_for_blocktype[168][2] = 1;
  733. minecraft_tex1_for_blocktype[168][3] = 1;
  734. minecraft_tex1_for_blocktype[168][4] = 1;
  735. minecraft_tex1_for_blocktype[168][5] = 1;
  736. minecraft_geom_for_blocktype[168] = STBVOX_GEOM_floor_vheight_12;
  737. effective_blocktype[169] = 169;
  738. minecraft_tex1_for_blocktype[169][0] = 1;
  739. minecraft_tex1_for_blocktype[169][1] = 1;
  740. minecraft_tex1_for_blocktype[169][2] = 1;
  741. minecraft_tex1_for_blocktype[169][3] = 1;
  742. minecraft_tex1_for_blocktype[169][4] = 1;
  743. minecraft_tex1_for_blocktype[169][5] = 1;
  744. minecraft_geom_for_blocktype[169] = STBVOX_GEOM_ceil_vheight_03;
  745. #endif
  746. remap[53] = 1;
  747. remap[67] = 2;
  748. remap[108] = 3;
  749. remap[109] = 4;
  750. remap[114] = 5;
  751. remap[136] = 6;
  752. remap[156] = 7;
  753. for (i=0; i < 256; ++i)
  754. if (remap[i])
  755. build_stair_rotations(i, remap_data[remap[i]]);
  756. remap[35] = 8;
  757. build_wool_variations(35, remap_data[remap[35]]);
  758. remap[5] = 11;
  759. build_wood_variations(5, remap_data[remap[5]]);
  760. // set the remap flags for these so they write the rotation values
  761. remap_in_place(54, 9);
  762. remap_in_place(146, 10);
  763. }
  764. // Timing stats while optimizing the single-threaded builder
  765. // 32..-32, 32..-32, SKIP_TERRAIN=0, !FANCY_LEAVES on 'mcrealm' data set
  766. // 6.27s - reblocked to do 16 z at a time instead of 256 (still using 66x66x258), 4 meshes in parallel
  767. // 5.96s - reblocked to use FAST_CHUNK (no intermediate data structure)
  768. // 5.45s - unknown change, or previous measurement was wrong
  769. // 6.12s - use preconverted data, not in-place
  770. // 5.91s - use preconverted, in-place
  771. // 5.34s - preconvert, in-place, avoid dependency chain (suggested by ryg)
  772. // 5.34s - preconvert, in-place, avoid dependency chain, use bit-table instead of byte-table
  773. // 5.50s - preconvert, in-place, branchless
  774. // 6.42s - non-preconvert, avoid dependency chain (not an error)
  775. // 5.40s - non-preconvert, w/dependency chain (same as earlier)
  776. // 5.50s - non-FAST_CHUNK, reblocked outer loop for better cache reuse
  777. // 4.73s - FAST_CHUNK non-preconvert, reblocked outer loop
  778. // 4.25s - preconvert, in-place, reblocked outer loop
  779. // 4.18s - preconvert, in-place, unrolled again
  780. // 4.10s - 34x34 1 mesh instead of 66x66 and 4 meshes (will make it easier to do multiple threads)
  781. // 4.83s - building bitmasks but not using them (2 bits per block, one if empty, one if solid)
  782. // 5.16s - using empty bitmasks to early out
  783. // 5.01s - using solid & empty bitmasks to early out - "foo"
  784. // 4.64s - empty bitmask only, test 8 at a time, then test geom
  785. // 4.72s - empty bitmask only, 8 at a time, then test bits
  786. // 4.46s - split bitmask building into three loops (each byte is separate)
  787. // 4.42s - further optimize computing bitmask
  788. // 4.58s - using solid & empty bitmasks to early out, same as "foo" but faster bitmask building
  789. // 4.12s - using solid & empty bitmasks to efficiently test neighbors
  790. // 4.04s - using 16-bit fetches (not endian-independent)
  791. // - note this is first place that beats previous best '4.10s - 34x34 1 mesh'
  792. // 4.30s - current time with bitmasks disabled again (note was 4.10s earlier)
  793. // 3.95s - bitmasks enabled again, no other changes
  794. // 4.00s - current time with bitmasks disabled again, no other changes -- wide variation that is time dependent?
  795. // (note that most of the numbers listed here are median of 3 values already)
  796. // 3.98s - bitmasks enabled
  797. // Bitmasks removed from the code as not worth the complexity increase
  798. // Raw data for Q&A:
  799. //
  800. // 26% parsing & loading minecraft files (4/5ths of which is zlib decode)
  801. // 39% building mesh from stb input format
  802. // 18% converting from minecraft blocks to stb blocks
  803. // 9% reordering from minecraft axis order to stb axis order
  804. // 7% uploading vertex buffer to OpenGL