0

biomes now work, still no swamp purple though

This commit is contained in:
Aaron Griffith
2012-02-22 04:14:44 -05:00
parent 4ac7c1222a
commit 414b754e24
4 changed files with 159 additions and 176 deletions

View File

@@ -18,30 +18,68 @@
#include "../overviewer.h"
typedef struct {
/* biome data for the chunk */
PyObject *biome_data;
/* grasscolor and foliagecolor lookup tables */
PyObject *grasscolor, *foliagecolor, *watercolor;
/* biome-compatible grass/leaf textures */
PyObject *grass_texture;
} PrimitiveBase;
typedef struct {
const char* name;
float temperature;
float rainfall;
} Biome;
/* each entry in this table is yanked *directly* out of the minecraft source
* temp/rainfall are taken from what MCP calls setTemperatureRainfall
*
* keep in mind the x/y coordinate in the color tables is found *after*
* multiplying rainfall and temperature for the second coordinate, *and* the
* origin is in the lower-right. <3 biomes.
*/
static Biome biome_table[] = {
/* 0 */
{"Ocean", 0.5, 0.5},
{"Plains", 0.8, 0.4},
{"Desert", 2.0, 0.0},
{"Extreme Hills", 0.2, 0.3},
{"Forest", 0.7, 0.8},
/* 5 */
{"Taiga", 0.05, 0.8},
{"Swampland", 0.8, 0.9},
{"River", 0.5, 0.5},
{"Hell", 2.0, 0.0},
{"Sky", 0.5, 0.5},
/* 10 */
{"FrozenOcean", 0.0, 0.5},
{"FrozenRiver", 0.0, 0.5},
{"Ice Plains", 0.0, 0.5},
{"Ice Mountains", 0.0, 0.5},
{"MushroomIsland", 0.9, 1.0},
/* 15 */
{"MushroomIslandShore", 0.9, 1.0},
{"Beach", 0.8, 0.4},
{"DesertHills", 2.0, 0.0},
{"ForestHills", 0.7, 0.8},
{"TaigaHills", 0.05, 0.8},
/* 20 */
{"Extreme Hills Edge", 0.2, 0.3},
{"Jungle", 2.0, 0.45}, /* <-- GUESS, but a good one */
};
#define NUM_BIOMES (sizeof(biome_table) / sizeof(Biome))
static int
base_start(void *data, RenderState *state, PyObject *support) {
PrimitiveBase *self = (PrimitiveBase *)data;
/* biome-compliant grass mask (includes sides!) */
self->grass_texture = PyObject_GetAttrString(state->textures, "biome_grass_texture");
self->biome_data = PyObject_CallMethod(state->regionset, "get_biome_data", "ii", state->chunkx, state->chunkz);
if (self->biome_data == NULL) {
/* error while loading biome info, or no biomes at all */
PyErr_Clear();
} else {
self->foliagecolor = PyObject_CallMethod(state->textures, "load_foliage_color", "");
self->grasscolor = PyObject_CallMethod(state->textures, "load_grass_color", "");
self->watercolor = PyObject_CallMethod(state->textures, "load_water_color", "");
}
/* color lookup tables */
self->foliagecolor = PyObject_CallMethod(state->textures, "load_foliage_color", "");
self->grasscolor = PyObject_CallMethod(state->textures, "load_grass_color", "");
self->watercolor = PyObject_CallMethod(state->textures, "load_water_color", "");
return 0;
}
@@ -50,11 +88,10 @@ static void
base_finish(void *data, RenderState *state) {
PrimitiveBase *self = (PrimitiveBase *)data;
Py_XDECREF(self->biome_data);
Py_XDECREF(self->foliagecolor);
Py_XDECREF(self->grasscolor);
Py_XDECREF(self->watercolor);
Py_XDECREF(self->grass_texture);
Py_DECREF(self->foliagecolor);
Py_DECREF(self->grasscolor);
Py_DECREF(self->watercolor);
Py_DECREF(self->grass_texture);
}
static int
@@ -72,13 +109,6 @@ base_occluded(void *data, RenderState *state, int x, int y, int z) {
return 0;
}
static int
base_hidden(void *data, RenderState *state, int x, int y, int z) {
PrimitiveBase *self = (PrimitiveBase *)data;
return 0;
}
static void
base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
PrimitiveBase *self = (PrimitiveBase *)data;
@@ -91,9 +121,8 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec
* NOTES for maintainers:
*
* To add a biome-compatible block, add an OR'd condition to this
* following if block, a case to the first switch statement to handle when
* biome info IS available, and another case to the second switch
* statement for when biome info ISN'T available.
* following if block, and a case to the switch statement to handle biome
* coloring.
*
* Make sure that in textures.py, the generated textures are the
* biome-compliant ones! The tinting is now all done here.
@@ -116,113 +145,102 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec
{
/* do the biome stuff! */
PyObject *facemask = mask;
unsigned char r, g, b;
unsigned char r = 255, g = 255, b = 255;
PyObject *color_table = NULL;
unsigned char flip_xy = 0;
if (state->block == 2) {
/* grass needs a special facemask */
facemask = self->grass_texture;
}
if (self->biome_data) {
/* we have data, so use it! */
unsigned int index;
switch (state->block) {
case 2:
/* grass */
color_table = self->grasscolor;
break;
case 8:
case 9:
/* water */
color_table = self->watercolor;
break;
case 18:
/* leaves */
color_table = self->foliagecolor;
if (state->block_data == 2)
{
/* birch!
birch foliage color is flipped XY-ways */
flip_xy = 1;
}
break;
case 31:
/* tall grass */
color_table = self->grasscolor;
break;
case 104:
/* pumpkin stem */
color_table = self->grasscolor;
break;
case 105:
/* melon stem */
color_table = self->grasscolor;
break;
case 106:
/* vines */
color_table = self->grasscolor;
break;
case 111:
/* lily pads */
color_table = self->grasscolor;
break;
default:
break;
};
if (color_table) {
int dx, dz;
unsigned char tablex, tabley;
float temp = 0.0, rain = 0.0;
PyObject *color = NULL;
index = big_endian_ushort(getArrayShort2D(self->biome_data, state->x, state->y));
switch (state->block) {
case 2:
/* grass */
color = PySequence_GetItem(self->grasscolor, index);
break;
case 8:
case 9:
/* water */
if (self->watercolor)
{
color = PySequence_GetItem(self->watercolor, index);
} else {
color = NULL;
facemask = NULL;
}
break;
case 18:
/* leaves */
if (state->block_data != 2)
{
/* not birch! */
color = PySequence_GetItem(self->foliagecolor, index);
} else {
/* birch!
birch foliage color is flipped XY-ways */
unsigned int index_x = 255 - (index % 256);
unsigned int index_y = 255 - (index / 256);
index = index_y * 256 + index_x;
/* average over all neighbors */
for (dx = -1; dx <= 1; dx++) {
for (dz = -1; dz <= 1; dz += (dx == 0 ? 2 : 1)) {
unsigned char biome = get_data(state, BIOMES, state->x + dx, state->y, state->z + dz);
if (biome > NUM_BIOMES)
biome = 0;
color = PySequence_GetItem(self->foliagecolor, index);
temp += biome_table[biome].temperature;
rain += biome_table[biome].rainfall;
}
break;
case 31:
/* tall grass */
color = PySequence_GetItem(self->grasscolor, index);
break;
case 104:
/* pumpkin stem */
color = PySequence_GetItem(self->grasscolor, index);
break;
case 105:
/* melon stem */
color = PySequence_GetItem(self->grasscolor, index);
break;
case 106:
/* vines */
color = PySequence_GetItem(self->grasscolor, index);
break;
case 111:
/* lily pads */
color = PySequence_GetItem(self->grasscolor, index);
break;
default:
break;
};
if (color)
{
/* we've got work to do */
r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
Py_DECREF(color);
}
} else {
if (state->block == 2 || state->block == 31 ||
state->block == 104 || state->block == 105)
/* grass and pumpkin/melon stems */
{
r = 115;
g = 175;
b = 71;
temp /= 8.0;
rain /= 8.0;
/* make sure they're sane */
temp = CLAMP(temp, 0.0, 1.0);
rain = CLAMP(rain, 0.0, 1.0);
/* convert to x/y coordinates in color table */
tablex = 255 - (255 * temp);
tabley = 255 - (255 * temp * rain);
if (flip_xy) {
unsigned char tmp = 255 - tablex;
tablex = 255 - tabley;
tabley = tmp;
}
if (state->block == 8 || state->block == 9)
/* water */
{
/* by default water is fine with nothing */
facemask = NULL;
}
if (state->block == 18 || state->block == 106 || state->block == 111)
/* leaves, vines and lyli pads */
{
r = 37;
g = 118;
b = 25;
}
/* look up color! */
color = PySequence_GetItem(color_table, tabley * 256 + tablex);
r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
Py_DECREF(color);
}
if (facemask)
tint_with_mask(state->img, r, g, b, 255, facemask, state->imgx, state->imgy, 0, 0);
/* final coloration */
tint_with_mask(state->img, r, g, b, 255, facemask, state->imgx, state->imgy, 0, 0);
}
}
@@ -231,6 +249,6 @@ RenderPrimitiveInterface primitive_base = {
base_start,
base_finish,
base_occluded,
base_hidden,
NULL,
base_draw,
};