added 'lighting' option to cave mode
This commit is contained in:
4
chunk.py
4
chunk.py
@@ -476,6 +476,10 @@ def generate_facemasks():
|
||||
for x,y in [(3,4), (7,2), (11,0)]:
|
||||
top.putpixel((x,y), 255)
|
||||
|
||||
# special fix for chunk boundary stipple
|
||||
for x,y in [(13,11), (17,9), (21,7)]:
|
||||
right.putpixel((x,y), 0)
|
||||
|
||||
return (top, left, right)
|
||||
facemasks = generate_facemasks()
|
||||
black_color = Image.new("RGB", (24,24), (0,0,0))
|
||||
|
||||
@@ -317,7 +317,7 @@ chunk_render(PyObject *self, PyObject *args) {
|
||||
|
||||
/* set up the render mode */
|
||||
rendermode_py = PyObject_GetAttrString(state.self, "rendermode");
|
||||
rendermode = render_mode_create(PyString_AsString(rendermode_py), &state);
|
||||
state.rendermode = rendermode = render_mode_create(PyString_AsString(rendermode_py), &state);
|
||||
Py_DECREF(rendermode_py);
|
||||
if (rendermode == NULL) {
|
||||
return Py_BuildValue("i", "-1");
|
||||
@@ -386,7 +386,7 @@ chunk_render(PyObject *self, PyObject *args) {
|
||||
blockid = PyInt_FromLong(state.block);
|
||||
|
||||
// check for occlusion
|
||||
if (render_mode_occluded(rendermode)) {
|
||||
if (render_mode_occluded(rendermode, state.x, state.y, state.z)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,9 @@ PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
||||
unsigned char sb, unsigned char sa,
|
||||
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
||||
|
||||
/* forward declaration of RenderMode object */
|
||||
typedef struct _RenderMode RenderMode;
|
||||
|
||||
/* in iterate.c */
|
||||
typedef struct {
|
||||
/* the ChunkRenderer object */
|
||||
@@ -61,6 +64,9 @@ typedef struct {
|
||||
PyObject *textures;
|
||||
PyObject *chunk;
|
||||
|
||||
/* the current render mode in use */
|
||||
RenderMode *rendermode;
|
||||
|
||||
/* the rest only make sense for occluded() and draw() !! */
|
||||
|
||||
/* the tile image and destination */
|
||||
|
||||
@@ -80,13 +80,13 @@ touches_light(unsigned int x, unsigned int y, unsigned int z,
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_cave_occluded(void *data, RenderState *state) {
|
||||
int x = state->x, y = state->y, z = state->z, dz = 0;
|
||||
rendermode_cave_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||
RenderModeCave* self;
|
||||
int dz = 0;
|
||||
self = (RenderModeCave *)data;
|
||||
|
||||
/* first, check to see if it's "normally" occluded */
|
||||
if (rendermode_normal.occluded(data, state))
|
||||
if (rendermode_lighting.occluded(data, state, x, y, z))
|
||||
return 1;
|
||||
|
||||
/* check if the block is touching skylight */
|
||||
@@ -182,7 +182,7 @@ rendermode_cave_start(void *data, RenderState *state, PyObject *options) {
|
||||
self = (RenderModeCave *)data;
|
||||
|
||||
/* first, chain up */
|
||||
ret = rendermode_normal.start(data, state, options);
|
||||
ret = rendermode_lighting.start(data, state, options);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
@@ -200,6 +200,13 @@ rendermode_cave_start(void *data, RenderState *state, PyObject *options) {
|
||||
self->only_lit = 0;
|
||||
}
|
||||
|
||||
opt = PyDict_GetItemString(options, "lighting");
|
||||
if (opt) {
|
||||
self->lighting = PyObject_IsTrue(opt);
|
||||
} else {
|
||||
self->lighting = 0;
|
||||
}
|
||||
|
||||
/* if there's skylight we are in the surface! */
|
||||
self->skylight = PyObject_GetAttrString(state->self, "skylight");
|
||||
self->left_skylight = PyObject_GetAttrString(state->self, "left_skylight");
|
||||
@@ -242,7 +249,7 @@ rendermode_cave_finish(void *data, RenderState *state) {
|
||||
|
||||
Py_DECREF(self->depth_colors);
|
||||
|
||||
rendermode_normal.finish(data, state);
|
||||
rendermode_lighting.finish(data, state);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -255,7 +262,11 @@ rendermode_cave_draw(void *data, RenderState *state, PyObject *src, PyObject *ma
|
||||
r = 0, g = 0, b = 0;
|
||||
|
||||
/* draw the normal block */
|
||||
rendermode_normal.draw(data, state, src, mask, mask_light);
|
||||
if (self->lighting) {
|
||||
rendermode_lighting.draw(data, state, src, mask, mask_light);
|
||||
} else {
|
||||
rendermode_normal.draw(data, state, src, mask, mask_light);
|
||||
}
|
||||
|
||||
if (self->depth_tinting) {
|
||||
/* get the colors and tint and tint */
|
||||
@@ -271,13 +282,14 @@ rendermode_cave_draw(void *data, RenderState *state, PyObject *src, PyObject *ma
|
||||
static RenderModeOption rendermode_cave_options[] = {
|
||||
{"depth_tinting", "tint caves based on how deep they are (default: True)"},
|
||||
{"only_lit", "only render lit caves (default: False)"},
|
||||
{"lighting", "render caves with lighting enabled (default: False)"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
RenderModeInterface rendermode_cave = {
|
||||
"cave", "render only caves in normal mode",
|
||||
"cave", "render only caves",
|
||||
rendermode_cave_options,
|
||||
&rendermode_normal,
|
||||
&rendermode_lighting,
|
||||
sizeof(RenderModeCave),
|
||||
rendermode_cave_start,
|
||||
rendermode_cave_finish,
|
||||
|
||||
@@ -83,12 +83,6 @@ get_lighting_coefficient(RenderModeLighting *self, RenderState *state,
|
||||
|
||||
block = getArrayByte3D(blocks, local_x, local_y, local_z);
|
||||
|
||||
/* if this block is opaque, use a fully-lit coeff instead
|
||||
to prevent stippled lines along chunk boundaries! */
|
||||
if (!is_transparent(block)) {
|
||||
return self->calculate_darkness(15, 0);
|
||||
}
|
||||
|
||||
/* only do special half-step handling if no authoratative pointer was
|
||||
passed in, which is a sign that we're recursing */
|
||||
if ((block == 44 || block == 53 || block == 67) && authoratative == NULL) {
|
||||
@@ -154,11 +148,14 @@ static inline void
|
||||
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
||||
int x, int y, int z, PyObject *mask) {
|
||||
float black_coeff;
|
||||
|
||||
PyObject *blocks;
|
||||
|
||||
/* first, check for occlusion if the block is in the local chunk */
|
||||
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
||||
unsigned char block = getArrayByte3D(state->blocks, x, y, z);
|
||||
if (!is_transparent(block)) {
|
||||
int occluded = render_mode_occluded(state->rendermode, x, y, z);
|
||||
|
||||
if (!occluded && !is_transparent(block)) {
|
||||
/* this face isn't visible, so don't draw anything */
|
||||
return;
|
||||
}
|
||||
@@ -230,9 +227,9 @@ rendermode_lighting_finish(void *data, RenderState *state) {
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_lighting_occluded(void *data, RenderState *state) {
|
||||
rendermode_lighting_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||
/* no special occlusion here */
|
||||
return rendermode_normal.occluded(data, state);
|
||||
return rendermode_normal.occluded(data, state, x, y, z);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -48,9 +48,9 @@ rendermode_night_finish(void *data, RenderState *state) {
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_night_occluded(void *data, RenderState *state) {
|
||||
rendermode_night_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||
/* no special occlusion here */
|
||||
return rendermode_lighting.occluded(data, state);
|
||||
return rendermode_lighting.occluded(data, state, x, y, z);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -144,9 +144,8 @@ rendermode_normal_finish(void *data, RenderState *state) {
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_normal_occluded(void *data, RenderState *state) {
|
||||
rendermode_normal_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||
RenderModeNormal *self = (RenderModeNormal *)data;
|
||||
int x = state->x, y = state->y, z = state->z;
|
||||
|
||||
if (z > self->max_depth || z < self->min_depth) {
|
||||
return 1;
|
||||
|
||||
@@ -57,9 +57,7 @@ rendermode_overlay_finish(void *data, RenderState *state) {
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_overlay_occluded(void *data, RenderState *state) {
|
||||
int x = state->x, y = state->y, z = state->z;
|
||||
|
||||
rendermode_overlay_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||
if ( (x != 0) && (y != 15) && (z != 127) &&
|
||||
!is_transparent(getArrayByte3D(state->blocks, x-1, y, z)) &&
|
||||
!is_transparent(getArrayByte3D(state->blocks, x, y, z+1)) &&
|
||||
|
||||
@@ -96,9 +96,9 @@ rendermode_spawn_finish(void *data, RenderState *state) {
|
||||
}
|
||||
|
||||
static int
|
||||
rendermode_spawn_occluded(void *data, RenderState *state) {
|
||||
rendermode_spawn_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||
/* no special occlusion here */
|
||||
return rendermode_overlay.occluded(data, state);
|
||||
return rendermode_overlay.occluded(data, state, x, y, z);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -164,8 +164,8 @@ void render_mode_destroy(RenderMode *self) {
|
||||
free(self);
|
||||
}
|
||||
|
||||
int render_mode_occluded(RenderMode *self) {
|
||||
return self->iface->occluded(self->mode, self->state);
|
||||
int render_mode_occluded(RenderMode *self, int x, int y, int z) {
|
||||
return self->iface->occluded(self->mode, self->state, x, y, z);
|
||||
}
|
||||
|
||||
void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light) {
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#define __RENDERMODES_H_INCLUDED__
|
||||
|
||||
#include <Python.h>
|
||||
#include "overviewer.h"
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -62,22 +63,22 @@ struct _RenderModeInterface {
|
||||
int (*start)(void *, RenderState *, PyObject *);
|
||||
void (*finish)(void *, RenderState *);
|
||||
/* returns non-zero to skip rendering this block */
|
||||
int (*occluded)(void *, RenderState *);
|
||||
int (*occluded)(void *, RenderState *, int, int, int);
|
||||
/* last two arguments are img and mask, from texture lookup */
|
||||
void (*draw)(void *, RenderState *, PyObject *, PyObject *, PyObject *);
|
||||
};
|
||||
|
||||
/* wrapper for passing around rendermodes */
|
||||
typedef struct {
|
||||
struct _RenderMode {
|
||||
void *mode;
|
||||
RenderModeInterface *iface;
|
||||
RenderState *state;
|
||||
} RenderMode;
|
||||
};
|
||||
|
||||
/* functions for creating / using rendermodes */
|
||||
RenderMode *render_mode_create(const char *mode, RenderState *state);
|
||||
void render_mode_destroy(RenderMode *self);
|
||||
int render_mode_occluded(RenderMode *self);
|
||||
int render_mode_occluded(RenderMode *self, int x, int y, int z);
|
||||
void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject *mask_light);
|
||||
|
||||
/* python metadata bindings */
|
||||
@@ -167,7 +168,7 @@ extern RenderModeInterface rendermode_spawn;
|
||||
/* CAVE */
|
||||
typedef struct {
|
||||
/* render blocks with lighting mode */
|
||||
RenderModeNormal parent;
|
||||
RenderModeLighting parent;
|
||||
|
||||
/* data used to know where the surface is */
|
||||
PyObject *skylight;
|
||||
@@ -188,6 +189,7 @@ typedef struct {
|
||||
|
||||
int depth_tinting;
|
||||
int only_lit;
|
||||
int lighting;
|
||||
} RenderModeCave;
|
||||
extern RenderModeInterface rendermode_cave;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user