Skip to main content
GameDev.net gamedev.net
🔒 Locked

AttributeError: 'NoneType' object has no attribute 'getData'

Started by PDX_Catalyst Oct 7, 2007 at 9:04 PM 15 replies 14.8k views
Original Post
PDX_Catalyst
PDX_Catalyst
AttributeError: 'NoneType' object has no attribute 'getData' I'm getting this error from a python script when trying to export from Blender to an .x file after adding rigging and animation. Any help would be hugely appreciated. ~ C
Oluseyi
Oluseyi
The script anticipates an object which has a method .getData(), but is receiving the Python value None instead (which is a global, intrinsic value of type NoneType). Basically, the data being passed to the script is wrong or malformed in some way.
PDX_Catalyst
PDX_Catalyst
Data from Blender? Is this a bug with Blender, a bug with the script, or user (me) error? And what should I do to fix it? I put two full days of work into this model and I'd like to get it out of Blender and into the game. ;)
PDX_Catalyst
PDX_Catalyst
SURELY someone knows a fix for this. My productivity is in the pooper until I can get this model out of Blender and into the app.
Oluseyi
Oluseyi
Quote:
Original post by PDX_Catalyst
Data from Blender? Is this a bug with Blender, a bug with the script, or user (me) error?

Any of the above. For example, the script may have been written against version x of Blender, but the data format changed in version y.

Quote:
And what should I do to fix it?

Blender has message boards. Use them. People who use Blender habitually are far more likely to have encountered this problem and understand the context well enough to proffer a solution. (For instance, I've only used Blender a handful of times, and it's been at least a year since the last.) Also consider contacting the author of the script, if you can determine who that is.

Good luck.
PDX_Catalyst
PDX_Catalyst
Oh trust me, I've posted on the Blender artist forums too. Only one reply asking for the line number, which I gave, and then nothing else.

~ C
Oluseyi
Oluseyi
Alright, post the script.
PDX_Catalyst
PDX_Catalyst
Ok, so three items below. First the error messages. Next the piece of the script where things go wrong. Third, a message from someone about the problem that I finally got on the Blender forums, though no response since then. I don't completely understand the message, though. It seems he's suggesting that I can't have a vertice be weighted anything other than 1, and only from one bone. It also seems he might be suggesting I could have 3/4 from one bone and 1/4 from another, but that I couldn't have 3/4 from one and 1/2 from another. I'm hoping it's the latter since I'd rather do the extra work than accept a weightpainting that is less than ideal. I do NOT want a model where a vertice can't be influenced by more than one bone. It makes for really unattractive deformations.

======================================================


Compiled with Python version 2.5.
Checking for installed Python... got it!
exporting...
Traceback (most recent call last):
File "", line 172, in draw
File "", line 86, in my_callback
File "", line 394, in SelectObjs
File "", line 352, in writeObjFrames
File "", line 514, in writeRootBone
File "", line 485, in exportMeshArm
AttributeError: 'NoneType' object has no attribute 'getData'

---------------------- Below is Line 485 in Context ---------------------

#***********************************************
#Export Mesh with Armature
#***********************************************
def exportMeshArm(self,arm,arm_ob,ch_obj):
tex = []
(Line 485) mesh = ch_obj.getData()
self.writeTextures(ch_obj, tex)
self.writeMeshcoordArm(ch_obj ,arm_ob)
self.writeMeshMaterialList(ch_obj, mesh, tex)
self.writeMeshNormals(ch_obj, mesh)
self.writeMeshTextureCoords(ch_obj, mesh)
self.writeSkinWeights(arm,mesh)
#self.file.write(" } // End of the Frame %s \n" % (ch_obj.name))
self.file.write(" } // End of the Object %s \n" % (ch_obj.name))


---------------------------------------------------

For lowpoly models, particularly when exporting to directX ,it is better to assign vertex groups manually. It's pretty important that a vertex has a weight of 1 which can only really be guaranteed by manually assigining vertex groups.

Blender's animation tools are geared more towards high poly models for film animation where all the fancy techniques such as weight painting, heat painting, soft body interaction, shape keys, lattices etc really come into their own. The rules for low poly modelling and animation for export to game formats is KISS....Keep it simple. Most, if not all the tutorials and techniques you see for using Blender's animation tools are unsuitable for Low Poly application. Low Poly is a technique all to it's self. Plus, DirectX is a pretty pish format and unfortunately not well supported by Blender... the script does work but you've got to do it exactly the way the exporter wants you to. The new FBX exporter is much better if your application supports it.

Once you've done it a couple of times you'll realise that assigning the vertex groups manually is actually faster than weight painting as long as you set your model up properly in a decent pose you can border select almost everything you need to.

One more thing, don't use envelopes either.
Oluseyi
Oluseyi
I can't debug a portion of a script; there's too much context missing, from the type of ch_obj (it's initialized elsewhere) to the various lines referenced in the traceback call stack.

Post the whole script inside a source box ([source lang="python"]code here[/source]) so it doesn't fill up the screen with pages and pages.
Vorpy
Vorpy
NoneType is the type of None. The third argument being passed to the function is None, and None doesn't have any user defined data or functions.
PDX_Catalyst
PDX_Catalyst
Thanks, here you go =)

