alex4545354@Posted: Tue Jan 15, 2008 1:12 am :
Thank you very much!



ratty redemption@Posted: Tue Jan 15, 2008 1:14 am :
your welcome :)



alex4545354@Posted: Tue Jan 15, 2008 3:08 am :
One more question please,*.py?



ratty redemption@Posted: Tue Jan 15, 2008 3:29 am :
.py is the python script extension used by blender. the name of the file can be anything eg.

ase_exporter.py



kat@Posted: Tue Jan 15, 2008 6:00 am :
...or, just open it ip in the text window and press ALT+P to run it ;)



alex4545354@Posted: Wed Jan 16, 2008 1:36 am :
Thanks both of you, I appreciate the help!



alex4545354@Posted: Wed Jan 16, 2008 2:52 am :
Hmm not working, I did everything but no ase option comes up with file/export. Can you explain how to move this script to the text window, I tried to copy/paste but it wont let me, sorry for the stupid questions.



kat@Posted: Wed Jan 16, 2008 6:01 am :
Don't move or copy/paste. Just open a text view and then *open* the ASE script into it. You should then be able to Alt+P it to run



alex4545354@Posted: Sat Jan 19, 2008 6:59 pm :
kat, Im still not getting it right. When you say open a text window, do you mean in Blender? The little black text box that comes up? And if so, how do I open the ASE text into it? If not, what text window are you referring to then? I know these things may seem elementary but they are not to me, Im still fairly computer illiterate despite starting to learn Blender. :oops:



kat@Posted: Sat Jan 19, 2008 7:29 pm :
Split the screen: Move the mouse to the border of the viewport (the dividing line between the 3D view and the buttons below) until you see a double headed black arrow.

Click : when you see the double header, right click and select "Split...", a line will appear. Just left click to set it where it is.

Text view : Go to the button you see bottom left (should have a grid on it) and click that to open the view selection options. Click "Text Editor", the view will change to what looks like a flat grey background.

Open script : To the left where it says "screen 12" is a double arrowed button, click that and select "Open New", a browse window opens, browse to the file and 'open' in.

Run script : Alt+P to run the script.



spelunkarr@Posted: Tue Jan 13, 2009 8:23 am :
I made some changes the ASE exporter to help me with some issues I was having in Unreal Editor. The problems are pretty well outlined in ths article.

What I did was modify the script so that when you export, every polygon belongs to a smoothgroup, regardless of the 'set smooth' or 'set solid' setting. Polygons that are connected belong to the same smoothgroup. (Credit to SynaGl0w for the idea.) So, if you have a cube, and use the Y-KEY to split a face, you will have 2 smoothgroups. One will contain a single square, and one with 5 sides of a cube.

In practice, this means that I set my entire model to be smooth, which is ok because that's a pretty good representation of how Unreal Editor is going to treat it. Then, I use the Y-KEY to split off polygon groups where I want hard creases or non-smooth shading.

Vertex groups and their names are ignored. It looks like Unreal merges the vertices with the same coordinates back together, but it works out ok with the smoothgroups set, and you get pretty much what you expect.

I don't know if this is the best solution; I suspect it might break down with a lot of separate meshes. Also, a model with a mirror modifier looks like it doubles the number of meshes. But, I've imported models with 70+ smoothgroups, and it seems to work reasonably well (not that I'd really want to do that, but still...)

Anyways, I thought I'd post the exporter and see if anyone else thought it was a) useful or b) a very bad idea.

Goofos exporter Unrealized



kat@Posted: Tue Jan 13, 2009 3:25 pm :
So long as smoothing info is stored in face data, which is the way Max does it iirc, this should work ok, as yes, UE3 merges coincidental vertexes back together which has been the bane of Blender ASE users. Nice job :wink:

[EDIT] mirrored file on katsbits



OrbWeaver@Posted: Sat Sep 01, 2007 5:56 pm :
I don't really understand the need for objects to be exported relative to the world centre in the first place -- surely the mesh coordinates should always be exported relative to the object's own centre point, with the world transformation handled separately (assuming that each object in the ASE file can have its own world transformation, which it sounds like it can)?

From Goofos' description above, it almost sounds like the mesh is being transformed into world coordinates AND the world transformation is saved separately, which doesn't make sense to me at present.



kat@Posted: Sat Sep 01, 2007 6:50 pm :
It's a hang over to do with the way MAX exports ASE models (which is where the format comes from basically), afaik you can't do what we can in Blender and export an object with a local centre, Max objects always needed to be centred on the grid otherwise they got exported incorrectly - the mesh at a distance from the world centre point.

We (Blender users) don't need this so yes, if G Man can sort it out it's going to be a good feature to have.



Goofos@Posted: Sun Sep 02, 2007 5:38 pm :
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).



ratty redemption@Posted: Sun Sep 02, 2007 11:35 pm :
I'm getting this error with 0.6.10

Quote:
File "<string>", line 820
file.write("%s*MESH_FACE %i: A: %i B: %i C: %i AB: %i BC: %i C
%i\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert1, vert2, eds_fgon[0], e
on[1], eds_fgon[2], smooth, matID))

^
IndentationError: unindent does not match any outer indentation level



Goofos@Posted: Mon Sep 03, 2007 8:20 pm :
Fixed, but there could be more errors like this ;)



ratty redemption@Posted: Mon Sep 03, 2007 10:41 pm :
cool but your first post in this topic still says 0.6.10, is that the fixed version? I can test it tonight if you post it.



Goofos@Posted: Tue Sep 04, 2007 7:14 pm :
No version change because i only replaced some spaces with a tab :)



ratty redemption@Posted: Tue Sep 04, 2007 9:39 pm :
goofos, understood and its not crashing so thanks. unfortunately there seems to be a shading bug now.

compare these two d3 renderbumpflat normalmaps rendered from my latest test model. the first shows the normal shading as I have been used to with your previous versions, but the second shot shows the normals using your latest version.

Image Image



Mordenkainen@Posted: Wed Sep 05, 2007 5:19 am :
Goofos wrote:
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).


You sure did. That 130K poly terrain that used to take 13 minutes with 0.6.9 now takes 14 seconds. Tomorrow I'll test the resulting ASE in-game to see if everything exported correctly. Thanks a lot man.

P.S. Uploaded the newest version of the script here.



ratty redemption@Posted: Wed Sep 05, 2007 11:23 pm :
goofos, can you change the behavior of the selection only option to only export select objects on visible layers? currently it exports selected objects on hidden layers as well.



ratty redemption@Posted: Thu Sep 27, 2007 10:54 pm :
among other things I've spent weeks trying to fix the shading problem with my rock cracks in my blender model exported via goofos's .ase to d3's renderbumpflat.

what ever I tried in blender, psp7 (including painting on black lines to the specular and diffuse textures) or renderbumpflat, the results would end up the with my cracks being smoothed at the bottom instead of sharp :(

Image Image

so today I've done this simple test, using various v shaped planes to see if there was anything wrong with the normals, and although I am a noobie with renderbumpflat, I'm wondering if these results indicate the .ase model is not exporting properly?

Image

Image

the planes are drawn in blender with their vertex and face normals. I've also tried various uv mapping and the results after renderbumpflat seemed the same.

can anyone here help?



motorsep@Posted: Wed Dec 12, 2007 11:52 pm :
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).



ratty redemption@Posted: Thu Dec 13, 2007 12:23 am :
is goofos still working on his script? I haven't seen him reply to posts about it in months :(



kat@Posted: Thu Dec 13, 2007 6:13 am :
motorsep wrote:
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).
You shouldn't need to... I'm assuming your setting the grid size and clip end from the view properties panal? Increasing the grid scale increases the clip distance large enough for just about anything (inc Quake Wars terrains)



alex4545354@Posted: Tue Jan 15, 2008 1:12 am :
Thank you very much!



ratty redemption@Posted: Tue Jan 15, 2008 1:14 am :
your welcome :)



alex4545354@Posted: Tue Jan 15, 2008 3:08 am :
One more question please,*.py?



ratty redemption@Posted: Tue Jan 15, 2008 3:29 am :
.py is the python script extension used by blender. the name of the file can be anything eg.

ase_exporter.py



kat@Posted: Tue Jan 15, 2008 6:00 am :
...or, just open it ip in the text window and press ALT+P to run it ;)



alex4545354@Posted: Wed Jan 16, 2008 1:36 am :
Thanks both of you, I appreciate the help!



alex4545354@Posted: Wed Jan 16, 2008 2:52 am :
Hmm not working, I did everything but no ase option comes up with file/export. Can you explain how to move this script to the text window, I tried to copy/paste but it wont let me, sorry for the stupid questions.



