Commit 8425c440950ffd24937356e04b947a1ea0bb4830

Authored by André Araújo
1 parent 9b7b787e
Exists in master

Altera código para formato JSON mais recente

  1 +JSON_ALL = \
  2 +'{ \
  3 + "userId": "lavid", \
  4 + "sinal": "Modelo JSON", \
  5 + "interpolacao": "lento|normal|rapido", \
  6 + "movimentos": [ \
  7 + { \
  8 + "facial": { \
  9 + "expressao": 0..21, \
  10 + "velocidade": "lento|normal|rapido" \
  11 + }, \
  12 + "mao_esquerda": { \
  13 + "circular": { \
  14 + "plano": "frente-esquerda|frente-cima|esquerda-cima", \
  15 + "raio": "pequeno|medio|grande", \
  16 + "velocidade": "lento|normal|rapido", \
  17 + "lado_oposto": true|false, \
  18 + "sentido_inverso": true|false, \
  19 + "articulacao": 0..124, \
  20 + "configuracao": 0..60, \
  21 + "orientacao": 0..142 \
  22 + }, \
  23 + "semicircular": { \
  24 + "plano": "frente-esquerda|frente-cima|esquerda-cima", \
  25 + "raio": "pequeno|medio|grande", \
  26 + "lado_oposto": true|false, \
  27 + "sentido_inverso": true|false, \
  28 + "articulacao": 0..124, \
  29 + "configuracao": 0..60, \
  30 + "orientacao": 0..142 \
  31 + }, \
  32 + "contato": { \
  33 + "alisar": { \
  34 + "movimento_orientacao": "perpendicular|paralelo|diagonal-direita|diagonal-esquerda", \
  35 + "articulacao": 0..124, \
  36 + "configuracao": 0..60, \
  37 + "orientacao": 0..142 \
  38 + }, \
  39 + "cocar": { \
  40 + "articulacao": 0..124, \
  41 + "configuracao": 0..60, \
  42 + "orientacao": 0..142 \
  43 + }, \
  44 + "tocar": { \
  45 + "articulacao": 0..124, \
  46 + "configuracao": 0..60, \
  47 + "orientacao": 0..142 \
  48 + }, \
  49 + "riscar": { \
  50 + "articulacao": 0..124, \
  51 + "configuracao": 0..60, \
  52 + "orientacao": 0..142 \
  53 + } \
  54 + }, \
  55 + "espiral": { \
  56 + "plano": "frente-esquerda|frente-cima|esquerda-cima", \
  57 + "raio": "pequeno|medio|grande", \
  58 + "lado_oposto": true|false, \
  59 + "sentido_inverso": true|false, \
  60 + "articulacao": 0..124, \
  61 + "configuracao": 0..60, \
  62 + "orientacao": 0..142 \
  63 + }, \
  64 + "helicoidal": { \
  65 + "plano": "frente-esquerda|frente-cima|esquerda-cima", \
  66 + "raio": "pequeno|medio|grande", \
  67 + "lado_oposto": true|false, \
  68 + "sentido_inverso": true|false, \
  69 + "articulacao": 0..124, \
  70 + "configuracao": 0..60, \
  71 + "orientacao": 0..142 \
  72 + }, \
  73 + "pontual": { \
  74 + "articulacao": 0..124, \
  75 + "configuracao": 0..60, \
  76 + "orientacao": 0..142 \
  77 + }, \
  78 + "retilineo": { \
  79 + "velocidade": "lento|normal|rapido", \
  80 + "articulacao_inicial": 0..124, \
  81 + "articulacao_final": 0..124, \
  82 + "configuracao": 0..60, \
  83 + "orientacao": 0..142 \
  84 + }, \
  85 + "senoidal": { \
  86 + "direcao": "frente|esquerda|cima", \
  87 + "direcao_oposta": true|false, \
  88 + "eixo_fixo": "frente-tras|esquerda-direita|cima-baixo", \
  89 + "comprimento_onda": "pequeno|medio|grande", \
  90 + "articulacao": 0..124, \
  91 + "configuracao": 0..60, \
  92 + "orientacao": 0..142 \
  93 + } \
  94 + }, \
  95 + "mao_direita": { \
  96 + } \
  97 + } \
  98 + ] \
  99 +}'
  100 +
  101 +JSON = \
  102 +'{ \
  103 + "userId": "lavid", \
  104 + "sinal": "Modelo JSON 2", \
  105 + "ex_interpolacao": "lento|normal|rapido", \
  106 + "interpolacao": "normal", \
  107 + "movimentos": [ \
  108 + { \
  109 + "facial": { \
  110 + "expressao": 21, \
  111 + "velocidade": "lento|normal|rapido" \
  112 + }, \
  113 + "mao_esquerda": { \
  114 + "circular": { \
  115 + "plano": "esquerda-cima", \
  116 + "raio": "pequeno", \
  117 + "velocidade": "lento", \
  118 + "lado_oposto": false, \
  119 + "sentido_inverso": false, \
  120 + "articulacao": 124, \
  121 + "configuracao": 129, \
  122 + "orientacao": 142 \
  123 + } \
  124 + }, \
  125 + "mao_direita": { \
  126 + } \
  127 + } \
  128 + ] \
  129 +}'
  130 +