#!BPY"""# Name: 'DirectX (.x)...'# Blender: 242# Group: 'Export'# Tooltip: 'Export to DirectX text file format format for XNA Animation Component Library.'"""__author__ = "minahito (original:Arben (Ben) Omari)"__url__ = ("blender", "elysiun", "Adjuster's site http://sunday-lab.blogspot.com/, Author's site http://www.omariben.too.it")__version__ = "3.0"__bpydoc__ = """This script exports a Blender mesh with armature to DirectX 8's text fileformat.Notes:
Check author's site or the elYsiun forum for a new beta version of theDX exporter."""# DirectXExporter.py version 3.0# Copyright (C) 2006 Arben OMARI -- omariarben@everyday.com ## 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.# This script export meshes created with Blender in DirectX8 file format# it exports meshes,armatures,materials,normals,texturecoords and animations# Grab the latest version here :www.omariben.too.it# [Notice]# This script is the custom version of Mr.Arben Omari's great work.# If you have a question about the adjusted part, visit http://sunday-lab.blogspot.com/.import Blenderfrom Blender import Types, Object, NMesh, Material,Armature,Meshfrom Blender.Mathutils import *from Blender import Draw, BGLfrom Blender.BGL import *import mathglobal mat_flip,index_list,space,bone_list,mat_dictglobal anim,flip_norm,swap_zy,flip_z,speed,ticks,no_light,recalc_norm,Bl_normbone_list =[]index_list = []mat_dict = {}space = 0;flip_z = 1;anim=0;swap_yz=0;flip_norm=0;speed=0;ticks= 25Bl_norm = 1;recalc_norm = 0;no_light = 0toggle_val = 0toggle1_val = 0toggle2_val = 0toggle3_val = 1toggle4_val = 0toggle5_val = 1toggle6_val = 0toggle7_val = 0anim_tick = Draw.Create(25)#***********************************************# DirectX file spec only allows letters, digits, and # underscore in Names.#***********************************************def make_legal_name(starting_name): new_name = starting_name.replace('.','_') new_name = new_name.replace(' ','_') if new_name[0].isdigit(): new_name = '_' + new_name return new_name#***********************************************# MAIN#***********************************************def my_callback(filename): if filename.find('.x', -2) <= 0: filename += '.x' xexport = xExport(filename) xexport.SelectObjs()def my_callback_sel(filename): if filename.find('.x', -2) <= 0: filename += '.x' xexport = xExport(filename) xexport.exportSelMesh()def event(evt, val): if evt == Draw.ESCKEY: Draw.Exit() returndef button_event(evt): global toggle_val,toggle1_val,toggle2_val,toggle3_val,toggle4_val,toggle5_val,toggle6_val,toggle7_val global flip_z,swap_yz,flip_norm,anim,ticks,speed,no_light,Bl_norm,recalc_norm arg = __script__['arg'] if evt == 1: toggle_val = 1 - toggle_val anim = toggle_val Draw.Redraw(1) if evt == 2: toggle1_val = 1 - toggle1_val flip_norm = toggle1_val Draw.Redraw(1) if evt == 3: toggle2_val = 1 - toggle2_val swap_yz = toggle2_val Draw.Redraw(1) if evt == 4: toggle3_val = 1 - toggle3_val flip_z = toggle3_val Draw.Redraw(1) if evt == 5: toggle4_val = 1 - toggle4_val speed = toggle4_val Draw.Redraw(1) if evt == 10: toggle5_val = 1 - toggle5_val if toggle5_val==1: toggle6_val = 0 toggle7_val = 0 else : toggle6_val = 1 toggle7_val = 1 no_light = toggle7_val recalc_norm = toggle6_val Bl_norm = toggle5_val Draw.Redraw(1) if evt == 11: toggle6_val = 1 - toggle6_val if toggle6_val==1: toggle5_val = 0 toggle7_val = 0 else : toggle5_val = 1 toggle7_val = 1 no_light = toggle7_val recalc_norm = toggle6_val Bl_norm = toggle5_val Draw.Redraw(1) if evt == 12: toggle7_val = 1 - toggle7_val if toggle7_val==1: toggle6_val = 0 toggle5_val = 0 else : toggle6_val = 1 toggle5_val = 1 no_light = toggle7_val recalc_norm = toggle6_val Bl_norm = toggle5_val Draw.Redraw(1) if evt == 6: ticks = anim_tick.val if evt == 7: fname = Blender.sys.makename(ext = ".x") Blender.Window.FileSelector(my_callback, "Export DirectX", fname) if evt == 8: fname = Blender.sys.makename(ext = ".x") Blender.Window.FileSelector(my_callback_sel, "Export DirectX", fname) if evt == 9: Draw.Exit() def draw(): global animsg,flipmsg,swapmsg,anim_tick global flip_z,swap_yz,flip_norm,anim,ticks,speed,recalc_norm,Bl_norm,no_light glClearColor(0.55,0.6,0.6,1) glClear(BGL.GL_COLOR_BUFFER_BIT) #external box glColor3f(0.2,0.3,0.3) rect(10,402,300,382) #-- #glColor3f(0.3,0.4,0.4) #rect(11,399,298,398) #-- glColor3f(0.5,0.75,0.65) rect(14,398,292,30) #-- glColor3f(0.5,0.75,0.65) rect(14,366,292,160) #-- glColor3f(0.5,0.75,0.65) rect(14,202,292,60) #-- glColor3f(0.5,0.75,0.65) rect(14,138,292,40) #-- glColor3f(0.5,0.75,0.65) rect(14,94,292,70) glColor3f(0.8,.8,0.6) glRasterPos2i(20, 380) Draw.Text("DirectX Exporter ",'large') Draw.Text("(for Blender 2.41)", 'small') #-------Aniamtion toggle--------------------------------------------- Draw.Toggle("Anim", 1, 20, 330, 55, 20, toggle_val,"export animations") if toggle_val : anim = 1 animsg = "animation will be exported" else: anim = 0 animsg = "animation will be not exported" glRasterPos2i(100,335) Draw.Text(animsg) #---Flip normals toggle----------------------------------------------- Draw.Toggle("Flip norm", 2, 20, 300, 55, 20, toggle1_val,"invert normals") if toggle1_val : flip_norm = 1 flipmsg = "flipped normals" else: flip_norm = 0 flipmsg = "not flipped normals" glRasterPos2i(100,305) Draw.Text(flipmsg) #------Swap yz toggle---------------------------------------------------------------- Draw.Toggle("Swap zy", 3, 20, 270, 55, 20, toggle2_val,"swap z,y axis(y up)") if toggle2_val : swap_yz = 1 swapmsg = "Y-axis up" else: swap_yz = 0 swapmsg = "Z-axis up" glRasterPos2i(100,275) Draw.Text(swapmsg) #------Flip z toggle---------------------------------------------------------------- Draw.Toggle("Flip z", 4, 20, 240, 55, 20, toggle3_val,"flip z axis") if toggle3_val : flip_z = 1 zmsg = "left handed system" else: flip_z = 0 zmsg = "right handed system" glRasterPos2i(100,245) Draw.Text(zmsg) #------Speed toggle---------------------------------------------------------------- Draw.Toggle("Speed", 5, 20, 210, 55, 20, toggle4_val,"Animation speed") if toggle4_val : speed = 1 spedmsg = "set speed" anim_tick = Draw.Number("", 6,200, 210, 85, 20, anim_tick.val,1,100000,"ticks per second") else: speed = 0 spedmsg = "" glRasterPos2i(100,215) Draw.Text(spedmsg) #------Blender Normals toggle---------------------------------------------------------------- Draw.Toggle("Bl.normals", 10, 20, 105, 75, 25, toggle5_val,"export normals as in Blender") if toggle5_val : Bl_norm = 1 #------Recalculute Normals toggle---------------------------------------------------------------- Draw.Toggle("recalc.no", 11, 120, 105, 75, 25, toggle6_val,"export recalculated normals") if toggle6_val : recalc_norm = 1 #------Recalculute Normals toggle---------------------------------------------------------------- Draw.Toggle("no smooth", 12, 220, 105, 75, 25, toggle7_val,"every vertex has the face normal,no smoothing") if toggle7_val : no_light = 1 #------Draw Button export---------------------------------------------------------------- exp_butt = Draw.Button("Export All",7,20, 155, 75, 30, "export all the scene objects") sel_butt = Draw.Button("Export Sel",8,120, 155, 75, 30, "export the selected object") exit_butt = Draw.Button("Exit",9,220, 155, 75, 30, "exit") glRasterPos2i(20,75) Draw.Text("(C) 2006 Arben OMARI ") glRasterPos2i(20,55) Draw.Text("http://www.omariben.too.it") glRasterPos2i(20,35) Draw.Text("aromar@tin.it") def rect(x,y,width,height): glBegin(GL_LINE_LOOP) glVertex2i(x,y) glVertex2i(x+width,y) glVertex2i(x+width,y-height) glVertex2i(x,y-height) glEnd() def rectFill(x,y,width,height): glBegin(GL_POLYGON) glVertex2i(x,y) glVertex2i(x+width,y) glVertex2i(x+width,y-height) glVertex2i(x,y-height) glEnd() Draw.Register(draw, event, button_event)#***********************************************#***********************************************# EXPORTER#***********************************************#***********************************************class xExport: def __init__(self, filename): self.file = open(filename, "w")#********************************************************************************************************************************************* #*********************************************** #Select Scene objects #*********************************************** def analyzeScene(self): parent_list = [] for obj in Blender.Scene.GetCurrent().objects: if obj.type in ('Mesh', 'Armature', 'Empty'): if obj.parent == None : parent_list.append(obj) return parent_list def getChildren(self,obj): obs = Blender.Scene.GetCurrent().objects return [ ob for ob in obs if ob.parent == obj ] def getArmChildren(self,obj): for ob in Blender.Scene.GetCurrent().objects: #Object.Get(): if ob.parent == obj : return ob def getLocMat(self, obj): pare = obj.parent mat = obj.matrixWorld mat_id = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]) if pare: mat_p = pare.matrixWorld mat_c = Matrix(mat_p) mat_c.invert() mat_f = mat * mat_c else : mat_id.invert() mat_f = mat * mat_id return mat_f def writeObjFrames(self,obj): global space,chld_obj,ch_list mesh = obj.getData() if obj.type == "Empty" : mat = self.getLocMat(obj) mat_c = Matrix(mat) self.writeArmFrames(mat_c, make_legal_name(obj.name)) if type(mesh) == Types.ArmatureType : Child_obj = self.getArmChildren(obj) chld_obj = obj ch_list.append(Child_obj) self.writeRootBone(obj, Child_obj) if obj.type == 'Mesh' and obj not in ch_list: self.exportMesh(obj) def writeChildObj(self,obj): global space,ch_list space += 1 if obj : for ob in obj: if ob not in ch_list: self.writeObjFrames(ob) ch_list.append(ob) ch_ob = self.getChildren(ob) self.writeChildObj(ch_ob) self.closeBrackets() self.file.write(" // End of the Object %s \n" % (ob.name)) def writeRootFrame(self): global flip_z,swap_yz,speed if speed: self.writeAnimTicks() if flip_z: mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]) else : mat_flip = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]) if swap_yz : mat_rot = RotationMatrix(-90, 4, 'x') mat_flip = mat_rot * mat_flip self.writeArmFrames(mat_flip, "RootFrame") ################################################################## def SelectObjs(self): global space,chld_obj,ch_list,flip_z,swap_yz,speed print "exporting..." self.writeHeader() self.writeRootFrame() obj_list = self.analyzeScene() space += 1 ch_list = [] for obj in obj_list: self.writeObjFrames(obj) ch_l = self.getChildren(obj) for ch in ch_l: if ch and ch.type == "Armature": ch_list.append(ch) self.writeObjFrames(ch) else : self.writeChildObj(ch_l) if obj.type != "Armature": self.file.write(" } // SI End of the Object %s \n" % (obj.name)) self.file.write("} // End of the Root Frame\n") if anim : self.file.write("AnimationSet AnimationSet0 {\n") for obj in Blender.Scene.GetCurrent().objects: if obj.type in ('Mesh', 'Empty'): ip_list = obj.ipo if ip_list != None : self.writeAnimationObj(obj) elif obj.type == 'Armature': act_list = obj.getAction() if act_list != None : self.writeAnimation(obj) #ip_list = obj.ipo #if ip_list != None : # self.writeAnimationObj(obj) self.file.write("} // End of Animation Set\n") self.writeEnd() ####################################################### def writeAnimTicks(self): global ticks self.file.write("AnimTicksPerSecond {\n") self.file.write("%d; \n" % (ticks)) self.file.write("}\n") #*********************************************** #Export Mesh without Armature #*********************************************** def exportMesh(self, obj): tex = [] mesh = obj.getData() self.writeTextures(obj, tex) self.writeMeshcoordArm(obj, arm_ob = None) self.writeMeshMaterialList(obj, mesh, tex) self.writeMeshNormals(obj, mesh) self.writeMeshTextureCoords(obj, mesh) self.file.write(" } // End of the Mesh %s \n" % (obj.name)) #*********************************************** #Export the Selected Mesh #*********************************************** def exportSelMesh(self): print "exporting ..." self.writeHeader() self.writeRootFrame() tex = [] objs = Object.GetSelected() for obj in objs: if obj.type == 'Mesh': mesh = obj.data self.writeTextures(obj, tex) self.writeMeshcoordArm(obj, arm_ob = None) self.writeMeshMaterialList(obj, mesh, tex) self.writeMeshNormals(obj, mesh) self.writeMeshTextureCoords(obj, mesh) self.file.write(" }\n") self.file.write("}\n") ind = objs.index(obj) if ind == len(objs)-1: self.file.write("}\n") ip_list = obj.ipo if ip_list != None : self.file.write("AnimationSet AnimationSet0 {\n") self.writeAnimationObj(obj) self.file.write("}\n") else : print "The selected object is not a mesh" print "...finished" #*********************************************** #Export Mesh with Armature #*********************************************** def exportMeshArm(self,arm,arm_ob,ch_obj): tex = [] mesh = ch_obj.getData() self.writeTextures(ch_obj, tex) self.writeMeshcoordArm(ch_obj ,arm_ob) self.writeMeshMaterialList(ch_obj, mesh, tex) self.writeMeshNormals(ch_obj, mesh) self.writeMeshTextureCoords(ch_obj, mesh) self.writeSkinWeights(arm,mesh) #self.file.write(" } // End of the Frame %s \n" % (ch_obj.name)) self.file.write(" } // End of the Object %s \n" % (ch_obj.name)) #*********************************************** #Export Root Bone #*********************************************** def writeRootBone(self, chld_obj, child_obj): global space,root_bon arms = chld_obj.getData() mat_arm = self.getLocMat(chld_obj) for bon in arms.bones.values(): if bon.hasParent(): pass else: root_bon = bon space += 1 mat_r = self.writeAnimCombineMatrix(root_bon,1) self.writeArmFrames(mat_r, make_legal_name(root_bon.name)) bon_c = root_bon.children self.writeChildren(bon_c) self.file.write(" } // End of the Bone %s \n" % (root_bon.name)) self.exportMeshArm(arms, chld_obj ,child_obj) #*********************************************** #Create Children structure #*********************************************** def writeBon(self,bon): global space mat_r = self.writeAnimCombineMatrix(bon,1) self.writeArmFrames(mat_r, make_legal_name(bon.name)) def writeChildren(self,bon_c): global space,bone_list space += 1 if bon_c: for bo in bon_c: if bo.name not in bone_list: self.writeBon(bo) bone_list.append(bo.name) bo_c = bo.children self.writeChildren(bo_c) self.closeBrackets() def closeBrackets(self): global space space = space-1 tab = " " self.file.write("%s" % (tab * space)) self.file.write("}\n") #*********************************************** #Offset Matrix #*********************************************** def writeMatrixOffset(self,bon): global chld_obj Blender.Set('curframe', 1) pose = chld_obj.getPose() pos_b = pose.bones[bon.name] mat_b = pos_b.poseMatrix mat_c = Matrix(mat_b) mat_c.invert() return mat_c #*********************************************** #Combine Matrix #*********************************************** def writeCombineMatrix(self,bon): global chld_obj Blender.Set('curframe', 1) pose = chld_obj.getPose() pos_b = pose.bones[bon.name] mat_b = pos_b.poseMatrix if bon.hasParent(): pare = bon.parent pos_p = pose.bones[pare.name] mat_p = pos_p.poseMatrix else: mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]) mat_c = Matrix(mat_p) mat_c.invert() mat_f = mat_b * mat_c return mat_f #*********************************************** #Combine Matrix #*********************************************** def writeAnimCombineMatrix(self,bon,fre): global chld_obj Blender.Set('curframe', fre) pose = chld_obj.getPose() pos_b = pose.bones[bon.name] mat_b = pos_b.poseMatrix if bon.hasParent(): pare = bon.parent pos_p = pose.bones[pare.name] mat_p = pos_p.poseMatrix else: mat_p = Matrix([1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]) mat_c = Matrix(mat_p) mat_c.invert() mat_f = mat_b * mat_c return mat_f#********************************************************************************************************************************************* #*********************************************** #Write SkinWeights #*********************************************** def writeSkinWeights(self, arm, mesh): global index_list v_dict = {} Blender.Set('curframe',1) self.file.write(" XSkinMeshHeader {\n") max_infl = 0 for bo in arm.bones.values() : name = bo.name try : vertx_list = mesh.getVertsFromGroup(name,1) for inde in vertx_list : vert_infl = mesh.getVertexInfluences(inde[0]) ln_infl = len(vert_infl) if ln_infl > max_infl : max_infl = ln_infl except: pass self.file.write(" %d; \n" % (max_infl)) self.file.write(" %d; \n" % (max_infl * 3)) self.file.write(" %d; \n" % (len(arm.bones.values()))) self.file.write(" }\n") for bo in arm.bones.values() : bo_list = [] weight_list = [] name = bo.name f_name = make_legal_name(name) try : vert_list = mesh.getVertsFromGroup(name,1) le = 0 for indx in vert_list: ver_infl = mesh.getVertexInfluences(indx[0]) infl = 0.0 if len(ver_infl) != 0: sum = 0.0 for bone_n, weight in ver_infl: if bone_n == name: infl = weight sum += weight infl /= sum i = -1 for el in index_list : i += 1 if el == indx[0] : le +=1 bo_list.append(i) weight_list.append(infl) self.file.write(" SkinWeights {\n") self.file.write(' "%s"; \n' % (f_name)) self.file.write(' %d; \n' % (le)) count = 0 for ind in bo_list : count += 1 if count == len(bo_list): self.file.write(" %d; \n" % (ind)) else : self.file.write(" %d, \n" % (ind)) cou = 0 for wegh in weight_list : cou += 1 if cou == len(weight_list): self.file.write(" %f; \n" % (round(wegh,6))) else : self.file.write(" %f, \n" % (round(wegh,6))) matx = self.writeMatrixOffset(bo) self.writeOffsFrames(matx, name) except : pass self.file.write(" } // End of XSkinMeshHeader\n") #*********************************************** # Write Matrices #*********************************************** def writeArmFrames(self, matx, name): global space tab = " " self.file.write("%s" % (tab * space)) self.file.write("Frame ") self.file.write("%s {\n\n" % (name)) self.file.write("%s" % (tab * space)) self.file.write(" FrameTransformMatrix {\n") self.writeFrame(matx) #*********************************************** # Write Frames #*********************************************** def writeOffsFrames(self, matx, name): space = 1 self.writeFrame(matx) #*********************************************** # Write Frames #*********************************************** def writeFrame(self, matx): tab = " " self.file.write("%s" % (tab * space)) self.file.write(" %f,%f,%f,%f,\n" % (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4))) self.file.write("%s" % (tab * space)) self.file.write(" %f,%f,%f,%f,\n" % (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4))) self.file.write("%s" % (tab * space)) self.file.write(" %f,%f,%f,%f,\n" % (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4))) self.file.write("%s" % (tab * space)) self.file.write(" %f,%f,%f,%f;;\n" % (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4))) self.file.write("%s" % (tab * space)) self.file.write(" }\n")#********************************************************************************************************************************************* #*********************************************** #HEADER #*********************************************** def writeHeader(self): self.file.write("xof 0303txt 0032\n\n\n") self.file.write("template VertexDuplicationIndices { \n <b8d65549-d7c9-4995-89cf-53a9a8b031e3>\n DWORD nIndices;\n DWORD nOriginalVertices;\n array DWORD indices[nIndices];\n}\ntemplate XSkinMeshHeader {\n <3cf169ce-ff7c-44ab-93c0-f78f62d172e2>\n WORD nMaxSkinWeightsPerVertex;\n WORD nMaxSkinWeightsPerFace;\n WORD nBones;\n}\ntemplate SkinWeights {\n <6f0d123b-bad2-4167-a0d0-80224f25fabb>\n STRING transformNodeName;\n DWORD nWeights;\n array DWORD vertexIndices[nWeights];\n array float weights[nWeights];\n Matrix4x4 matrixOffset;\n}\n\n") #*********************************************** #CLOSE FILE #*********************************************** def writeEnd(self): self.file.close() print "... finished" #*********************************************** #EXPORT TEXTURES #*********************************************** def writeTextures(self,name, tex): mesh = name.data for face in mesh.faces: if face.image and face.image.name not in tex: tex.append(face.image.name) #*********************************************** #EXPORT MESH DATA with Armature #*********************************************** def writeMeshcoordArm(self, obj ,arm_ob): global index_list,flip_z #TransformMatrix mat = self.getLocMat(obj) self.writeArmFrames(mat, make_legal_name(obj.name)) mesh = NMesh.GetRawFromObject(obj.name) self.file.write("Mesh {\n") numface=len(mesh.faces) #VERTICES NUMBER numvert = 0 for face in mesh.faces: numvert = numvert + len(face.v) self.file.write("%d;\n" % (numvert)) if numvert == 0: print "Mesh named",mesh.name,"has no vertices.Problems may occur using the .x file" #VERTICES COORDINATES counter = 0 for face in mesh.faces: counter += 1 for n in range(len(face.v)): index_list.append(face.v[n].index) vec_vert = Vector([(face.v[n].co[0]), face.v[n].co[1], face.v[n].co[2], 1]) if arm_ob : f_vec_vert = vec_vert * mat else : f_vec_vert = vec_vert self.file.write("%f; %f; %f;" % (round(f_vec_vert[0],4), round(f_vec_vert[1],4), round(f_vec_vert[2],4))) if counter == numface : if n == len(face.v)-1 : self.file.write(";\n") else : self.file.write(",\n") else : self.file.write(",\n") if flip_z: a3 = 0;b3 = 2;c3 = 1 a4 = 0;b4 = 3;c4 = 2;d4 = 1 else: a3 = 0;b3 = 1;c3 = 2 a4 = 0;b4 = 1;c4 = 2;d4 = 3 #FACES NUMBER self.file.write("%s;\n" % (numface)) coun,counter = 0, 0 for face in mesh.faces : coun += 1 separator = ',' if coun == numface: separator = ';' if len(face.v) == 3: self.file.write("3; %d, %d, %d;%c\n" % (counter + a3, counter + b3, counter + c3, separator)) counter += 3 elif len(face.v) == 4: self.file.write("4; %d, %d, %d, %d;%c\n" % (counter + a4, counter + b4, counter + c4, counter + d4, separator)) counter += 4 elif len(face.v) < 3: print "WARNING:the mesh has faces with less then 3 vertices" print " It my be not exported correctly." #*********************************************** #MESH MATERIAL LIST #*********************************************** def writeMeshMaterialList(self, obj, mesh, tex): self.file.write(" MeshMaterialList {\n") #HOW MANY MATERIALS ARE USED count = 0 for mat in mesh.getMaterials(): count+=1 self.file.write(" %d;\n" % (len(tex) + count)) #HOW MANY FACES IT HAS numfaces=len(mesh.faces) self.file.write(" %d;\n" % (numfaces)) ##MATERIALS INDEX FOR EVERY FACE counter = 0 for face in mesh.faces : counter += 1 mater = face.materialIndex if counter == numfaces: if face.image and face.image.name in tex : self.file.write(" %d;;\n" % (tex.index(face.image.name) + count)) else : self.file.write(" %d;;\n" % (mater)) else : if face.image and face.image.name in tex : self.file.write(" %d,\n" % (tex.index(face.image.name) + count)) else : self.file.write(" %d,\n" % (mater)) ##MATERIAL NAME for mat in mesh.getMaterials(): self.file.write(" Material") self.file.write(" %s "% (make_legal_name(mat.name))) self.file.write("{\n") self.file.write(" %f; %f; %f;" % (mat.R, mat.G, mat.B)) self.file.write("%s;;\n" % (mat.alpha)) self.file.write(" %f;\n" % (mat.spec)) self.file.write(" %f; %f; %f;;\n" % (mat.specR, mat.specG, mat.specB)) self.file.write(" 0.0; 0.0; 0.0;;\n") self.file.write(" } //End of Material\n") for mat in tex: self.file.write(" Material Mat") self.file.write("%s "% (len(tex))) self.file.write("{\n") self.file.write(" 1.0; 1.0; 1.0; 1.0;;\n") self.file.write(" 1.0;\n") self.file.write(" 1.0; 1.0; 1.0;;\n") self.file.write(" 0.0; 0.0; 0.0;;\n") self.file.write(" TextureFilename {") self.file.write(' "%s";'% (mat)) self.file.write(" }\n") self.file.write(" } // End of Material\n") self.file.write(" } //End of MeshMaterialList\n") #*********************************************** #MESH NORMALS #*********************************************** def writeMeshNormals(self,name,mesh): global flip_norm,flip_z,no_light,recalc_norm,Bl_norm self.file.write(" MeshNormals {\n") #VERTICES NUMBER numvert = 0 for face in mesh.faces: numvert = numvert + len(face.v) self.file.write("%d;\n" % (numvert)) numfaces=len(mesh.faces) if flip_norm : fl = -1 else : fl = 1 #VERTICES NORMAL if Bl_norm: self.writeBlenderNormals(mesh,fl) if recalc_norm: self.writeRecalcNormals(mesh,fl) if no_light: self.writeNoSmothing(mesh,fl) if flip_z: a3 = 0;b3 = 2;c3 = 1 a4 = 0;b4 = 3;c4 = 2;d4 = 1 else: a3 = 0;b3 = 1;c3 = 2 a4 = 0;b4 = 1;c4 = 2;d4 = 3 #FACES NUMBER self.file.write("%s;\n" % (numfaces)) coun,counter = 0, 0 for face in mesh.faces : coun += 1 if coun == numfaces: if len(face.v) == 3: self.file.write("3; %d, %d, %d;;\n" % (counter + a3, counter + b3, counter + c3)) counter += 3 else : self.file.write("4; %d, %d, %d, %d;;\n" % (counter + a4, counter + b4, counter + c4, counter + d4)) counter += 4 else: if len(face.v) == 3: self.file.write("3; %d, %d, %d;,\n" % (counter + a3, counter + b3, counter + c3)) counter += 3 else : self.file.write("4; %d, %d, %d, %d;,\n" % (counter + a4, counter + b4, counter + c4, counter + d4)) counter += 4 self.file.write("} //End of MeshNormals\n") def writeBlenderNormals(self,mesh,fl): numfaces=len(mesh.faces) #VERTICES NORMAL counter = 0 for face in mesh.faces: counter += 1 for n in range(len(face.v)): self.file.write(" %f; %f; %f;" % ( (round(face.v[n].no[0],6)*fl),(round(face.v[n].no[1],6)*fl),(round(face.v[n].no[2],6)*fl))) if counter == numfaces : if n == len(face.v)-1 : self.file.write(";\n") else : self.file.write(",\n") else : self.file.write(",\n") def writeRecalcNormals(self,mesh,fl): numfaces=len(mesh.faces) normal_list = {} idx = 0 for vertex in mesh.verts: v_norm = Vector([0, 0, 0]) normal_list[idx] = v_norm idx += 1 for face in mesh.faces: for verts in face.v: if verts.index == vertex.index : v_norm[0] += face.no[0] v_norm[1] += face.no[1] v_norm[2] += face.no[2] v_norm.normalize() counter = 0 for face in mesh.faces: counter += 1 n = 0 for vert in face.v: n += 1 norm = normal_list[vert.index] self.file.write(" %f; %f; %f;" % ( (round(norm[0],6)*fl),(round(norm[1],6)*fl),(round(norm[2],6)*fl))) if counter == numfaces : if n == len(face.v) : self.file.write(";\n") else : self.file.write(",\n") else : self.file.write(",\n") def writeNoSmothing(self,mesh,fl): numfaces=len(mesh.faces) counter = 0 for face in mesh.faces: counter += 1 n = 0 for n in range(len(face.v)): n += 1 self.file.write(" %f; %f; %f;" % ( (round(face.no[0],6)*fl),(round(face.no[1],6)*fl),(round(face.no[2],6)*fl))) if counter == numfaces : if n == len(face.v) : self.file.write(";\n") else : self.file.write(",\n") else : self.file.write(",\n") #*********************************************** #MESH TEXTURE COORDS #*********************************************** def writeMeshTextureCoords(self, name, mesh): if mesh.hasFaceUV(): self.file.write("MeshTextureCoords {\n") #VERTICES NUMBER numvert = 0 for face in mesh.faces: numvert += len(face.v) self.file.write("%d;\n" % (numvert)) #UV COORDS numfaces = len(mesh.faces) counter = -1 co = 0 for face in mesh.faces: counter += 1 co += 1 for n in range(len(face.v)): self.file.write("%f;%f;" % (mesh.faces[counter].uv[n][0], -mesh.faces[counter].uv[n][1])) if co == numfaces : if n == len(face.v) - 1 : self.file.write(";\n") else : self.file.write(",\n") else : self.file.write(",\n") self.file.write("} //End of MeshTextureCoords\n")#***********************************************#***********************************************#*********************************************** #*********************************************** #FRAMES #*********************************************** def writeFrames(self, matx): self.file.write("%f,%f,%f,%f," % (round(matx[0][0],4),round(matx[0][1],4),round(matx[0][2],4),round(matx[0][3],4))) self.file.write("%f,%f,%f,%f," % (round(matx[1][0],4),round(matx[1][1],4),round(matx[1][2],4),round(matx[1][3],4))) self.file.write("%f,%f,%f,%f," % (round(matx[2][0],4),round(matx[2][1],4),round(matx[2][2],4),round(matx[2][3],4))) self.file.write("%f,%f,%f,%f;;" % (round(matx[3][0],4),round(matx[3][1],4),round(matx[3][2],4),round(matx[3][3],4))) #*********************************************** #WRITE ANIMATION KEYS #*********************************************** def writeAnimation(self,arm_ob): global mat_dict, root_bon arm = arm_ob.getData() act_list = arm_ob.getAction() ip = act_list.getAllChannelIpos() for bon in arm.bones.values() : point_list = [] name = bon.name name_f = make_legal_name(name) try : ip_bon_channel = ip[bon.name] ip_bon_name = ip_bon_channel.getName() ip_bon = Blender.Ipo.Get(ip_bon_name) poi = ip_bon.getCurves() for po in poi[3].getPoints(): a = po.getPoints() point_list.append(int(a[0])) #point_list.pop(0) self.file.write(" Animation { \n") self.file.write(" { %s }\n" %(name_f)) self.file.write(" AnimationKey { \n") self.file.write(" 4;\n") self.file.write(" %d; \n" % (len(point_list))) for fr in point_list: if name == root_bon.name : mat_b = self.writeAnimCombineMatrix(bon,fr) mat_arm = self.getLocMat(arm_ob) mat = mat_b * mat_arm else: mat = self.writeAnimCombineMatrix(bon,fr) self.file.write(" %d;" % (fr)) self.file.write("16;") self.writeFrames(mat) if fr == point_list[len(point_list)-1]: self.file.write(";\n") else: self.file.write(",\n") self.file.write(" }\n") self.file.write(" }\n") self.file.write("\n") except: pass #*********************************************** #WRITE ANIMATION KEYS #*********************************************** def writeAnimationObj(self, obj): point_list = [] ip = obj.ipo poi = ip.getCurves() for po in poi[0].getPoints(): a = po.getPoints() point_list.append(int(a[0])) self.file.write(" Animation {\n") self.file.write(" { ") self.file.write("%s }\n" % (make_legal_name(obj.name))) self.file.write(" AnimationKey { \n") self.file.write(" 4;\n") self.file.write(" %d; \n" % (len(point_list))) for fr in point_list: self.file.write(" %d;" % (fr)) self.file.write("16;") Blender.Set('curframe',fr) #mat_new = self.getLocMat(obj) mat_new = obj.matrixLocal self.writeFrames(mat_new) if fr == point_list[len(point_list)-1]: self.file.write(";\n") else: self.file.write(",\n") self.file.write(" }\n") self.file.write(" }\n") #***********************************************#***********************************************#***********************************************
Vorpy
Vorpy
self.getArmChildren(obj) is returning None for some object.
PDX_Catalyst
PDX_Catalyst
What's that mean? Hehe.

