Pirando na batatinha com o Blender e Python

Pirando na batatinha com o Blender e Python
Buenas!

Aprender pode ser uma experiência deliciosa, principalmente quando o desafio envolvido nos instiga a ir além. Para apimentar, podemos desbravar esse continente didático de formas pouco convencionais, ou seja, pirando na batatinha!

Que área melhor para efetivar isso que a da programação? Pois é, uma mistura explosiva para essa brincadeira são dois elementos já por natureza superinteressantes: o Blender 3D e a linguagem Python.

1. Conhecimentos prévios

Para quem não conhece o Blender é um editor 3D. Ou seja, ele serve para fazer objetos e cenas tridimensionais, mas não apenas isso, entre outras coisas pode-se usá-lo para criar curta-metragens animados, efeitos visuais, edição de vídeo, maquetes eletrônicas e até jogos! Usaremos uma característica interessante para divertirmo-nos: o Blender permite que criemos scripts através da linguagem Python.

Podemos acessar todas as suas funcionalidades por ela, não é um barato!

Se você deseja colocar em prática os ensinamentos contidos nesse material, deverá ter conhecimentos básicos de Blender. Se nunca ouviu falar no próprio ou nunca aventurou-se a usá-lo, uma boa oportunidade é ler a apostila básica gratuita que desenvolvi a quem posso interessar, clicando aqui.

2. O que vamos fazer

43e15501
1. Coletar os dados de um objeto na cena;

m2514fc81
2. Jogar esses dados num arquivo de texto simples;

m49a24565
3. Postar esse arquivo num site usando ftp (você vai precisar de um site pessoal que permita essa operação);

1d642855
4. Abrir o arquivo remoto utilizando o Firefox.

Tudo dentro do Blender e via script!

3. Configurando a área de trabalho

Para esse tutorial, o Linux Fedora 8 foi escolhido como sistema operacional, mas relaxe, pois o Blender roda em todos os sistema operacionais mais conhecidos no mercado. Seja Linux, Windows, MacOSX, Irix e cia. ltda. ele rodará tranquilamente.

38d7142c
Vamos abrir um terminal e chamar o Blender pelo comando:

$ blender

Lembrando que o $ não deve ser digitado, ele serve apenas como referência para mostrar que estamos trabalhando no console.

7e0135b1
Assim que abrir o Blender, redimensione ele de modo que divida espaço com o terminal e depois divida a área de trabalho em duas.

358e8806
Em seguida vá na janela da direita e selecione Text Editor.

b26d323
Em seguida, mova o mouse sobre a janela a direita e pressione ALT+N, assim criamos um novo arquivo para ser editado.
Prontinho, temos um editor de texto aberto, basta digitarmos os comandos nele em Python que a coisa funcionará conforme o solicitado. Vamos fazer um teste?

417cc4f3

Digite o comando:

print “Ola mundo cruel!!!”

1d65dc51
Vá em File –> Run Python Script

Obs.: Da próxima ver que você for rodar o script, basta mover a seta do mouse sobre o editor de texto e pressionar ALT+P, como aparece no menu acima.

3685c513
Volte a sua atenção para o terminal e veja que a impressão apareceu logo abaixo da mensagem de inicialização do Blender.

O que aconteceu? Nós rodamos o Python dentro do Blender!

m8715e73
Para ativar a coloração de sintaxe do editor de texto basta clicar no botão que aparece acima.

Se quiser salvar o arquivo vá em File –> Save e salve com a extensão .py.

Agora você está apto a seguir adiante.

4. É hora de diversão!

Chegou a hora de montar o script, mas não pense que iremos direto ao ponto. Refestele-se em sua poltrona e vamos deliciarmo-nos ao digerir as possibilidades que essa dupla do barulho (Blender e Python) nos oferece.

4.1. Coletando os dados de um objeto selecionado

Nós temos vários objetos na cena padrão do Blender…

16a54fa
Como vemos aí, um Cube, uma Lamp e uma Camera.

Precisamos de um comando que liste os objetos na cena, para então selecionarmos um deles.