kat@Posted: Wed Jan 16, 2008 6:01 am :
Don't move or copy/paste. Just open a text view and then *open* the ASE script into it. You should then be able to Alt+P it to run



alex4545354@Posted: Sat Jan 19, 2008 6:59 pm :
kat, Im still not getting it right. When you say open a text window, do you mean in Blender? The little black text box that comes up? And if so, how do I open the ASE text into it? If not, what text window are you referring to then? I know these things may seem elementary but they are not to me, Im still fairly computer illiterate despite starting to learn Blender. :oops:



kat@Posted: Sat Jan 19, 2008 7:29 pm :
Split the screen: Move the mouse to the border of the viewport (the dividing line between the 3D view and the buttons below) until you see a double headed black arrow.

Click : when you see the double header, right click and select "Split...", a line will appear. Just left click to set it where it is.

Text view : Go to the button you see bottom left (should have a grid on it) and click that to open the view selection options. Click "Text Editor", the view will change to what looks like a flat grey background.

Open script : To the left where it says "screen 12" is a double arrowed button, click that and select "Open New", a browse window opens, browse to the file and 'open' in.

Run script : Alt+P to run the script.



spelunkarr@Posted: Tue Jan 13, 2009 8:23 am :
I made some changes the ASE exporter to help me with some issues I was having in Unreal Editor. The problems are pretty well outlined in ths article.

What I did was modify the script so that when you export, every polygon belongs to a smoothgroup, regardless of the 'set smooth' or 'set solid' setting. Polygons that are connected belong to the same smoothgroup. (Credit to SynaGl0w for the idea.) So, if you have a cube, and use the Y-KEY to split a face, you will have 2 smoothgroups. One will contain a single square, and one with 5 sides of a cube.

In practice, this means that I set my entire model to be smooth, which is ok because that's a pretty good representation of how Unreal Editor is going to treat it. Then, I use the Y-KEY to split off polygon groups where I want hard creases or non-smooth shading.

Vertex groups and their names are ignored. It looks like Unreal merges the vertices with the same coordinates back together, but it works out ok with the smoothgroups set, and you get pretty much what you expect.

I don't know if this is the best solution; I suspect it might break down with a lot of separate meshes. Also, a model with a mirror modifier looks like it doubles the number of meshes. But, I've imported models with 70+ smoothgroups, and it seems to work reasonably well (not that I'd really want to do that, but still...)

Anyways, I thought I'd post the exporter and see if anyone else thought it was a) useful or b) a very bad idea.

Goofos exporter Unrealized



kat@Posted: Tue Jan 13, 2009 3:25 pm :
So long as smoothing info is stored in face data, which is the way Max does it iirc, this should work ok, as yes, UE3 merges coincidental vertexes back together which has been the bane of Blender ASE users. Nice job :wink:

[EDIT] mirrored file on katsbits



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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 sg



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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:
   



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
:arrow: current Version: 0.6.9

- will not work with blender versions below 2.44.
- can export mesh objects with tris or quads, 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.9'
Blender: 244
Group: 'Export'
Tooltip: 'ASCII Scene Export (*.ase)'
"""
__author__ = "Goofos"
__version__ = "0.6.9"
__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.9 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>
   ... multiple smoothgroups currently only with a workaround. Solid
   faces will not have a smoothgroup, smooth faces 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>
"""
# 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 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'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)

      if guiTable['VG2SG'] == 1:
         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'] == 1 and len(vGroups) > 0:
         for current_VG in vGroups:
            if current_VG.lower().count("smooth."):
               hasTable['hasSG'] = 1
               gWeight = current_VG.lower().replace("smooth.", "")
               sGroups[current_VG] = gWeight

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

      if guiTable['VC'] == 1:
         if me.vertexColors == True or me.vertexColors == 1:
            hasTable['hasVC'] = 1
         elif hasTable['hasMat'] == 1: # 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.
   location = obj.getLocation()
   row = obj.getMatrix('localspace').invert()
   #row = obj.getInverseMatrix()
   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   %.4f   %.4f   %.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'] == 1 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'] == 1: # Blender mats
         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'] == 1 and hasTable['hasSG'] == 1 and current_face.smooth:
            firstSmooth = 1
            for current_SG in sGroups:
               sGroup = me.getVertsFromGroup(current_SG)
               if vert0 in sGroup and vert1 in sGroup and vert2 in sGroup:
                  if firstSmooth == 1:
                     smooth += ' %s' % (sGroups[current_SG])
                     firstSmooth = 0
                  else:
                     smooth += ', %s' % (sGroups[current_SG])
         elif current_face.smooth:
            smooth += ' 1'

         file.write("%s*MESH_FACE %i:    A: %4f B: %4f C: %4f AB:    %i BC:    %i CA:    %i %s %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'] == 1 and hasTable['hasSG'] == 1 and current_face.smooth:
            firstSmooth = 1
            for current_SG in sGroups:
               sGroup = me.getVertsFromGroup(current_SG)
               if vert0 in sGroup and vert1 in sGroup and vert2 in sGroup and vert3 in sGroup:
                  if firs



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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 sg



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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'))



kat@Posted: Thu Mar 10, 2005 4:06 am :
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.



Goofos@Posted: Thu Mar 10, 2005 5:33 am :
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.



kat@Posted: Thu Mar 10, 2005 5:53 am :
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.



kat@Posted: Sat Mar 12, 2005 3:41 pm :
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



Goofos@Posted: Sun Mar 13, 2005 3:43 pm :
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):



kat@Posted: Sun Mar 13, 2005 4:02 pm :
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.



kat@Posted: Sun Mar 13, 2005 10:26 pm :
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.



Goofos@Posted: Mon Mar 14, 2005 2:49 am :
I have no other answer :D I tried to make a really nasty Object, but it was always exported.



kat@Posted: Mon Mar 14, 2005 4:30 am :
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:



ratty redemption@Posted: Thu May 19, 2005 11:57 am :
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?



Black Dog@Posted: Thu May 19, 2005 1:41 pm :
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.



kat@Posted: Thu May 19, 2005 2:02 pm :
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.



ratty redemption@Posted: Thu May 19, 2005 5:47 pm :
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.



kat@Posted: Thu May 19, 2005 5:56 pm :
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



Black Dog@Posted: Thu May 19, 2005 6:11 pm :
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?



kat@Posted: Thu May 19, 2005 6:29 pm :
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.



ratty redemption@Posted: Thu May 19, 2005 6:53 pm :
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.



kat@Posted: Thu May 19, 2005 8:07 pm :
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.



ratty redemption@Posted: Thu May 19, 2005 8:23 pm :
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 :)



alex4545354@Posted: Tue Jan 15, 2008 1:12 am :
Thank you very much!



ratty redemption@Posted: Tue Jan 15, 2008 1:14 am :
your welcome :)



alex4545354@Posted: Tue Jan 15, 2008 3:08 am :
One more question please,*.py?



ratty redemption@Posted: Tue Jan 15, 2008 3:29 am :
.py is the python script extension used by blender. the name of the file can be anything eg.

ase_exporter.py



kat@Posted: Tue Jan 15, 2008 6:00 am :
...or, just open it ip in the text window and press ALT+P to run it ;)



alex4545354@Posted: Wed Jan 16, 2008 1:36 am :
Thanks both of you, I appreciate the help!



alex4545354@Posted: Wed Jan 16, 2008 2:52 am :
Hmm not working, I did everything but no ase option comes up with file/export. Can you explain how to move this script to the text window, I tried to copy/paste but it wont let me, sorry for the stupid questions.



kat@Posted: Wed Jan 16, 2008 6:01 am :
Don't move or copy/paste. Just open a text view and then *open* the ASE script into it. You should then be able to Alt+P it to run



alex4545354@Posted: Sat Jan 19, 2008 6:59 pm :
kat, Im still not getting it right. When you say open a text window, do you mean in Blender? The little black text box that comes up? And if so, how do I open the ASE text into it? If not, what text window are you referring to then? I know these things may seem elementary but they are not to me, Im still fairly computer illiterate despite starting to learn Blender. :oops:



kat@Posted: Sat Jan 19, 2008 7:29 pm :
Split the screen: Move the mouse to the border of the viewport (the dividing line between the 3D view and the buttons below) until you see a double headed black arrow.

Click : when you see the double header, right click and select "Split...", a line will appear. Just left click to set it where it is.

Text view : Go to the button you see bottom left (should have a grid on it) and click that to open the view selection options. Click "Text Editor", the view will change to what looks like a flat grey background.

Open script : To the left where it says "screen 12" is a double arrowed button, click that and select "Open New", a browse window opens, browse to the file and 'open' in.

Run script : Alt+P to run the script.



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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]
          



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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'))



kat@Posted: Thu Mar 10, 2005 4:06 am :
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.



