minor improvements to the heightfield shape
parent
30a665bead
commit
6e7ce77165
|
@ -25,6 +25,8 @@
|
||||||
#include <mitsuba/render/trimesh.h>
|
#include <mitsuba/render/trimesh.h>
|
||||||
#include <mitsuba/render/texture.h>
|
#include <mitsuba/render/texture.h>
|
||||||
#include <mitsuba/core/bitmap.h>
|
#include <mitsuba/core/bitmap.h>
|
||||||
|
#include <mitsuba/core/fresolver.h>
|
||||||
|
#include <mitsuba/core/fstream.h>
|
||||||
#include <mitsuba/core/statistics.h>
|
#include <mitsuba/core/statistics.h>
|
||||||
#include <mitsuba/core/timer.h>
|
#include <mitsuba/core/timer.h>
|
||||||
|
|
||||||
|
@ -81,6 +83,13 @@ namespace {
|
||||||
* this parameter specifies the resolution at which it should
|
* this parameter specifies the resolution at which it should
|
||||||
* be rasterized to create a height field made of bilinear patches.
|
* be rasterized to create a height field made of bilinear patches.
|
||||||
* }
|
* }
|
||||||
|
* \parameter{scale}{\Float}{Scale factor that is applied to the height field
|
||||||
|
* values\default{No scaling, i.e. \code{1}}
|
||||||
|
* }
|
||||||
|
* \parameter{filename}{\String}{
|
||||||
|
* File name of an image file containing height field values. Alternatively,
|
||||||
|
* a nested texture can be provided (see below).
|
||||||
|
* }
|
||||||
* \parameter{\Unnamed}{\Texture}{
|
* \parameter{\Unnamed}{\Texture}{
|
||||||
* A nested texture that specifies the height field values. This
|
* A nested texture that specifies the height field values. This
|
||||||
* could be a bitmap-backed texture or one that is procedurally defined.
|
* could be a bitmap-backed texture or one that is procedurally defined.
|
||||||
|
@ -104,13 +113,8 @@ namespace {
|
||||||
*
|
*
|
||||||
* \begin{xml}[caption={Declaring a height field from a monochromatic scaled bitmap texture}, label=lst:heightfield-bitmap]
|
* \begin{xml}[caption={Declaring a height field from a monochromatic scaled bitmap texture}, label=lst:heightfield-bitmap]
|
||||||
* <shape type="heightfield">
|
* <shape type="heightfield">
|
||||||
* <texture type="scale">
|
* <string name="filename" value="mountain_profile.exr"/>
|
||||||
* <float name="scale" value="0.5"/>
|
* <float name="scale" value="0.5"/>
|
||||||
* <texture type="bitmap">
|
|
||||||
* <float name="gamma" value="1"/>
|
|
||||||
* <string name="filename" value="mountain_profile.png"/>
|
|
||||||
* </texture>
|
|
||||||
* </texture>
|
|
||||||
* </shape>
|
* </shape>
|
||||||
* \end{xml}
|
* \end{xml}
|
||||||
*/
|
*/
|
||||||
|
@ -126,6 +130,11 @@ public:
|
||||||
m_objectToWorld = props.getTransform("toWorld", Transform());
|
m_objectToWorld = props.getTransform("toWorld", Transform());
|
||||||
m_shadingNormals = props.getBoolean("shadingNormals", true);
|
m_shadingNormals = props.getBoolean("shadingNormals", true);
|
||||||
m_flipNormals = props.getBoolean("flipNormals", false);
|
m_flipNormals = props.getBoolean("flipNormals", false);
|
||||||
|
m_scale = props.getFloat("scale", 1);
|
||||||
|
|
||||||
|
m_filename = props.getString("filename", "");
|
||||||
|
if (!m_filename.empty())
|
||||||
|
m_filename = Thread::getThread()->getFileResolver()->resolve(m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
Heightfield(Stream *stream, InstanceManager *manager)
|
Heightfield(Stream *stream, InstanceManager *manager)
|
||||||
|
@ -134,6 +143,8 @@ public:
|
||||||
m_objectToWorld = Transform(stream);
|
m_objectToWorld = Transform(stream);
|
||||||
m_shadingNormals = stream->readBool();
|
m_shadingNormals = stream->readBool();
|
||||||
m_flipNormals = stream->readBool();
|
m_flipNormals = stream->readBool();
|
||||||
|
m_scale = stream->readFloat();
|
||||||
|
m_filename = stream->readString();
|
||||||
m_dataSize = Vector2i(stream);
|
m_dataSize = Vector2i(stream);
|
||||||
size_t size = (size_t) m_dataSize.x * (size_t) m_dataSize.y;
|
size_t size = (size_t) m_dataSize.x * (size_t) m_dataSize.y;
|
||||||
m_data = (Float *) allocAligned(size * sizeof(Float));
|
m_data = (Float *) allocAligned(size * sizeof(Float));
|
||||||
|
@ -162,6 +173,8 @@ public:
|
||||||
m_objectToWorld.serialize(stream);
|
m_objectToWorld.serialize(stream);
|
||||||
stream->writeBool(m_shadingNormals);
|
stream->writeBool(m_shadingNormals);
|
||||||
stream->writeBool(m_flipNormals);
|
stream->writeBool(m_flipNormals);
|
||||||
|
stream->writeFloat(m_scale);
|
||||||
|
stream->writeString(m_filename.string());
|
||||||
m_dataSize.serialize(stream);
|
m_dataSize.serialize(stream);
|
||||||
stream->writeFloatArray(m_data, (size_t) m_dataSize.x * (size_t) m_dataSize.y);
|
stream->writeFloatArray(m_data, (size_t) m_dataSize.x * (size_t) m_dataSize.y);
|
||||||
}
|
}
|
||||||
|
@ -479,34 +492,43 @@ public:
|
||||||
if (m_minmax)
|
if (m_minmax)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_bitmap.get()) {
|
if (!m_filename.empty()) {
|
||||||
m_dataSize = m_bitmap->getSize();
|
if (m_bitmap.get())
|
||||||
if (m_dataSize.x < 2) m_dataSize.x = 2;
|
Log(EError, "Cannot specify a file name and a nested texture at the same time!");
|
||||||
if (m_dataSize.y < 2) m_dataSize.y = 2;
|
ref<FileStream> fs = new FileStream(m_filename, FileStream::EReadOnly);
|
||||||
if (!isPowerOfTwo(m_dataSize.x - 1)) m_dataSize.x = (int) roundToPowerOfTwo((uint32_t) m_dataSize.x - 1) + 1;
|
m_bitmap = new Bitmap(Bitmap::EAuto, fs);
|
||||||
if (!isPowerOfTwo(m_dataSize.y - 1)) m_dataSize.y = (int) roundToPowerOfTwo((uint32_t) m_dataSize.y - 1) + 1;
|
} else if (!m_bitmap.get()) {
|
||||||
|
Log(EError, "A height field texture must be specified (either as a nested texture, or using the 'filename' parameter)");
|
||||||
if (m_bitmap->getSize() != m_dataSize) {
|
|
||||||
m_bitmap = m_bitmap->convert(Bitmap::ELuminance, Bitmap::EFloat);
|
|
||||||
|
|
||||||
Log(EInfo, "Resampling heightfield texture from %ix%i to %ix%i ..",
|
|
||||||
m_bitmap->getWidth(), m_bitmap->getHeight(), m_dataSize.x, m_dataSize.y);
|
|
||||||
|
|
||||||
m_bitmap = m_bitmap->resample(m_rfilter, ReconstructionFilter::EClamp,
|
|
||||||
ReconstructionFilter::EClamp, m_dataSize,
|
|
||||||
-std::numeric_limits<Float>::infinity(),
|
|
||||||
std::numeric_limits<Float>::infinity());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = (size_t) m_dataSize.x * (size_t) m_dataSize.y * sizeof(Float);
|
|
||||||
m_data = (Float *) allocAligned(size);
|
|
||||||
m_bitmap->convert(m_data, Bitmap::ELuminance, Bitmap::EFloat);
|
|
||||||
|
|
||||||
m_objectToWorld = m_objectToWorld * Transform::translate(Vector(-1, -1, 0)) * Transform::scale(Vector(
|
|
||||||
(Float) 2 / (m_dataSize.x-1),
|
|
||||||
(Float) 2 / (m_dataSize.y-1), 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dataSize = m_bitmap->getSize();
|
||||||
|
if (m_dataSize.x < 2) m_dataSize.x = 2;
|
||||||
|
if (m_dataSize.y < 2) m_dataSize.y = 2;
|
||||||
|
if (!isPowerOfTwo(m_dataSize.x - 1)) m_dataSize.x = (int) roundToPowerOfTwo((uint32_t) m_dataSize.x - 1) + 1;
|
||||||
|
if (!isPowerOfTwo(m_dataSize.y - 1)) m_dataSize.y = (int) roundToPowerOfTwo((uint32_t) m_dataSize.y - 1) + 1;
|
||||||
|
|
||||||
|
if (m_bitmap->getSize() != m_dataSize) {
|
||||||
|
m_bitmap = m_bitmap->convert(Bitmap::ELuminance, Bitmap::EFloat);
|
||||||
|
|
||||||
|
Log(EInfo, "Resampling heightfield texture from %ix%i to %ix%i ..",
|
||||||
|
m_bitmap->getWidth(), m_bitmap->getHeight(), m_dataSize.x, m_dataSize.y);
|
||||||
|
|
||||||
|
m_bitmap = m_bitmap->resample(m_rfilter, ReconstructionFilter::EClamp,
|
||||||
|
ReconstructionFilter::EClamp, m_dataSize,
|
||||||
|
-std::numeric_limits<Float>::infinity(),
|
||||||
|
std::numeric_limits<Float>::infinity());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = (size_t) m_dataSize.x * (size_t) m_dataSize.y * sizeof(Float);
|
||||||
|
m_data = (Float *) allocAligned(size);
|
||||||
|
m_bitmap->convert(m_data, Bitmap::ELuminance, Bitmap::EFloat, 1.0f, m_scale);
|
||||||
|
|
||||||
|
m_objectToWorld = m_objectToWorld * Transform::translate(Vector(-1, -1, 0)) * Transform::scale(Vector(
|
||||||
|
(Float) 2 / (m_dataSize.x-1),
|
||||||
|
(Float) 2 / (m_dataSize.y-1), 1));
|
||||||
|
|
||||||
|
m_bitmap = NULL;
|
||||||
|
|
||||||
size_t storageSize = (size_t) m_dataSize.x * (size_t) m_dataSize.y * sizeof(Float);
|
size_t storageSize = (size_t) m_dataSize.x * (size_t) m_dataSize.y * sizeof(Float);
|
||||||
Log(EInfo, "Building acceleration data structure for %ix%i height field ..", m_dataSize.x, m_dataSize.y);
|
Log(EInfo, "Building acceleration data structure for %ix%i height field ..", m_dataSize.x, m_dataSize.y);
|
||||||
|
|
||||||
|
@ -525,7 +547,8 @@ public:
|
||||||
m_blockSizeF[0] = Vector2(1, 1);
|
m_blockSizeF[0] = Vector2(1, 1);
|
||||||
m_invSize = Vector2((Float) 1 / m_levelSize[0].x, (Float) 1 / m_levelSize[0].y);
|
m_invSize = Vector2((Float) 1 / m_levelSize[0].x, (Float) 1 / m_levelSize[0].y);
|
||||||
m_surfaceArea = 0;
|
m_surfaceArea = 0;
|
||||||
size_t size = (size_t) m_levelSize[0].x * (size_t) m_levelSize[0].y * sizeof(Interval);
|
|
||||||
|
size = (size_t) m_levelSize[0].x * (size_t) m_levelSize[0].y * sizeof(Interval);
|
||||||
m_minmax[0] = (Interval *) allocAligned(size);
|
m_minmax[0] = (Interval *) allocAligned(size);
|
||||||
storageSize += size;
|
storageSize += size;
|
||||||
|
|
||||||
|
@ -724,6 +747,8 @@ private:
|
||||||
AABB m_dataAABB;
|
AABB m_dataAABB;
|
||||||
bool m_shadingNormals;
|
bool m_shadingNormals;
|
||||||
bool m_flipNormals;
|
bool m_flipNormals;
|
||||||
|
Float m_scale;
|
||||||
|
fs::path m_filename;
|
||||||
|
|
||||||
/* Height field data */
|
/* Height field data */
|
||||||
Float *m_data;
|
Float *m_data;
|
||||||
|
|
Loading…
Reference in New Issue