Pythonlópes
El Python que yo sé


Parte I: los comienzos son siempre duros

La naturaleza es más sabia que el hombre:
en ella lo inútil tiende a desaparecer

Servidor de vds.

Python
Python es un lenguaje de programación de alto nivel, que quiere decir que tenemos que esforzarnos menos por aprenderlo y expresarnos con él (programar), aunque suele ocurrir que se vuelve más lento en la ejecución de los programas. De todas formas la lentitud de Python no se debe a que sea de alto nivel...
Sino a que, en lugar de compilar nuestros programas escritos en este lenguaje para obtener ficheros binarios y librerías, los ejecutamos sobre la marcha. Esto se llama lenguaje interpretado, y salvo la famosa lentitud en la ejecución, sólo nos ofrece ventajas: * Los códigos son siempre legibles, con lo que podemos aprender mucho de los demás * No hay que hacer pasos intermedios entre que tocamos el código y lo ejecutamos * Es más fácil encontrar errores y probar el programa, ya que el programa corre hasta que encuentra uno, en lugar de ser un compilador el que se detiene, sin haber ejecutado ninguna instrucción * Esto puede ser también una desventaja, porque tales errores podrían ser críticos y un compilador los filtraría, pero el hecho de que sea de alto nivel hace que no sea fácil provocar estos errores * Es sumamente utilizado para programar sobre otros programas, o sea, hacer scripts (guiones, aunque los llamaremos scripts) y manipular explícitamente los datos del proyecto activo, o sea, lo que vamos a hacer sobre Blender.

Dónde encontrar información: primero en www.python.org, y de allí es fácil acceder a casi cualquier recurso y documentación en varios idiomas. Especialmente recomendable es el manual de introducción de Guido Van Rossum, creador de Python, o el libro Dive into Python, ambos traducidos al español.
En cuanto a la documentación sobre el API de Blender, o la lista de módulos y objetos que sirven para comunicarse con el proyecto, se puede encontrar en http://www.blender.org/modules/documentation/228PythonDoc/index.html
Para preguntar dudas, presentar trabajos o charlar sobre Blender-Python hay un for hispano en el portal http://www.nicodigital.com

¿Hay que instalar alguna cosa? Para usar Python con Blender es recomendable bajarse el intérprete completo de www.python.org, versión 2.20 a 2.22, pero no es necesario para empezar a aprender, ya que Blender lleva incluido su propio intérprete (API) con todos los comandos de la librería principal. Sin embargo, se puede hacer uso de librerías externas que hacen necesario instalar Python en el sistema (o, al menos, las librerías típicas: string, math... en un directorio) Una vez instalado, hay que indicar en una variable de sistema llamada PYTHONPATH dónde están esas librerías.
Python está disponible para todos los sistemas operativos en los que podemos instalar Blender


El entorno de texto en Blender
Blender tiene un editor de texto con el que podemos abrir cualquier fichero y escribir, pero está pensado para programar scripts. Si no sabes dónde está, probablemente no conozcas Blender lo suficiente como para programar scripts, así que busca una guía de Blender, y vuelve más tarde a leer desde aquí.

Con el botón derecho accedemos al menú de archivos.
Con AltF hacemos un búsqueda de texto, y sigue buscando
Con CtrlAltF buscamos otra cosa
Copiar con AltC y CtrlC
Pegar con CtrlV y AltV
Copiar a windows con CtrlMaysC
Pegar de windows con CtrlMaysV
Deshacer con AltZ y CtrlZ
Rehacer con AltR
Reabrir fichero con CtrlR
Abajo hay un icono para mostrar números de línea, lo que viene realmente bien. Y creo que ya está todo. Ah, sí, a día de hoy el teclado en español no funciona. Conviene con figurarse el teclado en inglés, o bien poner un texto en la cabecera de todos tus scripts con los signos que no puedes escribir directamente, para copiar y pegar.


