1 // stb_voxel_render.h - v0.88 - Sean Barrett, 2015 - public domain
2 //
3 // This library helps render large-scale "voxel" worlds for games,
4 // in this case, one with blocks that can have textures and that
5 // can also be a few shapes other than cubes.
6 //
7 //    Video introduction:
8 //       http://www.youtube.com/watch?v=2vnTtiLrV1w
9 //
10 //    Minecraft-viewer sample app (not very simple though):
11 //       http://github.com/nothings/stb/tree/master/tests/caveview
12 //
13 // It works by creating triangle meshes. The library includes
14 //
15 //    - converter from dense 3D arrays of block info to vertex mesh
16 //    - vertex & fragment shaders for the vertex mesh
17 //    - assistance in setting up shader state
18 //
19 // For portability, none of the library code actually accesses
20 // the 3D graphics API. (At the moment, it's not actually portable
21 // since the shaders are GLSL only, but patches are welcome.)
22 //
23 // You have to do all the caching and tracking of vertex buffers
24 // yourself. However, you could also try making a game with
25 // a small enough world that it's fully loaded rather than
26 // streaming. Currently the preferred vertex format is 20 bytes
27 // per quad. There are designs to allow much more compact formats
28 // with a slight reduction in shader features, but no roadmap
29 // for actually implementing them.
30 //
31 //
32 // USAGE
33 //
34 //   #define the symbol STB_VOXEL_RENDER_IMPLEMENTATION in *one*
35 //   C/C++ file before the #include of this file; the implementation
36 //   will be generated in that file.
37 //
38 //   If you define the symbols STB_VOXEL_RENDER_STATIC, then the
39 //   implementation will be private to that file.
40 //
41 //
42 // FEATURES
43 //
44 //   - you can choose textured blocks with the features below,
45 //     or colored voxels with 2^24 colors and no textures.
46 //
47 //   - voxels are mostly just cubes, but there's support for
48 //     half-height cubes and diagonal slopes, half-height
49 //     diagonals, and even odder shapes especially for doing
50 //     more-continuous "ground".
51 //
52 //   - texture coordinates are projections along one of the major
53 //     axes, with the per-texture scaling.
54 //
55 //   - a number of aspects of the shader and the vertex format
56 //     are configurable; the library generally takes care of
57 //     coordinating the vertex format with the mesh for you.
58 //
59 //
60 // FEATURES (SHADER PERSPECTIVE)
61 //
62 //   - vertices aligned on integer lattice, z on multiples of 0.5
63 //   - per-vertex "lighting" or "ambient occlusion" value (6 bits)
64 //   - per-vertex texture crossfade (3 bits)
65 //
66 //   - per-face texture #1 id (8-bit index into array texture)
67 //   - per-face texture #2 id (8-bit index into second array texture)
68 //   - per-face color (6-bit palette index, 2 bits of per-texture boolean enable)
69 //   - per-face 5-bit normal for lighting calculations & texture coord computation
70 //   - per-face 2-bit texture matrix rotation to rotate faces
71 //
72 //   - indexed-by-texture-id scale factor (separate for texture #1 and texture #2)
73 //   - indexed-by-texture-#2-id blend mode (alpha composite or modulate/multiply);
74 //     the first is good for decals, the second for detail textures, "light maps",
75 //     etc; both modes are controlled by texture #2's alpha, scaled by the
76 //     per-vertex texture crossfade and the per-face color (if enabled on texture #2);
77 //     modulate/multiply multiplies by an extra factor of 2.0 so that if you
78 //     make detail maps whose average brightness is 0.5 everything works nicely.
79 //
80 //   - ambient lighting: half-lambert directional plus constant, all scaled by vertex ao
81 //   - face can be fullbright (emissive), controlled by per-face color
82 //   - installable lighting, with default single-point-light
83 //   - installable fog, with default hacked smoothstep
84 //
85 //  Note that all the variations of lighting selection and texture
86 //  blending are run-time conditions in the shader, so they can be
87 //  intermixed in a single mesh.
88 //
89 //
90 // INTEGRATION ARC
91 //
92 //   The way to get this library to work from scratch is to do the following:
93 //
94 //      Step 1. define STBVOX_CONFIG_MODE to 0
95 //
96 //        This mode uses only vertex attributes and uniforms, and is easiest
97 //        to get working. It requires 32 bytes per quad and limits the
98 //        size of some tables to avoid hitting uniform limits.
99 //
100 //      Step 2. define STBVOX_CONFIG_MODE to 1
101 //
102 //        This requires using a texture buffer to store the quad data,
103 //        reducing the size to 20 bytes per quad.
104 //
105 //      Step 3: define STBVOX_CONFIG_PREFER_TEXBUFFER
106 //
107 //        This causes some uniforms to be stored as texture buffers
108 //        instead. This increases the size of some of those tables,
109 //        and avoids a potential slow path (gathering non-uniform
110 //        data from uniforms) on some hardware.
111 //
112 //   In the future I might add additional modes that have significantly
113 //   smaller meshes but reduce features, down as small as 6 bytes per quad.
114 //   See elsewhere in this file for a table of candidate modes. Switching
115 //   to a mode will require changing some of your mesh creation code, but
116 //   everything else should be seamless. (And I'd like to change the API
117 //   so that mesh creation is data-driven the way the uniforms are, and
118 //   then you wouldn't even have to change anything but the mode number.)
119 //
120 //
121 // IMPROVEMENTS FOR SHIP-WORTHY PROGRAMS USING THIS LIBRARY
122 //
123 //   I currently tolerate a certain level of "bugginess" in this library.
124 //
125 //   I'm referring to things which look a little wrong (as long as they
126 //   don't cause holes or cracks in the output meshes), or things which
127 //   do not produce as optimal a mesh as possible. Notable examples:
128 //
129 //        -  incorrect lighting on slopes
130 //        -  inefficient meshes for vheight blocks
131 //
132 //   I am willing to do the work to improve these things if someone is
133 //   going to ship a substantial program that would be improved by them.
134 //   (It need not be commercial, nor need it be a game.) I just didn't
135 //   want to do the work up front if it might never be leveraged. So just
136 //   submit a bug report as usual (github is preferred), but add a note
137 //   that this is for a thing that is really going to ship. (That means
138 //   you need to be far enough into the project that it's clear you're
139 //   committed to it; not during early exploratory development.)
140 //
141 //
142 // VOXEL MESH API
143 //
144 //   Context
145 //
146 //     To understand the API, make sure you first understand the feature set
147 //     listed above.
148 //
149 //     Because the vertices are compact, they have very limited spatial
150 //     precision. Thus a single mesh can only contain the data for a limited
151 //     area. To make very large voxel maps, you'll need to build multiple
152 //     vertex buffers. (But you want this anyway for frustum culling.)
153 //
154 //     Each generated mesh has three components:
155 //             - vertex data (vertex buffer)
156 //             - face data (optional, stored in texture buffer)
157 //             - mesh transform (uniforms)
158 //
159 //     Once you've generated the mesh with this library, it's up to you
160 //     to upload it to the GPU, to keep track of the state, and to render
161 //     it.
162 //
163 //   Concept
164 //
165 //     The basic design is that you pass in one or more 3D arrays; each array
166 //     is (typically) one-byte-per-voxel and contains information about one
167 //     or more properties of some particular voxel property.
168 //
169 //     Because there is so much per-vertex and per-face data possible
170 //     in the output, and each voxel can have 6 faces and 8 vertices, it
171 //     would require an very large data structure to describe all
172 //     of the possibilities, and this would cause the mesh-creation
173 //     process to be slow. Instead, the API provides multiple ways
174 //     to express each property, some more compact, others less so;
175 //     each such way has some limitations on what it can express.
176 //
177 //     Note that there are so many paths and combinations, not all of them
178 //     have been tested. Just report bugs and I'll fix 'em.
179 //
180 //   Details
181 //
182 //     See the API documentation in the header-file section.
183 //
184 //
185 // CONTRIBUTORS
186 //
187 //   Features             Porting            Bugfixes & Warnings
188 //  Sean Barrett                          github:r-leyh   Jesus Fernandez
189 //                                        Miguel Lechon   github:Arbeiterunfallversicherungsgesetz
190 //                                        Thomas Frase    James Hofmann
191 //                                        Stephen Olsen   github:guitarfreak
192 //
193 // VERSION HISTORY
194 //
195 //   0.88   (2019-03-04)  fix warnings
196 //   0.87   (2019-02-25)  fix warning
197 //   0.86   (2019-02-07)  fix typos in comments
198 //   0.85   (2017-03-03)  add block_selector (by guitarfreak)
199 //   0.84   (2016-04-02)  fix GLSL syntax error on glModelView path
200 //   0.83   (2015-09-13)  remove non-constant struct initializers to support more compilers
201 //   0.82   (2015-08-01)  added input.packed_compact to store rot, vheight & texlerp efficiently
202 //                        fix broken tex_overlay2
203 //   0.81   (2015-05-28)  fix broken STBVOX_CONFIG_OPTIMIZED_VHEIGHT
204 //   0.80   (2015-04-11)  fix broken STBVOX_CONFIG_ROTATION_IN_LIGHTING refactoring
205 //                        change STBVOX_MAKE_LIGHTING to STBVOX_MAKE_LIGHTING_EXT so
206 //                                    that header defs don't need to see config vars
207 //                        add STBVOX_CONFIG_VHEIGHT_IN_LIGHTING and other vheight fixes
208 //                        added documentation for vheight ("weird slopes")
209 //   0.79   (2015-04-01)  fix the missing types from 0.78; fix string constants being const
210 //   0.78   (2015-04-02)  bad "#else", compile as C++
211 //   0.77   (2015-04-01)  documentation tweaks, rename config var to STB_VOXEL_RENDER_STATIC
212 //   0.76   (2015-04-01)  typos, signed/unsigned shader issue, more documentation
213 //   0.75   (2015-04-01)  initial release
214 //
215 //
216 // HISTORICAL FOUNDATION
217 //
218 //   stb_voxel_render   20-byte quads   2015/01
219 //   zmc engine         32-byte quads   2013/12
220 //   zmc engine         96-byte quads   2011/10
221 //
222 //
223 // LICENSE
224 //
225 //   See end of file for license information.
226 
227 #ifndef INCLUDE_STB_VOXEL_RENDER_H
228 #define INCLUDE_STB_VOXEL_RENDER_H
229 
230 #include <stdlib.h>
231 
232 typedef struct stbvox_mesh_maker stbvox_mesh_maker;
233 typedef struct stbvox_input_description stbvox_input_description;
234 
235 #ifdef STB_VOXEL_RENDER_STATIC
236 #define STBVXDEC static
237 #else
238 #define STBVXDEC extern
239 #endif
240 
241 #ifdef __cplusplus
242 extern "C" {
243 #endif
244 
245 //////////////////////////////////////////////////////////////////////////////
246 //
247 // CONFIGURATION MACROS
248 //
249 //  #define STBVOX_CONFIG_MODE <integer>           // REQUIRED
250 //     Configures the overall behavior of stb_voxel_render. This
251 //     can affect the shaders, the uniform info, and other things.
252 //     (If you need more than one mode in the same app, you can
253 //     use STB_VOXEL_RENDER_STATIC to create multiple versions
254 //     in separate files, and then wrap them.)
255 //
256 //         Mode value       Meaning
257 //             0               Textured blocks, 32-byte quads
258 //             1               Textured blocks, 20-byte quads
259 //            20               Untextured blocks, 32-byte quads
260 //            21               Untextured blocks, 20-byte quads
261 //
262 //
263 //  #define STBVOX_CONFIG_PRECISION_Z  <integer>   // OPTIONAL
264 //     Defines the number of bits of fractional position for Z.
265 //     Only 0 or 1 are valid. 1 is the default. If 0, then a
266 //     single mesh has twice the legal Z range; e.g. in
267 //     modes 0,1,20,21, Z in the mesh can extend to 511 instead
268 //     of 255. However, half-height blocks cannot be used.
269 //
270 // All of the following are just #ifdef tested so need no values, and are optional.
271 //
272 //    STBVOX_CONFIG_BLOCKTYPE_SHORT
273 //        use unsigned 16-bit values for 'blocktype' in the input instead of 8-bit values
274 //
275 //    STBVOX_CONFIG_OPENGL_MODELVIEW
276 //        use the gl_ModelView matrix rather than the explicit uniform
277 //
278 //    STBVOX_CONFIG_HLSL
279 //        NOT IMPLEMENTED! Define HLSL shaders instead of GLSL shaders
280 //
281 //    STBVOX_CONFIG_PREFER_TEXBUFFER
282 //        Stores many of the uniform arrays in texture buffers instead,
283 //        so they can be larger and may be more efficient on some hardware.
284 //
285 //    STBVOX_CONFIG_LIGHTING_SIMPLE
286 //        Creates a simple lighting engine with a single point light source
287 //        in addition to the default half-lambert ambient light.
288 //
289 //    STBVOX_CONFIG_LIGHTING
290 //        Declares a lighting function hook; you must append a lighting function
291 //        to the shader before compiling it:
292 //            vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient);
293 //        'ambient' is the half-lambert ambient light with vertex ambient-occlusion applied
294 //
295 //    STBVOX_CONFIG_FOG_SMOOTHSTEP
296 //        Defines a simple unrealistic fog system designed to maximize
297 //        unobscured view distance while not looking too weird when things
298 //        emerge from the fog. Configured using an extra array element
299 //        in the STBVOX_UNIFORM_ambient uniform.
300 //
301 //    STBVOX_CONFIG_FOG
302 //        Defines a fog function hook; you must append a fog function to
303 //        the shader before compiling it:
304 //            vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha);
305 //        "color" is the incoming pre-fogged color, fragment_alpha is the alpha value,
306 //        and relative_pos is the vector from the point to the camera in worldspace
307 //
308 //    STBVOX_CONFIG_DISABLE_TEX2
309 //        This disables all processing of texture 2 in the shader in case
310 //        you don't use it. Eventually this could be replaced with a mode
311 //        that omits the unused data entirely.
312 //
313 //    STBVOX_CONFIG_TEX1_EDGE_CLAMP
314 //    STBVOX_CONFIG_TEX2_EDGE_CLAMP
315 //        If you want to edge clamp the textures, instead of letting them wrap,
316 //        set this flag. By default stb_voxel_render relies on texture wrapping
317 //        to simplify texture coordinate generation. This flag forces it to do
318 //        it correctly, although there can still be minor artifacts.
319 //
320 //    STBVOX_CONFIG_ROTATION_IN_LIGHTING
321 //        Changes the meaning of the 'lighting' mesher input variable to also
322 //        store the rotation; see later discussion.
323 //
324 //    STBVOX_CONFIG_VHEIGHT_IN_LIGHTING
325 //        Changes the meaning of the 'lighting' mesher input variable to also
326 //        store the vheight; see later discussion. Cannot use both this and
327 //        the previous variable.
328 //
329 //    STBVOX_CONFIG_PREMULTIPLIED_ALPHA
330 //        Adjusts the shader calculations on the assumption that tex1.rgba,
331 //        tex2.rgba, and color.rgba all use premultiplied values, and that
332 //        the output of the fragment shader should be premultiplied.
333 //
334 //    STBVOX_CONFIG_UNPREMULTIPLY
335 //        Only meaningful if STBVOX_CONFIG_PREMULTIPLIED_ALPHA is defined.
336 //        Changes the behavior described above so that the inputs are
337 //        still premultiplied alpha, but the output of the fragment
338 //        shader is not premultiplied alpha. This is needed when allowing
339 //        non-unit alpha values but not doing alpha-blending (for example
340 //        when alpha testing).
341 //
342 
343 //////////////////////////////////////////////////////////////////////////////
344 //
345 // MESHING
346 //
347 // A mesh represents a (typically) small chunk of a larger world.
348 // Meshes encode coordinates using small integers, so those
349 // coordinates must be relative to some base location.
350 // All of the coordinates in the functions below use
351 // these relative coordinates unless explicitly stated
352 // otherwise.
353 //
354 // Input to the meshing step is documented further down
355 
356 STBVXDEC void stbvox_init_mesh_maker(stbvox_mesh_maker *mm);
357 // Call this function to initialize a mesh-maker context structure
358 // used to build meshes. You should have one context per thread
359 // that's building meshes.
360 
361 STBVXDEC void stbvox_set_buffer(stbvox_mesh_maker *mm, int mesh, int slot, void *buffer, size_t len);
362 // Call this to set the buffer into which stbvox will write the mesh
363 // it creates. It can build more than one mesh in parallel (distinguished
364 // by the 'mesh' parameter), and each mesh can be made up of more than
365 // one buffer (distinguished by the 'slot' parameter).
366 //
367 // Multiple meshes are under your control; use the 'selector' input
368 // variable to choose which mesh each voxel's vertices are written to.
369 // For example, you can use this to generate separate meshes for opaque
370 // and transparent data.
371 //
372 // You can query the number of slots by calling stbvox_get_buffer_count
373 // described below. The meaning of the buffer for each slot depends
374 // on STBVOX_CONFIG_MODE.
375 //
376 //   In mode 0 & mode 20, there is only one slot. The mesh data for that
377 //   slot is two interleaved vertex attributes: attr_vertex, a single
378 //   32-bit uint, and attr_face, a single 32-bit uint.
379 //
380 //   In mode 1 & mode 21, there are two slots. The first buffer should
381 //   be four times as large as the second buffer. The first buffer
382 //   contains a single vertex attribute: 'attr_vertex', a single 32-bit uint.
383 //   The second buffer contains texture buffer data (an array of 32-bit uints)
384 //   that will be accessed through the sampler identified by STBVOX_UNIFORM_face_data.
385 
386 STBVXDEC int stbvox_get_buffer_count(stbvox_mesh_maker *mm);
387 // Returns the number of buffers needed per mesh as described above.
388 
389 STBVXDEC int stbvox_get_buffer_size_per_quad(stbvox_mesh_maker *mm, int slot);
390 // Returns how much of a given buffer will get used per quad. This
391 // allows you to choose correct relative sizes for each buffer, although
392 // the values are fixed based on the configuration you've selected at
393 // compile time, and the details are described in stbvox_set_buffer.
394 
395 STBVXDEC void stbvox_set_default_mesh(stbvox_mesh_maker *mm, int mesh);
396 // Selects which mesh the mesher will output to (see previous function)
397 // if the input doesn't specify a per-voxel selector. (I doubt this is
398 // useful, but it's here just in case.)
399 
400 STBVXDEC stbvox_input_description *stbvox_get_input_description(stbvox_mesh_maker *mm);
401 // This function call returns a pointer to the stbvox_input_description part
402 // of stbvox_mesh_maker (which you should otherwise treat as opaque). You
403 // zero this structure, then fill out the relevant pointers to the data
404 // describing your voxel object/world.
405 //
406 // See further documentation at the description of stbvox_input_description below.
407 
408 STBVXDEC void stbvox_set_input_stride(stbvox_mesh_maker *mm, int x_stride_in_elements, int y_stride_in_elements);
409 // This sets the stride between successive elements of the 3D arrays
410 // in the stbvox_input_description. Z values are always stored consecutively.
411 // (The preferred coordinate system for stbvox is X right, Y forwards, Z up.)
412 
413 STBVXDEC void stbvox_set_input_range(stbvox_mesh_maker *mm, int x0, int y0, int z0, int x1, int y1, int z1);
414 // This sets the range of values in the 3D array for the voxels that
415 // the mesh generator will convert. The lower values are inclusive,
416 // the higher values are exclusive, so (0,0,0) to (16,16,16) generates
417 // mesh data associated with voxels up to (15,15,15) but no higher.
418 //
419 // The mesh generate generates faces at the boundary between open space
420 // and solid space but associates them with the solid space, so if (15,0,0)
421 // is open and (16,0,0) is solid, then the mesh will contain the boundary
422 // between them if x0 <= 16 and x1 > 16.
423 //
424 // Note that the mesh generator will access array elements 1 beyond the
425 // limits set in these parameters. For example, if you set the limits
426 // to be (0,0,0) and (16,16,16), then the generator will access all of
427 // the voxels between (-1,-1,-1) and (16,16,16), including (16,16,16).
428 // You may have to do pointer arithmetic to make it work.
429 //
430 // For example, caveview processes mesh chunks that are 32x32x16, but it
431 // does this using input buffers that are 34x34x18.
432 //
433 // The lower limits are x0 >= 0, y0 >= 0, and z0 >= 0.
434 //
435 // The upper limits are mode dependent, but all the current methods are
436 // limited to x1 < 127, y1 < 127, z1 < 255. Note that these are not
437 // powers of two; if you want to use power-of-two chunks (to make
438 // it efficient to decide which chunk a coordinate falls in), you're
439 // limited to at most x1=64, y1=64, z1=128. For classic Minecraft-style
440 // worlds with limited vertical extent, I recommend using a single
441 // chunk for the entire height, which limits the height to 255 blocks
442 // (one less than Minecraft), and only chunk the map in X & Y.
443 
444 STBVXDEC int stbvox_make_mesh(stbvox_mesh_maker *mm);
445 // Call this function to create mesh data for the currently configured
446 // set of input data. This appends to the currently configured mesh output
447 // buffer. Returns 1 on success. If there is not enough room in the buffer,
448 // it outputs as much as it can, and returns 0; you need to switch output
449 // buffers (either by calling stbvox_set_buffer to set new buffers, or
450 // by copying the data out and calling stbvox_reset_buffers), and then
451 // call this function again without changing any of the input parameters.
452 //
453 // Note that this function appends; you can call it multiple times to
454 // build a single mesh. For example, caveview uses chunks that are
455 // 32x32x255, but builds the mesh for it by processing 32x32x16 at atime
456 // (this is faster as it is reuses the same 34x34x18 input buffers rather
457 // than needing 34x34x257 input buffers).
458 
459 // Once you're done creating a mesh into a given buffer,
460 // consider the following functions:
461 
462 STBVXDEC int stbvox_get_quad_count(stbvox_mesh_maker *mm, int mesh);
463 // Returns the number of quads in the mesh currently generated by mm.
464 // This is the sum of all consecutive stbvox_make_mesh runs appending
465 // to the same buffer. 'mesh' distinguishes between the multiple user
466 // meshes available via 'selector' or stbvox_set_default_mesh.
467 //
468 // Typically you use this function when you're done building the mesh
469 // and want to record how to draw it.
470 //
471 // Note that there are no index buffers; the data stored in the buffers
472 // should be drawn as quads (e.g. with GL_QUAD); if your API does not
473 // support quads, you can create a single index buffer large enough to
474 // draw your largest vertex buffer, and reuse it for every rendering.
475 // (Note that if you use 32-bit indices, you'll use 24 bytes of bandwidth
476 // per quad, more than the 20 bytes for the vertex/face mesh data.)
477 
478 STBVXDEC void stbvox_set_mesh_coordinates(stbvox_mesh_maker *mm, int x, int y, int z);
479 // Sets the global coordinates for this chunk, such that (0,0,0) relative
480 // coordinates will be at (x,y,z) in global coordinates.
481 
482 STBVXDEC void stbvox_get_bounds(stbvox_mesh_maker *mm, float bounds[2][3]);
483 // Returns the bounds for the mesh in global coordinates. Use this
484 // for e.g. frustum culling the mesh. @BUG: this just uses the
485 // values from stbvox_set_input_range(), so if you build by
486 // appending multiple values, this will be wrong, and you need to
487 // set stbvox_set_input_range() to the full size. Someday this
488 // will switch to tracking the actual bounds of the *mesh*, though.
489 
490 STBVXDEC void stbvox_get_transform(stbvox_mesh_maker *mm, float transform[3][3]);
491 // Returns the 'transform' data for the shader uniforms. It is your
492 // job to set this to the shader before drawing the mesh. It is the
493 // only uniform that needs to change per-mesh. Note that it is not
494 // a 3x3 matrix, but rather a scale to decode fixed point numbers as
495 // floats, a translate from relative to global space, and a special
496 // translation for texture coordinate generation that avoids
497 // floating-point precision issues. @TODO: currently we add the
498 // global translation to the vertex, than multiply by modelview,
499 // but this means if camera location and vertex are far from the
500 // origin, we lose precision. Need to make a special modelview with
501 // the translation (or some of it) factored out to avoid this.
502 
503 STBVXDEC void stbvox_reset_buffers(stbvox_mesh_maker *mm);
504 // Call this function if you're done with the current output buffer
505 // but want to reuse it (e.g. you're done appending with
506 // stbvox_make_mesh and you've copied the data out to your graphics API
507 // so can reuse the buffer).
508 
509 //////////////////////////////////////////////////////////////////////////////
510 //
511 // RENDERING
512 //
513 
514 STBVXDEC char *stbvox_get_vertex_shader(void);
515 // Returns the (currently GLSL-only) vertex shader.
516 
517 STBVXDEC char *stbvox_get_fragment_shader(void);
518 // Returns the (currently GLSL-only) fragment shader.
519 // You can override the lighting and fogging calculations
520 // by appending data to the end of these; see the #define
521 // documentation for more information.
522 
523 STBVXDEC char *stbvox_get_fragment_shader_alpha_only(void);
524 // Returns a slightly cheaper fragment shader that computes
525 // alpha but not color. This is useful for e.g. a depth-only
526 // pass when using alpha test.
527 
528 typedef struct stbvox_uniform_info stbvox_uniform_info;
529 
530 STBVXDEC int stbvox_get_uniform_info(stbvox_uniform_info *info, int uniform);
531 // Gets the information about a uniform necessary for you to
532 // set up each uniform with a minimal amount of explicit code.
533 // See the sample code after the structure definition for stbvox_uniform_info,
534 // further down in this header section.
535 //
536 // "uniform" is from the list immediately following. For many
537 // of these, default values are provided which you can set.
538 // Most values are shared for most draw calls; e.g. for stateful
539 // APIs you can set most of the state only once. Only
540 // STBVOX_UNIFORM_transform needs to change per draw call.
541 //
542 // STBVOX_UNIFORM_texscale
543 //    64- or 128-long vec4 array. (128 only if STBVOX_CONFIG_PREFER_TEXBUFFER)
544 //    x: scale factor to apply to texture #1. must be a power of two. 1.0 means 'face-sized'
545 //    y: scale factor to apply to texture #2. must be a power of two. 1.0 means 'face-sized'
546 //    z: blend mode indexed by texture #2. 0.0 is alpha compositing; 1.0 is multiplication.
547 //    w: unused currently. @TODO use to support texture animation?
548 //
549 //    Texscale is indexed by the bottom 6 or 7 bits of the texture id; thus for
550 //    example the texture at index 0 in the array and the texture in index 128 of
551 //    the array must be scaled the same. This means that if you only have 64 or 128
552 //    unique textures, they all get distinct values anyway; otherwise you have
553 //    to group them in pairs or sets of four.
554 //
555 // STBVOX_UNIFORM_ambient
556 //    4-long vec4 array:
557 //      ambient[0].xyz   - negative of direction of a directional light for half-lambert
558 //      ambient[1].rgb   - color of light scaled by NdotL (can be negative)
559 //      ambient[2].rgb   - constant light added to above calculation;
560 //                         effectively light ranges from ambient[2]-ambient[1] to ambient[2]+ambient[1]
561 //      ambient[3].rgb   - fog color for STBVOX_CONFIG_FOG_SMOOTHSTEP
562 //      ambient[3].a     - reciprocal of squared distance of farthest fog point (viewing distance)
563 
564 
565                                //  +----- has a default value
566                                //  |  +-- you should always use the default value
567 enum                           //  V  V
568 {                              //  ------------------------------------------------
569    STBVOX_UNIFORM_face_data,   //  n      the sampler with the face texture buffer
570    STBVOX_UNIFORM_transform,   //  n      the transform data from stbvox_get_transform
571    STBVOX_UNIFORM_tex_array,   //  n      an array of two texture samplers containing the two texture arrays
572    STBVOX_UNIFORM_texscale,    //  Y      a table of texture properties, see above
573    STBVOX_UNIFORM_color_table, //  Y      64 vec4 RGBA values; a default palette is provided; if A > 1.0, fullbright
574    STBVOX_UNIFORM_normals,     //  Y  Y   table of normals, internal-only
575    STBVOX_UNIFORM_texgen,      //  Y  Y   table of texgen vectors, internal-only
576    STBVOX_UNIFORM_ambient,     //  n      lighting & fog info, see above
577    STBVOX_UNIFORM_camera_pos,  //  Y      camera position in global voxel space (for lighting & fog)
578 
579    STBVOX_UNIFORM_count,
580 };
581 
582 enum
583 {
584    STBVOX_UNIFORM_TYPE_none,
585    STBVOX_UNIFORM_TYPE_sampler,
586    STBVOX_UNIFORM_TYPE_vec2,
587    STBVOX_UNIFORM_TYPE_vec3,
588    STBVOX_UNIFORM_TYPE_vec4,
589 };
590 
591 struct stbvox_uniform_info
592 {
593    int type;                    // which type of uniform
594    int bytes_per_element;       // the size of each uniform array element (e.g. vec3 = 12 bytes)
595    int array_length;            // length of the uniform array
596    char *name;                  // name in the shader @TODO use numeric binding
597    float *default_value;        // if not NULL, you can use this as the uniform pointer
598    int use_tex_buffer;          // if true, then the uniform is a sampler but the data can come from default_value
599 };
600 
601 //////////////////////////////////////////////////////////////////////////////
602 //
603 // Uniform sample code
604 //
605 
606 #if 0
607 // Run this once per frame before drawing all the meshes.
608 // You still need to separately set the 'transform' uniform for every mesh.
609 void setup_uniforms(GLuint shader, float camera_pos[4], GLuint tex1, GLuint tex2)
610 {
611    int i;
612    glUseProgram(shader); // so uniform binding works
613    for (i=0; i < STBVOX_UNIFORM_count; ++i) {
614       stbvox_uniform_info sui;
615       if (stbvox_get_uniform_info(&sui, i)) {
616          GLint loc = glGetUniformLocation(shader, sui.name);
617          if (loc != 0) {
618             switch (i) {
619                case STBVOX_UNIFORM_camera_pos: // only needed for fog
620                   glUniform4fv(loc, sui.array_length, camera_pos);
621                   break;
622 
623                case STBVOX_UNIFORM_tex_array: {
624                   GLuint tex_unit[2] = { 0, 1 }; // your choice of samplers
625                   glUniform1iv(loc, 2, tex_unit);
626 
627                   glActiveTexture(GL_TEXTURE0 + tex_unit[0]); glBindTexture(GL_TEXTURE_2D_ARRAY, tex1);
628                   glActiveTexture(GL_TEXTURE0 + tex_unit[1]); glBindTexture(GL_TEXTURE_2D_ARRAY, tex2);
629                   glActiveTexture(GL_TEXTURE0); // reset to default
630                   break;
631                }
632 
633                case STBVOX_UNIFORM_face_data:
634                   glUniform1i(loc, SAMPLER_YOU_WILL_BIND_PER_MESH_FACE_DATA_TO);
635                   break;
636 
637                case STBVOX_UNIFORM_ambient:     // you definitely want to override this
638                case STBVOX_UNIFORM_color_table: // you might want to override this
639                case STBVOX_UNIFORM_texscale:    // you may want to override this
640                   glUniform4fv(loc, sui.array_length, sui.default_value);
641                   break;
642 
643                case STBVOX_UNIFORM_normals:     // you never want to override this
644                case STBVOX_UNIFORM_texgen:      // you never want to override this
645                   glUniform3fv(loc, sui.array_length, sui.default_value);
646                   break;
647             }
648          }
649       }
650    }
651 }
652 #endif
653 
654 #ifdef __cplusplus
655 }
656 #endif
657 
658 //////////////////////////////////////////////////////////////////////////////
659 //
660 // INPUT TO MESHING
661 //
662 
663 // Shapes of blocks that aren't always cubes
664 enum
665 {
666    STBVOX_GEOM_empty,
667    STBVOX_GEOM_knockout,  // creates a hole in the mesh
668    STBVOX_GEOM_solid,
669    STBVOX_GEOM_transp,    // solid geometry, but transparent contents so neighbors generate normally, unless same blocktype
670 
671    // following 4 can be represented by vheight as well
672    STBVOX_GEOM_slab_upper,
673    STBVOX_GEOM_slab_lower,
674    STBVOX_GEOM_floor_slope_north_is_top,
675    STBVOX_GEOM_ceil_slope_north_is_bottom,
676 
677    STBVOX_GEOM_floor_slope_north_is_top_as_wall_UNIMPLEMENTED,   // same as floor_slope above, but uses wall's texture & texture projection
678    STBVOX_GEOM_ceil_slope_north_is_bottom_as_wall_UNIMPLEMENTED,
679    STBVOX_GEOM_crossed_pair,    // corner-to-corner pairs, with normal vector bumped upwards
680    STBVOX_GEOM_force,           // like GEOM_transp, but faces visible even if neighbor is same type, e.g. minecraft fancy leaves
681 
682    // these access vheight input
683    STBVOX_GEOM_floor_vheight_03 = 12,  // diagonal is SW-NE
684    STBVOX_GEOM_floor_vheight_12,       // diagonal is SE-NW
685    STBVOX_GEOM_ceil_vheight_03,
686    STBVOX_GEOM_ceil_vheight_12,
687 
688    STBVOX_GEOM_count, // number of geom cases
689 };
690 
691 enum
692 {
693    STBVOX_FACE_east,
694    STBVOX_FACE_north,
695    STBVOX_FACE_west,
696    STBVOX_FACE_south,
697    STBVOX_FACE_up,
698    STBVOX_FACE_down,
699 
700    STBVOX_FACE_count,
701 };
702 
703 #ifdef STBVOX_CONFIG_BLOCKTYPE_SHORT
704 typedef unsigned short stbvox_block_type;
705 #else
706 typedef unsigned char stbvox_block_type;
707 #endif
708 
709 // 24-bit color
710 typedef struct
711 {
712    unsigned char r,g,b;
713 } stbvox_rgb;
714 
715 #define STBVOX_COLOR_TEX1_ENABLE   64
716 #define STBVOX_COLOR_TEX2_ENABLE  128
717 
718 // This is the data structure you fill out. Most of the arrays can be
719 // NULL, except when one is required to get the value to index another.
720 //
721 // The compass system used in the following descriptions is:
722 //     east means increasing x
723 //     north means increasing y
724 //     up means increasing z
725 struct stbvox_input_description
726 {
727    unsigned char lighting_at_vertices;
728    // The default is lighting values (i.e. ambient occlusion) are at block
729    // center, and the vertex light is gathered from those adjacent block
730    // centers that the vertex is facing. This makes smooth lighting
731    // consistent across adjacent faces with the same orientation.
732    //
733    // Setting this flag to non-zero gives you explicit control
734    // of light at each vertex, but now the lighting/ao will be
735    // shared by all vertices at the same point, even if they
736    // have different normals.
737 
738    // these are mostly 3D maps you use to define your voxel world, using x_stride and y_stride
739    // note that for cache efficiency, you want to use the block_foo palettes as much as possible instead
740 
741    stbvox_rgb *rgb;
742    // Indexed by 3D coordinate.
743    // 24-bit voxel color for STBVOX_CONFIG_MODE = 20 or 21 only
744 
745    unsigned char *lighting;
746    // Indexed by 3D coordinate. The lighting value / ambient occlusion
747    // value that is used to define the vertex lighting values.
748    // The raw lighting values are defined at the center of blocks
749    // (or at vertex if 'lighting_at_vertices' is true).
750    //
751    // If the macro STBVOX_CONFIG_ROTATION_IN_LIGHTING is defined,
752    // then an additional 2-bit block rotation value is stored
753    // in this field as well.
754    //
755    // Encode with STBVOX_MAKE_LIGHTING_EXT(lighting,rot)--here
756    // 'lighting' should still be 8 bits, as the macro will
757    // discard the bottom bits automatically. Similarly, if
758    // using STBVOX_CONFIG_VHEIGHT_IN_LIGHTING, encode with
759    // STBVOX_MAKE_LIGHTING_EXT(lighting,vheight).
760    //
761    // (Rationale: rotation needs to be independent of blocktype,
762    // but is only 2 bits so doesn't want to be its own array.
763    // Lighting is the one thing that was likely to already be
764    // in use and that I could easily steal 2 bits from.)
765 
766    stbvox_block_type *blocktype;
767    // Indexed by 3D coordinate. This is a core "block type" value, which is used
768    // to index into other arrays; essentially a "palette". This is much more
769    // memory-efficient and performance-friendly than storing the values explicitly,
770    // but only makes sense if the values are always synchronized.
771    //
772    // If a voxel's blocktype is 0, it is assumed to be empty (STBVOX_GEOM_empty),
773    // and no other blocktypes should be STBVOX_GEOM_empty. (Only if you do not
774    // have blocktypes should STBVOX_GEOM_empty ever used.)
775    //
776    // Normally it is an unsigned byte, but you can override it to be
777    // a short if you have too many blocktypes.
778 
779    unsigned char *geometry;
780    // Indexed by 3D coordinate. Contains the geometry type for the block.
781    // Also contains a 2-bit rotation for how the whole block is rotated.
782    // Also includes a 2-bit vheight value when using shared vheight values.
783    // See the separate vheight documentation.
784    // Encode with STBVOX_MAKE_GEOMETRY(geom, rot, vheight)
785 
786    unsigned char *block_geometry;
787    // Array indexed by blocktype containing the geometry for this block, plus
788    // a 2-bit "simple rotation". Note rotation has limited use since it's not
789    // independent of blocktype.
790    //
791    // Encode with STBVOX_MAKE_GEOMETRY(geom,simple_rot,0)
792 
793    unsigned char *block_tex1;
794    // Array indexed by blocktype containing the texture id for texture #1.
795 
796    unsigned char (*block_tex1_face)[6];
797    // Array indexed by blocktype and face containing the texture id for texture #1.
798    // The N/E/S/W face choices can be rotated by one of the rotation selectors;
799    // The top & bottom face textures will rotate to match.
800    // Note that it only makes sense to use one of block_tex1 or block_tex1_face;
801    // this pattern repeats throughout and this notice is not repeated.
802 
803    unsigned char *tex2;
804    // Indexed by 3D coordinate. Contains the texture id for texture #2
805    // to use on all faces of the block.
806 
807    unsigned char *block_tex2;
808    // Array indexed by blocktype containing the texture id for texture #2.
809 
810    unsigned char (*block_tex2_face)[6];
811    // Array indexed by blocktype and face containing the texture id for texture #2.
812    // The N/E/S/W face choices can be rotated by one of the rotation selectors;
813    // The top & bottom face textures will rotate to match.
814 
815    unsigned char *color;
816    // Indexed by 3D coordinate. Contains the color for all faces of the block.
817    // The core color value is 0..63.
818    // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable)
819 
820    unsigned char *block_color;
821    // Array indexed by blocktype containing the color value to apply to the faces.
822    // The core color value is 0..63.
823    // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable)
824 
825    unsigned char (*block_color_face)[6];
826    // Array indexed by blocktype and face containing the color value to apply to that face.
827    // The core color value is 0..63.
828    // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable)
829 
830    unsigned char *block_texlerp;
831    // Array indexed by blocktype containing 3-bit scalar for texture #2 alpha
832    // (known throughout as 'texlerp'). This is constant over every face even
833    // though the property is potentially per-vertex.
834 
835    unsigned char (*block_texlerp_face)[6];
836    // Array indexed by blocktype and face containing 3-bit scalar for texture #2 alpha.
837    // This is constant over the face even though the property is potentially per-vertex.
838 
839    unsigned char *block_vheight;
840    // Array indexed by blocktype containing the vheight values for the
841    // top or bottom face of this block. These will rotate properly if the
842    // block is rotated. See discussion of vheight.
843    // Encode with STBVOX_MAKE_VHEIGHT(sw_height, se_height, nw_height, ne_height)
844 
845    unsigned char *selector;
846    // Array indexed by 3D coordinates indicating which output mesh to select.
847 
848    unsigned char *block_selector;
849    // Array indexed by blocktype indicating which output mesh to select.
850 
851    unsigned char *side_texrot;
852    // Array indexed by 3D coordinates encoding 2-bit texture rotations for the
853    // faces on the E/N/W/S sides of the block.
854    // Encode with STBVOX_MAKE_SIDE_TEXROT(rot_e, rot_n, rot_w, rot_s)
855 
856    unsigned char *block_side_texrot;
857    // Array indexed by blocktype encoding 2-bit texture rotations for the faces
858    // on the E/N/W/S sides of the block.
859    // Encode with STBVOX_MAKE_SIDE_TEXROT(rot_e, rot_n, rot_w, rot_s)
860 
861    unsigned char *overlay;                 // index into palettes listed below
862    // Indexed by 3D coordinate. If 0, there is no overlay. If non-zero,
863    // it indexes into to the below arrays and overrides the values
864    // defined by the blocktype.
865 
866    unsigned char (*overlay_tex1)[6];
867    // Array indexed by overlay value and face, containing an override value
868    // for the texture id for texture #1. If 0, the value defined by blocktype
869    // is used.
870 
871    unsigned char (*overlay_tex2)[6];
872    // Array indexed by overlay value and face, containing an override value
873    // for the texture id for texture #2. If 0, the value defined by blocktype
874    // is used.
875 
876    unsigned char (*overlay_color)[6];
877    // Array indexed by overlay value and face, containing an override value
878    // for the face color. If 0, the value defined by blocktype is used.
879 
880    unsigned char *overlay_side_texrot;
881    // Array indexed by overlay value, encoding 2-bit texture rotations for the faces
882    // on the E/N/W/S sides of the block.
883    // Encode with STBVOX_MAKE_SIDE_TEXROT(rot_e, rot_n, rot_w, rot_s)
884 
885    unsigned char *rotate;
886    // Indexed by 3D coordinate. Allows independent rotation of several
887    // parts of the voxel, where by rotation I mean swapping textures
888    // and colors between E/N/S/W faces.
889    //    Block: rotates anything indexed by blocktype
890    //    Overlay: rotates anything indexed by overlay
891    //    EColor: rotates faces defined in ecolor_facemask
892    // Encode with STBVOX_MAKE_MATROT(block,overlay,ecolor)
893 
894    unsigned char *tex2_for_tex1;
895    // Array indexed by tex1 containing the texture id for texture #2.
896    // You can use this if the two are always/almost-always strictly
897    // correlated (e.g. if tex2 is a detail texture for tex1), as it
898    // will be more efficient (touching fewer cache lines) than using
899    // e.g. block_tex2_face.
900 
901    unsigned char *tex2_replace;
902    // Indexed by 3D coordinate. Specifies the texture id for texture #2
903    // to use on a single face of the voxel, which must be E/N/W/S (not U/D).
904    // The texture id is limited to 6 bits unless tex2_facemask is also
905    // defined (see below).
906    // Encode with STBVOX_MAKE_TEX2_REPLACE(tex2, face)
907 
908    unsigned char *tex2_facemask;
909    // Indexed by 3D coordinate. Specifies which of the six faces should
910    // have their tex2 replaced by the value of tex2_replace. In this
911    // case, all 8 bits of tex2_replace are used as the texture id.
912    // Encode with STBVOX_MAKE_FACE_MASK(east,north,west,south,up,down)
913 
914    unsigned char *extended_color;
915    // Indexed by 3D coordinate. Specifies a value that indexes into
916    // the ecolor arrays below (both of which must be defined).
917 
918    unsigned char *ecolor_color;
919    // Indexed by extended_color value, specifies an optional override
920    // for the color value on some faces.
921    // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable)
922 
923    unsigned char *ecolor_facemask;
924    // Indexed by extended_color value, this specifies which faces the
925    // color in ecolor_color should be applied to. The faces can be
926    // independently rotated by the ecolor value of 'rotate', if it exists.
927    // Encode with STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d)
928 
929    unsigned char *color2;
930    // Indexed by 3D coordinates, specifies an alternative color to apply
931    // to some of the faces of the block.
932    // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable)
933 
934    unsigned char *color2_facemask;
935    // Indexed by 3D coordinates, specifies which faces should use the
936    // color defined in color2. No rotation value is applied.
937    // Encode with STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d)
938 
939    unsigned char *color3;
940    // Indexed by 3D coordinates, specifies an alternative color to apply
941    // to some of the faces of the block.
942    // Encode with STBVOX_MAKE_COLOR(color_number, tex1_enable, tex2_enable)
943 
944    unsigned char *color3_facemask;
945    // Indexed by 3D coordinates, specifies which faces should use the
946    // color defined in color3. No rotation value is applied.
947    // Encode with STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d)
948 
949    unsigned char *texlerp_simple;
950    // Indexed by 3D coordinates, this is the smallest texlerp encoding
951    // that can do useful work. It consits of three values: baselerp,
952    // vertlerp, and face_vertlerp. Baselerp defines the value
953    // to use on all of the faces but one, from the STBVOX_TEXLERP_BASE
954    // values. face_vertlerp is one of the 6 face values (or STBVOX_FACE_NONE)
955    // which specifies the face should use the vertlerp values.
956    // Vertlerp defines a lerp value at every vertex of the mesh.
957    // Thus, one face can have per-vertex texlerp values, and those
958    // values are encoded in the space so that they will be shared
959    // by adjacent faces that also use vertlerp, allowing continuity
960    // (this is used for the "texture crossfade" bit of the release video).
961    // Encode with STBVOX_MAKE_TEXLERP_SIMPLE(baselerp, vertlerp, face_vertlerp)
962 
963    // The following texlerp encodings are experimental and maybe not
964    // that useful.
965 
966    unsigned char *texlerp;
967    // Indexed by 3D coordinates, this defines four values:
968    //   vertlerp is a lerp value at every vertex of the mesh (using STBVOX_TEXLERP_BASE values).
969    //   ud is the value to use on up and down faces, from STBVOX_TEXLERP_FACE values
970    //   ew is the value to use on east and west faces, from STBVOX_TEXLERP_FACE values
971    //   ns is the value to use on north and south faces, from STBVOX_TEXLERP_FACE values
972    // If any of ud, ew, or ns is STBVOX_TEXLERP_FACE_use_vert, then the
973    // vertlerp values for the vertices are gathered and used for those faces.
974    // Encode with STBVOX_MAKE_TEXLERP(vertlerp,ud,ew,sw)
975 
976    unsigned short *texlerp_vert3;
977    // Indexed by 3D coordinates, this works with texlerp and
978    // provides a unique texlerp value for every direction at
979    // every vertex. The same rules of whether faces share values
980    // applies. The STBVOX_TEXLERP_FACE vertlerp value defined in
981    // texlerp is only used for the down direction. The values at
982    // each vertex in other directions are defined in this array,
983    // and each uses the STBVOX_TEXLERP3 values (i.e. full precision
984    // 3-bit texlerp values).
985    // Encode with STBVOX_MAKE_VERT3(vertlerp_e,vertlerp_n,vertlerp_w,vertlerp_s,vertlerp_u)
986 
987    unsigned short *texlerp_face3;          // e:3,n:3,w:3,s:3,u:2,d:2
988    // Indexed by 3D coordinates, this provides a compact way to
989    // fully specify the texlerp value indepenendly for every face,
990    // but doesn't allow per-vertex variation. E/N/W/S values are
991    // encoded using STBVOX_TEXLERP3 values, whereas up and down
992    // use STBVOX_TEXLERP_SIMPLE values.
993    // Encode with STBVOX_MAKE_FACE3(face_e,face_n,face_w,face_s,face_u,face_d)
994 
995    unsigned char *vheight;                 // STBVOX_MAKE_VHEIGHT   -- sw:2, se:2, nw:2, ne:2, doesn't rotate
996    // Indexed by 3D coordinates, this defines the four
997    // vheight values to use if the geometry is STBVOX_GEOM_vheight*.
998    // See the vheight discussion.
999 
1000    unsigned char *packed_compact;
1001    // Stores block rotation, vheight, and texlerp values:
1002    //    block rotation: 2 bits
1003    //    vertex vheight: 2 bits
1004    //    use_texlerp   : 1 bit
1005    //    vertex texlerp: 3 bits
1006    // If STBVOX_CONFIG_UP_TEXLERP_PACKED is defined, then 'vertex texlerp' is
1007    // used for up faces if use_texlerp is 1. If STBVOX_CONFIG_DOWN_TEXLERP_PACKED
1008    // is defined, then 'vertex texlerp' is used for down faces if use_texlerp is 1.
1009    // Note if those symbols are defined but packed_compact is NULL, the normal
1010    // texlerp default will be used.
1011    // Encode with STBVOX_MAKE_PACKED_COMPACT(rot, vheight, texlerp, use_texlerp)
1012 };
1013 // @OPTIMIZE allow specializing; build a single struct with all of the
1014 // 3D-indexed arrays combined so it's AoS instead of SoA for better
1015 // cache efficiency
1016 
1017 
1018 //////////////////////////////////////////////////////////////////////////////
1019 //
1020 //  VHEIGHT DOCUMENTATION
1021 //
1022 //  "vheight" is the internal name for the special block types
1023 //  with sloped tops or bottoms. "vheight" stands for "vertex height".
1024 //
1025 //  Note that these blocks are very flexible (there are 256 of them,
1026 //  although at least 17 of them should never be used), but they
1027 //  also have a disadvantage that they generate extra invisible
1028 //  faces; the generator does not currently detect whether adjacent
1029 //  vheight blocks hide each others sides, so those side faces are
1030 //  always generated. For a continuous ground terrain, this means
1031 //  that you may generate 5x as many quads as needed. See notes
1032 //  on "improvements for shipping products" in the introduction.
1033 
1034 enum
1035 {
1036    STBVOX_VERTEX_HEIGHT_0,
1037    STBVOX_VERTEX_HEIGHT_half,
1038    STBVOX_VERTEX_HEIGHT_1,
1039    STBVOX_VERTEX_HEIGHT_one_and_a_half,
1040 };
1041 // These are the "vheight" values. Vheight stands for "vertex height".
1042 // The idea is that for a "floor vheight" block, you take a cube and
1043 // reposition the top-most vertices at various heights as specified by
1044 // the vheight values. Similarly, a "ceiling vheight" block takes a
1045 // cube and repositions the bottom-most vertices.
1046 //
1047 // A floor block only adjusts the top four vertices; the bottom four vertices
1048 // remain at the bottom of the block. The height values are 2 bits,
1049 // measured in halves of a block; so you can specify heights of 0/2,
1050 // 1/2, 2/2, or 3/2. 0 is the bottom of the block, 1 is halfway
1051 // up the block, 2 is the top of the block, and 3 is halfway up the
1052 // next block (and actually outside of the block). The value 3 is
1053 // actually legal for floor vheight (but not ceiling), and allows you to:
1054 //
1055 //     (A) have smoother terrain by having slopes that cross blocks,
1056 //         e.g. (1,1,3,3) is a regular-seeming slope halfway between blocks
1057 //     (B) make slopes steeper than 45-degrees, e.g. (0,0,3,3)
1058 //
1059 // (Because only z coordinates have half-block precision, and x&y are
1060 // limited to block corner precision, it's not possible to make these
1061 // things "properly" out of blocks, e.g. a half-slope block on its side
1062 // or a sloped block halfway between blocks that's made out of two blocks.)
1063 //
1064 // If you define STBVOX_CONFIG_OPTIMIZED_VHEIGHT, then the top face
1065 // (or bottom face for a ceiling vheight block) will be drawn as a
1066 // single quad even if the four vertex heights aren't planar, and a
1067 // single normal will be used over the entire quad. If you
1068 // don't define it, then if the top face is non-planar, it will be
1069 // split into two triangles, each with their own normal/lighting.
1070 // (Note that since all output from stb_voxel_render is quad meshes,
1071 // triangles are actually rendered as degenerate quads.) In this case,
1072 // the distinction between STBVOX_GEOM_floor_vheight_03 and
1073 // STBVOX_GEOM_floor_vheight_12 comes into play; the former introduces
1074 // an edge from the SW to NE corner (i.e. from <0,0,?> to <1,1,?>),
1075 // while the latter introduces an edge from the NW to SE corner
1076 // (i.e. from <0,1,?> to <1,0,?>.) For a "lazy mesh" look, use
1077 // exclusively _03 or _12. For a "classic mesh" look, alternate
1078 // _03 and _12 in a checkerboard pattern. For a "smoothest surface"
1079 // look, choose the edge based on actual vertex heights.
1080 //
1081 // The four vertex heights can come from several places. The simplest
1082 // encoding is to just use the 'vheight' parameter which stores four
1083 // explicit vertex heights for every block. This allows total independence,
1084 // but at the cost of the largest memory usage, 1 byte per 3D block.
1085 // Encode this with STBVOX_MAKE_VHEIGHT(vh_sw, vh_se, vh_nw, vh_ne).
1086 // These coordinates are absolute, not affected by block rotations.
1087 //
1088 // An alternative if you just want to encode some very specific block
1089 // types, not all the possibilities--say you just want half-height slopes,
1090 // so you want (0,0,1,1) and (1,1,2,2)--then you can use block_vheight
1091 // to specify them. The geometry rotation will cause block_vheight values
1092 // to be rotated (because it's as if you're just defining a type of
1093 // block). This value is also encoded with STBVOX_MAKE_VHEIGHT.
1094 //
1095 // If you want to save memory and you're creating a "continuous ground"
1096 // sort of effect, you can make each vertex of the lattice share the
1097 // vheight value; that is, two adjacent blocks that share a vertex will
1098 // always get the same vheight value for that vertex. Then you need to
1099 // store two bits of vheight for every block, which you do by storing it
1100 // as part another data structure. Store the south-west vertex's vheight
1101 // with the block. You can either use the "geometry" mesh variable (it's
1102 // a parameter to STBVOX_MAKE_GEOMETRY) or you can store it in the
1103 // "lighting" mesh variable if you defined STBVOX_CONFIG_VHEIGHT_IN_LIGHTING,
1104 // using STBVOX_MAKE_LIGHTING_EXT(lighting,vheight).
1105 //
1106 // Note that if you start with a 2D height map and generate vheight data from
1107 // it, you don't necessarily store only one value per (x,y) coordinate,
1108 // as the same value may need to be set up at multiple z heights. For
1109 // example, if height(8,8) = 13.5, then you want the block at (8,8,13)
1110 // to store STBVOX_VERTEX_HEIGHT_half, and this will be used by blocks
1111 // at (7,7,13), (8,7,13), (7,8,13), and (8,8,13). However, if you're
1112 // allowing steep slopes, it might be the case that you have a block
1113 // at (7,7,12) which is supposed to stick up to 13.5; that means
1114 // you also need to store STBVOX_VERTEX_HEIGHT_one_and_a_half at (8,8,12).
1115 
1116 enum
1117 {
1118    STBVOX_TEXLERP_FACE_0,
1119    STBVOX_TEXLERP_FACE_half,
1120    STBVOX_TEXLERP_FACE_1,
1121    STBVOX_TEXLERP_FACE_use_vert,
1122 };
1123 
1124 enum
1125 {
1126    STBVOX_TEXLERP_BASE_0,    // 0.0
1127    STBVOX_TEXLERP_BASE_2_7,  // 2/7
1128    STBVOX_TEXLERP_BASE_5_7,  // 4/7
1129    STBVOX_TEXLERP_BASE_1     // 1.0
1130 };
1131 
1132 enum
1133 {
1134    STBVOX_TEXLERP3_0_8,
1135    STBVOX_TEXLERP3_1_8,
1136    STBVOX_TEXLERP3_2_8,
1137    STBVOX_TEXLERP3_3_8,
1138    STBVOX_TEXLERP3_4_8,
1139    STBVOX_TEXLERP3_5_8,
1140    STBVOX_TEXLERP3_6_8,
1141    STBVOX_TEXLERP3_7_8,
1142 };
1143 
1144 #define STBVOX_FACE_NONE  7
1145 
1146 #define STBVOX_BLOCKTYPE_EMPTY    0
1147 
1148 #ifdef STBVOX_BLOCKTYPE_SHORT
1149 #define STBVOX_BLOCKTYPE_HOLE  65535
1150 #else
1151 #define STBVOX_BLOCKTYPE_HOLE    255
1152 #endif
1153 
1154 #define STBVOX_MAKE_GEOMETRY(geom, rotate, vheight) ((geom) + (rotate)*16 + (vheight)*64)
1155 #define STBVOX_MAKE_VHEIGHT(v_sw, v_se, v_nw, v_ne) ((v_sw) + (v_se)*4 + (v_nw)*16 + (v_ne)*64)
1156 #define STBVOX_MAKE_MATROT(block, overlay, color)  ((block) + (overlay)*4 + (color)*64)
1157 #define STBVOX_MAKE_TEX2_REPLACE(tex2, tex2_replace_face) ((tex2) + ((tex2_replace_face) & 3)*64)
1158 #define STBVOX_MAKE_TEXLERP(ns2, ew2, ud2, vert)  ((ew2) + (ns2)*4 + (ud2)*16 + (vert)*64)
1159 #define STBVOX_MAKE_TEXLERP_SIMPLE(baselerp,vert,face)   ((vert)*32 + (face)*4 + (baselerp))
1160 #define STBVOX_MAKE_TEXLERP1(vert,e2,n2,w2,s2,u4,d2) STBVOX_MAKE_TEXLERP(s2, w2, d2, vert)
1161 #define STBVOX_MAKE_TEXLERP2(vert,e2,n2,w2,s2,u4,d2) ((u2)*16 + (n2)*4 + (s2))
1162 #define STBVOX_MAKE_FACE_MASK(e,n,w,s,u,d)  ((e)+(n)*2+(w)*4+(s)*8+(u)*16+(d)*32)
1163 #define STBVOX_MAKE_SIDE_TEXROT(e,n,w,s) ((e)+(n)*4+(w)*16+(s)*64)
1164 #define STBVOX_MAKE_COLOR(color,t1,t2) ((color)+(t1)*64+(t2)*128)
1165 #define STBVOX_MAKE_TEXLERP_VERT3(e,n,w,s,u)   ((e)+(n)*8+(w)*64+(s)*512+(u)*4096)
1166 #define STBVOX_MAKE_TEXLERP_FACE3(e,n,w,s,u,d) ((e)+(n)*8+(w)*64+(s)*512+(u)*4096+(d)*16384)
1167 #define STBVOX_MAKE_PACKED_COMPACT(rot, vheight, texlerp, def) ((rot)+4*(vheight)+16*(use)+32*(texlerp))
1168 
1169 #define STBVOX_MAKE_LIGHTING_EXT(lighting, rot)  (((lighting)&~3)+(rot))
1170 #define STBVOX_MAKE_LIGHTING(lighting)       (lighting)
1171 
1172 #ifndef STBVOX_MAX_MESHES
1173 #define STBVOX_MAX_MESHES      2           // opaque & transparent
1174 #endif
1175 
1176 #define STBVOX_MAX_MESH_SLOTS  3           // one vertex & two faces, or two vertex and one face
1177 
1178 
1179 // don't mess with this directly, it's just here so you can
1180 // declare stbvox_mesh_maker on the stack or as a global
1181 struct stbvox_mesh_maker
1182 {
1183    stbvox_input_description input;
1184    int cur_x, cur_y, cur_z;       // last unprocessed voxel if it splits into multiple buffers
1185    int x0,y0,z0,x1,y1,z1;
1186    int x_stride_in_bytes;
1187    int y_stride_in_bytes;
1188    int config_dirty;
1189    int default_mesh;
1190    unsigned int tags;
1191 
1192    int cube_vertex_offset[6][4]; // this allows access per-vertex data stored block-centered (like texlerp, ambient)
1193    int vertex_gather_offset[6][4];
1194 
1195    int pos_x,pos_y,pos_z;
1196    int full;
1197 
1198    // computed from user input
1199    char *output_cur   [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS];
1200    char *output_end   [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS];
1201    char *output_buffer[STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS];
1202    int   output_len   [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS];
1203 
1204    // computed from config
1205    int   output_size  [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; // per quad
1206    int   output_step  [STBVOX_MAX_MESHES][STBVOX_MAX_MESH_SLOTS]; // per vertex or per face, depending
1207    int   num_mesh_slots;
1208 
1209    float default_tex_scale[128][2];
1210 };
1211 
1212 #endif //  INCLUDE_STB_VOXEL_RENDER_H
1213 
1214 
1215 #ifdef STB_VOXEL_RENDER_IMPLEMENTATION
1216 
1217 #include <stdlib.h>
1218 #include <assert.h>
1219 #include <string.h> // memset
1220 
1221 // have to use our own names to avoid the _MSC_VER path having conflicting type names
1222 #ifndef _MSC_VER
1223    #include <stdint.h>
1224    typedef uint16_t stbvox_uint16;
1225    typedef uint32_t stbvox_uint32;
1226 #else
1227    typedef unsigned short stbvox_uint16;
1228    typedef unsigned int   stbvox_uint32;
1229 #endif
1230 
1231 #ifdef _MSC_VER
1232    #define STBVOX_NOTUSED(v)  (void)(v)
1233 #else
1234    #define STBVOX_NOTUSED(v)  (void)sizeof(v)
1235 #endif
1236 
1237 
1238 
1239 #ifndef STBVOX_CONFIG_MODE
1240 #error "Must defined STBVOX_CONFIG_MODE to select the mode"
1241 #endif
1242 
1243 #if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) && defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING)
1244 #error "Can't store both rotation and vheight in lighting"
1245 #endif
1246 
1247 
1248 // The following are candidate voxel modes. Only modes 0, 1, and 20, and 21 are
1249 // currently implemented. Reducing the storage-per-quad further
1250 // shouldn't improve performance, although obviously it allow you
1251 // to create larger worlds without streaming.
1252 //
1253 //
1254 //                      -----------  Two textures -----------       -- One texture --     ---- Color only ----
1255 //            Mode:     0     1     2     3     4     5     6        10    11    12      20    21    22    23    24
1256 // ============================================================================================================
1257 //  uses Tex Buffer     n     Y     Y     Y     Y     Y     Y         Y     Y     Y       n     Y     Y     Y     Y
1258 //   bytes per quad    32    20    14    12    10     6     6         8     8     4      32    20    10     6     4
1259 //       non-blocks   all   all   some  some  some slabs stairs     some  some  none    all   all  slabs slabs  none
1260 //             tex1   256   256   256   256   256   256   256       256   256   256       n     n     n     n     n
1261 //             tex2   256   256   256   256   256   256   128         n     n     n       n     n     n     n     n
1262 //           colors    64    64    64    64    64    64    64         8     n     n     2^24  2^24  2^24  2^24  256
1263 //        vertex ao     Y     Y     Y     Y     Y     n     n         Y     Y     n       Y     Y     Y     n     n
1264 //   vertex texlerp     Y     Y     Y     n     n     n     n         -     -     -       -     -     -     -     -
1265 //      x&y extents   127   127   128    64    64   128    64        64   128   128     127   127   128   128   128
1266 //        z extents   255   255   128    64?   64?   64    64        32    64   128     255   255   128    64   128
1267 
1268 // not sure why I only wrote down the above "result data" and didn't preserve
1269 // the vertex formats, but here I've tried to reconstruct the designs...
1270 //     mode # 3 is wrong, one byte too large, but they may have been an error originally
1271 
1272 //            Mode:     0     1     2     3     4     5     6        10    11    12      20    21    22    23    24
1273 // =============================================================================================================
1274 //   bytes per quad    32    20    14    12    10     6     6         8     8     4            20    10     6     4
1275 //
1276 //    vertex x bits     7     7     0     6     0     0     0         0     0     0             7     0     0     0
1277 //    vertex y bits     7     7     0     0     0     0     0         0     0     0             7     0     0     0
1278 //    vertex z bits     9     9     7     4     2     0     0         2     2     0             9     2     0     0
1279 //   vertex ao bits     6     6     6     6     6     0     0         6     6     0             6     6     0     0
1280 //  vertex txl bits     3     3     3     0     0     0     0         0     0     0            (3)    0     0     0
1281 //
1282 //   face tex1 bits    (8)    8     8     8     8     8     8         8     8     8
1283 //   face tex2 bits    (8)    8     8     8     8     8     7         -     -     -
1284 //  face color bits    (8)    8     8     8     8     8     8         3     0     0            24    24    24     8
1285 // face normal bits    (8)    8     8     8     6     4     7         4     4     3             8     3     4     3
1286 //      face x bits                 7     0     6     7     6         6     7     7             0     7     7     7
1287 //      face y bits                 7     6     6     7     6         6     7     7             0     7     7     7
1288 //      face z bits                 2     2     6     6     6         5     6     7             0     7     6     7
1289 
1290 
1291 #if STBVOX_CONFIG_MODE==0 || STBVOX_CONFIG_MODE==1
1292 
1293    #define STBVOX_ICONFIG_VERTEX_32
1294    #define STBVOX_ICONFIG_FACE1_1
1295 
1296 #elif STBVOX_CONFIG_MODE==20 || STBVOX_CONFIG_MODE==21
1297 
1298    #define STBVOX_ICONFIG_VERTEX_32
1299    #define STBVOX_ICONFIG_FACE1_1
1300    #define STBVOX_ICONFIG_UNTEXTURED
1301 
1302 #else
1303 #error "Selected value of STBVOX_CONFIG_MODE is not supported"
1304 #endif
1305 
1306 #if STBVOX_CONFIG_MODE==0 || STBVOX_CONFIG_MODE==20
1307 #define STBVOX_ICONFIG_FACE_ATTRIBUTE
1308 #endif
1309 
1310 #ifndef STBVOX_CONFIG_HLSL
1311 // the fallback if all others are exhausted is GLSL
1312 #define STBVOX_ICONFIG_GLSL
1313 #endif
1314 
1315 #ifdef STBVOX_CONFIG_OPENGL_MODELVIEW
1316 #define STBVOX_ICONFIG_OPENGL_3_1_COMPATIBILITY
1317 #endif
1318 
1319 #if defined(STBVOX_ICONFIG_VERTEX_32)
1320    typedef stbvox_uint32 stbvox_mesh_vertex;
1321    #define stbvox_vertex_encode(x,y,z,ao,texlerp) \
1322       ((stbvox_uint32) ((x)+((y)<<7)+((z)<<14)+((ao)<<23)+((texlerp)<<29)))
1323 #elif defined(STBVOX_ICONFIG_VERTEX_16_1)  // mode=2
1324    typedef stbvox_uint16 stbvox_mesh_vertex;
1325    #define stbvox_vertex_encode(x,y,z,ao,texlerp) \
1326       ((stbvox_uint16) ((z)+((ao)<<7)+((texlerp)<<13)
1327 #elif defined(STBVOX_ICONFIG_VERTEX_16_2)  // mode=3
1328    typedef stbvox_uint16 stbvox_mesh_vertex;
1329    #define stbvox_vertex_encode(x,y,z,ao,texlerp) \
1330       ((stbvox_uint16) ((x)+((z)<<6))+((ao)<<10))
1331 #elif defined(STBVOX_ICONFIG_VERTEX_8)
1332    typedef stbvox_uint8 stbvox_mesh_vertex;
1333    #define stbvox_vertex_encode(x,y,z,ao,texlerp) \
1334       ((stbvox_uint8) ((z)+((ao)<<6))
1335 #else
1336    #error "internal error, no vertex type"
1337 #endif
1338 
1339 #ifdef STBVOX_ICONFIG_FACE1_1
1340    typedef struct
1341    {
1342       unsigned char tex1,tex2,color,face_info;
1343    } stbvox_mesh_face;
1344 #else
1345    #error "internal error, no face type"
1346 #endif
1347 
1348 
1349 // 20-byte quad format:
1350 //
1351 // per vertex:
1352 //
1353 //     x:7
1354 //     y:7
1355 //     z:9
1356 //     ao:6
1357 //     tex_lerp:3
1358 //
1359 // per face:
1360 //
1361 //     tex1:8
1362 //     tex2:8
1363 //     face:8
1364 //     color:8
1365 
1366 
1367 // Faces:
1368 //
1369 // Faces use the bottom 3 bits to choose the texgen
1370 // mode, and all the bits to choose the normal.
1371 // Thus the bottom 3 bits have to be:
1372 //      e, n, w, s, u, d, u, d
1373 //
1374 // These use compact names so tables are readable
1375 
1376 enum
1377 {
1378    STBVF_e,
1379    STBVF_n,
1380    STBVF_w,
1381    STBVF_s,
1382    STBVF_u,
1383    STBVF_d,
1384    STBVF_eu,
1385    STBVF_ed,
1386 
1387    STBVF_eu_wall,
1388    STBVF_nu_wall,
1389    STBVF_wu_wall,
1390    STBVF_su_wall,
1391    STBVF_ne_u,
1392    STBVF_ne_d,
1393    STBVF_nu,
1394    STBVF_nd,
1395 
1396    STBVF_ed_wall,
1397    STBVF_nd_wall,
1398    STBVF_wd_wall,
1399    STBVF_sd_wall,
1400    STBVF_nw_u,
1401    STBVF_nw_d,
1402    STBVF_wu,
1403    STBVF_wd,
1404 
1405    STBVF_ne_u_cross,
1406    STBVF_nw_u_cross,
1407    STBVF_sw_u_cross,
1408    STBVF_se_u_cross,
1409    STBVF_sw_u,
1410    STBVF_sw_d,
1411    STBVF_su,
1412    STBVF_sd,
1413 
1414    // @TODO we need more than 5 bits to encode the normal to fit the following
1415    // so for now we use the right projection but the wrong normal
1416    STBVF_se_u = STBVF_su,
1417    STBVF_se_d = STBVF_sd,
1418 
1419    STBVF_count,
1420 };
1421 
1422 /////////////////////////////////////////////////////////////////////////////
1423 //
1424 //    tables -- i'd prefer if these were at the end of the file, but: C++
1425 //
1426 
1427 static float stbvox_default_texgen[2][32][3] =
1428 {
1429    { {  0, 1,0 }, { 0, 0, 1 }, {  0,-1,0 }, { 0, 0,-1 },
1430      { -1, 0,0 }, { 0, 0, 1 }, {  1, 0,0 }, { 0, 0,-1 },
1431      {  0,-1,0 }, { 0, 0, 1 }, {  0, 1,0 }, { 0, 0,-1 },
1432      {  1, 0,0 }, { 0, 0, 1 }, { -1, 0,0 }, { 0, 0,-1 },
1433 
1434      {  1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 },
1435      { -1, 0,0 }, { 0,-1, 0 }, {  1, 0,0 }, { 0, 1, 0 },
1436      {  1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 },
1437      { -1, 0,0 }, { 0,-1, 0 }, {  1, 0,0 }, { 0, 1, 0 },
1438    },
1439    { { 0, 0,-1 }, {  0, 1,0 }, { 0, 0, 1 }, {  0,-1,0 },
1440      { 0, 0,-1 }, { -1, 0,0 }, { 0, 0, 1 }, {  1, 0,0 },
1441      { 0, 0,-1 }, {  0,-1,0 }, { 0, 0, 1 }, {  0, 1,0 },
1442      { 0, 0,-1 }, {  1, 0,0 }, { 0, 0, 1 }, { -1, 0,0 },
1443 
1444      { 0,-1, 0 }, {  1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 },
1445      { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, {  1, 0,0 },
1446      { 0,-1, 0 }, {  1, 0,0 }, { 0, 1, 0 }, { -1, 0,0 },
1447      { 0, 1, 0 }, { -1, 0,0 }, { 0,-1, 0 }, {  1, 0,0 },
1448    },
1449 };
1450 
1451 #define STBVOX_RSQRT2   0.7071067811865f
1452 #define STBVOX_RSQRT3   0.5773502691896f
1453 
1454 static float stbvox_default_normals[32][3] =
1455 {
1456    { 1,0,0 },  // east
1457    { 0,1,0 },  // north
1458    { -1,0,0 }, // west
1459    { 0,-1,0 }, // south
1460    { 0,0,1 },  // up
1461    { 0,0,-1 }, // down
1462    {  STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // east & up
1463    {  STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // east & down
1464 
1465    {  STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // east & up
1466    { 0, STBVOX_RSQRT2, STBVOX_RSQRT2 }, // north & up
1467    { -STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // west & up
1468    { 0,-STBVOX_RSQRT2, STBVOX_RSQRT2 }, // south & up
1469    {  STBVOX_RSQRT3, STBVOX_RSQRT3, STBVOX_RSQRT3 }, // ne & up
1470    {  STBVOX_RSQRT3, STBVOX_RSQRT3,-STBVOX_RSQRT3 }, // ne & down
1471    { 0, STBVOX_RSQRT2, STBVOX_RSQRT2 }, // north & up
1472    { 0, STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // north & down
1473 
1474    {  STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // east & down
1475    { 0, STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // north & down
1476    { -STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // west & down
1477    { 0,-STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // south & down
1478    { -STBVOX_RSQRT3, STBVOX_RSQRT3, STBVOX_RSQRT3 }, // NW & up
1479    { -STBVOX_RSQRT3, STBVOX_RSQRT3,-STBVOX_RSQRT3 }, // NW & down
1480    { -STBVOX_RSQRT2,0, STBVOX_RSQRT2 }, // west & up
1481    { -STBVOX_RSQRT2,0, -STBVOX_RSQRT2 }, // west & down
1482 
1483    {  STBVOX_RSQRT3, STBVOX_RSQRT3,STBVOX_RSQRT3 }, // NE & up crossed
1484    { -STBVOX_RSQRT3, STBVOX_RSQRT3,STBVOX_RSQRT3 }, // NW & up crossed
1485    { -STBVOX_RSQRT3,-STBVOX_RSQRT3,STBVOX_RSQRT3 }, // SW & up crossed
1486    {  STBVOX_RSQRT3,-STBVOX_RSQRT3,STBVOX_RSQRT3 }, // SE & up crossed
1487    { -STBVOX_RSQRT3,-STBVOX_RSQRT3, STBVOX_RSQRT3 }, // SW & up
1488    { -STBVOX_RSQRT3,-STBVOX_RSQRT3,-STBVOX_RSQRT3 }, // SW & up
1489    { 0,-STBVOX_RSQRT2, STBVOX_RSQRT2 }, // south & up
1490    { 0,-STBVOX_RSQRT2, -STBVOX_RSQRT2 }, // south & down
1491 };
1492 
1493 static float stbvox_default_texscale[128][4] =
1494 {
1495    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1496    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1497    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1498    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1499    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1500    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1501    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1502    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1503    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1504    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1505    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1506    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1507    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1508    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1509    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1510    {1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},{1,1,0,0},
1511 };
1512 
1513 static unsigned char stbvox_default_palette_compact[64][3] =
1514 {
1515    { 255,255,255 }, { 238,238,238 }, { 221,221,221 }, { 204,204,204 },
1516    { 187,187,187 }, { 170,170,170 }, { 153,153,153 }, { 136,136,136 },
1517    { 119,119,119 }, { 102,102,102 }, {  85, 85, 85 }, {  68, 68, 68 },
1518    {  51, 51, 51 }, {  34, 34, 34 }, {  17, 17, 17 }, {   0,  0,  0 },
1519    { 255,240,240 }, { 255,220,220 }, { 255,160,160 }, { 255, 32, 32 },
1520    { 200,120,160 }, { 200, 60,150 }, { 220,100,130 }, { 255,  0,128 },
1521    { 240,240,255 }, { 220,220,255 }, { 160,160,255 }, {  32, 32,255 },
1522    { 120,160,200 }, {  60,150,200 }, { 100,130,220 }, {   0,128,255 },
1523    { 240,255,240 }, { 220,255,220 }, { 160,255,160 }, {  32,255, 32 },
1524    { 160,200,120 }, { 150,200, 60 }, { 130,220,100 }, { 128,255,  0 },
1525    { 255,255,240 }, { 255,255,220 }, { 220,220,180 }, { 255,255, 32 },
1526    { 200,160,120 }, { 200,150, 60 }, { 220,130,100 }, { 255,128,  0 },
1527    { 255,240,255 }, { 255,220,255 }, { 220,180,220 }, { 255, 32,255 },
1528    { 160,120,200 }, { 150, 60,200 }, { 130,100,220 }, { 128,  0,255 },
1529    { 240,255,255 }, { 220,255,255 }, { 180,220,220 }, {  32,255,255 },
1530    { 120,200,160 }, {  60,200,150 }, { 100,220,130 }, {   0,255,128 },
1531 };
1532 
1533 static float stbvox_default_ambient[4][4] =
1534 {
1535    { 0,0,1      ,0 }, // reversed lighting direction
1536    { 0.5,0.5,0.5,0 }, // directional color
1537    { 0.5,0.5,0.5,0 }, // constant color
1538    { 0.5,0.5,0.5,1.0f/1000.0f/1000.0f }, // fog data for simple_fog
1539 };
1540 
1541 static float stbvox_default_palette[64][4];
1542 
stbvox_build_default_palette(void)1543 static void stbvox_build_default_palette(void)
1544 {
1545    int i;
1546    for (i=0; i < 64; ++i) {
1547       stbvox_default_palette[i][0] = stbvox_default_palette_compact[i][0] / 255.0f;
1548       stbvox_default_palette[i][1] = stbvox_default_palette_compact[i][1] / 255.0f;
1549       stbvox_default_palette[i][2] = stbvox_default_palette_compact[i][2] / 255.0f;
1550       stbvox_default_palette[i][3] = 1.0f;
1551    }
1552 }
1553 
1554 //////////////////////////////////////////////////////////////////////////////
1555 //
1556 // Shaders
1557 //
1558 
1559 #if defined(STBVOX_ICONFIG_OPENGL_3_1_COMPATIBILITY)
1560    #define STBVOX_SHADER_VERSION "#version 150 compatibility\n"
1561 #elif defined(STBVOX_ICONFIG_OPENGL_3_0)
1562    #define STBVOX_SHADER_VERSION "#version 130\n"
1563 #elif defined(STBVOX_ICONFIG_GLSL)
1564    #define STBVOX_SHADER_VERSION "#version 150\n"
1565 #else
1566    #define STBVOX_SHADER_VERSION ""
1567 #endif
1568 
1569 static const char *stbvox_vertex_program =
1570 {
1571       STBVOX_SHADER_VERSION
1572 
1573    #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE  // NOT TAG_face_sampled
1574       "in uvec4 attr_face;\n"
1575    #else
1576       "uniform usamplerBuffer facearray;\n"
1577    #endif
1578 
1579    #ifdef STBVOX_ICONFIG_FACE_ARRAY_2
1580       "uniform usamplerBuffer facearray2;\n"
1581    #endif
1582 
1583       // vertex input data
1584       "in uint attr_vertex;\n"
1585 
1586       // per-buffer data
1587       "uniform vec3 transform[3];\n"
1588 
1589       // per-frame data
1590       "uniform vec4 camera_pos;\n"  // 4th value is used for arbitrary hacking
1591 
1592       // to simplify things, we avoid using more than 256 uniform vectors
1593       // in fragment shader to avoid possible 1024 component limit, so
1594       // we access this table in the fragment shader.
1595       "uniform vec3 normal_table[32];\n"
1596 
1597       #ifndef STBVOX_CONFIG_OPENGL_MODELVIEW
1598          "uniform mat4x4 model_view;\n"
1599       #endif
1600 
1601       // fragment output data
1602       "flat out uvec4  facedata;\n"
1603       "     out  vec3  voxelspace_pos;\n"
1604       "     out  vec3  vnormal;\n"
1605       "     out float  texlerp;\n"
1606       "     out float  amb_occ;\n"
1607 
1608       // @TODO handle the HLSL way to do this
1609       "void main()\n"
1610       "{\n"
1611       #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE
1612          "   facedata = attr_face;\n"
1613       #else
1614          "   int faceID = gl_VertexID >> 2;\n"
1615          "   facedata   = texelFetch(facearray, faceID);\n"
1616       #endif
1617 
1618       // extract data for vertex
1619       "   vec3 offset;\n"
1620       "   offset.x = float( (attr_vertex       ) & 127u );\n"             // a[0..6]
1621       "   offset.y = float( (attr_vertex >>  7u) & 127u );\n"             // a[7..13]
1622       "   offset.z = float( (attr_vertex >> 14u) & 511u );\n"             // a[14..22]
1623       "   amb_occ  = float( (attr_vertex >> 23u) &  63u ) / 63.0;\n"      // a[23..28]
1624       "   texlerp  = float( (attr_vertex >> 29u)        ) /  7.0;\n"      // a[29..31]
1625 
1626       "   vnormal = normal_table[(facedata.w>>2u) & 31u];\n"
1627       "   voxelspace_pos = offset * transform[0];\n"  // mesh-to-object scale
1628       "   vec3 position  = voxelspace_pos + transform[1];\n"  // mesh-to-object translate
1629 
1630       #ifdef STBVOX_DEBUG_TEST_NORMALS
1631          "   if ((facedata.w & 28u) == 16u || (facedata.w & 28u) == 24u)\n"
1632          "      position += vnormal.xyz * camera_pos.w;\n"
1633       #endif
1634 
1635       #ifndef STBVOX_CONFIG_OPENGL_MODELVIEW
1636          "   gl_Position = model_view * vec4(position,1.0);\n"
1637       #else
1638          "   gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);\n"
1639       #endif
1640 
1641       "}\n"
1642 };
1643 
1644 
1645 static const char *stbvox_fragment_program =
1646 {
1647       STBVOX_SHADER_VERSION
1648 
1649       // rlerp is lerp but with t on the left, like god intended
1650       #if defined(STBVOX_ICONFIG_GLSL)
1651          "#define rlerp(t,x,y) mix(x,y,t)\n"
1652       #elif defined(STBVOX_CONFIG_HLSL)
1653          "#define rlerp(t,x,y) lerp(x,y,t)\n"
1654       #else
1655          #error "need definition of rlerp()"
1656       #endif
1657 
1658 
1659       // vertex-shader output data
1660       "flat in uvec4  facedata;\n"
1661       "     in  vec3  voxelspace_pos;\n"
1662       "     in  vec3  vnormal;\n"
1663       "     in float  texlerp;\n"
1664       "     in float  amb_occ;\n"
1665 
1666       // per-buffer data
1667       "uniform vec3 transform[3];\n"
1668 
1669       // per-frame data
1670       "uniform vec4 camera_pos;\n"  // 4th value is used for arbitrary hacking
1671 
1672       // probably constant data
1673       "uniform vec4 ambient[4];\n"
1674 
1675       #ifndef STBVOX_ICONFIG_UNTEXTURED
1676          // generally constant data
1677          "uniform sampler2DArray tex_array[2];\n"
1678 
1679          #ifdef STBVOX_CONFIG_PREFER_TEXBUFFER
1680             "uniform samplerBuffer color_table;\n"
1681             "uniform samplerBuffer texscale;\n"
1682             "uniform samplerBuffer texgen;\n"
1683          #else
1684             "uniform vec4 color_table[64];\n"
1685             "uniform vec4 texscale[64];\n" // instead of 128, to avoid running out of uniforms
1686             "uniform vec3 texgen[64];\n"
1687          #endif
1688       #endif
1689 
1690       "out vec4  outcolor;\n"
1691 
1692       #if defined(STBVOX_CONFIG_LIGHTING) || defined(STBVOX_CONFIG_LIGHTING_SIMPLE)
1693       "vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient);\n"
1694       #endif
1695       #if defined(STBVOX_CONFIG_FOG) || defined(STBVOX_CONFIG_FOG_SMOOTHSTEP)
1696       "vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha);\n"
1697       #endif
1698 
1699       "void main()\n"
1700       "{\n"
1701       "   vec3 albedo;\n"
1702       "   float fragment_alpha;\n"
1703 
1704       #ifndef STBVOX_ICONFIG_UNTEXTURED
1705          // unpack the values
1706          "   uint tex1_id = facedata.x;\n"
1707          "   uint tex2_id = facedata.y;\n"
1708          "   uint texprojid = facedata.w & 31u;\n"
1709          "   uint color_id  = facedata.z;\n"
1710 
1711          #ifndef STBVOX_CONFIG_PREFER_TEXBUFFER
1712             // load from uniforms / texture buffers
1713             "   vec3 texgen_s = texgen[texprojid];\n"
1714             "   vec3 texgen_t = texgen[texprojid+32u];\n"
1715             "   float tex1_scale = texscale[tex1_id & 63u].x;\n"
1716             "   vec4 color = color_table[color_id & 63u];\n"
1717             #ifndef STBVOX_CONFIG_DISABLE_TEX2
1718             "   vec4 tex2_props = texscale[tex2_id & 63u];\n"
1719             #endif
1720          #else
1721             "   vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n"
1722             "   vec3 texgen_t = texelFetch(texgen, int(texprojid+32u)).xyz;\n"
1723             "   float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n"
1724             "   vec4 color = texelFetch(color_table, int(color_id & 63u));\n"
1725             #ifndef STBVOX_CONFIG_DISABLE_TEX2
1726             "   vec4 tex2_props = texelFetch(texscale, int(tex1_id & 127u));\n"
1727             #endif
1728          #endif
1729 
1730          #ifndef STBVOX_CONFIG_DISABLE_TEX2
1731          "   float tex2_scale = tex2_props.y;\n"
1732          "   bool texblend_mode = tex2_props.z != 0.0;\n"
1733          #endif
1734          "   vec2 texcoord;\n"
1735          "   vec3 texturespace_pos = voxelspace_pos + transform[2].xyz;\n"
1736          "   texcoord.s = dot(texturespace_pos, texgen_s);\n"
1737          "   texcoord.t = dot(texturespace_pos, texgen_t);\n"
1738 
1739          "   vec2  texcoord_1 = tex1_scale * texcoord;\n"
1740          #ifndef STBVOX_CONFIG_DISABLE_TEX2
1741          "   vec2  texcoord_2 = tex2_scale * texcoord;\n"
1742          #endif
1743 
1744          #ifdef STBVOX_CONFIG_TEX1_EDGE_CLAMP
1745          "   texcoord_1 = texcoord_1 - floor(texcoord_1);\n"
1746          "   vec4 tex1 = textureGrad(tex_array[0], vec3(texcoord_1, float(tex1_id)), dFdx(tex1_scale*texcoord), dFdy(tex1_scale*texcoord));\n"
1747          #else
1748          "   vec4 tex1 = texture(tex_array[0], vec3(texcoord_1, float(tex1_id)));\n"
1749          #endif
1750 
1751          #ifndef STBVOX_CONFIG_DISABLE_TEX2
1752          #ifdef STBVOX_CONFIG_TEX2_EDGE_CLAMP
1753          "   texcoord_2 = texcoord_2 - floor(texcoord_2);\n"
1754          "   vec4 tex2 = textureGrad(tex_array[0], vec3(texcoord_2, float(tex2_id)), dFdx(tex2_scale*texcoord), dFdy(tex2_scale*texcoord));\n"
1755          #else
1756          "   vec4 tex2 = texture(tex_array[1], vec3(texcoord_2, float(tex2_id)));\n"
1757          #endif
1758          #endif
1759 
1760          "   bool emissive = (color.a > 1.0);\n"
1761          "   color.a = min(color.a, 1.0);\n"
1762 
1763          // recolor textures
1764          "   if ((color_id &  64u) != 0u) tex1.rgba *= color.rgba;\n"
1765          "   fragment_alpha = tex1.a;\n"
1766          #ifndef STBVOX_CONFIG_DISABLE_TEX2
1767             "   if ((color_id & 128u) != 0u) tex2.rgba *= color.rgba;\n"
1768 
1769             #ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
1770             "   tex2.rgba *= texlerp;\n"
1771             #else
1772             "   tex2.a *= texlerp;\n"
1773             #endif
1774 
1775             "   if (texblend_mode)\n"
1776             "      albedo = tex1.xyz * rlerp(tex2.a, vec3(1.0,1.0,1.0), 2.0*tex2.xyz);\n"
1777             "   else {\n"
1778             #ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
1779             "      albedo = (1.0-tex2.a)*tex1.xyz + tex2.xyz;\n"
1780             #else
1781             "      albedo = rlerp(tex2.a, tex1.xyz, tex2.xyz);\n"
1782             #endif
1783             "      fragment_alpha = tex1.a*(1-tex2.a)+tex2.a;\n"
1784             "   }\n"
1785          #else
1786             "      albedo = tex1.xyz;\n"
1787          #endif
1788 
1789       #else // UNTEXTURED
1790          "   vec4 color;"
1791          "   color.xyz = vec3(facedata.xyz) / 255.0;\n"
1792          "   bool emissive = false;\n"
1793          "   albedo = color.xyz;\n"
1794          "   fragment_alpha = 1.0;\n"
1795       #endif
1796 
1797       #ifdef STBVOX_ICONFIG_VARYING_VERTEX_NORMALS
1798          // currently, there are no modes that trigger this path; idea is that there
1799          // could be a couple of bits per vertex to perturb the normal to e.g. get curved look
1800          "   vec3 normal = normalize(vnormal);\n"
1801       #else
1802          "   vec3 normal = vnormal;\n"
1803       #endif
1804 
1805       "   vec3 ambient_color = dot(normal, ambient[0].xyz) * ambient[1].xyz + ambient[2].xyz;\n"
1806 
1807       "   ambient_color = clamp(ambient_color, 0.0, 1.0);"
1808       "   ambient_color *= amb_occ;\n"
1809 
1810       "   vec3 lit_color;\n"
1811       "   if (!emissive)\n"
1812       #if defined(STBVOX_ICONFIG_LIGHTING) || defined(STBVOX_CONFIG_LIGHTING_SIMPLE)
1813          "      lit_color = compute_lighting(voxelspace_pos + transform[1], normal, albedo, ambient_color);\n"
1814       #else
1815          "      lit_color = albedo * ambient_color ;\n"
1816       #endif
1817       "   else\n"
1818       "      lit_color = albedo;\n"
1819 
1820       #if defined(STBVOX_ICONFIG_FOG) || defined(STBVOX_CONFIG_FOG_SMOOTHSTEP)
1821          "   vec3 dist = voxelspace_pos + (transform[1] - camera_pos.xyz);\n"
1822          "   lit_color = compute_fog(lit_color, dist, fragment_alpha);\n"
1823       #endif
1824 
1825       #ifdef STBVOX_CONFIG_UNPREMULTIPLY
1826       "   vec4 final_color = vec4(lit_color/fragment_alpha, fragment_alpha);\n"
1827       #else
1828       "   vec4 final_color = vec4(lit_color, fragment_alpha);\n"
1829       #endif
1830       "   outcolor = final_color;\n"
1831       "}\n"
1832 
1833    #ifdef STBVOX_CONFIG_LIGHTING_SIMPLE
1834       "\n"
1835       "uniform vec3 light_source[2];\n"
1836       "vec3 compute_lighting(vec3 pos, vec3 norm, vec3 albedo, vec3 ambient)\n"
1837       "{\n"
1838       "   vec3 light_dir = light_source[0] - pos;\n"
1839       "   float lambert = dot(light_dir, norm) / dot(light_dir, light_dir);\n"
1840       "   vec3 diffuse = clamp(light_source[1] * clamp(lambert, 0.0, 1.0), 0.0, 1.0);\n"
1841       "   return (diffuse + ambient) * albedo;\n"
1842       "}\n"
1843    #endif
1844 
1845    #ifdef STBVOX_CONFIG_FOG_SMOOTHSTEP
1846       "\n"
1847       "vec3 compute_fog(vec3 color, vec3 relative_pos, float fragment_alpha)\n"
1848       "{\n"
1849       "   float f = dot(relative_pos,relative_pos)*ambient[3].w;\n"
1850       //"   f = rlerp(f, -2,1);\n"
1851       "   f = clamp(f, 0.0, 1.0);\n"
1852       "   f = 3.0*f*f - 2.0*f*f*f;\n" // smoothstep
1853       //"   f = f*f;\n"  // fade in more smoothly
1854       #ifdef STBVOX_CONFIG_PREMULTIPLIED_ALPHA
1855       "   return rlerp(f, color.xyz, ambient[3].xyz*fragment_alpha);\n"
1856       #else
1857       "   return rlerp(f, color.xyz, ambient[3].xyz);\n"
1858       #endif
1859       "}\n"
1860    #endif
1861 };
1862 
1863 
1864 // still requires full alpha lookups, including tex2 if texblend is enabled
1865 static const char *stbvox_fragment_program_alpha_only =
1866 {
1867    STBVOX_SHADER_VERSION
1868 
1869    // vertex-shader output data
1870    "flat in uvec4  facedata;\n"
1871    "     in  vec3  voxelspace_pos;\n"
1872    "     in float  texlerp;\n"
1873 
1874    // per-buffer data
1875    "uniform vec3 transform[3];\n"
1876 
1877    #ifndef STBVOX_ICONFIG_UNTEXTURED
1878       // generally constant data
1879       "uniform sampler2DArray tex_array[2];\n"
1880 
1881       #ifdef STBVOX_CONFIG_PREFER_TEXBUFFER
1882          "uniform samplerBuffer texscale;\n"
1883          "uniform samplerBuffer texgen;\n"
1884       #else
1885          "uniform vec4 texscale[64];\n" // instead of 128, to avoid running out of uniforms
1886          "uniform vec3 texgen[64];\n"
1887       #endif
1888    #endif
1889 
1890    "out vec4  outcolor;\n"
1891 
1892    "void main()\n"
1893    "{\n"
1894    "   vec3 albedo;\n"
1895    "   float fragment_alpha;\n"
1896 
1897    #ifndef STBVOX_ICONFIG_UNTEXTURED
1898       // unpack the values
1899       "   uint tex1_id = facedata.x;\n"
1900       "   uint tex2_id = facedata.y;\n"
1901       "   uint texprojid = facedata.w & 31u;\n"
1902       "   uint color_id  = facedata.z;\n"
1903 
1904       #ifndef STBVOX_CONFIG_PREFER_TEXBUFFER
1905          // load from uniforms / texture buffers
1906          "   vec3 texgen_s = texgen[texprojid];\n"
1907          "   vec3 texgen_t = texgen[texprojid+32u];\n"
1908          "   float tex1_scale = texscale[tex1_id & 63u].x;\n"
1909          "   vec4 color = color_table[color_id & 63u];\n"
1910          "   vec4 tex2_props = texscale[tex2_id & 63u];\n"
1911       #else
1912          "   vec3 texgen_s = texelFetch(texgen, int(texprojid)).xyz;\n"
1913          "   vec3 texgen_t = texelFetch(texgen, int(texprojid+32u)).xyz;\n"
1914          "   float tex1_scale = texelFetch(texscale, int(tex1_id & 127u)).x;\n"
1915          "   vec4 color = texelFetch(color_table, int(color_id & 63u));\n"
1916          "   vec4 tex2_props = texelFetch(texscale, int(tex2_id & 127u));\n"
1917       #endif
1918 
1919       #ifndef STBVOX_CONFIG_DISABLE_TEX2
1920       "   float tex2_scale = tex2_props.y;\n"
1921       "   bool texblend_mode = tex2_props.z &((facedata.w & 128u) != 0u);\n"
1922       #endif
1923 
1924       "   color.a = min(color.a, 1.0);\n"
1925 
1926       "   vec2 texcoord;\n"
1927       "   vec3 texturespace_pos = voxelspace_pos + transform[2].xyz;\n"
1928       "   texcoord.s = dot(texturespace_pos, texgen_s);\n"
1929       "   texcoord.t = dot(texturespace_pos, texgen_t);\n"
1930 
1931       "   vec2  texcoord_1 = tex1_scale * texcoord;\n"
1932       "   vec2  texcoord_2 = tex2_scale * texcoord;\n"
1933 
1934       #ifdef STBVOX_CONFIG_TEX1_EDGE_CLAMP
1935       "   texcoord_1 = texcoord_1 - floor(texcoord_1);\n"
1936       "   vec4 tex1 = textureGrad(tex_array[0], vec3(texcoord_1, float(tex1_id)), dFdx(tex1_scale*texcoord), dFdy(tex1_scale*texcoord));\n"
1937       #else
1938       "   vec4 tex1 = texture(tex_array[0], vec3(texcoord_1, float(tex1_id)));\n"
1939       #endif
1940 
1941       "   if ((color_id &  64u) != 0u) tex1.a *= color.a;\n"
1942       "   fragment_alpha = tex1.a;\n"
1943 
1944       #ifndef STBVOX_CONFIG_DISABLE_TEX2
1945       "   if (!texblend_mode) {\n"
1946          #ifdef STBVOX_CONFIG_TEX2_EDGE_CLAMP
1947          "      texcoord_2 = texcoord_2 - floor(texcoord_2);\n"
1948          "      vec4 tex2 = textureGrad(tex_array[0], vec3(texcoord_2, float(tex2_id)), dFdx(tex2_scale*texcoord), dFdy(tex2_scale*texcoord));\n"
1949          #else
1950          "      vec4 tex2 = texture(tex_array[1], vec3(texcoord_2, float(tex2_id)));\n"
1951          #endif
1952 
1953          "      tex2.a *= texlerp;\n"
1954          "      if ((color_id & 128u) != 0u) tex2.rgba *= color.a;\n"
1955          "      fragment_alpha = tex1.a*(1-tex2.a)+tex2.a;\n"
1956          "}\n"
1957       "\n"
1958       #endif
1959 
1960    #else // UNTEXTURED
1961       "   fragment_alpha = 1.0;\n"
1962    #endif
1963 
1964    "   outcolor = vec4(0.0, 0.0, 0.0, fragment_alpha);\n"
1965    "}\n"
1966 };
1967 
1968 
stbvox_get_vertex_shader(void)1969 STBVXDEC char *stbvox_get_vertex_shader(void)
1970 {
1971    return (char *) stbvox_vertex_program;
1972 }
1973 
stbvox_get_fragment_shader(void)1974 STBVXDEC char *stbvox_get_fragment_shader(void)
1975 {
1976    return (char *) stbvox_fragment_program;
1977 }
1978 
stbvox_get_fragment_shader_alpha_only(void)1979 STBVXDEC char *stbvox_get_fragment_shader_alpha_only(void)
1980 {
1981    return (char *) stbvox_fragment_program_alpha_only;
1982 }
1983 
1984 static float stbvox_dummy_transform[3][3];
1985 
1986 #ifdef STBVOX_CONFIG_PREFER_TEXBUFFER
1987 #define STBVOX_TEXBUF 1
1988 #else
1989 #define STBVOX_TEXBUF 0
1990 #endif
1991 
1992 static stbvox_uniform_info stbvox_uniforms[] =
1993 {
1994    { STBVOX_UNIFORM_TYPE_sampler  ,  4,   1, (char*) "facearray"    , 0                           },
1995    { STBVOX_UNIFORM_TYPE_vec3     , 12,   3, (char*) "transform"    , stbvox_dummy_transform[0]   },
1996    { STBVOX_UNIFORM_TYPE_sampler  ,  4,   2, (char*) "tex_array"    , 0                           },
1997    { STBVOX_UNIFORM_TYPE_vec4     , 16, 128, (char*) "texscale"     , stbvox_default_texscale[0] , STBVOX_TEXBUF },
1998    { STBVOX_UNIFORM_TYPE_vec4     , 16,  64, (char*) "color_table"  , stbvox_default_palette[0]  , STBVOX_TEXBUF },
1999    { STBVOX_UNIFORM_TYPE_vec3     , 12,  32, (char*) "normal_table" , stbvox_default_normals[0]   },
2000    { STBVOX_UNIFORM_TYPE_vec3     , 12,  64, (char*) "texgen"       , stbvox_default_texgen[0][0], STBVOX_TEXBUF },
2001    { STBVOX_UNIFORM_TYPE_vec4     , 16,   4, (char*) "ambient"      , stbvox_default_ambient[0]   },
2002    { STBVOX_UNIFORM_TYPE_vec4     , 16,   1, (char*) "camera_pos"   , stbvox_dummy_transform[0]   },
2003 };
2004 
stbvox_get_uniform_info(stbvox_uniform_info * info,int uniform)2005 STBVXDEC int stbvox_get_uniform_info(stbvox_uniform_info *info, int uniform)
2006 {
2007    if (uniform < 0 || uniform >= STBVOX_UNIFORM_count)
2008       return 0;
2009 
2010    *info = stbvox_uniforms[uniform];
2011    return 1;
2012 }
2013 
2014 #define STBVOX_GET_GEO(geom_data)  ((geom_data) & 15)
2015 
2016 typedef struct
2017 {
2018    unsigned char block:2;
2019    unsigned char overlay:2;
2020    unsigned char facerot:2;
2021    unsigned char ecolor:2;
2022 } stbvox_rotate;
2023 
2024 typedef struct
2025 {
2026    unsigned char x,y,z;
2027 } stbvox_pos;
2028 
2029 static unsigned char stbvox_rotate_face[6][4] =
2030 {
2031    { 0,1,2,3 },
2032    { 1,2,3,0 },
2033    { 2,3,0,1 },
2034    { 3,0,1,2 },
2035    { 4,4,4,4 },
2036    { 5,5,5,5 },
2037 };
2038 
2039 #define STBVOX_ROTATE(x,r)   stbvox_rotate_face[x][r] // (((x)+(r))&3)
2040 
stbvox_compute_mesh_face_value(stbvox_mesh_maker * mm,stbvox_rotate rot,int face,int v_off,int normal)2041 stbvox_mesh_face stbvox_compute_mesh_face_value(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, int normal)
2042 {
2043    stbvox_mesh_face face_data = { 0 };
2044    stbvox_block_type bt = mm->input.blocktype[v_off];
2045    unsigned char bt_face = STBVOX_ROTATE(face, rot.block);
2046    int facerot = rot.facerot;
2047 
2048    #ifdef STBVOX_ICONFIG_UNTEXTURED
2049    if (mm->input.rgb) {
2050       face_data.tex1  = mm->input.rgb[v_off].r;
2051       face_data.tex2  = mm->input.rgb[v_off].g;
2052       face_data.color = mm->input.rgb[v_off].b;
2053       face_data.face_info = (normal<<2);
2054       return face_data;
2055    }
2056    #else
2057    unsigned char color_face;
2058 
2059    if (mm->input.color)
2060       face_data.color = mm->input.color[v_off];
2061 
2062    if (mm->input.block_tex1)
2063       face_data.tex1 = mm->input.block_tex1[bt];
2064    else if (mm->input.block_tex1_face)
2065       face_data.tex1 = mm->input.block_tex1_face[bt][bt_face];
2066    else
2067       face_data.tex1 = bt;
2068 
2069    if (mm->input.block_tex2)
2070       face_data.tex2 = mm->input.block_tex2[bt];
2071    else if (mm->input.block_tex2_face)
2072       face_data.tex2 = mm->input.block_tex2_face[bt][bt_face];
2073 
2074    if (mm->input.block_color) {
2075       unsigned char mcol = mm->input.block_color[bt];
2076       if (mcol)
2077          face_data.color = mcol;
2078    } else if (mm->input.block_color_face) {
2079       unsigned char mcol = mm->input.block_color_face[bt][bt_face];
2080       if (mcol)
2081          face_data.color = mcol;
2082    }
2083 
2084    if (face <= STBVOX_FACE_south) {
2085       if (mm->input.side_texrot)
2086          facerot = mm->input.side_texrot[v_off] >> (2 * face);
2087       else if (mm->input.block_side_texrot)
2088          facerot = mm->input.block_side_texrot[v_off] >> (2 * bt_face);
2089    }
2090 
2091    if (mm->input.overlay) {
2092       int over_face = STBVOX_ROTATE(face, rot.overlay);
2093       unsigned char over = mm->input.overlay[v_off];
2094       if (over) {
2095          if (mm->input.overlay_tex1) {
2096             unsigned char rep1 = mm->input.overlay_tex1[over][over_face];
2097             if (rep1)
2098                face_data.tex1 = rep1;
2099          }
2100          if (mm->input.overlay_tex2) {
2101             unsigned char rep2 = mm->input.overlay_tex2[over][over_face];
2102             if (rep2)
2103                face_data.tex2 = rep2;
2104          }
2105          if (mm->input.overlay_color) {
2106             unsigned char rep3 = mm->input.overlay_color[over][over_face];
2107             if (rep3)
2108                face_data.color = rep3;
2109          }
2110 
2111          if (mm->input.overlay_side_texrot && face <= STBVOX_FACE_south)
2112             facerot = mm->input.overlay_side_texrot[over] >> (2*over_face);
2113       }
2114    }
2115 
2116    if (mm->input.tex2_for_tex1)
2117       face_data.tex2 = mm->input.tex2_for_tex1[face_data.tex1];
2118    if (mm->input.tex2)
2119       face_data.tex2 = mm->input.tex2[v_off];
2120    if (mm->input.tex2_replace) {
2121       if (mm->input.tex2_facemask[v_off] & (1 << face))
2122          face_data.tex2 = mm->input.tex2_replace[v_off];
2123    }
2124 
2125    color_face = STBVOX_ROTATE(face, rot.ecolor);
2126    if (mm->input.extended_color) {
2127       unsigned char ec = mm->input.extended_color[v_off];
2128       if (mm->input.ecolor_facemask[ec] & (1 << color_face))
2129          face_data.color = mm->input.ecolor_color[ec];
2130    }
2131 
2132    if (mm->input.color2) {
2133       if (mm->input.color2_facemask[v_off] & (1 << color_face))
2134          face_data.color = mm->input.color2[v_off];
2135       if (mm->input.color3 && (mm->input.color3_facemask[v_off] & (1 << color_face)))
2136          face_data.color = mm->input.color3[v_off];
2137    }
2138    #endif
2139 
2140    face_data.face_info = (normal<<2) + facerot;
2141    return face_data;
2142 }
2143 
2144 // these are the types of faces each block can have
2145 enum
2146 {
2147    STBVOX_FT_none    ,
2148    STBVOX_FT_upper   ,
2149    STBVOX_FT_lower   ,
2150    STBVOX_FT_solid   ,
2151    STBVOX_FT_diag_012,
2152    STBVOX_FT_diag_023,
2153    STBVOX_FT_diag_013,
2154    STBVOX_FT_diag_123,
2155    STBVOX_FT_force   , // can't be covered up, used for internal faces, also hides nothing
2156    STBVOX_FT_partial , // only covered by solid, never covers anything else
2157 
2158    STBVOX_FT_count
2159 };
2160 
2161 static unsigned char stbvox_face_lerp[6] = { 0,2,0,2,4,4 };
2162 static unsigned char stbvox_vert3_lerp[5] = { 0,3,6,9,12 };
2163 static unsigned char stbvox_vert_lerp_for_face_lerp[4] = { 0, 4, 7, 7 };
2164 static unsigned char stbvox_face3_lerp[6] = { 0,3,6,9,12,14 };
2165 static unsigned char stbvox_vert_lerp_for_simple[4] = { 0,2,5,7 };
2166 static unsigned char stbvox_face3_updown[8] = { 0,2,5,7,0,2,5,7 }; // ignore top bit
2167 
2168 // vertex offsets for face vertices
2169 static unsigned char stbvox_vertex_vector[6][4][3] =
2170 {
2171    { { 1,0,1 }, { 1,1,1 }, { 1,1,0 }, { 1,0,0 } }, // east
2172    { { 1,1,1 }, { 0,1,1 }, { 0,1,0 }, { 1,1,0 } }, // north
2173    { { 0,1,1 }, { 0,0,1 }, { 0,0,0 }, { 0,1,0 } }, // west
2174    { { 0,0,1 }, { 1,0,1 }, { 1,0,0 }, { 0,0,0 } }, // south
2175    { { 0,1,1 }, { 1,1,1 }, { 1,0,1 }, { 0,0,1 } }, // up
2176    { { 0,0,0 }, { 1,0,0 }, { 1,1,0 }, { 0,1,0 } }, // down
2177 };
2178 
2179 // stbvox_vertex_vector, but read coordinates as binary numbers, zyx
2180 static unsigned char stbvox_vertex_selector[6][4] =
2181 {
2182    { 5,7,3,1 },
2183    { 7,6,2,3 },
2184    { 6,4,0,2 },
2185    { 4,5,1,0 },
2186    { 6,7,5,4 },
2187    { 0,1,3,2 },
2188 };
2189 
2190 static stbvox_mesh_vertex stbvox_vmesh_delta_normal[6][4] =
2191 {
2192    {  stbvox_vertex_encode(1,0,1,0,0) ,
2193       stbvox_vertex_encode(1,1,1,0,0) ,
2194       stbvox_vertex_encode(1,1,0,0,0) ,
2195       stbvox_vertex_encode(1,0,0,0,0)  },
2196    {  stbvox_vertex_encode(1,1,1,0,0) ,
2197       stbvox_vertex_encode(0,1,1,0,0) ,
2198       stbvox_vertex_encode(0,1,0,0,0) ,
2199       stbvox_vertex_encode(1,1,0,0,0)  },
2200    {  stbvox_vertex_encode(0,1,1,0,0) ,
2201       stbvox_vertex_encode(0,0,1,0,0) ,
2202       stbvox_vertex_encode(0,0,0,0,0) ,
2203       stbvox_vertex_encode(0,1,0,0,0)  },
2204    {  stbvox_vertex_encode(0,0,1,0,0) ,
2205       stbvox_vertex_encode(1,0,1,0,0) ,
2206       stbvox_vertex_encode(1,0,0,0,0) ,
2207       stbvox_vertex_encode(0,0,0,0,0)  },
2208    {  stbvox_vertex_encode(0,1,1,0,0) ,
2209       stbvox_vertex_encode(1,1,1,0,0) ,
2210       stbvox_vertex_encode(1,0,1,0,0) ,
2211       stbvox_vertex_encode(0,0,1,0,0)  },
2212    {  stbvox_vertex_encode(0,0,0,0,0) ,
2213       stbvox_vertex_encode(1,0,0,0,0) ,
2214       stbvox_vertex_encode(1,1,0,0,0) ,
2215       stbvox_vertex_encode(0,1,0,0,0)  }
2216 };
2217 
2218 static stbvox_mesh_vertex stbvox_vmesh_pre_vheight[6][4] =
2219 {
2220    {  stbvox_vertex_encode(1,0,0,0,0) ,
2221       stbvox_vertex_encode(1,1,0,0,0) ,
2222       stbvox_vertex_encode(1,1,0,0,0) ,
2223       stbvox_vertex_encode(1,0,0,0,0)  },
2224    {  stbvox_vertex_encode(1,1,0,0,0) ,
2225       stbvox_vertex_encode(0,1,0,0,0) ,
2226       stbvox_vertex_encode(0,1,0,0,0) ,
2227       stbvox_vertex_encode(1,1,0,0,0)  },
2228    {  stbvox_vertex_encode(0,1,0,0,0) ,
2229       stbvox_vertex_encode(0,0,0,0,0) ,
2230       stbvox_vertex_encode(0,0,0,0,0) ,
2231       stbvox_vertex_encode(0,1,0,0,0)  },
2232    {  stbvox_vertex_encode(0,0,0,0,0) ,
2233       stbvox_vertex_encode(1,0,0,0,0) ,
2234       stbvox_vertex_encode(1,0,0,0,0) ,
2235       stbvox_vertex_encode(0,0,0,0,0)  },
2236    {  stbvox_vertex_encode(0,1,0,0,0) ,
2237       stbvox_vertex_encode(1,1,0,0,0) ,
2238       stbvox_vertex_encode(1,0,0,0,0) ,
2239       stbvox_vertex_encode(0,0,0,0,0)  },
2240    {  stbvox_vertex_encode(0,0,0,0,0) ,
2241       stbvox_vertex_encode(1,0,0,0,0) ,
2242       stbvox_vertex_encode(1,1,0,0,0) ,
2243       stbvox_vertex_encode(0,1,0,0,0)  }
2244 };
2245 
2246 static stbvox_mesh_vertex stbvox_vmesh_delta_half_z[6][4] =
2247 {
2248    { stbvox_vertex_encode(1,0,2,0,0) ,
2249      stbvox_vertex_encode(1,1,2,0,0) ,
2250      stbvox_vertex_encode(1,1,0,0,0) ,
2251      stbvox_vertex_encode(1,0,0,0,0)  },
2252    { stbvox_vertex_encode(1,1,2,0,0) ,
2253      stbvox_vertex_encode(0,1,2,0,0) ,
2254      stbvox_vertex_encode(0,1,0,0,0) ,
2255      stbvox_vertex_encode(1,1,0,0,0)  },
2256    { stbvox_vertex_encode(0,1,2,0,0) ,
2257      stbvox_vertex_encode(0,0,2,0,0) ,
2258      stbvox_vertex_encode(0,0,0,0,0) ,
2259      stbvox_vertex_encode(0,1,0,0,0)  },
2260    { stbvox_vertex_encode(0,0,2,0,0) ,
2261      stbvox_vertex_encode(1,0,2,0,0) ,
2262      stbvox_vertex_encode(1,0,0,0,0) ,
2263      stbvox_vertex_encode(0,0,0,0,0)  },
2264    { stbvox_vertex_encode(0,1,2,0,0) ,
2265      stbvox_vertex_encode(1,1,2,0,0) ,
2266      stbvox_vertex_encode(1,0,2,0,0) ,
2267      stbvox_vertex_encode(0,0,2,0,0)  },
2268    { stbvox_vertex_encode(0,0,0,0,0) ,
2269      stbvox_vertex_encode(1,0,0,0,0) ,
2270      stbvox_vertex_encode(1,1,0,0,0) ,
2271      stbvox_vertex_encode(0,1,0,0,0)  }
2272 };
2273 
2274 static stbvox_mesh_vertex stbvox_vmesh_crossed_pair[6][4] =
2275 {
2276    { stbvox_vertex_encode(1,0,2,0,0) ,
2277      stbvox_vertex_encode(0,1,2,0,0) ,
2278      stbvox_vertex_encode(0,1,0,0,0) ,
2279      stbvox_vertex_encode(1,0,0,0,0)  },
2280    { stbvox_vertex_encode(1,1,2,0,0) ,
2281      stbvox_vertex_encode(0,0,2,0,0) ,
2282      stbvox_vertex_encode(0,0,0,0,0) ,
2283      stbvox_vertex_encode(1,1,0,0,0)  },
2284    { stbvox_vertex_encode(0,1,2,0,0) ,
2285      stbvox_vertex_encode(1,0,2,0,0) ,
2286      stbvox_vertex_encode(1,0,0,0,0) ,
2287      stbvox_vertex_encode(0,1,0,0,0)  },
2288    { stbvox_vertex_encode(0,0,2,0,0) ,
2289      stbvox_vertex_encode(1,1,2,0,0) ,
2290      stbvox_vertex_encode(1,1,0,0,0) ,
2291      stbvox_vertex_encode(0,0,0,0,0)  },
2292    // not used, so we leave it non-degenerate to make sure it doesn't get gen'd accidentally
2293    { stbvox_vertex_encode(0,1,2,0,0) ,
2294      stbvox_vertex_encode(1,1,2,0,0) ,
2295      stbvox_vertex_encode(1,0,2,0,0) ,
2296      stbvox_vertex_encode(0,0,2,0,0)  },
2297    { stbvox_vertex_encode(0,0,0,0,0) ,
2298      stbvox_vertex_encode(1,0,0,0,0) ,
2299      stbvox_vertex_encode(1,1,0,0,0) ,
2300      stbvox_vertex_encode(0,1,0,0,0)  }
2301 };
2302 
2303 #define STBVOX_MAX_GEOM     16
2304 #define STBVOX_NUM_ROTATION  4
2305 
2306 // this is used to determine if a face is ever generated at all
2307 static unsigned char stbvox_hasface[STBVOX_MAX_GEOM][STBVOX_NUM_ROTATION] =
2308 {
2309    { 0,0,0,0 }, // empty
2310    { 0,0,0,0 }, // knockout
2311    { 63,63,63,63 }, // solid
2312    { 63,63,63,63 }, // transp
2313    { 63,63,63,63 }, // slab
2314    { 63,63,63,63 }, // slab
2315    { 1|2|4|48, 8|1|2|48, 4|8|1|48, 2|4|8|48, }, // floor slopes
2316    { 1|2|4|48, 8|1|2|48, 4|8|1|48, 2|4|8|48, }, // ceil slopes
2317    { 47,47,47,47 }, // wall-projected diagonal with down face
2318    { 31,31,31,31 }, // wall-projected diagonal with up face
2319    { 63,63,63,63 }, // crossed-pair has special handling, but avoid early-out
2320    { 63,63,63,63 }, // force
2321    { 63,63,63,63 }, // vheight
2322    { 63,63,63,63 }, // vheight
2323    { 63,63,63,63 }, // vheight
2324    { 63,63,63,63 }, // vheight
2325 };
2326 
2327 // this determines which face type above is visible on each side of the geometry
2328 static unsigned char stbvox_facetype[STBVOX_GEOM_count][6] =
2329 {
2330    { 0, },  // STBVOX_GEOM_empty
2331    { STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid }, // knockout
2332    { STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid, STBVOX_FT_solid }, // solid
2333    { STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force }, // transp
2334 
2335    { STBVOX_FT_upper, STBVOX_FT_upper, STBVOX_FT_upper, STBVOX_FT_upper, STBVOX_FT_solid, STBVOX_FT_force },
2336    { STBVOX_FT_lower, STBVOX_FT_lower, STBVOX_FT_lower, STBVOX_FT_lower, STBVOX_FT_force, STBVOX_FT_solid },
2337    { STBVOX_FT_diag_123, STBVOX_FT_solid, STBVOX_FT_diag_023, STBVOX_FT_none, STBVOX_FT_force, STBVOX_FT_solid },
2338    { STBVOX_FT_diag_012, STBVOX_FT_solid, STBVOX_FT_diag_013, STBVOX_FT_none, STBVOX_FT_solid, STBVOX_FT_force },
2339 
2340    { STBVOX_FT_diag_123, STBVOX_FT_solid, STBVOX_FT_diag_023, STBVOX_FT_force, STBVOX_FT_none, STBVOX_FT_solid },
2341    { STBVOX_FT_diag_012, STBVOX_FT_solid, STBVOX_FT_diag_013, STBVOX_FT_force, STBVOX_FT_solid, STBVOX_FT_none },
2342    { STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, 0,0 }, // crossed pair
2343    { STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force, STBVOX_FT_force }, // GEOM_force
2344 
2345    { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_force, STBVOX_FT_solid }, // floor vheight, all neighbors forced
2346    { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_force, STBVOX_FT_solid }, // floor vheight, all neighbors forced
2347    { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_solid, STBVOX_FT_force }, // ceil vheight, all neighbors forced
2348    { STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial,STBVOX_FT_partial, STBVOX_FT_solid, STBVOX_FT_force }, // ceil vheight, all neighbors forced
2349 };
2350 
2351 // This table indicates what normal to use for the "up" face of a sloped geom
2352 // @TODO this could be done with math given the current arrangement of the enum, but let's not require it
2353 static unsigned char stbvox_floor_slope_for_rot[4] =
2354 {
2355    STBVF_su,
2356    STBVF_wu, // @TODO: why is this reversed from what it should be? this is a north-is-up face, so slope should be south&up
2357    STBVF_nu,
2358    STBVF_eu,
2359 };
2360 
2361 static unsigned char stbvox_ceil_slope_for_rot[4] =
2362 {
2363    STBVF_sd,
2364    STBVF_ed,
2365    STBVF_nd,
2366    STBVF_wd,
2367 };
2368 
2369 // this table indicates whether, for each pair of types above, a face is visible.
2370 // each value indicates whether a given type is visible for all neighbor types
2371 static unsigned short stbvox_face_visible[STBVOX_FT_count] =
2372 {
2373    // we encode the table by listing which cases cause *obscuration*, and bitwise inverting that
2374    // table is pre-shifted by 5 to save a shift when it's accessed
2375    (unsigned short) ((~0x07ffu                                          )<<5),  // none is completely obscured by everything
2376    (unsigned short) ((~((1u<<STBVOX_FT_solid) | (1<<STBVOX_FT_upper)   ))<<5),  // upper
2377    (unsigned short) ((~((1u<<STBVOX_FT_solid) | (1<<STBVOX_FT_lower)   ))<<5),  // lower
2378    (unsigned short) ((~((1u<<STBVOX_FT_solid)                          ))<<5),  // solid is only completely obscured only by solid
2379    (unsigned short) ((~((1u<<STBVOX_FT_solid) | (1<<STBVOX_FT_diag_013)))<<5),  // diag012 matches diag013
2380    (unsigned short) ((~((1u<<STBVOX_FT_solid) | (1<<STBVOX_FT_diag_123)))<<5),  // diag023 matches diag123
2381    (unsigned short) ((~((1u<<STBVOX_FT_solid) | (1<<STBVOX_FT_diag_012)))<<5),  // diag013 matches diag012
2382    (unsigned short) ((~((1u<<STBVOX_FT_solid) | (1<<STBVOX_FT_diag_023)))<<5),  // diag123 matches diag023
2383    (unsigned short) ((~0u                                               )<<5),  // force is always rendered regardless, always forces neighbor
2384    (unsigned short) ((~((1u<<STBVOX_FT_solid)                          ))<<5),  // partial is only completely obscured only by solid
2385 };
2386 
2387 // the vertex heights of the block types, in binary vertex order (zyx):
2388 // lower: SW, SE, NW, NE; upper: SW, SE, NW, NE
2389 static stbvox_mesh_vertex stbvox_geometry_vheight[8][8] =
2390 {
2391    #define STBVOX_HEIGHTS(a,b,c,d,e,f,g,h) \
2392      { stbvox_vertex_encode(0,0,a,0,0),  \
2393        stbvox_vertex_encode(0,0,b,0,0),  \
2394        stbvox_vertex_encode(0,0,c,0,0),  \
2395        stbvox_vertex_encode(0,0,d,0,0),  \
2396        stbvox_vertex_encode(0,0,e,0,0),  \
2397        stbvox_vertex_encode(0,0,f,0,0),  \
2398        stbvox_vertex_encode(0,0,g,0,0),  \
2399        stbvox_vertex_encode(0,0,h,0,0) }
2400 
2401    STBVOX_HEIGHTS(0,0,0,0, 2,2,2,2),
2402    STBVOX_HEIGHTS(0,0,0,0, 2,2,2,2),
2403    STBVOX_HEIGHTS(0,0,0,0, 2,2,2,2),
2404    STBVOX_HEIGHTS(0,0,0,0, 2,2,2,2),
2405    STBVOX_HEIGHTS(1,1,1,1, 2,2,2,2),
2406    STBVOX_HEIGHTS(0,0,0,0, 1,1,1,1),
2407    STBVOX_HEIGHTS(0,0,0,0, 0,0,2,2),
2408    STBVOX_HEIGHTS(2,2,0,0, 2,2,2,2),
2409 };
2410 
2411 // rotate vertices defined as [z][y][x] coords
2412 static unsigned char stbvox_rotate_vertex[8][4] =
2413 {
2414    { 0,1,3,2 }, // zyx=000
2415    { 1,3,2,0 }, // zyx=001
2416    { 2,0,1,3 }, // zyx=010
2417    { 3,2,0,1 }, // zyx=011
2418    { 4,5,7,6 }, // zyx=100
2419    { 5,7,6,4 }, // zyx=101
2420    { 6,4,5,7 }, // zyx=110
2421    { 7,6,4,5 }, // zyx=111
2422 };
2423 
2424 #ifdef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
2425 // optimized vheight generates a single normal over the entire face, even if it's not planar
2426 static unsigned char stbvox_optimized_face_up_normal[4][4][4][4] =
2427 {
2428    {
2429       {
2430          { STBVF_u   , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2431          { STBVF_nw_u, STBVF_nu  , STBVF_nu  , STBVF_ne_u, },
2432          { STBVF_nw_u, STBVF_nu  , STBVF_nu  , STBVF_nu  , },
2433          { STBVF_nw_u, STBVF_nw_u, STBVF_nu  , STBVF_nu  , },
2434       },{
2435          { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2436          { STBVF_u   , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2437          { STBVF_nw_u, STBVF_nu  , STBVF_nu  , STBVF_ne_u, },
2438          { STBVF_nw_u, STBVF_nu  , STBVF_nu  , STBVF_nu  , },
2439       },{
2440          { STBVF_eu  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2441          { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2442          { STBVF_u   , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2443          { STBVF_nw_u, STBVF_nu  , STBVF_nu  , STBVF_ne_u, },
2444       },{
2445          { STBVF_eu  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2446          { STBVF_eu  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2447          { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2448          { STBVF_u   , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2449       },
2450    },{
2451       {
2452          { STBVF_sw_u, STBVF_u   , STBVF_ne_u, STBVF_ne_u, },
2453          { STBVF_wu  , STBVF_nw_u, STBVF_nu  , STBVF_nu  , },
2454          { STBVF_wu  , STBVF_nw_u, STBVF_nu  , STBVF_nu  , },
2455          { STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, STBVF_nu  , },
2456       },{
2457          { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2458          { STBVF_sw_u, STBVF_u   , STBVF_ne_u, STBVF_ne_u, },
2459          { STBVF_wu  , STBVF_nw_u, STBVF_nu  , STBVF_nu  , },
2460          { STBVF_wu  , STBVF_nw_u, STBVF_nu  , STBVF_nu  , },
2461       },{
2462          { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2463          { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2464          { STBVF_sw_u, STBVF_u   , STBVF_ne_u, STBVF_ne_u, },
2465          { STBVF_wu  , STBVF_nw_u, STBVF_nu  , STBVF_nu  , },
2466       },{
2467          { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2468          { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2469          { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2470          { STBVF_sw_u, STBVF_u   , STBVF_ne_u, STBVF_ne_u, },
2471       },
2472    },{
2473       {
2474          { STBVF_sw_u, STBVF_sw_u, STBVF_u   , STBVF_ne_u, },
2475          { STBVF_wu  , STBVF_wu  , STBVF_nw_u, STBVF_nu  , },
2476          { STBVF_wu  , STBVF_wu  , STBVF_nw_u, STBVF_nu  , },
2477          { STBVF_wu  , STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, },
2478       },{
2479          { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2480          { STBVF_sw_u, STBVF_sw_u, STBVF_u   , STBVF_ne_u, },
2481          { STBVF_wu  , STBVF_wu  , STBVF_nw_u, STBVF_nu  , },
2482          { STBVF_wu  , STBVF_wu  , STBVF_nw_u, STBVF_nu  , },
2483       },{
2484          { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2485          { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2486          { STBVF_sw_u, STBVF_sw_u, STBVF_u   , STBVF_ne_u, },
2487          { STBVF_wu  , STBVF_wu  , STBVF_nw_u, STBVF_nu  , },
2488       },{
2489          { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2490          { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2491          { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2492          { STBVF_sw_u, STBVF_sw_u, STBVF_u   , STBVF_ne_u, },
2493       },
2494    },{
2495       {
2496          { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_u   , },
2497          { STBVF_sw_u, STBVF_wu  , STBVF_wu  , STBVF_nw_u, },
2498          { STBVF_wu  , STBVF_wu  , STBVF_wu  , STBVF_nw_u, },
2499          { STBVF_wu  , STBVF_wu  , STBVF_nw_u, STBVF_nw_u, },
2500       },{
2501          { STBVF_sw_u, STBVF_su  , STBVF_su  , STBVF_su  , },
2502          { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_u   , },
2503          { STBVF_sw_u, STBVF_wu  , STBVF_wu  , STBVF_nw_u, },
2504          { STBVF_wu  , STBVF_wu  , STBVF_wu  , STBVF_nw_u, },
2505       },{
2506          { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2507          { STBVF_sw_u, STBVF_su  , STBVF_su  , STBVF_su  , },
2508          { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_u   , },
2509          { STBVF_sw_u, STBVF_wu  , STBVF_wu  , STBVF_nw_u, },
2510       },{
2511          { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2512          { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2513          { STBVF_sw_u, STBVF_su  , STBVF_su  , STBVF_su  , },
2514          { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_u   , },
2515       },
2516    },
2517 };
2518 #else
2519 // which normal to use for a given vheight that's planar
2520 // @TODO: this table was constructed by hand and may have bugs
2521 //                                 nw se sw
2522 static unsigned char stbvox_planar_face_up_normal[4][4][4] =
2523 {
2524    {                                                      // sw,se,nw,ne;  ne = se+nw-sw
2525       { STBVF_u   , 0         , 0         , 0          }, //  0,0,0,0; 1,0,0,-1; 2,0,0,-2; 3,0,0,-3;
2526       { STBVF_u   , STBVF_u   , 0         , 0          }, //  0,1,0,1; 1,1,0, 0; 2,1,0,-1; 3,1,0,-2;
2527       { STBVF_wu  , STBVF_nw_u, STBVF_nu  , 0          }, //  0,2,0,2; 1,2,0, 1; 2,2,0, 0; 3,2,0,-1;
2528       { STBVF_wu  , STBVF_nw_u, STBVF_nw_u, STBVF_nu   }, //  0,3,0,3; 1,3,0, 2; 2,3,0, 1; 3,3,0, 0;
2529    },{
2530       { STBVF_u   , STBVF_u   , 0         , 0          }, //  0,0,1,1; 1,0,1, 0; 2,0,1,-1; 3,0,1,-2;
2531       { STBVF_sw_u, STBVF_u   , STBVF_ne_u, 0          }, //  0,1,1,2; 1,1,1, 1; 2,1,1, 0; 3,1,1,-1;
2532       { STBVF_sw_u, STBVF_u   , STBVF_u   , STBVF_ne_u }, //  0,2,1,3; 1,2,1, 2; 2,2,1, 1; 3,2,1, 0;
2533       { 0         , STBVF_wu  , STBVF_nw_u, STBVF_nu   }, //  0,3,1,4; 1,3,1, 3; 2,3,1, 2; 3,3,1, 1;
2534    },{
2535       { STBVF_su  , STBVF_se_u, STBVF_eu  , 0          }, //  0,0,2,2; 1,0,2, 1; 2,0,2, 0; 3,0,2,-1;
2536       { STBVF_sw_u, STBVF_u   , STBVF_u   , STBVF_ne_u }, //  0,1,2,3; 1,1,2, 2; 2,1,2, 1; 3,1,2, 0;
2537       { 0         , STBVF_sw_u, STBVF_u   , STBVF_ne_u }, //  0,2,2,4; 1,2,2, 3; 2,2,2, 2; 3,2,2, 1;
2538       { 0         , 0         , STBVF_u   , STBVF_u    }, //  0,3,2,5; 1,3,2, 4; 2,3,2, 3; 3,3,2, 2;
2539    },{
2540       { STBVF_su  , STBVF_se_u, STBVF_se_u, STBVF_eu   }, //  0,0,3,3; 1,0,3, 2; 2,0,3, 1; 3,0,3, 0;
2541       { 0         , STBVF_su  , STBVF_se_u, STBVF_eu   }, //  0,1,3,4; 1,1,3, 3; 2,1,3, 2; 3,1,3, 1;
2542       { 0         , 0         , STBVF_u   , STBVF_u    }, //  0,2,3,5; 1,2,3, 4; 2,2,3, 3; 3,2,3, 2;
2543       { 0         , 0         , 0         , STBVF_u    }, //  0,3,3,6; 1,3,3, 5; 2,3,3, 4; 3,3,3, 3;
2544    }
2545 };
2546 
2547 // these tables were constructed automatically using a variant of the code
2548 // below; however, they seem wrong, so who knows
2549 static unsigned char stbvox_face_up_normal_012[4][4][4] =
2550 {
2551    {
2552       { STBVF_u   , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2553       { STBVF_wu  , STBVF_nu  , STBVF_ne_u, STBVF_ne_u, },
2554       { STBVF_wu  , STBVF_nw_u, STBVF_nu  , STBVF_ne_u, },
2555       { STBVF_wu  , STBVF_nw_u, STBVF_nw_u, STBVF_nu  , },
2556    },{
2557       { STBVF_su  , STBVF_eu  , STBVF_ne_u, STBVF_ne_u, },
2558       { STBVF_sw_u, STBVF_u   , STBVF_ne_u, STBVF_ne_u, },
2559       { STBVF_sw_u, STBVF_wu  , STBVF_nu  , STBVF_ne_u, },
2560       { STBVF_sw_u, STBVF_wu  , STBVF_nw_u, STBVF_nu  , },
2561    },{
2562       { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2563       { STBVF_sw_u, STBVF_su  , STBVF_eu  , STBVF_ne_u, },
2564       { STBVF_sw_u, STBVF_sw_u, STBVF_u   , STBVF_ne_u, },
2565       { STBVF_sw_u, STBVF_sw_u, STBVF_wu  , STBVF_nu  , },
2566    },{
2567       { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2568       { STBVF_sw_u, STBVF_su  , STBVF_eu  , STBVF_eu  , },
2569       { STBVF_sw_u, STBVF_sw_u, STBVF_su  , STBVF_eu  , },
2570       { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_u   , },
2571    }
2572 };
2573 
2574 static unsigned char stbvox_face_up_normal_013[4][4][4] =
2575 {
2576    {
2577       { STBVF_u   , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2578       { STBVF_nw_u, STBVF_nu  , STBVF_ne_u, STBVF_ne_u, },
2579       { STBVF_nw_u, STBVF_nw_u, STBVF_nu  , STBVF_ne_u, },
2580       { STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, STBVF_nu  , },
2581    },{
2582       { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2583       { STBVF_wu  , STBVF_u   , STBVF_eu  , STBVF_eu  , },
2584       { STBVF_nw_u, STBVF_nw_u, STBVF_nu  , STBVF_ne_u, },
2585       { STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, STBVF_nu  , },
2586    },{
2587       { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2588       { STBVF_sw_u, STBVF_su  , STBVF_eu  , STBVF_eu  , },
2589       { STBVF_wu  , STBVF_wu  , STBVF_u   , STBVF_eu  , },
2590       { STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, STBVF_nu  , },
2591    },{
2592       { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_eu  , },
2593       { STBVF_sw_u, STBVF_su  , STBVF_su  , STBVF_su  , },
2594       { STBVF_sw_u, STBVF_sw_u, STBVF_su  , STBVF_eu  , },
2595       { STBVF_wu  , STBVF_wu  , STBVF_wu  , STBVF_u   , },
2596    }
2597 };
2598 
2599 static unsigned char stbvox_face_up_normal_023[4][4][4] =
2600 {
2601    {
2602       { STBVF_u   , STBVF_nu  , STBVF_nu  , STBVF_nu  , },
2603       { STBVF_eu  , STBVF_eu  , STBVF_ne_u, STBVF_ne_u, },
2604       { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2605       { STBVF_eu  , STBVF_eu  , STBVF_eu  , STBVF_eu  , },
2606    },{
2607       { STBVF_wu  , STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, },
2608       { STBVF_su  , STBVF_u   , STBVF_nu  , STBVF_nu  , },
2609       { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2610       { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2611    },{
2612       { STBVF_wu  , STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, },
2613       { STBVF_sw_u, STBVF_wu  , STBVF_nw_u, STBVF_nw_u, },
2614       { STBVF_su  , STBVF_su  , STBVF_u   , STBVF_nu  , },
2615       { STBVF_su  , STBVF_su  , STBVF_eu  , STBVF_eu  , },
2616    },{
2617       { STBVF_wu  , STBVF_nw_u, STBVF_nw_u, STBVF_nw_u, },
2618       { STBVF_sw_u, STBVF_wu  , STBVF_nw_u, STBVF_nw_u, },
2619       { STBVF_sw_u, STBVF_sw_u, STBVF_wu  , STBVF_nw_u, },
2620       { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_u   , },
2621    }
2622 };
2623 
2624 static unsigned char stbvox_face_up_normal_123[4][4][4] =
2625 {
2626    {
2627       { STBVF_u   , STBVF_nu  , STBVF_nu  , STBVF_nu  , },
2628       { STBVF_eu  , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2629       { STBVF_eu  , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2630       { STBVF_eu  , STBVF_ne_u, STBVF_ne_u, STBVF_ne_u, },
2631    },{
2632       { STBVF_sw_u, STBVF_wu  , STBVF_nw_u, STBVF_nw_u, },
2633       { STBVF_su  , STBVF_u   , STBVF_nu  , STBVF_nu  , },
2634       { STBVF_eu  , STBVF_eu  , STBVF_ne_u, STBVF_ne_u, },
2635       { STBVF_eu  , STBVF_eu  , STBVF_ne_u, STBVF_ne_u, },
2636    },{
2637       { STBVF_sw_u, STBVF_sw_u, STBVF_wu  , STBVF_nw_u, },
2638       { STBVF_sw_u, STBVF_sw_u, STBVF_wu  , STBVF_nw_u, },
2639       { STBVF_su  , STBVF_su  , STBVF_u   , STBVF_nu  , },
2640       { STBVF_su  , STBVF_eu  , STBVF_eu  , STBVF_ne_u, },
2641    },{
2642       { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_wu  , },
2643       { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_wu  , },
2644       { STBVF_sw_u, STBVF_sw_u, STBVF_sw_u, STBVF_wu  , },
2645       { STBVF_su  , STBVF_su  , STBVF_su  , STBVF_u   , },
2646    }
2647 };
2648 #endif
2649 
stbvox_get_quad_vertex_pointer(stbvox_mesh_maker * mm,int mesh,stbvox_mesh_vertex ** vertices,stbvox_mesh_face face)2650 void stbvox_get_quad_vertex_pointer(stbvox_mesh_maker *mm, int mesh, stbvox_mesh_vertex **vertices, stbvox_mesh_face face)
2651 {
2652    char *p = mm->output_cur[mesh][0];
2653    int step = mm->output_step[mesh][0];
2654 
2655    // allocate a new quad from the mesh
2656    vertices[0] = (stbvox_mesh_vertex *) p; p += step;
2657    vertices[1] = (stbvox_mesh_vertex *) p; p += step;
2658    vertices[2] = (stbvox_mesh_vertex *) p; p += step;
2659    vertices[3] = (stbvox_mesh_vertex *) p; p += step;
2660    mm->output_cur[mesh][0] = p;
2661 
2662    // output the face
2663    #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE
2664       // write face as interleaved vertex data
2665       *(stbvox_mesh_face *) (vertices[0]+1) = face;
2666       *(stbvox_mesh_face *) (vertices[1]+1) = face;
2667       *(stbvox_mesh_face *) (vertices[2]+1) = face;
2668       *(stbvox_mesh_face *) (vertices[3]+1) = face;
2669    #else
2670       *(stbvox_mesh_face *) mm->output_cur[mesh][1] = face;
2671       mm->output_cur[mesh][1] += 4;
2672    #endif
2673 }
2674 
stbvox_make_mesh_for_face(stbvox_mesh_maker * mm,stbvox_rotate rot,int face,int v_off,stbvox_pos pos,stbvox_mesh_vertex vertbase,stbvox_mesh_vertex * face_coord,unsigned char mesh,int normal)2675 void stbvox_make_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, int normal)
2676 {
2677    stbvox_mesh_face face_data = stbvox_compute_mesh_face_value(mm,rot,face,v_off, normal);
2678 
2679    // still need to compute ao & texlerp for each vertex
2680 
2681    // first compute texlerp into p1
2682    stbvox_mesh_vertex p1[4] = { 0 };
2683 
2684    #if defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) && defined(STBVOX_CONFIG_UP_TEXLERP_PACKED)
2685       #define STBVOX_USE_PACKED(f) ((f) == STBVOX_FACE_up || (f) == STBVOX_FACE_down)
2686    #elif defined(STBVOX_CONFIG_UP_TEXLERP_PACKED)
2687       #define STBVOX_USE_PACKED(f) ((f) == STBVOX_FACE_up                           )
2688    #elif defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED)
2689       #define STBVOX_USE_PACKED(f) (                         (f) == STBVOX_FACE_down)
2690    #endif
2691 
2692    #if defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED) || defined(STBVOX_CONFIG_UP_TEXLERP_PACKED)
2693    if (STBVOX_USE_PACKED(face)) {
2694       if (!mm->input.packed_compact || 0==(mm->input.packed_compact[v_off]&16))
2695          goto set_default;
2696       p1[0] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][0]] >> 5);
2697       p1[1] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][1]] >> 5);
2698       p1[2] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][2]] >> 5);
2699       p1[3] = (mm->input.packed_compact[v_off + mm->cube_vertex_offset[face][3]] >> 5);
2700       p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]);
2701       p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]);
2702       p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]);
2703       p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]);
2704       goto skip;
2705    }
2706    #endif
2707 
2708    if (mm->input.block_texlerp) {
2709       stbvox_block_type bt = mm->input.blocktype[v_off];
2710       unsigned char val = mm->input.block_texlerp[bt];
2711       p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,val);
2712    } else if (mm->input.block_texlerp_face) {
2713       stbvox_block_type bt = mm->input.blocktype[v_off];
2714       unsigned char bt_face = STBVOX_ROTATE(face, rot.block);
2715       unsigned char val = mm->input.block_texlerp_face[bt][bt_face];
2716       p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,val);
2717    } else if (mm->input.texlerp_face3) {
2718       unsigned char val = (mm->input.texlerp_face3[v_off] >> stbvox_face3_lerp[face]) & 7;
2719       if (face >= STBVOX_FACE_up)
2720          val = stbvox_face3_updown[val];
2721       p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,val);
2722    } else if (mm->input.texlerp_simple) {
2723       unsigned char val = mm->input.texlerp_simple[v_off];
2724       unsigned char lerp_face = (val >> 2) & 7;
2725       if (lerp_face == face) {
2726          p1[0] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][0]] >> 5) & 7;
2727          p1[1] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][1]] >> 5) & 7;
2728          p1[2] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][2]] >> 5) & 7;
2729          p1[3] = (mm->input.texlerp_simple[v_off + mm->cube_vertex_offset[face][3]] >> 5) & 7;
2730          p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]);
2731          p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]);
2732          p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]);
2733          p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]);
2734       } else {
2735          unsigned char base = stbvox_vert_lerp_for_simple[val&3];
2736          p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,base);
2737       }
2738    } else if (mm->input.texlerp) {
2739       unsigned char facelerp = (mm->input.texlerp[v_off] >> stbvox_face_lerp[face]) & 3;
2740       if (facelerp == STBVOX_TEXLERP_FACE_use_vert) {
2741          if (mm->input.texlerp_vert3 && face != STBVOX_FACE_down) {
2742             unsigned char shift = stbvox_vert3_lerp[face];
2743             p1[0] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][0]] >> shift) & 7;
2744             p1[1] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][1]] >> shift) & 7;
2745             p1[2] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][2]] >> shift) & 7;
2746             p1[3] = (mm->input.texlerp_vert3[mm->cube_vertex_offset[face][3]] >> shift) & 7;
2747          } else {
2748             p1[0] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][0]]>>6];
2749             p1[1] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][1]]>>6];
2750             p1[2] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][2]]>>6];
2751             p1[3] = stbvox_vert_lerp_for_simple[mm->input.texlerp[mm->cube_vertex_offset[face][3]]>>6];
2752          }
2753          p1[0] = stbvox_vertex_encode(0,0,0,0,p1[0]);
2754          p1[1] = stbvox_vertex_encode(0,0,0,0,p1[1]);
2755          p1[2] = stbvox_vertex_encode(0,0,0,0,p1[2]);
2756          p1[3] = stbvox_vertex_encode(0,0,0,0,p1[3]);
2757       } else {
2758          p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,stbvox_vert_lerp_for_face_lerp[facelerp]);
2759       }
2760    } else {
2761       #if defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) || defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED)
2762       set_default:
2763       #endif
2764       p1[0] = p1[1] = p1[2] = p1[3] = stbvox_vertex_encode(0,0,0,0,7); // @TODO make this configurable
2765    }
2766 
2767    #if defined(STBVOX_CONFIG_UP_TEXLERP_PACKED) || defined(STBVOX_CONFIG_DOWN_TEXLERP_PACKED)
2768    skip:
2769    #endif
2770 
2771    // now compute lighting and store to vertices
2772    {
2773       stbvox_mesh_vertex *mv[4];
2774       stbvox_get_quad_vertex_pointer(mm, mesh, mv, face_data);
2775 
2776       if (mm->input.lighting) {
2777          // @TODO: lighting at block centers, but not gathered, instead constant-per-face
2778          if (mm->input.lighting_at_vertices) {
2779             int i;
2780             for (i=0; i < 4; ++i) {
2781                *mv[i] = vertbase + face_coord[i]
2782                           + stbvox_vertex_encode(0,0,0,mm->input.lighting[v_off + mm->cube_vertex_offset[face][i]] & 63,0)
2783                           + p1[i];
2784             }
2785          } else {
2786             unsigned char *amb = &mm->input.lighting[v_off];
2787             int i,j;
2788             #if defined(STBVOX_CONFIG_ROTATION_IN_LIGHTING) || defined(STBVOX_CONFIG_VHEIGHT_IN_LIGHTING)
2789             #define STBVOX_GET_LIGHTING(light) ((light) & ~3)
2790             #define STBVOX_LIGHTING_ROUNDOFF   8
2791             #else
2792             #define STBVOX_GET_LIGHTING(light) (light)
2793             #define STBVOX_LIGHTING_ROUNDOFF   2
2794             #endif
2795 
2796             for (i=0; i < 4; ++i) {
2797                // for each vertex, gather from the four neighbor blocks it's facing
2798                unsigned char *vamb = &amb[mm->cube_vertex_offset[face][i]];
2799                int total=0;
2800                for (j=0; j < 4; ++j)
2801                   total += STBVOX_GET_LIGHTING(vamb[mm->vertex_gather_offset[face][j]]);
2802                *mv[i] = vertbase + face_coord[i]
2803                           + stbvox_vertex_encode(0,0,0,(total+STBVOX_LIGHTING_ROUNDOFF)>>4,0)
2804                           + p1[i];
2805                           // >> 4 is because:
2806                           //   >> 2 to divide by 4 to get average over 4 samples
2807                           //   >> 2 because input is 8 bits, output is 6 bits
2808             }
2809 
2810             // @TODO: note that gathering baked *lighting*
2811             // is different from gathering baked ao; baked ao can count
2812             // solid blocks as 0 ao, but baked lighting wants average
2813             // of non-blocked--not take average & treat blocked as 0. And
2814             // we can't bake the right value into the solid blocks
2815             // because they can have different lighting values on
2816             // different sides. So we need to actually gather and
2817             // then divide by 0..4 (which we can do with a table-driven
2818             // multiply, or have an 'if' for the 3 case)
2819 
2820          }
2821       } else {
2822          vertbase += stbvox_vertex_encode(0,0,0,63,0);
2823          *mv[0] = vertbase + face_coord[0] + p1[0];
2824          *mv[1] = vertbase + face_coord[1] + p1[1];
2825          *mv[2] = vertbase + face_coord[2] + p1[2];
2826          *mv[3] = vertbase + face_coord[3] + p1[3];
2827       }
2828    }
2829 }
2830 
2831 // get opposite-facing normal & texgen for opposite face, used to map up-facing vheight data to down-facing data
2832 static unsigned char stbvox_reverse_face[STBVF_count] =
2833 {
2834    STBVF_w, STBVF_s, STBVF_e, STBVF_n, STBVF_d   , STBVF_u   , STBVF_wd, STBVF_wu,
2835          0,       0,       0,       0, STBVF_sw_d, STBVF_sw_u, STBVF_sd, STBVF_su,
2836          0,       0,       0,       0, STBVF_se_d, STBVF_se_u, STBVF_ed, STBVF_eu,
2837          0,       0,       0,       0, STBVF_ne_d, STBVF_ne_d, STBVF_nd, STBVF_nu
2838 };
2839 
2840 #ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
2841 // render non-planar quads by splitting into two triangles, rendering each as a degenerate quad
stbvox_make_12_split_mesh_for_face(stbvox_mesh_maker * mm,stbvox_rotate rot,int face,int v_off,stbvox_pos pos,stbvox_mesh_vertex vertbase,stbvox_mesh_vertex * face_coord,unsigned char mesh,unsigned char * ht)2842 static void stbvox_make_12_split_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, unsigned char *ht)
2843 {
2844    stbvox_mesh_vertex v[4];
2845 
2846    unsigned char normal1 = stbvox_face_up_normal_012[ht[2]][ht[1]][ht[0]];
2847    unsigned char normal2 = stbvox_face_up_normal_123[ht[3]][ht[2]][ht[1]];
2848 
2849    if (face == STBVOX_FACE_down) {
2850       normal1 = stbvox_reverse_face[normal1];
2851       normal2 = stbvox_reverse_face[normal2];
2852    }
2853 
2854    // the floor side face_coord is stored in order NW,NE,SE,SW, but ht[] is stored SW,SE,NW,NE
2855    v[0] = face_coord[2];
2856    v[1] = face_coord[3];
2857    v[2] = face_coord[0];
2858    v[3] = face_coord[2];
2859    stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal1);
2860    v[1] = face_coord[0];
2861    v[2] = face_coord[1];
2862    stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal2);
2863 }
2864 
stbvox_make_03_split_mesh_for_face(stbvox_mesh_maker * mm,stbvox_rotate rot,int face,int v_off,stbvox_pos pos,stbvox_mesh_vertex vertbase,stbvox_mesh_vertex * face_coord,unsigned char mesh,unsigned char * ht)2865 static void stbvox_make_03_split_mesh_for_face(stbvox_mesh_maker *mm, stbvox_rotate rot, int face, int v_off, stbvox_pos pos, stbvox_mesh_vertex vertbase, stbvox_mesh_vertex *face_coord, unsigned char mesh, unsigned char *ht)
2866 {
2867    stbvox_mesh_vertex v[4];
2868 
2869    unsigned char normal1 = stbvox_face_up_normal_013[ht[3]][ht[1]][ht[0]];
2870    unsigned char normal2 = stbvox_face_up_normal_023[ht[3]][ht[2]][ht[0]];
2871 
2872    if (face == STBVOX_FACE_down) {
2873       normal1 = stbvox_reverse_face[normal1];
2874       normal2 = stbvox_reverse_face[normal2];
2875    }
2876 
2877    v[0] = face_coord[1];
2878    v[1] = face_coord[2];
2879    v[2] = face_coord[3];
2880    v[3] = face_coord[1];
2881    stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal1);
2882    v[1] = face_coord[3];
2883    v[2] = face_coord[0];
2884    stbvox_make_mesh_for_face(mm, rot, face, v_off, pos, vertbase, v, mesh, normal2);  // this one is correct!
2885 }
2886 #endif
2887 
2888 #ifndef STBVOX_CONFIG_PRECISION_Z
2889 #define STBVOX_CONFIG_PRECISION_Z 1
2890 #endif
2891 
2892 // simple case for mesh generation: we have only solid and empty blocks
stbvox_make_mesh_for_block(stbvox_mesh_maker * mm,stbvox_pos pos,int v_off,stbvox_mesh_vertex * vmesh)2893 static void stbvox_make_mesh_for_block(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off, stbvox_mesh_vertex *vmesh)
2894 {
2895    int ns_off = mm->y_stride_in_bytes;
2896    int ew_off = mm->x_stride_in_bytes;
2897 
2898    unsigned char *blockptr = &mm->input.blocktype[v_off];
2899    stbvox_mesh_vertex basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z , 0,0);
2900 
2901    stbvox_rotate rot = { 0,0,0,0 };
2902    unsigned char simple_rot = 0;
2903 
2904    unsigned char mesh = mm->default_mesh;
2905 
2906    if (mm->input.selector)
2907       mesh = mm->input.selector[v_off];
2908    else if (mm->input.block_selector)
2909       mesh = mm->input.block_selector[mm->input.blocktype[v_off]];
2910 
2911    // check if we're going off the end
2912    if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) {
2913       mm->full = 1;
2914       return;
2915    }
2916 
2917    #ifdef STBVOX_CONFIG_ROTATION_IN_LIGHTING
2918    simple_rot = mm->input.lighting[v_off] & 3;
2919    #endif
2920 
2921    if (mm->input.packed_compact)
2922       simple_rot = mm->input.packed_compact[v_off] & 3;
2923 
2924    if (blockptr[ 1]==0) {
2925       rot.facerot = simple_rot;
2926       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_up  , v_off, pos, basevert, vmesh+4*STBVOX_FACE_up, mesh, STBVOX_FACE_up);
2927    }
2928    if (blockptr[-1]==0) {
2929       rot.facerot = (-simple_rot) & 3;
2930       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_down, v_off, pos, basevert, vmesh+4*STBVOX_FACE_down, mesh, STBVOX_FACE_down);
2931    }
2932 
2933    if (mm->input.rotate) {
2934       unsigned char val = mm->input.rotate[v_off];
2935       rot.block   = (val >> 0) & 3;
2936       rot.overlay = (val >> 2) & 3;
2937       //rot.tex2    = (val >> 4) & 3;
2938       rot.ecolor  = (val >> 6) & 3;
2939    } else {
2940       rot.block = rot.overlay = rot.ecolor = simple_rot;
2941    }
2942    rot.facerot = 0;
2943 
2944    if (blockptr[ ns_off]==0)
2945       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, vmesh+4*STBVOX_FACE_north, mesh, STBVOX_FACE_north);
2946    if (blockptr[-ns_off]==0)
2947       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_south, v_off, pos, basevert, vmesh+4*STBVOX_FACE_south, mesh, STBVOX_FACE_south);
2948    if (blockptr[ ew_off]==0)
2949       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_east , v_off, pos, basevert, vmesh+4*STBVOX_FACE_east, mesh, STBVOX_FACE_east);
2950    if (blockptr[-ew_off]==0)
2951       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_west , v_off, pos, basevert, vmesh+4*STBVOX_FACE_west, mesh, STBVOX_FACE_west);
2952 }
2953 
2954 // complex case for mesh generation: we have lots of different
2955 // block types, and we don't want to generate faces of blocks
2956 // if they're hidden by neighbors.
2957 //
2958 // we use lots of tables to determine this: we have a table
2959 // which tells us what face type is generated for each type of
2960 // geometry, and then a table that tells us whether that type
2961 // is hidden by a neighbor.
stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker * mm,stbvox_pos pos,int v_off)2962 static void stbvox_make_mesh_for_block_with_geo(stbvox_mesh_maker *mm, stbvox_pos pos, int v_off)
2963 {
2964    int ns_off = mm->y_stride_in_bytes;
2965    int ew_off = mm->x_stride_in_bytes;
2966    int visible_faces, visible_base;
2967    unsigned char mesh;
2968 
2969    // first gather the geometry info for this block and all neighbors
2970 
2971    unsigned char bt, nbt[6];
2972    unsigned char geo, ngeo[6];
2973    unsigned char rot, nrot[6];
2974 
2975    bt = mm->input.blocktype[v_off];
2976    nbt[0] = mm->input.blocktype[v_off + ew_off];
2977    nbt[1] = mm->input.blocktype[v_off + ns_off];
2978    nbt[2] = mm->input.blocktype[v_off - ew_off];
2979    nbt[3] = mm->input.blocktype[v_off - ns_off];
2980    nbt[4] = mm->input.blocktype[v_off +      1];
2981    nbt[5] = mm->input.blocktype[v_off -      1];
2982    if (mm->input.geometry) {
2983       int i;
2984       geo = mm->input.geometry[v_off];
2985       ngeo[0] = mm->input.geometry[v_off + ew_off];
2986       ngeo[1] = mm->input.geometry[v_off + ns_off];
2987       ngeo[2] = mm->input.geometry[v_off - ew_off];
2988       ngeo[3] = mm->input.geometry[v_off - ns_off];
2989       ngeo[4] = mm->input.geometry[v_off +      1];
2990       ngeo[5] = mm->input.geometry[v_off -      1];
2991 
2992       rot = (geo >> 4) & 3;
2993       geo &= 15;
2994       for (i=0; i < 6; ++i) {
2995          nrot[i] = (ngeo[i] >> 4) & 3;
2996          ngeo[i] &= 15;
2997       }
2998    } else {
2999       int i;
3000       assert(mm->input.block_geometry);
3001       geo = mm->input.block_geometry[bt];
3002       for (i=0; i < 6; ++i)
3003          ngeo[i] = mm->input.block_geometry[nbt[i]];
3004       if (mm->input.selector) {
3005          #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
3006          if (mm->input.packed_compact == NULL) {
3007             rot     = (mm->input.selector[v_off         ] >> 4) & 3;
3008             nrot[0] = (mm->input.selector[v_off + ew_off] >> 4) & 3;
3009             nrot[1] = (mm->input.selector[v_off + ns_off] >> 4) & 3;
3010             nrot[2] = (mm->input.selector[v_off - ew_off] >> 4) & 3;
3011             nrot[3] = (mm->input.selector[v_off - ns_off] >> 4) & 3;
3012             nrot[4] = (mm->input.selector[v_off +      1] >> 4) & 3;
3013             nrot[5] = (mm->input.selector[v_off -      1] >> 4) & 3;
3014          }
3015          #endif
3016       } else {
3017          #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
3018          if (mm->input.packed_compact == NULL) {
3019             rot = (geo>>4)&3;
3020             geo &= 15;
3021             for (i=0; i < 6; ++i) {
3022                nrot[i] = (ngeo[i]>>4)&3;
3023                ngeo[i] &= 15;
3024             }
3025          }
3026          #endif
3027       }
3028    }
3029 
3030    #ifndef STBVOX_CONFIG_ROTATION_IN_LIGHTING
3031    if (mm->input.packed_compact) {
3032       rot = mm->input.packed_compact[rot] & 3;
3033       nrot[0] = mm->input.packed_compact[v_off + ew_off] & 3;
3034       nrot[1] = mm->input.packed_compact[v_off + ns_off] & 3;
3035       nrot[2] = mm->input.packed_compact[v_off - ew_off] & 3;
3036       nrot[3] = mm->input.packed_compact[v_off - ns_off] & 3;
3037       nrot[4] = mm->input.packed_compact[v_off +      1] & 3;
3038       nrot[5] = mm->input.packed_compact[v_off -      1] & 3;
3039    }
3040    #else
3041    rot = mm->input.lighting[v_off] & 3;
3042    nrot[0] = (mm->input.lighting[v_off + ew_off]) & 3;
3043    nrot[1] = (mm->input.lighting[v_off + ns_off]) & 3;
3044    nrot[2] = (mm->input.lighting[v_off - ew_off]) & 3;
3045    nrot[3] = (mm->input.lighting[v_off - ns_off]) & 3;
3046    nrot[4] = (mm->input.lighting[v_off +      1]) & 3;
3047    nrot[5] = (mm->input.lighting[v_off -      1]) & 3;
3048    #endif
3049 
3050    if (geo == STBVOX_GEOM_transp) {
3051       // transparency has a special rule: if the blocktype is the same,
3052       // and the faces are compatible, then can hide them; otherwise,
3053       // force them on
3054       // Note that this means we don't support any transparentshapes other
3055       // than solid blocks, since detecting them is too complicated. If
3056       // you wanted to do something like minecraft water, you probably
3057       // should just do that with a separate renderer anyway. (We don't
3058       // support transparency sorting so you need to use alpha test
3059       // anyway)
3060       int i;
3061       for (i=0; i < 6; ++i)
3062          if (nbt[i] != bt) {
3063             nbt[i] = 0;
3064             ngeo[i] = STBVOX_GEOM_empty;
3065          } else
3066             ngeo[i] = STBVOX_GEOM_solid;
3067       geo = STBVOX_GEOM_solid;
3068    }
3069 
3070    // now compute the face visibility
3071    visible_base = stbvox_hasface[geo][rot];
3072    // @TODO: assert(visible_base != 0); // we should have early-outted earlier in this case
3073    visible_faces = 0;
3074 
3075    // now, for every face that might be visible, check if neighbor hides it
3076    if (visible_base & (1 << STBVOX_FACE_east)) {
3077       int  type = stbvox_facetype[ geo   ][(STBVOX_FACE_east+ rot   )&3];
3078       int ntype = stbvox_facetype[ngeo[0]][(STBVOX_FACE_west+nrot[0])&3];
3079       visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_east)) & (1 << STBVOX_FACE_east);
3080    }
3081    if (visible_base & (1 << STBVOX_FACE_north)) {
3082       int  type = stbvox_facetype[ geo   ][(STBVOX_FACE_north+ rot   )&3];
3083       int ntype = stbvox_facetype[ngeo[1]][(STBVOX_FACE_south+nrot[1])&3];
3084       visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_north)) & (1 << STBVOX_FACE_north);
3085    }
3086    if (visible_base & (1 << STBVOX_FACE_west)) {
3087       int  type = stbvox_facetype[ geo   ][(STBVOX_FACE_west+ rot   )&3];
3088       int ntype = stbvox_facetype[ngeo[2]][(STBVOX_FACE_east+nrot[2])&3];
3089       visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_west)) & (1 << STBVOX_FACE_west);
3090    }
3091    if (visible_base & (1 << STBVOX_FACE_south)) {
3092       int  type = stbvox_facetype[ geo   ][(STBVOX_FACE_south+ rot   )&3];
3093       int ntype = stbvox_facetype[ngeo[3]][(STBVOX_FACE_north+nrot[3])&3];
3094       visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_south)) & (1 << STBVOX_FACE_south);
3095    }
3096    if (visible_base & (1 << STBVOX_FACE_up)) {
3097       int  type = stbvox_facetype[ geo   ][STBVOX_FACE_up];
3098       int ntype = stbvox_facetype[ngeo[4]][STBVOX_FACE_down];
3099       visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_up)) & (1 << STBVOX_FACE_up);
3100    }
3101    if (visible_base & (1 << STBVOX_FACE_down)) {
3102       int  type = stbvox_facetype[ geo   ][STBVOX_FACE_down];
3103       int ntype = stbvox_facetype[ngeo[5]][STBVOX_FACE_up];
3104       visible_faces |= ((stbvox_face_visible[type]) >> (ntype + 5 - STBVOX_FACE_down)) & (1 << STBVOX_FACE_down);
3105    }
3106 
3107    if (geo == STBVOX_GEOM_force)
3108       geo = STBVOX_GEOM_solid;
3109 
3110    assert((geo == STBVOX_GEOM_crossed_pair) ? (visible_faces == 15) : 1);
3111 
3112    // now we finally know for sure which faces are getting generated
3113    if (visible_faces == 0)
3114       return;
3115 
3116    mesh = mm->default_mesh;
3117    if (mm->input.selector)
3118       mesh = mm->input.selector[v_off];
3119    else if (mm->input.block_selector)
3120       mesh = mm->input.block_selector[bt];
3121 
3122    if (geo <= STBVOX_GEOM_ceil_slope_north_is_bottom) {
3123       // this is the simple case, we can just use regular block gen with special vmesh calculated with vheight
3124       stbvox_mesh_vertex basevert;
3125       stbvox_mesh_vertex vmesh[6][4];
3126       stbvox_rotate rotate = { 0,0,0,0 };
3127       unsigned char simple_rot = rot;
3128       int i;
3129       // we only need to do this for the displayed faces, but it's easier
3130       // to just do it up front; @OPTIMIZE check if it's faster to do it
3131       // for visible faces only
3132       for (i=0; i < 6*4; ++i) {
3133          int vert = stbvox_vertex_selector[0][i];
3134          vert = stbvox_rotate_vertex[vert][rot];
3135          vmesh[0][i] = stbvox_vmesh_pre_vheight[0][i]
3136                      + stbvox_geometry_vheight[geo][vert];
3137       }
3138 
3139       basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z, 0,0);
3140       if (mm->input.selector) {
3141          mesh = mm->input.selector[v_off];
3142       } else if (mm->input.block_selector)
3143          mesh = mm->input.block_selector[bt];
3144 
3145 
3146       // check if we're going off the end
3147       if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) {
3148          mm->full = 1;
3149          return;
3150       }
3151 
3152       if (geo >= STBVOX_GEOM_floor_slope_north_is_top) {
3153          if (visible_faces & (1 << STBVOX_FACE_up)) {
3154             int normal = geo == STBVOX_GEOM_floor_slope_north_is_top ? stbvox_floor_slope_for_rot[simple_rot] : STBVOX_FACE_up;
3155             rotate.facerot = simple_rot;
3156             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up  , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, normal);
3157          }
3158          if (visible_faces & (1 << STBVOX_FACE_down)) {
3159             int normal = geo == STBVOX_GEOM_ceil_slope_north_is_bottom ? stbvox_ceil_slope_for_rot[simple_rot] : STBVOX_FACE_down;
3160             rotate.facerot = (-rotate.facerot) & 3;
3161             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, normal);
3162          }
3163       } else {
3164          if (visible_faces & (1 << STBVOX_FACE_up)) {
3165             rotate.facerot = simple_rot;
3166             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up  , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, STBVOX_FACE_up);
3167          }
3168          if (visible_faces & (1 << STBVOX_FACE_down)) {
3169             rotate.facerot = (-rotate.facerot) & 3;
3170             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, STBVOX_FACE_down);
3171          }
3172       }
3173 
3174       if (mm->input.rotate) {
3175          unsigned char val = mm->input.rotate[v_off];
3176          rotate.block   = (val >> 0) & 3;
3177          rotate.overlay = (val >> 2) & 3;
3178          //rotate.tex2    = (val >> 4) & 3;
3179          rotate.ecolor  = (val >> 6) & 3;
3180       } else {
3181          rotate.block = rotate.overlay = rotate.ecolor = simple_rot;
3182       }
3183 
3184       rotate.facerot = 0;
3185 
3186       if (visible_faces & (1 << STBVOX_FACE_north))
3187          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_north, v_off, pos, basevert, vmesh[STBVOX_FACE_north], mesh, STBVOX_FACE_north);
3188       if (visible_faces & (1 << STBVOX_FACE_south))
3189          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_south, v_off, pos, basevert, vmesh[STBVOX_FACE_south], mesh, STBVOX_FACE_south);
3190       if (visible_faces & (1 << STBVOX_FACE_east))
3191          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_east , v_off, pos, basevert, vmesh[STBVOX_FACE_east ], mesh, STBVOX_FACE_east);
3192       if (visible_faces & (1 << STBVOX_FACE_west))
3193          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_west , v_off, pos, basevert, vmesh[STBVOX_FACE_west ], mesh, STBVOX_FACE_west);
3194    }
3195    if (geo >= STBVOX_GEOM_floor_vheight_03) {
3196       // this case can also be generated with regular block gen with special vmesh,
3197       // except:
3198       //     if we want to generate middle diagonal for 'weird' blocks
3199       //     it's more complicated to detect neighbor matchups
3200       stbvox_mesh_vertex vmesh[6][4];
3201       stbvox_mesh_vertex cube[8];
3202       stbvox_mesh_vertex basevert;
3203       stbvox_rotate rotate = { 0,0,0,0 };
3204       unsigned char simple_rot = rot;
3205       unsigned char ht[4];
3206       int extreme;
3207 
3208       // extract the heights
3209       #ifdef STBVOX_CONFIG_VHEIGHT_IN_LIGHTING
3210       ht[0] = mm->input.lighting[v_off              ] & 3;
3211       ht[1] = mm->input.lighting[v_off+ew_off       ] & 3;
3212       ht[2] = mm->input.lighting[v_off       +ns_off] & 3;
3213       ht[3] = mm->input.lighting[v_off+ew_off+ns_off] & 3;
3214       #else
3215       if (mm->input.vheight) {
3216          unsigned char v =  mm->input.vheight[v_off];
3217          ht[0] = (v >> 0) & 3;
3218          ht[1] = (v >> 2) & 3;
3219          ht[2] = (v >> 4) & 3;
3220          ht[3] = (v >> 6) & 3;
3221       } else if (mm->input.block_vheight) {
3222          unsigned char v = mm->input.block_vheight[bt];
3223          unsigned char raw[4];
3224          int i;
3225 
3226          raw[0] = (v >> 0) & 3;
3227          raw[1] = (v >> 2) & 3;
3228          raw[2] = (v >> 4) & 3;
3229          raw[3] = (v >> 6) & 3;
3230 
3231          for (i=0; i < 4; ++i)
3232             ht[i] = raw[stbvox_rotate_vertex[i][rot]];
3233       } else if (mm->input.packed_compact) {
3234          ht[0] = (mm->input.packed_compact[v_off              ] >> 2) & 3;
3235          ht[1] = (mm->input.packed_compact[v_off+ew_off       ] >> 2) & 3;
3236          ht[2] = (mm->input.packed_compact[v_off       +ns_off] >> 2) & 3;
3237          ht[3] = (mm->input.packed_compact[v_off+ew_off+ns_off] >> 2) & 3;
3238       } else if (mm->input.geometry) {
3239          ht[0] = mm->input.geometry[v_off              ] >> 6;
3240          ht[1] = mm->input.geometry[v_off+ew_off       ] >> 6;
3241          ht[2] = mm->input.geometry[v_off       +ns_off] >> 6;
3242          ht[3] = mm->input.geometry[v_off+ew_off+ns_off] >> 6;
3243       } else {
3244          assert(0);
3245       }
3246       #endif
3247 
3248       // flag whether any sides go off the top of the block, which means
3249       // our visible_faces test was wrong
3250       extreme = (ht[0] == 3 || ht[1] == 3 || ht[2] == 3 || ht[3] == 3);
3251 
3252       if (geo >= STBVOX_GEOM_ceil_vheight_03) {
3253          cube[0] = stbvox_vertex_encode(0,0,ht[0],0,0);
3254          cube[1] = stbvox_vertex_encode(0,0,ht[1],0,0);
3255          cube[2] = stbvox_vertex_encode(0,0,ht[2],0,0);
3256          cube[3] = stbvox_vertex_encode(0,0,ht[3],0,0);
3257          cube[4] = stbvox_vertex_encode(0,0,2,0,0);
3258          cube[5] = stbvox_vertex_encode(0,0,2,0,0);
3259          cube[6] = stbvox_vertex_encode(0,0,2,0,0);
3260          cube[7] = stbvox_vertex_encode(0,0,2,0,0);
3261       } else {
3262          cube[0] = stbvox_vertex_encode(0,0,0,0,0);
3263          cube[1] = stbvox_vertex_encode(0,0,0,0,0);
3264          cube[2] = stbvox_vertex_encode(0,0,0,0,0);
3265          cube[3] = stbvox_vertex_encode(0,0,0,0,0);
3266          cube[4] = stbvox_vertex_encode(0,0,ht[0],0,0);
3267          cube[5] = stbvox_vertex_encode(0,0,ht[1],0,0);
3268          cube[6] = stbvox_vertex_encode(0,0,ht[2],0,0);
3269          cube[7] = stbvox_vertex_encode(0,0,ht[3],0,0);
3270       }
3271       if (!mm->input.vheight && mm->input.block_vheight) {
3272          // @TODO: support block vheight here, I've forgotten what needs to be done specially
3273       }
3274 
3275       // build vertex mesh
3276       {
3277          int i;
3278          for (i=0; i < 6*4; ++i) {
3279             int vert = stbvox_vertex_selector[0][i];
3280             vmesh[0][i] = stbvox_vmesh_pre_vheight[0][i]
3281                         + cube[vert];
3282          }
3283       }
3284 
3285       basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z, 0,0);
3286       // check if we're going off the end
3287       if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*6 > mm->output_end[mesh][0]) {
3288          mm->full = 1;
3289          return;
3290       }
3291 
3292       // @TODO generate split faces
3293       if (visible_faces & (1 << STBVOX_FACE_up)) {
3294          if (geo >= STBVOX_GEOM_ceil_vheight_03)
3295             // flat
3296             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up  , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, STBVOX_FACE_up);
3297          else {
3298          #ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
3299             // check if it's non-planar
3300             if (cube[5] + cube[6] != cube[4] + cube[7]) {
3301                // not planar, split along diagonal and make degenerate quads
3302                if (geo == STBVOX_GEOM_floor_vheight_03)
3303                   stbvox_make_03_split_mesh_for_face(mm, rotate, STBVOX_FACE_up, v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, ht);
3304                else
3305                   stbvox_make_12_split_mesh_for_face(mm, rotate, STBVOX_FACE_up, v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, ht);
3306             } else
3307                stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up  , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, stbvox_planar_face_up_normal[ht[2]][ht[1]][ht[0]]);
3308          #else
3309             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_up  , v_off, pos, basevert, vmesh[STBVOX_FACE_up], mesh, stbvox_optimized_face_up_normal[ht[3]][ht[2]][ht[1]][ht[0]]);
3310          #endif
3311          }
3312       }
3313       if (visible_faces & (1 << STBVOX_FACE_down)) {
3314          if (geo < STBVOX_GEOM_ceil_vheight_03)
3315             // flat
3316             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, STBVOX_FACE_down);
3317          else {
3318          #ifndef STBVOX_CONFIG_OPTIMIZED_VHEIGHT
3319             // check if it's non-planar
3320             if (cube[1] + cube[2] != cube[0] + cube[3]) {
3321                // not planar, split along diagonal and make degenerate quads
3322                if (geo == STBVOX_GEOM_ceil_vheight_03)
3323                   stbvox_make_03_split_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, ht);
3324                else
3325                   stbvox_make_12_split_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, ht);
3326             } else
3327                stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, stbvox_reverse_face[stbvox_planar_face_up_normal[ht[2]][ht[1]][ht[0]]]);
3328          #else
3329             stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_down, v_off, pos, basevert, vmesh[STBVOX_FACE_down], mesh, stbvox_reverse_face[stbvox_optimized_face_up_normal[ht[3]][ht[2]][ht[1]][ht[0]]]);
3330          #endif
3331          }
3332       }
3333 
3334       if (mm->input.rotate) {
3335          unsigned char val = mm->input.rotate[v_off];
3336          rotate.block   = (val >> 0) & 3;
3337          rotate.overlay = (val >> 2) & 3;
3338          //rotate.tex2    = (val >> 4) & 3;
3339          rotate.ecolor  = (val >> 6) & 3;
3340       } else if (mm->input.selector) {
3341          rotate.block = rotate.overlay = rotate.ecolor = simple_rot;
3342       }
3343 
3344       if ((visible_faces & (1 << STBVOX_FACE_north)) || (extreme && (ht[2] == 3 || ht[3] == 3)))
3345          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_north, v_off, pos, basevert, vmesh[STBVOX_FACE_north], mesh, STBVOX_FACE_north);
3346       if ((visible_faces & (1 << STBVOX_FACE_south)) || (extreme && (ht[0] == 3 || ht[1] == 3)))
3347          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_south, v_off, pos, basevert, vmesh[STBVOX_FACE_south], mesh, STBVOX_FACE_south);
3348       if ((visible_faces & (1 << STBVOX_FACE_east)) || (extreme && (ht[1] == 3 || ht[3] == 3)))
3349          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_east , v_off, pos, basevert, vmesh[STBVOX_FACE_east ], mesh, STBVOX_FACE_east);
3350       if ((visible_faces & (1 << STBVOX_FACE_west)) || (extreme && (ht[0] == 3 || ht[2] == 3)))
3351          stbvox_make_mesh_for_face(mm, rotate, STBVOX_FACE_west , v_off, pos, basevert, vmesh[STBVOX_FACE_west ], mesh, STBVOX_FACE_west);
3352    }
3353 
3354    if (geo == STBVOX_GEOM_crossed_pair) {
3355       // this can be generated with a special vmesh
3356       stbvox_mesh_vertex basevert = stbvox_vertex_encode(pos.x, pos.y, pos.z << STBVOX_CONFIG_PRECISION_Z , 0,0);
3357       unsigned char simple_rot=0;
3358       stbvox_rotate rot = { 0,0,0,0 };
3359       unsigned char mesh = mm->default_mesh;
3360       if (mm->input.selector) {
3361          mesh = mm->input.selector[v_off];
3362          simple_rot = mesh >> 4;
3363          mesh &= 15;
3364       }
3365       if (mm->input.block_selector) {
3366          mesh = mm->input.block_selector[bt];
3367       }
3368 
3369       // check if we're going off the end
3370       if (mm->output_cur[mesh][0] + mm->output_size[mesh][0]*4 > mm->output_end[mesh][0]) {
3371          mm->full = 1;
3372          return;
3373       }
3374 
3375       if (mm->input.rotate) {
3376          unsigned char val = mm->input.rotate[v_off];
3377          rot.block   = (val >> 0) & 3;
3378          rot.overlay = (val >> 2) & 3;
3379          //rot.tex2    = (val >> 4) & 3;
3380          rot.ecolor  = (val >> 6) & 3;
3381       } else if (mm->input.selector) {
3382          rot.block = rot.overlay = rot.ecolor = simple_rot;
3383       }
3384       rot.facerot = 0;
3385 
3386       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_north, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_north], mesh, STBVF_ne_u_cross);
3387       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_south, v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_south], mesh, STBVF_sw_u_cross);
3388       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_east , v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_east ], mesh, STBVF_se_u_cross);
3389       stbvox_make_mesh_for_face(mm, rot, STBVOX_FACE_west , v_off, pos, basevert, stbvox_vmesh_crossed_pair[STBVOX_FACE_west ], mesh, STBVF_nw_u_cross);
3390    }
3391 
3392 
3393    // @TODO
3394    // STBVOX_GEOM_floor_slope_north_is_top_as_wall,
3395    // STBVOX_GEOM_ceil_slope_north_is_bottom_as_wall,
3396 }
3397 
stbvox_make_mesh_for_column(stbvox_mesh_maker * mm,int x,int y,int z0)3398 static void stbvox_make_mesh_for_column(stbvox_mesh_maker *mm, int x, int y, int z0)
3399 {
3400    stbvox_pos pos;
3401    int v_off = x * mm->x_stride_in_bytes + y * mm->y_stride_in_bytes;
3402    int ns_off = mm->y_stride_in_bytes;
3403    int ew_off = mm->x_stride_in_bytes;
3404    pos.x = x;
3405    pos.y = y;
3406    pos.z = 0;
3407    if (mm->input.geometry) {
3408       unsigned char *bt  = mm->input.blocktype + v_off;
3409       unsigned char *geo = mm->input.geometry + v_off;
3410       int z;
3411       for (z=z0; z < mm->z1; ++z) {
3412          if (bt[z] && ( !bt[z+ns_off] || !STBVOX_GET_GEO(geo[z+ns_off]) || !bt[z-ns_off] || !STBVOX_GET_GEO(geo[z-ns_off])
3413                       || !bt[z+ew_off] || !STBVOX_GET_GEO(geo[z+ew_off]) || !bt[z-ew_off] || !STBVOX_GET_GEO(geo[z-ew_off])
3414                       || !bt[z-1] || !STBVOX_GET_GEO(geo[z-1]) || !bt[z+1] || !STBVOX_GET_GEO(geo[z+1])))
3415          {  // TODO check up and down
3416             pos.z = z;
3417             stbvox_make_mesh_for_block_with_geo(mm, pos, v_off+z);
3418             if (mm->full) {
3419                mm->cur_z = z;
3420                return;
3421             }
3422          }
3423       }
3424    } else if (mm->input.block_geometry) {
3425       int z;
3426       unsigned char *bt  = mm->input.blocktype + v_off;
3427       unsigned char *geo = mm->input.block_geometry;
3428       for (z=z0; z < mm->z1; ++z) {
3429          if (bt[z] && (    geo[bt[z+ns_off]] != STBVOX_GEOM_solid
3430                         || geo[bt[z-ns_off]] != STBVOX_GEOM_solid
3431                         || geo[bt[z+ew_off]] != STBVOX_GEOM_solid
3432                         || geo[bt[z-ew_off]] != STBVOX_GEOM_solid
3433                         || geo[bt[z-1]] != STBVOX_GEOM_solid
3434                         || geo[bt[z+1]] != STBVOX_GEOM_solid))
3435          {
3436             pos.z = z;
3437             stbvox_make_mesh_for_block_with_geo(mm, pos, v_off+z);
3438             if (mm->full) {
3439                mm->cur_z = z;
3440                return;
3441             }
3442          }
3443       }
3444    } else {
3445       unsigned char *bt = mm->input.blocktype + v_off;
3446       int z;
3447       #if STBVOX_CONFIG_PRECISION_Z == 1
3448       stbvox_mesh_vertex *vmesh = stbvox_vmesh_delta_half_z[0];
3449       #else
3450       stbvox_mesh_vertex *vmesh = stbvox_vmesh_delta_normal[0];
3451       #endif
3452       for (z=z0; z < mm->z1; ++z) {
3453          // if it's solid and at least one neighbor isn't solid
3454          if (bt[z] && (!bt[z+ns_off] || !bt[z-ns_off] || !bt[z+ew_off] || !bt[z-ew_off] || !bt[z-1] || !bt[z+1])) {
3455             pos.z = z;
3456             stbvox_make_mesh_for_block(mm, pos, v_off+z, vmesh);
3457             if (mm->full) {
3458                mm->cur_z = z;
3459                return;
3460             }
3461          }
3462       }
3463    }
3464 }
3465 
stbvox_bring_up_to_date(stbvox_mesh_maker * mm)3466 static void stbvox_bring_up_to_date(stbvox_mesh_maker *mm)
3467 {
3468    if (mm->config_dirty) {
3469       int i;
3470       #ifdef STBVOX_ICONFIG_FACE_ATTRIBUTE
3471          mm->num_mesh_slots = 1;
3472          for (i=0; i < STBVOX_MAX_MESHES; ++i) {
3473             mm->output_size[i][0] = 32;
3474             mm->output_step[i][0] = 8;
3475          }
3476       #else
3477          mm->num_mesh_slots = 2;
3478          for (i=0; i < STBVOX_MAX_MESHES; ++i) {
3479             mm->output_size[i][0] = 16;
3480             mm->output_step[i][0] = 4;
3481             mm->output_size[i][1] = 4;
3482             mm->output_step[i][1] = 4;
3483          }
3484       #endif
3485 
3486       mm->config_dirty = 0;
3487    }
3488 }
3489 
stbvox_make_mesh(stbvox_mesh_maker * mm)3490 int stbvox_make_mesh(stbvox_mesh_maker *mm)
3491 {
3492    int x,y;
3493    stbvox_bring_up_to_date(mm);
3494    mm->full = 0;
3495    if (mm->cur_x > mm->x0 || mm->cur_y > mm->y0 || mm->cur_z > mm->z0) {
3496       stbvox_make_mesh_for_column(mm, mm->cur_x, mm->cur_y, mm->cur_z);
3497       if (mm->full)
3498          return 0;
3499       ++mm->cur_y;
3500       while (mm->cur_y < mm->y1 && !mm->full) {
3501          stbvox_make_mesh_for_column(mm, mm->cur_x, mm->cur_y, mm->z0);
3502          if (mm->full)
3503             return 0;
3504          ++mm->cur_y;
3505       }
3506       ++mm->cur_x;
3507    }
3508    for (x=mm->cur_x; x < mm->x1; ++x) {
3509       for (y=mm->y0; y < mm->y1; ++y) {
3510          stbvox_make_mesh_for_column(mm, x, y, mm->z0);
3511          if (mm->full) {
3512             mm->cur_x = x;
3513             mm->cur_y = y;
3514             return 0;
3515          }
3516       }
3517    }
3518    return 1;
3519 }
3520 
stbvox_init_mesh_maker(stbvox_mesh_maker * mm)3521 void stbvox_init_mesh_maker(stbvox_mesh_maker *mm)
3522 {
3523    memset(mm, 0, sizeof(*mm));
3524    stbvox_build_default_palette();
3525 
3526    mm->config_dirty = 1;
3527    mm->default_mesh = 0;
3528 }
3529 
stbvox_get_buffer_count(stbvox_mesh_maker * mm)3530 int stbvox_get_buffer_count(stbvox_mesh_maker *mm)
3531 {
3532    stbvox_bring_up_to_date(mm);
3533    return mm->num_mesh_slots;
3534 }
3535 
stbvox_get_buffer_size_per_quad(stbvox_mesh_maker * mm,int n)3536 int stbvox_get_buffer_size_per_quad(stbvox_mesh_maker *mm, int n)
3537 {
3538    return mm->output_size[0][n];
3539 }
3540 
stbvox_reset_buffers(stbvox_mesh_maker * mm)3541 void stbvox_reset_buffers(stbvox_mesh_maker *mm)
3542 {
3543    int i;
3544    for (i=0; i < STBVOX_MAX_MESHES*STBVOX_MAX_MESH_SLOTS; ++i) {
3545       mm->output_cur[0][i] = 0;
3546       mm->output_buffer[0][i] = 0;
3547    }
3548 }
3549 
stbvox_set_buffer(stbvox_mesh_maker * mm,int mesh,int slot,void * buffer,size_t len)3550 void stbvox_set_buffer(stbvox_mesh_maker *mm, int mesh, int slot, void *buffer, size_t len)
3551 {
3552    int i;
3553    stbvox_bring_up_to_date(mm);
3554    mm->output_buffer[mesh][slot] = (char *) buffer;
3555    mm->output_cur   [mesh][slot] = (char *) buffer;
3556    mm->output_len   [mesh][slot] = (int) len;
3557    mm->output_end   [mesh][slot] = (char *) buffer + len;
3558    for (i=0; i < STBVOX_MAX_MESH_SLOTS; ++i) {
3559       if (mm->output_buffer[mesh][i]) {
3560          assert(mm->output_len[mesh][i] / mm->output_size[mesh][i] == mm->output_len[mesh][slot] / mm->output_size[mesh][slot]);
3561       }
3562    }
3563 }
3564 
stbvox_set_default_mesh(stbvox_mesh_maker * mm,int mesh)3565 void stbvox_set_default_mesh(stbvox_mesh_maker *mm, int mesh)
3566 {
3567    mm->default_mesh = mesh;
3568 }
3569 
stbvox_get_quad_count(stbvox_mesh_maker * mm,int mesh)3570 int stbvox_get_quad_count(stbvox_mesh_maker *mm, int mesh)
3571 {
3572    return (int) ((mm->output_cur[mesh][0] - mm->output_buffer[mesh][0]) / mm->output_size[mesh][0]);
3573 }
3574 
stbvox_get_input_description(stbvox_mesh_maker * mm)3575 stbvox_input_description *stbvox_get_input_description(stbvox_mesh_maker *mm)
3576 {
3577    return &mm->input;
3578 }
3579 
stbvox_set_input_range(stbvox_mesh_maker * mm,int x0,int y0,int z0,int x1,int y1,int z1)3580 void stbvox_set_input_range(stbvox_mesh_maker *mm, int x0, int y0, int z0, int x1, int y1, int z1)
3581 {
3582    mm->x0 = x0;
3583    mm->y0 = y0;
3584    mm->z0 = z0;
3585 
3586    mm->x1 = x1;
3587    mm->y1 = y1;
3588    mm->z1 = z1;
3589 
3590    mm->cur_x = x0;
3591    mm->cur_y = y0;
3592    mm->cur_z = z0;
3593 
3594    // @TODO validate that this range is representable in this mode
3595 }
3596 
stbvox_get_transform(stbvox_mesh_maker * mm,float transform[3][3])3597 void stbvox_get_transform(stbvox_mesh_maker *mm, float transform[3][3])
3598 {
3599    // scale
3600    transform[0][0] = 1.0;
3601    transform[0][1] = 1.0;
3602    #if STBVOX_CONFIG_PRECISION_Z==1
3603    transform[0][2] = 0.5f;
3604    #else
3605    transform[0][2] = 1.0f;
3606    #endif
3607    // translation
3608    transform[1][0] = (float) (mm->pos_x);
3609    transform[1][1] = (float) (mm->pos_y);
3610    transform[1][2] = (float) (mm->pos_z);
3611    // texture coordinate projection translation
3612    transform[2][0] = (float) (mm->pos_x & 255); // @TODO depends on max texture scale
3613    transform[2][1] = (float) (mm->pos_y & 255);
3614    transform[2][2] = (float) (mm->pos_z & 255);
3615 }
3616 
stbvox_get_bounds(stbvox_mesh_maker * mm,float bounds[2][3])3617 void stbvox_get_bounds(stbvox_mesh_maker *mm, float bounds[2][3])
3618 {
3619    bounds[0][0] = (float) (mm->pos_x + mm->x0);
3620    bounds[0][1] = (float) (mm->pos_y + mm->y0);
3621    bounds[0][2] = (float) (mm->pos_z + mm->z0);
3622    bounds[1][0] = (float) (mm->pos_x + mm->x1);
3623    bounds[1][1] = (float) (mm->pos_y + mm->y1);
3624    bounds[1][2] = (float) (mm->pos_z + mm->z1);
3625 }
3626 
stbvox_set_mesh_coordinates(stbvox_mesh_maker * mm,int x,int y,int z)3627 void stbvox_set_mesh_coordinates(stbvox_mesh_maker *mm, int x, int y, int z)
3628 {
3629    mm->pos_x = x;
3630    mm->pos_y = y;
3631    mm->pos_z = z;
3632 }
3633 
stbvox_set_input_stride(stbvox_mesh_maker * mm,int x_stride_in_bytes,int y_stride_in_bytes)3634 void stbvox_set_input_stride(stbvox_mesh_maker *mm, int x_stride_in_bytes, int y_stride_in_bytes)
3635 {
3636    int f,v;
3637    mm->x_stride_in_bytes = x_stride_in_bytes;
3638    mm->y_stride_in_bytes = y_stride_in_bytes;
3639    for (f=0; f < 6; ++f) {
3640       for (v=0; v < 4; ++v) {
3641          mm->cube_vertex_offset[f][v]   =   stbvox_vertex_vector[f][v][0]    * mm->x_stride_in_bytes
3642                                          +  stbvox_vertex_vector[f][v][1]    * mm->y_stride_in_bytes
3643                                          +  stbvox_vertex_vector[f][v][2]                           ;
3644          mm->vertex_gather_offset[f][v] =  (stbvox_vertex_vector[f][v][0]-1) * mm->x_stride_in_bytes
3645                                          + (stbvox_vertex_vector[f][v][1]-1) * mm->y_stride_in_bytes
3646                                          + (stbvox_vertex_vector[f][v][2]-1)                        ;
3647       }
3648    }
3649 }
3650 
3651 /////////////////////////////////////////////////////////////////////////////
3652 //
3653 //    offline computation of tables
3654 //
3655 
3656 #if 0
3657 // compute optimized vheight table
3658 static char *normal_names[32] =
3659 {
3660    0,0,0,0,"u   ",0, "eu  ",0,
3661    0,0,0,0,"ne_u",0, "nu  ",0,
3662    0,0,0,0,"nw_u",0, "wu  ",0,
3663    0,0,0,0,"sw_u",0, "su  ",0,
3664 };
3665 
3666 static char *find_best_normal(float x, float y, float z)
3667 {
3668    int best_slot = 4;
3669    float best_dot = 0;
3670    int i;
3671    for (i=0; i < 32; ++i) {
3672       if (normal_names[i]) {
3673          float dot = x * stbvox_default_normals[i][0] + y * stbvox_default_normals[i][1] + z * stbvox_default_normals[i][2];
3674          if (dot > best_dot) {
3675             best_dot = dot;
3676             best_slot = i;
3677          }
3678       }
3679    }
3680    return normal_names[best_slot];
3681 }
3682 
3683 int main(int argc, char **argv)
3684 {
3685    int sw,se,nw,ne;
3686    for (ne=0; ne < 4; ++ne) {
3687       for (nw=0; nw < 4; ++nw) {
3688          for (se=0; se < 4; ++se) {
3689             printf("        { ");
3690             for (sw=0; sw < 4; ++sw) {
3691                float x = (float) (nw + sw - ne - se);
3692                float y = (float) (sw + se - nw - ne);
3693                float z = 2;
3694                printf("STBVF_%s, ", find_best_normal(x,y,z));
3695             }
3696             printf("},\n");
3697          }
3698       }
3699    }
3700    return 0;
3701 }
3702 #endif
3703 
3704 // @TODO
3705 //
3706 //   - test API for texture rotation on side faces
3707 //   - API for texture rotation on top & bottom
3708 //   - better culling of vheight faces with vheight neighbors
3709 //   - better culling of non-vheight faces with vheight neighbors
3710 //   - gather vertex lighting from slopes correctly
3711 //   - better support texture edge_clamp: currently if you fall
3712 //     exactly on 1.0 you get wrapped incorrectly; this is rare, but
3713 //     can avoid: compute texcoords in vertex shader, offset towards
3714 //     center before modding, need 2 bits per vertex to know offset direction)
3715 //   - other mesh modes (10,6,4-byte quads)
3716 //
3717 //
3718 // With TexBuffer for the fixed vertex data, we can actually do
3719 // minecrafty non-blocks like stairs -- we still probably only
3720 // want 256 or so, so we can't do the equivalent of all the vheight
3721 // combos, but that's ok. The 256 includes baked rotations, but only
3722 // some of them need it, and lots of block types share some faces.
3723 //
3724 // mode 5 (6 bytes):   mode 6 (6 bytes)
3725 //   x:7                x:6
3726 //   y:7                y:6
3727 //   z:6                z:6
3728 //   tex1:8             tex1:8
3729 //   tex2:8             tex2:7
3730 //   color:8            color:8
3731 //   face:4             face:7
3732 //
3733 //
3734 //  side faces (all x4)        top&bottom faces (2x)    internal faces (1x)
3735 //     1  regular                1 regular
3736 //     2  slabs                                             2
3737 //     8  stairs                 4 stairs                  16
3738 //     4  diag side                                         8
3739 //     4  upper diag side                                   8
3740 //     4  lower diag side                                   8
3741 //                                                          4 crossed pairs
3742 //
3743 //    23*4                   +   5*4                    +  46
3744 //  == 92 + 20 + 46 = 158
3745 //
3746 //   Must drop 30 of them to fit in 7 bits:
3747 //       ceiling half diagonals: 16+8 = 24
3748 //   Need to get rid of 6 more.
3749 //       ceiling diagonals: 8+4 = 12
3750 //   This brings it to 122, so can add a crossed-pair variant.
3751 //       (diagonal and non-diagonal, or randomly offset)
3752 //   Or carpet, which would be 5 more.
3753 //
3754 //
3755 // Mode 4 (10 bytes):
3756 //  v:  z:2,light:6
3757 //  f:  x:6,y:6,z:7, t1:8,t2:8,c:8,f:5
3758 //
3759 // Mode ? (10 bytes)
3760 //  v:  xyz:5 (27 values), light:3
3761 //  f:  x:7,y:7,z:6, t1:8,t2:8,c:8,f:4
3762 // (v:  x:2,y:2,z:2,light:2)
3763 
3764 #endif // STB_VOXEL_RENDER_IMPLEMENTATION
3765 
3766 /*
3767 ------------------------------------------------------------------------------
3768 This software is available under 2 licenses -- choose whichever you prefer.
3769 ------------------------------------------------------------------------------
3770 ALTERNATIVE A - MIT License
3771 Copyright (c) 2017 Sean Barrett
3772 Permission is hereby granted, free of charge, to any person obtaining a copy of
3773 this software and associated documentation files (the "Software"), to deal in
3774 the Software without restriction, including without limitation the rights to
3775 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
3776 of the Software, and to permit persons to whom the Software is furnished to do
3777 so, subject to the following conditions:
3778 The above copyright notice and this permission notice shall be included in all
3779 copies or substantial portions of the Software.
3780 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3781 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3782 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3783 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3784 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3785 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3786 SOFTWARE.
3787 ------------------------------------------------------------------------------
3788 ALTERNATIVE B - Public Domain (www.unlicense.org)
3789 This is free and unencumbered software released into the public domain.
3790 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
3791 software, either in source code form or as a compiled binary, for any purpose,
3792 commercial or non-commercial, and by any means.
3793 In jurisdictions that recognize copyright laws, the author or authors of this
3794 software dedicate any and all copyright interest in the software to the public
3795 domain. We make this dedication for the benefit of the public at large and to
3796 the detriment of our heirs and successors. We intend this dedication to be an
3797 overt act of relinquishment in perpetuity of all present and future rights to
3798 this software under copyright law.
3799 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3800 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3801 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3802 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3803 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
3804 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3805 ------------------------------------------------------------------------------
3806 */
3807