From 93424c296d1b608ea8dd98613aa840aa8c72e8f1 Mon Sep 17 00:00:00 2001 From: Aaron Griffith Date: Fri, 13 May 2011 12:30:13 -0400 Subject: [PATCH] textures are now only generated when actual *rendering* is done --- rendernode.py | 14 ++++++++++++-- src/iterate.c | 42 ++++++++++++++++++++---------------------- src/main.c | 8 ++------ src/overviewer.h | 4 ++-- textures.py | 43 +++++++++++++++++++++++++++---------------- 5 files changed, 63 insertions(+), 48 deletions(-) diff --git a/rendernode.py b/rendernode.py index 9dce5cc..f99c087 100644 --- a/rendernode.py +++ b/rendernode.py @@ -26,6 +26,8 @@ import collections import json import logging import util +import textures +import c_overviewer import cPickle import stat import errno @@ -59,14 +61,22 @@ def pool_initializer(rendernode): logging.debug("Child process {0}".format(os.getpid())) #stash the quadtree objects in a global variable after fork() for windows compat. global child_rendernode - child_rendernode = rendernode + child_rendernode = rendernode + + # make sure textures are generated for this process + # and initialize c_overviewer + textures.generate() + c_overviewer.init_chunk_render() + + # load biome data in each process, if needed for quadtree in rendernode.quadtrees: if quadtree.world.useBiomeData: - import textures # make sure we've at least *tried* to load the color arrays in this process... textures.prepareBiomeData(quadtree.world.worlddir) if not textures.grasscolor or not textures.foliagecolor: raise Exception("Can't find grasscolor.png or foliagecolor.png") + # only load biome data once + break #http://docs.python.org/library/itertools.html def roundrobin(iterables): diff --git a/src/iterate.c b/src/iterate.c index 9f9be9a..b55e3df 100644 --- a/src/iterate.c +++ b/src/iterate.c @@ -24,43 +24,41 @@ static PyObject *special_blocks = NULL; static PyObject *specialblockmap = NULL; static PyObject *transparent_blocks = NULL; -int init_chunk_render(void) { +PyObject *init_chunk_render(PyObject *self, PyObject *args) { - /* if blockmap (or any of these) is not NULL, then that means that we've - * somehow called this function twice. error out so we can notice this - * */ - if (blockmap) return 1; + /* this function only needs to be called once, anything more is an + * error... */ + if (blockmap) { + PyErr_SetString(PyExc_RuntimeError, "init_chunk_render should only be called once per process."); + return NULL; + } textures = PyImport_ImportModule("textures"); /* ensure none of these pointers are NULL */ if ((!textures)) { - fprintf(stderr, "\ninit_chunk_render failed to load; textures\n"); - PyErr_Print(); - return 1; + return NULL; } chunk_mod = PyImport_ImportModule("chunk"); /* ensure none of these pointers are NULL */ if ((!chunk_mod)) { - fprintf(stderr, "\ninit_chunk_render failed to load; chunk\n"); - PyErr_Print(); - return 1; + return NULL; } blockmap = PyObject_GetAttrString(textures, "blockmap"); + if (!blockmap) + return NULL; special_blocks = PyObject_GetAttrString(textures, "special_blocks"); + if (!special_blocks) + return NULL; specialblockmap = PyObject_GetAttrString(textures, "specialblockmap"); + if (!specialblockmap) + return NULL; transparent_blocks = PyObject_GetAttrString(chunk_mod, "transparent_blocks"); + if (!transparent_blocks) + return NULL; - /* ensure none of these pointers are NULL */ - if ((!transparent_blocks) || (!blockmap) || (!special_blocks) || (!specialblockmap)) { - fprintf(stderr, "\ninit_chunk_render failed\n"); - PyErr_Print(); - return 1; - } - - return 0; - + Py_RETURN_NONE; } int @@ -310,7 +308,7 @@ chunk_render(PyObject *self, PyObject *args) { PyObject *t = NULL; if (!PyArg_ParseTuple(args, "OOiiO", &state.self, &state.img, &xoff, &yoff, &blockdata_expanded)) - return Py_BuildValue("i", "-1"); + return NULL; /* fill in important modules */ state.textures = textures; @@ -435,7 +433,7 @@ chunk_render(PyObject *self, PyObject *args) { blockid = NULL; } } - } + } /* free up the rendermode info */ rendermode->finish(rm_data, &state); diff --git a/src/main.c b/src/main.c index 4de7eec..19d3612 100644 --- a/src/main.c +++ b/src/main.c @@ -26,6 +26,8 @@ static PyMethodDef COverviewerMethods[] = { {"alpha_over", alpha_over_wrap, METH_VARARGS, "alpha over composite function"}, + {"init_chunk_render", init_chunk_render, METH_VARARGS, + "Initializes the stuffs renderer."}, {"render_loop", chunk_render, METH_VARARGS, "Renders stuffs"}, @@ -53,12 +55,6 @@ initc_overviewer(void) (void)Py_InitModule("c_overviewer", COverviewerMethods); /* for numpy */ import_array(); - - /* initialize some required variables in iterage.c */ - if (init_chunk_render()) { - fprintf(stderr, "failed to init_chunk_render\n"); - exit(1); // TODO better way to indicate error? - } init_endian(); } diff --git a/src/overviewer.h b/src/overviewer.h index 55243a5..5ee89dc 100644 --- a/src/overviewer.h +++ b/src/overviewer.h @@ -26,7 +26,7 @@ // increment this value if you've made a change to the c extesion // and want to force users to rebuild -#define OVERVIEWER_EXTENSION_VERSION 5 +#define OVERVIEWER_EXTENSION_VERSION 6 /* Python PIL, and numpy headers */ #include @@ -76,7 +76,7 @@ typedef struct { PyObject *left_blocks; PyObject *right_blocks; } RenderState; -int init_chunk_render(void); +PyObject *init_chunk_render(PyObject *self, PyObject *args); int is_transparent(unsigned char b); PyObject *chunk_render(PyObject *self, PyObject *args); diff --git a/textures.py b/textures.py index b740420..8a63d3c 100644 --- a/textures.py +++ b/textures.py @@ -112,9 +112,6 @@ def _split_terrain(terrain): return textures -# This maps terainids to 16x16 images -terrain_images = _split_terrain(_get_terrain_image()) - def transform_image(img, blockID=None): """Takes a PIL image and rotates it left 45 degrees and shrinks the y axis by a factor of 2. Returns the resulting image, which will be 24x12 pixels @@ -460,7 +457,6 @@ def _build_blockimages(): while len(allimages) < 256: allimages.append(None) return allimages -blockmap = _build_blockimages() def load_water(): """Evidentially, the water and lava textures are not loaded from any files @@ -482,8 +478,6 @@ def load_water(): lavablock = _build_block(lavatexture, lavatexture) blockmap[10] = lavablock.convert("RGB"), lavablock blockmap[11] = blockmap[10] -load_water() - def generate_special_texture(blockID, data): """Generates a special texture, such as a correctly facing minecraft track""" @@ -1541,11 +1535,6 @@ def tintTexture(im, c): i.putalpha(im.split()[3]); # copy the alpha band back in. assuming RGBA return i -# generate biome (still grayscale) leaf, grass textures -biome_grass_texture = _build_block(terrain_images[0], terrain_images[38], 2) -biome_leaf_texture = _build_block(terrain_images[52], terrain_images[52], 18) - - currentBiomeFile = None currentBiomeData = None grasscolor = None @@ -1665,9 +1654,31 @@ special_map[2] = range(11) + [0x10,] # grass, grass has not ancildata but is # and is harmless for normal maps special_map[18] = range(16) # leaves, birch, normal or pine leaves (not implemented) +# placeholders that are generated in generate() +terrain_images = None +blockmap = None +biome_grass_texture = None +biome_leaf_texture = None +specialblockmap = None -specialblockmap = {} - -for blockID in special_blocks: - for data in special_map[blockID]: - specialblockmap[(blockID, data)] = generate_special_texture(blockID, data) +def generate(): + # This maps terainids to 16x16 images + global terrain_images + terrain_images = _split_terrain(_get_terrain_image()) + + # generate the normal blocks + global blockmap + blockmap = _build_blockimages() + load_water() + + # generate biome (still grayscale) leaf, grass textures + global biome_grass_texture, biome_leaf_texture + biome_grass_texture = _build_block(terrain_images[0], terrain_images[38], 2) + biome_leaf_texture = _build_block(terrain_images[52], terrain_images[52], 18) + + # generate the special blocks + global specialblockmap, special_blocks + specialblockmap = {} + for blockID in special_blocks: + for data in special_map[blockID]: + specialblockmap[(blockID, data)] = generate_special_texture(blockID, data)