limited TGA loading support, better OBJ material import

metadata
Wenzel Jakob 2010-08-22 23:46:49 +02:00
parent 76e6ac6322
commit bd9ff72f4d
6 changed files with 203 additions and 22 deletions

View File

@ -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);

View File

@ -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<FileResolver> 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<FileStream> input = new FileStream(filename, FileStream::EReadOnly);
ref<FileStream> output = new FileStream(textureDir + leaf.c_str(), FileStream::ETruncReadWrite);
ref<FileStream> output = new FileStream(textureDir + path.leaf(), FileStream::ETruncReadWrite);
input->copyTo(output);
os << "\t<texture id=\"" << image.getId() << "\" type=\"ldrtexture\">" << endl;
os << "\t\t<string name=\"filename\" value=\"" << textureDir + leaf << "\"/>" << endl;
os << "\t\t<string name=\"filename\" value=\"" << textureDir + path.leaf() << "\"/>" << endl;
os << "\t</texture>" << endl << endl;
}

View File

@ -55,6 +55,8 @@ void help() {
<< "Syntax: mtsimport [options] <DAE/OBJ scene> <XML output file> [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 <num> 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<std::string> paths = tokenize(optarg, ";");
for (unsigned int i=0; i<paths.size(); ++i)
resolver->addPath(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<Logger> log = Thread::getThread()->getLogger();
log->setLogLevel(logLevel);
ConsoleGeometryConverter converter;
converter.setSRGB(srgb);

View File

@ -1,25 +1,147 @@
#define BOOST_FILESYSTEM_NO_LIB
#define BOOST_SYSTEM_NO_LIB
#include <mitsuba/core/plugin.h>
#include <mitsuba/core/fresolver.h>
#include <mitsuba/core/fstream.h>
#include <mitsuba/render/trimesh.h>
#include <boost/filesystem.hpp>
#include <fstream>
#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<filename.length(); ++i)
if (filename[i] == '/')
filename[i] = '\\';
#else
for (size_t i=0; i<filename.length(); ++i)
if (filename[i] == '\\')
filename[i] = '/';
#endif
boost::filesystem::path path = boost::filesystem::path(filename, boost::filesystem::native);
ref<FileResolver> 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<FileStream> input = new FileStream(filename, FileStream::EReadOnly);
ref<FileStream> 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<bsdf id=\"" << mtlName << "\" type=\"lambertian\">" << endl;
if (diffuseMap == "") {
Float r, g, b;
diffuseValue.toLinearRGB(r, g, b);
os << "\t\t<rgb name=\"reflectance\" value=\""
<< r << " " << g << " " << b << "\"/>" << endl;
} else {
os << "\t\t<texture name=\"reflectance\" type=\"ldrtexture\">" << endl
<< "\t\t\t<string name=\"filename\" value=\"" << copyTexture(cvt, texturesDir, diffuseMap) << "\"/>" << endl
<< "\t\t</texture>" << endl;
}
os << "\t</bsdf>" << 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 << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl << endl;
os << "<!--" << endl << endl;
os << "\tAutomatically converted from Wavefront OBJ" << endl << endl;
os << "-->" << endl << endl;
os << "<scene>" << endl;
os << "\t<integrator id=\"integrator\" type=\"direct\"/>" << 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<FileResolver> 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<Shape> rootShape = static_cast<Shape *> (PluginManager::getInstance()->
createObject(Shape::m_theClass, objProps));
SAssert(rootShape->isCompound());
os << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << endl << endl;
os << "<!--" << endl << endl;
os << "\tAutomatically converted from Wavefront OBJ" << endl << endl;
os << "-->" << endl << endl;
os << "<scene>" << endl;
os << "\t<integrator id=\"integrator\" type=\"direct\"/>" << endl << endl;
int ctr = 0;
while (true) {

View File

@ -150,9 +150,11 @@ Bitmap::Bitmap(int width, int height, int bpp)
m_data = static_cast<unsigned char *>(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<unsigned char *>(allocAligned(m_size));
stream->setPos(18 + headerSize);
stream->read(m_data, m_size);
/* Convert BGR to RGB */
for (size_t i=0; i<m_size; i += channels) {
uint8_t tmp = m_data[i];
m_data[i] = m_data[i+2];
m_data[i+2] = tmp;
}
}
void Bitmap::loadPNG(Stream *stream) {
png_structp png_ptr;
@ -357,7 +393,8 @@ void Bitmap::loadJPEG(Stream *stream) {
}
Bitmap::~Bitmap() {
freeAligned(m_data);
if (m_data)
freeAligned(m_data);
}
void Bitmap::clear() {

View File

@ -11,7 +11,7 @@
MTS_NAMESPACE_BEGIN
/**
* Gamma-corrected bitmap texture using the JPG or PNG file format
* Gamma-corrected bitmap texture using the JPG, TGA or PNG file format
*/
class LDRTexture : public Texture {
public:
@ -24,13 +24,14 @@ public:
ref<FileStream> 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> 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