support texture rotation; better interaction of mouse centering & VC6 debugger; fix in-place conversion when mca blocks are written in different order

This commit is contained in:
Sean Barrett 2015-03-12 19:03:49 -07:00
parent 3d4f545fd7
commit efcd76c9ab
5 changed files with 160 additions and 61 deletions

View File

@ -1,6 +1,5 @@
// @TODO // @TODO
// //
// - extend 2 bits below normal/texgen to support texture rotation
// - compute full set of texture normals // - compute full set of texture normals
// - handle output buffer being full // - handle output buffer being full
// - gather vertex lighting from slopes correctly // - gather vertex lighting from slopes correctly
@ -516,6 +515,13 @@ struct stbvox_mesh_maker
typedef unsigned int stbvox_uint32; typedef unsigned int stbvox_uint32;
#endif #endif
#ifdef _MSC_VER
#define STBVOX_NOTUSED(v) (void)(v)
#else
#define STBVOX_NOTUSED(v) (void)sizeof(v)
#endif
// 20-byte quad format: // 20-byte quad format:
// //
// per vertex: // per vertex:
@ -536,10 +542,22 @@ struct stbvox_mesh_maker
// Default uniform values // Default uniform values
static float stbvox_default_texgen[2][16][3] = static float stbvox_default_texgen[2][32][3] =
{ {
{ { 0,1,0 }, { 1,0,0 }, { 0,-1,0 }, { -1,0,0 }, { 1,0,0 }, { -1,0,0 } }, { { 0, 1,0 }, { 0, 0, 1 }, { 0,-1,0 }, { 0, 0,-1 },
{ { 0,0,-1 }, { 0,0,-1 }, { 0,0,-1 }, { 0,0,-1 }, { 0,-1,0 }, { 0,1,0 } }, { 1, 0,0 }, { 0, 0, 1 }, { -1, 0,0 }, { 0, 0,-1 },
{ 0,-1,0 }, { 0, 0, 1 }, { 0, 1,0 }, { 0, 0,-1 },
{ -1, 0,0 }, { 0, 0, 1 }, { 1, 0,0 }, { 0, 0,-1 },
{ 1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 },
{ -1, 0,0 }, { 0,-1, 0 }, { 1, 0,0 }, { 0, 1, 0 },
},
{ { 0, 0,-1 }, { 0, 1,0 }, { 0, 0, 1 }, { 0,-1,0 },
{ 0, 0,-1 }, { 1, 0,0 }, { 0, 0, 1 }, { -1, 0,0 },
{ 0, 0,-1 }, { 0,-1,0 }, { 0, 0, 1 }, { 0, 1,0 },
{ 0, 0,-1 }, { -1, 0,0 }, { 0, 0, 1 }, { 1, 0,0 },
{ 0,-1, 0 }, { 1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 },
{ 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, { 1, 0,0 },
},
}; };
static float stbvox_default_normals[32][3] = static float stbvox_default_normals[32][3] =
@ -684,7 +702,7 @@ stbvox_tagged_string stbvox_vertex_program[] =
" amb_occ = float( (attr_vertex >> 23u) & 63u ) / 63.0;\n" // a[23..28] " amb_occ = float( (attr_vertex >> 23u) & 63u ) / 63.0;\n" // a[23..28]
" texlerp = float( (attr_vertex >> 29u) ) / 7.0;\n" // a[29..31] " texlerp = float( (attr_vertex >> 29u) ) / 7.0;\n" // a[29..31]
" vnormal = normal_table[facedata.w & 31u];\n" " vnormal = normal_table[(facedata.w>>2) & 31u];\n"
" objectspace_pos = offset * transform[0];\n" // object-to-world scale " objectspace_pos = offset * transform[0];\n" // object-to-world scale
" vec3 position = objectspace_pos + transform[1];\n" // object-to-world translate " vec3 position = objectspace_pos + transform[1];\n" // object-to-world translate
}, },
@ -745,8 +763,8 @@ stbvox_tagged_string stbvox_fragment_program[] =
#if 0 #if 0
"uniform vec4 color_table[64];\n" "uniform vec4 color_table[64];\n"
"uniform vec2 texscale[128];\n" "uniform vec2 texscale[64];\n" // instead of 128, to avoid running out of uniforms
"uniform vec3 texgen[32];\n" "uniform vec3 texgen[64];\n"
#else #else
"uniform samplerBuffer color_table;\n" "uniform samplerBuffer color_table;\n"
"uniform samplerBuffer texscale;\n" "uniform samplerBuffer texscale;\n"
@ -771,20 +789,20 @@ stbvox_tagged_string stbvox_fragment_program[] =
// unpack the values // unpack the values
" uint tex1_id = facedata.x;\n" " uint tex1_id = facedata.x;\n"
" uint tex2_id = facedata.y;\n" " uint tex2_id = facedata.y;\n"
" uint texprojid = facedata.w & 15u;\n" " uint texprojid = facedata.w & 31u;\n"
" uint color_id = facedata.z;\n" " uint color_id = facedata.z;\n"
" bool texblend_mode = ((facedata.w & 128u) != 0u);\n" " bool texblend_mode = ((facedata.w & 128u) != 0u);\n"
#if 0 #if 0
// load from uniforms / texture buffers // load from uniforms / texture buffers
" vec3 texgen_s = texgen[texprojid];\n" " vec3 texgen_s = texgen[texprojid];\n"
" vec3 texgen_t = texgen[texprojid+16u];\n" " vec3 texgen_t = texgen[texprojid+32u];\n"
" float tex1_scale = texscale[tex1_id & 127u].x;\n" " float tex1_scale = texscale[tex1_id & 63u].x;\n"
" float tex2_scale = texscale[tex2_id & 127u].y;\n" " float tex2_scale = texscale[tex2_id & 63u].y;\n"
" vec4 color = color_table[color_id & 63u];\n" " vec4 color = color_table[color_id & 63u];\n"
#else #else
" vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n" " vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n"
" vec3 texgen_t = texelFetch(texgen, int(texprojid+16u)).xyz;\n" " vec3 texgen_t = texelFetch(texgen, int(texprojid+32u)).xyz;\n"
" float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n" " float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n"
" float tex2_scale = texelFetch(texscale, int(tex2_id & 127u)).y;\n" " float tex2_scale = texelFetch(texscale, int(tex2_id & 127u)).y;\n"
" vec4 color = texelFetch(color_table, int(color_id & 63u));\n" " vec4 color = texelFetch(color_table, int(color_id & 63u));\n"
@ -794,7 +812,7 @@ stbvox_tagged_string stbvox_fragment_program[] =
" texcoord.s = dot(texturespace_pos, texgen_s);\n" " texcoord.s = dot(texturespace_pos, texgen_s);\n"
" texcoord.t = dot(texturespace_pos, texgen_t);\n" " texcoord.t = dot(texturespace_pos, texgen_t);\n"
// @TODO: use 2 bits of facedata.w to enable animation of facedata.x & y // @TODO: use 2 bits of facedata.w to enable animation of facedata.x & y?
" vec4 tex1 = texture(tex_array[0], vec3(tex1_scale * texcoord, float(tex1_id)));\n" " vec4 tex1 = texture(tex_array[0], vec3(tex1_scale * texcoord, float(tex1_id)));\n"
" vec4 tex2 = texture(tex_array[1], vec3(tex2_scale * texcoord, float(tex2_id)));\n" " vec4 tex2 = texture(tex_array[1], vec3(tex2_scale * texcoord, float(tex2_id)));\n"
@ -925,7 +943,7 @@ stbvox_uniform_info stbvox_uniforms[] =
{ STBVOX_UNIFORM_TYPE_vec4 , 16, 64, "color_table" , stbvox_default_palette[0] , STBVOX_TAG_textured }, { STBVOX_UNIFORM_TYPE_vec4 , 16, 64, "color_table" , stbvox_default_palette[0] , STBVOX_TAG_textured },
{ STBVOX_UNIFORM_TYPE_vec3 , 12, 32, "normal_table" , stbvox_default_normals[0] , STBVOX_TAG_all }, { STBVOX_UNIFORM_TYPE_vec3 , 12, 32, "normal_table" , stbvox_default_normals[0] , STBVOX_TAG_all },
{ STBVOX_UNIFORM_TYPE_vec3 , 12, 32, "texgen" , stbvox_default_texgen[0][0] , STBVOX_TAG_textured }, { STBVOX_UNIFORM_TYPE_vec3 , 12, 64, "texgen" , stbvox_default_texgen[0][0] , STBVOX_TAG_textured },
{ STBVOX_UNIFORM_TYPE_vec3 , 12, 4, "ambient" , 0 , STBVOX_TAG_all }, { STBVOX_UNIFORM_TYPE_vec3 , 12, 4, "ambient" , 0 , STBVOX_TAG_all },
{ STBVOX_UNIFORM_TYPE_vec3 , 12, 1, "camera_pos" , stbvox_dummy_transform[0] , STBVOX_TAG_all }, { STBVOX_UNIFORM_TYPE_vec3 , 12, 1, "camera_pos" , stbvox_dummy_transform[0] , STBVOX_TAG_all },
@ -960,8 +978,9 @@ typedef struct
{ {
unsigned char block; unsigned char block;
unsigned char overlay; unsigned char overlay;
unsigned char facerot:4;
unsigned char ecolor:4;
unsigned char tex2; unsigned char tex2;
unsigned char ecolor;
} stbvox_rotate; } stbvox_rotate;
typedef struct typedef struct
@ -983,7 +1002,7 @@ static unsigned char stbvox_rotate_face[6][4] =
static unsigned char face_info_for_side[6] = static unsigned char face_info_for_side[6] =
{ {
0,1,2,3,4,5 0*4,1*4,2*4,3*4,4*4,5*4
}; };
stbvox_mesh_face stbvox_compute_mesh_face_value(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off) stbvox_mesh_face stbvox_compute_mesh_face_value(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off)
@ -1058,7 +1077,7 @@ stbvox_mesh_face stbvox_compute_mesh_face_value(stbvox_mesh_maker *mm, stbvox_ro
if (mm->input.color3 && (mm->input.color3_facemask[v_off] & (1 << color_face))) if (mm->input.color3 && (mm->input.color3_facemask[v_off] & (1 << color_face)))
face_data.color = mm->input.color3[v_off]; face_data.color = mm->input.color3[v_off];
} }
face_data.face_info = face_info_for_side[face]; face_data.face_info = face_info_for_side[face] + rot.facerot;
return face_data; return face_data;
} }
@ -1374,7 +1393,7 @@ void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off
unsigned char *blockptr = &mm->input.blocktype[v_off]; unsigned char *blockptr = &mm->input.blocktype[v_off];
stbvox_mesh_vertex basevert = stbvox_vertex_p(pos.x, pos.y, pos.z<<mm->precision_z , 0,0); stbvox_mesh_vertex basevert = stbvox_vertex_p(pos.x, pos.y, pos.z<<mm->precision_z , 0,0);
stbvox_rotate rot = { 0,0,0,0 }; stbvox_rotate rot = { 0,0,0,0,0 };
unsigned char simple_rot = 0; unsigned char simple_rot = 0;
unsigned char mesh = mm->default_mesh; unsigned char mesh = mm->default_mesh;
@ -1392,10 +1411,14 @@ void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off
simple_rot = mm->input.lighting[v_off] & 3; simple_rot = mm->input.lighting[v_off] & 3;
#endif #endif
if (blockptr[ 1]==0) if (blockptr[ 1]==0) {
rot.facerot = simple_rot;
stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_up , v_off, pos, basevert, vmesh+4*STBVOX_FACE_up, mesh); stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_up , v_off, pos, basevert, vmesh+4*STBVOX_FACE_up, mesh);
if (blockptr[-1]==0) }
if (blockptr[-1]==0) {
rot.facerot = (-simple_rot) & 3;
stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_down, v_off, pos, basevert, vmesh+4*STBVOX_FACE_down, mesh); stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_down, v_off, pos, basevert, vmesh+4*STBVOX_FACE_down, mesh);
}
if (mm->input.rotate) { if (mm->input.rotate) {
unsigned char val = mm->input.rotate[v_off]; unsigned char val = mm->input.rotate[v_off];
@ -1403,9 +1426,10 @@ void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off
rot.overlay = (val >> 2) & 3; rot.overlay = (val >> 2) & 3;
rot.tex2 = (val >> 4) & 3; rot.tex2 = (val >> 4) & 3;
rot.ecolor = (val >> 6) & 3; rot.ecolor = (val >> 6) & 3;
} else if (mm->input.selector) { } else {
rot.block = rot.overlay = rot.tex2 = rot.ecolor = simple_rot; rot.block = rot.overlay = rot.tex2 = rot.ecolor = simple_rot;
} }
rot.facerot = 0;
if (blockptr[ ns_off]==0) if (blockptr[ ns_off]==0)
stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, vmesh+4*STBVOX_FACE_north, mesh); stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, vmesh+4*STBVOX_FACE_north, mesh);
@ -1580,12 +1604,15 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
ngeo[4] = mm->input.geometry[v_off + 1]; ngeo[4] = mm->input.geometry[v_off + 1];
ngeo[5] = mm->input.geometry[v_off - 1]; ngeo[5] = mm->input.geometry[v_off - 1];
#ifndef STBVOX_ROTATION_IN_LIGHTING
rot = (geo >> 4) & 3; rot = (geo >> 4) & 3;
geo &= 15; geo &= 15;
for (i=0; i < 6; ++i) { for (i=0; i < 6; ++i) {
nrot[i] = (ngeo[i] >> 4) & 3; nrot[i] = (ngeo[i] >> 4) & 3;
ngeo[i] &= 15; ngeo[i] &= 15;
} }
#endif
STBVOX_NOTUSED(i);
} else { } else {
int i; int i;
assert(mm->input.block_geometry); assert(mm->input.block_geometry);
@ -1593,6 +1620,7 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
for (i=0; i < 6; ++i) for (i=0; i < 6; ++i)
ngeo[i] = mm->input.block_geometry[nbt[i]]; ngeo[i] = mm->input.block_geometry[nbt[i]];
if (mm->input.selector) { if (mm->input.selector) {
#ifndef STBVOX_ROTATION_IN_LIGHTING
rot = (mm->input.selector[v_off ] >> 4) & 3; rot = (mm->input.selector[v_off ] >> 4) & 3;
nrot[0] = (mm->input.selector[v_off + ew_off] >> 4) & 3; nrot[0] = (mm->input.selector[v_off + ew_off] >> 4) & 3;
nrot[1] = (mm->input.selector[v_off + ns_off] >> 4) & 3; nrot[1] = (mm->input.selector[v_off + ns_off] >> 4) & 3;
@ -1600,13 +1628,16 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
nrot[3] = (mm->input.selector[v_off - ns_off] >> 4) & 3; nrot[3] = (mm->input.selector[v_off - ns_off] >> 4) & 3;
nrot[4] = (mm->input.selector[v_off + 1] >> 4) & 3; nrot[4] = (mm->input.selector[v_off + 1] >> 4) & 3;
nrot[5] = (mm->input.selector[v_off - 1] >> 4) & 3; nrot[5] = (mm->input.selector[v_off - 1] >> 4) & 3;
#endif
} else { } else {
#ifndef STBVOX_ROTATION_IN_LIGHTING
rot = (geo>>4)&3; rot = (geo>>4)&3;
geo &= 15; geo &= 15;
for (i=0; i < 6; ++i) { for (i=0; i < 6; ++i) {
nrot[i] = (ngeo[i]>>4)&3; nrot[i] = (ngeo[i]>>4)&3;
ngeo[i] &= 15; ngeo[i] &= 15;
} }
#endif
} }
} }
@ -1620,6 +1651,8 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
nrot[5] = (mm->input.lighting[v_off - 1]) & 3; nrot[5] = (mm->input.lighting[v_off - 1]) & 3;
#endif #endif
//rot = 2;
if (geo == STBVOX_GEOM_transp) { if (geo == STBVOX_GEOM_transp) {
// transparency has a special rule: if the blocktype is the same, // transparency has a special rule: if the blocktype is the same,
// and the faces are compatible, then can hide them; otherwise, // and the faces are compatible, then can hide them; otherwise,
@ -1694,7 +1727,7 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
// this is the simple case, we can just use regular block gen with special vmesh calculated with vheight // this is the simple case, we can just use regular block gen with special vmesh calculated with vheight
stbvox_mesh_vertex basevert; stbvox_mesh_vertex basevert;
stbvox_mesh_vertex vmesh[6][4]; stbvox_mesh_vertex vmesh[6][4];
stbvox_rotate rotate = { 0,0,0,0 }; stbvox_rotate rotate = { 0,0,0,0,0 };
unsigned char simple_rot = rot; unsigned char simple_rot = rot;
int i; int i;
// we only need to do this for the displayed faces, but it's easier // we only need to do this for the displayed faces, but it's easier
@ -1718,10 +1751,14 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
return; return;
} }
if (visible_faces & (1 << STBVOX_FACE_up)) if (visible_faces & (1 << STBVOX_FACE_up)) {
rotate.facerot = simple_rot;
stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh); stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh);
if (visible_faces & (1 << STBVOX_FACE_down)) }
if (visible_faces & (1 << STBVOX_FACE_down)) {
rotate.facerot = (-rotate.facerot) & 3;
stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh); stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh);
}
if (mm->input.rotate) { if (mm->input.rotate) {
unsigned char val = mm->input.rotate[v_off]; unsigned char val = mm->input.rotate[v_off];
@ -1729,10 +1766,12 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
rotate.overlay = (val >> 2) & 3; rotate.overlay = (val >> 2) & 3;
rotate.tex2 = (val >> 4) & 3; rotate.tex2 = (val >> 4) & 3;
rotate.ecolor = (val >> 6) & 3; rotate.ecolor = (val >> 6) & 3;
} else if (mm->input.selector) { } else {
rotate.block = rotate.overlay = rotate.tex2 = rotate.ecolor = simple_rot; rotate.block = rotate.overlay = rotate.tex2 = rotate.ecolor = simple_rot;
} }
rotate.facerot = 0;
if (visible_faces & (1 << STBVOX_FACE_north)) if (visible_faces & (1 << STBVOX_FACE_north))
stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_north, v_off, pos, basevert, vmesh[STBVOX_FACE_north], mesh); stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_north, v_off, pos, basevert, vmesh[STBVOX_FACE_north], mesh);
if (visible_faces & (1 << STBVOX_FACE_south)) if (visible_faces & (1 << STBVOX_FACE_south))
@ -1750,7 +1789,7 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
stbvox_mesh_vertex vmesh[6][4]; stbvox_mesh_vertex vmesh[6][4];
stbvox_mesh_vertex cube[8]; stbvox_mesh_vertex cube[8];
stbvox_mesh_vertex basevert; stbvox_mesh_vertex basevert;
stbvox_rotate rotate = { 0,0,0,0 }; stbvox_rotate rotate = { 0,0,0,0,0 };
unsigned char simple_rot = rot; unsigned char simple_rot = rot;
unsigned char ht[4]; unsigned char ht[4];
int extreme; int extreme;
@ -1775,7 +1814,7 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
for (i=0; i < 4; ++i) for (i=0; i < 4; ++i)
ht[i] = raw[stbvox_rotate_vertex[i][rot]]; ht[i] = raw[stbvox_rotate_vertex[i][rot]];
} else { } else {
assert(mm->input.geometry); assert(0);
} }
// flag whether any sides go off the top of the block, which means // flag whether any sides go off the top of the block, which means
@ -1872,9 +1911,8 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
if (geo == STBVOX_GEOM_crossed_pair) { if (geo == STBVOX_GEOM_crossed_pair) {
// this can be generated with a special vmesh // this can be generated with a special vmesh
stbvox_mesh_vertex basevert = stbvox_vertex_p(pos.x, pos.y, pos.z<<mm->precision_z , 0,0); stbvox_mesh_vertex basevert = stbvox_vertex_p(pos.x, pos.y, pos.z<<mm->precision_z , 0,0);
stbvox_rotate rot = { 0,0,0,0 }; unsigned char simple_rot=0;
unsigned char simple_rot; stbvox_rotate rot = { 0,0,0,0,0 };
unsigned char mesh = mm->default_mesh; unsigned char mesh = mm->default_mesh;
if (mm->input.selector) { if (mm->input.selector) {
mesh = mm->input.selector[v_off]; mesh = mm->input.selector[v_off];
@ -1897,6 +1935,7 @@ void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos,
} else if (mm->input.selector) { } else if (mm->input.selector) {
rot.block = rot.overlay = rot.tex2 = rot.ecolor = simple_rot; rot.block = rot.overlay = rot.tex2 = rot.ecolor = simple_rot;
} }
rot.facerot = 0;
stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_north], mesh); stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_north], mesh);
stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_south, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_south], mesh); stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_south, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_south], mesh);

