Scripts:
authorWillian Padovani Germano <wpgermano@gmail.com>
Thu, 22 Feb 2007 20:19:58 +0000 (20:19 +0000)
committerWillian Padovani Germano <wpgermano@gmail.com>
Thu, 22 Feb 2007 20:19:58 +0000 (20:19 +0000)
- Updated ac3d exporter to use first material found in the mesh for loose edges (lines) color. Inspired by bug report from Stewart Andreason. Also made a few updates to very old parts of the code, got rid of two "try/except".

- Updated ac3d importer to be even more forgiving to bad data. Also added option to turn transparency on in the 3D View for models using materials with alpha < 1.0. Added optional support for ac3d's subdiv tag, works by adding a subsurf modifier to the imported model(s) that have this tag, so they appear as intended.

release/scripts/ac3d_export.py
release/scripts/ac3d_import.py

index 80e88d933c8e4c206e1e10526aa9c0a85082c3be..5ae4eaf2f2d9dc6da360e226b156e6e45b88b8a8 100644 (file)
@@ -2,7 +2,7 @@
 
 """ Registration info for Blender menus:
 Name: 'AC3D (.ac)...'
-Blender: 242
+Blender: 243
 Group: 'Export'
 Tip: 'Export selected meshes to AC3D (.ac) format'
 """
@@ -10,7 +10,7 @@ Tip: 'Export selected meshes to AC3D (.ac) format'
 __author__ = "Willian P. Germano"
 __url__ = ("blender", "elysiun", "AC3D's homepage, http://www.ac3d.org",
        "PLib 3d gaming lib, http://plib.sf.net")
-__version__ = "2.43 2007-01-14"
+__version__ = "2.43.1 2007-02-22"
 
 __bpydoc__ = """\
 This script exports selected Blender meshes to AC3D's .ac file format.
@@ -29,6 +29,7 @@ file, if needed.
 Known issues:<br>
     The ambient and emit data we can retrieve from Blender are single values,
 that this script copies to R, G, B, giving shades of gray.<br>
+    Loose edges (lines) receive the first material found in the mesh, if any, or a default white material.<br>
     In AC3D 4 "compatibility mode":<br>
     - shininess of materials is taken from the shader specularity value in Blender, mapped from [0.0, 2.0] to [0, 128];<br>
     - crease angle is exported, but in Blender it is limited to [1, 80], since there are other more powerful ways to control surface smoothing.  In AC3D 4.0 crease's range is [0.0, 180.0];
@@ -60,7 +61,7 @@ Notes:<br>
        This version updates:<br>
     - modified meshes are correctly exported, no need to apply the modifiers in Blender;<br>
     - correctly export each used material, be it assigned to the object or to its mesh data;<br>
-    - exporting lines (edges) is again supported;<br>
+    - exporting lines (edges) is again supported; color comes from first material found in the mesh, if any, or a default white one.<br>
     - there's a new option to choose between exporting meshes with transformed (global) coordinates or local ones;<br>
     Multiple textures per mesh are supported (mesh gets split);<br>
        Parents are exported as a group containing both the parent and its children;<br>
@@ -71,16 +72,17 @@ Notes:<br>
 # $Id$
 #
 # --------------------------------------------------------------------------
-# AC3DExport version 2.43
+# AC3DExport version 2.43.1
 # Program versions: Blender 2.42+ and AC3Db files (means version 0xb)
 # new: updated for new Blender version and Mesh module; supports lines (edges) again;
 # option to export vertices transformed to global coordinates or not; now the modified
 # (by existing mesh modifiers) mesh is exported; materials are properly exported, no
-# matter if each of them is linked to the mesh or to the object.
+# matter if each of them is linked to the mesh or to the object. New (2.43.1): loose
+# edges use color of first material found in the mesh, if any.
 # --------------------------------------------------------------------------
 # Thanks: Steve Baker for discussions and inspiration; for testing, bug
 # reports, suggestions, patches: David Megginson, Filippo di Natale,
-# Franz Melchior, Campbell Barton, Josh Babcock, Ralf Gerlich
+# Franz Melchior, Campbell Barton, Josh Babcock, Ralf Gerlich, Stewart Andreason.
 # --------------------------------------------------------------------------
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
@@ -530,9 +532,7 @@ class AC3DExport: # the ac3d exporter part
                        mlist = self.mlist
                        for m in xrange(len(mat)):
                                name = mat[m].name
-                               try:
-                                       mlist.index(name)
-                               except ValueError:
+                               if name not in mlist:
                                        mlist.append(name)
                                        M = Material.Get(name)
                                        material = 'MATERIAL "%s"' % name
@@ -656,17 +656,15 @@ class AC3DExport: # the ac3d exporter part
 
                if not foomesh: verts = list(self.mesh.verts)
 
+               materials = self.mesh.materials
                mlist = self.mlist
                omlist = {}
-               objmats = self.mesh.materials[:]
                matidx_error_told = 0
-               for i in range(len(objmats)):
-                       objmats[i] = objmats[i].name
+               objmats = [omat.name for omat in materials]
                for f in faces:
-                       m_idx = f.mat
-                       try:
-                               m_idx = mlist.index(objmats[m_idx])
-                       except IndexError:
+                       if objmats[f.mat] in mlist:
+                               m_idx = mlist.index(objmats[f.mat])
+                       else:
                                if not lc_MATIDX_ERROR:
                                        rdat = REPORT_DATA['warns']
                                        rdat.append("Object %s" % self.obj.name)
@@ -715,6 +713,14 @@ class AC3DExport: # the ac3d exporter part
 
                        file.write("%s%s%s%s" % (surfstr, matstr, refstr, fvstr))
 
+               # material for loose edges
+               edges_mat = 0 # default to first material
+               for omat in objmats: # but look for a material from this mesh
+                       if omat in mlist:
+                               edges_mat = mlist.index(omat)
+                               if lc_ADD_DEFAULT_MAT: edges_mat += 1
+                               break
+
                for e in looseEdges:
                        fvstr = []
                        #flaglow = 2 # 1 = closed line, 2 = line
@@ -726,7 +732,7 @@ class AC3DExport: # the ac3d exporter part
                        fvstr.append("%d 0 0\n" % verts.index(e.v2))
                        fvstr = "".join(fvstr)
 
-                       matstr = "mat 0\n" # for now, use first material 
+                       matstr = "mat %d\n" % edges_mat # for now, use first material 
                        refstr = "refs 2\n" # 2 verts
 
                        file.write("%s%s%s%s" % (surfstr, matstr, refstr, fvstr))
index fc169f0d6d73801fa207f909a0b17c6038f2a938..d538838fdf3b764285b916f15c8a2fb8fa28012d 100644 (file)
@@ -2,7 +2,7 @@
 
 """ Registration info for Blender menus:
 Name: 'AC3D (.ac)...'
