Aprende a desarrollar aplicaciones gráficas 2D y 3D paso a paso.
Programacion Grafica: Desarrollo 2D/3D con C++ y DirectX/OpenGL/GLUT/SDL - Windows/Linux


  Crear una cuenta
 • Portada • Descargas • Tu Cuenta • 
Menú
 Portada
 Noticias
 Archivo de Noticias
 Temas
 Descargas
 Inicio
 Ver Nuevas
 Más Popular
 Más Votadas
 Contenido
 Contenido
 Secciones
 Enciclopedia
 Revisiones
 FAQ
 Tus Opciones
 Tu Cuenta
 Mensajes Privados
 Recomiéndenos
 Buscar
 Diarios
 Contacto
 Enlaces Web
 Inicio
 Enviar Enlace
 Ver Nuevos
 Más Popular
 Más Valorados
 Estadísticas
 Inicio
 Detalladas
 Top 10
 
Estadísticas
 
Tutorial 11 - Transformaciones 
DirectX/Opengl

Empecemos con un poco de movimiento. Vamos a realizar algunas transformaciones en 3-D, traslación, giro y escalado.



Para realizar transformaciones utilizaremos la clase matriz que se muestra a continuación:


    class Matrix
    {
    public:

        union
        {
            struct
            {
                float   _11, _12, _13, _14;
                float   _21, _22, _23, _24;
                float   _31, _32, _33, _34;
                float   _41, _42, _43, _44;
            };

            struct
            {
                float   StrafeX, UpX, ForwardX, DummyX;
                float   StrafeY, UpY, ForwardY, DummyY;
                float   StrafeZ, UpZ, ForwardZ, DummyZ;
                float   PositionX, PositionY, PositionZ, One;
            };

            float m[4][4];
        };

La matriz está definida como un union de C de forma que podemos acceder a los elementos que componen la matriz de diferentes formas.

Básicamente es la misma definición que tiene DirectX, pero le he añadido otro struct más que corresponden con los vectores de la base vectorial que representa la matriz.

En el fondo, una matriz define los tres vectores de un sistema de coordenadas. Así que cuando se hace una transformación (multiplicando matrices) lo que estamos haciendo es trasformar este sistema.

Hay que hacer una puntualización importante. Una transformación inversa, es aquella que deshace una transformación, de forma que vuelve a dejar el objeto como estaba. Esto se consigue multiplicando por la inversa de la matriz. Y he aquí una conclusión importante: EN UNA MATRIZ EN LA QUE LOS VECTORES QUE LA FORMAN SON ORTOGONALES (forman 90º entre ellos) LA INVERSA DE UNA MATRIZ ES IGUAL A LA TRANSPUESTA.

Debido a que siempre vamos a mantener dichos vectores ortogonales, cuando querramos realizar una operación inversa, sólo tenemos que transponer la matriz, no hace falta calcular la inversa.

Entonces, para realizar una transformación, calculamos una matriz con la transformación a realizar y se la pasamos al Driver de Vídeo. Este aplicará dicha transformación a todos los vértices a renderizar hasta que se fije una nueva transformación.

Para acumular transformaciones, sólo tenemos que multiplicar la matriz por la siguiente matriz con la transformación a aplicar. Veamos el método OnRender() para que nos sirva de ejemplo:


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

        Material yellowMaterial, greenMaterial;

        memset( &yellowMaterial, 0, sizeof(Material) );
        yellowMaterial.ambient  = yellowColor;
        yellowMaterial.diffuse  = yellowColor;
        yellowMaterial.specular = yellowColor;

        memset( &greenMaterial, 0, sizeof(Material) );
        greenMaterial.ambient   = greenColor;
        greenMaterial.diffuse   = greenColor;
        greenMaterial.specular  = greenColor;


        if ( m_pVideoDriver )
        {
            // Limpiamos la pantalla.
            m_pVideoDriver->ClearColor( clearColor );
            m_pVideoDriver->ClearZBuffer();
    // ********************************* NEW **************************************
            m_pVideoDriver->EnableDepthBuffer( true );
    // ****************************************************************************

            // Proyección en perspectiva
            m_pVideoDriver->SetPerspective( FOV, m_WindowProps.width, m_WindowProps.height );

            m_pVideoDriver->LookAt( Vector3(2.0f,1.0f,3.0f) ,   // Posición de la cámara.
                                    Vector3(0.0f,0.0f,0.0f) ,   // A dónde mira.
                                    Vector3(0.0f,1.0f,0.0f) );  // Dónde se encuentra el "techo", eje Y. 

            m_pVideoDriver->BeginRender();

    // ********************************* NEW **************************************

            // Reseteamos las transformaciones previas.
            Matrix  mIdentity;
            m_pVideoDriver->SetTransform ( mIdentity );

            m_pVideoDriver->EnableLighting( false );            // Desactivamos la iluminación.
            m_pVideoDriver->RenderAxis( 1.1f );                 // Renderizamos un eje de coordenadas en el origen.

    // ****************************************************************************

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

    // ********************************* NEW **************************************

            Matrix  transform;
            Matrix  worldTransform;

            worldTransform = transform.RotateY( -m_AngleRotation );         // Rotamos sobre el eje Y.
            m_pVideoDriver->SetTransform ( worldTransform );                // Aplicamos la transformación.

            m_pVideoDriver->SetMaterial  ( yellowMaterial );                // Fijamos el material
            RenderCube   ( 1.1f );                                          // Renderizamos el cubo.

            worldTransform  = transform.RotateY( m_AngleRotation );         // 1. Rotamos sobre el eje Y.
            worldTransform *= transform.TranslateX( 5.0f );                 // 2. Trasladamos 5 unidades.
            worldTransform *= transform.RotateY( 2.0f*m_AngleRotation );    // 3. Orbitamos sobre el cubo anterior.
            m_pVideoDriver->SetTransform ( worldTransform );                // Aplicamos la transformación.

            m_pVideoDriver->SetMaterial  ( greenMaterial );                 // Fijamos el material
            RenderCube   ( 1.0f );                                          // Renderizamos el cubo.

    // ********************************* NEW **************************************

            m_pVideoDriver->EndRender();
        }
    }

