Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



kat@Posted: Mon Apr 17, 2006 10:30 pm : Doom3world • View topic - ASE Importer

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Fri Dec 21, 2007 1:36 pm

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: ASE Importer
PostPosted: Mon Apr 17, 2006 2:00 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)


Last edited by Goofos on Sun Jun 17, 2007 7:00 pm, edited 5 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 1:12 pm 
Offline
True believer
User avatar

Joined: Sun Aug 29, 2004 10:39 pm
Posts: 1730
Nice job, thanks Goofos!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 10:30 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York



Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



kat@Posted: Mon Apr 17, 2006 10:30 pm :
Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!



kat@Posted: Fri May 19, 2006 8:04 pm :
Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^



Goofos@Posted: Sun May 21, 2006 3:58 pm :
Should work now. Seems my OS is a bit more tollerant with format errors :>



OrbWeaver@Posted: Fri May 26, 2006 10:43 am :
I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.



kat@Posted: Fri May 26, 2006 5:33 pm :
New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^



Goofos@Posted: Wed May 31, 2006 3:07 pm :
There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.



kat@Posted: Wed May 31, 2006 6:19 pm :
DUDE!! sorted. Both vertex and UVW import work fine and dandy.



Goofos@Posted: Tue Aug 15, 2006 12:07 pm :
Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) :D to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.



Tweaker@Posted: Fri Aug 25, 2006 2:29 am :
Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. :D



kat@Posted: Wed Apr 11, 2007 7:52 pm :
Goofos, can you double check the script to make sure it works in 2.42/2.43 et-al.. I'm getting reports of the script working for some but not for others, I've not recently checked the script post 2.41.



Goofos@Posted: Fri Apr 13, 2007 11:35 am :
So far it works with 2.43, at least with ase files exported with 3ds or blender. The only problems i found are if the file has key animations or if you set the faces to smooth it looks a bit wrong but the smooth problem is fixed when you enter edit mode.



kat@Posted: Fri Apr 13, 2007 1:03 pm :
Thanks for double checking :wink:



Trakerz@Posted: Thu May 31, 2007 2:27 pm :
Hi Goofos

Since multiple mapping coordinates have been introduced in blender 2.43 is there any way you could update ASE importer so we can see the models in blender with 2 or more UV coordinates?

Also is there a fix for importing the smoothing of the faces?..i`m using blender 2.44



Goofos@Posted: Thu May 31, 2007 5:31 pm :
On the way for the next version, which should be ready within one or two weeks.



Trakerz@Posted: Tue Jun 12, 2007 8:13 am :
That sounds great..i have searched all the importers for blender and none of them support multiple uv`s

Can`t wait for the new ASE importer 8)



Goofos@Posted: Sun Jun 17, 2007 7:06 pm :
Updated the script (v0.13).

I think this version needs some testing and a bit cleanup but i think this can wait for Blender 2.44a.



Trakerz@Posted: Mon Jun 18, 2007 8:40 pm :
GREAT WORK Goofos!!!!!!
I just tested an ASE file and works like a charm ;)


BTW in the code there is a problem at line 485 : unexpected indent
i fixed mine by just fixing the right alingment to the 'if' statement ;)

Here is the file if you with to do a try:

The tank model is not mine...is a free low poly tank from turbo squid for testing purposes:

The archive contains

tank.3ds
tank.ASE
tank_diff.tga - diffuse texture that goes on UV 1
tabk_AO.tga - ambient occlusion(lightmap) texture that goes on UV 2

the 3ds file is for the smoothing comparision

from what i have seen the smoothings are ok on the entire model...

http://www.4shared.com/file/18162300/42ec9c5b/tank.html

FINALY!!! an importer with multi UV support!!! 8)



Goofos@Posted: Tue Jun 19, 2007 5:33 pm :
I have no idea how the ase Materials/Maps deal with multiple UV channels. There is no reference either to a specific UV channel in the maps or in the UV channels itself to a specific map.

According to a manual/tutorial of the UT2kx Engine you have to create a new Material in the Unreal Editor if you want to use a second UV channel, therefore my guess is that the ase file format don't support Materials/Maps referencing multiple UV channels.



hyp3rfocus@Posted: Sun Jul 29, 2007 10:31 pm :
hi, i've had some problems with this script. i was getting the "python script error : check console" error message as soon as i selected this script. the output from the console said this...
Quote:
File "<string>", line 485
add_EDGESPLIT = True
^
IndentationError: unindent does not match any outer indentation level
...so i opened the file and added a couple of spaces so that it matched the line above and that seemed to do the trick.

apart from that little glitch it's a fantastic script. thanks for all your work.



kissaki@Posted: Sat Jul 26, 2008 10:03 pm :
with that fix from the previous post it also seems to work with recent Blender 2.46
(just a short note)
nice! thx :)



Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



kat@Posted: Mon Apr 17, 2006 10:30 pm :
Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!



kat@Posted: Fri May 19, 2006 8:04 pm :
Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^



Goofos@Posted: Sun May 21, 2006 3:58 pm :
Should work now. Seems my OS is a bit more tollerant with format errors :>



OrbWeaver@Posted: Fri May 26, 2006 10:43 am :
I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.



kat@Posted: Fri May 26, 2006 5:33 pm :
New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^



Goofos@Posted: Wed May 31, 2006 3:07 pm :
There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.



kat@Posted: Wed May 31, 2006 6:19 pm :
DUDE!! sorted. Both vertex and UVW import work fine and dandy.



Goofos@Posted: Tue Aug 15, 2006 12:07 pm :
Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) :D to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.



Tweaker@Posted: Fri Aug 25, 2006 2:29 am :
Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. :D



kat@Posted: Wed Apr 11, 2007 7:52 pm :
Goofos, can you double check the script to make sure it works in 2.42/2.43 et-al.. I'm getting reports of the script working for some but not for others, I've not recently checked the script post 2.41.



Goofos@Posted: Fri Apr 13, 2007 11:35 am :
So far it works with 2.43, at least with ase files exported with 3ds or blender. The only problems i found are if the file has key animations or if you set the faces to smooth it looks a bit wrong but the smooth problem is fixed when you enter edit mode.



kat@Posted: Fri Apr 13, 2007 1:03 pm :
Thanks for double checking :wink:



Trakerz@Posted: Thu May 31, 2007 2:27 pm :
Hi Goofos

Since multiple mapping coordinates have been introduced in blender 2.43 is there any way you could update ASE importer so we can see the models in blender with 2 or more UV coordinates?

Also is there a fix for importing the smoothing of the faces?..i`m using blender 2.44



Goofos@Posted: Thu May 31, 2007 5:31 pm :
On the way for the next version, which should be ready within one or two weeks.



Trakerz@Posted: Tue Jun 12, 2007 8:13 am :
That sounds great..i have searched all the importers for blender and none of them support multiple uv`s

Can`t wait for the new ASE importer 8)



Goofos@Posted: Sun Jun 17, 2007 7:06 pm :
Updated the script (v0.13).

I think this version needs some testing and a bit cleanup but i think this can wait for Blender 2.44a.



