[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11525] trunk/blender: Mesh. c - getVertFromGroup ~25% speedup.
Campbell Barton
cbarton at metavr.com
Thu Aug 9 15:34:45 CEST 2007
Revision: 11525
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11525
Author: campbellbarton
Date: 2007-08-09 15:34:44 +0200 (Thu, 09 Aug 2007)
Log Message:
-----------
Mesh.c - getVertFromGroup ~25% speedup.
export_fbx.py - initial support for bones applied to weighted meshes.
Modified Paths:
--------------
trunk/blender/release/scripts/export_fbx.py
trunk/blender/source/blender/python/api2_2x/Mesh.c
Modified: trunk/blender/release/scripts/export_fbx.py
===================================================================
--- trunk/blender/release/scripts/export_fbx.py 2007-08-09 09:09:25 UTC (rev 11524)
+++ trunk/blender/release/scripts/export_fbx.py 2007-08-09 13:34:44 UTC (rev 11525)
@@ -92,6 +92,7 @@
def strip_path(p):
return p.split('\\')[-1].split('/')[-1]
+# todo - Disallow the name 'Scene' and 'blend_root' - it will bugger things up.
def sane_name(data, dct):
if not data: return None
name = data.name
@@ -107,6 +108,9 @@
def sane_matname(data): return sane_name(data, sane_name_mapping_mat)
def sane_texname(data): return sane_name(data, sane_name_mapping_tex)
+def mat4x4str(mat):
+ return '%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f,%.15f' % tuple([ f for v in mat for f in v ])
+
# May use this later
"""
# Auto class, use for datastorage only, a like a dictionary but with limited slots
@@ -181,17 +185,18 @@
def write_scene(file, sce, world):
- def write_object_tx(ob, loc, matrix):
+ def object_tx(ob, loc, matrix, matrix_mod = None):
'''
- We have loc to set the location if non blender objects that have a location
+ Matrix mod is so armature objects can modify their bone matricies
'''
- if type(ob) == Blender.Types.BoneType:
+ if isinstance(ob, Blender.Types.BoneType):
+
# we know we have a matrix
- matrix = mtx4_z90 * ob.matrix['ARMATURESPACE']
+ matrix = mtx4_z90 * (matrix_mod * ob.matrix['ARMATURESPACE'])
parent = ob.parent
if parent:
- par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'].copy()
+ par_matrix = mtx4_z90 * (matrix_mod * parent.matrix['ARMATURESPACE'].copy())
matrix = matrix * par_matrix.copy().invert()
matrix_rot = matrix.rotationPart()
@@ -227,13 +232,23 @@
scale = 1,1,1
rot = 0,0,0
+ return loc, rot, scale, matrix, matrix_rot
+
+ def write_object_tx(ob, loc, matrix, matrix_mod= None):
+ '''
+ We have loc to set the location if non blender objects that have a location
+
+ matrix_mod is only used for bones at the moment
+ '''
+ loc, rot, scale, matrix, matrix_rot = object_tx(ob, loc, matrix, matrix_mod)
+
# print rot
file.write('\n\t\t\tProperty: "Lcl Translation", "Lcl Translation", "A+",%.15f,%.15f,%.15f' % loc)
file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % rot)
file.write('\n\t\t\tProperty: "Lcl Scaling", "Lcl Scaling", "A+",%.15f,%.15f,%.15f' % scale)
return loc, rot, scale, matrix, matrix_rot
- def write_object_props(ob=None, loc=None, matrix=None):
+ def write_object_props(ob=None, loc=None, matrix=None, matrix_mod=None):
# if the type is 0 its an empty otherwise its a mesh
# only difference at the moment is one has a color
file.write('''
@@ -241,7 +256,7 @@
Property: "QuaternionInterpolate", "bool", "",0
Property: "Visibility", "Visibility", "A+",1''')
- loc, rot, scale, matrix, matrix_rot = write_object_tx(ob, loc, matrix)
+ loc, rot, scale, matrix, matrix_rot = write_object_tx(ob, loc, matrix, matrix_mod)
# Rotation order
# eEULER_XYZ
@@ -316,7 +331,7 @@
Property: "Show", "bool", "",1
Property: "NegativePercentShapeSupport", "bool", "",1
Property: "DefaultAttributeIndex", "int", "",0''')
- if ob:
+ if ob and type(ob) != Blender.Types.BoneType:
# Only mesh objects have color
file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8')
file.write('\n\t\t\tProperty: "Size", "double", "",100')
@@ -326,13 +341,16 @@
# -------------------------------------------- Armatures
- def write_bone(bone, name):
- file.write('\n\tModel: "Model::%s", "Limb" {' % name)
+ def write_bone(bone, name, matrix_mod):
+ file.write('\n\tModel: "Model::%s", "LimbNode" {' % name)
file.write('\n\t\tVersion: 232')
- write_object_props(bone)
- file.write('\n\t\t\tProperty: "Size", "double", "",100')
- file.write('\n\t\t\tProperty: "LimbLength", "double", "",%.6f' % (bone.head['ARMATURESPACE']-bone.tail['ARMATURESPACE']).length)
+ write_object_props(bone, None, None, matrix_mod)
+
+ file.write('\n\t\t\tProperty: "Size", "double", "",%.6f' % (bone.head['ARMATURESPACE']-bone.tail['ARMATURESPACE']).length)
+ #file.write('\n\t\t\tProperty: "Size", "double", "",1')
+ #file.write('\n\t\t\tProperty: "LimbLength", "double", "",%.6f' % (bone.head['ARMATURESPACE']-bone.tail['ARMATURESPACE']).length)
+ file.write('\n\t\t\tProperty: "LimbLength", "double", "",1')
file.write('\n\t\t\tProperty: "Color", "ColorRGB", "",0.8,0.8,0.8')
file.write('\n\t\t\tProperty: "Color", "Color", "A",0.8,0.8,0.8')
file.write('\n\t\t}')
@@ -634,13 +652,30 @@
file.write('\n\t\tGeometryVersion: 124')
file.write('\n\t}')
+ def write_null(ob, name):
+ # ob can be null
+ file.write('\n\tModel: "Model::%s", "Null" {' % name)
+ file.write('\n\t\tVersion: 232')
+ write_object_props(ob)
+ file.write('''
+ }
+ MultiLayer: 0
+ MultiTake: 1
+ Shading: Y
+ Culling: "CullingOff"
+ TypeFlags: "Null"
+ }''')
+
+
+
+
+
# Material Settings
if world:
world_amb = world.getAmb()
else:
world_amb = (0,0,0) # Default value
-
def write_material(matname, mat):
file.write('\n\tMaterial: "Material::%s", "" {' % matname)
@@ -794,10 +829,81 @@
Cropping: 0,0,0,0
}''')
+
+ def write_deformer_skin(obname):
+ file.write('\n\tDeformer: "Deformer::Skin %s", "Skin" {' % obname)
+ file.write('''
+ Version: 100
+ MultiLayer: 0
+ Type: "Skin"
+ Properties60: {
+ }
+ Link_DeformAcuracy: 50
+ }''')
+
+ # in the example was 'Bip01 L Thigh_2'
+ def write_sub_deformer_skin(obname, group_name, bone, me):
+ file.write('\n\tDeformer: "SubDeformer::Cluster %s", "Cluster" {' % group_name)
+ file.write('''
+ Version: 100
+ MultiLayer: 0
+ Type: "Cluster"
+ Properties60: {
+ Property: "SrcModel", "object", ""
+ Property: "SrcModelReference", "object", ""
+ }
+ UserData: "", ""''')
+
+ try:
+ vgroup_data = me.getVertsFromGroup(bone.name, 1)
+ except:
+ vgroup_data = []
+
+ file.write('\n\t\tIndexes: ')
+
+ i = -1
+ for vg in vgroup_data:
+ if i == -1:
+ file.write('%i' % vg[0])
+ i=0
+ else:
+ if i==38:
+ file.write('\n\t\t')
+ i=0
+ file.write(',%i' % vg[0])
+ i+=1
+
+ file.write('\n\t\tWeights: ')
+ i = -1
+ for vg in vgroup_data:
+ if i == -1:
+ file.write('%.8f' % vg[1])
+ i=0
+ else:
+ if i==38:
+ file.write('\n\t\t')
+ i=0
+ file.write(',%.8f' % vg[1])
+ i+=1
+
+ m = mtx4_z90 * bone.matrix['ARMATURESPACE']
+ matstr = mat4x4str(m)
+ matstr_i = mat4x4str(m.invert())
+ #matstr = mat4x4str(Matrix())
+
+ # It seems fine to have these matricies the same! - worldspace bone or pose locations?
+ file.write('\n\t\tTransform: %s' % matstr_i) # THIS IS __NOT__ THE GLOBAL MATRIX AS DOCUMENTED :/
+ file.write('\n\t\tTransformLink: %s' % matstr)
+ file.write('\n\t}')
+
ob_meshes = []
ob_lights = []
ob_cameras = []
- ob_bones = [] # in fbx we treat bones as root level objects - be carefull!
+ # in fbx we export bones as children of the mesh
+ # armatures not a part of a mesh, will be added to ob_arms
+ ob_bones = []
+ ob_arms = []
+ ob_null = [] # emptys
materials = {}
textures = {}
@@ -811,7 +917,11 @@
ob_cameras.append((sane_obname(ob), ob))
elif ob_type == 'Lamp':
ob_lights.append((sane_obname(ob), ob))
-
+ elif ob_type == 'Armature':
+ #ob_arms.append(sane_obname(ob), ob)
+ ob_arms.append(ob) # replace later.
+ elif ob_type == 'Empty':
+ ob_null.append((sane_obname(ob), ob))
else:
if ob_type == 'Mesh': me = ob.getData(mesh=1)
else: me = BPyMesh.getMeshFromObject(ob)
@@ -832,30 +942,45 @@
me.activeUVLayer = uvlayer_orig
- arm = BPyObject.getObjectArmature(ob)
+ obname = sane_obname(ob)
- if arm:
- armname = sane_obname(arm)
- bones = arm.data.bones.values()
+ armob = BPyObject.getObjectArmature(ob)
+
+ if armob:
+ armname = sane_obname(armob)
+ bones = armob.data.bones.values()
# armatures.append((arm, armname, bones))
# arm_name = BPySys.cleanName(arm.name)
- for b in bones:
+ for bone in bones:
#name = sane_obname(arm_name + ' ' + b.name)
- name = sane_obname(b)
- ob_bones.append( (name, b) )
+ ob_bones.append( (sane_obname(bone), bone, obname, me, armob) )
else:
armname = None
#### me.transform(ob.matrixWorld) # Export real ob coords.
#### High Quality, not realy needed for now.
#BPyMesh.meshCalcNormals(me) # high quality normals nice for realtime engines.
- ob_meshes.append( (sane_obname(ob), ob, mtx, me, mats, arm, armname) )
+ ob_meshes.append( (obname, ob, mtx, me, mats, armob, armname) )
del ob_type
#print ob_bones
+ # this sucks a bit, remove all armatures that are used by a mesh.
+ for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
+ if arm:
+ try: ob_arms.remove(arm)
+ except: pass
+
+ # now we have removed, get the unique names
+ for i, ob in enumerate(ob_arms):
+ name = sane_obname(ob)
+ ob_arms[i] = name, ob
+
+ for bone in ob.data.bones.values():
+ ob_bones.append( (sane_obname(bone), bone, name, None, ob) )
+
materials = [(sane_matname(mat), mat) for mat in materials.itervalues()]
textures = [(sane_texname(img), img) for img in textures.itervalues()]
materials.sort() # sort by name
@@ -892,6 +1017,8 @@
len(ob_meshes)+\
len(ob_lights)+\
len(ob_cameras)+\
+ len(ob_arms)+\
+ len(ob_null)+\
len(ob_bones)+\
len(materials)+\
(len(textures)*2))) # add 1 for the root model 1 for global settings
@@ -904,6 +1031,8 @@
len(ob_meshes)+\
len(ob_lights)+\
len(ob_cameras)+\
+ len(ob_arms)+\
+ len(ob_null)+\
len(ob_bones))) # add 1 for the root model
file.write('''
@@ -927,42 +1056,55 @@
Count: %i
}''' % len(textures)) # add 1 for an empty tex
+ tmp = 0
+ for obname, ob, mtx, me, mats, arm, armname in ob_meshes:
+ if armname:
+ tmp+=1
+
+ for bonename, bone, obname, me, armob in ob_bones:
+ if me:
+ tmp += 1
+
+ if tmp:
+ file.write('''
+ ObjectType: "Deformer" {
+ Count: %i
+ }''' % tmp)
+ del tmp
+
+ # we could avoid writing this possibly but for now just write it
+ """
file.write('''
+ ObjectType: "Pose" {
+ Count: 1
+ }''')
+ """
+
+ file.write('''
ObjectType: "GlobalSettings" {
Count: 1
}
-}
-''')
+}''')
- file.write(\
-'''
+ file.write('''
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list