MtsBlend: support for textures and materials

metadata
Wenzel Jakob 2010-11-13 01:40:31 +01:00
parent 81982c8932
commit fd68671dbc
16 changed files with 1061 additions and 176 deletions

View File

@ -29,29 +29,29 @@ MTS_NAMESPACE_BEGIN
class Checkerboard : public Texture2D {
public:
Checkerboard(const Properties &props) : Texture2D(props) {
m_brightReflectance = props.getSpectrum("brightReflectance", Spectrum(.4f));
m_darkReflectance = props.getSpectrum("darkReflectance", Spectrum(.2f));
m_brightColor.g = props.getSpectrum("brightReflectance", Spectrum(.4f));
m_darkColor.g = props.getSpectrum("darkReflectance", Spectrum(.2f));
}
Checkerboard(Stream *stream, InstanceManager *manager)
: Texture2D(stream, manager) {
m_brightReflectance = Spectrum(stream);
m_darkReflectance = Spectrum(stream);
m_brightColor.g = Spectrum(stream);
m_darkColor.g = Spectrum(stream);
}
void serialize(Stream *stream, InstanceManager *manager) const {
Texture2D::serialize(stream, manager);
m_brightReflectance.serialize(stream);
m_darkReflectance.serialize(stream);
m_brightColor.g.serialize(stream);
m_darkColor.g.serialize(stream);
}
inline Spectrum getValue(const Point2 &uv) const {
int x = 2*(((int) uv.x) % 2) - 1, y = 2*(((int) uv.y) % 2) - 1;
if (x*y == 1)
return m_brightReflectance;
return m_brightColor.g;
else
return m_darkReflectance;
return m_darkColor.g;
}
Spectrum getValue(const Point2 &uv, Float dudx, Float dudy, Float dvdx, Float dvdy) const {
@ -63,11 +63,11 @@ public:
}
Spectrum getAverage() const {
return m_darkReflectance * .5f;
return m_darkColor.g * .5f;
}
Spectrum getMaximum() const {
return m_brightReflectance;
return m_brightColor.g;
}
std::string toString() const {
@ -78,26 +78,26 @@ public:
MTS_DECLARE_CLASS()
protected:
Spectrum m_darkReflectance;
Spectrum m_brightReflectance;
Spectrum m_darkColor.g;
Spectrum m_brightColor.g;
};
// ================ Hardware shader implementation ================
class CheckerboardShader : public Shader {
public:
CheckerboardShader(Renderer *renderer, const Spectrum &brightReflectance,
const Spectrum &darkReflectance, const Point2 &uvOffset,
CheckerboardShader(Renderer *renderer, const Spectrum &brightColor.g,
const Spectrum &darkColor.g, const Point2 &uvOffset,
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) {
}
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "uniform vec3 " << evalName << "_brightReflectance;" << endl
<< "uniform vec3 " << evalName << "_darkReflectance;" << endl
oss << "uniform vec3 " << evalName << "_brightColor.g;" << endl
<< "uniform vec3 " << evalName << "_darkColor.g;" << endl
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
<< "uniform vec2 " << evalName << "_uvScale;" << endl
<< endl
@ -107,37 +107,37 @@ public:
<< " 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
<< " if (x*y == 1)" << endl
<< " return " << evalName << "_brightReflectance;" << endl
<< " return " << evalName << "_brightColor.g;" << endl
<< " else" << endl
<< " return " << evalName << "_darkReflectance;" << endl
<< " return " << evalName << "_darkColor.g;" << endl
<< "}" << endl;
}
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> &parameterIDs) const {
parameterIDs.push_back(program->getParameterID(evalName + "_brightReflectance", false));
parameterIDs.push_back(program->getParameterID(evalName + "_darkReflectance", false));
parameterIDs.push_back(program->getParameterID(evalName + "_brightColor.g", false));
parameterIDs.push_back(program->getParameterID(evalName + "_darkColor.g", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
}
void bind(GPUProgram *program, const std::vector<int> &parameterIDs,
int &textureUnitOffset) const {
program->setParameter(parameterIDs[0], m_brightReflectance);
program->setParameter(parameterIDs[1], m_darkReflectance);
program->setParameter(parameterIDs[0], m_brightColor.g);
program->setParameter(parameterIDs[1], m_darkColor.g);
program->setParameter(parameterIDs[2], m_uvOffset);
program->setParameter(parameterIDs[3], m_uvScale);
}
MTS_DECLARE_CLASS()
private:
Spectrum m_brightReflectance;
Spectrum m_darkReflectance;
Spectrum m_brightColor.g;
Spectrum m_darkColor.g;
Point2 m_uvOffset;
Vector2 m_uvScale;
};
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);
}

View File