Goofos@Posted: Thu Mar 10, 2005 5:33 am :
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.



kat@Posted: Thu Mar 10, 2005 5:53 am :
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.



kat@Posted: Sat Mar 12, 2005 3:41 pm :
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



Goofos@Posted: Sun Mar 13, 2005 3:43 pm :
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):



kat@Posted: Sun Mar 13, 2005 4:02 pm :
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.



kat@Posted: Sun Mar 13, 2005 10:26 pm :
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.



Goofos@Posted: Mon Mar 14, 2005 2:49 am :
I have no other answer :D I tried to make a really nasty Object, but it was always exported.



kat@Posted: Mon Mar 14, 2005 4:30 am :
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:



ratty redemption@Posted: Thu May 19, 2005 11:57 am :
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?



Black Dog@Posted: Thu May 19, 2005 1:41 pm :
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.



kat@Posted: Thu May 19, 2005 2:02 pm :
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.



ratty redemption@Posted: Thu May 19, 2005 5:47 pm :
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.



kat@Posted: Thu May 19, 2005 5:56 pm :
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



Black Dog@Posted: Thu May 19, 2005 6:11 pm :
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?



kat@Posted: Thu May 19, 2005 6:29 pm :
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.



ratty redemption@Posted: Thu May 19, 2005 6:53 pm :
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.



kat@Posted: Thu May 19, 2005 8:07 pm :
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.



ratty redemption@Posted: Thu May 19, 2005 8:23 pm :
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 :)



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am :
Yes that's right.. right now you have to make the model, break it up, recentre and then rebuild in the editor, it just makes the bit in Blender less time consuming becasue you still have to 'reconstruct' in Radiant anyway.



Goofos@Posted: Fri Aug 31, 2007 4:01 pm :
Ok, you want the object centre as centre point instead of the world centre as centre point when loading the model into d3edit :idea:



kat@Posted: Fri Aug 31, 2007 4:24 pm :
It's not so much to do with Radiant per say becasue you can't import models into the editor based on their absolute positioning as they were in Blender. So it's more about speeding up the export process by allowing object centre export - otherwsise you have to move segments to world 000 which can take a lot of time on big models (obviously one does have to make sure in either case that the centre is placed correctly relative to the grid set up but that's simpel to do). If it can be done it'd be a huge time saver! :wink:



OrbWeaver@Posted: Sat Sep 01, 2007 5:56 pm :
I don't really understand the need for objects to be exported relative to the world centre in the first place -- surely the mesh coordinates should always be exported relative to the object's own centre point, with the world transformation handled separately (assuming that each object in the ASE file can have its own world transformation, which it sounds like it can)?

From Goofos' description above, it almost sounds like the mesh is being transformed into world coordinates AND the world transformation is saved separately, which doesn't make sense to me at present.



kat@Posted: Sat Sep 01, 2007 6:50 pm :
It's a hang over to do with the way MAX exports ASE models (which is where the format comes from basically), afaik you can't do what we can in Blender and export an object with a local centre, Max objects always needed to be centred on the grid otherwise they got exported incorrectly - the mesh at a distance from the world centre point.

We (Blender users) don't need this so yes, if G Man can sort it out it's going to be a good feature to have.



Goofos@Posted: Sun Sep 02, 2007 5:38 pm :
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).



ratty redemption@Posted: Sun Sep 02, 2007 11:35 pm :
I'm getting this error with 0.6.10

Quote:
File "<string>", line 820
file.write("%s*MESH_FACE %i: A: %i B: %i C: %i AB: %i BC: %i C
%i\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert1, vert2, eds_fgon[0], e
on[1], eds_fgon[2], smooth, matID))

^
IndentationError: unindent does not match any outer indentation level



Goofos@Posted: Mon Sep 03, 2007 8:20 pm :
Fixed, but there could be more errors like this ;)



ratty redemption@Posted: Mon Sep 03, 2007 10:41 pm :
cool but your first post in this topic still says 0.6.10, is that the fixed version? I can test it tonight if you post it.



Goofos@Posted: Tue Sep 04, 2007 7:14 pm :
No version change because i only replaced some spaces with a tab :)



ratty redemption@Posted: Tue Sep 04, 2007 9:39 pm :
goofos, understood and its not crashing so thanks. unfortunately there seems to be a shading bug now.

compare these two d3 renderbumpflat normalmaps rendered from my latest test model. the first shows the normal shading as I have been used to with your previous versions, but the second shot shows the normals using your latest version.

Image Image



Mordenkainen@Posted: Wed Sep 05, 2007 5:19 am :
Goofos wrote:
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).


You sure did. That 130K poly terrain that used to take 13 minutes with 0.6.9 now takes 14 seconds. Tomorrow I'll test the resulting ASE in-game to see if everything exported correctly. Thanks a lot man.

P.S. Uploaded the newest version of the script here.



ratty redemption@Posted: Wed Sep 05, 2007 11:23 pm :
goofos, can you change the behavior of the selection only option to only export select objects on visible layers? currently it exports selected objects on hidden layers as well.



ratty redemption@Posted: Thu Sep 27, 2007 10:54 pm :
among other things I've spent weeks trying to fix the shading problem with my rock cracks in my blender model exported via goofos's .ase to d3's renderbumpflat.

what ever I tried in blender, psp7 (including painting on black lines to the specular and diffuse textures) or renderbumpflat, the results would end up the with my cracks being smoothed at the bottom instead of sharp :(

Image Image

so today I've done this simple test, using various v shaped planes to see if there was anything wrong with the normals, and although I am a noobie with renderbumpflat, I'm wondering if these results indicate the .ase model is not exporting properly?

Image

Image

the planes are drawn in blender with their vertex and face normals. I've also tried various uv mapping and the results after renderbumpflat seemed the same.

can anyone here help?



motorsep@Posted: Wed Dec 12, 2007 11:52 pm :
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).



ratty redemption@Posted: Thu Dec 13, 2007 12:23 am :
is goofos still working on his script? I haven't seen him reply to posts about it in months :(



kat@Posted: Thu Dec 13, 2007 6:13 am :
motorsep wrote:
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).
You shouldn't need to... I'm assuming your setting the grid size and clip end from the view properties panal? Increasing the grid scale increases the clip distance large enough for just about anything (inc Quake Wars terrains)



motorsep@Posted: Wed Dec 19, 2007 9:57 pm :
Ahh, I didn't know that!
I have another question though. Can somebody (goofos probably) add animation support for ASE exporter? I was thinking of making some MD3 files with animations, but goofos ASE exporter doesn't support animation :(
Maybe you know about other ASE exporters that support animation?
Thanks.



kat@Posted: Thu Dec 20, 2007 12:37 am :
By "others" I take it you mean the Max ASE exporter? It's been asked before but as there is little documentation about the additional features of the format available freely on the net it's not likely to be added without extensive work (decompiling Max animated ASE files).



der_ton@Posted: Thu Dec 20, 2007 10:39 am :
Another issue might come up when you want to use those ASE files that contain animation. Not everything that can read ASE necessarily supports this feature. I highly doubt the Doom3 engine does, for example.



motorsep@Posted: Thu Dec 20, 2007 4:29 pm :
There is an util called q3data that converts animated ASE files to MD3 files (Quake 3 models) and it's very good method (unlike using MD3 exporters for Blender). That's why I was asking about animation support in ASE exporter.
It would be our back up plan if we will be unable to get animated meshes out of Blender into MD5 or SMD formats.



alex4545354@Posted: Mon Jan 14, 2008 9:43 pm :
Hello all, Im a noob blender user modeling for a Doom 3 mod and I need to convert .blend files to .ase. I see that the script above does that but could someone point me to a page that explains how to correctly install it? Thanks in advance!



ratty redemption@Posted: Mon Jan 14, 2008 11:35 pm :
copy and paste the code into a new .txt file and rename the .txt extension to .py then save that inside the .blender/scripts folder, it should then show up in blenders file menu/export next time blender is run.



alex4545354@Posted: Tue Jan 15, 2008 1:12 am :
Thank you very much!



ratty redemption@Posted: Tue Jan 15, 2008 1:14 am :
your welcome :)



alex4545354@Posted: Tue Jan 15, 2008 3:08 am :
One more question please,*.py?



ratty redemption@Posted: Tue Jan 15, 2008 3:29 am :
.py is the python script extension used by blender. the name of the file can be anything eg.

ase_exporter.py



kat@Posted: Tue Jan 15, 2008 6:00 am :
...or, just open it ip in the text window and press ALT+P to run it ;)



alex4545354@Posted: Wed Jan 16, 2008 1:36 am :
Thanks both of you, I appreciate the help!



