Aplicando el mapa de la textura de la tierra una Esfera

He estado tratando de implementar una animación 3D en OpenGL (usando JOGL) de un sistema solar. Hasta ahora tengo 5 planetas de diferentes tamaños pero el problema que parece tener es que no puedo agregar un mapa de la textura de la tierra en una Esfera. ayúdame en cómo se hace?

Este es el código que tengo hasta ahora en mi método de visualización:

@Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); GLU glu = new GLU(); gl.glClear(GL.GL_COLOR_BUFFER_BIT); //make sure we are in model_view mode gl.glMatrixMode(GL2.GL_MODELVIEW); gl.glLoadIdentity(); glu.gluLookAt(10,20,20,0,3,0,0, 20, 0); //gl.glMatrixMode(GL2.GL_PROJECTION); //glu.gluPerspective(45,1,1,25); //render ground plane gl.glPushMatrix(); gl.glTranslatef(-10.75f, 3.0f, -1.0f); gl.glColor3f(0.3f, 0.5f, 1f); GLUquadric earth = glu.gluNewQuadric(); glu.gluQuadricDrawStyle(earth, GLU.GLU_FILL); glu.gluQuadricNormals(earth, GLU.GLU_FLAT); glu.gluQuadricOrientation(earth, GLU.GLU_OUTSIDE); final float radius = 3.378f; final int slices = 89; final int stacks = 16; glu.gluSphere(earth, radius, slices, stacks); glu.gluDeleteQuadric(earth); Texture earths; try { earths = TextureIO.newTexture(new File("earth.png"), true); } catch (IOException e) { javax.swing.JOptionPane.showMessageDialog(null, e); } gl.glPopMatrix(); //gl.glEnd(); gl.glPushMatrix(); gl.glTranslatef(2.75f, 3.0f, -0.0f); gl.glColor3f(0.3f, 0.5f, 1f); GLUquadric earth1 = glu.gluNewQuadric(); glu.gluQuadricDrawStyle(earth1, GLU.GLU_FILL); glu.gluQuadricNormals(earth1, GLU.GLU_FLAT); glu.gluQuadricOrientation(earth1, GLU.GLU_OUTSIDE); final float radius1 = 3.378f; final int slices1 = 90; final int stacks1 = 63; glu.gluSphere(earth1, radius1, slices1, stacks1); glu.gluDeleteQuadric(earth1); gl.glPopMatrix(); gl.glPushMatrix(); gl.glTranslatef(3.75f, 6.0f, -7.20f); gl.glColor3f(0.3f, 0.5f, 1f); GLUquadric earth3 = glu.gluNewQuadric(); glu.gluQuadricDrawStyle(earth3, GLU.GLU_FILL); glu.gluQuadricNormals(earth3, GLU.GLU_FLAT); glu.gluQuadricOrientation(earth1, GLU.GLU_OUTSIDE); final float radius3 = 1.878f; final int slices3 = 89; final int stacks3 = 16; glu.gluSphere(earth3, radius3, slices3, stacks3); glu.gluDeleteQuadric(earth3); gl.glPopMatrix(); gl.glPushMatrix(); gl.glTranslatef(12.75f, 2.0f, -7.20f); gl.glColor3f(0.3f, 0.5f, 1f); GLUquadric earth4 = glu.gluNewQuadric(); glu.gluQuadricDrawStyle(earth4, GLU.GLU_FILL); glu.gluQuadricNormals(earth4, GLU.GLU_FLAT); glu.gluQuadricOrientation(earth4, GLU.GLU_OUTSIDE); final float radius4 = 1.078f; final int slices4 = 89; final int stacks4 = 16; glu.gluSphere(earth4, radius4, slices4, stacks4); glu.gluDeleteQuadric(earth4); gl.glPopMatrix(); gl.glPushMatrix(); gl.glTranslatef(2.75f, -6.0f, -0.0f); gl.glColor3f(0.3f, 0.5f, 1f); GLUquadric earth5 = glu.gluNewQuadric(); glu.gluQuadricDrawStyle(earth5, GLU.GLU_FILL); glu.gluQuadricNormals(earth5, GLU.GLU_FLAT); glu.gluQuadricOrientation(earth5, GLU.GLU_OUTSIDE); final float radius5 = 3.778f; final int slices5 = 90; final int stacks5 = 63; glu.gluSphere(earth5, radius5, slices5, stacks5); glu.gluDeleteQuadric(earth5); gl.glPopMatrix(); } 

  1. crea tu propia malla de esfera

    bucle 2D simple a través de 2 angularjs (sistema de coordenadas esféricas 2 cartesianas). Puede agregar fácilmente propiedades elipsoidales (la tierra no es una esfera) si quiere más precisión. Si no, entonces puedes usar malla de esfera única para todos los planetas y simplemente escalarla antes de usar …

    a sea ​​a la longitud b la latitud, de modo que bucle a de 0 a 2*PI [rad] b de -0.5*PI a +0.5*PI [rad] donde PI=3.1415... es el Pi (en C ++ .h se llama M_PI ). Si su api de matemáticas usa grados, conviértalo en grados PI [rad] = 180.0 [deg]

  2. agregue la información necesaria por vértice

    normales para iluminación

      // just unit sphere nx=cos(b)*cos(a); ny=cos(b)*sin(a); nz=sin(b); 

    Coordenada de textura (suponiendo que la imagen no está distorsionada en el rectángulo)

      // just convert a,b to <0,1> range tx=a/(2.0*PI) ty=(b/PI)+0.5; 

    ejemplo de textura

    posición del vértice

      // just sphere(rx=ry=rz=r) or ellipsoid (rx=ry=equatorial and rz=polar radius) // can also use rx*nx,ry*ny,rz*nz instead ... x=rx*cos(b)*cos(a); y=ry*cos(b)*sin(a); z=rz*sin(b); 
  3. envía todo esto a OpenGL

    así que todo lo anterior almacena en algún espacio de memoria ( CPU o GPU ) y luego envía a renderizado. Puede usar glBegin(QUAD_STRIP); ... glEnd(); heredado glBegin(QUAD_STRIP); ... glEnd(); glBegin(QUAD_STRIP); ... glEnd(); o displaylist / VBO / VAO. Enlaza la textura correcta antes de cada planeta / cuerpo y no te olvides de actualizar la matriz ModelView también. Así es como se ven los sistemas de coordenadas de la mina:

    sistemas coordinados