-Blender: 242
+Blender: 243
 Group: 'Import'
 Tip: 'Import an AC3D (.ac) file.'
 """
@@ -10,7 +10,7 @@ Tip: 'Import an AC3D (.ac) file.'
 __author__ = "Willian P. Germano"
 __url__ = ("blender", "elysiun", "AC3D's homepage, http://www.ac3d.org",
        "PLib 3d gaming lib, http://plib.sf.net")
-__version__ = "2.43 2007-02-12"
+__version__ = "2.43.1 2007-02-21"
 
 __bpydoc__ = """\
 This script imports AC3D models into Blender.
@@ -29,6 +29,8 @@ Known issues:<br>
     - Some objects may be imported with wrong normals due to wrong information in the model itself. This can be noticed by strange shading, like darker than expected parts in the model. To fix this, select the mesh with wrong normals, enter edit mode and tell Blender to recalculate the normals, either to make them point outside (the usual case) or inside.<br>
  
 Config Options:<br>
+    - display transp (toggle): if "on", objects that have materials with alpha < 1.0 are shown with translucency (transparency) in the 3D View.<br>
+    - subdiv (toggle): if "on", ac3d objects meant to be subdivided receive a SUBSURF modifier in Blender.<br>
     - textures dir (string): if non blank, when imported texture paths are
 wrong in the .ac file, Blender will also look for them at this dir.
 
@@ -41,9 +43,10 @@ users can configure (see config options above).
 # $Id$
 #
 # --------------------------------------------------------------------------
-# AC3DImport version 2.43 Feb 12, 2007
+# AC3DImport version 2.43.1 Feb 21, 2007
 # Program versions: Blender 2.43 and AC3Db files (means version 0xb)
