ct

    Pirando na batatinha com o Blender e Python

    Dicas do Guia do Hardware

    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. Cícero Moraes
    06/10/2008


    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



    Blog:

    Add to Google

    » Gostou do texto? Veja nossos livros impressos:
    Hardware | Redes | Servidores | Kurumin 7

    ... ou encontre o que procura usando a busca:

cb
Livros de Carlos E. Morimoto Contato HOME