View File

@ -11,11 +11,13 @@ Not very. Many Minecraft blocks are not handled correctly:
* Only one wood type * Only one wood type
* Colored glass becomes regular glass * Colored glass becomes regular glass
* Glass panes become glass blocks * Glass panes become glass blocks
* Water is opaque
* Water level is incorrect * Water level is incorrect
* No biome coloration * No biome coloration
* Cactus is not shrunk, shows holes * Cactus is not shrunk, shows holes
* Chests are not shrunk * Chests are not shrunk
* Chests, pumpkins, etc. are not rotated properly * Double-chests draw as two chests
* Pumpkins etc. are not rotated properly
* Torches are drawn hackily, do not attach to walls * Torches are drawn hackily, do not attach to walls
* Incorrect textures for blocks that postdate terrain.png * Incorrect textures for blocks that postdate terrain.png
* Transparent textures have black fringes due to non-premultiplied-alpha * Transparent textures have black fringes due to non-premultiplied-alpha
@ -47,9 +49,11 @@ things that way wouldn't be so bad.
Rails, ladders, and redstone lines could be implemented by Rails, ladders, and redstone lines could be implemented by
using tex2 to overlay those effects, but you can't rotate using tex2 to overlay those effects, but you can't rotate
tex1 and tex2 independently, so you'd have to have a tex1 and tex2 independently, so there may be cases where
separate texture for each orientation of rail, etc, and the underlying texture needs a different rotation from the
you'd need special rendering for rail up/down sections. overlaid texture, which would require separate rendering.
Handling redstone's brightness being different from underlying
block's brightness would require separate rendering.
You can use the face-color effect to do biome coloration, You can use the face-color effect to do biome coloration,
but the change won't be smooth the way it is in Minecraft. but the change won't be smooth the way it is in Minecraft.
@ -60,8 +64,7 @@ but the change won't be smooth the way it is in Minecraft.
Partly because converting from minecraft data is expensive. Partly because converting from minecraft data is expensive.
Here is the approximate breakdown of an older version Here is the approximate breakdown of an older version
of this executable and lib that did the building single-threaded, of this executable and lib that did the building single-threaded.
and was a bit slower at building mesh data.
* 25% loading & parsing minecraft files (4/5ths of this is my zlib) * 25% loading & parsing minecraft files (4/5ths of this is my zlib)
* 18% converting from minecraft blockids & lighting to stb blockids & lighting * 18% converting from minecraft blockids & lighting to stb blockids & lighting

