Crear animaciones con Python en Blender

2 de enero de 2013

Es posible crear animaciones en Blender con ayuda de Python. Con Python un mesh puede:

Para crear animaciones en Blender se hace uso de keyframes. En un keyframe se puede definir la rotación, escala / tamaño y ubicación en los planos "x", "y" o "z" de un mesh.

En el ejemplo siguiente un mesh se desplaza en el plano de "y". La animación durará 60 frames / 5 segundos. Al mesh se le ha asignado el nombre "cubo". En el frame 1 el mesh está en la posición -8 en el plano de "y". En el frame 60 el mesh está en la posición 8 en el plano de "y". El resultado es el mesh moviéndose en el plano "y". Para ello se creará un keyframe en el frame 1 y se definirá la posición inicial en el plano de "y". También se creará un keyframe en el frame 60 y se definirá la posición final en el plano de "y".

El código Python para crear esta animación es:

bpy.data.objects["cubo"].location[1] = -8
bpy.data.objects["cubo"].keyframe_insert(data_path="location", frame=1, index=1)
bpy.data.objects["cubo"].location[1] = 8
bpy.data.objects["cubo"].keyframe_insert(data_path="location", frame=60, index=1)

Para utilizar el código Python en Blender se debe abrir la "Python console". En la "Python console" se puede escribir los comandos o simplemente copiarlos y pegarlos. Al final de cada línea se debe presionar la tecla ENTER para ejecutar el comando.

La Python Console en Blender

Este es el resultado:

Ahora explicaré línea por línea el código empleado. Con color se señala lo que no debe modificarse.

bpy.data.objects["cubo"].location[1] = -8

bpy.data.objects["cubo"] es la manera para referirnos a nuestro mesh y tener acceso a sus propiedades y métodos. En este caso al mesh se le ha asignado el nombre "cubo".

location es una propiedad de nuestro mesh y define la posición en el plano de "x", "y" o "z". En este caso se define la posición inicial en el plano de "y" y se le asigna el valor -8. El mesh se colocará en el punto -8 del plano de "y". Entre corchetes se escribe el plano a modificar: el número 0 corresponde al plano de "x", 1 corresponde al plano de "y" y el número 2 corresponde al plano de "z"

bpy.data.objects["cubo"].keyframe_insert(data_path="location", frame=1, index=1)

keyframe_insert() Crea un keyframe para nuestro mesh.

data_path define el tipo de transformación que sufrirá nuestro mesh, en este caso la propiedad a modificar es location / ubicación.

frame define el frame donde se creará el keyframe para nuestro mesh, en este caso el keyframe se creará en el frame 1.

index define el plano donde se realizará la transformación que sufrirá nuestro mesh: el número 0 corresponde al plano de "x", 1 corresponde al plano de "y" y el número 2 corresponde al plano de "z"

bpy.data.objects["cubo"].location[1] =8

location es una propiedad de nuestro mesh y define la posición en el plano de "x", "y" o "z". En este caso se define la posición final en el plano de "y" y se le asigna el valor 8. El mesh se colocará en el punto 8 del plano de "y". El resultado es que el mesh irá del punto -8 al punto 8 en el plano de "y". Entre corchetes se escribe el plano a modificar: el número 0 corresponde al plano de "x", 1 corresponde al plano de "y" y el número 2 corresponde al plano de "z"

bpy.data.objects["cubo"].keyframe_insert(data_path="location", frame=60, index=1)

keyframe_insert() Crea un keyframe para nuestro mesh.

data_path define el tipo de transformación que sufrirá nuestro mesh, en este caso la propiedad a modificar es location / ubicación.

frame define el frame donde se creará el keyframe para nuestro mesh, en este caso el keyframe se creará en el frame 60.

index define el plano donde se realizará la transformación que sufrirá nuestro mesh: el número 0 corresponde al plano de "x", 1 corresponde al plano de "y" y el número 2 corresponde al plano de "z"

Esta animación se puede hacer en Blender sin ayuda de Python. Pero la ventaja de usar Python es que facilita crear animaciones. ¿Qué tal si se quisiera animar no un mesh sino 50 mesh? ¿Qué tal si se quisiera que el mesh se desplazará no en 60 frames sino en 12 frames?

