Entradas populares

domingo, 27 de abril de 2014

crear y parsear textos y direcciones de fichero con python

Muchas veces tenemos que crear cadenas de texto a partir de variables que tenemos, estas cadenas de texto pueden ser  lineas en un archivo, expresiones o direcciones de archivos por ejemplo, muchas veces el modo normal de hacerlo es crear un pattern para esa linea y reemplazar las etiquetas por variables, por ejemplo, si queremos crear en un archivo para configurar las variables de entorno podemos tener una clase para crear un pattern parecido a 

self.pattern ='export <ENVVARNAME>=<ENVVARVALUE>'

y reemplazamos las etiquetas por el valor que nos interese, por ejemplo

self.ENVVARNAME='MAYA_VERSION'
self.ENVVARVALUE='2014'

line=self.solvePattern()

si tenemos el método solvePattern que nos busque todas las variables que hay en la clase y si esta en el patter nos la sustituya por su valor, al final tendremos la linea como la queremos

export MAYA_VERSION=2014

esto es bastante fácil de hacer, pero que pasa si queremos hacer al reves?? si lo que queremos es parsear ese archivo de configuración para ver que variables de entorno setea?

pues para ello contamos con la librería re, para comparar cadenas de texto con expresiones. Nosotros ya tenemos el patter de la linea de texto, y lo que queremos es convertir ese pattern en la expresión con la que lo queremos comparar las lineas del archivo. para ello realizamos dos sustituciones en la cadena de texto

tempExpresion=self.ppatern.replace('<','(?p<')
self.expression=tempExpresion.replace('>','>)')

con esto nuestro texto sera una expresion como esta

export (?p<ENVVARNAME>)=(?p<ENVVARVALUE>)

y si lo utilizamos en una comparacion en el modulo re

import re

outDict=re.match(currentLine,self.expression)

si tenemos una coincidencia outDict sera no None y nos devolverá un diccionario con dos keys, una sera ENVVARNAME y otra ENVVARVALUE y sus correspondientes valores

Esto que aqui parece algo interesante pero no muy util en principio, cuando lo aplicamos a los archivos nos encontramos que nos ofrece unas oportunidades enormes para buscar y navegar por los archivos que nos interesen y conseguir los datos que nos interesan de ese fichero, es decir, podemos hacer consultas y filtrar resultados como si de una base de datos se tratase. Para ello lo que tenemos que hacer es que el archivo sea creado a partir de un patter que nos defina la dirección del archivo, estilo

/<projecto>/<secuencia>/<plano>/modelado/<personaje>/v<version>/<formato>/<personaje>_v<version>.<formato>

con esto, navegando recursivamente cada nivel de las carpetas y comparandolas con el mismo nivel del pattern podemos conseguir todos los datos de cada archivo en forma de diccionario, con ello tenemos una lista de diccionarios que cada uno nos da informacion de un archivo, como si fuese una base de datos

Pero que pasa si queremos un(os) archivos en concreto?, por ejemplo, queremos todas las versiones del personaje "principal", pues aplicamos la primera parte de lo que hemos hablado hoy, solucionamos el pattern con los valores que tenemos, por lo tanto si seteamos el valor personaje a "principal" y lo reemplazamos en el pattern este sera 
  

/<projecto>/<secuencia>/<plano>/modelado/principal/v<version>/<formato>/principal_v<version>.<formato>

con lo que solo seran encontrados los archivos que coincidan en ese pattern que seran solo las versiones que hay de ese archivo  en los distintos planos


de este modo, el mismo formato que utilizamos para la creacion de las direcciones de los archivos nos vale tambien para hacer consultas a los directorios como si fuese una base de datos










miércoles, 23 de octubre de 2013

Creacion de interfaces para las herramientas

Creacion de interfaces para las herramientas

Uno de los problemas cuando intentamos hacer una interface para una herramienta ya sea en maya o en nuke es el refresco de los datos que mostramos en la interface y las posibles diferencias que puede haber entre los datos que mostramos y los que realmente hay en el programa.

Voy a comentar un metodo de creacion de interfaces que nos permite el tener en todo momento actualizado los datos con el programa y es el que estoy utilizando tanto en Maya como en Nuke

Normalmente hacemos las interfaces en pyqt o pySide, y hacemos sus conexiones mediante las senhales que emite pyqt, podemos utilizar estas senhales para actualizar las interfaces si conseguimos que el programa emita las senhales que queremos

Para ello creamos una clase, que podremos utilizar luego en todas las interfaces que hagamos, esta clase lo que hara sera conectar, en el caso de maya por ejemplo, los callbacks de maya mediante el api en python con signals de pyqt, por ejemplo, hacer que emita un signal "newNode" cada vez que se crea un  nuevo nodo, otro cada vez que se cambia un atributo, etc. en nuke podemos hacer lo mismo de un modo muy parecido

