0

broke out nether, heightfading, depth, and edgelines from base primitive

This commit is contained in:
Aaron Griffith
2012-01-08 00:03:31 -05:00
parent e3610f8ac5
commit a682b8a689
8 changed files with 317 additions and 146 deletions

View File

@@ -30,15 +30,30 @@ class RenderPrimitive(object):
self.option_values[key] = val
class Base(RenderPrimitive):
options = {
"edge_opacity": "darkness of the edge lines, from 0.0 to 1.0 (default: 0.15)",
"min_depth": "lowest level of blocks to render (default: 0)",
"max_depth": "highest level of blocks to render (default: 127)",
"height_fading": "darken or lighten blocks based on height (default: False)",
"nether": "if True, remove the roof of the map. Useful on nether maps. (defualt: False)",
}
name = "base"
class Nether(RenderPrimitive):
name = "nether"
class HeightFading(RenderPrimitive):
name = "height-fading"
black_color = Image.new("RGB", (24,24), (0,0,0))
white_color = Image.new("RGB", (24,24), (255,255,255))
class Depth(RenderPrimitive):
name = "depth"
options = {
"min": "lowest level of blocks to render (default: 0)",
"max": "highest level of blocks to render (default: 127)",
}
class EdgeLines(RenderPrimitive):
name = "edge-lines"
options = {
"opacity": "darkness of the edge lines, from 0.0 to 1.0 (default: 0.15)",
}
# Render 3 blending masks for lighting
# first is top (+Z), second is left (-X), third is right (+Y)
def generate_facemasks():
@@ -70,8 +85,6 @@ def generate_facemasks():
return (top, left, right)
facemasks = generate_facemasks()
black_color = Image.new("RGB", (24,24), (0,0,0))
white_color = Image.new("RGB", (24,24), (255,255,255))
# Render 128 different color images for color coded depth blending in cave mode
def generate_depthcolors():

View File