Lo primero que se ha añadido, es habilitar el DepthBuffer. Esto hace que cada pixel que se va a renderizar en pantalla tenga asociado un valor que indica si está más lejos o más cerca. De esta forma los elementos más próximos que ocultan a otros más lejanos serán los que se pinten en pantalla.

Posteriormente se aplica la transformación identidad para anular cualquier transformación realizada en la iteración anterior. Se habilita la iluminación y dibujamos un sistema de coordenadas que nos sirva de referencia.

A continuación definimos una matriz (transform) para realizar un trasformación individual. El producto acumulado de estas transformaciones indiviuales en worldTransform nos dará como resultado la transformación final.

Fijaros bien que el orden en el que se realizan las tranformaciones es importante. Se ve más claro en el cubo que da órbitas. Dicho cubo (el verde) para rotar sobre sí mismo, hay que hacerlo rotar en primer lugar y luego trasladarlo. Posteriormente se vuelve a aplicar una transformación de rotación para que describa órbitas.

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



Nota: Compartir en Facebook
Enviado el Miércoles, 05 septiembre a las 20:44:40 por administrador
 
Enlaces Relacionados
· Más Acerca de DirectX/Opengl
· Noticias de administrador


Noticia más leída sobre DirectX/Opengl:
Tutorial 16 - Movimiento-3D - (Tercera Persona)

 
Votos del Artículo
Puntuación Promedio: 4.25
votos: 4


Por favor tómate un segundo y vota por este artículo:
Excelente
Muy Bueno
Bueno
Regular
Malo

 
Opciones

 Versión Imprimible  Versión Imprimible

 
"Tutorial 11 - Transformaciones" | Entrar / Crear Cuenta | 5 Comentarios | Buscar Discusión
Los comentarios son propiedad de quien los envió. No somos responsables por su contenido.

No se permiten comentarios Anónimos, Regístrese por favor

Re: Tutorial 11 - Transformaciones (Puntuación 1)
por sumaya el Miércoles, 14 mayo a las 11:58:04
(Información del Usuario | Enviar un Mensaje)
Esta muy bien el manual me ha servido mucho pero el enlace de descarga no funciona.

Gracias



Re: Tutorial 11 - Transformaciones (Puntuación 1)
por pacasmayo001 el Martes, 26 octubre a las 11:33:20
(Información del Usuario | Enviar un Mensaje)
muy interesante,.......gracias.justo lo que buscaba....(¬-.-)¬



Re: Tutorial 11 - Transformaciones (Puntuación 1)
por BiiChiiTha el Sábado, 05 noviembre a las 14:08:59
(Información del Usuario | Enviar un Mensaje)
Hola que tal, antes que nada gracias por estos tutoriales ya que están ayudando mucho a entender sobre opengl, ahora tengo una pregunta, es que al compilar el proyecto me marca un error referente a "FreeImage" y no se exactamente que hacer?? vi que hay un enlace y descargue la carpeta "FreeImage.zip" pero no se en que parte colocarla, espero me puedas ayudar, gracias



Sitio potenciado por NukeProjects.Net        NukeStilo 1.0 se basa en PHP-Nuke        Theme Diseñado por NukeMods

© Antonio Lucas Moreno