Add vheight documentation;
Add a missing vheight case; Add STBVOX_CONFIG_VHEIGHT_IN_LIGHTING; Fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING that was broken when I incompletely refactored the #define
This commit is contained in:
parent
b7570147f7
commit
e2b645e4d7
@ -1,4 +1,4 @@
|
||||
// stb_voxel_render.h - v0.79 - Sean Barrett, 2015 - public domain
|
||||
// stb_voxel_render.h - v0.80 - Sean Barrett, 2015 - public domain
|
||||
//
|
||||
// This library helps render large-scale "voxel" worlds for games,
|
||||
// in this case, one with blocks that can have textures and that
|
||||
@ -146,10 +146,11 @@
|
||||
//
|
||||
// Because there is so much per-vertex and per-face data possible
|
||||
// in the output, and each voxel can have 6 faces and 8 vertices, it
|
||||
// would require an impossibly large data structure to describe all
|
||||
// of the possibilities. Instead, the API provides multiple ways
|
||||
// to express each property; each such way has some limitations on
|
||||
// what it can express.
|
||||
// would require an very large data structure to describe all
|
||||
// of the possibilities, and this would cause the mesh-creation
|
||||
// process to be slow. Instead, the API provides multiple ways
|
||||
// to express each property, some more compact, others less so;
|
||||
// each such way has some limitations on what it can express.
|
||||
//
|
||||
// Note that there are so many paths and combinations, not all of them
|
||||
// have been tested. Just report bugs and I'll fix 'em.
|
||||
@ -159,28 +160,30 @@
|
||||
// See the API documentation in the header-file section.
|
||||
//
|
||||
//
|
||||
// HISTORICAL FOUNDATION
|
||||
//
|
||||
// zmc engine 96-byte quads 2011/10
|
||||
// zmc engine 32-byte quads 2013/12
|
||||
// stb_voxel_render 20-byte quads 2015/01
|
||||
//
|
||||
//
|
||||
// CONTRIBUTORS
|
||||
//
|
||||
// Features Porting Bugfixes & Warnings
|
||||
// Sean Barrett github:r-leyh Jesus Fernandez
|
||||
// Miguel Lechon github:Arbeiterunfallversicherungsgesetz
|
||||
// Thomas Frase
|
||||
//
|
||||
// VERSION HISTORY
|
||||
//
|
||||
// 0.79 fix the missing types from 0.78; fix string constants being const
|
||||
// 0.78 bad "#else", compile as C++
|
||||
// 0.77 documentation tweaks, rename config var to STB_VOXEL_RENDER_STATIC
|
||||
// 0.76 typos, signed/unsigned shader issue, more documentation
|
||||
// 0.75 initial release
|
||||
// 0.80 (2015-04-11) fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring;
|
||||
// add STBVOX_CONFIG_VHEIGHT_IN_LIGHTING and other vheight fixes;
|
||||
// added documentation for vheight ("weird slopes")
|
||||
// 0.79 (2015-04-01) fix the missing types from 0.78; fix string constants being const
|
||||
// 0.78 (2015-04-02) bad "#else", compile as C++
|
||||
// 0.77 (2015-04-01) documentation tweaks, rename config var to STB_VOXEL_RENDER_STATIC
|
||||
// 0.76 (2015-04-01) typos, signed/unsigned shader issue, more documentation
|
||||
// 0.75 (2015-04-01) initial release
|
||||
//
|
||||
//
|
||||
// HISTORICAL FOUNDATION
|
||||
//
|
||||
// stb_voxel_render 20-byte quads 2015/01
|
||||
// zmc engine 32-byte quads 2013/12
|
||||
// zmc engine 96-byte quads 2011/10
|
||||
|
||||
#ifndef INCLUDE_STB_VOXEL_RENDER_H
|
||||
#define INCLUDE_STB_VOXEL_RENDER_H
|
||||
@ -279,6 +282,11 @@ extern "C" {
|
||||
// Changes the meaning of the 'lighting' mesher input variable to also
|
||||
// store the rotation; see later discussion.
|
||||
//
|
||||
// STBVOX_CONFIG_VHEIGHT_IN_LIGHTING
|
||||
// Changes the meaning of the 'lighting' mesher input variable to also
|
||||
// store the vheight; see later discussion. Cannot use both this and
|
||||
// the previous variable.
|
||||
//
|
||||
// STBVOX_CONFIG_PREMULTIPLIED_ALPHA
|
||||
// Adjusts the shader calculations on the assumption that tex1.rgba,
|
||||
// tex2.rgba, and color.rgba all use premultiplied values, and that
|
||||
@ -293,7 +301,6 @@ extern "C" {
|
||||
// when alpha testing).
|
||||
//
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// MESHING
|
||||
@ -671,6 +678,11 @@ typedef struct
|
||||
|
||||
// This is the data structure you fill out. Most of the arrays can be
|
||||
// NULL, except when one is required to get the value to index another.
|
||||
//
|
||||
// The compass system used in the following descriptions is:
|
||||
// east means increasing x
|
||||
// north means increasing y
|
||||
// up means increasing z
|
||||
struct stbvox_input_description
|
||||
{
|
||||
unsigned char lighting_at_vertices;
|
||||
@ -697,19 +709,20 @@ struct stbvox_input_description
|
||||
// The raw lighting values are defined at the center of blocks
|
||||
// (or at vertex if 'lighting_at_vertices' is true).
|
||||
//
|
||||
// If the macro STBVOX_ROTATION_IN_LIGHTING is defined,
|
||||
// If the macro STBVOX_CONFIG_ROTATION_IN_LIGHTING is defined,
|
||||
// then an additional 2-bit block rotation value is stored
|
||||
// in this field as well.
|
||||
//
|
||||
// Encode with STBVOX_MAKE_LIGHTING(lighting,rot)--here
|
||||
// 'lighting' should still be 8 bits, as the macro will
|
||||
// discard the bottom bits automatically.
|
||||
// discard the bottom bits automatically. Similarly, if
|
||||
// using STBVOX_CONFIG_VHEIGHT_IN_LIGHTING, encode with
|
||||
// STBVOX_MAKE_LIGHTING(lighting,vheight).
|
||||
//
|
||||
// (Rationale: rotation needs to
|
||||
// be independent of blocktype, but is only 2 bits so
|
||||
// doesn't want to be its own array. Lighting is the one
|
||||
// thing that was likely to already be in use and that
|
||||
// I could easily steal 2 bits from.)
|
||||
// (Rationale: rotation needs to be independent of blocktype,
|
||||
// but is only 2 bits so doesn't want to be its own array.
|
||||
// Lighting is the one thing that was likely to already be
|
||||
// in use and that I could easily steal 2 bits from.)
|
||||
|
||||
stbvox_block_type *blocktype;
|
||||
// Indexed by 3D coordinate. This is a core "block type" value, which is used
|
||||
@ -950,12 +963,92 @@ struct stbvox_input_description
|
||||
// cache efficiency
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// VHEIGHT DOCUMENTATION
|
||||
//
|
||||
|
||||
enum
|
||||
{
|
||||
STBVOX_VERTEX_HEIGHT_0,
|
||||
STBVOX_VERTEX_HEIGHT_half,
|
||||
STBVOX_VERTEX_HEIGHT_1,
|
||||
STBVOX_VERTEX_HEIGHT_one_and_a_half,
|
||||
};
|
||||
// These are the "vheight" values. Vheight stands for "vertex height".
|
||||
// The idea is that for a "floor vheight" block, you take a cube and
|
||||
// reposition the top-most vertices at various heights as specified by
|
||||
// the vheight values. Similarly, a "ceiling vheight" block takes a
|
||||
// cube and repositions the bottom-most vertices.
|
||||
//
|
||||
// A floor block only adjusts the top four vertices; the bottom four vertices
|
||||
// remain at the bottom of the block. The height values are 2 bits,
|
||||
// measured in halves of a block; so you can specify heights of 0/2,
|
||||
// 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:
|
||||
//
|
||||
// (A) allows 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)
|
||||
//
|
||||
// (Because only z coordinates have half-block precision, and x&y are
|
||||
// limited to block corner precision, it's not possible to make these
|
||||
// things "properly" out of blocks, e.g. a half-slope block on its side
|
||||
// or a sloped block halfway between blocks that's made out of two blocks.)
|
||||
//
|
||||
// If you define STBVOX_CONFIG_OPTIMIZED_VHEIGHT, then the top face
|
||||
// (or bottom face for a ceiling vheight block) will be drawn as a
|
||||
// single quad even if the four vertex heights aren't planar, and a
|
||||
// single normal will be used over the entire quad. If you
|
||||
// don't define it, then if the top face is non-planar, it will be
|
||||
// split into two triangles, each with their own normal/lighting.
|
||||
// (Note that since all output from stb_voxel_render is quad meshes,
|
||||
// triangles are actually rendered as degenerate quads.) In this case,
|
||||
// the distinction betwen STBVOX_GEOM_floor_vheight_03 and
|
||||
// STBVOX_GEOM_floor_vheight_12 comes into play; the former introduces
|
||||
// an edge from the SW to NE corner (i.e. from <0,0,?> to <1,1,?>),
|
||||
// while the latter introduces an edge from the NW to SE corner
|
||||
// (i.e. from <0,1,?> to <1,0,?>.) For a "lazy mesh" look, use
|
||||
// exclusively _03 or _12. For a "classic mesh" look, alternate
|
||||
// _03 and _12 in a checkerboard pattern. For a "smoothest surface"
|
||||
// look, choose the edge based on actual vertex heights.
|
||||
//
|
||||
// The four vertex heights can come from several places. The simplest
|
||||
// encoding is to just use the 'vheight' parameter which stores four
|
||||
// explicit vertex heights for every block. This allows total indepdence,
|
||||
// but at the cost of the most memory usage. Encode this with
|
||||
// STBVOX_MAKE_VHEIGHT(vh_sw, vh_se, vh_nw, vh_ne). These coordinates
|
||||
// are absolute, not affected by block rotations.
|
||||
//
|
||||
// An alternative if you just want to encode some very specific block
|
||||
// types, not all the possibilities--say you just want half-height slopes,
|
||||
// so you want (0,0,1,1) and (1,1,2,2)--then you can use block_vheight
|
||||
// to specify them. The geometry rotation will cause block_vheight values
|
||||
// to be rotated (because it's as if you're just defining a type of
|
||||
// block). This value is also encoded with STBVOX_MAKE_VHEIGHT.
|
||||
//
|
||||
// If you want to save memory and you're creating a "continuous ground"
|
||||
// sort of effect, you can make each vertex of the lattice share the
|
||||
// vheight value; that is, two adjacent blocks that share a vertex will
|
||||
// always get the same vheight value for that vertex. Then you need to
|
||||
// store two bits of vheight for every block, which you do by storing it
|
||||
// as part another data structure. Store the south-west vertex's vheight
|
||||
// with the block. You can either use the "geometry" mesh variable (it's
|
||||
// a parameter to STBVOX_MAKE_GEOMETRY) or you can store it in the
|
||||
// "lighting" mesh variable if you defined STBVOX_CONFIG_VHEIGHT_IN_LIGHTING,
|
||||
// using STBVOX_MAKE_LIGHTING(lighting,vheight).
|
||||
//
|
||||
// Note that if you start with a 2D height map and generate vheight data from
|
||||
// it, you don't necessarily store only one value per (x,y) coordinate,
|
||||
// as the same value may need to be set up at multiple z heights. For
|
||||
// example, if height(8,8) = 13.5, then you want the block at (8,8,13)
|
||||
// to store STBVOX_VERTEX_HEIGHT_half, and this will be used by blocks
|
||||
// at (7,7,13), (8,7,13), (7,8,13), and (8,8,13). However, if you're
|
||||
// allowing steep slopes, it might be the case that you have a block
|
||||
// at (7,7,12) which is supposed to stick up to 13.5; that means
|
||||
// you also need to store STBVOX_VERTEX_HEIGHT_one_and_a_half at (8,8,12).
|
||||
|
||||
enum
|
||||
{
|
||||
@ -1009,7 +1102,7 @@ enum
|
||||
#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)
|
||||
|
||||
#ifdef STBVOX_ROTATION_IN_LIGHTING
|
||||
#if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) || defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING)
|
||||
#define STBVOX_MAKE_LIGHTING(lighting, rot) (((lighting)&~3)+(rot))
|
||||
#else
|
||||
#define STBVOX_MAKE_LIGHTING(lighting) (lighting)
|
||||
@ -1064,6 +1157,7 @@ struct stbvox_mesh_maker
|
||||
#include <assert.h>
|
||||
#include <string.h> // memset
|
||||
|
||||
// have to use our own names to avoid the _MSC_VER path having conflicting type names
|
||||
#ifndef _MSC_VER
|
||||
#include <stdint.h>
|
||||
typedef uint16_t stbvox_uint16;
|
||||
@ -1085,6 +1179,11 @@ struct stbvox_mesh_maker
|
||||
#error "Must defined STBVOX_CONFIG_MODE to select the mode"
|
||||
#endif
|
||||
|
||||
#if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) && defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING)
|
||||
#error "Can't store both rotation and vheight in lighting"
|
||||
#endif
|
||||
|
||||
|
||||
// The following are candidate voxel modes. Only modes 0, 1, and 20 are
|
||||
// currently implemented. Reducing the storage-per-quad further
|
||||
// shouldn't improve performance, although obviously it allow you
|
||||
@ -2261,7 +2360,7 @@ static unsigned char stbvox_rotate_vertex[8][4] =
|
||||
{ 7,6,4,5 }, // zyx=111
|
||||
};
|
||||
|
||||
#ifdef STBVOX_OPTIMIZED_VHEIGHT
|
||||
#ifdef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
|
||||
// optimized vheight generates a single normal over the entire face, even if it's not planar
|
||||
static unsigned char stbvox_optimized_face_up_normal[4][4][4][4] =
|
||||
{
|
||||
@ -2593,7 +2692,7 @@ void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int fac
|
||||
} else {
|
||||
unsigned char *amb = &mm->input.lighting[v_off];
|
||||
int i,j;
|
||||
#ifdef STBVOX_ROTATION_IN_LIGHTING
|
||||
#if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) || defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING)
|
||||
#define STBVOX_GET_LIGHTING(light) ((light) & ~3)
|
||||
#define STBVOX_LIGHTING_ROUNDOFF 8
|
||||
#else
|
||||
@ -2636,7 +2735,7 @@ void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int fac
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef STBVOX_OPTIMIZED_VHEIGHT
|
||||
#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
|
||||
// get opposite-facing normal & texgen for opposite face, used to map up-facing vheight data to down-facing data
|
||||
static unsigned char stbvox_reverse_face[STBVF_count] =
|
||||
{
|
||||
@ -2721,7 +2820,7 @@ static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, in
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef STBVOX_ROTATION_IN_LIGHTING
|
||||
#ifdef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
simple_rot = mm->input.lighting[v_off] & 3;
|
||||
#endif
|
||||
|
||||
@ -2798,7 +2897,7 @@ 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_ROTATION_IN_LIGHTING
|
||||
#ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
rot = (geo >> 4) & 3;
|
||||
geo &= 15;
|
||||
for (i=0; i < 6; ++i) {
|
||||
@ -2814,7 +2913,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
for (i=0; i < 6; ++i)
|
||||
ngeo[i] = mm->input.block_geometry[nbt[i]];
|
||||
if (mm->input.selector) {
|
||||
#ifndef STBVOX_ROTATION_IN_LIGHTING
|
||||
#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;
|
||||
@ -2824,7 +2923,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
nrot[5] = (mm->input.selector[v_off - 1] >> 4) & 3;
|
||||
#endif
|
||||
} else {
|
||||
#ifndef STBVOX_ROTATION_IN_LIGHTING
|
||||
#ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
rot = (geo>>4)&3;
|
||||
geo &= 15;
|
||||
for (i=0; i < 6; ++i) {
|
||||
@ -2835,7 +2934,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef STBVOX_ROTATION_IN_LIGHTING
|
||||
#ifdef STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
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;
|
||||
@ -3000,6 +3099,12 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
int extreme;
|
||||
|
||||
// extract the heights
|
||||
#ifdef STBVOX_CONFIG_VHEIGHT_IN_LIGHTING
|
||||
ht[0] = mm->input.lighting[v_off ] & 3;
|
||||
ht[1] = mm->input.lighting[v_off+ew_off ] & 3;
|
||||
ht[2] = mm->input.lighting[v_off +ns_off] & 3;
|
||||
ht[3] = mm->input.lighting[v_off+ew_off+ns_off] & 3;
|
||||
#else
|
||||
if (mm->input.vheight) {
|
||||
unsigned char v = mm->input.vheight[v_off];
|
||||
ht[0] = (v >> 0) & 3;
|
||||
@ -3018,9 +3123,15 @@ 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.geometry) {
|
||||
ht[0] = mm->input.geometry[v_off ] >> 6;
|
||||
ht[1] = mm->input.geometry[v_off+ew_off ] >> 6;
|
||||
ht[2] = mm->input.geometry[v_off +ns_off] >> 6;
|
||||
ht[3] = mm->input.geometry[v_off+ew_off+ns_off] >> 6;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// flag whether any sides go off the top of the block, which means
|
||||
// our visible_faces test was wrong
|
||||
@ -3072,7 +3183,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
// flat
|
||||
stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, STBVOX_FACE_up);
|
||||
else {
|
||||
#ifndef STBVOX_OPTIMIZED_VHEIGHT
|
||||
#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
|
||||
// check if it's non-planar
|
||||
if (cube[5] + cube[6] != cube[4] + cube[7]) {
|
||||
// not planar, split along diagonal and make degenerate quads
|
||||
@ -3092,7 +3203,7 @@ static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_po
|
||||
// flat
|
||||
stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, STBVOX_FACE_down);
|
||||
else {
|
||||
#ifndef STBVOX_OPTIMIZED_VHEIGHT
|
||||
#ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
|
||||
// check if it's non-planar
|
||||
if (cube[1] + cube[2] != cube[0] + cube[3]) {
|
||||
// not planar, split along diagonal and make degenerate quads
|
||||
|
@ -26,7 +26,7 @@
|
||||
//#define STBVOX_CONFIG_TEX1_EDGE_CLAMP
|
||||
#define STBVOX_CONFIG_DISABLE_TEX2
|
||||
|
||||
#define STBVOX_ROTATION_IN_LIGHTING
|
||||
#define STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
#define STB_VOXEL_RENDER_IMPLEMENTATION
|
||||
#include "stb_voxel_render.h"
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "stb.h"
|
||||
|
||||
#define STBVOX_ROTATION_IN_LIGHTING
|
||||
#define STBVOX_CONFIG_ROTATION_IN_LIGHTING
|
||||
#include "stb_voxel_render.h"
|
||||
|
||||
typedef struct
|
||||
|
Loading…
Reference in New Issue
Block a user