added input.packed_compact for storing most of the major 2/3-bit values in one byte
This commit is contained in:
parent
75f69ce5ed
commit
9534eb2e08
@ -117,6 +117,27 @@
|
||||
// then you wouldn't even have to change anything but the mode number.)
|
||||
//
|
||||
//
|
||||
// IMPROVEMENTS FOR SHIP-WORTHY PROGRAMS USING THIS LIBRARY
|
||||
//
|
||||
// I currently tolerate a certain level of "bugginess" in this library.
|
||||
//
|
||||
// I'm referring to things which look a little wrong (as long as they
|
||||
// don't cause holes or cracks in the output meshes), or things which
|
||||
// do not produce as optimal a mesh as possible. Notable examples:
|
||||
//
|
||||
// - incorrect lighting on slopes
|
||||
// - inefficient meshes for vheight blocks
|
||||
//
|
||||
// I am willing to do the work to improve these things if someone is
|
||||
// going to ship a substantial program that would be improved by them.
|
||||
// (It need not be commercial, nor need it be a game.) I just didn't
|
||||
// want to do the work up front if it might never be leveraged. So just
|
||||
// submit a bug report as usual (github is preferred), but add a note
|
||||
// that this is for a thing that is really going to ship. (That means
|
||||
// you need to be far enough into the project that it's clear you're
|
||||
// committed to it; not during early exploratory development.)
|
||||
//
|
||||
//
|
||||
// VOXEL MESH API
|
||||
//
|
||||
// Context
|
||||
@ -169,6 +190,7 @@
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 0.81 (2015-04-12) added input.packed_compact to store rot, vheight & texlerp efficiently
|
||||
// 0.80 (2015-04-11) fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring
|
||||
// change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so
|
||||
// that header defs don't need to see config vars
|
||||
@ -959,6 +981,19 @@ struct stbvox_input_description
|
||||
// Indexed by 3D coordinates, this defines the four
|
||||
// vheight values to use if the geometry is STBVOX_GEOM_vheight*.
|
||||
// See the vheight discussion.
|
||||
|
||||
unsigned char *packed_compact;
|
||||
// Stores block rotation, vheight, and texlerp values:
|
||||
// block rotation: 2 bits
|
||||
// vertex vheight: 2 bits
|
||||
// use_texlerp : 1 bit
|
||||
// vertex texlerp: 3 bits
|
||||
// If STBVOX_CONFIG_UP_TEXLERP_PACKED is defined, then 'vertex texlerp' is
|
||||
// used for up faces if use_texlerp is 1. If STBVOX_CONFIG_DOWN_TEXLERP_PACKED
|
||||
// is defined, then 'vertex texlerp' is used for down faces if use_texlerp is 1.
|
||||
// Note if those symbols are defined but packed_compact is NULL, the normal
|
||||
// texlerp default will be used.
|
||||
// Encode with STBVOX_MAKE_PACKED_COMPACT(rot, vheight, texlerp, use_texlerp)
|
||||
};
|
||||
// @OPTIMIZE allow specializing; build a single struct with all of the
|
||||
// 3D-indexed arrays combined so it's AoS instead of SoA for better
|
||||
@ -969,6 +1004,17 @@ struct stbvox_input_description
|
||||
//
|
||||
// VHEIGHT DOCUMENTATION
|
||||
//
|
||||
// "vheight" is the internal name for the special block types
|
||||
// with sloped tops or bottoms. "vheight" stands for "vertex height".
|
||||
//
|
||||
// Note that these blocks are very flexible (there are 256 of them,
|
||||
// although at least 17 of them should never be used), but they
|
||||
// also have a disadvantage that they generate extra invisible
|
||||
// faces; the generator does not currently detect whether adjacent
|
||||
// vheight blocks hide each others sides, so those side faces are
|
||||
// always generated. For a continuous ground terrain, this means
|
||||
// that you may generate 5x as many quads as needed. See notes
|
||||
// on "improvements for shipping products" in the introduction.
|
||||
|
||||
enum
|
||||
{
|
||||
@ -989,9 +1035,9 @@ enum
|
||||
// 1/2, 2/2, or 3/2. 0 is the bottom of the block, 1 is halfway
|
||||
// up the block, 2 is the top of the block, and 3 is halfway up the
|
||||
// next block (and actually outside of the block). The value 3 is
|
||||
// actually legal, and allows you to:
|
||||
// actually legal for floor vheight (but not ceiling), and allows you to:
|
||||
//
|
||||
// (A) allows smoother terrain by having slopes that cross blocks,
|
||||
// (A) have smoother terrain by having slopes that cross blocks,
|
||||
// e.g. (1,1,3,3) is a regular-seeming slope halfway between blocks
|
||||
// (B) make slopes steeper than 45-degrees, e.g. (0,0,3,3)
|
||||
//
|
||||
@ -1103,6 +1149,7 @@ enum
|
||||
#define STBVOX_MAKE_COLOR(color,t1,t2) ((color)+(t1)*64+(t2)*128)
|
||||
#define STBVOX_MAKE_TEXLERP_VERT3(e,n,w,s,u) ((e)+(n)*8+(w)*64+(s)*512+(u)*4096)
|
||||
#define STBVOX_MAKE_TEXLERP_FACE3(e,n,w,s,u,d) ((e)+(n)*8+(w)*64+(s)*512+(u)*4096+(d)*16384)
|
||||
#define STBVOX_MAKE_PACKED_COMPACT(rot, vheight, texlerp, def) ((rot)+4*(vheight)+16*(use)+32*(texlerp))
|
||||
|
||||
#define STBVOX_MAKE_LIGHTING_EXT(lighting, rot) (((lighting)&~3)+(rot))
|
||||
#define STBVOX_MAKE_LIGHTING(lighting) (lighting)
|
||||
@ -2256,10 +2303,10 @@ static unsigned char stbvox_hasface[STBVOX_MAX_GEOM][STBVOX_NUM_ROTATION] =
|
||||
{ 31,31,31,31 }, // wall-projected diagonal with up face
|
||||
{ 63,63,63,63 }, // crossed-pair has special handling, but avoid early-out
|
||||
{ 63,63,63,63 }, // force
|
||||
{ 63,63,63,63 },
|
||||
{ 63,63,63,63 },
|
||||
{ 63,63,63,63 },
|
||||
{ 63,63,63,63 },
|
||||
{ 63,63,63,63 }, // vheight
|
||||
{ 63,63,63,63 }, // vheight
|
||||
{ 63,63,63,63 }, // vheight
|
||||
{ 63,63,63,63 }, // vheight
|
||||
};
|
||||
|
||||
// this determines which face type above is visible on each side of the geometry
|
||||
@ -2619,6 +2666,30 @@ void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int fac
|
||||
// first compute texlerp into p1
|
||||
stbvox_mesh_vertex p1[4] = { 0 };
|
||||
|
||||
#if defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) && defined(STBVOX_CONFIG_UP_TEXLERP_PACKED)
|
||||
#define STBVOX_USE_PACKED(f) ((f) == STBVOX_FACE_up || (f) == STBVOX_FACE_down)
|
||||
#elif defined(STBVOX_CONFIG_UP_TEXLERP_PACKED)
|
||||
#define STBVOX_USE_PACKED(f) ((f) == STBVOX_FACE_up )
|
||||
#elif defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED)
|
||||
#define STBVOX_USE_PACKED(f) ( (f) == STBVOX_FACE_down)
|
||||
#endif
|
||||
|
||||
#if defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) || defined(STBVOX_CONFIG_UP_TEXLERP_PACKED)
|
||||
if (STBVOX_USE_PACKED(face)) {
|
||||
if (!mm->input.packed_compact || 0==(mm->input.packed_compact[v_off]&16))
|
||||
goto set_default;
|
||||
p1[0] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][0]] >> 5);
|
||||
p1[1] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][1]] >> 5);
|
||||
p1[2] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][2]] >> 5);
|
||||
p1[3] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][3]] >> 5);
|
||||
p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]);
|
||||
p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]);
|
||||
p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]);
|
||||
p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]);
|
||||
goto skip;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mm->input.block_texlerp) {
|
||||
stbvox_block_type bt = mm->input.blocktype[v_off];
|
||||
unsigned char val = mm->input.block_texlerp[bt];
|
||||
@ -2672,9 +2743,17 @@ void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int fac
|
||||
p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,stbvox_vert_lerp_for_face_lerp[facelerp]);
|
||||
}
|
||||
} else {
|
||||
p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,7);
|
||||
#if defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) || defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED)
|
||||
set_default:
|
||||
#endif
|
||||
p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,7); // @TODO make this configurable
|
||||
}
|
||||
|
||||
#if defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) || defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED)
|
||||
skip:
|
||||
#endif
|
||||
|
||||
// now compute lighting and store to vertices
|
||||
{
|
||||
stbvox_mesh_vertex *mv[4];
|
||||
stbvox_get_quad_vertex_pointer(mm, mesh, mv, face_data);
|
||||
@ -2823,6 +2902,9 @@ static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, in
|
||||
simple_rot = mm->input.lighting[v_off] & 3;
|
||||
#endif
|
||||
|
||||
if (mm->input.packed_compact)
|
||||
simple_rot = mm->input.packed_compact[v_off] & 3;
|
||||
|
||||
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_FACE_up);
|
||||
@ -2853,9 +2935,6 @@ static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, in
|
||||
stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_west , v_off, pos, basevert, vmesh+4*STBVOX_FACE_west, mesh, STBVOX_FACE_west);
|
||||
}
|
||||
|
||||
|
||||
// void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off)
|
||||
//
|
||||
// complex case for mesh generation: we have lots of different
|
||||
// block types, and we don't want to generate faces of blocks
|
||||
// if they're hidden by neighbors.
|
||||
@ -2864,8 +2943,6 @@ static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, in
|
||||
// which tells us what face type is generated for each type of
|
||||
// geometry, and then a table that tells us whether that type
|
||||
// is hidden by a neighbor.
|
||||
|
||||
|
||||
static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off)
|
||||
{
|
||||
int ns_off = mm->y_stride_in_bytes;
|
||||
@ -2896,15 +2973,12 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
ngeo[4] = mm->input.geometry[v_off + 1];
|
||||
ngeo[5] = mm->input.geometry[v_off - 1];
|
||||
|
||||
#ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
rot = (geo >> 4) & 3;
|
||||
geo &= 15;
|
||||
for (i=0; i < 6; ++i) {
|
||||
nrot[i] = (ngeo[i] >> 4) & 3;
|
||||
ngeo[i] &= 15;
|
||||
}
|
||||
#endif
|
||||
STBVOX_NOTUSED(i);
|
||||
} else {
|
||||
int i;
|
||||
assert(mm->input.block_geometry);
|
||||
@ -2913,27 +2987,41 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
ngeo[i] = mm->input.block_geometry[nbt[i]];
|
||||
if (mm->input.selector) {
|
||||
#ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
rot = (mm->input.selector[v_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[2] = (mm->input.selector[v_off - ew_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[5] = (mm->input.selector[v_off - 1] >> 4) & 3;
|
||||
if (mm->input.packed_compact == NULL) {
|
||||
rot = (mm->input.selector[v_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[2] = (mm->input.selector[v_off - ew_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[5] = (mm->input.selector[v_off - 1] >> 4) & 3;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
rot = (geo>>4)&3;
|
||||
geo &= 15;
|
||||
for (i=0; i < 6; ++i) {
|
||||
nrot[i] = (ngeo[i]>>4)&3;
|
||||
ngeo[i] &= 15;
|
||||
if (mm->input.packed_compact == NULL) {
|
||||
rot = (geo>>4)&3;
|
||||
geo &= 15;
|
||||
for (i=0; i < 6; ++i) {
|
||||
nrot[i] = (ngeo[i]>>4)&3;
|
||||
ngeo[i] &= 15;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
#ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
if (mm->input.packed_compact) {
|
||||
rot = mm->input.packed_compact[rot] & 3;
|
||||
nrot[0] = mm->input.packed_compact[v_off + ew_off] & 3;
|
||||
nrot[1] = mm->input.packed_compact[v_off + ns_off] & 3;
|
||||
nrot[2] = mm->input.packed_compact[v_off - ew_off] & 3;
|
||||
nrot[3] = mm->input.packed_compact[v_off - ns_off] & 3;
|
||||
nrot[4] = mm->input.packed_compact[v_off + 1] & 3;
|
||||
nrot[5] = mm->input.packed_compact[v_off - 1] & 3;
|
||||
}
|
||||
#else
|
||||
rot = mm->input.lighting[v_off] & 3;
|
||||
nrot[0] = (mm->input.lighting[v_off + ew_off]) & 3;
|
||||
nrot[1] = (mm->input.lighting[v_off + ns_off]) & 3;
|
||||
@ -3122,6 +3210,11 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
|
||||
for (i=0; i < 4; ++i)
|
||||
ht[i] = raw[stbvox_rotate_vertex[i][rot]];
|
||||
} else if (mm->input.packed_compact) {
|
||||
ht[0] = (mm->input.packed_compact[v_off ] >> 2) & 3;
|
||||
ht[1] = (mm->input.packed_compact[v_off+ew_off ] >> 2) & 3;
|
||||
ht[2] = (mm->input.packed_compact[v_off +ns_off] >> 2) & 3;
|
||||
ht[3] = (mm->input.packed_compact[v_off+ew_off+ns_off] >> 2) & 3;
|
||||
} else if (mm->input.geometry) {
|
||||
ht[0] = mm->input.geometry[v_off ] >> 6;
|
||||
ht[1] = mm->input.geometry[v_off+ew_off ] >> 6;
|
||||
@ -3586,7 +3679,7 @@ int main(int argc, char **argv)
|
||||
// - test API for texture rotation on side faces
|
||||
// - API for texture rotation on top & bottom
|
||||
// - better culling of vheight faces with vheight neighbors
|
||||
// - better culling of non-vheight faces with fheight neighbors
|
||||
// - better culling of non-vheight faces with vheight neighbors
|
||||
// - gather vertex lighting from slopes correctly
|
||||
// - better support texture edge_clamp: currently if you fall
|
||||
// exactly on 1.0 you get wrapped incorrectly; this is rare, but
|
||||
|
@ -25,8 +25,9 @@
|
||||
//#define STBVOX_CONFIG_UNPREMULTIPLY // slower, fixes alpha test makes windows & fancy leaves look better
|
||||
//#define STBVOX_CONFIG_TEX1_EDGE_CLAMP
|
||||
#define STBVOX_CONFIG_DISABLE_TEX2
|
||||
|
||||
//#define STBVOX_CONFIG_DOWN_TEXLERP_PACKED
|
||||
#define STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
|
||||
#define STB_VOXEL_RENDER_IMPLEMENTATION
|
||||
#include "stb_voxel_render.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user