1 BLEND = avatar_cartoon_v2.74.blend 131 BLEND = avatar_cartoon_v2.74.blend
2 CONTROLLER = controller.py 132 CONTROLLER = controller.py
3 MAIN = libras.py 133 MAIN = libras.py
4 -# Circular: ['circular', x, x, Raio=1, Voltas=3 CfM=0, PAr=80, Ori=0]  
5 -JSON = '{"userId": 4, "rightHand": ["circular", "plano", "horario", 1, 3, 0, 80, 0], "leftHand":[], "facialExp": [1], "signName": "teste circular"}'  
6 -#JSON = '{"userId": 4, "rightHand": ["pontual", 55, 81, 21], "leftHand":[], "facialExp": [], "signName": "teste pontual"}'  
7 -#JSON = '{"userId": 4, "rightHand": ["pontual", 0, 80, 1], "leftHand":[], "facialExp": [1], "signName": "teste facial 1"}'  
8 -#JSON = '{"userId": 4, "rightHand": ["pontual", 0, 80, 2], "leftHand":[], "facialExp": [21], "signName": "teste facial 2"}'  
9 BLENDER = blender 134 BLENDER = blender
10 CACHE += "./__pycache__" 135 CACHE += "./__pycache__"
11 CACHE += "./users" 136 CACHE += "./users"
1 # -*- coding: UTF-8 -*- 1 # -*- coding: UTF-8 -*-
2 2
3 -from subprocess import call  
4 -from sys import argv  
5 -from os.path import abspath, dirname, join 3 +import subprocess
  4 +import sys
  5 +import os
6 6
7 -getcwd = dirname(abspath(__file__)) 7 +getcwd = os.path.dirname(os.path.abspath(__file__))
8 8
9 -from pyutil import printStackTrace 9 +import pyutil
  10 +
  11 +blend_path = os.path.join(getcwd, "avatar_cartoon_v2.74.blend")
  12 +main_path = os.path.join(getcwd, "libras.py")
10 13
11 -blend_path = join(getcwd, "avatar_cartoon_v2.74.blend")  
12 -main_path = join(getcwd, "libras.py")  
13 result = 0 14 result = 0
14 15
15 try: 16 try:
16 - # Caso seja necessário gravar logs do blender utilizar a linha de código abaixo  
17 - # result = call(['blender', '-b', blend_path, '-P', main_path, '--', argv[1]], stdout = open('bpy.log', 'w'))  
18 - result = call(['blender', '-b', blend_path, '-P', main_path, '--', argv[1]]) 17 + # para gravar logs do blender, usar codigo abaixo
  18 + # result = subprocess.call(['blender', '-b', blend_path, '-P', main_path, '--', sys.argv[1]], stdout = open('bpy.log', 'w'))
  19 + result = subprocess.call(['blender', '-b', blend_path, '-P', main_path, '--', sys.argv[1]])
19 except: 20 except:
20 - result = printStackTrace(__file__) 21 + result = pyutil.printStackTrace(__file__)
21 22
22 exit(result) 23 exit(result)
@@ -5,71 +5,111 @@ import bpy @@ -5,71 +5,111 @@ import bpy
5 5
6 # importa modulos do Python 6 # importa modulos do Python
7 import json 7 import json
8 -from sys import argv, path  
9 -from os.path import abspath, dirname 8 +import sys
  9 +import os
10 10
11 -# define o caminho absoluto do diretório deste arquivo  
12 -getcwd = dirname(abspath(__file__)) 11 +# define o caminho absoluto do diretorio deste arquivo
  12 +getcwd = os.path.dirname(os.path.abspath(__file__))
13 13
14 # insere o caminho do diretorio atual no path (permite o acesso aos modulos locais) 14 # insere o caminho do diretorio atual no path (permite o acesso aos modulos locais)
15 -path.insert(0, getcwd) 15 +sys.path.insert(0, getcwd)
16 16
17 # importa modulos locais 17 # importa modulos locais
18 -import util, moves  
19 -from pyutil import printStackTrace  
20 -  
21 -# tenta decodificar o argumento JSON recebido  
22 -try:  
23 - json_input = json.loads(argv[6])  
24 -except Exception:  
25 - printStackTrace(__file__)  
26 - exit(1)  
27 -  
28 -# ajusta as configurações de renderização  
29 -util.outconf()  
30 -  
31 -# Cria uma Action  
32 -act = bpy.context.scene.animation_data_create()  
33 -  
34 -# Função responsável por setar pose padrão  
35 -def poseDefault(positionFrames, collisionFlag = False): 18 +import util
  19 +import moves
  20 +import pyutil
  21 +
  22 +# intervalos de interpolacao dos keyframes
  23 +interpolation = {'inicial': 20, 'lento': 5, 'normal': 10, 'rapido': 15, 'final': 20}
  24 +
  25 +def insert_keyframe_pose_default(current_frame = 0, frame_jump = 0, pose_bones = bpy.context.object.pose.bones, types_keyframe = ['location', 'rotation_quaternion']):
  26 + for obj in (pose_bones):
  27 + obj.bone.select = True
  28 + for type_keyframe in types_keyframe:
  29 + obj.keyframe_insert(index = -1, frame = current_frame, group = obj.name, data_path = type_keyframe)
  30 + obj.bone.select = False
  31 + return current_frame + frame_jump
  32 +
  33 +def pose_default(current_frame = 0, frame_jump = 0, actions = bpy.data.actions):
  34 + result = 0
  35 + for action in actions:
  36 + if (action.use_fake_user):
  37 + bpy.context.object.pose_library = action
  38 + bpy.ops.poselib.apply_pose(pose_index = 0)
  39 + result = insert_keyframe_pose_default(current_frame, frame_jump)
  40 + return result
  41 +
  42 +def decode_circular_semicircular(js_movement, current_frame, frame_jump, is_right_hand, is_semicircular):
  43 + # const
  44 + obj_raio = {'pequeno': 0.5, 'normal': 1.0, 'grande': 1.5}
  45 + obj_periodo = {'lento': 55, 'normal': 45, 'rapido': 35}
  46 + # decodificar valores
  47 + raio = obj_raio[js_movement['raio']]
  48 + periodo = obj_periodo[js_movement['velocidade']]
  49 + # diminuir a velocidade
  50 + if (js_movement['velocidade'] == 'lento'):
  51 + periodo += 10
  52 + # aumentar a velocidade
  53 + elif (js_movement['velocidade'] == 'rapido'):
  54 + periodo -= 10
  55 + # definir eixos do movimento
  56 + if (js_movement['plano'] == 'frente-esquerda'):
  57 + x, y = 2, 0
  58 + elif (js_movement['plano'] == 'frente-cima'):
  59 + x, y = 2, 1
  60 + else:
  61 + x, y = 0, 1
  62 + # mao usada (direita/esquerda)
  63 + if (is_right_hand):
  64 + ik = bpy.context.object.pose.bones[1]
  65 + else:
  66 + ik = bpy.context.object.pose.bones[0]
  67 + current_frame = insert_keyframe_pose_default(current_frame, frame_jump, [ik], ['location'])
  68 + current_frame = moves.circular(ik, current_frame + frame_jump, raio, periodo, x, y, js_movement['lado_oposto'], js_movement['sentido_inverso'], is_semicircular)
  69 + return current_frame
  70 +
  71 +def decode_hand_mov(current_frame, frame_jump, js_mao, is_right_hand):
  72 + if (js_mao == {}):
  73 + return
  74 + movement_name = next(iter(js_mao.keys()))
  75 + print("Movimento: " + movement_name)
  76 + if (movement_name == 'circular'):
  77 + current_frame = decode_circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, False)
  78 + elif (movement_name == 'semicircular'):
  79 + current_frame = decode_circular_semicircular(js_mao[movement_name], current_frame, frame_jump, is_right_hand, True)
  80 + return current_frame + frame_jump
  81 +
  82 +# Funcao responsavel por setar pose padrao
  83 +def poseDefault(json_input, positionFrames, collisionFlag = False):
