mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-04 17:23:33 +01:00
Generate light layer
This commit is contained in:
parent
e1b3347da5
commit
9e0bbcf685
5 changed files with 52 additions and 30 deletions
|
@ -52,16 +52,21 @@ namespace MinedMap {
|
||||||
static const size_t DIM = World::Region::SIZE*World::Chunk::SIZE;
|
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();
|
World::Chunk::Blocks layer = chunk->getTopLayer();
|
||||||
|
|
||||||
for (size_t x = 0; x < World::Chunk::SIZE; x++) {
|
for (size_t x = 0; x < World::Chunk::SIZE; x++) {
|
||||||
for (size_t z = 0; z < World::Chunk::SIZE; z++)
|
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());
|
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;
|
struct stat instat, outstat;
|
||||||
|
|
||||||
if (stat(input.c_str(), &instat) < 0) {
|
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());
|
std::printf("Generating %s from %s...\n", output.c_str(), input.c_str());
|
||||||
|
|
||||||
const std::string tmpfile = output + ".tmp";
|
const std::string tmpfile = output + ".tmp";
|
||||||
|
const std::string tmpfile_light = output_light + ".tmp";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
uint32_t image[DIM*DIM] = {};
|
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<const uint8_t*>(image), DIM, DIM);
|
PNG::write(tmpfile.c_str(), reinterpret_cast<const uint8_t*>(image), DIM, DIM, true);
|
||||||
|
PNG::write(tmpfile_light.c_str(), lightmap, DIM, DIM, false);
|
||||||
|
|
||||||
struct timespec times[2] = {instat.st_mtim, instat.st_mtim};
|
struct timespec times[2] = {instat.st_mtim, instat.st_mtim};
|
||||||
if (utimensat(AT_FDCWD, tmpfile.c_str(), times, 0) < 0)
|
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));
|
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) {
|
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));
|
std::fprintf(stderr, "Unable to save %s: %s\n", output.c_str(), std::strerror(errno));
|
||||||
unlink(tmpfile.c_str());
|
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) {
|
catch (const std::exception& ex) {
|
||||||
std::fprintf(stderr, "Failed to generate %s: %s\n", output.c_str(), ex.what());
|
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 regiondir = inputdir + "/region";
|
||||||
|
|
||||||
std::string outputdir(argv[2]);
|
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());
|
DIR *dir = opendir(regiondir.c_str());
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
|
@ -160,8 +176,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
info.addRegion(x, z);
|
info.addRegion(x, z);
|
||||||
|
|
||||||
std::string name(entry->d_name);
|
std::string name(entry->d_name), outname = name.substr(0, name.length()-3) + "png";
|
||||||
doRegion(regiondir + "/" + name, regionoutdir + "/" + name.substr(0, name.length()-3) + "png");
|
doRegion(regiondir + "/" + name, outputdir + "/map/0/" + outname, outputdir + "/light/0/" + outname);
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
34
src/PNG.cpp
34
src/PNG.cpp
|
@ -37,7 +37,7 @@
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace PNG {
|
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");
|
std::FILE *f = std::fopen(filename, "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
throw std::system_error(errno, std::generic_category(), "unable to open PNG file");
|
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_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);
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
uint8_t *row_pointers[height];
|
uint8_t *row_pointers[height];
|
||||||
for (size_t i = 0; i < height; i++)
|
for (size_t i = 0; i < height; i++)
|
||||||
row_pointers[i] = const_cast<uint8_t*>(&data[4*i*width]);
|
row_pointers[i] = const_cast<uint8_t*>(&data[(colored ? 4 : 2)*i*width]);
|
||||||
|
|
||||||
png_set_rows(png_ptr, info_ptr, row_pointers);
|
png_set_rows(png_ptr, info_ptr, row_pointers);
|
||||||
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
|
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);
|
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");
|
std::FILE *f = std::fopen(filename, "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
throw std::system_error(errno, std::generic_category(), "unable to open PNG file");
|
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
|
if (png_get_image_width(png_ptr, info_ptr) != width
|
||||||
|| png_get_image_height(png_ptr, info_ptr) != height
|
|| png_get_image_height(png_ptr, info_ptr) != height
|
||||||
|| png_get_bit_depth(png_ptr, info_ptr) != 8
|
|| 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);
|
longjmp(png_jmpbuf(png_ptr), 1);
|
||||||
|
|
||||||
uint8_t **row_pointers = png_get_rows(png_ptr, info_ptr);
|
uint8_t **row_pointers = png_get_rows(png_ptr, info_ptr);
|
||||||
for (size_t i = 0; i < height; i++)
|
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);
|
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
||||||
std::fclose(f);
|
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)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
size_t b = (colored ? 4 : 2);
|
||||||
|
|
||||||
uint8_t input[4*width*height];
|
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 h = 0; h < width/2; h++) {
|
||||||
for (size_t w = 0; w < width/2; w++) {
|
for (size_t w = 0; w < width/2; w++) {
|
||||||
for (size_t c = 0; c < 4; c++) {
|
for (size_t c = 0; c < 4; c++) {
|
||||||
size_t i = 8*width*h + 8*w + c;
|
size_t i = 2*b*(width*h + 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;
|
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];
|
uint8_t data[4*width*height];
|
||||||
std::memset(data, 0, sizeof(data));
|
std::memset(data, 0, sizeof(data));
|
||||||
|
|
||||||
readScaled(data, 0, 0, nw, width, height);
|
readScaled(data, 0, 0, nw, width, height, colored);
|
||||||
readScaled(data, width/2, 0, ne, width, height);
|
readScaled(data, width/2, 0, ne, width, height, colored);
|
||||||
readScaled(data, 0, height/2, sw, width, height);
|
readScaled(data, 0, height/2, sw, width, height, colored);
|
||||||
readScaled(data, width/2, height/2, se, width, height);
|
readScaled(data, width/2, height/2, se, width, height, colored);
|
||||||
|
|
||||||
write(output, data, width, height);
|
write(output, data, width, height, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,9 +33,9 @@
|
||||||
namespace MinedMap {
|
namespace MinedMap {
|
||||||
namespace PNG {
|
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);
|
||||||
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);
|
||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,10 @@ struct Block {
|
||||||
Block(uint8_t id0, uint8_t data0, unsigned height0, uint8_t blockLight0, uint8_t skyLight0, uint8_t biome0)
|
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) {}
|
: id(id0), data(data0), height(height0), blockLight(blockLight0), skyLight(skyLight0), biome(biome0) {}
|
||||||
|
|
||||||
|
uint8_t getBlockLight() const {
|
||||||
|
return blockLight;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t getColor() const;
|
uint32_t getColor() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ var MinedMapLayer = L.GridLayer.extend({
|
||||||
if (coords.x >= this._info.minX && coords.x <= this._info.maxX &&
|
if (coords.x >= this._info.minX && coords.x <= this._info.maxX &&
|
||||||
coords.y >= this._info.minZ && coords.y <= this._info.maxZ &&
|
coords.y >= this._info.minZ && coords.y <= this._info.maxZ &&
|
||||||
this._regions[coords.y-this._info.minZ][coords.x-this._info.minX])
|
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;
|
return tile;
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue