Commit 8425c440950ffd24937356e04b947a1ea0bb4830

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

Altera código para formato JSON mais recente

Makefile
  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 131 BLEND = avatar_cartoon_v2.74.blend
2 132 CONTROLLER = controller.py
3 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 134 BLENDER = blender
10 135 CACHE += "./__pycache__"
11 136 CACHE += "./users"
... ...
controller.py
1 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 14 result = 0
14 15  
15 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 20 except:
20   - result = printStackTrace(__file__)
  21 + result = pyutil.printStackTrace(__file__)
21 22  
22 23 exit(result)
... ...
libras.py
... ... @@ -5,71 +5,111 @@ import bpy
5 5  
6 6 # importa modulos do Python
7 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 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 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 84 handDefaultParam = [0, 0, 0]
37 85 util.setPose(util.right_hand_actions, handDefaultParam, positionFrames, util.rightBonesConf, collisionFlag)
38 86 if(json_input["leftHand"] != []):
39 87 util.setPose(util.left_hand_actions, handDefaultParam, positionFrames, util.leftBonesConf, collisionFlag)
40 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 91 def setHandConfiguration(actions, handParam, positionFrames, bones):
44 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 95 def setFaceConfiguration(handParam, positionFrames, bones):
48 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 101 hands = ["rightHand", "leftHand"]
59 102 iks = ["ik_FK.R", "ik_FK.L"]
60 103 bones_ = [util.rightBonesConf, util.leftBonesConf]
61 104 # Array com as actions FAKES que seram selecionadas no Blender para cada lado do corpo
62 105 actions = [util.right_hand_actions, util.left_hand_actions]
63   - global endFrame
64 106 for i in range(len(hands)):
65 107 if(json_input[hands[i]] != []):
66 108 move = json_input[hands[i]][0]
67 109 pose = util.armature.pose.bones[iks[i]]
68 110 handParam = json_input[hands[i]][-3:]
69   -
70 111 if(move in ["pontual", "circular", "semicircular", "retilineo", "senoidal"]):
71 112 setHandConfiguration(actions[i], handParam, util.hands_default_frames, bones_[i])
72   -
73 113 if(move in ["circular", "semicircular"]):
74 114 orientation, direction, radius, laps = json_input[hands[i]][1:5]
75 115 #endFrame = moves.circular_or_semiCircular(pose, orientation, direction, radius, laps, 5)
... ... @@ -84,20 +124,71 @@ def configureHands():
84 124 elif(move == "contato"):
85 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 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 193 if __name__ == "__main__":
103 194 main()
... ...
moves.py
... ... @@ -159,14 +159,14 @@ def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensi
159 159 # raio: "grande" raio = 1.5, velocidade: "normal" periodo = 55
160 160 # raio: "grande" raio = 1.5, velocidade: "lento" periodo = 65
161 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 163 # @param raio: (int) raio da circunferencia
164 164 # @param periodo: (int) quantidade de keyframes necessarios para completar uma volta completa
165 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 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 170 # limita inferiormente
171 171 if (periodo < 16):
172 172 periodo = 16
... ... @@ -174,7 +174,7 @@ def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inve
174 174 elif (periodo > 360):
175 175 periodo = 360
176 176 # muda lado inicial
177   - if (ladoOposto):
  177 + if (usar_lado_oposto):
