2011-09-21 12 views
5

Voglio disegnare un globo terrestre su Android. A questo punto ho bisogno di aiuto con le coordinate della texture UV. Sto usando questa texture terrestre (kibotu.net/earth.jpg). Attualmente sembra questo lato anteriore (kibotu.net/earthsphere.png), ma ruotato di 90 ° sembra così (kibotu.net/earthsphere2.png).Sfera con texture Android

Poiché OpenGL ES non supporta Quadrics e non ha una libreria GLUT nativa, trovo piuttosto difficile. Quindi forse qualcuno ha incontrato lo stesso problema e può aiutarmi.

Il mio primo approccio è stato quello di usare Blender ed esportarlo come OBJ file e caricarlo nella mia applicazione. Tuttavia ci sono 2 effetti collaterali: normalissime dall'aspetto assolutamente strano (kibotu.net/sphere.png) e, soprattutto, nessuna coordinata della trama.

(ho usato queste opzioni di esportazione Blender [kibotu.net/blenderobjoptions.png])

Il mio secondo tentativo è stato quello di utilizzare la libreria freeglut per fare il lavoro. Ora ho una bella sfera (kibotu.net/sphere5.png). Tuttavia non ci sono nemmeno le coordinate della trama. Dal momento che la sua ultima versione è stata rilasciata il 27 novembre 2009, dubito fortemente che ci sarà un aggiornamento in qualunque momento presto.

Quindi dopo che ho provato ad applicare il wiki approach to calculate sphere uvs. Comunque sembrava questo kibotu.net/sphere2.png. Stavo cercando ogni singolo thread di stackoverflow dopo questo problema e ho trovato this uv approach. Tuttavia non esiste una soluzione finale. L'ho applicato al codice 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); 
} 

e l'algoritmo di disegno:

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); 
    } 
} 

Qualcuno può aiutarmi a capire questo fuori per favore?

risposta

1

Si dovrebbe essere in grado di prendere qualsiasi maglia triangolare per una sfera (unit) e applicare una mappatura dal vertice (X, Y, Z) a (UV).

Sono troppo pigro/occupato (cancella quello che desideri) per passare attraverso il tuo codice, ma potresti trovare la risposta nel capitolo 6 di Watt & "Advanced Animation and Rendering Techniques" di Watt. Fornisce alcuni semplici approcci per generare coordini UV adatti per le sfere.

IIRC, per evitare troppe distorsioni ai poli, la loro mappatura utilizza il seno per comprimere/estendere la mappatura della latitudine.

+0

La soluzione finale può essere trovata qui: https://github.com/kibotu/net.gtamps/blob/refactoring3d/android/graphic/src/net/gtamps/android/renderer/graph/scene/primitives/Sphere .Giava –