Browse Source

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.
alteredq 14 years ago
parent
commit
10e86a45fe

+ 19 - 0
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_castsShadow = bpy.props.BoolProperty()
 bpy.types.Object.THREE_meshCollider = 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 ):
 class OBJECT_PT_hello( bpy.types.Panel ):
     
     
     bl_label = "THREE"
     bl_label = "THREE"
@@ -62,7 +64,24 @@ class OBJECT_PT_hello( bpy.types.Panel ):
         row = layout.row()
         row = layout.row()
         row.prop( obj, "THREE_meshCollider", text="Mesh collider" )
         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
 # Importer
 # ################################################################
 # ################################################################

+ 28 - 24
utils/exporters/blender/2.56/scripts/op/io_mesh_threejs/export_threejs.py

@@ -165,20 +165,20 @@ TEMPLATE_CAMERA_ORTHO = """\
     }"""
     }"""
 
 
 TEMPLATE_LIGHT_DIRECTIONAL = """\
 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 = """\
 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_VEC4 = '[ %f, %f, %f, %f ]'
 TEMPLATE_VEC3 = '[ %f, %f, %f ]'
 TEMPLATE_VEC3 = '[ %f, %f, %f ]'
@@ -628,7 +628,7 @@ def generate_mtl(materials):
     return mtl
     return mtl
 
 
 def value2string(v):
 def value2string(v):
-    if type(v) == str and v[0] != "0":
+    if type(v) == str and v[0:2] != "0x":
         return '"%s"' % v
         return '"%s"' % v
     elif type(v) == bool:
     elif type(v) == bool:
         return str(v).lower()
         return str(v).lower()
@@ -649,7 +649,7 @@ def generate_materials(mtl, materials, use_colors, draw_type):
         mtl[m]['DbgName'] = m
         mtl[m]['DbgName'] = m
         mtl[m]['DbgIndex'] = index
         mtl[m]['DbgIndex'] = index
         mtl[m]['DbgColor'] = generate_color(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" ]:
         if draw_type in [ "BOUNDS", "WIRE" ]:
             mtl[m]['wireframe'] = True
             mtl[m]['wireframe'] = True
@@ -671,16 +671,16 @@ def extract_materials(mesh, scene):
             material = materials[m.name]
             material = materials[m.name]
             
             
             material['colorDiffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
             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],
             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],
             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
             material['transparency'] = m.alpha
 
 
@@ -695,10 +695,14 @@ def extract_materials(mesh, scene):
                 fn_strip = os.path.basename(fn)
                 fn_strip = os.path.basename(fn)
                 material['mapDiffuse'] = fn_strip
                 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
     return materials
 
 

+ 106 - 9
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
 # Generators
 # #####################################################
 # #####################################################
+def setColor(c, t):
+    c.r = t[0]
+    c.g = t[1]
+    c.b = t[2]
+
+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):
 
 
-def create_mesh_object(name, vertices, face_data, flipYZ, recalculate_normals):
+        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"]
     faces   = face_data["faces"]
     vertexNormals = face_data["vertexNormals"]
     vertexNormals = face_data["vertexNormals"]
     vertexColors = face_data["vertexColors"]
     vertexColors = face_data["vertexColors"]
     vertexUVs = face_data["vertexUVs"]
     vertexUVs = face_data["vertexUVs"]
+    faceMaterials = face_data["materials"]
     
     
     edges = []
     edges = []
     
     
@@ -88,14 +156,14 @@ def create_mesh_object(name, vertices, face_data, flipYZ, recalculate_normals):
                         
                         
                         if flipYZ:
                         if flipYZ:
                             tmp = y
                             tmp = y
-                            y = z
+                            y = -z
                             z = tmp
                             z = tmp
 
 
                             # flip normals (this make them look consistent with the original before export)
                             # 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]
                         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
                         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
     # Create a new object
     
     
     ob = bpy.data.objects.new(name, me) 
     ob = bpy.data.objects.new(name, me) 
     ob.data = me                                # link the mesh data to the object
     ob.data = me                                # link the mesh data to the object
 
 
+
     scene = bpy.context.scene                   # get the current scene
     scene = bpy.context.scene                   # get the current scene
     scene.objects.link(ob)                      # link the object into the scene
     scene.objects.link(ob)                      # link the object into the scene
 
 
@@ -187,7 +275,8 @@ def extract_faces(data):
     
     
     "hasVertexNormals"  : False,
     "hasVertexNormals"  : False,
     "hasVertexUVs"      : False,
     "hasVertexUVs"      : False,
-    "hasVertexColors"   : False
+    "hasVertexColors"   : False,
+    "hasMaterials"      : False
     }
     }
     
     
     faces = data.get("faces", [])
     faces = data.get("faces", [])
@@ -228,6 +317,7 @@ def extract_faces(data):
         result["hasVertexUVs"] = result["hasVertexUVs"] or hasFaceVertexUv
         result["hasVertexUVs"] = result["hasVertexUVs"] or hasFaceVertexUv
         result["hasVertexNormals"] = result["hasVertexNormals"] or hasFaceVertexNormal
         result["hasVertexNormals"] = result["hasVertexNormals"] or hasFaceVertexNormal
         result["hasVertexColors"] = result["hasVertexColors"] or hasFaceVertexColor
         result["hasVertexColors"] = result["hasVertexColors"] or hasFaceVertexColor
+        result["hasMaterials"] = result["hasMaterials"] or hasMaterial
         
         
         # vertices
         # vertices
         
         
@@ -431,7 +521,10 @@ def extract_json_string(text):
 
 
 def get_name(filepath):
 def get_name(filepath):
     return os.path.splitext(os.path.basename(filepath))[0]
     return os.path.splitext(os.path.basename(filepath))[0]
-    
+
+def get_path(filepath):
+    return os.path.dirname(filepath)
+
 # #####################################################
 # #####################################################
 # Parser
 # Parser
 # #####################################################
 # #####################################################
@@ -464,7 +557,7 @@ def load(operator, context, filepath, option_flip_yz = True, recalculate_normals
     vertices = splitArray(data["vertices"], 3)
     vertices = splitArray(data["vertices"], 3)
     
     
     if option_flip_yz:
     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
     # 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 ...' % ( 
     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 ))
         nfaces, nvertices, nnormals, nuvs, ncolors, nmaterials ))
 
 
+    # Create materials
+    
+    materials = create_materials(data, get_path(filepath))
+    
     # Create new obj
     # 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 = bpy.context.scene 
     scene.update()
     scene.update()