alex4545354@Posted: Wed Jan 16, 2008 2:52 am :
Hmm not working, I did everything but no ase option comes up with file/export. Can you explain how to move this script to the text window, I tried to copy/paste but it wont let me, sorry for the stupid questions.



kat@Posted: Wed Jan 16, 2008 6:01 am :
Don't move or copy/paste. Just open a text view and then *open* the ASE script into it. You should then be able to Alt+P it to run



alex4545354@Posted: Sat Jan 19, 2008 6:59 pm :
kat, Im still not getting it right. When you say open a text window, do you mean in Blender? The little black text box that comes up? And if so, how do I open the ASE text into it? If not, what text window are you referring to then? I know these things may seem elementary but they are not to me, Im still fairly computer illiterate despite starting to learn Blender. :oops:



kat@Posted: Sat Jan 19, 2008 7:29 pm :
Split the screen: Move the mouse to the border of the viewport (the dividing line between the 3D view and the buttons below) until you see a double headed black arrow.

Click : when you see the double header, right click and select "Split...", a line will appear. Just left click to set it where it is.

Text view : Go to the button you see bottom left (should have a grid on it) and click that to open the view selection options. Click "Text Editor", the view will change to what looks like a flat grey background.

Open script : To the left where it says "screen 12" is a double arrowed button, click that and select "Open New", a browse window opens, browse to the file and 'open' in.

Run script : Alt+P to run the script.



Goofos@Posted: Thu Mar 10, 2005 2:25 am :
: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 s



Goofos@Posted: Mon May 14, 2007 7:03 pm :
As far as i know doom3 doesn't support smoothgroups from imported models but generate its own smoothing. If you want smoothgroups you should split those faces out of the mesh (or use the EdgeSplit Modifier).



ratty redemption@Posted: Tue May 15, 2007 1:14 am :
Goofos wrote:
As far as i know doom3 doesn't support smoothgroups from imported models but generate its own smoothing. If you want smoothgroups you should split those faces out of the mesh (or use the EdgeSplit Modifier).

iirc edges in the uvw maps also split smoothgroups in d3 engine.

also goofos, can you update your exporter for the latest blender release, currently blender reports

Code:
ImportError: No module named os

note: the .obj exporter shipped with blender 2.44 seems to work and doesn't report that error although the .lwo exporter also appears to be broken.



Goofos@Posted: Tue May 15, 2007 9:55 pm :
I have updated the script for 2.44. I dont recall all the changes i made :) but at least the radians thingy and the problem with zero VC and UV nums, mentioned by g77ase, is fixed. A better way to export smoothgroups is not included but solid or smooth faces is supported now.
The layer problem, mentioned by ratty, seems fixed in blender 2.44, if not i need a more detailed explanation.



ratty redemption@Posted: Tue May 15, 2007 11:27 pm :
thanks goofos, will test this tomorrow morning and report back to you :)



g77ase@Posted: Wed May 16, 2007 7:07 am :
Quote:
I think i made one of two simple mistakes with smoothgroups. First the vertex normals will be all smoothed (even vertex normals of solid faces and sharp edges) in a mesh, or second might something is wrong with the face smoothgroups, especially those outer faces of a smoothgroup

and
Quote:
A better way to export smoothgroups is not included but solid or smooth faces is supported now.


I not reffer to the smoothgroups result bad writed in the ase(and this engine dont read .ase normals at all). I say that the vgroups 2 sgroups simply dont work. No difference in the exported .ase with or without this option selected in the script UI. i only get "*MESH_SMOOTHING" for solid faces or "*MESH_SMOOTHING 1" for smooth faces into blender, but the script have a lot of code to read the VGroups and by these quotes look like that this almost make any effect(almost a non reliable one). :(

and over your quotes in the code over the mat/map name lengths, i find this in an .ase on the web (supposedly created with 3dmax)
Quote:
*MATERIAL_NAME "textures/desert/t_rockwall1_clip"
*MAP_NAME "textures\desert\t_rockwall1.tga"


finally, over the way to make the material list, its suppoded that for it exist multi mats, and i mean more reliable to follow the .ase way for it of one material with multiple users pointing to it by MATERIAL_REF(and probably some converters/editor crash if find more that one mat with the sme name)

EDIT: i test the exporter both with BL 2.40, 2.42a and 2.43, and in all dont get any result with VG > SG



Goofos@Posted: Wed May 16, 2007 7:58 pm :
VG2SG should be fixed now (v0.6.4). For Materials i added a simple check so that they are not duplicated, but this is limited to objects which have 100% the same materials. This mean if you have a mesh with same materials + 1 additional material, the script will write a new MultiMat for that object. To completely fix this i really think the script needs a complete rewrite (might worth too for future additions along with the idea of sharpedges2smoothgroups).



kat@Posted: Wed May 16, 2007 10:23 pm :
If you can work on a rewrite and update the current at the same time then that would be good; I imagine it'd take a while and it's be a shame for the script to loose it's grip on current Blender versions.

No one says this enough, sincere thanks for even doing the ASE export/importer in the first place!



ratty redemption@Posted: Thu May 17, 2007 12:41 am :
Goofos wrote:
VG2SG should be fixed now (v0.6.4). For Materials i added a simple check so that they are not duplicated, but this is limited to objects which have 100% the same materials. This mean if you have a mesh with same materials + 1 additional material, the script will write a new MultiMat for that object. To completely fix this i really think the script needs a complete rewrite (might worth too for future additions along with the idea of sharpedges2smoothgroups).

seems to be working with my models and d3 :)



Goofos@Posted: Thu May 17, 2007 1:11 am :
Because a rewrite need its time, i tried to completely get rid of duplicate materials with the current script and now its fixed (v0.6.5) ... somehow :> but i removed the "UV Image as Materials" feature. If someone need this and if there isn't already a script which can do this, i would write a separate script (that's easier :)).

If the current script has a problem, i will update it as long as it isn't such a big thing like correct vertex normals, this is really something for a rewrite.

BTW thanks for those who offer a download of the scripts ;)



kat@Posted: Thu May 17, 2007 1:22 am :
Goofos wrote:
...BTW thanks for those who offer a download of the scripts ;)
Me yo No.1 fan! Just updated KatsBits with the relavant details.



ratty redemption@Posted: Thu May 17, 2007 1:32 am :
kat, hehe :)

goofos v0.6.5 also appears to be working fine my end and I personally don't need that feature you took out :)



ratty redemption@Posted: Thu May 17, 2007 2:08 am :
Goofos wrote:
The layer problem, mentioned by ratty, seems fixed in blender 2.44, if not i need a more detailed explanation.

sorry, I forgot to test this earlier, both 0.6.4 and 0.6.5 are reporting errors:

Code:
Traceback (most recent call last):
  File "<string>", line 1175, in write_ui
  File "<string>", line 97, in write
  File "<string>", line 142, in set_up
  File "<string>", line 177, in set_lists
IndexError: list index out of range

Traceback (most recent call last):
  File "<string>", line 1102, in write_ui
  File "<string>", line 98, in write
  File "<string>", line 611, in write_mesh
  File "<string>", line 722, in mesh_faceLis
TypeError: list objects are unhashable


but tbh, as 2.44 and your script don't hang like before, I'm content for you to leave the script like this, ie the error popup is enough to remind me to use the 3d views > lock layers and used camera to scene button on the header bar.



Goofos@Posted: Thu May 17, 2007 3:47 pm :
Aww the OOPS Schematic View looks ugly after a few exports. It seems that Blender now saves Object and Mesh Datablocks even when these are not linked to a scene.

Ratty, where is the l3d views > lock layers and used camera to scene button? :>



ratty redemption@Posted: Thu May 17, 2007 4:35 pm :
next to the toggle layer visibility buttons on the toolbar/header of the 3d view.

ot: I'm off on a trip for a few days so won't be able to reply until I get back.



g77ase@Posted: Tue May 22, 2007 5:36 pm :
0.6.5 are showing the same error all the time(i try a lot of settings/models)
Code:
Traceback (most recent call last):
  File "<string>", line 1102, in write_ui
  File "<string>", line 98, in write
  File "<string>", line 611, in write_mesh
  File "<string>", line 722, in mesh_faceLis
TypeError: list objects are unhashable



kat@Posted: Tue May 22, 2007 6:09 pm :
Have you got Python 2.5.x installed?



Goofos@Posted: Wed May 23, 2007 1:06 am :
I guess this is a bug in blender 2.44 which i could reproduce after some experimenting with "Lock layers and cameras to scene". I posted this problem in the blender.org forum, maybe i simply do something wrong.



ratty redemption@Posted: Wed May 23, 2007 2:02 am :
thanks for looking into it goofos :)



Goofos@Posted: Thu May 24, 2007 3:31 pm :
I think it's fixed (v0.6.6)

