Tutorial 16 - Movimiento-3D - (Tercera Persona)
Fecha Miércoles, 05 septiembre a las 23:57:03
Tema DirectX/Opengl


Vamos a cambiar nuestro punto de vista. Ahora nos situaremos detrás de nuestro personaje (un pobre cilindro) para desarrollar el movimiento en tercera persona (Third Person Camera).



Lo primero que haremos en el constructor, es situar la cámara detrás de nuestro protagonista.


    // ********************************* NEW **************************************
        // La posición de la cámara será relativa a la posición de m_Player.
        m_Camera.SetPosition( m_Player.GetPosition() - m_Player.GetLocalMatrix().GetForwardVector() );
    // ****************************************************************************

Realizaremos unos cambios en CheckMovement() para que el giro de la cámara, según movemos el ratón, gire alrededor de nuestro personaje.

Según movemos el ratón de izquierda a derecha o viceversa, giramos el cilindro e igualmente trasladamos la cámara detrás de nuestro protagonista y aplicamos un giro. Al haber realizado primero la traslación, la cámara orbitará alrededor nuestro.


    ///////////////////////////////////////////////////////////////////////////////
    ///     CheckMovement: Comprueba si hay pulsada una tecla.
    ///
    ///     @param  long msElapsed: misilegundos transcurridos entre cada frame.
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::CheckMovement( long msElapsed )
    {
    // ********************************* NEW **************************************
        Matrix mCamera, m;
        float angleY;
    // ****************************************************************************

        float speed= m_Player.GetSpeed();

        if ( m_KeysPressed[KEY_UP] || m_KeysPressed[''W''] || m_KeysPressed[''w''] )
        {
            m_Player.Forward( speed * msElapsed );      // Avance
        }
        else if ( m_KeysPressed[KEY_DOWN] || m_KeysPressed[''S''] || m_KeysPressed[''s''] )
        {
            m_Player.Forward( -speed * msElapsed );     // Retroceso
        }

        if ( m_KeysPressed[KEY_LEFT] || m_KeysPressed[''A''] || m_KeysPressed[''a''] )
        {
            // Izquierda
            if ( m_pVideoDriver->GetAxisSystem() == eRightHanded )
                m_Player.Strafe( -speed * msElapsed );
            else
                m_Player.Strafe(  speed * msElapsed );
        }
        else if ( m_KeysPressed[KEY_RIGHT] || m_KeysPressed[''D''] || m_KeysPressed[''d''] )
        {
            // Derecha
            if ( m_pVideoDriver->GetAxisSystem() == eRightHanded )
                m_Player.Strafe(  speed * msElapsed );
            else
                m_Player.Strafe( -speed * msElapsed );
        }

        // Si ha cambiado de posición
        if ( (m_MousePosition.x != m_MiddleWindow.x) || (m_MousePosition.y != m_MiddleWindow.y) )
        {
    // ********************************* NEW **************************************

            // Movimiento del ratón en eje Y de pantalla, giro en eje X en 3D
            angleY= (float)( m_MiddleWindow.x - m_MousePosition.x ) / 10.0f;


            // Giramos el jugador
            if ( m_pVideoDriver->GetAxisSystem() == eRightHanded )
                m_Player.Yaw( -angleY );
            else
                m_Player.Yaw(  angleY );

            // Trasladamos la cámara a su posición respecto el jugador ...
            mCamera *= m.Translate( m_Camera.GetPosition() );

            // ... orbitamos alrededor del jugador
            if ( m_pVideoDriver->GetAxisSystem() == eRightHanded )
                mCamera *= m.RotateY( -angleY );
            else
                mCamera *= m.RotateY(  angleY );

            // Fijamos la nueva posición de la cámara
            m_Camera.SetPosition( Vector3(mCamera.PositionX,mCamera.PositionY,mCamera.PositionZ) );

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

            // Colocamos siempre el puntero del ratón en el centro de la pantalla
            System::SetMousePosition( m_MiddleWindow.x, m_MiddleWindow.y );
        }
    }

Finalmente, en el método OnRender(), la cámara mira siempre a nuestro jugador, el cual renderizamos como un cilindro. Un pobre personaje de momento, pero bueno.


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

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

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

            vPosition= m_Player.GetPosition() + m_Camera.GetPosition();
            vUp      = m_Camera.GetLocalMatrix().GetUpVector();
    // ********************************* NEW **************************************
            vLook    = m_Player.GetPosition();                  // La cámara mirando siempre al jugador.
    // ****************************************************************************

            m_pVideoDriver->LookAt( vPosition, vLook, vUp );

            m_pVideoDriver->BeginRender();

            m_pVideoDriver->SetTransform( mIdentity );          // Reseteamos las transformaciones previas.
            m_pVideoDriver->EnableLighting( false );            // Desactivamos la iluminación.
            RenderFloor ( 20, 20 );                             // Renderizamos el suelo.

            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.
            }

            m_pVideoDriver->EnableLighting( true );             // Activamos la iluminación.
            RenderSceneObjects();                               // Renderizamos las geometrías.

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

            // Renderizamos nuestro personaje (el cilindro).
            Matrix mWorld= m_Player.GetWorldMatrix();
            Matrix mScale;
            mScale.Scale( Vector3(0.5f,0.8f,0.5f) );

            m_pVideoDriver->SetTransform( mScale * mWorld );
            m_Me->Render(24,1);

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

            m_pVideoDriver->EndRender();
        }
    }

Podéis descargaros el ejemplo: tutorial-16.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=17