En este otro ejemplo la misma animación dura tan sólo 12 frames / 1 segundo:

bpy.data.objects["cubo"].location[1] = -8
bpy.data.objects["cubo"].keyframe_insert(data_path="location", frame=1, index=1)
bpy.data.objects["cubo"].location[1] = 8
bpy.data.objects["cubo"].keyframe_insert(data_path="location", frame=12, index=1)

Al cambiar el valor del frame donde se creará el keyframe se modifica la duración de la animación. Cualquiera que haya modificado la duración de una animación desde el "Dope Sheet" reconocerá y agradecerá la sencillez de realizar esta tarea con ayuda de Python.

En el siguiente ejemplo el mesh rotará sobre el eje "z" 360 grados y dará una vuelta completa. La animación durará 60 frames / 5 segundos.

El código Python para crear esta animación es:

bpy.data.objects["cubo"].rotation_euler[2] = 0
bpy.data.objects["cubo"].keyframe_insert(data_path="rotation_euler", frame=1, index=2)
bpy.data.objects["cubo"].rotation_euler[2] = 3.1416
bpy.data.objects["cubo"].keyframe_insert(data_path="rotation_euler", frame=60, index=2)

Este es el resultado:

En el siguiente ejemplo el mesh crecerá en el plano de y. La animación durará 60 frames / 5 segundos.

El código Python para crear esta animación es:

bpy.data.objects["cubo"].scale[1] = 1
bpy.data.objects["cubo"].keyframe_insert(data_path="scale", frame=1, index=1)
bpy.data.objects["cubo"].scale[1] = 5
bpy.data.objects["cubo"].keyframe_insert(data_path="scale", frame=60, index=1)

Este es el resultado:

Se puede hacer uso de iteraciones para animar varios mesh. Se puede combinar varias transformaciones (posición, rotación y escala) para lograr efectos más complejos.

En el siguiente ejemplo se duplica 12 veces un mesh existente. Los mesh duplicados se colocan y animan con Python. Cada mesh duplicado se desplaza en el plano de "y" y al mismo tiempo gira en el plano de "z".

El código Python empleado es:

		
#almacena en un array la posicion final en x de los cubos
cubos_xpos = [-0.7500001788139343,
-0.2500000596046448,
0.2500000596046448,
0.7500001788139343,
-0.7500001788139343,
-0.2500000596046448,
0.2500000596046448,
0.7500001788139343,
-0.7500001788139343,
-0.2500000596046448,
0.2500000596046448,
0.7500001788139343]


#almacena en un array la posicion final en y de los cubos
cubos_ypos = [2.2009620666503906,
3.0669872760772705,
3.9330127239227295,
4.799037933349609,
2.2009620666503906,
3.0669872760772705,
3.9330127239227295,
4.799037933349609,
2.2009620666503906,
3.0669872760772705,
3.9330127239227295,
4.799037933349609]


#almacena en un array la posicion final en z de los cubos
cubos_zpos = [1.0,
1.0,
1.0,
1.0,
0.0,
0.0,
0.0,
0.0,
-1.0,
-1.0,
-1.0,
-1.0]


#duplica 12 veces un cubo gris / mesh SELECCIONADO
#el cubo / mesh previamente ha sido creado con sus materiales correspondientes
for index in range(1, 13):
	xpos = cubos_xpos[index-1]
	#recupera la posicion en x desde el array
	ypos = cubos_ypos[index-1]
	#recupera la posicion en y desde el array
	zpos = cubos_zpos[index-1]
	#recupera la posicion en z desde el array
	bpy.ops.object.duplicate()
	#duplica el mesh SELECCIONADO
	nombre = "c" + str(index);
	#define el nombre del mesh
	bpy.context.object.name = nombre
	# bautiza el mesh
	bpy.context.object.location[0] = xpos
	# define la posicion en el plano x del mesh
	bpy.context.object.location[1] = ypos
	# define la posicion en el plano y del mesh
	bpy.context.object.location[2] = zpos
	# define la posicion en el plano z del mesh
	bpy.context.object.rotation_euler[2] = -0.5235989093780518
	#rota el mesh
	
	
