inline unsigned char estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state, int x, int y, int z, int *authoratative) { /* placeholders for later data arrays, coordinates */ unsigned char block, blocklevel; unsigned int average_count = 0, average_gather = 0, coeff = 0; /* defaults to "guess" until told otherwise */ if (authoratative) *authoratative = 0; block = get_data(state, BLOCKS, x, y, z); if (authoratative == NULL) { int auth; /* iterate through all surrounding blocks to take an average */ int dx, dy, dz, local_block; for (dx = -1; dx <= 1; dx += 2) { for (dy = -1; dy <= 1; dy += 2) { for (dz = -1; dz <= 1; dz += 2) { coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth); local_block = get_data(state, BLOCKS, x+dx, y+dy, z+dz); /* only add if the block is transparent, this seems to look better than using every block */ if (auth && is_transparent(local_block)) { average_gather += coeff; average_count++; } } } } } /* only return the average if at least one was authoratative */ if (average_count > 0) { return average_gather / average_count; } blocklevel = get_data(state, BLOCKLIGHT, x, y, z); /* no longer a guess */ if (!(block == 44 || block == 53 || block == 67 || block == 108 || block == 109) && authoratative) { *authoratative = 1; } return blocklevel; }
inline void get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, int x, int y, int z, unsigned char *r, unsigned char *g, unsigned char *b) { /* placeholders for later data arrays, coordinates */ unsigned char block, skylevel, blocklevel; block = get_data(state, BLOCKS, x, y, z); skylevel = get_data(state, SKYLIGHT, x, y, z); blocklevel = get_data(state, BLOCKLIGHT, x, y, z); /* special half-step handling, stairs handling */ /* Anvil also needs to be here, blockid 145 */ if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114 || block == 128 || block == 134 || block == 135 || block == 136 || block == 145 || block == 156) { unsigned int upper_block; /* stairs and half-blocks take the skylevel from the upper block if it's transparent */ int upper_counter = 0; /* but if the upper_block is one of these special half-steps, we need to look at *its* upper_block */ do { upper_counter++; upper_block = get_data(state, BLOCKS, x, y + upper_counter, z); } while (upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || upper_block == 109 || upper_block == 114 || upper_block == 128 || upper_block == 134 || upper_block == 135 || upper_block == 136 || upper_block == 156 ); if (is_transparent(upper_block)) { skylevel = get_data(state, SKYLIGHT, x, y + upper_counter, z); } else { skylevel = 15; } /* the block has a bad blocklevel, estimate it from neigborhood * use given coordinates, no local ones! */ blocklevel = estimate_blocklevel(self, state, x, y, z, NULL); } if (block == 10 || block == 11) { /* lava blocks should always be lit! */ *r = 255; *g = 255; *b = 255; return; } self->calculate_light_color(self, MIN(skylevel, 15), MIN(blocklevel, 15), r, g, b); }
inline unsigned char estimate_blocklevel(RenderModeLighting *self, RenderState *state, int x, int y, int z, int *authoratative) { /* placeholders for later data arrays, coordinates */ PyObject *blocks = NULL; PyObject *blocklight = NULL; int local_x = x, local_y = y, local_z = z; unsigned char block, blocklevel; unsigned int average_count = 0, average_gather = 0, coeff = 0; /* defaults to "guess" until told otherwise */ if (authoratative) *authoratative = 0; /* find out what chunk we're in, and translate accordingly */ if (x >= 0 && y < 16) { blocks = state->blocks; blocklight = self->blocklight; } else if (x < 0) { local_x += 16; blocks = state->left_blocks; blocklight = self->left_blocklight; } else if (y >= 16) { local_y -= 16; blocks = state->right_blocks; blocklight = self->right_blocklight; } /* make sure we have correctly-ranged coordinates */ if (!(local_x >= 0 && local_x < 16 && local_y >= 0 && local_y < 16 && local_z >= 0 && local_z < 128)) { return 0; } /* also, make sure we have enough info to correctly calculate lighting */ if (blocks == Py_None || blocks == NULL || blocklight == Py_None || blocklight == NULL) { return 0; } block = getArrayByte3D(blocks, local_x, local_y, local_z); if (authoratative == NULL) { int auth; /* iterate through all surrounding blocks to take an average */ int dx, dy, dz, local_block; for (dx = -1; dx <= 1; dx += 2) { for (dy = -1; dy <= 1; dy += 2) { for (dz = -1; dz <= 1; dz += 2) { /* skip if block is out of range */ if (x+dx < 0 || x+dx >= 16 || y+dy < 0 || y+dy >= 16 || z+dz < 0 || z+dz >= 128) { continue; } coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth); local_block = getArrayByte3D(blocks, x+dx, y+dy, z+dz); /* only add if the block is transparent, this seems to look better than using every block */ if (auth && is_transparent(local_block)) { average_gather += coeff; average_count++; } } } } } /* only return the average if at least one was authoratative */ if (average_count > 0) { return average_gather / average_count; } blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); /* no longer a guess */ if (!(block == 44 || block == 53 || block == 67) && authoratative) { *authoratative = 1; } return blocklevel; }
inline float get_lighting_coefficient(RenderModeLighting *self, RenderState *state, int x, int y, int z) { /* placeholders for later data arrays, coordinates */ PyObject *blocks = NULL; PyObject *skylight = NULL; PyObject *blocklight = NULL; int local_x = x, local_y = y, local_z = z; unsigned char block, skylevel, blocklevel; /* find out what chunk we're in, and translate accordingly */ if (x >= 0 && y < 16) { blocks = state->blocks; skylight = self->skylight; blocklight = self->blocklight; } else if (x < 0) { local_x += 16; blocks = state->left_blocks; skylight = self->left_skylight; blocklight = self->left_blocklight; } else if (y >= 16) { local_y -= 16; blocks = state->right_blocks; skylight = self->right_skylight; blocklight = self->right_blocklight; } /* make sure we have correctly-ranged coordinates */ if (!(local_x >= 0 && local_x < 16 && local_y >= 0 && local_y < 16 && local_z >= 0 && local_z < 128)) { return self->calculate_darkness(15, 0); } /* also, make sure we have enough info to correctly calculate lighting */ if (blocks == Py_None || blocks == NULL || skylight == Py_None || skylight == NULL || blocklight == Py_None || blocklight == NULL) { return self->calculate_darkness(15, 0); } 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); } skylevel = getArrayByte3D(skylight, local_x, local_y, local_z); blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z); /* special half-step handling */ if (block == 44 || block == 53 || block == 67) { unsigned int upper_block; /* stairs and half-blocks take the skylevel from the upper block if it's transparent */ if (local_z != 127) { int upper_counter = 0; /* but if the upper_block is one of these special half-steps, we need to look at *its* upper_block */ do { upper_counter++; upper_block = getArrayByte3D(blocks, local_x, local_y, local_z + upper_counter); } while ((upper_block == 44 || upper_block == 54 || upper_block == 67) && local_z < 127); if (is_transparent(upper_block)) { skylevel = getArrayByte3D(skylight, local_x, local_y, local_z + upper_counter); } } else { upper_block = 0; skylevel = 15; } /* the block has a bad blocklevel, estimate it from neigborhood * use given coordinates, no local ones! */ blocklevel = estimate_blocklevel(self, state, x, y, z, NULL); } if (block == 10 || block == 11) { /* lava blocks should always be lit! */ return 0.0f; } return self->calculate_darkness(skylevel, blocklevel); }