mtsgui: ability to view multi-channel EXRs
parent
461827ec11
commit
9f9df009ef
|
@ -297,6 +297,22 @@ public:
|
||||||
EDivision
|
EDivision
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Describes a sub-layer of a multilayer bitmap (e.g. OpenEXR)
|
||||||
|
*
|
||||||
|
* A layer is defined as a named collection of bitmap channels and a pixel format
|
||||||
|
*
|
||||||
|
* This data structure is used by \ref Bitmap::getLayers()
|
||||||
|
*/
|
||||||
|
struct Layer {
|
||||||
|
/// Descriptive name of the bitmap layer
|
||||||
|
std::string name;
|
||||||
|
/// Pixel format that should be associated with underlying combination of bitmap channels
|
||||||
|
EPixelFormat format;
|
||||||
|
/// References to bitmap channels
|
||||||
|
std::vector<int> channels;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Create a bitmap of the specified type and allocate
|
* \brief Create a bitmap of the specified type and allocate
|
||||||
* the necessary amount of memory
|
* the necessary amount of memory
|
||||||
|
@ -813,9 +829,26 @@ public:
|
||||||
*/
|
*/
|
||||||
ref<Bitmap> extractChannels(Bitmap::EPixelFormat fmt, const std::vector<int> &channels) const;
|
ref<Bitmap> extractChannels(Bitmap::EPixelFormat fmt, const std::vector<int> &channels) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Extracts layer information from the bitmap
|
||||||
|
*
|
||||||
|
* This is a convenience function which analyzes the bitmap's
|
||||||
|
* channel names and extracts groups matching a name
|
||||||
|
* convention specified by the OpenEXR standard.
|
||||||
|
*
|
||||||
|
* A series of channel names referred to as
|
||||||
|
* 'diffuse.R', 'diffuse.B', and 'diffuse.G'
|
||||||
|
* will be identified as a single \ref Bitmap::ERGB "layer".
|
||||||
|
* This works for RGB[A]/XYZ[A], and Luminance[A] images
|
||||||
|
*/
|
||||||
|
std::vector<Layer> getLayers() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Split an multi-channel image buffer (e.g. from an OpenEXR image
|
* \brief Split an multi-channel image buffer (e.g. from an OpenEXR image
|
||||||
* with lots of AOVs) into group of RGB[A]/XYZ[A]/Luminance images
|
* with lots of AOVs) into its constituent layers
|
||||||
|
*
|
||||||
|
* This operation internally calls \ref getLayers() to extract bitmap
|
||||||
|
* layers followed by one or more calls to \ref extractChannels()
|
||||||
*/
|
*/
|
||||||
std::map<std::string, Bitmap *> split() const;
|
std::map<std::string, Bitmap *> split() const;
|
||||||
|
|
||||||
|
|
|
@ -1875,32 +1875,34 @@ void Bitmap::tonemapReinhard(Float &logAvgLuminance, Float &maxLuminance, Float
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Bitmap::Layer> Bitmap::getLayers() const {
|
||||||
std::map<std::string, Bitmap *> Bitmap::split() const {
|
|
||||||
typedef std::map<std::string, int> ChannelMap;
|
typedef std::map<std::string, int> ChannelMap;
|
||||||
std::map<std::string, Bitmap *> result;
|
|
||||||
if (m_channelNames.empty())
|
if (m_channelNames.empty())
|
||||||
Log(EError, "Bitmap::split(): color channel names not available!");
|
Log(EError, "Bitmap::getLayers(): required color channel names were not available!");
|
||||||
|
|
||||||
ChannelMap channels;
|
ChannelMap channels;
|
||||||
for (size_t i=0; i<m_channelNames.size(); ++i)
|
for (size_t i=0; i<m_channelNames.size(); ++i)
|
||||||
channels[boost::to_lower_copy(m_channelNames[i])] = (int) i;
|
channels[boost::to_lower_copy(m_channelNames[i])] = (int) i;
|
||||||
|
|
||||||
|
std::vector<Layer> layers;
|
||||||
for (size_t i=0; i<m_channelNames.size(); ++i) {
|
for (size_t i=0; i<m_channelNames.size(); ++i) {
|
||||||
std::string name = boost::to_lower_copy(m_channelNames[i]);
|
std::string name = boost::to_lower_copy(m_channelNames[i]);
|
||||||
if (channels.find(name) == channels.end())
|
if (channels.find(name) == channels.end())
|
||||||
continue;
|
continue;
|
||||||
std::string prefix = "";
|
std::string prefix = name;
|
||||||
char postfix = '\0';
|
char postfix = '\0';
|
||||||
|
Layer layer;
|
||||||
|
|
||||||
if (!name.empty()) {
|
layer.name = m_channelNames[i];
|
||||||
prefix = name.substr(0, name.length()-1);
|
if (name.length() == 1) {
|
||||||
postfix = name[name.length()-1];
|
prefix = layer.name = "";
|
||||||
|
postfix = name[name.length() - 1];
|
||||||
|
} if (name.length() >= 3 && name[name.length()-2] == '.') {
|
||||||
|
prefix = name.substr(0, name.length() - 1);
|
||||||
|
layer.name = layer.name.substr(0, layer.name.length() - 2);
|
||||||
|
postfix = name[name.length() - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> extractChannels;
|
|
||||||
EPixelFormat extractFormat;
|
|
||||||
|
|
||||||
ChannelMap::iterator
|
ChannelMap::iterator
|
||||||
itR = channels.find(prefix + "r"),
|
itR = channels.find(prefix + "r"),
|
||||||
itG = channels.find(prefix + "g"),
|
itG = channels.find(prefix + "g"),
|
||||||
|
@ -1915,68 +1917,75 @@ std::map<std::string, Bitmap *> Bitmap::split() const {
|
||||||
bool maybeY = postfix == 'y' || postfix == 'a';
|
bool maybeY = postfix == 'y' || postfix == 'a';
|
||||||
|
|
||||||
if (maybeRGB && itR != channels.end() && itG != channels.end() && itB != channels.end()) {
|
if (maybeRGB && itR != channels.end() && itG != channels.end() && itB != channels.end()) {
|
||||||
extractFormat = ERGB;
|
layer.format = ERGB;
|
||||||
extractChannels.push_back(itR->second);
|
layer.channels.push_back(itR->second);
|
||||||
extractChannels.push_back(itG->second);
|
layer.channels.push_back(itG->second);
|
||||||
extractChannels.push_back(itB->second);
|
layer.channels.push_back(itB->second);
|
||||||
if (itA != channels.end()) {
|
if (itA != channels.end()) {
|
||||||
extractFormat = ERGBA;
|
layer.format = ERGBA;
|
||||||
extractChannels.push_back(itA->second);
|
layer.channels.push_back(itA->second);
|
||||||
channels.erase(prefix + "a");
|
channels.erase(prefix + "a");
|
||||||
}
|
}
|
||||||
channels.erase(prefix + "r");
|
channels.erase(prefix + "r");
|
||||||
channels.erase(prefix + "g");
|
channels.erase(prefix + "g");
|
||||||
channels.erase(prefix + "b");
|
channels.erase(prefix + "b");
|
||||||
} else if (maybeXYZ && itX != channels.end() && itY != channels.end() && itZ != channels.end()) {
|
} else if (maybeXYZ && itX != channels.end() && itY != channels.end() && itZ != channels.end()) {
|
||||||
extractFormat = EXYZ;
|
layer.format = EXYZ;
|
||||||
extractChannels.push_back(itX->second);
|
layer.channels.push_back(itX->second);
|
||||||
extractChannels.push_back(itY->second);
|
layer.channels.push_back(itY->second);
|
||||||
extractChannels.push_back(itZ->second);
|
layer.channels.push_back(itZ->second);
|
||||||
if (itA != channels.end()) {
|
if (itA != channels.end()) {
|
||||||
extractFormat = EXYZA;
|
layer.format = EXYZA;
|
||||||
extractChannels.push_back(itA->second);
|
layer.channels.push_back(itA->second);
|
||||||
channels.erase(prefix + "a");
|
channels.erase(prefix + "a");
|
||||||
}
|
}
|
||||||
channels.erase(prefix + "x");
|
channels.erase(prefix + "x");
|
||||||
channels.erase(prefix + "y");
|
channels.erase(prefix + "y");
|
||||||
channels.erase(prefix + "z");
|
channels.erase(prefix + "z");
|
||||||
} else if (maybeY && itY != channels.end()) {
|
} else if (maybeY && itY != channels.end()) {
|
||||||
extractFormat = ELuminance;
|
layer.format = ELuminance;
|
||||||
extractChannels.push_back(itY->second);
|
layer.channels.push_back(itY->second);
|
||||||
if (itA != channels.end()) {
|
if (itA != channels.end()) {
|
||||||
extractFormat = ELuminanceAlpha;
|
layer.format = ELuminanceAlpha;
|
||||||
extractChannels.push_back(itA->second);
|
layer.channels.push_back(itA->second);
|
||||||
channels.erase(prefix + "a");
|
channels.erase(prefix + "a");
|
||||||
}
|
}
|
||||||
channels.erase(prefix + "y");
|
channels.erase(prefix + "y");
|
||||||
} else {
|
} else {
|
||||||
extractFormat = ELuminance;
|
if (layer.name.empty())
|
||||||
extractChannels.push_back((int) i);
|
layer.name = m_channelNames[i];
|
||||||
|
layer.format = ELuminance;
|
||||||
|
layer.channels.push_back((int) i);
|
||||||
channels.erase(name);
|
channels.erase(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layers.push_back(layer);
|
||||||
|
}
|
||||||
|
return layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, Bitmap *> Bitmap::split() const {
|
||||||
|
std::map<std::string, Bitmap *> result;
|
||||||
|
|
||||||
|
std::vector<Layer> layers = getLayers();
|
||||||
|
for (size_t i=0; i<layers.size(); ++i) {
|
||||||
|
const Layer &layer = layers[i];
|
||||||
std::vector<std::string> channelNames;
|
std::vector<std::string> channelNames;
|
||||||
for (size_t j=0; j<extractChannels.size(); ++j)
|
for (size_t j=0; j<layer.channels.size(); ++j)
|
||||||
channelNames.push_back(m_channelNames[extractChannels[j]]);
|
channelNames.push_back(m_channelNames[layer.channels[j]]);
|
||||||
|
|
||||||
Bitmap *bitmap = NULL;
|
Bitmap *bitmap = NULL;
|
||||||
{
|
{
|
||||||
ref<Bitmap> _bitmap = this->extractChannels(extractFormat, extractChannels);
|
ref<Bitmap> _bitmap = this->extractChannels(layer.format, layer.channels);
|
||||||
bitmap = _bitmap.get();
|
bitmap = _bitmap.get();
|
||||||
bitmap->incRef();
|
bitmap->incRef();
|
||||||
}
|
}
|
||||||
bitmap->decRef(false);
|
bitmap->decRef(false);
|
||||||
bitmap->setChannelNames(channelNames);
|
bitmap->setChannelNames(channelNames);
|
||||||
|
|
||||||
prefix = m_channelNames[i];
|
if (result.find(layer.name) != result.end())
|
||||||
if (!prefix.empty())
|
Log(EError, "Internal error -- encountered two layers with the same name \"%s\"", layer.name.c_str());
|
||||||
prefix = prefix.substr(0, prefix.length()-1);
|
result[layer.name] = bitmap;
|
||||||
if (!prefix.empty() && prefix[prefix.length()-1] == '.')
|
|
||||||
prefix = prefix.substr(0, prefix.length()-1);
|
|
||||||
|
|
||||||
if (result.find(prefix) != result.end())
|
|
||||||
Log(EError, "Internal error -- encountered two sub-images with the same prefix");
|
|
||||||
result[prefix] = bitmap;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -771,7 +771,8 @@ void GLRenderer::drawText(const Point2i &_pos,
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
font->getTexture()->bind();
|
font->getTexture()->bind();
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||||
|
// glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
|
||||||
Point2i pos(_pos);
|
Point2i pos(_pos);
|
||||||
int initial = pos.x;
|
int initial = pos.x;
|
||||||
|
|
||||||
|
|
|
@ -1110,7 +1110,7 @@ void TriMesh::writePLY(const fs::path &path) const {
|
||||||
*ptr += (uint8_t) std::max(0.0f, std::min(255.0f, (float) m_colors[i][2] * 255.0f + 0.5f));
|
*ptr += (uint8_t) std::max(0.0f, std::min(255.0f, (float) m_colors[i][2] * 255.0f + 0.5f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Assert(ptr-vertexStorage == vertexStorageSize);
|
Assert((size_t) (ptr-vertexStorage) == vertexStorageSize);
|
||||||
os.write((const char *) vertexStorage, vertexStorageSize);
|
os.write((const char *) vertexStorage, vertexStorageSize);
|
||||||
delete[] vertexStorage;
|
delete[] vertexStorage;
|
||||||
|
|
||||||
|
@ -1122,7 +1122,7 @@ void TriMesh::writePLY(const fs::path &path) const {
|
||||||
memcpy(ptr, &m_triangles[i], sizeof(Triangle));
|
memcpy(ptr, &m_triangles[i], sizeof(Triangle));
|
||||||
ptr += sizeof(Triangle);
|
ptr += sizeof(Triangle);
|
||||||
}
|
}
|
||||||
Assert(ptr-faceStorage == faceStorageSize);
|
Assert((size_t) (ptr-faceStorage) == faceStorageSize);
|
||||||
os.write((const char *) faceStorage, faceStorageSize);
|
os.write((const char *) faceStorage, faceStorageSize);
|
||||||
delete[] faceStorage;
|
delete[] faceStorage;
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,9 @@ struct SceneContext {
|
||||||
float progress;
|
float progress;
|
||||||
QString eta, progressName;
|
QString eta, progressName;
|
||||||
ref<Bitmap> framebuffer;
|
ref<Bitmap> framebuffer;
|
||||||
|
std::vector<std::pair<std::string, Bitmap*> > layers;
|
||||||
std::set<VisualWorkUnit, block_comparator> workUnits;
|
std::set<VisualWorkUnit, block_comparator> workUnits;
|
||||||
|
int currentLayer;
|
||||||
EMode mode, cancelMode;
|
EMode mode, cancelMode;
|
||||||
Float gamma, exposure, clamping;
|
Float gamma, exposure, clamping;
|
||||||
bool srgb;
|
bool srgb;
|
||||||
|
@ -209,6 +211,7 @@ struct SceneContext {
|
||||||
|
|
||||||
SceneContext() : scene(NULL), sceneResID(-1),
|
SceneContext() : scene(NULL), sceneResID(-1),
|
||||||
renderJob(NULL), wasRendering(false),
|
renderJob(NULL), wasRendering(false),
|
||||||
|
currentLayer(0),
|
||||||
selectionMode(ENothing),
|
selectionMode(ENothing),
|
||||||
selectedShape(NULL) { }
|
selectedShape(NULL) { }
|
||||||
|
|
||||||
|
|
|
@ -220,6 +220,14 @@ void GLWidget::setScene(SceneContext *context) {
|
||||||
m_movementTimer->stop();
|
m_movementTimer->stop();
|
||||||
m_context = context;
|
m_context = context;
|
||||||
|
|
||||||
|
if (context && context->layers.size() > 0) {
|
||||||
|
m_statusMessage =
|
||||||
|
formatString("Showing layer \"%s\" (%i/%i); use '[' and ']' to switch.",
|
||||||
|
m_context->layers[m_context->currentLayer].first.c_str(),
|
||||||
|
m_context->currentLayer+1, m_context->layers.size());
|
||||||
|
m_statusTimer->reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (context && context->scene == NULL)
|
if (context && context->scene == NULL)
|
||||||
context = NULL;
|
context = NULL;
|
||||||
|
|
||||||
|
@ -503,7 +511,9 @@ void GLWidget::keyPressEvent(QKeyEvent *event) {
|
||||||
emit stopRendering();
|
emit stopRendering();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->isAutoRepeat() || !m_context)
|
if (!m_context ||
|
||||||
|
(event->isAutoRepeat() && event->key() != Qt::Key_BracketLeft &&
|
||||||
|
event->key() != Qt::Key_BracketRight))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (event->key()) {
|
switch (event->key()) {
|
||||||
|
@ -526,7 +536,15 @@ void GLWidget::keyPressEvent(QKeyEvent *event) {
|
||||||
case Qt::Key_Down:
|
case Qt::Key_Down:
|
||||||
m_downKeyDown = true; break;
|
m_downKeyDown = true; break;
|
||||||
case Qt::Key_BracketLeft:
|
case Qt::Key_BracketLeft:
|
||||||
if (m_context->showKDTree) {
|
if (m_context->layers.size() > 0) {
|
||||||
|
m_context->currentLayer = std::max(0, m_context->currentLayer-1);
|
||||||
|
m_context->framebuffer = m_context->layers[m_context->currentLayer].second->convert(Bitmap::ERGBA, Bitmap::EFloat32);
|
||||||
|
m_statusMessage =
|
||||||
|
formatString("Showing layer \"%s\" (%i/%i); use '[' and ']' to switch.",
|
||||||
|
m_context->layers[m_context->currentLayer].first.c_str(),
|
||||||
|
m_context->currentLayer+1, m_context->layers.size());
|
||||||
|
m_statusTimer->reset();
|
||||||
|
} else if (m_context->showKDTree) {
|
||||||
m_context->shownKDTreeLevel
|
m_context->shownKDTreeLevel
|
||||||
= std::max(0, m_context->shownKDTreeLevel - 1);
|
= std::max(0, m_context->shownKDTreeLevel - 1);
|
||||||
updateGL();
|
updateGL();
|
||||||
|
@ -534,7 +552,15 @@ void GLWidget::keyPressEvent(QKeyEvent *event) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Qt::Key_BracketRight:
|
case Qt::Key_BracketRight:
|
||||||
if (m_context->showKDTree) {
|
if (m_context->layers.size() > 0) {
|
||||||
|
m_context->currentLayer = std::min((int) m_context->layers.size() - 1, m_context->currentLayer+1);
|
||||||
|
m_context->framebuffer = m_context->layers[m_context->currentLayer].second->convert(Bitmap::ERGBA, Bitmap::EFloat32);
|
||||||
|
m_statusMessage =
|
||||||
|
formatString("Showing layer \"%s\" (%i/%i); use '[' and ']' to switch.",
|
||||||
|
m_context->layers[m_context->currentLayer].first.c_str(),
|
||||||
|
m_context->currentLayer+1, m_context->layers.size());
|
||||||
|
m_statusTimer->reset();
|
||||||
|
} else if (m_context->showKDTree) {
|
||||||
m_context->shownKDTreeLevel++;
|
m_context->shownKDTreeLevel++;
|
||||||
updateGL();
|
updateGL();
|
||||||
return;
|
return;
|
||||||
|
@ -1215,11 +1241,17 @@ void GLWidget::paintGL() {
|
||||||
if (m_context->mode == EPreview) {
|
if (m_context->mode == EPreview) {
|
||||||
m_preview->releaseBuffer(entry);
|
m_preview->releaseBuffer(entry);
|
||||||
if (m_context->showKDTree) {
|
if (m_context->showKDTree) {
|
||||||
|
std::string message = "kd-tree visualization mode\nPress '[' "
|
||||||
|
"and ']' to change the shown level";
|
||||||
|
Vector2i size = m_font->getSize(message);
|
||||||
int pos = m_statusMessage.empty() ? 10 : 30;
|
int pos = m_statusMessage.empty() ? 10 : 30;
|
||||||
|
m_renderer->setBlendMode(Renderer::EBlendAlpha);
|
||||||
|
m_renderer->setColor(Spectrum(0.0f), 0.5f);
|
||||||
|
m_renderer->drawFilledRectangle(Point2i(5, pos-2), Point2i(15, pos+5)+size);
|
||||||
|
m_renderer->setBlendMode(Renderer::EBlendNone);
|
||||||
m_renderer->setColor(Spectrum(1.0f));
|
m_renderer->setColor(Spectrum(1.0f));
|
||||||
m_renderer->drawText(Point2i(10, pos), m_font,
|
m_renderer->setColor(Spectrum(1.0f));
|
||||||
formatString("kd-tree visualization mode\nPress '[' "
|
m_renderer->drawText(Point2i(10, pos), m_font, message);
|
||||||
"and ']' to change the shown level"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,7 +1276,15 @@ void GLWidget::paintGL() {
|
||||||
m_statusMessage = "Camera type is incompatible with the OpenGL preview!";
|
m_statusMessage = "Camera type is incompatible with the OpenGL preview!";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_statusMessage.empty() && m_context->mode == EPreview) {
|
if (!m_statusMessage.empty() && (m_context->mode == EPreview
|
||||||
|
|| (m_context->mode == ERender && m_context->scene == NULL))) {
|
||||||
|
m_renderer->setDepthTest(false);
|
||||||
|
Vector2i size = m_font->getSize(m_statusMessage);
|
||||||
|
m_renderer->setBlendMode(Renderer::EBlendAlpha);
|
||||||
|
m_renderer->setColor(Spectrum(0.0f), 0.5f);
|
||||||
|
m_renderer->drawFilledRectangle(Point2i(5, 7), Point2i(15, 15)+size);
|
||||||
|
m_renderer->setBlendMode(Renderer::EBlendNone);
|
||||||
|
m_renderer->setColor(Spectrum(1.0f));
|
||||||
m_renderer->drawText(Point2i(10, 10), m_font, m_statusMessage);
|
m_renderer->drawText(Point2i(10, 10), m_font, m_statusMessage);
|
||||||
if (m_statusTimer->getMilliseconds() > 2000)
|
if (m_statusTimer->getMilliseconds() > 2000)
|
||||||
m_statusMessage = "";
|
m_statusMessage = "";
|
||||||
|
|
|
@ -398,7 +398,7 @@ bool MainWindow::initWorkersProcessArgv() {
|
||||||
scheduler->registerWorker(new LocalWorker(-1, formatString("wrk%i", 0), m_workerPriority));
|
scheduler->registerWorker(new LocalWorker(-1, formatString("wrk%i", 0), m_workerPriority));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<toBeLoaded.size(); ++i)
|
for (size_t i=0; i<toBeLoaded.size(); ++i)
|
||||||
loadFile(toBeLoaded[i].first, toBeLoaded[i].second);
|
loadFile(toBeLoaded[i].first, toBeLoaded[i].second);
|
||||||
|
|
||||||
scheduler->start();
|
scheduler->start();
|
||||||
|
@ -2157,6 +2157,10 @@ SceneContext::SceneContext(SceneContext *ctx) {
|
||||||
selectionMode = ctx->selectionMode;
|
selectionMode = ctx->selectionMode;
|
||||||
originalSize = ctx->originalSize;
|
originalSize = ctx->originalSize;
|
||||||
doc = ctx->doc.cloneNode(true).toDocument();
|
doc = ctx->doc.cloneNode(true).toDocument();
|
||||||
|
layers = ctx->layers;
|
||||||
|
for (size_t i=0; i<layers.size(); ++i)
|
||||||
|
layers[i].second->incRef();
|
||||||
|
currentLayer = ctx->currentLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneContext::~SceneContext() {
|
SceneContext::~SceneContext() {
|
||||||
|
@ -2166,6 +2170,8 @@ SceneContext::~SceneContext() {
|
||||||
previewBuffer.buffer->decRef();
|
previewBuffer.buffer->decRef();
|
||||||
if (previewBuffer.sync)
|
if (previewBuffer.sync)
|
||||||
previewBuffer.sync->decRef();
|
previewBuffer.sync->decRef();
|
||||||
|
for (size_t i=0; i<layers.size(); ++i)
|
||||||
|
layers[i].second->decRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
int SceneContext::detectPathLength() const {
|
int SceneContext::detectPathLength() const {
|
||||||
|
|
|
@ -65,12 +65,25 @@ void SceneLoader::run() {
|
||||||
m_result->toneMappingMethod = (EToneMappingMethod) settings.value("preview_toneMappingMethod", EGamma).toInt();
|
m_result->toneMappingMethod = (EToneMappingMethod) settings.value("preview_toneMappingMethod", EGamma).toInt();
|
||||||
m_result->diffuseSources = settings.value("preview_diffuseSources", true).toBool();
|
m_result->diffuseSources = settings.value("preview_diffuseSources", true).toBool();
|
||||||
m_result->diffuseReceivers = settings.value("preview_diffuseReceivers", false).toBool();
|
m_result->diffuseReceivers = settings.value("preview_diffuseReceivers", false).toBool();
|
||||||
|
m_result->currentLayer = 0;
|
||||||
|
|
||||||
if (suffix == "exr" || suffix == "png" || suffix == "jpg" || suffix == "jpeg" ||
|
if (suffix == "exr" || suffix == "png" || suffix == "jpg" || suffix == "jpeg" ||
|
||||||
suffix == "hdr" || suffix == "rgbe" || suffix == "pfm" || suffix == "ppm") {
|
suffix == "hdr" || suffix == "rgbe" || suffix == "pfm" || suffix == "ppm") {
|
||||||
/* This is an image, not a scene */
|
/* This is an image, not a scene */
|
||||||
ref<FileStream> fs = new FileStream(toFsPath(m_filename), FileStream::EReadOnly);
|
ref<FileStream> fs = new FileStream(toFsPath(m_filename), FileStream::EReadOnly);
|
||||||
ref<Bitmap> bitmap = new Bitmap(Bitmap::EAuto, fs);
|
ref<Bitmap> bitmap = new Bitmap(Bitmap::EAuto, fs, (suffix == "exr") ? "*" : "");
|
||||||
|
|
||||||
|
if (suffix == "exr" && bitmap->getLayers().size() > 1) {
|
||||||
|
std::map<std::string, Bitmap*> bitmaps = bitmap->split();
|
||||||
|
for (std::map<std::string, Bitmap *>::iterator it = bitmaps.begin(); it != bitmaps.end(); ++it) {
|
||||||
|
std::string name = it->first;
|
||||||
|
Bitmap *layer = it->second;
|
||||||
|
layer->incRef();
|
||||||
|
m_result->layers.push_back(std::make_pair(name, layer));
|
||||||
|
}
|
||||||
|
bitmap = m_result->layers[m_result->currentLayer].second;
|
||||||
|
}
|
||||||
|
|
||||||
bitmap = bitmap->convert(Bitmap::ERGBA, Bitmap::EFloat32);
|
bitmap = bitmap->convert(Bitmap::ERGBA, Bitmap::EFloat32);
|
||||||
|
|
||||||
m_result->mode = ERender;
|
m_result->mode = ERender;
|
||||||
|
|
Loading…
Reference in New Issue