Android-текстурированная сфера

Я хочу нарисовать земной шар на андроиде. В этот момент мне нужна помощь с координатами UV-текстуры. Я использую эту текстуру земли (kibotu.net/earth.jpg). В настоящее время он выглядит как эта передняя сторона (kibotu.net/earthsphere.png), но поворот на 90 ° выглядит так (kibotu.net/earthsphere2.png).

Поскольку OpenGL ES не поддерживает Quadrics и у него нет собственной библиотеки GLUT, мне это довольно сложно. Так что, может быть, кто-то столкнулся с одной и той же проблемой и может мне помочь.

Мой первый подход состоял в том, чтобы использовать Blender и экспортировать его как OBJ-файл и загрузить его в мое приложение. Однако есть 2 побочных эффекта: совершенно странные выглядящие нормали (kibotu.net/sphere.png) и, самое главное, отсутствие текстурных координат.

(Я использовал эти параметры экспорта Blender [kibotu.net/blenderobjoptions.png])

Моя вторая попытка состояла в том, чтобы использовать библиотеку freeglut для выполнения этой работы. Теперь у меня красивая сфера (kibotu.net/sphere5.png). Однако нет координат текстуры. Поскольку последняя версия была выпущена 27 ноября 2009 года, я очень сомневаюсь, что скоро будет обновление.

Поэтому после этого я попытался применить вики-подход для вычисления сферы uvs . Однако это выглядело как kibotu.net/sphere2.png. Я искал каждый поток stackoverflow после этой проблемы и наткнулся на этот подход uv . Однако окончательного решения нет. Я применил его к коду 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); } } 

Может ли кто-нибудь помочь мне понять это, пожалуйста?

Вы должны иметь возможность использовать любую треугольную сетку для сферы (единицы) и применять отображение из вершин (X, Y, Z) в (UV).

Я слишком ленив / занят (удаляю, что бы вы пожелали), чтобы пройти через ваш код, но вы можете найти ответ в главе 6 «Усовершенствованная анимация и методы рендеринга» Watt & Watt. Он дает несколько простых подходов к созданию подходящих УФ-коордов для сфер.

IIRC, чтобы избежать слишком большого искажения на полюсах, их отображение использует синус для сжатия / растяжения широтного отображения.