@ -29,22 +29,22 @@ MTS_NAMESPACE_BEGIN
class GridTexture : public Texture2D {
public:
GridTexture(const Properties &props) : Texture2D(props) {
m_brightReflectance = props.getSpectrum("brightReflectance", Spectrum(.4f));
m_darkReflectance = props.getSpectrum("darkReflectance", Spectrum(.2f));
m_brightColor = props.getSpectrum("brightColor", Spectrum(.4f));
m_darkColor = props.getSpectrum("darkColor", Spectrum(.2f));
m_width = props.getFloat("width", .01f);
}
GridTexture(Stream *stream, InstanceManager *manager)
: Texture2D(stream, manager) {
m_brightReflectance = Spectrum(stream);
m_darkReflectance = Spectrum(stream);
m_brightColor = Spectrum(stream);
m_darkColor = Spectrum(stream);
m_width = stream->readFloat();
}
void serialize(Stream *stream, InstanceManager *manager) const {
Texture2D::serialize(stream, manager);
m_brightReflectance.serialize(stream);
m_darkReflectance.serialize(stream);
m_brightColor.serialize(stream);
m_darkColor.serialize(stream);
stream->writeFloat(m_width);
}
@ -58,9 +58,9 @@ public:
y-=1;
if (std::abs(x) < m_width || std::abs(y) < m_width)
return m_darkReflectance;
return m_darkColor;
else
return m_brightReflectance;
return m_brightColor;
}
Spectrum getValue(const Point2 &uv, Float dudx,
@ -73,11 +73,11 @@ public:
}
Spectrum getMaximum() const {
return m_brightReflectance;
return m_brightColor;
}
Spectrum getAverage() const {
return m_brightReflectance; // that's not quite right
return m_brightColor; // that's not quite right
}
std::string toString() const {
@ -88,8 +88,8 @@ public:
MTS_DECLARE_CLASS()
protected:
Spectrum m_brightReflectance;
Spectrum m_darkReflectance;
Spectrum m_brightColor;
Spectrum m_darkColor;
Float m_width;
};
@ -97,18 +97,18 @@ protected:
class GridTextureShader : public Shader {
public:
GridTextureShader(Renderer *renderer, const Spectrum &brightReflectance,
const Spectrum &darkReflectance, Float width, const Point2 &uvOffset,
GridTextureShader(Renderer *renderer, const Spectrum &brightColor,
const Spectrum &darkColor, Float width, const Point2 &uvOffset,
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) {
}
void generateCode(std::ostringstream &oss,
const std::string &evalName,
const std::vector<std::string> &depNames) const {
oss << "uniform vec3 " << evalName << "_brightReflectance;" << endl
<< "uniform vec3 " << evalName << "_darkReflectance;" << endl
oss << "uniform vec3 " << evalName << "_brightColor;" << endl
<< "uniform vec3 " << evalName << "_darkColor;" << endl
<< "uniform float " << evalName << "_width;" << endl
<< "uniform vec2 " << evalName << "_uvOffset;" << endl
<< "uniform vec2 " << evalName << "_uvScale;" << endl
@ -122,15 +122,15 @@ public:
<< " if (x > .5) x -= 1.0;" << endl
<< " if (y > .5) y -= 1.0;" << endl
<< " if (abs(x) < " << evalName << "_width || abs(y) < " << evalName << "_width)" << endl
<< " return " << evalName << "_darkReflectance;" << endl
<< " return " << evalName << "_darkColor;" << endl
<< " else" << endl
<< " return " << evalName << "_brightReflectance;" << endl
<< " return " << evalName << "_brightColor;" << endl
<< "}" << endl;
}
void resolve(const GPUProgram *program, const std::string &evalName, std::vector<int> &parameterIDs) const {
parameterIDs.push_back(program->getParameterID(evalName + "_brightReflectance", false));
parameterIDs.push_back(program->getParameterID(evalName + "_darkReflectance", false));
parameterIDs.push_back(program->getParameterID(evalName + "_brightColor", false));
parameterIDs.push_back(program->getParameterID(evalName + "_darkColor", false));
parameterIDs.push_back(program->getParameterID(evalName + "_width", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvOffset", false));
parameterIDs.push_back(program->getParameterID(evalName + "_uvScale", false));
@ -138,8 +138,8 @@ public:
void bind(GPUProgram *program, const std::vector<int> &parameterIDs,
int &textureUnitOffset) const {
program->setParameter(parameterIDs[0], m_brightReflectance);
program->setParameter(parameterIDs[1], m_darkReflectance);
program->setParameter(parameterIDs[0], m_brightColor);
program->setParameter(parameterIDs[1], m_darkColor);
program->setParameter(parameterIDs[2], m_width);
program->setParameter(parameterIDs[3], m_uvOffset);
program->setParameter(parameterIDs[4], m_uvScale);
@ -147,15 +147,15 @@ public:
MTS_DECLARE_CLASS()
private:
Spectrum m_brightReflectance;
Spectrum m_darkReflectance;
Spectrum m_brightColor;
Spectrum m_darkColor;
Float m_width;
Point2 m_uvOffset;
Vector2 m_uvScale;
};
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);
}

View File

@ -29,12 +29,19 @@ from extensions_framework import util as efutil
# Mitsuba-related classes
from mitsuba.properties.engine import mitsuba_engine
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.outputs import MtsLog, MtsFilmDisplay
from mitsuba.export.film import resolution
from mitsuba.ui import render_panels
from mitsuba.ui import lamps
from mitsuba.ui.textures import main, ldrtexture, checkerboard
from mitsuba.ui.materials import main, lambertian
def compatible(mod):
mod = __import__(mod)
@ -45,7 +52,6 @@ def compatible(mod):
pass
del mod
import properties_data_lamp
properties_data_lamp.DATA_PT_context_lamp.COMPAT_ENGINES.add('mitsuba')
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')
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_camera")
@ -65,7 +75,12 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
property_groups = [
('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()
@ -142,7 +157,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
self.render_update_timer.start()
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:
# Use SIGTERM because that's the only one supported on Windows
mitsuba_process.send_signal(subprocess.signal.SIGTERM)
@ -152,6 +167,7 @@ class RENDERENGINE_mitsuba(bpy.types.RenderEngine, engine_base):
framebuffer_thread.join()
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.')
else:
framebuffer_thread.kick(render_end=True)

View File

@ -16,105 +16,84 @@
#
# ##### 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:
'''
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, *args):
self.type, self.name, self.value = args
self.type_name = "%s %s" % (self.type, self.name)
self.append(self.type_name)
self.append(self.value)
def __init__(self, target_file, target_dir):
self.target_file = target_file
self.target_dir = target_dir
def to_string(self):
if self.type == "color":
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):
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')
class ParamSet(list):
names = []
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)
def update(self, other):
for p in other:
self.add(p.type, p.name, p.value)
return self
adjfile.write('\t\t<string name="filename" value="%s"/>\n' % path)
self.export_worldtrafo(adjfile, lamp.matrix_world)
def add(self, type, name, value):
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)
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')
self.append(
ParamSetItem(type, name, value)
)
self.names.append(name)
return self
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)
idx = idx+1
adjfile.write('</adjustments>\n');
adjfile.close()
def add_float(self, name, value):
self.add('float', name, value)
return self
def add_integer(self, name, value):
self.add('integer', name, value)
return self
def add_reference(self, type, name, value):
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)

View File

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

View File

@ -27,7 +27,7 @@ from presets import AddPresetBase
from extensions_framework import util as efutil
from mitsuba.outputs import MtsLog
from mitsuba.export import MtsAdjustments
from mitsuba.export.adjustments import MtsAdjustments
def try_preset_path_create(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'
class MitsubaCheckOp(bpy.types.Operator):
bl_idname = 'mts.check'
bl_label = 'Check scene'
def reportWarning(self, msg):
self.report({'WARNING'}, msg)
MtsLog("MtsBlend: %s" % msg)
class MITSUBA_MT_presets_texture(MITSUBA_MT_base, bpy.types.Menu):
bl_label = "Mitsuba Texture Presets"
preset_subdir = "mitsuba/texture"
def _check_lamp(self, lamp):
hasErrors = False
if lamp.type == 'POINT' and lamp.falloff_type != 'INVERSE_SQUARE':
self.reportWarning('Point light "%s" needs to have inverse square falloff' % lamp.name)
hasErrors = True
if hasErrors:
self.reportWarning('Encountered one or more problems -- check the console')
else:
self.report({'INFO'}, "No problems found")
class MITSUBA_OT_preset_texture_add(MITSUBA_OT_preset_base, bpy.types.Operator):
'''Save the current settings as a preset'''
bl_idname = 'mitsuba.preset_texture_add'
bl_label = 'Add Mitsuba Texture settings preset'
preset_menu = 'MITSUBA_MT_presets_texture'
preset_values = []
preset_subdir = 'mitsuba/texture'
def execute(self, context):
scene = bpy.data.scenes[0]
for obj in scene.objects:
if obj.type == 'LAMP':
self._check_lamp(obj.data)
return {'FINISHED'}
pv = [
'bpy.context.texture.mitsuba_texture.%s'%v['attr'] for v in bpy.types.mitsuba_texture.get_exportable_properties()
]
mts_type = context.texture.mitsuba_texture.type
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):
bl_idname = 'export.mitsuba'

View File

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

View File

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

View File

@ -79,14 +79,13 @@ class lamps(DataButtonsPanel, property_group_renderer, bpy.types.Panel):
# AREA LAMP: Blender Properties
elif lamp.type == 'AREA':
if wide_ui:
col=layout.row()
else:
col=layout.column()
col.row().prop(lamp, "shape", expand=True)
sub = col.column(align=True)
if (lamp.shape == 'SQUARE'):
sub.prop(lamp, "size")
elif (lamp.shape == 'RECTANGLE'):

View File

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

View File

@ -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' )
]

View File

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

View File

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

View File

@ -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' )
]

View File

@ -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' )
]

View File

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