MtsBlend: support for textures and materials
parent
81982c8932
commit
fd68671dbc
|
@ -29,29 +29,29 @@ MTS_NAMESPACE_BEGIN
|
||||||
class Checkerboard : public Texture2D {
|
class Checkerboard : public Texture2D {
|
||||||
public:
|
public:
|
||||||
Checkerboard(const Properties &props) : Texture2D(props) {
|
Checkerboard(const Properties &props) : Texture2D(props) {
|
||||||
m_brightReflectance = props.getSpectrum("brightReflectance", Spectrum(.4f));
|
m_brightColor.g = props.getSpectrum("brightReflectance", Spectrum(.4f));
|
||||||
m_darkReflectance = props.getSpectrum("darkReflectance", Spectrum(.2f));
|
m_darkColor.g = props.getSpectrum("darkReflectance", Spectrum(.2f));
|
||||||
}
|
}
|
||||||
|
|
||||||
Checkerboard(Stream *stream, InstanceManager *manager)
|
Checkerboard(Stream *stream, InstanceManager *manager)
|
||||||
: Texture2D(stream, manager) {
|
: Texture2D(stream, manager) {
|
||||||
m_brightReflectance = Spectrum(stream);
|
m_brightColor.g = Spectrum(stream);
|
||||||
m_darkReflectance = Spectrum(stream);
|
m_darkColor.g = Spectrum(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
Texture2D::serialize(stream, manager);
|
Texture2D::serialize(stream, manager);
|
||||||
m_brightReflectance.serialize(stream);
|
m_brightColor.g.serialize(stream);
|
||||||
m_darkReflectance.serialize(stream);
|
m_darkColor.g.serialize(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Spectrum getValue(const Point2 &uv) const {
|
inline Spectrum getValue(const Point2 &uv) const {
|
||||||
int x = 2*(((int) uv.x) % 2) - 1, y = 2*(((int) uv.y) % 2) - 1;
|
int x = 2*(((int) uv.x) % 2) - 1, y = 2*(((int) uv.y) % 2) - 1;
|
||||||
|
|
||||||
if (x*y == 1)
|
if (x*y == 1)
|
||||||
return m_brightReflectance;
|
return m_brightColor.g;
|
||||||
else
|
else
|
||||||
return m_darkReflectance;
|
return m_darkColor.g;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum getValue(const Point2 &uv, Float dudx, Float dudy, Float dvdx, Float dvdy) const {
|
Spectrum getValue(const Point2 &uv, Float dudx, Float dudy, Float dvdx, Float dvdy) const {
|
||||||
|
@ -63,11 +63,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum getAverage() const {
|
Spectrum getAverage() const {
|
||||||
return m_darkReflectance * .5f;
|
return m_darkColor.g * .5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum getMaximum() const {
|
Spectrum getMaximum() const {
|
||||||
return m_brightReflectance;
|
return m_brightColor.g;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
|
@ -78,26 +78,26 @@ public:
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
protected:
|
protected:
|
||||||
Spectrum m_darkReflectance;
|
Spectrum m_darkColor.g;
|
||||||
Spectrum m_brightReflectance;
|
Spectrum m_brightColor.g;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ================ Hardware shader implementation ================
|
// ================ Hardware shader implementation ================
|
||||||
|
|
||||||
class CheckerboardShader : public Shader {
|
class CheckerboardShader : public Shader {
|
||||||
public:
|
public:
|
||||||
CheckerboardShader(Renderer *renderer, const Spectrum &brightReflectance,
|
CheckerboardShader(Renderer *renderer, const Spectrum &brightColor.g,
|
||||||
const Spectrum &darkReflectance, const Point2 &uvOffset,
|
const Spectrum &darkColor.g, const Point2 &uvOffset,
|
||||||
const Vector2 &uvScale) : Shader(renderer, ETextureShader),
|
const Vector2 &uvScale) : Shader(renderer, ETextureShader),
|
||||||
m_brightReflectance(brightReflectance), m_darkReflectance(darkReflectance),
|
m_brightColor.g(brightReflectance), m_darkReflectance(darkReflectance),
|
||||||
m_uvOffset(uvOffset), m_uvScale(uvScale) {
|
m_uvOffset(uvOffset), m_uvScale(uvScale) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateCode(std::ostringstream &oss,
|
void generateCode(std::ostringstream &oss,
|
||||||
const std::string &evalName,
|
const std::string &evalName,
|
||||||
const std::vector<std::string> &depNames) const {
|
const std::vector<std::string> &depNames) const {
|
||||||
oss << "uniform vec3 " << evalName << "_brightReflectance;" << endl
|
oss << "uniform vec3 " << evalName << "_brightColor.g;" << endl
|
||||||
<< "uniform vec3 " << evalName << "_darkReflectance;" << endl
|
<< "uniform vec3 " << evalName << "_darkColor.g;" << endl
|
||||||
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
|
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
|
||||||
<< "uniform vec2 " << evalName << "_uvScale;" << endl
|
<< "uniform vec2 " << evalName << "_uvScale;" << endl
|
||||||
<< endl
|
<< endl
|
||||||
|
@ -107,37 +107,37 @@ public:
|
||||||
<< " uv.y * " << evalName << "_uvScale.y + " << evalName << "_uvOffset.y);" << endl
|
<< " uv.y * " << evalName << "_uvScale.y + " << evalName << "_uvOffset.y);" << endl
|
||||||
<< " float x = 2*(mod(int(uv.x), 2)) - 1, y = 2*(mod(int(uv.y), 2)) - 1;" << endl
|
<< " float x = 2*(mod(int(uv.x), 2)) - 1, y = 2*(mod(int(uv.y), 2)) - 1;" << endl
|
||||||
<< " if (x*y == 1)" << endl
|
<< " if (x*y == 1)" << endl
|
||||||
<< " return " << evalName << "_brightReflectance;" << endl
|
<< " return " << evalName << "_brightColor.g;" << endl
|
||||||
<< " else" << endl
|
<< " else" << endl
|
||||||
<< " return " << evalName << "_darkReflectance;" << endl
|
<< " return " << evalName << "_darkColor.g;" << endl
|
||||||
<< "}" << endl;
|
<< "}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_brightReflectance", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_brightColor.g", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_darkReflectance", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_darkColor.g", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs,
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs,
|
||||||
int &textureUnitOffset) const {
|
int &textureUnitOffset) const {
|
||||||
program->setParameter(parameterIDs[0], m_brightReflectance);
|
program->setParameter(parameterIDs[0], m_brightColor.g);
|
||||||
program->setParameter(parameterIDs[1], m_darkReflectance);
|
program->setParameter(parameterIDs[1], m_darkColor.g);
|
||||||
program->setParameter(parameterIDs[2], m_uvOffset);
|
program->setParameter(parameterIDs[2], m_uvOffset);
|
||||||
program->setParameter(parameterIDs[3], m_uvScale);
|
program->setParameter(parameterIDs[3], m_uvScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
private:
|
private:
|
||||||
Spectrum m_brightReflectance;
|
Spectrum m_brightColor.g;
|
||||||
Spectrum m_darkReflectance;
|
Spectrum m_darkColor.g;
|
||||||
Point2 m_uvOffset;
|
Point2 m_uvOffset;
|
||||||
Vector2 m_uvScale;
|
Vector2 m_uvScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader *Checkerboard::createShader(Renderer *renderer) const {
|
Shader *Checkerboard::createShader(Renderer *renderer) const {
|
||||||
return new CheckerboardShader(renderer, m_brightReflectance, m_darkReflectance,
|
return new CheckerboardShader(renderer, m_brightColor.g, m_darkReflectance,
|
||||||
m_uvOffset, m_uvScale);
|
m_uvOffset, m_uvScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,22 +29,22 @@ MTS_NAMESPACE_BEGIN
|
||||||
class GridTexture : public Texture2D {
|
class GridTexture : public Texture2D {
|
||||||
public:
|
public:
|
||||||
GridTexture(const Properties &props) : Texture2D(props) {
|
GridTexture(const Properties &props) : Texture2D(props) {
|
||||||
m_brightReflectance = props.getSpectrum("brightReflectance", Spectrum(.4f));
|
m_brightColor = props.getSpectrum("brightColor", Spectrum(.4f));
|
||||||
m_darkReflectance = props.getSpectrum("darkReflectance", Spectrum(.2f));
|
m_darkColor = props.getSpectrum("darkColor", Spectrum(.2f));
|
||||||
m_width = props.getFloat("width", .01f);
|
m_width = props.getFloat("width", .01f);
|
||||||
}
|
}
|
||||||
|
|
||||||
GridTexture(Stream *stream, InstanceManager *manager)
|
GridTexture(Stream *stream, InstanceManager *manager)
|
||||||
: Texture2D(stream, manager) {
|
: Texture2D(stream, manager) {
|
||||||
m_brightReflectance = Spectrum(stream);
|
m_brightColor = Spectrum(stream);
|
||||||
m_darkReflectance = Spectrum(stream);
|
m_darkColor = Spectrum(stream);
|
||||||
m_width = stream->readFloat();
|
m_width = stream->readFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialize(Stream *stream, InstanceManager *manager) const {
|
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
Texture2D::serialize(stream, manager);
|
Texture2D::serialize(stream, manager);
|
||||||
m_brightReflectance.serialize(stream);
|
m_brightColor.serialize(stream);
|
||||||
m_darkReflectance.serialize(stream);
|
m_darkColor.serialize(stream);
|
||||||
stream->writeFloat(m_width);
|
stream->writeFloat(m_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@ public:
|
||||||
y-=1;
|
y-=1;
|
||||||
|
|
||||||
if (std::abs(x) < m_width || std::abs(y) < m_width)
|
if (std::abs(x) < m_width || std::abs(y) < m_width)
|
||||||
return m_darkReflectance;
|
return m_darkColor;
|
||||||
else
|
else
|
||||||
return m_brightReflectance;
|
return m_brightColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum getValue(const Point2 &uv, Float dudx,
|
Spectrum getValue(const Point2 &uv, Float dudx,
|
||||||
|
@ -73,11 +73,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum getMaximum() const {
|
Spectrum getMaximum() const {
|
||||||
return m_brightReflectance;
|
return m_brightColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum getAverage() const {
|
Spectrum getAverage() const {
|
||||||
return m_brightReflectance; // that's not quite right
|
return m_brightColor; // that's not quite right
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string toString() const {
|
std::string toString() const {
|
||||||
|
@ -88,8 +88,8 @@ public:
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
protected:
|
protected:
|
||||||
Spectrum m_brightReflectance;
|
Spectrum m_brightColor;
|
||||||
Spectrum m_darkReflectance;
|
Spectrum m_darkColor;
|
||||||
Float m_width;
|
Float m_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,18 +97,18 @@ protected:
|
||||||
|
|
||||||
class GridTextureShader : public Shader {
|
class GridTextureShader : public Shader {
|
||||||
public:
|
public:
|
||||||
GridTextureShader(Renderer *renderer, const Spectrum &brightReflectance,
|
GridTextureShader(Renderer *renderer, const Spectrum &brightColor,
|
||||||
const Spectrum &darkReflectance, Float width, const Point2 &uvOffset,
|
const Spectrum &darkColor, Float width, const Point2 &uvOffset,
|
||||||
const Vector2 &uvScale) : Shader(renderer, ETextureShader),
|
const Vector2 &uvScale) : Shader(renderer, ETextureShader),
|
||||||
m_brightReflectance(brightReflectance), m_darkReflectance(darkReflectance),
|
m_brightColor(brightColor), m_darkColor(darkColor),
|
||||||
m_width(width), m_uvOffset(uvOffset), m_uvScale(uvScale) {
|
m_width(width), m_uvOffset(uvOffset), m_uvScale(uvScale) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generateCode(std::ostringstream &oss,
|
void generateCode(std::ostringstream &oss,
|
||||||
const std::string &evalName,
|
const std::string &evalName,
|
||||||
const std::vector<std::string> &depNames) const {
|
const std::vector<std::string> &depNames) const {
|
||||||
oss << "uniform vec3 " << evalName << "_brightReflectance;" << endl
|
oss << "uniform vec3 " << evalName << "_brightColor;" << endl
|
||||||
<< "uniform vec3 " << evalName << "_darkReflectance;" << endl
|
<< "uniform vec3 " << evalName << "_darkColor;" << endl
|
||||||
<< "uniform float " << evalName << "_width;" << endl
|
<< "uniform float " << evalName << "_width;" << endl
|
||||||
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
|
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
|
||||||
<< "uniform vec2 " << evalName << "_uvScale;" << endl
|
<< "uniform vec2 " << evalName << "_uvScale;" << endl
|
||||||
|
@ -122,15 +122,15 @@ public:
|
||||||
<< " if (x > .5) x -= 1.0;" << endl
|
<< " if (x > .5) x -= 1.0;" << endl
|
||||||
<< " if (y > .5) y -= 1.0;" << endl
|
<< " if (y > .5) y -= 1.0;" << endl
|
||||||
<< " if (abs(x) < " << evalName << "_width || abs(y) < " << evalName << "_width)" << endl
|
<< " if (abs(x) < " << evalName << "_width || abs(y) < " << evalName << "_width)" << endl
|
||||||
<< " return " << evalName << "_darkReflectance;" << endl
|
<< " return " << evalName << "_darkColor;" << endl
|
||||||
<< " else" << endl
|
<< " else" << endl
|
||||||
<< " return " << evalName << "_brightReflectance;" << endl
|
<< " return " << evalName << "_brightColor;" << endl
|
||||||
<< "}" << endl;
|
<< "}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> ¶meterIDs) const {
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_brightReflectance", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_brightColor", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_darkReflectance", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_darkColor", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_width", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_width", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
|
||||||
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
|
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
|
||||||
|
@ -138,8 +138,8 @@ public:
|
||||||
|
|
||||||
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs,
|
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs,
|
||||||
int &textureUnitOffset) const {
|
int &textureUnitOffset) const {
|
||||||
program->setParameter(parameterIDs[0], m_brightReflectance);
|
program->setParameter(parameterIDs[0], m_brightColor);
|
||||||
program->setParameter(parameterIDs[1], m_darkReflectance);
|
program->setParameter(parameterIDs[1], m_darkColor);
|
||||||
program->setParameter(parameterIDs[2], m_width);
|
program->setParameter(parameterIDs[2], m_width);
|
||||||
program->setParameter(parameterIDs[3], m_uvOffset);
|
program->setParameter(parameterIDs[3], m_uvOffset);
|
||||||
program->setParameter(parameterIDs[4], m_uvScale);
|
program->setParameter(parameterIDs[4], m_uvScale);
|
||||||
|
@ -147,15 +147,15 @@ public:
|
||||||
|
|
||||||
MTS_DECLARE_CLASS()
|
MTS_DECLARE_CLASS()
|
||||||
private:
|
private:
|
||||||
Spectrum m_brightReflectance;
|
Spectrum m_brightColor;
|
||||||
Spectrum m_darkReflectance;
|
Spectrum m_darkColor;
|
||||||
Float m_width;
|
Float m_width;
|
||||||
Point2 m_uvOffset;
|
Point2 m_uvOffset;
|
||||||
Vector2 m_uvScale;
|
Vector2 m_uvScale;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shader *GridTexture::createShader(Renderer *renderer) const {
|
Shader *GridTexture::createShader(Renderer *renderer) const {
|
||||||
return new GridTextureShader(renderer, m_brightReflectance, m_darkReflectance,
|
return new GridTextureShader(renderer, m_brightColor, m_darkColor,
|
||||||
m_width, m_uvOffset, m_uvScale);
|
m_width, m_uvOffset, m_uvScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,19 @@ from extensions_framework import util as efutil
|
||||||
# Mitsuba-related classes
|
# Mitsuba-related classes
|
||||||
from mitsuba.properties.engine import mitsuba_engine
|
from mitsuba.properties.engine import mitsuba_engine
|
||||||
from mitsuba.properties.lamp import mitsuba_lamp
|
from mitsuba.properties.lamp import mitsuba_lamp
|
||||||
|
from mitsuba.properties.texture import mitsuba_texture, \
|
||||||
|
mitsuba_tex_ldrtexture, mitsuba_tex_checkerboard
|
||||||
|
from mitsuba.properties.material import mitsuba_material, \
|
||||||
|
mitsuba_mat_lambertian
|
||||||
|
|
||||||
from mitsuba.operators import MITSUBA_OT_preset_engine_add, EXPORT_OT_mitsuba
|
from mitsuba.operators import MITSUBA_OT_preset_engine_add, EXPORT_OT_mitsuba
|
||||||
from mitsuba.outputs import MtsLog, MtsFilmDisplay
|
from mitsuba.outputs import MtsLog, MtsFilmDisplay
|
||||||
from mitsuba.export.film import resolution
|
from mitsuba.export.film import resolution
|
||||||
|
|
||||||
from mitsuba.ui import render_panels
|
from mitsuba.ui import render_panels
|
||||||
from mitsuba.ui import lamps
|
from mitsuba.ui import lamps
|
||||||
|
from mitsuba.ui.textures import main, ldrtexture, checkerboard
|
||||||
|
from mitsuba.ui.materials import main, lambertian
|
||||||
|
|
||||||
def compatible(mod):
|
def compatible(mod):
|
||||||
mod = __import__(mod)
|
mod = __import__(mod)
|
||||||
|
@ -45,7 +52,6 @@ def compatible(mod):
|
||||||
pass
|
pass
|
||||||
del mod
|
del mod
|
||||||
|
|
||||||
|
|
||||||
import properties_data_lamp
|
import properties_data_lamp
|
||||||
properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('mitsuba')
|
properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('mitsuba')
|
||||||
del properties_data_lamp
|
del properties_data_lamp
|
||||||
|
@ -56,6 +62,10 @@ properties_render.RENDER_PT_dimensions.COMPAT_ENGINES.add('mitsuba')
|
||||||
properties_render.RENDER_PT_output.COMPAT_ENGINES.add('mitsuba')
|
properties_render.RENDER_PT_output.COMPAT_ENGINES.add('mitsuba')
|
||||||
del properties_render
|
del properties_render
|
||||||
|
|
||||||
|
import properties_texture
|
||||||
|
properties_texture.TEXTURE_PT_context_texture.COMPAT_ENGINES.add('mitsuba')
|
||||||
|
del properties_texture
|
||||||
|
|
||||||
compatible("properties_data_mesh")
|
compatible("properties_data_mesh")
|
||||||
compatible("properties_data_camera")
|
compatible("properties_data_camera")
|
||||||
|
|
||||||
|
@ -65,7 +75,12 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||||
|
|
||||||
property_groups = [
|
property_groups = [
|
||||||
('Scene', mitsuba_engine),
|
('Scene', mitsuba_engine),
|
||||||
('Lamp', mitsuba_lamp)
|
('Lamp', mitsuba_lamp),
|
||||||
|
('Texture', mitsuba_texture),
|
||||||
|
('mitsuba_texture', mitsuba_tex_ldrtexture),
|
||||||
|
('mitsuba_texture', mitsuba_tex_checkerboard),
|
||||||
|
('Material', mitsuba_material),
|
||||||
|
('mitsuba_material', mitsuba_mat_lambertian)
|
||||||
]
|
]
|
||||||
|
|
||||||
render_lock = threading.Lock()
|
render_lock = threading.Lock()
|
||||||
|
@ -142,7 +157,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||||
self.render_update_timer.start()
|
self.render_update_timer.start()
|
||||||
if self.render_update_timer.isAlive(): self.render_update_timer.join()
|
if self.render_update_timer.isAlive(): self.render_update_timer.join()
|
||||||
|
|
||||||
# If we exit the wait loop (user cancelled) and luxconsole is still running, then send SIGINT
|
# If we exit the wait loop (user cancelled) and mitsuba is still running, then send SIGINT
|
||||||
if mitsuba_process.poll() == None:
|
if mitsuba_process.poll() == None:
|
||||||
# Use SIGTERM because that's the only one supported on Windows
|
# Use SIGTERM because that's the only one supported on Windows
|
||||||
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
|
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
|
||||||
|
@ -152,6 +167,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
|
||||||
framebuffer_thread.join()
|
framebuffer_thread.join()
|
||||||
|
|
||||||
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
if mitsuba_process.poll() != None and mitsuba_process.returncode != 0:
|
||||||
|
MtsLog("MtsBlend: Rendering failed -- check the console")
|
||||||
bpy.ops.ef.msg(msg_type='ERROR', msg_text='Rendering failed -- check the console.')
|
bpy.ops.ef.msg(msg_type='ERROR', msg_text='Rendering failed -- check the console.')
|
||||||
else:
|
else:
|
||||||
framebuffer_thread.kick(render_end=True)
|
framebuffer_thread.kick(render_end=True)
|
||||||
|
|
|
@ -16,105 +16,84 @@
|
||||||
#
|
#
|
||||||
# ##### END GPL LICENSE BLOCK #####
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
import os, math, mathutils
|
import os
|
||||||
|
|
||||||
from extensions_framework import util as efutil
|
class ParamSetItem(list):
|
||||||
|
type = None
|
||||||
|
type_name = None
|
||||||
|
name = None
|
||||||
|
value = None
|
||||||
|
|
||||||
class MtsAdjustments:
|
def __init__(self, *args):
|
||||||
'''
|
self.type, self.name, self.value = args
|
||||||
Writes scene information to an "adjustments" file. This
|
self.type_name = "%s %s" % (self.type, self.name)
|
||||||
mechanism is used to capture information which gets lost
|
self.append(self.type_name)
|
||||||
in translation when using the COLLADA exporter.
|
self.append(self.value)
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, target_file, target_dir):
|
def to_string(self):
|
||||||
self.target_file = target_file
|
if self.type == "color":
|
||||||
self.target_dir = target_dir
|
return '\t\t<rgb name="%s" value="%s %s %s"/>\n' % (self.name,
|
||||||
|
self.value[0], self.value[1], self.value[2])
|
||||||
|
elif self.type == "point" or self.type == "vector":
|
||||||
|
return '\t\t<%s name="%s" value="%s %s %s"/>\n' % (self.type,
|
||||||
|
self.name, self.value[0], self.value[1], self.value[2])
|
||||||
|
elif self.type == "integer" or self.type == "float" \
|
||||||
|
or self.type == "string":
|
||||||
|
return '\t\t<%s name="%s" value="%s"/>\n' % (self.type, self.name, self.value)
|
||||||
|
elif self.type == "reference_texture" or self.type == "reference_material":
|
||||||
|
return '\t\t<ref name="%s" id="%s"/>\n' % (self.name, self.value)
|
||||||
|
|
||||||
def export_worldtrafo(self, adjfile, trafo):
|
class ParamSet(list):
|
||||||
adjfile.write('\t\t<transform name="toWorld">\n')
|
names = []
|
||||||
adjfile.write('\t\t\t<matrix value="')
|
|
||||||
for j in range(0,4):
|
|
||||||
for i in range(0,4):
|
|
||||||
adjfile.write("%f " % trafo[i][j])
|
|
||||||
adjfile.write('"/>\n\t\t</transform>\n')
|
|
||||||
|
|
||||||
def export_lamp(self, adjfile, lamp, idx):
|
def update(self, other):
|
||||||
ltype = lamp.data.mitsuba_lamp.type
|
for p in other:
|
||||||
if ltype == 'POINT':
|
self.add(p.type, p.name, p.value)
|
||||||
adjfile.write('\t<luminaire id="%s-light" type="point">\n' % lamp.data.name)
|
return self
|
||||||
mult = lamp.data.mitsuba_lamp.intensity
|
|
||||||
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
|
||||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
|
||||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
|
||||||
adjfile.write('\t</luminaire>\n')
|
|
||||||
elif ltype == 'AREA':
|
|
||||||
adjfile.write('\t<shape type="obj">\n')
|
|
||||||
size_x = lamp.data.size
|
|
||||||
size_y = lamp.data.size
|
|
||||||
if lamp.data.shape == 'RECTANGLE':
|
|
||||||
size_y = lamp.data.size_y
|
|
||||||
path = os.path.join(os.path.join(self.target_dir, 'meshes'), "_area_luminaire_%d.obj" % idx)
|
|
||||||
|
|
||||||
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % path)
|
def add(self, type, name, value):
|
||||||
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
if name in self.names:
|
||||||
|
for p in self:
|
||||||
|
if p.name == name:
|
||||||
|
self.remove(p)
|
||||||
|
|
||||||
adjfile.write('\n\t\t<luminaire id="%s-light" type="area">\n' % lamp.data.name)
|
self.append(
|
||||||
mult = lamp.data.mitsuba_lamp.intensity / (2 * size_x * size_y)
|
ParamSetItem(type, name, value)
|
||||||
adjfile.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
)
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
self.names.append(name)
|
||||||
adjfile.write('\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
return self
|
||||||
adjfile.write('\t\t</luminaire>\n')
|
|
||||||
adjfile.write('\t</shape>\n')
|
|
||||||
objFile = open(path, 'w')
|
|
||||||
objFile.write('v %f %f 0\n' % (-size_x/2, -size_y/2))
|
|
||||||
objFile.write('v %f %f 0\n' % ( size_x/2, -size_y/2))
|
|
||||||
objFile.write('v %f %f 0\n' % ( size_x/2, size_y/2))
|
|
||||||
objFile.write('v %f %f 0\n' % (-size_x/2, size_y/2))
|
|
||||||
objFile.write('f 4 3 2 1\n')
|
|
||||||
objFile.close()
|
|
||||||
elif ltype == 'SUN':
|
|
||||||
adjfile.write('\t<luminaire id="%s-light" type="directional">\n' % lamp.data.name)
|
|
||||||
mult = lamp.data.mitsuba_lamp.intensity
|
|
||||||
scale = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
|
|
||||||
self.export_worldtrafo(adjfile, lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
|
||||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
|
||||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
|
||||||
adjfile.write('\t</luminaire>\n')
|
|
||||||
elif ltype == 'SPOT':
|
|
||||||
adjfile.write('\t<luminaire id="%s-light" type="spot">\n' % lamp.data.name)
|
|
||||||
mult = lamp.data.mitsuba_lamp.intensity
|
|
||||||
self.export_worldtrafo(adjfile, lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
|
||||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
|
||||||
adjfile.write('\t\t<float name="cutoffAngle" value="%f"/>\n' % (lamp.data.spot_size * 180 / (math.pi * 2)))
|
|
||||||
adjfile.write('\t\t<float name="beamWidth" value="%f"/>\n' % (lamp.data.spot_blend * lamp.data.spot_size * 180 / (math.pi * 2)))
|
|
||||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
|
||||||
adjfile.write('\t</luminaire>\n')
|
|
||||||
elif ltype == 'ENV':
|
|
||||||
if lamp.data.mitsuba_lamp.envmap_type == 'constant':
|
|
||||||
adjfile.write('\t<luminaire id="%s-light" type="constant">\n' % lamp.data.name)
|
|
||||||
mult = lamp.data.mitsuba_lamp.intensity
|
|
||||||
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
|
||||||
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
|
||||||
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
|
||||||
adjfile.write('\t</luminaire>\n')
|
|
||||||
elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
|
|
||||||
adjfile.write('\t<luminaire id="%s-light" type="envmap">\n' % lamp.data.name)
|
|
||||||
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file))
|
|
||||||
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
|
||||||
adjfile.write('\t\t<float name="intensityScale" value="%f"/>\n' % lamp.data.mitsuba_lamp.intensity)
|
|
||||||
adjfile.write('\t</luminaire>\n')
|
|
||||||
|
|
||||||
def export(self, scene):
|
def add_float(self, name, value):
|
||||||
adjfile = open(self.target_file, 'w')
|
self.add('float', name, value)
|
||||||
adjfile.write('<adjustments>\n');
|
return self
|
||||||
idx = 0
|
|
||||||
for obj in scene.objects:
|
def add_integer(self, name, value):
|
||||||
if obj.type == 'LAMP':
|
self.add('integer', name, value)
|
||||||
self.export_lamp(adjfile, obj, idx)
|
return self
|
||||||
idx = idx+1
|
|
||||||
adjfile.write('</adjustments>\n');
|
def add_reference(self, type, name, value):
|
||||||
adjfile.close()
|
self.add('reference_%s' % type, name, value)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_bool(self, name, value):
|
||||||
|
self.add('bool', name, bool(value))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_string(self, name, value):
|
||||||
|
self.add('string', name, str(value))
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_vector(self, name, value):
|
||||||
|
self.add('vector', name, [i for i in value])
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_point(self, name, value):
|
||||||
|
self.add('point', name, [p for p in value])
|
||||||
|
return self
|
||||||
|
|
||||||
|
def add_color(self, name, value):
|
||||||
|
self.add('color', name, [c for c in value])
|
||||||
|
return self
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
return ''.join(item.to_string() for item in self)
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import os, math, mathutils
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from extensions_framework import util as efutil
|
||||||
|
|
||||||
|
class MtsAdjustments:
|
||||||
|
'''
|
||||||
|
Writes scene information to an "adjustments" file. This
|
||||||
|
mechanism is used to capture information which gets lost
|
||||||
|
in translation when using the COLLADA exporter.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, target_file, target_dir):
|
||||||
|
self.target_file = target_file
|
||||||
|
self.target_dir = target_dir
|
||||||
|
self.exported_materials = []
|
||||||
|
self.exported_textures = []
|
||||||
|
|
||||||
|
def export_worldtrafo(self, adjfile, trafo):
|
||||||
|
adjfile.write('\t\t<transform name="toWorld">\n')
|
||||||
|
adjfile.write('\t\t\t<matrix value="')
|
||||||
|
for j in range(0,4):
|
||||||
|
for i in range(0,4):
|
||||||
|
adjfile.write("%f " % trafo[i][j])
|
||||||
|
adjfile.write('"/>\n\t\t</transform>\n')
|
||||||
|
|
||||||
|
def export_lamp(self, adjfile, lamp, idx):
|
||||||
|
ltype = lamp.data.mitsuba_lamp.type
|
||||||
|
if ltype == 'POINT':
|
||||||
|
adjfile.write('\t<luminaire id="%s-light" type="point">\n' % lamp.data.name)
|
||||||
|
mult = lamp.data.mitsuba_lamp.intensity
|
||||||
|
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
||||||
|
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||||
|
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||||
|
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
||||||
|
adjfile.write('\t</luminaire>\n')
|
||||||
|
elif ltype == 'AREA':
|
||||||
|
adjfile.write('\t<shape type="obj">\n')
|
||||||
|
size_x = lamp.data.size
|
||||||
|
size_y = lamp.data.size
|
||||||
|
if lamp.data.shape == 'RECTANGLE':
|
||||||
|
size_y = lamp.data.size_y
|
||||||
|
path = os.path.join(os.path.join(self.target_dir, 'meshes'), "_area_luminaire_%d.obj" % idx)
|
||||||
|
|
||||||
|
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % path)
|
||||||
|
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
||||||
|
|
||||||
|
adjfile.write('\n\t\t<luminaire id="%s-light" type="area">\n' % lamp.data.name)
|
||||||
|
mult = lamp.data.mitsuba_lamp.intensity / (2 * size_x * size_y)
|
||||||
|
adjfile.write('\t\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||||
|
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||||
|
adjfile.write('\t\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
||||||
|
adjfile.write('\t\t</luminaire>\n')
|
||||||
|
adjfile.write('\t</shape>\n')
|
||||||
|
objFile = open(path, 'w')
|
||||||
|
objFile.write('v %f %f 0\n' % (-size_x/2, -size_y/2))
|
||||||
|
objFile.write('v %f %f 0\n' % ( size_x/2, -size_y/2))
|
||||||
|
objFile.write('v %f %f 0\n' % ( size_x/2, size_y/2))
|
||||||
|
objFile.write('v %f %f 0\n' % (-size_x/2, size_y/2))
|
||||||
|
objFile.write('f 4 3 2 1\n')
|
||||||
|
objFile.close()
|
||||||
|
elif ltype == 'SUN':
|
||||||
|
adjfile.write('\t<luminaire id="%s-light" type="directional">\n' % lamp.data.name)
|
||||||
|
mult = lamp.data.mitsuba_lamp.intensity
|
||||||
|
scale = mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1]))
|
||||||
|
self.export_worldtrafo(adjfile, lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||||
|
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||||
|
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||||
|
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
||||||
|
adjfile.write('\t</luminaire>\n')
|
||||||
|
elif ltype == 'SPOT':
|
||||||
|
adjfile.write('\t<luminaire id="%s-light" type="spot">\n' % lamp.data.name)
|
||||||
|
mult = lamp.data.mitsuba_lamp.intensity
|
||||||
|
self.export_worldtrafo(adjfile, lamp.matrix_world * mathutils.Matrix.Scale(-1, 4, mathutils.Vector([0, 0, 1])))
|
||||||
|
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||||
|
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||||
|
adjfile.write('\t\t<float name="cutoffAngle" value="%f"/>\n' % (lamp.data.spot_size * 180 / (math.pi * 2)))
|
||||||
|
adjfile.write('\t\t<float name="beamWidth" value="%f"/>\n' % (lamp.data.spot_blend * lamp.data.spot_size * 180 / (math.pi * 2)))
|
||||||
|
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
||||||
|
adjfile.write('\t</luminaire>\n')
|
||||||
|
elif ltype == 'ENV':
|
||||||
|
if lamp.data.mitsuba_lamp.envmap_type == 'constant':
|
||||||
|
adjfile.write('\t<luminaire id="%s-light" type="constant">\n' % lamp.data.name)
|
||||||
|
mult = lamp.data.mitsuba_lamp.intensity
|
||||||
|
adjfile.write('\t\t<rgb name="intensity" value="%f %f %f"/>\n'
|
||||||
|
% (lamp.data.color.r*mult, lamp.data.color.g*mult, lamp.data.color.b*mult))
|
||||||
|
adjfile.write('\t\t<float name="samplingWeight" value="%f"/>\n' % lamp.data.mitsuba_lamp.sampling_weight)
|
||||||
|
adjfile.write('\t</luminaire>\n')
|
||||||
|
elif lamp.data.mitsuba_lamp.envmap_type == 'envmap':
|
||||||
|
adjfile.write('\t<luminaire id="%s-light" type="envmap">\n' % lamp.data.name)
|
||||||
|
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % efutil.filesystem_path(lamp.data.mitsuba_lamp.envmap_file))
|
||||||
|
self.export_worldtrafo(adjfile, lamp.matrix_world)
|
||||||
|
adjfile.write('\t\t<float name="intensityScale" value="%f"/>\n' % lamp.data.mitsuba_lamp.intensity)
|
||||||
|
adjfile.write('\t</luminaire>\n')
|
||||||
|
|
||||||
|
def find_texture(self, name):
|
||||||
|
if name in bpy.data.textures:
|
||||||
|
return bpy.data.textures[name]
|
||||||
|
else:
|
||||||
|
raise Exception('Failed to find texture "%s"' % name)
|
||||||
|
|
||||||
|
def find_material(self, name):
|
||||||
|
if name in bpy.data.materials:
|
||||||
|
return bpy.data.materials[name]
|
||||||
|
else:
|
||||||
|
raise Exception('Failed to find material "%s"' % name)
|
||||||
|
|
||||||
|
def export_texture(self, adjfile, mat):
|
||||||
|
if mat.name in self.exported_textures:
|
||||||
|
return
|
||||||
|
self.exported_textures += [mat.name]
|
||||||
|
params = mat.mitsuba_texture.get_params()
|
||||||
|
|
||||||
|
for p in params:
|
||||||
|
if p.type == 'reference_texture':
|
||||||
|
self.export_texture(adjfile, self.find_texture(p.value))
|
||||||
|
|
||||||
|
adjfile.write('\t<texture id="%s" type="%s">\n' % (mat.name, mat.mitsuba_texture.type))
|
||||||
|
adjfile.write(params.to_string())
|
||||||
|
adjfile.write('\t</texture>\n')
|
||||||
|
|
||||||
|
def export_material(self, adjfile, mat):
|
||||||
|
if mat.name in self.exported_materials:
|
||||||
|
return
|
||||||
|
self.exported_materials += [mat.name]
|
||||||
|
params = mat.mitsuba_material.get_params()
|
||||||
|
|
||||||
|
for p in params:
|
||||||
|
if p.type == 'reference_material':
|
||||||
|
self.export_material(adjfile, self.find_material(p.value))
|
||||||
|
elif p.type == 'reference_texture':
|
||||||
|
self.export_texture(adjfile, self.find_texture(p.value))
|
||||||
|
|
||||||
|
adjfile.write('\t<bsdf id="%s" type="%s">\n' % (mat.name, mat.mitsuba_material.type))
|
||||||
|
adjfile.write(params.to_string())
|
||||||
|
adjfile.write('\t</bsdf>\n')
|
||||||
|
|
||||||
|
def export(self, scene):
|
||||||
|
adjfile = open(self.target_file, 'w')
|
||||||
|
adjfile.write('<adjustments>\n');
|
||||||
|
idx = 0
|
||||||
|
for obj in scene.objects:
|
||||||
|
if obj.type == 'LAMP':
|
||||||
|
self.export_lamp(adjfile, obj, idx)
|
||||||
|
elif obj.type == 'MESH':
|
||||||
|
for mat in obj.data.materials:
|
||||||
|
self.export_material(adjfile, mat)
|
||||||
|
idx = idx+1
|
||||||
|
adjfile.write('</adjustments>\n');
|
||||||
|
adjfile.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ from presets import AddPresetBase
|
||||||
from extensions_framework import util as efutil
|
from extensions_framework import util as efutil
|
||||||
|
|
||||||
from mitsuba.outputs import MtsLog
|
from mitsuba.outputs import MtsLog
|
||||||
from mitsuba.export import MtsAdjustments
|
from mitsuba.export.adjustments import MtsAdjustments
|
||||||
|
|
||||||
def try_preset_path_create(preset_subdir):
|
def try_preset_path_create(preset_subdir):
|
||||||
target_path = os.path.join(bpy.utils.preset_paths('')[0], preset_subdir)
|
target_path = os.path.join(bpy.utils.preset_paths('')[0], preset_subdir)
|
||||||
|
@ -59,32 +59,61 @@ class MITSUBA_OT_preset_engine_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
||||||
]
|
]
|
||||||
preset_subdir = 'mitsuba/engine'
|
preset_subdir = 'mitsuba/engine'
|
||||||
|
|
||||||
class MitsubaCheckOp(bpy.types.Operator):
|
|
||||||
bl_idname = 'mts.check'
|
|
||||||
bl_label = 'Check scene'
|
|
||||||
|
|
||||||
def reportWarning(self, msg):
|
class MITSUBA_MT_presets_texture(MITSUBA_MT_base, bpy.types.Menu):
|
||||||
self.report({'WARNING'}, msg)
|
bl_label = "Mitsuba Texture Presets"
|
||||||
MtsLog("MtsBlend: %s" % msg)
|
preset_subdir = "mitsuba/texture"
|
||||||
|
|
||||||
def _check_lamp(self, lamp):
|
class MITSUBA_OT_preset_texture_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
||||||
hasErrors = False
|
'''Save the current settings as a preset'''
|
||||||
if lamp.type == 'POINT' and lamp.falloff_type != 'INVERSE_SQUARE':
|
bl_idname = 'mitsuba.preset_texture_add'
|
||||||
self.reportWarning('Point light "%s" needs to have inverse square falloff' % lamp.name)
|
bl_label = 'Add Mitsuba Texture settings preset'
|
||||||
hasErrors = True
|
preset_menu = 'MITSUBA_MT_presets_texture'
|
||||||
|
preset_values = []
|
||||||
if hasErrors:
|
preset_subdir = 'mitsuba/texture'
|
||||||
self.reportWarning('Encountered one or more problems -- check the console')
|
|
||||||
else:
|
|
||||||
self.report({'INFO'}, "No problems found")
|
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
scene = bpy.data.scenes[0]
|
pv = [
|
||||||
for obj in scene.objects:
|
'bpy.context.texture.mitsuba_texture.%s'%v['attr'] for v in bpy.types.mitsuba_texture.get_exportable_properties()
|
||||||
if obj.type == 'LAMP':
|
]
|
||||||
self._check_lamp(obj.data)
|
mts_type = context.texture.mitsuba_texture.type
|
||||||
return {'FINISHED'}
|
sub_type = getattr(bpy.types, 'mitsuba_tex_%s' % mts_type)
|
||||||
|
|
||||||
|
pv.extend([
|
||||||
|
'bpy.context.texture.mitsuba_texture.mitsuba_tex_%s.%s'%(mts_type, v['attr']) for v in sub_type.get_exportable_properties()
|
||||||
|
])
|
||||||
|
|
||||||
|
self.preset_values = pv
|
||||||
|
return super().execute(context)
|
||||||
|
|
||||||
|
|
||||||
|
class MITSUBA_MT_presets_material(MITSUBA_MT_base, bpy.types.Menu):
|
||||||
|
bl_label = "Mitsuba Material Presets"
|
||||||
|
preset_subdir = "mitsuba/material"
|
||||||
|
|
||||||
|
class MITSUBA_OT_preset_material_add(MITSUBA_OT_preset_base, bpy.types.Operator):
|
||||||
|
'''Save the current settings as a preset'''
|
||||||
|
bl_idname = 'mitsuba.preset_material_add'
|
||||||
|
bl_label = 'Add Mitsuba Material settings preset'
|
||||||
|
preset_menu = 'MITSUBA_MT_presets_material'
|
||||||
|
preset_values = []
|
||||||
|
preset_subdir = 'mitsuba/material'
|
||||||
|
|
||||||
|
def execute(self, context):
|
||||||
|
pv = [
|
||||||
|
'bpy.context.material.mitsuba_material.%s'%v['attr'] for v in bpy.types.mitsuba_material.get_exportable_properties()
|
||||||
|
]
|
||||||
|
|
||||||
|
# store only the sub-properties of the selected mitsuba material type
|
||||||
|
mts_type = context.material.mitsuba_material.type
|
||||||
|
sub_type = getattr(bpy.types, 'mitsuba_mat_%s' % mts_type)
|
||||||
|
|
||||||
|
pv.extend([
|
||||||
|
'bpy.context.material.mitsuba_material.mitsuba_mat_%s.%s'%(mts_type, v['attr']) for v in sub_type.get_exportable_properties()
|
||||||
|
])
|
||||||
|
|
||||||
|
self.preset_values = pv
|
||||||
|
return super().execute(context)
|
||||||
|
|
||||||
class EXPORT_OT_mitsuba(bpy.types.Operator):
|
class EXPORT_OT_mitsuba(bpy.types.Operator):
|
||||||
bl_idname = 'export.mitsuba'
|
bl_idname = 'export.mitsuba'
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
import math
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from extensions_framework import declarative_property_group
|
||||||
|
from extensions_framework import util as efutil
|
||||||
|
from mitsuba.properties.texture import TextureParameter
|
||||||
|
from mitsuba.export import ParamSet
|
||||||
|
|
||||||
|
param_reflectance = TextureParameter('reflectance', 'Reflectance', \
|
||||||
|
'Diffuse reflectance value', default=(0.5, 0.5, 0.5))
|
||||||
|
|
||||||
|
def dict_merge(*args):
|
||||||
|
vis = {}
|
||||||
|
for vis_dict in args:
|
||||||
|
vis.update(deepcopy(vis_dict))
|
||||||
|
return vis
|
||||||
|
|
||||||
|
|
||||||
|
class mitsuba_material(declarative_property_group):
|
||||||
|
'''
|
||||||
|
Storage class for Mitsuba Material settings.
|
||||||
|
This class will be instantiated within a Blender Material
|
||||||
|
object.
|
||||||
|
'''
|
||||||
|
|
||||||
|
controls = [
|
||||||
|
'type',
|
||||||
|
]
|
||||||
|
|
||||||
|
properties = [
|
||||||
|
# Material Type Select
|
||||||
|
{
|
||||||
|
'type': 'enum',
|
||||||
|
'attr': 'type',
|
||||||
|
'name': 'Type',
|
||||||
|
'description': 'Mitsuba material type',
|
||||||
|
'default': 'matte',
|
||||||
|
'items': [
|
||||||
|
('lambertian', 'Lambertian', 'Lambertian (i.e. ideally diffuse) material')
|
||||||
|
],
|
||||||
|
'save_in_preset': True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
sub_type = getattr(self, 'mitsuba_mat_%s' % self.type)
|
||||||
|
return sub_type.get_params()
|
||||||
|
|
||||||
|
class mitsuba_mat_lambertian(declarative_property_group):
|
||||||
|
controls = [
|
||||||
|
] + param_reflectance.controls
|
||||||
|
|
||||||
|
properties = [
|
||||||
|
] + param_reflectance.properties
|
||||||
|
|
||||||
|
visibility = dict_merge(
|
||||||
|
param_reflectance.visibility
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
params = ParamSet()
|
||||||
|
params.update(param_reflectance.get_params(self))
|
||||||
|
return params
|
||||||
|
|
|
@ -0,0 +1,368 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
from extensions_framework import declarative_property_group
|
||||||
|
from extensions_framework import util as efutil
|
||||||
|
from extensions_framework.validate import Logic_OR as O
|
||||||
|
|
||||||
|
from mitsuba.export import ParamSet
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Texture property group construction helpers
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class TextureParameterBase(object):
|
||||||
|
attr = None
|
||||||
|
name = None
|
||||||
|
default = (0.8, 0.8, 0.8)
|
||||||
|
min = 0.0
|
||||||
|
max = 1.0
|
||||||
|
|
||||||
|
texture_collection = 'texture_slots'
|
||||||
|
|
||||||
|
controls = None
|
||||||
|
visibility = None
|
||||||
|
properties = None
|
||||||
|
|
||||||
|
def __init__(self, attr, name, description, default=None, min=None, max=None):
|
||||||
|
self.attr = attr
|
||||||
|
self.name = name
|
||||||
|
self.description = description
|
||||||
|
if default is not None:
|
||||||
|
self.default = default
|
||||||
|
if min is not None:
|
||||||
|
self.min = min
|
||||||
|
if max is not None:
|
||||||
|
self.max = max
|
||||||
|
|
||||||
|
self.controls = self.get_controls()
|
||||||
|
self.visibility = self.get_visibility()
|
||||||
|
self.properties = self.get_properties()
|
||||||
|
|
||||||
|
def texture_collection_finder(self):
|
||||||
|
return lambda s,c: s.object.material_slots[s.object.active_material_index].material
|
||||||
|
|
||||||
|
def texture_slot_set_attr(self):
|
||||||
|
def set_attr(s,c):
|
||||||
|
if type(c).__name__ == 'mitsuba_material':
|
||||||
|
return getattr(c, 'mitsuba_mat_%s'%c.type)
|
||||||
|
else:
|
||||||
|
return getattr(c, 'mitsuba_tex_%s'%c.type)
|
||||||
|
return set_attr
|
||||||
|
|
||||||
|
def get_controls(self):
|
||||||
|
'''
|
||||||
|
Subclasses can override this for their own needs
|
||||||
|
'''
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_visibility(self):
|
||||||
|
'''
|
||||||
|
Subclasses can override this for their own needs
|
||||||
|
'''
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def get_properties(self):
|
||||||
|
'''
|
||||||
|
Subclasses can override this for their own needs
|
||||||
|
'''
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_extra_controls(self):
|
||||||
|
'''
|
||||||
|
Subclasses can override this for their own needs
|
||||||
|
'''
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_extra_visibility(self):
|
||||||
|
'''
|
||||||
|
Subclasses can override this for their own needs
|
||||||
|
'''
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def get_extra_properties(self):
|
||||||
|
'''
|
||||||
|
Subclasses can override this for their own needs
|
||||||
|
'''
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_params(self, context):
|
||||||
|
'''
|
||||||
|
Return a Mitsuba ParamSet of the properties
|
||||||
|
defined in this Texture, getting parameters
|
||||||
|
from property group 'context'
|
||||||
|
'''
|
||||||
|
return ParamSet()
|
||||||
|
|
||||||
|
class TextureParameter(TextureParameterBase):
|
||||||
|
def get_controls(self):
|
||||||
|
return [
|
||||||
|
[ 0.9, [0.375,'%s_colorlabel' % self.attr, '%s_color' % self.attr], '%s_usetexture' % self.attr ],
|
||||||
|
'%s_texture' % self.attr
|
||||||
|
] + self.get_extra_controls()
|
||||||
|
|
||||||
|
def get_visibility(self):
|
||||||
|
vis = {
|
||||||
|
'%s_texture' % self.attr: { '%s_usetexture' % self.attr: True },
|
||||||
|
}
|
||||||
|
vis.update(self.get_extra_visibility())
|
||||||
|
return vis
|
||||||
|
|
||||||
|
# colour for each material type. If the property name is
|
||||||
|
# not set, then the color won't be changed.
|
||||||
|
master_color_map = {
|
||||||
|
'lambertian': 'reflectance'
|
||||||
|
}
|
||||||
|
|
||||||
|
def set_master_colour(self, s, c):
|
||||||
|
'''
|
||||||
|
This neat little hack will set the blender material colour to the value
|
||||||
|
given in the material panel via the property's 'draw' lambda function.
|
||||||
|
'''
|
||||||
|
|
||||||
|
if c.type in self.master_color_map.keys() and self.attr == self.master_color_map[c.type]:
|
||||||
|
submat = getattr(c, 'mitsuba_mat_%s'%c.type)
|
||||||
|
submat_col = getattr(submat, self.attr+'_color')
|
||||||
|
if s.material.diffuse_color != submat_col:
|
||||||
|
s.material.diffuse_color = submat_col
|
||||||
|
|
||||||
|
def get_properties(self):
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
'attr': self.attr,
|
||||||
|
'type': 'string',
|
||||||
|
'default': 'mts_color_texture'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'attr': '%s_usetexture' % self.attr,
|
||||||
|
'type': 'bool',
|
||||||
|
'name': 'T',
|
||||||
|
'description': 'Textured %s' % self.name,
|
||||||
|
'default': False,
|
||||||
|
'toggle': True,
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'text',
|
||||||
|
'attr': '%s_colorlabel' % self.attr,
|
||||||
|
'name': self.name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'float_vector',
|
||||||
|
'attr': '%s_color' % self.attr,
|
||||||
|
'name': '', #self.name,
|
||||||
|
'description': self.description,
|
||||||
|
'default': self.default,
|
||||||
|
'min': self.min,
|
||||||
|
'soft_min': self.min,
|
||||||
|
'max': self.max,
|
||||||
|
'soft_max': self.max,
|
||||||
|
'subtype': 'COLOR',
|
||||||
|
'draw': lambda s,c: self.set_master_colour(s, c),
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'attr': '%s_texturename' % self.attr,
|
||||||
|
'type': 'string',
|
||||||
|
'name': '%s_texturename' % self.attr,
|
||||||
|
'description': '%s Texture' % self.name,
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'prop_search',
|
||||||
|
'attr': '%s_texture' % self.attr,
|
||||||
|
'src': self.texture_collection_finder(),
|
||||||
|
'src_attr': self.texture_collection,
|
||||||
|
'trg': self.texture_slot_set_attr(),
|
||||||
|
'trg_attr': '%s_texturename' % self.attr,
|
||||||
|
'name': self.name
|
||||||
|
}
|
||||||
|
] + self.get_extra_properties()
|
||||||
|
|
||||||
|
def get_params(self, context):
|
||||||
|
params = ParamSet()
|
||||||
|
if hasattr(context, '%s_usetexture' % self.attr) \
|
||||||
|
and getattr(context, '%s_usetexture' % self.attr):
|
||||||
|
params.add_reference('texture', self.attr, getattr(context, '%s_texturename' % self.attr))
|
||||||
|
else:
|
||||||
|
params.add_color(
|
||||||
|
self.attr,
|
||||||
|
getattr(context, '%s_color' % self.attr)
|
||||||
|
)
|
||||||
|
return params
|
||||||
|
|
||||||
|
class mitsuba_texture(declarative_property_group):
|
||||||
|
'''
|
||||||
|
Storage class for Mitsuba Texture settings.
|
||||||
|
This class will be instantiated within a Blender Texture
|
||||||
|
object.
|
||||||
|
'''
|
||||||
|
|
||||||
|
controls = [
|
||||||
|
'type'
|
||||||
|
]
|
||||||
|
|
||||||
|
properties = [
|
||||||
|
{
|
||||||
|
'attr': 'type',
|
||||||
|
'name': 'Texture type',
|
||||||
|
'type': 'enum',
|
||||||
|
'items': [
|
||||||
|
('ldrtexture', 'Bitmap', 'ldrtexture'),
|
||||||
|
('checkerboard', 'Checkerboard', 'checkerboard')
|
||||||
|
],
|
||||||
|
'default' : 'ldrtexture',
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
if hasattr(self, 'mitsuba_tex_%s' % self.type):
|
||||||
|
mts_texture = getattr(self, 'mitsuba_tex_%s' % self.type)
|
||||||
|
return mts_texture.get_params()
|
||||||
|
else:
|
||||||
|
return ParamSet()
|
||||||
|
|
||||||
|
class mitsuba_tex_ldrtexture(declarative_property_group):
|
||||||
|
controls = [
|
||||||
|
'filename',
|
||||||
|
'filtertype',
|
||||||
|
'gamma',
|
||||||
|
'max_anisotropy',
|
||||||
|
'wrap',
|
||||||
|
]
|
||||||
|
|
||||||
|
visibility = {
|
||||||
|
'max_anisotropy': { 'filtertype': 'ewa' },
|
||||||
|
'gamma': { 'srgb': False }
|
||||||
|
}
|
||||||
|
|
||||||
|
properties = [
|
||||||
|
{
|
||||||
|
'type': 'string',
|
||||||
|
'subtype': 'FILE_PATH',
|
||||||
|
'attr': 'filename',
|
||||||
|
'description' : 'Path to a PNG/JPG/TGA/BMP file',
|
||||||
|
'name': 'File Name',
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'enum',
|
||||||
|
'attr': 'filtertype',
|
||||||
|
'name': 'Filter type',
|
||||||
|
'description' : 'Specifies the type of texture filtering',
|
||||||
|
'items': [
|
||||||
|
('isotropic', 'Isotropic (Trilinear MipMap)', 'isotropic'),
|
||||||
|
('ewa', 'Anisotropic (EWA Filtering)', 'ewa')
|
||||||
|
],
|
||||||
|
'default' : 'ewa',
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'bool',
|
||||||
|
'attr': 'srgb',
|
||||||
|
'name': 'sRGB',
|
||||||
|
'description' : 'Is the texture stored in sRGB color space?',
|
||||||
|
'default': True,
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'float',
|
||||||
|
'attr': 'gamma',
|
||||||
|
'name': 'Gamma',
|
||||||
|
'description' : 'Specifies the texture gamma value',
|
||||||
|
'default': 2.2,
|
||||||
|
'min': 0.01,
|
||||||
|
'soft_min': 0.01,
|
||||||
|
'max': 6.0,
|
||||||
|
'soft_max': 6.0,
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'float',
|
||||||
|
'description' : 'Maximum allowed anisotropy when using the EWA filter',
|
||||||
|
'attr': 'max_anisotropy',
|
||||||
|
'name': 'Max. Anisotropy',
|
||||||
|
'default': 8.0,
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'type': 'enum',
|
||||||
|
'attr': 'wrap',
|
||||||
|
'name': 'Wrapping',
|
||||||
|
'description' : 'What should be done when encountering UV coordinates outside of the range [0,1]',
|
||||||
|
'items': [
|
||||||
|
('repeat', 'Repeat', 'repeat'),
|
||||||
|
('black', 'Black outside of [0, 1]', 'black'),
|
||||||
|
('white', 'White outside of [0, 1]', 'white'),
|
||||||
|
('clamp', 'Clamp to edges', 'clamp')
|
||||||
|
],
|
||||||
|
'save_in_preset': True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
params = ParamSet()
|
||||||
|
|
||||||
|
params.add_string('filename', efutil.path_relative_to_export(self.filename) ) \
|
||||||
|
.add_string('filtertype', self.filtertype) \
|
||||||
|
.add_float('max_anisotropy', self.max_anisotropy) \
|
||||||
|
.add_string('wrap', self.wrap) \
|
||||||
|
.add_float('gamma', -1 if self.srgb else self.gamma)
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
class mitsuba_tex_checkerboard(declarative_property_group):
|
||||||
|
controls = [
|
||||||
|
'darkColor',
|
||||||
|
'brightColor'
|
||||||
|
]
|
||||||
|
|
||||||
|
properties = [
|
||||||
|
{
|
||||||
|
'attr': 'darkColor',
|
||||||
|
'type': 'float_vector',
|
||||||
|
'subtype': 'COLOR',
|
||||||
|
'name' : 'Dark color',
|
||||||
|
'description' : 'Color of the dark patches',
|
||||||
|
'default' : (0.2, 0.2, 0.2),
|
||||||
|
'min': 0.0,
|
||||||
|
'max': 1.0,
|
||||||
|
'save_in_preset': True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'attr': 'brightColor',
|
||||||
|
'type': 'float_vector',
|
||||||
|
'subtype': 'COLOR',
|
||||||
|
'description' : 'Color of the bright patches',
|
||||||
|
'name' : 'Bright color',
|
||||||
|
'default' : (0.4, 0.4, 0.4),
|
||||||
|
'min': 0.0,
|
||||||
|
'max': 1.0,
|
||||||
|
'save_in_preset': True
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_params(self):
|
||||||
|
params = ParamSet()
|
||||||
|
|
||||||
|
params.add_color('darkColor', self.darkColor)
|
||||||
|
params.add_color('brightColor', self.brightColor)
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
|
@ -79,14 +79,13 @@ class lamps(DataButtonsPanel, property_group_renderer, bpy.types.Panel):
|
||||||
|
|
||||||
# AREA LAMP: Blender Properties
|
# AREA LAMP: Blender Properties
|
||||||
elif lamp.type == 'AREA':
|
elif lamp.type == 'AREA':
|
||||||
|
|
||||||
if wide_ui:
|
if wide_ui:
|
||||||
col=layout.row()
|
col=layout.row()
|
||||||
else:
|
else:
|
||||||
col=layout.column()
|
col=layout.column()
|
||||||
col.row().prop(lamp, "shape", expand=True)
|
col.row().prop(lamp, "shape", expand=True)
|
||||||
|
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
|
|
||||||
if (lamp.shape == 'SQUARE'):
|
if (lamp.shape == 'SQUARE'):
|
||||||
sub.prop(lamp, "size")
|
sub.prop(lamp, "size")
|
||||||
elif (lamp.shape == 'RECTANGLE'):
|
elif (lamp.shape == 'RECTANGLE'):
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
from properties_material import MaterialButtonsPanel
|
||||||
|
|
||||||
|
from extensions_framework.ui import property_group_renderer
|
||||||
|
|
||||||
|
class mitsuba_material_base(MaterialButtonsPanel, property_group_renderer):
|
||||||
|
COMPAT_ENGINES = {'mitsuba'}
|
||||||
|
|
||||||
|
class mitsuba_material_sub(MaterialButtonsPanel, property_group_renderer):
|
||||||
|
COMPAT_ENGINES = {'mitsuba'}
|
||||||
|
MTS_COMPAT = set()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
'''
|
||||||
|
Only show Mitsuba panel if mitsuba_material.material in MTS_COMPAT
|
||||||
|
'''
|
||||||
|
|
||||||
|
return super().poll(context) and context.material.mitsuba_material.type in cls.MTS_COMPAT
|
|
@ -0,0 +1,30 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from mitsuba.ui.materials import mitsuba_material_sub
|
||||||
|
|
||||||
|
class ui_material_lambertian(mitsuba_material_sub, bpy.types.Panel):
|
||||||
|
bl_label = 'Mitsuba Lambertian Material'
|
||||||
|
|
||||||
|
MTS_COMPAT = {'lambertian'}
|
||||||
|
|
||||||
|
display_property_groups = [
|
||||||
|
( ('material', 'mitsuba_material'), 'mitsuba_mat_lambertian' )
|
||||||
|
]
|
|
@ -0,0 +1,40 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from mitsuba.ui.materials import mitsuba_material_base
|
||||||
|
|
||||||
|
class main(mitsuba_material_base, bpy.types.Panel):
|
||||||
|
'''
|
||||||
|
Material Editor UI Panel
|
||||||
|
'''
|
||||||
|
|
||||||
|
bl_label = 'Mitsuba Materials'
|
||||||
|
|
||||||
|
display_property_groups = [
|
||||||
|
( ('material',), 'mitsuba_material' )
|
||||||
|
]
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.menu("MITSUBA_MT_presets_material", text=bpy.types.MITSUBA_MT_presets_material.bl_label)
|
||||||
|
row.operator("mitsuba.preset_material_add", text="", icon="ZOOMIN")
|
||||||
|
row.operator("mitsuba.preset_material_add", text="", icon="ZOOMOUT").remove_active = True
|
||||||
|
|
||||||
|
super().draw(context)
|
|
@ -0,0 +1,41 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from properties_texture import TextureButtonsPanel
|
||||||
|
|
||||||
|
from extensions_framework.ui import property_group_renderer
|
||||||
|
|
||||||
|
class mitsuba_texture_base(TextureButtonsPanel, property_group_renderer):
|
||||||
|
'''
|
||||||
|
This is the base class for all Mitsuba texture sub-panels.
|
||||||
|
'''
|
||||||
|
|
||||||
|
COMPAT_ENGINES = {'mitsuba'}
|
||||||
|
MTS_COMPAT = set()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
'''
|
||||||
|
Only show panel if mitsuba_texture.type in MTS_COMPAT
|
||||||
|
'''
|
||||||
|
tex = context.texture
|
||||||
|
return tex and \
|
||||||
|
(context.scene.render.engine in cls.COMPAT_ENGINES) and \
|
||||||
|
context.texture.mitsuba_texture.type in cls.MTS_COMPAT
|
|
@ -0,0 +1,30 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from mitsuba.ui.textures import mitsuba_texture_base
|
||||||
|
|
||||||
|
class ui_texture_checkerboard(mitsuba_texture_base, bpy.types.Panel):
|
||||||
|
bl_label = 'Mitsuba Checkerboard Texture'
|
||||||
|
|
||||||
|
MTS_COMPAT = {'checkerboard'}
|
||||||
|
|
||||||
|
display_property_groups = [
|
||||||
|
( ('texture', 'mitsuba_texture'), 'mitsuba_tex_checkerboard' )
|
||||||
|
]
|
|
@ -0,0 +1,30 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from mitsuba.ui.textures import mitsuba_texture_base
|
||||||
|
|
||||||
|
class ui_texture_ldrtexture(mitsuba_texture_base, bpy.types.Panel):
|
||||||
|
bl_label = 'Mitsuba Bitmap Texture'
|
||||||
|
|
||||||
|
MTS_COMPAT = {'ldrtexture'}
|
||||||
|
|
||||||
|
display_property_groups = [
|
||||||
|
( ('texture', 'mitsuba_texture'), 'mitsuba_tex_ldrtexture' )
|
||||||
|
]
|
|
@ -0,0 +1,48 @@
|
||||||
|
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
#
|
||||||
|
# ##### END GPL LICENSE BLOCK #####
|
||||||
|
|
||||||
|
import bpy
|
||||||
|
|
||||||
|
from mitsuba.ui.textures import mitsuba_texture_base
|
||||||
|
|
||||||
|
class ui_texture_main(mitsuba_texture_base, bpy.types.Panel):
|
||||||
|
'''
|
||||||
|
Texture Editor UI Panel
|
||||||
|
'''
|
||||||
|
|
||||||
|
bl_label = 'Mitsuba Textures'
|
||||||
|
|
||||||
|
display_property_groups = [
|
||||||
|
( ('texture',), 'mitsuba_texture' )
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
'''
|
||||||
|
Only show Mitsuba panel with the correct texture type
|
||||||
|
'''
|
||||||
|
tex = context.texture
|
||||||
|
return tex and (context.scene.render.engine in cls.COMPAT_ENGINES)
|
||||||
|
|
||||||
|
def draw(self, context):
|
||||||
|
row = self.layout.row(align=True)
|
||||||
|
row.menu("MITSUBA_MT_presets_texture", text=bpy.types.MITSUBA_MT_presets_texture.bl_label)
|
||||||
|
row.operator("mitsuba.preset_texture_add", text="", icon="ZOOMIN")
|
||||||
|
row.operator("mitsuba.preset_texture_add", text="", icon="ZOOMOUT").remove_active = True
|
||||||
|
|
||||||
|
super().draw(context)
|
Loading…
Reference in New Issue