@@ -26,49 +26,12 @@ typedef struct {
PyObject *grasscolor, *foliagecolor, *watercolor;
/* biome-compatible grass/leaf textures */
PyObject *grass_texture;
/* black and white colors for height fading */
PyObject *black_color, *white_color;
float edge_opacity;
unsigned int min_depth;
unsigned int max_depth;
int height_fading;
int nether;
} PrimitiveBase;
static int
base_start(void *data, RenderState *state, PyObject *support) {
PrimitiveBase *self = (PrimitiveBase *)data;
/* load up the given options, first */
self->edge_opacity = 0.15;
if (!render_mode_parse_option(support, "edge_opacity", "f", &(self->edge_opacity)))
return 1;
self->min_depth = 0;
if (!render_mode_parse_option(support, "min_depth", "I", &(self->min_depth)))
return 1;
self->max_depth = 127;
if (!render_mode_parse_option(support, "max_depth", "I", &(self->max_depth)))
return 1;
self->height_fading = 0;
/* XXX skip height fading */
/*if (!render_mode_parse_option(support, "height_fading", "i", &(self->height_fading)))
return 1;*/
self->nether = 0;
if (!render_mode_parse_option(support, "nether", "i", &(self->nether)))
return 1;
/*if (self->height_fading) {
self->black_color = PyObject_GetAttrString(state->chunk, "black_color");
self->white_color = PyObject_GetAttrString(state->chunk, "white_color");
}*/
/* biome-compliant grass mask (includes sides!) */
self->grass_texture = PyObject_GetAttrString(state->textures, "biome_grass_texture");
@@ -123,8 +86,6 @@ base_finish(void *data, RenderState *state) {
Py_XDECREF(self->grasscolor);
Py_XDECREF(self->watercolor);
Py_XDECREF(self->grass_texture);
Py_XDECREF(self->black_color);
Py_XDECREF(self->white_color);
}
static int
@@ -146,30 +107,6 @@ static int
base_hidden(void *data, RenderState *state, int x, int y, int z) {
PrimitiveBase *self = (PrimitiveBase *)data;
if (z > self->max_depth || z < self->min_depth) {
return 1;
}
if (self->nether)
{
/* hide all blocks above all air blocks */
int below_air = 0;
while (z < 128)
{
if (getArrayByte3D(state->blocks, x, y, z) == 0)
{
below_air = 1;
break;
}
z++;
}
if (!below_air)
return 1;
}
return 0;
}
@@ -319,65 +256,6 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec
if (facemask)
tint_with_mask(state->img, r, g, b, 255, facemask, state->imgx, state->imgy, 0, 0);
}
if (self->height_fading) {
/* do some height fading */
PyObject *height_color = self->white_color;
/* negative alpha => darkness, positive => light */
float alpha = (1.0 / (1 + expf((70 - state->z) / 11.0))) * 0.6 - 0.55;
if (alpha < 0.0) {
alpha *= -1;
height_color = self->black_color;
}
alpha_over_full(state->img, height_color, mask_light, alpha, state->imgx, state->imgy, 0, 0);
}
/* Draw some edge lines! */
// draw.line(((imgx+12,imgy+increment), (imgx+22,imgy+5+increment)), fill=(0,0,0), width=1)
if (state->block == 44 || state->block == 78 || !is_transparent(state->block)) {
Imaging img_i = imaging_python_to_c(state->img);
unsigned char ink[] = {0, 0, 0, 255 * self->edge_opacity};
int increment=0;
if (state->block == 44) // half-step
increment=6;
else if ((state->block == 78) || (state->block == 93) || (state->block == 94)) // snow, redstone repeaters (on and off)
increment=9;
if ((state->x == 15) && (state->up_right_blocks != Py_None)) {
unsigned char side_block = getArrayByte3D(state->up_right_blocks, 0, state->y, state->z);
if (side_block != state->block && is_transparent(side_block)) {
ImagingDrawLine(img_i, state->imgx+12, state->imgy+1+increment, state->imgx+22+1, state->imgy+5+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx+12, state->imgy+increment, state->imgx+22+1, state->imgy+5+increment, &ink, 1);
}
} else if (state->x != 15) {
unsigned char side_block = getArrayByte3D(state->blocks, state->x+1, state->y, state->z);
if (side_block != state->block && is_transparent(side_block)) {
ImagingDrawLine(img_i, state->imgx+12, state->imgy+1+increment, state->imgx+22+1, state->imgy+5+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx+12, state->imgy+increment, state->imgx+22+1, state->imgy+5+increment, &ink, 1);
}
}
// if y != 0 and blocks[x,y-1,z] == 0
// chunk boundries are annoying
if ((state->y == 0) && (state->up_left_blocks != Py_None)) {
unsigned char side_block = getArrayByte3D(state->up_left_blocks, state->x, 15, state->z);
if (side_block != state->block && is_transparent(side_block)) {
ImagingDrawLine(img_i, state->imgx, state->imgy+6+1+increment, state->imgx+12+1, state->imgy+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx, state->imgy+6+increment, state->imgx+12+1, state->imgy+increment, &ink, 1);
}
} else if (state->y != 0) {
unsigned char side_block = getArrayByte3D(state->blocks, state->x, state->y-1, state->z);
if (side_block != state->block && is_transparent(side_block)) {
// draw.line(((imgx,imgy+6+increment), (imgx+12,imgy+increment)), fill=(0,0,0), width=1)
ImagingDrawLine(img_i, state->imgx, state->imgy+6+1+increment, state->imgx+12+1, state->imgy+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx, state->imgy+6+increment, state->imgx+12+1, state->imgy+increment, &ink, 1);
}
}
}
}
RenderPrimitiveInterface primitive_base = {

View File

@@ -0,0 +1,56 @@
/*
* This file is part of the Minecraft Overviewer.
*
* Minecraft Overviewer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Minecraft Overviewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../overviewer.h"
typedef struct {
unsigned int min;
unsigned int max;
} PrimitiveDepth;
static int
depth_start(void *data, RenderState *state, PyObject *support) {
PrimitiveDepth *self = (PrimitiveDepth *)data;
self->min = 0;
if (!render_mode_parse_option(support, "min", "I", &(self->min)))
return 1;
self->max = 127;
if (!render_mode_parse_option(support, "max", "I", &(self->max)))
return 1;
return 0;
}
static int
depth_hidden(void *data, RenderState *state, int x, int y, int z) {
PrimitiveDepth *self = (PrimitiveDepth *)data;
if (z > self->max || z < self->min) {
return 1;
}
return 0;
}
RenderPrimitiveInterface primitive_depth = {
"depth", sizeof(PrimitiveDepth),
depth_start,
NULL,
NULL,
depth_hidden,
NULL,
};

View File

@@ -0,0 +1,90 @@
/*
* This file is part of the Minecraft Overviewer.
*
* Minecraft Overviewer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Minecraft Overviewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../overviewer.h"
typedef struct {
float opacity;
} PrimitiveEdgeLines;
static int
edge_lines_start(void *data, RenderState *state, PyObject *support) {
PrimitiveEdgeLines *self = (PrimitiveEdgeLines *)data;
self->opacity = 0.15;
if (!render_mode_parse_option(support, "opacity", "f", &(self->opacity)))
return 1;
return 0;
}
static void
edge_lines_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
PrimitiveEdgeLines *self = (PrimitiveEdgeLines *)data;
/* Draw some edge lines! */
// draw.line(((imgx+12,imgy+increment), (imgx+22,imgy+5+increment)), fill=(0,0,0), width=1)
if (state->block == 44 || state->block == 78 || !is_transparent(state->block)) {
Imaging img_i = imaging_python_to_c(state->img);
unsigned char ink[] = {0, 0, 0, 255 * self->opacity};
int increment=0;
if (state->block == 44) // half-step
increment=6;
else if ((state->block == 78) || (state->block == 93) || (state->block == 94)) // snow, redstone repeaters (on and off)
increment=9;
if ((state->x == 15) && (state->up_right_blocks != Py_None)) {
unsigned char side_block = getArrayByte3D(state->up_right_blocks, 0, state->y, state->z);
if (side_block != state->block && is_transparent(side_block)) {
ImagingDrawLine(img_i, state->imgx+12, state->imgy+1+increment, state->imgx+22+1, state->imgy+5+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx+12, state->imgy+increment, state->imgx+22+1, state->imgy+5+increment, &ink, 1);
}
} else if (state->x != 15) {
unsigned char side_block = getArrayByte3D(state->blocks, state->x+1, state->y, state->z);
if (side_block != state->block && is_transparent(side_block)) {
ImagingDrawLine(img_i, state->imgx+12, state->imgy+1+increment, state->imgx+22+1, state->imgy+5+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx+12, state->imgy+increment, state->imgx+22+1, state->imgy+5+increment, &ink, 1);
}
}
// if y != 0 and blocks[x,y-1,z] == 0
// chunk boundries are annoying
if ((state->y == 0) && (state->up_left_blocks != Py_None)) {
unsigned char side_block = getArrayByte3D(state->up_left_blocks, state->x, 15, state->z);
if (side_block != state->block && is_transparent(side_block)) {
ImagingDrawLine(img_i, state->imgx, state->imgy+6+1+increment, state->imgx+12+1, state->imgy+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx, state->imgy+6+increment, state->imgx+12+1, state->imgy+increment, &ink, 1);
}
} else if (state->y != 0) {
unsigned char side_block = getArrayByte3D(state->blocks, state->x, state->y-1, state->z);
if (side_block != state->block && is_transparent(side_block)) {
// draw.line(((imgx,imgy+6+increment), (imgx+12,imgy+increment)), fill=(0,0,0), width=1)
ImagingDrawLine(img_i, state->imgx, state->imgy+6+1+increment, state->imgx+12+1, state->imgy+1+increment, &ink, 1);
ImagingDrawLine(img_i, state->imgx, state->imgy+6+increment, state->imgx+12+1, state->imgy+increment, &ink, 1);
}
}
}
}
RenderPrimitiveInterface primitive_edge_lines = {
"edge-lines", sizeof(PrimitiveEdgeLines),
edge_lines_start,
NULL,
NULL,
NULL,
edge_lines_draw,
};

