提交 e2b645e4 编写于 作者: S Sean Barrett

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
上级 b7570147
// 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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册