36 handDefaultParam = [0, 0, 0] 84 handDefaultParam = [0, 0, 0]
37 util.setPose(util.right_hand_actions, handDefaultParam, positionFrames, util.rightBonesConf, collisionFlag) 85 util.setPose(util.right_hand_actions, handDefaultParam, positionFrames, util.rightBonesConf, collisionFlag)
38 if(json_input["leftHand"] != []): 86 if(json_input["leftHand"] != []):
39 util.setPose(util.left_hand_actions, handDefaultParam, positionFrames, util.leftBonesConf, collisionFlag) 87 util.setPose(util.left_hand_actions, handDefaultParam, positionFrames, util.leftBonesConf, collisionFlag)
40 #setFaceConfiguration([0], positionFrames, util.faceBonesConf) 88 #setFaceConfiguration([0], positionFrames, util.faceBonesConf)
41 89
42 -# Função responsável por setar as configurações das mãos 90 +# Funcao responsavel por setar as configuracoes das maos
43 def setHandConfiguration(actions, handParam, positionFrames, bones): 91 def setHandConfiguration(actions, handParam, positionFrames, bones):
44 util.setPose(actions, handParam, positionFrames, bones) 92 util.setPose(actions, handParam, positionFrames, bones)
45 93
46 -# Função responsável por setar a configuração da face 94 +# Funcao responsavel por setar a configuracao da face
47 def setFaceConfiguration(handParam, positionFrames, bones): 95 def setFaceConfiguration(handParam, positionFrames, bones):
48 util.setPose(util.facial_expression_action, handParam, positionFrames, bones) 96 util.setPose(util.facial_expression_action, handParam, positionFrames, bones)
49 97
50 -# Sugestao: Alguma forma de uniformizar o calculo do endFrame (atualizado aqui e no movimento circular)  
51 -initialFrame, endFrame = 15, util.get_endFrame(json_input, util.hands_frames_retilineo)  
52 -  
53 -#------------------ Configurações------------------------------  
54 -  
55 -#Função que inicia a configuração de ambas as mãos  
56 -def configureHands():  
57 - # Array com valores dos campos que serão passados pelo JSON 98 +#Funcao que inicia a configuracao de ambas as maos
  99 +def configureHands(endFrame):
  100 + # Array com valores dos campos que serao passados pelo JSON
