#!BPY """ reg info: Name: 'BRF Export (.brf)' Blender: 235 Group: 'Export' Tip: 'Export Skeletons, Meshes and Animations to brf-Format' """ __author__ = "Dirk Schulz" __version__ = "0.1" __bpydoc__ = """\ Exports from Blender to the brf-FileFormat (used by Mount&Blade) """ import Blender from Blender.Mathutils import * from Blender import Draw, BGL from Blender.BGL import * import struct, os, re from math import * import os global toggle_scale_10, scale_10 global args args = '' toggle_scale_10 = 0 scale_10 = 0 scalemat = ScaleMatrix(0.1, 4) class BoneType: def __init__(self, index, bone): self.index = index self.parent = None self.bone = bone self.pos = [] self.name = "" self.matrix = Matrix() self.posemat = Matrix() class BoneWeight: def __init__(self, index): self.index = index self.weights = [] self.endweight = 0 self.groups = [] def addWeight(self, weight, group): self.weights.append(weight) self.groups.append(group) def normalizeWeights(self): totalweight = 0 for weight in self.weights: totalweight += weight self.endweight = totalweight / len(self.weights) class VertexUV: def __init__(self, index, uv, faceindex): self.vertindex = index self.uv = uv self.faceindex = faceindex def writeInt(file, int): file.write(struct.pack(' playtime: playtime = knot.pt[ 0 ] playtime = int(round(playtime, 0)) if playtime < 1: playtime = 1 action.setActive(obj) matFixAnim = RotationMatrix( 90.0, 4, 'z' ) for bones in self.bones: realbone = bones.bone writeUInt(file, playtime) for time in range(1, playtime+1): obj.evaluatePose( time) writeUInt(file, time-1) posebone = pose.bones[ realbone.name] posemat = Matrix(posebone.poseMatrix) if bones.parent: posemat = posemat * Matrix(pose.bones[ bones.parent.name].poseMatrix).invert() quat = posemat.toQuat() posequat = Quaternion(quat[1], quat[2], quat[3], quat[0]) writeFloat(file, posequat[0]) writeFloat(file, posequat[1]) writeFloat(file, posequat[2]) writeFloat(file, posequat[3]) writeUInt(file, playtime) for time in range(1, playtime+1): writeUInt(file, time-1) obj.evaluatePose( time) for bone in self.bones: if not bone.parent: posebone = pose.bones[ bone.bone.name] pos = posebone.loc #* posebone.poseMatrix writeFloat(file, pos[0]) writeFloat(file, pos[2]) writeFloat(file, pos[1]) writeInt(file, 3) file.write('%s' % ('end')) file.close() class MeshExport ( SkeletonExport ) : def __init__(self): self.weights = [] self.faces = [] self.meshes = [] self.objects = [] self.bones = [] self.individualverts = [] def callback(self, filename): self.export(filename) def export(self, filename): os.system('cls') file = open(filename, "wb") if not file: print 'something happened' writeUInt(file, len('mesh')) file.write('mesh') scn = Blender.Scene.GetCurrent() selobj = scn.objects.selected nummeshes = 0 armafound = False for obj in selobj: if obj.type == 'Armature': armafound = True arm_obj = obj.getData() arm_bones = arm_obj.bones for bone in arm_bones.values(): if not bone.hasParent(): self.addBone(bone, None) if obj.type == 'Mesh': nummeshes += 1 self.meshes.append(obj.getData(False, True)) self.objects.append(obj) if nummeshes == 0: Blender.Draw.PupMenu('Error%t|No Mesh selected, exit!') file.flush() file.close() return print '%u' % (nummeshes) writeUInt(file, nummeshes) for i, mesh in enumerate(self.meshes): storeverts = mesh.verts[:] self.faces = mesh.faces mesh.quadToTriangle() mesh.transform(self.objects[i].getMatrix(), True) if scale_10: mesh.transform(scalemat, True) mesh.recalcNormals() writeUInt(file, len(mesh.name)) file.write(mesh.name) writeInt(file, 0) if mesh.materials[0] != None: writeUInt(file, len(mesh.materials[0].name)) file.write(mesh.materials[0].name) else: writeUInt(file, len('None')) file.write('None') writeUInt(file, len(mesh.verts)) for vert in mesh.verts: writeFloat(file, vert.co.x) writeFloat(file, vert.co.y) writeFloat(file, vert.co.z) if armafound == True: groupnames = mesh.getVertGroupNames() writeUInt(file, len(groupnames)) boneweights = [] for group in groupnames: vertweightlist = mesh.getVertsFromGroup(group, 1) for vertweightpair in vertweightlist: if vertweightpair[1] > 1e-6: found = False for boweight in boneweights: if boweight.index == vertweightpair[0]: boweight.addWeight(vertweightpair[1], group) found = True break if found == False: newindex = BoneWeight(vertweightpair[0]) newindex.addWeight(vertweightpair[1], group) boneweights.append(newindex) for boweight in boneweights: boweight.normalizeWeights() for group in groupnames: for i, bone in enumerate(self.bones): if bone.name == group: writeUInt(file, i) break #print 'bone %u' % (i) realvertindices = [] realvertweights = [] for boweight in boneweights: for j, bogroup in enumerate(boweight.groups): if bogroup == group: realvertindices.append(boweight.index) realvertweights.append(boweight.weights[j]) #print 'index: %u weight %f' % (boweight.index, boweight.weights[j]) writeUInt(file, len(realvertweights)) for j in range(0, len(realvertweights)): writeUInt(file, realvertindices[j]) writeFloat(file, realvertweights[j]) else: writeUInt(file, 0) for face in self.faces: for i in range(0, len(face.verts)): newvertex = VertexUV(face.verts[i].index, face.uv[i], face.index) found = False for vert in self.individualverts: if equalVector2(newvertex.uv, vert.uv) and newvertex.vertindex == vert.vertindex: found = True break if found == False: self.individualverts.append(newvertex) print 'indyverts: %u' % (len(self.individualverts)) writeInt(file, 0) writeUInt(file, len(self.individualverts)) for vert in self.individualverts: writeUInt(file, vert.vertindex) if mesh.vertexColors: writeChar(file, self.faces[vert.faceindex].col.a) writeChar(file, self.faces[vert.faceindex].col.b) writeChar(file, self.faces[vert.faceindex].col.g) writeChar(file, self.faces[vert.faceindex].col.r) else: writeChar(file, 255) writeChar(file, 255) writeChar(file, 255) writeChar(file, 255) writeFloat(file, mesh.verts[vert.vertindex].no.x) writeFloat(file, mesh.verts[vert.vertindex].no.y) writeFloat(file, mesh.verts[vert.vertindex].no.z) if mesh.faceUV: writeFloat(file, vert.uv[0]) writeFloat(file, vert.uv[1]) writeFloat(file, 0.0) writeFloat(file, 0.0) else: writeFloat(file, 0.0) writeFloat(file, 0.0) writeFloat(file, 0.0) writeFloat(file, 0.0) writeUInt(file, len(self.faces)) for face in self.faces: for i, vert in enumerate(self.individualverts): if vert.vertindex == face.v[0].index and equalVector2(face.uv[0], vert.uv): writeUInt(file, i) break for i, vert in enumerate(self.individualverts): if vert.vertindex == face.v[1].index and equalVector2(face.uv[1], vert.uv): writeUInt(file, i) break for i, vert in enumerate(self.individualverts): if vert.vertindex == face.v[2].index and equalVector2(face.uv[2], vert.uv): writeUInt(file, i) break # writeUInt(file, face.v[0].index) # writeUInt(file, face.v[1].index) # writeUInt(file, face.v[2].index) mesh.verts = storeverts writeInt(file, 3) file.write('%s' % ('end')) file.close() def event(evt, val): if evt == Draw.ESCKEY: Draw.Exit() return def button_event(evt): global toggle_scale_10, scale_10 if evt == 0: export = MeshExport() filename = Blender.sys.makename(ext = ".brf") Blender.Window.FileSelector(export.callback, "Export brf", filename); elif evt == 1: export = SkeletonExport() filename = Blender.sys.makename(ext = ".brf") Blender.Window.FileSelector(export.callback, "Export brf", filename); elif evt == 2: export = AnimationExport() filename = Blender.sys.makename(ext = ".brf") Blender.Window.FileSelector(export.callback, "Export brf", filename); elif evt == 3: Draw.Exit() elif evt == 4: toggle_scale_10 = 1 - toggle_scale_10 scale_10 = toggle_scale_10 Draw.Redraw(1) else: return #Draw.Redraw(1) def draw(): glClearColor(0.55, 0.6, 0.6, 1) glClear(BGL.GL_COLOR_BUFFER_BIT) glColor3f(0.2, 0.3, 0.3) rect(10, 180, 300, 180) glColor3f(0.8,.8,0.6) glRasterPos2i(20, 150) Draw.Text("dsm-Exporter ", 'large') glRasterPos2i(20, 130) Draw.Text("for rigged mesh, skeleton has to be selected", 'small') exportmesh_button = Draw.Button("Export Mesh", 0, 220, 155, 75, 30, "Export Mesh") exportskel_button = Draw.Button("Export Skeleton", 1, 220, 120, 75, 30, "Export Skeleton") exportanim_button = Draw.Button("Export Animation", 2, 220, 85, 75, 30, "Export Animation") exit_button = Draw.Button("Exit", 3, 220, 25, 75, 30, "Exit") Draw.Toggle("Imported smd from OpenBrf", 4, 10, 90, 200, 30, toggle_scale_10, "scales by 0.1") glRasterPos2i(20, 70) if toggle_scale_10 : scale_msg = "object will be scaled by 0.1" else : scale_msg = "no scaling will be applied" Draw.Text(scale_msg) Draw.Register(draw, event, button_event) 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()