Not that I understand what you're saying, but what I'm immediately getting from your statement is that I have a bone somewhere with no children. And if so, ummm... not all bones have children as far as I understand it, which means the script should have a check to make sure it's not getting None back... which I guess is like getting null back?

I don't know. I know nothing about Python. I'm new with animation. So not much of this makes sense to me. Maybe you could go beyond a diagnosis and move on to the prescription? =)

It's been almost a week since I got any work done. I'm starting to think I'm going to need to start learning Python just to get past this one problem. Agh!

- C
Vorpy
Vorpy
I think your description of the problem is correct. None is what Python's null is called. The solution might be to change it like this:

	def exportMeshArm(self,arm,arm_ob,ch_obj):		if ch_obj:			tex = []			mesh = ch_obj.getData()			self.writeTextures(ch_obj, tex)					self.writeMeshcoordArm(ch_obj ,arm_ob)			self.writeMeshMaterialList(ch_obj, mesh, tex)			self.writeMeshNormals(ch_obj, mesh)			self.writeMeshTextureCoords(ch_obj, mesh)			self.writeSkinWeights(arm,mesh)		#self.file.write("  }  // End of the Frame %s \n" % (ch_obj.name))		self.file.write("  }  // End of the Object %s \n" % (ch_obj.name))

PDX_Catalyst
PDX_Catalyst
That works if I indent the last two lines as well, but when I say "works" I mean it exports the model without an error. It doesn't export the armature, animations, or anything else. I just get a plain model.

Don't bother replying. I'll be killing myself now.

Just kidding!

This whole project has ground to a halt. I'm close to starting over in a different modeling app, but I know people have done this before (and I hate to lose all that modeling/animation work), so it must be a problem with the way I've set up my model in Blender.
Oluseyi
Oluseyi
Here's the change I would make:

def getArmChildren(self,obj):  for ob in Blender.Scene.GetCurrent().objects: #Object.Get():    if ob.parent == obj :      return ob  raise ValueError, 'no children found for armature ' + obj.name

This would point out to you which armature/s is/are causing the problem.
Vorpy
Vorpy
Oops, I didn't notice that that last line also referenced ch_obj. That line seems to be placing a closing bracket in the file, which is probably important when parsing the file. Try leaving it unindented so it is executed unconditionally, but change it to:

self.file.write(" } // End of the Object\n")

Also, the getArmChildren function only returns the first child it finds. Could there be more than one child?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.