#duplica 12 veces el contorno del cubo / mesh SELECCIONADO
#el cubo / mesh previamente ha sido creado con sus materiales correspondientes
for index in range(1, 13):
	xpos = cubos_xpos[index-1]
	ypos = cubos_ypos[index-1]
	zpos = cubos_zpos[index-1]
	# crea 8 cubos
	bpy.ops.object.duplicate()
	#duplica el mesh
	nombre = "s" + str(index);
	#define el nombre del mesh
	bpy.context.object.name = nombre
	#bautiza el mesh
	bpy.context.object.location[0] = xpos
	# define la posicion en el plano x del mesh
	bpy.context.object.location[1] = ypos
	# define la posicion en el plano y del mesh
	bpy.context.object.location[2] = zpos
	# define la posicion en el plano z del mesh
	bpy.context.object.rotation_euler[2] = -0.5235989093780518
	#rota el mesh


cubos =["c4", "c8", "c12", "c3", "c7", "c11", "c2", "c6", "c10", "c1", "c5", "c9"]
#almacena en un array el orden de animacion de los cubos grises


ypos_f1 = -7.245;
#define la posicion inicial en y de los cubos

frame_inicial =1;
#la animacion inicia en el frame 1


frame_final =10;  
#la animacion dura 10 frames

#con una iteracion se crea la animacion para los cubos grises
for item in cubos:
	y_final_pos = bpy.data.objects[item].location[1]
	# almacena la posicion final
	bpy.data.objects[item].location[1] = ypos_f1
	#define la posicion inicial en y del cubo
	bpy.data.objects[item].keyframe_insert(data_path="location", frame=frame_inicial, index=1)
	# crea un keyframe para el objeto seleccionado
	# data_path define el tipo de transofmacion
	#frame: frame donde se creara el keyframe
	# index define el eje de la transformacion
	bpy.data.objects[item].rotation_euler[2] = -3.6651989094
	#rotacion inicial en el plano z
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_inicial, index=2)
	#se crea un keyframe que almacena la rotacion en el plano z
	bpy.data.objects[item].rotation_euler[0] = 3.1416	
	#rotacion inicial en el plano x
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_inicial, index=0)	
	#se crea un keyframe que almacena la rotacion en el plano x	
	bpy.data.objects[item].location[1] = y_final_pos
	# define la posicion final en y para el objeto seleccionado
	bpy.data.objects[item].keyframe_insert(data_path="location", frame=frame_final, index=1)
	# crea un keyframe con la posicion final
	bpy.data.objects[item].rotation_euler[2] = -.5235989093780518
	#rotacion final en el plano z
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_final, index=2)
	#se crea un keyframe que almacena la rotacion en el plano z	
	#data_path: tipo de transformacion
	#frame: frame donde se creara el keyframe
	#index: plano en el que operara el cambio 0 = x; 1 = y; z = 2
	bpy.data.objects[item].rotation_euler[0] = 0
	#rotacion final en el plano x
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_final, index=0)	
	#se crea un keyframe que almacena la rotacion en el plano x	
	frame_inicial = frame_inicial + 5;
	#el siguiente cubo se animara 5 frames despues
	frame_final = frame_final +  10;
	#se define la duracion de la animacion del siguiente cubo

contornos =["s4", "s8", "s12", "s3", "s7", "s11", "s2", "s6", "s10", "s1", "s5", "s9"]
#almacena en un array el orden de animacion de los contornos

frame_inicial =1;
#la animacion inicia en el frame 1

frame_final =10;
#la animacion dura 10 frames