View File

@@ -0,0 +1,68 @@
/*
* This file is part of the Minecraft Overviewer.
*
* Minecraft Overviewer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Minecraft Overviewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../overviewer.h"
typedef struct {
PyObject *black_color;
PyObject *white_color;
} PrimitiveHeightFading;
static int
height_fading_start(void *data, RenderState *state, PyObject *support) {
PrimitiveHeightFading *self = (PrimitiveHeightFading *)data;
self->black_color = PyObject_GetAttrString(support, "black_color");
self->white_color = PyObject_GetAttrString(support, "white_color");
return 0;
}
static void
height_fading_finish(void *data, RenderState *state) {
PrimitiveHeightFading *self = (PrimitiveHeightFading *)data;
Py_DECREF(self->black_color);
Py_DECREF(self->white_color);
}
static void
height_fading_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
PrimitiveHeightFading *self = (PrimitiveHeightFading *)data;
/* do some height fading */
PyObject *height_color = self->white_color;
/* negative alpha => darkness, positive => light */
float alpha = (1.0 / (1 + expf((70 - state->z) / 11.0))) * 0.6 - 0.55;
if (alpha < 0.0) {
alpha *= -1;
height_color = self->black_color;
}
alpha_over_full(state->img, height_color, mask_light, alpha, state->imgx, state->imgy, 0, 0);
}
RenderPrimitiveInterface primitive_height_fading = {
"height-fading", sizeof(PrimitiveHeightFading),
height_fading_start,
height_fading_finish,
NULL,
NULL,
height_fading_draw,
};

View File

@@ -0,0 +1,42 @@
/*
* This file is part of the Minecraft Overviewer.
*
* Minecraft Overviewer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Minecraft Overviewer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "../overviewer.h"
static int
nether_hidden(void *data, RenderState *state, int x, int y, int z) {
/* hide all blocks above all air blocks */
while (z < 128)
{
if (getArrayByte3D(state->blocks, x, y, z) == 0)
{
return 0;
break;
}
z++;
}
return 1;
}
RenderPrimitiveInterface primitive_nether = {
"nether", 0,
NULL,
NULL,
NULL,
nether_hidden,
NULL,
};