58 hands = ["rightHand", "leftHand"] 101 hands = ["rightHand", "leftHand"]
59 iks = ["ik_FK.R", "ik_FK.L"] 102 iks = ["ik_FK.R", "ik_FK.L"]
60 bones_ = [util.rightBonesConf, util.leftBonesConf] 103 bones_ = [util.rightBonesConf, util.leftBonesConf]
61 # Array com as actions FAKES que seram selecionadas no Blender para cada lado do corpo 104 # Array com as actions FAKES que seram selecionadas no Blender para cada lado do corpo
62 actions = [util.right_hand_actions, util.left_hand_actions] 105 actions = [util.right_hand_actions, util.left_hand_actions]
63 - global endFrame  
64 for i in range(len(hands)): 106 for i in range(len(hands)):
65 if(json_input[hands[i]] != []): 107 if(json_input[hands[i]] != []):
66 move = json_input[hands[i]][0] 108 move = json_input[hands[i]][0]
67 pose = util.armature.pose.bones[iks[i]] 109 pose = util.armature.pose.bones[iks[i]]
68 handParam = json_input[hands[i]][-3:] 110 handParam = json_input[hands[i]][-3:]
69 -  
70 if(move in ["pontual", "circular", "semicircular", "retilineo", "senoidal"]): 111 if(move in ["pontual", "circular", "semicircular", "retilineo", "senoidal"]):
71 setHandConfiguration(actions[i], handParam, util.hands_default_frames, bones_[i]) 112 setHandConfiguration(actions[i], handParam, util.hands_default_frames, bones_[i])
72 -  
73 if(move in ["circular", "semicircular"]): 113 if(move in ["circular", "semicircular"]):
74 orientation, direction, radius, laps = json_input[hands[i]][1:5] 114 orientation, direction, radius, laps = json_input[hands[i]][1:5]
75 #endFrame = moves.circular_or_semiCircular(pose, orientation, direction, radius, laps, 5) 115 #endFrame = moves.circular_or_semiCircular(pose, orientation, direction, radius, laps, 5)
@@ -84,20 +124,71 @@ def configureHands(): @@ -84,20 +124,71 @@ def configureHands():
84 elif(move == "contato"): 124 elif(move == "contato"):
85 endFrame = moves.contato(actions[i], json_input[hands[i]], bones_[i], pose) 125 endFrame = moves.contato(actions[i], json_input[hands[i]], bones_[i], pose)
86 126
87 -# Função que inicia a configuração da face  
88 -def configureFace():  
89 - global endFrame  
90 - if(json_input["facialExp"] != []):  
91 - setFaceConfiguration(json_input["facialExp"], [endFrame/4], util.faceBonesConf) 127 +# Funcao que inicia a configuracao da face
  128 +def setFacialExpr(a, b):
  129 + pass
  130 + #if(json_input["facialExp"] != []):
  131 + # setFaceConfiguration(json_input["facialExp"], [endFrame/4], util.faceBonesConf)
92 132
93 def main(): 133 def main():
94 - poseDefault([1])  
95 - configureHands()  
96 - configureFace()  
97 - poseDefault([endFrame + 15])  
98 - # Default Pose  
99 - print("Total frames: %.3i" % (endFrame))  
100 - util.render_sign(json_input["userId"], json_input["signName"], 1, endFrame + 25) 134 + util.configure_output()
  135 + bpy.context.scene.animation_data_create()
  136 +
  137 + try:
  138 + js_input = json.loads(sys.argv[6])
  139 + js_movimentos = js_input['movimentos']
  140 + frame_jump = interpolation[js_input['interpolacao']]
  141 +
  142 + endFrame = pose_default(0)
  143 + facial_frame = 0
  144 + mao_esquerda_frame = 0
  145 + mao_direita_frame = 0
  146 +
  147 + # setar pose padrao inicial em todos os bones ('location' e 'rotation_quaternion')
  148 + endFrame += pose_default(interpolation['inicial'])
  149 +
  150 + for i in range(0, len(js_movimentos)):
  151 +
  152 + js_facial = js_movimentos[i]['facial']
  153 +
  154 + if (js_facial != {}):
  155 + setFacialExpr(js_facial['expressao'], js_facial['velocidade'])
  156 + else:
  157 + pyutil.log("<Vazio> Expressao Facial %d" % (i))
  158 +
  159 + js_mao_esquerda = js_movimentos[i]['mao_esquerda']
  160 + if (js_mao_esquerda != {}):
  161 + mao_esquerda_frame += decode_hand_mov(mao_esquerda_frame, frame_jump, js_mao_esquerda, False)
  162 + else:
  163 + pyutil.log("<Vazio> mov %d Mao esquerda" % (i))
  164 +
  165 + js_mao_direita = js_movimentos[i]['mao_direita']
  166 + if (js_mao_direita != {}):
  167 + mao_direita_frame += decode_hand_mov(mao_direita_frame, frame_jump, js_mao_direita, True)
  168 + else:
  169 + pyutil.log("<Vazio> mov %d Mao direita" % (i))
  170 +
  171 + endFrame = max(facial_frame, mao_esquerda_frame, mao_direita_frame)
  172 + endFrame += frame_jump
  173 +
  174 + # setar pose padrao final em todos os bones (location e rotation)
  175 + #endFrame += pose_default(endFrame + interpolation['final'])
  176 + endFrame = insert_keyframe_pose_default(endFrame, frame_jump)
  177 + endFrame += interpolation['final']
  178 +
  179 + # Sugestao: Alguma forma de uniformizar o calculo do endFrame (atualizado aqui e no movimento circular)
  180 + #initialFrame = 15
  181 + #endFrame = util.get_endFrame(js_input, util.hands_frames_retilineo)
  182 + #poseDefault([1])
  183 + #configureHands(endFrame)
  184 + #configureFace(endFrame)
  185 + #poseDefault(js_input, [endFrame + 15])
  186 +
  187 + util.render_sign(js_input["userId"], js_input["sinal"], endFrame)
  188 +
  189 + except:
  190 + pyutil.printStackTrace(__file__)
  191 + raise
