I program a code WriteAmatureAnimation :
def writeAnimationAmature(ident,
used_UV,
dico,
key_tab,
tab,
key2_tab_anim_texture,
tab_anim_texture,
mesh_id_coords,
name_obj,
scene,
frame_rate):
print("dicoAma : ", dico)
if use_animation:
name_obj = (name_obj[1:(len(name_obj)-1)])
start_frame = scene[0].frame_start
end_frame = scene[0].frame_end
fw('%s<TimeSensor DEF="time_%s" cycleInterval="%s" loop="true" enabled="true"></TimeSensor>\n' % (ident, name_obj, (end_frame - start_frame) / frame_rate))
for type_animation in dico.keys():
new_name_obj=""
debut = type_animation.find('"') + 1
fin = type_animation.find('"', debut)
if debut != -1 and fin != -1:
new_name_obj = type_animation[debut:fin]
new_name_obj =new_name_obj.replace('.', '_')
print('le nouveau nom', new_name_obj)
if 'location' in type_animation :
fw('\n%s<PositionInterpolator DEF="location_%s" key="' % (ident, new_name_obj))
for key in dico[type_animation].keys():
fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
fw('" keyValue="')
counter =0
#sub_value = dico[type_animation].values()
#print("sub_value : MIAOU : ",sub_value)
#list_sub_value = list(sub_value)
fw('0.5 0.5 0.5 1 1 1 2 2 2 3 3 3')
fw(' ')
fw('"></PositionInterpolator>\n')
fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="location_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, new_name_obj))
fw('%s<ROUTE fromNode="location_%s" fromField="value_changed" toNode="%s" toField="translation"></ROUTE>\n' % (ident, new_name_obj, new_name_obj))
print("type_animation123" , type(type_animation))
if 'rotation_euler' in type_animation or 'rotation_axis_angle' in type_animation or 'rotation_quaternion' in type_animation :
print("rotation_euler rotation_axis_angle ok")
fw('\n%s<OrientationInterpolator DEF="rotation_%s" key="' % (ident, new_name_obj))
for key in dico[type_animation].keys():
fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
fw('" keyValue="')
counter =0
#sub_value = dico[type_animation].values()
#print('subissons ',sub_value)
#list_sub_value = list(sub_value)
fw('0.5 0.5 0.5 0.5 0.5 1 1 1 1 2 2 2 2 3 3 3 3')
fw(' ')
fw('"></OrientationInterpolator>\n')
fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="rotation_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, new_name_obj))
fw('%s<ROUTE fromNode="rotation_%s" fromField="value_changed" toNode="%s" toField="set_rotation"></ROUTE>\n' % (ident, new_name_obj, new_name_obj))
if 'scale' in type_animation:
print("scale ok")
fw('\n%s<PositionInterpolator DEF="scale_%s" key="' % (ident, new_name_obj))
for key in dico[type_animation].keys():
fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
fw('" keyValue="')
counter =0
sub_value = dico[type_animation].values()
list_sub_value = list(sub_value)
for i in range(0, len(list_sub_value),3):
tab = list_sub_value[i:i+3]
if not (len(tab) < 3 ) :
fw('%s %s %s'%(tab[2],tab[1],-tab[0]))
fw(' ')
fw('"></PositionInterpolator>\n')
fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="scale_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, new_name_obj))
fw('%s<ROUTE fromNode="scale_%s" fromField="value_changed" toNode="%s" toField="scale"></ROUTE>\n' % (ident, new_name_obj, new_name_obj))
if key_tab !=0 and tab!=0:
fw('\n%s<CoordinateInterpolator DEF="coordinateInterpolation_%s" key="' % (ident, name_obj))
for key in key_tab:
key_int = int(key)
print('taille de la key: ', len(key_tab))
fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
fw('')
fw('" keyValue="')
print('tab_final : ',tab)
print ('taille du tab_final : ',len(tab))
for valeur in tab:
fw('%s %s %s'%(valeur[0],valeur[1],valeur[2]))
fw(' ')
fw('"></CoordinateInterpolator>\n')
fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="coordinateInterpolation_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, name_obj))
fw('%s<ROUTE fromNode="coordinateInterpolation_%s" fromField="value_changed" toNode=%s toField="point"></ROUTE>\n' % (ident, name_obj, mesh_id_coords))
if key2_tab_anim_texture !=0 and tab_anim_texture !=0:
iteration =0
for uv in used_UV:
fw('\n%s<CoordinateInterpolator2D DEF="coordinateInterpolaton2D_%s" key="' % (ident, uv))
for key in key2_tab_anim_texture:
key_int = int(key)
print('taille de la key: ', len(key2_tab_anim_texture))
fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
fw('')
fw('" keyValue="')
print('putin t es grand : ', len(tab_anim_texture))
for i in range( int((len(tab_anim_texture)/len(used_UV)))*iteration,(int(len(tab_anim_texture)/len(used_UV)))*(1+iteration)):
print("valeur de i : ",i , 'avec comme iteration : ',iteration)
valeur = tab_anim_texture[i]
fw('%s %s '%(valeur[0],valeur[1]))
fw(' ')
iteration = iteration +1
fw('"></CoordinateInterpolator2D>\n')
fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="coordinateInterpolaton2D_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, uv))
fw('%s<ROUTE fromNode="coordinateInterpolaton2D_%s" fromField="value_changed" toNode="%s" toField="point"></ROUTE>\n' % (ident, uv,uv))
This code is a function called writeAnimationAmature that generates animations for an object using the X3d format. Here is an overview of how this function works:
This code is a function called writeAnimationAmature that generates animations for an object using the X3d format. Here is an overview of how this function works:
Function Parameters:
ident: indentation for the text output.
used_UV: UV coordinates used for texture animation.
dico: dictionary containing animation information (position, rotation, scale).
key_tab: array of animation keys.
tab: array of coordinates.
key2_tab_anim_texture: array of texture animation keys.
tab_anim_texture: array of texture animation coordinates.
mesh_id_coords: identifier for the mesh coordinates.
name_obj: name of the animated object.
scene: scene containing timeline information.
frame_rate: frame rate of the animation.
Variable Declaration:
The object’s name is extracted and modified to remove quotation marks.
Animation Setup:
Start and end frames are defined from the scene.
A X3d TimeSensor is created to manage the timing of the animation.
Handling Animation Types:
For each animation type in dico, the code generates X3d interpolators (PositionInterpolator, OrientationInterpolator, etc.) based on the type of animation (position, rotation, scale).
Creating Interpolators:
Position: Generates keys and values for position interpolation.
Rotation: Generates keys and values for rotation interpolation.
Scale: Generates keys and values for scale interpolation.
X3d Routes:
Creates X3d routes linking the interpolators to the TimeSensor and the corresponding fields of objects to animate the transformations (position, rotation, scale).
Texture Animation:
If texture animations are present, they are handled similarly with 2D interpolators.
Output:
Information is written using the fw function, it write to a file or output stream.
For the fw('0.5 0.5 0.5 1 1 1 2 2 2 3 3 3) , i write this because i want to try with a numbers to show if my amature move . When i make the true number , i have one number or two number and not 3 number for one keyframe.
And writeAmature :
def writeAmature(ident , obj, amature):
obj_id = quoteattr(unique_name(amature, OB_ + amature.name, uuid_cache_object, clean_func=clean_def, sep="_"))
dico_animation = {}
if amature.animation_data.action != None:
scene=bpy.data.scenes
key_amature = []
stop =0
print('existe un anime : ', amature.animation_data)
for fc in amature.animation_data.action.fcurves: # ajout des key dans le tableur 2
for key in fc.keyframe_points :
if stop == 0:
key_amature.append(int(key.co[0]))
print('time : ',int(key.co[0]))
stop =1
print('key_amature',key_amature)
armute_all =[]
print('le type de l objet est : ', amature.type)
amature1= amature.data
for joint in amature1.bones:
if not joint.name.endswith("_end"):
armute_all.append(joint.name)
print('armature est de : ',armute_all)
key_tab=[]
tab_finale= []
for fc in amature.animation_data.action.fcurves :
print("fc : ",fc)
print("type blblblbl : ", fc.data_path)
if fc.data_path.endswith(('location','rotation_euler','rotation_quaternion','scale', 'rotation_axis_angle')) or "key_blocks" in fc.data_path:
print("if 2")
dico_key = {}
for key in fc.keyframe_points :
print(fc.data_path,": ",key.co)
dico_key [key.co[0]] = key.co[1]
if fc.data_path not in dico_animation:
dico_animation [fc.data_path] = dico_key
print('dico_animation : ',dico_animation)
for type_anim in dico_animation.keys():
for key, value in dico_animation[type_anim].items():
if type_anim == "location":
dico_animation[type_anim][key] = value[1:] + value[:1]
elif type_anim == "rotation_axis_angle":
dico_animation[type_anim][key] = [-value[2]] + [-value[3]] + [-value[1]] + [value[0]]
elif type_anim == "rotation_euler":
euler = mathutils.Euler((value[0], value[1], value[2]), "XYZ")
euler = mathutils.Euler((euler.x, euler.z, -euler.y), "XYZ")
print("\n\nblender euler: ",euler)
quat = euler.to_quaternion()
print("blender quaternion:\n",quat_str(quat))
print("blender axisangle: ",quat.to_axis_angle())
print("my quaternion:\n",quat_str(eulerToQuat(euler.x,euler.y,euler.z)))
axis = quat.to_axis_angle()
#axis = toAxisAngle(quat) # retourne un vecteur + un angle
#axis = toAxisAngle(eulerToQuat(euler.x,euler.y,euler.z))
print("Final axisAngle : x : ", axis[0].x, " y : ", axis[0].y, " z : ", axis[0].z, "angle : ", axis[1])
#dico_animation[type_anim][key] = [-axis[0].y] + [-axis[0].z] + [-axis[0].x] + [axis[1]]
dico_animation[type_anim][key] = [axis[0].x] + [axis[0].y] + [axis[0].z] + [axis[1]]
writeAnimationAmature(ident,0, dico_animation,0,0,0,0,0, obj_id, bpy.data.scenes, bpy.context.scene.render.fps)
This code is a function called writeAmature that extracts animation data from an armature object in Blender and prepares it for export in X3d. Here is an overview of how this function works:
Function Parameters:
ident: indentation for text output.
obj: 3D object.
amature: armature of the object.
Variable Preparation:
obj_id: unique identifier for the armature, obtained using a unique_name function.
dico_animation: dictionary to store animation data.
Checking for Animation Data:
Checks if the armature has animation data. If so, retrieves scenes and initializes key_amature.
Extracting Keyframes:
Iterates through the armature’s animation curves (fcurves) to extract keyframe points and adds them to key_amature.
Extracting Joint Names:
Iterates through the armature’s bones to extract joint names (excluding those ending in “_end”).
Creating Tables and Extracting Animation Data:
Iterates through the animation curves to identify those related to position (location), rotation (rotation_euler, rotation_quaternion, rotation_axis_angle), and scale (scale).
Stores keyframe data in dico_animation.
Converting Animation Data:
For each animation type, converts the keyframe values into X3d-compatible formats:
Position: Adjusts position values.
Rotation Axis Angle: Converts rotation values into axis-angle format.
Rotation Euler: Converts Euler values into quaternion, then into axis-angle format.
Calling the Writing Function:
Calls writeAnimationAmature to generate X3d animations using the prepared data.
the ‘0’ in writeAnimationAmature when the code call writeAnimationAmature , it is because i don’t finish all parameter , i try the parameter to move , scale and rotate.
So with two functions , when i call there and export on x3D , the amature don’t move and i don’t konw why ?