From bd9ff72f4dc7c814f762fc08864cb6df26ed8199 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Sun, 22 Aug 2010 23:46:49 +0200 Subject: [PATCH] limited TGA loading support, better OBJ material import --- include/mitsuba/core/bitmap.h | 4 + src/converter/collada.cpp | 15 ++-- src/converter/mtsimport.cpp | 18 ++++- src/converter/obj.cpp | 134 ++++++++++++++++++++++++++++++++-- src/libcore/bitmap.cpp | 41 ++++++++++- src/textures/ldrtexture.cpp | 13 ++-- 6 files changed, 203 insertions(+), 22 deletions(-) diff --git a/include/mitsuba/core/bitmap.h b/include/mitsuba/core/bitmap.h index 69b3038b..abb8183a 100644 --- a/include/mitsuba/core/bitmap.h +++ b/include/mitsuba/core/bitmap.h @@ -17,6 +17,7 @@ public: enum EFileFormat { EPNG = 0, EEXR, + ETGA, EJPEG }; @@ -100,6 +101,9 @@ protected: /// Load a file stored using the PNG file format void loadPNG(Stream *stream); + + /// Load a file stored using the TGA file format + void loadTGA(Stream *stream); /// Load a file stored using the JPEG file format void loadJPEG(Stream *stream); diff --git a/src/converter/collada.cpp b/src/converter/collada.cpp index 1648407e..cbaf8199 100644 --- a/src/converter/collada.cpp +++ b/src/converter/collada.cpp @@ -629,29 +629,30 @@ void loadImage(GeometryConverter *cvt, std::ostream &os, const std::string &text fileToId[filename] = image.getId(); boost::filesystem::path path = boost::filesystem::path(filename, boost::filesystem::native); - std::string leaf = path.leaf(); + ref fRes = FileResolver::getInstance(); + std::string resolved = fRes->resolve(path.leaf()); - if (endsWith(leaf, ".rgb")) + if (endsWith(resolved, ".rgb")) SLog(EWarn, "Maya RGB images must be converted to PNG, EXR or JPEG! The 'imgcvt' " "utility found in the Maya binary directory can be used to do this."); if (!FileStream::exists(filename)) { - if (!FileStream::exists(leaf)) { - SLog(EWarn, "Found neither \"%s\" nor \"%s\"!", filename.c_str(), leaf.c_str()); + if (!FileStream::exists(resolved)) { + SLog(EWarn, "Found neither \"%s\" nor \"%s\"!", filename.c_str(), resolved.c_str()); filename = cvt->locateResource(filename); if (filename == "") SLog(EError, "Unable to locate a resource -- aborting conversion."); } else { - filename = leaf; + filename = resolved; } } ref input = new FileStream(filename, FileStream::EReadOnly); - ref output = new FileStream(textureDir + leaf.c_str(), FileStream::ETruncReadWrite); + ref output = new FileStream(textureDir + path.leaf(), FileStream::ETruncReadWrite); input->copyTo(output); os << "\t" << endl; - os << "\t\t" << endl; + os << "\t\t" << endl; os << "\t" << endl << endl; } diff --git a/src/converter/mtsimport.cpp b/src/converter/mtsimport.cpp index f8f689cf..95896a7a 100644 --- a/src/converter/mtsimport.cpp +++ b/src/converter/mtsimport.cpp @@ -55,6 +55,8 @@ void help() { << "Syntax: mtsimport [options] [Adjustment file]" << endl << "Options/Arguments:" << endl << " -h Display this help text" << endl << endl + << " -a p1;p2;.. Add one or more entries to the resource search path" << endl << endl + << " -v Be more verbose" << endl << endl << " -p Use the specified number of samples per pixel." << endl << endl << " -s Assume that colors are in sRGB space." << endl << endl << " -m Map the larger image side to the full field of view" << endl << endl @@ -69,11 +71,19 @@ int colladaMain(int argc, char **argv) { int xres = -1, yres = -1; int samplesPerPixel = 8; Float fov = -1; + FileResolver *resolver = FileResolver::getInstance(); + ELogLevel logLevel = EInfo; optind = 1; - while ((optchar = getopt(argc, argv, "shmr:p:f:")) != -1) { + while ((optchar = getopt(argc, argv, "svhmr:a:p:f:")) != -1) { switch (optchar) { + case 'a': { + std::vector paths = tokenize(optarg, ";"); + for (unsigned int i=0; iaddPath(paths[i]); + } + break; case 's': srgb = true; break; @@ -85,6 +95,9 @@ int colladaMain(int argc, char **argv) { if (*end_ptr != '\0') SLog(EError, "Invalid number of samples per pixel!"); break; + case 'v': + logLevel = EDebug; + break; case 'f': fov = strtod(optarg, &end_ptr); if (*end_ptr != '\0') @@ -113,6 +126,9 @@ int colladaMain(int argc, char **argv) { help(); return -1; } + + ref log = Thread::getThread()->getLogger(); + log->setLogLevel(logLevel); ConsoleGeometryConverter converter; converter.setSRGB(srgb); diff --git a/src/converter/obj.cpp b/src/converter/obj.cpp index 77562580..c11cd1a2 100644 --- a/src/converter/obj.cpp +++ b/src/converter/obj.cpp @@ -1,25 +1,147 @@ +#define BOOST_FILESYSTEM_NO_LIB +#define BOOST_SYSTEM_NO_LIB + #include +#include #include #include +#include +#include #include "converter.h" +std::string copyTexture(GeometryConverter *cvt, const std::string &textureDir, std::string filename) { + SLog(EInfo, "Copying texture \"%s\" ..", filename.c_str()); +#if defined(WIN32) + for (size_t i=0; i fRes = FileResolver::getInstance(); + std::string resolved = fRes->resolve(path.leaf()); + if (!FileStream::exists(filename)) { + if (!FileStream::exists(resolved)) { + SLog(EWarn, "Found neither \"%s\" nor \"%s\"!", filename.c_str(), resolved.c_str()); + filename = cvt->locateResource(filename); + if (filename == "") + SLog(EError, "Unable to locate a resource -- aborting conversion."); + } else { + filename = resolved; + } + } + + + std::string targetPath = textureDir + path.leaf(); + + ref input = new FileStream(filename, FileStream::EReadOnly); + ref output = new FileStream(targetPath, FileStream::ETruncReadWrite); + input->copyTo(output); + output->close(); + input->close(); + + return targetPath; +} + +void addMaterial(GeometryConverter *cvt, std::ostream &os, const std::string &mtlName, + const std::string &texturesDir, const Spectrum &diffuseValue, + const std::string &diffuseMap) { + if (mtlName == "") + return; + SLog(EInfo, "Copying material \"%s\" ..", mtlName.c_str()); + os << "\t" << endl; + if (diffuseMap == "") { + Float r, g, b; + diffuseValue.toLinearRGB(r, g, b); + os << "\t\t" << endl; + } else { + os << "\t\t" << endl + << "\t\t\t" << endl + << "\t\t" << endl; + } + os << "\t" << endl << endl; +} + +void parseMaterials(GeometryConverter *cvt, std::ostream &os, const std::string &texturesDir, + const std::string &mtlFileName) { + SLog(EInfo, "Loading OBJ materials from \"%s\" ..", mtlFileName.c_str()); + std::ifstream is(mtlFileName.c_str()); + if (is.bad() || is.fail()) + SLog(EError, "Unexpected I/O error while accessing material file '%s'!", mtlFileName.c_str()); + std::string buf, line; + std::string mtlName; + Spectrum diffuse(0.0f); + std::string diffuseMap; + + while (is >> buf) { + if (buf == "newmtl") { + addMaterial(cvt, os, mtlName, texturesDir, diffuse, diffuseMap); + std::getline(is, line); + mtlName = line.substr(1, line.length()-2); + diffuse = Spectrum(0.0f); + diffuseMap = ""; + } else if (buf == "Kd") { + Float r, g, b; + is >> r >> g >> b; + if (cvt->m_srgb) + diffuse.fromSRGB(r, g, b); + else + diffuse.fromLinearRGB(r, g, b); + } else if (buf == "map_Kd") { + std::getline(is, line); + diffuseMap = line.substr(1, line.length()-2); + } else { + /* Ignore */ + std::getline(is, line); + } + } + addMaterial(cvt, os, mtlName, texturesDir, diffuse, diffuseMap); +} + void GeometryConverter::convertOBJ(const std::string &inputFile, std::ostream &os, const std::string &textureDirectory, const std::string &meshesDirectory) { + std::ifstream is(inputFile.c_str()); + if (is.bad() || is.fail()) + SLog(EError, "Could not open OBJ file '%s'!", inputFile.c_str()); + + os << "" << endl << endl; + os << "" << endl << endl; + os << "" << endl; + os << "\t" << endl << endl; + + std::string buf, line; + while (is >> buf) { + if (buf == "mtllib") { + std::getline(is, line); + std::string mtlName = line.substr(1, line.length()-2); + ref fRes = FileResolver::getInstance()->clone(); + fRes->addPathFromFile(fRes->resolveAbsolute(inputFile)); + std::string fullMtlName = fRes->resolve(mtlName); + if (FileStream::exists(fullMtlName)) + parseMaterials(this, os, textureDirectory, fullMtlName); + else + SLog(EWarn, "Could not find referenced material library '%s'", mtlName.c_str()); + } else { + /* Ignore */ + std::getline(is, line); + } + } + Properties objProps("obj"); objProps.setString("filename", inputFile); ref rootShape = static_cast (PluginManager::getInstance()-> createObject(Shape::m_theClass, objProps)); SAssert(rootShape->isCompound()); - os << "" << endl << endl; - os << "" << endl << endl; - os << "" << endl; - os << "\t" << endl << endl; int ctr = 0; while (true) { diff --git a/src/libcore/bitmap.cpp b/src/libcore/bitmap.cpp index 5c4492aa..425bd2b5 100644 --- a/src/libcore/bitmap.cpp +++ b/src/libcore/bitmap.cpp @@ -150,9 +150,11 @@ Bitmap::Bitmap(int width, int height, int bpp) m_data = static_cast(allocAligned(m_size)); } -Bitmap::Bitmap(EFileFormat format, Stream *stream) { +Bitmap::Bitmap(EFileFormat format, Stream *stream) : m_data(NULL) { if (format == EPNG) loadPNG(stream); + else if (format == ETGA) + loadTGA(stream); else if (format == EJPEG) loadJPEG(stream); else if (format == EEXR) @@ -189,6 +191,40 @@ void Bitmap::loadEXR(Stream *stream) { delete[] rgba; } +void Bitmap::loadTGA(Stream *stream) { + int headerSize = stream->readUChar(); + if (stream->readUChar() != 0) + Log(EError, "Invalid TGA format -- only raw (non-RLE encoded) RGB is supported for now"); + if (stream->readUChar() != 2) + Log(EError, "Invalid TGA format -- only raw (non-RLE encoded) RGB is supported for now"); + stream->setPos(8); + int x1 = stream->readShort(); + int y1 = stream->readShort(); + int x2 = stream->readShort(); + int y2 = stream->readShort(); + m_width = x2-x1; + m_height = y2-y1; + Log(EInfo, "Reading %ix%i TGA file", m_width, m_height); + + stream->setPos(16); + m_bpp = stream->readUChar(); + if (m_bpp != 24 && m_bpp != 32) + Log(EError, "Invalid TGA format -- only 24 or 32 bpp images are supported for now"); + + m_gamma = -1; + int channels = m_bpp / 8; + m_size = m_width * m_height * channels; + m_data = static_cast(allocAligned(m_size)); + stream->setPos(18 + headerSize); + stream->read(m_data, m_size); + + /* Convert BGR to RGB */ + for (size_t i=0; i fs = new FileStream(m_filename, FileStream::EReadOnly); std::string lower = toLowerCase(m_filename); - if (lower.find("jpg") != std::string::npos || lower.find("jpeg") != std::string::npos) { + if (endsWith(lower, ".jpg") || endsWith(lower, ".jpeg")) m_format = Bitmap::EJPEG; - } else if (lower.find("png") != std::string::npos) { + else if (endsWith(lower, ".png")) m_format = Bitmap::EPNG; - } else { + else if (endsWith(lower, ".tga")) + m_format = Bitmap::ETGA; + else Log(EError, "Cannot deduce the file type of '%s'!", m_filename.c_str()); - } ref bitmap = new Bitmap(m_format, fs); initializeFrom(bitmap); @@ -281,5 +282,5 @@ Shader *LDRTexture::createShader(Renderer *renderer) const { MTS_IMPLEMENT_CLASS_S(LDRTexture, false, Texture) MTS_IMPLEMENT_CLASS(LDRTextureShader, false, Shader) -MTS_EXPORT_PLUGIN(LDRTexture, "LDR texture (JPG/PNG)"); +MTS_EXPORT_PLUGIN(LDRTexture, "LDR texture (JPG/TGA/PNG)"); MTS_NAMESPACE_END