Trakerz@Posted: Mon Jun 18, 2007 8:40 pm :
GREAT WORK Goofos!!!!!!
I just tested an ASE file and works like a charm ;)


BTW in the code there is a problem at line 485 : unexpected indent
i fixed mine by just fixing the right alingment to the 'if' statement ;)

Here is the file if you with to do a try:

The tank model is not mine...is a free low poly tank from turbo squid for testing purposes:

The archive contains

tank.3ds
tank.ASE
tank_diff.tga - diffuse texture that goes on UV 1
tabk_AO.tga - ambient occlusion(lightmap) texture that goes on UV 2

the 3ds file is for the smoothing comparision

from what i have seen the smoothings are ok on the entire model...

http://www.4shared.com/file/18162300/42ec9c5b/tank.html

FINALY!!! an importer with multi UV support!!! 8)



Goofos@Posted: Tue Jun 19, 2007 5:33 pm :
I have no idea how the ase Materials/Maps deal with multiple UV channels. There is no reference either to a specific UV channel in the maps or in the UV channels itself to a specific map.

According to a manual/tutorial of the UT2kx Engine you have to create a new Material in the Unreal Editor if you want to use a second UV channel, therefore my guess is that the ase file format don't support Materials/Maps referencing multiple UV channels.



hyp3rfocus@Posted: Sun Jul 29, 2007 10:31 pm :
hi, i've had some problems with this script. i was getting the "python script error : check console" error message as soon as i selected this script. the output from the console said this...
Quote:
File "<string>", line 485
add_EDGESPLIT = True
^
IndentationError: unindent does not match any outer indentation level
...so i opened the file and added a couple of spaces so that it matched the line above and that seemed to do the trick.

apart from that little glitch it's a fantastic script. thanks for all your work.



kissaki@Posted: Sat Jul 26, 2008 10:03 pm :
with that fix from the previous post it also seems to work with recent Blender 2.46
(just a short note)
nice! thx :)



Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



kat@Posted: Mon Apr 17, 2006 10:30 pm :
Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!



kat@Posted: Fri May 19, 2006 8:04 pm :
Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^



Goofos@Posted: Sun May 21, 2006 3:58 pm :
Should work now. Seems my OS is a bit more tollerant with format errors :>



OrbWeaver@Posted: Fri May 26, 2006 10:43 am :
I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.



kat@Posted: Fri May 26, 2006 5:33 pm :
New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^



Goofos@Posted: Wed May 31, 2006 3:07 pm :
There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.



kat@Posted: Wed May 31, 2006 6:19 pm :
DUDE!! sorted. Both vertex and UVW import work fine and dandy.



Goofos@Posted: Tue Aug 15, 2006 12:07 pm :
Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) :D to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.



Tweaker@Posted: Fri Aug 25, 2006 2:29 am :
Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. :D



kat@Posted: Wed Apr 11, 2007 7:52 pm :
Goofos, can you double check the script to make sure it works in 2.42/2.43 et-al.. I'm getting reports of the script working for some but not for others, I've not recently checked the script post 2.41.



Goofos@Posted: Fri Apr 13, 2007 11:35 am :
So far it works with 2.43, at least with ase files exported with 3ds or blender. The only problems i found are if the file has key animations or if you set the faces to smooth it looks a bit wrong but the smooth problem is fixed when you enter edit mode.



kat@Posted: Fri Apr 13, 2007 1:03 pm :
Thanks for double checking :wink:



Trakerz@Posted: Thu May 31, 2007 2:27 pm :
Hi Goofos

Since multiple mapping coordinates have been introduced in blender 2.43 is there any way you could update ASE importer so we can see the models in blender with 2 or more UV coordinates?

Also is there a fix for importing the smoothing of the faces?..i`m using blender 2.44



Goofos@Posted: Thu May 31, 2007 5:31 pm :
On the way for the next version, which should be ready within one or two weeks.



Trakerz@Posted: Tue Jun 12, 2007 8:13 am :
That sounds great..i have searched all the importers for blender and none of them support multiple uv`s