[edit] ... and finally i hope i found out what the problem is.
This happend when you deleted a material and than exported the mesh?



g77ase@Posted: Fri May 25, 2007 6:49 am :
Quote:
Have you got Python 2.5.x installed?

i try both without python and with 2.5.1

Quote:
This happend when you deleted a material and than exported the mesh?

no, i simply open some of my models and try to export.

testing 0.6.6...

EDIT:tested. and now dont crash
but looks like the script forgot to change/cut the VG names:
Code:
*MESH_SMOOTHING Smooth.1, Smooth.2    *MESH_MTLID 0



Goofos@Posted: Fri May 25, 2007 4:11 pm :
You should write "smooth" uncapitalised :> but i quickly fixed it so capitalised or uncapitalised works.

I still think deleted or unlinked materials are the problem. You might tried the script with some more complex scenes where its possible you unlinked materials, relinked it or linked it to another meshes as i trying to reproduce that problem with a simple cube.

We can test this.

1. Open a file where you has had that error
2. select some Meshes
3. load this simple script into a "Text Editor" Window of blender:
Code:
import Blender
scn = Blender.Scene.GetCurrent()

obs = [ob for ob in scn.objects.selected if ob.type == 'Mesh']


for ob in obs:
   me = ob.getData(0,1)
   
   if me.materials:
      print "Mesh Materials:", me.materials
      print "Mesh has exactly", len(me.materials), "Materials"

4. press Alt+P (Run Phyton Script) in the text editor window.
5. this should print the material list for each mesh in the Command Window . If there is a material list with "None" items, that's the problem.



OrbWeaver@Posted: Sat Jul 21, 2007 6:35 pm :
I'm having some difficulty with the latest script version (0.6.7), in that it always seems to export the model relative to the world origin, rather than its own origin. This means that for models which are some distance from world origin, the exported ASE has its origin way outside the model itself, leading to leaks.

Is this a problem with the script or am I just doing something wrong?



kat@Posted: Sat Jul 21, 2007 7:19 pm :
If I understand what you've said properly it sounds like you've no recentred the POO of those mesh sections.

http://www.katsbits.com/cgi-bin/ikonboa ... 60#entry65



OrbWeaver@Posted: Sat Jul 21, 2007 7:23 pm :
I'm not sure what the POO is, is this the Blender mesh center (i.e. set with Center New and Center Cursor)? I always set this correctly before exporting, but my resulting ASE does not have its origin at this location, but at the world origin.



ratty redemption@Posted: Sat Jul 21, 2007 7:59 pm :
I'm using 0.6.7 with d3edit and gtkr 1.5 and don't have any problems with the centers.



kat@Posted: Sat Jul 21, 2007 8:47 pm :
OrbWeaver wrote:
I'm not sure what the POO is, is this the Blender mesh center (i.e. set with Center New and Center Cursor)? I always set this correctly before exporting, but my resulting ASE does not have its origin at this location, but at the world origin.
POO = Point of Origin, just an easy acronym for people to remember the importance of recentring the mesh sections centre point.

What version of Blender & Python are you using?



OrbWeaver@Posted: Sat Jul 21, 2007 9:59 pm :
I'm using Blender 2.44 with Python 2.4.3 on Ubuntu Linux 6.06.

I'm sure it must be something about my setup or technique, since other people would have noticed such a major problem -- I can even just create a simple cube, move it to the left, check that the Center is still inside the cube, and export it to find an ASE with the origin point several units to the right of the cube.



kat@Posted: Sun Jul 22, 2007 6:11 am :
You need python 2.5.x for Blender 2.44, that's probably the problem.



OrbWeaver@Posted: Sun Jul 22, 2007 9:06 am :
Ah OK, I will try that.



OrbWeaver@Posted: Sun Jul 22, 2007 11:11 am :
Nope, upgrading Python (and Blender to use the new Python version) made no difference.

The Blender scene looks as follows:

Image

with a correctly-positioned object centre. When the ASE is imported into Doom it looks like this:
Image

with the ASE origin corresponding to the Blender world origin, not the object's own centre.

Maybe the script doesn't work on Linux, for some reason?



kat@Posted: Sun Jul 22, 2007 6:56 pm :
Where abouts is the objects centre? The little pink sphere, I can't see it in that Blender shot so I'm assuming it's where the cursor gizmo is?



OrbWeaver@Posted: Sun Jul 22, 2007 8:53 pm :
Yes, the manipulator is aligned to the object's center in that shot.



Mordenkainen@Posted: Mon Jul 23, 2007 1:25 pm :
Is it normal for a 130K poly mesh (with UV mapping info) to take over 2 hours to export? I have a C2D E6600 with 2gb 667Mhz ram. I know Python, being an interpreted language, is slow and all but my heighmap to ase exporter written in C# only takes 5 seconds to generate the same .ASE.

I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?



kat@Posted: Mon Jul 23, 2007 5:21 pm :
It's got to be something with using Linux as both of you appear to be having odd problems that us winOS users don't have (afaict). I don't have the first idea about how to fix that though.



Mordenkainen@Posted: Thu Jul 26, 2007 1:35 pm :
Can anyone please comment on the export speeds their getting and how it compares to my experience?



kat@Posted: Thu Jul 26, 2007 2:08 pm :
iirc it's you're vertices that cause slow downs not the polycount. If you've got a lot of forced smoothgroups it really slows the process down. Donkey posted this on my forums, a modelled remake of chartres by qkennyq which too 30 mins or so to export, not sure how that compares to what you've done though.



ratty redemption@Posted: Thu Jul 26, 2007 2:14 pm :
I just tried exporting a high poly mesh and it hung my system win xp home edition sp2, p4 3ghz, 512mb ram.



Mordenkainen@Posted: Fri Jul 27, 2007 1:01 pm :
Thanks kat and ratty redemption; it seems the slow export speed is normal then :|

kat: I don't use "forced smoothgroup" as you defined it in the link you posted ("smoothgroup splits"). The model is not split up (i.e. single object with no redundant vertices) and only has one "vertex smooth group".



ratty redemption@Posted: Fri Jul 27, 2007 1:37 pm :
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script



Goofos@Posted: Fri Jul 27, 2007 3:58 pm :
Slowdown issue should be fixed in both windows and linux ;> ( v0.6.8 )



Mordenkainen@Posted: Fri Jul 27, 2007 8:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 9:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 9:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 3:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 11:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 11:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 9:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 2:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 5:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 10:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 11:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 1:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 9:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 1:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 1:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 2:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 7:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 9:09 am :
Yes that's right.. right now you have to make the model, break it up, recentre and then rebuild in the editor, it just makes the bit in Blender less time consuming becasue you still have to 'reconstruct' in Radiant anyway.



Goofos@Posted: Fri Aug 31, 2007 5:01 pm :
Ok, you want the object centre as centre point instead of the world centre as centre point when loading the model into d3edit :idea:



kat@Posted: Fri Aug 31, 2007 5:24 pm :
It's not so much to do with Radiant per say becasue you can't import models into the editor based on their absolute positioning as they were in Blender. So it's more about speeding up the export process by allowing object centre export - otherwsise you have to move segments to world 000 which can take a lot of time on big models (obviously one does have to make sure in either case that the centre is placed correctly relative to the grid set up but that's simpel to do). If it can be done it'd be a huge time saver! :wink:



OrbWeaver@Posted: Sat Sep 01, 2007 6:56 pm :
I don't really understand the need for objects to be exported relative to the world centre in the first place -- surely the mesh coordinates should always be exported relative to the object's own centre point, with the world transformation handled separately (assuming that each object in the ASE file can have its own world transformation, which it sounds like it can)?

From Goofos' description above, it almost sounds like the mesh is being transformed into world coordinates AND the world transformation is saved separately, which doesn't make sense to me at present.



kat@Posted: Sat Sep 01, 2007 7:50 pm :
It's a hang over to do with the way MAX exports ASE models (which is where the format comes from basically), afaik you can't do what we can in Blender and export an object with a local centre, Max objects always needed to be centred on the grid otherwise they got exported incorrectly - the mesh at a distance from the world centre point.

We (Blender users) don't need this so yes, if G Man can sort it out it's going to be a good feature to have.



Goofos@Posted: Sun Sep 02, 2007 6:38 pm :
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).



ratty redemption@Posted: Mon Sep 03, 2007 12:35 am :
I'm getting this error with 0.6.10

Quote:
File "<string>", line 820
file.write("%s*MESH_FACE %i: A: %i B: %i C: %i AB: %i BC: %i C
%i\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert1, vert2, eds_fgon[0], e
on[1], eds_fgon[2], smooth, matID))

^
IndentationError: unindent does not match any outer indentation level



