Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Creacion de Animaciones en Tiempo Real C
Creacion de Animaciones en Tiempo Real C
Dirección: Juventino Rosas y Jesús Urueta. Col. Los Mangos C.P. 89440 Cd. Madero,
Tamaulipas, México.
Teléfono: 215-85-44.
Nombre del Jefe de Unidad Académica: MP. Ma. Yolanda Chávez Cinco
Perfil: Computación
Participantes:
Nombre del alumno: Palomera Hervert Iván de Jesús Núm. Control: 04070694
Nombre del alumno: Hernández Ruiz Marco Polo Núm. Control: 04070789
NOTA: Este proyecto está perfilado para titulación por tesis (Opción I).
INDICE
Capítulo I. Introducción................................................................................................................. 5
1.1 Instituto Tecnológico de Ciudad Madero............................................................................ 5
1.1.1. Antecedentes............................................................................................................. 5
1.1.2. Maestría en Ciencias de la Computación .................................................................. 5
1.2 Información del Proyecto de Residencias ........................................................................... 6
1.2.1. Antecedentes .............................................................................................................. 6
1.2.2. Justificación ................................................................................................................. 6
1.3. OBJETIVOS .......................................................................................................................... 7
1.3.1. Objetivo General ......................................................................................................... 7
1.3.2. Objetivos Específicos................................................................................................... 7
1.4. Caracterización del Área .................................................................................................... 7
1.5. Problemas a Resolver......................................................................................................... 8
1.6. Alcances y Limitaciones...................................................................................................... 8
1.6.1. Alcances....................................................................................................................... 8
1.6.2. Limitaciones ................................................................................................................ 8
1.1.1. Antecedentes
La historia del Instituto Tecnológico de Cd. Madero inicia con la perseverante labor del
Ing. Luis Hidalgo y Castro quien concibió la idea de fundar una casa de estudios
técnicos que permitiera a los jóvenes de la región recibir una formación profesional del
más alto nivel sin tener que emigrar a otras ciudades.
Tras de vencer múltiples obstáculos de carácter político, económico y social, y con la
cooperación exclusiva de la gente de escasos recursos de esta ciudad, se hizo posible
reunir inicialmente la cantidad de 25 mil pesos, que fue el principio virtual del
Tecnológico de Cd. Madero. Posteriormente, gracias a la colaboración de las
Secciones Petroleras de la Zona Norte se logró reunir el primer millón de pesos del
patronato en 1950.
En el mes de septiembre de ese mismo año; El entonces Presidente de la República,
Lic. Miguel Alemán Valdés, autorizó el convenio tripartita en el que se establecería la
cooperación de PEMEX, la Secretaria de Educación Pública y el Patronato, cada uno
con un millón de pesos, para la construcción de nuestro instituto, bajo la supervisión
del Instituto Politécnico Nacional.
Después de 4 años, las clases dieron inicio el día 2 de septiembre de 1954 con 511
alumnos uniformados de guinda y blanco. En justo reconocimiento a su labor, la
superioridad otorgo el cargo de director al Sr. Ingeniero Luis Hidalgo y Castro.
Los cursos a nivel licenciatura iniciaron en 1956 con las carreras de Ingeniería
Eléctrica, Mecánica y Química. En 1961 se procedió a la apertura de Ingeniería
Industrial y en 1975 se iniciaron las carreras de Geología y Geofísica.
A mediados de la década de los 80's se abrieron las carreras de Ingeniería Electrónica
e Ingeniería en Sistemas Computacionales. La más reciente carrera, Lic. en
Informática dio inicio en septiembre de 1995.
En el año 2000, se inició un programa propio denominado originalmente Maestría en
Computación. Actualmente cambió de nombre a Maestría en Ciencias en Ciencias de
la Computación. Este programa cuenta con una sola línea de investigación de
optimización inteligente, donde se profundiza en problemas que por su complejidad,
requieren de encontrar soluciones óptimas, mediante los nuevos métodos de
computación inteligente.
1.1.2.1. MISIÓN
5
productivo y social del país; con capacidad de realizar investigación básica y aplicada,
así como desarrollos tecnológicos de alto nivel con impacto nacional e internacional en
al campo de la computación inteligente; sustenta los conocimientos científicos y
tecnológicos para atender la problemática del sector productivo nacional en las áreas
de Visión Computacional y Bases de datos distribuidas; forma grupos de investigación
y desarrollo que contribuyen a satisfacer la demanda nacional e impartir cátedra en el
campo de la computación.
1.1.2.3. OBJETIVO
1.2.1. Antecedentes
1.2.2. Justificación
Esta residencia podrá facilitar el trabajo futuro para los próximos proyectos de
maestría, disminuyendo esfuerzo en el proceso de animación de personajes y
facilitando el aprendizaje.
Así mismo, se identificaran las propiedades y funciones que trabajan con huesos y
Esqueletos para posteriormente crear una biblioteca de funciones con las cuales se
podrán manipular las diferentes partes del cuerpo de los personajes. Con esto
6
buscamos que éstos sean capaces de producir expresiones no verbales y puedan
llegar a generar una sensación de inmersión en un mundo virtual.
1.3. OBJETIVOS
7
1.5. Problemas a Resolver
Los problemas que se piensan resolver durante la realización de este proyecto son:
• La instalación del software que nos servirá de base para la manipulación de las
diferentes partes de un cuerpo, así como también la instalación del motor de
juego.
1.6.1. Alcances
1.6.2. Limitaciones
8
Capítulo II. Marco Teórico
2.1. Introducción
Este término nació a mediados de los 90’s y es relacionado especialmente con los
videos juegos de tipo combate en primera persona , cuyas siglas son FPS ( First-
person shooter). Los precursores de este nuevo modelo de programación de juegos y
aplicaciones 3d fue la compañía productora de video juegos idsoftware, con los
video juegos Quake y Doom para PC.
Un lenguaje que puede ser utilizado para controlar el comportamiento de una máquina,
particularmente una computadora. Consiste en un conjunto de símbolos y reglas
sintácticas y semánticas que definen su estructura y el significado de sus elementos y
expresiones.
9
2.3.1. Python
Python es un lenguaje de programación creado por Guido van Ros sum a principios de
los años 90 cuyo nombre está inspirado en el grupo de cómicos ingleses “Monty
Python”. Es un lenguaje similar a Perl, pero con una sintaxis muy limpia y que favorece
un código legible El tiempo del desarrollado es más importante que el tiempo del
procesamiento del programa; este lenguaje de programación es utilizado por La
Nasa en sus proyectos.
2.4. Animación 3D
Una animación 3d hace referencia a un tipo de animación que simula las tres
dimensiones. Se trata de la descripción de los objetos de un modelo 3d a lo largo del
tiempo. Para que exista animación, esa descripción debe variar en algo con respecto
al tiempo: movimiento de objetos y cámaras, cambio de luces y formas, etc. Puede
tratarse de una animación que se renderiza en tiempo real cuando se está ejecutando,
o una animación que utiliza tres dimensiones pero ya ha sido renderizada
previamente, por lo tanto sólo se trata de un video.
10
2.4.2. Ángulos de Euler
2.4.3. Definición
Dados dos sistemas de coordenadas xyz y XYZ con origen común, es posible
especificar la posición de un sistema en términos del otro usando tres ángulos α, β y γ.
La intersección de los planos escogidos se llama línea de nodos, y se usa para definir
los tres ángulos:
11
La intersección de los planos coordenados xy y XY se llama línea de nodos. Más
adelante se establecerá que los tres ángulos de Euler descritos son los valores de las
tres rotaciones intrínsecas que describen el sistema.
Otra forma de poder explicar la convención utilizada para poder manejar los ángulos
Euler en panda es la siguiente.
Z Y Y
+ - + - + -
X Z X
YAW PITCH ROLL
Estos sistemas de rotación a simple vista se observan sencillos, pero hay que tomar
en cuenta que al momento de rotar un solo eje afecta a los otros dos.
12
2.5. Modelado 3D
Los personajes virtuales son actores animados representados por medio de una
computadora que coexisten dentro de un universo virtual con la finalidad de interactuar
con el usuario. Existen dos tipos de personajes virtuales, los avatares, controlados por
un humano y los agentes virtuales inteligentes que tienen un comportamiento regido
por un diseño o fórmula computacional con un objetivo en específico.
13
2.6.1. Mundos Virtuales
14
2.7. Actores en Panda3D
La clase actor de Panda3D está diseñada para trabajar modelos animables y sus
animaciones.
No hay que confundir la clase de actor con la clase ActorNode, que se utiliza para la
física. Son completamente clases no relacionadas con nombres similares.
La clase de actor debe ser importado antes de cualquier carga o manipulación de los
actores.
from direct.actor.Actor import Actor
Una vez cargado el módulo, el objeto actor debe ser construido, y el modelo y las
animaciones debe cargarse:
2.8. Animaciones
Las animaciones puede ser jugadas una vez (play) o en bucle (loop). Cuando se
reproduce una animación en bucle la animación se reproduce de forma continua. No
hay interpolación entre el último y el primer cuadro, así que si la animación va a ser
puesto en loop, debe ser construido con esa idea en mente.
Usted puede usar pose() para decirle a un actor que mantenga una posición en
particular en la animación. Las posiciones son numeradas comenzando en 0.
15
actor.pose('Animation Name', FrameNumber)
actor.loop("reload", partName="torso")
2.9. Intervalos
El núcleo del sistema es la clase de intervalo. Hay varios tipos diferentes de intervalos,
que se discutirá en detalle en las páginas siguientes, pero todos ellos tienen en común
los siguiente: cada intervalo representa una acción (o una serie de acciones) que
ocurren durante un intervalo específico, finito de tiempo.
El poder real del sistema de intervalo viene a partir de secuencias y Parallels, que son
un tipo especial de intervalo que puede contener intervalos anidados de cualquier tipo
(incluidas las secuencias adicionales y / o paralelos). Mediante el uso de estos
16
intervalos de agrupación, usted puede fácilmente montar secuencias de comandos
complejas de los átomos de base.
Los Intervalos permiten que las animaciones de un actor se combinen con otros
intervalos, a través de secuencias y paralelismos.
myInterval = myactor.actorInterval(
"Animation Name",
loop=<0 or 1>,
contrainedLoop=<0 or 1>,
duration=D,
startTime=T1,
endTime=T2,
startFrame=N1,
endFrame=N2,
playRate=R,
partName=PN,
lodName=LN,
)
En cualquier módulo Panda3D que utiliza intervalos, primero debe importar el módulo
de intervalo:
from direct.interval.IntervalGlobal import *
interval.start()
interval.start(startT, endT, playRate)
interval.loop()
interval.loop(startT, endT, playRate)
Los tres parámetros son opcionales. Los parámetros startTime y del tiempo del fin
define el subconjunto del intervalo de jugar, que deben darse en los tiempos en
17
segundos, desde el inicio del intervalo. El parámetro playRate, si se especifica, permite
jugar un intervalo más lento o más rápido que en tiempo real, su valor por defecto es
1.0, para jugar en tiempo real.
interval.finish()
interval.setT(time)
interval.getDuration()
Devuelve la longitud del intervalo en segundos.
interval.getT()
Devuelve el tiempo transcurrido en curso dentro del intervalo, desde el comienzo del
intervalo.
interval.isPlaying()
Devuelve true si el intervalo se está reproduciendo, o false si no se inició, ya ha
terminado, o ha sido explícitamente una pausa o terminado.
interval.isStopped()
Devuelve true si el intervalo no se ha iniciado, ya ha jugado a su conclusión, o se ha
detenido explícitamente a través de acabado (). Esto no es lo mismo como (not
interval.isPlaying ()), ya que no devuelve true para un intervalo de pausa.
18
Capítulo III. Descripción del Proyecto
En este capítulo se describirán los requisitos que fueron necesarios para llevar a cabo
el presente proyecto de residencias.
"...es un modelo del comportamiento del sistema que puede ser usado para entenderlo
completamente o ciertos aspectos de él y así clarificar los requerimientos... Un
prototipo es una representación de un sistema, aunque no es un sistema completo,
posee las características del sistema final o parte de ellas"
El prototipo es una aplicación que funciona. La finalidad del prototipo es probar varias
suposiciones formuladas por analistas y usuarios con respecto a las características
requeridas del sistema. Los prototipos se crean con rapidez, evolucionan a través de
un proceso interactivo y tienen un bajo costo de desarrollo.
19
Razones para emplear los Prototipos
20
A continuación se describe la metodología general que se siguió en el desarrollo del
proyecto para la investigación de los métodos de Panda3d que manipulan las
animaciones y los huesos de actores:
1) Personajes virtuales,
2) Modelado y animación de objetos 3D y personajes
3) Software de modelado 3d
.
21
3.3. Análisis de los Requerimientos
Conexión a Internet
3.3.2. Software
22
Capítulo IV. Desarrollo del Proyecto
Las actividades que realizara el residente Marco Polo Hernández Ruiz se enfocaron
en la animación facial, tronco y cabeza:
23
4. Desarrollo de prototipo y documentación que ilustre el proceso de
animación de esqueletos.
5. Desarrollo de biblioteca de funciones que animan partes del cuerpo
tales como cara, tronco y cabeza.
6. Desarrollo de prototipo que ilustra el funcionamiento de la biblioteca
de funciones
En esta sección se dará una descripción de los procedimientos más significativos que
se realizaron al momento de desarrollar las residencias, así como también el proceso
de instalación del software utilizado en este proyecto.
Los pasos a seguir para poder utilizar este editor son los siguientes:
24
2.- Descomprimimos el archivo anteriormente descargado en la ubicación que
nosotros deseemos, esto será solo una carpeta.
3.- Dentro del folder de PyPE se encuentra el ejecutable llamado pype.exe, y solo
daremos un doble clic para poder abrir la ventana del editor.
25
4.2.1.2. Descarga e instalación de Panda3D
1.- Para poder descargar este motor de juego primeramente se tendrá que acceder a
la página que es la siguiente http://www.panda3d.org/
2.- Para poderlo descargar nos tendremos que ubicar en la pestaña que dice
Download y en la opción de SDK donde daremos clic.
26
3.- En la imagen anterior se puede observar las versiones de Panda3D y para los
sistemas operativos en los que se puede manejar. Nosotros ocuparemos la versión
1.7.0 para Windows.
4.- Cuando se haya descargado el ejecutable solo le daremos doble clic para poder
instalar el Panda3D.
27
6.- En esta ventana solo pide la aceptación de términos y condiciones de Panda3D.
28
8.- Y solo daremos en el botón de finalizar para que quede instalado y poderlo
utilizar.
Hay dos clases de Panda3D de geometría 3D: El "modelo", que es para la geometría
no-animados, y el 'actor', que es para la geometría de animación.
Hay que tener en cuenta que sólo se considera la geometría animada si cambia de
forma. Así, por ejemplo, una pelota de béisbol no se considera animado, puede volar
por todo el lugar, pero se mantiene una esfera. Una pelota de béisbol sería un modelo,
no un actor.
Este formato .egg es el que se maneja para poder ver las articulaciones que contiene
el actor a controlar.
29
fuerte, ya que los desarrolladores de Panda3D utilizan principalmente Maya. El
exportador de Max no es muy fiable ahora. Hay un tercer exportador para Blender, que
se dice que es bastante bueno. Esto es solo un comentario porque estos programas
son para poder crear los modelos y en este documento se manejaran actores ya
creados.
Aunque nosotros no utilizaremos muy afondo esto, si es necesario que podamos saber
cómo cargar el escenario y algunas cosas esenciales.
ambiente1 = loader.loadModel("models/environment")
environ = loader.loadModel("models/environment")
environ.reparentTo(render)
environ.setScale(0.25,0.25,0.25)
environ.setPos(20,90,-5)
run()
30
Figura 15: Muestra de escenario cargado
El poder manipular la cámara es otro de los puntos que tomaremos en cuenta para
poder enfocar o rotar sobre las imágenes.
Por defecto, Panda3D lleva a cabo una tarea que le permite mover la cámara
utilizando el ratón. Las claves para ello son:
• Botón Central: Hace girar la cámara en torno al modelo que fue cargado.
Se puede seguir adelante y tratar con este sistema de control de cámara. El problema
con este sistema de control de la cámara es que a veces es muy incómodo, no
siempre es fácil llevar a la cámara en la dirección que queremos.
31
En lugar de ello, vamos a utilizar una tarea que controla la posición de la cámara de
manera un poco más sencilla. Una tarea no es nada más que una subrutina que es
llamada en cada cuadro.
base.camera.setPos(20*math.sin(angleradians),-20.0*math.cos(angleradians),2)
base.camera.setHpr(angledegrees, 0, 0)
return Task.cont
taskMgr.add(SpinCameraTask, "SpinCameraTask")
Ahora se verá un ejemplo donde se utiliza una tarea para realizar el movimiento de la
cámara, utilizando también un escenario para observar el recorrido que hace la
cámara.
import direct.directbase.DirectStart
import math
def SpinCameraTask(task):
base.camera.setPos(20*math.sin(angleradians),
20.0*math.cos(angleradians),2)
base.camera.setHpr(angledegrees, 0, 0)
return Task.cont
32
TaskMgr.add(SpinCameraTask, "SpinCameraTask")
environ = loader.loadModel("models/environment")
environ.reparentTo(render)
environ.setScale(0.25,0.25,0.25)
environ.setPos(0,40,-5)
run()
33
Figura 18: Movimiento de cámara 2
Primero se carga la clase que contiene los métodos que permiten la utilización del
manejo de un actor, luego el actor y sus animaciones, para ser manipulados.
Como siguiente paso se verá cómo se carga un actor y las animaciones por medio del
método Actor.Actor
Sintaxis
Nombredelobjeto = Actor.Actor ("ruta de la carpeta donde está el modelo
/nombre del modelo ",
{"Nombre para ejecutar esa la animación ":"Carpeta donde está el modelo /nombre de
la animación del modelo ",
Ejemplo:
pandaActor = Actor.Actor("models/bvw-f2004--ralph/ralph",
{"walk":"models/bvw-f2004--ralph/ralph-walk",
"run":"models/bvw-f2004--ralph/ralph-run",
"jump":"models/bvw-f2004--ralph/ralph-jump"})
34
En las líneas anteriores se muestra cómo se puede cargar al actor y sus acciones.
Al utilizar el comando play la acción que se realiza es que el actor solo hace la
animación indicada una sola vez y luego se detiene.
Sintaxis:
Nombreobjeto.play(nombreanimacion)
pandaActor.play("run")
Al utilizar play con rango del frame (cuadro) en el que queremos que inicie al cuadro
en que deseamos que esta termine, hacemos que la animación solo realice este
movimiento una vez en el rango especificado.
Sintaxis:
Nombreobjeto.play(“nombreanimacion”, fromFrame = valor inicial , toFrame =
valor final)
pandaActor.play("jump", fromFrame = 0, toFrame = 90)
El comando loop al momento de ser aplicado a una de nuestras animaciones hará que
la animación seleccionada se realice de forma continua en un ciclo.
Y la sintaxis es la siguiente:
Nombreobjeto.loop(“nombreanimación”)
pandaActor.loop("run")
Sintaxis:
Nombreobjeto.pose(“nombreanimación”, valor del frame en el cual queremos que
se quede parado)
pandaActor.pose("run", 9)
El método stop al ser utilizado hace que la animación que está realizando el actor pare
quedándose inmóvil.
35
La sintaxis es:
Nombreobjeto.pose(“nombreanimación”)
pandaActor.stop()
Este código de ejemplo hace uso de la clase Actor, carga el modelo y sus
animaciones, le da una escala al modelo, lo coloca en una posición y lo manda
mostrar en la pantalla y le activa un ciclo continuo donde el actor va a estar corriendo
en el mismo lugar.
import direct.directbase.DirectStart
# No hay que olvidar poner la function run() por que sin esta la animación no correrá.
Cuando se carga a un actor éste puede realizar movimientos que pueden ser
manejados o manipulados por medio del teclado o ratón, pero para poder empezar a
manejar eventos que son producidos por el ratón o teclado se necesita importar la
clase DirectObject, con lo cual ya se puede usar el método accept el cual activa un
evento y realiza una llamada a una función, los nombre de eventos disponibles son los
nombres de las letras del teclado y los botones del ratón.
36
Ejemplo del uso del método accept.
Nombreobjeto.accpet(“nombre de evento”, función)
pandaActor.accept("3",llamaanimacion2)
37
4.2.8. Animación de Actores
El cuerpo del actor está compuesto por varios huesos y uniones entre ellos llamados
joints, estos vienen simulando o representando las articulaciones de los huesos del
cuerpo humano, para poder dar forma y movimientos más reales o similares. Pero los
problemas con los que podemos toparnos es que al momento de dar movimiento estas
articulaciones rebasen el límite de lo que el cuerpo humano sería capaz, así que
primeramente se tendera que buscar la orientación de los joints para saber cómo
poder manipularlos y así dar un límite de movimiento.
Cuello
Hombro Hombro
Derecho Izquierdo
Codo
Codo
Izquierdo
Derecho
Cadera Cadera
derecha Muñeca Muñeca Izquierda
Derecha Izquierda
Mano Mano
Derecha Izquierda
Rodilla
Rodilla
Izquierda
Derecha
Tobillo
Tobillo Izquierdo
Derecho
Parpado
Parpado
Derecho
Izquierdo
Mejilla Mejilla
Derecho Izquierda
Labio
Superior
Parpado
derecho
38
Tomando en cuenta que es tanta la información que se tiene para poder realizar
movimientos con un actor solo veremos los puntos más importantes y después nos
enfocaremos en lo que es la manipulación de los huesos.
En este tema nos enfocaremos más a la manipulación de los actores y los métodos
que pueden ser utilizados.
Para comenzar se tiene que dar a conocer que hay dos métodos para revelar las
articulaciones, controlJoint y exposeJoint. Cada uno tiene un argumento 'Modelo
Nodo', que es generalmente la cadena, "modelRoot.". Asimismo, ambos quieren el
nombre de la articulación. Usted puede ver el nombre del hueso en un paquete de
modelado, o buscar una cadena como <Joint> dentro de un archivo egg.
Como ya se explicó anterior mente el archivo .egg es el que contiene las articulaciones
o joint del actor a manipular.
39
Para poder ver los efectos el actor debe estar en alguna acción como pude ser
caminar.
Ralph = Actor.Actor("ralph",
{"camina":"ralph-walk"}) ## acción del actor
Ralph.setScale(1,1,1)# Escalar
Ralph.setPos(0,5,-1)#Posicionar
Ralph.setHpr(0,0,0)#Rotar
Ralph.reparentTo(render)
4.2.9.2. ExposeJoint
Esto crea una nueva NodePath de la NodePath del actor que sostiene el conjunto.
40
mano_derecha = Ralph.exposeJoint(None, 'modelRoot', 'RightHand')
mano_izquierda = Ralph.exposeJoint(None, 'modelRoot', 'LeftHand')
sword = loader.loadModel("sword") #cargar el modelo
sword.setScale(.5) #Escala el modelo
sword.setHpr(90,0,90) #orienta el modelo en grados
sword.reparentTo(mano_derecha)# en esta línea se agrega la espada a la mano
derecha
candycane = loader.loadModel("candycane")
candycane.setScale(1)
candycane.setHpr(0,0,90)
candycane.reparentTo(mano_izquierda)
Ralph.accept("escape",sys.exit)
4.2.9.3. ControlJoint
Para poder realizar los movimientos con este método es importante saber las
orientaciones de cada joint o articulación del actor, estas orientaciones serán
mostradas cunando se manipulen cada uno de los joints por separado.
41
El método controlJoint es utilizado para poder controlar las articulaciones que
contenga el actor. En este método existen varias funciones que se pueden utilizar, a
continuación se mencionaran las que utilizaremos.
Pos()
Una de las formas en que se pueden manipular las articulaciones de los actores es
cuando esta se cambia de posición, la función que se utilizara será setPos(). A
continuación se mostrara con una pequeña parte del código lo que se puede hacer.
De igual manera se tiene que hacer uso de la función controlJoint para tener un tipo de
acceso a la articulación que se desee manipular. Se tiene que recordar que la
posición de la articulación se da en el plano x,y,z.
cuello = Ralph.controlJoint(None, 'modelRoot','Neck')
def mueve_cuello():
cuello.setPos(2,-5,2)## Posición de la articulación
42
Hay que recordar que la función Pos() es para posicionar la articulación y es por eso
que se puede llegar a deformar el actor.
Hay diversas formas de poder manipular los huesos del actor, esto puede ser con
getPos() que sirve para posicionar el hueso o también con getHpr() que sirve para
orientar la parte del cuerpo que se desee cambiar.
Los valores utilizados para estas funciones son los grados, utilizando las coordenadas
en 3D y viendo cómo están orientados los huesos del actor.
Con la función getHpr() es posible manejar los tres valores xyz al mismo tiempo, pero
también es posible manejarlo por separado, hay que tener en cuenta que el tipo de
grados que se manejan en este caso serán los grados eurelianos. Con esto tenemos
que el valor asignado a H corresponde a x, el de P corresponde a y y el valor de R es
el valor de z.
43
menton = Ralph.controlJoint(None,'modelRoot','Jaw')
brazoDerecho = Ralph.controlJoint(None,'modelRoot','RightShoulder')
brazoIzquierdo = Ralph.controlJoint(None,'modelRoot','LeftShoulder')
tobillo_derecho = Ralph.controlJoint(None, 'modelRoot', 'RightAnkle')
def mueve_brazoDerecho():
i=20+brazoDerecho.getH()
brazoDerecho.setH(i)
def mueve_menton():
i=20-Menton.getH()
Menton.setH(i)
def mueve_labio():
i=20-Labio_superior.getH()
Labio_superior.setH(i)
44
def mueve_parpadoDerecho():
k=90-parpado_derecho.getP()
parpado_derecho.setP(k)
def mueve_parpadoIzquierdo():
k=90-parpado_izquierdo.getP()
parpado_izquierdo.setP(k)
def mueve_manoDer():
i=-20-mano_derecha.getR()
mano_derecha.setR(i)
def mueve_manoIzq():
i=-20+mano_izquierda.getH()
j=-90+mano_izquierda.getP()
k=-20+mano_izquierda.getR()
mano_izquierda.setHpr(i,0,k)
def mueve_tobillo():
i=10+tobillo_derecho.getH()
tobillo_derecho.setHpr(i,0,0)
Ralph.accept("escape",sys.exit)
Ralph.accept("1",mueve_manoDer)
Ralph.accept("2",mueve_manoIzq)
Ralph.accept("3",mueve_parpadoDerecho)
Ralph.accept("4",mueve_parpadoIzquierdo)
Ralph.accept("5",mueve_labio)
Ralph.accept("6",mueve_tobillo)
Ralph.accept("7",mueve_menton)
Ralph.accept("8",mueve_brazoDerecho)
Ralph.accept("9",mueve_brazoIzquierdo)
run()
45
Variantes de la Hpr().
Este tema se enfoca más que nada en la función del Hpr() y las variantes que puede
llegar a tener en su utilización, las dos formas que se analizaron son al manejar los
tres movimientos del eje cartesiano en una sola función y la otra es manejando los
movimientos por separado en cada uno de los ejes.
def mueve_hombroIzquierdoP(self):
i=-90+self.hombroIzquierdo.getP()
self.hombroIzquierdo.setP(i)
def mueve_hombroIzquierdoR(self):
i=-90+self.hombroIzquierdo.getR()
self.hombroIzquierdo.setR(i)
46
En el código anterior se muestra que en donde se define mueve_hombroIzquierdo,
solo se está enviando a que el hombro de la animación sea manipulada sobre el eje x,
no hay que dejar pasar que los movimientos de los ejes no serán sobre ejes
cartesianos, si no que por los ángulos Eurelíanos.
def mueve_hombroIzquierdo2(self):
self.hombroIzquierdo2.setHpr(-90,-90,-90)
(En este fragmento de código se le está enviando que el movimiento se tiene que
hacer en los tres ejes al mismo tiempo).
En la imagen anterior se observa el movimiento del brazo derecho de cada una de las
animaciones, el movimiento de la animación de la derecha fue hecho con una sola
función en cambio el movimiento de la animación de la izquierda se realizó en tres
pasos donde primero se hizo el movimiento en el eje X, luego en el eje Y, y finalmente
en el eje Z.
47
Para lograr que dos animaciones quedaran en la misma posición en la animación de la
izquierda se calcularon los grados que se tenía que mover la extremidad en cada eje,
ya que cuando una animación se manda a llamar esta ya viene con los grados de cada
extremidad ya establecidos.
48
4.2.3. Manipulación de Todas las Partes del Cuerpo
En esta sección se explicará cómo se pueden manipular las partes del cuerpo del
actor para dar la posición que más deseemos.
Inicialmente el actor tiene una posición un tanto extraña, pero con algunas funciones
en sus articulaciones le daremos una postura un más seria.
En la imagen anterior se puede apreciar que el brazo izquierdo del actor está en una
posición hacia atrás, lo que se realizará en seguida será darle una posición con ambos
brazos hacia abajo.
Para poder saber como y hacia donde realizar los movimientos de los brazos se tienen
se tomaron las orientaciones de cada cuna de las articulaciones que pueden afectar el
movimineto de ambos brazos.
Analizando cada joint por separado se pudieron observar sus coordenadas, esto
permitirá que al momento de querer hacer los movimientos sea más fácil saber sobre
que eje o ejes rotar la articulación.
En esta extremidad se pueden observar las articulaciones del hombro, codo, muñeca y
mano.
49
Z
X
-Y Y
-X
-Z
X
Z
-Y Y
-Z
-X
Y
Z
-X X
-Z
-Y
X
-Z
y
-Y
-X
50
Estas son las funciones que se ocuparon para poder saber la posición inicial de las
articulaciones en este caso serán las del hombro izquierdo.
def mueve_codoIzquierdo(self):
self.codoIzquierdo.setHpr(0,0,0 )
## Esta línea se manda las coordenadas en cero de cada uno de los ejes
def mueve_hombroIzquierdo(self):
self.hombroIzquierdo.setHpr(0,0,0)
## esta línea manda la ubicación en cero de cada una de las coordenadas
para el hombro derecho.
51
A si que para llegar al resultado de la imagen siguiente se tuvo que aumentar los
grados para lograr la posición deseada, todo esto con la siguiente función.
def mueve_codoIzquierdo(self):
self.codoIzquierdo.setH(180
def mueve_hombroIzquierdo(self):
self.hombroIzquierdo.setHpr(180,0,0)
Para poder mostrar estos movimientos se usa una función cuya acción será de la ida y
retorno, trabajaremos con el mismo actor pero ahora mostraremos como limitar los
movimientos.
52
A continuación se mostrara la función que hace que el movimiento sea limitado en los
grados.
def mueve_manoDer(self):
self.mano_derecha.setR(i)
En las imágenes anteriores los huesos que se manipularon son los de la muñeca
derecha y de igual forma se limita en el movimiento, su función es la siguiente.
def mueve_munecaDer(self):
i=-60-self.muneca_derecha.getP()
## En esta función se está manipulando los huesos en el eje y
self.muneca_derecha.setP(i)
53
En la secuencia de imágenes anterior se trata de mostrar el movimiento de la mano
izquierda, pero este movimiento es un tipo de secuencia la cual se maneja en los ejes
de X y Z. La función aplicada es la siguiente.
def mueve_manoIzq(self):
i=-20+self.mano_izquierda.getH()
k=-20+self.mano_izquierda.getR()
self.mano_izquierda.setHpr(i,0,k)
i=-60-self.muneca_izquierda.getR()
self.muneca_izquierda.setHpr(i)
54
4.2.3.3. Manipulación de Pierna, Rodilla y Tobillo
Los joints que se encargan de la manipulación de las piernas son los que representan
las caderas, así que se observara que estos están en el área del tronco del cuerpo
como a continuación se muestra en la siguiente imagen.
X
-Y X -Y
-Z
-Z Z
Z
Y Y
-X -X
Las articulaciones de las piernas las componen las rodillas y los tobillos, estas
articulaciones tienen las mismas orientaciones como a continuación se muestra en la
imagen siguiente.
- -
- -
X - X -
Z Z
Y Y
- -
- -
X - X -
Z Z
Y Y
55
Inicialmente la posición de las piernas son las comunes cuando una persona esta de
pie.
Sacando las coordenadas de la posición de las piernas, rodillas y tobillos estas están
en ceros en los tres ejes lo que hace más fácil su manipulación.
56
Habiendo analizando anteriormente cuales son los ejes (por qué no todos los huesos
tienen la misma orientación) se observó que los ejes a manipular son el Y y Z.
i=90-self.rodilla_izquierda.getP()
self.rodilla_izquierda.setP(i)
57
La imagen anterior muestra la mitad de la acción que se quiere realizar, y el
movimiento del tobillo fue posible con la siguiente función.
def mueve_tobilloIzquierdo(self):
i=100-self.tobillo_izquierdo.getP( )
##El eje en el que es realizada la acción es en el eje Y .
self.tobillo_izquierdo.setP(i)
58
Esto se logra con la siguiente función.
def mueve_cuello(self):
i=-30-self.cuello.getH()
self.cuello.setHpr(i,0,0)
self.cuello.setHpr(i,0,0)
i=50-self.cuello.getP()
self.cuello.setHpr(0,i,0)
59
Pero si el movimiento que se quiere es hacia la derecha se utilizara la función
siguiente.
def mueve_cuello(self):
i=-50-self.cuello.getP()
self.cuello.setHpr(0,i,0)
Y finalmente cuando el movimiento que se desea es hacia los laterales el eje que se
ocupara será el eje Z, y dependiendo del lado que se quiera mover el cuello será la
función que se defina.
i=-30-self.cuello.getR()
self.cuello.setHpr(0,0,i)
Y la acción es la correspondiente a la
siguiente imagen.
i=30-self.cuello.getR()
self.cuello.setHpr(0,0,i)
60
4.2.3.5. Movimiento de los Parpados
Para poder saber cómo manipular cada uno de las articulaciones que existen en la
cara también fue necesario poder sacar la orientación década uno de los huesos que
se encuentran en el rostro, a continuación se muestran los joints encontrados con sus
respectivas orientaciones.
En el rostro se encuentran varias articulaciones como son: los parpados, las mejillas,
el labio superior y la barbilla.
Como se puede observar en la imagen siguiente los parpados tienen las mismas
orientaciones en los parpados, de igual forma las orientaciones de las mejillas son las
mismas y finalmente las orientaciones del labio superior y de la barbilla son similares.
61
Como se puede notar el parpado derecho tiende a deformarse y la textura de este no
logra cubrir todo el ojo, así que para mostrar lo que se puede hacer manejaremos el
parpado izquierdo.
i=90-self.parpado_izquierdo.getP()
self.parpado_izquierdo.setHpr(0,i,0)
62
Lo que se trata de hacer es hacer simulación donde la majilla izquierda se mueva en
una forma vertical de arriba hacia abajo con la siguiente función.
def mueve_mejillaIzquierda(self):
i=-200-self.mejillaIzquierda.getR()
self.mejillaIzquierda.setR(i)
Movimiento de la barbilla.
En esta articulación el movimiento será manipulado sobre el eje X, esto simulara como
si el actor estuviese abriendo la boca, pero solo que habrá un pequeño problema con
la textura ya que esta cubre lo que son los dientes, y el movimiento solo se podrá notar
por la parte lateral del actor.
63
Movimiento del labio superior.
Este es el último hueso a manipular en el rostro del actor y es algo simple y sencillo,
ya que este movimiento se hará sobre el eje X como el de la barbilla y será con la
siguiente función.
def mueve_labio(self):
i=20-self.Labio_superior.getH()
self.Labio_superior.setH(i)
Manteniendo la imagen anterior del actor con la barbilla hacia abajo manipularemos el
labio para que sea un poco más visible.
Con esto terminamos con la manipulación de cada una de las articulaciones que tiene
este actor y a continuación se mostrara el programa completo.
import direct.directbase.DirectStart
from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import Filename,AmbientLight,DirectionalLight
from panda3d.core import PandaNode,NodePath,Camera,TextNode
from panda3d.core import Vec3,Vec4,BitMask32
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
from direct.showbase.DirectObject import DirectObject
import random, sys, os, math
64
## En las siguientes cuatro líneas se cargara al actor, también se cargara una
## de las acciones que puede realizar como lo es el caminar, tambien se escala
## al actor se posiciona en la pantalla y finalmente se carga.
self.ralph = Actor("ralph",{"camina":"ralph-walk"})
self.ralph.setScale(1)
self.ralph.setPos(0,5,-1)
self.ralph.reparentTo(render)
## También es podsible agregar objetos a los joints, como se ha visto
##anterior mente.
self.manoDerecha = self.ralph.exposeJoint(None, 'modelRoot',
'RightHand')
self.floater = NodePath(PandaNode("floater"))
self.floater.reparentTo(render)
self.accept("escape", sys.exit)
self.accept("arrow_left", self.setKey, ["cam-left",1])
self.accept("arrow_right", self.setKey, ["cam-right",1])
self.ralph.accept("r",self.mueve_rodillaIzquierda)
self.ralph.accept("t",self.mueve_tobilloIzquierdo)
self.ralph.accept("p",self.mueve_parpadoDerecho)
self.ralph.accept("o",self.mueve_parpadoIzquierdo)
self.ralph.accept("l",self.mueve_labio)
self.ralph.accept("z",self.mueve_cuello)
self.ralph.accept("b",self.mueve_barbilla)
self.ralph.accept("8",self.mueve_brazoDerecho)
self.ralph.accept("9",self.mueve_hombroIzquierdo)
self.ralph.accept("p",self.mueve_parpadoDerecho)
self.ralph.accept("i",self.mueve_codoIzquierdo)
65
self.ralph.accept("n",self.mueve_mejillaIzquierda)
self.ralph.accept("m",self.mueve_mejillaDerecha)
self.ralph.accept("v",self.animacion_camina)
self.ralph.accept("q",self.pose_inicial_ralph)
taskMgr.add(self.move,"moveTask")
## Se definen cada una de los metodos a realizar.Estos metodos son cada uno de
##los movimientos que el actor podrarealizar.
def pose_inicial_ralph(self):
self.ralph.pose("camina",6)
def animacion_camina(self):
self.ralph.loop("camina")
def mueve_mejillaDerecha(self):
i=-200-self.mejillaDerecha.getR()
self.mejillaDerecha.setR(i)
def mueve_mejillaIzquierda(self):
i=-200-self.mejillaIzquierda.getR()
self.mejillaIzquierda.setR(i)
def mueve_cuello(self):
66
i=30-self.cuello.getR()
self.cuello.setHpr(0,0,i)
def mueve_caderaIzquierda(self):
i=140-self.cadera_izquierda.getR()
self.cadera_izquierda.setHpr(0,60,i)
def mueve_rodillaIzquierda(self):
i=90-self.rodilla_izquierda.getP()
self.rodilla_izquierda.setP(i)
def mueve_tobilloIzquierdo(self):
i=90-self.tobillo_izquierdo.getP()
self.tobillo_izquierdo.setP(i)
def mueve_codoIzquierdo(self):
self.codoIzquierdo.setH(180)
def mueve_hombroIzquierdo(self):
self.hombroIzquierdo.setHpr(180,0,0)
def mueve_brazoDerecho(self):
i=20+self.brazoDerecho.getH()
self.brazoDerecho.setHpr(i,0,0)
def mueve_barbilla(self):
i=-90-self.barbilla.getH()
self.barbilla.setH(i)
def mueve_labio(self):
i=20-self.Labio_superior.getH()
self.Labio_superior.setH(i)
def mueve_parpadoDerecho(self):
i=90-self.parpado_derecho.getP()
self.parpado_derecho.setHpr(0,i,0)
def mueve_parpadoIzquierdo(self):
i=90-self.parpado_izquierdo.getP()
self.parpado_izquierdo.setHpr(0,i,0)
def mueve_manoDer(self):
i=-60-self.mano_derecha.getR()
self.mano_derecha.setR(i)
def mueve_manoIzq(self):
i=-20+self.mano_izquierda.getH()
k=-20+self.mano_izquierda.getR()
self.mano_izquierda.setHpr(i,0,k)
def mueve_munecaDer(self):
i=-60-self.muneca_derecha.getP()
self.muneca_derecha.setP(i)
def mueve_munecaIzq(self):
i=-60-self.muneca_izquierda.getR()
self.muneca_izquierda.setHpr(i)
67
def setKey(self, key, value):
## En las siguientes lineas se definen los movimientos que realizará la
##camara.
self.keyMap[key] = value
return task.cont
w = World()
68
Capítulo V. Resultados y Conclusiones
5.1. Resultados
5.2. Conclusiones
Las conclusiones a las cuales se llegaron durante el desarrollo de este proyecto son
que Panda 3D es un programa que es sencillo de aprender a manejar y que
proporciona muchas facilidades en el desarrollo de animaciones en 3D.
El proyecto puede ser retomado más adelante para seguir desarrollando las
animaciones y buscarles un fin específico, es decir que no solo nos quedemos con las
animaciones y sus respectivas manipulaciones, sino que nos sirvan mas adelante para
el desarrollo de aplicaciones interactivas en un mundo virtual.
69
Bibliografía
[7]http://www.google.com.mx/search?hl=es&q=caracteristicas+motor+de+juego&meta=
Es el componente de software central de un video juego que maneja todos los
elementos.
[11]http://www.ub.edu.ar/catedras/ingenieria/ing_software/ubftecwwwdfd/mids_web/prot
otyp/estrdes.htm Estrategia de Desarrollo por Prototipos. Metodología integral de
desarrollo de sistemas. Lic. Domingo F. Donadello. Universidad de Belgrano, Buenos
Aires-Argentina.
70