From 10e86a45fe0e656067f8dbf87df3a328dcd31d3f Mon Sep 17 00:00:00 2001 From: alteredq Date: Tue, 29 Mar 2011 05:51:49 +0200 Subject: [PATCH] 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. --- .../scripts/op/io_mesh_threejs/__init__.py | 19 +++ .../op/io_mesh_threejs/export_threejs.py | 52 ++++---- .../op/io_mesh_threejs/import_threejs.py | 115 ++++++++++++++++-- 3 files changed, 153 insertions(+), 33 deletions(-) diff --git a/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/__init__.py b/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/__init__.py index 664d29f9..dbcc7b39 100644 --- a/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/__init__.py +++ b/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/__init__.py @@ -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 # ################################################################ diff --git a/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/export_threejs.py b/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/export_threejs.py index 31e693b1..99692955 100644 --- a/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/export_threejs.py +++ b/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/export_threejs.py @@ -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 diff --git a/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/import_threejs.py b/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/import_threejs.py index c9fc124e..7f47ea5e 100644 --- a/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/import_threejs.py +++ b/utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/import_threejs.py @@ -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()