Goofos@Posted: Mon Sep 03, 2007 9:20 pm :
Fixed, but there could be more errors like this ;)



ratty redemption@Posted: Mon Sep 03, 2007 11:41 pm :
cool but your first post in this topic still says 0.6.10, is that the fixed version? I can test it tonight if you post it.



Goofos@Posted: Tue Sep 04, 2007 8:14 pm :
No version change because i only replaced some spaces with a tab :)



ratty redemption@Posted: Tue Sep 04, 2007 10:39 pm :
goofos, understood and its not crashing so thanks. unfortunately there seems to be a shading bug now.

compare these two d3 renderbumpflat normalmaps rendered from my latest test model. the first shows the normal shading as I have been used to with your previous versions, but the second shot shows the normals using your latest version.

Image Image



Mordenkainen@Posted: Wed Sep 05, 2007 6:19 am :
Goofos wrote:
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).


You sure did. That 130K poly terrain that used to take 13 minutes with 0.6.9 now takes 14 seconds. Tomorrow I'll test the resulting ASE in-game to see if everything exported correctly. Thanks a lot man.

P.S. Uploaded the newest version of the script here.



ratty redemption@Posted: Thu Sep 06, 2007 12:23 am :
goofos, can you change the behavior of the selection only option to only export select objects on visible layers? currently it exports selected objects on hidden layers as well.



ratty redemption@Posted: Thu Sep 27, 2007 11:54 pm :
among other things I've spent weeks trying to fix the shading problem with my rock cracks in my blender model exported via goofos's .ase to d3's renderbumpflat.

what ever I tried in blender, psp7 (including painting on black lines to the specular and diffuse textures) or renderbumpflat, the results would end up the with my cracks being smoothed at the bottom instead of sharp :(

Image Image

so today I've done this simple test, using various v shaped planes to see if there was anything wrong with the normals, and although I am a noobie with renderbumpflat, I'm wondering if these results indicate the .ase model is not exporting properly?

Image

Image

the planes are drawn in blender with their vertex and face normals. I've also tried various uv mapping and the results after renderbumpflat seemed the same.

can anyone here help?



motorsep@Posted: Thu Dec 13, 2007 12:52 am :
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).



ratty redemption@Posted: Thu Dec 13, 2007 1:23 am :
is goofos still working on his script? I haven't seen him reply to posts about it in months :(



kat@Posted: Thu Dec 13, 2007 7:13 am :
motorsep wrote:
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).
You shouldn't need to... I'm assuming your setting the grid size and clip end from the view properties panal? Increasing the grid scale increases the clip distance large enough for just about anything (inc Quake Wars terrains)



motorsep@Posted: Wed Dec 19, 2007 10:57 pm :
Ahh, I didn't know that!
I have another question though. Can somebody (goofos probably) add animation support for ASE exporter? I was thinking of making some MD3 files with animations, but goofos ASE exporter doesn't support animation :(
Maybe you know about other ASE exporters that support animation?
Thanks.



kat@Posted: Thu Dec 20, 2007 1:37 am :
By "others" I take it you mean the Max ASE exporter? It's been asked before but as there is little documentation about the additional features of the format available freely on the net it's not likely to be added without extensive work (decompiling Max animated ASE files).



der_ton@Posted: Thu Dec 20, 2007 11:39 am :
Another issue might come up when you want to use those ASE files that contain animation. Not everything that can read ASE necessarily supports this feature. I highly doubt the Doom3 engine does, for example.



motorsep@Posted: Thu Dec 20, 2007 5:29 pm :
There is an util called q3data that converts animated ASE files to MD3 files (Quake 3 models) and it's very good method (unlike using MD3 exporters for Blender). That's why I was asking about animation support in ASE exporter.
It would be our back up plan if we will be unable to get animated meshes out of Blender into MD5 or SMD formats.



alex4545354@Posted: Mon Jan 14, 2008 10:43 pm :
Hello all, Im a noob blender user modeling for a Doom 3 mod and I need to convert .blend files to .ase. I see that the script above does that but could someone point me to a page that explains how to correctly install it? Thanks in advance!



ratty redemption@Posted: Tue Jan 15, 2008 12:35 am :
copy and paste the code into a new .txt file and rename the .txt extension to .py then save that inside the .blender/scripts folder, it should then show up in blenders file menu/export next time blender is run.



Mordenkainen@Posted: Fri Jul 27, 2007 8:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 9:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 9:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 3:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 11:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 11:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 9:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 2:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 5:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 10:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 11:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 1:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 9:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 1:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 1:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 2:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 7:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 9:09 am :
Yes that's right.. right now you have to make the model, break it up, recentre and then rebuild in the editor, it just makes the bit in Blender less time consuming becasue you still have to 'reconstruct' in Radiant anyway.



Goofos@Posted: Fri Aug 31, 2007 5:01 pm :
Ok, you want the object centre as centre point instead of the world centre as centre point when loading the model into d3edit :idea:



kat@Posted: Fri Aug 31, 2007 5:24 pm :
It's not so much to do with Radiant per say becasue you can't import models into the editor based on their absolute positioning as they were in Blender. So it's more about speeding up the export process by allowing object centre export - otherwsise you have to move segments to world 000 which can take a lot of time on big models (obviously one does have to make sure in either case that the centre is placed correctly relative to the grid set up but that's simpel to do). If it can be done it'd be a huge time saver! :wink:



OrbWeaver@Posted: Sat Sep 01, 2007 6:56 pm :
I don't really understand the need for objects to be exported relative to the world centre in the first place -- surely the mesh coordinates should always be exported relative to the object's own centre point, with the world transformation handled separately (assuming that each object in the ASE file can have its own world transformation, which it sounds like it can)?

From Goofos' description above, it almost sounds like the mesh is being transformed into world coordinates AND the world transformation is saved separately, which doesn't make sense to me at present.



kat@Posted: Sat Sep 01, 2007 7:50 pm :
It's a hang over to do with the way MAX exports ASE models (which is where the format comes from basically), afaik you can't do what we can in Blender and export an object with a local centre, Max objects always needed to be centred on the grid otherwise they got exported incorrectly - the mesh at a distance from the world centre point.

We (Blender users) don't need this so yes, if G Man can sort it out it's going to be a good feature to have.



Goofos@Posted: Sun Sep 02, 2007 6:38 pm :
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).



ratty redemption@Posted: Mon Sep 03, 2007 12:35 am :
I'm getting this error with 0.6.10

Quote:
File "<string>", line 820
file.write("%s*MESH_FACE %i: A: %i B: %i C: %i AB: %i BC: %i C
%i\t %s \t%s\n" % ((Tab*idnt), faceNo, vert0, vert1, vert2, eds_fgon[0], e
on[1], eds_fgon[2], smooth, matID))

^
IndentationError: unindent does not match any outer indentation level



Goofos@Posted: Mon Sep 03, 2007 9:20 pm :
Fixed, but there could be more errors like this ;)



ratty redemption@Posted: Mon Sep 03, 2007 11:41 pm :
cool but your first post in this topic still says 0.6.10, is that the fixed version? I can test it tonight if you post it.



Goofos@Posted: Tue Sep 04, 2007 8:14 pm :
No version change because i only replaced some spaces with a tab :)



ratty redemption@Posted: Tue Sep 04, 2007 10:39 pm :
goofos, understood and its not crashing so thanks. unfortunately there seems to be a shading bug now.

compare these two d3 renderbumpflat normalmaps rendered from my latest test model. the first shows the normal shading as I have been used to with your previous versions, but the second shot shows the normals using your latest version.

Image Image



Mordenkainen@Posted: Wed Sep 05, 2007 6:19 am :
Goofos wrote:
I added a "Center Objects" feature (but still keeps rot and scale infos) and might have fixed mordenkainen's performance issue (v0.6.10).


You sure did. That 130K poly terrain that used to take 13 minutes with 0.6.9 now takes 14 seconds. Tomorrow I'll test the resulting ASE in-game to see if everything exported correctly. Thanks a lot man.

P.S. Uploaded the newest version of the script here.



ratty redemption@Posted: Thu Sep 06, 2007 12:23 am :
goofos, can you change the behavior of the selection only option to only export select objects on visible layers? currently it exports selected objects on hidden layers as well.



ratty redemption@Posted: Thu Sep 27, 2007 11:54 pm :
among other things I've spent weeks trying to fix the shading problem with my rock cracks in my blender model exported via goofos's .ase to d3's renderbumpflat.

what ever I tried in blender, psp7 (including painting on black lines to the specular and diffuse textures) or renderbumpflat, the results would end up the with my cracks being smoothed at the bottom instead of sharp :(

Image Image

so today I've done this simple test, using various v shaped planes to see if there was anything wrong with the normals, and although I am a noobie with renderbumpflat, I'm wondering if these results indicate the .ase model is not exporting properly?

Image

Image

the planes are drawn in blender with their vertex and face normals. I've also tried various uv mapping and the results after renderbumpflat seemed the same.

can anyone here help?



motorsep@Posted: Thu Dec 13, 2007 12:52 am :
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).