View File

@ -66,7 +66,7 @@ static void print(char *text, ...)
pos_y += 10; pos_y += 10;
} }
float camang[3], camloc[3] = { 0,0,75 }; float camang[3], camloc[3] = { 60,22,77 };
float player_zoom = 1.0; float player_zoom = 1.0;
float rotate_view = 0.0; float rotate_view = 0.0;
@ -551,8 +551,12 @@ int SDL_main(int argc, char **argv)
SDL_GL_MakeCurrent(window, context); // is this true by default? SDL_GL_MakeCurrent(window, context); // is this true by default?
// if (!IsDebuggerPresent())
SDL_SetRelativeMouseMode(SDL_TRUE); SDL_SetRelativeMouseMode(SDL_TRUE);
#if defined(_MSC_VER) && _MSC_VER < 1300
// work around broken behavior in VC6 debugging
if (IsDebuggerPresent())
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
#endif
stbgl_initExtensions(); stbgl_initExtensions();

View File

@ -121,7 +121,7 @@ unsigned char minecraft_info[256][7] =
{ C_empty }, // fire { C_empty }, // fire
{ C_trans, 65,65,65,65,65,65 }, { C_trans, 65,65,65,65,65,65 },
{ C_stair, 4,4,4,4,4,4 }, { C_stair, 4,4,4,4,4,4 },
{ C_solid, 27,26,26,26,25,25 }, { C_solid, 26,26,26,27,25,25 },
{ C_empty }, // redstone { C_empty }, // redstone
// 56 // 56
@ -237,7 +237,7 @@ unsigned char minecraft_info[256][7] =
// 144 // 144
{ C_empty }, // mob head { C_empty }, // mob head
{ C_empty }, // anvil { C_empty }, // anvil
{ C_solid, 27,26,26,26,25,25 }, // trapped chest { C_solid, 26,26,26,27,25,25 }, // trapped chest
{ C_empty }, // weighted pressure plate light { C_empty }, // weighted pressure plate light
{ C_empty }, // weighted pressure plat eheavy { C_empty }, // weighted pressure plat eheavy
{ C_empty }, // comparator inactive { C_empty }, // comparator inactive
@ -315,11 +315,13 @@ void convert_fastchunk_inplace(fast_chunk *fc)
{ {
int i; int i;
int num_blocks=0, step=0; int num_blocks=0, step=0;
unsigned char rot[4096] = { 0 }; unsigned char rot[4096];
#ifndef IN_PLACE #ifndef IN_PLACE
unsigned char *storage; unsigned char *storage;
#endif #endif
memset(rot, 0, 4096);
for (i=0; i < 16; ++i) for (i=0; i < 16; ++i)
num_blocks += fc->blockdata[i] != NULL; num_blocks += fc->blockdata[i] != NULL;
@ -340,15 +342,12 @@ void convert_fastchunk_inplace(fast_chunk *fc)
sky = fc->skylight[i]; sky = fc->skylight[i];
#ifdef IN_PLACE #ifdef IN_PLACE
assert(dd < sky && sky < lt && lt < bd);
out = bd; out = bd;
outb = dd;
#else #else
out = storage + 16*16*16*2*step; out = storage + 16*16*16*2*step;
outb = out + 16*16*16;
++step;
#endif #endif
// bd is written in place, but also reads from dd
for (o=0; o < 16*16*16/2; o += 1) { for (o=0; o < 16*16*16/2; o += 1) {
unsigned char v1,v2; unsigned char v1,v2;
unsigned char d = dd[o]; unsigned char d = dd[o];
@ -359,7 +358,7 @@ void convert_fastchunk_inplace(fast_chunk *fc)
{ {
//unsigned char d = bd[o] & 15; //unsigned char d = bd[o] & 15;
v1 = remap_data[remap[v1]][d&15]; v1 = remap_data[remap[v1]][d&15];
rot[o] = rotate_data[d&3]; rot[o*2+0] = rotate_data[d&3];
} else } else
v1 = effective_blocktype[v1]; v1 = effective_blocktype[v1];
@ -367,7 +366,7 @@ void convert_fastchunk_inplace(fast_chunk *fc)
{ {
//unsigned char d = bd[o] >> 4; //unsigned char d = bd[o] >> 4;
v2 = remap_data[remap[v2]][d>>4]; v2 = remap_data[remap[v2]][d>>4];
rot[o+1] = rotate_data[(d>>4)&3]; rot[o*2+1] = rotate_data[(d>>4)&3];
} else } else
v2 = effective_blocktype[v2]; v2 = effective_blocktype[v2];
@ -375,18 +374,54 @@ void convert_fastchunk_inplace(fast_chunk *fc)
out[o*2+1] = v2; out[o*2+1] = v2;
} }
// because this stores to data[], can't run at same time as above loop // this reads from lt & sky
for (o=0; o < 16*16*16/2; ++o) { #ifndef IN_PLACE
int bright; outb = out + 16*16*16;
bright = (lt[o]&15)*12 + 15 + (sky[o]&15)*16; ++step;
if (bright > 255) bright = 255; #endif
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; // MC used to write in this order and it makes it possible to compute in-place
if (bright > 255) bright = 255; if (dd < sky && sky < lt) {
if (bright < 32) bright = 32; // @TODO go this path always if !IN_PLACE
outb[o*2+1] = STBVOX_MAKE_LIGHTING((unsigned char) bright, rot[o+1]); #ifdef IN_PLACE
outb = dd;
#endif
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*2+0]&3));
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*2+1]&3));
}
} else {
// @TODO: if blocktype is in between others, this breaks; need to find which side has two pointers, and use that
// overwrite rot[] array, then copy out
#ifdef IN_PLACE
outb = (dd < sky) ? dd : sky;
if (lt < outb) lt = outb;
#endif
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;
rot[o*2+0] = STBVOX_MAKE_LIGHTING((unsigned char) bright, (rot[o*2+0]&3));
bright = (lt[o]>>4)*12 + 15 + (sky[o]>>4)*16;
if (bright > 255) bright = 255;
if (bright < 32) bright = 32;
rot[o*2+1] = STBVOX_MAKE_LIGHTING((unsigned char) bright, (rot[o*2+1]&3));
}
memcpy(outb, rot, 4096);
fc->data[i] = outb;
} }
#ifndef IN_PLACE #ifndef IN_PLACE
@ -653,10 +688,11 @@ void build_stair_rotations(int blocktype, unsigned char *map)
int i,j,k; int i,j,k;
for (j=0; j < 2; ++j) { for (j=0; j < 2; ++j) {
int geom = j ? STBVOX_GEOM_ceil_slope_north_is_bottom : STBVOX_GEOM_floor_slope_north_is_top; int geom = j ? STBVOX_GEOM_ceil_slope_north_is_bottom : STBVOX_GEOM_floor_slope_north_is_top;
//int geom = STBVOX_GEOM_solid;
for (i=0; i < 4; ++i) { for (i=0; i < 4; ++i) {
if (i == 0 && j == 0) { if (i == 0 && j == 0) {
map[j*4+i+8] = map[j*4+i] = blocktype; 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); minecraft_geom_for_blocktype[blocktype] = (unsigned char) STBVOX_MAKE_GEOMETRY(geom, 0, 0);
} else { } else {
map[j*4+i+8] = map[j*4+i] = next_blocktype; map[j*4+i+8] = map[j*4+i] = next_blocktype;
@ -664,7 +700,7 @@ void build_stair_rotations(int blocktype, unsigned char *map)
minecraft_color_for_blocktype[next_blocktype][k] = minecraft_color_for_blocktype[blocktype][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_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); minecraft_geom_for_blocktype[next_blocktype] = (unsigned char) STBVOX_MAKE_GEOMETRY(geom, 0, 0);
--next_blocktype; --next_blocktype;
} }
} }
@ -690,6 +726,15 @@ void build_wool_variations(int bt, unsigned char *map)
} }
} }
void remap_in_place(int bt, int rm)
{
int i;
remap[bt] = rm;
for (i=0; i < 16; ++i)
remap_data[rm][i] = bt;
}
void mesh_init(void) void mesh_init(void)
{ {
int i; int i;
@ -750,6 +795,10 @@ void mesh_init(void)
remap[35] = 8; remap[35] = 8;
build_wool_variations(35, remap_data[remap[35]]); build_wool_variations(35, remap_data[remap[35]]);
// set the remap flags for these so they write the rotation values
remap_in_place(54, 9);
remap_in_place(146, 10);
for (i=0; i < 256; ++i) { for (i=0; i < 256; ++i) {
if (remap[i]) if (remap[i])
effective_block_add[i] = 0; effective_block_add[i] = 0;

View File

@ -123,6 +123,10 @@ SOURCE=.\glext_list.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\README.md
# End Source File
# Begin Source File
SOURCE=.\win32\SDL_windows_main.c SOURCE=.\win32\SDL_windows_main.c
# End Source File # End Source File
# Begin Source File # Begin Source File