Una vez que tenemos esas clases, las utilizamos de modo que sean las senhales las que lancen los metodos que actualizan la interface, nunca una accion de la herramienta actualiza la interface, la interface se sincroniza con lo que tengamos en maya siempre, y las acciones que tengamos en la herramienta trabajan directamente contra maya, no se preocupan en ningun momento de la interface, las acciones modifican algo en maya y mediante la clase que hemos definido se actualiza la herramienta, si modificamos algo en maya directamente se ve reflejado en la interface evitando muchos problemas


Este es un ejemplo de interface compleja usando esa tecnica, tanto el sistema nodal como el editor se actualizan directamente desde maya, y las acciones que hacemos en la interface solo se preocupan de realizar el trabajo





jueves, 1 de noviembre de 2012

generando pipelines desde ficheros de configuracion

Voy a comentar algo sobre el proyecto en que estoy ahora desarrollando en Blue bolt, los primeros dias me explicaron la idea que tenian ellos para publicacion de assets o mejor dicho de publicacion de bundles (grupos de assets), al cabo de unos dias me dijeron que me pusiese a desarrollar la idea y prepare una prueba de concepto que funcionaba para explicar mi idea y como se ajustaba a la suya, el problema es que funciono y ahora soy el encargado de todo el proyecto que comprende practicamente todo el pipeline de la empresa  :).

La idea base es que en vez de tener varios scripts que cada uno hiciese todo el proceso de una sola vez, tener una serie de scripts simples que pudiesemos enlazarlos entre ellos y nos generasen los procesos, en cierto modo seria tener un sistema nodal de pipeline seteado por unos archivos de configuracion, cada uno de esos nodos haria funciones simples, lanzar un render, hablar con la base de datos, copiar archivos, y unos ficheros de descripcion del trabajo definirian las conexiones entre estos trabajos

Para poder hacerlo de un modo flexible el principal problema era como pasar unos datos que seteabamos en la definicion a variables en cada uno de los nodos, o como se pasaban datos de un nodo a otro, al final gracias a una de las caracteristicas de python fue relativamente sencillo, y es la introspeccion, gracias a ella podemos saber que variables tenemos en una clase, y facilmente leer su valor y pasarselo a otra clase.

Por ejemplo: suponer que tenemos dos clases,la clase renderMaya que hemos llamado 'render1' y la clase mkQuicktime que hemos llamado 'quicktime' y queremos que primero renderice maya para luego crear un quicktime con esas imagenes,  'render1' tiene una variable outputPath que es la que usa para setear el trabajo en la granja, desde la definicion le decimos que al nodo 'quicktime', la variable 'inputSequence' tiene el valor  '^/render1/outputPath', lo hacemos con

setatt(self,'quicktime','^/render1/outputPath')

asi hemos creado en nuestra clase una variable y le hemos seteado un valor a partir de dos strings

Para empezar se ejecuta primero el nodo 'render1' y cuando va a ejecutar el nodo 'quicktime' lo primero que le decimos es que resuelva las dependencias, para ello recorremos todas las variables de la clase que se encuentran en el diccionario __dict__ y vemos cuales son string y comienzan con '^', cogemos los valores que nos dan de nodo y variable, el script busca en todas las clases una que tenga la variable name con valor 'render1', y mira a ver si en esa clase existe la variable 'outputPath' con

hasattr(nodo, atributo)

si existe lo que hacemos es recoger su valor con getattr

value=getattr (clase, 'outputPath')

y lo seteamos en la clase actual

setattr(self,'quicktime',value)

De este modo tenemos acceso a TODAS las variables de las distintas clases que conforman nuestro arbol de dependencias, asi podemos setear los valores de cada modulo ya sea con un valor fijo o relativo a la salida de otro modulo como puede ser la version que estamos creando o el path a los fotogramas renderizados

Otra de los puntos fuertes de este proyecto es que creamos todos los nodos llamando a la misma clase y dependiendo del parametro 'type' que le pasemos nos devuelve una u otro, por ejemplo la llamamos aqui nodoBase, leemos el tipo y el nombre desde la definicion  y creamos el nodo 'render1' del modo

nodo=nodoBase(name='render1',nType='renderMaya')

si le hacemos un type a 'nodo' lo que nos devolvera sera una clase renderMaya, no una clase nodoBase, esto es usando el metodo __new__ que comente hace unas cuantas entradas

con estas dos aproximaciones podemos crear y conectar nodos de un modo muy sencillo a partir de una fichero de configuracion, y por lo tanto generar archivos de configuracion para generar trabajos complejos  de un modo bastante facil y sobre todo muy reutilizable


viernes, 29 de junio de 2012

Los clientes del departamento de pipeline