101 192
102 if __name__ == "__main__": 193 if __name__ == "__main__":
103 main() 194 main()
@@ -159,14 +159,14 @@ def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensi @@ -159,14 +159,14 @@ def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensi
159 # raio: "grande" raio = 1.5, velocidade: "normal" periodo = 55 159 # raio: "grande" raio = 1.5, velocidade: "normal" periodo = 55
160 # raio: "grande" raio = 1.5, velocidade: "lento" periodo = 65 160 # raio: "grande" raio = 1.5, velocidade: "lento" periodo = 65
161 # @param obj: (objeto) bone, mesh, e.g. 161 # @param obj: (objeto) bone, mesh, e.g.
162 -# @param itFrame: (int) posicao onde o primeiro keyframe vai ser inserido 162 +# @param frame_atual: (int) posicao onde o primeiro keyframe vai ser inserido
163 # @param raio: (int) raio da circunferencia 163 # @param raio: (int) raio da circunferencia
164 # @param periodo: (int) quantidade de keyframes necessarios para completar uma volta completa 164 # @param periodo: (int) quantidade de keyframes necessarios para completar uma volta completa
165 # @param x: (int) in [0,1,2] define qual eixo vai variar no seno (0 = eixo X, 1 = eixo Y, 2 = eixo Z) 165 # @param x: (int) in [0,1,2] define qual eixo vai variar no seno (0 = eixo X, 1 = eixo Y, 2 = eixo Z)
166 # @param y: (int) in [0,1,2] define qual eixo vai variar no cosseno (0 = eixo X, 1 = eixo Y, 2 = eixo Z) 166 # @param y: (int) in [0,1,2] define qual eixo vai variar no cosseno (0 = eixo X, 1 = eixo Y, 2 = eixo Z)
167 -# @param ladoOposto: (bool) inverte o lado da primeira posicao (pode ser util em alguns casos para espelhar)  
168 -# @param inverterDirecao (bool) inverte o sentido do movimento (horario para anti-horario)  
169 -def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inverterDirecao = False): 167 +# @param usar_lado_oposto: (bool) inverte o lado da primeira posicao (pode ser util em alguns casos para espelhar)
  168 +# @param usar_sentido_oposto (bool) inverte o sentido do movimento (horario para anti-horario)
  169 +def circular(obj, frame_atual, raio, periodo, x = 0, y = 1, usar_lado_oposto = False, usar_sentido_oposto = False, meia_volta = False):
170 # limita inferiormente 170 # limita inferiormente
171 if (periodo < 16): 171 if (periodo < 16):
172 periodo = 16 172 periodo = 16
@@ -174,7 +174,7 @@ def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inve @@ -174,7 +174,7 @@ def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inve
174 elif (periodo > 360): 174 elif (periodo > 360):
175 periodo = 360 175 periodo = 360
176 # muda lado inicial 176 # muda lado inicial
177 - if (ladoOposto): 177 + if (usar_lado_oposto):
178 k = round(periodo / 2) 178 k = round(periodo / 2)
179 else: 179 else:
180 k = 0 180 k = 0
@@ -182,17 +182,22 @@ def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inve @@ -182,17 +182,22 @@ def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inve
182 x %= 3 182 x %= 3
183 y %= 3 183 y %= 3
184 # inverte direcao do movimento 184 # inverte direcao do movimento
185 - if (inverterDirecao): 185 + if (usar_sentido_oposto):
186 tmp = x 186 tmp = x
187 x = y 187 x = y
188 y = tmp 188 y = tmp
189 # copia posicao inicial para transladar 189 # copia posicao inicial para transladar
190 loc = [obj.location[0], obj.location[1], obj.location[2]] 190 loc = [obj.location[0], obj.location[1], obj.location[2]]
191 - for i in range(k, periodo + k):  
192 - # pequena otimizacao para reduzir a quantidade de keyframes  
193 - if (itFrame % 2 == 0): 191 + # semi-circular
  192 + limite = periodo + k
  193 + if (meia_volta):
  194 + limite = round(limite / 2)
  195 + for i in range(k, limite + 1):
  196 + # reduz a quantidade de keyframes
  197 + if (frame_atual % 2 == 0):
194 obj.location[x] = loc[x] + (raio * math.cos(i / periodo * (2 * math.pi))) 198 obj.location[x] = loc[x] + (raio * math.cos(i / periodo * (2 * math.pi)))
195 obj.location[y] = loc[y] + (raio * math.sin(i / periodo * (2 * math.pi))) 199 obj.location[y] = loc[y] + (raio * math.sin(i / periodo * (2 * math.pi)))
196 - util.keyframe_insert(obj, 'location', itFrame)  
197 - itFrame += 1 200 + util.keyframe_insert(obj, 'location', frame_atual)
  201 + frame_atual += 1
  202 + util.keyframe_insert(obj, 'location', frame_atual)
