limited TGA loading support, better OBJ material import
parent
76e6ac6322
commit
bd9ff72f4d
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue