2011-09-21 76 views
5

我想在android上绘制地球地球。此时我需要UV纹理坐标的帮助。我正在使用这个地球纹理(kibotu.net/earth.jpg)。目前看起来像这个前端(kibotu.net/earthsphere.png),但90°旋转它看起来像这样(kibotu.net/earthsphere2.png)。Android纹理球体

由于OpenGL ES不支持Quadrics,并且它没有原生的GLUT库,所以我觉得它很困难。所以也许有人遇到同样的问题,可以帮助我。

我的第一种方法是使用Blender并将其导出为OBJ文件并将其加载到我的应用程序中。但是有2个副作用:完全奇怪的看法线(kibotu.net/sphere.png),最重要的是没有纹理坐标。

(我用这些搅拌机导出选项[kibotu.net/blenderobjoptions.png])

我的第二次尝试使用freeglut库来完成这项工作。现在我有一个漂亮的球体(kibotu.net/sphere5.png)。但是也没有纹理坐标。由于它是2009年11月27日发布的最后一个版本,我非常怀疑随时会有更新。

所以在那之后我试着申请wiki approach to calculate sphere uvs。但它看起来像这个kibotu.net/sphere2.png。在这个问题之后,我正在搜索每个单独的stackoverflow线程,并且遇到了this uv approach。但是没有最终的解决方案。我已经将它应用于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); 
} 

和绘制算法:

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

谁能帮我搞清楚了这一点吗?

回答

1

您应该能够为(单位)球体拍摄任何三角形网格,并应用顶点(X,Y,Z)到(UV)的映射。

瓦特的“高级动画和渲染技术”第6章中提到了我太懒惰/繁忙(删除任何你想要的)代码,但你可能会找到答案。它提供了一些简单的方法来为球体产生合适的紫外线坐标。

IIRC,为了避免极点失真太多,它们的映射使用正弦来挤压/拉伸纬度映射。

+0

最终的解决方案可以在这里找到:https://github.com/kibotu/net.gtamps/blob/refactoring3d/android/graphic/src/net/gtamps/android/renderer/graph/scene/primitives/Sphere的.java –