178 178 k = round(periodo / 2)
179 179 else:
180 180 k = 0
... ... @@ -182,17 +182,22 @@ def circular(obj, itFrame, raio, periodo, x = 0, y = 1, ladoOposto = False, inve
182 182 x %= 3
183 183 y %= 3
184 184 # inverte direcao do movimento
185   - if (inverterDirecao):
  185 + if (usar_sentido_oposto):
186 186 tmp = x
187 187 x = y
188 188 y = tmp
189 189 # copia posicao inicial para transladar
190 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 198 obj.location[x] = loc[x] + (raio * math.cos(i / periodo * (2 * math.pi)))
195 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 203 return periodo - 1
... ...
param.json
... ... @@ -13,6 +13,7 @@
13 13 "circular": {
14 14 "plano": "frente-esquerda|frente-cima|esquerda-cima",
15 15 "raio": "pequeno|medio|grande",
  16 + "velocidade": "lento|normal|rapido",
16 17 "lado_oposto": false,
17 18 "sentido_inverso": false,
18 19 "articulacao": 124,
... ... @@ -22,6 +23,7 @@
22 23 "semicircular": {
23 24 "plano": "frente-esquerda|frente-cima|esquerda-cima",
24 25 "raio": "pequeno|medio|grande",
  26 + "velocidade": "lento|normal|rapido",
25 27 "lado_oposto": false,
26 28 "sentido_inverso": false,
27 29 "articulacao": 124,
... ... @@ -82,8 +84,8 @@
82 84 "orientacao": 142
83 85 },
84 86 "retilineo": {
85   - "articulacao_inicial_id": 124,
86   - "articulacao_final_id": 124,
  87 + "articulacao_inicial": 124,
  88 + "articulacao_final": 124,
87 89 "configuracao": 129,
88 90 "orientacao": 142
89 91 },
... ...
util.py
... ... @@ -2,6 +2,9 @@
2 2  
3 3 import bpy
4 4 import math
  5 +import pyutil
  6 +import os
  7 +import sys
5 8 from bmesh_collision import bmesh_check_intersect_objects
6 9  
7 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 50  
48 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 67 # Função responsável por selecionar as pose-libs e setar os frames
51 68 def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True):
52 69 bpy.ops.object.mode_set(mode = 'OBJECT')
53 70 bpy.ops.object.select_all(action="DESELECT")
54 71 bpy.ops.object.mode_set(mode = 'POSE')
55   -
  72 +
56 73 for x in range(len(positionFrames)):
57 74 for l in range(len(actions)):
58 75 action = actions[l]
... ... @@ -63,20 +80,20 @@ def setPose(actions, parametesConf, positionFrames, bones, collisionFlag = True)
63 80 validHandConf = action in [conf_direita_id, conf_esquerda_id] and "BnDedo" in bone.name
64 81 validPA = action in [pa_direita_id, pa_esquerda_id] and "ik_FK" in bone.name or "BnPolyV" in bone.name
65 82 validO = action in [orient_direita_id, orient_esquerda_id] and "BnMao" in bone.name
66   -
  83 +
67 84 if (validHandConf or validPA or validO):
68 85 keyframe_insert(bone, 'location', positionFrames[x], collisionFlag and validPA, validO)
69 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 89 bone.keyframe_insert(data_path = path, index = -1, frame = positionFrame)
73 90 keyframe_id = bone.name + "_" + path
74 91 last_keyframe = last_keyframe_dict[keyframe_id] if keyframe_id in last_keyframe_dict else 0
75 92 last_keyframe_dict[keyframe_id] = positionFrame
76   -
  93 +
77 94 if (rotationFlag and path == "rotation_quaternion"):
78 95 checkRotation(bone, positionFrame, last_keyframe)
79   -
  96 +
80 97 if (collisionFlag):
81 98 checkCollision(bone, path, positionFrame, last_keyframe)
82 99  
... ... @@ -95,9 +112,9 @@ def checkRotation(bone, positionFrame, last_keyframe):
95 112 boneRQ = bone.rotation_quaternion.to_euler()
96 113 scene.frame_set(frame_current)
97 114 isRightHand = ".R" in bone.name
98   - resetBnMaoPosition(isRightHand)
  115 + resetBnMaoPosition(isRightHand)
99 116 valid_rotation = validate_rotation(bone, positionFrame, last_keyframe)
100   -
  117 +
101 118 if (not valid_rotation):
102 119 new_rotation = boneRQ.to_quaternion() * (-1)
103 120 bone.rotation_quaternion = new_rotation
... ... @@ -106,7 +123,7 @@ def checkRotation(bone, positionFrame, last_keyframe):
106 123 def checkCollision(bone, path, positionFrame, last_keyframe):
107 124 if (last_keyframe == positionFrame):
108 125 return
109   -
  126 +
110 127 isRightHand = ".R" in bone.name
111 128 resetIKPosition(isRightHand)
112 129 handCollisionFrame = check_hand_collision(last_keyframe, positionFrame)
... ... @@ -114,7 +131,7 @@ def checkCollision(bone, path, positionFrame, last_keyframe):
114 131 if (handCollisionFrame != -1):
115 132 handle_collision(bone, path, positionFrame, handCollisionFrame)
116 133 return
117   -
  134 +
118 135 bodyCollisionFrame = check_body_collision(isRightHand, last_keyframe, positionFrame)
119 136 if (bodyCollisionFrame != -1):
120 137 handle_collision(bone, path, positionFrame, bodyCollisionFrame)
... ... @@ -124,7 +141,7 @@ def handle_collision(bone, path, positionFrame, collisionFrame, rollbackFrames =
124 141 scene = bpy.context.scene
125 142 frame_current = scene.frame_current
126 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 145 bpy.context.scene.frame_set(frame_current)
129 146  
130 147 def check_hand_collision(initFrame, endFrame):
... ... @@ -133,7 +150,7 @@ def check_hand_collision(initFrame, endFrame):
133 150 def check_collision(objName, otherObjName, initFrame, endFrame):
134 151 scene = bpy.context.scene
135 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 154 collisionFrame = -1
138 155 for i in range(startFrame, endFrame + 1, 1):
139 156 scene.frame_set(i)
... ... @@ -153,24 +170,23 @@ def check_body_collision(isRightHand, initFrame, endFrame):
153 170 return result
154 171  
155 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 175 for i in bpy.data.objects:
158 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 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 184 bpy.context.scene.render.resolution_x = 640
167 185 bpy.context.scene.render.resolution_y = 480
168 186 bpy.context.scene.render.resolution_percentage = 100
169 187 bpy.context.scene.render.image_settings.file_format = 'H264'
170 188 bpy.context.scene.render.ffmpeg.format = 'MPEG4'
171 189 bpy.context.scene.render.ffmpeg.codec = 'H264'
172   - # bpy.context.scene.render.filepath = '/tmp/'
173   -
174 190 # Otimização da renderização
175 191 bpy.context.scene.render.use_shadows = False
176 192 bpy.context.scene.render.use_raytrace = False
... ... @@ -180,21 +196,16 @@ def outconf():
180 196 bpy.context.scene.render.tile_x = 320
181 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 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 206 bpy.ops.wm.quit_blender()
196 207  
197   -# Função que recupera o frame final do movimento
  208 +# descontinuada: get_endFrame
198 209 def get_endFrame(json_input, hands_frames_retilineo):
199 210 endsFrame = [18]
200 211 if(json_input["rightHand"] != []):
... ... @@ -217,19 +228,19 @@ def get_endFrame(json_input, hands_frames_retilineo):
217 228 def validate_rotation(bone, endFrame, startFrame = 0):
218 229 if (endFrame - startFrame == 1):
219 230 return True
220   -
  231 +
221 232 rotFrames = [[]]
222 233 scene = bpy.context.scene
223 234 frame_current = scene.frame_current
224   -
  235 +
225 236 for i in range(startFrame+1, endFrame+1, 1):
226 237 scene.frame_set(i)
227 238 rotFrames[-1] = bone.rotation_quaternion.to_euler()
228 239 rotFrames.append([])
229   -
  240 +
230 241 rotFrames.remove([])
231 242 scene.frame_set(frame_current)
232   -
  243 +
233 244 for k in range(1, len(rotFrames), 1):
234 245 for i in range(0, 3, 1):
235 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 252 new_rotation = bone.rotation_quaternion.to_euler()
242 253 new_rotation.rotate_axis(axis, math.radians(degree))
243 254 new_rotation = new_rotation.to_quaternion()
244   -
  255 +
245 256 bone.rotation_quaternion = new_rotation
246 257 keyframe_insert(bone, 'rotation_quaternion', currentFrame, False, True)
247 258 \ No newline at end of file
... ...