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)) | ... | ... |