-# changed: updated for new Blender version, Mesh module
+# changed: better triangulation of ngons, more fixes to support bad .ac files,
+# option to display transp mats in 3d view, support "subdiv" tag (via SUBSURF modifier)
 # --------------------------------------------------------------------------
 # Thanks: Melchior Franz for extensive bug testing and reporting, making this
 # version cope much better with old or bad .ac files, among other improvements;
@@ -70,30 +73,31 @@ users can configure (see config options above).
 # ***** END GPL LICENCE BLOCK *****
 # --------------------------------------------------------------------------
 
-# Note:
-# Blender doesn't handle n-gons (polygons with more than 4 vertices):
-#  The script triangulates them, but concave polygons come out wrong and need
-#  fixing. Avoiding or triangulating concave n-gons in AC3D is a simple way to
-#  avoid problems.
-
 from math import radians
 
 import Blender
-from Blender import Scene, Object, Mesh, Lamp, Registry, sys as bsys, Window, Image, Material
+from Blender import Scene, Object, Mesh, Lamp, Registry, sys as bsys, Window, Image, Material, Modifier
 from Blender.sys import dirsep
 from Blender.Mathutils import Vector, Matrix, Euler
+from Blender.Geometry import PolyFill
 
 # Default folder for AC3D textures, to override wrong paths, change to your
 # liking or leave as "":
 TEXTURES_DIR = ""
 
+DISPLAY_TRANSP = True
+
+SUBDIV = True
+
 tooltips = {
-       'TEXTURES_DIR': 'additional dir to look for missing textures'
+       'DISPLAY_TRANSP': 'Turn transparency on in the 3d View for objects using materials with alpha < 1.0.',
+       'SUBDIV': 'Apply a SUBSURF modifier to objects meant to appear subdivided.',
+       'TEXTURES_DIR': 'Additional folder to look for missing textures.'
 }
 
 def update_registry():
-       global TEXTURES_DIR
-       rd = dict([('TEXTURES_DIR', TEXTURES_DIR)])
+       global TEXTURES_DIR, DISPLAY_TRANSP
+       rd = dict([('tooltips', tooltips), ('TEXTURES_DIR', TEXTURES_DIR), ('DISPLAY_TRANSP', DISPLAY_TRANSP), ('SUBDIV', SUBDIV)])
        Registry.SetKey('ac3d_import', rd, True)
 
 rd = Registry.GetKey('ac3d_import', True)
@@ -101,7 +105,12 @@ rd = Registry.GetKey('ac3d_import', True)
 if rd:
        if 'GROUP' in rd:
                update_registry()
-       TEXTURES_DIR = rd['TEXTURES_DIR']
+       try:
+               TEXTURES_DIR = rd['TEXTURES_DIR']
+               DISPLAY_TRANSP = rd['DISPLAY_TRANSP']
+               SUBDIV = rd['SUBDIV']
+       except:
+               update_registry()
 else: update_registry()
 
 if TEXTURES_DIR:
@@ -135,6 +144,8 @@ AC_OB_TYPES = {
        'light':  AC_LIGHT
        }
 
+AC_OB_BAD_TYPES_LIST = [] # to hold references to unknown (wrong) ob types
+
 def inform(msg):
        global VERBOSE
        if VERBOSE: print msg
@@ -160,6 +171,7 @@ class Obj:
                self.rot = []
                self.size = []
                self.crease = 30
+               self.subdiv = 0
                self.vlist = []
                self.flist_cfg = []
                self.flist_v = []
@@ -212,6 +224,7 @@ class AC3DImport:
                                          'texture':    self.parse_tex,
                                          'texrep':             self.parse_texrep,
                                          'texoff':             self.parse_texoff,
+                                         'subdiv':             self.parse_subdiv,
                                          'crease':             self.parse_crease}
 
                self.objlist = []
@@ -237,7 +250,13 @@ class AC3DImport:
                                        inform('Ignoring unexpected data at end of file.')
                                        return -1 # bad file with more objects than reported
                        kidsnumlist[-1] -= 1
-               new = Obj(AC_OB_TYPES[value])
+               if value in AC_OB_TYPES:
+                       new = Obj(AC_OB_TYPES[value])
+               else:
+                       if value not in AC_OB_BAD_TYPES_LIST:
+                               AC_OB_BAD_TYPES_LIST.append(value)
+                               inform('Unexpected object type keyword: "%s". Assuming it is of type: "poly".' % value)
+                       new = Obj(AC_OB_TYPES['poly'])
                new.dad = self.dad
                new.name = value
                self.objlist.append(new)
