diff --git a/blender/io_scene_emf/__init__.py b/blender/io_scene_emf/__init__.py new file mode 100644 index 00000000..81a7d12f --- /dev/null +++ b/blender/io_scene_emf/__init__.py @@ -0,0 +1,286 @@ +# add this folder in ~/.config/blender/2.66/scripts/addons + + +bl_info = { + "name": "Ewol Mesh file format emf", + "author": "Edouard DUPIN", + "blender": (2, 53, 0), + "location": "File > Import-Export", + "description": "Import-Export emf, Import EMF mesh, UV's, materials and textures", + "warning": "", + "wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Import-Export/EwolMechFile_EMF", + "tracker_url": "", + "support": 'OFFICIAL', + "category": "Import-Export"} + +if "bpy" in locals(): + import imp + if "import_emf" in locals(): + imp.reload(import_emf) + if "export_emf" in locals(): + imp.reload(export_emf) + + +import bpy +from bpy.props import (BoolProperty, + FloatProperty, + StringProperty, + EnumProperty, + ) +from bpy_extras.io_utils import (ExportHelper, + ImportHelper, + path_reference_mode, + axis_conversion, + ) + + +class ImportEMF(bpy.types.Operator, ImportHelper): + """Load a Wavefront EMF File""" + bl_idname = "import_scene.emf" + bl_label = "Import EMF" + bl_options = {'PRESET', 'UNDO'} + + filename_ext = ".emf" + filter_glob = StringProperty( + default="*.emf", + options={'HIDDEN'}, + ) + + use_ngons = BoolProperty( + name="NGons", + description="Import faces with more than 4 verts as ngons", + default=True, + ) + use_edges = BoolProperty( + name="Lines", + description="Import lines and faces with 2 verts as edge", + default=True, + ) + use_smooth_groups = BoolProperty( + name="Smooth Groups", + description="Surround smooth groups by sharp edges", + default=True, + ) + + use_split_objects = BoolProperty( + name="Object", + description="Import EMF Objects into Blender Objects", + default=True, + ) + use_split_groups = BoolProperty( + name="Group", + description="Import EMF Groups into Blender Objects", + default=True, + ) + + use_groups_as_vgroups = BoolProperty( + name="Poly Groups", + description="Import EMF groups as vertex groups", + default=False, + ) + + use_image_search = BoolProperty( + name="Image Search", + description="Search subdirs for any associated images " + "(Warning, may be slow)", + default=True, + ) + + split_mode = EnumProperty( + name="Split", + items=(('ON', "Split", "Split geometry, omits unused verts"), + ('OFF', "Keep Vert Order", "Keep vertex order from file"), + ), + ) + + global_clamp_size = FloatProperty( + name="Clamp Size", + description="Clamp bounds under this value (zero to disable)", + min=0.0, max=1000.0, + soft_min=0.0, soft_max=1000.0, + default=0.0, + ) + axis_forward = EnumProperty( + name="Forward", + items=(('X', "X Forward", ""), + ('Y', "Y Forward", ""), + ('Z', "Z Forward", ""), + ('-X', "-X Forward", ""), + ('-Y', "-Y Forward", ""), + ('-Z', "-Z Forward", ""), + ), + default='-Z', + ) + + axis_up = EnumProperty( + name="Up", + items=(('X', "X Up", ""), + ('Y', "Y Up", ""), + ('Z', "Z Up", ""), + ('-X', "-X Up", ""), + ('-Y', "-Y Up", ""), + ('-Z', "-Z Up", ""), + ), + default='Y', + ) + + def execute(self, context): + # print("Selected: " + context.active_object.name) + from . import import_obj + + if self.split_mode == 'OFF': + self.use_split_objects = False + self.use_split_groups = False + else: + self.use_groups_as_vgroups = False + + keywords = self.as_keywords(ignore=("axis_forward", + "axis_up", + "filter_glob", + "split_mode", + )) + + global_matrix = axis_conversion(from_forward=self.axis_forward, + from_up=self.axis_up, + ).to_4x4() + keywords["global_matrix"] = global_matrix + + return import_obj.load(self, context, **keywords) + + def draw(self, context): + layout = self.layout + + row = layout.row(align=True) + + box = layout.box() + row = box.row() + row.prop(self, "split_mode", expand=True) + + row = box.row() + if self.split_mode == 'ON': + row.label(text="Split by:") + row.prop(self, "use_split_objects") + row.prop(self, "use_split_groups") + else: + row.prop(self, "use_groups_as_vgroups") + + row = layout.split(percentage=0.67) + row.prop(self, "global_clamp_size") + layout.prop(self, "axis_forward") + layout.prop(self, "axis_up") + + layout.prop(self, "use_image_search") + + +class ExportEMF(bpy.types.Operator, ExportHelper): + """Save a Wavefront EMF File""" + + bl_idname = "export_scene.emf" + bl_label = 'Export EMF' + bl_options = {'PRESET'} + + filename_ext = ".emf" + filter_glob = StringProperty( + default="*.emf", + options={'HIDDEN'}, + ) + + # context group + use_selection = BoolProperty( + name="Selection Only", + description="Export selected objects only", + default=True, + ) + # generate binary file + use_binary = BoolProperty( + name="Binary", + description="Export the filein binary mode", + default=False, + ) + + global_scale = FloatProperty( + name="Scale", + description="Scale all data", + min=0.01, max=1000.0, + soft_min=0.01, + soft_max=1000.0, + default=1.0, + ) + + axis_forward = EnumProperty( + name="Forward", + items=(('X', "X Forward", ""), + ('Y', "Y Forward", ""), + ('Z', "Z Forward", ""), + ('-X', "-X Forward", ""), + ('-Y', "-Y Forward", ""), + ('-Z', "-Z Forward", ""), + ), + default='-Z', + ) + + axis_up = EnumProperty( + name="Up", + items=(('X', "X Up", ""), + ('Y', "Y Up", ""), + ('Z', "Z Up", ""), + ('-X', "-X Up", ""), + ('-Y', "-Y Up", ""), + ('-Z', "-Z Up", ""), + ), + default='Y', + ) + + path_mode = path_reference_mode + + check_extension = True + + def execute(self, context): + from . import export_emf + + from mathutils import Matrix + keywords = self.as_keywords(ignore=("axis_forward", + "axis_up", + "global_scale", + "check_existing", + "filter_glob", + )) + + global_matrix = Matrix() + + global_matrix[0][0] = \ + global_matrix[1][1] = \ + global_matrix[2][2] = self.global_scale + + global_matrix = (global_matrix * + axis_conversion(to_forward=self.axis_forward, + to_up=self.axis_up, + ).to_4x4()) + + keywords["global_matrix"] = global_matrix + return export_emf.save(self, context, **keywords) + + +def menu_func_import(self, context): + self.layout.operator(ImportEMF.bl_idname, text="Ewol mesh file (.emf)") + + +def menu_func_export(self, context): + self.layout.operator(ExportEMF.bl_idname, text="Ewol mesh File (.emf)") + + +def register(): + bpy.utils.register_module(__name__) + + bpy.types.INFO_MT_file_import.append(menu_func_import) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_module(__name__) + + bpy.types.INFO_MT_file_import.remove(menu_func_import) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + +if __name__ == "__main__": + register() diff --git a/blender/io_scene_emf/export_emf.py b/blender/io_scene_emf/export_emf.py new file mode 100644 index 00000000..0a28c5bb --- /dev/null +++ b/blender/io_scene_emf/export_emf.py @@ -0,0 +1,487 @@ + +import os +import time + +import bpy +import mathutils +import bpy_extras.io_utils + + +def name_compat(name): + if name is None: + return 'None' + else: + return name.replace(' ', '_') + + +def mesh_triangulate(me): + import bmesh + bm = bmesh.new() + bm.from_mesh(me) + bmesh.ops.triangulate(bm, faces=bm.faces) + bm.to_mesh(me) + bm.free() + + +def write_mtl(scene, file, filepath, path_mode, copy_set, mtl_dict): + from mathutils import Color + world = scene.world + if world: + world_amb = world.ambient_color + else: + world_amb = Color((0.0, 0.0, 0.0)) + source_dir = os.path.dirname(bpy.data.filepath) + dest_dir = os.path.dirname(filepath) + fw = file.write + fw('\nMaterials : %i\n' % len(mtl_dict)) + mtl_dict_values = list(mtl_dict.values()) + mtl_dict_values.sort(key=lambda m: m[0]) + # Write material/image combinations we have used. + # Using mtl_dict.values() directly gives un-predictable order. + for mtl_mat_name, mat, face_img in mtl_dict_values: + # Get the Blender data for the material and the image. + # Having an image named None will make a bug, dont do it :) + fw('\t%s\n' % mtl_mat_name) # Define a new material: matname_imgname + if mat: + # convert from blenders spec to 0 - 1000 range. + if mat.specular_shader == 'WARDISO': + tspec = (0.4 - mat.specular_slope) / 0.0004 + else: + tspec = (mat.specular_hardness - 1) * 1.9607843137254901 + fw('\t\tNs %.6f\n' % tspec) + del tspec + fw('\t\tKa %.6f %.6f %.6f\n' % (mat.ambient * world_amb)[:]) # Ambient, uses mirror color, + fw('\t\tKd %.6f %.6f %.6f\n' % (mat.diffuse_intensity * mat.diffuse_color)[:]) # Diffuse + fw('\t\tKs %.6f %.6f %.6f\n' % (mat.specular_intensity * mat.specular_color)[:]) # Specular + if hasattr(mat, "ior"): + fw('\t\tNi %.6f\n' % mat.ior) # Refraction index + else: + fw('\t\tNi %.6f\n' % 1.0) + fw('\t\td %.6f\n' % mat.alpha) # Alpha (obj uses 'd' for dissolve) + # 0 to disable lighting, 1 for ambient & diffuse only (specular color set to black), 2 for full lighting. + if mat.use_shadeless: + fw('\t\tillum 0\n') # ignore lighting + elif mat.specular_intensity == 0: + fw('\t\tillum 1\n') # no specular. + else: + fw('\t\tillum 2\n') # light normaly + else: + #write a dummy material here? + fw('\t\tNs 0\n') + fw('\t\tKa %.6f %.6f %.6f\n' % world_amb[:]) # Ambient, uses mirror color, + fw('\t\tKd 0.8 0.8 0.8\n') + fw('\t\tKs 0.8 0.8 0.8\n') + fw('\t\td 1\n') # No alpha + fw('\t\tillum 2\n') # light normaly + # Write images! + if face_img: # We have an image on the face! + filepath = face_img.filepath + if filepath: # may be '' for generated images + # write relative image path + filepath = bpy_extras.io_utils.path_reference(filepath, + source_dir, + dest_dir, + path_mode, + "", + copy_set, + face_img.library) + fw('\t\tmap_Kd %s\n' % filepath) # Diffuse mapping image + del filepath + else: + # so we write the materials image. + face_img = None + if mat: # No face image. if we havea material search for MTex image. + image_map = {} + # backwards so topmost are highest priority + for mtex in reversed(mat.texture_slots): + if mtex and mtex.texture and mtex.texture.type == 'IMAGE': + image = mtex.texture.image + if image: + # texface overrides others + if (mtex.use_map_color_diffuse and + (face_img is None) and + (mtex.use_map_warp is False) and + (mtex.texture_coords != 'REFLECTION')): + image_map["map_Kd"] = image + if mtex.use_map_ambient: + image_map["map_Ka"] = image + # this is the Spec intensity channel but Ks stands for specular Color + if mtex.use_map_color_spec: # specular color + image_map["map_Ks"] = image + if mtex.use_map_hardness: # specular hardness/glossiness + image_map["map_Ns"] = image + if mtex.use_map_alpha: + image_map["map_d"] = image + if mtex.use_map_translucency: + image_map["map_Tr"] = image + if mtex.use_map_normal and (mtex.texture.use_normal_map is True): + image_map["map_Bump"] = image + if mtex.use_map_normal and (mtex.texture.use_normal_map is False): + image_map["map_Disp"] = image + if mtex.use_map_color_diffuse and (mtex.texture_coords == 'REFLECTION'): + image_map["map_refl"] = image + if mtex.use_map_emit: + image_map["map_Ke"] = image + for key, image in image_map.items(): + filepath = bpy_extras.io_utils.path_reference(image.filepath, + source_dir, + dest_dir, + path_mode, + "", + copy_set, + image.library) + fw('\t\t%s %s\n' % (key, repr(filepath)[1:-1])) + + +""" + " @brief Basic write function. The context and options must be already set. +""" +def write_file(filepath, + objects, + scene, + EXPORT_GLOBAL_MATRIX=None, + EXPORT_PATH_MODE='AUTO', + ): + if EXPORT_GLOBAL_MATRIX is None: + EXPORT_GLOBAL_MATRIX = mathutils.Matrix() + + def veckey3d(v): + return round(v.x, 6), round(v.y, 6), round(v.z, 6) + + def veckey2d(v): + return round(v[0], 6), round(v[1], 6) + + print('EMF Export path: %r' % filepath) + + time1 = time.time() + + mtlfilepath = os.path.splitext(filepath)[0] + ".mtl" + + file = open(filepath, "w", encoding="utf8", newline="\n") + fw = file.write + + # Write Header + fw('EMF(STRING)\n') # if binary : fw('EMF(BINARY)\n') + fw('# Blender v%s EMF File: %r\n' % (bpy.app.version_string, os.path.basename(bpy.data.filepath))) + + # Initialize totals, these are updated each object + totverts = totuvco = totno = 1 + + face_vert_index = 1 + + globalNormals = {} + + # A Dict of Materials + # (material.name, image.name):matname_imagename # matname_imagename has gaps removed. + mtl_dict = {} + # Used to reduce the usage of matname_texname materials, which can become annoying in case of + # repeated exports/imports, yet keeping unique mat names per keys! + # mtl_name: (material.name, image.name) + mtl_rev_dict = {} + + copy_set = set() + + # Get all meshes + for ob_main in objects: + # ignore dupli children + if ob_main.parent and ob_main.parent.dupli_type in {'VERTS', 'FACES'}: + # XXX + print(ob_main.name, 'is a dupli child - ignoring') + continue + obs = [] + if ob_main.dupli_type != 'NONE': + # XXX + print('creating dupli_list on', ob_main.name) + ob_main.dupli_list_create(scene) + obs = [(dob.object, dob.matrix) for dob in ob_main.dupli_list] + # XXX debug print + print(ob_main.name, 'has', len(obs), 'dupli children') + else: + obs = [(ob_main, ob_main.matrix_world)] + idMesh=0 + for ob, ob_mat in obs: + try: + # apply the mesh modifieur at the curent object : + me = ob.to_mesh(scene, True, 'PREVIEW', calc_tessface=False) + except RuntimeError: + me = None + if me is None: + continue + idMesh = idMesh+1; + fw('Mesh : %d\n' % idMesh) + me.transform(EXPORT_GLOBAL_MATRIX * ob_mat) + # _must_ do this first since it re-allocs arrays + # triangulate all the mesh : + mesh_triangulate(me) + # export UV mapping : + faceuv = len(me.uv_textures) > 0 + if faceuv: + uv_texture = me.uv_textures.active.data[:] + uv_layer = me.uv_layers.active.data[:] + me_verts = me.vertices[:] + # Make our own list so it can be sorted to reduce context switching + face_index_pairs = [(face, index) for index, face in enumerate(me.polygons)] + # faces = [ f for f in me.tessfaces ] + edges = me.edges + if not (len(face_index_pairs) + len(edges) + len(me.vertices)): # Make sure there is somthing to write + # clean up + bpy.data.meshes.remove(me) + continue # dont bother with this mesh. + # calculated normals: + me.calc_normals() + materials = me.materials[:] + material_names = [m.name if m else None for m in materials] + # avoid bad index errors + if not materials: + materials = [None] + material_names = [name_compat(None)] + # Sort by Material, then images + # so we dont over context switch in the obj file. + if faceuv: + face_index_pairs.sort(key=lambda a: (a[0].material_index, hash(uv_texture[a[1]].image), a[0].use_smooth)) + elif len(materials) > 1: + face_index_pairs.sort(key=lambda a: (a[0].material_index, a[0].use_smooth)) + else: + # no materials + face_index_pairs.sort(key=lambda a: a[0].use_smooth) + # Set the default mat to no material and no image. + contextMat = 0, 0 # Can never be this, so we will label a new material the first chance we get. + contextSmooth = None # Will either be true or false, set bad to force initialization switch. + # use : blen obs ??? what is this .... + if True: + name1 = ob.name + name2 = ob.data.name + if name1 == name2: + obnamestring = name_compat(name1) + else: + obnamestring = '%s_%s' % (name_compat(name1), name_compat(name2)) + fw('\tName : %s\n' % obnamestring) # Write Object name + ########################################################### + ## Vert + ########################################################### + fw('\tVertex : %d\n\t\t' % len(me_verts)) + for v in me_verts: + fw('%.6f %.6f %.6f|' % v.co[:]) + fw('\n') + ########################################################### + ## UV + ########################################################### + fw('\tUV-mapping :\n\t\t') + if faceuv: + # in case removing some of these dont get defined. + uv = uvkey = uv_dict = f_index = uv_index = None + uv_face_mapping = [None] * len(face_index_pairs) + uv_dict = {} # could use a set() here + for f, f_index in face_index_pairs: + uv_ls = uv_face_mapping[f_index] = [] + for uv_index, l_index in enumerate(f.loop_indices): + uv = uv_layer[l_index].uv + uvkey = veckey2d(uv) + try: + uv_k = uv_dict[uvkey] + except: + uv_k = uv_dict[uvkey] = len(uv_dict) + fw('%.6f %.6f|' % uv[:]) + uv_ls.append(uv_k) + uv_unique_count = len(uv_dict) + del uv, uvkey, uv_dict, f_index, uv_index, uv_ls, uv_k + # Only need uv_unique_count and uv_face_mapping + fw('\n') + ########################################################### + ## NORMAL + ########################################################### + if f.use_smooth: + localIsSmooth = 'vertex' + else: + localIsSmooth = 'face' + fw('\tNormal(%s) : %d\n\t\t' % (localIsSmooth, len(face_index_pairs)) ) + for f, f_index in face_index_pairs: + if f.use_smooth: + for v_idx in f.vertices: + v = me_verts[v_idx] + noKey = veckey3d(v.normal) + if noKey not in globalNormals: + globalNormals[noKey] = totno + totno += 1 + fw('%.6f %.6f %.6f|' % noKey) + else: + # Hard, 1 normal from the face. + noKey = veckey3d(f.normal) + if noKey not in globalNormals: + globalNormals[noKey] = totno + totno += 1 + fw('%.6f %.6f %.6f|' % noKey) + + fw('\n') + if not faceuv: + f_image = None + ########################################################### + ## faces + ########################################################### + fw('\tFace : %d' % len(face_index_pairs)) + for f, f_index in face_index_pairs: + f_smooth = f.use_smooth + f_mat = min(f.material_index, len(materials) - 1) + if faceuv: + tface = uv_texture[f_index] + f_image = tface.image + # MAKE KEY + if faceuv and f_image: # Object is always true. + key = material_names[f_mat], f_image.name + else: + key = material_names[f_mat], None # No image, use None instead. + # CHECK FOR CONTEXT SWITCH + if key == contextMat: + pass # Context already switched, dont do anything + else: + if key[0] is None and key[1] is None: + # inform the use of a material : + fw("\n\t\t---:") # mat, image + else: + mat_data = mtl_dict.get(key) + if not mat_data: + # First add to global dict so we can export to mtl + # Then write mtl + # Make a new names from the mat and image name, + # converting any spaces to underscores with name_compat. + # If none image dont bother adding it to the name + # Try to avoid as much as possible adding texname (or other things) + # to the mtl name (see [#32102])... + mtl_name = "%s" % name_compat(key[0]) + if mtl_rev_dict.get(mtl_name, None) not in {key, None}: + if key[1] is None: + tmp_ext = "_NONE" + else: + tmp_ext = "_%s" % name_compat(key[1]) + i = 0 + while mtl_rev_dict.get(mtl_name + tmp_ext, None) not in {key, None}: + i += 1 + tmp_ext = "_%3d" % i + mtl_name += tmp_ext + mat_data = mtl_dict[key] = mtl_name, materials[f_mat], f_image + mtl_rev_dict[mtl_name] = key + # set the use of a material : + fw("\n\t\t%s:" % mat_data[0]) # can be mat_image or (null) + contextMat = key + f_v = [(vi, me_verts[v_idx]) for vi, v_idx in enumerate(f.vertices)] + if faceuv: + # export the normals : + if f_smooth: # Smoothed, use vertex normals + for vi, v in f_v: + fw(" %d/%d/%d" % + (v.index + totverts-1, + totuvco + uv_face_mapping[f_index][vi]-1, + globalNormals[veckey3d(v.normal)]-1, + )) # vert, uv, normal + else: # No smoothing, face normals + no = globalNormals[veckey3d(f.normal)] + for vi, v in f_v: + fw(" %d/%d/%d" % + (v.index + totverts-1, + totuvco + uv_face_mapping[f_index][vi]-1, + no-1, + )) # vert, uv, normal + face_vert_index += len(f_v) + else: # No UV's + # export the normals : + if f_smooth: # Smoothed, use vertex normals + for vi, v in f_v: + fw(" %d//%d" % ( + v.index + totverts-1, + globalNormals[veckey3d(v.normal)]-1, + )) + else: # No smoothing, face normals + no = globalNormals[veckey3d(f.normal)] + for vi, v in f_v: + fw(" %d//%d" % (v.index + totverts-1, no-1)) + fw('|') + fw('\n') + # Write edges. ==> did not know what it is ... + #fw('Faces : %d' % len(edges)) + #for ed in edges: + # if ed.is_loose: + # fw('%d %d\n' % (ed.vertices[0] + totverts, ed.vertices[1] + totverts)) + + # Make the indices global rather then per mesh + totverts += len(me_verts) + if faceuv: + totuvco += uv_unique_count + # clean up + bpy.data.meshes.remove(me) + if ob_main.dupli_type != 'NONE': + ob_main.dupli_list_clear() + + ########################################################### + ## Now we have all our materials, save them + ## material generation : + ########################################################### + write_mtl(scene, file, mtlfilepath, EXPORT_PATH_MODE, copy_set, mtl_dict) + + file.close() + + # copy all collected files. + bpy_extras.io_utils.path_reference_copy(copy_set) + + print("EMF Export time: %.2f" % (time.time() - time1)) + + +""" + " @brief generate the requested object file ... with his material inside and ... + " +""" +def _write(context, + filepath, + EXPORT_SEL_ONLY, + EXPORT_GLOBAL_MATRIX, + EXPORT_PATH_MODE, + ): + # + base_name, ext = os.path.splitext(filepath) + # create the output name : + context_name = [base_name, '', '', ext] # Base name, scene name, frame number, extension + # get the curent scene : + scene = context.scene + # Exit edit mode before exporting, so current object states are exported properly. + if bpy.ops.object.mode_set.poll(): + bpy.ops.object.mode_set(mode='OBJECT') + # get the curent frame selected : + frame = scene.frame_current + # Loop through all frames in the scene and export. + scene.frame_set(frame, 0.0) + # get only the object that are selected or all ... + if EXPORT_SEL_ONLY: + objects = context.selected_objects + else: + objects = scene.objects + + full_path = ''.join(context_name) + + write_file(full_path, + objects, + scene, + EXPORT_GLOBAL_MATRIX, + EXPORT_PATH_MODE, + ) + + + +""" + " @brief Save the current element in the file requested. + " +""" +def save(operator, + context, + filepath="", + use_selection=True, + use_binary=False, + global_matrix=None, + path_mode='AUTO' + ): + _write(context, + filepath, + EXPORT_SEL_ONLY=use_selection, + EXPORT_GLOBAL_MATRIX=global_matrix, + EXPORT_PATH_MODE=path_mode, + ) + + return {'FINISHED'} diff --git a/blender/obj_inport_export.py b/blender/obj_inport_export.py deleted file mode 100644 index 13a0e342..00000000 --- a/blender/obj_inport_export.py +++ /dev/null @@ -1,1269 +0,0 @@ -#!BPY -"""Registration info for Blender menus: -Name: 'OBJ...' -Blender: 232 -Group: 'Import' -Tip: 'Import Wavefront File Format (*.obj)' -""" - -#========================================================================= -# Wavefront OBJ Importer/Exporter v1.2 -# This is a complete OBJ importer and exporter script -# All Rights Reserved -# chris@artdreamdesigns.com -#========================================================================= - -#========================================================================= -# mise a jour pour Blender 228 et suivant jm soler -# mise a jour pour importer zbrush obj avec uvmapping jm soler -# mise a jour pour utiliser le selecteur de fichier jm soler -# mise a jour pour importer les fichiers obj de forester/arboretum jm soler -#========================================================================= - -#========================================================================= -# DESCRIPTION: This script allows for full importing and exporting of -# .obj files. uv texture coordinates and normals can be exported and -# imported. .obj groups and materials can also be converted to and -# from material indexes in Blender. -# -# INSTALLATION: -# You need the FULL python installation to run this script. You can -# down load the latest version of PYTHON from http://www.python.org. -# -# INSTRUCTIONS (You definitely want to read this!): -# Once the script is loaded in Blender, hit alt-p. This will bring up -# the main interface panel. You will have a choise of exporting or -# importing an .obj module. If you are exporting you must have at least -# one mesh selected in Blender, or you will get an error. -# You can change the export filename by entering the path and filename -# in the dialog. If you do not enter a path, the path will default to -# your blender directory. You can change the default path in the script <==== NOTE -# itself by modifying the variable 'Filename' at the top of the script. -# -# EXPORTING: -# There are 4 different export options: Default, Groups, Material Layers, -# and Standard. "Default" will export your mesh using Material Layers if -# the mesh has material indexes. "Groups" and "Material Layers" are -# logically equivalent, but are a different .obj format. If you are -# exporting a Poser morph target, you must select "Material Layers". <===== NOTE -# "Standard" will ignore grouping information, even if your mesh has -# material indexes. -# -# There is also a choice between export using "mesh coordinates" or -# "object coordinates". "Object coordinates" are any location, rotation, -# or scaling values created outside of mesh edit. They belong to the object -# rather than the mesh. If you export using mesh coordinates (the default) -# the center of the object will always be at 0, 0, 0. Export using "mesh -# coordinates is definintely what you want to use if you are working with -# a Poser morph target. If you are exporting a group of objects, you will -# automatically be placed in "object coordinate" mode. -# -# IMPORTING: -# If your OBJ model has uv mapping coordinates, and you want to use them <===== NOTE -# in Blender, you can access them in two ways. The best way is through Blender's -# realtime UV coordinates which you enable simply by selecting the UV option in -# the material edit window. This gives you an exact version of the uv coordinates. -# An older method is to select the "stick" option in the material edit window. I -# really don't know why anyone would want to use this option since it cannot handle -# seams and texture overlap, but I left it in just in case someone could use it for -# something. -# -# If your OBJ contains groups, once it has been imported, it may still appear -# to lack any material indexes. If this happens, it can be remedied <=== NOTE -# by going to the mesh editor window, clicking on the mesh selection button, and -# reselecting the mesh you have just imported. You will now have as many -# materials attached to your object as there are groups. You can then select -# different groups by doing a material select when you are in edit mode. -# -# Finally, you might have problems with certain parts of the object not displaying -# after you go in and out of edit mode the first time. To fix this, simply go into -# edit mode again, and select the "remove doubles" option. -# -# -# HISTORY: -# Nov 13, 2001: Initial Release -# Nov 16, 2001: Version 1.1 - no longer need to pre-define dummy materials -# Dec 13, 2001: Version 1.2 - now imports into realtime UV (the UV button in the material edit window), and -# exports realtime UV. This format is more compatible with the native .OBJ uv format. Should eliminate -# texture misalignments and seams. Simply press the UV button in the material edit window after importing. -# -# GetRaw -#================================ - - -# =============================== -# Setup our runtime constants -# =============================== - -DEBUG=1 #Set this to "1" to see extra messages -MESHVERSION=3 # If the export file doesn't work, -FILEVERSION=3 # try changing these to "2" - -EVENT_PATHCHANGE= 1 -EVENT_IMPORT= 2 -EVENT_IMPORT_CONT= 3 -EVENT_OPTIONS= 4 -EVENT_EXPORT= 7 -EVENT_EXPORT_CHK= 5 -EVENT_EXPORT_CANCEL= 6 -EVENT_QUIT= 8 -EVENT_EXPORT_ERR= 9 -EVENT_TYPE= 10 -EVENT_DONE= 11 -EVENT_IMPORT_SELECT= 12 - -# =============================== -# Import our libraries -# =============================== - -#import string -#import os -#import struct - -try: - import nt - os=nt - os.sep='\\' -except: - import posix - os=posix - os.sep='/' - -def isdir(path): - try: - st = os.stat(path) - return 1 - except: - return 0 - -def split(pathname): - PATHNAME=pathname - PATHNAME=PATHNAME.replace('\\','/') - k0=PATHNAME.split('/') - directory=pathname.replace(k0[len(k0)-1],'') - Name=k0[len(k0)-1] - return directory, Name - -def join(l0,l1): - return l0+os.sep+l1 - -os.isdir=isdir -os.split=split -os.join=join - -import math -import Blender -#import Blender210 -from Blender import * -from Blender import NMesh -from Blender.Draw import * -from Blender.BGL import * -from Blender import Material -from Blender import Window - - - -# =============================== -# Input Variables -# =============================== - -Filename = "G:\\tmp\\test.obj" - -gFilename=Create(Filename) -gAlert = 0 -type = 1 -exporttype = 1 -returncode = 0 -operation = "Export" -center = [0,0,0] -rotation = [0,0,0] -Transform = [] -multiflag = 0 - -#================================ -# def Fileselect function: -#================================ -def ImportFunctionselet(filename): - global gFilename - global ExportOptions - global ExportType - global type - global exporttype - global operation - global gAlert - gFilename.val=filename - ImportFunction(filename, type) - operation = "Import" - -#================================ -def ExitGUI (): -#================================ - Exit() - -#================================ -def EventGUI (event): -#================================ - global gFilename - global ExportOptions - global ExportType - global type - global exporttype - global operation - global gAlert - - if (event==EVENT_IMPORT): - ImportFunction(gFilename.val, type) - operation = "Import" - - if (event==EVENT_IMPORT_SELECT): - Window.FileSelector (ImportFunctionselet, 'IMPORT FILE') - - - if (event==EVENT_IMPORT_CONT): - gAlert = 0 - operation = "Import" - Draw () - - if (event==EVENT_EXPORT): - ExportFunction(gFilename.val, type) - operation = "Export" - - if (event==EVENT_EXPORT_CHK): - ExportFunctionOK(gFilename.val, type) - Draw () - if (event==EVENT_EXPORT_CANCEL): - gAlert = 0 - Draw () - if (event==EVENT_OPTIONS): - type = ExportOptions.val - Draw () - if (event==EVENT_TYPE): - exporttype = ExportType.val - Draw () - if (event==EVENT_EXPORT_ERR): - gAlert = 0 - Draw () - if (event==EVENT_DONE): - gAlert = 0 - Draw () - if (event==EVENT_QUIT): - ExitGUI() - -#================================ -def DrawGUI(): -#================================ - global type - global exporttype - global operation - - glClearColor (0.6,0.6,0.6,0) - glClear (GL_COLOR_BUFFER_BIT) - - global gFilename - global gAlert - global ExportOptions - global ExportType - - if (gAlert==0): - # Add in the copyright notice and title - glRasterPos2d(32, 380) - Text("Wavefront OBJ Importer/Exporter") - glRasterPos2d(32, 350) - Text("Copyright (C) Chris Lynch 2001") - - gFilename=String ("Filename: ",EVENT_PATHCHANGE,32,250,320,32,gFilename.val,255,"Full pathname and filename") - Button ("Export",EVENT_EXPORT,32,200,100,32) - Button ("Import",EVENT_IMPORT,252,200,100,32) - Button ("Select Import",EVENT_IMPORT_SELECT,355,200,100,32) - glRasterPos2d(32, 165) - Text("Select Export Options:") - options = "Export Options %t| Default %x1| Material Layers %x2| Obj Groups %x3| Standard %x4" - ExportOptions = Menu (options,EVENT_OPTIONS,200,150,150,32, type) - Button ("Done",EVENT_QUIT,142,50,100,32) - glRasterPos2d(32, 115) - Text("Export using ") - options = "Export Type %t| Mesh Coordinates %x1| Object Coordinates %x2" - ExportType = Menu (options,EVENT_TYPE,170,100,180,32, exporttype) - Button ("Done",EVENT_QUIT,142,50,100,32) - - elif (gAlert==1): - glRasterPos2i (32,250) - Text (gFilename.val+ " already exists. Save anyway?") - Button ("Save",EVENT_EXPORT_CHK,150,200,50,32) - Button ("Cancel",EVENT_EXPORT_CANCEL,250,200,50,32) - gAlert = 0 - elif (gAlert==2): - glRasterPos2i (32,250) - Text (gFilename.val+ " cannot be found. Check directory and filename.") - Button ("Continue",EVENT_IMPORT_CONT,32,190,70,32) - gAlert = 0 - elif gAlert == 3: - glRasterPos2i (32,250) - Text ("No objects selected to export. You must select one or more objects.") - Button ("Continue",EVENT_EXPORT_ERR,192,200,70,32) - gAlert = 0 - elif gAlert == 5: - glRasterPos2i (32,250) - Text ("Invalid directory path.") - Button ("Continue",EVENT_EXPORT_ERR,192,200,70,32) - gAlert = 0 - else: - glRasterPos2i (32,250) - Text (str(operation)+ " of " +str(gFilename.val)+ " done.") - Button ("Continue",EVENT_DONE,192,200,70,32) - -#================================ -def RegisterGUI (): -#================================ - Register (DrawGUI,None,EventGUI) - -#================================ -# MAIN SCRIPT -#================================ -# Opens a file, writes data in it -# and closes it up. -#================================ -RegisterGUI() - -#================================ -def ImportFunction (importName, type): -#================================ - global gFilename - global gAlert - - try: - FILE=open (importName,"r") - directory, Name = os.split(gFilename.val) - print directory, Name - words = Name.split(".") - Name = words[0] - ObjImport(FILE, Name, gFilename.val) - FILE.close() - gAlert = 4 - Draw () - except IOError: - gAlert=2 - Draw () - -#================================ -def ExportFunction (exportName, type): -#================================ - global gFilename - global gAlert - - try: - FILE=open (exportName,"r") - FILE.close() - gAlert = 1 - Draw () - except IOError: - - directory, Name = os.split(gFilename.val) - - - if os.isdir(directory): - ExportFunctionOK(exportName, type) - Draw () - else: - gAlert = 5 - Draw () - -#================================ -def ExportFunctionOK (exportName, type): -#================================ - global gFilename - global gAlert - global returncode - - FILE=open (exportName,"w") - - directory, Name = os.split(gFilename.val) - - words = Name.split(".") - Name = words[0] - ObjExport(FILE, Name, type) - if returncode > 0: - gAlert = 3 - else: - gAlert = 4 - FILE.flush() - FILE.close() - -#========================= -def ObjImport(file, Name, filename): -#========================= - vcount = 0 - vncount = 0 - vtcount = 0 - fcount = 0 - gcount = 0 - setcount = 0 - groupflag = 0 - objectflag = 0 - mtlflag = 0 - baseindex = 0 - basevtcount = 0 - basevncount = 0 - matindex = 0 - - pointList = [] - uvList = [] - normalList = [] - faceList = [] - materialList = [] - imagelist = [] - - uv = [] - lines = file.readlines() - linenumber = 1 - - for line in lines: - words = line.split() - if words and words[0] == "#": - pass # ignore comments - elif words and words[0] == "v": - vcount = vcount + 1 - - for n_ in [1,2,3]: - if words[n_].find(',')!=-1: - words[n_]=words[n_].replace(',','.') - - x = float(words[1]) - y = float(words[2]) - z = float(words[3]) - - pointList.append([x, y, z]) - - elif words and words[0] == "vt": - vtcount = vtcount + 1 - for n_ in [1,2]: - if words[n_].find(',')!=-1: - words[n_]=words[n_].replace(',','.') - - u = float(words[1]) - v = float(words[2]) - uvList.append([u, v]) - - elif words and words[0] == "vn": - vncount = vncount + 1 - - for n_ in [1,2,3]: - if words[n_].find(',')!=-1: - words[n_]=words[n_].replace(',','.') - - i = float(words[1]) - j = float(words[2]) - k = float(words[3]) - normalList.append([i, j, k]) - - elif words and words[0] == "f": - fcount = fcount + 1 - vi = [] # vertex indices - ti = [] # texture indices - ni = [] # normal indices - words = words[1:] - lcount = len(words) - for index in (xrange(lcount)): - if words[index].find( "/") == -1: - vindex = int(words[index]) - if vindex < 0: vindex = baseindex + vindex + 1 - vi.append(vindex) - else: - vtn = words[index].split( "/") - vindex = int(vtn[0]) - if vindex < 0: vindex = baseindex + vindex + 1 - vi.append(vindex) - - if len(vtn) > 1 and vtn[1]: - tindex = int(vtn[1]) - if tindex < 0: tindex = basevtcount +tindex + 1 - ti.append(tindex) - - if len(vtn) > 2 and vtn[2]: - nindex = int(vtn[2]) - if nindex < 0: nindex = basevncount +nindex + 1 - ni.append(nindex) - faceList.append([vi, ti, ni, matindex]) - - elif words and words[0] == "o": - ObjectName = words[1] - objectflag = 1 - #print "Name is %s" % ObjectName - - elif words and words[0] == "g": - groupflag = 1 - index = len(words) - if objectflag == 0: - objectflag = 1 - if index > 1: - ObjectName = words[1].join("_") - GroupName = words[1].join("_") - else: - ObjectName = "Default" - GroupName = "Default" - #print "Object name is %s" % ObjectName - #print "Group name is %s" % GroupName - else: - if index > 1: - GroupName = join(words[1],"_") - else: - GroupName = "Default" - #print "Group name is %s" % GroupName - - if mtlflag == 0: - matindex = AddMeshMaterial(GroupName,materialList, matindex) - gcount = gcount + 1 - - if fcount > 0: - baseindex = vcount - basevncount = vncount - basevtcount = vtcount - - elif words and words[0] == "mtllib": - # try to export materials - directory, dummy = os.split(filename) - filename = os.join(directory, words[1]) - print "try to import : ",filename - - try: - file = open(filename, "r") - except: - print "no material file %s" % filename - else: - mtlflag = 0 - #file = open(filename, "r") - line = file.readline() - mtlflag = 1 - while line: - words = line.split() - if words and words[0] == "newmtl": - name = words[1] - line = file.readline() # Ns ? - words = line.split() - while words[0] not in ["Ka","Kd","Ks","map_Kd"]: - line = file.readline() - words = line.split() - - if words[0] == "Ka": - Ka = [float(words[1]), - float(words[2]), - float(words[3])] - line = file.readline() # Kd - words = line.split() - - if words[0] == "Kd": - Kd = [float(words[1]), - float(words[2]), - float(words[3])] - line = file.readline() # Ks - words = line.split() - - if words[0] == "Ks": - Ks = [float(words[1]), - float(words[2]), - float(words[3])] - line = file.readline() # Ks - words = line.split() - - if words[0] == "map_Kd": - Kmap= words[1] - img=os.join(directory, Kmap) - im=Blender.Image.Load(img) - line = file.readline() # Ks - words = line.split() - - matindex = AddGlobalMaterial(name, matindex) - matlist = Material.Get() - - if len(matlist) > 0: - if name!='defaultMat': - material = matlist[matindex] - material.R = Kd[0] - material.G = Kd[1] - material.B = Kd[2] - try: - material.specCol[0] = Ks[0] - material.specCol[1] = Ks[1] - material.specCol[2] = Ks[2] - except: - pass - try: - alpha = 1 - ((Ka[0]+Ka[1]+Ka[2])/3) - except: - pass - try: - material.alpha = alpha - except: - pass - - try: - - img=os.join(directory, Kmap) - im=Blender.Image.Load(img) - imagelist.append(im) - - t=Blender.Texture.New(Kmap) - t.setType('Image') - t.setImage(im) - - material.setTexture(0,t) - material.getTextures()[0].texco=16 - except: - pass - - else: - material = matlist[matindex] - - material.R = 0.8 - material.G = 0.8 - material.B = 0.8 - material.specCol[0] = 0.5 - material.specCol[1] = 0.5 - material.specCol[2] = 0.5 - - img=os.join(directory, Kmap) - im=Blender.Image.Load(img) - imagelist.append(im) - - t=Blender.Texture.New(Kmap) - t.setType('Image') - t.setImage(im) - - material.setTexture(0,t) - material.getTextures()[0].texco=16 - - else: - mtlflag = 0 - - line = file.readline() - - - file.close() - - elif words and words[0] == "usemtl": - if mtlflag == 1: - name = words[1] - matindex = AddMeshMaterial(name, materialList, matindex) - elif words: - print "%s: %s" % (linenumber, words) - linenumber = linenumber + 1 - file.close() - - # import in Blender - - print "import into Blender ..." - mesh = NMesh.GetRaw () - - i = 0 - while i < vcount: - x, y, z = pointList[i] - vert=NMesh.Vert(x, y, z) - mesh.verts.append(vert) - i=i+1 - - if vtcount > 0: - #mesh.hasFaceUV() = 1 - print ("Object has uv coordinates") - - if len(materialList) > 0: - for m in materialList: - try: - M=Material.Get(m) - mesh.materials.append(M) - except: - pass - - total = len(faceList) - i = 0 - - for f in faceList: - if i%1000 == 0: - print ("Progress = "+ str(i)+"/"+ str(total)) - - i = i + 1 - vi, ti, ni, matindex = f - face=NMesh.Face() - if len(materialList) > 0: - face.mat = matindex - - limit = len(vi) - setcount = setcount + len(vi) - c = 0 - - while c < limit: - m = vi[c]-1 - if vtcount > 0 and len(ti) > c: - n = ti[c]-1 - if vncount > 0 and len(ni) > c: - p = ni[c]-1 - - if vtcount > 0: - try: - u, v = uvList[n] - except: - pass - - """ - # multiply uv coordinates by 2 and add 1. Apparently blender uses uv range of 1 to 3 (not 0 to 1). - mesh.verts[m].uvco[0] = (u*2)+1 - mesh.verts[m].uvco[1] = (v*2)+1 - """ - - if vncount > 0: - if p > len(normalList): - print("normal len = " +str(len(normalList))+ " vector len = " +str(len(pointList))) - print("p = " +str(p)) - x, y, z = normalList[p] - mesh.verts[m].no[0] = x - mesh.verts[m].no[1] = y - mesh.verts[m].no[2] = z - c = c+1 - - if len(vi) < 5: - for index in vi: - face.v.append (mesh.verts[index-1]) - - if vtcount > 0: - for index in ti: - u, v = uvList[index-1] - face.uv.append((u,v)) - - if len(imagelist)>0: - face.image=imagelist[0] - #print - - if vcount>0: - face.smooth=1 - - mesh.faces.append(face) - - print "all other (general) polygons ..." - for f in faceList: - vi, ti, ni, matindex = f - if len(vi) > 4: - # export the polygon as edges - print ("Odd face, vertices = "+ str(len(vi))) - for i in range(len(vi)-2): - face = NMesh.Face() - if len(materialList) > 0: - face.mat = matindex - face.v.append(mesh.verts[vi[0]-1]) - face.v.append(mesh.verts[vi[i+1]-1]) - face.v.append(mesh.verts[vi[i+2]-1]) - - if vtcount > 0: - if len(ti) > i+2: - u, v = uvList[ti[0]-1] - face.uv.append((u,v)) - u, v = uvList[ti[i+1]-1] - face.uv.append((u,v)) - u, v = uvList[ti[i+2]-1] - face.uv.append((u,v)) - - mesh.faces.append(face) - - NMesh.PutRaw(mesh, Name,1) - - print ("Total number of vertices is "+ str(vcount)) - print ("Total number of faces is "+ str(len(faceList))) - print ("Total number of sets is "+ str(setcount)) - - - print("Finished importing " +str(Name)+ ".obj") - -#========================================= -def AddMeshMaterial(name, materialList, matindex): -#========================================= - - index = 0 - found = 0 - limit = len(materialList) - - while index < limit: - if materialList[index] == name: - matindex = index - found = 1 - index = limit - index = index + 1 - - if found == 0: - materialList.append(name) - matindex = len(materialList)-1 - - return matindex - -#========================================= -def AddGlobalMaterial (name, matindex): -#========================================= - - index = 0 - found = 0 - matindex = 0 - MatList = Material.Get() - limit = len(MatList) - - while index < limit: - if MatList[index].name == name: - matindex = index - found = 1 - index = limit - index = index + 1 - - if found == 0: - material = Material.New(name) - matindex = index - - return matindex - -#================================ -def ObjExport(FILE, Name, type): -#================================ - global returncode - global vertexcount - global uvcount - global Transform - global multiflag - global exporttype - - vertexcount = 0 - uvcount = 0 - returncode = 0 - print("Writing %s..." % Name) - FILE.write("# Wavefront OBJ (1.0) exported by lynx's OBJ import/export script\n\n") - - Objects = Object.GetSelected() - if Objects == []: - print("You have not selected an object!") - returncode = 4 - else: - for object in Objects: - MtlList = [] - if len(Objects) > 1 or exporttype > 1: - Transform = CreateMatrix(object, Transform) - multiflag = 1 - - mesh = NMesh.GetRawFromObject(object.name) - ObjName = mesh.name - has_uvco = mesh.hasVertexUV() - - FILE.write("# Meshname:\t%s\n" % ObjName) - - faces = mesh.faces - materials = mesh.materials - Vertices = mesh.verts - GlobalMaterials = Material.Get() - - if len(materials) >= 1 and len(GlobalMaterials) > 0 and type < 4: - CreateMtlFile(Name, materials, MtlList) - - # Total Vertices and faces; comment if not useful - FILE.write("# Total number of Faces:\t%s\n" % len(faces)) - FILE.write("# Total number of Vertices:\t%s\n" % len(Vertices)) - - FILE.write("\n") - - # print first image map for uvcoords to use - # to be updated when we get access to other textures - if mesh.hasFaceUV(): FILE.write("# UV Texture:\t%s\n\n" % mesh.hasFaceUV()) - - if len(materials) >= 1 and len(GlobalMaterials) > 0 and type < 3: - UseLayers(faces, Vertices, MtlList, has_uvco, FILE, ObjName, Name) - elif len(materials) >= 1 and len(GlobalMaterials) > 0 and type == 3: - UseMtl(faces, Vertices, MtlList, has_uvco, FILE, ObjName, Name) - else: - Standard(faces, Vertices, has_uvco, FILE, ObjName) - -#================================================ -def CreateMtlFile (name, MeshMaterials, MtlList): -#================================================ - global gFilename - - # try to export materials - directory, mtlname = os.split(gFilename.val) - mtlname = name + ".mtl" - filename = os.join(directory, mtlname) - file = open(filename, "w") - - file.write("# Materials for %s.\n" % (name + ".obj")) - file.write("# Created by Blender.\n") - file.write("# These files must be in the same directory for the materials to be read correctly.\n\n") - - MatList = Material.Get() - print str(MeshMaterials) - - MtlNList=[] - for m in MatList: - MtlNList.append(m.name) - - counter = 1 - found = 0 - - for material in MeshMaterials: - for mtl in MtlList: - if material == mtl: - found = 1 - - MtlList.append(material) - - if found == 0: - file.write("newmtl %s \n" % material.name) - index = 0 - print material, MatList - while index < len(MatList): - if material.name == MatList[index].name: - mtl = MatList[index] - index = len(MatList) - found = 1 - index = index + 1 - - if found == 1: - alpha = mtl.getAlpha() - file.write(" Ka %s %s %s \n" % (round(1-alpha,5), round(1-alpha,5), round(1-alpha,5))) - file.write(" Kd %s %s %s \n" % (round(mtl.R,5), round(mtl.G,5), round(mtl.B,5))) - file.write(" Ks %s %s %s \n" % (round(mtl.specCol[0],5), round(mtl.specCol[1],5), round(mtl.specCol[2],5))) - mtextures = mtl.getTextures() # get a list of the MTex objects - try: - for mtex in mtextures: - if mtex.tex.type == Texture.Types.IMAGE and (mtex.texco & Texture.TexCo.UV): - file.write(" map_Kd %s \n" % Blender.sys.basename(mtex[0].tex.image.filename)) - break - except: - if mtextures[0].tex.type == Texture.Types.IMAGE and (mtextures[0].texco & Texture.TexCo.UV): - file.write(" map_Kd %s \n" % Blender.sys.basename(mtextures[0].tex.image.filename)) - - - file.write(" illum 1\n") - - else: - file.write(" Ka %s %s %s \n" % (0, 0, 0)) - file.write(" Kd %s %s %s \n" % (1, 1, 1)) - file.write(" Ks %s %s %s \n" % (1, 1, 1)) - file.write(" illum 1\n") - - found = 0 - - file.flush() - file.close() - -#=========================================================== -def Standard(faces, Vertices, has_uvco, FILE, ObjName): -#=========================================================== - global vertexcount - global uvcount - global multiflag - - uvPtrs = [] - uvList = [] - - FILE.write("o %s\n\n" % (ObjName)) - FILE.write("g %s\n\n" % (ObjName)) - - for v in Vertices: - vert = v.co - if multiflag == 1: - vert = Alter(vert, Transform) - x, y, z = vert - - FILE.write("v %s %s %s\n" % (x, y, z)) - - uv_flag = 0 - for face in faces: - for uv in face.uv: - found = 0 - index = len(uvList) - limit = 0 - if len(uvList)-200 > 0: - limit = len(uvList)-200 - while index > limit and found == 0: - uv_value = uvList[index-1] - if uv[0] == uv_value[0] and uv[1] == uv_value[1]: - uvPtrs.append(index+uvcount) - found = 1 - index = index - 1 - if found == 0: - uvList.append(uv) - index = len(uvList) - uvPtrs.append(index+uvcount) - u, v = uv - FILE.write("vt %s %s\n" % (u, v)) - uv_flag = 1 - - if has_uvco and uv_flag == 0: - for v in Vertices: - u, v, z = v.uvco - u = (u-1)/2 - v = (v-1)/2 - FILE.write("vt %s %s\n" % (u, v)) - - for v in Vertices: - x, y, z = v.no - FILE.write("vn %s %s %s\n" % (x, y, z)) - - p = 0 - uvindex = 0 - total = len(faces) - - for face in faces: - p = p+1 - if (p%1000) == 0: - print ("Progress = "+ str(p)+ " of "+ str(total) +" faces") - - FILE.write("f ") - for index in range(len(face.v)): - v = face.v[index].index + vertexcount - if len(face.uv) > 0: - FILE.write("%s/%s/%s " % (v+1, uvPtrs[uvindex], v+1)) - uvindex = uvindex+1 - elif has_uvco: - FILE.write("%s/%s/%s " % (v+1, v+1, v+1)) - else: - FILE.write("%s//%s " % (v+1, v+1)) - FILE.write("\n") - - vertexcount = vertexcount + len(Vertices) - uvcount = uvcount + len(uvList) - - print("Export of " +str(ObjName)+ ".obj finished.\n") - -#===================================================================== -def UseLayers(faces, Vertices, MtlList, has_uvco, FILE, ObjName, Name): -#===================================================================== - global vertexcount - global uvcount - global multiflag - - uvPtrs = [] - uvList = [] - - FILE.write("mtllib %s\n\n" % (Name + ".mtl")) - FILE.write("g %s\n\n" % (ObjName)) - - for v in Vertices: - vert = v.co - if multiflag == 1: - vert = Alter(vert, Transform) - x, y, z = vert - FILE.write("v %s %s %s\n" % (x, y, z)) - - uv_flag = 0 - for m in range(len(MtlList)): - for face in faces: - if face.mat == m: - for uv in face.uv: - found = 0 - index = len(uvList) - limit = 0 - if len(uvList)-200 > 0: - limit = len(uvList)-200 - while index > limit and found == 0: - uv_value = uvList[index-1] - if uv[0] == uv_value[0] and uv[1] == uv_value[1]: - uvPtrs.append(index+uvcount) - found = 1 - index = index - 1 - if found == 0: - uvList.append(uv) - index = len(uvList) - uvPtrs.append(index+uvcount) - u, v = uv - FILE.write("vt %s %s\n" % (u, v)) - uv_flag = 1 - - if has_uvco and uv_flag == 0: - for v in Vertices: - u, v, z = v.uvco - u = (u-1)/2 - v = (v-1)/2 - FILE.write("vt %s %s\n" % (u, v)) - - for v in Vertices: - x, y, z = v.no - FILE.write("vn %s %s %s\n" % (x, y, z)) - - total = len(faces) - p = 0 - uvindex = 0 - for m in range(len(MtlList)): - FILE.write("usemtl %s\n" % (MtlList[m].name)) - for face in faces: - if face.mat == m: - p = p+1 - if (p%1000) == 0: - print ("Progress = "+ str(p)+ " of "+ str(total) +" faces") - - FILE.write("f ") - for index in range(len(face.v)): - v = face.v[index].index + vertexcount - if len(face.uv) > 0: - FILE.write("%s/%s/%s " % (v+1, uvPtrs[uvindex], v+1)) - uvindex = uvindex+1 - elif has_uvco: - FILE.write("%s/%s/%s " % (v+1, v+1, v+1)) - else: - FILE.write("%s//%s " % (v+1, v+1)) - FILE.write("\n") - - vertexcount = vertexcount + len(Vertices) - print("Export of " +str(ObjName)+ ".obj using material layers finished.\n") - -#================================================================== -def UseMtl(faces, Vertices, MtlList, has_uvco, FILE, ObjName, Name): -#================================================================== - global vertexcount - global multiflag - - FILE.write("mtllib %s\n\n" % (Name + ".mtl")) - FILE.write("o %s\n\n" % (ObjName)) - - index = 0 - VertexList = [] - for vertex in Vertices: - VertexList.append(-1) - index = index + 1 - print("number of vertices is " +str(len(VertexList))) - - Totalindex = 0 - ix = 0 - NewVertexList = [] - NewVertexCo = [] - for m in range(len(MtlList)): - # Group name is the name of the mesh - if MtlList[m]: - FILE.write("g %s\n" % (MtlList[m].name+str(m+1))) - else: - FILE.write("g %s\n" % ("Null"+str(m+1))) - FILE.write("s off\n\n") - - FILE.write("usemtl %s\n\n" % (MtlList[m].name)) - - for face in faces: - if face.mat == m: - for vertex in face.v: - v = vertex.index - if VertexList[v] < 0: - VertexList[v] = Totalindex - NewVertexList.append(v) - Totalindex = Totalindex + 1 - - for v_old in NewVertexList: - vert = Vertices[v_old].co - if multiflag == 1: - vert = Alter(vert, Transform) - x, y, z = vert - FILE.write("v %s %s %s\n" % (x, y, z)) - NewVertexCo.append([x,y,z]) - - if has_uvco: - for v_old in NewVertexList: - u, v, z = Vertices[v_old].uvco - u = (u-1)/2 - v = (v-1)/2 - FILE.write("vt %s %s\n" % (u, v)) - - for v_old in NewVertexList: - x, y, z = Vertices[v_old].no - FILE.write("vn %s %s %s\n" % (x, y, z)) - - for face in faces: - if face.mat == m: - FILE.write("f ") - for index in range(len(face.v)): - v = face.v[index].index - v_new = VertexList[v] - if has_uvco: - FILE.write("%s/%s/%s " % (v_new+1, v_new+1, v_new+1)) - else: - FILE.write("%s//%s " % (v_new+1, v_new+1)) - FILE.write("\n") - - FILE.write("\n") - - NewVertexList = [] - print("Group " +str(m+1)+ " of " +str(len(MtlList))+ " finished.") - - print("Export of " +str(ObjName)+ ".obj using groups finished.\n") - -#======================================== -def CreateMatrix(object, Transform): -#======================================== - Mx = [] - My = [] - Mz = [] - T1 = [] - Transform = [] - - angle = object.RotX - Mx.append([1, 0, 0]) - y = math.cos(angle) - z = -math.sin(angle) - Mx.append([0, y, z]) - y = math.sin(angle) - z = math.cos(angle) - Mx.append([0, y, z]) - - angle = object.RotY - x = math.cos(angle) - z = math.sin(angle) - My.append([x, 0, z]) - My.append([0, 1, 0]) - x = -math.sin(angle) - z = math.cos(angle) - My.append([x, 0, z]) - - angle = object.RotZ - x = math.cos(angle) - y = -math.sin(angle) - Mz.append([x, y, 0]) - x = math.sin(angle) - y = math.cos(angle) - Mz.append([x, y, 0]) - Mz.append([0, 0, 1]) - - m0 = Mx[0] - m1 = Mx[1] - m2 = Mx[2] - for row in My: - x, y, z = row - nx = x*m0[0] + y*m1[0] + z*m2[0] - ny = x*m0[1] + y*m1[1] + z*m2[1] - nz = x*m0[2] + y*m1[2] + z*m2[2] - T1.append([nx, ny, nz]) - - m0 = T1[0] - m1 = T1[1] - m2 = T1[2] - for row in Mz: - x, y, z = row - nx = x*m0[0] + y*m1[0] + z*m2[0] - ny = x*m0[1] + y*m1[1] + z*m2[1] - nz = x*m0[2] + y*m1[2] + z*m2[2] - Transform.append([nx, ny, nz]) - - Transform.append([object.SizeX, object.SizeY, object.SizeZ]) - Transform.append([object.LocX, object.LocY, object.LocZ]) - - return Transform - -#====================================== -def Alter(vect, Transform): -#====================================== - v2 = [] - nv = [] - - x, y, z = vect - sx, sy, sz = Transform[3] - lx, ly, lz = Transform[4] - - v2.append(x*sx) - v2.append(y*sy) - v2.append(z*sz) - - for index in range(len(vect)): - t = Transform[index] - nv.append(v2[0]*t[0] + v2[1]*t[1] +v2[2]*t[2]) - - nv[0] = nv[0]+lx - nv[1] = nv[1]+ly - nv[2] = nv[2]+lz - - return nv diff --git a/blender/wrl2export.py b/blender/wrl2export.py deleted file mode 100644 index 3fedfb9f..00000000 --- a/blender/wrl2export.py +++ /dev/null @@ -1,1080 +0,0 @@ -#!BPY -""" Registration info for Blender menus: -Name: 'VRML 2.0 (.wrl)...' -Blender: 242 -Group: 'Export' -Submenu: 'All Objects...' all -Submenu: 'All Objects compressed...' comp -Submenu: 'Selected Objects...' selected -Submenu: 'Selected Objects compressed...' compselected -Tooltip: 'Export to VRML2 (.wrl) file.' -""" - -#------------------------------------------------------------------------ -# VRML2 exporter for blender 2.42 or above -# -# Source: http://blender.kimballsoftware.com/ -# -# $Id: wrl2export.py,v 1.32 2006/09/29 10:19 kimballr Exp kimballr $ -# -# Authors: Rick Kimball with much inspiration -# from the forum at www.elysiun.com -# and irc://irc.freenode.net/blenderchat -# Ken Miller and Steve Matthews (Added Camera Support) -# -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# Copyright (C) 2003,2004: Rick Kimball rick@vrmlworld.net -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ***** END GPL LICENCE BLOCK ***** -# -# To use script: -# 1.) copy to C:\program files\blender foundation\blender\.blender\scripts -# 2.) Select the File/Export/VRML2 menu item in blender. -# -# Notes: -# This exporter only deals with Meshes, Camera, Lights and Viewpoints -# The output filename is same as current blender file with .wrl extension -# Error messages go to the Blender DOS console window -# -# The latest version of this python export script: -# http://blender.kimballsoftware.com/ -# -# If you like this script, try using http://vrmlworld.net/ -# to show off your VRML world. -# -# 2006-09-29 by Rick Kimball -# o Fixed for Blender 2.42 -# o uses new file select dialog. -# o prompts before overwriting output -# o Added support for gzip compressed output -# -# 2004-01-19 by Rick Kimball -# o added sub menus and file selector dialog -# -# 2004-01-17 by Rick Kimball -# o add meta comments so script will appear in export menu list -# -# 2003-11-01 by Rick Kimball -# o fixed issues related to Lamp object and 2.28a API. -# -# 2003-07-19 by Rick Kimball -# o made compatible with new Python API in 2.28 -# -# 2003-01-16 by Ken Miller - with math help from Steve Matthews :) -# o Added support for exporting cameras out of Blender -# o Sets the name of the camera as the object name -# o sets the description of the camera as the object name, -# which should be modified to something meaningful -# o sets the position and orientation -# -# 2003-01-19 Rick Kimball -# o Added Support For PointLight, SpotLight and DirectionalLight using Lamps -# o Creates multi singlesided or doublesided IFS -# o Creates IndexedLineSets if DrawTypes is WIRE instead of Shaded -# -# 2003-02-03 Rick Kimball -# o attempts to catch exceptions for empty objects -# -# 2003-02-04 Rick Kimball -# o fixed file overwrite problem when blender filename is all uppercase -# -# 2003-02-08 Rick Kimball -# o cleanStr() creates valid VRML DEF names even if object.name -# is zero length or uses VRML reserved names or characters -# -#------------------------------------------------------------------------ -# Known Issue: -# o doesn't handle multiple materials (don't use material indices) -# o doesn't handle multiple UV textures on a single mesh. (create a mesh for each texture) -# o material colors need work -# o spotlight softness needs work -# o can't get the texture array associated with material * not the UV ones -# o can't set smoothing, crease angle and mesh smoothing * setting not accesible -# -# Still Todo: -# -# - Support for material indexes -# - Automatically Split IFS when multiple UV textures found * warning only now -# - Automatically Split IFS when combination of single vs double sided -# - Automatically Split IFS when face with only 2 vertices is found should be an ILS -# - Export common coordinate map for split IFS -# - Intelligent color array vs color index -# - Support more blender objects: World -# - Figure out how to output Animation -# - Add GUI to control the following: -# o All/Layer/Object output radio button -# o Color per vertex toggle yes/no -# o Complex/Simple VRML output radio button -# o Compressed/Uncompressed output radio button -# o Decimal precision dropdown 1,2,3,4,5,6 -# o IFS/Elevation Grid output radio button -# o Normals output toggle yes/no -# o Proto output toggle yes/no -# o Verbose console progress - -import Blender -from Blender import Object, Mesh, NMesh, Lamp, Draw, BGL, Image, Text, sys, Mathutils -import math - -#-- module constants -radD=math.pi/180.0 -rad90=90.0*radD # for rotation -rad30=30.0*radD # default crease angle -extension = '' -ARG='' - -# Blender is Z up, VRML is Y up, both are right hand coordinate -# systems, so to go from Blender coords to VRML coords we rotate -# by 90 degrees around the X axis. In matrix notation, we have a -# matrix, and it's inverse, as: -M_blen2vrml = Mathutils.Matrix([1,0,0,0], \ - [0,0,1,0], \ - [0,-1,0,0], \ - [0,0,0,1]) - -M_vrml2blen = Mathutils.Matrix([1,0,0,0], \ - [0,0,-1,0], \ - [0,1,0,0], \ - [0,0,0,1]) - -M_rotX = Mathutils.Matrix([1.0, 0.0, 0.0], \ - [0.0, 0.0, -1.0], \ - [0.0, 1.0, 0.0]) - -#------------------------------------------------------------------------ -#-- utility functions and classes -- -#------------------------------------------------------------------------ -def rad2deg(v): - return round(v*180.0/math.pi,4) - -def deg2rad(v): - return (v*math.pi)/180.0; - -def eulToVecRot(self, RotX, RotY, RotZ): - ti = RotX*0.5 - tj = RotY*0.5 - th = RotZ*0.5 - - ci = math.cos(ti) - cj = math.cos(tj) - ch = math.cos(th) - si = math.sin(ti) - sj = math.sin(tj) - sh = math.sin(th) - cc = ci*ch - cs = ci*sh - sc = si*ch - ss = si*sh - - q0 = cj*cc + sj*ss - q1 = cj*sc - sj*cs - q2 = cj*ss + sj*cc - q3 = cj*cs - sj*sc - - angle = 2 * math.acos(q0) - if (math.fabs(angle) < 0.000001): - axis = [1.0, 0.0, 0.0] - else: - sphi = 1.0/math.sqrt(1.0 - (q0*q0)) - axis = [q1 * sphi, q2 * sphi, q3 * sphi] - - a = Mathutils.Vector(axis) - a.normalize() - return ([a.x, a.y, a.z], angle) - -class DrawTypes: - """Object DrawTypes enum values - BOUNDS - draw only the bounding box of the object - WIRE - draw object as a wire frame - SOLID - draw object with flat shading - SHADED - draw object with OpenGL shading -""" - BOUNDBOX = 1 - WIRE = 2 - SOLID = 3 - SHADED = 4 - TEXTURE = 5 - -#------------------------------------------------------ -# the Blender.Object class seems to be missing this... -#------------------------------------------------------ -if not hasattr(Blender.Object,'DrawTypes'): - Blender.Object.DrawTypes = DrawTypes() - -#------------------------------------------------------------------------ -#-- VRML2Export -- -#------------------------------------------------------------------------ -class VRML2Export: - #------------------------------------------------------------------------ - def __init__(self, filename): - #--- public you can change these --- - self.verbose=1 # level of verbosity in console 0-none, 1-some, 2-most - self.cp=3 # decimals for material color values 0.000 - 1.000 - self.vp=3 # decimals for vertex coordinate values 0.000 - n.000 - self.tp=3 # decimals for texture coordinate values 0.000 - 1.000 - self.ambientIntensity=.2 - self.defCreaseAngle=rad30 - self.smooth=0 - - #--- class private don't touch --- - self.texNames={} # dictionary of textureNames - self.matNames={} # dictionary of materiaNames - self.indentLevel=0 # keeps track of current indenting - self.filename=filename - self.file = open(filename, "w") - self.bNav=0 - self.nNodeID=0 - self.VRMLReserved=[ "Anchor","Appearance","Anchor","AudioClip","Background", - "Billboard", "Box", "Collision", "Color", "ColorInterpolator", - "Cone", "Coordinate", "CoordinateInterpolator", "Cylinder", - "CylinderSensor", "DirectionalLight", "ElevationGrid", - "Extrustion", "Fog", "FontStyle", "Group", "ImageTexture", - "IndexedFaceSet", "IndexedLineSet", "Inline", "LOD", - "Material", "MovieTexture", "NavigationInfo", "Normal", - "NormalInterpolator","OrientationInterpolator", "PixelTexture", - "PlaneSensor", "PointLight", "PointSet", "PositionInterpolator", - "ProxmimitySensor", "ScalarInterpolator", "Script", "Shape", - "Sound", "Sphere", "SphereSensor", "SpotLight", "Switch", - "Text", "TextureCoordinate", "TextureTransform", "TimeSensor", - "TouchSensor", "Transform", "Viewpoint", "VisibilitySensor", - "WorldInfo" - ] - - #------------------------------------------------------------------------ - # writeHeader, export file, cleanup - #------------------------------------------------------------------------ - def writeHeader(self): - self.file.write("#VRML V2.0 utf8\n") - self.file.write("# modeled using blender3d http://blender.org/$\n") - self.file.write("# exported using wrl2export.py version $Revision: 1.32 $\n") - self.file.write("# get latest exporter at http://kimballsoftware.com/blender/\n\n") - - def export(self, scene): - self.scene=scene - print "Info: starting VRML2 export to " + self.filename + "..." - - self.writeHeader() - theObjects = [] - if ARG == 'selected' or ARG == 'compselected': - theObjects = Blender.Object.GetSelected() - else: - theObjects = scene.getChildren() - - for object in theObjects: - try: - objType=object.getType() - - if objType == "Mesh": - self.writeIndexedFaceSet(object, normals = 0) - elif objType == "Camera": - self.writeCameraInfo(object) - elif objType == "Lamp": - # if there is a lamp then we probably want to turn off the headlight - if self.bNav == 0: - self.writeNavigationInfo() - self.bNav=1 - #endif - - lamp=Lamp.Get(object.data.getName()) - try: - lampType=lamp.getType() - - if lampType == Lamp.Types.Lamp: - self.writePointLight(object, lamp) - elif lampType == Lamp.Types.Spot: - self.writeSpotLight(object, lamp) - elif lampType == Lamp.Types.Sun: - self.writeDirectionalLight(object, lamp) - else: - self.writeDirectionalLight(object, lamp) - #endif - except AttributeError: - print "Error: Unable to get type info for %s" % object.name - else: - print "Info: Ignoring [%s], object type [%s] not handle yet" % \ - (object.name,object.getType()) - #endif - except ValueError: - print "Error: object named %s has problem with accessing an attribute" % object.name - #end try - #endfor - self.cleanup() - - def cleanup(self): - self.file.close() - self.texNames={} - self.matNames={} - self.indentLevel=0 - print "Info: finished VRML2 export to %s\n" % self.filename - - #------------------------------------------------------------------------ - # Writes out camera info as a viewpoint - # Handles orientation, position - # Use camera object name to set description - #------------------------------------------------------------------------ - def writeCameraInfo(self, object): - if self.verbose > 0: - print "Info: exporting camera named="+object.name - #endif - - self.writeIndented("DEF %s Viewpoint {\n" % (self.cleanStr(object.name)), 1) - - self.writeIndented("description \"%s\" \n" % (object.name)) - - # get the camera location, subtract 90 degress from X to orient like VRML does - loc = self.rotatePointForVRML(object.loc) - rot = [object.RotX - 1.57, object.RotY, object.RotZ] - nRot = self.rotatePointForVRML(rot) - - # convert to Quaternion and to Angle Axis - Q = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2]) - Q1 = self.multiplyQuaternions(Q[0], Q[1]) - Qf = self.multiplyQuaternions(Q1, Q[2]) - angleAxis = self.quaternionToAngleAxis(Qf) - - # write orientation statement - self.writeIndented("orientation %3.2f %3.2f %3.2f %3.2f\n" % - (angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3])) - - # write position statement - self.writeIndented("position %3.2f %3.2f %3.2f\n" % - (loc[0], loc[1], loc[2])) - - self.writeIndented("} # Viewpoint\n", -1) - - self.writeIndented("\n") - #enddef - - #------------------------------------------------------------------------ - def writeIndexedFaceSet(self, object, normals = 0): - if self.verbose > 0: - print "Info: exporting mesh named=["+object.name+"]" - #endif - - imageMap={} # set of used images - sided={} # 'one':cnt , 'two':cnt - vColors={} # 'multi':1 - - mesh=object.getData() - - nIFSCnt=self.countIFSSetsNeeded(mesh, imageMap, sided, vColors) - - objName = self.cleanStr(object.name) - - if nIFSCnt > 1: - self.writeIndented("DEF %s%s Group {\n" % ("G_", objName),1) - self.writeIndented("children [\n",1) - #endif - - if self.verbose > 0: - print "Debug: [%s] has %d UV Textures" % (object.name, nIFSCnt) - #endif - - if sided.has_key('two') and sided['two'] > 0: - bTwoSided=1 - else: - bTwoSided=0 - - self.writeIndented("DEF %s Shape {\n" % objName,1) - - # show script debugging info - if self.verbose > 1: - self.meshToString(mesh) - print "Debug: mesh.faces[" - for face in mesh.faces: - self.faceToString(face) - #endfor - print "Debug: ]" - #endif - - maters=mesh.materials - hasImageTexture=0 - - if len(maters) > 0 or mesh.hasFaceUV(): - self.writeIndented("appearance Appearance {\n", 1) - - # right now this script can only handle a single material per mesh. - if len(maters) >= 1: - mat=Blender.Material.Get(maters[0].name) - self.writeMaterial(mat, self.cleanStr(maters[0].name,'mat_')) - if len(maters) > 1: - print "Warning: mesh named %s has multiple materials" % objName - print "Warning: only one material per object handled" - #endif - else: - self.writeIndented("material NULL\n") - #endif - - #-- textures - if mesh.hasFaceUV(): - for face in mesh.faces: - if (hasImageTexture == 0) and (face.image): - self.writeImageTexture(face.image.name) - hasImageTexture=1 # keep track of face texture - #endif - #endfor - #endif - - self.writeIndented("} # Appearance\n", -1) - #endif - - #------------------------------------------------------------------- - #-- - #-- IndexedFaceSet or IndexedLineSet - # - - # check if object is wireframe only - if object.drawType == Blender.Object.DrawTypes.WIRE: - # user selected WIRE=2 on the Drawtype=Wire on (F9) Edit page - ifStyle="IndexedLineSet" - else: - # user selected BOUNDS=1, SOLID=3, SHARED=4, or TEXTURE=5 - ifStyle="IndexedFaceSet" - #endif - - meshName=self.cleanStr(mesh.name) - - self.writeIndented("geometry DEF %s %s {\n" % (meshName,ifStyle), 1) - if object.drawType != Blender.Object.DrawTypes.WIRE: - if bTwoSided == 1: - self.writeIndented("solid FALSE # two sided\n") - else: - self.writeIndented("solid TRUE # one sided\n") - #endif - #endif - - #--- - #--- output coordinates - self.writeCoordinates(object, mesh, objName) - - if object.drawType != Blender.Object.DrawTypes.WIRE: - #--- - #--- output textureCoordinates if UV texture used - if mesh.hasFaceUV(): - self.writeTextureCoordinates(mesh) - self.writeVertexColors(mesh) # experiment - #if hasImageTexture == 1: - # self.writeTextureCoordinates(mesh) - # if vColors.has_key('multi'): - # self.writeVertexColors(mesh) # experiment - # #endif - #else: - # self.writeFaceColors(mesh) - #endif hasImageTexture - #endif hasFaceUV - - # TBD: figure out how to get this properly - if self.smooth: - creaseAngle=self.defCreaseAngle; - self.writeIndented("creaseAngle %s\n" % creaseAngle) - else: - self.writeIndented("creaseAngle 0.0 # in radians\n") - #endif mesh.smooth - #endif WIRE - - #--- output vertexColors - if mesh.hasVertexColours() and vColors.has_key('multi'): - self.writeVertexColors(mesh) - #endif - - #--- output closing braces - self.writeIndented("} # %s\n" % ifStyle, -1) - self.writeIndented("} # Shape\n", -1) - - if nIFSCnt > 1: - self.writeIndented("] # children\n", -1) - self.writeIndented("} # Group\n", -1) - #endif - - self.writeIndented("\n") - #enddef - - #------------------------------------------------------------------------ - def writeCoordinates(self, object, mesh, objName): - #-- vertices - self.writeIndented("coord Coordinate {\n", 1) - self.writeIndented("point [\n", 1) - meshVertexList = mesh.verts - - # create vertex list and pre rotate -90 degrees X for VRML - mm=object.getMatrix() - for vertex in meshVertexList: - ob_matrix = Mathutils.Matrix(object.getMatrix('worldspace')) - mm = M_blen2vrml * ob_matrix * M_vrml2blen - blenvert = Mathutils.Vector(vertex.co) - v=M_blen2vrml * blenvert * mm - self.writeIndented("%s %s %s,\n" % - (round(v[0],self.vp), - round(v[1],self.vp), - round(v[2],self.vp) )) - #endfor - self.writeIndented("] # point\n", -1) - self.writeIndented("} # Coordinate\n", -1) - - self.writeIndented("coordIndex [\n", 1) - coordIndexList=[] - for face in mesh.faces: - cordStr="" - for i in range(len(face)): - indx=meshVertexList.index(face[i]) - cordStr = cordStr + "%s, " % indx - #endfor - self.writeIndented(cordStr + "-1,\n") - #endfor - self.writeIndented("] # coordIndex\n", -1) - #enddef - - #------------------------------------------------------------------------ - def writeTextureCoordinates(self, mesh): - texCoordList=[] - texIndexList=[] - j=0 - - for face in mesh.faces: - for i in range(len(face)): - texIndexList.append(j) - texCoordList.append(face.uv[i]) - j=j+1 - #endfor - texIndexList.append(-1) - #endfor - - self.writeIndented("texCoord TextureCoordinate {\n", 1) - self.writeIndented("point [\n", 1) - for i in range(len(texCoordList)): - self.writeIndented("%s %s," % - (round(texCoordList[i][0],self.tp), - round(texCoordList[i][1],self.tp))+"\n") - #endfor - self.writeIndented("] # point\n", -1) - self.writeIndented("} # texCoord\n", -1) - - self.writeIndented("texCoordIndex [\n", 1) - texIndxStr="" - for i in range(len(texIndexList)): - texIndxStr = texIndxStr + "%d, " % texIndexList[i] - if texIndexList[i]==-1: - self.writeIndented(texIndxStr + "\n") - texIndxStr="" - #endif - #endfor - self.writeIndented("] # texCoordIndex\n", -1) - #enddef - - #------------------------------------------------------------------------ - def writeFaceColors(self, mesh): - self.writeIndented("colorPerVertex FALSE\n") - self.writeIndented("color Color {\n",1) - self.writeIndented("color [\n",1) - - for face in mesh.faces: - if face.col: - c=face.col[0] - if self.verbose > 1: - print "Debug: face.col r=%d g=%d b=%d" % (c.r, c.g, c.b) - #endif - - aColor = self.rgbToFS(c) - self.writeIndented("%s,\n" % aColor) - #endfor - - self.writeIndented("] # color\n",-1) - self.writeIndented("} # Color\n",-1) - #enddef - - #------------------------------------------------------------------------ - def writeVertexColors(self, mesh): - self.writeIndented("colorPerVertex TRUE\n") - self.writeIndented("color Color {\n",1) - self.writeIndented("color [\n",1) - - for i in range(len(mesh.verts)): - c=self.getVertexColorByIndx(mesh,i) - if self.verbose > 1: - print "Debug: vertex[%d].col r=%d g=%d b=%d" % (i, c.r, c.g, c.b) - #endif - - aColor = self.rgbToFS(c) - self.writeIndented("%s,\n" % aColor) - #endfor - - self.writeIndented("] # color\n",-1) - self.writeIndented("} # Color\n",-1) - #enddef - - #------------------------------------------------------------------------ - def writeMaterial(self, mat, matName): - # look up material name, use it if available - if self.matNames.has_key(matName): - self.writeIndented("material USE %s\n" % matName) - self.matNames[matName]+=1 - return; - #endif - - self.matNames[matName]=1 - - ambient = mat.amb - diffuseR, diffuseG, diffuseB = mat.rgbCol[0], mat.rgbCol[1],mat.rgbCol[2] - emisR, emisG, emisB = diffuseR*mat.emit, diffuseG*mat.emit, diffuseB*mat.emit - shininess = mat.hard/255.0 - specR = mat.specCol[0] - specG = mat.specCol[1] - specB = mat.specCol[2] - transp = 1-mat.alpha - - self.writeIndented("material DEF %s Material {\n" % matName, 1) - self.writeIndented("diffuseColor %s %s %s" % - (round(diffuseR,self.cp), round(diffuseG,self.cp), round(diffuseB,self.cp)) + - "\n") - self.writeIndented("ambientIntensity %s" % - (round(ambient,self.cp))+ - "\n") - self.writeIndented("specularColor %s %s %s" % - (round(specR,self.cp), round(specG,self.cp), round(specB,self.cp)) + - "\n" ) - self.writeIndented("emissiveColor %s %s %s" % - (round(emisR,self.cp), round(emisG,self.cp), round(emisB,self.cp)) + - "\n" ) - self.writeIndented("shininess %s" % - (round(shininess,self.cp)) + - "\n" ) - self.writeIndented("transparency %s" % - (round(transp,self.cp)) + - "\n") - self.writeIndented("} # Material\n",-1) - #enddef - - #------------------------------------------------------------------------ - def writeImageTexture(self, name): - if self.texNames.has_key(name): - self.writeIndented("texture USE %s\n" % self.cleanStr(name)) - self.texNames[name] += 1 - return - else: - self.writeIndented("texture DEF %s ImageTexture {\n" % self.cleanStr(name), 1) - self.writeIndented("url \"%s\"\n" % name) - self.writeIndented("} # ImageTexture \n",-1) - self.texNames[name] = 1 - #endif - #enddef - - #------------------------------------------------------------------------ - def writeSpotLight(self, object, lamp): - safeName = self.cleanStr(object.name) - - # compute cutoff and beamwidth - intensity=min(lamp.energy/1.5,1.0) # TBD: figure out the right value - - beamWidth=deg2rad(lamp.spotSize)*.5; - cutOffAngle=beamWidth*.99 - - (dx,dy,dz)=self.computeDirection(object) - # note -dx seems to equal om[3][0] - # note -dz seems to equal om[3][1] - # note dy seems to equal om[3][2] - om = object.getMatrix() - - location=self.rotVertex(om, (0,0,0)); - radius = lamp.dist*math.cos(beamWidth) - self.writeIndented("DEF %s SpotLight {\n" % safeName,1) - self.writeIndented("radius %s\n" % radius ) - self.writeIndented("intensity %s\n" % intensity ) - self.writeIndented("beamWidth %s # lamp.spotSize %s\n" % (beamWidth, lamp.spotSize) ) - self.writeIndented("cutOffAngle %s # lamp.spotBlend %s\n" % (cutOffAngle, lamp.spotBlend)) - self.writeIndented("direction %s %s %s # lamp.RotX=%s RotY=%s RotZ=%s\n" % \ - (round(dx,3),round(dy,3),round(dz,3), - round(rad2deg(object.RotX),3), - round(rad2deg(object.RotY),3), - round(rad2deg(object.RotZ),3))) - self.writeIndented("location %s %s %s\n" % (round(location[0],3), - round(location[1],3), - round(location[2],3))) - self.writeIndented("} # SpotLight\n",-1) - - # export a cone that matches the spotlight in verbose mode - if self.verbose > 1: - self.writeIndented("#generated visible spotlight cone\n") - self.writeIndented("Transform { # Spotlight Cone\n",1) - self.writeIndented("translation %s %s %s\n" % (round(location[0],3), - round(location[1],3), - round(location[2],3))) - rot = [object.RotX, object.RotY, object.RotZ] - nRot = self.rotatePointForVRML(rot) - - # convert to Quaternion and to Angle Axis - Q = self.eulerToQuaternions(nRot[0], nRot[1], nRot[2]) - Q1 = self.multiplyQuaternions(Q[0], Q[1]) - Qf = self.multiplyQuaternions(Q1, Q[2]) - angleAxis = self.quaternionToAngleAxis(Qf) - - # write orientation statement - self.writeIndented("rotation %3.2f %3.2f %3.2f %3.2f\n" % - (angleAxis[0], angleAxis[1], -angleAxis[2], angleAxis[3])) - - self.writeIndented("children [\n",1) - - ch=radius - br=ch*math.sin(beamWidth) - self.writeIndented("Transform {\n",1) - self.writeIndented("translation 0 -%s 0\n" % (ch/2)) - self.writeIndented("children ") - self.writeIndented("Collision {\n",1) - self.writeIndented("collide FALSE children Shape {\n",1) - self.writeIndented("geometry Cone { height %s bottomRadius %s }\n" % (ch, br)) - self.writeIndented("appearance Appearance{\n",1) - self.writeIndented("material Material { diffuseColor 1 1 1 transparency .8 }\n") - self.writeIndented("} # Appearance\n",-1) - self.writeIndented("} # Shape\n",-1) - self.writeIndented("} # Collision\n",-1) - self.writeIndented("} # Transform visible cone \n",-1) - self.writeIndented("] # Spot children\n",-1) - self.writeIndented("} # SpotLight Cone Transform\n",-1) - #endif debug cone - self.writeIndented("\n") - #enddef - - #------------------------------------------------------------------------ - def writeDirectionalLight(self, object, lamp): - safeName = self.cleanStr(object.name) - - intensity=min(lamp.energy/1.5, 1.0) # TBD: figure out the right value - (dx,dy,dz)=self.computeDirection(object) - - self.writeIndented("DEF %s DirectionalLight {\n" % safeName,1) - self.writeIndented("ambientIntensity %s\n" % self.ambientIntensity ) - self.writeIndented("intensity %s\n" % intensity ) - self.writeIndented("direction %s %s %s\n" % (round(dx,4),round(dy,4),round(dz,4))) - self.writeIndented("} # DirectionalLight\n",-1) - self.writeIndented("\n") - #enddef - - #------------------------------------------------------------------------ - def writePointLight(self, object, lamp): - safeName = self.cleanStr(object.name) - - om = object.getMatrix() - location=self.rotVertex(om, (0,0,0)); - intensity=min(lamp.energy/1.5,1.0) # TBD: figure out the right value - - radius = lamp.dist - self.writeIndented("DEF %s PointLight {\n" % safeName,1) - self.writeIndented("ambientIntensity %s\n" % self.ambientIntensity ) - self.writeIndented("intensity %s\n" % intensity ) - self.writeIndented("location %s %s %s\n" % (round(location[0],3), - round(location[1],3), - round(location[2],3))) - self.writeIndented("radius %s\n" % radius ) - self.writeIndented("} # PointLight\n",-1) - self.writeIndented("\n") - #enddef - - #------------------------------------------------------------------------ - def writeNavigationInfo(self): - self.writeIndented("NavigationInfo {\n",1) - self.writeIndented("headlight FALSE\n") - self.writeIndented("avatarSize [0.25, 1.75, 0.75]\n") - self.writeIndented("} # NavigationInfo\n",-1) - self.writeIndented("\n") - #enddef - - #------------------------------------------------------------------------ - #--- Utility methods - #------------------------------------------------------------------------ - - def cleanStr(self, name, prefix='rsvd_'): - """cleanStr(name,prefix) - try to create a valid VRML DEF name from object name""" - - newName=name[:] - if len(newName) == 0: - self.nNodeID+=1 - return "%s%d" % (prefix, self.nNodeID) - - if newName in self.VRMLReserved: - newName='%s%s' % (prefix,newName) - #endif - - if newName[0] in ['0','1','2','3','4','5','6','7','8','9']: - newName='%s%s' % ('_',newName) - #endif - - for bad in [' ','"','#',"'",',','.','[','\\',']','{','}']: - newName=newName.replace(bad,'_') - return newName - #enddef - - def countIFSSetsNeeded(self, mesh, imageMap, sided, vColors): - """ - countIFFSetsNeeded() - should look at a blender mesh to determine - how many VRML IndexFaceSets or IndexLineSets are needed. A - new mesh created under the following conditions: - - o - split by UV Textures / one per mesh - o - split by face, one sided and two sided - o - split by smooth and flat faces - o - split when faces only have 2 vertices * needs to be an IndexLineSet - """ - - imageNameMap={} - faceMap={} - nFaceIndx=0 - - for face in mesh.faces: - sidename=''; - if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE: - sidename='two' - else: - sidename='one' - #endif - - if not vColors.has_key('multi'): - for face in mesh.faces: - if face.col: - c=face.col[0] - if c.r != 255 and c.g != 255 and c.b !=255: - vColors['multi']=1 - #endif - #endif - #endfor - #endif - - if sided.has_key(sidename): - sided[sidename]+=1 - else: - sided[sidename]=1 - #endif - - if face.image: - faceName="%s_%s" % (face.image.name, sidename); - - if imageMap.has_key(faceName): - imageMap[faceName].append(face) - else: - imageMap[faceName]=[face.image.name,sidename,face] - #endif - #endif - #endfor - - if self.verbose > 0: - for faceName in imageMap.keys(): - ifs=imageMap[faceName] - print "Debug: faceName=%s image=%s, solid=%s facecnt=%d" % \ - (faceName, ifs[0], ifs[1], len(ifs)-2) - #endif - #endif - - return len(imageMap.keys()) - #enddef - - def faceToString(self,face): - print "Debug: face.flag=0x%x (bitflags)" % face.flag - if face.flag & NMesh.FaceFlags.SELECT == NMesh.FaceFlags.SELECT: - print "Debug: face.flag.SELECT=true" - #endif - - print "Debug: face.mode=0x%x (bitflags)" % face.mode - if (face.mode & NMesh.FaceModes.TWOSIDE) == NMesh.FaceModes.TWOSIDE: - print "Debug: face.mode twosided" - #endif - - print "Debug: face.transp=0x%x (enum)" % face.transp - if face.transp == NMesh.FaceTranspModes.SOLID: - print "Debug: face.transp.SOLID" - # - - if face.image: - print "Debug: face.image=%s" % face.image.name - #endif - print "Debug: face.materialIndex=%d" % face.materialIndex - #enddef - - def getVertexColorByIndx(self, mesh, indx): - for face in mesh.faces: - j=0 - for vertex in face.v: - if vertex.index == indx: - c=face.col[j] - #endif - j=j+1 - #endfor - #endfor - return c - #enddef - - def meshToString(self,mesh): - print "Debug: mesh.hasVertexUV=%d" % mesh.hasVertexUV() - print "Debug: mesh.hasFaceUV=%d" % mesh.hasFaceUV() - print "Debug: mesh.hasVertexColours=%d" % mesh.hasVertexColours() - print "Debug: mesh.verts=%d" % len(mesh.verts) - print "Debug: mesh.faces=%d" % len(mesh.faces) - print "Debug: mesh.materials=%d" % len(mesh.materials) - #enddef - - def rgbToFS(self, c): - s="%s %s %s" % ( - round(c.r/255.0,self.cp), - round(c.g/255.0,self.cp), - round(c.b/255.0,self.cp)) - return s - #enddef - - def computeDirection(self, object): - x,y,z=(0,-1.0,0) # point down - ax,ay,az = (object.RotX,object.RotZ,object.RotY) - - # rot X - x1=x - y1=y*math.cos(ax)-z*math.sin(ax) - z1=y*math.sin(ax)+z*math.cos(ax) - - # rot Y - x2=x1*math.cos(ay)+z1*math.sin(ay) - y2=y1 - z2=z1*math.cos(ay)-x1*math.sin(ay) - - # rot Z - x3=x2*math.cos(az)-y2*math.sin(az) - y3=x2*math.sin(az)+y2*math.cos(az) - z3=z2 - - return [x3,y3,z3] - #enddef - - - # swap Y and Z to handle axis difference between Blender and VRML - #------------------------------------------------------------------------ - def rotatePointForVRML(self, v): - x = v[0] - y = v[2] - z = -v[1] - - vrmlPoint=[x, y, z] - return vrmlPoint - #enddef - - def rotVertex(self, mm, v): - lx,ly,lz=v[0],v[1],v[2] - gx=(mm[0][0]*lx + mm[1][0]*ly + mm[2][0]*lz) + mm[3][0] - gy=((mm[0][2]*lx + mm[1][2]*ly+ mm[2][2]*lz) + mm[3][2]) - gz=-((mm[0][1]*lx + mm[1][1]*ly + mm[2][1]*lz) + mm[3][1]) - rotatedv=[gx,gy,gz] - return rotatedv - #enddef - - def writeIndented(self, s, inc=0): - if inc < 1: - self.indentLevel = self.indentLevel + inc - #endif - - spaces="" - for x in xrange(self.indentLevel): - spaces = spaces + " " - #endfor - self.file.write(spaces + s) - - if inc > 0: - self.indentLevel = self.indentLevel + inc - #endif - #enddef - - # Converts a Euler to three new Quaternions - # Angles of Euler are passed in as radians - #------------------------------------------------------------------------ - def eulerToQuaternions(self, x, y, z): - Qx = [math.cos(x/2), math.sin(x/2), 0, 0] - Qy = [math.cos(y/2), 0, math.sin(y/2), 0] - Qz = [math.cos(z/2), 0, 0, math.sin(z/2)] - - quaternionVec=[Qx,Qy,Qz] - return quaternionVec - #enddef - - # Multiply two Quaternions together to get a new Quaternion - #------------------------------------------------------------------------ - def multiplyQuaternions(self, Q1, Q2): - result = [((Q1[0] * Q2[0]) - (Q1[1] * Q2[1]) - (Q1[2] * Q2[2]) - (Q1[3] * Q2[3])), - ((Q1[0] * Q2[1]) + (Q1[1] * Q2[0]) + (Q1[2] * Q2[3]) - (Q1[3] * Q2[2])), - ((Q1[0] * Q2[2]) + (Q1[2] * Q2[0]) + (Q1[3] * Q2[1]) - (Q1[1] * Q2[3])), - ((Q1[0] * Q2[3]) + (Q1[3] * Q2[0]) + (Q1[1] * Q2[2]) - (Q1[2] * Q2[1]))] - - return result - #enddef - - # Convert a Quaternion to an Angle Axis (ax, ay, az, angle) - # angle is in radians - #------------------------------------------------------------------------ - def quaternionToAngleAxis(self, Qf): - scale = math.pow(Qf[1],2) + math.pow(Qf[2],2) + math.pow(Qf[3],2) - ax = Qf[1] - ay = Qf[2] - az = Qf[3] - - if scale > .0001: - ax/=scale - ay/=scale - az/=scale - #endif - - angle = 2 * math.acos(Qf[0]) - - result = [ax, ay, az, angle] - return result - #endef - -def file_callback(filename): - if sys.exists(filename): - result = Draw.PupMenu("File Already Exists, Overwrite?%t|Yes%x1|No%x0") - if result != 1: - return - - if not filename.endswith(extension): - filename += extension - - wrlexport=VRML2Export(filename) - scene = Blender.Scene.getCurrent() - wrlexport.export(scene) -#enddef - -#------------------------------------------------------------------------ -# main routine -#------------------------------------------------------------------------ -try: - ARG = __script__['arg'] # user selected argument -except: - print "older version" - -if Blender.Get('version') < 242: - print "Warning: VRML2 export failed, wrong blender version!" - print " You aren't running blender version 2.42a or greater" - print " download a newer version from http://blender3d.com/" -else: - if ARG == 'comp' or ARG == 'compselected': - extension=".wrz" - from gzip import * - else: - extension=".wrl" - #endif - Blender.Window.FileSelector(file_callback,"Save VRML 2.0", \ - sys.makename(ext=extension)) - m = Mathutils.Matrix() - print m - e = m.toEuler() - e.x = e.x-90.0 - m = e.toMatrix() - print e - print m -#endif diff --git a/external/etk b/external/etk index 3c27f446..35b678fb 160000 --- a/external/etk +++ b/external/etk @@ -1 +1 @@ -Subproject commit 3c27f446f4f33bede07292ab3512c4ab4c531f9e +Subproject commit 35b678fb65f9d6a86fcf0b8a4ea8f6c51417df4d diff --git a/sources/ewol/renderer/Material.cpp b/sources/ewol/renderer/Material.cpp index 1a0841d3..967ac046 100644 --- a/sources/ewol/renderer/Material.cpp +++ b/sources/ewol/renderer/Material.cpp @@ -6,44 +6,77 @@ * @license BSD v3 (see license file) */ +#include #include #include +ewol::MaterialGlId::MaterialGlId(void) : + m_GL_ambientFactor(0), + m_GL_diffuseFactor(0), + m_GL_specularFactor(0), + m_GL_shininess(0), + m_GL_texture0(0) +{ + // nothing to do else ... +} + + +void ewol::MaterialGlId::Link(ewol::Program* _prog, const etk::UString& _baseName) +{ + if (NULL == _prog) { + return; + } + m_GL_ambientFactor = _prog->GetUniform(_baseName+".ambientFactor"); + m_GL_diffuseFactor = _prog->GetUniform(_baseName+".diffuseFactor"); + m_GL_specularFactor = _prog->GetUniform(_baseName+".specularFactor"); + m_GL_shininess = _prog->GetUniform(_baseName+".shininess"); + m_GL_texture0 = _prog->GetUniform("EW_texID"); +} + ewol::Material::Material(void) : m_ambientFactor(0,0,0,0), m_diffuseFactor(0,0,0,0), m_specularFactor(0,0,0,0), m_shininess(0), - m_GL_ambientFactor(0), - m_GL_diffuseFactor(0), - m_GL_specularFactor(0), - m_GL_shininess(0) + m_texture0(NULL) { // nothing to do else ... } - ewol::Material::~Material(void) { - + if(NULL!=m_texture0) { + ewol::resource::Release(m_texture0); + } } -void ewol::Material::Link(ewol::Program* prog, const etk::UString& baseName) +void ewol::Material::Draw(ewol::Program* _prog, const MaterialGlId& _glID) { - if (NULL == prog) { + _prog->Uniform4(_glID.m_GL_ambientFactor, m_ambientFactor); + _prog->Uniform4(_glID.m_GL_diffuseFactor, m_diffuseFactor); + _prog->Uniform4(_glID.m_GL_specularFactor, m_specularFactor); + _prog->Uniform1f(_glID.m_GL_shininess, m_shininess); + if (NULL != m_texture0) { + _prog->SetTexture0(_glID.m_GL_texture0, m_texture0->GetId()); + } +} + +void ewol::Material::SetTexture0(const etk::UString& _filename) +{ + ivec2 tmpSize(256, 256); + // prevent overloard error : + ewol::TextureFile* tmpCopy = m_texture0; + m_texture0 = NULL; + if (false == ewol::resource::Keep(_filename, m_texture0, tmpSize)) { + EWOL_ERROR("Can not load specific texture : " << _filename); + // retreave previous texture: + m_texture0 = tmpCopy; return; } - m_GL_ambientFactor = prog->GetUniform(baseName+".ambientFactor"); - m_GL_diffuseFactor = prog->GetUniform(baseName+".diffuseFactor"); - m_GL_specularFactor = prog->GetUniform(baseName+".specularFactor"); - m_GL_shininess = prog->GetUniform(baseName+".shininess"); -} - -void ewol::Material::Draw(ewol::Program* prog) -{ - prog->Uniform4(m_GL_ambientFactor, m_ambientFactor); - prog->Uniform4(m_GL_diffuseFactor, m_diffuseFactor); - prog->Uniform4(m_GL_specularFactor, m_specularFactor); - prog->Uniform1f(m_GL_shininess, m_shininess); + if (NULL != tmpCopy) { + // really release previous texture. In case of same texture loading, then we did not have reload it .. just increase and decrease index... + ewol::resource::Release(tmpCopy); + } } + diff --git a/sources/ewol/renderer/Material.h b/sources/ewol/renderer/Material.h index da36dca8..609dec49 100644 --- a/sources/ewol/renderer/Material.h +++ b/sources/ewol/renderer/Material.h @@ -13,41 +13,50 @@ #include #include #include +#include namespace ewol { - class Material + class MaterialGlId { - private: - // values - vec4 m_ambientFactor; - vec4 m_diffuseFactor; - vec4 m_specularFactor; - float m_shininess; - private: + public: // GL index int32_t m_GL_ambientFactor; int32_t m_GL_diffuseFactor; int32_t m_GL_specularFactor; int32_t m_GL_shininess; + int32_t m_GL_texture0; + MaterialGlId(void); + void Link(ewol::Program* _prog, const etk::UString& _baseName); + }; + class Material + { + private: + // values + vec4 m_ambientFactor; + vec4 m_diffuseFactor; + vec4 m_specularFactor; + float m_shininess; + ewol::TextureFile* m_texture0; public: Material(void); ~Material(void); - void Link(ewol::Program* prog, const etk::UString& baseName); - void Draw(ewol::Program* prog); - void SetAmbientFactor(const vec4& val) { - m_ambientFactor = val; + void Draw(ewol::Program* _prog, const MaterialGlId& _glID); + void SetAmbientFactor(const vec4& _val) { + m_ambientFactor = _val; } - void SetDiffuseFactor(const vec4& val) { - m_diffuseFactor = val; + void SetDiffuseFactor(const vec4& _val) { + m_diffuseFactor = _val; } - void SetSpecularFactor(const vec4& val) { - m_specularFactor = val; + void SetSpecularFactor(const vec4& _val) { + m_specularFactor = _val; } - void SetShininess(float val) { - m_shininess = val; + void SetShininess(float _val) { + m_shininess = _val; } + void SetTexture0(const etk::UString& _filename); }; + }; diff --git a/sources/ewol/renderer/ResourceManager.cpp b/sources/ewol/renderer/ResourceManager.cpp index f091c725..57cbc95b 100644 --- a/sources/ewol/renderer/ResourceManager.cpp +++ b/sources/ewol/renderer/ResourceManager.cpp @@ -348,47 +348,32 @@ bool ewol::resource::Keep(const etk::UString& _filename, ewol::TextureFile*& _ob return true; } -bool ewol::resource::Keep(const etk::UString& filename, ewol::MeshObj*& object) + +bool ewol::resource::Keep(const etk::UString& _meshName, ewol::Mesh*& _object) { - object = static_cast(LocalKeep(filename)); - if (NULL != object) { + _object = static_cast(LocalKeep(_meshName)); + if (NULL != _object) { return true; } - object = new ewol::MeshObj(filename); - if (NULL == object) { - EWOL_ERROR("allocation error of a resource : ??Mesh.obj??" << filename); + _object = new ewol::Mesh(_meshName); + if (NULL == _object) { + EWOL_ERROR("allocation error of a resource : ??Mesh??" << _meshName); return false; } - LocalAdd(object); + LocalAdd(_object); return true; } -bool ewol::resource::Keep(const etk::UString& meshName, ewol::Mesh*& object) -{ - object = static_cast(LocalKeep(meshName)); - if (NULL != object) { - return true; - } - object = new ewol::Mesh(meshName); - if (NULL == object) { - EWOL_ERROR("allocation error of a resource : ??Mesh??" << meshName); - return false; - } - LocalAdd(object); - return true; -} - - -bool ewol::resource::Keep(const etk::UString& accesMode, ewol::VirtualBufferObject*& object) +bool ewol::resource::Keep(const etk::UString& _accesMode, ewol::VirtualBufferObject*& _object) { // this element create a new one every time .... - object = new ewol::VirtualBufferObject(accesMode); - if (NULL == object) { + _object = new ewol::VirtualBufferObject(_accesMode); + if (NULL == _object) { EWOL_ERROR("allocation error of a resource : ??VBO??"); return false; } - LocalAdd(object); + LocalAdd(_object); return true; } @@ -483,13 +468,6 @@ void ewol::resource::Release(ewol::TextureFile*& object) object = NULL; } -void ewol::resource::Release(ewol::MeshObj*& object) -{ - ewol::Resource* object2 = static_cast(object); - Release(object2); - object = NULL; -} - void ewol::resource::Release(ewol::Mesh*& object) { ewol::Resource* object2 = static_cast(object); diff --git a/sources/ewol/renderer/ResourceManager.h b/sources/ewol/renderer/ResourceManager.h index eaeee0e2..a6916a5e 100644 --- a/sources/ewol/renderer/ResourceManager.h +++ b/sources/ewol/renderer/ResourceManager.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include namespace ewol @@ -77,7 +77,6 @@ namespace ewol bool Keep(ewol::Texture*& object); // no name needed here ... bool Keep(const etk::UString& filename, ewol::TextureFile*& object, ivec2 size=ivec2(-1,-1)); bool Keep(const etk::UString& accesMode, ewol::VirtualBufferObject*& object); - bool Keep(const etk::UString& filename, ewol::MeshObj*& object); bool Keep(const etk::UString& meshName, ewol::Mesh*& object); bool Keep(const etk::UString& filename, ewol::ConfigFile*& object); bool Keep(ewol::Colored3DObject*& object); @@ -94,7 +93,6 @@ namespace ewol void Release(ewol::Texture*& object); void Release(ewol::TextureFile*& object); void Release(ewol::VirtualBufferObject*& object); - void Release(ewol::MeshObj*& object); void Release(ewol::Mesh*& object); void Release(ewol::ConfigFile*& object); void Release(ewol::Colored3DObject*& object); diff --git a/sources/ewol/renderer/resources/Mesh.cpp b/sources/ewol/renderer/resources/Mesh.cpp index 863af4bf..415061b6 100644 --- a/sources/ewol/renderer/resources/Mesh.cpp +++ b/sources/ewol/renderer/resources/Mesh.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #undef __class__ #define __class__ "Mesh" @@ -61,21 +62,21 @@ class VertexNode { -ewol::Mesh::Mesh(etk::UString genName, etk::UString shaderName) : - ewol::Resource(genName), +ewol::Mesh::Mesh(const etk::UString& _fileName, const etk::UString& _shaderName) : + ewol::Resource(_fileName), m_enableFaceNormal(true), m_enableVertexNormal(true), - m_numberOfElments(0), - m_texture0(NULL) + m_numberOfElments(0) { + EWOL_DEBUG("Load a new mesh : '" << _fileName << "'"); // get the shader resource : m_GLPosition = 0; // set the element material properties : - m_material.SetAmbientFactor(vec4(0.100000,0.100000,0.100000, 1.0)); - m_material.SetDiffuseFactor(vec4(0.640000, 0.640000, 0.640000, 1.0)); - m_material.SetSpecularFactor(vec4(0.500000, 0.500000, 0.500000, 1.0)); - m_material.SetShininess(0.96078431); + //m_material.SetAmbientFactor(vec4(0.100000,0.100000,0.100000, 1.0)); + //m_material.SetDiffuseFactor(vec4(0.640000, 0.640000, 0.640000, 1.0)); + //m_material.SetSpecularFactor(vec4(0.500000, 0.500000, 0.500000, 1.0)); + //m_material.SetShininess(0.96078431); m_light.SetDirection(vec3(0,cos(M_PI/4),sin(M_PI/4))); m_light.SetHalfPlane(vec3(1,0,0)); @@ -83,28 +84,42 @@ ewol::Mesh::Mesh(etk::UString genName, etk::UString shaderName) : m_light.SetDiffuseColor(vec4(1.0,1.0,1.0,1)); m_light.SetSpecularColor(vec4(0.0,0.0,0.0,1)); - if (true == ewol::resource::Keep(shaderName, m_GLprogram) ) { + if (true == ewol::resource::Keep(_shaderName, m_GLprogram) ) { m_GLPosition = m_GLprogram->GetAttribute("EW_coord3d"); - m_GLtexture = m_GLprogram->GetAttribute("EW_texture2d"); - m_GLNormal = m_GLprogram->GetAttribute("EW_normal"); + m_GLtexture = m_GLprogram->GetAttribute("EW_texture2d"); + m_GLNormal = m_GLprogram->GetAttribute("EW_normal"); m_GLNormalFace = m_GLprogram->GetAttribute("EW_faceNormal"); - m_GLMatrix = m_GLprogram->GetUniform("EW_MatrixTransformation"); + m_GLMatrix = m_GLprogram->GetUniform("EW_MatrixTransformation"); m_GLMatrixPosition = m_GLprogram->GetUniform("EW_MatrixPosition"); - m_GLtexID0 = m_GLprogram->GetUniform("EW_texID"); // Link material and Lights - m_material.Link(m_GLprogram, "EW_material"); + m_GLMaterial.Link(m_GLprogram, "EW_material"); m_light.Link(m_GLprogram, "EW_directionalLight"); } // this is the properties of the buffer requested : "r"/"w" + "-" + buffer type "f"=flaot "i"=integer ewol::resource::Keep("w-fff", m_verticesVBO); + + // load the curent file : + etk::UString tmpName = _fileName.ToLower(); + // select the corect Loader : + if (true == tmpName.EndWith(".obj") ) { + if (false == LoadOBJ(_fileName)) { + EWOL_ERROR("Error To load OBJ file " << tmpName ); + return; + } + } else if (true == tmpName.EndWith(".emf") ) { + if (false == LoadEMF(_fileName)) { + EWOL_ERROR("Error To load EMF file " << tmpName ); + return; + } + //EWOL_CRITICAL("Load a new mesh : '" << _fileName << "' (end)"); + } else { + // nothing to do ==> reqiest an enmpty mesh ==> user manage it ... + } } ewol::Mesh::~Mesh(void) { // remove dynamics dependencies : - if(NULL!=m_texture0) { - ewol::resource::Release(m_texture0); - } ewol::resource::Release(m_GLprogram); ewol::resource::Release(m_verticesVBO); m_numberOfElments=0; @@ -113,6 +128,7 @@ ewol::Mesh::~Mesh(void) void ewol::Mesh::Draw(mat4& positionMatrix) { + EWOL_DEBUG("Request Draw : " << m_listIndexFaces.Size() << " elements"); #ifndef USE_INDEXED_MESH if (m_numberOfElments<=0) { return; @@ -122,10 +138,6 @@ void ewol::Mesh::Draw(mat4& positionMatrix) return; } #endif - if (NULL == m_texture0) { - EWOL_WARNING("Texture does not exist ..."); - return; - } if (m_GLprogram==NULL) { EWOL_ERROR("No shader ..."); return; @@ -139,8 +151,6 @@ void ewol::Mesh::Draw(mat4& positionMatrix) mat4 tmpMatrix = projMatrix * camMatrix; m_GLprogram->UniformMatrix4fv(m_GLMatrix, 1, tmpMatrix.m_mat); m_GLprogram->UniformMatrix4fv(m_GLMatrixPosition, 1, positionMatrix.m_mat); - // TextureID - m_GLprogram->SetTexture0(m_GLtexID0, m_texture0->GetId()); // position : m_GLprogram->SendAttributePointer(m_GLPosition, 3/*x,y,z*/, m_verticesVBO, MESH_VBO_VERTICES); // Texture : @@ -152,7 +162,7 @@ void ewol::Mesh::Draw(mat4& positionMatrix) m_GLprogram->SendAttributePointer(m_GLNormalFace, 3/*x,y,z*/, m_verticesVBO, MESH_VBO_FACE_NORMAL); #endif // draw materials : - m_material.Draw(m_GLprogram); + m_materials.GetValue(0)->Draw(m_GLprogram, m_GLMaterial); m_light.Draw(m_GLprogram); #ifndef USE_INDEXED_MESH @@ -160,6 +170,7 @@ void ewol::Mesh::Draw(mat4& positionMatrix) ewol::openGL::DrawArrays(GL_TRIANGLES, 0, m_numberOfElments); #else ewol::openGL::DrawElements(GL_TRIANGLES, m_listIndexFaces); + EWOL_DEBUG("Draw : " << m_listIndexFaces.Size() << " elements"); #endif m_GLprogram->UnUse(); ewol::openGL::Disable(ewol::openGL::FLAG_DEPTH_TEST); @@ -168,6 +179,7 @@ void ewol::Mesh::Draw(mat4& positionMatrix) } void ewol::Mesh::Draw2(mat4& positionMatrix) { + EWOL_DEBUG("Request Draw2 : " << m_listIndexFaces.Size() << " elements"); #ifndef USE_INDEXED_MESH if (m_numberOfElments<=0) { return; @@ -177,10 +189,6 @@ void ewol::Mesh::Draw2(mat4& positionMatrix) return; } #endif - if (NULL == m_texture0) { - EWOL_WARNING("Texture does not exist ..."); - return; - } if (m_GLprogram==NULL) { EWOL_ERROR("No shader ..."); return; @@ -193,8 +201,6 @@ void ewol::Mesh::Draw2(mat4& positionMatrix) mat4 tmpMatrix = projMatrix; m_GLprogram->UniformMatrix4fv(m_GLMatrix, 1, tmpMatrix.m_mat); m_GLprogram->UniformMatrix4fv(m_GLMatrixPosition, 1, positionMatrix.m_mat); - // TextureID - m_GLprogram->SetTexture0(m_GLtexID0, m_texture0->GetId()); // position : m_GLprogram->SendAttributePointer(m_GLPosition, 3/*x,y,z*/, m_verticesVBO, MESH_VBO_VERTICES); // Texture : @@ -205,10 +211,10 @@ void ewol::Mesh::Draw2(mat4& positionMatrix) #ifndef USE_INDEXED_MESH m_GLprogram->SendAttributePointer(m_GLNormalFace, 3/*x,y,z*/, m_verticesVBO, MESH_VBO_FACE_NORMAL); #endif - // draw materials : - m_material.Draw(m_GLprogram); m_light.Draw(m_GLprogram); + // draw materials : + m_materials.GetValue(0)->Draw(m_GLprogram, m_GLMaterial); #ifndef USE_INDEXED_MESH // Request the draw od the elements : ewol::openGL::DrawArrays(GL_TRIANGLES, 0, m_numberOfElments); @@ -221,6 +227,7 @@ void ewol::Mesh::Draw2(mat4& positionMatrix) glBindBuffer(GL_ARRAY_BUFFER,0); } + // normal calculation of the normal face is really easy : void ewol::Mesh::CalculateNormaleFace(void) { @@ -229,10 +236,11 @@ void ewol::Mesh::CalculateNormaleFace(void) if( true==m_enableFaceNormal || true==m_enableVertexNormal) { - for(int32_t iii=0 ; iii& tmpFaceList = m_listFaces.GetValue(0); + for(int32_t iii=0 ; iii& tmpFaceList = m_listFaces.GetValue(0); vec3 normal(0,0,0); // add the vertex from all the element in the list for face when the element in the face ... - for(int32_t jjj=0 ; jjj& tmpFaceList = m_listFaces.GetValue(0); + for (int32_t iii=0; iiiSizeOnBufferVec3(MESH_VBO_VERTICES); jjj++) { if( m_verticesVBO->GetOnBufferVec3(MESH_VBO_VERTICES,jjj) == position && m_verticesVBO->GetOnBufferVec3(MESH_VBO_VERTICES_NORMAL,jjj) == normal && m_verticesVBO->GetOnBufferVec2(MESH_VBO_TEXTURE,jjj) == texturepos) { - m_listFaces[iii].m_vertexVBOId[indice] = jjj; + tmpFaceList[iii].m_vertexVBOId[indice] = jjj; elementFind = true; // stop searching ... break; @@ -301,25 +311,25 @@ void ewol::Mesh::GenerateVBO(void) m_verticesVBO->PushOnBuffer(MESH_VBO_VERTICES, position); m_verticesVBO->PushOnBuffer(MESH_VBO_VERTICES_NORMAL, normal); m_verticesVBO->PushOnBuffer(MESH_VBO_TEXTURE, texturepos); - m_listFaces[iii].m_vertexVBOId[indice] = m_verticesVBO->SizeOnBufferVec3(MESH_VBO_VERTICES)-1; + tmpFaceList[iii].m_vertexVBOId[indice] = m_verticesVBO->SizeOnBufferVec3(MESH_VBO_VERTICES)-1; } } } - for (int32_t iii=0; iii& list) { +#if 0 for (int32_t iii=0; iiiGetPos() == point) { return iii; @@ -576,10 +574,14 @@ int32_t CreateOrGetNewPointId(vertex_te type, const vec3& point, etk::Vector& list) { +#if 0 for (int32_t iii=0; iii& list) } list.PushBack(point); return list.Size()-1; +#else + return 0; +#endif } void ewol::Mesh::InternalSubdivide(bool smooth) { +#if 0 //Copy the mesh for modify this one and not his parrent (that one is needed for smoothing) etk::Vector listVertex; for(int32_t iii=0; iii we recalculated it if needed (some .obj does not export normal, then it is simple like this ... + // TODO : Use the normal provided ... => can be smooth or not ... (cf check "s 1") + } else if (inputDataLine[1]=='t') { + // Texture position : vt 0.748573 0.750412 + vec2 vertex(0,0); + sscanf(&inputDataLine[3], "%f %f", &vertex.m_floats[0], &vertex.m_floats[1]); + m_listUV.PushBack(vertex); + } else { + // Vertice position : v 1.000000 -1.000000 -1.000000 + vec3 vertex(0,0,0); + sscanf(&inputDataLine[2], "%f %f %f", &vertex.m_floats[0], &vertex.m_floats[1], &vertex.m_floats[2] ); + m_listVertex.PushBack(vertex); + } + } else if (inputDataLine[0]=='f') { + // face : f 5/1/1 1/2/1 4/3/1* + uint32_t vertexIndex[4], uvIndex[4], normalIndex[4]; + bool quadMode = true; + int32_t matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n", + &vertexIndex[0], &uvIndex[0], &normalIndex[0], + &vertexIndex[1], &uvIndex[1], &normalIndex[1], + &vertexIndex[2], &uvIndex[2], &normalIndex[2], + &vertexIndex[3], &uvIndex[3], &normalIndex[3] ); + if (12 != matches){ + // no normal mode : + matches = sscanf(&inputDataLine[2], "%d/%d %d/%d %d/%d %d/%d\n", + &vertexIndex[0], &uvIndex[0], + &vertexIndex[1], &uvIndex[1], + &vertexIndex[2], &uvIndex[2], + &vertexIndex[3], &uvIndex[3] ); + if (8 != matches){ + quadMode = false; + matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d\n", + &vertexIndex[0], &uvIndex[0], &normalIndex[0], + &vertexIndex[1], &uvIndex[1], &normalIndex[1], + &vertexIndex[2], &uvIndex[2], &normalIndex[2] ); + if (9 != matches){ + // no normal mode : + matches = sscanf(&inputDataLine[2], "%d/%d %d/%d %d/%d\n", + &vertexIndex[0], &uvIndex[0], + &vertexIndex[1], &uvIndex[1], + &vertexIndex[2], &uvIndex[2] ); + if (6 != matches){ + EWOL_ERROR("Parsing error in the .obj files : " << fileName << " (l=" << lineID << ") in 'f' section : \"" << &inputDataLine[2] << "\" expected : %d/%d(/%d) %d/%d(/%d) %d/%d(/%d) (%d/%d(/%d)) () for option"); + continue; + } + } + } + } + if (true==quadMode) { + m_listFaces.PushBack(Face(vertexIndex[0]-1, uvIndex[0]-1, + vertexIndex[1]-1, uvIndex[1]-1, + vertexIndex[2]-1, uvIndex[2]-1, + vertexIndex[3]-1, uvIndex[3]-1)); + } else { + m_listFaces.PushBack(Face(vertexIndex[0]-1, uvIndex[0]-1, + vertexIndex[1]-1, uvIndex[1]-1, + vertexIndex[2]-1, uvIndex[2]-1)); + } + /* + EWOL_DEBUG(" plop : " << tmpFace.m_nbElement << " ? " << m_listFaces[m_listFaces.Size()-1].m_nbElement); + EWOL_DEBUG(" : " << tmpFace.m_vertex[0] << " ? " << m_listFaces[m_listFaces.Size()-1].m_vertex[0]); + EWOL_DEBUG(" : " << tmpFace.m_uv[0] << " ? " << m_listFaces[m_listFaces.Size()-1].m_uv[0]); + */ + } else if (inputDataLine[0]=='s') { + // ??? : s off + } else if (inputDataLine[0]=='#') { + // comment + // nothing to do ... just go to the new line ... + } else if( inputDataLine[0]=='u' + && inputDataLine[1]=='s' + && inputDataLine[2]=='e' + && inputDataLine[3]=='m' + && inputDataLine[4]=='t' + && inputDataLine[5]=='l' ) { + // Use Material : usemtl imageName.xxx + while( inputDataLine[strlen(inputDataLine)-1] == '\n' + || inputDataLine[strlen(inputDataLine)-1] == '\r' + || inputDataLine[strlen(inputDataLine)-1] == ' ') { + if (1 == strlen(inputDataLine) ){ + break; + } + inputDataLine[strlen(inputDataLine)-1] = '\0'; + } + etk::UString tmpVal(&inputDataLine[7]); + SetTexture(fileName.GetRelativeFolder() + tmpVal); + } else if( inputDataLine[0]=='m' + && inputDataLine[1]=='t' + && inputDataLine[2]=='l' + && inputDataLine[3]=='l' + && inputDataLine[4]=='i' + && inputDataLine[5]=='b' ) { + // ???? : mtllib cube.mtl + } + } + fileName.FileClose(); + GenerateVBO(); +#endif + return true; +} + + +char* LoadNextData(char* _elementLine, int64_t _maxData, etk::FSNode& _file, bool _removeTabs=false, bool _stopColomn=false) +{ + memset(_elementLine, 0, _maxData); + char * element = _elementLine; + int64_t outSize = 0; + /* + if (m_zipReadingOffset>=m_zipContent->Size()) { + element[0] = '\0'; + return NULL; + } + */ + char current = _file.FileGet(); + while (current != '\0') { + if( _removeTabs==false + || element != _elementLine) { + *element = current; + element++; + } + if( current == '\n' + || current == '\r' + || current == '|' + || ( current == ':' + && _stopColomn==true) ) + { + *element = '\0'; + //EWOL_DEBUG(" plop : '" << _elementLine << "'" ); + return _elementLine; + } else if( element == _elementLine + && current != '\t') { + *element = current; + element++; + } + // check maxData Size ... + if (outSize>=_maxData-1) { + *element = '\0'; + return _elementLine; + } + current = _file.FileGet(); + } + if (outSize==0) { + return NULL; + } else { + // send last line + return _elementLine; + } + return NULL; +} + +bool ewol::Mesh::LoadEMF(const etk::UString& _fileName) +{ + etk::FSNode fileName(_fileName); + // Get the fileSize ... + int32_t size = fileName.FileSize(); + if (size == 0 ) { + EWOL_ERROR("No data in the file named=\"" << fileName << "\""); + return false; + } + if(false == fileName.FileOpenRead() ) { + EWOL_ERROR("Can not find the file name=\"" << fileName << "\""); + return false; + } + char inputDataLine[2048]; + // load the first line : + fileName.FileGets(inputDataLine, 2048); + if(0==strncmp(inputDataLine, "EMF(STRING)", 11)) { + // parse in string mode ... + } else if (0==strncmp(inputDataLine, "EMF(BINARY)", 11)) { + EWOL_ERROR(" file binary mode is not supported now : 'EMF(BINARY)'"); + return false; + } else { + EWOL_ERROR(" file mode is not supported now : 'EMF(? ? ?)' = '" << inputDataLine << "'"); + return false; + } + while (NULL != LoadNextData(inputDataLine, 2048, fileName) ) { + //EWOL_DEBUG("min line : '" << inputDataLine << "'"); + if( inputDataLine[0]=='#' + || inputDataLine[0]=='\0' ) { + // comment line ... or empty line + continue; + } + if( inputDataLine[0]=='\t' + || 0 == strncmp(inputDataLine, " ", 4) ) { + // Sub section that is not parsed ... + continue; + } + if( 0 == strncmp(inputDataLine, "Mesh :", 6) ) { + //Find a mesh ==> parse it ... + while (NULL != LoadNextData(inputDataLine, 2048, fileName) ) { + if( inputDataLine[0]=='#' + || inputDataLine[0]=='\0' ) { + // comment line ... or empty line + continue; + } + if( 0 == strncmp(inputDataLine, "\tName : ", 8) ) { + // find the mesh name. + etk::UString m_meshName = &inputDataLine[8]; + EWOL_DEBUG("Load sub mesh named : '" << m_meshName << "'"); + continue; + } + if( 0 == strncmp(inputDataLine, "\tVertex : ", 10) ) { + // find the vertex list of elements. + while (NULL != LoadNextData(inputDataLine, 2048, fileName, true) ) { + if (inputDataLine[0] == '\0') { + break; + } + vec3 vertex(0,0,0); + sscanf(inputDataLine, "%f %f %f", &vertex.m_floats[0], &vertex.m_floats[1], &vertex.m_floats[2] ); + m_listVertex.PushBack(vertex); + } + EWOL_DEBUG("Load " << m_listVertex.Size() << " vertex"); + continue; + } + if( 0 == strncmp(inputDataLine, "\tUV-mapping :", 13) ) { + // find the UV mapping. + while (NULL != LoadNextData(inputDataLine, 2048, fileName, true) ) { + if (inputDataLine[0] == '\0') { + break; + } + vec2 uvMap(0,0); + sscanf(inputDataLine, "%f %f", &uvMap.m_floats[0], &uvMap.m_floats[1]); + m_listUV.PushBack(uvMap); + } + EWOL_DEBUG("Load " << m_listUV.Size() << " uv mapping point"); + continue; + } + if( 0 == strncmp(inputDataLine, "\tNormal(vertex) : ", 18) ) { + // find the vertex Normal list. + while (NULL != LoadNextData(inputDataLine, 2048, fileName, true) ) { + if (inputDataLine[0] == '\0') { + break; + } + vec3 normal(0,0,0); + sscanf(inputDataLine, "%f %f %f", &normal.m_floats[0], &normal.m_floats[1], &normal.m_floats[2] ); + m_listVertexNormal.PushBack(normal); + } + EWOL_DEBUG("Load " << m_listVertexNormal.Size() << " vertex normal"); + continue; + } + if( 0 == strncmp(inputDataLine, "\tNormal(face) : ", 16) ) { + // find the face Normal list. + while (NULL != LoadNextData(inputDataLine, 2048, fileName, true) ) { + if (inputDataLine[0] == '\0') { + break; + } + vec3 normal(0,0,0); + sscanf(inputDataLine, "%f %f %f", &normal.m_floats[0], &normal.m_floats[1], &normal.m_floats[2] ); + m_listFacesNormal.PushBack(normal); + } + EWOL_DEBUG("Load " << m_listFacesNormal.Size() << " face normal"); + continue; + } + if( 0 == strncmp(inputDataLine, "\tFace : ", 8) ) { + // find the face list. + int32_t elementID = -1; + while (NULL != LoadNextData(inputDataLine, 2048, fileName, true, true) ) { + if (inputDataLine[0] == '\0') { + break; + } + //EWOL_DEBUG("parse :'" << inputDataLine << "'"); + int32_t len = strlen(inputDataLine); + if (inputDataLine[len-1] == ':') { + // find the material : + inputDataLine[len-1] = '\0'; + etk::UString materialName = inputDataLine; + etk::Vector empty; + m_listFaces.Add(materialName, empty); + elementID = m_listFaces.GetId(materialName); + } else { + if (elementID < 0) { + continue; + } + int32_t matches; + uint32_t vertexIndex[3], uvIndex[3], normalIndex[3]; + vertexIndex[0] = 0; + vertexIndex[1] = 0; + vertexIndex[2] = 0; + uvIndex[0] = 0; + uvIndex[1] = 0; + uvIndex[2] = 0; + normalIndex[0] = 0; + normalIndex[1] = 0; + normalIndex[2] = 0; + matches = sscanf(inputDataLine, "%d/%d/%d %d/%d/%d %d/%d/%d", + &vertexIndex[0], &uvIndex[0], &normalIndex[0], + &vertexIndex[1], &uvIndex[1], &normalIndex[1], + &vertexIndex[2], &uvIndex[2], &normalIndex[2] ); + m_listFaces.GetValue(elementID).PushBack(Face(vertexIndex[0], uvIndex[0], + vertexIndex[1], uvIndex[1], + vertexIndex[2], uvIndex[2])); + /* + EWOL_DEBUG("face :" << vertexIndex[0] << "/" << uvIndex[0] << "/" << normalIndex[0] << + " " << vertexIndex[1] << "/" << uvIndex[1] << "/" << normalIndex[1] << + " " << vertexIndex[2] << "/" << uvIndex[2] << "/" << normalIndex[2]); + */ + } + } + EWOL_DEBUG("Load " << m_listFaces.Size() << " faces (mode) :"); + for (esize_t iii=0; iii< m_listFaces.Size(); iii++) { + EWOL_DEBUG(" mat='" << m_listFaces.GetKey(iii) << "' nb faces=" << m_listFaces.GetValue(iii).Size()); + } + break; + } + } + continue; + } + if( 0 == strncmp(inputDataLine, "Materials : ", 11) ) { + //Find Material section ==> parse it ... + //EWOL_DEBUG("find a Maretials section :"); + // all object might have minimaly one material : + ewol::Material* material = NULL; + etk::UString name = ""; + //Find a mesh ==> parse it ... + while (NULL != LoadNextData(inputDataLine, 2048, fileName) ) { + //EWOL_DEBUG("mat parse : '" << inputDataLine << "'"); + if( inputDataLine[0] == '\t' + && inputDataLine[1] != '\t') { + if( name != "" + && material!=NULL) { + m_materials.Add(name, material); + name = ""; + material = NULL; + } + material = new ewol::Material(); + inputDataLine[strlen(inputDataLine)-1] = '\0'; + name = &inputDataLine[1]; + EWOL_DEBUG("Create materials : '" << name << "'"); + } else { + if (NULL != material) { + if( inputDataLine[2] == 'N' + && inputDataLine[3] == 's' + && inputDataLine[4] == ' ' ) { + float tmpVal=0; + sscanf(&inputDataLine[5], "%f", &tmpVal); + material->SetShininess(tmpVal); + } else if( inputDataLine[2] == 'K' + && inputDataLine[3] == 'a' + && inputDataLine[4] == ' ' ) { + float tmpVal1=0; + float tmpVal2=0; + float tmpVal3=0; + sscanf(&inputDataLine[5], "%f %f %f", &tmpVal1, &tmpVal2, &tmpVal3); + vec4 tmp(tmpVal1, tmpVal2, tmpVal3, 1); + material->SetAmbientFactor(tmp); + } else if( inputDataLine[2] == 'K' + && inputDataLine[3] == 'd' + && inputDataLine[4] == ' ' ) { + float tmpVal1=0; + float tmpVal2=0; + float tmpVal3=0; + sscanf(&inputDataLine[5], "%f %f %f", &tmpVal1, &tmpVal2, &tmpVal3); + vec4 tmp(tmpVal1, tmpVal2, tmpVal3, 1); + material->SetDiffuseFactor(tmp); + } else if( inputDataLine[2] == 'K' + && inputDataLine[3] == 's' + && inputDataLine[4] == ' ' ) { + float tmpVal1=0; + float tmpVal2=0; + float tmpVal3=0; + sscanf(&inputDataLine[5], "%f %f %f", &tmpVal1, &tmpVal2, &tmpVal3); + vec4 tmp(tmpVal1, tmpVal2, tmpVal3, 1); + material->SetSpecularFactor(tmp); + } else if( inputDataLine[2] == 'N' + && inputDataLine[3] == 'i' + && inputDataLine[4] == ' ' ) { + float tmpVal=0; + sscanf(&inputDataLine[5], "%f", &tmpVal); + // TODO : ... + } else if( inputDataLine[2] == 'd' + && inputDataLine[3] == ' ' ) { + float tmpVal=0; + sscanf(&inputDataLine[4], "%f", &tmpVal); + // TODO : ... + } else if( inputDataLine[2] == 'i' + && inputDataLine[3] == 'l' + && inputDataLine[4] == 'l' + && inputDataLine[5] == 'u' + && inputDataLine[6] == 'm' + && inputDataLine[7] == ' ' ) { + // TODO : ... + } else if( inputDataLine[2] == 'm' + && inputDataLine[3] == 'a' + && inputDataLine[4] == 'p' + && inputDataLine[5] == '_' + && inputDataLine[6] == 'K' + && inputDataLine[7] == 'd' + && inputDataLine[8] == ' ' ) { + inputDataLine[strlen(inputDataLine)-1] = '\0'; + material->SetTexture0(fileName.GetRelativeFolder() + &inputDataLine[9]); + } else { + EWOL_ERROR("unknow material property ... : '" << inputDataLine << "'"); + } + } + } + } + if( name != "" + && material!=NULL) { + m_materials.Add(name, material); + name = ""; + material = NULL; + } + continue; + } + +/* exemple of file +EMF(STRING) +# Blender v2.66 (sub 1) EMF File: 'station.blend' +Mesh : 1 + Name : MainControl_mesh + Vertex : 174 + 0.500000 0.015097 -1.170499|-1.003113 0.010738 -1.000184|1.003173 0.013001 -0.998027| + UV-mapping : + 0.964431 0.766844|0.939031 0.811940|1.050593 0.813877|0.815493 0.602993|0.783793 0.520610| + Normal(face) : 344 + 0.310313 -0.276298 0.909596|-0.426055 -0.318865 0.846642|-0.915346 -0.402637 -0.004953| + Face : 344 + Material: 23/1/1 9/2/1 2/3/1| 18/4/2 20/5/2 1/6/2| 18/4/3 1/6/3 5/7/3| + +Materials : 1 + Material + Ns 96.078431 + Ka 0.000000 0.000000 0.000000 + Kd 0.640000 0.640000 0.640000 + Ks 0.500000 0.500000 0.500000 + Ni 1.000000 + d 1.000000 + illum 2 + map_Kd station.png + +- Ka - material ambient is multiplied by the texture value +- Kd - material diffuse is multiplied by the texture value +- Ks - material specular is multiplied by the texture value +- Ns - material specular exponent is multiplied by the texture value +- d - material dissolve is multiplied by the texture value +*/ + } + fileName.FileClose(); + GenerateVBO(); + return true; +} diff --git a/sources/ewol/renderer/resources/Mesh.h b/sources/ewol/renderer/resources/Mesh.h index 485ab8f1..fb9f47de 100644 --- a/sources/ewol/renderer/resources/Mesh.h +++ b/sources/ewol/renderer/resources/Mesh.h @@ -10,6 +10,7 @@ #define __MESH_H__ #include +#include #include #include #include @@ -152,25 +153,24 @@ namespace ewol int32_t m_GLNormal; int32_t m_GLNormalFace; int32_t m_GLtexture; - int32_t m_GLtexID0; int32_t m_bufferOfset; int32_t m_numberOfElments; - ewol::Material m_material; + MaterialGlId m_GLMaterial; ewol::Light m_light; protected: etk::Vector m_listVertex; //!< List of all vertex in the element etk::Vector m_listUV; //!< List of all UV point in the mesh (for the specify texture) - etk::Vector m_listFaces; //!< List of all Face for the mesh etk::Vector m_listFacesNormal; //!< List of all Face normal, when calculated etk::Vector m_listVertexNormal; //!< List of all Face normal, when calculated + etk::Hash > m_listFaces; //!< List of all Face for the mesh + etk::Hash m_materials; #ifdef USE_INDEXED_MESH etk::Vector m_listIndexFaces; #endif protected: - ewol::VirtualBufferObject* m_verticesVBO; - ewol::TextureFile* m_texture0; + ewol::VirtualBufferObject* m_verticesVBO; public: - Mesh(etk::UString genName, etk::UString shaderName="DATA:textured3D2.prog"); + Mesh(const etk::UString& _fileName, const etk::UString& _shaderName="DATA:textured3D2.prog"); virtual ~Mesh(void); virtual const char* GetType(void) { return "ewol::Mesh"; }; virtual void Draw(mat4& positionMatrix); @@ -201,6 +201,9 @@ namespace ewol void CreateViewBox(float size=1.0); void Subdivide(int32_t numberOfTime, bool smooth); void DisplaceElement(const ewol::DisplacementTable& displacement); + private: + bool LoadOBJ(const etk::UString& _fileName); + bool LoadEMF(const etk::UString& _fileName); }; }; diff --git a/sources/ewol/renderer/resources/MeshObj.cpp b/sources/ewol/renderer/resources/MeshObj.cpp deleted file mode 100644 index b5da6b31..00000000 --- a/sources/ewol/renderer/resources/MeshObj.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license BSD v3 (see license file) - */ - -#include -#include -#include - -#include -#include -#include - -#undef __class__ -#define __class__ "MeshObj" - -ewol::MeshObj::MeshObj(etk::UString _fileName) : - ewol::Mesh(_fileName) -{ - etk::FSNode fileName(_fileName); - // Get the fileSize ... - int32_t size = fileName.FileSize(); - if (size == 0 ) { - EWOL_ERROR("No data in the file named=\"" << fileName << "\""); - return; - } - if(false == fileName.FileOpenRead() ) { - EWOL_ERROR("Can not find the file name=\"" << fileName << "\""); - return; - } - char inputDataLine[2048]; - - int32_t lineID = 0; - while (NULL != fileName.FileGets(inputDataLine, 2048) ) - { - lineID++; - if (inputDataLine[0]=='v') { - if (inputDataLine[1]=='n') { - // Vertice normal : vn 0.000000 0.000000 -1.000000 - // we did not use normal ==> we recalculated it if needed (some .obj does not export normal, then it is simple like this ... - } else if (inputDataLine[1]=='t') { - // Texture position : vt 0.748573 0.750412 - vec2 vertex(0,0); - sscanf(&inputDataLine[3], "%f %f", &vertex.m_floats[0], &vertex.m_floats[1]); - m_listUV.PushBack(vertex); - } else { - // Vertice position : v 1.000000 -1.000000 -1.000000 - vec3 vertex(0,0,0); - sscanf(&inputDataLine[2], "%f %f %f", &vertex.m_floats[0], &vertex.m_floats[1], &vertex.m_floats[2] ); - m_listVertex.PushBack(vertex); - } - } else if (inputDataLine[0]=='f') { - // face : f 5/1/1 1/2/1 4/3/1* - uint32_t vertexIndex[4], uvIndex[4], normalIndex[4]; - bool quadMode = true; - int32_t matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n", - &vertexIndex[0], &uvIndex[0], &normalIndex[0], - &vertexIndex[1], &uvIndex[1], &normalIndex[1], - &vertexIndex[2], &uvIndex[2], &normalIndex[2], - &vertexIndex[3], &uvIndex[3], &normalIndex[3] ); - if (12 != matches){ - // no normal mode : - matches = sscanf(&inputDataLine[2], "%d/%d %d/%d %d/%d %d/%d\n", - &vertexIndex[0], &uvIndex[0], - &vertexIndex[1], &uvIndex[1], - &vertexIndex[2], &uvIndex[2], - &vertexIndex[3], &uvIndex[3] ); - if (8 != matches){ - quadMode = false; - matches = sscanf(&inputDataLine[2], "%d/%d/%d %d/%d/%d %d/%d/%d\n", - &vertexIndex[0], &uvIndex[0], &normalIndex[0], - &vertexIndex[1], &uvIndex[1], &normalIndex[1], - &vertexIndex[2], &uvIndex[2], &normalIndex[2] ); - if (9 != matches){ - // no normal mode : - matches = sscanf(&inputDataLine[2], "%d/%d %d/%d %d/%d\n", - &vertexIndex[0], &uvIndex[0], - &vertexIndex[1], &uvIndex[1], - &vertexIndex[2], &uvIndex[2] ); - if (6 != matches){ - EWOL_ERROR("Parsing error in the .obj files : " << fileName << " (l=" << lineID << ") in 'f' section : \"" << &inputDataLine[2] << "\" expected : %d/%d(/%d) %d/%d(/%d) %d/%d(/%d) (%d/%d(/%d)) () for option"); - continue; - } - } - } - } - if (true==quadMode) { - m_listFaces.PushBack(Face(vertexIndex[0]-1, uvIndex[0]-1, - vertexIndex[1]-1, uvIndex[1]-1, - vertexIndex[2]-1, uvIndex[2]-1, - vertexIndex[3]-1, uvIndex[3]-1)); - } else { - m_listFaces.PushBack(Face(vertexIndex[0]-1, uvIndex[0]-1, - vertexIndex[1]-1, uvIndex[1]-1, - vertexIndex[2]-1, uvIndex[2]-1)); - } - /* - EWOL_DEBUG(" plop : " << tmpFace.m_nbElement << " ? " << m_listFaces[m_listFaces.Size()-1].m_nbElement); - EWOL_DEBUG(" : " << tmpFace.m_vertex[0] << " ? " << m_listFaces[m_listFaces.Size()-1].m_vertex[0]); - EWOL_DEBUG(" : " << tmpFace.m_uv[0] << " ? " << m_listFaces[m_listFaces.Size()-1].m_uv[0]); - */ - } else if (inputDataLine[0]=='s') { - // ??? : s off - } else if (inputDataLine[0]=='#') { - // comment - // nothing to do ... just go to the new line ... - } else if( inputDataLine[0]=='u' - && inputDataLine[1]=='s' - && inputDataLine[2]=='e' - && inputDataLine[3]=='m' - && inputDataLine[4]=='t' - && inputDataLine[5]=='l' ) { - // Use Material : usemtl imageName.xxx - while( inputDataLine[strlen(inputDataLine)-1] == '\n' - || inputDataLine[strlen(inputDataLine)-1] == '\r' - || inputDataLine[strlen(inputDataLine)-1] == ' ') { - if (1 == strlen(inputDataLine) ){ - break; - } - inputDataLine[strlen(inputDataLine)-1] = '\0'; - } - etk::UString tmpVal(&inputDataLine[7]); - SetTexture(fileName.GetRelativeFolder() + tmpVal); - } else if( inputDataLine[0]=='m' - && inputDataLine[1]=='t' - && inputDataLine[2]=='l' - && inputDataLine[3]=='l' - && inputDataLine[4]=='i' - && inputDataLine[5]=='b' ) { - // ???? : mtllib cube.mtl - } - } - fileName.FileClose(); - GenerateVBO(); -} - - diff --git a/sources/ewol/renderer/resources/MeshObj.h b/sources/ewol/renderer/resources/MeshObj.h deleted file mode 100644 index 854edcdf..00000000 --- a/sources/ewol/renderer/resources/MeshObj.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @author Edouard DUPIN - * - * @copyright 2011, Edouard DUPIN, all right reserved - * - * @license BSD v3 (see license file) - */ - -#ifndef __MESH_OBJ_H__ -#define __MESH_OBJ_H__ - -#include -#include -#include - -namespace ewol -{ - class MeshObj : public ewol::Mesh - { - public: - MeshObj(etk::UString fileName); - ~MeshObj(void) { }; - virtual const char* GetType(void) { return "ewol::MeshObj"; }; - }; -}; - - - - - -#endif - diff --git a/sources/ewol/widget/Mesh.h b/sources/ewol/widget/Mesh.h index f75af3b4..4c8ccaef 100644 --- a/sources/ewol/widget/Mesh.h +++ b/sources/ewol/widget/Mesh.h @@ -11,7 +11,7 @@ #include #include -#include +#include extern const char * const ewolEventMeshPressed; @@ -22,7 +22,7 @@ namespace widget { private: // mesh name : etk::UString m_meshName; - ewol::MeshObj* m_object; + ewol::Mesh* m_object; // mesh display properties: vec3 m_position; vec3 m_angle; diff --git a/sources/lutin_ewol.py b/sources/lutin_ewol.py index ea1bab04..c8a585b7 100755 --- a/sources/lutin_ewol.py +++ b/sources/lutin_ewol.py @@ -52,7 +52,6 @@ def Create(target): 'ewol/renderer/resources/FontFreeType.cpp', 'ewol/renderer/resources/TexturedFont.cpp', 'ewol/renderer/resources/Mesh.cpp', - 'ewol/renderer/resources/MeshObj.cpp', 'ewol/renderer/resources/Texture.cpp', 'ewol/renderer/resources/Colored3DObject.cpp', 'ewol/renderer/resources/Image.cpp',