#con una iteracion se crea la animacion para los contornos
for item in contornos:
	y_final_pos = bpy.data.objects[item].location[1]
	# almacena la posicion final
	bpy.data.objects[item].location[1] = ypos_f1
	#define la posicion inicial en y
	bpy.data.objects[item].keyframe_insert(data_path="location", frame=frame_inicial, index=1)
	# crea un keyframe 
	# data_path define el tipo de transofmacion
	#frame: frame donde se creara el keyframe
	#index define el eje de la transformacion
	bpy.data.objects[item].rotation_euler[2] = -3.6651989094
	#rotacion inicial en el plano z
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_inicial, index=2)
	#se crea un keyframe que almacena la rotacion en el plano z
	bpy.data.objects[item].rotation_euler[0] = 3.1416	
	#rotacion inicial en el plano x
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_inicial, index=0)	
	#se crea un keyframe que almacena la rotacion en el plano x	
	bpy.data.objects[item].location[1] = y_final_pos
	# define la posicion final en y
	bpy.data.objects[item].keyframe_insert(data_path="location", frame=frame_final, index=1)
	# crea un keyframe con la posicion final
	bpy.data.objects[item].rotation_euler[2] = -.5235989093780518
	#rotacion final en el plano z
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_final, index=2)
	#se crea un keyframe que almacena la rotacion en el plano z	
	#data_path: tipo de transformacion
	#frame: frame donde se creara el keyframe
	#index: plano en el que operara el cambio 0 = x; 1 = y; z = 2
	bpy.data.objects[item].rotation_euler[0] = 0
	#rotacion final en el plano x
	bpy.data.objects[item].keyframe_insert(data_path="rotation_euler", frame=frame_final, index=0)	
	#se crea un keyframe que almacena la rotacion en el plano x	
	frame_inicial = frame_inicial + 5;
	#el siguiente cubo se animara 5 frames despues
	frame_final = frame_final +  10;
	#se define la duracion de la animacion del siguiente cubo


	

Este es el resultado:

Otra animación creada con Blender y Python:

El código Python empleado es:

import random, bmesh;

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# crea 16 colores
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


for index in range(1, 17):
	# crea 7 materiales con textura
	nombre_material = "material_" + str(index);
	# define el nombre del material
	bpy.data.materials.new(nombre_material);
	# crea un material y lo bautiza
	rojo = random.random();
	# define el tono de rojo del material al azar
	azul = random.random();
	# define el tono de azul del material al azar
	verde = random.random();	
	# define el tono de verde del material al azar
	bpy.data.materials[nombre_material].diffuse_color = (rojo,azul,verde);
	# define el "diffuse color" (color) del material
	bpy.data.materials[nombre_material].use_shadeless = 1;
	#desactiva las sombras

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# crea el color gris
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


nombre_material = "material_gris";
# define el nombre del material
bpy.data.materials.new(nombre_material);
# crea un material y lo bautiza
rojo = .8;
# define el tono de rojo del material al azar
azul = .8;
# define el tono de azul del material al azar
verde = .8;
# define el tono de verde del material al azar
bpy.data.materials[nombre_material].diffuse_color = (rojo,azul,verde);

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# crea 16 cubos, 
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


crea_cubo = bpy.ops.mesh.primitive_cube_add
#crea un cubo
xpos = 0
# define la posicion en el plano x del cubo
ypos = 0
# define la posicion en el plano y del cubo
zpos = 0
# define la posicion en el plano z del cubo
frame_inicial = 1
# define el frame inicial
frame_final = 10
# define el frame final