@@ -322,6 +341,9 @@ class AC3DImport:
                value = float(value)
                self.objlist[-1].crease = int(value)
 
+       def parse_subdiv(self, value):
+               self.objlist[-1].subdiv = int(value)
+
        def parse_vert(self, value):
                i = self.i
                lines = self.lines
@@ -347,6 +369,7 @@ class AC3DImport:
                double_sided = 0
                lines = self.lines
                obj = self.objlist[-1]
+               vlist = obj.vlist
                matlist = obj.matlist
                numsurf = int(value)
                NUMSURF = numsurf
@@ -364,12 +387,17 @@ class AC3DImport:
 
                        is_smooth = flaghigh & 1
                        twoside = flaghigh & 2
-                       mat = lines[i+1].split()
-                       mat = int(mat[1])
-                       if not mat in matlist: matlist.append(mat)
-                       refs = lines[i+2].split()
-                       refs = int(refs[1])
-                       i += 3
+                       nextline = lines[i+1].split()
+                       if nextline[0] != 'mat': # the "mat" line may be missing (found in one buggy .ac file)
+                               matid = 0
+                               if not matid in matlist: matlist.append(matid)
+                               i += 2
+                       else:
+                               matid = int(nextline[1])
+                               if not matid in matlist: matlist.append(matid)
+                               nextline = lines[i+2].split()
+                               i += 3
+                       refs = int(nextline[1])
                        face = []
                        faces = []
                        edges = []
@@ -407,20 +435,21 @@ class AC3DImport:
                                        # multiple references to the same vertex
                                        badface_multirefs += 1
                                else: # ok, seems fine
-                                       while len(face) > 4:
-                                               cut = face[:4]
-                                               cutuv = fuv[:4]
-                                               face = face[3:]
-                                               fuv = fuv[3:]
-                                               face.insert(0, cut[0])
-                                               fuv.insert(0, cutuv[0])
-                                               faces.append(cut)
-                                               fuvs.append(cutuv)
-
-                                       faces.append(face)
-                                       fuvs.append(fuv)
-
-                       obj.flist_cfg.extend([[mat, is_smooth, twoside]] * len(faces))
+                                       if len(face) > 4: # ngon, triangulate it
+                                               polyline = []
+                                               for vi in face:
+                                                       polyline.append(Vector(vlist[vi]))
+                                               tris = PolyFill([polyline])
+                                               for t in tris:
+                                                       tri = [face[t[0]], face[t[1]], face[t[2]]]
+                                                       triuvs = [fuv[t[0]], fuv[t[1]], fuv[t[2]]]
+                                                       faces.append(tri)
+                                                       fuvs.append(triuvs)
+                                       else: # tri or quad
+                                               faces.append(face)
+                                               fuvs.append(fuv)
+
+                       obj.flist_cfg.extend([[matid, is_smooth, twoside]] * len(faces))
                        obj.flist_v.extend(faces)
                        obj.flist_uv.extend(fuvs)
                        obj.elist.extend(edges) # loose edges
@@ -608,6 +637,8 @@ class AC3DImport:
                                if bmat.index(mat) in obj.matlist:
                                        objmat_indices.append(bmat.index(mat))
                                        mesh.materials += [mat]
+                                       if DISPLAY_TRANSP and mat.alpha < 1.0:
+                                               object.transp = True
 
                        for e in obj.elist:
                                mesh.edges.extend(e)
@@ -705,6 +736,17 @@ class AC3DImport:
 
                                mesh.mode = MESH_AUTOSMOOTH
 
+                               # subdiv: create SUBSURF modifier in Blender
+                               if SUBDIV and obj.subdiv > 0:
+                                       subdiv = obj.subdiv
+                                       subdiv_render = subdiv
+                                       # just to be safe:
+                                       if subdiv_render > 6: subdiv_render = 6
+                                       if subdiv > 3: subdiv = 3
+                                       modif = object.modifiers.append(Modifier.Types.SUBSURF)
+                                       modif[Modifier.Settings.LEVELS] = subdiv
+                                       modif[Modifier.Settings.RENDLEVELS] = subdiv_render
+
                        obj_idx += 1
 
                self.build_hierarchy()