Acceso a los datos del proyecto y un vistazo al API
Llamaremos "proyecto" a lo que estamos haciendo bajo Blender. O sea, el conjunto de Objetos y Relaciones que manejamos sin saberlo. Ahora sí lo sabremos.
No voy a contar cómo se organizan los Objetos en Blender (que a partir de ahora llamaremos BlObjetos) ni los de Python (que llamaremos PyObjetos), ni cómo se relacionan. Esto se irá viendo conforme hagamos cosas con el API.
Diré sin embargo, que un BlObjeto pasa a ser PyObjeto cuando lo capturamos, usualmente con el método Get(), y tenemos acceso a sus atributos como un PyObjeto según su clase, es decir, el objeto llamado "obj" puede tener unas coordenadas a las que se accede con "obj.loc", o un enlace a otro objeto que podemos visualizar con "obj.data". También hay métodos funcionales, que sirven por ejemplo para manipular de una forma más efectiva los objetos: por ejempo, "obj.loc" es de sólo lectura, siendo preferible acceder a las coordenadas con "obj.getLocation()" y aplicar unas nuevas con "obj.setLocation(x,y,z)"
Por otro lado, el API de Blender dispone de varias librerías de funciones, asociadas a cada clase, que nos permiten operar directamente en los objetos. Así, la librería "Object" sirve para capturar objetos por su nombre ("Object.Get('Plane.002')"), objetos que estén en la selección actual ("Object.GetSelected()")
Un aspecto importante del concepto de Objeto: en Blender hay objetos de varias clases: clase Lámpara, clase Escena, clase Material... y clase OBJETO. Este OBJETO se refiere a "Objeto3D", que es como lo llamaremos en adelante, y consta de una referencia de lugar, orientación y tamaño que va asociada a otro bloque de datos (otro BlObjeto), que será de unos de estos tipos: malla ('Mesh'), lámpara ('Lamp'), curva ('Curve'), cámara ('Camera'), y aunque no estén implementados en el API en todo momento, hay otros: Armature, Lattice, Metaball, Surface... Es a estos objetos3D, visibles en una escena, a los que se refiere el módulo/librería "Blender.Object"


Tipos de scripts
Dependiendo de su funcionalidad, los scripts son de estos tipos:
De ejecución manual: sirven para realizar una tarea en el diseño del proyecto. Es decir, se ejecutan y ya está. Empezaremos con ellos por ser los más sencillos. Se ejecutan dejando el cursor sobre la ventana de texto y pulsando AltP. A su vez pueden tener un entorno gráfico, usando instrucciones OpenGl, y funcionando por eventos.
De ejecución automática: se ejecutan cada vez que (a)Blender redibuja el entorno, o (b)cambiamos de frame. Así podemos aplicar instrucciones a un objeto, por ejemplo, para darle una localización dependiendo del tiempo.
Para hacer esto, pulsa el botón de script linking (el que tiene un papel dibujado, en la ventana de botones) y asocia el script pulsando uno de los botones Add.
Se asocian a toda una escena (mitad derecha), o a ciertos objetos3D (mitad izquierda), afectando a alguno de los distintos objetos enganchados a este: objeto3D, material, etc.
Logicbrick: se emplean en el motor de tiempo real para toma de decisiones, aplicación de atributos, etc.


Vamos a ver un objeto3D
Iniciemos Blender con la configuración de fábrica, o sea, que nos aparezca el plano y la cámara. Debemos saber que el plano es un BlObjeto de clase objeto3D llamado 'Plane', de tipo 'Mesh', asociado por tanto a un objeto de clase Mesh llamado también 'Plane'.
Por otro lado, la cámara es un BlObjeto de clase objeto3D llamado 'Camera', de tipo 'Camera', asociado por tanto a un objeto de clase Camera llamado también 'Camera'.Escribamos el siguiente código:

Manipulación de un objeto
import Blender

obj=Blender.Object.Get('Plane')
objL=obj.getLocation()
print obj.name,"es un objeto situado en",objL
print "Otra forma de decirlo:",obj.loc
	

Ahora hacemos AltP y miramos en la consola, o ventana que se abre cuando ejecutamos Blender, o mejor aún, desde la cual hemos abierto blender escribiendo "blender.exe" o algo así. Si ha habido algún problema, ahí es donde aparecerá el error. Si no, nos aparecerá una frase informándonos de la posición que ocupa el objeto3d "Plane". En el caso de los Mac, es frecuente preguntar "dónde está la consola esa". Bien, hay una consola en el menú Utilities, en Terminal.
No creo que haya código más sencillo, pero creo que me toca explicarlo:

import Blender
	
Importa el módulo principal, con todos sus submódulos
obj=Blender.Object.Get('Plane')
	
