From 9e0bbcf685786e21b7d61216f4e1a24f0b1a3354 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 3 Feb 2015 13:13:12 +0100 Subject: Generate light layer --- src/MinedMap.cpp | 36 ++++++++++++++++++++++++++---------- src/PNG.cpp | 34 ++++++++++++++++++---------------- src/PNG.hpp | 6 +++--- src/World/Block.hpp | 4 ++++ viewer/MinedMap.js | 2 +- 5 files changed, 52 insertions(+), 30 deletions(-) diff --git a/src/MinedMap.cpp b/src/MinedMap.cpp index bf6f4fb..5092ceb 100644 --- a/src/MinedMap.cpp +++ b/src/MinedMap.cpp @@ -52,16 +52,21 @@ namespace MinedMap { static const size_t DIM = World::Region::SIZE*World::Chunk::SIZE; -static void addChunk(uint32_t image[DIM*DIM], size_t X, size_t Z, const World::Chunk *chunk) { +static void addChunk(uint32_t image[DIM*DIM], uint8_t lightmap[2*DIM*DIM], size_t X, size_t Z, const World::Chunk *chunk) { World::Chunk::Blocks layer = chunk->getTopLayer(); for (size_t x = 0; x < World::Chunk::SIZE; x++) { - for (size_t z = 0; z < World::Chunk::SIZE; z++) - image[(Z*World::Chunk::SIZE+z)*DIM + X*World::Chunk::SIZE+x] = htonl(layer.blocks[x][z].getColor()); + for (size_t z = 0; z < World::Chunk::SIZE; z++) { + size_t i = (Z*World::Chunk::SIZE+z)*DIM + X*World::Chunk::SIZE+x; + const World::Block &block = layer.blocks[x][z]; + + image[i] = htonl(block.getColor()); + lightmap[2*i+1] = (1 - block.getBlockLight()/15.f)*128; + } } } -static void doRegion(const std::string &input, const std::string &output) { +static void doRegion(const std::string &input, const std::string &output, const std::string &output_light) { struct stat instat, outstat; if (stat(input.c_str(), &instat) < 0) { @@ -80,21 +85,30 @@ static void doRegion(const std::string &input, const std::string &output) { std::printf("Generating %s from %s...\n", output.c_str(), input.c_str()); const std::string tmpfile = output + ".tmp"; + const std::string tmpfile_light = output_light + ".tmp"; try { uint32_t image[DIM*DIM] = {}; - World::Region::visitChunks(input.c_str(), [&image] (size_t X, size_t Z, const World::Chunk *chunk) { addChunk(image, X, Z, chunk); }); + uint8_t lightmap[2*DIM*DIM] = {}; + World::Region::visitChunks(input.c_str(), [&] (size_t X, size_t Z, const World::Chunk *chunk) { addChunk(image, lightmap, X, Z, chunk); }); - PNG::write(tmpfile.c_str(), reinterpret_cast(image), DIM, DIM); + PNG::write(tmpfile.c_str(), reinterpret_cast(image), DIM, DIM, true); + PNG::write(tmpfile_light.c_str(), lightmap, DIM, DIM, false); struct timespec times[2] = {instat.st_mtim, instat.st_mtim}; if (utimensat(AT_FDCWD, tmpfile.c_str(), times, 0) < 0) std::fprintf(stderr, "Warning: failed to set utime on %s: %s\n", tmpfile.c_str(), std::strerror(errno)); + if (utimensat(AT_FDCWD, tmpfile_light.c_str(), times, 0) < 0) + std::fprintf(stderr, "Warning: failed to set utime on %s: %s\n", tmpfile_light.c_str(), std::strerror(errno)); if (std::rename(tmpfile.c_str(), output.c_str()) < 0) { std::fprintf(stderr, "Unable to save %s: %s\n", output.c_str(), std::strerror(errno)); unlink(tmpfile.c_str()); } + if (std::rename(tmpfile_light.c_str(), output_light.c_str()) < 0) { + std::fprintf(stderr, "Unable to save %s: %s\n", output_light.c_str(), std::strerror(errno)); + unlink(tmpfile_light.c_str()); + } } catch (const std::exception& ex) { std::fprintf(stderr, "Failed to generate %s: %s\n", output.c_str(), ex.what()); @@ -140,9 +154,11 @@ int main(int argc, char *argv[]) { std::string regiondir = inputdir + "/region"; std::string outputdir(argv[2]); - std::string regionoutdir = outputdir + "/0"; - makeDir(regionoutdir); + makeDir(outputdir + "/map"); + makeDir(outputdir + "/map/0"); + makeDir(outputdir + "/light"); + makeDir(outputdir + "/light/0"); DIR *dir = opendir(regiondir.c_str()); if (!dir) { @@ -160,8 +176,8 @@ int main(int argc, char *argv[]) { info.addRegion(x, z); - std::string name(entry->d_name); - doRegion(regiondir + "/" + name, regionoutdir + "/" + name.substr(0, name.length()-3) + "png"); + std::string name(entry->d_name), outname = name.substr(0, name.length()-3) + "png"; + doRegion(regiondir + "/" + name, outputdir + "/map/0/" + outname, outputdir + "/light/0/" + outname); } closedir(dir); diff --git a/src/PNG.cpp b/src/PNG.cpp index 0154f61..78df385 100644 --- a/src/PNG.cpp +++ b/src/PNG.cpp @@ -37,7 +37,7 @@ namespace MinedMap { namespace PNG { -void write(const char *filename, const uint8_t *data, size_t width, size_t height) { +void write(const char *filename, const uint8_t *data, size_t width, size_t height, bool colored) { std::FILE *f = std::fopen(filename, "wb"); if (!f) throw std::system_error(errno, std::generic_category(), "unable to open PNG file"); @@ -60,12 +60,12 @@ void write(const char *filename, const uint8_t *data, size_t width, size_t heigh png_init_io(png_ptr, f); - png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, + png_set_IHDR(png_ptr, info_ptr, width, height, 8, colored ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); uint8_t *row_pointers[height]; for (size_t i = 0; i < height; i++) - row_pointers[i] = const_cast(&data[4*i*width]); + row_pointers[i] = const_cast(&data[(colored ? 4 : 2)*i*width]); png_set_rows(png_ptr, info_ptr, row_pointers); png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr); @@ -74,7 +74,7 @@ void write(const char *filename, const uint8_t *data, size_t width, size_t heigh std::fclose(f); } -void read(const char *filename, uint8_t *data, size_t width, size_t height) { +void read(const char *filename, uint8_t *data, size_t width, size_t height, bool colored) { std::FILE *f = std::fopen(filename, "rb"); if (!f) throw std::system_error(errno, std::generic_category(), "unable to open PNG file"); @@ -108,44 +108,46 @@ void read(const char *filename, uint8_t *data, size_t width, size_t height) { if (png_get_image_width(png_ptr, info_ptr) != width || png_get_image_height(png_ptr, info_ptr) != height || png_get_bit_depth(png_ptr, info_ptr) != 8 - || png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGB_ALPHA) + || png_get_color_type(png_ptr, info_ptr) != (colored ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_GRAY_ALPHA)) longjmp(png_jmpbuf(png_ptr), 1); uint8_t **row_pointers = png_get_rows(png_ptr, info_ptr); for (size_t i = 0; i < height; i++) - std::memcpy(&data[4*i*width], row_pointers[i], 4*width); + std::memcpy(&data[(colored ? 4 : 2)*i*width], row_pointers[i], (colored ? 4 : 2)*width); png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); std::fclose(f); } -static void readScaled(uint8_t *data, size_t offset_w, size_t offset_h, const char *file, size_t width, size_t height) { +static void readScaled(uint8_t *data, size_t offset_w, size_t offset_h, const char *file, size_t width, size_t height, bool colored) { if (!file) return; + size_t b = (colored ? 4 : 2); + uint8_t input[4*width*height]; - read(file, input, width, height); + read(file, input, width, height, colored); for (size_t h = 0; h < width/2; h++) { for (size_t w = 0; w < width/2; w++) { for (size_t c = 0; c < 4; c++) { - size_t i = 8*width*h + 8*w + c; - data[4*width*(offset_h+h) + 4*(offset_w+w) + c] = (input[i] + input[i+4] + input[i+4*width] + input[i+4*width+4])/4; + size_t i = 2*b*(width*h + w) + c; + data[b*(width*(offset_h+h) + offset_w+w) + c] = (input[i] + input[i+b] + input[i+b*width] + input[i+b*width+b])/4; } } } } -void mipmap(const char *output, size_t width, size_t height, const char *nw, const char *ne, const char *sw, const char *se) { +void mipmap(const char *output, size_t width, size_t height, bool colored, const char *nw, const char *ne, const char *sw, const char *se) { uint8_t data[4*width*height]; std::memset(data, 0, sizeof(data)); - readScaled(data, 0, 0, nw, width, height); - readScaled(data, width/2, 0, ne, width, height); - readScaled(data, 0, height/2, sw, width, height); - readScaled(data, width/2, height/2, se, width, height); + readScaled(data, 0, 0, nw, width, height, colored); + readScaled(data, width/2, 0, ne, width, height, colored); + readScaled(data, 0, height/2, sw, width, height, colored); + readScaled(data, width/2, height/2, se, width, height, colored); - write(output, data, width, height); + write(output, data, width, height, true); } } diff --git a/src/PNG.hpp b/src/PNG.hpp index 1647d03..ee6ffd4 100644 --- a/src/PNG.hpp +++ b/src/PNG.hpp @@ -33,9 +33,9 @@ namespace MinedMap { namespace PNG { -void write(const char *filename, const uint8_t *data, size_t width, size_t height); -void read(const char *filename, uint8_t *data, size_t width, size_t height); -void mipmap(const char *output, size_t width, size_t height, const char *nw, const char *ne, const char *sw, const char *se); +void write(const char *filename, const uint8_t *data, size_t width, size_t height, bool colored); +void read(const char *filename, uint8_t *data, size_t width, size_t height, bool colored); +void mipmap(const char *output, size_t width, size_t height, bool colored, const char *nw, const char *ne, const char *sw, const char *se); } } diff --git a/src/World/Block.hpp b/src/World/Block.hpp index f078503..b636f06 100644 --- a/src/World/Block.hpp +++ b/src/World/Block.hpp @@ -47,6 +47,10 @@ struct Block { Block(uint8_t id0, uint8_t data0, unsigned height0, uint8_t blockLight0, uint8_t skyLight0, uint8_t biome0) : id(id0), data(data0), height(height0), blockLight(blockLight0), skyLight(skyLight0), biome(biome0) {} + uint8_t getBlockLight() const { + return blockLight; + } + uint32_t getColor() const; }; diff --git a/viewer/MinedMap.js b/viewer/MinedMap.js index 464bd22..ad330b2 100644 --- a/viewer/MinedMap.js +++ b/viewer/MinedMap.js @@ -21,7 +21,7 @@ var MinedMapLayer = L.GridLayer.extend({ if (coords.x >= this._info.minX && coords.x <= this._info.maxX && coords.y >= this._info.minZ && coords.y <= this._info.maxZ && this._regions[coords.y-this._info.minZ][coords.x-this._info.minX]) - tile.src = 'data/0/r.'+coords.x+'.'+coords.y+'.png'; + tile.src = 'data/map/0/r.'+coords.x+'.'+coords.y+'.png'; return tile; }, -- cgit v1.2.3