Commit ab51f390bdcf2d76115c52c1916c2175fb1878cc
Exists in
master
Realiza merge
Showing
4 changed files
with
114 additions
and
46 deletions
Show diff stats
... | ... | @@ -0,0 +1,21 @@ |
1 | +BLENDER = blender | |
2 | +DONE = [\33[30;32mOK\33[m]\n | |
3 | +FAIL = [\33[30;31mERRO\33[m]\n | |
4 | +MODULE = Wikilibras | |
5 | +CLEAR = @echo -n "\033c" | |
6 | +CACHE = __pycache__ | |
7 | +SCRIPT = libras.py | |
8 | +AVATAR = avatar_Hozana_wikiLibras.blend | |
9 | +JSON = '{"userId": 4,"rightHand": ["circular", "perpendicular", "horario", 0.6, 1, 20, 4, 6], "leftHand":["pontual", 10, 3, 3], "facialExp": [6], "signName":"teste_circular"}' | |
10 | + | |
11 | +default: main | |
12 | + | |
13 | +main: | |
14 | + $(CLEAR) | |
15 | + @echo Executando... | |
16 | + @$(BLENDER) -b $(AVATAR) -P $(SCRIPT) $(JSON) && echo "$(DONE)" || { echo "$(FAIL)"; exit 1; } | |
17 | + | |
18 | +clean: | |
19 | + $(CLEAR) | |
20 | + @echo -n "Limpando..." | |
21 | + @rm -rf $(CACHE) > /dev/null 2>&1 && echo " $(DONE)" || { echo " $(FAIL)"; exit 1; } | ... | ... |
libras.py
1 | 1 | # -*- coding: UTF-8 -*- |
2 | 2 | |
3 | -# importa modulos do Python | |
4 | -import sys | |
3 | +# importa modulos do Blender e Python | |
4 | +import bpy | |
5 | +import json | |
5 | 6 | import os |
6 | -# insere o diretorio atual no path | |
7 | -# permite que o código seja executado de qualquer diretório, possibilitando acesso aos modulos locais | |
7 | +import sys | |
8 | + | |
9 | +# insere o diretorio atual no path (permite o acesso aos modulos locais) | |
8 | 10 | sys.path.append(os.getcwd()) |
9 | 11 | |
10 | -# importa modulos nativos do Blender e Python | |
11 | -import bpy | |
12 | -import json | |
13 | 12 | # importa modulos locais |
14 | 13 | import util |
15 | 14 | import moves |
16 | 15 | |
17 | -# verifica a quantidade de argumentos recebidos | |
18 | -if (len(sys.argv) != 6): | |
19 | - print ("WikiLibras: Invalid number of arguments") | |
20 | - exit(1) | |
21 | - | |
22 | 16 | # tenta decodificar o argumento JSON recebido |
23 | 17 | try: |
18 | + util.file_rename("./users/4/teste_circular_0001-0083.mp4") | |
24 | 19 | json_input = json.loads(sys.argv[5]) |
25 | -except (ValueError, KeyError, TypeError): | |
26 | - print ("WikiLibras: JSON format error") | |
20 | +except Exception: | |
21 | + util.printStackTrace(__file__) | |
27 | 22 | exit(1) |
28 | 23 | |
29 | 24 | # ajusta as configuraçẽs de renderização |
... | ... | @@ -38,12 +33,12 @@ hands_frames_retilineo = [30,33] |
38 | 33 | armature = bpy.context.scene.objects.get('Armature.001') |
39 | 34 | |
40 | 35 | # Cria uma Action |
41 | -act = bpy.context.scene.animation_data_create() | |
36 | +act = bpy.context.scene.animation_data_create() | |
42 | 37 | |
43 | -# Função responsável por selecionar as pose-libs e setar os frames | |
38 | +# Função responsável por selecionar as pose-libs e setar os frames | |
44 | 39 | def setPose(actions, parametesConf, positionFrames, bones): |
45 | 40 | bpy.ops.object.mode_set(mode = 'OBJECT') |
46 | - bpy.ops.object.select_all(action="DESELECT") | |
41 | + bpy.ops.object.select_all(action="DESELECT") | |
47 | 42 | bpy.ops.object.mode_set(mode = 'POSE') |
48 | 43 | for l in range(len(actions)): |
49 | 44 | armature.pose_library = bpy.data.actions[actions[l]] |
... | ... | @@ -54,8 +49,8 @@ def setPose(actions, parametesConf, positionFrames, bones): |
54 | 49 | armature.pose.bones[bones[i]].keyframe_insert(data_path = 'rotation_quaternion', index = -1, frame = positionFrames[x]) |
55 | 50 | |
56 | 51 | # Função responsável por setar pose padrão |
57 | -def poseDefault(positionFrames, bones): | |
58 | - setPose([0], [0], positionFrames, bones) | |
52 | +def poseDefault(positionFrames, bones): | |
53 | + setPose([0], [0], positionFrames, bones) | |
59 | 54 | |
60 | 55 | # Função responsável por setar as configuraçẽs das mãos |
61 | 56 | def generationConfigurations(actions, handParam, positionFrames, bones): |
... | ... | @@ -72,11 +67,11 @@ initialFrame, endFrame = 15, util.get_endFrame(json_input,hands_frames_retilineo |
72 | 67 | #Função que inicia a configuração de ambas as mãos |
73 | 68 | def configureHands(): |
74 | 69 | # Array com valores dos campos que serão passados pelo JSON |
75 | - hands = ["rightHand", "leftHand"] | |
70 | + hands = ["rightHand", "leftHand"] | |
76 | 71 | iks = ['ik_FK.R', 'ik_FK.L'] |
77 | 72 | bones_ = [util.rightBonesConf, util.leftBonesConf] |
78 | 73 | #Array com as actions FAKES que seram selecionadas no Blender para cada lado do corpo |
79 | - actions = [[1, 3, 5], [2, 4, 6]] | |
74 | + actions = [[1, 3, 5], [2, 4, 6]] | |
80 | 75 | global endFrame |
81 | 76 | for i in range(len(hands)): |
82 | 77 | if(json_input[hands[i]] != []): |
... | ... | @@ -93,19 +88,27 @@ def configureHands(): |
93 | 88 | elif(move == "retilineo"): |
94 | 89 | generationConfigurations(actions[i], json_input[hands[i]][-6:-3], hands_default_frames, bones_[i]) |
95 | 90 | generationConfigurations(actions[i], json_input[hands[i]][-3:],hands_frames_retilineo, bones_[i]) |
91 | +<<<<<<< HEAD | |
96 | 92 | |
97 | 93 | |
94 | +======= | |
95 | + elif(json_input[hands[i]][0] == "senoidal"): | |
96 | + orientation, direction, radius, laps = json_input[hands[i]][1:5] | |
97 | + endFrame = circular_or_semiCircular(pose, orientation, direction, radius, laps, 5) | |
98 | + generationConfigurations(actions[i], json_input[hands[i]][-3:], [endFrame], bones_[i]) | |
99 | + | |
100 | +>>>>>>> 4973c0eb8bf544c810f4405a8974cf6e962d7bd4 | |
98 | 101 | # Função que inicia a configuração da face |
99 | -def configureFace(): | |
102 | +def configureFace(): | |
100 | 103 | global endFrame |
101 | 104 | if(json_input["facialExp"] != []): |
102 | 105 | # Set face |
103 | - faceConfiguration(json_input["facialExp"], [endFrame/4], util.faceBonesConf) | |
106 | + faceConfiguration(json_input["facialExp"], [endFrame/4], util.faceBonesConf) | |
104 | 107 | |
105 | 108 | # Default Pose |
106 | 109 | print(endFrame) |
107 | -poseDefault([1, endFrame+15], util.allBones) | |
110 | +poseDefault([1, endFrame + 15], util.allBones) | |
108 | 111 | configureHands() |
109 | 112 | configureFace() |
110 | 113 | |
111 | -util.render_sign(json_input["userId"], json_input["signName"], 1, endFrame + 25) | |
112 | 114 | \ No newline at end of file |
115 | +util.render_sign(json_input["userId"], json_input["signName"], 1, endFrame + 25) | ... | ... |
moves.py
1 | 1 | # -*- coding: UTF-8 -*- |
2 | + | |
2 | 3 | import math |
3 | 4 | |
4 | 5 | def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensity = 5, initialFrame = 18, turn = None): |
... | ... | @@ -7,7 +8,7 @@ def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensi |
7 | 8 | if(direction == 'horario'): |
8 | 9 | endFrame = moves.locationCircular(center, radius, 1, 0, 2, pose, 0, laps, intensity, initialFrame,turn) |
9 | 10 | else: |
10 | - endFrame = moves.locationCircular(center, radius, 0, 1, 2, pose, 0, laps, intensity, initialFrame,turn) | |
11 | + endFrame = moves.locationCircular(center, radius, 0, 1, 2, pose, 0, laps, intensity, initialFrame,turn) | |
11 | 12 | elif(orientation == 'paralelo'): |
12 | 13 | if(direction == 'horario'): |
13 | 14 | endFrame = moves.locationCircular(center, radius, 1, 2, 0, pose, 0, laps, intensity, initialFrame,turn) |
... | ... | @@ -20,6 +21,11 @@ def circular_or_semiCircular(pose, orientation, direction, radius, laps, intensi |
20 | 21 | endFrame = moves.locationCircular(center, radius, 0, 2, 1, pose, 0, laps, intensity, initialFrame,turn) |
21 | 22 | return endFrame |
22 | 23 | |
24 | +# center[3]: float vector (posição xyz centro) | |
25 | +# radius: float (distancia do centro) | |
26 | +# i_axis: int (indice do eixo i [0 | 1 | 2]) | |
27 | +# j_axis: int (indice do eixo j [0 | 1 | 2]) | |
28 | +# k_axis: int (indice do eixo k [0 | 1 | 2]) | |
23 | 29 | def locationCircular(center, radius, i_axis, j_axis, k_axis, pose, initialPosition, laps, frameJump = 5, initialFrame = 18, turn = None): |
24 | 30 | sqrt22 = radius * (math.sqrt(2) / 2) |
25 | 31 | rad2 = (radius/2) |
... | ... | @@ -71,14 +77,14 @@ def locationCircular(center, radius, i_axis, j_axis, k_axis, pose, initialPositi |
71 | 77 | pose.location[k_axis] = center[k_axis] + rad2 |
72 | 78 | pose.keyframe_insert(frame = currentFrame, index = -1, data_path = 'location') |
73 | 79 | currentFrame += frameJump |
74 | - | |
80 | + | |
75 | 81 | if ((l % 8) == 4): |
76 | 82 | pose.location[i_axis] = center[i_axis] - radius |
77 | 83 | pose.location[j_axis] = center[j_axis] |
78 | - pose.location[k_axis] = center[k_axis] | |
84 | + pose.location[k_axis] = center[k_axis] | |
79 | 85 | pose.keyframe_insert(frame = currentFrame, index = -1, data_path = 'location') |
80 | 86 | currentFrame += frameJump |
81 | - | |
87 | + | |
82 | 88 | if ((l % 8) == 5): |
83 | 89 | pose.location[i_axis] = center[i_axis] - sqrt22 |
84 | 90 | pose.location[j_axis] = center[j_axis] - sqrt22 |
... | ... | @@ -93,7 +99,7 @@ def locationCircular(center, radius, i_axis, j_axis, k_axis, pose, initialPositi |
93 | 99 | pose.location[k_axis] = center[k_axis] - rad2 |
94 | 100 | pose.keyframe_insert(frame = currentFrame, index = -1, data_path = 'location') |
95 | 101 | currentFrame += frameJump |
96 | - | |
102 | + | |
97 | 103 | if ((l % 8) == 6): |
98 | 104 | pose.location[i_axis] = center[i_axis] |
99 | 105 | pose.location[j_axis] = center[j_axis] - radius |
... | ... | @@ -106,7 +112,7 @@ def locationCircular(center, radius, i_axis, j_axis, k_axis, pose, initialPositi |
106 | 112 | pose.location[k_axis] = center[k_axis] - sqrt22 |
107 | 113 | pose.keyframe_insert(frame = currentFrame, index = -1, data_path = 'location') |
108 | 114 | currentFrame += frameJump |
109 | - | |
115 | + | |
110 | 116 | if ((l % 8) == 7): |
111 | 117 | pose.location[i_axis] = center[i_axis] + sqrt22 |
112 | 118 | pose.location[j_axis] = center[j_axis] - sqrt22 |
... | ... | @@ -121,11 +127,9 @@ def locationCircular(center, radius, i_axis, j_axis, k_axis, pose, initialPositi |
121 | 127 | pose.location[k_axis] = center[k_axis] - rad2 |
122 | 128 | pose.keyframe_insert(frame = currentFrame, index = -1, data_path = 'location') |
123 | 129 | currentFrame += frameJump |
124 | - currentFrame -= frameJump | |
130 | + currentFrame -= frameJump | |
125 | 131 | return currentFrame |
126 | 132 | |
127 | - | |
128 | -# testing . . . | |
129 | 133 | def locationHelicoidal(center, startRadius, incRadius, x, y, z,pose, currentLoc, laps, frameJump): |
130 | 134 | sqrt22 = radius * math.sqrt(2) / 2 |
131 | 135 | allLaps = math.floor(8 * laps) + 1 |
... | ... | @@ -191,11 +195,7 @@ def locationHelicoidal(center, startRadius, incRadius, x, y, z,pose, currentLoc, |
191 | 195 | |
192 | 196 | bpy.context.scene.frame_end -= frameJump |
193 | 197 | |
194 | -# testing . . . | |
195 | 198 | def locationSenoidal(obj): |
196 | - obj.location = [0, 0, 0] | |
197 | - bpy.context.scene.frame_start = 1 | |
198 | - bpy.context.scene.frame_end = 1 | |
199 | 199 | seno = 0 |
200 | 200 | waveHeight = 5.0 |
201 | 201 | wave = 5 |
... | ... | @@ -208,4 +208,3 @@ def locationSenoidal(obj): |
208 | 208 | if (i % 10 == 0): |
209 | 209 | obj.keyframe_insert(frame = bpy.context.scene.frame_end, index = -1, data_path = 'location') |
210 | 210 | bpy.context.scene.frame_end += 1 |
211 | - | |
212 | 211 | \ No newline at end of file | ... | ... |
util.py
... | ... | @@ -2,22 +2,45 @@ |
2 | 2 | |
3 | 3 | import bpy |
4 | 4 | import math |
5 | +import sys | |
6 | +import os | |
5 | 7 | |
6 | -bones = ["BnMao.R", "BnMao.L"] | |
7 | 8 | armature = bpy.context.scene.objects.get('Armature.001') |
9 | + | |
10 | +bones = ["BnMao.R", "BnMao.L"] | |
11 | + | |
12 | +# Vetor com indices de cada bone do lado direito | |
8 | 13 | rightBonesConf = [1, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66] |
14 | + | |
15 | +# Vetor com indices de cada bone do lado esquerdo | |
9 | 16 | leftBonesConf = [0, 43, 44, 45, 46, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82] |
17 | + | |
18 | +# Vetor com indices de cada bone da face | |
10 | 19 | faceBonesConf =[15, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 47] |
20 | + | |
21 | +# Vetor com indices de todos os bones | |
11 | 22 | allBones = list(range(len(armature.pose.bones))) |
12 | 23 | |
24 | +def printStackTrace(filename): | |
25 | + print("\n[Exception]\n File: %s\n Name: %s\n Line: %s\n Type: %s\n Message: %s\n[Exception]\n" % ( | |
26 | + os.path.basename(filename), # os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), | |
27 | + sys.exc_info()[2].tb_frame.f_code.co_name, | |
28 | + sys.exc_info()[2].tb_lineno, | |
29 | + sys.exc_info()[0].__name__, | |
30 | + sys.exc_info()[1], | |
31 | + ) | |
32 | + ) | |
33 | + | |
34 | +# Função que limpa todos os keyframes e define a quantidade de frames | |
13 | 35 | def erase_all_keyframes(): |
14 | 36 | for i in bpy.data.objects: |
15 | 37 | i.animation_data_clear() |
16 | 38 | bpy.context.scene.frame_start = 1 |
17 | 39 | bpy.context.scene.frame_current = bpy.context.scene.frame_start |
18 | 40 | bpy.context.scene.frame_end = bpy.context.scene.frame_start |
19 | - | |
41 | + | |
20 | 42 | def outconf(): |
43 | + erase_all_keyframes() | |
21 | 44 | bpy.context.scene.render.resolution_x = 640 |
22 | 45 | bpy.context.scene.render.resolution_y = 480 |
23 | 46 | bpy.context.scene.render.resolution_percentage = 100 |
... | ... | @@ -25,16 +48,38 @@ def outconf(): |
25 | 48 | bpy.context.scene.render.ffmpeg.format = 'MPEG4' |
26 | 49 | bpy.context.scene.render.ffmpeg.codec = 'H264' |
27 | 50 | # bpy.context.scene.render.filepath = '/tmp/' |
28 | - | |
51 | + | |
52 | +def file_rename(filename): | |
53 | + from shutil import move | |
54 | + newFilename = "" | |
55 | + isValidChar = True | |
56 | + for char in reversed(filename): | |
57 | + if (isValidChar == True): | |
58 | + newFilename += char | |
59 | + if (char == '_'): | |
60 | + isValidChar = True | |
61 | + elif (char == '.'): | |
62 | + isValidChar = False | |
63 | + if (len(filename) != len(newFilename)): | |
64 | + try: | |
65 | + move(filename, newFilename[::-1]) | |
66 | + return 1 | |
67 | + except Exception as e: | |
68 | + printStackTrace(__file__) | |
69 | + return 0 | |
70 | + return 0 | |
71 | + | |
29 | 72 | def render_sign(userId, signName, beginFrame, endFrame): |
30 | 73 | bpy.context.scene.render.filepath = "//users//"+ str(userId)+ "//"+ signName + "_" |
31 | 74 | bpy.context.scene.frame_start = beginFrame |
32 | 75 | bpy.context.scene.frame_end = endFrame |
33 | - bpy.ops.render.render(animation = True, write_still = False, layer = "", scene = "") | |
76 | + outFilename = (bpy.context.scene.render.filepath + "%0.4i-%0.4i.mp4" % (bpy.context.scene.frame_start, bpy.context.scene.frame_end)) | |
77 | + bpy.ops.render.render(animation = True, write_still = False, layer = "", scene = "") | |
78 | + file_rename(outFilename) | |
34 | 79 | bpy.ops.wm.quit_blender() |
35 | 80 | |
36 | 81 | # Função que recupera o frame final do movimento |
37 | -def get_endFrame(json_input,hands_frames_retilineo): | |
82 | +def get_endFrame(json_input,hands_frames_retilineo): | |
38 | 83 | endsFrame = [18] |
39 | 84 | if(json_input["rightHand"] != []): |
40 | 85 | if(json_input["rightHand"][0] == "circular"): |
... | ... | @@ -44,10 +89,10 @@ def get_endFrame(json_input,hands_frames_retilineo): |
44 | 89 | elif(json_input["rightHand"][0] == "retilineo"): |
45 | 90 | endsFrame.append(max(hands_frames_retilineo)) |
46 | 91 | if(json_input["leftHand"] != []): |
47 | - if(json_input["leftHand"][0] == "circular"): | |
92 | + if(json_input["leftHand"][0] == "circular"): | |
48 | 93 | endsFrame.append(int(json_input["leftHand"][4]*8*5+18)) |
49 | 94 | elif(json_input["leftHand"][0] == "semicircular"): |
50 | 95 | endsFrame.append(int(json_input["rightHand"][4]*5*5+18)) |
51 | 96 | elif(json_input["rightHand"][0] == "retilineo"): |
52 | 97 | endsFrame.append(max(hands_frames_retilineo)) |
53 | - return(max(endsFrame)) | |
98 | + return(max(endsFrame)) | ... | ... |