From eb762eaf08cdd66f0c726ad17c91db19b4a9559a Mon Sep 17 00:00:00 2001 From: kervala Date: Sun, 1 Jan 2017 22:44:27 +0100 Subject: [PATCH] Added: New tool textures_tool to produce diffuse, normal, specular, etc... textures from an UV template and seamless textures or colorize a texture with a color --- code/nel/tools/3d/CMakeLists.txt | 1 + .../nel/tools/3d/textures_tool/CMakeLists.txt | 9 + code/nel/tools/3d/textures_tool/main.cpp | 269 ++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 code/nel/tools/3d/textures_tool/CMakeLists.txt create mode 100644 code/nel/tools/3d/textures_tool/main.cpp diff --git a/code/nel/tools/3d/CMakeLists.txt b/code/nel/tools/3d/CMakeLists.txt index ff5c37db0..08fd9e776 100644 --- a/code/nel/tools/3d/CMakeLists.txt +++ b/code/nel/tools/3d/CMakeLists.txt @@ -36,6 +36,7 @@ IF(WITH_NEL_TOOLS) build_interface get_neighbors textures_optimizer + textures_tool tga_cut tga_resize) ENDIF() diff --git a/code/nel/tools/3d/textures_tool/CMakeLists.txt b/code/nel/tools/3d/textures_tool/CMakeLists.txt new file mode 100644 index 000000000..203167162 --- /dev/null +++ b/code/nel/tools/3d/textures_tool/CMakeLists.txt @@ -0,0 +1,9 @@ +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(textures_tool ${SRC}) + +TARGET_LINK_LIBRARIES(textures_tool nelmisc) +NL_DEFAULT_PROPS(textures_tool "NeL, Tools, 3D: Textures Tool") +NL_ADD_RUNTIME_FLAGS(textures_tool) + +INSTALL(TARGETS textures_tool RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d) diff --git a/code/nel/tools/3d/textures_tool/main.cpp b/code/nel/tools/3d/textures_tool/main.cpp new file mode 100644 index 000000000..589ab8d72 --- /dev/null +++ b/code/nel/tools/3d/textures_tool/main.cpp @@ -0,0 +1,269 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "nel/misc/file.h" +#include "nel/misc/common.h" +#include "nel/misc/bitmap.h" +#include "nel/misc/path.h" +#include "nel/misc/cmd_args.h" +#include "nel/misc/vector_2d.h" + +struct CPoint +{ + CPoint(sint _x, sint _y) :x(_x), y(_y) + { + } + + CPoint operator + (const CPoint &p) const + { + return CPoint(x + p.x, y + p.y); + } + + sint x; + sint y; +}; + +const CPoint Up(0, -1); +const CPoint Down(0, 1); +const CPoint Left(-1, 0); +const CPoint Right(1, 0); + +const NLMISC::CRGBA DiscardColor = NLMISC::CRGBA::Red; +const NLMISC::CRGBA KeepColor = NLMISC::CRGBA::Blue; + +typedef std::vector CPoints; + +bool fillPoint(NLMISC::CBitmap &bitmap, sint width, CPoints &points) +{ + if (points.empty()) return false; + + // take last point in queue + CPoint p(points.back()); + points.pop_back(); + + NLMISC::CRGBA c = bitmap.getPixelColor(p.x, p.y); + + if (c == NLMISC::CRGBA::White) + { + // white is used for background + + // replace with color we want to discard + bitmap.setPixelColor(p.x, p.y, DiscardColor); + + uint w = bitmap.getWidth(); + uint h = bitmap.getHeight(); + + // put adjacent pixels in queue to process later + if (p.y > 0) points.push_back(p + Up); + if (p.y < h-1) points.push_back(p + Down); + if (p.x > 0) points.push_back(p + Left); + if (p.x < w-1) points.push_back(p + Right); + } + else if (c == NLMISC::CRGBA::Black) + { + // black is used for vertices + + // increase them by border width + for (sint y = -width; y <= width; ++y) + { + for (sint x = -width; x <= width; ++x) + { + bitmap.setPixelColor(p.x + x, p.y + y, KeepColor); + } + } + } + + return true; +} + +int main(int argc, char **argv) +{ + NLMISC::CApplicationContext applicationContext; + + // Parse Command Line. + //==================== + NLMISC::CCmdArgs args; + + args.setDescription("Textures tool"); + args.addArg("c", "colorize", "color", "Colorize textures using a color (in HTML hexdecimal format like #rrggbb)"); + args.addArg("f", "fill", "color or image", "Fill background part with color or image"); + args.addArg("w", "width", "width of border", "Width of the border to fill (default 0)"); + args.addArg("b", "background", "background color", "Color to use to fill background"); + args.addArg("o", "output", "filename", "Output filename"); + args.addAdditionalArg("filename", "File to process", true, true); + + if (!args.parse(argc, argv)) return 1; + + std::string filename = args.getAdditionalArg("filename").front(); + + std::string output = args.haveArg("o") ? args.getArg("o").front() : ""; + + if (args.haveArg("c")) + { + // colorize + NLMISC::CIFile file; + + NLMISC::CRGBA color; + color.fromString(args.getArg("c").front()); + + if (file.open(filename)) + { + NLMISC::CBitmap bitmap; + + if (bitmap.load(file)) + { + NLMISC::CObjectVector &pixels = bitmap.getPixels(); + + NLMISC::CRGBA *pRGBA = (NLMISC::CRGBA*)&pixels[0]; + + uint32 size = bitmap.getSize(); + + for (uint j = 0; j < size; ++j) + { + // TODO: find what computation do +// *(pRGBA++)-> = color; + } + + NLMISC::COFile out; + + if (out.open(output)) + { + bitmap.writePNG(out, 24); + } + } + } + } + + if (args.haveArg("f")) + { + // fill areas in a bitmap with another texture or color + + // for example : + // textures_tool -f normal.png -w 2 -b #000000 uvmap.png -o test_normal.png + // will use a copy 1024x1024 texture map on a 4096x4096 UV Map preserving the different areas + + std::string foregroundColorOrFilename = args.getArg("f").front(); + + NLMISC::CRGBA foregroundColor = NLMISC::CRGBA::Black, backgroundColor = NLMISC::CRGBA::Black; + + NLMISC::CBitmap textureBitmap; + + bool useTexture = false; + + // f parameter is required + if (NLMISC::CFile::fileExists(foregroundColorOrFilename)) + { + // load texture + NLMISC::CIFile textureFile; + + if (!textureFile.open(foregroundColorOrFilename)) + { + nlwarning("Unable to open %s", foregroundColorOrFilename.c_str()); + return 1; + } + + // decode texture + if (!textureBitmap.load(textureFile)) + { + nlwarning("Unable to decode %s", foregroundColorOrFilename.c_str()); + return 1; + } + + useTexture = true; + } + else + { + // parse color from argument + foregroundColor.fromString(foregroundColorOrFilename); + } + + if (args.haveArg("b")) + { + // parse HTML color from argument + backgroundColor.fromString(args.getArg("b").front()); + } + + sint width = 0; + + if (args.haveArg("w")) + { + // parse width of borders + NLMISC::fromString(args.getArg("w").front(), width); + } + + // load bitmap + NLMISC::CIFile file; + + if (!file.open(filename)) + { + nlwarning("Unable to open %s", filename.c_str()); + return 1; + } + + // decode bitmap + NLMISC::CBitmap inBitmap; + + if (!inBitmap.load(file)) + { + nlwarning("Unable to decode %s", filename.c_str()); + return 1; + } + + CPoints Points; + + // we can't have more than width * height points, so allocate memory for all of them + Points.reserve(inBitmap.getWidth() * inBitmap.getHeight()); + + // first point to process + Points.push_back(CPoint(0, 0)); + + // process all points from 0, 0 + while(fillPoint(inBitmap, width, Points)) { } + + // create a new bitmap for output + NLMISC::CBitmap outBitmap; + outBitmap.resize(inBitmap.getWidth(), inBitmap.getHeight()); + + // copy points colors to new bitmap + for (sint y = 0, h = inBitmap.getHeight(); y < h; ++y) + { + for (sint x = 0, w = inBitmap.getWidth(); x < w; ++x) + { + if (inBitmap.getPixelColor(x, y) != DiscardColor) + { + // we copy this point, repeat texture image if using it + outBitmap.setPixelColor(x, y, useTexture ? textureBitmap.getPixelColor(x % textureBitmap.getWidth(), y % textureBitmap.getHeight()) : foregroundColor); + } + else + { + // put a background color + outBitmap.setPixelColor(x, y, backgroundColor); + } + } + } + + // save output bitmap + NLMISC::COFile outFile; + + if (outFile.open(output)) + { + outBitmap.writePNG(outFile, 24); + } + } + + return 0; +}