View File

@@ -20,12 +20,20 @@
#include <stdarg.h>
extern RenderPrimitiveInterface primitive_base;
extern RenderPrimitiveInterface primitive_nether;
extern RenderPrimitiveInterface primitive_height_fading;
extern RenderPrimitiveInterface primitive_depth;
extern RenderPrimitiveInterface primitive_edge_lines;
/* list of all render primitives, ending in NULL
all of these will be available to the user, so DON'T include primitives
that are only useful as a base for other primitives. */
static RenderPrimitiveInterface *render_primitives[] = {
&primitive_base,
&primitive_nether,
&primitive_height_fading,
&primitive_depth,
&primitive_edge_lines,
//&rendermode_lighting,
//&rendermode_smooth_lighting,
//&rendermode_cave,
@@ -59,25 +67,29 @@ RenderPrimitive *render_primitive_create(PyObject *prim, RenderState *state) {
Py_DECREF(pyname);
if (iface == NULL)
return NULL;
return (RenderPrimitive *)PyErr_Format(PyExc_RuntimeError, "invalid primitive name: %s", name);
ret = calloc(1, sizeof(RenderPrimitive));
if (ret == NULL) {
return (RenderPrimitive *)PyErr_Format(PyExc_RuntimeError, "Failed to alloc a render primitive");
}
ret->primitive = calloc(1, iface->data_size);
if (ret->primitive == NULL) {
free(ret);
return (RenderPrimitive *)PyErr_Format(PyExc_RuntimeError, "Failed to alloc render primitive data");
if (iface->data_size > 0) {
ret->primitive = calloc(1, iface->data_size);
if (ret->primitive == NULL) {
free(ret);
return (RenderPrimitive *)PyErr_Format(PyExc_RuntimeError, "Failed to alloc render primitive data");
}
}
ret->iface = iface;
if (iface->start(ret->primitive, state, prim)) {
free(ret->primitive);
free(ret);
return NULL;
if (iface->start) {
if (iface->start(ret->primitive, state, prim)) {
free(ret->primitive);
free(ret);
return NULL;
}
}
return ret;
@@ -120,8 +132,12 @@ void render_mode_destroy(RenderMode *self) {
/* we may be destroying a half-constructed mode, so we need this
check */
if (prim) {
prim->iface->finish(prim->primitive, self->state);
free(prim->primitive);
if (prim->iface->finish) {
prim->iface->finish(prim->primitive, self->state);
}
if (prim->primitive) {
free(prim->primitive);
}
free(prim);
}
}
@@ -134,7 +150,10 @@ int render_mode_occluded(RenderMode *self, int x, int y, int z) {
int occluded = 0;
for (i = 0; i < self->num_primitives; i++) {
RenderPrimitive *prim = self->primitives[i];
occluded |= prim->iface->occluded(prim->primitive, self->state, x, y, z);
if (prim->iface->occluded) {
occluded |= prim->iface->occluded(prim->primitive, self->state, x, y, z);
}
if (occluded)
return occluded;
}
@@ -146,7 +165,10 @@ int render_mode_hidden(RenderMode *self, int x, int y, int z) {
int hidden = 0;
for (i = 0; i < self->num_primitives; i++) {
RenderPrimitive *prim = self->primitives[i];
hidden |= prim->iface->hidden(prim->primitive, self->state, x, y, z);
if (prim->iface->hidden) {
hidden |= prim->iface->hidden(prim->primitive, self->state, x, y, z);
}
if (hidden)
return hidden;
}
@@ -157,7 +179,9 @@ void render_mode_draw(RenderMode *self, PyObject *img, PyObject *mask, PyObject
unsigned int i;
for (i = 0; i < self->num_primitives; i++) {
RenderPrimitive *prim = self->primitives[i];
prim->iface->draw(prim->primitive, self->state, img, mask, mask_light);
if (prim->iface->draw) {
prim->iface->draw(prim->primitive, self->state, img, mask, mask_light);
}
}
}

View File

@@ -151,7 +151,7 @@ except Exception:
# used to figure out what files to compile
#render_modes = ['normal', 'lighting', 'smooth-lighting', 'cave']
#render_modes += ['overlay', 'spawn', 'mineral']
primitives = ['base',]
primitives = ['base', 'nether', 'height-fading', 'depth', 'edge-lines']
c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c']
c_overviewer_files += map(lambda mode: 'primitives/%s.c' % (mode,), primitives)