la variable 'obj' apunta al objeto3D 'Plane'
objL=obj.getLocation()
	
la variable 'objL' recoge lo que devuelve la función .getLocation(), es decir, las coordenadas de 'obj'
print obj.name,"es un objeto situado en",objL
	
Aquí el nombre de 'obj' se toma como el atributo que contiene el nombre del objeto3D 'Plane', y se imprime también la variable objL, que es un vector de tres componentes
print "Otra forma de decirlo:",obj.loc
	
A la manera del nombre, el atributo 'objeto.loc' es una forma directa, sólo de lectura, de mostrar las coordenadas del objeto3D al que apunta 'obj'. Más rápida, pero menos recomendable.

La cosa parece, pues, que puede complicarse cuanto queramos. Pero no es mucho más que esto, pues todas las dudas aparecen al preguntarse si tal o cual cosa debe hacerse accediendo a un atributo del objeto para cambiarlo, a un método de este, o a una función del módulo "Blender.Object".
Para despejar algunas dudas, vamos a ejecutar este script:

from Blender import Object

obj=Object.Get('Plane')
print "Los métodos y atributos de un objeto3D son:\n",dir(obj)
print "\nLas funciones y variables del módulo Object son:\n",dir(Object)
	


from Blender import Object
	
importa sólo el submódulo Object, con lo que para llamarlo no es necesario escribir "Blender.Object" sino sólo "Object"
dir
	
Muestra lo que podemos poner tras el punto de un PyObjeto, o sea: atributos, métodos, funciones, variables...


Un poco más de objetos3D, y ya vale
Haremos un script ahora que manipula los objetos3D y añade algunos más, explicando el significado de cada paso nuevo.

Manipulación avanzada de objetos
from Blender import Object,Scene			 1
	
carga solamente los módulos Object y Scene
obj=Object.Get('Plane')					 2
objL=obj.getLocation()					 3
obj.setLocation(0,1,-1)					 4
cam=Object.Get('Camera')				 5
cam.setLocation(1,-2,0)					 6
#cam.SetEuler(90,0,20)					 7
	
como vemos, hasta ahora no hay nada que distinga la estructura de una malla y de una cámara, puesto que ambos son Objetos3D. La diferencia está en el tipo, y en el bloque de datos que va linkado a ellos.
Debemos estar siempre atentos a la evolución del API. En el momento de hacer este tutorial, hay varios bug que impiden que algunos atributos de objetos3D sean asignados con métodos ".set*", por eso la orden 7, como la 14, aunque correctas, está como comentario poniéndole el signo "#".
cam.RotZ=20 * 3.1416/180				 8
	
Esto nos da una excusa para asignar el ángulo con el atributo RotZ, que contiene el tercer ángulo de Euler (la orientación del objeto3D). Eso sí, internamente Blender guarda los ángulos en radianes, no en grados, por lo que aquí hay que introducirlos con el factor de propoción pi/180
me=obj.getData()					 9
	
Así es como se accede al famoso bloque de datos. Ahora me es un objeto de clase Mesh, "enganchado" al objeto 'obj' de clase Objeto3D.
obj2=Object.New('Mesh')					10
obj2.link(me)						11
	
En 10 creamos un nuevo objeto3D, de tipo Mesh, pero vacío: de momento tiene asignados valores Loc, Rot, Size, etc. estándar, pero sólo está en la memoria. En 11 lo "llenamos" con en bloque de datos 'me', con lo que se convierte en una nueva instancia del original 'obj'. A pesar de esto, aún no es visible porque no lo hemos puesto en ninguna escena.
sc=Scene.GetCurrent()					12
sc.link(obj2)						13
	
Este bloque es rutinario, y hay que acordarse de él: los objetos3D no se ven hasta que no están en una escena, no basta con crearlos: 12 asigna a 'sc' el objeto Scene (que contiene a todos los objeto3D de la escena) que tenemos en ese momento en pantalla, y 13 mete además en ella al objeto nuevo 'obj2'.

#obj2.setName('PlanoNuevo')				14
obj2.setLocation(0,1,1)					15
	
V.18,9,3 - © 2003 Carlos López
Escríbeme y dime algo... ¡tú puedes hacerlo!
Gracias a todos los reporteros de fallos que hacen que esto se vaya corrigiendo ;-)