Added handling of materials and textures to Blender importer.

Also added custom property to materials to be able to select if vertex colors should be used for the material.
This commit is contained in:
alteredq
2011-03-29 05:51:49 +02:00
parent 377d1904de
commit 10e86a45fe
3 changed files with 153 additions and 33 deletions
@@ -42,6 +42,8 @@ from io_utils import ExportHelper, ImportHelper
bpy.types.Object.THREE_castsShadow = bpy.props.BoolProperty()
bpy.types.Object.THREE_meshCollider = bpy.props.BoolProperty()
bpy.types.Material.THREE_useVertexColors = bpy.props.BoolProperty()
class OBJECT_PT_hello( bpy.types.Panel ):
bl_label = "THREE"
@@ -62,7 +64,24 @@ class OBJECT_PT_hello( bpy.types.Panel ):
row = layout.row()
row.prop( obj, "THREE_meshCollider", text="Mesh collider" )
class MATERIAL_PT_hello( bpy.types.Panel ):
bl_label = "THREE"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
def draw(self, context):
layout = self.layout
mat = context.material
row = layout.row()
row.label(text="Selected material: " + mat.name )
row = layout.row()
row.prop( mat, "THREE_useVertexColors", text="Use vertex colors" )
# ################################################################
# Importer
# ################################################################
@@ -165,20 +165,20 @@ TEMPLATE_CAMERA_ORTHO = """\
}"""
TEMPLATE_LIGHT_DIRECTIONAL = """\
%(light_id)s: {
"type" : "directional",
"direction" : %(direction)s,
"color" : %(color)d,
"intensity" : %(intensity).2f
}"""
%(light_id)s: {
"type" : "directional",
"direction" : %(direction)s,
"color" : %(color)d,
"intensity" : %(intensity).2f
}"""
TEMPLATE_LIGHT_POINT = """\
%(light_id)s: {
"type" : "point",
"position" : %(position)s,
"color" : %(color)d,
"intensity" : %(intensity).3f
}"""
%(light_id)s: {
"type" : "point",
"position" : %(position)s,
"color" : %(color)d,
"intensity" : %(intensity).3f
}"""
TEMPLATE_VEC4 = '[ %f, %f, %f, %f ]'
TEMPLATE_VEC3 = '[ %f, %f, %f ]'
@@ -628,7 +628,7 @@ def generate_mtl(materials):
return mtl
def value2string(v):
if type(v) == str and v[0] != "0":
if type(v) == str and v[0:2] != "0x":
return '"%s"' % v
elif type(v) == bool:
return str(v).lower()
@@ -649,7 +649,7 @@ def generate_materials(mtl, materials, use_colors, draw_type):
mtl[m]['DbgName'] = m
mtl[m]['DbgIndex'] = index
mtl[m]['DbgColor'] = generate_color(index)
mtl[m]['vertexColors'] = use_colors
mtl[m]['vertexColors'] = use_colors and mtl[m]["useVertexColors"]
if draw_type in [ "BOUNDS", "WIRE" ]:
mtl[m]['wireframe'] = True
@@ -671,16 +671,16 @@ def extract_materials(mesh, scene):
material = materials[m.name]
material['colorDiffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
m.diffuse_intensity * m.diffuse_color[1],
m.diffuse_intensity * m.diffuse_color[2]]
m.diffuse_intensity * m.diffuse_color[1],
m.diffuse_intensity * m.diffuse_color[2]]
material['colorSpecular'] = [m.specular_intensity * m.specular_color[0],
m.specular_intensity * m.specular_color[1],
m.specular_intensity * m.specular_color[2]]
m.specular_intensity * m.specular_color[1],
m.specular_intensity * m.specular_color[2]]
material['colorAmbient'] = [m.ambient * world.ambient_color[0],
m.ambient * world.ambient_color[1],
m.ambient * world.ambient_color[2]]
m.ambient * world.ambient_color[1],
m.ambient * world.ambient_color[2]]
material['transparency'] = m.alpha
@@ -695,10 +695,14 @@ def extract_materials(mesh, scene):
fn_strip = os.path.basename(fn)
material['mapDiffuse'] = fn_strip
if m.specular_intensity > 0.0 and (m.specular_color[0] > 0 or m.specular_color[1] > 0 or m.specular_color[2] > 0):
material['shading'] = "Phong"
else:
material['shading'] = "Lambert"
material["useVertexColors"] = m.THREE_useVertexColors
# can't really use this reliably to tell apart Phong from Lambert
# as Blender defaults to non-zero specular color
#if m.specular_intensity > 0.0 and (m.specular_color[0] > 0 or m.specular_color[1] > 0 or m.specular_color[2] > 0):
# material['shading'] = "Phong"
#else:
# material['shading'] = "Lambert"
return materials
@@ -36,13 +36,81 @@ from io_utils import load_image, unpack_list, unpack_face_list
# #####################################################
# Generators
# #####################################################
def setColor(c, t):
c.r = t[0]
c.g = t[1]
c.b = t[2]
def create_mesh_object(name, vertices, face_data, flipYZ, recalculate_normals):
def create_texture(filename, modelpath):
name = filename
texture = bpy.data.textures.new(name, type='IMAGE')
image = load_image(filename, modelpath)
has_data = False
if image:
texture.image = image
has_data = image.has_data
return texture
def create_materials(data, modelpath):
materials = []
materials_data = data.get("materials", [])
for i, m in enumerate(materials_data):
name = m.get("DbgName", "material_%d" % i)
colorAmbient = m.get("colorAmbient", None)
colorDiffuse = m.get("colorDiffuse", None)
colorSpecular = m.get("colorSpecular", None)
alpha = m.get("transparency", 1.0)
specular_hardness = m.get("specularCoef", 0)
mapDiffuse = m.get("mapDiffuse", None)
mapLightmap = m.get("mapLightmap", None)
useVertexColors = m.get("vertexColors", False)
material = bpy.data.materials.new(name)
material.THREE_useVertexColors = useVertexColors
if colorDiffuse:
setColor(material.diffuse_color, colorDiffuse)
material.diffuse_intensity = 1.0
if colorSpecular:
setColor(material.specular_color, colorSpecular)
material.specular_intensity = 1.0
if alpha < 1.0:
material.alpha = alpha
material.use_transparency = True
if specular_hardness:
material.specular_hardness = specular_hardness
if mapDiffuse:
texture = create_texture(mapDiffuse, modelpath)
mtex = material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use = True
mtex.use_map_color_diffuse = True
materials.append(material)
return materials
def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate_normals):
faces = face_data["faces"]
vertexNormals = face_data["vertexNormals"]
vertexColors = face_data["vertexColors"]
vertexUVs = face_data["vertexUVs"]
faceMaterials = face_data["materials"]
edges = []
@@ -88,14 +156,14 @@ def create_mesh_object(name, vertices, face_data, flipYZ, recalculate_normals):
if flipYZ:
tmp = y
y = z
y = -z
z = tmp
# flip normals (this make them look consistent with the original before export)
x = -x
y = -y
z = -z
#x = -x
#y = -y
#z = -z
vi = me.faces[fi].vertices[j]
@@ -158,11 +226,31 @@ def create_mesh_object(name, vertices, face_data, flipYZ, recalculate_normals):
face_uvs[vi].y = 1.0 - v
# Handle materials # 1
if face_data["hasMaterials"]:
print("setting materials (mesh)")
for m in materials:
me.materials.append(m)
print("setting materials (faces)")
for fi in range(len(faces)):
if faceMaterials[fi] >= 0:
me.faces[fi].material_index = faceMaterials[fi]
# Create a new object
ob = bpy.data.objects.new(name, me)
ob.data = me # link the mesh data to the object
scene = bpy.context.scene # get the current scene
scene.objects.link(ob) # link the object into the scene
@@ -187,7 +275,8 @@ def extract_faces(data):
"hasVertexNormals" : False,
"hasVertexUVs" : False,
"hasVertexColors" : False
"hasVertexColors" : False,
"hasMaterials" : False
}
faces = data.get("faces", [])
@@ -228,6 +317,7 @@ def extract_faces(data):
result["hasVertexUVs"] = result["hasVertexUVs"] or hasFaceVertexUv
result["hasVertexNormals"] = result["hasVertexNormals"] or hasFaceVertexNormal
result["hasVertexColors"] = result["hasVertexColors"] or hasFaceVertexColor
result["hasMaterials"] = result["hasMaterials"] or hasMaterial
# vertices
@@ -431,7 +521,10 @@ def extract_json_string(text):
def get_name(filepath):
return os.path.splitext(os.path.basename(filepath))[0]
def get_path(filepath):
return os.path.dirname(filepath)
# #####################################################
# Parser
# #####################################################
@@ -464,7 +557,7 @@ def load(operator, context, filepath, option_flip_yz = True, recalculate_normals
vertices = splitArray(data["vertices"], 3)
if option_flip_yz:
vertices[:] = [(v[0], v[2], v[1]) for v in vertices]
vertices[:] = [(v[0], -v[2], v[1]) for v in vertices]
# extract faces
@@ -484,9 +577,13 @@ def load(operator, context, filepath, option_flip_yz = True, recalculate_normals
print('\tbuilding geometry...\n\tfaces:%i, vertices:%i, vertex normals: %i, vertex uvs: %i, vertex colors: %i, materials: %i ...' % (
nfaces, nvertices, nnormals, nuvs, ncolors, nmaterials ))
# Create materials
materials = create_materials(data, get_path(filepath))
# Create new obj
create_mesh_object(get_name(filepath), vertices, face_data, option_flip_yz, recalculate_normals)
create_mesh_object(get_name(filepath), vertices, materials, face_data, option_flip_yz, recalculate_normals)
scene = bpy.context.scene
scene.update()