mirror of
https://github.com/nothings/stb
synced 2024-12-15 12:22:55 +03:00
760 lines
22 KiB
C
760 lines
22 KiB
C
// This file takes minecraft chunks (decoded by cave_parse) and
|
|
// uses stb_voxel_render to turn them into vertex buffers.
|
|
|
|
#define STB_GLEXT_DECLARE "glext_list.h"
|
|
#include "stb_gl.h"
|
|
#include "stb_image.h"
|
|
#include "stb_glprog.h"
|
|
|
|
#include "caveview.h"
|
|
#include "cave_parse.h"
|
|
#include "stb.h"
|
|
#include "sdl.h"
|
|
#include "sdl_thread.h"
|
|
#include <math.h>
|
|
|
|
#define STB_VOXEL_RENDER_IMPLEMENTATION
|
|
#define STBVOX_ROTATION_IN_LIGHTING
|
|
#include "stb_voxel_render.h"
|
|
|
|
extern void ods(char *fmt, ...);
|
|
|
|
#define FANCY_LEAVES // nearly 2x the triangles when enabled (if underground is filled)
|
|
#define FAST_CHUNK
|
|
#define IN_PLACE
|
|
|
|
#define SKIP_TERRAIN 0 // must be a multiple of 16; doesn't build some underground stuff
|
|
|
|
enum
|
|
{
|
|
C_empty,
|
|
C_solid,
|
|
C_trans,
|
|
C_cross,
|
|
C_water,
|
|
C_slab,
|
|
C_stair,
|
|
C_force,
|
|
};
|
|
|
|
unsigned char geom_map[] =
|
|
{
|
|
STBVOX_GEOM_empty,
|
|
STBVOX_GEOM_solid,
|
|
STBVOX_GEOM_transp,
|
|
STBVOX_GEOM_crossed_pair,
|
|
STBVOX_GEOM_solid,
|
|
STBVOX_GEOM_slab_lower,
|
|
STBVOX_GEOM_floor_slope_north_is_top,
|
|
STBVOX_GEOM_force,
|
|
};
|
|
|
|
unsigned char minecraft_info[256][7] =
|
|
{
|
|
{ C_empty, 0,0,0,0,0,0 },
|
|
{ C_solid, 1,1,1,1,1,1 },
|
|
{ C_solid, 3,3,3,3,40,2 },
|
|
{ C_solid, 2,2,2,2,2,2 },
|
|
{ C_solid, 16,16,16,16,16,16 },
|
|
{ C_solid, 4,4,4,4,4,4 },
|
|
{ C_cross, 15,15,15,15 },
|
|
{ C_solid, 17,17,17,17,17,17 },
|
|
|
|
// 8
|
|
{ C_water, 223,223,223,223,223,223 },
|
|
{ C_water, 223,223,223,223,223,223 },
|
|
{ C_solid, 255,255,255,255,255,255 },
|
|
{ C_solid, 255,255,255,255,255,255 },
|
|
{ C_solid, 18,18,18,18,18,18 },
|
|
{ C_solid, 19,19,19,19,19,19 },
|
|
{ C_solid, 32,32,32,32,32,32 },
|
|
{ C_solid, 33,33,33,33,33,33 },
|
|
|
|
// 16
|
|
{ C_solid, 34,34,34,34,34,34 },
|
|
{ C_solid, 20,20,20,20,21,21 },
|
|
#ifdef FANCY_LEAVES
|
|
{ C_force, 52,52,52,52,52,52 }, // leaves
|
|
#else
|
|
{ C_solid, 53,53,53,53,53,53 }, // leaves
|
|
#endif
|
|
{ C_solid, 24,24,24,24,24,24 },
|
|
{ C_trans, 49,49,49,49,49,49 }, // glass
|
|
{ C_solid, 160,160,160,160,160,160 },
|
|
{ C_solid, 144,144,144,144,144,144 },
|
|
{ C_solid, 46,45,45,45,62,62 },
|
|
|
|
// 24
|
|
{ C_solid, 192,192,192,192, 176,176 },
|
|
{ C_solid, 74,74,74,74,74,74 },
|
|
{ C_empty }, // bed
|
|
{ C_empty }, // powered rail
|
|
{ C_empty }, // detector rail
|
|
{ C_solid, 106,108,109,108,108,108 },
|
|
{ C_empty }, // cobweb=11
|
|
{ C_cross, 39,39,39,39 },
|
|
|
|
// 32
|
|
{ C_cross, 55,55,55,55,0,0 },
|
|
{ C_solid, 107,108,109,108,108,108 },
|
|
{ C_empty }, // piston head
|
|
{ C_solid, 64,64,64,64,64,64 }, // various colors
|
|
{ C_empty }, // unused
|
|
{ C_cross, 13,13,13,13,0,0 },
|
|
{ C_cross, 12,12,12,12,0,0 },
|
|
{ C_cross, 29,29,29,29,0,0 },
|
|
|
|
// 40
|
|
{ C_cross, 28,28,28,28,0,0 },
|
|
{ C_solid, 23,23,23,23,23,23 },
|
|
{ C_solid, 22,22,22,22,22,22 },
|
|
{ C_solid, 5,5,5,5,6,6, },
|
|
{ C_slab , 5,5,5,5,6,6, },
|
|
{ C_solid, 7,7,7,7,7,7, },
|
|
{ C_solid, 8,8,8,8,9,10 },
|
|
{ C_solid, 35,35,35,35,4,4, },
|
|
|
|
// 48
|
|
{ C_solid, 36,36,36,36,36,36 },
|
|
{ C_solid, 37,37,37,37,37,37 },
|
|
{ C_cross, 80,80,80,80,80,80 }, // torch
|
|
{ C_empty }, // fire
|
|
{ C_trans, 65,65,65,65,65,65 },
|
|
{ C_stair, 4,4,4,4,4,4 },
|
|
{ C_solid, 27,26,26,26,25,25 },
|
|
{ C_empty }, // redstone
|
|
|
|
// 56
|
|
{ C_solid, 50,50,50,50,50,50 },
|
|
{ C_solid, 26,26,26,26,26,26 },
|
|
{ C_solid, 60,59,59,59,43,43 },
|
|
{ C_cross, 95,95,95,95 },
|
|
{ C_solid, 2,2,2,2,86,2 },
|
|
{ C_solid, 44,45,45,45,62,62 },
|
|
{ C_solid, 61,45,45,45,62,62 },
|
|
{ C_empty }, // sign
|
|
|
|
// 64
|
|
{ C_empty }, // door
|
|
{ C_empty }, // ladder
|
|
{ C_empty }, // rail
|
|
{ C_stair, 16,16,16,16,16,16 }, // cobblestone stairs
|
|
{ C_empty }, // sign
|
|
{ C_empty }, // lever
|
|
{ C_empty }, // stone pressure plate
|
|
{ C_empty }, // iron door
|
|
|
|
// 72
|
|
{ C_empty }, // wooden pressure
|
|
{ C_solid, 51,51,51,51,51,51 },
|
|
{ C_solid, 51,51,51,51,51,51 },
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_empty }, // snow on block below, do as half slab?
|
|
{ C_solid, 67,67,67,67,67,67 },
|
|
|
|
// 80
|
|
{ C_solid, 66,66,66,66,66,66 },
|
|
{ C_solid, 70,70,70,70,69,71 },
|
|
{ C_solid, 72,72,72,72,72,72 },
|
|
{ C_cross, 73,73,73,73,73,73 },
|
|
{ C_solid, 74,74,74,74,75,74 },
|
|
{ C_empty }, // fence
|
|
{ C_solid,119,118,118,118,102,102 },
|
|
{ C_solid,103,103,103,103,103,103 },
|
|
|
|
// 88
|
|
{ C_solid, 104,104,104,104,104,104 },
|
|
{ C_solid, 105,105,105,105,105,105 },
|
|
{ C_solid, 167,167,167,167,167,167 },
|
|
{ C_solid, 120,118,118,118,102,102 },
|
|
{ C_empty }, // cake
|
|
{ C_empty }, // repeater
|
|
{ C_empty }, // repeater
|
|
{ C_solid, 49,49,49,49,49,49 }, // colored glass
|
|
|
|
// 96
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_solid, 54,54,54,54,54,54 },
|
|
{ C_solid, 125,125,125,125,125,125 },
|
|
{ C_solid, 124,124,124,124,124,124 },
|
|
{ C_empty }, // bars
|
|
{ C_trans, 49,49,49,49,49,49 }, // glass pane
|
|
{ C_solid, 136,136,136,136,137,137 }, // melon
|
|
|
|
// 104
|
|
{ C_empty }, // pumpkin stem
|
|
{ C_empty }, // melon stem
|
|
{ C_empty }, // vines
|
|
{ C_empty }, // gate
|
|
{ C_stair, 7,7,7,7,7,7, }, // brick stairs
|
|
{ C_stair, 54,54,54,54,54,54 }, // stone brick stairs
|
|
{ C_empty }, // mycelium
|
|
{ C_empty }, // lily pad
|
|
|
|
// 112
|
|
{ C_solid, 224,224,224,224,224,224 },
|
|
{ C_empty }, // nether brick fence
|
|
{ C_stair, 224,224,224,224,224,224 }, // nether brick stairs
|
|
{ C_empty }, // nether wart
|
|
{ C_solid, 182,182,182,182,166,183 },
|
|
{ C_empty }, // brewing stand
|
|
{ C_empty }, // cauldron
|
|
{ C_empty }, // end portal
|
|
|
|
// 120
|
|
{ C_solid, 159,159,159,159,158,158 },
|
|
{ C_solid, 175,175,175,175,175,175 },
|
|
{ C_empty }, // dragon egg
|
|
{ C_solid, 211,211,211,211,211,211 },
|
|
{ C_solid, 212,212,212,212,212,212 },
|
|
{ C_solid, 4,4,4,4,4,4, }, // wood double-slab
|
|
{ C_slab , 4,4,4,4,4,4, }, // wood slab
|
|
{ C_empty }, // cocoa
|
|
|
|
// 128
|
|
{ C_solid, 192,192,192,192,176,176 }, // sandstone stairs
|
|
{ C_solid, 32,32,32,32,32,32 }, // emerald ore
|
|
{ C_empty }, // ender chest
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_solid, 23,23,23,23,23,23 }, // emerald block
|
|
{ C_solid, 198,198,198,198,198,198 }, // spruce stairs
|
|
{ C_solid, 214,214,214,214,214,214 }, // birch stairs
|
|
|
|
// 136
|
|
{ C_stair, 199,199,199,199,199,199 }, // jungle stairs
|
|
{ C_empty }, // command block
|
|
{ C_empty }, // beacon
|
|
{ C_slab, 16,16,16,16,16,16 }, // cobblestone wall
|
|
{ C_empty }, // flower pot
|
|
{ C_empty }, // carrot
|
|
{ C_empty }, // potatoes
|
|
{ C_empty }, // wooden button
|
|
|
|
// 144
|
|
{ C_empty }, // mob head
|
|
{ C_empty }, // anvil
|
|
{ C_solid, 27,26,26,26,25,25 }, // trapped chest
|
|
{ C_empty }, // weighted pressure plate light
|
|
{ C_empty }, // weighted pressure plat eheavy
|
|
{ C_empty }, // comparator inactive
|
|
{ C_empty }, // comparator active
|
|
{ C_empty }, // daylight sensor
|
|
|
|
// 152
|
|
{ C_solid, 135,135,135,135,135,135 }, // redstone block
|
|
{ C_solid, 0,0,0,0,0,0, }, // nether quartz ore
|
|
{ C_empty }, // hopper
|
|
{ C_solid, 22,22,22,22,22,22 }, // quartz block
|
|
{ C_stair, 22,22,22,22,22,22 }, // quartz stairs
|
|
{ C_empty }, // activator rail
|
|
{ C_solid, 46,45,45,45,62,62 }, // dropper
|
|
{ C_solid, 72,72,72,72,72,72 }, // stained clay
|
|
|
|
// 160
|
|
{ C_trans, 49,49,49,49,49,49 }, // stained glass pane
|
|
#ifdef FANCY_LEAVES
|
|
{ C_force, 52,52,52,52,52,52 }, // leaves
|
|
#else
|
|
{ C_solid, 53,53,53,53,53,53 }, // acacia leaves
|
|
#endif
|
|
{ C_solid, 20,20,20,20,21,21 }, // acacia tree
|
|
{ C_solid, 199,199,199,199,199,199 }, // acacia wood stairs
|
|
{ C_solid, 198,198,198,198,198,198 }, // dark oak stairs
|
|
{ C_solid, 146,146,146,146,146,146 }, // slime block
|
|
|
|
{ C_solid, 176,176,176,176,176,176 }, // red sandstone
|
|
{ C_solid, 176,176,176,176,176,176 }, // red sandstone
|
|
|
|
// 168
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_solid, 72,72,72,72,72,72 }, // hardened clay
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_empty },
|
|
|
|
// 176
|
|
{ C_empty },
|
|
{ C_empty },
|
|
{ C_solid, 176,176,176,176,176,176 }, // red sandstone
|
|
};
|
|
|
|
unsigned char minecraft_tex1_for_blocktype[256][6];
|
|
unsigned char effective_blocktype[256];
|
|
unsigned char effective_block_add[256];
|
|
unsigned char minecraft_color_for_blocktype[256][6];
|
|
unsigned char minecraft_geom_for_blocktype[256];
|
|
|
|
uint8 build_buffer[BUILD_BUFFER_SIZE];
|
|
uint8 face_buffer[FACE_BUFFER_SIZE];
|
|
|
|
//GLuint vbuf, fbuf, fbuf_tex;
|
|
|
|
//unsigned char tex1_for_blocktype[256][6];
|
|
|
|
//unsigned char blocktype[34][34][257];
|
|
//unsigned char lighting[34][34][257];
|
|
|
|
// a superchunk is 64x64x256, with the border blocks computed as well,
|
|
// which means we need 4x4 chunks plus 16 border chunks plus 4 corner chunks
|
|
|
|
#define SUPERCHUNK_X 4
|
|
#define SUPERCHUNK_Y 4
|
|
|
|
unsigned char remap_data[16][16];
|
|
unsigned char remap[256];
|
|
unsigned char rotate_data[4] = { 1,3,2,0 };
|
|
|
|
void convert_fastchunk_inplace(fast_chunk *fc)
|
|
{
|
|
int i;
|
|
int num_blocks=0, step=0;
|
|
unsigned char rot[4096] = { 0 };
|
|
#ifndef IN_PLACE
|
|
unsigned char *storage;
|
|
#endif
|
|
|
|
for (i=0; i < 16; ++i)
|
|
num_blocks += fc->blockdata[i] != NULL;
|
|
|
|
#ifndef IN_PLACE
|
|
storage = malloc(16*16*16*2 * num_blocks);
|
|
#endif
|
|
|
|
for (i=0; i < 16; ++i) {
|
|
if (fc->blockdata[i]) {
|
|
int o=0;
|
|
unsigned char *bd,*dd,*lt,*sky;
|
|
unsigned char *out, *outb;
|
|
|
|
// this ordering allows us to determine which data we can safely overwrite for in-place processing
|
|
bd = fc->blockdata[i];
|
|
dd = fc->data[i];
|
|
lt = fc->light[i];
|
|
sky = fc->skylight[i];
|
|
|
|
#ifdef IN_PLACE
|
|
assert(dd < sky && sky < lt && lt < bd);
|
|
out = bd;
|
|
outb = dd;
|
|
#else
|
|
out = storage + 16*16*16*2*step;
|
|
outb = out + 16*16*16;
|
|
++step;
|
|
#endif
|
|
|
|
for (o=0; o < 16*16*16/2; o += 1) {
|
|
unsigned char v1,v2;
|
|
unsigned char d = dd[o];
|
|
v1 = bd[o*2+0];
|
|
v2 = bd[o*2+1];
|
|
|
|
if (remap[v1])
|
|
{
|
|
//unsigned char d = bd[o] & 15;
|
|
v1 = remap_data[remap[v1]][d&15];
|
|
rot[o] = rotate_data[d&3];
|
|
} else
|
|
v1 = effective_blocktype[v1];
|
|
|
|
if (remap[v2])
|
|
{
|
|
//unsigned char d = bd[o] >> 4;
|
|
v2 = remap_data[remap[v2]][d>>4];
|
|
rot[o+1] = rotate_data[(d>>4)&3];
|
|
} else
|
|
v2 = effective_blocktype[v2];
|
|
|
|
out[o*2+0] = v1;
|
|
out[o*2+1] = v2;
|
|
}
|
|
|
|
// because this stores to data[], can't run at same time as above loop
|
|
for (o=0; o < 16*16*16/2; ++o) {
|
|
int bright;
|
|
bright = (lt[o]&15)*12 + 15 + (sky[o]&15)*16;
|
|
if (bright > 255) bright = 255;
|
|
if (bright < 32) bright = 32;
|
|
outb[o*2+0] = STBVOX_MAKE_LIGHTING((unsigned char) bright, rot[o]);
|
|
|
|
bright = (lt[o]>>4)*12 + 15 + (sky[o]>>4)*16;
|
|
if (bright > 255) bright = 255;
|
|
if (bright < 32) bright = 32;
|
|
outb[o*2+1] = STBVOX_MAKE_LIGHTING((unsigned char) bright, rot[o+1]);
|
|
}
|
|
|
|
#ifndef IN_PLACE
|
|
fc->blockdata[i] = out;
|
|
fc->data[i] = outb;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifndef IN_PLACE
|
|
free(fc->pointer_to_free);
|
|
fc->pointer_to_free = storage;
|
|
#endif
|
|
}
|
|
|
|
void make_converted_fastchunk(fast_chunk *fc, int x, int y, int segment, uint8 *sv_blocktype, uint8 *sv_lighting)
|
|
{
|
|
int z;
|
|
assert(fc == NULL || (fc->refcount > 0 && fc->refcount < 64));
|
|
if (fc == NULL || fc->blockdata[segment] == NULL) {
|
|
for (z=0; z < 16; ++z) {
|
|
sv_blocktype[z] = C_empty;
|
|
sv_lighting[z] = 255;
|
|
}
|
|
} else {
|
|
unsigned char *block = fc->blockdata[segment];
|
|
unsigned char *data = fc->data[segment];
|
|
y = 15-y;
|
|
for (z=0; z < 16; ++z) {
|
|
sv_blocktype[z] = block[z*256 + y*16 + x];
|
|
sv_lighting [z] = data [z*256 + y*16 + x];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#define CHUNK_CACHE 64
|
|
typedef struct
|
|
{
|
|
int valid;
|
|
int chunk_x, chunk_y;
|
|
fast_chunk *fc;
|
|
} cached_converted_chunk;
|
|
|
|
cached_converted_chunk chunk_cache[CHUNK_CACHE][CHUNK_CACHE];
|
|
int cache_size = CHUNK_CACHE;
|
|
|
|
void reset_cache_size(int size)
|
|
{
|
|
int i,j;
|
|
for (j=size; j < cache_size; ++j) {
|
|
for (i=size; i < cache_size; ++i) {
|
|
cached_converted_chunk *ccc = &chunk_cache[j][i];
|
|
if (ccc->valid) {
|
|
if (ccc->fc) {
|
|
free(ccc->fc->pointer_to_free);
|
|
free(ccc->fc);
|
|
ccc->fc = NULL;
|
|
}
|
|
ccc->valid = 0;
|
|
}
|
|
}
|
|
}
|
|
cache_size = size;
|
|
}
|
|
|
|
// this must be called inside mutex
|
|
void deref_fastchunk(fast_chunk *fc)
|
|
{
|
|
if (fc) {
|
|
assert(fc->refcount > 0);
|
|
--fc->refcount;
|
|
if (fc->refcount == 0) {
|
|
free(fc->pointer_to_free);
|
|
free(fc);
|
|
}
|
|
}
|
|
}
|
|
|
|
SDL_mutex * chunk_cache_mutex;
|
|
SDL_mutex * chunk_get_mutex;
|
|
|
|
void lock_chunk_get_mutex(void)
|
|
{
|
|
SDL_LockMutex(chunk_get_mutex);
|
|
}
|
|
void unlock_chunk_get_mutex(void)
|
|
{
|
|
SDL_UnlockMutex(chunk_get_mutex);
|
|
}
|
|
|
|
fast_chunk *get_converted_fastchunk(int chunk_x, int chunk_y)
|
|
{
|
|
int slot_x = (chunk_x & (cache_size-1));
|
|
int slot_y = (chunk_y & (cache_size-1));
|
|
fast_chunk *fc;
|
|
cached_converted_chunk *ccc;
|
|
SDL_LockMutex(chunk_cache_mutex);
|
|
ccc = &chunk_cache[slot_y][slot_x];
|
|
if (ccc->valid) {
|
|
if (ccc->chunk_x == chunk_x && ccc->chunk_y == chunk_y) {
|
|
fast_chunk *fc = ccc->fc;
|
|
if (fc)
|
|
++fc->refcount;
|
|
SDL_UnlockMutex(chunk_cache_mutex);
|
|
return fc;
|
|
}
|
|
if (ccc->fc) {
|
|
deref_fastchunk(ccc->fc);
|
|
ccc->fc = NULL;
|
|
ccc->valid = 0;
|
|
}
|
|
}
|
|
SDL_UnlockMutex(chunk_cache_mutex);
|
|
|
|
fc = get_decoded_fastchunk_uncached(chunk_x, -chunk_y);
|
|
if (fc)
|
|
convert_fastchunk_inplace(fc);
|
|
|
|
SDL_LockMutex(chunk_cache_mutex);
|
|
// another thread might have updated it, so before we overwrite it...
|
|
if (ccc->fc) {
|
|
deref_fastchunk(ccc->fc);
|
|
ccc->fc = NULL;
|
|
}
|
|
|
|
if (fc)
|
|
fc->refcount = 1; // 1 in the cache
|
|
|
|
ccc->chunk_x = chunk_x;
|
|
ccc->chunk_y = chunk_y;
|
|
ccc->valid = 1;
|
|
if (fc)
|
|
++fc->refcount;
|
|
ccc->fc = fc;
|
|
SDL_UnlockMutex(chunk_cache_mutex);
|
|
return fc;
|
|
}
|
|
|
|
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])
|
|
{
|
|
int a,b;
|
|
assert((chunk_x & 1) == 0);
|
|
assert((chunk_y & 1) == 0);
|
|
for (b=-1; b < 3; ++b) {
|
|
for (a=-1; a < 3; ++a) {
|
|
int xo = a*16+1;
|
|
int yo = b*16+1;
|
|
int x,y;
|
|
fast_chunk *fc = fc_table[b+1][a+1];
|
|
for (y=0; y < 16; ++y)
|
|
for (x=0; x < 16; ++x)
|
|
if (xo+x >= 0 && xo+x < 34 && yo+y >= 0 && yo+y < 34)
|
|
make_converted_fastchunk(fc,x,y, segment, sv_blocktype[xo+x][yo+y], sv_lighting[xo+x][yo+y]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void build_chunk(int chunk_x, int chunk_y, fast_chunk *fc_table[4][4], raw_mesh *rm)
|
|
{
|
|
int a,b,z;
|
|
stbvox_input_description *map;
|
|
|
|
//unsigned char vheight[34][34][18];
|
|
|
|
assert((chunk_x & 1) == 0);
|
|
assert((chunk_y & 1) == 0);
|
|
|
|
rm->cx = chunk_x;
|
|
rm->cy = chunk_y;
|
|
|
|
stbvox_set_input_stride(&rm->mm, 34*18, 18);
|
|
|
|
assert(rm->mm.input.geometry == NULL);
|
|
|
|
map = stbvox_get_input_description(&rm->mm);
|
|
map->block_tex1_face = minecraft_tex1_for_blocktype;
|
|
map->block_color_face = minecraft_color_for_blocktype;
|
|
map->block_geometry = minecraft_geom_for_blocktype;
|
|
stbvox_config_set_z_precision(&rm->mm, 1);
|
|
|
|
// we're going to build 4 meshes in parallel, each covering 2x2 chunks
|
|
stbvox_reset_buffers(&rm->mm);
|
|
stbvox_set_buffer(&rm->mm, 0, 0, rm->build_buffer, BUILD_BUFFER_SIZE);
|
|
stbvox_set_buffer(&rm->mm, 0, 1, rm->face_buffer , FACE_BUFFER_SIZE);
|
|
|
|
map->blocktype = &rm->sv_blocktype[1][1][1]; // this is (0,0,0), but we need to be able to query off the edges
|
|
map->lighting = &rm->sv_lighting[1][1][1];
|
|
|
|
// fill in the top two rows of the buffer
|
|
for (a=0; a < 34; ++a) {
|
|
for (b=0; b < 34; ++b) {
|
|
rm->sv_blocktype[a][b][16] = 0;
|
|
rm->sv_lighting [a][b][16] = 255;
|
|
rm->sv_blocktype[a][b][17] = 0;
|
|
rm->sv_lighting [a][b][17] = 255;
|
|
}
|
|
}
|
|
|
|
for (z=256-16; z >= SKIP_TERRAIN; z -= 16)
|
|
{
|
|
int z0 = z;
|
|
int z1 = z+16;
|
|
if (z1 == 256) z1 = 255;
|
|
|
|
make_map_segment_for_superchunk_preconvert(chunk_x, chunk_y, z >> 4, fc_table, rm->sv_blocktype, rm->sv_lighting);
|
|
|
|
map->blocktype = &rm->sv_blocktype[1][1][1-z]; // specify location of 0,0,0 so that accessing z0..z1 gets right data
|
|
map->lighting = &rm->sv_lighting[1][1][1-z];
|
|
|
|
#if 0
|
|
// hacky test of vheight
|
|
for (a=0; a < 34; ++a) {
|
|
for (b=0; b < 34; ++b) {
|
|
int c;
|
|
for (c=0; c < 17; ++c) {
|
|
if (rm->sv_blocktype[a][b][c] != 0 && rm->sv_blocktype[a][b][c+1] == 0) {
|
|
// topmost block
|
|
rm->sv_blocktype[a][b][c] = 168;
|
|
vheight[a][b][c] = rand() & 255;
|
|
}
|
|
}
|
|
vheight[a][b][c] = STBVOX_MAKE_VHEIGHT(2,2,2,2); // flat top
|
|
}
|
|
}
|
|
map->vheight = &vheight[1][1][1-z];
|
|
#endif
|
|
|
|
{
|
|
stbvox_set_input_range(&rm->mm, 0,0,z0, 32,32,z1);
|
|
stbvox_set_default_mesh(&rm->mm, 0);
|
|
stbvox_make_mesh(&rm->mm);
|
|
}
|
|
|
|
// copy the bottom two rows of data up to the top
|
|
for (a=0; a < 34; ++a) {
|
|
for (b=0; b < 34; ++b) {
|
|
rm->sv_blocktype[a][b][16] = rm->sv_blocktype[a][b][0];
|
|
rm->sv_blocktype[a][b][17] = rm->sv_blocktype[a][b][1];
|
|
rm->sv_lighting [a][b][16] = rm->sv_lighting [a][b][0];
|
|
rm->sv_lighting [a][b][17] = rm->sv_lighting [a][b][1];
|
|
}
|
|
}
|
|
}
|
|
|
|
stbvox_set_mesh_coordinates(&rm->mm, chunk_x*16, chunk_y*16, 0);
|
|
stbvox_get_transform(&rm->mm, rm->transform);
|
|
|
|
stbvox_set_input_range(&rm->mm, 0,0,0, 32,32,255);
|
|
stbvox_get_bounds(&rm->mm, rm->bounds);
|
|
|
|
rm->num_quads = stbvox_get_quad_count(&rm->mm, 0);
|
|
}
|
|
|
|
int next_blocktype = 255;
|
|
|
|
unsigned char mc_rot[4] = { 1,3,2,0 };
|
|
|
|
// create blocktypes with rotation baked into type...
|
|
// @TODO we no longer need this now that we store rotations
|
|
// in lighting
|
|
void build_stair_rotations(int blocktype, unsigned char *map)
|
|
{
|
|
int i,j,k;
|
|
for (j=0; j < 2; ++j) {
|
|
int geom = j ? STBVOX_GEOM_ceil_slope_north_is_bottom : STBVOX_GEOM_floor_slope_north_is_top;
|
|
for (i=0; i < 4; ++i) {
|
|
if (i == 0 && j == 0) {
|
|
map[j*4+i+8] = map[j*4+i] = blocktype;
|
|
minecraft_geom_for_blocktype[blocktype] = (unsigned char) STBVOX_MAKE_GEOMETRY(geom, mc_rot[i], 0);
|
|
} else {
|
|
map[j*4+i+8] = map[j*4+i] = next_blocktype;
|
|
|
|
for (k=0; k < 6; ++k) {
|
|
minecraft_color_for_blocktype[next_blocktype][k] = minecraft_color_for_blocktype[blocktype][k];
|
|
minecraft_tex1_for_blocktype [next_blocktype][k] = minecraft_tex1_for_blocktype [blocktype][k];
|
|
}
|
|
minecraft_geom_for_blocktype[next_blocktype] = (unsigned char) STBVOX_MAKE_GEOMETRY(geom, mc_rot[i], 0);
|
|
--next_blocktype;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void build_wool_variations(int bt, unsigned char *map)
|
|
{
|
|
int i,k;
|
|
unsigned char tex[16] = { 64, 210, 194, 178, 162, 146, 130, 114, 225, 209, 193, 177, 161, 145, 129, 113 };
|
|
for (i=0; i < 16; ++i) {
|
|
if (i == 0)
|
|
map[i] = bt;
|
|
else {
|
|
map[i] = next_blocktype;
|
|
for (k=0; k < 6; ++k) {
|
|
minecraft_tex1_for_blocktype[next_blocktype][k] = tex[i];
|
|
minecraft_color_for_blocktype[next_blocktype][k] = 0;
|
|
}
|
|
minecraft_geom_for_blocktype[next_blocktype] = minecraft_geom_for_blocktype[bt];
|
|
--next_blocktype;
|
|
}
|
|
}
|
|
}
|
|
|
|
void mesh_init(void)
|
|
{
|
|
int i;
|
|
|
|
chunk_cache_mutex = SDL_CreateMutex();
|
|
chunk_get_mutex = SDL_CreateMutex();
|
|
|
|
for (i=0; i < 256; ++i) {
|
|
memcpy(minecraft_tex1_for_blocktype[i], minecraft_info[i]+1, 6);
|
|
effective_blocktype[i] = (minecraft_info[i][0] == C_empty ? 0 : i);
|
|
minecraft_geom_for_blocktype[i] = geom_map[minecraft_info[i][0]];
|
|
}
|
|
//effective_blocktype[50] = 0; // delete torches
|
|
|
|
for (i=0; i < 6*256; ++i) {
|
|
if (minecraft_tex1_for_blocktype[0][i] == 40)
|
|
minecraft_color_for_blocktype[0][i] = 38 | 64; // apply to tex1
|
|
if (minecraft_tex1_for_blocktype[0][i] == 39)
|
|
minecraft_color_for_blocktype[0][i] = 39 | 64; // apply to tex1
|
|
if (minecraft_tex1_for_blocktype[0][i] == 105)
|
|
minecraft_color_for_blocktype[0][i] = 63; // emissive
|
|
if (minecraft_tex1_for_blocktype[0][i] == 212)
|
|
minecraft_color_for_blocktype[0][i] = 63; // emissive
|
|
if (minecraft_tex1_for_blocktype[0][i] == 80)
|
|
minecraft_color_for_blocktype[0][i] = 63; // emissive
|
|
}
|
|
|
|
for (i=0; i < 6; ++i) {
|
|
minecraft_color_for_blocktype[172][i] = 47 | 64; // apply to tex1
|
|
minecraft_color_for_blocktype[178][i] = 47 | 64; // apply to tex1
|
|
minecraft_color_for_blocktype[18][i] = 39 | 64; // green
|
|
minecraft_color_for_blocktype[161][i] = 37 | 64; // green
|
|
minecraft_color_for_blocktype[10][i] = 63; // emissive lava
|
|
minecraft_color_for_blocktype[11][i] = 63; // emissive
|
|
}
|
|
|
|
#if 0 // vheight test
|
|
effective_blocktype[168] = 168;
|
|
minecraft_tex1_for_blocktype[168][0] = 1;
|
|
minecraft_tex1_for_blocktype[168][1] = 1;
|
|
minecraft_tex1_for_blocktype[168][2] = 1;
|
|
minecraft_tex1_for_blocktype[168][3] = 1;
|
|
minecraft_tex1_for_blocktype[168][4] = 1;
|
|
minecraft_tex1_for_blocktype[168][5] = 1;
|
|
minecraft_geom_for_blocktype[168] = STBVOX_GEOM_floor_vheight_02;
|
|
#endif
|
|
|
|
remap[53] = 1;
|
|
remap[67] = 2;
|
|
remap[108] = 3;
|
|
remap[109] = 4;
|
|
remap[114] = 5;
|
|
remap[136] = 6;
|
|
remap[156] = 7;
|
|
for (i=0; i < 256; ++i)
|
|
if (remap[i])
|
|
build_stair_rotations(i, remap_data[remap[i]]);
|
|
remap[35] = 8;
|
|
build_wool_variations(35, remap_data[remap[35]]);
|
|
|
|
for (i=0; i < 256; ++i) {
|
|
if (remap[i])
|
|
effective_block_add[i] = 0;
|
|
else
|
|
effective_block_add[i] = effective_blocktype[i];
|
|
}
|
|
}
|