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 12 - Objetos-3D 
DirectX/Opengl

Vamos a empezar gestionando los objetos de la escena 3D. En un principio (ya que hay pocos) lo vamos a hacer almacenando los objetos en una lista, aprovechando la librería estandar de C++: STL.



STL (Standard Template Library) es una librería de plantillas que contiene estructuras de datos de uso común en programación, como son listas, pilas, colas, etc. Para ello incluiremos el fichero stl.h que contiene inclusiones de diferentes plantillas así como unos "pragmas" para eliminar los "millones" de "warnings" que aparecen en Visual cuando se usan las STL.

Definimos OBJECT_MAP en el fichero glapplication.h como una tabla hash donde cada elemento se referencia por una cadena de texto. STL tiene la clase string para el uso de cadenas de caracteres. NUNCA defináis un map con "char *" como clave hacedlo con la clase string, ya que de la otra forma, la clave sería el valor del puntero a char y no os funcionaría.


    typedef std::map< std::string, Object * >       OBJECT_MAP;

En nuestro ejemplo hemos creado la clase Object de la cual derivan las clases Cube, Cylinder y Sphere. La lista de objetos, almacena punteros a la clase Object, pero se almacenan punteros a las clases derivadas. Esto es lo que se denomina en C++ polimorfismo dinámico.

Al crear el objeto dinámicamente, se crea de la clase de objeto que corresponda, y realiza un casting a (Object*) para almacenarlo en el map. Podríamos usar castings de C, pero vamos a usar los de C++ para ver cómo funcionan.

En este caso, vamos a realizar un casting de una clase derivada a una clase padre. Como podemos ver en el comentario del código, este casting se resuelve en tiempo de compilación, con lo que se utiliza: > static_cast < T > (ptr).


    ///////////////////////////////////////////////////////////////////////////////
    ///     CreateSceneObjects: Crea los objetos que componen la escena 3D.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::CreateSceneObjects()
    {
        Vector3 points[2] =
        {
            Vector3( -1,-1,-1 ),
            Vector3(  1, 1, 1 )
        };

        Object *pObject= NULL;

        // **************************************************************************************************************************
        // NOTA:
        // La conversión una clase derivada a una clase-base (upcast) se resuelve en tiempo de compilación -> static_cast < T > (ptr)
        // Si fuese una conversión de una clase-base a una derivada (downcast) se resuelve en tiempo de ejecución -> dynamic_cast< T > (ptr)
        // **************************************************************************************************************************

        // *** Creamos un cubo ***
        Cube *pCube= new Cube("CUBO");

        if ( pCube )
        {
            pCube->Calculate( points, 2 );

            // Lo posicionamos
            Vector3 vPosition(0,2,0);
            pCube->SetPosition( vPosition );

            // Añadimos el objeto a la lista.
            m_ObjectList[ std::string(pCube->GetName()) ]= static_cast( pCube );
        }

        // *** Creamos una esfera ***
        Sphere *pSphere= new Sphere("ESFERA");

        if ( pSphere )
        {
            pSphere->Calculate( points, 2 );

            // Lo posicionamos
            Vector3 vPosition(4,1.5f,0);
            pSphere->SetPosition( vPosition );

            // Añadimos el objeto a la lista.
            m_ObjectList[ std::string(pSphere->GetName()) ]=  static_cast( pSphere );
        }

        // *** Creamos un cilindro ***
        Cylinder *pCylinder= new Cylinder("CILINDRO");

        if ( pCylinder )
        {
            pCylinder->Calculate( points, 2 );

            // Lo posicionamos
            Vector3 vPosition(-5,2,0);
            pCylinder->SetPosition( vPosition );

            // Añadimos el objeto a la lista.
            m_ObjectList[ std::string(pCylinder->GetName()) ]=  static_cast( pCylinder );
        }
    }

Cuando vamos a renderizar, vamos a acceder a los elementos almacenados en el map, que son punteros a Object, pero realmente contiene referencias a los diferentes tipos de geometrías. Debemos realizar un casting a la inversa ya que las distintas geometrías tienen métodos particulares que no se encuentran presentes en la clase Object.

Para realizar un casting de la clase padre a la clase derivada (ver comentario del código fuente) hay que usar > dynamic_cast< T > (ptr).


    ///////////////////////////////////////////////////////////////////////////////
    ///     RenderSceneObjects: Renderiza los objetos que componen la escena 3D.
    ///
    ///     @param  nada
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void GraphicApplication::RenderSceneObjects()
    {
        Object *pObject;
        OBJECT_MAP::iterator itObj;

        fColorRGBA greenColor   = { 0.0f, 1.0f, 0.0f, 0.0f };   // Verde
        fColorRGBA yellowColor  = { 1.0f, 1.0f, 0.0f, 0.0f };   // Amarillo
        fColorRGBA redColor     = { 1.0f, 0.0f, 0.0f, 0.0f };   // Rojo

        Material greenMaterial, yellowMaterial, redMaterial;

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

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

        memset( &redMaterial, 0, sizeof(Material) );
        redMaterial.ambient     = redColor;
        redMaterial.diffuse     = redColor;
        redMaterial.specular    = redColor;

        for ( itObj=m_ObjectList.begin(); itObj!=m_ObjectList.end(); ++itObj )
        {
            pObject= itObj->second;

            if ( pObject )
            {
                // *****************************************************************************************************************
                // NOTA:
                // La conversión es de una clase-base a una derivada y se resuelve en tiempo de ejecución -> dynamic_cast< T > (ptr)
                // Para poder usar dynamic_cast en Visual C, hay que activar la opción RTTI.
                // Menú: Project -> Settings... -> Pestaña C/C++ -> Category: C++ Language, marcar "Enable Run-Time Type Information (RTTI)".
                // *****************************************************************************************************************

                if ( !strcmp(pObject->GetName(),"CUBO") )
                {
                    Cube *pCube= dynamic_cast(pObject);
                    m_pVideoDriver->SetMaterial  ( greenMaterial );
                    m_pVideoDriver->SetTransform ( pCube->GetWorldMatrix() );
                    pCube->Render();
                }

                else if ( !strcmp(pObject->GetName(),"ESFERA") )
                {
                    Sphere *pSphere= dynamic_cast(pObject);
                    m_pVideoDriver->SetMaterial  ( yellowMaterial );
                    m_pVideoDriver->SetTransform ( pSphere->GetWorldMatrix() );
                    pSphere->Render( 24, 12 );
                }
                else if ( !strcmp(pObject->GetName(),"CILINDRO") )
                {
                    Cylinder *pCylinder= dynamic_cast(pObject);

                    m_pVideoDriver->SetMaterial  ( redMaterial );
                    m_pVideoDriver->SetTransform ( pCylinder->GetWorldMatrix() );
                    pCylinder->Render( 12, 6 );
                }
            }
        } // end for
    }

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



Nota: Compartir en Facebook
Enviado el Miércoles, 05 septiembre a las 21:25:51 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: 5
votos: 3


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 12 - Objetos-3D" | Entrar / Crear Cuenta | 0 Comentarios
Los comentarios son propiedad de quien los envió. No somos responsables por su contenido.

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

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

© Antonio Lucas Moreno