[英]Android textured Sphere
我想在android上繪制一個地球地球儀。 此時我需要UV紋理坐標的幫助。 我正在使用這個地球紋理(kibotu.net/earth.jpg)。 目前它看起來像這個正面(kibotu.net/earthsphere.png),但90°旋轉它看起來像這樣(kibotu.net/earthsphere2.png)。
由於OpenGL ES不支持Quadrics,並且它沒有原生GLUT庫,我覺得它很難。 所以也許有人遇到同樣的問題,可以幫助我。
我的第一種方法是使用Blender並將其導出為OBJ文件並將其加載到我的應用程序中。 然而,有兩個副作用:完全奇怪的看起來正常(kibotu.net/sphere.png),最重要的是沒有紋理坐標。
(我使用過這些Blender導出選項[kibotu.net/blenderobjoptions.png])
我的第二次嘗試是使用freeglut庫來完成這項工作。 現在我有一個漂亮的球體(kibotu.net/sphere5.png)。 但是也沒有紋理坐標。 由於它的最后一個版本於2009年11月27日發布,我非常懷疑將很快發布更新。
所以在那之后我嘗試應用wiki方法來計算球體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)的映射。
我太懶/忙(刪除任何你想要的)來完成你的代碼,但你可能會在Watt&Watt的“高級動畫和渲染技術”的第6章找到答案。 它提供了一些簡單的方法來為球體生成合適的UV線。
IIRC,為了避免極點處的太多失真,它們的映射使用正弦來擠壓/拉伸緯度映射。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.