Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Wed Jun 19, 2013 9:25 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 277 posts ]  Go to page 1, 2, 3, 4, 5 ... 14  Next
Author Message
 Post subject: new ASE Exporter
PostPosted: Thu Mar 10, 2005 3:25 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 3:05 am
Posts: 177
Location: black forrest
:arrow: current Version: 0.6.10

- will not work with blender versions below 2.44.
- can export mesh objects with tris or quads (and maybe fgons as ngons), uv coords (plus multiple uv layers, note that in the ase format the materials don't support multiple uv layers) and vertex colors, materials (Standard and Multi/Sub-Object) with a Image Texture.
- normals are completley new calculated. This is needed for exporting quads!
- export all selected Objects or if nothing is selected, all (Mesh) Objects of the current Scene
- Released under the GNU GPL License


I think some bugs or wrong exported values are given especialy in the material part and mesh transformations, but its beta :lol:

You can create SmoothGroups -> make a VertexGroup, name it "smooth." and a group number, f.e. "smooth.2". The number is stored in the faces via *MESH_SMOOTHING.

If you don't use the VertGroup 2 SmoothGroup Option, it will export at least solid or smooth faces.

Objects with Vertex Color are only possible if the mesh has no materials or materials which have enabled "VCOL Paint".


Code:
#!BPY

"""
Name: 'ASCII Scene (.ase) v0.6.10'
Blender: 244
Group: 'Export'
Tooltip: 'ASCII Scene Export (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.6.10"
__url__ = ["http://www.doom3world.org","http://www.doom3world.org/phpbb2/viewtopic.php?f=50&t=9275&st=0&sk=t&sd=a"]
__bpydoc__ = """\
-- ASCII Scene Export (.ase) export script v0.6.10 for Blender 2.44 --<br>

Can export:<br>
-Mesh Objects<br>
-Materials and Textures (no Procedural but Image)<br>
   Note: Normalmaps will be exported as Bumpmaps (FixMe).
      Image path depends on how you have loaded it
      (absolute path's looks better :))
   Currently supported: Amb, Col, Csp, Hard, Alpha, Nor, Disp<br>
-Vertex Colors<br>
   Note: If the mesh has materials you must enable "Vcol Paint"
   in Material tab. Without Materials, make sure "VertCol"
   in Mesh tab is enabled. Seems like the ASE Format doesn't
   support multiple Vertex Color layers.<br>
-Face UV<br>
   Make sure "TexFace" in Mesh tab is enabled.
   Multi UV layers are now supported<br>
-Solid or Smooth Faces<br>
   ... smoothgroups currently only with a workaround. Solid
   faces will not have a smoothgroup, smooth faces will be by default in
   smoothgroup 1.<br>

-- Export Options Description --<br>
Apply Modifiers: Export the mesh with applied modifiers.
   Note: This uses the render settings of the modifiers.<br>
Materials: Export Materials if any.<br>
Face UV: Export TexFace UV if any. The current active UV Layer will be used
   as the first mapping channel.<br>
Vertex Colors: Export Vertex Colors if any (See note above). The
   current VC Layer will be used.<br>
Selection Only: Export only selected Objects or if nothing is selected
   all Objects.<br>
VertGr. as SmoothGr.: You can export SmoothGroups defined by
   VertexGroups. Simply create a VertGroup and name it "smooth." plus
   a group number, e.g. "smooth.2". Please note that you should not use
   more than 32 smoothgroups!
   Vertex Normals currently might not calculated right!!
   And there is a simple problem, if you add e.g. 3 faces of a cube
   to a smoothgroup, all 6 faces will be in the smoothgroup!! This is
   because the verts of the other 3 faces are in that group, too.
   You can see this if you select the vertexgroup.<br>
Center Objects: Move all objects to the World Grid Center.
"""
# 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 Blender, time, math, sys as osSys #os
from Blender import sys, Window, Draw, Scene, Mesh, Material, Texture, Image, Mathutils

#============================================
#           Write!
#============================================

def write(filename):
   start = time.clock()
   print_boxed('---------Start of Export------------')
   print 'Export Path: ' + filename

   global exp_list, Tab, idnt, imgTable, worldTable

   exp_list =[]
   Tab = "\t"
   idnt = 1
   matTable = {}
   worldTable = {'ambR': 0.0, 'ambG': 0.0, 'ambB': 0.0, 'horR': 0.0, 'horG': 0.0, 'horB': 0.0} #default
   total = {'Verts': 0, 'Tris': 0, 'Faces': 0}
   
   scn = Blender.Scene.GetCurrent()

   set_up(scn, exp_list, matTable, worldTable)
   if not exp_list:
      #if there is nothing to export, end here
      return

   file = open(filename, "w")
   write_header(file, filename, scn, worldTable)
   write_materials(file, exp_list, worldTable, matTable)
   write_mesh(file, scn, exp_list, matTable, total)
   file.close()
   
   Blender.Window.DrawProgressBar(0, "")    # clear progressbar
   end = time.clock()
   seconds = " in %.2f %s" % (end-start, "seconds")
   totals = "Verts: %i Tris: %i Faces: %i" % (total['Verts'], total['Tris'], total['Faces'])
   print_boxed(totals)
   name = filename.split('/')[-1].split('\\')[-1]
   message = "Successfully exported " + name + 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

#============================================
#           Setup
#============================================

def set_up(scn, exp_list, matTable, worldTable):
   print "Setup"
   #Get selected Objects or if none selected all Objects from the current Scene
   if scn.objects.selected and guiTable['SELO'] == 1:
      objects = scn.objects.selected
   elif scn.objects:
      objects = scn.objects
   else:
      print "No Objects"
      return

   set_lists(exp_list, objects, matTable, worldTable)


def set_lists(exp_list, objects, matTable, worldTable):
   global mat_cnt
   mat_cnt = 0
   mat_index = 0
   #exp_list = [container1 = [ [mesh], [material_ref] ],...]

   for current_obj in objects:
      container = []
      if current_obj.getType() == 'Mesh':
         container.append(current_obj)

         mat_type = 0 #1=Material, 2=UV Images
         mat_ref = []
         mesh = current_obj.data
         mats_me = mesh.materials
         mats_ob = current_obj.getMaterials(0)
         #Find used Materials by Meshes or Objects
         if guiTable['MTL'] == 1 and mats_me or mats_ob: #Materials
            if mats_me:
               me_mats = mats_me
            elif mats_ob:
               me_mats = mats_ob
            mat_ref = -1

            for i,m in matTable.iteritems():
               for mat in me_mats:
                  if mat in m:
                     for amat in me_mats:
                        if amat not in m:
                           m.append(amat)
                     mat_ref = i
                     break

            if mat_ref < 0:
               matTable[mat_index] = me_mats
               mat_ref = mat_index
               mat_cnt+=1
               mat_index+=1
         container.append(mat_ref)
         exp_list.append(container)

   #If there is a world shader get some values
   world = Blender.World.GetCurrent()
   if world != None:
      worldAmb = world.getAmb()
      worldHor = world.getHor()

      worldTable['ambR'] = worldAmb[0]
      worldTable['ambG'] = worldAmb[1]
      worldTable['ambB'] = worldAmb[2]

      worldTable['horR'] = worldHor[0]
      worldTable['horG'] = worldHor[1]
      worldTable['horB'] = worldHor[2]



#============================================
#           Header/Scene
#============================================

def write_header(file, filename, scn, worldTable):
   print "Write Header"

   context = scn.getRenderingContext()

   file.write("*3DSMAX_ASCIIEXPORT%s200\n" % (Tab))
   file.write("*COMMENT \"Exported from Blender %s - %s\"\n" % (Blender.Get('version'), time.asctime(time.localtime())))
   file.write("*SCENE {\n")
   #file.write("%s*SCENE_FILENAME \"%s\"\n" % (Tab, os.path.basename(Blender.Get('filename'))))
   name = Blender.Get('filename').split('/')[-1].split('\\')[-1] #Blender 2.44
   file.write("%s*SCENE_FILENAME \"%s\"\n" % (Tab, name))

   file.write("%s*SCENE_FIRSTFRAME %d\n" % (Tab,context.startFrame()))
   file.write("%s*SCENE_LASTFRAME %d\n" % (Tab,context.endFrame()))
   file.write("%s*SCENE_FRAMESPEED %d\n" % (Tab,context.framesPerSec()))
   file.write("%s*SCENE_TICKSPERFRAME 160\n" % (Tab)) #Blender has no Ticks?

   file.write("%s*SCENE_BACKGROUND_STATIC %.4f %.4f %.4f\n" % (Tab, worldTable['horR'], worldTable['horG'], worldTable['horB']))
   file.write("%s*SCENE_AMBIENT_STATIC %.4f %.4f %.4f\n" % (Tab, worldTable['ambR'], worldTable['ambG'], worldTable['ambB']))
   file.write("}\n")


#============================================
#           Materials
#============================================

def write_materials(file, exp_list, worldTable, matTable):
   print "Write Materials"

   file.write("*MATERIAL_LIST {\n")
   file.write("%s*MATERIAL_COUNT %s\n" % (Tab, mat_cnt))

   for i,m in matTable.iteritems():
      if len(m) == 1: # single mat
         mat_class = 'Standard'

         mats = m
         material = mats[0]
         mat_name = material.name

         file.write("%s*MATERIAL %d {\n" % ((Tab), i))

         idnt = 2
         mat_para(file, idnt, material, mat_name, mat_class, worldTable)
         mat_dummy(file, idnt)
         mat_map(file, idnt, mat_name)

         file.write("%s}\n" % (Tab))

      elif len(m) > 1: # multiple mat
         mat_class = 'Multi/Sub-Object'

         mats = m
         material = mats[0]
         mat_name = 'Multi # ' + material.name
         submat_no = len(mats)

         idnt = 2
         file.write("%s*MATERIAL %d {\n" % ((Tab), i))

         mat_para(file, idnt, material, mat_name, mat_class, worldTable)

         file.write("%s*NUMSUBMTLS %d\n" % ((Tab*idnt), submat_no))

         for submat_cnt,current_mat in enumerate(mats):
            material = current_mat
            mat_class = 'Standard'
            mat_name = material.name

            idnt = 2
            file.write("%s*SUBMATERIAL %d {\n" % ((Tab*idnt), submat_cnt))
            submat_cnt += 1

            idnt = 3
            mat_para(file, idnt, material, mat_name, mat_class, worldTable)
            mat_dummy(file, idnt)
            mat_map(file, idnt, mat_name)

            idnt = 2
            file.write("%s}\n" % (Tab*idnt))

         file.write("%s}\n" % (Tab))


   file.write("}\n")


def mat_para(file, idnt, material, mat_name, mat_class, worldTable):

   mat_amb = material.getAmb()
   mat_dif = material.getRGBCol()
   mat_specCol = material.getSpecCol()
   mat_spec = material.getSpec()
   mat_hard = material.getHardness()
   mat_alpha = 1.0000-material.getAlpha()

   file.write("%s*MATERIAL_NAME \"%s\"\n" % ((Tab*idnt), mat_name))
   file.write("%s*MATERIAL_CLASS \"%s\"\n" % ((Tab*idnt), mat_class))
   file.write("%s*MATERIAL_AMBIENT %.4f   %.4f   %.4f\n" % ((Tab*idnt), (worldTable['ambR']*mat_amb), (worldTable['ambG']*mat_amb), (worldTable['ambB']*mat_amb))) #-Usefull?
   file.write("%s*MATERIAL_DIFFUSE %.4f   %.4f   %.4f\n" % ((Tab*idnt), mat_dif[0], mat_dif[1], mat_dif[2]))
   file.write("%s*MATERIAL_SPECULAR %.4f   %.4f   %.4f\n" % ((Tab*idnt), mat_specCol[0], mat_specCol[1], mat_specCol[2]))
   file.write("%s*MATERIAL_SHINE %.4f\n" % ((Tab*idnt), mat_spec))
   file.write("%s*MATERIAL_SHINESTRENGTH %.4f\n" % ((Tab*idnt), (mat_hard/511.))) #-511 or 512?
   file.write("%s*MATERIAL_TRANSPARENCY %.4f\n" % ((Tab*idnt), mat_alpha))
   file.write("%s*MATERIAL_WIRESIZE 1.0000\n" % (Tab*idnt))


def mat_dummy(file, idnt):

   file.write("%s*MATERIAL_SHADING Blinn\n" % (Tab*idnt))
   file.write("%s*MATERIAL_XP_FALLOFF 0.0000\n" % (Tab*idnt))
   file.write("%s*MATERIAL_SELFILLUM 0.0000\n" % (Tab*idnt))
   file.write("%s*MATERIAL_FALLOFF In\n" % (Tab*idnt))
   file.write("%s*MATERIAL_XP_TYPE Filter\n" % (Tab*idnt))


def mat_map(file, idnt, mat_name):

   mapTable = {0:'*MAP_AMBIENT',1:'*MAP_DIFFUSE',2:'*MAP_SPECULAR',3:'*MAP_SHINE',4:'*MAP_SHINESTRENGTH',5:'*MAP_SELFILLUM',6:'*MAP_OPACITY',7:'*MAP_FILTERCOLOR',8:'*MAP_BUMP',9:'*MAP_REFLECT',10:'*MAP_REFRACT',11:'*MAP_REFRACT'}
   tex_list = [[],[],[],[],[],[],[],[],[],[],[],[]]

   mat = Material.Get(mat_name)
   MTexes = mat.getTextures()

   for current_MTex in MTexes:
      if current_MTex is not None:
         # MAP_SUBNO 0 = *MAP_AMBIENT
         if current_MTex.mapto & Texture.MapTo.AMB:
            map_getTex(current_MTex, 0, (current_MTex.dvar*current_MTex.varfac), tex_list)
         # MAP_SUBNO 1 = *MAP_DIFFUSE = COL = 1
         elif current_MTex.mapto & Texture.MapTo.COL:
            map_getTex(current_MTex, 1, current_MTex.colfac, tex_list)
         # MAP_SUBNO 2 = *MAP_SPECULAR (Color)= CSP or SPEC? = 4
         elif current_MTex.mapto & Texture.MapTo.CSP:
            map_getTex(current_MTex, 2, current_MTex.colfac, tex_list)
         # MAP_SUBNO 3 = *MAP_SHINE (Spec Level) = SPEC or CSP? = 32
         elif current_MTex.mapto & Texture.MapTo.SPEC:
            map_getTex(current_MTex, 3, (current_MTex.dvar*current_MTex.varfac), tex_list)
         # MAP_SUBNO 4 = *MAP_SHINESTRENGTH (Gloss) = HARD = 256
         elif current_MTex.mapto & Texture.MapTo.HARD:
            map_getTex(current_MTex, 4, (current_MTex.dvar*current_MTex.varfac), tex_list)
         # MAP_SUBNO 5 = *MAP_SELFILLUM
         # MAP_SUBNO 6 = *MAP_OPACITY = ALPHA = 128
         elif current_MTex.mapto & Texture.MapTo.ALPHA:
            map_getTex(current_MTex, 6, (current_MTex.dvar*current_MTex.varfac), tex_list)
         # MAP_SUBNO 7 = *MAP_FILTERCOLOR
         # MAP_SUBNO 8 = *MAP_BUMP = NOR = 2
         elif current_MTex.mapto & Texture.MapTo.NOR:
            map_getTex(current_MTex, 8, (current_MTex.norfac/25), tex_list)
         # MAP_SUBNO 9 = *MAP_REFLECT
         elif current_MTex.mapto & Texture.MapTo.REF:
            map_getTex(current_MTex, 9, (current_MTex.norfac/25), tex_list)
         # MAP_SUBNO 10 = *MAP_REFRACT (refraction)
         # MAP_SUBNO 11 = *MAP_REFRACT (displacement)
         elif current_MTex.mapto & Texture.MapTo.DISP:
            map_getTex(current_MTex, 11, (current_MTex.norfac/25), tex_list)

   # Write maps
   for current_LI in tex_list:
      subNo = tex_list.index(current_LI)
      for current_MTex in current_LI:
         tex = current_MTex[0].tex
         if tex.type == Texture.Types.IMAGE:
            map_image(file, idnt, current_MTex, subNo, tex, mapTable[subNo])


def map_getTex(MTex, map_subNo, map_amount, texes):
   # container = [[[MTex], [map_amount]], ...]
   container = []
   container.append(MTex)
   container.append(map_amount)
   texes[map_subNo].append(container)

         
def map_image(file, idnt, MTexCon, subNo, tex, mapType):

   img = tex.getImage()
   #path = sys.expandpath(img.getFilename()).replace('/', '\\')
   path = img.filename #or img.getFilename()
   tex_class = 'Bitmap'
   tex_mapType = 'Screen'
   tex_filter = 'Pyramidal'

   file.write("%s%s {\n" % ((Tab*idnt), mapType))

   idnt += 1
   file.write("%s*MAP_NAME \"%s\"\n" % ((Tab*idnt), tex.getName()))
   file.write("%s*MAP_CLASS \"%s\"\n" % ((Tab*idnt), tex_class))
   file.write("%s*MAP_SUBNO %s\n" % ((Tab*idnt), subNo))
   file.write("%s*MAP_AMOUNT %.4f\n" % ((Tab*idnt), MTexCon[1]))
   file.write("%s*BITMAP \"%s\"\n" % ((Tab*idnt), path))
   file.write("%s*MAP_TYPE %s\n" % ((Tab*idnt), tex_mapType))

   # hope this part is right!
   u_tiling = tex.repeat[0]*tex.crop[2]
   v_tiling = tex.repeat[1]*tex.crop[3]
   file.write("%s*UVW_U_OFFSET %.4f\n" % ((Tab*idnt), tex.crop[0]))
   file.write("%s*UVW_V_OFFSET %.4f\n" % ((Tab*idnt), tex.crop[1]))
   file.write("%s*UVW_U_TILING %.4f\n" % ((Tab*idnt), u_tiling))
   file.write("%s*UVW_V_TILING %.4f\n" % ((Tab*idnt), v_tiling))

   map_uvw(file, idnt) #hardcoded

   file.write("%s*BITMAP_FILTER %s\n" % ((Tab*idnt), tex_filter))

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mat_uv(file, idnt, uv_image, uv_name, mat_class, worldTable):
   fake_val0 = '0.0000'
   fake_val1 = '0.1000'
   fake_val2 = '0.5882'
   fake_val3 = '0.9000'
   fake_val4 = '1.0000'

   file.write("%s*MATERIAL_NAME \"%s\"\n" % ((Tab*idnt), uv_name))
   file.write("%s*MATERIAL_CLASS \"%s\"\n" % ((Tab*idnt), mat_class))
   file.write("%s*MATERIAL_AMBIENT %.4f   %.4f   %.4f\n" % ((Tab*idnt), worldTable['ambR'], worldTable['ambG'], worldTable['ambB'])) #------------Usefull?
   file.write("%s*MATERIAL_DIFFUSE %s   %s   %s\n" % ((Tab*idnt), fake_val2, fake_val2, fake_val2))
   file.write("%s*MATERIAL_SPECULAR %s   %s   %s\n" % ((Tab*idnt), fake_val3, fake_val3, fake_val3))
   file.write("%s*MATERIAL_SHINE %s\n" % ((Tab*idnt), fake_val1))
   file.write("%s*MATERIAL_SHINESTRENGTH %s\n" % ((Tab*idnt), fake_val0))
   file.write("%s*MATERIAL_TRANSPARENCY %s\n" % ((Tab*idnt), fake_val0))
   file.write("%s*MATERIAL_WIRESIZE %s\n" % ((Tab*idnt), fake_val4))


def map_uv(file, idnt, uv_image, uv_name):
   map_type = '*MAP_DIFFUSE'
   map_subNo = '1'
   tex_class = 'Bitmap'
   tex_mapType = 'Screen'
   tex_filter = 'Pyramidal'

   fake_val0 = '0.0000'
   fake_val1 = '0.1000'
   fake_val2 = '0.5882'
   fake_val3 = '0.9000'
   fake_val4 = '1.0000'

   #replace "/" with "\" in image path
   uv_filename = uv_image.getFilename().replace('/', '\\')

   file.write("%s%s {\n" % ((Tab*idnt), map_type))

   idnt += 1
   file.write("%s*MAP_NAME \"%s\"\n" % ((Tab*idnt), uv_name))
   file.write("%s*MAP_CLASS \"%s\"\n" % ((Tab*idnt), tex_class))
   file.write("%s*MAP_SUBNO %s\n" % ((Tab*idnt), map_subNo))
   file.write("%s*MAP_AMOUNT %s\n" % ((Tab*idnt), fake_val4))
   file.write("%s*BITMAP \"%s\"\n" % ((Tab*idnt), uv_filename))
   file.write("%s*MAP_TYPE %s\n" % ((Tab*idnt), tex_mapType))
   file.write("%s*UVW_U_OFFSET %s\n" % ((Tab*idnt), fake_val0))
   file.write("%s*UVW_V_OFFSET %s\n" % ((Tab*idnt), fake_val0))
   file.write("%s*UVW_U_TILING %s\n" % ((Tab*idnt), fake_val4))
   file.write("%s*UVW_V_TILING %s\n" % ((Tab*idnt), fake_val4))

   map_uvw(file, idnt) #hardcoded

   file.write("%s*BITMAP_FILTER %s\n" % ((Tab*idnt), tex_filter))

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def map_uvw(file, idnt):

   fake_val0 = '0.0000'
   fake_val1 = '1.0000'

   file.write("%s*UVW_ANGLE %s\n" % ((Tab*idnt), fake_val0))
   file.write("%s*UVW_BLUR %s\n" % ((Tab*idnt), fake_val1))
   file.write("%s*UVW_BLUR_OFFSET %s\n" % ((Tab*idnt), fake_val0))
   file.write("%s*UVW_NOUSE_AMT %s\n" % ((Tab*idnt), fake_val1))
   file.write("%s*UVW_NOISE_SIZE %s\n" % ((Tab*idnt), fake_val1))
   file.write("%s*UVW_NOISE_LEVEL 1\n" % (Tab*idnt))
   file.write("%s*UVW_NOISE_PHASE %s\n" % ((Tab*idnt), fake_val0))


#============================================
#           Mesh
#============================================


def write_mesh(file, scn, exp_list, matTable, total):
   print "Write Geometric"

   for current_container in exp_list:

      TransTable = {'SizeX': 1, 'SizeY': 1, 'SizeZ': 1}
      nameMe = {'objName': 'obj', 'meName': 'me'}
      sGroups = {}
      hasTable = {'hasMat': 0, 'hasSG': 0, 'hasUV': 0, 'hasVC': 0, 'matRef': 0}
      count = {'face': 0, 'vert': 0, 'UVs': 0, 'cVert': 0}

      obj = current_container[0]
      #mat_ref = current_container[1]
      data = obj.getData(0,1)
      nameMe['objName'] = obj.name
      nameMe['meName'] = data.name

      mats_me = [mat for mat in data.materials if mat] #fix for 2.44, get rid of NoneType Objects in me.materials
      mats_ob = obj.getMaterials(0)
      materials = False

      if mats_me:
         materials = mats_me
      elif mats_ob:
         materials = mats_ob

      if guiTable['MTL'] and materials:
         hasTable['hasMat'] = 1
         hasTable['matRef'] = current_container[1]

      if obj.getParent():
         nameMe['parent'] = obj.getParent().name
      
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD']:   # Use modified mesh
         me.getFromObject(obj.name, 0) # Get the object's mesh data, cage 0 = apply mod
      else:
         me.getFromObject(obj.name, 1)

      me.transform(obj.matrix)   # ASE stores transformed mesh data
      if guiTable['RECENTER']:   # Recentre Objects to 0,0,0 feature
         rec_matrix = Mathutils.TranslationMatrix(obj.matrix.translationPart().negate())
         me.transform(rec_matrix)

      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)

      if guiTable['VG2SG']:
         VGNames = data.getVertGroupNames()
         for vg in VGNames:
            me.addVertGroup(vg)
            gverts = data.getVertsFromGroup(vg, 1)
            gverts_copy = []
            for gv in gverts:
               gverts_copy.append(gv[0])
            me.assignVertsToGroup(vg, gverts_copy, 1, 1)

      obj = tempObj
      faces = me.faces
      verts = me.verts

      count['vert'] = len(verts)
      total['Verts'] += count['vert']

      if count['vert'] == 0:
         print 'Error: ' + nameMe['meName'] + 'has 0 Verts'
         continue

      vGroups = me.getVertGroupNames()
      if guiTable['VG2SG'] and len(vGroups) > 0:
         for current_VG in vGroups:
            if current_VG.lower().count("smooth."):
               hasTable['hasSG'] = 1
               smooth_num = int(current_VG.lower().replace("smooth.", ""))
               gverts = me.getVertsFromGroup(current_VG)
               for vi in gverts:
                  if not sGroups.has_key(vi):
                     sGroups[vi] = [smooth_num]
                  else:
                     sGroups[vi].append(smooth_num)

      if guiTable['UV']:
         if me.faceUV == True or me.faceUV == 1:
            hasTable['hasUV'] = 1

      if guiTable['VC']:
         if me.vertexColors:
            hasTable['hasVC'] = 1
         elif hasTable['hasMat']: # Blender material
            for current_mat in materials:
               if current_mat.getMode() & Material.Modes['VCOL_PAINT']:
                  hasTable['hasVC'] = 1
                  break

      for current_face in faces:
         if len(current_face.verts) is 3:
            count['face'] += 1
            total['Tris'] += 1
            total['Faces'] += 1
         elif len(current_face.verts) is 4:
            count['face'] += 2
            total['Tris'] += 2
            total['Faces'] += 1

      #Open Geomobject
      file.write("*GEOMOBJECT {\n")
      file.write("%s*NODE_NAME \"%s\"\n" % (Tab, nameMe['objName']))

      if nameMe.has_key('parent'):
         file.write("%s*NODE_PARENT \"%s\"\n" % (Tab, nameMe['parent']))

      idnt = 1
      mesh_matrix(file, idnt, obj, nameMe, TransTable)

      #Open Mesh
      file.write("%s*MESH {\n" % (Tab))

      idnt = 2
      file.write("%s*TIMEVALUE 0\n" % (Tab*idnt))
      file.write("%s*MESH_NUMVERTEX %i\n" % ((Tab*idnt), count['vert']))
      file.write("%s*MESH_NUMFACES %i\n" % ((Tab*idnt), count['face']))

      idnt = 2
      mesh_vertexList(file, idnt, verts, count)
      idnt = 2
      mesh_faceList(file, idnt, me, materials, sGroups, faces, matTable, hasTable, count)


      if hasTable['hasUV'] == 1:
         UVTable = {}

         active_map_channel = me.activeUVLayer
         map_channels = me.getUVLayerNames()

         idnt = 2
         mesh_tVertList(file, idnt, faces, UVTable, count)
         #idnt = 2
         mesh_tFaceList(file, idnt, faces, UVTable, count)
         UVTable = {}
         
         if len(map_channels) > 1:
            chan_index = 2
            for map_chan in map_channels:
               if map_chan != active_map_channel:
                  me.activeUVLayer = map_chan

                  idnt = 2
                  file.write("%s*MESH_MAPPINGCHANNEL %i {\n" % ((Tab*idnt), chan_index))
                  idnt = 3
                  mesh_tVertList(file, idnt, faces, UVTable, count)
                  mesh_tFaceList(file, idnt, faces, UVTable, count)
                  UVTable = {}
                  chan_index += 1
                  idnt = 2
                  file.write("%s}\n" % (Tab*idnt))

         me.activeUVLayer = active_map_channel

      else:
      # dirty fix
         file.write("%s*MESH_NUMTVERTEX %i\n" % ((Tab*idnt), count['UVs']))

      if hasTable['hasVC'] == 1:
         cVertTable = {}

         idnt = 2
         mesh_cVertList(file, idnt, faces, cVertTable, count)
         #idnt = 2
         mesh_cFaceList(file, idnt, faces, cVertTable, count)
      else:
      # dirty fix
         file.write("%s*MESH_NUMCVERTEX %i\n" % ((Tab*idnt), count['cVert']))


      idnt = 2
      mesh_normals(file, idnt, faces, verts, count)

      # Close *MESH
      idnt = 1
      file.write("%s}\n" % (Tab*idnt))

      idnt = 1
      mesh_footer(file, idnt, hasTable)

      # Close *GEOMOBJECT
      file.write("}\n")
      
      #free some memory
      me.materials = [None]
      me.faces.delete(1,[(f.index) for f in me.faces])
      me.verts.delete(me.verts)
      obj.fakeUser = False
      me.fakeUser = False
      scn.objects.unlink(obj)

def mesh_matrix(file, idnt, obj, nameMe, TransTable):

   #i should check why i have to get and invert the matrix
   #exactly in that sequence.

   row = obj.getMatrix('localspace').invert()
   #row = obj.getInverseMatrix()

   if guiTable['RECENTER']:
      location = 0.0,0.0,0.0
      row[3][0] = row[3][1] = row[3][2] = 0.0
   else:
      location = obj.getLocation()

   quat = row.invert().toQuat()
   #quat = obj.getMatrix('localspace').toQuat()
   rota = quat.axis
   #angle = quat.angle * (math.pi/180) #Blender: degrees -> ASE: radians
   angle = math.radians(quat.angle)

   Blender.Window.DrawProgressBar(0.0, "Writing Transform Node")

   file.write("%s*NODE_TM {\n" % (Tab*idnt))

   idnt += 1
   file.write("%s*NODE_NAME \"%s\"\n" % ((Tab*idnt), nameMe['meName']))
   # Inherit from what?..
   file.write("%s*INHERIT_POS 0 0 0\n" % (Tab*idnt))
   file.write("%s*INHERIT_ROT 0 0 0\n" % (Tab*idnt))
   file.write("%s*INHERIT_SCL 0 0 0\n" % (Tab*idnt))

   file.write("%s*TM_ROW0 %.4f %.4f %.4f\n" % ((Tab*idnt), row[0][0], row[0][1], row[0][2]))
   file.write("%s*TM_ROW1 %.4f %.4f %.4f\n" % ((Tab*idnt), row[1][0], row[1][1], row[1][2]))
   file.write("%s*TM_ROW2 %.4f %.4f %.4f\n" % ((Tab*idnt), row[2][0], row[2][1], row[2][2]))
   file.write("%s*TM_ROW3 %.4f %.4f %.4f\n" % ((Tab*idnt), row[3][0], row[3][1], row[3][2]))

   file.write("%s*TM_POS %.4f %.4f %.4f\n" % ((Tab*idnt), location[0], location[1], location[2]))

   file.write("%s*TM_ROTAXIS %.4f %.4f %.4f\n" % ((Tab*idnt), rota.x, rota.y, rota.z))
   file.write("%s*TM_ROTANGLE %.4f\n" % ((Tab*idnt), angle))

   file.write("%s*TM_SCALE %.4f %.4f %.4f\n" % ((Tab*idnt), TransTable['SizeX'], TransTable['SizeY'], TransTable['SizeZ']))
   #file.write("%s*TM_SCALEAXIS 0.0000 0.0000 0.0000\n" % (Tab*idnt))
   # Looks more logic, because blender use the rotaxis for rot and scale:
   file.write("%s*TM_SCALEAXIS %.4f %.4f %.4f\n" % ((Tab*idnt), rota.x, rota.y, rota.z))
   file.write("%s*TM_SCALEAXISANG %.4f\n" % ((Tab*idnt), angle))

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mesh_vertexList(file, idnt, verts, count):

   file.write("%s*MESH_VERTEX_LIST {\n" % (Tab*idnt))

   idnt += 1

   Blender.Window.DrawProgressBar(0.0, "Writing vertices")

   for current_vert in verts:

      vIndex = current_vert.index

      if (vIndex % 1000) == 0:
                   Blender.Window.DrawProgressBar((vIndex+1.0) / count['vert'], "Writing vertices")

      file.write("%s*MESH_VERTEX %d\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), vIndex, current_vert.co[0], current_vert.co[1], current_vert.co[2]))

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mesh_faceList(file, idnt, me, materials, sGroups, faces, matTable, hasTable, count):

   file.write("%s*MESH_FACE_LIST {\n" % (Tab*idnt))
   idnt += 1
   faceNo = 0

   Blender.Window.DrawProgressBar(0.0, "Writing faces")
   if hasTable['hasMat'] and matTable:
      mats = matTable[hasTable['matRef']]

   fgon_eds = [(ed.key) for ed in me.edges if ed.flag & Mesh.EdgeFlags.FGON]
   for current_face in faces:

      face_verts = current_face.verts
      smooth = '*MESH_SMOOTHING'
      matID = '*MESH_MTLID 0'

      if (faceNo % 500) == 0:
         Blender.Window.DrawProgressBar((faceNo+1.0) / count['face'], "Writing faces")

      if hasTable['hasMat']: # Blender mats
         #print current_face.mat
         mtlid = mats.index(materials[current_face.mat])
         matID = '*MESH_MTLID %i' % (mtlid)

      if len(face_verts) is 3:
         vert0 = face_verts[0].index
         vert1 = face_verts[1].index
         vert2 = face_verts[2].index

         #Find hidden (fgon) edges
         edge_keys = current_face.edge_keys
         eds_fgon = [1,1,1]
         for i,ed_key in enumerate(edge_keys):
            if ed_key in fgon_eds:
               eds_fgon[i] = 0

         #Find Smoothgroups for this face:
         if guiTable['VG2SG'] and hasTable['hasSG'] and current_face.smooth:
            if sGroups.has_key(vert0) and sGroups.has_key(vert1) and sGroups.has_key(vert2):
               sg = []
               gis = [sGroups[vert0],sGroups[vert1],sGroups[vert2]]
               for gil in gis:
                  for gi in gil:
                     sg.append(gi)
               sg = set(sg)
               for gi in sg:
                  smooth += ' %s,' % gi
               smooth = smooth[:-1]

         elif current_face.smooth:
            smooth += ' 1'

         file.write("%s*MESH_FACE %i:    A: %i B: %i C: %i AB:    %i BC:    %i CA:    %i\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert1, vert2, eds_fgon[0], eds_fgon[1], eds_fgon[2], smooth, matID))
         faceNo+=1

      elif len(face_verts) is 4:
         vert0 = face_verts[0].index
         vert1 = face_verts[1].index
         vert2 = face_verts[2].index
         vert3 = face_verts[3].index

         #Find hidden (fgon) edges
         edge_keys = current_face.edge_keys
         eds_fgon = [1,1,1,1]
         for i,ed_key in enumerate(edge_keys):
            if ed_key in fgon_eds:
               eds_fgon[i] = 0

         #Find Smooth for this face:
         if guiTable['VG2SG'] and hasTable['hasSG'] and current_face.smooth:
            if sGroups.has_key(vert0) and sGroups.has_key(vert1) and sGroups.has_key(vert2) and sGroups.has_key(vert3):
               ## I hate VG2SG ;> not sure which way is correct
               #sg0,sg1,sg2,sg3 = sGroups[vert0],sGroups[vert1],sGroups[vert2],sGroups[vert3]
               #if sg0 == sg1 == sg2 == sg3:
               #   sg = sg0
               #else:
               #   lens = [len(sg0),len(sg1),len(sg2),len(sg3)]
               #   lens_sort = lens
               #   lens_sort.sort()
               #   lowest = lens_sort[0]
               #   for l,s in zip(lens,[sg0,sg1,sg2,sg2]):
               #      if l == lowest:
               #         sg = s
               #         break

               sg = []
               gis = [sGroups[vert0],sGroups[vert1],sGroups[vert2],sGroups[vert3]]
               for gil in gis:
                  for gi in gil:
                     sg.append(gi)
               sg = set(sg)
               for gi in sg:
                  smooth += ' %s,' % gi
               smooth = smooth[:-1]
            else:
               smooth += ' 1'

         elif current_face.smooth:
            smooth += ' 1'

         file.write("%s*MESH_FACE %i:    A: %i B: %i C: %i AB:    %i BC:    %i CA:    0\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert1, vert2, eds_fgon[0], eds_fgon[1], smooth, matID))
         faceNo+=1
         file.write("%s*MESH_FACE %i:    A: %i B: %i C: %i AB:    %i BC:    %i CA:    0\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert2, vert3, eds_fgon[1], eds_fgon[2], smooth, matID))
         faceNo+=1

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))

def mesh_tVertList(file, idnt, faces, UVTable, count):

   Blender.Window.DrawProgressBar(0.0, "Setup UV index")

   for current_face in faces:
      faceuv = current_face.uv
      for current_uv in faceuv:
         uv = (current_uv.x, current_uv.y)
         if not UVTable.has_key(uv):
            UVTable[uv] = 0
            count['UVs'] += 1

   #count['UVs'] = len(UVTable)
   file.write("%s*MESH_NUMTVERTEX %d\n" % ((Tab*idnt), count['UVs']))
   file.write("%s*MESH_TVERTLIST {\n" % (Tab*idnt))

   idnt += 1
   Blender.Window.DrawProgressBar(0.0, "Writing UV index")

   for index,current_UV in enumerate(UVTable.iterkeys()):
      if (index % 1000) == 0:
         Blender.Window.DrawProgressBar((index+1.0) / count['face'], "Writing UV index")

      file.write("%s*MESH_TVERT %i\t%.4f\t%.4f\t0.0000\n" % ((Tab*idnt), index, current_UV[0], current_UV[1]))
      UVTable[current_UV] = index

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mesh_tFaceList(file, idnt, faces, UVTable, count):

   tfaceNo = 0

   Blender.Window.DrawProgressBar(0.0, "Writing Face UV")

   file.write("%s*MESH_NUMTVFACES %i\n" % ((Tab*idnt), count['face']))
   file.write("%s*MESH_TFACELIST {\n" % (Tab*idnt))

   idnt += 1

   for current_face in faces:

      faceUV = current_face.uv

      if (tfaceNo % 1000) == 0:
         Blender.Window.DrawProgressBar((tfaceNo+1.0) / count['face'], "Writing Face UV")

      if len(faceUV) is 3: #tri
         UV0 = UVTable[(faceUV[0].x, faceUV[0].y)]
         UV1 = UVTable[(faceUV[1].x, faceUV[1].y)]
         UV2 = UVTable[(faceUV[2].x, faceUV[2].y)]
         file.write("%s*MESH_TFACE %i\t%i\t%i\t%d\n" % ((Tab*idnt), tfaceNo, UV0, UV1, UV2))
         tfaceNo+=1

      elif len(faceUV) is 4: #quad
         UV0 = UVTable[(faceUV[0].x, faceUV[0].y)]
         UV1 = UVTable[(faceUV[1].x, faceUV[1].y)]
         UV2 = UVTable[(faceUV[2].x, faceUV[2].y)]
         UV3 = UVTable[(faceUV[3].x, faceUV[3].y)]
         file.write("%s*MESH_TFACE %i\t%i\t%i\t%i\n" % ((Tab*idnt), tfaceNo, UV0, UV1, UV2))
         tfaceNo+=1
         file.write("%s*MESH_TFACE %i\t%i\t%i\t%i\n" % ((Tab*idnt), tfaceNo, UV0, UV2, UV3))
         tfaceNo+=1

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mesh_cVertList(file, idnt, faces, cVertTable, count):

   Blender.Window.DrawProgressBar(0.0, "Setup VCol index")

   for current_face in faces:
      facecol = current_face.col
      for current_col in facecol:
         col = (current_col.r, current_col.g, current_col.b)
         if not cVertTable.has_key(col):
            cVertTable[col] = 0
            count['cVert'] += 1

   file.write("%s*MESH_NUMCVERTEX %i\n" % ((Tab*idnt), count['cVert']))
   file.write("%s*MESH_CVERTLIST {\n" % (Tab*idnt))

   idnt += 1

   Blender.Window.DrawProgressBar(0.0, "Writing VCol index")

   for index,current_cvert in enumerate(cVertTable.iterkeys()):
      if (index % 1000) == 0:
         Blender.Window.DrawProgressBar((index+1.0) / count['face'], "Writing VCol index")

      file.write("%s*MESH_VERTCOL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), index, (current_cvert[0]/256.), (current_cvert[1]/256.), (current_cvert[2]/256.)))
      cVertTable[current_cvert] = index

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mesh_cFaceList(file, idnt, faces, cVertTable, count):

   cFaceNo = 0

   Blender.Window.DrawProgressBar(0.0, "Writing Face Colors")

   file.write("%s*MESH_NUMCFACES %i\n" % ((Tab*idnt), count['face']))
   file.write("%s*MESH_CFACELIST {\n" % (Tab*idnt))

   idnt += 1
   for current_face in faces:

      if (cFaceNo % 500) == 0:
         Blender.Window.DrawProgressBar((cFaceNo+1.0) / count['face'], "Writing Face Colors")

      if len(current_face.verts) is 3: #tri
         color0 = cVertTable[(current_face.col[0].r, current_face.col[0].g, current_face.col[0].b)]
         color1 = cVertTable[(current_face.col[1].r, current_face.col[1].g, current_face.col[1].b)]
         color2 = cVertTable[(current_face.col[2].r, current_face.col[2].g, current_face.col[2].b)]

         file.write("%s*MESH_CFACE %i\t%i\t%i\t%i\n" % ((Tab*idnt), cFaceNo, color0, color1, color2))
         cFaceNo+= 1

      elif len(current_face.verts) is 4: #quad
         color0 = cVertTable[(current_face.col[0].r, current_face.col[0].g, current_face.col[0].b)]
         color1 = cVertTable[(current_face.col[1].r, current_face.col[1].g, current_face.col[1].b)]
         color2 = cVertTable[(current_face.col[2].r, current_face.col[2].g, current_face.col[2].b)]
         color3 = cVertTable[(current_face.col[3].r, current_face.col[3].g, current_face.col[3].b)]

         file.write("%s*MESH_CFACE %i\t%i\t%i\t%i\n" % ((Tab*idnt), cFaceNo, color0, color1, color2))
         cFaceNo+= 1
         file.write("%s*MESH_CFACE %i\t%i\t%i\t%i\n" % ((Tab*idnt), cFaceNo, color0, color2, color3))
         cFaceNo+= 1

   idnt -= 1
   file.write("%s}\n" % (Tab*idnt))


def mesh_normals(file, idnt, faces, verts, count):
   # To export quads it is needed to calculate all face and vertex normals new!
   vec_null = Blender.Mathutils.Vector(0.0, 0.0, 0.0)
   v_normals = dict([(v.index, vec_null) for v in verts])
   f_normals = dict([(f.index, vec_null) for f in faces])
   f_normals_quad = {}

   file.write("%s*MESH_NORMALS {\n" % (Tab*idnt))

   Blender.Window.DrawProgressBar(0.0, "Setup Normals")

   #-- Calculate new face and vertex normals

   for i,f in enumerate(faces):
      f_dic = f_normals[i]
      f_vec = f_dic[0]

      f_verts = f.verts

      if len(f_verts) is 3: #tri
         v0,v1,v2 = f_verts[:]
         v0_i,v1_i,v2_i = f_verts[0].index, f_verts[1].index, f_verts[2].index
         f_no = Blender.Mathutils.TriangleNormal(v0.co, v1.co, v2.co)
         f_normals[f.index] = f_no
         if f.smooth:
            v_normals[v0_i] = v_normals[v0_i] + f_no
            v_normals[v1_i] = v_normals[v1_i] + f_no
            v_normals[v2_i] = v_normals[v2_i] + f_no

      if len(f_verts) is 4: #quad
         v0,v1,v2,v3 = f_verts[:]
         v0_i,v1_i,v2_i,v3_i = f_verts[0].index, f_verts[1].index, f_verts[2].index,f_verts[3].index
         f_no0 = Blender.Mathutils.TriangleNormal(v0.co, v1.co, v2.co)
         f_no1 = Blender.Mathutils.TriangleNormal(v2.co, v3.co, v0.co)
         f_normals[f.index] = f_no0
         f_normals_quad[f.index] = f_no1
         if f.smooth:
            v_normals[v0_i] = v_normals[v0_i] + f_no0
            v_normals[v1_i] = v_normals[v1_i] + f_no0
            v_normals[v2_i] = v_normals[v2_i] + f_no0
            
            v_normals[v0_i] = v_normals[v2_i] + f_no1
            v_normals[v2_i] = v_normals[v3_i] + f_no1
            v_normals[v3_i] = v_normals[v0_i] + f_no1


   #-- Normalize vectors
   #for i,vec in v_normals.iteritems():
   for vec in v_normals.itervalues():
      vec.normalize()

   #-- Finally write normals
   normNo = 0
   idnt += 2

   Blender.Window.DrawProgressBar(0.0, "Writing Normals")

   for f in faces:

      if (normNo % 500) == 0:
         Blender.Window.DrawProgressBar((normNo+1.0) / count['face'], "Writing Normals")

      f_verts = f.verts
      smooth = f.smooth

      if len(f_verts) is 3: #tri
         v0_i = f_verts[0].index
         v1_i = f_verts[1].index
         v2_i = f_verts[2].index

         idnt -= 1
         f_no = f_normals[f.index]
         file.write("%s*MESH_FACENORMAL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), normNo, f_no.x, f_no.y, f_no.z))
         normNo += 1

         idnt += 1
         mesh_vertNorm(file, idnt, v0_i, v1_i, v2_i, v_normals, smooth, f_no)

      #elif len(f_verts) is 4: #quad
      if len(f_verts) is 4: #quad
         v0_i = f_verts[0].index
         v1_i = f_verts[1].index
         v2_i = f_verts[2].index
         v3_i = f_verts[3].index

         idnt -= 1
         f_no = f_normals[f.index]
         file.write("%s*MESH_FACENORMAL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), normNo, f_no0.x, f_no0.y, f_no0.z))
         normNo += 1

         idnt += 1
         mesh_vertNorm(file, idnt, v0_i, v1_i, v2_i, v_normals, smooth, f_no0)

         idnt -= 1
         f_no = f_normals_quad[f.index]
         file.write("%s*MESH_FACENORMAL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), normNo, f_no1.x, f_no1.y, f_no1.z))
         normNo += 1

         idnt += 1
         mesh_vertNorm(file, idnt, v0_i, v2_i, v3_i, v_normals, smooth, f_no1)


   idnt -= 2
   file.write("%s}\n" % (Tab*idnt))
   
def mesh_vertNorm(file, idnt, v0_i, v1_i, v2_i, v_normals, smooth, f_no):
   if smooth:
      v_no0 = v_normals[v0_i]
      v_no1 = v_normals[v1_i]
      v_no2 = v_normals[v2_i]
   else: #If solid use the face normal
      v_no0 = v_no1 = v_no2 = f_no

   file.write("%s*MESH_VERTEXNORMAL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), v0_i, v_no0.x, v_no0.y, v_no0.z))
   file.write("%s*MESH_VERTEXNORMAL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), v1_i, v_no1.x, v_no1.y, v_no1.z))
   file.write("%s*MESH_VERTEXNORMAL %i\t%.4f\t%.4f\t%.4f\n" % ((Tab*idnt), v2_i, v_no2.x, v_no2.y, v_no2.z))


def mesh_footer(file, idnt, hasTable):

   file.write("%s*PROP_MOTIONBLUR 0\n" % (Tab*idnt))
   file.write("%s*PROP_CASTSHADOW 1\n" % (Tab*idnt))
   file.write("%s*PROP_RECVSHADOW 1\n" % (Tab*idnt))

   if hasTable['hasMat'] != 0:
      file.write("%s*MATERIAL_REF %i\n" % ((Tab*idnt), hasTable['matRef']))

   #-------------------------End?----------------------


def write_ui(filename):

   global guiTable, EXPORT_MOD, EXPORT_MTL, EXPORT_UV, EXPORT_VC, EXPORT_SELO, EXPORT_UVI, EXPORT_VG2SG
   guiTable = {'MOD': 1, 'MTL': 1, 'UV': 1, 'VC': 1, 'SELO': 1, 'UVI': 0, 'VG2SG': 1, 'RECENTER':0}

   EXPORT_MOD = Draw.Create(guiTable['MOD'])
   EXPORT_MTL = Draw.Create(guiTable['MTL'])
   EXPORT_UV = Draw.Create(guiTable['UV'])
   EXPORT_VC = Draw.Create(guiTable['VC'])
   EXPORT_SELO = Draw.Create(guiTable['SELO'])
   EXPORT_VG2SG = Draw.Create(guiTable['VG2SG'])
   EXPORT_REC = Draw.Create(guiTable['RECENTER'])

   # Get USER Options
   pup_block = [('Mesh Options...'),('Apply Modifiers', EXPORT_MOD, 'Use modified mesh data from each object.'),('Materials', EXPORT_MTL, 'Export Materials.'),('Face UV', EXPORT_UV, 'Export texface UV coords.'),('Vertex Colors', EXPORT_VC, 'Export vertex colors'),('Context...'),('Selection Only', EXPORT_SELO, 'Only export objects in visible selection, else export all mesh object.'),('Bonus...'),('VertGr. as SmoothGr.', EXPORT_VG2SG, 'Make SmoothGroups by VertGroups. See doc.'), ('Center Objects', EXPORT_REC, 'Center ALL objects to World-Grid-Origin-Center-Point-(0,0,0). ;)')]

   if not Draw.PupBlock('Export...', pup_block):
      return

   Window.WaitCursor(1)

   guiTable['MOD'] = EXPORT_MOD.val
   guiTable['MTL'] = EXPORT_MTL.val
   guiTable['UV'] = EXPORT_UV.val
   guiTable['VC'] = EXPORT_VC.val
   guiTable['SELO'] = EXPORT_SELO.val
   guiTable['VG2SG'] = EXPORT_VG2SG.val
   guiTable['RECENTER'] = EXPORT_REC.val

   if not filename.lower().endswith('.ase'):
      filename += '.ase'

   write(filename)

   Window.WaitCursor(0)


if __name__ == '__main__':
   Window.FileSelector(write_ui, 'Export ASCII Scene', sys.makename(ext='.ase'))


Last edited by Goofos on Mon Sep 03, 2007 9:18 pm, edited 34 times in total.

Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Thu Mar 10, 2005 5:06 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
Goofos wrote:
- not much tested! ...
Oh don't you worry about that..!! I'd suggest you try and get yourself set up with an instant messenger account - MSN, ICQ etc...

I've got some models I can test this on which had to be exported in sections so it'll be interesting to see what this script does. It might be worth making the script more 'global' though and allowing the export of material refs as well.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu Mar 10, 2005 6:33 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 3:05 am
Posts: 177
Location: black forrest
I'm working on a more global script, but currently I search for a few possibilities how to handle the materials, submaterials and UV's in a simple and comfortable way. Not easy because in Blender the link between Materials and UV's is a bit ugly :? (or I don't understand it :)). In any case, this is next implemented.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 10, 2005 6:53 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
Yeah, der_ton said the same thing about the MD5 exporter, the way Blender works when it comes to external formats isn't exactly 'user friendly'. Anyway, will give feedback on this tomorrow.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Sat Mar 12, 2005 4:41 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
ok.. I get the following error when exporting selected objects (several separate objects)

Code:
Write Header
Write MAterials
Traceback (most recent call last)
      File "goofosASE.py", line 350, in fs_callback
      File "goofosASE.py", line 40, in write
NameError: global name 'ingame_list' in not defined


If I check the exported object in 3Dexplorer it's currupted (i.e. it won't display), the file itself opened in notepad only contains material info (separate materila entries for each object).

[EDIT]forgot to add... this is from Blender 2.36 sitting on top of Python 2.34

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Sun Mar 13, 2005 4:43 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 3:05 am
Posts: 177
Location: black forrest
Yes, because "imgname_list" was only for testing :oops:

Have removed it from:

write_mesh(file, mesh_list, img_list)
and
def write_mesh(file, mesh_list, img_list):


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 13, 2005 5:02 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
Ok, I'll copy/paste the ammended script from above and try that.

[EDIT]ok.. tried this version.

The objects get exported ok and although I've not yet tested them in D3 the object *does* appear ok (and textured) in 3DExplorer - generally if there is any problem with a mesh object it'll show in this app.

I did get a slightly different error though (see below). Just to confirm, mesh is triangulated and the exported selection contain 2 separate mesh objects.
Code:
---------Start of Export------------
Write Header
Write Materials
Write Geometric
Traceback (most recent call last):
  File "goofosASE_130405.py", line 350, in fs_callback
  File "goofosASE_130405.py", line 40, in write
  File "goofosASE_130405.py", line 339, in write_mesh
IndexError: list index out of range


[EDIT 2]I'm not 100% sure on this but I think that error above has something to do with the mesh objects being exported rather than the script. I've done a couple of models now and most of them have exported fine with the PC giving a little 'beep' noise to says it's done, only the odd one or two have thrown up that error.

I think it might have something to do with the mesh being 'dirty' (rouge vertices/faces etc) which on being cleaned allow the objects to be exported without error.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Sun Mar 13, 2005 11:26 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
Ok... I think I figured the error out, or at least what's causing it and it's similar to the problems der_ton and I had when testing the MD5 exporter..... 'dirty' *.blend files.

Becasue of the way Blender works it doesn't properly 'release' the links it creates to data blocks so if you try to export a mesh that has a lot of data linked to 'dead' blocks it screws up the export - presumably becasue the exporter is trying to export what it see as 'ligitimate' mesh data.

Once you 'clean' the file (activate *all* the layers - select all - de-select the objects wanted - then delete all) by removing the dead data the models export properly.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Mon Mar 14, 2005 3:49 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 3:05 am
Posts: 177
Location: black forrest
I have no other answer :D I tried to make a really nasty Object, but it was always exported.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 14, 2005 5:30 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
Goofos wrote:
I have no other answer :D I tried to make a really nasty Object, but it was always exported.
No worries, we had the same problem with the MD5 exporter testing, it was extremely difficult to deliberately make a dirty file. At least we can make an educated guess that is the reason behind the error here.

I've got more objects to export/work on over the coming weeks so I'll keep you posted of any other errors. For now we have a decent working ASE exporter, so many thanks for that. *thunbsup*

If you need further ideas for development let me know :wink:

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu May 19, 2005 12:57 pm 
Offline
Last man standing
User avatar

Joined: Tue Dec 14, 2004 12:21 pm
Posts: 1151
Location: bath, england
this seems like a stable and quite easy to use script, except it confused me for several days why I couldn`t get my vertex blending to work in d3, until I tried the usm .ase exporter again and found my same blender models work fine with vertex color.

also a minor 'bug' is it doesn`t seem to remember the export path of the .ase and reverts back to the blender folder... not a big problem as I wrote a simple .bat to copy it to my d3 models folder, but it would be more convenient if it did remember the path.

can anyone else test Goofos`s .ase exporter?


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 19, 2005 2:41 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Mon Mar 01, 2004 9:22 pm
Posts: 890
I use this for anything which needs more than one texture. The major issue I noticed was that it puts everything in the same smoothing group, so in order to get hard edges you have to split faces.

There is code to assign smoothing groups based on whether a tri has the smoothing tag or not in the script, although it's commented out. As far as I can tell that would mean everything that Blender thinks should be hard will be put into smoothing group 0 and appear smoothed together, which might not be what's intended - but you could use that to control smoothing groups.

Other than that, it works fine.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 19, 2005 3:02 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
ratty redemption wrote:
..also a minor 'bug' is it doesn`t seem to remember the export path of the .ase and reverts back to the blender folder...
You must be doing something odd based on that description, the script should be defaulting to your working directory when you hit Alt+P if it's loaded into the script/text window.

With regards to smooth groups, you should be using 'split face' to create groups as they tend to be ignored 'globally', iirc D3 ignors groupings as well hense the need to split the mesh.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu May 19, 2005 6:47 pm 
Offline
Last man standing
User avatar

Joined: Tue Dec 14, 2004 12:21 pm
Posts: 1151
Location: bath, england
kat, I first copied and pasted Goofos`s above script into a renamed .txt file saved in the following path:

"C:\program files\Blender\.blender\scripts\d3_ase.py"

in blender`s user prefs, I have the 'default python script location' set to:

"C:\program files\Blender\.blender\scripts\"

and I pressed the 're-evaluate scripts' button.

I select the mesh I want, and use the 'file menu\export\d3 ase' script which changes the previously focused 3d window to a file browser window, which is where it always defaults to:

'C:\program files\Blender\.blender\'

even if when previously exporting, I`ve browsed to another folder like my model`s folder.

so I press the 'export ase' button at the top of the browser window and it dumps the .ase file into the above path.

that is where I then run my .bat file from window`s explorer to copy the .ase into the correct model folder.

I assuming your using some other method of running the script as I don`t at any time press 'alt p' so can you give me step by step instructions, or a link to some page which explains the method you use?

and is what you guys are saying about smoothing groups, different from the vertex color/blending I was talking about? ...unless I`m getting confused, then I think smoothing groups is an area of modeling I`ve yet to try.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 19, 2005 6:56 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
I've not noticed that directory problem before with the other script run from the 'file' menu, it's not somethng that's really bothered me that much as most of the scripts I run tend to be from the 'text viewport'. Just split your display (right click on the edge of a window and select 'split') adn hit Shift+F11 to load in the text window. Open new file. Once you load in the script make sure the mouse has focus on that window (move the mouse over the window) and then hit Alt+P.

Smoothgroups basically 'smooths' the mesh (stops it looking faceted). It's the same/similar sort of thing to phong shading a terrain mesh in level editing. To get an actual group you need to do what BlackDog mentioned above and 'split' the mesh up. It's mentioned in my D3 model tutorial.

http://www.quake3bits.com/htm/tutorials ... models.htm

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu May 19, 2005 7:11 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Mon Mar 01, 2004 9:22 pm
Posts: 890
Quote:
Smoothgroups basically 'smooths' the mesh (stops it looking faceted). It's the same/similar sort of thing to phong shading a terrain mesh in level editing. To get an actual group you need to do what BlackDog mentioned above and 'split' the mesh up. It's mentioned in my D3 model tutorial.


I thought that smoothgroups worked fine in D3, but that neither of the available exporters used them properly?


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 19, 2005 7:29 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
It might be something to do with the exporters but from what I've seen of the other file formats (and other 3D apps), D3 doesn't appear to be using the way you'd expect. I've had the same sort of problem with ASE files exported from Max, even though sm_g are present D3 seemed to ignore them which result in the model being incorrectly lit.

I've also found this with Bob and the MD5 format, if I used different groupings on the mesh (say the end of his sleave because I wanted a hard edge there) they'd get ignored unless the mesh group was split. It might be a side effect of the way Lightwave works with smoothgroups I don't know, but the only way I've been able to 100% gaurentee smooth 'groups' is to split the mesh where they've been needed.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu May 19, 2005 7:53 pm 
Offline
Last man standing
User avatar

Joined: Tue Dec 14, 2004 12:21 pm
Posts: 1151
Location: bath, england
understood and thanks kat, although Goofo`s script still doesn`t remember the export path with this method either (well not on my system) but the usm .ase exporter does, which is why I thought it was Goofo`s script doing something wrong and not the way blender runs it.

regarding smooth groups, I seem to be getting some weird lighting and a few hard edges on my terrain test model, where I created seams in blender to project the uv mapping at different angles.

some seams in game aren`t that noticeable, but where the ones that are, I think it`s more then the texture being slightly out of alignment which draws attention to them... is there a way we can we use smooth groups across these seams?

my current mesh isn`t split into sub objects (as I understand them) only divided up into patches of uv mapping.

I`m almost ready to post a pic of this in case it helps you guys determine if this is just a limit of the modeling and or rendering process or if it can be fixed.


Top
 Profile  
 
 Post subject:
PostPosted: Thu May 19, 2005 9:07 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Fri Nov 09, 2001 12:00 am
Posts: 5139
Location: UK
I've not got that problem with the export not remembering my working directory, most odd.

Anyway, you can't smooth across seams, otherwise there wouldn't be a seam, there are a couple of material shader parameters you can use to reduce the visual effect of them being there but I can't recall what they are off-hand. Speaking of which, I just spoke to der_ton about smoothgroups, MD5 doesn't use what you add to a mesh but, LWO and ASE does.

_________________
Modeling and modding tutorials and tips


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu May 19, 2005 9:23 pm 
Offline
Last man standing
User avatar

Joined: Tue Dec 14, 2004 12:21 pm
Posts: 1151
Location: bath, england
maybe the export bug is a 98se issue?

and thanks, I`ll study the original d3 material shaders, but if you remember what the parameters is, please tell me :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 277 posts ]  Go to page 1, 2, 3, 4, 5 ... 14  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group