198 return periodo - 1 203 return periodo - 1
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 "circular": { 13 "circular": {
14 "plano": "frente-esquerda|frente-cima|esquerda-cima", 14 "plano": "frente-esquerda|frente-cima|esquerda-cima",
15 "raio": "pequeno|medio|grande", 15 "raio": "pequeno|medio|grande",
  16 + "velocidade": "lento|normal|rapido",
16 "lado_oposto": false, 17 "lado_oposto": false,
17 "sentido_inverso": false, 18 "sentido_inverso": false,
18 "articulacao": 124, 19 "articulacao": 124,
@@ -22,6 +23,7 @@ @@ -22,6 +23,7 @@
22 "semicircular": { 23 "semicircular": {
23 "plano": "frente-esquerda|frente-cima|esquerda-cima", 24 "plano": "frente-esquerda|frente-cima|esquerda-cima",
24 "raio": "pequeno|medio|grande", 25 "raio": "pequeno|medio|grande",
  26 + "velocidade": "lento|normal|rapido",
25 "lado_oposto": false, 27 "lado_oposto": false,
26 "sentido_inverso": false, 28 "sentido_inverso": false,
27 "articulacao": 124, 29 "articulacao": 124,
@@ -82,8 +84,8 @@ @@ -82,8 +84,8 @@
82 "orientacao": 142 84 "orientacao": 142
83 }, 85 },
84 "retilineo": { 86 "retilineo": {
85 - "articulacao_inicial_id": 124,  
86 - "articulacao_final_id": 124, 87 + "articulacao_inicial": 124,
  88 + "articulacao_final": 124,
87 "configuracao": 129, 89 "configuracao": 129,
88 "orientacao": 142 90 "orientacao": 142
89 }, 91 },
@@ -2,6 +2,9 @@ @@ -2,6 +2,9 @@
2 2
3 import bpy 3 import bpy
4 import math 4 import math
  5 +import pyutil
  6 +import os
  7 +import sys
5 from bmesh_collision import bmesh_check_intersect_objects 8 from bmesh_collision import bmesh_check_intersect_objects
6 9
7 armature = bpy.context.scene.objects.get('Armature.001') 10 armature = bpy.context.scene.objects.get('Armature.001')
@@ -47,12 +50,26 @@ left_hand_actions = [conf_esquerda_id, pa_esquerda_id, orient_esquerda_id] @@ -47,12 +50,26 @@ left_hand_actions = [conf_esquerda_id, pa_esquerda_id, orient_esquerda_id]
47 50
48 last_keyframe_dict = {} 51 last_keyframe_dict = {}
49 52
  53 +def select_bones(bones = None):
  54 + if (isinstance(bones, int)):
  55 + bpy.context.object.pose.bones[bones].bone.select = True
  56 + else:
  57 + for bone in bones:
  58 + bpy.context.object.pose.bones[bone].bone.select = True
  59 +
  60 +def deselect_bones(bones = None):
  61 + if (isinstance(bones, int)):
  62 + bpy.context.object.pose.bones[bones].bone.select = False
  63 + else:
  64 + for bone in bones:
  65 + bpy.context.object.pose.bones[bone].bone.select = False
  66 +
50 # Função responsável por selecionar as pose-libs e setar os frames 67 # Função responsável por selecionar as pose-libs e setar os frames
51 def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True): 68 def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True):
52 bpy.ops.object.mode_set(mode = 'OBJECT') 69 bpy.ops.object.mode_set(mode = 'OBJECT')
53 bpy.ops.object.select_all(action="DESELECT") 70 bpy.ops.object.select_all(action="DESELECT")
54 bpy.ops.object.mode_set(mode = 'POSE') 71 bpy.ops.object.mode_set(mode = 'POSE')
55 - 72 +
56 for x in range(len(positionFrames)): 73 for x in range(len(positionFrames)):
57 for l in range(len(actions)): 74 for l in range(len(actions)):
58 action = actions[l] 75 action = actions[l]
@@ -63,20 +80,20 @@ def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True) @@ -63,20 +80,20 @@ def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True)
63 validHandConf = action in [conf_direita_id, conf_esquerda_id] and "BnDedo" in bone.name 80 validHandConf = action in [conf_direita_id, conf_esquerda_id] and "BnDedo" in bone.name
64 validPA = action in [pa_direita_id, pa_esquerda_id] and "ik_FK" in bone.name or "BnPolyV" in bone.name 81 validPA = action in [pa_direita_id, pa_esquerda_id] and "ik_FK" in bone.name or "BnPolyV" in bone.name
65 validO = action in [orient_direita_id, orient_esquerda_id] and "BnMao" in bone.name 82 validO = action in [orient_direita_id, orient_esquerda_id] and "BnMao" in bone.name
66 - 83 +
67 if (validHandConf or validPA or validO): 84 if (validHandConf or validPA or validO):
68 keyframe_insert(bone, 'location', positionFrames[x], collisionFlag and validPA, validO) 85 keyframe_insert(bone, 'location', positionFrames[x], collisionFlag and validPA, validO)
69 keyframe_insert(bone, 'rotation_quaternion', positionFrames[x], collisionFlag and validPA, validO) 86 keyframe_insert(bone, 'rotation_quaternion', positionFrames[x], collisionFlag and validPA, validO)
70 87
71 -def keyframe_insert(bone, path, positionFrame, collisionFlag = True, rotationFlag = False): 88 +def keyframe_insert(bone, path, positionFrame, collisionFlag = True, rotationFlag = False):
72 bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame) 89 bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame)
73 keyframe_id = bone.name + "_" + path 90 keyframe_id = bone.name + "_" + path
74 last_keyframe = last_keyframe_dict[keyframe_id] if keyframe_id in last_keyframe_dict else 0 91 last_keyframe = last_keyframe_dict[keyframe_id] if keyframe_id in last_keyframe_dict else 0
75 last_keyframe_dict[keyframe_id] = positionFrame 92 last_keyframe_dict[keyframe_id] = positionFrame
76 - 93 +
77 if (rotationFlag and path == "rotation_quaternion"): 94 if (rotationFlag and path == "rotation_quaternion"):
78 checkRotation(bone, positionFrame, last_keyframe) 95 checkRotation(bone, positionFrame, last_keyframe)
79 - 96 +
80 if (collisionFlag): 97 if (collisionFlag):
81 checkCollision(bone, path, positionFrame, last_keyframe) 98 checkCollision(bone, path, positionFrame, last_keyframe)
82 99
@@ -95,9 +112,9 @@ def checkRotation(bone, positionFrame, last_keyframe): @@ -95,9 +112,9 @@ def checkRotation(bone, positionFrame, last_keyframe):
95 boneRQ = bone.rotation_quaternion.to_euler() 112 boneRQ = bone.rotation_quaternion.to_euler()
96 scene.frame_set(frame_current) 113 scene.frame_set(frame_current)
97 isRightHand = ".R" in bone.name 114 isRightHand = ".R" in bone.name
98 - resetBnMaoPosition(isRightHand) 115 + resetBnMaoPosition(isRightHand)
99 valid_rotation = validate_rotation(bone, positionFrame, last_keyframe) 116 valid_rotation = validate_rotation(bone, positionFrame, last_keyframe)
100 - 117 +
101 if (not valid_rotation): 118 if (not valid_rotation):
102 new_rotation = boneRQ.to_quaternion() * (-1) 119 new_rotation = boneRQ.to_quaternion() * (-1)
103 bone.rotation_quaternion = new_rotation 120 bone.rotation_quaternion = new_rotation
@@ -106,7 +123,7 @@ def checkRotation(bone, positionFrame, last_keyframe): @@ -106,7 +123,7 @@ def checkRotation(bone, positionFrame, last_keyframe):
106 def checkCollision(bone, path, positionFrame, last_keyframe): 123 def checkCollision(bone, path, positionFrame, last_keyframe):
107 if (last_keyframe == positionFrame): 124 if (last_keyframe == positionFrame):
108 return 125 return
109 - 126 +
110 isRightHand = ".R" in bone.name 127 isRightHand = ".R" in bone.name
111 resetIKPosition(isRightHand) 128 resetIKPosition(isRightHand)
112 handCollisionFrame = check_hand_collision(last_keyframe, positionFrame) 129 handCollisionFrame = check_hand_collision(last_keyframe, positionFrame)
@@ -114,7 +131,7 @@ def checkCollision(bone, path, positionFrame, last_keyframe): @@ -114,7 +131,7 @@ def checkCollision(bone, path, positionFrame, last_keyframe):
114 if (handCollisionFrame != -1): 131 if (handCollisionFrame != -1):
115 handle_collision(bone, path, positionFrame, handCollisionFrame) 132 handle_collision(bone, path, positionFrame, handCollisionFrame)
116 return 133 return
117 - 134 +
118 bodyCollisionFrame = check_body_collision(isRightHand, last_keyframe, positionFrame) 135 bodyCollisionFrame = check_body_collision(isRightHand, last_keyframe, positionFrame)
119 if (bodyCollisionFrame != -1): 136 if (bodyCollisionFrame != -1):
120 handle_collision(bone, path, positionFrame, bodyCollisionFrame) 137 handle_collision(bone, path, positionFrame, bodyCollisionFrame)
@@ -124,7 +141,7 @@ def handle_collision(bone, path, positionFrame, collisionFrame, rollbackFrames = @@ -124,7 +141,7 @@ def handle_collision(bone, path, positionFrame, collisionFrame, rollbackFrames =
124 scene = bpy.context.scene 141 scene = bpy.context.scene
125 frame_current = scene.frame_current 142 frame_current = scene.frame_current
126 scene.frame_set(collisionFrame - rollbackFrames) 143 scene.frame_set(collisionFrame - rollbackFrames)
127 - bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame) 144 + bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame)
128 bpy.context.scene.frame_set(frame_current) 145 bpy.context.scene.frame_set(frame_current)
129 146
130 def check_hand_collision(initFrame, endFrame): 147 def check_hand_collision(initFrame, endFrame):
@@ -133,7 +150,7 @@ def check_hand_collision(initFrame, endFrame): @@ -133,7 +150,7 @@ def check_hand_collision(initFrame, endFrame):
133 def check_collision(objName, otherObjName, initFrame, endFrame): 150 def check_collision(objName, otherObjName, initFrame, endFrame):
134 scene = bpy.context.scene 151 scene = bpy.context.scene
135 frame_current = scene.frame_current 152 frame_current = scene.frame_current
136 - startFrame = initFrame + int(math.fabs((endFrame - initFrame)/2)) 153 + startFrame = initFrame + int(math.fabs((endFrame - initFrame)/2))
137 collisionFrame = -1 154 collisionFrame = -1
138 for i in range(startFrame, endFrame + 1, 1): 155 for i in range(startFrame, endFrame + 1, 1):
139 scene.frame_set(i) 156 scene.frame_set(i)
@@ -153,24 +170,23 @@ def check_body_collision(isRightHand, initFrame, endFrame): @@ -153,24 +170,23 @@ def check_body_collision(isRightHand, initFrame, endFrame):
153 return result 170 return result
154 171
155 # Função que limpa todos os keyframes e define a quantidade de frames 172 # Função que limpa todos os keyframes e define a quantidade de frames
156 -def erase_all_keyframes(): 173 +def limpar_keyframes():
  174 + bpy.context.active_object.animation_data_clear()