A raiz de unas preguntas en una entrevista de trabajo y de unas ideas que tenia desde hace tiempo voy a exponeros unas ideas generales sobre pipelines

Creo que cuando tenemos que diseñar una herramienta tenemos que tener en cuenta los posibles clientes o mejor dicho grupos de clientes, y estos pueden ser 3, artistas, departamento de produccion y pipeline, dependiendo de si incluye a 1, 2 o incluso a los 3 clientes las herramientas pueden ser diseñadas o incluso implementadas por distintos departamentos

Una herramienta para un solo departamento podria ser una herramienta por ejemplo de limpieza de poligonos, o una de limpieza de directorios, estas solo incumben a un departamento por lo que podrian ser facilmente desarrolladas por un TD de ese departamento

Luego la mayoria de las herramientas tienen como clientes a 2 departamentos son las mas usuales, ya que la mayoria deben de dar un aviso a produccion ya sea mandando mails, dando de alta en la base de datos o actualizando estados, por ejemplo una herramienta de publicaccion de assets, o de creacion de projectos seria de este tipo

Tambien puede haber herramientas que sean los 3 los clientes,como puede ser una herramienta para que el artista cree una textura nueva, que puede crear la estructura de archivos para contenerla, da aviso a produccion y se la abre en el programa de edicion

Teniendo esto en cuenta, a veces podemos structurar un script o una clase de modo que los metodos solo interactuen con uno de esos clientes, si por ejemplo tenemos que hacer un script para publicar un asset, podemos crear una clase asset, esa clase asset tendra un metodo publicar, pero en vez de que sea un metodo muy complejo podemos construirlo como llamadas a los distintos clientes, por ejemplo puede contener 3 metodos, un sanity check, un export y un notify, en el sanity check nuestro cliente seria el artista, serian script para ver si su trabajo esta bien y notificarselo a el, en el export nuestro cliente seria pipeline, creariamos carpetas, copiariamos archivos ... y en el notify lo que hariamos seria mandar los mails, dar de alta en la base de datos, actualizar flags y requires..

Bueno, esto son unas pocas ideas no muy elaboradas que me vinieron, que os parecen

lunes, 12 de marzo de 2012

renderizar massive desde maya con vray

Como ya comente en el post anterior estamos preparando un proyecto para el cual massive va a ser una gran complicacion ya que no es tan facil como meter una agente ya pre-hecho sino que tendremos que diseñar varios agentes distintos para combates y mas, asi que cuanto mas facilitemos el trabajo mejor, una de las ideas es que se puede hacer una buena parte del trabajo en maya de modo que pueda trabajar mas gente sin que tengan que tener obligatoriamente unos conocimientos buenos de massive, para ello primero hemos probado varios renders como Prman, Vray, Air o incluso importar los agentes de massive a maya,