ratty redemption@Posted: Thu Dec 13, 2007 1:23 am :
is goofos still working on his script? I haven't seen him reply to posts about it in months :(



kat@Posted: Thu Dec 13, 2007 7:13 am :
motorsep wrote:
goofos, could you please add <Scale> option to your ASE exporter?
Sometimes scene become too big and since Blender has limited clipping planes, parts of the model disappear :( If we would have scale option, we could model level in smaller scale (1:4 let's say), but after export get level with original size (1:1, scaled up 4 times).
You shouldn't need to... I'm assuming your setting the grid size and clip end from the view properties panal? Increasing the grid scale increases the clip distance large enough for just about anything (inc Quake Wars terrains)



motorsep@Posted: Wed Dec 19, 2007 10:57 pm :
Ahh, I didn't know that!
I have another question though. Can somebody (goofos probably) add animation support for ASE exporter? I was thinking of making some MD3 files with animations, but goofos ASE exporter doesn't support animation :(
Maybe you know about other ASE exporters that support animation?
Thanks.



kat@Posted: Thu Dec 20, 2007 1:37 am :
By "others" I take it you mean the Max ASE exporter? It's been asked before but as there is little documentation about the additional features of the format available freely on the net it's not likely to be added without extensive work (decompiling Max animated ASE files).



der_ton@Posted: Thu Dec 20, 2007 11:39 am :
Another issue might come up when you want to use those ASE files that contain animation. Not everything that can read ASE necessarily supports this feature. I highly doubt the Doom3 engine does, for example.



motorsep@Posted: Thu Dec 20, 2007 5:29 pm :
There is an util called q3data that converts animated ASE files to MD3 files (Quake 3 models) and it's very good method (unlike using MD3 exporters for Blender). That's why I was asking about animation support in ASE exporter.
It would be our back up plan if we will be unable to get animated meshes out of Blender into MD5 or SMD formats.



alex4545354@Posted: Mon Jan 14, 2008 10:43 pm :
Hello all, Im a noob blender user modeling for a Doom 3 mod and I need to convert .blend files to .ase. I see that the script above does that but could someone point me to a page that explains how to correctly install it? Thanks in advance!



ratty redemption@Posted: Tue Jan 15, 2008 12:35 am :
copy and paste the code into a new .txt file and rename the .txt extension to .py then save that inside the .blender/scripts folder, it should then show up in blenders file menu/export next time blender is run.



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am : Doom3world • View topic - new ASE Exporter

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Sun Dec 30, 2007 5:41 am

All times are UTC




Post new topic Reply to topic  [ 258 posts ]  Go to page Previous  1 ... 9, 10, 11, 12, 13  Next
Author Message
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 7:19 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:54 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:57 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 951
Location: milton keynes, england
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 2:04 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 10:32 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sun Jul 29, 2007 10:16 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Jul 30, 2007 8:24 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Jul 31, 2007 1:26 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 951
Location: milton keynes, england
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 01, 2007 4:08 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 03, 2007 9:21 pm 
Offline
is connecting to Doom3world.org

Joined: Sun Jul 29, 2007 10:13 pm
Posts: 7
edit- post deleted.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 10:43 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 12:06 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 8:23 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 12:26 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 12:44 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 1:30 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 6:40 am 
Offline
found a secret

Joined: Wed Sep 08, 2004 7:48 am
Posts: 556
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.

_________________
Project Lead and lead coder The Dark Mod http://www.thedarkmod.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 8:09 am 
Offline



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am : Doom3world • View topic - new ASE Exporter

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Wed Dec 26, 2007 1:46 pm

All times are UTC




Post new topic Reply to topic  [ 258 posts ]  Go to page Previous  1 ... 9, 10, 11, 12, 13  Next
Author Message
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 7:19 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:54 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:57 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 951
Location: milton keynes, england
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 2:04 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 10:32 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sun Jul 29, 2007 10:16 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Jul 30, 2007 8:24 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Jul 31, 2007 1:26 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 951
Location: milton keynes, england
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 01, 2007 4:08 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 03, 2007 9:21 pm 
Offline
is connecting to Doom3world.org

Joined: Sun Jul 29, 2007 10:13 pm
Posts: 7
edit- post deleted.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 10:43 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 12:06 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 8:23 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 12:26 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 12:44 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 1:30 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 6:40 am 
Offline
found a secret

Joined: Wed Sep 08, 2004 7:48 am
Posts: 554
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.

_________________
Project Lead and lead coder The Dark Mod http://www.thedarkmod.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 8:09 am 
Offline



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am : Doom3world • View topic - new ASE Exporter

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Thu Dec 20, 2007 10:55 pm

All times are UTC




Post new topic Reply to topic  [ 258 posts ]  Go to page Previous  1 ... 9, 10, 11, 12, 13  Next
Author Message
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 7:19 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:54 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:57 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 943
Location: milton keynes, england
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 2:04 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 10:32 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sun Jul 29, 2007 10:16 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Jul 30, 2007 8:24 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Jul 31, 2007 1:26 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 943
Location: milton keynes, england
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 01, 2007 4:08 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 03, 2007 9:21 pm 
Offline
is connecting to Doom3world.org

Joined: Sun Jul 29, 2007 10:13 pm
Posts: 7
edit- post deleted.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 10:43 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 12:06 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 8:23 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 12:26 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 12:44 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 1:30 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 6:40 am 
Offline
found a secret

Joined: Wed Sep 08, 2004 7:48 am
Posts: 554
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.

_________________
Project Lead and lead coder The Dark Mod http://www.thedarkmod.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 8:09 am 
Offline



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am : Doom3world • View topic - new ASE Exporter

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Mon Dec 24, 2007 7:37 am

All times are UTC




Post new topic Reply to topic  [ 258 posts ]  Go to page Previous  1 ... 9, 10, 11, 12, 13  Next
Author Message
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 7:19 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:54 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:57 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 949
Location: milton keynes, england
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 2:04 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 10:32 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sun Jul 29, 2007 10:16 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Jul 30, 2007 8:24 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Jul 31, 2007 1:26 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 949
Location: milton keynes, england
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 01, 2007 4:08 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 03, 2007 9:21 pm 
Offline
is connecting to Doom3world.org

Joined: Sun Jul 29, 2007 10:13 pm
Posts: 7
edit- post deleted.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 10:43 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 12:06 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 8:23 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 12:26 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 12:44 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 1:30 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 6:40 am 
Offline
found a secret

Joined: Wed Sep 08, 2004 7:48 am
Posts: 554
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.

_________________
Project Lead and lead coder The Dark Mod http://www.thedarkmod.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 8:09 am 
Offline



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am : Doom3world • View topic - new ASE Exporter

Doom3world

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

All times are UTC




Post new topic Reply to topic  [ 258 posts ]  Go to page Previous  1 ... 9, 10, 11, 12, 13  Next
Author Message
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 7:19 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:54 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:57 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 947
Location: milton keynes, england
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 2:04 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 10:32 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sun Jul 29, 2007 10:16 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Jul 30, 2007 8:24 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Jul 31, 2007 1:26 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 947
Location: milton keynes, england
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 01, 2007 4:08 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1310
Location: PT, EU
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 03, 2007 9:21 pm 
Offline
is connecting to Doom3world.org

Joined: Sun Jul 29, 2007 10:13 pm
Posts: 7
edit- post deleted.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 10:43 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Aug 27, 2007 12:06 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 8:23 am 
Offline
fired 300 rounds
User avatar

Joined: Tue May 24, 2005 7:41 pm
Posts: 343
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Tue Aug 28, 2007 12:26 pm 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 12:44 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Wed Aug 29, 2007 1:30 am 
Offline
"...mostly harmless?!"
User avatar

Joined: Thu Nov 08, 2001 11:00 pm
Posts: 4940
Location: UK, York
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?

_________________
ImageCo-Admin - Modelling and modding tutorials and tips


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 6:40 am 
Offline
found a secret

Joined: Wed Sep 08, 2004 7:48 am
Posts: 554
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.

_________________
Project Lead and lead coder The Dark Mod http://www.thedarkmod.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Aug 31, 2007 8:09 am 
Offline



Mordenkainen@Posted: Fri Jul 27, 2007 7:19 pm :
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.



Mordenkainen@Posted: Fri Jul 27, 2007 8:54 pm :
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.



ratty redemption@Posted: Fri Jul 27, 2007 8:57 pm :
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.



Goofos@Posted: Sat Jul 28, 2007 2:04 pm :
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.



Mordenkainen@Posted: Sat Jul 28, 2007 10:32 pm :
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.



Goofos@Posted: Sun Jul 29, 2007 10:16 am :
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?



Mordenkainen@Posted: Mon Jul 30, 2007 8:24 pm :
Goofos wrote:
I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.


Yeah. Do you want me to upload my model somewhere so you can see if there's anything wrong with it?

Quote:
If you track the progressbar, when does the script completely hang for a good while?


Most of the time is spent during "Writing Faces".



ratty redemption@Posted: Tue Jul 31, 2007 1:26 pm :
goofos, sorry I didn't get to back to you earlier on this but I have just exported a high poly mesh a few times with uv's and vertex color, heres the console report.

Code:
Verts: 263169 Tris: 524288 Faces: 262144
Successfully exported temp.ase in 146.48 seconds

which I think is truly amazing how much you've optimized your code :D



Mordenkainen@Posted: Wed Aug 01, 2007 4:08 pm :
Mordenkainen wrote:
I precompiled the Python API during its installation it but Blender's own python scripts (including this exporter) aren't precompiled. Anyway I can precompile these too?


Yep, answering myself. :) After some persistant searching I've found a way to precompile Blender's Python scripts too. I haven't experienced any noticeable perf increase but if you want to try it paste the following to Blender's Script editor and execute. Replace the path file with the one you installed Blender to, obviously:

Code:
import compileall

compileall.compile_dir('C:\Programs\Blender\.blender\scripts', force=True)



hyp3rfocus@Posted: Fri Aug 03, 2007 9:21 pm :
edit- post deleted.



OrbWeaver@Posted: Mon Aug 27, 2007 10:43 am :
I have identified the cause of the mesh's coordinates being written relative to the world origin rather than the mesh object's own origin:

Code:
      me = Mesh.New()      # Create a new mesh

      if guiTable['MOD'] == 1:   # 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
      tempObj = Blender.Object.New('Mesh', 'ASE_export_temp_obj')
      tempObj.setMatrix(obj.matrix)
      tempObj.link(me)


What I assume this is doing (not being a Blender Python expert myself) is creating a new mesh object, copying the mesh data from the selected mesh into this new object, and then setting the new object to have the same transformation as the previous object (basically a deep copy of the mesh being exported).

The problem is the line me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.

I assume that the purpose of this line is to avoid the user having to use Ctrl-A to apply size/rotation before exporting? Personally I would prefer to have to do this manually rather than having the translation applied to the mesh as well.



kat@Posted: Mon Aug 27, 2007 12:06 pm :
I just re-read the problem you were having, am I right in assuming that you're basically centring the objects origin and then trying to export the mesh when it's not centred on the 000 grid origin? (so the objects centre is relative to where the object is on the grid?)



OrbWeaver@Posted: Tue Aug 28, 2007 8:23 am :
Yes -- the object's own centre point is correct, but is not aligned with the world center (0, 0, 0). With the script as written, the exported object's centre point is aligned with the world origin (0, 0, 0) and ignores the object's own centre point. With the problematic line commented out, it works as expected.



kat@Posted: Tue Aug 28, 2007 12:26 pm :
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*



Goofos@Posted: Wed Aug 29, 2007 12:44 am :
OrbWeaver wrote:
me.transform(obj.matrix) which (I assume) applies the transformation of the object to the mesh data itself -- however, this transformation would include the location as well as the rotation and scale parameters, essentially applying the object's translation value to the contained mesh data, which is not what is needed when exporting a single object.


Yes, it applies loc/rot/scale to the mesh data. In earlier script versions this was an optional option. Later i discovered that the mesh data is transformed in ASE files but the object still has the loc/rot/scale informations.

If you comment that line out, it basically use the local mesh data without loc/rot/scale but it still write the transformation infos to the ase file and would have a negative transformation when importing the ase file in apps which care about loc/rot/scale. I think usually you would need to change some more lines in the script so it don't export the original transform infos. But i'm currently unsure which lines (at least some lines in def mesh_matrix).


kat wrote:
I wonder if this could be added as an export option? Being able to export objects inplace (but with correctly recentred POO's) would be handy when building levels; it's pain in the arse to keep having to pull everything to the grid centre making sure you don't screw up the position of each section, an option to export in place would mean not having to do any of that *looks at Goofos with a Spock like raised eyebrow in question*


I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?



kat@Posted: Wed Aug 29, 2007 1:30 am :
Goofos wrote:
...I think i don't got it. :> You mean export each object moved to world origin, or export each object with its origin moved to the world origin?
Soory Goofos.. what I mean was this... say you design a level (as I've been doing) and in order to export it and make it efficient with the engine it has to be cut up into segments. Normally each of these segments needs both the mesh and the segments centre to bo placed over the 000 grid point, that means each piece has to be moved which runs the risk of messing up the alignment with other segments.

What would be ideal is if you could correctly position the segments centre where it was originally and have the mesh export from there - unless I'm missing something in the new code the mesh gets exported with the polygons positioned where they were but the objects centre in then placed at 000, is that right? What you'd want on a big mesh cut into many segments is to leave them where they are and just repostion the origin locally and export like that.

Does that make sense?



sparhawk@Posted: Fri Aug 31, 2007 6:40 am :
Not sure if I understand it correctly, but an option that could specify wether you want the object to be exported as residing a 0,0,0 or stay where it is would be very usefull.

Normally, I would like my objects to be at the centerpoint. When I model, then I often enough break them up into individual models and align them properly. In this case the models should stay relativ to where they are, because otherwise they would end up all at the centerpoint instead of making a bigger model.

In some cases I model stuff together in one file, which are still individual usable models though. Of course I can use different layers, but there is a limit to that, so I often enough move them out of the way. In such a case it would be usefull to export all the models as centerpoint models. This could be simply a toggle on the export dialog, which adjusts the matrix accordingly.



kat@Posted: Fri Aug 31, 2007 8:09 am : Doom3world • View topic - new ASE Exporter

Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Fri Dec 21, 2007 2:14 am

All times are UTC




Post new topic Reply to topic  [ 258 posts ]  Go to page Previous  1 ... 9, 10, 11, 12, 13  Next
Author Message
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 7:19 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
ratty redemption wrote:
mordenkainen, if you split the model in say 4 sections, does it take a quarter of the time to export one section? this is something I've been wondering about with some of my tests. there seems to be a threshold (could be ram related?) although I'm not sure yet what the verts/poly count threshold is yet, and whether it is a restriction of our systems or blender and goofos's .script


The same model at 30K takes around 5 mins. At 130K it takes 2 hours. Didn't experiment splitting it though.

Goofos: Thanks, dinner first but I'll try it and then report back.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:54 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Fri Jul 27, 2007 8:57 pm 
Offline
did just hit his 750th monster
User avatar

Joined: Tue Dec 14, 2004 11:21 am
Posts: 943
Location: milton keynes, england
cool, I'll test this later tonight, and thanks mordenkainen for ul the file. that is easier then copy/paste the script from the forum here.

_________________
(wip) ratty d3 hell map
katsbits.com


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 2:04 pm 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
Mordenkainen wrote:
Excellent work Goofos. 30K poly version now takes 50 seconds and the 130K one only takes 19 minutes! I also did a quick test and it appears the export worked correctly so a big thank you!

Btw, if anyone wants to download the script file instead of copy/paste get it here.


19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.

(BTW quickly added support for multiple uv layers :> )

Please test the updated v0.6.9 script if uv and vcolor is exported right.


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sat Jul 28, 2007 10:32 pm 
Offline
King of the Hill
User avatar

Joined: Mon Nov 04, 2002 10:50 pm
Posts: 1309
Location: PT, EU
Goofos wrote:
19 min still is a bit to slow therefore i looked too into the uv (and vcolor) part of the script and rewrote/optimised this. I think now exporting a highpoly mesh should not need more than a minute.


130K poly version now takes 13 minutes. Export worked nicely. Great job man.

EDIT: 0.6.9 version uploaded here.

_________________
Beyond3D.com | Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Sun Jul 29, 2007 10:16 am 
Offline
picked up the chaingun
User avatar

Joined: Thu Mar 10, 2005 2:05 am
Posts: 177
Location: black forrest
13 min? Hrmz, i have no idea where else i could search for lame code in the script.

I exported a mesh with 266766 verts, 531456 tris (265728 faces), two UV layers and some vcolors in 114 seconds with an old Athlon XP 3200 and 512 MB Ram. Usually i would think your PC should be faster.

If you track the progressbar, when does the script completely hang for a good while?


Top
 Profile  
 
 Post subject: Re: new ASE Exporter
PostPosted: Mon Jul 30, 2007 8:24 pm