157 for i in bpy.data.objects: 175 for i in bpy.data.objects:
158 i.animation_data_clear() 176 i.animation_data_clear()
159 - bpy.context.scene.frame_start = 1  
160 - bpy.context.scene.frame_current = bpy.context.scene.frame_start  
161 - bpy.context.scene.frame_end = bpy.context.scene.frame_start  
162 177
163 # Função que define as configurações de saida 178 # Função que define as configurações de saida
164 -def outconf():  
165 - erase_all_keyframes() 179 +def configure_output():
  180 + limpar_keyframes()
  181 + bpy.context.scene.frame_start = 0
  182 + bpy.context.scene.frame_current = bpy.context.scene.frame_start
  183 + bpy.context.scene.frame_end = bpy.context.scene.frame_start
166 bpy.context.scene.render.resolution_x = 640 184 bpy.context.scene.render.resolution_x = 640
167 bpy.context.scene.render.resolution_y = 480 185 bpy.context.scene.render.resolution_y = 480
168 bpy.context.scene.render.resolution_percentage = 100 186 bpy.context.scene.render.resolution_percentage = 100
169 bpy.context.scene.render.image_settings.file_format = 'H264' 187 bpy.context.scene.render.image_settings.file_format = 'H264'
170 bpy.context.scene.render.ffmpeg.format = 'MPEG4' 188 bpy.context.scene.render.ffmpeg.format = 'MPEG4'
171 bpy.context.scene.render.ffmpeg.codec = 'H264' 189 bpy.context.scene.render.ffmpeg.codec = 'H264'
172 - # bpy.context.scene.render.filepath = '/tmp/'  
173 -  
174 # Otimização da renderização 190 # Otimização da renderização
175 bpy.context.scene.render.use_shadows = False 191 bpy.context.scene.render.use_shadows = False
176 bpy.context.scene.render.use_raytrace = False 192 bpy.context.scene.render.use_raytrace = False
@@ -180,21 +196,16 @@ def outconf(): @@ -180,21 +196,16 @@ def outconf():
180 bpy.context.scene.render.tile_x = 320 196 bpy.context.scene.render.tile_x = 320
181 bpy.context.scene.render.tile_y = 240 197 bpy.context.scene.render.tile_y = 240
182 198
183 -def render_sign(userId, signName, beginFrame, endFrame):  
184 - from sys import argv, path  
185 - from os.path import abspath, dirname  
186 - from pyutil import log, file_rename  
187 - getcwd = dirname(abspath(__file__))  
188 - bpy.context.scene.render.filepath = getcwd + "/users/"+ str(userId)+ "/"+ signName + "_"  
189 - bpy.context.scene.frame_start = beginFrame  
190 - bpy.context.scene.frame_end = endFrame  
191 - outFilename = ("%s%0.4i-%0.4i.mp4" % (bpy.context.scene.render.filepath, bpy.context.scene.frame_start, bpy.context.scene.frame_end))  
192 - log("All frames: %i" % (endFrame)) 199 +def render_sign(user_id, nome_sinal = "sinal", frame_final = bpy.context.scene.frame_end):
  200 + getcwd = os.path.dirname(os.path.abspath(__file__))
  201 + bpy.context.scene.render.filepath = getcwd + "/users/" + str(user_id) + "/"+ nome_sinal + "_"
  202 + bpy.context.scene.frame_end = frame_final
  203 + pyutil.log("Gerando Video... Frames: %i" % (frame_final))
