2011-09-21 19 views
5

Quiero dibujar un globo terráqueo en Android. En este punto, necesito ayuda con las coordenadas de la textura UV. Estoy usando esta textura de tierra (kibotu.net/earth.jpg). Actualmente se ve como este lado frontal (kibotu.net/earthsphere.png), pero girado 90 ° se ve así (kibotu.net/earthsphere2.png).esfera con textura de Android

Como OpenGL ES no es compatible con Quadrics y no tiene una biblioteca GLUT nativa, me resulta bastante difícil. Entonces, tal vez alguien se encontró con el mismo problema y puede ayudarme.

Mi primer enfoque fue utilizar Blender y exportarlo como archivo OBJ y cargarlo en mi aplicación. Sin embargo, hay 2 efectos secundarios: normales de apariencia extraña (kibotu.net/sphere.png) y lo más importante, sin coordenadas de textura.

(que he usado estas opciones de exportación de Blender [kibotu.net/blenderobjoptions.png])

Mi segundo intento fue usar la biblioteca freeglut para hacer el trabajo. Ahora tengo una esfera bonita (kibotu.net/sphere5.png). Sin embargo, tampoco hay coordenadas de textura. Dado que se lanzó su última versión el 27 de noviembre de 2009, dudo mucho que haya una actualización pronto.

Así que después de eso he intentado aplicar el wiki approach to calculate sphere uvs. Sin embargo, se veía como este kibotu.net/sphere2.png. Estaba buscando cada hilo de stackoverflow después de este problema y me encontré con this uv approach. Sin embargo, no hay una solución final. Lo he aplicado al código freeglut.

static private FloatBuffer sphereVertex; 
static private FloatBuffer sphereNormal; 
static private FloatBuffer sphereTexture; 
static float sphere_parms[]=new float[3]; 
private static void plotSpherePoints(float radius, int stacks, int slices) 
{ 
    sphereVertex = OpenGLUtils.allocateFloatBuffer(4* 6 * stacks * (slices+1)); 
    sphereNormal = OpenGLUtils.allocateFloatBuffer(4* 6 * stacks * (slices+1)); 
    sphereTexture = OpenGLUtils.allocateFloatBuffer(4* 4 * stacks * (slices+1)); 

    int i, j; 
    float slicestep, stackstep; 

    stackstep = ((float)Math.PI)/stacks; 
    slicestep = 2.0f * ((float)Math.PI)/slices; 

    int counter = 0; 

    for (i = 0; i < stacks; ++i) { 
     float a = i * stackstep; 
     float b = a + stackstep; 

     float s0 = (float)Math.sin(a); 
     float s1 = (float)Math.sin(b); 

     float c0 = (float)Math.cos(a); 
     float c1 = (float)Math.cos(b); 

     float nv,u,v,dx,dy,dz; 
     for (j = 0; j <= slices; ++j)  
     { 
      float c = j * slicestep; 
      float x = (float)Math.cos(c); 
      float y = (float)Math.sin(c); 

      nv=x * s0; 
      sphereNormal.put(nv); 
      sphereVertex.put(dx = nv * radius); 

      nv=y * s0; 
      sphereNormal.put(nv); 
      sphereVertex.put(dy = nv * radius); 

      nv=c0; 

      sphereNormal.put(nv); 
      sphereVertex.put(dz = nv * radius); 
      // uv 1 
      if (dz < 0) 
       u = (float) (1 + dx/Math.sqrt(dx*dx+dy*dy+dz*dz)/4); 
      else 
       u = (float) (1 - (1 + dx/Math.sqrt(dx*dx+dy*dy+dz*dz))/4); 

      v = (float) (0.5 + (-dy/Math.sqrt(dx*dx+dy*dy+dz*dz)) /2); 

      // u = (float) (dx/Math.sqrt(dx*dx + dy*dy +dz*dz)); 
      // v = (float) (dy/Math.sqrt(dx*dx + dy*dy +dz*dz)); 
      sphereTexture.put(u); 
      sphereTexture.put(v); 

      nv=x * s1; 

      sphereNormal.put(nv); 
      sphereVertex.put(dx = nv * radius); 

      nv=y * s1; 

      sphereNormal.put(nv); 
      sphereVertex.put(dy = nv * radius); 

      nv=c1; 

      sphereNormal.put(nv); 
      sphereVertex.put(dz = nv * radius); 

      // uv 2 
      if (dz < 0) 
       u = (float) (1 + dx/Math.sqrt(dx*dx+dy*dy+dz*dz)/4); 
      else 
       u = (float) (1 - (1 + dx/Math.sqrt(dx*dx+dy*dy+dz*dz))/4); 

      v = (float) (0.5 + (-dy/Math.sqrt(dx*dx+dy*dy+dz*dz)) /2); 

      sphereTexture.put(u); 
      sphereTexture.put(v); 
     } 
    } 
    sphereNormal.position(0); 
    sphereVertex.position(0); 
    sphereTexture.position(0); 
} 

y el algoritmo de dibujo:

public static class SolidSphere{ 
    public static void draw(GL10 gl,float radius, int slices, int stacks) 
    { 
     int i, triangles; 

     if (sphereVertex!=null) 
     { 
      if (sphere_parms[0] != radius || sphere_parms[1] != slices || sphere_parms[2] != stacks) 
      { 
       sphereVertex=null; 
       sphereNormal=null; 
       sphereTexture = null; 

       gl.glVertexPointer(3, GL10.GL_FLOAT, 0, OpenGLUtils.allocateFloatBuffer(0)); 
       gl.glNormalPointer(GL10.GL_FLOAT, 0, OpenGLUtils.allocateFloatBuffer(0)); 
       gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, OpenGLUtils.allocateFloatBuffer(0)); 
      } 
     } 

     if (sphereVertex==null) 
     { 
      sphere_parms[0] = radius; 
      sphere_parms[1] = (float)slices; 
      sphere_parms[2] = (float)stacks; 

      plotSpherePoints(radius, stacks, slices); 
     } 

     gl.glVertexPointer(3, GL10.GL_FLOAT, 0, sphereVertex); 
     gl.glNormalPointer(GL10.GL_FLOAT, 0, sphereNormal); 
     gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, sphereTexture); 

     gl.glEnableClientState (GL10.GL_VERTEX_ARRAY); 
     gl.glEnableClientState (GL10.GL_NORMAL_ARRAY); 
     gl.glEnableClientState (GL10.GL_TEXTURE_COORD_ARRAY); 

     triangles = (slices + 1) * 2; 
     for(i = 0; i < stacks; i++) 
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, i * triangles, triangles); 

     gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
     gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); 
     gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); 
    } 
} 

¿Puede alguien ayudarme a calcular esto, por favor?

Respuesta

1

Debería poder tomar cualquier malla triangular para una esfera (unidad) y aplicar un mapeo desde el vértice (X, Y, Z) a (UV).

Estoy demasiado vago/ocupado (elimine lo que desee) para ir a través de su código, pero puede encontrar la respuesta en el capítulo 6 de Watt & Watt "Técnicas avanzadas de animación y representación". Proporciona algunos enfoques simples para generar coords UV adecuados para esferas.

IIRC, para evitar demasiada distorsión en los polos, su mapeo utiliza el seno para exprimir/estirar el mapeo de latitud.

+0

La solución final se puede encontrar aquí: https://github.com/kibotu/net.gtamps/blob/refactoring3d/android/graphic/src/net/gtamps/android/renderer/graph/scene/primitives/Sphere .Java –