Conseguiremos isso com:

O seguinte:

import Blender
obj = Blender.Object.Get()
print obj

Pelo qual teremos essa saída no terminal:

[[Object “Camera”], [Object “Cube”], [Object “Lamp”]]

Mas o que significa o comando? Vamos estudá-lo a la Jack, o Estripador… por partes…

import Blender

Aqui importamos o módulo que permite ao Python comunicar-se com o Blender.

obj = Blender.Object.Get()

Depois atribuíamos à variável obj uma lista com os objetos que a cena contém.

Perceba os pontos separando os objetos… primeiro temos o Blender, seguido de Object e por fim Get().

Dentro do módulo Blender, encontra-se simplesmente tudo que consta no programa. Nesse caso nós escolhemos Object, mas poderia ser Scene, Curve, Render e uma infinidade de opções como podemos atestar aqui.

Uma vez dentro do submódulo Object, temos ainda outras opções, como New() que cria um novo objeto, GetSelected() que pega o objeto selecionado, entre outras. No nosso caso selecionamos o Get() por que ele pega os objetos da cena e joga tudo numa lista.

print obj

Para podermos ver o que tem dentro da variável obj é necessário que imprimamos ela na tela. Taí o por que do comandinho final.

Agora vamos pensar um pouco. O intuito dessa primeira etapa é selecionarmos um dos objetos da cena e fazer extrair os dados dele. Isolando em partes:

1. Selecionar um objeto da cena;
2. Extrair dados.

Vamos efetivar o primeiro objetivo. Dentro os três que vimos na saída:

[[Object “Camera”], [Object “Cube”], [Object “Lamp”]]

Selecionaremos um deles… mas como?

Bem, não citei a pouco que essa saída tratava-se de uma lista? Pois bem, podemos isolar os elemtos dela, simplesmente colocando o número dele depois do código…

import Blender
obj = Blender.Object.Get()[0]
print obj

Rodando o comando temos a seguinte saída:

