Tutorial 06 - Dibujando Geometrías.
Fecha Jueves, 30 agosto a las 22:13:41
Tema DirectX/Opengl


Por fin vamos a dibujar algo, aunque parezca poca cosa, pero son las primitivas básicas para renderizar.



Podemos ver en el método OnRender() que es la función que es invocada cuando se puede renderizar.

Limpiamos la imagen renderizada previamente llamando a ClearColor(), limpiamos el buffer de profundidad con ClearZBuffer() y especificamos una proyección Ortogonal. ¿Y qué es esto?. Pues significa que los vértices declarados en el espacio se representan en pantalla sin importar a qué distancia se encuentren del observador, es decir, es equivalente a programar en 2D.

Hemos definido un par de funciones BeginRender() y EndRender() entre las cuales se especificarán las llamadas a funciones de renderizado. A continuación, en función de que hayamos pulsado o no el tabulador, renderizará los polígonos rellenos o en modo de malla. Estos polígos nos dibujaremos en la función RenderObjects().


    ///////////////////////////////////////////////////////////////////////////////
    ///     OnRender: Esta función es invocada cuando el sistema está listo para renderizar.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::OnRender()
    {
        fColorRGBA color = { 0.0f, 0.0f, 0.8f, 1.0f };  // Color de fondo.

        if ( m_pVideoDriver )
        {
            // Limpiamos la pantalla.
            m_pVideoDriver->ClearColor( color );
            m_pVideoDriver->ClearZBuffer();

    // ********************************* NEW **************************************
            // Proyección ortogonal
            m_pVideoDriver->SetOrthoProjection( 0.0f, m_WindowProps.width,  // left, right
                                                0.0f, m_WindowProps.height, // bottom, top
                                               -1.0f, 1.0f );
            m_pVideoDriver->BeginRender();

            if ( m_bWireframe )
            {
                m_pVideoDriver->SetRenderMode( eWireFrame );    // Renderizado wireframe
                m_pVideoDriver->SetCullFaces ( eCullNone  );    // Desactivamos la selección de caras a renderizar.
            }
            else
            {
                m_pVideoDriver->SetRenderMode( eSolid     );    // Renderizado sólido.
                m_pVideoDriver->SetCullFaces ( eCullBack  );    // No se renderizarán las caras traseras.
            }

            RenderObjects();

            m_pVideoDriver->EndRender();
    // ****************************************************************************
        }
    }

En la función RenderObjects() especificamos los puntos (vértices del polígono) que se va dibujar. Para ello, indicamos cuándo comenzamos y qué tipo de polígno vamos a dibujar. Con el método RenderVertexArray() especificamos la lista de vértices a renderizar. Hay que indicar, que tal como hemos definido la proyección, el origen de coordenadas se encuentra en la esquina inferior izquierda de la pantalla y la X es positiva hacia la derecha y la Y positiva hacia arriba.

Fijémonos cómo están numerados los vértices, es importante el orden en el que se pintan ya que ello determina las caras frontales y las traseras. La cara frontal es aquella que se recorre en sentido antihorario. Esto es así si usamos el sistema de ejes de la "mano derecha" lo que significa que si cerramos nuestra mano con el pulgar hacia arriba y con los otros dedos seguimos el orden en que se recorren los vértices, el pulgar apuntará en el sentido de la cara frontal. Esto es importante, porque en algunos casos no interesa renderizar la cara trasera ya que no es visible). De todas formas, cómo descartamos las caras frontales y traseras se define mediante la función: SetCullFaces()

Esta función está adaptada para según qué sistemas de ejes usemos. Por defecto, para todos los tutoriales y para no liarnos, vamos a usar siempre el sistema de ejes de "mano derecha" que es el que se usa en OpenGL. Hasta no llegar al capítulo de matrices, para OpenGL sólo podremos usar de momento el sistema de ejes de mano derecha.