for index in range(1, 17):
	# crea una iteracion para crear 16 cubos
	crea_cubo(location=(xpos,ypos,zpos))
	# crea cubo en la posicion xpos,ypos,zpos
	material_a_usar = "material_gris"
	# selecciona el material a usar
	bpy.context.object.data.materials.append(bpy.data.materials[material_a_usar])
	# selecciona el cubo recien creado y le aplica el material
	material_a_usar = "material_"+ str(index)
	# selecciona el material a usar
	bpy.context.object.data.materials.append(bpy.data.materials[material_a_usar])
	# selecciona el cubo recien creado y le aplica el material
	bpy.ops.object.mode_set(mode = 'EDIT')
	# entra al modo de edicion
	bmesh.from_edit_mesh(bpy.context.object.data)
	#crea un bmesh
	bmesh.from_edit_mesh(bpy.context.object.data).select_mode = {'FACE'}
	#elige el modo de seleccion
	bpy.ops.mesh.select_all(action='TOGGLE')
	# deselecciona todo EN MODO DE EDIT
	bmesh.from_edit_mesh(bpy.context.object.data).faces[5].select_set(True) 
	#selecciona la cara 1
	bpy.context.object.active_material_index = 1
	#selecciona el material a emplear
	bpy.ops.object.material_slot_assign()
	#asigna el material a la cara seleccionada
	bpy.context.object.data.update()   
	#actualiza el mesh
	bpy.ops.object.mode_set(mode = 'OBJECT')
	# salir del modo de edicion
	bpy.context.object.keyframe_insert(data_path="location", frame=frame_inicial, index=2)
	# crea un keyframe para el objeto seleccionado
	bpy.context.object.location[2] = 5
	# define la nueva posicion en y para el objeto seleccionado
	bpy.context.object.keyframe_insert(data_path="location", frame=frame_final, index=2)
	# crea un keyframe para el objeto seleccionado
	bpy.context.object.rotation_euler[2] = 0
	bpy.context.object.keyframe_insert(data_path="rotation_euler", frame=frame_inicial, index=2)
	bpy.context.object.rotation_euler[2] = 3.1416
	bpy.context.object.keyframe_insert(data_path="rotation_euler", frame=frame_final, index=2)
	frame_inicial +=5
	#el siguiente cubo se animara 5 frames despues
	frame_final +=5
	#el siguiente cubo se animara 5 frames despues
	xpos += 3
	# tras crear el cubo modificamos la posicion en x para el siguiente cubo
	if index % 4 == 0:
		# si se colocaron 5 cubos se crea una nueva linea de cubos
		xpos = 0
		# se restablece la posicion en x
		ypos +=3	
		# modificamos la posicion en y para la siguiente linea


Otra animación creada con Blender y Python:

El código Python empleado es:


texturas = ["01.jpg",
"02.jpg",
"03.jpg",
"04.jpg",
"05.jpg",
"06.jpg",
"07.jpg",
"08.jpg",
"09.jpg",
"10.jpg",
"11.jpg",
"12.jpg",
"13.jpg",
"14.jpg",
"15.jpg",
"16.jpg"]
# crea un array para almacenar los texturas
# las texturas se guardan en la misma carpeta que el archivo .blend


import random, bmesh;

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# crea 16 materiales
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


for index in range(1, 17):
	# crea 16 materiales con textura
	nombre_material = "pic_" + str(index);
	# define el nombre del material
	bpy.data.materials.new(nombre_material);
	# crea un material y lo bautiza
	rojo = random.random();
	# define el tono de rojo del material al azar
	azul = random.random();
	# define el tono de azul del material al azar
	verde = random.random();	
	# define el tono de verde del material al azar
	bpy.data.materials[nombre_material].diffuse_color = (rojo,azul,verde);
	# define el "diffuse color" (color) del material
	bpy.data.materials[nombre_material].use_shadeless = 1;
	#desactiva las sombras
	archivo = "//"	+ texturas[index-1];
	#almacena el nombre del archivo
	imagen_original=bpy.data.images.load(filepath=archivo)	
	# importa el archivo
	nombre_textura = "nombre_textura_" + str(index);
	# define el nombre de la textura
	textura_creada = bpy.data.textures.new(nombre_textura, type = 'IMAGE')
	# crea la textura
	bpy.data.textures[nombre_textura].image = imagen_original
	# asigna el archivo a la textura
	textura_en_material = bpy.data.materials[nombre_material].texture_slots.add();
	#agrega un slot para textura
	textura_en_material.texture = textura_creada
	#asigna la textura al material
	textura_en_material.mapping = 'CUBE'
	# define el tipo de mapping

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# crea el color gris
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


nombre_material = "material_gris";
# define el nombre del material
bpy.data.materials.new(nombre_material);
# crea un material y lo bautiza
rojo = .8;
# define el tono de rojo del material al azar
azul = .8;
# define el tono de azul del material al azar
verde = .8;
# define el tono de verde del material al azar
bpy.data.materials[nombre_material].diffuse_color = (rojo,azul,verde);

# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
# crea 16 cubos, 
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *


