Grupo de Usuarios de Python/pyopengl/PyOpenGL para Programadores
De Proyecto Ciencia
Esta página es una introducción rápida de varias características de PyOpenGL que normalmente no se encuentran en los textos de OpenGL (ej. manejo estricto de excepciones, funciones de aliases, métodos de arreglos/punteros con Numpy).
En este documento se describen esas características de PyOpenGL que pueden ser nuevas para los programadores de OpenGL. También explica las varias características de PyOpenGL que no se cubren en la documentación general de OpenGL.
Siga este enlace si desea regresar al Índice Principal
Contenido |
Preocupación por Velocidad
PyOpenGL 3.x es mucho mas lento que PyOpenGL 2.x y este no era rápido. Recién instalado PyOpenGL 3.x está configurado para ser tan útil y robusto como es posible, ambas características pueden hacer que el sistema sea mas lento de lo que es. PyOpenGL ahora esta implementado usando ctypes, en lugar de SWIG, la flexibilidad de los ctypes tiene un costo significativo en el rendimiento. PyOpenGL 3.x es mucho mas flexible en cuanto a tipos de dato (data-types), esa flexibilidad tiene un notorio costo en rendimiento. A través de este documento verá descripciones de como cambiar flexibilidad, utilidad y robustez para obtener velocidad.
Si intenta hacer operaciones por vértice (ej. glColor, glNormal, glVertex) encontrara que PyOpenGL es ridículamente lento. Por suerte, todas esas características han sido deprecadas. Ya que la geometría basada en arreglos donde los arreglos son grandes y en formatos nativos compatibles, el tope de PyOpenGL tiende a ser amortizado sobre el tamaño de los arreglos siendo procesados.
Firmas de Métodos Vs. C OpenGL
La mayoría de las funciones que aparecen en PyOpenGL 3 son idénticas en método de llamado con aquellas en la especificación de C. Existen varias excepciones por las diferencias existentes entre C y Python. La mayoría de estas excepciones en la manera que ellos acceden a los arreglos. Por ejemplo, una función de C como esta:
void foo(int count, const int *args);
tendría la atadura (binding) de python:
foo(args) -> None
También las funciones en C que escriben datos a los arreglos por medio de un argumento en una función como:
void bar(int args[4]);
normalmente tendría la atadura de python:
bar() -> args[]
Las siguientes secciones documentaran los cambios no como los ejemplos simples mencionados anteriormente.
Errores Levantan Excepciones
PyOpenGL generalmente usa operación "estricta" de OpenGL, las cual está más cercano a la operación de python mismo, es decir que los errores se levantan como excepciones, en lugar de requerir que el usuario verifique los valores y/o llamar glCheckError manualmente.
Puede inhabilitar la verificación de errores en PyOpenGL colocando una bandera a nivel de módulo en el paquete de PyOpenGL antes de importar cualquier sub-módulo, de esta manera:
import OpenGL OpenGL.ERROR_CHECKING = False from OpenGL.GL import * from OpenGL.GLU import * ...
Esto causara un gran incremento en la velocidad de su código, ya que el numero de llamadas realizadas a OpenGL prácticamente se dividen a la mitad en comparación con la versión que verifica errores del mismo guión. Normalmente querrá desarrollar con la verificación de errores encendida y desactivarla para el código de producción/liberación.
Las excepciones normalmente levantadas por PyOpenGL son:
- GL:GLerror por todos los módulos menos WGL
- GLU.GLUerror por algunas funciones GLU. Note que GLU también lanzará GL.GLerror
- WindowsError/SystemError por WGL
- Errores generales TypeError/ValueError por ejemplo problemas de tipo de dato incorrectos
GL.GLerror es una sub-clase de GL.Error y tiene una gran cantidad de información extra sobre el proceso envoltorio de llamadas:
- err -- código de error de OpenGL
- result -- código-resultado para la operación de OpenGL
- baseOperation -- la función base OpenGL está siendo llamada
- pyArgs -- el conjunto de argumentos de alto nivel pasados a la función
- cArgs -- el conjunto de objetos de nivel C convertidos desde cArgs
- description -- descripción textual OpenGL del error (normalmente bastante vinculante, útil primordialmente para mirar la documentación)
Registros (logging)
Por defecto, PyOpenGL registrará los errores en el módulo logging de Python. Puede inhabilitar esto colocando una bandera antes de importar los sub-modulos de OpenGL:
import OpenGL OpenGL.ERROR_LOGGING = False from OpenGL.GL import * ...
lo cual provee mejoras en el desempeño en el código de producción.
Por lo contrario, si observa que su código no funciona y necesita hace un seguimiento de la operación de PyOpenGL entonces es posible instruir a PyOpenGL para que realice un seguimiento a las llamadas al OpenGL en el módulo de registros (logging)
import OpenGL OpenGL.FULL_LOGGING = True from OpenGL.GL import * ...
esto es extremadamente lento, pero útil en ciertos momentos durante el proceso de búsqueda de errores (debugging).
Operaciones de Envolturas
Los argumentos envueltos de Python pueden pasar por un número de operaciones de envoltura para producir una llamada final al conjunto de argumentos de Python:
- toma un grupo de argumentos y los pasa un conjunto de convertidores por ellos para convertirlos a un tipo de objetos accesibles (pyArgs)
- ejecuta un grupo de cConverters sobre los pyArgs para producir un conjunto de cArgs, representando los objetos Pyhonicos que son 1:1 con los argumentos de C (cArgs), esto generalmente expandirá de un simple argumento de Python a múltiples objetos argumentos de C
- ejecuta un grupo de cResolvers sobre cArgs para producir un conjunto final de argumentos ctype compatibles
- ejecuta un grupo de convertidores storeValues para guardar cualquier objeto temporal que necesiten mantenerse en memoria par prevenir fallos de acceso a memoria por próximas llamadas (ej. referencias a apuntadores requieren que el objeto que sujeta la memoria se mantenga en memoria)
- ejecuta una función para escoger que valor regresar desde la función
Estas operaciones son implementados por la clase OpenGLl.wrapper.Wrapper, la cual es el foco de la mayoría de las optimizaciones de módulos OpenGL_accelerate (por razones obvias).
Manejo de Arreglos
PyOpenGL 3.x soporta un amplio rango de tipos de datos compatibles con arreglos, entre estos los agregados (plug-ins) por descarte son:
- arreglos numpy
- arreglos Numeric
- arreglos numarray
- cadenas de Python (búfers en Python 2.6)
- números (actuando como arreglos de apuntadores a un solo valor)
- arreglos ctypes
- parámetros ctypes
- listas/tuples
- objetos de búfer en vértices (demostración de un envoltorio cuya intención es dar un modelo para otros tipos de formato)
Cuando un punto de entrada PyOpenGL 3.x requiere un tipo de dato "arreglo" (o un tipo de dato vacío* [void*]), usara los agregados FormatHandler de PyOpenGL (OpenGL.arrays.formathandler) para decidir como convertir el arreglo a un formato compatible con los API de bajo nivel de OpenGL.
Ciertos tipos de formato pueden permitir el uso como tipos de arreglo mientras no contenga una copia compatible de la data. Las lista de Python, los tuples y números todos requieren la creación de una variable temporal para aguantar su data. Como tal generalmente no deberá usarlos para operaciones de rendimiento critico. Similarmente, si para un arreglo numpy con un tipo de dato incompatible el envoltorio puede tener una copia de la data para pasarla a las funciones de nivel C. Para los arreglos numpy, donde el comportamiento es tan rápido que usted puede que no se de cuenta, pero puede impactar de forma negativa el rendimiento, puede prevenir este comportamiento colocando una bandera en el paquete OpenGL antes de importar cualquiera de los módulos de OpenGL:
import OpenGL OpenGL.ERROR_ON_COPY = True from OpenGL.GL import *
lo cual causara que el manejador de formatos numpy levante errores si se encuentra a si mismo copiando un arreglo a otro tipo de dato.
Tenga en cuenta que con OpenGL 3.1 sera requerido que todos los arreglos no indexados sean manejados como objetos de búfer en vértices.