En cuanto a cómo renderiza los vértices RenderVertexArray() depende de si usamos OpenGL o DirectX. Es importante destacar el último parámetro de la función, ya que define qué elementos componen el vértice, en este caso sería eFVF_XYZ|eFVF_DIFFUSE las coordenadas y el color. Hay declarar los elementnos en la estructura del vértice en el orden en que están declarados los flags en el enumerado e_VERTEX_FORMAT. Esto es así porque en RenderVertexArray() se va comprobando su existencia en dicho orden.


    ///////////////////////////////////////////////////////////////////////////////
    ///     RenderObjects: Dibuja las geometrías.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::RenderObjects()
    {
        Vertex vertexArray[8];
        int i;

        if ( m_pVideoDriver )
        {
            m_pVideoDriver->EnableLighting  ( false );

            // Lista de líneas
            //
            //  v0 v2 v4
            //   *  *  *
            //   | /| /|
            //   */ */ *
            //  v1 v3 v5
            //
            for (i=0; i<6; i+=2)
            {
                vertexArray[ i ].color.rgba= COLOR_RGBA(0xff,0xff,0x00,0xff);   // Amarillo
                vertexArray[i+1].color.rgba= COLOR_RGBA(0x00,0xff,0x00,0xff);   // Verde

                vertexArray[ i ].x= 40*i+50, vertexArray[ i ].y= 400, vertexArray[ i ].z= 0.1f;
                vertexArray[i+1].x= 40*i+50, vertexArray[i+1].y= 150, vertexArray[i+1].z= 0.1f;
            }

            m_pVideoDriver->RenderVertexArray( eLineStrip, (BYTE*)vertexArray, sizeof(Vertex), 0, 6, eFVF_XYZ|eFVF_DIFFUSE );

            // Definimos un cuadrado (formado por dos triángulos consecutivos)
            //
            // v0   v2
            //  *---*
            //  |  /|
            //  |/  |
            //  *---*
            // v1   v3
            //
            for (i=0; i<4; i++)
            {
                vertexArray[i].color.rgba= COLOR_RGBA(0xff,0x00,0x00,0xff); // Rojo
            }

            vertexArray[0].x= 250, vertexArray[0].y= 330, vertexArray[0].z= 0.1f;   // v0
            vertexArray[1].x= 250, vertexArray[1].y= 130, vertexArray[1].z= 0.1f;   // v1
            vertexArray[2].x= 450, vertexArray[2].y= 330, vertexArray[2].z= 0.1f;   // v2
            vertexArray[3].x= 450, vertexArray[3].y= 130, vertexArray[3].z= 0.1f;   // v3

            m_pVideoDriver->RenderVertexArray( eTriangleStrip, (BYTE*)vertexArray, sizeof(Vertex), 0, 4, eFVF_XYZ|eFVF_DIFFUSE );

            // Triángulos aislados
            //
            // v0  v3 v5
            //  *  *--*
            //  |   |
            //  |   |
            //  *--*  *
            // v1 v2 v4
            //
            for (i=0; i<6; i++)
            {
                vertexArray[i].color.rgba= COLOR_RGBA(0xff,0xff,0x00,0xff); // Amarillo
            }

            vertexArray[0].x= 460, vertexArray[0].y= 300, vertexArray[0].z= 0.1f;   // v0
            vertexArray[1].x= 460, vertexArray[1].y= 100, vertexArray[1].z= 0.1f;   // v1
            vertexArray[2].x= 560, vertexArray[2].y= 100, vertexArray[2].z= 0.1f;   // v2

            vertexArray[3].x= 480, vertexArray[3].y= 300, vertexArray[3].z= 0.1f;   // v3
            vertexArray[4].x= 580, vertexArray[4].y= 100, vertexArray[4].z= 0.1f;   // v4
            vertexArray[5].x= 580, vertexArray[5].y= 300, vertexArray[5].z= 0.1f;   // v5

            m_pVideoDriver->RenderVertexArray( eTriangleList, (BYTE*)vertexArray, sizeof(Vertex), 0, 6, eFVF_XYZ|eFVF_DIFFUSE );
        }
    }

Podéis descargaros el ejemplo: tutorial-06.zip



Compartir en Facebook



Este artículo proviene de Programacion Grafica: Desarrollo 2D/3D con C++ y DirectX/OpenGL/GLUT/SDL - Windows/Linux
http://www.programaciongrafica.com

La dirección de esta noticia es:
http://www.programaciongrafica.com/modules.php?name=News&file=article&sid=7