Skip to content
Snippets Groups Projects
export_x3d.py 69.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + '/>\n')
    
        def writeMaterialH3D(ident, material, world,
    
                             obj, gpu_shader):
    
            material_id = quoteattr(unique_name(material, 'MA_' + material.name, uuid_cache_material, clean_func=clean_def, sep="_"))
    
            fw('%s<Material />\n' % ident)
    
            if material.tag:
                fw('%s<ComposedShader USE=%s />\n' % (ident, material_id))
    
    Campbell Barton's avatar
    Campbell Barton committed
            else:
    
                # GPU_material_bind_uniforms
                # GPU_begin_object_materials
    
    Campbell Barton's avatar
    Campbell Barton committed
    
                #~ CD_MCOL 6
                #~ CD_MTFACE 5
                #~ CD_ORCO 14
                #~ CD_TANGENT 18
                #~ GPU_DATA_16F 7
                #~ GPU_DATA_1F 2
                #~ GPU_DATA_1I 1
                #~ GPU_DATA_2F 3
                #~ GPU_DATA_3F 4
                #~ GPU_DATA_4F 5
                #~ GPU_DATA_4UB 8
                #~ GPU_DATA_9F 6
                #~ GPU_DYNAMIC_LAMP_DYNCO 7
                #~ GPU_DYNAMIC_LAMP_DYNCOL 11
                #~ GPU_DYNAMIC_LAMP_DYNENERGY 10
                #~ GPU_DYNAMIC_LAMP_DYNIMAT 8
                #~ GPU_DYNAMIC_LAMP_DYNPERSMAT 9
                #~ GPU_DYNAMIC_LAMP_DYNVEC 6
                #~ GPU_DYNAMIC_OBJECT_COLOR 5
                #~ GPU_DYNAMIC_OBJECT_IMAT 4
                #~ GPU_DYNAMIC_OBJECT_MAT 2
                #~ GPU_DYNAMIC_OBJECT_VIEWIMAT 3
                #~ GPU_DYNAMIC_OBJECT_VIEWMAT 1
                #~ GPU_DYNAMIC_SAMPLER_2DBUFFER 12
                #~ GPU_DYNAMIC_SAMPLER_2DIMAGE 13
                #~ GPU_DYNAMIC_SAMPLER_2DSHADOW 14
    
                '''
                inline const char* typeToString( X3DType t ) {
                  switch( t ) {
                  case     SFFLOAT: return "SFFloat";
                  case     MFFLOAT: return "MFFloat";
                  case    SFDOUBLE: return "SFDouble";
                  case    MFDOUBLE: return "MFDouble";
                  case      SFTIME: return "SFTime";
                  case      MFTIME: return "MFTime";
                  case     SFINT32: return "SFInt32";
                  case     MFINT32: return "MFInt32";
                  case     SFVEC2F: return "SFVec2f";
                  case     MFVEC2F: return "MFVec2f";
                  case     SFVEC2D: return "SFVec2d";
                  case     MFVEC2D: return "MFVec2d";
                  case     SFVEC3F: return "SFVec3f";
                  case     MFVEC3F: return "MFVec3f";
                  case     SFVEC3D: return "SFVec3d";
                  case     MFVEC3D: return "MFVec3d";
                  case     SFVEC4F: return "SFVec4f";
                  case     MFVEC4F: return "MFVec4f";
                  case     SFVEC4D: return "SFVec4d";
                  case     MFVEC4D: return "MFVec4d";
                  case      SFBOOL: return "SFBool";
                  case      MFBOOL: return "MFBool";
                  case    SFSTRING: return "SFString";
                  case    MFSTRING: return "MFString";
                  case      SFNODE: return "SFNode";
                  case      MFNODE: return "MFNode";
                  case     SFCOLOR: return "SFColor";
                  case     MFCOLOR: return "MFColor";
                  case SFCOLORRGBA: return "SFColorRGBA";
                  case MFCOLORRGBA: return "MFColorRGBA";
                  case  SFROTATION: return "SFRotation";
                  case  MFROTATION: return "MFRotation";
                  case  SFQUATERNION: return "SFQuaternion";
                  case  MFQUATERNION: return "MFQuaternion";
                  case  SFMATRIX3F: return "SFMatrix3f";
                  case  MFMATRIX3F: return "MFMatrix3f";
                  case  SFMATRIX4F: return "SFMatrix4f";
                  case  MFMATRIX4F: return "MFMatrix4f";
                  case  SFMATRIX3D: return "SFMatrix3d";
                  case  MFMATRIX3D: return "MFMatrix3d";
                  case  SFMATRIX4D: return "SFMatrix4d";
                  case  MFMATRIX4D: return "MFMatrix4d";
    
                  case UNKNOWN_X3D_TYPE:
    
    Campbell Barton's avatar
    Campbell Barton committed
                  default:return "UNKNOWN_X3D_TYPE";
                '''
                import gpu
    
    
                fw('%s<ComposedShader DEF=%s language="GLSL" >\n' % (ident, material_id))
    
                ident += '\t'
    
                shader_url_frag = 'shaders/%s_%s.frag' % (filename_strip, material_id[1:-1])
                shader_url_vert = 'shaders/%s_%s.vert' % (filename_strip, material_id[1:-1])
    
    Campbell Barton's avatar
    Campbell Barton committed
    
                # write files
    
                shader_dir = os.path.join(base_dst, 'shaders')
    
    Campbell Barton's avatar
    Campbell Barton committed
                if not os.path.isdir(shader_dir):
                    os.mkdir(shader_dir)
    
    
                # ------------------------------------------------------
                # shader-patch
    
                field_descr = " <!--- H3D View Matrix Patch -->"
                fw('%s<field name="%s" type="SFMatrix4f" accessType="inputOutput" />%s\n' % (ident, H3D_VIEW_MATRIX, field_descr))
    
                frag_vars = ["uniform mat4 %s;" % H3D_VIEW_MATRIX]
    
                # annoying!, we need to track if some of the directional lamp
                # vars are children of the camera or not, since this adjusts how
                # they are patched.
                frag_uniform_var_map = {}
    
                        '<ROUTE fromNode="%s" fromField="glModelViewMatrix" toNode=%s toField="%s" />%s' %
                        (H3D_TOP_LEVEL, material_id, H3D_VIEW_MATRIX, field_descr))
    
                # ------------------------------------------------------
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                for uniform in gpu_shader['uniforms']:
                    if uniform['type'] == gpu.GPU_DYNAMIC_SAMPLER_2DIMAGE:
    
                        field_descr = " <!--- Dynamic Sampler 2d Image -->"
                        fw('%s<field name="%s" type="SFNode" accessType="inputOutput">%s\n' % (ident, uniform['varname'], field_descr))
                        writeImageTexture(ident + '\t', uniform['image'])
    
                        fw('%s</field>\n' % ident)
    
    Campbell Barton's avatar
    Campbell Barton committed
    
                    elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNCO:
    
                        lamp_obj = uniform['lamp']
                        frag_uniform_var_map[uniform['varname']] = lamp_obj
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                        if uniform['datatype'] == gpu.GPU_DATA_3F:  # should always be true!
    
                            lamp_obj_id = quoteattr(unique_name(lamp_obj, LA_ + lamp_obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_"))
    
                            lamp_obj_transform_id = quoteattr(unique_name(lamp_obj, lamp_obj.name, uuid_cache_object, clean_func=clean_def, sep="_"))
    
                            value = '%.6f %.6f %.6f' % (global_matrix * lamp_obj.matrix_world).to_translation()[:]
    
                            field_descr = " <!--- Lamp DynCo '%s' -->" % lamp_obj.name
                            fw('%s<field name="%s" type="SFVec3f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr))
    
                            # ------------------------------------------------------
                            # shader-patch
    
                            field_descr = " <!--- Lamp DynCo '%s' (shader patch) -->" % lamp_obj.name
                            fw('%s<field name="%s_transform" type="SFMatrix4f" accessType="inputOutput" />%s\n' % (ident, uniform['varname'], field_descr))
    
    
                            # transform
                            frag_vars.append("uniform mat4 %s_transform;" % uniform['varname'])
                            h3d_material_route.append(
    
                                    '<ROUTE fromNode=%s fromField="accumulatedForward" toNode=%s toField="%s_transform" />%s' %
    
                                    (suffix_quoted_str(lamp_obj_transform_id, _TRANSFORM), material_id, uniform['varname'], field_descr))
    
                            h3d_material_route.append(
    
                                    '<ROUTE fromNode=%s fromField="location" toNode=%s toField="%s" /> %s' %
    
                                    (lamp_obj_id, material_id, uniform['varname'], field_descr))
    
                            # ------------------------------------------------------
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                        else:
                            assert(0)
    
                    elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNCOL:
                        # odd  we have both 3, 4 types.
    
                        lamp_obj = uniform['lamp']
    
                        frag_uniform_var_map[uniform['varname']] = lamp_obj
    
    
                        lamp = lamp_obj.data
    
                        value = '%.6f %.6f %.6f' % (lamp.color * lamp.energy)[:]
    
                        field_descr = " <!--- Lamp DynColor '%s' -->" % lamp_obj.name
    
    Campbell Barton's avatar
    Campbell Barton committed
                        if uniform['datatype'] == gpu.GPU_DATA_3F:
    
                            fw('%s<field name="%s" type="SFVec3f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr))
    
    Campbell Barton's avatar
    Campbell Barton committed
                        elif uniform['datatype'] == gpu.GPU_DATA_4F:
    
                            fw('%s<field name="%s" type="SFVec4f" accessType="inputOutput" value="%s 1.0" />%s\n' % (ident, uniform['varname'], value, field_descr))
    
    Campbell Barton's avatar
    Campbell Barton committed
                        else:
                            assert(0)
    
                    elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNENERGY:
                        # not used ?
                        assert(0)
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                    elif uniform['type'] == gpu.GPU_DYNAMIC_LAMP_DYNVEC:
    
                        lamp_obj = uniform['lamp']
                        frag_uniform_var_map[uniform['varname']] = lamp_obj
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                        if uniform['datatype'] == gpu.GPU_DATA_3F:
    
                            lamp_obj = uniform['lamp']
    
                            value = '%.6f %.6f %.6f' % ((global_matrix * lamp_obj.matrix_world).to_quaternion() * mathutils.Vector((0.0, 0.0, 1.0))).normalized()[:]
    
                            field_descr = " <!--- Lamp DynDirection '%s' -->" % lamp_obj.name
                            fw('%s<field name="%s" type="SFVec3f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr))
    
    
                            # route so we can have the lamp update the view
                            if h3d_is_object_view(scene, lamp_obj):
    
                                lamp_id = quoteattr(unique_name(lamp_obj, LA_ + lamp_obj.name, uuid_cache_lamp, clean_func=clean_def, sep="_"))
    
                                h3d_material_route.append(
                                    '<ROUTE fromNode=%s fromField="direction" toNode=%s toField="%s" />%s' %
                                            (lamp_id, material_id, uniform['varname'], field_descr))
    
    Campbell Barton's avatar
    Campbell Barton committed
                        else:
                            assert(0)
    
                    elif uniform['type'] == gpu.GPU_DYNAMIC_OBJECT_VIEWIMAT:
    
                        frag_uniform_var_map[uniform['varname']] = None
    
    Campbell Barton's avatar
    Campbell Barton committed
                        if uniform['datatype'] == gpu.GPU_DATA_16F:
    
                            field_descr = " <!--- Object View Matrix Inverse '%s' -->" % obj.name
    
                            fw('%s<field name="%s" type="SFMatrix4f" accessType="inputOutput" />%s\n' % (ident, uniform['varname'], field_descr))
    
    
                            h3d_material_route.append(
                                '<ROUTE fromNode="%s" fromField="glModelViewMatrixInverse" toNode=%s toField="%s" />%s' %
                                        (H3D_TOP_LEVEL, material_id, uniform['varname'], field_descr))
    
    Campbell Barton's avatar
    Campbell Barton committed
                        else:
                            assert(0)
    
                    elif uniform['type'] == gpu.GPU_DYNAMIC_OBJECT_IMAT:
    
                        frag_uniform_var_map[uniform['varname']] = None
    
    Campbell Barton's avatar
    Campbell Barton committed
                        if uniform['datatype'] == gpu.GPU_DATA_16F:
    
                            value = ' '.join(['%.6f' % f for v in (global_matrix * obj.matrix_world).inverted().transposed() for f in v])
    
                            field_descr = " <!--- Object Invertex Matrix '%s' -->" % obj.name
                            fw('%s<field name="%s" type="SFMatrix4f" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr))
    
    Campbell Barton's avatar
    Campbell Barton committed
                        else:
                            assert(0)
    
                    elif uniform['type'] == gpu.GPU_DYNAMIC_SAMPLER_2DSHADOW:
                        pass  # XXX, shadow buffers not supported.
    
    Campbell Barton's avatar
    Campbell Barton committed
                    elif uniform['type'] == gpu.GPU_DYNAMIC_SAMPLER_2DBUFFER:
    
                        frag_uniform_var_map[uniform['varname']] = None
    
    
    Campbell Barton's avatar
    Campbell Barton committed
                        if uniform['datatype'] == gpu.GPU_DATA_1I:
                            if 1:
    
                                tex = uniform['texpixels']
                                value = []
                                for i in range(0, len(tex) - 1, 4):
                                    col = tex[i:i + 4]
    
                                    value.append('0x%.2x%.2x%.2x%.2x' % (col[0], col[1], col[2], col[3]))
    
    
                                field_descr = " <!--- Material Buffer -->"
                                fw('%s<field name="%s" type="SFNode" accessType="inputOutput">%s\n' % (ident, uniform['varname'], field_descr))
    
                                ident_step = ident + (' ' * (-len(ident) + \
                                fw('%s<PixelTexture \n' % ident)))
    
                                fw(ident_step + 'repeatS="false"\n')
                                fw(ident_step + 'repeatT="false"\n')
    
                                fw(ident_step + 'image="%s 1 4 %s"\n' % (len(value), " ".join(value)))
    
                                ident = ident[:-1]
    
                                fw('%s</field>\n' % ident)
    
                                #for i in range(0, 10, 4)
                                #value = ' '.join(['%d' % f for f in uniform['texpixels']])
    
                                # value = ' '.join(['%.6f' % (f / 256) for f in uniform['texpixels']])
    
                                #fw('%s<field name="%s" type="SFInt32" accessType="inputOutput" value="%s" />%s\n' % (ident, uniform['varname'], value, field_descr))
    
                                #print('test', len(uniform['texpixels']))
    
    Campbell Barton's avatar
    Campbell Barton committed
                        else:
                            assert(0)
    
                    else:
                        print("SKIPPING", uniform['type'])
    
                file_frag = open(os.path.join(base_dst, shader_url_frag), 'w', encoding='utf-8')
    
    Campbell Barton's avatar
    Campbell Barton committed
                file_frag.write(gpu_shader['fragment'])
                file_frag.close()
    
                # patch it
    
                h3d_shader_glsl_frag_patch(os.path.join(base_dst, shader_url_frag),
                                           scene,
                                           frag_vars,
                                           frag_uniform_var_map,
                                           )
    
                file_vert = open(os.path.join(base_dst, shader_url_vert), 'w', encoding='utf-8')
    
    Campbell Barton's avatar
    Campbell Barton committed
                file_vert.write(gpu_shader['vertex'])
                file_vert.close()
    
    
                fw('%s<ShaderPart type="FRAGMENT" url=%s />\n' % (ident, quoteattr(shader_url_frag)))
                fw('%s<ShaderPart type="VERTEX" url=%s />\n' % (ident, quoteattr(shader_url_vert)))
    
    Campbell Barton's avatar
    Campbell Barton committed
                ident = ident[:-1]
    
    
                fw('%s</ComposedShader>\n' % ident)
    
        def writeImageTexture(ident, image):
    
            image_id = quoteattr(unique_name(image, IM_ + image.name, uuid_cache_image, clean_func=clean_def, sep="_"))
    
                fw('%s<ImageTexture USE=%s />\n' % (ident, image_id))
    
    Campbell Barton's avatar
    Campbell Barton committed
                ident_step = ident + (' ' * (-len(ident) + \
                fw('%s<ImageTexture ' % ident)))
    
                # collect image paths, can load multiple
    
                filepath = image.filepath
    
                filepath_full = bpy.path.abspath(filepath, library=image.library)
                filepath_ref = bpy_extras.io_utils.path_reference(filepath_full, base_src, base_dst, path_mode, "textures", copy_set, image.library)
    
                filepath_base = os.path.basename(filepath_full)
    
                images = [
                    filepath_ref,
    
                    filepath_full,
                ]
    
                images = [f.replace('\\', '/') for f in images]
                images = [f for i, f in enumerate(images) if f not in images[:i]]
    
                fw(ident_step + "url='%s' " % ' '.join(['"%s"' % escape(f) for f in images]))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + '/>\n')
    
        def writeBackground(ident, world):
    
            world_id = quoteattr(unique_name(world, WO_ + world.name, uuid_cache_world, clean_func=clean_def, sep="_"))
    
            blending = world.use_sky_blend, world.use_sky_paper, world.use_sky_real
    
    
            grd_triple = clamp_color(world.horizon_color)
            sky_triple = clamp_color(world.zenith_color)
            mix_triple = clamp_color((grd_triple[i] + sky_triple[i]) / 2.0 for i in range(3))
    
    Campbell Barton's avatar
    Campbell Barton committed
            ident_step = ident + (' ' * (-len(ident) + \
            fw('%s<Background ' % ident)))
    
            # No Skytype - just Hor color
            if blending == (False, False, False):
    
                fw(ident_step + 'groundColor="%.3f %.3f %.3f"\n' % grd_triple)
                fw(ident_step + 'skyColor="%.3f %.3f %.3f"\n' % grd_triple)
    
            # Blend Gradient
            elif blending == (True, False, False):
    
                fw(ident_step + 'groundColor="%.3f %.3f %.3f, %.3f %.3f %.3f"\n' % (grd_triple + mix_triple))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + 'groundAngle="1.57, 1.57"\n')
    
                fw(ident_step + 'skyColor="%.3f %.3f %.3f, %.3f %.3f %.3f"\n' % (sky_triple + mix_triple))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + 'skyAngle="1.57, 1.57"\n')
    
            # Blend+Real Gradient Inverse
            elif blending == (True, False, True):
    
                fw(ident_step + 'groundColor="%.3f %.3f %.3f, %.3f %.3f %.3f"\n' % (sky_triple + grd_triple))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + 'groundAngle="1.57"\n')
    
                fw(ident_step + 'skyColor="%.3f %.3f %.3f, %.3f %.3f %.3f, %.3f %.3f %.3f"\n' % (sky_triple + grd_triple + sky_triple))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + 'skyAngle="1.57, 3.14159"\n')
    
            # Paper - just Zen Color
            elif blending == (False, False, True):
    
                fw(ident_step + 'groundColor="%.3f %.3f %.3f"\n' % sky_triple)
                fw(ident_step + 'skyColor="%.3f %.3f %.3f"\n' % sky_triple)
    
            # Blend+Real+Paper - komplex gradient
            elif blending == (True, True, True):
    
                fw(ident_step + 'groundColor="%.3f %.3f %.3f, %.3f %.3f %.3f"\n' % (sky_triple + grd_triple))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + 'groundAngle="1.57, 1.57"\n')
    
                fw(ident_step + 'skyColor="%.3f %.3f %.3f, %.3f %.3f %.3f"\n' % (sky_triple + grd_triple))
    
    Campbell Barton's avatar
    Campbell Barton committed
                fw(ident_step + 'skyAngle="1.57, 1.57"\n')
    
                fw(ident_step + 'groundColor="%.3f %.3f %.3f"\n' % grd_triple)
                fw(ident_step + 'skyColor="%.3f %.3f %.3f"\n' % sky_triple)
    
            for tex in bpy.data.textures:
    
    Campbell Barton's avatar
    Campbell Barton committed
                if tex.type == 'IMAGE' and tex.image:
                    namemat = tex.name
                    pic = tex.image
    
                    basename = quoteattr(bpy.path.basename(pic.filepath))
    
                    if namemat == 'back':
    
                        fw(ident_step + 'backUrl=%s\n' % basename)
    
                    elif namemat == 'bottom':
    
                        fw(ident_step + 'bottomUrl=%s\n' % basename)
    
                    elif namemat == 'front':
    
                        fw(ident_step + 'frontUrl=%s\n' % basename)
    
                    elif namemat == 'left':
    
                        fw(ident_step + 'leftUrl=%s\n' % basename)
    
                    elif namemat == 'right':
    
                        fw(ident_step + 'rightUrl=%s\n' % basename)
    
                    elif namemat == 'top':
    
                        fw(ident_step + 'topUrl=%s\n' % basename)
    
    Campbell Barton's avatar
    Campbell Barton committed
            fw(ident_step + '/>\n')
    
        # -------------------------------------------------------------------------
        # Export Object Hierarchy (recursively called)
        # -------------------------------------------------------------------------
        def export_object(ident, obj_main_parent, obj_main, obj_children):
            world = scene.world
            free, derived = create_derived_objects(scene, obj_main)
    
            if use_hierarchy:
                obj_main_matrix_world = obj_main.matrix_world
                if obj_main_parent:
                    obj_main_matrix = obj_main_parent.matrix_world.inverted() * obj_main_matrix_world
                else:
                    obj_main_matrix = obj_main_matrix_world
                obj_main_matrix_world_invert = obj_main_matrix_world.inverted()
    
    
                obj_main_id = quoteattr(unique_name(obj_main, obj_main.name, uuid_cache_object, clean_func=clean_def, sep="_"))
    
                ident = writeTransform_begin(ident, obj_main_matrix if obj_main_parent else global_matrix * obj_main_matrix, suffix_quoted_str(obj_main_id, _TRANSFORM))
    
            for obj, obj_matrix in (() if derived is None else derived):
    
                if use_hierarchy:
                    # make transform node relative
                    obj_matrix = obj_main_matrix_world_invert * obj_matrix
    
    
                # H3D - use for writing a dummy transform parent
                is_dummy_tx = False
    
    
                if obj_type == 'CAMERA':
                    writeViewpoint(ident, obj, obj_matrix, scene)
    
                    if use_h3d and scene.camera == obj:
                        view_id = uuid_cache_view[obj]
                        fw('%s<Transform DEF="%s">\n' % (ident, H3D_CAMERA_FOLLOW))
                        h3d_material_route.extend([
                            '<ROUTE fromNode="%s" fromField="totalPosition" toNode="%s" toField="translation" />' % (view_id, H3D_CAMERA_FOLLOW),
                            '<ROUTE fromNode="%s" fromField="totalOrientation" toNode="%s" toField="rotation" />' % (view_id, H3D_CAMERA_FOLLOW),
                            ])
                        is_dummy_tx = True
                        ident += '\t'
    
                elif obj_type in {'MESH', 'CURVE', 'SURFACE', 'FONT'}:
    
                    if (obj_type != 'MESH') or (use_apply_modifiers and obj.is_modified(scene, 'PREVIEW')):
                        try:
                            me = obj.to_mesh(scene, use_apply_modifiers, 'PREVIEW')
                        except:
                            me = None
    
                        # ensure unique name, we could also do this by
                        # postponing mesh removal, but clearing data - TODO
                        if do_remove:
                            me.name = obj.name.rstrip("1234567890").rstrip(".")
                            me_name_new = me_name_org = me.name
                            count = 0
                            while me_name_new in mesh_name_set:
                                me.name = "%.17s.%03d" % (me_name_org, count)
                                me_name_new = me.name
                                count += 1
                            mesh_name_set.add(me_name_new)
                            del me_name_new, me_name_org, count
                        # done
    
    
                        writeIndexedFaceSet(ident, obj, me, obj_matrix, world)
    
                        # free mesh created with create_mesh()
    
                            bpy.data.meshes.remove(me)
    
                elif obj_type == 'LAMP':
                    data = obj.data
                    datatype = data.type
                    if datatype == 'POINT':
                        writePointLight(ident, obj, obj_matrix, data, world)
                    elif datatype == 'SPOT':
                        writeSpotLight(ident, obj, obj_matrix, data, world)
                    elif datatype == 'SUN':
                        writeDirectionalLight(ident, obj, obj_matrix, data, world)
                    else:
                        writeDirectionalLight(ident, obj, obj_matrix, data, world)
                else:
                    #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType)
                    pass
    
            if free:
                free_derived_objects(obj_main)
    
            # ---------------------------------------------------------------------
            # write out children recursively
            # ---------------------------------------------------------------------
            for obj_child, obj_child_children in obj_children:
                export_object(ident, obj_main, obj_child, obj_child_children)
    
    
            if is_dummy_tx:
                ident = ident[:-1]
                fw('%s</Transform>\n' % ident)
                is_dummy_tx = False
    
    
            if use_hierarchy:
                ident = writeTransform_end(ident)
    
        # -------------------------------------------------------------------------
        # Main Export Function
        # -------------------------------------------------------------------------
    
            world = scene.world
    
    
            # tag un-exported IDs
            bpy.data.meshes.tag(False)
            bpy.data.materials.tag(False)
            bpy.data.images.tag(False)
    
    
            print('Info: starting X3D export to %r...' % file.name)
            ident = ''
    
            ident = writeHeader(ident)
    
            writeNavigationInfo(ident, scene)
            writeBackground(ident, world)
            writeFog(ident, world)
    
            ident = '\t\t'
    
    Campbell Barton's avatar
    Campbell Barton committed
                objects = [obj for obj in scene.objects if obj.is_visible(scene) and obj.select]
    
                objects = [obj for obj in scene.objects if obj.is_visible(scene)]
    
            if use_hierarchy:
                objects_hierarchy = build_hierarchy(objects)
            else:
                objects_hierarchy = ((obj, []) for obj in objects)
    
            for obj_main, obj_main_children in objects_hierarchy:
                export_object(ident, None, obj_main, obj_main_children)
    
            ident = writeFooter(ident)
    
    Campbell Barton's avatar
    Campbell Barton committed
    
        # -------------------------------------------------------------------------
        # global cleanup
        # -------------------------------------------------------------------------
    
    Campbell Barton's avatar
    Campbell Barton committed
        if use_h3d:
            bpy.data.materials.remove(gpu_shader_dummy_mat)
    
    
        # copy all collected files.
    
        bpy_extras.io_utils.path_reference_copy(copy_set)
    
    
        print('Info: finished X3D export to %r' % file.name)
    
    
    
    ##########################################################
    # Callbacks, needed before Main
    ##########################################################
    
    
    
    def gzip_open_utf8(filepath, mode):
        """Workaround for py3k only allowing binary gzip writing"""
    
        import gzip
    
        # need to investigate encoding
        file = gzip.open(filepath, mode)
        write_real = file.write
    
        def write_wrap(data):
            return write_real(data.encode("utf-8"))
    
        file.write = write_wrap
    
        return file
    
    
    
    def save(operator, context, filepath="",
    
             use_selection=True,
             use_apply_modifiers=False,
             use_triangulate=False,
    
             use_normals=False,
    
             use_compress=False,
    
    Campbell Barton's avatar
    Campbell Barton committed
             use_h3d=False,
    
             global_matrix=None,
    
             path_mode='AUTO',
    
        bpy.path.ensure_ext(filepath, '.x3dz' if use_compress else '.x3d')
    
    
        if bpy.ops.object.mode_set.poll():
            bpy.ops.object.mode_set(mode='OBJECT')
    
    
        if use_compress:
    
            file = gzip_open_utf8(filepath, 'w')
    
            file = open(filepath, 'w', encoding='utf-8')
    
        if global_matrix is None:
            global_matrix = mathutils.Matrix()
    
    
        export(file,
               global_matrix,
               context.scene,
               use_apply_modifiers=use_apply_modifiers,
               use_selection=use_selection,
    
               use_triangulate=use_triangulate,
               use_normals=use_normals,
    
    Campbell Barton's avatar
    Campbell Barton committed
               use_h3d=use_h3d,
    
               path_mode=path_mode,
    
               name_decorations=name_decorations,