Can`t wait for the new ASE importer 8)



Goofos@Posted: Sun Jun 17, 2007 7:06 pm :
Updated the script (v0.13).

I think this version needs some testing and a bit cleanup but i think this can wait for Blender 2.44a.



Trakerz@Posted: Mon Jun 18, 2007 8:40 pm :
GREAT WORK Goofos!!!!!!
I just tested an ASE file and works like a charm ;)


BTW in the code there is a problem at line 485 : unexpected indent
i fixed mine by just fixing the right alingment to the 'if' statement ;)

Here is the file if you with to do a try:

The tank model is not mine...is a free low poly tank from turbo squid for testing purposes:

The archive contains

tank.3ds
tank.ASE
tank_diff.tga - diffuse texture that goes on UV 1
tabk_AO.tga - ambient occlusion(lightmap) texture that goes on UV 2

the 3ds file is for the smoothing comparision

from what i have seen the smoothings are ok on the entire model...

http://www.4shared.com/file/18162300/42ec9c5b/tank.html

FINALY!!! an importer with multi UV support!!! 8)



Goofos@Posted: Tue Jun 19, 2007 5:33 pm :
I have no idea how the ase Materials/Maps deal with multiple UV channels. There is no reference either to a specific UV channel in the maps or in the UV channels itself to a specific map.

According to a manual/tutorial of the UT2kx Engine you have to create a new Material in the Unreal Editor if you want to use a second UV channel, therefore my guess is that the ase file format don't support Materials/Maps referencing multiple UV channels.



Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



kat@Posted: Mon Apr 17, 2006 10:30 pm : Doom3world • View topic - ASE Importer

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Sat Dec 22, 2007 4:11 pm

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: ASE Importer
PostPosted: Mon Apr 17, 2006 2:00 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)


Last edited by Goofos on Sun Jun 17, 2007 7:00 pm, edited 5 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 1:12 pm 
Offline
True believer
User avatar

Joined: Sun Aug 29, 2004 10:39 pm
Posts: 1730
Nice job, thanks Goofos!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 10:30 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York



Goofos@Posted: Mon Apr 17, 2006 2:00 am :
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm :
Nice job, thanks Goofos!



kat@Posted: Mon Apr 17, 2006 10:30 pm : Doom3world • View topic - ASE Importer

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Sun Dec 23, 2007 10:02 pm

All times are UTC




Post new topic Reply to topic  [ 21 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: ASE Importer
PostPosted: Mon Apr 17, 2006 2:00 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
:arrow: Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b
            ase_me.append_vertcol(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMCVFACES':
            ase_me.num['CVFACES'] = words[1]
            continue
         elif word0 == '*MESH_CFACE':
            #ase_face_index, ci0, ci1, ci2
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_cface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]))
            continue
      #elif word0 == '*MESH_NORMALS':
      elif IMP_AUTOSMOOTH:
         if word0 == '*MESH_FACENORMAL':
            # ase_face_index, x, y, z
            ase_face_index = int(words[1])
            ase_me.append_normal(ase_face_index,float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_VERTEXNORMAL':
            # ase_face_index, ase_vert_index, x, y, z
            ase_me.append_vnormal(ase_face_index,int(words[1]),float(words[2]),float(words[3]),float(words[4]),IMP_AUTOSMOOTH)
            continue
      else:
         continue
   return ase_objects

def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if sys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'

def read(filename):

   global counts
   counts = {'verts':0,'tris':0,'faces':0}

   start = time.clock()

   print_boxed("----------ASCII Scene Import----------")
   print 'Import File: ', filename

   mode = Blender.Window.EditMode()     # are we in edit mode?  If so ...
   if mode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh

   file = open(filename,'r', OPT_FILE_BUFFER)
   ase_objects = read_file(file)
   file.close()
   spawn(ase_objects)
   Blender.Redraw()
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   # Blender.Window.EditMode(mode)

   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   #totals = "Imported Verts: %i Faces: %i Tris: %i " % (counts['verts'],counts['tris'],counts['faces'])
   #print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   print_boxed(message)




def read_ui(filename):

   global IMPORT_SC, IMPORT_VC, IMP_UV, IMPORT_GO, IMPORT_SE, IMPORT_SM
   global IMP_SCALED,IMP_SMOOTHGROUPS,IMP_VCOLOR,IMP_UV,IMP_FGONS,IMP_QUADS,IMP_SEAMS,IMP_SMOOTHGROUPS,IMP_AUTOSMOOTH

   IMPORT_SC = Blender.Draw.Create(IMP_SCALED)
   IMPORT_VC = Blender.Draw.Create(IMP_VCOLOR)
   IMP_UV = Blender.Draw.Create(IMP_UV)
   IMPORT_SE = Blender.Draw.Create(IMP_SEAMS)
   IMPORT_SM = Blender.Draw.Create(IMP_SMOOTHGROUPS)

   # Get USER Options
   pup_block = [('Import Options'),('Scale Meshes', IMPORT_SC, 'Scale the Objects so that they better fit into Blender\'s grid size'),('Vertex Colors', IMPORT_VC, 'Import Vertex Colors if existing'),('UV (Layer)', IMP_UV, 'Import UV and UV layer\'s if existing'),('Smoothing', IMPORT_SM, 'Surround Smoothgroups with sharp edges'),('Seams', IMPORT_SE, 'Try to import Seams from UV islands (from the first UV layer!)')]

   if not Blender.Draw.PupBlock('Import ASCII Scene...', pup_block):
      return

   Blender.Window.WaitCursor(1)

   IMP_SCALED = IMPORT_SC.val
   IMP_VCOLOR = IMPORT_VC.val
   IMP_UV = IMP_UV.val
   IMP_SEAMS = IMPORT_SE.val
   IMP_SMOOTHGROUPS = IMPORT_SM.val

   read(filename)

   Blender.Window.WaitCursor(0)
   Blender.Redraw()


if __name__ == '__main__' and OPT_FILESELECTOR:
   Blender.Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))
elif __name__ == '__main__':
   read_ui(OPT_STATIC_FILENAME)


Last edited by Goofos on Sun Jun 17, 2007 7:00 pm, edited 5 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 1:12 pm 
Offline
True believer
User avatar

Joined: Sun Aug 29, 2004 10:39 pm
Posts: 1730
Nice job, thanks Goofos!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 17, 2006 10:30 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York



Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: Arrow Version: 0.13

Supports Mesh Objects with vertex colors, multiple UV, smoothgroups.

A little Note!: you should not try to import very big ase files (>50 MB with 512 MB RAM). With much RAM you might can try this.

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.13'
Blender: 244
Group: 'Import'
Tooltip: 'Import from ASCII Scene Export file format (.ase)'
"""
__author__ = "Goofos"
__version__ = "0.13"

# goofos
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import time, sys
import Blender
from Blender import Scene, Object, Mesh

'''
Some Options
'''
# Scale Factor (float)
OPT_SCALE = 0.1
# Add EdgeSplit Modifier when importing sharp edges (bool)
OPT_MOD_EDGESPLIT = True
# Enable the fileselector (bool)
OPT_FILESELECTOR = True
# If the fileselector is disabled, specify a static filename (string)
OPT_STATIC_FILENAME = 'E:\ASE Files\garage.ASE'
# Enable Progressbar (bool)
OPT_PROGRESSBAR = False
# File buffer. After testing with big files i think there is no real difference.
# -1 = system default, 0 = unbuffered, 1 = line buffered, >1 = buffer size
OPT_FILE_BUFFER = -1

'''
Import Options
'''
# Import Meshes scaled, defined by the scale factor of OPT_SCALE (bool)
# Note: Object location data looses some precision, .. i think!
IMP_SCALED = True
# Import Vertex Colors (bool)
IMP_VCOLOR = True
# Import UV Coords and UV layers (bool)
IMP_UV = True
# Import NGons as Blender FGons (bool)
# Note: Include quads, too.
IMP_FGONS = False
# Try to find possible quads and convert the two tris to a quad (bool)
# Note: Very slow!! ablsolutely doesn't work accurate :/
# i don't know wether this is a script problem or a blender problem!
IMP_QUADS = False
# Surround UV islands with seams (bool)
IMP_SEAMS = False
# Surround smooth groups with sharp edges (bool)
IMP_SMOOTHGROUPS = True
# Try to find the lowest autosmooth angle in vertex normals (bool)
# Note: i dont know if this is correct :>
IMP_AUTOSMOOTH = False





class Ase_group:
   def __init__(self):
      self.name = 'Name'
      self.ase_type = 'GROUP'
      self.ase_helper = None
      self.ase_objects = []

class Ase_object:

   def __init__(self, ase_object_type, name=''):
      #if ase_object_type not in ['GEOM','HELPER','SHAPE','LIGHT','CAMERA']: return
      if ase_object_type not in ['geom','helper','shape','light','camera']: return
      self.name = name
      self.ase_type = ase_object_type #GEOM, HELPER, SHAPE, LIGHT, CAMERA
      self.row0 = None
      self.row1 = None
      self.row2 = None
      self.row3 = None
      self.parent = None

      #new_ase_data = None
      if ase_object_type == 'geom':
         new_ase_data = Ase_mesh(self)
      self.ase_data = new_ase_data

class Ase_mesh:
   def __init__(self, ase_obj=None):
      self.name = 'Name'
      self.num = {'VERTS':0,'FACES':0,'CVERTEX':0,'CVFACES':0}
      self.ase_verts = {}
      self.vertseq = []
      self.ase_edges = {}
      self.ase_faces = {}
      self.faceseq = []
      self.ase_uv_channels = {}
      self.active_uv = None
      self.ase_vertcolors = {}
      self.ase_cfaces = {}
      self.autosmooth = 0
      self.hasUV = 0
      self.hasVC = 0

   def sort_edgekeys(self,vi0,vi1,vi2):
      '''
      Returns sorted edge keys of the given triangle vert indicies.
      '''
      if vi0 > vi1: ed_k0 = vi1,vi0
      else: ed_k0 = vi0,vi1
      if vi1 > vi2: ed_k1 = vi2,vi1
      else: ed_k1 = vi1,vi2
      if vi0 > vi2: ed_k2 = vi2,vi0
      else: ed_k2 = vi0,vi2
      return ed_k0,ed_k1,ed_k2

   def append_vert(self, ase_vert_index, x, y, z):
      '''
      Create a new Vertex for this Mesh.
      '''
      ase_v = Ase_vert(ase_vert_index, x, y, z)
      self.ase_verts[ase_vert_index] = ase_v
      #self.vertseq.insert(ase_vert_index, (ase_v.co.x,ase_v.co.y,ase_v.co.z))
      self.vertseq.insert(ase_vert_index, ase_v.co)
      
   def append_face(self, index, vi0, vi1, vi2, AB=1, BC=1, CA=1, smooth_groups=[0], mat_indices=0):
      '''
      Uhm ... work in progress!
      '''
      # create a new Ase_face
      ase_f = Ase_face(index, vi0, vi1, vi2, smooth_groups, mat_indices)
      ed_keys = self.sort_edgekeys(vi0,vi1,vi2)
      #ed_keys = [vi0,vi1].sort(),[vi1,vi2].sort(),[vi0,vi2].sort()
      ase_f.edge_keys = ed_keys
      ase_f.vis_sum = AB+BC+CA
      if ase_f.vis_sum == 2:
         if not AB: ase_f.tri_edge = ed_keys[0]
         elif not BC: ase_f.tri_edge = ed_keys[1]
         elif not CA: ase_f.tri_edge = ed_keys[2]

      # set visibility (fgon) and sharp for edges
      # and look if the two face users might form a quad
      # or create a new Ase_edge
      for k,vis in zip(ed_keys,[AB,BC,CA]):
         # Ase_edge already exist or create a new one
         if not self.ase_edges.has_key(k):
            ase_ed = Ase_edge(k)
            ase_ed.fusers.append(ase_f.index)
            ase_ed.visible = vis
            self.ase_edges[k] = ase_ed
            continue
         else:
            ase_ed = self.ase_edges[k]
            ase_ed.fusers.append(ase_f.index)
            if ase_f.vis_sum == 2 and not ase_ed.visible:
               ase_f.tri_edge = k

         fusers = [i for i in ase_ed.fusers if i != ase_f.index]
         if not fusers: continue
         for i in fusers:
            ase_f2 = self.ase_faces[i]
            # if this edge is invisible and both tris only have
            # this invisible edge, than the two tris could form a quad
            # easy done with a sum of all vis variables of the edges
            if k == ase_f.tri_edge:
               if ase_f.tri_edge == ase_f2.tri_edge:
                  ase_f.quad_team = ase_f2.index
                  ase_f2.quad_team = ase_f.index

            # look if this edge is sharp
            # if not both faces share at least one smoothgroup var
            # than this edge is sharp
            #if ase_ed.sharp: continue
            for sg in smooth_groups:
               if sg not in ase_f2.smooth_groups:
                  ase_ed.sharp = True

      self.ase_faces[ase_f.index] = ase_f
      self.faceseq.insert(ase_f.index, (ase_f.v0, ase_f.v1, ase_f.v2))

   def append_uv_channel(self, layer_index=1):
      '''
      Create a new UV Layer and set it active.
      '''
      self.ase_uv_channels[layer_index] = Ase_uv_channel(layer_index)
      self.active_uv = self.ase_uv_channels[layer_index]

   def append_tvert(self, ase_uv_index, u, v, w=0):
      '''
      Create a new UV Vector in the active! UV Channel.
      '''
      if not self.active_uv: return
      #self.active_uv.ase_tverts[ase_uv_index] = Ase_tvert(ase_uv_index,u,v,w)
      self.active_uv.ase_tverts[ase_uv_index] = (u,v)

   def append_tface(self, ase_face_index, uvi0, uvi1, uvi2, opt_check_seams=False):
      '''
      Create a new Face UV with indicies to UV Vectors in the active UV Layer.
      Optional check for Seams and store into the UV Channel.
      '''
      if not self.active_uv: return
      self.active_uv.ase_tfaces[ase_face_index] = [uvi0, uvi1, uvi2]
      # look if this face has seams
      # might useless because it makes no sense to import seams for all UV layers
      # that's why those edge keys are separately written to each ase UV layer
      if opt_check_seams:
         edge_keys = self.ase_faces[ase_face_index].edge_keys
         for ed_key,uvs in zip(edge_keys,[[uvi0,uvi1],[uvi1,uvi2],[uvi0,uvi2]]):
            uvs.sort()
            ase_ed,active_uv = self.ase_edges[ed_key],self.active_uv
            if not active_uv.ase_tedges.has_key(ed_key):
               active_uv.ase_tedges[ed_key] = uvs
               continue
            elif active_uv.ase_tedges[ed_key] != uvs:
               active_uv.seams.append(ed_key)

   def append_vertcol(self, ase_color_index, r, g, b):
      #new = Ase_vertcolor(ase_color_index, r, g, b)
      #self.ase_vertcolors[ase_color_index] = new
      self.ase_vertcolors[ase_color_index] = (r,g,b)
      
   def append_cface(self, ase_face_index, ci0, ci1, ci2):
      ase_f = self.ase_faces[ase_face_index]
      #f.c0, f.c1, f.c2 = ci0, ci1, ci2
      self.ase_cfaces[ase_face_index] = (ci0, ci1, ci2)

   def append_normal(self, ase_face_index, x, y, z):
      self.ase_faces[ase_face_index].normal = Blender.Mathutils.Vector(x,y,z)

   def append_vnormal(self, ase_face_index, ase_vert_index, x, y, z, opt_check_smooth=False):
      ase_f = self.ase_faces[ase_face_index]
      self.ase_verts[ase_vert_index].normals[ase_face_index] = Blender.Mathutils.Vector(x,y,z)
      if opt_check_smooth and ase_f.smooth_groups:
         ase_edges = [self.ase_edges[key] for key in ase_f.edge_keys]
         for ed_key,ase_ed in zip(ase_f.edge_keys,ase_edges):
            if ase_ed.sharp or len(ase_ed.fusers) < 2: continue
            for vi in ed_key:
               if not self.ase_verts.has_key(vi): continue
               vnormals = self.ase_verts[vi].normals
               fi0, fi1 = ase_ed.fusers[0:2]
               if vnormals.has_key(fi0) and vnormals.has_key(fi1):
                  vnor0, vnor1 = vnormals[fi0],vnormals[fi1]
                  if vnor0 == vnor1:
                     continue
                  else:
                     angle = round(Blender.Mathutils.AngleBetweenVecs(vnor0, vnor1))
                     if not self.autosmooth: self.autosmooth = angle
                     elif angle and self.autosmooth > angle:
                        print angle
                        self.autosmooth = angle


class Ase_vert:
   def __init__(self, index, x, y, z):
      self.index = index
      #self.co = Blender.Mathutils.Vector(x,y,z)
      self.co = (x,y,z)
      self.normals = {}

class Ase_edge:
   def __init__(self, key):
      self.key = key
      self.fusers = []
      self.uvs = None
      self.visible = 1
      self.sharp = False

class Ase_face:
   def __init__(self, ase_face_index, v0, v1, v2, smooth_groups=0, mat_indices=0):
      self.index = ase_face_index
      self.v0 = v0
      self.v1 = v1
      self.v2 = v2
      self.edge_keys = None
      self.c0 = None
      self.c1 = None
      self.c2 = None
      self.normal = None
      #self.vert_normals = {}
      self.mat_indices = mat_indices
      self.smooth_groups = smooth_groups # 0 = solid face
      self.vis_sum = 3
      self.quad_team = None
      self.tri_edge = None

class Ase_uv_channel:
   def __init__(self, index=1):
      self.index = index
      self.num = {'TVERTEX':0,'TVFACES':0}
      self.uv_layer_name = 'UVTex#' + str(self.index)
      self.ase_tverts = {}
      self.ase_tfaces = {}
      self.ase_tedges = {}
      self.seams = []

class Ase_tvert:
   def __init__(self,index, u, v, w=0):
      self.index = index
      #self.vec = Blender.Mathutils.Vector(u,v)
      self.vec = (u,v)

class Ase_tface:
   def __init__(self, index, uvi0, uvi1, uvi2):
      self.index = index
      self.uv = {0:uvi0, 1:uvi1, 2:uvi2}

class Ase_vertcolor:
   def __init__(self, index, r, g, b):
      self.index = 0
      self.r = round(r*256)
      self.g = round(g*256)
      self.b = round(b*256)
      self.a = 255.0


def spawn(ase_objects):

   PB_index = 0.0
   PB_num = float(len(ase_objects))

   print 'Import Objects...'
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   scene = Blender.Scene.GetCurrent()
   for ase_ob in ase_objects:
      if OPT_PROGRESSBAR and not (PB_index % PB_num):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Importing Objects...")

      if ase_ob.ase_type == 'geom':
         spawn_mesh(scene,ase_ob)

      PB_index += 1.0

def spawn_mesh(scene,ase_ob):

   ase_me = ase_ob.ase_data
   #normal_flag = 1

   row0 = ase_ob.row0
   row1 = ase_ob.row1
   row2 = ase_ob.row2
   row3 = ase_ob.row3

   matrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   matrix.resize4x4()

   # create new Blender Object and link to scene
   ob = Blender.Object.New('Mesh', ase_ob.name)
   ob.setMatrix(matrix)
   scene.objects.link(ob)

   # get Mesh data from Object
   me = ob.getData(0,1)
   me.vertexColors = me.faceUV = False

   # create Verts and Faces
   # seems like extend() is limited to a length of 64000?
   # this is a problem when importing big meshes.
   div = divmod(ase_me.num['VERTEX'], 64000)
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.verts.extend(ase_me.vertseq[start:end])
      start = end
   div = divmod(ase_me.num['FACES'], 64000)
   face_index_list = []
   if div[1]: div = div[0]+1
   else: div = div[0]
   start = 0
   for i in range(div):
      end = start+64000
      me.faces.extend(ase_me.faceseq[start:end])
      start = end

   # import Vertex Colors, Solid/Smooth to faces
   if IMP_VCOLOR:
      me.vertexColors = ase_me.hasVC
      ase_vcolors = ase_me.ase_vertcolors
   for i,ase_f in ase_me.ase_faces.iteritems():
      try:f = me.faces[i]
      except:
         # dont know what's the problem with this
         print 'array index out of range:', i
         continue
      if me.vertexColors:
         cface = ase_me.ase_cfaces[i]
         c0,c1,c2 = ase_vcolors[cface[0]],ase_vcolors[cface[1]],ase_vcolors[cface[2]]
         fc0,fc1,fc2 = f.col[:]
         fc0.r,fc0.g,fc0.b = int(c0[0]*255),int(c0[1]*255),int(c0[2]*255)
         fc1.r,fc1.g,fc1.b = int(c1[0]*255),int(c1[1]*255),int(c1[2]*255)
         fc2.r,fc2.g,fc2.b = int(c2[0]*255),int(c2[1]*255),int(c2[2]*255)
      if ase_f.smooth_groups:
         f.smooth = 1

   # import UV layer's
   if IMP_UV and ase_me.hasUV:
      for uv_chan in ase_me.ase_uv_channels.itervalues():
         me.addUVLayer(uv_chan.uv_layer_name)
         me.activeUVLayer = uv_chan.uv_layer_name
         tverts = uv_chan.ase_tverts
         for fi,uvis in uv_chan.ase_tfaces.iteritems():
            try:f = me.faces[fi]
            except: continue
            uv1,uv2,uv3 = tverts[uvis[0]],tverts[uvis[1]],tverts[uvis[2]]
            f.uv = [Blender.Mathutils.Vector(uv1), Blender.Mathutils.Vector(uv2), Blender.Mathutils.Vector(uv3)]
      me.activeUVLayer = ase_me.ase_uv_channels[1].uv_layer_name

   # EXPERIMENTAL!
   # convert tris to quads
   # this is currently the easiest way i found without destroying uvs or vcolors
   # but don't work like expected...:/
   if IMP_QUADS:
      #quad_teams = set([i for i,ase_f in ase_me.ase_faces.iteritems() if ase_f.quad_team != None])
      quad_teams = []
      for i,ase_f in ase_me.ase_faces.iteritems():
         if ase_f.quad_team != None:
            if ase_f.index < ase_f.quad_team: qt = ase_f.index,ase_f.quad_team
            elif ase_f.index > ase_f.quad_team: qt = ase_f.quad_team,ase_f.index
            if qt not in quad_teams:
               quad_teams.append(qt)

      faces = me.faces
      # first deselect all faces
      for f in faces: f.sel = 0
      for t0,t1 in quad_teams:
         ase_f0 = ase_me.ase_faces[t0]
         ase_f1 = ase_me.ase_faces[t1]
         try: f0,f1 = me.faces[ase_f0.index], me.faces[ase_f1.index]
         except: continue
         f0.sel = 1
         f1.sel = 1
         me.triangleToQuad()
         for i in faces.selected():
            faces[i].sel = 0

   # apply the matrix to mesh (and optional fit the ob and me to blender)
   if IMP_SCALED:
      # seems this isn't accurate because of precision of the location vector
      scale = Blender.Mathutils.ScaleMatrix(OPT_SCALE,4)
      inv_matrix = ob.getMatrix().copy().invert() * scale
      ob.setLocation(ob.getMatrix().translationPart() * scale)
   else:
      inv_matrix = ob.getMatrix().copy().invert()
   me.transform(inv_matrix, 1)
   me.calcNormals()

   # apply sharp, seam and fgon flags to edges.
   add_EDGESPLIT = False
   if IMP_FGONS or IMP_SEAMS or IMP_SMOOTHGROUPS:
      SHARP = Mesh.EdgeFlags.SHARP
      SEAM = Mesh.EdgeFlags.SEAM
      FGON = Mesh.EdgeFlags.FGON
      seam_keys = []
      if ase_me.hasUV: seam_keys = ase_me.ase_uv_channels[1].seams
      for k,ase_ed in ase_me.ase_edges.iteritems():
         if ase_ed.sharp or not ase_ed.visible or k in seam_keys:
            edi = me.findEdges(k[0],k[1])
            if edi:
               ed = me.edges[edi]
               if ase_me.hasUV and k in seam_keys and IMP_SEAMS: ed.flag |= SEAM
               if not ase_ed.visible and IMP_FGONS: ed.flag |= FGON
               if ase_ed.sharp and IMP_SMOOTHGROUPS:
                    ed.flag |= SHARP
                  add_EDGESPLIT = True



   # add EdgeSplit Modiefier when the mesh has sharp edges
   # autosmooth is EXPERIMENTAL! because i dont know if this is correct!
   if add_EDGESPLIT and OPT_MOD_EDGESPLIT:
      mod = ob.modifiers.append(Blender.Modifier.Types.EDGESPLIT)
      if not ase_me.autosmooth:
         mod[Blender.Modifier.Settings.EDGESPLIT_FROM_ANGLE] = 0
      else:
         mod[Blender.Modifier.Settings.EDGESPLIT_ANGLE] = ase_me.autosmooth
      mod[Blender.Modifier.Settings.EDGESPLIT_FROM_SHARP] = 1
      ob.makeDisplayList() # Needed to apply the modifier
   elif not add_EDGESPLIT and ase_me.autosmooth:
      AUTOSMOOTH = Mesh.Modes.AUTOSMOOTH
      me.modes |= AUTOSMOOTH
      me.degr = ase_me.autosmooth

   me.update()
   counts['verts'] += ase_me.num['VERTEX']
   counts['tris'] += ase_me.num['FACES']
   counts['faces'] += len(me.faces)
   print 'Imported Mesh-Object: ', ob.name

#def oj_the_object_jockey(file):
def read_file(file):
   '''
   Read an .ase file and return a list of ase_objects
   '''
   lines= file.readlines()

   print 'Read file...'
   PB_index = 0.0
   PB_num = float(len(lines))
   if OPT_PROGRESSBAR: Blender.Window.DrawProgressBar(0.0, "Read File...")

   # it is needed to read UV if Seams should be imported even when importing UV is disabled
   READ_UV = False
   if IMP_UV or IMP_SEAMS: READ_UV = True
   #if IMP_AUTOSMOOTH and not IMP_SMOOTHGROUPS: IMP_AUTOSMOOTH = False

   ase_objects = []
   ase_ob = False
   for line in lines:
      if OPT_PROGRESSBAR and not (PB_index % 10000):
         Blender.Window.DrawProgressBar(PB_index / PB_num, "Read File...")
      PB_index += 1

      words = line.split()
      if not words:
         continue
      word0 = words[0]
      if word0 == '*GEOMOBJECT':
         #if ase_ob: ase_objects.append(ase_ob)
         ase_ob_type = word0.lower()[1:-6] #get rid of '*' and 'OBJECT'
         ase_ob = Ase_object(ase_ob_type)
         ase_objects.append(ase_ob)
         continue
      elif word0 in ['*HELPEROBJECT','*SHAPEOBJECT','*LIGHTOBJECT','*CAMERAOBJECT','*GROUP']:
         # Not supported objects!
         # because these objects too use a TM_NODE,
         # ase_ob should be set back to False to prevent errors.
         ase_ob = False
         continue
      elif word0 == '*NODE_NAME' and ase_ob:
         name = words[1][1:-1] #get rid of '"'
         if ase_ob and ase_ob.name != '': ase_ob.ase_data.name = name
         elif ase_ob: ase_ob.name = name
         continue
      elif word0 == '*NODE_PARENT' and ase_ob:
         ase_ob.parent = words[1][1:-1] #get rid of '"'
         continue
      elif word0 == '*TM_ROW0' and ase_ob:
         ase_ob.row0 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW1' and ase_ob:
         ase_ob.row1 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW2' and ase_ob:
         ase_ob.row2 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*TM_ROW3' and ase_ob:
         ase_ob.row3 = float(words[1]), float(words[2]), float(words[3])
         continue
      elif word0 == '*MESH':
         ase_me = ase_ob.ase_data
         continue
      elif word0 == '*MESH_NUMVERTEX':
         ase_me.num['VERTEX'] = int(words[1])
         continue
      elif word0 == '*MESH_NUMFACES':
         ase_me.num['FACES'] = int(words[1])
         continue
      elif word0 == '*MESH_VERTEX':
         #vert_index, x, y, z
         ase_me.append_vert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
         continue
      elif word0 == '*MESH_FACE':
         #ase_face_index, vi0, vi1, vi2, AB, BC, CA, smooth_groups, mat_indicies
         #smooth = mat = False
         ase_face_index = words[1]
         if ase_face_index.endswith(':'):
            ase_face_index = ase_face_index[:-1]

         smooth_groups = mat_indices = []
         for i,w in enumerate(words):
            if w == '*MESH_SMOOTHING' and IMP_SMOOTHGROUPS:
               try:
                  if words[i+1] != '*MESH_MTLID':
                     smooth_groups = [int(i) for i in words[i+1].split(',')]
               except:
                  smooth_groups = 0
            elif w == '*MESH_MTLID' and IMP_SMOOTHGROUPS:
               try:
                  mat_indices = [int(i) for i in words[i+1].split(',')]
               except:
                  mat_indices = 0
         ase_me.append_face(int(ase_face_index),int(words[3]),int(words[5]),int(words[7]),int(words[9]),int(words[11]),int(words[13]),smooth_groups,mat_indices)
         continue
      elif READ_UV:
         if word0 == '*MESH_NUMTVERTEX':
            if not ase_me.ase_uv_channels: ase_me.append_uv_channel()
            ase_me.active_uv.num['TVERTEX'] = int(words[1])
            ase_me.hasUV = True
            continue
         elif word0 == '*MESH_MAPPINGCHANNEL':
            # uv_channel_index
            ase_me.append_uv_channel(int(words[1]))
            continue
         elif word0 == '*MESH_TVERT':
            #uv_index, u, v, w
            ase_me.append_tvert(int(words[1]),float(words[2]),float(words[3]),float(words[4]))
            continue
         elif word0 == '*MESH_NUMTVFACES':
            ase_me.active_uv.num['TVFACES'] = int(words[1])
            continue
         elif word0 == '*MESH_TFACE':
            #ase_face_index, uv0, uv1, uv2, opt_IMP_SEAMS
            ase_face_index = words[1]
            if ase_face_index.endswith(':'):
               ase_face_index = ase_face_index[:-1]
            ase_me.append_tface(int(ase_face_index),int(words[2]),int(words[3]),int(words[4]),IMP_SEAMS)
            continue
      elif IMP_VCOLOR:
         if word0 == '*MESH_NUMCVERTEX':
            ase_me.num['CVERTEX'] = int(words[1])
            if ase_me.num['CVERTEX']:
               ase_me.hasVC = True
            continue
         elif word0 == '*MESH_VERTCOL':
            #color_index, r, g, b



Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Wed May 31, 2006 3:07 pm    Post subject: : There was a space at end of the line if you copy/paste the script from the forum. I have put the array in one line, should work now.


kat@Posted: Wed May 31, 2006 6:19 pm    Post subject: : DUDE!! sorted. Both vertex and UVW import work fine and dandy.
_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Tue Aug 15, 2006 12:07 pm    Post subject: : Fixed a problem with the matrices, dont know why this suddenly happened.

[edit]
I quickly updated it again (to v0.12) Very Happy to use some improvements of 2.42 (which doesn't worked with 2.40). Now it should import (big) meshes much faster.


Last edited by Goofos on Tue Aug 15, 2006 12:34 pm; edited 1 time in total



Tweaker@Posted: Fri Aug 25, 2006 2:29 am    Post subject: : Excellent, I was having problems importing with 2.42a, but this seems to have fixed it. Thanks. Very Happy


Goofos@Posted: Mon Apr 17, 2006 2:00 am    Post subject: ASE Importer: I made a first small script to import ASE meshes. Its not perfect and may a bit lame but should import correct meshes (from 3DS). Materials are currently not supported but UV coords and VertexColors.
Note: Meshes from 3DS are very big in Blender Very Happy

Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.12'
Blender: 242
Group: 'Import'
Tooltip: 'ASCII Scene import (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.12"

# goofos at epruegel.de
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 *****

import string, time, sys as osSys
import Blender
from Blender import Draw, Mesh, Window, Object, Scene
#import meshtools


def read_main(filename):

   global counts
   counts = {'verts': 0, 'tris': 0}

   start = time.clock()
   file = open(filename, "r")

   print_boxed("----------------start-----------------")
   print 'Import Patch: ', filename

   editmode = Window.EditMode()    # are we in edit mode?  If so ...
   if editmode: Window.EditMode(0) # leave edit mode before getting the mesh

   lines= file.readlines()
   read_file(file, lines)

   Blender.Window.DrawProgressBar(1.0, '')  # clear progressbar
   file.close()
   print "----------------end-----------------"
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i " % (counts['verts'], counts['tris'])
   print_boxed(totals)
   message = "Successfully imported " + Blender.sys.basename(filename) + seconds
   #meshtools.print_boxed(message)
   print_boxed(message)


def print_boxed(text): #Copy/Paste from meshtools, only to remove the beep :)
   lines = text.splitlines()
   maxlinelen = max(map(len, lines))
   if osSys.platform[:3] == "win":
      print chr(218)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(191)
      for line in lines:
         print chr(179) + ' ' + line.ljust(maxlinelen) + ' ' + chr(179)
      print chr(192)+chr(196) + chr(196)*maxlinelen + chr(196)+chr(217)
   else:
      print '+-' + '-'*maxlinelen + '-+'
      for line in lines: print '| ' + line.ljust(maxlinelen) + ' |'
      print '+-' + '-'*maxlinelen + '-+'
   #print '\a\r', # beep when done


class ase_obj:

   def __init__(self):
      self.name = 'Name'
      self.objType = None
      self.row0x = None
      self.row0y = None
      self.row0z = None
      self.row1x = None
      self.row1y = None
      self.row1z = None
      self.row2x = None
      self.row2y = None
      self.row2z = None
      self.row3x = None
      self.row3y = None
      self.row3z = None
      self.parent = None
      self.obj = None
      self.objName = 'Name'

class ase_mesh:

   def __init__(self):
      self.name = ''
      self.vCount = 0
      self.fCount = 0
      self.uvVCount = 0
      self.uvFCount = 0
      self.vcVCount = 0
      self.vcFCount = 0
      self.meVerts = []
      self.meFaces = []
      self.uvVerts = []
      self.uvFaces = []
      self.vcVerts = []
      self.vcFaces = []
      self.hasFUV = 0
      self.hasVC = 0

class mesh_face:

   def __init__(self):
      self.v1 = 0
      self.v2 = 0
      self.v3 = 0
      self.mat = None
       
class mesh_vert:

   def __init__(self):
      self.x = 0.0
      self.y = 0.0
      self.z = 0.0

class mesh_uvVert:

   def __init__(self):
      self.index = 0
      self.u = 0.0
      self.v = 0.0
      self.vec = Blender.Mathutils.Vector(self.u, self.v)

class mesh_uvFace:

   def __init__(self):
      self.index = 0
      self.uv1 = 0
      self.uv2 = 0
      self.uv3 = 0
       
class mesh_vcVert:

   def __init__(self):
      self.index = 0
      self.r = 0
      self.g = 0
      self.b = 0
      self.a = 255
       
class mesh_vcFace:

   def __init__(self):
      self.index = 0
      self.c1 = 0
      self.c2 = 0
      self.c3 = 0


def read_file(file, lines):

   objects = []
   objIdx = 0
   objCheck = -1 #needed to skip helper objects
   PBidx = 0.0
   lineCount = float(len(lines))

   print 'Read file'
   Blender.Window.DrawProgressBar(0.0, "Read File...")

   for line in lines:
      words = string.split(line)

      if (PBidx % 10000) == 0.0:
                   Blender.Window.DrawProgressBar(PBidx / lineCount, "Read File...")

      if not words:
         continue
      elif words[0] == '*GEOMOBJECT':
         objCheck = 0
         newObj = ase_obj()
         objects.append(newObj)
         obj = objects[objIdx]
         objIdx += 1
      elif words[0] == '*NODE_NAME' and objCheck != -1:
         if objCheck == 0:
            obj.name = words[1]
            objCheck = 1
         elif objCheck == 1:
            obj.objName = words[1]
      elif words[0] == '*TM_ROW0' and objCheck != -1:
         obj.row0x = float(words[1])
         obj.row0y = float(words[2])
         obj.row0z = float(words[3])
      elif words[0] == '*TM_ROW1' and objCheck != -1:
         obj.row1x = float(words[1])
         obj.row1y = float(words[2])
         obj.row1z = float(words[3])
      elif words[0] == '*TM_ROW2' and objCheck != -1:
         obj.row2x = float(words[1])
         obj.row2y = float(words[2])
         obj.row2z = float(words[3])
      elif words[0] == '*TM_ROW3' and objCheck != -1:
         obj.row3x = float(words[1])
         obj.row3y = float(words[2])
         obj.row3z = float(words[3])
         objCheck = -1
      elif words[0] == '*MESH':
         obj.objType = 'Mesh'
         obj.obj = ase_mesh()
         me = obj.obj
      elif words[0] == '*MESH_NUMVERTEX':
         me.vCount = int(words[1])
      elif words[0] == '*MESH_NUMFACES':
         me.fCount = int(words[1])
      elif words[0] == '*MESH_VERTEX':
         #v = mesh_vert()
         v = [float(words[2]),float(words[3]),float(words[4])]
         #v.x = float(words[2])
         #v.y = float(words[3])
         #v.z = float(words[4])
         me.meVerts.append(v)
      elif words[0] == '*MESH_FACE':
         #f = mesh_face()
         f = [int(words[3]),int(words[5]),int(words[7])]
         #f.v1 = int(words[3])
         #f.v2 = int(words[5])
         #f.v3 = int(words[7])
         me.meFaces.append(f)
      elif words[0] == '*MESH_NUMTVERTEX':
         me.uvVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasFUV = 1
      elif words[0] == '*MESH_TVERT':
         uv = mesh_uvVert()
         uv.index = int(words[1])
         uv.u = float(words[2])
         uv.v = float(words[3])
         me.uvVerts.append(uv)
      elif words[0] == '*MESH_NUMTVFACES':
         me.uvFCount = int(words[1])
      elif words[0] == '*MESH_TFACE':
         fUv = mesh_uvFace()
         fUv.index = int(words[1])
         fUv.uv1 = int(words[2])
         fUv.uv2 = int(words[3])
         fUv.uv3 = int(words[4])
         me.uvFaces.append(fUv)
      elif words[0] == '*MESH_NUMCVERTEX':
         me.vcVCount = int(words[1])
         if me.uvVCount > 0:
            me.hasVC = 1
      elif words[0] == '*MESH_VERTCOL':
         c = mesh_vcVert()
         c.index = int(words[1])
         c.r = round(float(words[2])*256)
         c.g = round(float(words[3])*256)
         c.b = round(float(words[4])*256)
         me.vcVerts.append(c)
      elif words[0] == '*MESH_CFACE':
         fc = mesh_vcFace()
         fc.index = int(words[1])
         fc.c1 = int(words[2])
         fc.c2 = int(words[3])
         fc.c3 = int(words[4])
         me.vcFaces.append(fc)

      PBidx += 1.0

   spawn_main(objects)

   Blender.Redraw()

def spawn_main(objects):

   PBidx = 0.0
   objCount = float(len(objects))

   print 'Import Objects'
   Blender.Window.DrawProgressBar(0.0, "Importing Objects...")

   for obj in objects:

      Blender.Window.DrawProgressBar(PBidx / objCount, "Importing Objects...")

      if obj.objType == 'Mesh':
         spawn_mesh(obj)

      PBidx += 1.0


def spawn_mesh(obj):

   objMe = obj.obj
   #normal_flag = 1

   row0 = obj.row0x, obj.row0y, obj.row0z
   row1 = obj.row1x, obj.row1y, obj.row1z
   row2 = obj.row2x, obj.row2y, obj.row2z
   row3 = obj.row3x, obj.row3y, obj.row3z

   newMatrix = Blender.Mathutils.Matrix(row0, row1, row2, row3)
   newMatrix.resize4x4()

   newObj = Blender.Object.New(obj.objType, obj.name)
   newObj.setMatrix(newMatrix)
   Blender.Scene.getCurrent().link(newObj)


   newMesh = Blender.Mesh.New(obj.objName)
   newMesh.getFromObject(newObj.name)


   # Verts
   newMesh.verts.extend(objMe.meVerts)

   # Faces
   newMesh.faces.extend(objMe.meFaces)

   #VertCol
   if guiTable['VC'] == 1 and objMe.hasVC == 1:
      newMesh.vertexColors = 1
      for c in objMe.vcFaces:

         FCol0 = newMesh.faces[c.index].col[0]
         FCol1 = newMesh.faces[c.index].col[1]
         FCol2 = newMesh.faces[c.index].col[2]

         FCol0.r = int(objMe.vcVerts[c.c1].r)
         FCol0.g = int(objMe.vcVerts[c.c1].g)
         FCol0.b = int(objMe.vcVerts[c.c1].b)

         FCol1.r = int(objMe.vcVerts[c.c2].r)
         FCol1.g = int(objMe.vcVerts[c.c2].g)
         FCol1.b = int(objMe.vcVerts[c.c2].b)

         FCol2.r = int(objMe.vcVerts[c.c3].r)
         FCol2.g = int(objMe.vcVerts[c.c3].g)
         FCol2.b = int(objMe.vcVerts[c.c3].b)

   # UV
   if guiTable['UV'] == 1 and objMe.hasFUV == 1:
      newMesh.faceUV = 1
      for f in objMe.uvFaces:
         uv1 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv1].u), float(objMe.uvVerts[f.uv1].v))
         uv2 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv2].u), float(objMe.uvVerts[f.uv2].v))
         uv3 = Blender.Mathutils.Vector(float(objMe.uvVerts[f.uv3].u), float(objMe.uvVerts[f.uv3].v))
         newMesh.faces[f.index].uv = [uv1, uv2, uv3]

   newMesh.transform((newObj.getMatrix('worldspace').invert()), 1)
   newObj.link(newMesh)

   counts['verts'] += objMe.vCount
   counts['tris'] += objMe.fCount
   print 'Imported Mesh-Object: ', obj.name



def read_ui(filename):

   global guiTable, IMPORT_VC, IMPORT_UV
   guiTable = {'VC': 1, 'UV': 1}

   for s in Window.GetScreenInfo():
      Window.QHandle(s['id'])

   IMPORT_VC = Draw.Create(guiTable['VC'])
   IMPORT_UV = Draw.Create(guiTable['UV'])

   # Get USER Options
   pup_block = [('Import Options'),('Vertex Color', IMPORT_VC, 'Import Vertex Colors if exist'),('UV', IMPORT_UV, 'Import UV if exist'),]

   if not Draw.PupBlock('Import...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['VC'] = IMPORT_VC.val
   guiTable['UV'] = IMPORT_UV.val

   read_main(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(read_ui, 'Import ASCII Scene', ('.ase'))


Last edited by Goofos on Tue Aug 15, 2006 12:25 pm; edited 4 times in total



Bittoman@Posted: Mon Apr 17, 2006 1:12 pm    Post subject: : Nice job, thanks Goofos!


kat@Posted: Mon Apr 17, 2006 10:30 pm    Post subject: : Not tried it yet but 'GG' on doing this one. Another step up the ladder for Blender!
_________________
Co-Admin - Modelling and modding tutorials and tips



kat@Posted: Fri May 19, 2006 8:04 pm    Post subject: : Just tried this script for the 1st time and encountered the following error with Blender 2.41 when run as a script from the text window (Alt+P).
Code:
IndentationError: unindent does not match any outer indentation level
  File "goofosASE_import_17Ap", line 295
    if obj.objType == 'Mesh':
                             ^

_________________
Co-Admin - Modelling and modding tutorials and tips



Goofos@Posted: Sun May 21, 2006 3:58 pm    Post subject: : Should work now. Seems my OS is a bit more tollerant with format errors :>


OrbWeaver@Posted: Fri May 26, 2006 10:43 am    Post subject: : I haven't tried this but it sounds great. Until now ASE has been almost universally considered an "export-only" format.


kat@Posted: Fri May 26, 2006 5:33 pm    Post subject: New error: New error when doing Ctrl+P to run the script
Code:
SyntaxError: invalid token
  File "goofosASE_import_26Ma", line 382
    pup_block = [\
                  ^

_________________
Co-Admin - Modelling and modding tutorials and tips