193 bpy.ops.render.render(animation = True, write_still = False, layer = "", scene = "") 204 bpy.ops.render.render(animation = True, write_still = False, layer = "", scene = "")
194 - file_rename(outFilename) 205 + pyutil.file_rename("%s%0.4i-%0.4i.mp4" % (bpy.context.scene.render.filepath, bpy.context.scene.frame_start, bpy.context.scene.frame_end))
195 bpy.ops.wm.quit_blender() 206 bpy.ops.wm.quit_blender()
196 207
197 -# Função que recupera o frame final do movimento 208 +# descontinuada: get_endFrame
198 def get_endFrame(json_input, hands_frames_retilineo): 209 def get_endFrame(json_input, hands_frames_retilineo):
199 endsFrame = [18] 210 endsFrame = [18]
200 if(json_input["rightHand"] != []): 211 if(json_input["rightHand"] != []):
@@ -217,19 +228,19 @@ def get_endFrame(json_input, hands_frames_retilineo): @@ -217,19 +228,19 @@ def get_endFrame(json_input, hands_frames_retilineo):
217 def validate_rotation(bone, endFrame, startFrame = 0): 228 def validate_rotation(bone, endFrame, startFrame = 0):
218 if (endFrame - startFrame == 1): 229 if (endFrame - startFrame == 1):
219 return True 230 return True
220 - 231 +
221 rotFrames = [[]] 232 rotFrames = [[]]
222 scene = bpy.context.scene 233 scene = bpy.context.scene
223 frame_current = scene.frame_current 234 frame_current = scene.frame_current
224 - 235 +
225 for i in range(startFrame+1, endFrame+1, 1): 236 for i in range(startFrame+1, endFrame+1, 1):
226 scene.frame_set(i) 237 scene.frame_set(i)
227 rotFrames[-1] = bone.rotation_quaternion.to_euler() 238 rotFrames[-1] = bone.rotation_quaternion.to_euler()
228 rotFrames.append([]) 239 rotFrames.append([])
229 - 240 +
230 rotFrames.remove([]) 241 rotFrames.remove([])
231 scene.frame_set(frame_current) 242 scene.frame_set(frame_current)
232 - 243 +
233 for k in range(1, len(rotFrames), 1): 244 for k in range(1, len(rotFrames), 1):
234 for i in range(0, 3, 1): 245 for i in range(0, 3, 1):
235 if (math.fabs(rotFrames[k][i] - rotFrames[k-1][i])) > math.pi/2: 246 if (math.fabs(rotFrames[k][i] - rotFrames[k-1][i])) > math.pi/2:
@@ -241,6 +252,6 @@ def apply_rotation(bone, axis, currentFrame, endFrame, degree): @@ -241,6 +252,6 @@ def apply_rotation(bone, axis, currentFrame, endFrame, degree):
241 new_rotation = bone.rotation_quaternion.to_euler() 252 new_rotation = bone.rotation_quaternion.to_euler()
242 new_rotation.rotate_axis(axis, math.radians(degree)) 253 new_rotation.rotate_axis(axis, math.radians(degree))
243 new_rotation = new_rotation.to_quaternion() 254 new_rotation = new_rotation.to_quaternion()
244 - 255 +
245 bone.rotation_quaternion = new_rotation 256 bone.rotation_quaternion = new_rotation
246 keyframe_insert(bone, 'rotation_quaternion', currentFrame, False, True) 257 keyframe_insert(bone, 'rotation_quaternion', currentFrame, False, True)
247 \ No newline at end of file 258 \ No newline at end of file