Una API de dibujo de depuración agnóstica y de depuración agnóstica de renderista, agnóstico de renderista para C ++.
Este software está en el dominio público. Cuando no se reconoce esa dedicación, se le otorga una licencia perpetua e irrevocable para copiar, distribuir y modificar el código fuente como lo mejore.
El código fuente se proporciona "tal cual", sin garantía de ningún tipo, expresa o implícita. No se requiere atribución, pero se aprecia una mención sobre el autor (s).
El sorteo de depuración es una biblioteca de archivos de origen único, por lo que las declaraciones de reenvío de "encabezado" y la implementación están contenidas en el mismo archivo ( debug_draw.hpp ). Esto debería facilitar la implementación e integración con sus propios proyectos. Todo lo que tiene que hacer es #include el archivo de la biblioteca en uno de sus propios archivos de origen y defina DEBUG_DRAW_IMPLEMENTATION en ese archivo para generar la implementación. También puede incluir la biblioteca en otros lugares. Cuando no se define DEBUG_DRAW_IMPLEMENTATION , actúa como un archivo de encabezado C ++ normal. Ejemplo:
En my_program.cpp :
# define DEBUG_DRAW_IMPLEMENTATION
# include " debug_draw.hpp " Ahora en my_program.hpp o en cualquier otro encabezado o archivo fuente, puede incluirlo como un encabezado C ++ normal:
# include " debug_draw.hpp "Eso es todo, ahora deberías poder construir el dibujo de depuración en tu propia aplicación.
El dibujo de depuración no hace suposiciones sobre la API de renderizador subyacente, por lo que se puede integrar muy fácilmente con Direct3D o OpenGL o cualquier otro motor de renderizado de su elección. Todo lo que se requiere es que proporcione una implementación para la clase abstractor dd::RenderInterface , que proporciona a la depuración el dibujo con métodos básicos para dibujar puntos, líneas y glifos de caracteres. Lo siguiente es cómo se ve dd::RenderInterface :
class RenderInterface
{
public:
virtual void beginDraw ();
virtual void endDraw ();
virtual GlyphTextureHandle createGlyphTexture ( int width, int height, const void * pixels);
virtual void destroyGlyphTexture (GlyphTextureHandle glyphTex);
virtual void drawPointList ( const DrawVertex * points, int count, bool depthEnabled);
virtual void drawLineList ( const DrawVertex * lines, int count, bool depthEnabled);
virtual void drawGlyphList ( const DrawVertex * glyphs, int count, GlyphTextureHandle glyphTex);
virtual ~RenderInterface () = 0 ;
}; ¡No se deben implementar todos los métodos, usted decide qué características admitir! Busque el código fuente para la declaración de RenderInterface . Cada método está bien comentado y describe el comportamiento esperado que debe implementar. Para las implementaciones de referencia de RenderInterface utilizando API estándar como OpenGL, consulte las samples/ directorio en este proyecto.
Una vez que implementa una RenderInterface para su renderizador, todo lo que necesita hacer antes de comenzar a usar Draw de depuración es llamar dd::initialize() Pasando un puntero a su RenderInterface personalizado:
MyRenderInterface renderIface;
dd::initialize (&renderIface); Sin embargo, tenga en cuenta que la depuración dibuja todas las primitivas para reducir la cantidad de llamadas para RenderInterface , por lo que el dibujo solo tendrá lugar cuando llame dd::flush() , que normalmente se realiza al final de un marco, antes de voltear los buffers de pantalla:
// You only have to pass the current time if you have timed debug
// draws in the queues. Otherwise just omit the argument or pass 0.
dd::flush (getTimeMilliseconds());Entonces, la configuración general debería parecerse a lo siguiente:
class MyRenderInterface : public dd ::RenderInterface
{
// Cherrypick the methods you want to implement or implement them all
...
};
int main ()
{
MyRenderInterface renderIface;
dd::initialize (&renderIface);
while (!quitting)
{
// Any other drawing that you already do
...
// Call any dd:: functions to add debug primitives to the draw queues
...
dd::flush ( getTimeMilliseconds ());
// Swap buffers to present the scene
...
}
dd::shutdown ();
} Dibuja de depuración proporciona varios interruptores de compiladores para la configuración y personalización de la biblioteca. Consulte la documentación en debug_draw.hpp para una lista de todos los conmutadores más una descripción detallada de cada uno.
La biblioteca tiene muy pocos requisitos de idioma. Uno de sus objetivos principales es ser indoloro para integrarse y portátiles. El único requisito es un compilador C ++ bastante reciente con un mínimo soporte de biblioteca estándar. Se suponen algunas características de C ++ 11, como nullptr y <cstdint> . Las muestras incluyeron hacer un uso más pesado de la biblioteca estándar C ++ para demostrar el uso de dibujo de depuración con hilos.
No se utilizan excepciones RTTI y C ++, por lo que no debe tener problemas para integrar la biblioteca con proyectos que desactiven esas características.
La huella de la memoria también es pequeña y puede administrar la cantidad de memoria que se compromete con las colas internas a través de las directivas del preprocesador. Actualmente solo asignamos una pequeña cantidad de memoria dinámica en el inicio de la biblioteca para descomprimir los glifos de fuentes para las funciones de dibujo de texto de depuración y para las colas de dibujo y los datos de contexto de la biblioteca.
Por defecto, el sorteo de depuración utilizará un contexto global estático internamente, proporcionando una API de estilo de procedimiento que no es segura . Este es el modo de dibujo de depuración "clásico" que es el más fácil de usar y configurar, pero la biblioteca también admite otros dos modos que son seguros y configurables en los subproces en el momento de la compilación:
DEBUG_DRAW_PER_THREAD_CONTEXT : si esto se define antes de la implementación, la biblioteca usará un contexto local de hilo en lugar del valor predeterminado compartido global. Esto permite llamar a la biblioteca desde diferentes hilos, ya que cada uno mantendrá su contexto privado y dibujará colas. Este modo proporciona la misma interfaz de biblioteca pública, pero requiere soporte TLS (almacenamiento local de subprocesos) del compilador.
DEBUG_DRAW_EXPLICIT_CONTEXT : si esto se define antes de la implementación, la biblioteca espera que el usuario proporcione un mango a un contexto. Este modo expone el tipo dd::ContextHandle y cambia cada función en la biblioteca para tomar este mango como el primer argumento. Este modo hace que la biblioteca sea totalmente estancada, de modo que cada hilo de representación que llame a la biblioteca pueda crear y mantener su propia instancia de dibujo de depuración.
El modo de contexto explícito es una API más limpia y de estilo funcional y debería ser el preferido para los nuevos usuarios. El modo de procedimiento todavía se mantiene como el valor predeterminado para la compatibilidad con versiones de la biblioteca más antiguas, pero se recomienda que use el modo de contexto explícito agregando #define DEBUG_DRAW_EXPLICIT_CONTEXT junto con DEBUG_DRAW_IMPLEMENTATION . En el futuro, la API de procedimiento de estado de estado se verá desapercibida a favor de la explícita.
Dibujar una caja con un conjunto de ejes de coordenadas en su centro:
const ddVec3 boxColor = { 0 . 0f , 0 . 8f , 0 . 8f };
const ddVec3 boxCenter = { 0 . 0f , 0 . 0f , 3 . 0f };
dd::box (boxCenter, boxColor, 1 . 5f , 1 . 5f , 1 . 5f );
dd::cross (boxCenter, 1 . 0f ); Para visualizar una transformación de matriz, puede usar dd::axisTriad() para dibujar la transformación como tres flechas:
const ddMat4x4 transform = { // The identity matrix
1 . 0f , 0 . 0f , 0 . 0f , 0 . 0f ,
0 . 0f , 1 . 0f , 0 . 0f , 0 . 0f ,
0 . 0f , 0 . 0f , 1 . 0f , 0 . 0f ,
0 . 0f , 0 . 0f , 0 . 0f , 1 . 0f
};
dd::axisTriad (transform, 0 . 3f , 2 . 0f ); Se pueden encontrar muestras y ejemplos más complejos sobre cómo integrar el dibujo de depuración con su propio renderizador dentro de las samples/ directorio. Cada función proporcionada en la API pública también está bien documentada en el archivo de encabezado. Encontrará un comentario de encabezado descriptivo antes del prototipo de cada función pública exportada por la biblioteca.