[[Object “Camera”]

Mas por que isso aconteceu? Simples, a resposta está no [0] depois do Get(). O primeiro elemento da lista é a Camera, e seu número no índice é 0. Se quisermos ver o segundo elemento basta trocarmos o 0 pelo 1:

import Blender
obj = Blender.Object.Get()[1]print obj

Logo, teremos a saída:

[Object “Cube”]

m1dfd69f9
Entendidos? Brinque um pouco com essa possilidade antes de passarmos para o segundo objetivo. Lembra? O esquema aqui é degustar o que se aprende.

Agora vamos extrair os dados de um objeto na cena. Por convensão decidi escolher um sólido, nesse caso o Cube. Se olharmos na figura acima veremos que trata-se do Blender.Object.Get()[1].

Os dados que serão extraídos:

1. Nome do objeto;
2. Localização (coordenadas);
3. Tipo de visualização do objeto.
4.1.1. Extraindo o nome do objeto


Vamos alterar levemente o código do script.

import Blender
obj = Blender.Object.Get()[1]obj_name = obj.getName()
print obj_name

Obs.: Perceba que o print foi alterado para que a saída do comando seja apenas os dados da nossa nova variável, a obj_name.

Logo, teremos a saída:

Cube

Pequena no tamanho, mas grande na eficiência, era isso mesmo que precisávamos!

obj_name = obj.getName()

Aqui pegamos os dados da seleção do objeto, o obj e isolamos apenas o seu nome atravéz do getName().

print obj_name

Por fim mandamos imprimir os dados contidos na variável, o que oferecerá apenas o nome do objeto, ou seja, Cube.

4.1.2. Extraindo a localização do objeto

Novamente mais um incremento no código.

import Blender
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
print obj_loc

Obs.: Perceba que o print foi alterado para que a saída do comando seja apenas os dados da nossa nova variável, a obj_loc.

O nosso querido getLocation() funciona da mesma forma que o anterior… a saída:

(0.0, 0.0, 0.0)
4.1.3. Extraindo o tipo de visualização do objeto

Com esse comando, vamos ver o tipo de visualização do objeto. O que vem a ser isso? Vamos ver o resultado, depois explico o significado.

import Blender
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_mod = obj.getDrawType()
print obj_mod

Obs.: Perceba que o print foi alterado para que a saída do comando seja apenas os dados da nossa nova variável, a obj_mod.

Quando vemos a saída, temos o seguinte resultado:

4

4? Mas quatro o que? Simples… veja o gráfico abaixo:

3e067e38
Esse é o mesmo objeto com modos de visualização diferenciados. O tipo padrão é o Shaded, taí o motivo do 4 ter aparecido! Mas não selecionei o getDrawType() à toa. Nós não vamos imprimir um 4 em nosso arquivo de saída e sim o tipo de visualização, nesse caso o Shaded. Mas para isso teremos que rebuscar um pouco o nosso código…

import Blender
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_mod = obj.getDrawType()
if obj_mod == 1:
obj_mod_str = “Bounding box”
elif obj_mod == 2:
obj_mod_str = “Wire”
elif obj_mod == 3:
obj_mod_str = “Solid”
elif obj_mod == 4:
obj_mod_str = “Shaded”
elif obj_mod == 5:
obj_mod_str = “Textured”
print obj_mod_str

Aqui criamos uma estruturas de ifs e elifs que vão testar um por um dos tipos até achar o que é coerente com o do objeto e por fim imprimí-lo na tela:

Shaded

4.2. Jogando os dados coletados num arquivo de texto

Antes de tudo, vamos entender como criar um arquivo de texto no Python. A forma geral é a seguinte:

1. Cria-se um arquivo vazio e o atribui a uma variável;
2. Escreve-se no arquivo;
3. Fecha-se o arquivo.

Num exemplo em código ficaria assim:

arquivo = file(‘/tmp/arquivinho.txt’, ‘w’)
arquivo.write(“Escrevendo no arquivo.”)
arquivo.close()

Simples não? Só três passos… criar, escrever e fechar.

Vamos transportar essa idéia para o nosso script:

import Blender
# Coleta dados
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_mod = obj.getDrawType()
if obj_mod == 1:
obj_mod_str = “Bounding box”
elif obj_mod == 2:
obj_mod_str = “Wire”
elif obj_mod == 3:
obj_mod_str = “Solid”
elif obj_mod == 4:
obj_mod_str = “Shaded”
elif obj_mod == 5:
obj_mod_str = “Textured”
# Escreve dados num arquivo de texto
arquivo = file(‘/tmp/arquivo_dados.txt’, ‘w’)
arquivo.write(obj_name)
arquivo.write(obj_loc)
arquivo.write(obj_mod_str)
arquivo.close()

Tudo certinho, vamos rodar e ver o que acontece:

Traceback (most recent call last):
File “Text.001”, line 27, in <module>
TypeError: argument 1 must be string or read-only character buffer, not tuple

Uia! O que é isso?
Bem, vamos analisar… ele diz que o problema está na linha 27:
mos transportar essa idéia para o nosso script:

arquivo.write(obj_loc)

No TypeError ele diz que não pode ser uma tupla, então, temos que fazer uma conversão de tupla para… bem, como estou nos rudimentos da programação a saída que achei foi converter para uma string. De olho para uma pequena alteração no código:

import Blender
# Coleta dados
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_loc_str = str(obj_loc)
obj_mod = obj.getDrawType()
if obj_mod == 1:
obj_mod_str = “Bounding box”
elif obj_mod == 2:
obj_mod_str = “Wire”
elif obj_mod == 3:
obj_mod_str = “Solid”
elif obj_mod == 4:
obj_mod_str = “Shaded”
elif obj_mod == 5:
obj_mod_str = “Textured”
# Escreve dados num arquivo de texto
arquivo = file(‘/tmp/arquivo_dados.txt’, ‘w’)
arquivo.write(obj_name)
arquivo.write(obj_loc_str)
arquivo.write(obj_mod_str)
arquivo.close()

Com a função str() convertermos a tupla numa string, ou, num texto formado por números.

Vamos rodar o script e depois abrir o resultado em /tmp/arquivo_dados.txt usando um editor de texto.

741f0be1
É… deu certo mas ainda não está agradável aos olhos. Os dados estão concatenados (tudo grudado!). Seria legal se colocassemos os resultados em linhas diferentes e é o que faremos. De olho no código:

import Blender
# Coleta dados
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_loc_str = str(obj_loc)
obj_mod = obj.getDrawType()
if obj_mod == 1:
obj_mod_str = “Bounding box”
elif obj_mod == 2:
obj_mod_str = “Wire”
elif obj_mod == 3:
obj_mod_str = “Solid”
elif obj_mod == 4:
obj_mod_str = “Shaded”
elif obj_mod == 5:
obj_mod_str = “Textured”
# Escreve dados num arquivo de texto
arquivo = file(‘/tmp/arquivo_dados.txt’, ‘w’)
arquivo.write(obj_name)
arquivo.write(“n”)
arquivo.write(obj_loc_str)
arquivo.write(“n”)
arquivo.write(obj_mod_str)
arquivo.close()

O segredinho é inserir um caractere de nova linha n onde for necessário.

m108b3091
Prontinho, nosso arquivo está criado!

4.3. Mandando o arquivo para a internet

Até agora só não achei um módulo que fizesse chover, de resto o Python tem pra tudo!

Um belo dia me deparei com o ftplib e foi amor a primeira vista. Trago um pouco dessa paixão aqui para você nobre leitor, nesse próximo passo.

1. Importa o módulo ftplib;
2. Atribui os dados de conexão a uma variável;
3. Abre o arquivo que será enviado atribuindo-o a uma variável;
4. Envia o arquivo;
5. Fecha o arquivo;
6. Encerra a conexão.

Algo nesse sentido:

from ftplib import FTP
con = FTP(‘ftp.endereco.com.br’,’nome_usuario’,’senha’)
arquivo_envia = open(‘/tmp/arquivo_dados.txt’,’rb’)
con.storbinary(‘STOR arquivo_dados.txt’, arquivo_envia)
arquivo_envia.close()
con.quit()

Vamos destrinchar o código…

from ftplib import FTP

Primeiro importamos o submódulo FTP do ftplib.

con = FTP(‘ftp.endereco.com.br’,’nome_usuario’,’senha’)

Depois atribuímos à con variável com os dados de conexão… imaginemos que no teu caso os dados fossem esses:

Servidor ftp: ftp://teste.com.br
Usuário: hombrecito
Senha: bagualdemais
con = FTP(‘teste.com.br‘,’hombrecito‘,’bagualdemais‘)

Ficaria como aparece acima…

arquivo_envia = open(‘/tmp/arquivo_dados.txt’,’rb’)

Aqui abrimos o arquivo arquivo_dados.txt, aquele que criamos no passo anterior e atribuímos ele à variável arquvo_envia.

con.storbinary(‘STOR arquivo_dados.txt’, arquivo_envia)

Em seguida, usamos os dados contidos na variável con para fazer a operação de upload (storbinary()) ou envio do arquivo arquivo_dados.txt, cujos dados estão contidos na variável arquivo_envia.

arquivo_envia.close()

Fechamos o arquivo.

con.quit()

Fechamos a conexão.

Vamos tranferir o que aprendemos para o nosso script:

import Blender
from ftplib import FTP
# Coleta dados
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_loc_str = str(obj_loc)
obj_mod = obj.getDrawType()
if obj_mod == 1:
obj_mod_str = “Bounding box”
elif obj_mod == 2:
obj_mod_str = “Wire”
elif obj_mod == 3:
obj_mod_str = “Solid”
elif obj_mod == 4:
obj_mod_str = “Shaded”
elif obj_mod == 5:
obj_mod_str = “Textured”
# Escreve dados num arquivo de texto
arquivo = file(‘/tmp/arquivo_dados.txt’, ‘w’)
arquivo.write(obj_name)
arquivo.write(“n”)
arquivo.write(obj_loc_str)
arquivo.write(“n”)
arquivo.write(obj_mod_str)
arquivo.close()
# Envia dados para a internet
con = FTP(‘teste.com.br’,’hombrecito’,’bagualdemais’)
arquivo_envia = open(‘/tmp/arquivo_dados.txt’,’rb’)
con.storbinary(‘STOR arquivo_dados.txt’, arquivo_envia)
arquivo_envia.close()
con.quit()

Rodamos o script e se tudo correr bem, basta abrir o Firefox e entrar no endereço corresposdente ao site enviado:

6588c313
Certinho! Isso nos permite dar o próximo passo.

4.4. Abrindo o Firefox com o endereço remoto

Para fechar com chave de ouro vamos terminar o script acessando os comandos do sistema operacional como se estivessemos no console, mas via Python. Para tal lançaremos mão do módulo os. Com ele nós chamaremos o navegador de internet e de quebra já setaremos a URL que ele abrirá.

import Blender
from ftplib import FTP
import os
# Coleta dados
obj = Blender.Object.Get()[1] obj_name = obj.getName()
obj_loc = obj.getLocation()
obj_loc_str = str(obj_loc)
obj_mod = obj.getDrawType()
if obj_mod == 1:
obj_mod_str = “Bounding box”
elif obj_mod == 2:
obj_mod_str = “Wire”
elif obj_mod == 3:
obj_mod_str = “Solid”
elif obj_mod == 4:
obj_mod_str = “Shaded”
elif obj_mod == 5:
obj_mod_str = “Textured”
# Escreve dados num arquivo de texto
arquivo = file(‘/tmp/arquivo_dados.txt’, ‘w’)
arquivo.write(obj_name)
arquivo.write(“n”)
arquivo.write(obj_loc_str)
arquivo.write(“n”)
arquivo.write(obj_mod_str)
arquivo.close()
# Envia dados para a internet
con = FTP(‘teste.com.br’,’hombrecito’,’bagualdemais’)
arquivo_envia = open(‘/tmp/arquivo_dados.txt’,’rb’)
con.storbinary(‘STOR arquivo_dados.txt’, arquivo_envia)
arquivo_envia.close()
con.quit()
# Abre o Firefox no endereco do arquivo na internet
os.popen(‘firefox http://cogitas3d.procedural.com.br/arquivo_dados.txt’)

Agora é só rodar e correr pro abraço!

5. Conclusão

O que é bom dura pouco, mas nem tudo. No caso da programação podemos estender o nosso prazer didático por um tempo indeterminado. Isso por que sempre podemos melhorar o que criamos, sem contar que ainda temos um mar de novos recursos a explorar.

Programar não é apenas criar novos códigos, mas ajudar no desenvolvimento do que já existe, ou mesmo testar os de terceiros. Nesse caso, não é apenas didático, mas nobre.

Então fique esperto, a coisa não termina por aqui. A API de script do Blender é riquíssima e tem um monte de recursos te esperando para serem descobertos e deliciados. Comece agora mesmo a explorá-los!

Sucesso nessa busca e grande abraço.

Cícero Moraes.

Cícero Moraes (cogitas3d) é digital designer, eventual palestrante e instrutor de cursos técnicos de informática. Autoditada, aprendeu a sua profissão na internet, lendo diversos tutoriais e artigos sobre computação gráfica. Hoje retribui essa informação escrevendo seus próprios documentos, onde compartilha o que aprendeu. Colaborou com diversas publicações online e impressas lidas em todo o Brasil e outros países. Participa de vários projetos voltados para instituições de ensino superior e prefeituras, cujo principal objetivo é levar ao dia-a-dia das pessoas não apenas o software livre, mas todo o conhecimento que ele oferece através de oficinas, cursos e eventos. Mais informações e contato pelo site pessoal: http://cogitas3d.site.vu

Sobre o Autor

Redes Sociais:

Deixe seu comentário

X