/* shades the drawn block with the given facemask/black_color, based on the
   lighting results from (x, y, z) */
static inline void
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
                     int x, int y, int z, PyObject *mask) {
    float black_coeff;

    /* 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)) {
            /* this face isn't visible, so don't draw anything */
            return;
        }
    }
    
    black_coeff = get_lighting_coefficient(self, state, x, y, z, NULL);
    alpha_over_full(state->img, self->black_color, mask, black_coeff, state->imgx, state->imgy, 0, 0);
}
Esempio n. 2
0
void
overlay_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
    RenderPrimitiveOverlay *self = (RenderPrimitiveOverlay *)data;
    unsigned char r, g, b, a;
    unsigned short top_block;

    // exactly analogous to edge-line code for these special blocks
    int increment=0;
    if (state->block == 44)  // half-step
        increment=6;
    else if (state->block == 78) // snow
        increment=9;
    
    /* skip rendering the overlay if we can't see it */
    top_block = get_data(state, BLOCKS, state->x, state->y+1, state->z);
    if (!is_transparent(top_block)) {
        return;
    }
    
    /* check to be sure this block is solid/fluid */
    if (block_has_property(top_block, SOLID) || block_has_property(top_block, FLUID)) {
        
        /* top block is fluid or solid, skip drawing */
        return;
    }
    
    /* check to be sure this block is solid/fluid */
    if (!block_has_property(state->block, SOLID) && !block_has_property(state->block, FLUID)) {
        
        /* not fluid or solid, skip drawing the overlay */
        return;
    }

    /* get our color info */
    self->get_color(data, state, &r, &g, &b, &a);
    
    /* do the overlay */
    if (a > 0) {
        alpha_over_full(state->img, self->white_color, self->facemask_top, a/255.f, state->imgx, state->imgy + increment, 0, 0);
        tint_with_mask(state->img, r, g, b, 255, self->facemask_top, state->imgx, state->imgy + increment, 0, 0);
    }
}
/* shades the drawn block with the given facemask/black_color, based on the
   lighting results from (x, y, z) */
static inline void
do_shading_with_mask(RenderModeLighting *self, RenderState *state,
                     int x, int y, int z, PyObject *mask) {
    float black_coeff;
    
    /* 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) && !render_mode_hidden(state->rendermode, x, y, z)) {
            /* this face isn't visible, so don't draw anything */
            return;
        }
    } else if (self->skip_sides && (x == -1) && (state->left_blocks != Py_None)) {
        unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, state->z);
        if (!is_transparent(block)) {
            /* the same thing but for adjacent chunks, this solves an
               ugly black doted line between chunks in night rendermode.
               This wouldn't be necessary if the textures were truly
               tessellate-able */
               return;
           }
    } else if (self->skip_sides && (y == 16) && (state->right_blocks != Py_None)) {
        unsigned char block = getArrayByte3D(state->right_blocks, state->x, 0, state->z);
        if (!is_transparent(block)) {
            /* the same thing but for adjacent chunks, this solves an
               ugly black doted line between chunks in night rendermode.
               This wouldn't be necessary if the textures were truly
               tessellate-able */
               return;
           }
    }
    
    black_coeff = get_lighting_coefficient(self, state, x, y, z);
    black_coeff *= self->shade_strength;
    alpha_over_full(state->img, self->black_color, mask, black_coeff, state->imgx, state->imgy, 0, 0);
}
static void
rendermode_normal_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
    RenderModeNormal *self = (RenderModeNormal *)data;

    /* draw the block! */
    alpha_over(state->img, src, mask, state->imgx, state->imgy, 0, 0);
    
    /* check for biome-compatible blocks
     *
     * 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.
     *
     * Make sure that in textures.py, the generated textures are the
     * biome-compliant ones! The tinting is now all done here.
     */
    if (/* grass, but not snowgrass */
        (state->block == 2 && !(state->z < 127 && getArrayByte3D(state->blocks, state->x, state->y, state->z+1) == 78)) ||
        /* water */
        state->block == 8 || state->block == 9 ||
        /* leaves */
        state->block == 18 ||
        /* tallgrass, but not dead shrubs */
        (state->block == 31 && state->block_data != 0) ||
        /* pumpkin/melon stem, not fully grown. Fully grown stems
         * get constant brown color (see textures.py) */
        (((state->block == 104) || (state->block == 105)) && (state->block_data != 7)) ||
        /* vines */
        state->block == 106 ||
        /* lily pads */
        state->block == 111)
    {
        /* do the biome stuff! */
        PyObject *facemask = mask;
        unsigned char r, g, b;
        
        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;
            PyObject *color = NULL;
            
            index = ((self->chunk_y * 16) + state->y) * 16 * 32 + (self->chunk_x * 16) + state->x;
            index = big_endian_ushort(getArrayShort1D(self->biome_data, index));
            
            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;
                    
                    color = PySequence_GetItem(self->foliagecolor, index);
                }
                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 padas */
                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;
            }
            
            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;
            }
        }
        
        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);
            }
        }
    }
}
Esempio n. 5
0
/* convenience alpha_over with 1.0 as overall_alpha */
inline PyObject* alpha_over(PyObject *dest, PyObject *src, PyObject *mask,
                            int dx, int dy, int xsize, int ysize) {
    return alpha_over_full(dest, src, mask, 1.0f, dx, dy, xsize, ysize);
}