También eche un vistazo a estas preguntas y respuestas relacionadas:

  • sistema solar de n-cuerpo realista
  • esfera de malla por subdivision

[edit1] Ejemplo de C ++

 //--------------------------------------------------------------------------- const int nb=15; // slices const int na=nb< <1; // points per equator class planet { public: bool _init; // has been initiated ? GLfloat x0,y0,z0; // center of planet [GCS] GLfloat pos[na][nb][3]; // vertex GLfloat nor[na][nb][3]; // normal GLfloat txr[na][nb][2]; // texcoord GLuint txrid; // texture id GLfloat t; // dayly rotation angle [deg] planet() { _init=false; txrid=0; x0=0.0; y0=0.0; z0=0.0; t=0.0; } ~planet() { if (_init) glDeleteTextures(1,&txrid); } void init(GLfloat r,AnsiString texture); // call after OpenGL is already working !!! void draw(); }; void planet::init(GLfloat r,AnsiString texture) { if (!_init) { _init=true; glGenTextures(1,&txrid); } GLfloat x,y,z,a,b,da,db; GLfloat tx0,tdx,ty0,tdy;// just correction if CLAMP_TO_EDGE is not available int ia,ib; // a,b to texture coordinate system tx0=0.0; ty0=0.5; tdx=0.5/M_PI; tdy=1.0/M_PI; // load texture to GPU memory if (texture!="") { Byte q; unsigned int *pp; int xs,ys,x,y,adr,*txr; union { unsigned int c32; Byte db[4]; } c; Graphics::TBitmap *bmp=new Graphics::TBitmap; // new bmp bmp->LoadFromFile(texture); // load from file bmp->HandleType=bmDIB; // allow direct access to pixels bmp->PixelFormat=pf32bit; // set pixel to 32bit so int is the same size as pixel xs=bmp->Width; // resolution should be power of 2 ys=bmp->Height; txr=new int[xs*ys]; for(adr=0,y=0;yScanLine[y]; for(x=0;x txr[] c.c32=pp[x]; q =c.db[2]; c.db[2]=c.db[0]; c.db[0]=q; txr[adr]=c.c32; } } glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,txrid); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0, GL_RGBA, GL_UNSIGNED_BYTE, txr); glDisable(GL_TEXTURE_2D); delete bmp; delete[] txr; // texture coordinates by 1 pixel from each edge (GL_CLAMP_TO_EDGE) tx0+=1.0/GLfloat(xs); ty0+=1.0/GLfloat(ys); tdx*=GLfloat(xs-2)/GLfloat(xs); tdy*=GLfloat(ys-2)/GLfloat(ys); } // correct texture coordinate system (invert x) tx0=1.0-tx0; tdx=-tdx; da=(2.0*M_PI)/GLfloat(na-1); db= M_PI /GLfloat(nb-1); for (ib=0,b=-0.5*M_PI;ib 

uso:

 // variable to store planet (global) planet earth; // init after OpenGL initialisation earth.init(1.0,"earth.bmp"); // position update earth.x0= 0.0; earth.y0= 0.0; earth.z0=-20.0; // add this to render loop earth.draw(); // draws the planet earth.t+=2.5; // just rotate planet by 2.5 deg each frame... 

ejemplo

Sé que es feo, pero no usa nada gracioso, solo legado OpenGL y Math.h ( cos(),sin(),M_PI ) y VCL para carga de bitmap. Así que reescribe a tu entorno y estarás bien. No olvides que cada planeta tiene su propia textura, por lo que debes tener una txrid por planeta, por lo tanto, txrid tener cada planeta como una variable de planet separada o reescribir ...