1 # ##### BEGIN GPL LICENSE BLOCK #####
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software Foundation,
15 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 # ##### END GPL LICENSE BLOCK #####
21 ###############################################################################
22 #234567890123456789012345678901234567890123456789012345678901234567890123456789
23 #--------1---------2---------3---------4---------5---------6---------7---------
26 # ##### BEGIN COPYRIGHT BLOCK #####
28 # initial script copyright (c)2011-2013 Alexander Nussbaumer
30 # ##### END COPYRIGHT BLOCK #####
38 from mathutils
import (
52 # import io_scene_ms3d stuff
53 from io_scene_ms3d
.ms3d_strings
import (
56 from io_scene_ms3d
.ms3d_spec
import (
65 Ms3dTranslationKeyframe
,
69 from io_scene_ms3d
.ms3d_utils
import (
72 pre_setup_environment
,
73 post_setup_environment
,
76 from io_scene_ms3d
.ms3d_ui
import (
78 Ms3dMaterialProperties
,
90 ###############################################################################
93 Load a MilkShape3D MS3D File
98 use_blender_names
=True,
99 use_blender_materials
=False,
100 apply_transform
=True,
101 apply_modifiers
=True,
102 apply_modifiers_mode
='PREVIEW',
104 normalize_weights
=True,
105 shrink_to_keys
=False,
106 bake_each_frame
=True,
109 self
.options_verbose
= verbose
110 self
.options_use_blender_names
= use_blender_names
111 self
.options_use_blender_materials
= use_blender_materials
112 self
.options_apply_transform
= apply_transform
113 self
.options_apply_modifiers
= apply_modifiers
114 self
.options_apply_modifiers_mode
= apply_modifiers_mode
115 self
.options_use_animation
= use_animation
116 self
.options_normalize_weights
= normalize_weights
117 self
.options_shrink_to_keys
= shrink_to_keys
118 self
.options_bake_each_frame
= bake_each_frame
121 # create a empty ms3d ms3d_model
122 # fill ms3d_model with blender content
124 def write(self
, blender_context
, filepath
):
125 """convert bender content to ms3d content and write it to file"""
132 pre_setup_environment(self
, blender_context
)
134 # create an empty ms3d template
135 ms3d_model
= Ms3dModel()
137 # inject blender data to ms3d file
138 self
.from_blender(blender_context
, ms3d_model
)
143 # write ms3d file to disk
144 with io
.FileIO(filepath
, "wb") as raw_io
:
145 debug_out
= ms3d_model
.write(raw_io
)
149 if self
.options_verbose
in Ms3dUi
.VERBOSE_MAXIMAL
:
154 # if option is set, this time will enlargs the io time
155 if self
.options_verbose
in Ms3dUi
.VERBOSE_MAXIMAL
:
156 ms3d_model
.print_internal()
158 post_setup_environment(self
, blender_context
)
159 # restore active object
160 blender_context
.scene
.objects
.active
= self
.active_object
162 if ((not blender_context
.scene
.objects
.active
)
163 and (blender_context
.selected_objects
)):
164 blender_context
.scene
.objects
.active \
165 = blender_context
.selected_objects
[0]
167 # restore pre operator undo state
168 blender_context
.user_preferences
.edit
.use_global_undo
= self
.undo
170 is_valid
, statistics
= ms3d_model
.is_valid()
171 if self
.options_verbose
in Ms3dUi
.VERBOSE_NORMAL
:
173 print("##########################################################")
174 print("Export from Blender to MS3D")
176 print("##########################################################")
179 type, value
, traceback
= exc_info()
180 if self
.options_verbose
in Ms3dUi
.VERBOSE_NORMAL
:
181 print("write - exception in try block\n type: '{0}'\n"
182 " value: '{1}'".format(type, value
, traceback
))
184 self
.report({'WARNING', 'ERROR', }, "write - exception.")
195 if self
.options_verbose
in Ms3dUi
.VERBOSE_NORMAL
:
196 print(ms3d_str
['SUMMARY_EXPORT'].format(
197 (t3
- t1
), (t2
- t1
), (t3
- t2
)))
202 ###########################################################################
203 def from_blender(self
, blender_context
, ms3d_model
):
204 blender_mesh_objects
= []
206 source
= (blender_context
.active_object
, )
208 for blender_object
in source
:
209 if blender_object
and blender_object
.type == 'MESH' \
210 and blender_object
.is_visible(blender_context
.scene
):
211 blender_mesh_objects
.append(blender_object
)
213 blender_to_ms3d_bones
= {}
215 self
.create_animation(blender_context
, ms3d_model
, blender_mesh_objects
, blender_to_ms3d_bones
)
216 self
.create_geometry(blender_context
, ms3d_model
, blender_mesh_objects
,
217 blender_to_ms3d_bones
)
220 ###########################################################################
221 def create_geometry(self
, blender_context
, ms3d_model
, blender_mesh_objects
, blender_to_ms3d_bones
):
222 blender_scene
= blender_context
.scene
224 blender_to_ms3d_vertices
= {}
225 blender_to_ms3d_triangles
= {}
226 blender_to_ms3d_groups
= {}
227 blender_to_ms3d_materials
= {}
229 for blender_mesh_object
in blender_mesh_objects
:
230 blender_mesh
= blender_mesh_object
.data
232 ms3d_model
._model
_ex
_object
.joint_size
= \
233 blender_mesh
.ms3d
.joint_size
234 ms3d_model
._model
_ex
_object
.alpha_ref
= blender_mesh
.ms3d
.alpha_ref
235 ms3d_model
._model
_ex
_object
.transparency_mode
= \
236 Ms3dUi
.transparency_mode_to_ms3d(
237 blender_mesh
.ms3d
.transparency_mode
)
239 if blender_mesh
.ms3d
.comment
:
240 ms3d_model
._comment
_object
= Ms3dComment(blender_mesh
.ms3d
.comment
)
242 ##########################
243 # prepare ms3d groups if available
244 # works only for exporting active object
245 ##EXPORT_ACTIVE_ONLY:
246 for ms3d_local_group_index
, blender_ms3d_group
in enumerate(
247 blender_mesh
.ms3d
.groups
):
248 ms3d_group
= Ms3dGroup()
249 ms3d_group
.__index
= len(ms3d_model
._groups
)
250 ms3d_group
.name
= blender_ms3d_group
.name
251 ms3d_group
.flags
= Ms3dUi
.flags_to_ms3d(blender_ms3d_group
.flags
)
252 if blender_ms3d_group
.comment
:
253 ms3d_group
._comment
_object
= Ms3dCommentEx()
254 ms3d_group
._comment
_object
.comment
= \
255 blender_ms3d_group
.comment
256 ms3d_group
._comment
_object
.index
= len(ms3d_model
._groups
)
257 ms3d_group
.material_index
= None # to mark as not setted
258 ms3d_model
._groups
.append(ms3d_group
)
259 blender_to_ms3d_groups
[blender_ms3d_group
.id] = ms3d_group
261 ##########################
262 # i have to use BMesh, because there are several custom data stored.
263 # BMesh doesn't support quads_convert_to_tris()
264 # so, i use that very ugly way:
265 # create a complete copy of mesh and bend object data
266 # to be able to apply operations to it.
268 # temporary, create a full heavy copy of the model
269 # (object, mesh, modifiers)
270 blender_mesh_temp
= blender_mesh_object
.data
.copy()
271 blender_mesh_object_temp
= blender_mesh_object
.copy()
272 blender_mesh_object_temp
.data
= blender_mesh_temp
273 blender_scene
.objects
.link(blender_mesh_object_temp
)
274 blender_scene
.objects
.active
= blender_mesh_object_temp
277 if self
.options_apply_transform
:
278 matrix_transform
= blender_mesh_object_temp
.matrix_basis
283 for modifier
in blender_mesh_object_temp
.modifiers
:
284 if self
.options_apply_modifiers
:
285 # disable only armature modifiers and only,
286 # when use_animation is enabled
287 if self
.options_use_animation \
288 and modifier
.type in {'ARMATURE', }:
289 modifier
.show_viewport
= False
290 modifier
.show_render
= False
292 # disable all modifiers,
293 # to be able to add and apply triangulate modifier later
294 modifier
.show_viewport
= False
295 modifier
.show_render
= False
297 # convert to tris by using the triangulate modifier
298 blender_mesh_object_temp
.modifiers
.new("temp", 'TRIANGULATE')
299 blender_mesh_temp
= blender_mesh_object_temp
.to_mesh(
302 self
.options_apply_modifiers_mode
)
304 enable_edit_mode(True, blender_context
)
306 bm
.from_mesh(blender_mesh_temp
)
308 layer_texture
= bm
.faces
.layers
.tex
.get(
309 ms3d_str
['OBJECT_LAYER_TEXTURE'])
310 if layer_texture
is None:
311 layer_texture
= bm
.faces
.layers
.tex
.new(
312 ms3d_str
['OBJECT_LAYER_TEXTURE'])
314 layer_smoothing_group
= bm
.faces
.layers
.int.get(
315 ms3d_str
['OBJECT_LAYER_SMOOTHING_GROUP'])
316 if layer_smoothing_group
is None:
317 layer_smoothing_group
= bm
.faces
.layers
.int.new(
318 ms3d_str
['OBJECT_LAYER_SMOOTHING_GROUP'])
320 layer_group
= bm
.faces
.layers
.int.get(
321 ms3d_str
['OBJECT_LAYER_GROUP'])
322 if layer_group
is None:
323 layer_group
= bm
.faces
.layers
.int.new(
324 ms3d_str
['OBJECT_LAYER_GROUP'])
326 layer_uv
= bm
.loops
.layers
.uv
.get(ms3d_str
['OBJECT_LAYER_UV'])
328 if bm
.loops
.layers
.uv
:
329 layer_uv
= bm
.loops
.layers
.uv
[0]
331 layer_uv
= bm
.loops
.layers
.uv
.new(
332 ms3d_str
['OBJECT_LAYER_UV'])
334 layer_deform
= bm
.verts
.layers
.deform
.active
336 layer_extra
= bm
.verts
.layers
.int.get(ms3d_str
['OBJECT_LAYER_EXTRA'])
337 if layer_extra
is None:
338 layer_extra
= bm
.verts
.layers
.int.new(
339 ms3d_str
['OBJECT_LAYER_EXTRA'])
342 ##########################
345 item
= blender_to_ms3d_vertices
.get(bmv
)
347 index
= len(ms3d_model
._vertices
)
348 ms3d_vertex
= Ms3dVertex()
349 ms3d_vertex
.__index
= index
351 ms3d_vertex
._vertex
= self
.geometry_correction(
352 matrix_transform
* bmv
.co
)
354 if self
.options_use_animation
and layer_deform
:
355 blender_vertex_group_ids
= bmv
[layer_deform
]
356 if blender_vertex_group_ids
:
358 for blender_index
, blender_weight \
359 in blender_vertex_group_ids
.items():
360 ms3d_joint
= blender_to_ms3d_bones
.get(
361 blender_mesh_object_temp
.vertex_groups
[\
364 weight
= bone_weights
.get(ms3d_joint
.__index
)
367 bone_weights
[ms3d_joint
.__index
] = weight
+ blender_weight
369 # sort (bone_id: weight) according its weights
370 # to skip only less important weights in the next pass
371 bone_weights_sorted
= sorted(bone_weights
.items(), key
=lambda item
: item
[1], reverse
=True)
376 for ms3d_index
, blender_weight \
377 in bone_weights_sorted
:
380 ms3d_vertex
.bone_id
= ms3d_index
381 weights
.append(blender_weight
)
383 bone_ids
.append(ms3d_index
)
384 weights
.append(blender_weight
)
386 bone_ids
.append(ms3d_index
)
387 weights
.append(blender_weight
)
389 bone_ids
.append(ms3d_index
)
390 if self
.report
and self
.options_verbose
in Ms3dUi
.VERBOSE_NORMAL
:
393 ms3d_str
['WARNING_EXPORT_SKIP_WEIGHT'])
395 # only first three weights will be supported / four bones
396 if self
.report
and self
.options_verbose
in Ms3dUi
.VERBOSE_NORMAL
:
399 ms3d_str
['WARNING_EXPORT_SKIP_WEIGHT_EX'])
403 # normalize weights to 100%
404 if self
.options_normalize_weights
:
406 for weight
in weights
:
410 weight_normalize
= 1.0 / weight_sum
412 weight_normalize
= 1.0
415 for index
, weight
in enumerate(weights
):
416 if index
>= count
-1 or index
>= 2:
417 # take the full rest instead of calculate,
418 # that should fill up to exactly 100%
419 # (in some cases it is only 99% bacaus of roulding errors)
420 weights
[index
] = int(weight_sum
)
422 normalized_weight
= int(weight
* weight_normalize
* 100)
423 weights
[index
] = normalized_weight
424 weight_sum
-= normalized_weight
426 # fill up missing values
427 while len(bone_ids
) < 3:
428 bone_ids
.append(Ms3dSpec
.DEFAULT_VERTEX_BONE_ID
)
429 while len(weights
) < 3:
432 ms3d_vertex
._vertex
_ex
_object
._bone
_ids
= \
434 ms3d_vertex
._vertex
_ex
_object
._weights
= \
438 #ms3d_vertex._vertex_ex_object.extra = bmv[layer_extra]
439 # bm.verts.layers.int does only support signed int32
440 # convert signed int32 to unsigned int32 (little-endian)
441 signed_int32
= bmv
[layer_extra
]
442 bytes_int32
= signed_int32
.to_bytes(
443 4, byteorder
='little', signed
=True)
444 unsigned_int32
= int.from_bytes(
445 bytes_int32
, byteorder
='little', signed
=False)
446 ms3d_vertex
._vertex
_ex
_object
.extra
= unsigned_int32
448 ms3d_model
._vertices
.append(ms3d_vertex
)
449 blender_to_ms3d_vertices
[bmv
] = ms3d_vertex
451 ##########################
452 # handle faces / tris
454 item
= blender_to_ms3d_triangles
.get(bmf
)
456 index
= len(ms3d_model
._triangles
)
457 ms3d_triangle
= Ms3dTriangle()
458 ms3d_triangle
.__index
= index
462 ms3d_vertex0
= blender_to_ms3d_vertices
[bmv0
]
463 ms3d_vertex1
= blender_to_ms3d_vertices
[bmv1
]
464 ms3d_vertex2
= blender_to_ms3d_vertices
[bmv2
]
465 ms3d_vertex0
.reference_count
+= 1
466 ms3d_vertex1
.reference_count
+= 1
467 ms3d_vertex2
.reference_count
+= 1
468 ms3d_triangle
._vertex
_indices
= (
469 ms3d_vertex0
.__index
,
470 ms3d_vertex1
.__index
,
471 ms3d_vertex2
.__index
,
473 ms3d_triangle
._vertex
_normals
= (
474 self
.geometry_correction(bmv0
.normal
),
475 self
.geometry_correction(bmv1
.normal
),
476 self
.geometry_correction(bmv2
.normal
),
479 bmf
.loops
[0][layer_uv
].uv
.x
,
480 bmf
.loops
[1][layer_uv
].uv
.x
,
481 bmf
.loops
[2][layer_uv
].uv
.x
,
484 1.0 - bmf
.loops
[0][layer_uv
].uv
.y
,
485 1.0 - bmf
.loops
[1][layer_uv
].uv
.y
,
486 1.0 - bmf
.loops
[2][layer_uv
].uv
.y
,
489 ms3d_triangle
.smoothing_group
= bmf
[layer_smoothing_group
]
490 ms3d_model
._triangles
.append(ms3d_triangle
)
492 ms3d_material
= self
.get_ms3d_material_add_if(
493 blender_mesh
, ms3d_model
,
494 blender_to_ms3d_materials
, bmf
.material_index
)
495 ms3d_group
= blender_to_ms3d_groups
.get(bmf
[layer_group
])
497 ##EXPORT_ACTIVE_ONLY:
498 if ms3d_group
is not None:
499 if ms3d_material
is None:
500 ms3d_group
.material_index
= \
501 Ms3dSpec
.DEFAULT_GROUP_MATERIAL_INDEX
503 if ms3d_group
.material_index
is None:
504 ms3d_group
.material_index
= \
505 ms3d_material
.__index
507 if ms3d_group
.material_index
!= \
508 ms3d_material
.__index
:
510 self
.get_ms3d_group_by_material_add_if(
511 ms3d_model
, ms3d_material
)
513 if ms3d_material
is not None:
514 ms3d_group
= self
.get_ms3d_group_by_material_add_if(
515 ms3d_model
, ms3d_material
)
517 ms3d_group
= self
.get_ms3d_group_default_material_add_if(
520 if ms3d_group
is not None:
521 ms3d_group
._triangle
_indices
.append(
522 ms3d_triangle
.__index
)
523 ms3d_triangle
.group_index
= ms3d_group
.__index
525 blender_to_ms3d_triangles
[bmf
] = ms3d_triangle
530 enable_edit_mode(False, blender_context
)
532 ##########################
533 # remove the temporary data
534 blender_scene
.objects
.unlink(blender_mesh_object_temp
)
535 if blender_mesh_temp
is not None:
536 blender_mesh_temp
.user_clear()
537 blender_context
.blend_data
.meshes
.remove(blender_mesh_temp
)
538 blender_mesh_temp
= None
539 if blender_mesh_object_temp
is not None:
540 blender_mesh_temp
= blender_mesh_object_temp
.data
.user_clear()
541 blender_mesh_object_temp
.user_clear()
542 blender_context
.blend_data
.objects
.remove(
543 blender_mesh_object_temp
)
544 if blender_mesh_temp
is not None:
545 blender_mesh_temp
.user_clear()
546 blender_context
.blend_data
.meshes
.remove(blender_mesh_temp
)
549 ###########################################################################
550 def create_animation(self
, blender_context
, ms3d_model
,
551 blender_mesh_objects
, blender_to_ms3d_bones
):
552 ##########################
554 blender_scene
= blender_context
.scene
556 if not self
.options_use_animation
:
557 ms3d_model
.animation_fps
= 24
558 ms3d_model
.number_total_frames
= 1
559 ms3d_model
.current_time
= 0
562 frame_start
= blender_scene
.frame_start
563 frame_end
= blender_scene
.frame_end
564 frame_total
= (frame_end
- frame_start
) + 1
565 frame_step
= blender_scene
.frame_step
568 fps
= blender_scene
.render
.fps
* blender_scene
.render
.fps_base
569 time_base
= 1.0 / fps
571 base_bone_correction
= Matrix
.Rotation(pi
/ 2, 4, 'Z')
573 for blender_mesh_object
in blender_mesh_objects
:
575 blender_action
= None
576 blender_nla_tracks
= None
578 # note: only one armature modifier/parent will be handled.
579 # if the parent is an armature, it will be handled irrespective
580 # of existence of any armature modifier
582 # question: maybe it is better to handle
583 # all existing armature sources (parent / modifier)
584 # as a merged animation...
585 # what is best practice in case of multiple animation sources?
587 # take parent to account if it is an armature
588 if blender_mesh_object
.parent
and \
589 blender_mesh_object
.parent_type
== 'ARMATURE' and \
590 blender_mesh_object
.parent
.pose
:
591 blender_bones
= blender_mesh_object
.parent
.data
.bones
592 blender_pose_bones
= blender_mesh_object
.parent
.pose
.bones
593 if blender_mesh_object
.parent
.animation_data
:
595 blender_mesh_object
.parent
.animation_data
.action
596 blender_nla_tracks
= \
597 blender_mesh_object
.parent
.animation_data
.nla_tracks
600 if self
.options_apply_transform
:
601 matrix_transform
= blender_mesh_object
.parent
.matrix_basis
605 # search for animation modifier
607 for blender_modifier
in blender_mesh_object
.modifiers
:
608 if blender_modifier
.type == 'ARMATURE' \
609 and blender_modifier
.object.pose
:
610 blender_bones
= blender_modifier
.object.data
.bones
611 blender_pose_bones
= blender_modifier
.object.pose
.bones
612 if blender_modifier
.object.animation_data
:
614 blender_modifier
.object.animation_data
.action
615 blender_nla_tracks
= \
616 blender_modifier
.object.animation_data
.nla_tracks
619 if self
.options_apply_transform
:
620 matrix_transform
= blender_modifier
.object.matrix_basis
626 # skip animation/bone handling, if no animation data is available
627 if blender_bones
is None \
628 and (blender_action
is None and blender_nla_tracks
is None):
631 ##########################
633 blender_bones_ordered
= []
634 self
.build_blender_bone_dependency_order(
635 blender_bones
, blender_bones_ordered
)
636 for blender_bone_name
in blender_bones_ordered
:
637 blender_bone_oject
= blender_bones
[blender_bone_name
]
638 ms3d_joint
= Ms3dJoint()
639 ms3d_joint
.__index
= len(ms3d_model
._joints
)
641 blender_bone_ms3d
= blender_bone_oject
.ms3d
642 blender_bone
= blender_bone_oject
644 ms3d_joint
.flags
= Ms3dUi
.flags_to_ms3d(blender_bone_ms3d
.flags
)
645 if blender_bone_ms3d
.comment
:
646 ms3d_joint
._comment
_object
= Ms3dCommentEx()
647 ms3d_joint
._comment
_object
.comment
= \
648 blender_bone_ms3d
.comment
649 ms3d_joint
._comment
_object
.index
= ms3d_joint
.__index
651 ms3d_joint
.joint_ex_object
._color
= blender_bone_ms3d
.color
[:]
653 ms3d_joint
.name
= blender_bone
.name
655 if blender_bone
.parent
:
656 ms3d_joint
.parent_name
= blender_bone
.parent
.name
657 ms3d_joint
.__matrix
= matrix_difference(
658 matrix_transform
* blender_bone
.matrix_local
,
659 matrix_transform
* blender_bone
.parent
.matrix_local
)
661 ms3d_joint
.__matrix
= base_bone_correction \
662 * matrix_transform
* blender_bone
.matrix_local
664 mat
= ms3d_joint
.__matrix
665 loc
= mat
.to_translation()
666 rot
= mat
.to_euler('XZY')
667 ms3d_joint
._position
= self
.joint_correction(loc
)
668 ms3d_joint
._rotation
= self
.joint_correction(rot
)
670 ms3d_model
._joints
.append(ms3d_joint
)
671 blender_to_ms3d_bones
[blender_bone
.name
] = ms3d_joint
673 ##########################
676 frames_location
= set()
677 frames_rotation
= set()
681 self
.fill_keyframe_sets(
682 blender_action
.fcurves
,
683 frames_location
, frames_rotation
, frames_scale
,
686 if blender_nla_tracks
:
687 for nla_track
in blender_nla_tracks
:
690 for strip
in nla_track
.strips
:
693 frame_correction
= strip
.frame_start \
694 - strip
.action_frame_start
695 self
.fill_keyframe_sets(
696 strip
.action
.fcurves
,
697 frames_location
, frames_rotation
, frames_scale
,
700 frames
= set(frames_location
)
701 frames
= frames
.union(frames_rotation
)
702 frames
= frames
.union(frames_scale
)
704 if not self
.options_shrink_to_keys
:
705 frames
= frames
.intersection(range(
706 blender_scene
.frame_start
, blender_scene
.frame_end
+ 1))
708 frames_sorted
= list(frames
)
711 if self
.options_shrink_to_keys
and len(frames_sorted
) >= 2:
712 frame_start
= frames_sorted
[0]
713 frame_end
= frames_sorted
[len(frames_sorted
)-1]
714 frame_total
= (frame_end
- frame_start
) + 1
715 frame_offset
= frame_start
- 1
717 if self
.options_bake_each_frame
:
718 frames_sorted
= range(int(frame_start
), int(frame_end
+ 1),
721 frame_temp
= blender_scene
.frame_current
723 for current_frame
in frames_sorted
:
724 blender_scene
.frame_set(current_frame
)
726 current_time
= (current_frame
- frame_offset
) * time_base
727 for blender_bone_name
in blender_bones_ordered
:
728 blender_bone
= blender_bones
[blender_bone_name
]
729 blender_pose_bone
= blender_pose_bones
[blender_bone_name
]
730 ms3d_joint
= blender_to_ms3d_bones
[blender_bone_name
]
732 m1
= blender_bone
.matrix_local
.inverted()
733 if blender_pose_bone
.parent
:
734 m2
= blender_pose_bone
.parent
.matrix_channel
.inverted()
737 m3
= blender_pose_bone
.matrix
.copy()
739 loc
= m
.to_translation()
740 rot
= m
.to_euler('XZY')
742 ms3d_joint
.translation_key_frames
.append(
743 Ms3dTranslationKeyframe(
744 current_time
, self
.joint_correction(loc
)
747 ms3d_joint
.rotation_key_frames
.append(
748 Ms3dRotationKeyframe(
749 current_time
, self
.joint_correction(rot
)
753 blender_scene
.frame_set(frame_temp
)
755 ms3d_model
.animation_fps
= fps
756 if ms3d_model
.number_joints
> 0:
757 ms3d_model
.number_total_frames
= int(frame_total
)
758 ms3d_model
.current_time
= ((blender_scene
.frame_current \
759 - blender_scene
.frame_start
) + 1) * time_base
761 ms3d_model
.number_total_frames
= 1
762 ms3d_model
.current_time
= 0
765 ###########################################################################
766 def get_ms3d_group_default_material_add_if(self
, ms3d_model
):
767 markerName
= "MaterialGroupDefault"
768 markerComment
= "group without material"
770 for ms3d_group
in ms3d_model
._groups
:
771 if ms3d_group
.material_index
== \
772 Ms3dSpec
.DEFAULT_GROUP_MATERIAL_INDEX \
773 and ms3d_group
.name
== markerName \
774 and ms3d_group
._comment
_object \
775 and ms3d_group
._comment
_object
.comment
== markerComment
:
778 ms3d_group
= Ms3dGroup()
779 ms3d_group
.__index
= len(ms3d_model
._groups
)
780 ms3d_group
.name
= markerName
781 ms3d_group
._comment
_object
= Ms3dCommentEx()
782 ms3d_group
._comment
_object
.comment
= markerComment
783 ms3d_group
._comment
_object
.index
= len(ms3d_model
._groups
)
784 ms3d_group
.material_index
= Ms3dSpec
.DEFAULT_GROUP_MATERIAL_INDEX
786 ms3d_model
._groups
.append(ms3d_group
)
791 ###########################################################################
792 def get_ms3d_group_by_material_add_if(self
, ms3d_model
, ms3d_material
):
793 if ms3d_material
.__index
< 0 \
794 or ms3d_material
.__index
>= len(ms3d_model
.materials
):
797 markerName
= "MaterialGroup.{}".format(ms3d_material
.__index
)
798 markerComment
= "MaterialGroup({})".format(ms3d_material
.name
)
800 for ms3d_group
in ms3d_model
._groups
:
801 if ms3d_group
.name
== markerName \
802 and ms3d_group
._comment
_object \
803 and ms3d_group
._comment
_object
.comment
== markerComment
:
806 ms3d_group
= Ms3dGroup()
807 ms3d_group
.__index
= len(ms3d_model
._groups
)
808 ms3d_group
.name
= markerName
809 ms3d_group
._comment
_object
= Ms3dCommentEx()
810 ms3d_group
._comment
_object
.comment
= markerComment
811 ms3d_group
._comment
_object
.index
= len(ms3d_model
._groups
)
812 ms3d_group
.material_index
= ms3d_material
.__index
814 ms3d_model
._groups
.append(ms3d_group
)
819 ###########################################################################
820 def get_ms3d_material_add_if(self
, blender_mesh
, ms3d_model
,
821 blender_to_ms3d_materials
, blender_index
):
822 if blender_index
< 0 or blender_index
>= len(blender_mesh
.materials
):
825 blender_material
= blender_mesh
.materials
[blender_index
]
826 ms3d_material
= blender_to_ms3d_materials
.get(blender_material
)
827 if ms3d_material
is None:
828 ms3d_material
= Ms3dMaterial()
829 ms3d_material
.__index
= len(ms3d_model
.materials
)
831 blender_ms3d_material
= blender_material
.ms3d
833 if not self
.options_use_blender_names \
834 and not self
.options_use_blender_materials \
835 and blender_ms3d_material
.name
:
836 ms3d_material
.name
= blender_ms3d_material
.name
838 ms3d_material
.name
= blender_material
.name
841 if self
.options_use_blender_materials
:
842 temp_material
= Ms3dMaterial()
843 Ms3dMaterialHelper
.copy_from_blender(
844 None, None, temp_material
, blender_material
)
846 temp_material
= blender_ms3d_material
848 ms3d_material
._ambient
= temp_material
.ambient
[:]
849 ms3d_material
._diffuse
= temp_material
.diffuse
[:]
850 ms3d_material
._specular
= temp_material
.specular
[:]
851 ms3d_material
._emissive
= temp_material
.emissive
[:]
852 ms3d_material
.shininess
= temp_material
.shininess
853 ms3d_material
.transparency
= temp_material
.transparency
854 ms3d_material
.texture
= temp_material
.texture
855 ms3d_material
.alphamap
= temp_material
.alphamap
857 ms3d_material
.mode
= Ms3dUi
.texture_mode_to_ms3d(
858 blender_ms3d_material
.mode
)
859 if blender_ms3d_material
.comment
:
860 ms3d_material
._comment
_object
= Ms3dCommentEx()
861 ms3d_material
._comment
_object
.comment
= \
862 blender_ms3d_material
.comment
863 ms3d_material
._comment
_object
.index
= ms3d_material
.__index
865 ms3d_model
.materials
.append(ms3d_material
)
867 blender_to_ms3d_materials
[blender_material
] = ms3d_material
872 ###########################################################################
873 def geometry_correction(self
, value
):
874 return (value
[1], value
[2], value
[0])
877 ###########################################################################
878 def joint_correction(self
, value
):
879 return (-value
[0], value
[2], value
[1])
882 ###########################################################################
883 def build_blender_bone_dependency_order(self
, blender_bones
,
884 blender_bones_ordered
):
885 if not blender_bones
:
886 return blender_bones_ordered
888 blender_bones_children
= {None: []}
889 for blender_bone
in blender_bones
:
890 if blender_bone
.parent
:
891 blender_bone_children
= blender_bones_children
.get(
892 blender_bone
.parent
.name
)
893 if blender_bone_children
is None:
894 blender_bone_children
= blender_bones_children
[
895 blender_bone
.parent
.name
] = []
897 blender_bone_children
= blender_bones_children
[None]
899 blender_bone_children
.append(blender_bone
.name
)
901 self
.traverse_dependencies(
902 blender_bones_ordered
,
903 blender_bones_children
,
906 return blender_bones_ordered
909 ###########################################################################
910 def traverse_dependencies(self
, blender_bones_ordered
,
911 blender_bones_children
, key
):
912 blender_bone_children
= blender_bones_children
.get(key
)
913 if blender_bone_children
:
914 for blender_bone_name
in blender_bone_children
:
915 blender_bones_ordered
.append(blender_bone_name
)
916 self
.traverse_dependencies(
917 blender_bones_ordered
,
918 blender_bones_children
,
921 ###########################################################################
922 def fill_keyframe_sets(self
,
924 frames_location
, frames_rotation
, frames_scale
,
926 for fcurve
in fcurves
:
927 if fcurve
.data_path
.endswith(".location"):
928 frames
= frames_location
929 elif fcurve
.data_path
.endswith(".rotation_euler"):
930 frames
= frames_rotation
931 elif fcurve
.data_path
.endswith(".rotation_quaternion"):
932 frames
= frames_rotation
933 elif fcurve
.data_path
.endswith(".scale"):
934 frames
= frames_scale
938 for keyframe_point
in fcurve
.keyframe_points
:
939 frames
.add(int(keyframe_point
.co
[0] + frame_correction
))
942 ###############################################################################
943 #234567890123456789012345678901234567890123456789012345678901234567890123456789
944 #--------1---------2---------3---------4---------5---------6---------7---------
945 # ##### END OF FILE #####