Commit 7736a4b143a8fdbb07150322028f641526d43e3d
1 parent
bb4c6ded
Exists in
master
Integração do movimento de contato ao novo modelo JSON
Showing
6 changed files
with
174 additions
and
263 deletions
Show diff stats
avatar_cartoon_v2.74.blend
No preview for this file type
... | ... | @@ -0,0 +1,54 @@ |
1 | +import moves | |
2 | +import util | |
3 | + | |
4 | +def circular_semicircular(js_movement, current_frame, frame_jump, is_right_hand, is_semicircular): | |
5 | + # const | |
6 | + dict_ray = {'pequeno': 0.5, 'normal': 1.0, 'grande': 1.5} | |
7 | + dict_period = {'lento': 55, 'normal': 45, 'rapido': 35} | |
8 | + # decodificar valores | |
9 | + ray = dict_ray[js_movement['raio']] | |
10 | + period = dict_period[js_movement['velocidade']] | |
11 | + #print('setar articulacao:', js_movement['articulacao']) | |
12 | + #print('setar configuracao:', js_movement['configuracao']) | |
13 | + #print('setar orientacao:', js_movement['orientacao']) | |
14 | + # diminuir a velocidade | |
15 | + if (js_movement['velocidade'] == 'lento'): | |
16 | + period += 10 | |
17 | + # aumentar a velocidade | |
18 | + elif (js_movement['velocidade'] == 'rapido'): | |
19 | + period -= 10 | |
20 | + # definir eixos do movimento | |
21 | + if (js_movement['plano'] == 'frente-esquerda'): | |
22 | + x, y = 2, 0 | |
23 | + elif (js_movement['plano'] == 'frente-cima'): | |
24 | + x, y = 2, 1 | |
25 | + else: | |
26 | + x, y = 0, 1 | |
27 | + # mao usada (direita/esquerda) | |
28 | + if (is_right_hand): | |
29 | + ik = bpy.context.object.pose.bones['ik_FK.R'] | |
30 | + else: | |
31 | + ik = bpy.context.object.pose.bones['ik_FK.L'] | |
32 | + current_frame = insert_keyframe_pose_default(current_frame, frame_jump, [ik], ['location']) | |
33 | + current_frame = moves.circular(ik, current_frame + frame_jump, ray, period, x, y, js_movement['lado_oposto'], js_movement['sentido_inverso'], is_semicircular) | |
34 | + return current_frame | |
35 | + | |
36 | +def contato(js_movement, current_frame, frame_jump, is_right_hand): | |
37 | + sub_type = next(iter(js_movement.keys())) | |
38 | + mov_param = js_movement[sub_type] | |
39 | + action = util.right_hand_actions if is_right_hand else util.left_hand_actions | |
40 | + bones = util.rightBonesConf if is_right_hand else util.leftBonesConf | |
41 | + current_frame = current_frame + 2*frame_jump | |
42 | + return moves.contato(action, sub_type, mov_param, bones, current_frame, frame_jump) | |
43 | + | |
44 | +def hand_mov(current_frame, frame_jump, js_mao, is_right_hand): | |
45 | + if (js_mao == {}): | |
46 | + return | |
47 | + movement_name = next(iter(js_mao.keys())) | |
48 | + if (movement_name == 'circular'): | |
49 | + current_frame = circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, False) | |
50 | + elif (movement_name == 'semicircular'): | |
51 | + current_frame = circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, True) | |
52 | + elif (movement_name == 'contato'): | |
53 | + current_frame = contato(js_mao[movement_name], current_frame, frame_jump, is_right_hand) | |
54 | + return current_frame + frame_jump | |
0 | 55 | \ No newline at end of file | ... | ... |
facial.py
... | ... | @@ -3,8 +3,6 @@ |
3 | 3 | import bpy |
4 | 4 | import util |
5 | 5 | |
6 | -library_name = '07_facial' | |
7 | - | |
8 | 6 | # duracao na posicao selecionada |
9 | 7 | dict_duration = { |
10 | 8 | 'lento': 15, |
... | ... | @@ -19,9 +17,6 @@ dict_transition = { |
19 | 17 | 'rapido': 5 |
20 | 18 | } |
21 | 19 | |
22 | -# marcador global da linha do tempo exclusivo para expressao facial | |
23 | -timeline_facial = 0 | |
24 | - | |
25 | 20 | # insere keyframes aos bones selecionados anteriormente e passados como parametro |
26 | 21 | def keyframe_insert(current_frame = 0, pose_bones = bpy.context.object.pose.bones, keyframe_types = ['location', 'rotation_quaternion']): |
27 | 22 | # verifica se existe apenas um bone |
... | ... | @@ -64,9 +59,8 @@ def apply_pose(index = 0, pose_library = list(bpy.data.actions)): |
64 | 59 | return |
65 | 60 | |
66 | 61 | # consolida o movimento (faz insercao dos keyframes) e incrementa a timeline |
67 | -def set_expression(index, frame_duration = dict_duration['normal'], frame_transition = 0): | |
68 | - global timeline_facial | |
69 | - global library_name | |
62 | +def set_expression(timeline_facial, index, frame_duration = dict_duration['normal'], frame_transition = 0): | |
63 | + library_name = util.facial_expression_id | |
70 | 64 | bones_facial = util.dict_bones[library_name] |
71 | 65 | util.select_bones(bones_facial) |
72 | 66 | # TODO separar bones 'location' e 'rotation_quaternion' |
... | ... | @@ -81,7 +75,7 @@ def set_expression(index, frame_duration = dict_duration['normal'], frame_transi |
81 | 75 | return timeline_facial |
82 | 76 | |
83 | 77 | # decodifica objeto JSON |
84 | -def decode_expression(js_facial, initial_interpolation = dict_duration['normal']): | |
78 | +def decode_expression(timeline_facial, js_facial, initial_interpolation = dict_duration['normal']): | |
85 | 79 | global dict_duration |
86 | 80 | global dict_transition |
87 | 81 | index = js_facial['expressao'] |
... | ... | @@ -89,9 +83,9 @@ def decode_expression(js_facial, initial_interpolation = dict_duration['normal'] |
89 | 83 | frame_transition = dict_duration[js_facial['transicao']] |
90 | 84 | # insere o primeiro keyframe |
91 | 85 | if (timeline_facial == 0): |
92 | - set_expression(0, initial_interpolation) | |
93 | - set_expression(index, frame_duration, frame_transition) | |
94 | - set_expression(0, frame_duration) | |
86 | + set_expression(timeline_facial, 0, initial_interpolation) | |
87 | + set_expression(timeline_facial, index, frame_duration, frame_transition) | |
88 | + set_expression(timeline_facial, 0, frame_duration) | |
95 | 89 | return timeline_facial |
96 | 90 | |
97 | 91 | """ | ... | ... |
libras.py
... | ... | @@ -19,13 +19,14 @@ import util |
19 | 19 | import moves |
20 | 20 | import pyutil |
21 | 21 | import facial |
22 | +import decode | |
22 | 23 | |
23 | 24 | # intervalos de interpolacao dos keyframes |
24 | 25 | dict_interpolation = { |
25 | 26 | 'inicial': 20, |
26 | - 'lento': 5, | |
27 | + 'lento': 15, | |
27 | 28 | 'normal': 10, |
28 | - 'rapido': 15, | |
29 | + 'rapido': 5, | |
29 | 30 | 'final': 20 |
30 | 31 | } |
31 | 32 | |
... | ... | @@ -33,108 +34,18 @@ def insert_keyframe_pose_default(current_frame = 0, frame_jump = 0, pose_bones = |
33 | 34 | for obj in (pose_bones): |
34 | 35 | obj.bone.select = True |
35 | 36 | for type_keyframe in types_keyframe: |
36 | - obj.keyframe_insert(index = -1, frame = current_frame, group = obj.name, data_path = type_keyframe) | |
37 | + util.keyframe_insert(obj, type_keyframe, current_frame, False) | |
37 | 38 | obj.bone.select = False |
38 | - return current_frame + frame_jump | |
39 | + return current_frame | |
39 | 40 | |
40 | 41 | def pose_default(current_frame = 0, frame_jump = 0, actions = bpy.data.actions): |
41 | - result = 0 | |
42 | + result = current_frame | |
42 | 43 | for action in actions: |
43 | 44 | if (action.use_fake_user): |
44 | 45 | bpy.context.object.pose_library = action |
45 | 46 | bpy.ops.poselib.apply_pose(pose_index = 0) |
46 | 47 | result = insert_keyframe_pose_default(current_frame, frame_jump) |
47 | - return result | |
48 | - | |
49 | -def decode_circular_semicircular(js_movement, current_frame, frame_jump, is_right_hand, is_semicircular): | |
50 | - # const | |
51 | - dict_ray = {'pequeno': 0.5, 'normal': 1.0, 'grande': 1.5} | |
52 | - dict_period = {'lento': 55, 'normal': 45, 'rapido': 35} | |
53 | - # decodificar valores | |
54 | - ray = dict_ray[js_movement['raio']] | |
55 | - period = dict_period[js_movement['velocidade']] | |
56 | - print('setar articulacao:', js_movement['articulacao']) | |
57 | - print('setar configuracao:', js_movement['configuracao']) | |
58 | - print('setar orientacao:', js_movement['orientacao']) | |
59 | - # diminuir a velocidade | |
60 | - if (js_movement['velocidade'] == 'lento'): | |
61 | - period += 10 | |
62 | - # aumentar a velocidade | |
63 | - elif (js_movement['velocidade'] == 'rapido'): | |
64 | - period -= 10 | |
65 | - # definir eixos do movimento | |
66 | - if (js_movement['plano'] == 'frente-esquerda'): | |
67 | - x, y = 2, 0 | |
68 | - elif (js_movement['plano'] == 'frente-cima'): | |
69 | - x, y = 2, 1 | |
70 | - else: | |
71 | - x, y = 0, 1 | |
72 | - # mao usada (direita/esquerda) | |
73 | - if (is_right_hand): | |
74 | - ik = bpy.context.object.pose.bones['ik_FK.R'] | |
75 | - else: | |
76 | - ik = bpy.context.object.pose.bones['ik_FK.L'] | |
77 | - current_frame = insert_keyframe_pose_default(current_frame, frame_jump, [ik], ['location']) | |
78 | - current_frame = moves.circular(ik, current_frame + frame_jump, ray, period, x, y, js_movement['lado_oposto'], js_movement['sentido_inverso'], is_semicircular) | |
79 | - return current_frame | |
80 | - | |
81 | -def decode_hand_mov(current_frame, frame_jump, js_mao, is_right_hand): | |
82 | - if (js_mao == {}): | |
83 | - return | |
84 | - movement_name = next(iter(js_mao.keys())) | |
85 | - print("Movimento: " + movement_name) | |
86 | - if (movement_name == 'circular'): | |
87 | - current_frame = decode_circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, False) | |
88 | - elif (movement_name == 'semicircular'): | |
89 | - current_frame = decode_circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, True) | |
90 | - return current_frame + frame_jump | |
91 | - | |
92 | -""" | |
93 | -# Funcao responsavel por setar pose padrao | |
94 | -def poseDefault(json_input, positionFrames, collisionFlag = False): | |
95 | - handDefaultParam = [0, 0, 0] | |
96 | - util.setPose(util.right_hand_actions, handDefaultParam, positionFrames, util.rightBonesConf, collisionFlag) | |
97 | - if(json_input["leftHand"] != []): | |
98 | - util.setPose(util.left_hand_actions, handDefaultParam, positionFrames, util.leftBonesConf, collisionFlag) | |
99 | - setFaceConfiguration([0], positionFrames, util.faceBonesConf) | |
100 | - | |
101 | -# Funcao responsavel por setar as configuracoes das maos | |
102 | -def setHandConfiguration(actions, handParam, positionFrames, bones): | |
103 | - util.setPose(actions, handParam, positionFrames, bones) | |
104 | - | |
105 | -# Funcao responsavel por setar a configuracao da face | |
106 | -def setFaceConfiguration(handParam, positionFrames, bones): | |
107 | - util.setPose(util.facial_expression_action, handParam, positionFrames, bones) | |
108 | - | |
109 | -#Funcao que inicia a configuracao de ambas as maos | |
110 | -def configureHands(endFrame): | |
111 | - # Array com valores dos campos que serao passados pelo JSON | |
112 | - hands = ["rightHand", "leftHand"] | |
113 | - iks = ["ik_FK.R", "ik_FK.L"] | |
114 | - bones_ = [util.rightBonesConf, util.leftBonesConf] | |
115 | - # Array com as actions FAKES que seram selecionadas no Blender para cada lado do corpo | |
116 | - actions = [util.right_hand_actions, util.left_hand_actions] | |
117 | - for i in range(len(hands)): | |
118 | - if(json_input[hands[i]] != []): | |
119 | - move = json_input[hands[i]][0] | |
120 | - pose = util.armature.pose.bones[iks[i]] | |
121 | - handParam = json_input[hands[i]][-3:] | |
122 | - if(move in ["pontual", "circular", "semicircular", "retilineo", "senoidal"]): | |
123 | - setHandConfiguration(actions[i], handParam, util.hands_default_frames, bones_[i]) | |
124 | - if(move in ["circular", "semicircular"]): | |
125 | - orientation, direction, radius, laps = json_input[hands[i]][1:5] | |
126 | - #endFrame = moves.circular_or_semiCircular(pose, orientation, direction, radius, laps, 5) | |
127 | - setHandConfiguration(actions[i], handParam, [endFrame], bones_[i]) | |
128 | - elif(move == "retilineo"): | |
129 | - setHandConfiguration(actions[i], json_input[hands[i]][-6:-3], util.hands_default_frames, bones_[i]) | |
130 | - setHandConfiguration(actions[i], handParam, util.hands_frames_retilineo, bones_[i]) | |
131 | - elif(move == "senoidal"): | |
132 | - orientation, direction, radius, laps = json_input[hands[i]][1:5] | |
133 | - #endFrame = circular_or_semiCircular(pose, orientation, direction, radius, laps, 5) | |
134 | - setHandConfiguration(actions[i], handParam, [endFrame], bones_[i]) | |
135 | - elif(move == "contato"): | |
136 | - endFrame = moves.contato(actions[i], json_input[hands[i]], bones_[i], pose) | |
137 | -""" | |
48 | + return result + frame_jump | |
138 | 49 | |
139 | 50 | def main(): |
140 | 51 | util.delete_all_keyframes() |
... | ... | @@ -147,11 +58,14 @@ def main(): |
147 | 58 | frame_jump = dict_interpolation[js_input['interpolacao']] |
148 | 59 | |
149 | 60 | endFrame = pose_default(0) |
150 | - mao_esquerda_frame = 0 | |
151 | - mao_direita_frame = 0 | |
61 | + timeline_mao_esquerda = 0 | |
62 | + timeline_mao_direita = 0 | |
63 | + timeline_facial = 0 | |
152 | 64 | |
153 | - # pose padrao inicial em todos os bones ('location' e 'rotation_quaternion') | |
65 | + # setar pose padrao inicial em todos os bones ('location' e 'rotation_quaternion') | |
154 | 66 | endFrame += pose_default(dict_interpolation['inicial']) |
67 | + timeline_mao_esquerda = endFrame | |
68 | + timeline_mao_direita = endFrame | |
155 | 69 | |
156 | 70 | for i in range(0, len(js_movimentos)): |
157 | 71 | # tenta decodificar objetos JSON |
... | ... | @@ -171,35 +85,27 @@ def main(): |
171 | 85 | # faz tratamento dos objetos |
172 | 86 | if (js_facial == {}): |
173 | 87 | pyutil.log("<Vazio> js_movimentos[%d] >> Exp facial" % (i)) |
174 | - facial.set_expression(0, facial.timeline_facial + frame_jump) | |
88 | + timeline_facial = facial.set_expression(timeline_facial, 0) | |
175 | 89 | else: |
176 | - facial.decode_expression(js_facial) | |
90 | + timeline_facial = facial.decode_expression(timeline_facial, js_facial) | |
177 | 91 | |
178 | 92 | if (js_mao_esquerda == {}): |
179 | 93 | pyutil.log("<Vazio> js_movimentos[%d] >> Mao esquerda" % (i)) |
180 | 94 | # TODO posicionar mao esquerda na lateral do corpo |
181 | 95 | else: |
182 | - mao_esquerda_frame += decode_hand_mov(mao_esquerda_frame, frame_jump, js_mao_esquerda, False) | |
96 | + timeline_mao_esquerda = decode.hand_mov(timeline_mao_esquerda, frame_jump, js_mao_esquerda, False) | |
183 | 97 | |
184 | 98 | if (js_mao_direita == {}): |
185 | 99 | pyutil.log("<Vazio> js_movimentos[%d] >> Mao direita" % (i)) |
186 | 100 | # TODO posicionar mao direita na lateral do corpo |
187 | 101 | else: |
188 | - mao_direita_frame += decode_hand_mov(mao_direita_frame, frame_jump, js_mao_direita, True) | |
102 | + timeline_mao_direita = decode.hand_mov(timeline_mao_direita, frame_jump, js_mao_direita, True) | |
189 | 103 | |
190 | - endFrame = max(facial.timeline_facial, mao_esquerda_frame, mao_direita_frame) | |
104 | + endFrame = max(timeline_facial, timeline_mao_esquerda, timeline_mao_direita) | |
191 | 105 | endFrame += frame_jump |
192 | 106 | |
193 | 107 | # setar pose padrao final em todos os bones (location e rotation) |
194 | - #endFrame += pose_default(endFrame + dict_interpolation['final']) | |
195 | - #endFrame = insert_keyframe_pose_default(endFrame, frame_jump) | |
196 | - #endFrame += dict_interpolation['final'] | |
197 | - #endFrame = util.get_endFrame(js_input, util.hands_frames_retilineo) | |
198 | - #poseDefault([1]) | |
199 | - #configureHands(endFrame) | |
200 | - #configureFace(endFrame) | |
201 | - #poseDefault(js_input, [endFrame + 15]) | |
202 | - | |
108 | + endFrame += pose_default(endFrame + dict_interpolation['final']) | |
203 | 109 | util.render_sign(js_input["userId"], js_input["sinal"], endFrame) |
204 | 110 | |
205 | 111 | except: | ... | ... |
moves.py
... | ... | @@ -3,148 +3,127 @@ |
3 | 3 | import bpy |
4 | 4 | import math |
5 | 5 | import util |
6 | +import pyutil | |
6 | 7 | |
7 | -def contato(action, input_hand, bones, pose, initialFrame = 18): | |
8 | - currentFrame = initialFrame | |
9 | - contact_type = input_hand[1] | |
8 | +def read_hand_param(mov_param): | |
9 | + conf_param = mov_param['configuracao'] if 'configuracao' in mov_param else 0 | |
10 | + artic_param = mov_param['articulacao'] if 'articulacao' in mov_param else 0 | |
11 | + orient_param = mov_param['orientacao'] if 'orientacao' in mov_param else 0 | |
12 | + return [conf_param, artic_param, orient_param] | |
10 | 13 | |
14 | +def contato(action, contact_type, mov_param, bones, initialFrame = 18, frameJump = 10): | |
11 | 15 | if (contact_type == "alisar"): |
12 | - currentFrame = alisar(action, input_hand, pose, bones, initialFrame) | |
16 | + currentFrame = alisar(action, mov_param, bones, initialFrame, frameJump) | |
13 | 17 | elif (contact_type == "cocar"): |
14 | - currentFrame = cocar(action, input_hand, bones, initialFrame) | |
18 | + currentFrame = cocar(action, mov_param, bones, initialFrame, frameJump) | |
15 | 19 | elif (contact_type == "tocar"): |
16 | - currentFrame = tocar(action, input_hand, bones, initialFrame) | |
20 | + currentFrame = tocar(action, mov_param, bones, initialFrame, frameJump) | |
17 | 21 | elif (contact_type == "riscar"): |
18 | - currentFrame = riscar(action, input_hand, bones, initialFrame) | |
22 | + currentFrame = riscar(action, mov_param, bones, initialFrame, frameJump) | |
19 | 23 | return currentFrame |
20 | 24 | |
21 | -def riscar(action, input_hand, bones, pose, initialFrame = 18, bnAntBracoDegree = 2, bnMaoDegree = 45, frameJump = 10): | |
25 | +def riscar(action, mov_param, bones, initialFrame = 25, frameJump = 10, bnAntBracoDegree = 2, bnMaoDegree = 45): | |
22 | 26 | currentFrame = initialFrame |
23 | - endFrame = initialFrame + 2 * frameJump | |
24 | - handParam = input_hand[-3:] | |
27 | + handParam = read_hand_param(mov_param) | |
25 | 28 | lado = "R" if util.rightBonesConf == bones else "L" |
26 | 29 | |
27 | - bnAntBraco = bpy.context.object.pose.bones["BnAntBraco." + lado] | |
28 | - bnAntBraco.bone.select = True | |
29 | - util.apply_rotation(bnAntBraco, "Z", currentFrame, endFrame, bnAntBracoDegree) | |
30 | - currentFrame += frameJump | |
31 | - util.apply_rotation(bnAntBraco, "Z", currentFrame, endFrame, (-1)*(bnAntBracoDegree+1)) | |
32 | - bnAntBraco.bone.select = False | |
30 | + #bnAntBraco = bpy.context.object.pose.bones["BnAntBraco." + lado] | |
31 | + #util.apply_rotation(bnAntBraco, "Z", currentFrame, bnAntBracoDegree) | |
32 | + #currentFrame += frameJump | |
33 | + #util.apply_rotation(bnAntBraco, "Z", currentFrame, (-1)*(bnAntBracoDegree+1)) | |
33 | 34 | |
34 | 35 | currentFrame = initialFrame |
35 | 36 | util.setPose(action, handParam, [currentFrame], bones) |
36 | 37 | bnMao = bpy.context.object.pose.bones["BnMao." + lado] |
37 | - bnMao.bone.select = True | |
38 | - util.apply_rotation(bnMao, "Y", currentFrame, endFrame, bnMaoDegree) | |
39 | 38 | currentFrame += frameJump |
40 | - util.apply_rotation(bnMao, "Y", currentFrame, endFrame, (-2)*bnMaoDegree) | |
41 | - currentFrame += frameJump | |
42 | - util.apply_rotation(bnMao, "Y", currentFrame, endFrame, bnMaoDegree) | |
43 | - util.setPose(action[0:2], handParam[0:2], [currentFrame], bones) | |
39 | + util.apply_rotation(bnMao, "Y", currentFrame, bnMaoDegree) | |
40 | + currentFrame += int(frameJump/2) | |
41 | + util.apply_rotation(bnMao, "Y", currentFrame, (-1)*bnMaoDegree) | |
42 | + currentFrame += int(frameJump/2) | |
43 | + util.apply_rotation(bnMao, "Y", currentFrame, (-2)*bnMaoDegree) | |
44 | 44 | currentFrame += frameJump |
45 | - bnMao.bone.select = False | |
45 | + util.setPose(action, handParam, [currentFrame], bones) | |
46 | 46 | return currentFrame |
47 | 47 | |
48 | -def tocar(action, input_hand, bones, pose, initialFrame = 18, degree = 30, frameJump = 10): | |
48 | +def tocar(action, mov_param, bones, initialFrame = 25, degree = 30, frameJump = 10): | |
49 | 49 | currentFrame = initialFrame |
50 | - endFrame = initialFrame + 2 * frameJump | |
51 | - handParam = input_hand[-3:] | |
50 | + handParam = read_hand_param(mov_param) | |
52 | 51 | util.setPose(action, handParam, [initialFrame], bones) |
52 | + pose = util.armature.pose.bones["ik_FK.R" if util.rightBonesConf == bones else "ik_FK.L"] | |
53 | 53 | |
54 | 54 | lado = "BnMao.R" if util.rightBonesConf == bones else "BnMao.L" |
55 | 55 | bnMao = bpy.context.object.pose.bones[lado] |
56 | - bnMao.bone.select = True | |
57 | - currentFrame += frameJump | |
58 | - util.apply_rotation(bnMao, "X", currentFrame, endFrame, -degree) | |
59 | 56 | currentFrame += frameJump |
60 | - util.apply_rotation(bnMao, "X", currentFrame, endFrame, degree) | |
61 | - util.setPose([action[0]], [handParam[0]], [currentFrame], bones) | |
57 | + util.apply_rotation(bnMao, "X", currentFrame, -degree) | |
58 | + pose = util.armature.pose.bones["ik_FK.R" if util.rightBonesConf == bones else "ik_FK.L"] | |
62 | 59 | currentFrame += frameJump |
63 | - bnMao.bone.select = False | |
60 | + util.apply_rotation(bnMao, "X", currentFrame, degree) | |
61 | + util.setPose(action[0:2], handParam[0:2], [currentFrame], bones) | |
64 | 62 | return currentFrame |
65 | 63 | |
66 | -def cocar(action, input_hand, bones, initialFrame = 18, repetition = 2, frameJump = 6): | |
64 | +def cocar(action, mov_param, bones, initialFrame = 18, frameJump = 10): | |
67 | 65 | currentFrame = initialFrame |
68 | - pa_index = input_hand[-1] | |
66 | + pa_index = mov_param['articulacao'] if 'articulacao' in mov_param else 0 | |
67 | + repetition = mov_param['repeticoes'] if 'repeticoes' in mov_param else 2 | |
69 | 68 | |
70 | 69 | for i in range(0, repetition): |
71 | - util.setPose(action, [util.cocar_mao_aberta_index, pa_index, util.cocar_orientation_index], [currentFrame], bones) | |
70 | + util.setPose(action, [util.cocar_mao_aberta_index, pa_index, util.cocar_orientation_index], [currentFrame], bones, False) | |
72 | 71 | currentFrame += frameJump |
73 | - lastFrame = i == repetition - 1 | |
74 | - util.setPose(action, [util.cocar_mao_fechada_index, pa_index, util.cocar_orientation_index], [currentFrame], bones) | |
72 | + util.setPose(action, [util.cocar_mao_fechada_index, pa_index, util.cocar_orientation_index], [currentFrame], bones, False) | |
75 | 73 | currentFrame += frameJump |
76 | 74 | return currentFrame |
77 | 75 | |
78 | -def alisar(action, input_hand, pose, bones, initialFrame = 18, frameJump = 10, width = 0.25): | |
76 | +def alisar(action, mov_param, bones, initialFrame = 18, frameJump = 10, width = 0.25): | |
79 | 77 | currentFrame = initialFrame |
80 | - orientation, repetition = input_hand[2:4] | |
81 | - handParam = input_hand[-3:] | |
82 | - util.setPose(action, handParam, util.hands_default_frames, bones) | |
83 | - | |
84 | - if (orientation == "perpendicular"): | |
85 | - currentFrame = alisar_xy(pose, 1, repetition, initialFrame, frameJump, width) | |
86 | - elif (orientation == "paralelo"): | |
87 | - currentFrame = alisar_xy(pose, 0, repetition, initialFrame, frameJump, width) | |
88 | - elif (orientation == "diagonal-direita"): | |
89 | - currentFrame = alisar_diagonal(pose, True, repetition, initialFrame, frameJump, width) | |
90 | - elif (orientation == "diagonal-esquerda"): | |
91 | - currentFrame = alisar_diagonal(pose, False, repetition, initialFrame, frameJump, width) | |
92 | - | |
78 | + plane = mov_param['plano'] if 'plano' in mov_param else "perpendicular" | |
79 | + repetition = mov_param['repeticoes'] if 'repeticoes' in mov_param else 2 | |
80 | + handParam = read_hand_param(mov_param) | |
81 | + util.setPose(action, handParam, [currentFrame], bones) | |
82 | + boneIK = util.armature.pose.bones["ik_FK.R" if util.rightBonesConf == bones else "ik_FK.L"] | |
83 | + | |
84 | + if (plane == "perpendicular"): | |
85 | + currentFrame = alisar_xy(boneIK, 1, repetition, currentFrame, frameJump, width) | |
86 | + elif (plane == "paralelo"): | |
87 | + currentFrame = alisar_xy(boneIK, 0, repetition, currentFrame, frameJump, width) | |
88 | + elif (plane == "diagonal-direita"): | |
89 | + currentFrame = alisar_diagonal(boneIK, True, repetition, currentFrame, frameJump, width) | |
90 | + elif (plane == "diagonal-esquerda"): | |
91 | + currentFrame = alisar_diagonal(boneIK, False, repetition, currentFrame, frameJump, width) | |
93 | 92 | util.setPose(action, handParam, [currentFrame], bones) |
94 | 93 | return currentFrame |
95 | 94 | |
96 | -def alisar_xy(pose, orientation_index, repetition, initialFrame = 18, frameJump = 10, width = 0.25): | |
95 | +def alisar_xy(boneIK, orientation_index, repetition, initialFrame = 18, frameJump = 10, width = 0.25): | |
97 | 96 | currentFrame = initialFrame |
98 | - center = pose.location.x, pose.location.y, pose.location.z | |
99 | - | |
97 | + location = util.get_bone_data_from_frame(boneIK, currentFrame, 'location') | |
98 | + center = location.x, location.y, location.z | |
100 | 99 | for i in range(0, repetition): |
101 | - pose.location[orientation_index] = center[orientation_index] - width | |
102 | - util.keyframe_insert(pose, 'location', currentFrame) | |
100 | + boneIK.location = center | |
101 | + boneIK.location[orientation_index] = center[orientation_index] - width | |
102 | + util.keyframe_insert(boneIK, 'location', currentFrame) | |
103 | 103 | currentFrame += frameJump |
104 | - pose.location[orientation_index] = center[orientation_index] + width | |
105 | - util.keyframe_insert(pose, 'location', currentFrame) | |
104 | + boneIK.location = center | |
105 | + boneIK.location[orientation_index] = center[orientation_index] + width | |
106 | + util.keyframe_insert(boneIK, 'location', currentFrame) | |
106 | 107 | currentFrame += frameJump |
107 | 108 | return currentFrame |
108 | 109 | |
109 | -def alisar_diagonal(pose, to_right, repetition, initialFrame = 18, frameJump = 10, width = 0.25): | |
110 | +def alisar_diagonal(boneIK, to_right, repetition, initialFrame = 18, frameJump = 10, width = 0.25): | |
110 | 111 | currentFrame = initialFrame |
111 | - center = pose.location.x, pose.location.y, pose.location.z | |
112 | - | |
112 | + location = util.get_bone_data_from_frame(boneIK, currentFrame, 'location') | |
113 | + center = location.x, location.y, location.z | |
113 | 114 | for i in range(0, repetition): |
114 | - pose.location[0] = center[0] - width if to_right else center[0] - width | |
115 | - pose.location[1] = center[1] - width if to_right else center[1] + width | |
116 | - | |
117 | - util.keyframe_insert(pose, 'location', currentFrame) | |
115 | + boneIK.location = center | |
116 | + boneIK.location[0] = center[0] - width if to_right else center[0] - width | |
117 | + boneIK.location[1] = center[1] - width if to_right else center[1] + width | |
118 | + util.keyframe_insert(boneIK, 'location', currentFrame) | |
118 | 119 | currentFrame += frameJump |
119 | - | |
120 | - pose.location[0] = center[0] + width if to_right else center[0] + width | |
121 | - pose.location[1] = center[1] + width if to_right else center[1] - width | |
122 | - util.keyframe_insert(pose, 'location', currentFrame) | |
120 | + boneIK.location = center | |
121 | + boneIK.location[0] = center[0] + width if to_right else center[0] + width | |
122 | + boneIK.location[1] = center[1] + width if to_right else center[1] - width | |
123 | + util.keyframe_insert(boneIK, 'location', currentFrame) | |
123 | 124 | currentFrame += frameJump |
124 | 125 | return currentFrame |
125 | 126 | |
126 | -""" | |
127 | -# descontinuada: circular_or_semiCircular | |
128 | -def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensity = 5, initialFrame = 18, turn = None): | |
129 | - center = pose.location.x, pose.location.y, pose.location.z | |
130 | - if(orientation == 'perpendicular'): | |
131 | - if(direction == 'horario'): | |
132 | - endFrame = circular(center, radius, 1, 0, 2, pose, 0, laps, intensity, initialFrame, turn) | |
133 | - else: | |
134 | - endFrame = locationCircular(center, radius, 0, 1, 2, pose, 0, laps, intensity, initialFrame, turn) | |
135 | - elif(orientation == 'paralelo'): | |
136 | - if(direction == 'horario'): | |
137 | - endFrame = locationCircular(center, radius, 1, 2, 0, pose, 0, laps, intensity, initialFrame, turn) | |
138 | - else: | |
139 | - endFrame = locationCircular(center, radius, 2, 1, 0, pose, 0, laps, intensity, initialFrame, turn) | |
140 | - elif(orientation == 'plano'): | |
141 | - if(direction == 'horario'): | |
142 | - endFrame = locationCircular(center, radius, 2, 0, 1, pose, 0, laps, intensity, initialFrame, turn) | |
143 | - else: | |
144 | - endFrame = locationCircular(center, radius, 0, 2, 1, pose, 0, laps, intensity, initialFrame, turn) | |
145 | - return endFrame | |
146 | -""" | |
147 | - | |
148 | 127 | # Obs.: A velocidade do movimento vai ser a relacao entre tamanho do raio e o periodo |
149 | 128 | # quanto maior o periodo mais keyframes |
150 | 129 | # quanto menor o raio mais rapido |
... | ... | @@ -200,4 +179,4 @@ def circular(obj, frame_atual, raio, periodo, x = 0, y = 1, usar_lado_oposto = F |
200 | 179 | util.keyframe_insert(obj, 'location', frame_atual) |
201 | 180 | frame_atual += 1 |
202 | 181 | util.keyframe_insert(obj, 'location', frame_atual) |
203 | 182 | - return periodo - 1 |
183 | + return periodo - 1 | |
204 | 184 | \ No newline at end of file | ... | ... |
util.py
... | ... | @@ -5,6 +5,7 @@ import math |
5 | 5 | import pyutil |
6 | 6 | import os |
7 | 7 | import sys |
8 | +import copy | |
8 | 9 | from bmesh_collision import bmesh_check_intersect_objects |
9 | 10 | |
10 | 11 | armature = bpy.context.scene.objects.get('Armature.001') |
... | ... | @@ -20,27 +21,15 @@ dict_bones = { |
20 | 21 | } |
21 | 22 | |
22 | 23 | # Vetor com indices de cada bone do lado direito |
23 | -# rightBonesConf = [1, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66] | |
24 | +rightBonesConf = [1, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66] | |
24 | 25 | |
25 | 26 | # Vetor com indices de cada bone do lado esquerdo |
26 | -# leftBonesConf = [0, 43, 44, 45, 46, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82] | |
27 | - | |
28 | -# Vetor com indices de cada bone da face | |
29 | -# faceBonesConf = [15, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 47] | |
30 | - | |
31 | -# Vetor com indices de todos os bones | |
32 | -# allBones = list(range(len(armature.pose.bones))) | |
33 | - | |
34 | -# define a posição dos keyframes | |
35 | -# hands_default_frames = [15] | |
36 | - | |
37 | -# define a posição dos keyframes | |
38 | -# hands_frames_retilineo = [30, 33] | |
27 | +leftBonesConf = [0, 43, 44, 45, 46, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82] | |
39 | 28 | |
40 | 29 | # Movimento coçar - Índices de poses |
41 | -cocar_mao_aberta_index = 56 | |
30 | +cocar_mao_aberta_index = 55 | |
42 | 31 | cocar_mao_fechada_index = 24 |
43 | -cocar_orientation_index = 20 | |
32 | +cocar_orientation_index = 11 | |
44 | 33 | |
45 | 34 | # Action expressão facial |
46 | 35 | facial_expression_id = '07_facial' |
... | ... | @@ -83,6 +72,9 @@ def deselect_bones(bones = bpy.context.object.pose.bones): |
83 | 72 | return |
84 | 73 | |
85 | 74 | def delete_all_keyframes(): |
75 | + bpy.ops.object.mode_set(mode = 'OBJECT') | |
76 | + bpy.ops.object.select_all(action = "DESELECT") | |
77 | + bpy.ops.object.mode_set(mode = 'POSE') | |
86 | 78 | bpy.context.active_object.animation_data_clear() |
87 | 79 | for obj in bpy.data.objects: |
88 | 80 | obj.animation_data_clear() |
... | ... | @@ -90,9 +82,6 @@ def delete_all_keyframes(): |
90 | 82 | |
91 | 83 | # Função responsável por selecionar as pose-libs e setar os frames |
92 | 84 | def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True): |
93 | - bpy.ops.object.mode_set(mode = 'OBJECT') | |
94 | - bpy.ops.object.select_all(action="DESELECT") | |
95 | - bpy.ops.object.mode_set(mode = 'POSE') | |
96 | 85 | for x in range(len(positionFrames)): |
97 | 86 | for l in range(len(actions)): |
98 | 87 | action = actions[l] |
... | ... | @@ -108,6 +97,9 @@ def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True) |
108 | 97 | keyframe_insert(bone, 'rotation_quaternion', positionFrames[x], collisionFlag and validPA, validO) |
109 | 98 | |
110 | 99 | def keyframe_insert(bone, path, positionFrame, collisionFlag = True, rotationFlag = False): |
100 | + # Limit hand depth | |
101 | + if ("ik_FK" in bone.name and bone.location.z < 1): | |
102 | + bone.location.z = 1 | |
111 | 103 | bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame) |
112 | 104 | keyframe_id = bone.name + "_" + path |
113 | 105 | last_keyframe = last_keyframe_dict[keyframe_id] if keyframe_id in last_keyframe_dict else 0 |
... | ... | @@ -124,18 +116,22 @@ def resetIKPosition(isRightHand): |
124 | 116 | def resetBnMaoPosition(isRightHand): |
125 | 117 | armature.pose_library = bpy.data.actions[orient_direita_id if isRightHand else orient_esquerda_id] |
126 | 118 | bpy.ops.poselib.apply_pose(pose_index = 0) |
127 | - | |
128 | -def checkRotation(bone, positionFrame, last_keyframe): | |
119 | + | |
120 | +def get_bone_data_from_frame(bone, positionFrame, path): | |
129 | 121 | scene = bpy.context.scene |
130 | 122 | frame_current = scene.frame_current |
131 | 123 | scene.frame_set(positionFrame) |
132 | - boneRQ = bone.rotation_quaternion.to_euler() | |
124 | + result = copy.copy(bone.location) if path == 'location' else copy.copy(bone.rotation_quaternion) | |
133 | 125 | scene.frame_set(frame_current) |
126 | + return result | |
127 | + | |
128 | +def checkRotation(bone, positionFrame, last_keyframe): | |
129 | + boneRQ = get_bone_data_from_frame(bone, positionFrame, 'rotation_quaternion') | |
134 | 130 | isRightHand = ".R" in bone.name |
135 | 131 | resetBnMaoPosition(isRightHand) |
136 | 132 | valid_rotation = validate_rotation(bone, positionFrame, last_keyframe) |
137 | 133 | if (not valid_rotation): |
138 | - new_rotation = boneRQ.to_quaternion() * (-1) | |
134 | + new_rotation = boneRQ * (-1) | |
139 | 135 | bone.rotation_quaternion = new_rotation |
140 | 136 | bone.keyframe_insert(data_path = 'rotation_quaternion', index = -1, frame = positionFrame) |
141 | 137 | |
... | ... | @@ -168,11 +164,14 @@ def check_collision(objName, otherObjName, initFrame, endFrame): |
168 | 164 | frame_current = scene.frame_current |
169 | 165 | startFrame = initFrame + int(math.fabs((endFrame - initFrame)/2)) |
170 | 166 | collisionFrame = -1 |
167 | + | |
171 | 168 | for i in range(startFrame, endFrame + 1, 1): |
172 | 169 | scene.frame_set(i) |
173 | 170 | obj = scene.objects.get(objName) |
174 | 171 | otherObj = scene.objects.get(otherObjName) |
175 | 172 | if (bmesh_check_intersect_objects(obj, otherObj)): |
173 | + pyutil.log("bla") | |
174 | + pyutil.log(i) | |
176 | 175 | collisionFrame = i |
177 | 176 | break |
178 | 177 | scene.frame_set(frame_current) |
... | ... | @@ -215,27 +214,6 @@ def render_sign(user_id, nome_sinal = "sinal", frame_final = bpy.context.scene.f |
215 | 214 | bpy.ops.wm.quit_blender() |
216 | 215 | return |
217 | 216 | |
218 | -""" | |
219 | -def get_endFrame(json_input, hands_frames_retilineo): | |
220 | - endsFrame = [18] | |
221 | - if(json_input["rightHand"] != []): | |
222 | - if(json_input["rightHand"][0] == "circular"): | |
223 | - # Sugestao: json_input["rightHand"][4] eh o número de voltas/repeticoes? colocar numa variavel | |
224 | - endsFrame.append(int(json_input["rightHand"][4]*8*5+18)) | |
225 | - elif(json_input["rightHand"][0] == "semicircular"): | |
226 | - endsFrame.append(int(json_input["rightHand"][4]*5*5+18)) | |
227 | - elif(json_input["rightHand"][0] == "retilineo"): | |
228 | - endsFrame.append(max(hands_frames_retilineo)) | |
229 | - if(json_input["leftHand"] != []): | |
230 | - if(json_input["leftHand"][0] == "circular"): | |
231 | - endsFrame.append(int(json_input["leftHand"][4]*8*5+18)) | |
232 | - elif(json_input["leftHand"][0] == "semicircular"): | |
233 | - endsFrame.append(int(json_input["rightHand"][4]*5*5+18)) | |
234 | - elif(json_input["rightHand"][0] == "retilineo"): | |
235 | - endsFrame.append(max(hands_frames_retilineo)) | |
236 | - return(max(endsFrame)) | |
237 | -""" | |
238 | - | |
239 | 217 | def validate_rotation(bone, endFrame, startFrame = 0): |
240 | 218 | if (endFrame - startFrame == 1): |
241 | 219 | return True |
... | ... | @@ -250,12 +228,12 @@ def validate_rotation(bone, endFrame, startFrame = 0): |
250 | 228 | scene.frame_set(frame_current) |
251 | 229 | for k in range(1, len(rotFrames), 1): |
252 | 230 | for i in range(0, 3, 1): |
253 | - if (math.fabs(rotFrames[k][i] - rotFrames[k-1][i])) > math.pi/2: | |
231 | + if (math.fabs(rotFrames[k][i] - rotFrames[k-1][i])) > math.pi/3: | |
254 | 232 | return False |
255 | 233 | return True |
256 | 234 | |
257 | 235 | # Axis: "X", "Y" e "Z" |
258 | -def apply_rotation(bone, axis, currentFrame, endFrame, degree): | |
236 | +def apply_rotation(bone, axis, currentFrame, degree): | |
259 | 237 | new_rotation = bone.rotation_quaternion.to_euler() |
260 | 238 | new_rotation.rotate_axis(axis, math.radians(degree)) |
261 | 239 | new_rotation = new_rotation.to_quaternion() | ... | ... |