# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is the Python Computer Graphics Kit.
#
# The Initial Developer of the Original Code is Matthias Baas.
# Portions created by the Initial Developer are Copyright (C) 2004
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
# $Id: material3ds.py,v 1.4 2005/08/28 19:42:43 mbaas Exp $
## \file material3ds.py
## Contains the Material3DS class.
import os.path, sys, shutil
import protocols
from _OpenGL.GL import *
from Interfaces import *
from slots import *
import lookat, sl, math
from material import Material
from glmaterial import GLMaterial,GLTexture
import ribexport
import _Image as Image
# TextureMap3DS
class TextureMap3DS:
"""A texture map definition as it appears in 3DS files.
"""
def __init__(self,
name,
flags = 0,
percent = 0.0,
blur = 0.0,
scale = (1.0, 1.0),
offset = (0,0),
rotation = 0,
tint1 = (0,0,0),
tint2 = (0,0,0),
tintr = (0,0,0),
tintg = (0,0,0),
tintb = (0,0,0)
):
self.name = name
self.flags = flags
self.percent = percent
self.blur = blur
self.scale = scale
self.offset = offset
self.rotation = rotation
self.tint1 = tint1
self.tint2 = tint2
self.tintr = tintr
self.tintg = tintg
self.tintb = tintb
def __str__(self):
s = "TextureMap3DS:\n"
s += ' Name : "%s"\n'%self.name
s += ' Flags : %d\n'%self.flags
s += ' Percent : %s\n'%self.percent
s += ' Blur : %s\n'%self.blur
s += ' Scale : %s, %s\n'%self.scale
s += ' Offset : %s, %s\n'%self.offset
s += ' Rotation: %s\n'%self.rotation
s += ' Tint1 : %s\n'%(self.tint1,)
s += ' Tint2 : %s\n'%(self.tint2,)
s += ' TintR : %s\n'%(self.tintr,)
s += ' TintG : %s\n'%(self.tintg,)
s += ' TintB : %s'%(self.tintb,)
return s
# Material3DS
class Material3DS(Material):
"""This class represents a material as it appears in 3DS files.
"""
protocols.advise(instancesProvide=[ribexport.IMaterial])
# protocols.advise(instancesProvide=[ISceneItem])
def __init__(self,
name="Material3DS",
ambient = (0,0,0,0),
diffuse = (1.0, 1.0, 1.0, 1.0),
specular = (1.0, 1.0, 1.0, 1.0),
shininess = 1,
shin_strength = 0,
use_blur = 0,
transparency = 0.0,
falloff = 0,
additive = 0,
use_falloff = 0,
self_illum = False,
self_ilpct = 0.0,
shading = 0,
soften = 0,
face_map = 0,
two_sided = 0,
map_decal = 0,
use_wire = 0,
use_wire_abs = 0,
wire_size = 0,
density = 1.0,
texture1_map = None,
texture1_mask = None,
texture2_map = None,
texture2_mask = None,
opacity_map = None,
opacity_mask = None,
bump_map = None,
bump_mask = None,
specular_map = None,
specular_mask = None,
shininess_map = None,
shininess_mask = None,
self_illum_map = None,
self_illum_mask = None,
reflection_map = None,
reflection_mask = None,
bump_size = 1.0 # Extra parameter to control the bump map
):
Material.__init__(self, name=name, density=density)
self.ambient = ambient
self.diffuse = diffuse
self.specular = specular
self.shininess = shininess
self.shin_strength = shin_strength
self.transparency = transparency
self.self_illum = self_illum
self.self_ilpct = self_ilpct
self.texture1_map = texture1_map
self.texture1_mask = texture1_mask
self.texture2_map = texture2_map
self.texture2_mask = texture2_mask
self.opacity_map = opacity_map
self.opacity_mask = opacity_mask
self.bump_map = bump_map
self.bump_mask = bump_mask
self.specular_map = specular_map
self.specular_mask = specular_mask
self.shininess_map = shininess_map
self.shininess_mask = shininess_mask
self.self_illum_map = self_illum_map
self.self_illum_mask = self_illum_mask
self.reflection_map = reflection_map
self.reflection_mask = reflection_mask
self.bump_size = bump_size
if texture1_map==None:
self._gltexture = None
glambient = ambient
gldiffuse = diffuse
else:
map = texture1_map
T = mat4(1,0,0,-map.offset[0]-0.5, 0,-1,0,0.5-map.offset[1], 0,0,1,0, 0,0,0,1)
a = sl.radians(map.rotation)
ca = math.cos(a)
sa = math.sin(a)
R = mat4(ca,-sa,0,0, sa,ca,0,0, 0,0,1,0, 0,0,0,1)
S = mat4(map.scale[0],0,0,0.5, 0,map.scale[1],0,0.5, 0,0,1,0, 0,0,0,1)
self._gltexture = GLTexture(imagename = map.name,
mode = GL_MODULATE,
# transform = mat4().scaling(vec3(1,-1,1))
transform = S*R*T
)
glambient = map.percent*vec4(1,1,1,1) + (1-map.percent)*vec4(ambient)
gldiffuse = map.percent*vec4(1,1,1,1) + (1-map.percent)*vec4(diffuse)
self._glmaterial = GLMaterial(ambient = glambient,
diffuse = gldiffuse,
specular = shin_strength*specular,
shininess = 25*shininess,
texture = self._gltexture
)
## print >>sys.stderr, "---",name,"---"
## print >>sys.stderr, "ambient",self.ambient
## print >>sys.stderr, "diffuse",self.diffuse
## print >>sys.stderr, "Map1:"
## print >>sys.stderr, self.texture1_map
## print >>sys.stderr, "Map2:"
## print >>sys.stderr, self.texture2_map
## print >>sys.stderr, "Opacity:"
## print >>sys.stderr, self.opacity_map
## print >>sys.stderr, "Bump:"
## print >>sys.stderr, self.bump_map
## print >>sys.stderr, "Specular:"
## print >>sys.stderr, self.specular_map
## print >>sys.stderr, "Shininess:"
## print >>sys.stderr, self.shininess_map
## print >>sys.stderr, "Self illum:"
## print >>sys.stderr, self.self_illum_map
## print >>sys.stderr, "Reflection:"
## print >>sys.stderr, self.reflection_map
## print >>sys.stderr, "shininess",shininess
## print >>sys.stderr, "shin_strength",shin_strength
## print >>sys.stderr, "transparency",transparency
## print >>sys.stderr, "falloff",falloff
## print >>sys.stderr, "use_falloff",use_falloff
## print >>sys.stderr, "use_blur", use_blur
## print >>sys.stderr, "additive",additive
## print >>sys.stderr, "shading",shading
## print >>sys.stderr, "soften",soften
## print >>sys.stderr, "self_illum", self_illum
## print >>sys.stderr, "face_map", face_map
## print >>sys.stderr, "two_sided", two_sided
## print >>sys.stderr, "map_decal", map_decal
## print >>sys.stderr, "use_wire", use_wire
## print >>sys.stderr, "use_wire_abs", use_wire_abs
## print >>sys.stderr, "wire_size", wire_size
def applyGL(self):
self._glmaterial.applyGL()
def usesBlending(self):
return self._glmaterial.usesBlending()
def createPasses(self):
"""Returns a list of RenderPass objects."""
texdefs = []
texdefs += self._createTexDef(self.texture1_map)
texdefs += self._createTexDef(self.opacity_map)
texdefs += self._createTexDef(self.bump_map)
texdefs += self._createTexDef(self.specular_map)
texdefs += self._createTexDef(self.shininess_map)
texdefs += self._createTexDef(self.self_illum_map)
texdefs += self._createTexDef(self.reflection_map)
if texdefs!=[]:
return [ribexport.TexPass(maps=texdefs)]
else:
return []
def preProcess(self, exporter):
"""Preprocessing method.
This method is called before the image is rendered and can be used
to create or copy image maps.
"""
pass
# self._copyImageMap(self.texture1_map, exporter)
# self._copyImageMap(self.opacity_map, exporter)
# self._copyImageMap(self.bump_map, exporter)
# self._copyImageMap(self.specular_map, exporter)
# self._copyImageMap(self.shininess_map, exporter)
# self._copyImageMap(self.self_illum_map, exporter)
# self._copyImageMap(self.reflection_map, exporter)
def color(self):
"""Return the color for the RiColor() call or None.
"""
return self.diffuse
def opacity(self):
"""Return the opacity for the RiOpacity() call or None.
"""
a = 1.0-self.transparency
return (a,a,a)
def surfaceShaderName(self):
"""Returns the name of the corresponding surface shader or None.
"""
return "mat3ds"
def surfaceShaderSource(self):
"""Returns surface shader source code as a string or None.
If the return value is None, then shaderName() must return
the name of the shader to use.
"""
return """// 3DS material shader
surface $SHADERNAME(color ambient_col = color "rgb" (0, 0, 0);
color diffuse_col = color "rgb" (1, 1, 1);
color specular_col = color "rgb" (1, 1, 1);
float shininess = 0.0;
float shin_strength = 0.0;
float self_ilpct = 0.0;
// Texture map 1
string texture1_map = "";
float t1_uscale = 1.0;
float t1_vscale = 1.0;
float t1_uoffset = 0;
float t1_voffset = 0;
float t1_rotation = 0;
float t1_blur = 0.0;
// Specular map
string specular_map = "";
float sp_uscale = 1.0;
float sp_vscale = 1.0;
float sp_uoffset = 0;
float sp_voffset = 0;
float sp_rotation = 0;
float sp_blur = 0.0;
// Shininess map
string shininess_map = "";
float sh_uscale = 1.0;
float sh_vscale = 1.0;
float sh_uoffset = 0;
float sh_voffset = 0;
float sh_rotation = 0;
float sh_blur = 0.0;
// Opacity map
string opacity_map = "";
float op_uscale = 1.0;
float op_vscale = 1.0;
float op_uoffset = 0;
float op_voffset = 0;
float op_rotation = 0;
float op_blur = 0.0;
// Self illumination map
string self_illum_map = "";
float si_uscale = 1.0;
float si_vscale = 1.0;
float si_uoffset = 0;
float si_voffset = 0;
float si_rotation = 0;
float si_blur = 0.0;
// Reflection map
string reflection_map = "";
float refl_uscale = 1.0;
float refl_vscale = 1.0;
float refl_uoffset = 0;
float refl_voffset = 0;
float refl_rotation = 0;
float refl_percent = 0.0;
float refl_blur = 0.0;
varying point Pref = point(0,0,0);
)
{
BAKE_BEGIN
normal Nf = BAKE_NORMAL(N);
color C_diffuse = diffuse_col;
color C_specular = specular_col;
color C_opacity = Os;
color C_refl = 0;
float final_shininess = shininess;
float final_self_ilpct = self_ilpct;
float s0, t0, ss, tt, a, ca, sa;
color col;
if (texture1_map!="")
{
a = radians(t1_rotation);
ca = cos(a);
sa = sin(a);
s0 = s-t1_uoffset-0.5;
t0 = 0.5-t-t1_voffset;
ss = ca*s0 - sa*t0;
tt = sa*s0 + ca*t0;
ss = t1_uscale*ss+0.5;
tt = t1_vscale*tt+0.5;
C_diffuse = texture(texture1_map, ss, tt, "blur", t1_blur);
}
if (specular_map!="")
{
a = radians(sp_rotation);
ca = cos(a);
sa = sin(a);
s0 = s-sp_uoffset-0.5;
t0 = 0.5-t-sp_voffset;
ss = ca*s0 - sa*t0;
tt = sa*s0 + ca*t0;
ss = sp_uscale*ss+0.5;
tt = sp_vscale*tt+0.5;
C_specular = texture(specular_map, ss, tt, "blur", sp_blur);
}
if (shininess_map!="")
{
a = radians(sh_rotation);
ca = cos(a);
sa = sin(a);
s0 = s-sh_uoffset-0.5;
t0 = 0.5-t-sh_voffset;
ss = ca*s0 - sa*t0;
tt = sa*s0 + ca*t0;
ss = sh_uscale*ss+0.5;
tt = sh_vscale*tt+0.5;
col = texture(shininess_map, ss, tt, "blur", sh_blur);
final_shininess = (comp(col,0)+comp(col,1)+comp(col,2))/3;
}
if (opacity_map!="")
{
a = radians(op_rotation);
ca = cos(a);
sa = sin(a);
s0 = s-op_uoffset-0.5;
t0 = 0.5-t-op_voffset;
ss = ca*s0 - sa*t0;
tt = sa*s0 + ca*t0;
ss = op_uscale*ss+0.5;
tt = op_vscale*tt+0.5;
float op = texture(opacity_map, ss, tt, "blur", op_blur);
C_opacity = color "rgb" (op, op, op);
}
if (self_illum_map!="")
{
a = radians(si_rotation);
ca = cos(a);
sa = sin(a);
s0 = s-si_uoffset-0.5;
t0 = 0.5-t-si_voffset;
ss = ca*s0 - sa*t0;
tt = sa*s0 + ca*t0;
ss = si_uscale*ss+0.5;
tt = si_vscale*tt+0.5;
col = texture(self_illum_map, ss, tt, "blur", si_blur);
final_self_ilpct = (comp(col,0)+comp(col,1)+comp(col,2))/3;
}
if (reflection_map!="")
{
vector R = normalize(vtransform("world", reflect(I, Nf)));
float lat = acos(zcomp(R));
float long = acos(ycomp(R)/sin(lat));
lat = lat/PI;
long = long/(2*PI);
if (xcomp(R)>0)
long = -long;
C_refl = texture(reflection_map, long, lat, "blur", refl_blur);
}
Ci = C_diffuse*diffuse(Nf) +
shin_strength*C_specular*phong(Nf, -normalize(I), 25*final_shininess) +
refl_percent*C_refl;
Ci = mix(Ci, C_diffuse, final_self_ilpct);
Oi = C_opacity;
Ci *= Oi;
BAKE_END
}
"""
def surfaceShaderParams(self, passes):
"""Return a dictionary with shader parameters and their values."""
a = self.ambient
d = self.diffuse
s = self.specular
res = {"uniform color ambient_col" : (a[0], a[1], a[2]),
"uniform color diffuse_col" : (d[0], d[1], d[2]),
"uniform color specular_col" : (s[0], s[1], s[2]),
"uniform float shininess" : self.shininess,
"uniform float shin_strength" : self.shin_strength,
"uniform float self_ilpct" : self.self_ilpct
}
if self.texture1_map!=None:
texname = os.path.basename(self.texture1_map.name)
name, ext = os.path.splitext(texname)
res["uniform string texture1_map"] = name+".tex"
res["uniform float t1_uscale"] = self.texture1_map.scale[0]
res["uniform float t1_vscale"] = self.texture1_map.scale[1]
res["uniform float t1_uoffset"] = self.texture1_map.offset[0]
res["uniform float t1_voffset"] = self.texture1_map.offset[1]
res["uniform float t1_rotation"] = self.texture1_map.rotation
if self.specular_map!=None:
texname = os.path.basename(self.specular_map.name)
name, ext = os.path.splitext(texname)
res["uniform string specular_map"] = name+".tex"
res["uniform float sp_uscale"] = self.specular_map.scale[0]
res["uniform float sp_vscale"] = self.specular_map.scale[1]
res["uniform float sp_uoffset"] = self.specular_map.offset[0]
res["uniform float sp_voffset"] = self.specular_map.offset[1]
res["uniform float sp_rotation"] = self.specular_map.rotation
if self.shininess_map!=None:
texname = os.path.basename(self.shininess_map.name)
name, ext = os.path.splitext(texname)
res["uniform string shininess_map"] = name+".tex"
res["uniform float sh_uscale"] = self.shininess_map.scale[0]
res["uniform float sh_vscale"] = self.shininess_map.scale[1]
res["uniform float sh_uoffset"] = self.shininess_map.offset[0]
res["uniform float sh_voffset"] = self.shininess_map.offset[1]
res["uniform float sh_rotation"] = self.shininess_map.rotation
if self.opacity_map!=None:
texname = os.path.basename(self.opacity_map.name)
name, ext = os.path.splitext(texname)
res["uniform string opacity_map"] = name+".tex"
res["uniform float op_uscale"] = self.opacity_map.scale[0]
res["uniform float op_vscale"] = self.opacity_map.scale[1]
res["uniform float op_uoffset"] = self.opacity_map.offset[0]
res["uniform float op_voffset"] = self.opacity_map.offset[1]
res["uniform float op_rotation"] = self.opacity_map.rotation
if self.self_illum_map!=None:
texname = os.path.basename(self.self_illum_map.name)
name, ext = os.path.splitext(texname)
res["uniform string self_illum_map"] = name+".tex"
res["uniform float si_uscale"] = self.self_illum_map.scale[0]
res["uniform float si_vscale"] = self.self_illum_map.scale[1]
res["uniform float si_uoffset"] = self.self_illum_map.offset[0]
res["uniform float si_voffset"] = self.self_illum_map.offset[1]
res["uniform float si_rotation"] = self.self_illum_map.rotation
if self.reflection_map!=None:
texname = os.path.basename(self.reflection_map.name)
name, ext = os.path.splitext(texname)
res["uniform string reflection_map"] = name+".tex"
res["uniform float refl_uscale"] = self.reflection_map.scale[0]
res["uniform float refl_vscale"] = self.reflection_map.scale[1]
res["uniform float refl_uoffset"] = self.reflection_map.offset[0]
res["uniform float refl_voffset"] = self.reflection_map.offset[1]
res["uniform float refl_rotation"] = self.reflection_map.rotation
res["uniform float refl_percent"] = self.reflection_map.percent
res["uniform float refl_blur"] = self.reflection_map.blur
return res
def surfaceShaderTransform(self):
return mat4(1)
def displacementShaderName(self):
if self.bump_map==None:
return None
return "mat3ds_bump"
def displacementShaderSource(self):
if self.bump_map==None:
return None
return """// 3DS material shader (bump)
displacement $SHADERNAME(
// Bump map
string bump_map = "";
float uscale = 1.0;
float vscale = 1.0;
float uoffset = 0;
float voffset = 0;
float rotation = 0;
float blur = 0;
float bump_size = 1.0;
)
{
float s0, t0, ss, tt, a, ca, sa;
color bc;
float amount = 0.0;
if (bump_map!="")
{
a = radians(rotation);
ca = cos(a);
sa = sin(a);
s0 = s-uoffset-0.5;
t0 = 0.5-t-voffset;
ss = ca*s0 - sa*t0;
tt = sa*s0 + ca*t0;
ss = uscale*ss+0.5;
tt = vscale*tt+0.5;
bc = texture(bump_map, ss, tt, "blur", blur);
amount = (comp(bc,0)+comp(bc,1)+comp(bc,2))/3;
}
P = P - bump_size*amount*normalize(N);
N = calculatenormal(P);
}
"""
def displacementShaderParams(self, passes):
if self.bump_map==None:
return {}
res = {}
texname = os.path.basename(self.bump_map.name)
name, ext = os.path.splitext(texname)
res["uniform string bump_map"] = name+".tex"
res["uniform float uscale"] = self.bump_map.scale[0]
res["uniform float vscale"] = self.bump_map.scale[1]
res["uniform float uoffset"] = self.bump_map.offset[0]
res["uniform float voffset"] = self.bump_map.offset[1]
res["uniform float rotation"] = self.bump_map.rotation
res["uniform float blur"] = self.bump_map.blur
res["uniform float bump_size"] = self.bump_size
return res
def displacementBound(self):
if self.bump_map==None:
return "current", 0
else:
return "current", self.bump_size
def displacementShaderTransform(self):
return mat4(1)
def interiorShaderName(self):
return None
def interiorShaderSource(self):
return None
def interiorShaderParams(self, passes):
return {}
def interiorShaderTransform(self):
return mat4(1)
## def _copyImageMap(self, texmap, exporter):
## """Copy the texture map image into the map folder.
## \param texmap (\c TextureMap3DS) Texture map object or None
## \param exporter Exporter instance
## """
## return
## if texmap==None:
## return
## exporter.checkMapPath()
## texname = os.path.basename(texmap.name)
## name, ext = os.path.splitext(texname)
## if ext.lower()!=".tif":
## print 'Converting "%s"'%texmap.name
## tifname = os.path.join(exporter.map_path, name+".tif")
## # Read original map
## try:
## img = Image.open(texmap.name)
## except IOError, e:
## print e
## return
## # Save map as TIF file
## img.save(tifname)
## else:
## print 'Copying "%s"'%texmap.name
## shutil.copyfile(texmap.name, os.path.join(exporter.map_path, texmap.name))
def _createTexDef(self, texmap):
"""Create texture definition for the TexPass.
The method returns a list that is either empty or contains
one texture definition tuple.
\param texmap (\c TextureMap3DS) Texture map object or None
\return An empty list or a list containing one texture def
"""
if texmap==None:
return []
# texname = os.path.basename(texmap.name)
texname = texmap.name
# texname, ext = os.path.splitext(texname)
blur = texmap.blur+1.0
texdef = (texname, #+".tif",
"periodic", "periodic",
"gaussian", blur, blur, {})
return [texdef]
|