Al principio cada uno nos dio unos problemas, PRman lo lento que es en algunos casos en cuanto se activa el raytrace, el Vray en la version que teniamos no renderizaba mas que a single thread y el Air que para windows (que es en lo que tenemos la farm :( ) no hay version mas que de 32 bits, asi que con cada uno teniamos una limitacion pero en esta actualizacion que hicimos de massive el plugin ya funcionaba bien y ya se puede renderizar en vray sin demasiada complicacion, esto unido a que en la version de vray 2.0 podemos editar las escenas mediante python nos da la posibilidad de crear un modo de trabajo que a mi personalmente me parece muy viable para este tipo de proyectos

Lo que intentabe hacer fue que desde maya, mientras se esta trabajando en el entorno se pudiese cargar en tiempo de render la escena de massive, para ello usamos en las render globals de Vray dentro de la seccion de Mel/Python callbacks la seccion de Post Translate Python Script, en esta seccion podemos editar la escena en python una vez que ya la hemos exportado, nos da la posibilidad de cambiar shaders, eliminar objetos o incluir otras escenas. Esta ultima posibilidad es la que vamos a usar para hacer que nos cargue la escena de massive, para ello en massive tenemos que crear la simulacion y decir que nos genere las vrscenes en vez de los ribs, tendremos que tener todas las variables de entorno seteadas para acceder a los shaders y al render y nuestros agentes deben de tener los shaders de Vray bien seteados en el renderpass correspondiente. y solo necesitamos escribir algo asi en el PTPS



es un poco mas largo de lo exactamente necesario, pero es para poder cargar los distintos frames, segun esta renderizando, ya que el script se ejecuta solo al lanzar el render, con lo que tendremos que lanzar el render a la farm en trabajos de 1 frame

de este modo tenemos una linea de trabajo definida, ahora quedaria exprimirla un poco mas para poder sacar recortes de objetos, modificar shaders en maya y mas

viernes, 10 de febrero de 2012

editor de agentes de massive en maya

Hace tiempo que no posteo nada, el curro que ha sido sobre todo de otras cosas y no tanto de picar codigo y ahora que estamos preparando otro(s) proyectos y estoy volviendo a meterle caña pues vuelvo a escribir aqui.

El proyecto que estamos empezando tiene muchas escenas de multitudes, batallas y demas, para ello vamos a usar massive, es un programa muy bueno pero es un poco arisco, y sobre todo algo complejo para poder editar bien temas como texturas, shaders o geometria, por ello estoy preparando una serie de scripts para poder editar todas estas cosas desde maya, de modo que yo me centre en el diseño de las acciones, cerebro y setup de escenas y los compañeros puedan ayudarme facilmente con la parte de modelado y shaders

La intencion es poder editar el archivo *.cdl de massive que es donde guarda los datos de los agentes, estos ficheros estan escritos en formato ascii sin compresion, con la filosofia de que muchas de las cosas que se podrian querer hacer en massive con plugins se pueden hacer editando o parseando los archivos

Para editar estos archivos estoy creando una libreria de clases, cada una de ellas es uno de los bloques de datos del archivo que a su vez se corresponden con nodos o variables de massive (bones, materials, geo....), cada una de estas clases tiene 4 funciones basicas, init, read, update y write, luego tendran las funciones para editarlas y en eso es en lo que estoy ahora

Tambien he creado una interface en maya en la que podemos ir editando el personaje que por ahora consta de 3 partes, file, variables, options, aunque poco a poco ira teniendo mas ya que la intencion es poder llegar hasta editar el setup o incluso los ciclos de animacion


En esta parte seleccionamos el archivo, una vez seleccionado hace una primera lectura y seleccionamos que renderpass queremos editar, por ahora solo estoy aplicando funcionalidad al Air render, luego ira renderman y si solucionan un bug que tiene vray que lo hace inservible para massive pues vray


En la segunda parte podemos cambiar el valor de las variables, todas las variables estan creadas como atributos y con conexiones de modo que simula el modo de funcionamiento de las mismas, cambiando de una geometria o cambiar datos del shader a otra al cambiar la variable


y una tercera que es en la que estoy trabajando ahora que seria editar las opciones, poder añadir geometria o eliminarla, cambiar el orden o la variable que lo modifica

Una vez hecho esto, podemos dar a update a shaders o a geometria en la primera pestaña y ya tendriamos el archivo modificado para usar con massive



Quedan por hacer bastantes cosas, una de ellas como se ve en la imagen es que los objetos creados esten mas ordenados en el outliner, pero poco a poco, por ahora creo que hoy ya dejare algo funcional a nivel de shaders y geometria, luego ya ira creciendo

viernes, 28 de octubre de 2011

conexion massive maya

ultimamente estoy haciendo bastante cosas con massive, algun anuncio, algun plano para una peli y cosas varias casi siempre con agentes muy standar, pero para un proyecto que tenemos ahora tenemos que crear personajes de otras epocas, asi que tenemos que modelarlos y texturizarlos completamente, y verlo todo en massive es un poco lento, asi que estoy preparando aqui una conexion entre maya y massive para poder modificar todo lo que es la parte de geometria y texturas

la idea:

la idea es tener una ventana en la que podamos cargar un archivo de agente de massive, un .cdl, estos archivos son ascii con un include a otro archivo donde esta la parte del cerebro del agente, lo que intentare hacer es primero, un importador, que nos cargue el archivo, use locators para conectar y guardar la informacion de distintos tipos de nodo que tiene, nos cargue la geometria y genere shaders similares a los que tenemos

tambien creara las conexiones entre variables de massive y las opciones de geometria o shader que tengamos, de modo que podremos ir viendo las distintas modificaciones

tendremos tambien un exportador, que nos grabara todo eso de vuelta en un archivo .cdl que lo lea massive

estas dos partes ya las tengo programadas y funcionan, ahora queda la tercera, que es definir un modo de trabajo y unas herramientas en maya de modo que podamos añadir geometria a un "set", añadir texturas, refinar el rig, la idea es tener una ventana donde tengamos las diferentes geometrias que componen un set, por ejemplo pantalones vaqueros, bermudas, bañadores..., poder añadir mas, eliminar, añadir sets de texturas a una geometria, o incluso definir el shading, o modificar parametros ya que tenemos todo definido en los locators que hacen de "contenedores" para la informacion, de modo que si yo grabo la escena y la vuelvo a abrir sigo teniendo todo

de este modo, sin tener que estar familiarizado con massive se podria generar la parte renderizable de un agente

no se si podre poner codigo de esta herramienta aqui, tendre que hablarlo con el jefe, pero mi idea es que si, que al igual que nosotros estamos usando scripts que dejo libremente otra gente, dejar aqui este por si a alguien le puede ayudar

por ahora lo tengo todo separado en clases, la clase bone, geo, material..., a estas podre acceder luego cuando tenga todo