crea_cubo = bpy.ops.mesh.primitive_cube_add
#crea un cubo
xpos = 0
# define la posicion en el plano x del cubo
ypos = 0
# define la posicion en el plano y del cubo
zpos = 0
# define la posicion en el plano z del cubo
frame_inicial = 1
# define el frame inicial
frame_final = 10
# define el frame final

for index in range(1, 17):
	# crea una iteracion para crear 16 cubos
	crea_cubo(location=(xpos,ypos,zpos))
	# crea cubo en la posicion xpos,ypos,zpos
	nombre = "c" + str(index);
	#define el nombre del mesh
	bpy.context.object.name = nombre
	#bautiza el mesh
	material_a_usar = "material_gris"
	# selecciona el material a usar
	bpy.context.object.data.materials.append(bpy.data.materials[material_a_usar])
	# selecciona el cubo recien creado y le aplica el material
	material_a_usar = "pic_"+ str(index)
	# selecciona el material a usar
	bpy.context.object.data.materials.append(bpy.data.materials[material_a_usar])
	# selecciona el cubo recien creado y le aplica el material
	bpy.ops.object.mode_set(mode = 'EDIT')
	# entra al modo de edicion
	bmesh.from_edit_mesh(bpy.context.object.data)
	#crea un bmesh
	bmesh.from_edit_mesh(bpy.context.object.data).select_mode = {'FACE'}
	#elige el modo de seleccion
	bpy.ops.mesh.select_all(action='TOGGLE')
	# deselecciona todo EN MODO DE EDIT
	bmesh.from_edit_mesh(bpy.context.object.data).faces[5].select_set(True) 
	#selecciona la cara 1
	bpy.context.object.active_material_index = 1
	#selecciona el material a emplear
	bpy.ops.object.material_slot_assign()
	#asigna el material a la cara seleccionada
	bpy.context.object.data.update()   
	#actualiza el mesh
	bpy.ops.object.mode_set(mode = 'OBJECT')
	# salir del modo de edicion
	bpy.context.object.keyframe_insert(data_path="location", frame=frame_inicial, index=2)
	# crea un keyframe para el objeto seleccionado
	bpy.context.object.location[2] = 5
	# define la nueva posicion en y para el objeto seleccionado
	bpy.context.object.keyframe_insert(data_path="location", frame=frame_final, index=2)
	# crea un keyframe para el objeto seleccionado
	bpy.context.object.rotation_euler[2] = 0
	bpy.context.object.keyframe_insert(data_path="rotation_euler", frame=frame_inicial, index=2)
	bpy.context.object.rotation_euler[2] = 3.1416
	bpy.context.object.keyframe_insert(data_path="rotation_euler", frame=frame_final, index=2)
	frame_inicial +=5
	#el siguiente cubo se animara 5 frames despues
	frame_final +=5
	#el siguiente cubo se animara 5 frames despues
	xpos += 3
	# tras crear el cubo modificamos la posicion en x para el siguiente cubo
	if index % 4 == 0:
		# si se colocaron 4 cubos se crea una nueva linea de cubos
		xpos = 0
		# se restablece la posicion en x
		ypos +=3	
		# modificamos la posicion en y para la siguiente linea

Están disponibles los archivos .blend de estos ejercicios para un análisis más detallado.

Sitios de interés

Sitio oficial de Blender

Sitio para descargar Blender. Blender es software libre - gratuito - y permite dibujar, animar y modelar en 3D para hacer imagenes, videojuegos y animaciones.

Tutorial de Python

Python es un lenguaje de programación. Uno de sus usos es trabajar con Blender.

La API de Python para Blender

Contiene las propiedades y métodos disponibles para Blender. Con Python se puede controlar todo en Blender.


Comenta y opina este texto     Lee mi libro de visitas
© 1997-2017 Alain García Gómez
albegago@hotmail.com
Twitter: @feesgo
El vínculo a este documento es:

Compartir en facebook Compartir en twitter Compartir en whatsapp Rss

Puedes apoyar a este sitio invitándome a comer...

Este sitio utiliza cookies propias y de terceros para mejorar sus servicios. Si continua navegando, entendemos que acepta su uso. Política de Privacidad