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 20 - Mapeado Esférico. 
DirectX/Opengl

Vamos a ver cómo mapear una textura sobre una esfera. Nos vendrá bien para renderizar planetas, por ejemplo.



En el método Render() de la clase Sphere, se ha añadido las coordenadas de textura con el siguiente planteamiento:

Tenemos que mapear la textura sobre el total de la circunferancia. Es decir, si la longitud de la circunferencia es 2*PI*r tenemos que asociarla al rango 0-1. Nos da igual el radio de la circunferencia, así que simplificaremos para r=1.

Horizontalmente, tenemos que cada división es xzAngle y xyAngle en vertical. Así cada coordenada de textura será igual a la porción multiplicada por el elemento i o j usado en ese momento. Para reducirlo a un rango de 0 a 1 habrá que dividir por el total, 2*PI.

En vertical, en lugar de ser 2*PI (la longitud total de la circunferencia), sólo será la mitad PI, ya que la textura recorre de un polo a otro.

Como renderiamos la esfera (recorremos sus vértices) de Este a Oeste y el rango de la textura va de 0 a 1 de Oeste a Este (al revés) por eso hacemos 1-coordenada_textura, para invertir dicho orden.

Si finalmente sustituimos xzAngle y xyAngle por sus valores 2*PI/slices y 2*PI/stacks, las fórmulas se nos simplifican. Sólo hay que reseñar, que si el sistema de ejes es de mano izquierda, la coordenada su sigue el mismo orden que los vértices.

Con todo esto, la función que renderiza la esfera queda:


    ///////////////////////////////////////////////////////////////////////////////
    ///     Render: Renderiza la esfera.
    ///
    ///     @param  int slices: Nº de divisiones verticales (meridianos).
    ///     @param  int stacks: Nº de divisiones transversales (paralelos).
    ///
    ///     @return  nada
    ///////////////////////////////////////////////////////////////////////////////
    void Sphere::Render( int slices, int stacks )
    {
        float x0, y0, z0;
        float x1, y1, z1;
        float sinxy;
        int i, j, v= 0;

        unsigned int numVertex  = 2*slices*stacks;
        float        xzAngle    = 2.0f*PI/(float)slices;
        float        xyAngle    = 2.0f*PI/(float)stacks;

        if ( numVertex <= MAX_VERTEX_SPHERE )
        {
            for (i=0; i// Meridianos
            {
                for (j=0; j// Paralelos
                {
                    sinxy= sin(j*xyAngle);  // Para no calcularlo 4 veces

                    x0= sinxy * cos(i*xzAngle);
                    y0= cos(j*xyAngle);
                    z0= sinxy * sin(i*xzAngle);

                    // Vértice
                    m_Vertex[v].x = m_Radius*x0;
                    m_Vertex[v].y = m_Radius*y0;
                    m_Vertex[v].z = m_Radius*z0;

                    // Normal
                    m_Vertex[v].nx= x0;
                    m_Vertex[v].ny= y0;
                    m_Vertex[v].nz= z0;

    // ********************************* NEW **************************************
                    if ( IVideoDriver::GetVideoDriver()->GetAxisSystem() == eRightHanded )
                        m_Vertex[v].su= 1.0f-i/(float)slices;               // SU= 1-i*xzAngle/2PI
                    else
                        m_Vertex[v].su= i/(float)slices;                    // SU= i*xzAngle/2PI

                    m_Vertex[v].tv= ((float)stacks-2.0f*j)/(float)stacks;   // TV= 1-j*xyAngle/PI
    // ****************************************************************************

                    v++;

                    x1= sinxy * cos((i+1)*xzAngle);
                    y1= y0;
                    z1= sinxy * sin((i+1)*xzAngle);

                    m_Vertex[v].x = m_Radius*x1;
                    m_Vertex[v].y = m_Radius*y1;
                    m_Vertex[v].z = m_Radius*z1;
                    m_Vertex[v].nx= x1;
                    m_Vertex[v].ny= y1;
                    m_Vertex[v].nz= z1;
    // ********************************* NEW **************************************
                    if ( IVideoDriver::GetVideoDriver()->GetAxisSystem() == eRightHanded )
                        m_Vertex[v].su= 1.0f-(i+1)/(float)slices;
                    else
                        m_Vertex[v].su= (i+1)/(float)slices;

                    m_Vertex[v].tv= m_Vertex[v-1].tv;   // Igual que el anterior.
    // ****************************************************************************

                    v++;
                }
            }

            IVideoDriver::GetVideoDriver()->RenderVertexArray( eTriangleStrip, (BYTE*)m_Vertex, sizeof(Vertex),
                                                               0, numVertex, eFVF_XYZ|eFVF_NORMAL|eFVF_TEX1 );
        }
    }

Si queréis renderizar más planetas, aquí podéis encontrar las texturas para los planetas del Sistema Solar:
http://planetpixelemporium.com/planets.html

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



Nota: Compartir en Facebook
Enviado el Martes, 29 abril a las 10:42:08 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: 2


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 20 - Mapeado Esférico." | 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