def read_step(self, stream, tgi): hash = {} while self.read_property(stream, hash, tgi): pass step = TextureStep.get_step(hash[FNV32.hash('id')])() for key in step.params.keys(): hname = FNV32.hash(key) if hname in hash: step.params[key] = hash[hname] return step
def save_bone_delta(skeleton): bond = BoneDelta() for pose_bone in skeleton.pose.bones: if pose_bone.location != Vector(0, 0, 0) or pose_bone.scale != Vector(1, 1, 1) or pose_bone.rotation_quaternion != Quaternion(1, 0, 0, 0): delta = BoneDelta.Delta() delta.position = list(pose_bone.location) delta.scale = list(pose_bone.scale) delta.orientation = list(quat_xyzw(pose_bone.rotation_quaternion)) bond.deltas[FNV32.hash(pose_bone.name)] = delta return bond
def load_bone_delta(bond, skeleton): assert isinstance(bond, BoneDelta) for pose_bone in skeleton.pose.bones: hash = FNV32.hash(pose_bone.name) if hash in bond.deltas: delta = bond.deltas[hash] assert isinstance(delta, BoneDelta.Delta) pose_bone.scale += Vector(swizzle_v3(delta.scale)) pose_bone.location += Vector(swizzle_v3(delta.position)) pose_bone.rotation_quaternion += Quaternion(quat_wxyz(delta.orientation))
def save_bone_delta(skeleton): bond = BoneDelta() for pose_bone in skeleton.pose.bones: if pose_bone.location != Vector(0, 0, 0) or pose_bone.scale != Vector( 1, 1, 1) or pose_bone.rotation_quaternion != Quaternion( 1, 0, 0, 0): delta = BoneDelta.Delta() delta.position = list(pose_bone.location) delta.scale = list(pose_bone.scale) delta.orientation = list(quat_xyzw(pose_bone.rotation_quaternion)) bond.deltas[FNV32.hash(pose_bone.name)] = delta return bond
def load_bone_delta(bond, skeleton): assert isinstance(bond, BoneDelta) for pose_bone in skeleton.pose.bones: hash = FNV32.hash(pose_bone.name) if hash in bond.deltas: delta = bond.deltas[hash] assert isinstance(delta, BoneDelta.Delta) pose_bone.scale += Vector(swizzle_v3(delta.scale)) pose_bone.location += Vector(swizzle_v3(delta.position)) pose_bone.rotation_quaternion += Quaternion( quat_wxyz(delta.orientation))
def read(self, stream, resource=None): s = StreamReader(stream) self.version_major = s.u32() self.version_minor = s.u32() cBones = s.i32() self.bones = [] opposites = [] parents = [] self.__hashes = {} for i in range(cBones): bone = Bone(self) bone.position = [s.f32() for i in range(3)] bone.orientation = [s.f32() for i in range(4)] bone.scale = [s.f32() for i in range(3)] bone.name = s.p32() opposites.append(s.i32()) parents.append(s.i32()) hash_name = s.u32() if not hash_name == FNV32.hash(bone.name): print( "WARNING: Bone %s should have matching hash 0x%08X, but has 0x%08X", bone.name, FNV32.hash(bone.name), hash_name) self.__hashes[hash] = bone bone.flags = s.u32() self.bones.append(bone) for bone_index, opposite_index in enumerate(opposites): if opposite_index >= 0: self.bones[bone_index].opposite = self.bones[opposite_index] for bone_index, parent_index in enumerate(parents): if parent_index >= 0: self.bones[bone_index].parent = self.bones[parent_index] if self.version_major >= 4: self.name = s.p32() self.ik_chains = [] cChains = s.i32() for i in range(cChains): chain = IKChain(self) chain.read(stream) self.ik_chains.append(chain)
def animate_bone(root_bone): track_key = FNV32.hash(root_bone.name) if track_key in frame_map: group = action.groups.new(name=root_bone.name) data_path = 'pose.bones["%s"].' % root_bone.name location_path = '%slocation' % data_path rotation_path = '%srotation_quaternion' % data_path fcurves_translate = [] fcurves_rotate = [] for i in range(3): fcurve = action.fcurves.new(data_path=location_path, index=i) fcurve.group = group fcurves_translate.append(fcurve) for i in range(4): fcurve = action.fcurves.new(data_path=rotation_path, index=i) fcurve.group = group fcurves_rotate.append(fcurve) frame_indices = sorted(frame_map[track_key].keys()) current_matrix = root_bone.bone.matrix_local rotation_matrix = current_matrix.to_3x3().to_4x4() translation_matrix = Matrix.Translation( current_matrix.to_translation()) for frame_index in frame_indices: frame_data = frame_map[track_key][frame_index] if frame_data['orientation']: rotation_matrix = ( Quaternion() if not root_bone.parent else frame_data['orientation']).to_matrix().to_4x4() if frame_data['position']: translation_matrix = Matrix.Translation( frame_data['position']) transform_matrix = translation_matrix * rotation_matrix if root_bone.parent: transform_matrix = root_bone.parent.matrix * transform_matrix root_bone.matrix = transform_matrix if frame_data['position']: for i in range(3): fcurves_translate[i].keyframe_points.add(1) fcurves_translate[i].keyframe_points[-1].co = [ frame_index, root_bone.location[i] ] if frame_data['orientation']: for i in range(4): fcurves_rotate[i].keyframe_points.add(1) fcurves_rotate[i].keyframe_points[-1].co = [ frame_index, root_bone.rotation_quaternion[i] ] root_bone.matrix = root_bone.bone.matrix_local for child in root_bone.children: animate_bone(child)
def write(self, stream, resource=None): s = StreamWriter(stream) s.u32(self.version_major) s.u32(self.version_minor) s.i32(len(self.bones)) for bone in self.bones: for i in range(3): s.f32(bone.position[i]) for i in range(4): s.f32(bone.orientation[i]) for i in range(3): s.f32(bone.scale[i]) assert bone.name != None, "Bone %s must have a name" s.p32(bone.name) s.i32(-1 if not bone.opposite in self.bones else self.bones.index(bone.opposite)) s.i32(-1 if not bone.parent in self.bones else self.bones.index(bone.parent)) s.u32(FNV32.hash(bone.name)) s.u32(bone.flags) if self.version_major >= 4: s.p32(self.name) s.i32(len(self.ik_chains)) for chain in self.ik_chains: chain.write(stream)
def animate_bone(root_bone): track_key = FNV32.hash(root_bone.name) if track_key in frame_map: group = action.groups.new(name=root_bone.name) data_path = 'pose.bones["%s"].' % root_bone.name location_path = '%slocation' % data_path rotation_path = '%srotation_quaternion' % data_path fcurves_translate = [] fcurves_rotate = [] for i in range(3): fcurve = action.fcurves.new(data_path=location_path, index=i) fcurve.group = group fcurves_translate.append(fcurve) for i in range(4): fcurve = action.fcurves.new(data_path=rotation_path, index=i) fcurve.group = group fcurves_rotate.append(fcurve) frame_indices = sorted(frame_map[track_key].keys()) current_matrix = root_bone.bone.matrix_local rotation_matrix = current_matrix.to_3x3().to_4x4() translation_matrix = Matrix.Translation(current_matrix.to_translation()) for frame_index in frame_indices: frame_data = frame_map[track_key][frame_index] if frame_data['orientation']: rotation_matrix = ( Quaternion() if not root_bone.parent else frame_data['orientation']).to_matrix().to_4x4() if frame_data['position']: translation_matrix = Matrix.Translation(frame_data['position']) transform_matrix = translation_matrix * rotation_matrix if root_bone.parent: transform_matrix = root_bone.parent.matrix * transform_matrix root_bone.matrix = transform_matrix if frame_data['position']: for i in range(3): fcurves_translate[i].keyframe_points.add(1) fcurves_translate[i].keyframe_points[-1].co = [frame_index, root_bone.location[i]] if frame_data['orientation']: for i in range(4): fcurves_rotate[i].keyframe_points.add(1) fcurves_rotate[i].keyframe_points[-1].co = [frame_index, root_bone.rotation_quaternion[i]] root_bone.matrix = root_bone.bone.matrix_local for child in root_bone.children: animate_bone(child)
def write(self, stream, resource=None): s = StreamWriter(stream) s.u32(self.version_major) s.u32(self.version_minor) s.i32(len(self.bones)) for bone in self.bones: for i in range(3): s.f32(bone.position[i]) for i in range(4): s.f32(bone.orientation[i]) for i in range(3): s.f32(bone.scale[i]) assert bone.name != None, "Bone %s must have a name" s.p32(bone.name) s.i32(-1 if not bone.opposite in self.bones else self.bones. index(bone.opposite)) s.i32(-1 if not bone.parent in self.bones else self.bones. index(bone.parent)) s.u32(FNV32.hash(bone.name)) s.u32(bone.flags) if self.version_major >= 4: s.p32(self.name) s.i32(len(self.ik_chains)) for chain in self.ik_chains: chain.write(stream)
def read(self, stream, resource=None): s = StreamReader(stream) self.version_major = s.u32() self.version_minor = s.u32() cBones = s.i32() self.bones = [] opposites = [] parents = [] self.__hashes = {} for i in range(cBones): bone = Bone(self) bone.position = [s.f32() for i in range(3)] bone.orientation = [s.f32() for i in range(4)] bone.scale = [s.f32() for i in range(3)] bone.name = s.p32() opposites.append(s.i32()) parents.append(s.i32()) hash_name = s.u32() if not hash_name == FNV32.hash(bone.name): print("WARNING: Bone %s should have matching hash 0x%08X, but has 0x%08X",bone.name, FNV32.hash(bone.name),hash_name) self.__hashes[hash] = bone bone.flags = s.u32() self.bones.append(bone) for bone_index, opposite_index in enumerate(opposites): if opposite_index >= 0: self.bones[bone_index].opposite = self.bones[opposite_index] for bone_index, parent_index in enumerate(parents): if parent_index >= 0: self.bones[bone_index].parent = self.bones[parent_index] if self.version_major >= 4: self.name = s.p32() self.ik_chains = [] cChains = s.i32() for i in range(cChains): chain = IKChain(self) chain.read(stream) self.ik_chains.append(chain)
def load_mesh(armature_rig,model_mesh,materials): assert isinstance(model_mesh,s3py.buybuild.geometry.ObjectMesh) bone_name_map = {} if armature_rig.type == 'ARMATURE': for bone_hash in armature_rig.data.bones: bone_name_map[FNV32.hash(bone_hash.name)] = bone_hash.name vertices = model_mesh.get_vertices() faces = model_mesh.get_triangles() mesh_name = '%08X' % int(model_mesh.name) print(mesh_name) print('Creating Mesh %s'%mesh_name) mesh = bpy.data.meshes.new(mesh_name) mesh_obj = bpy.data.objects.new(mesh_name, mesh) bpy.context.scene.objects.link(mesh_obj) bpy.context.scene.objects.active = mesh_obj mesh_obj.parent = armature_rig mesh_obj.show_transparent = True matd = model_mesh.material if isinstance(matd,MaterialSet): matd= matd.default_material if isinstance(matd,MaterialDefinition): mesh_material = materials.generate(mesh_name,matd.material_block) mesh_obj.data.materials.append(mesh_material) vertex_groups = [] if model_mesh.skin_controller: print('Adding Vertex groups from skin controller') for bone_hash in model_mesh.bone_references: bone_name = '%0X8'%bone_hash if bone_hash in bone_name_map: bone_name = bone_name_map[bone_hash] vertex_groups.append(mesh_obj.vertex_groups.new(bone_name)) print('Adding armature modifier and attach to rig') mesh_skin = mesh_obj.modifiers.new(type='ARMATURE', name="%s_skin" % mesh_name) mesh_skin.use_bone_envelopes = False mesh_skin.object = armature_rig bm = bmesh.new() bm.from_mesh(mesh) for vertex in vertices: bm.verts.new(vertex.position) for face_index,face in enumerate(faces): if invalid_face(face): print('[%s]Face[%04i] %s has duplicate points, skipped'%(mesh_name,face_index,face)); continue bm.faces.new([bm.verts[face_point] for face_point in face]) for vertex_index,vertex in enumerate(vertices): bm.verts[vertex_index].normal = Vector(vertex.normal[:-1]) bm.to_mesh(mesh) print('Adding weights') for vertex_index,vertex in enumerate(vertices): if vertex.blend_indices and vertex.blend_weights: for blend_index, blend_bone_index in enumerate(vertex.blend_indices): if blend_bone_index >= 0: weight = vertex.blend_weights[blend_index] if weight > 0.0: blend_vertex_group = vertex_groups[int(blend_bone_index)] blend_vertex_group.add((vertex_index,), weight, 'ADD') print('Adding UV Groups') for declaration in model_mesh.get_vertex_format().declarations: if declaration.usage == VertexFormat.USAGE.UV: mesh.uv_textures.new(name='uv_%i' % declaration.usage_index) faces_skipped = 0 for face_index, face in enumerate(faces): if invalid_face(face): faces_skipped+=1; continue for face_point_index, face_point_vertex_index in enumerate([face[1],face[2],face[0]]): vertex = vertices[face_point_vertex_index] if vertex.uv: for uv_channel_index, uv_coord in enumerate(vertex.uv): mesh.uv_layers[uv_channel_index].data[ face_point_index + ((face_index-faces_skipped)* 3)].uv = swizzle_uv(uv_coord) mesh_obj.select = True bpy.ops.object.shade_smooth() mesh_obj.select = False return mesh_obj
def load_clip(clip_resource, skeleton, scale=1.0): print('Loading clip...') #clear existing animations skeleton.animation_data_clear() clip = clip_resource.clip skeleton.hide = False bpy.context.scene.objects.active = skeleton skeleton.animation_data_clear() skeleton.animation_data_create() action = skeleton.animation_data.action = bpy.data.actions.new(clip.name) #set custom props action.s3py.actor_name = clip_resource.actor_name action.s3py.name = clip.name action.s3py.source_name = clip.source_file_name bone_transforms = {} pose_bone_map = {} for pose_bone in skeleton.pose.bones: hash = FNV32.hash(pose_bone.name) pose_bone_map[hash] = pose_bone bone_transforms[hash] = pose_bone.bone.matrix_local bpy.ops.object.mode_set(mode='POSE') #reset to bind pose bpy.ops.pose.user_transforms_clear() frame_map = {} for track in clip.tracks: if not track.track_key in frame_map: frame_map[track.track_key] = {} if track.orientations: for orientation_key in track.orientations.frames: if not orientation_key.frame_index in frame_map[ track.track_key].keys(): frame_map[track.track_key][orientation_key.frame_index] = { 'orientation': None, 'position': None, 'morph': None } frame_map[track.track_key][ orientation_key.frame_index]['orientation'] = Quaternion( quat_wxyz(orientation_key.data)) if track.positions: for position_key in track.positions.frames: if not position_key.frame_index in frame_map[ track.track_key].keys(): frame_map[track.track_key][position_key.frame_index] = { 'orientation': None, 'position': None, 'morph': None } position = Vector(position_key.data) # if track.track_key == FNV32.hash(ROOT_BIND): # position[1] /= scale frame_map[track.track_key][ position_key.frame_index]['position'] = position if track.morphs: for morph_key in track.morphs.frames: if not morph_key.frame_index in frame_map[ track.track_key].keys(): frame_map[track.track_key][morph_key.frame_index] = { 'orientation': None, 'position': None, 'morph': None } frame_map[track.track_key][ morph_key.frame_index]['morph'] = morph_key.data def animate_driver_bones(driver_root): for shape_key in driver_root.children: track_key = FNV64.hash(shape_key.name) & 0xFFFFFFFF print('shape_key %s' % shape_key) print('track_key: %08X' % track_key) if track_key in frame_map: group = action.groups.new(name=shape_key.name) data_path = 'pose.bones["%s"].morph_value' % shape_key.name fcurve = action.fcurves.new(data_path=data_path, index=0) fcurve.group = group frame_indices = sorted(frame_map[track_key].keys()) for frame_index in frame_indices: print('[%i]: %s' % (frame_index, frame_map[track_key][frame_index]['morph'][0])) val = frame_map[track_key][frame_index]['morph'][0] fcurve.keyframe_points.add(1) fcurve.keyframe_points[-1].co = [frame_index, val] def animate_bone(root_bone): track_key = FNV32.hash(root_bone.name) if track_key in frame_map: group = action.groups.new(name=root_bone.name) data_path = 'pose.bones["%s"].' % root_bone.name location_path = '%slocation' % data_path rotation_path = '%srotation_quaternion' % data_path fcurves_translate = [] fcurves_rotate = [] for i in range(3): fcurve = action.fcurves.new(data_path=location_path, index=i) fcurve.group = group fcurves_translate.append(fcurve) for i in range(4): fcurve = action.fcurves.new(data_path=rotation_path, index=i) fcurve.group = group fcurves_rotate.append(fcurve) frame_indices = sorted(frame_map[track_key].keys()) current_matrix = root_bone.bone.matrix_local rotation_matrix = current_matrix.to_3x3().to_4x4() translation_matrix = Matrix.Translation( current_matrix.to_translation()) for frame_index in frame_indices: frame_data = frame_map[track_key][frame_index] if frame_data['orientation']: rotation_matrix = ( Quaternion() if not root_bone.parent else frame_data['orientation']).to_matrix().to_4x4() if frame_data['position']: translation_matrix = Matrix.Translation( frame_data['position']) transform_matrix = translation_matrix * rotation_matrix if root_bone.parent: transform_matrix = root_bone.parent.matrix * transform_matrix root_bone.matrix = transform_matrix if frame_data['position']: for i in range(3): fcurves_translate[i].keyframe_points.add(1) fcurves_translate[i].keyframe_points[-1].co = [ frame_index, root_bone.location[i] ] if frame_data['orientation']: for i in range(4): fcurves_rotate[i].keyframe_points.add(1) fcurves_rotate[i].keyframe_points[-1].co = [ frame_index, root_bone.rotation_quaternion[i] ] root_bone.matrix = root_bone.bone.matrix_local for child in root_bone.children: animate_bone(child) animate_bone(skeleton.pose.bones[ROOT_BONE]) if ROOT_MORPH in skeleton.pose.bones: animate_driver_bones(skeleton.pose.bones[ROOT_MORPH]) bpy.context.scene.frame_set(0) print('Done.') return action
def __getitem__(self, item): if isinstance(item, int) and item < len(self.bones): return self.bones[item] elif isinstance(item, str) and FNV32.hash(item) in self.__hashes: return self.__hashes[FNV32.hash(item)] return None
def save_clip(clip_resource, skeleton, scale=1.0): print(skeleton.name, skeleton.type) clip = clip_resource.clip clip.tracks = [] action = skeleton.animation_data.action clip_resource.actor_name = action.s3py.actor_name clip.name = action.s3py.name clip.source_file_name = action.s3py.source_name clip.max_frame_count = int(action.frame_range[1]) start_time = time.clock() print('Saving CLIP...') track_map = {} used_bones = [] for fcurve in action.fcurves: s = str(fcurve.data_path).split('.') if s[0] != 'pose' or s[1][:5] != 'bones': continue cname = s[1][7:-2] if cname == ROOT_MORPH: continue if cname in skeleton.pose.bones: pose_bone = skeleton.pose.bones[cname] track_key = FNV32.hash(cname) clip_track_key = FNV64.hash( cname ) & 0xFFFFFFFF if pose_bone.parent and pose_bone.parent.name == ROOT_MORPH else track_key if not track_key in track_map: track = Track(clip_track_key) used_bones.append(pose_bone) clip.tracks.append(track) track_map[track_key] = track print(list(ub.name for ub in used_bones)) print('%i Frames found in %s' % (int(action.frame_range[1]), action.name)) def write_frame(current_value, track, frame_index): write = False if not any(track.frames): write = True else: last_value = track.frames[-1].data for i in range(len(current_value)): difference = math.fabs(current_value[i] - last_value[i]) if difference > 0.0001: write = True if write: f = Frame() f.frame_index = frame_index f.data = current_value track.frames.append(f) set_context('POSE', skeleton) for frame_index in range(int(action.frame_range[0]), int(action.frame_range[1])): bpy.context.scene.frame_set(frame_index) for pose_bone in used_bones: track_key = FNV32.hash(pose_bone.name) if not track_key in track_map: continue track = track_map[track_key] if pose_bone.parent and pose_bone.parent.name == ROOT_MORPH: if not track.morphs: track.morphs = Curve.create_morph() cur_morph = [pose_bone.morph_value] write_frame(cur_morph, track.morphs, frame_index) continue matrix_parent = Matrix( ) if not pose_bone.parent else pose_bone.parent.matrix matrix_delta = matrix_parent.inverted() * pose_bone.matrix if not track.orientations: track.orientations = Curve.create_orientation() rotation = quat_xyzw(matrix_delta.to_quaternion()) write_frame(rotation, track.orientations, frame_index) if not track.positions: track.positions = Curve.create_position() translation = matrix_delta.to_translation() # if pose_bone.name == ROOT_BIND: # translation[1] *= scale write_frame(translation, track.positions, frame_index) print('Finished in %.4f sec.' % (time.clock() - start_time))
def __getitem__(self, item): if isinstance(item,int) and item < len(self.bones): return self.bones[item] elif isinstance(item,str) and FNV32.hash(item) in self.__hashes: return self.__hashes[FNV32.hash(item)] return None
def load_clip(clip_resource, skeleton, scale=1.0): print('Loading clip...') #clear existing animations skeleton.animation_data_clear() clip = clip_resource.clip skeleton.hide = False bpy.context.scene.objects.active = skeleton skeleton.animation_data_clear() skeleton.animation_data_create() action = skeleton.animation_data.action = bpy.data.actions.new(clip.name) #set custom props action.s3py.actor_name = clip_resource.actor_name action.s3py.name = clip.name action.s3py.source_name = clip.source_file_name bone_transforms = {} pose_bone_map = {} for pose_bone in skeleton.pose.bones: hash = FNV32.hash(pose_bone.name) pose_bone_map[hash] = pose_bone bone_transforms[hash] = pose_bone.bone.matrix_local bpy.ops.object.mode_set(mode='POSE') #reset to bind pose bpy.ops.pose.user_transforms_clear() frame_map = {} for track in clip.tracks: if not track.track_key in frame_map: frame_map[track.track_key] = {} if track.orientations: for orientation_key in track.orientations.frames: if not orientation_key.frame_index in frame_map[track.track_key].keys(): frame_map[track.track_key][orientation_key.frame_index] = { 'orientation': None, 'position': None, 'morph': None } frame_map[track.track_key][orientation_key.frame_index]['orientation'] = Quaternion( quat_wxyz(orientation_key.data)) if track.positions: for position_key in track.positions.frames: if not position_key.frame_index in frame_map[track.track_key].keys(): frame_map[track.track_key][position_key.frame_index] = { 'orientation': None, 'position': None, 'morph': None } position = Vector(position_key.data) # if track.track_key == FNV32.hash(ROOT_BIND): # position[1] /= scale frame_map[track.track_key][position_key.frame_index]['position'] = position if track.morphs: for morph_key in track.morphs.frames: if not morph_key.frame_index in frame_map[track.track_key].keys(): frame_map[track.track_key][morph_key.frame_index] = { 'orientation': None, 'position': None, 'morph': None } frame_map[track.track_key][morph_key.frame_index]['morph'] = morph_key.data def animate_driver_bones(driver_root): for shape_key in driver_root.children: track_key = FNV64.hash(shape_key.name) & 0xFFFFFFFF print('shape_key %s' % shape_key) print('track_key: %08X' % track_key) if track_key in frame_map: group = action.groups.new(name=shape_key.name) data_path = 'pose.bones["%s"].morph_value' % shape_key.name fcurve = action.fcurves.new(data_path=data_path, index=0) fcurve.group = group frame_indices = sorted(frame_map[track_key].keys()) for frame_index in frame_indices: print('[%i]: %s' % ( frame_index, frame_map[track_key][frame_index]['morph'][0])) val = frame_map[track_key][frame_index]['morph'][0] fcurve.keyframe_points.add(1) fcurve.keyframe_points[-1].co = [frame_index, val] def animate_bone(root_bone): track_key = FNV32.hash(root_bone.name) if track_key in frame_map: group = action.groups.new(name=root_bone.name) data_path = 'pose.bones["%s"].' % root_bone.name location_path = '%slocation' % data_path rotation_path = '%srotation_quaternion' % data_path fcurves_translate = [] fcurves_rotate = [] for i in range(3): fcurve = action.fcurves.new(data_path=location_path, index=i) fcurve.group = group fcurves_translate.append(fcurve) for i in range(4): fcurve = action.fcurves.new(data_path=rotation_path, index=i) fcurve.group = group fcurves_rotate.append(fcurve) frame_indices = sorted(frame_map[track_key].keys()) current_matrix = root_bone.bone.matrix_local rotation_matrix = current_matrix.to_3x3().to_4x4() translation_matrix = Matrix.Translation(current_matrix.to_translation()) for frame_index in frame_indices: frame_data = frame_map[track_key][frame_index] if frame_data['orientation']: rotation_matrix = ( Quaternion() if not root_bone.parent else frame_data['orientation']).to_matrix().to_4x4() if frame_data['position']: translation_matrix = Matrix.Translation(frame_data['position']) transform_matrix = translation_matrix * rotation_matrix if root_bone.parent: transform_matrix = root_bone.parent.matrix * transform_matrix root_bone.matrix = transform_matrix if frame_data['position']: for i in range(3): fcurves_translate[i].keyframe_points.add(1) fcurves_translate[i].keyframe_points[-1].co = [frame_index, root_bone.location[i]] if frame_data['orientation']: for i in range(4): fcurves_rotate[i].keyframe_points.add(1) fcurves_rotate[i].keyframe_points[-1].co = [frame_index, root_bone.rotation_quaternion[i]] root_bone.matrix = root_bone.bone.matrix_local for child in root_bone.children: animate_bone(child) animate_bone(skeleton.pose.bones[ROOT_BONE]) if ROOT_MORPH in skeleton.pose.bones: animate_driver_bones(skeleton.pose.bones[ROOT_MORPH]) bpy.context.scene.frame_set(0) print('Done.') return action
def load_geom(name, geom, blend_vertex_lod_map, armature_rig, material): bone_name_map = {} for bone in armature_rig.data.bones: bone_name_map[FNV32.hash(bone.name)] = bone.name mesh_name = name mesh = bpy.data.meshes.new(mesh_name) mesh_obj = bpy.data.objects.new(mesh_name, mesh) if material: mesh_obj.data.materials.append(material) bpy.context.scene.objects.link(mesh_obj) bpy.context.scene.objects.active = mesh_obj mesh_obj.parent = armature_rig print('processing mesh: %s' % mesh_name) shape_key_basis = mesh_obj.shape_key_add(from_mix=False, name='Basis') for blend_name in blend_vertex_lod_map: shape_key_morph = mesh_obj.shape_key_add(from_mix=False, name=blend_name) shape_key_morph.relative_key = shape_key_basis print('making driver %s for %s' % (blend_name, mesh_name)) shape_key_fcurve = shape_key_morph.driver_add('value') shape_key_fcurve.driver.type = 'AVERAGE' shape_key_var = shape_key_fcurve.driver.variables.new() shape_key_var.type = 'SINGLE_PROP' shape_key_var.targets[0].id_type = 'OBJECT' shape_key_var.targets[0].id = armature_rig shape_key_var.targets[ 0].data_path = 'pose.bones["%s"].morph_value' % blend_name mesh_uvs = [] mesh_skin = mesh_obj.modifiers.new(type='ARMATURE', name="%s_skin" % mesh_name) mesh_skin.use_bone_envelopes = False mesh_skin.object = armature_rig vertex_groups = [] for geom_bone in geom.bones: if not geom_bone in bone_name_map: raise Exception('0x%08X not found' % geom_bone) vertex_groups.append( mesh_obj.vertex_groups.new(bone_name_map[geom_bone])) bm = bmesh.new() bm.from_mesh(mesh) for vertex in geom.vertices: bvert = bm.verts.new(vertex.position) bvert.normal = Vector(swizzle_v3(vertex.normal[:3])) faces_skipped = 0 for face_index, face in enumerate(geom.indices): if invalid_face(face): print('[%s]Face[%04i] %s has duplicate points, skipped' % (mesh_name, face_index, face)) continue try: bm.verts.ensure_lookup_table() bm.edges.ensure_lookup_table() bm.faces.ensure_lookup_table() bm.faces.new([bm.verts[face_point] for face_point in face]) except ValueError as e: faces_skipped += 1 print('Unable to load face %s' % face) print(e) bm.to_mesh(mesh) for vertex_index, vertex in enumerate(geom.vertices): # Positions blender_vertex = mesh.vertices[vertex_index] pos = blender_vertex.co.copy() shape_key_basis.data[vertex_index].co = pos # Add Shape Keys for blend_name in sorted(blend_vertex_lod_map): morph_blend_vertices = blend_vertex_lod_map[blend_name] morph_pos = pos.copy() if vertex.id in morph_blend_vertices: morph_blend_vertex = morph_blend_vertices[vertex.id] if morph_blend_vertex.position: morph_pos += Vector(morph_blend_vertex.position) mesh.shape_keys.key_blocks[blend_name].data[ vertex_index].co = morph_pos # Add Vertex Weights if vertex.blend_indices: for blend_index, blend_bone_index in enumerate( vertex.blend_indices): if blend_bone_index <= len(vertex_groups): blend_vertex_group = vertex_groups[blend_bone_index] weight = vertex.blend_weights[blend_index] if weight > 0.000: blend_vertex_group.add( (vertex_index, ), vertex.blend_weights[blend_index], 'REPLACE') for face_index, face in enumerate(geom.indices): if invalid_face(face): faces_skipped += 1 continue for face_point_index, face_point_vertex_index in enumerate(face): vertex = geom.vertices[face_point_vertex_index] if vertex.uv: for uv_channel_index, uv_coord in enumerate(vertex.uv): if (uv_channel_index + 1) > len(mesh_uvs): mesh_uvs.append( mesh.uv_textures.new(name='uv_%i' % uv_channel_index)) mesh.uv_layers[uv_channel_index].data[face_point_index + ( (face_index - faces_skipped) * 3)].uv = swizzle_uv(uv_coord) mesh_obj.select = True bpy.ops.object.shade_smooth() mesh_obj.select = False mesh_obj.active_shape_key_index = 0 return mesh_obj
def load_mesh(armature_rig, model_mesh, materials): assert isinstance(model_mesh, s3py.buybuild.geometry.ObjectMesh) bone_name_map = {} if armature_rig.type == 'ARMATURE': for bone_hash in armature_rig.data.bones: bone_name_map[FNV32.hash(bone_hash.name)] = bone_hash.name vertices = model_mesh.get_vertices() faces = model_mesh.get_triangles() mesh_name = '%08X' % int(model_mesh.name) print(mesh_name) print('Creating Mesh %s' % mesh_name) mesh = bpy.data.meshes.new(mesh_name) mesh_obj = bpy.data.objects.new(mesh_name, mesh) bpy.context.scene.objects.link(mesh_obj) bpy.context.scene.objects.active = mesh_obj mesh_obj.parent = armature_rig mesh_obj.show_transparent = True matd = model_mesh.material if isinstance(matd, MaterialSet): matd = matd.default_material if isinstance(matd, MaterialDefinition): mesh_material = materials.generate(mesh_name, matd.material_block) mesh_obj.data.materials.append(mesh_material) vertex_groups = [] if model_mesh.skin_controller: print('Adding Vertex groups from skin controller') for bone_hash in model_mesh.bone_references: bone_name = '%0X8' % bone_hash if bone_hash in bone_name_map: bone_name = bone_name_map[bone_hash] vertex_groups.append(mesh_obj.vertex_groups.new(bone_name)) print('Adding armature modifier and attach to rig') mesh_skin = mesh_obj.modifiers.new(type='ARMATURE', name="%s_skin" % mesh_name) mesh_skin.use_bone_envelopes = False mesh_skin.object = armature_rig bm = bmesh.new() bm.from_mesh(mesh) for vertex in vertices: bm.verts.new(vertex.position) for face_index, face in enumerate(faces): bm.verts.ensure_lookup_table() bm.edges.ensure_lookup_table() bm.faces.ensure_lookup_table() if invalid_face(face): print('[%s]Face[%04i] %s has duplicate points, skipped' % (mesh_name, face_index, face)) continue bm.faces.new([bm.verts[face_point] for face_point in face]) for vertex_index, vertex in enumerate(vertices): bm.verts[vertex_index].normal = Vector(vertex.normal[:-1]) bm.to_mesh(mesh) print('Adding weights') for vertex_index, vertex in enumerate(vertices): if vertex.blend_indices and vertex.blend_weights: for blend_index, blend_bone_index in enumerate( vertex.blend_indices): if blend_bone_index >= 0: weight = vertex.blend_weights[blend_index] if weight > 0.0: blend_vertex_group = vertex_groups[int( blend_bone_index)] blend_vertex_group.add((vertex_index, ), weight, 'ADD') print('Adding UV Groups') for declaration in model_mesh.get_vertex_format().declarations: if declaration.usage == VertexFormat.USAGE.UV: mesh.uv_textures.new(name='uv_%i' % declaration.usage_index) faces_skipped = 0 for face_index, face in enumerate(faces): if invalid_face(face): faces_skipped += 1 continue for face_point_index, face_point_vertex_index in enumerate(face): vertex = vertices[face_point_vertex_index] if vertex.uv: for uv_channel_index, uv_coord in enumerate(vertex.uv): mesh.uv_layers[uv_channel_index].data[face_point_index + ( (face_index - faces_skipped) * 3)].uv = swizzle_uv(uv_coord) mesh_obj.select = True bpy.ops.object.shade_smooth() mesh_obj.select = False return mesh_obj
def save_clip(clip_resource, skeleton, scale=1.0): print(skeleton.name, skeleton.type) clip = clip_resource.clip clip.tracks = [] action = skeleton.animation_data.action clip_resource.actor_name = action.s3py.actor_name clip.name = action.s3py.name clip.source_file_name = action.s3py.source_name clip.max_frame_count = int(action.frame_range[1]) start_time = time.clock() print('Saving CLIP...') track_map = {} used_bones = [] for fcurve in action.fcurves: s = str(fcurve.data_path).split('.') if s[0] != 'pose' or s[1][:5] != 'bones': continue cname = s[1][7:-2] if cname == ROOT_MORPH: continue if cname in skeleton.pose.bones: pose_bone = skeleton.pose.bones[cname] track_key = FNV32.hash(cname) clip_track_key = FNV64.hash( cname) & 0xFFFFFFFF if pose_bone.parent and pose_bone.parent.name == ROOT_MORPH else track_key if not track_key in track_map: track = Track(clip_track_key) used_bones.append(pose_bone) clip.tracks.append(track) track_map[track_key] = track print(list(ub.name for ub in used_bones)) print('%i Frames found in %s' % (int(action.frame_range[1]), action.name)) def write_frame(current_value, track, frame_index): write = False if not any(track.frames): write = True else: last_value = track.frames[-1].data for i in range(len(current_value)): difference = math.fabs(current_value[i] - last_value[i]) if difference > 0.0001: write = True if write: f = Frame() f.frame_index = frame_index f.data = current_value track.frames.append(f) set_context('POSE', skeleton) for frame_index in range(int(action.frame_range[0]), int(action.frame_range[1])): bpy.context.scene.frame_set(frame_index) for pose_bone in used_bones: track_key = FNV32.hash(pose_bone.name) if not track_key in track_map: continue track = track_map[track_key] if pose_bone.parent and pose_bone.parent.name == ROOT_MORPH: if not track.morphs: track.morphs = Curve.create_morph() cur_morph = [pose_bone.morph_value] write_frame(cur_morph, track.morphs, frame_index) continue matrix_parent = Matrix() if not pose_bone.parent else pose_bone.parent.matrix matrix_delta = matrix_parent.inverted() * pose_bone.matrix if not track.orientations: track.orientations = Curve.create_orientation() rotation = quat_xyzw(matrix_delta.to_quaternion()) write_frame(rotation, track.orientations, frame_index) if not track.positions: track.positions = Curve.create_position() translation = matrix_delta.to_translation() # if pose_bone.name == ROOT_BIND: # translation[1] *= scale write_frame(translation, track.positions, frame_index) print('Finished in %.4f sec.' % (time.clock() - start_time))