Convirtiendo un cilindro en una esfera sin pellizcar los polos

Estoy trabajando en la generación de un planeta hecho de una red hexagonal. Los polos no son necesarios, lo que hace que esto sea un poco más fácil. ¿Hay una mejor manera de convertir el cilindro en una esfera que tenga hexágonos / triangularjs uniformes?

Aquí están los pasos deseados:

  1. Generar un plano 2D de hexágonos (ok)
  2. Convierte el avión en un cilindro (ok)
  3. Convierta el cilindro en una esfera / geosfera (tipo de obras)

Para el paso 2, solo estoy usando Sin y Cos para mover los vértices a una forma circular. Para el paso 3, en este momento solo estoy usando: vertices[i] = vertices[i].normalized * radius;

Imagen para visualizar el problema tal como está actualmente.

Tenga en cuenta que los polos están cortados a propósito. Las partes rojas muestran cómo se ve una malla hexagonal. Tendría que mantenerlos más o menos del mismo tamaño y orientación, ya que se utilizan para el juego y elementos visuales. Cada hex tiene una lista de vecinos y funciona básicamente como un gráfico.

En lugar del mapeo de cilindro a esfera, haría una triangulación de esfera …

  1. Primero comenzaría con 2 hexágonos

    cada uno comienza en el polo y termina en el ecuador o solo hace la mitad y refleja el otro cuando todo está hecho …

  2. luego subdividir recursivamente los triangularjs

    así que divida las líneas a la mitad y cambie la coordenada del punto medio para alinearla con la superficie de la esfera. Esto creará una esfera triangulada. Subdividir a una cantidad válida de puntos para formar hexágonos y tener suficientes puntos de cuadrícula.

  3. cambiar las coordenadas del punto medio del hexágono de nuevo al plano del hexágono

    Así que tome los otros 6 puntos y calcule las coordenadas promedio que le da el punto para el medio …

Algo como esto:

hexagonacion

para más ideas mira aquí:

  • Ubicación de mayor densidad en una esfera
  • Haz una esfera con vértices equidistantes

[edit1] triangulación (sin correcciones hexagonales)

 //--------------------------------------------------------------------------- #include  #include "list.h" class mesh { public: class _pnt { public: double p[3]; _pnt(){}; _pnt(_pnt& a){ *this=a; }; ~_pnt(){}; _pnt* operator = (const _pnt *a) { *this=*a; return this; }; /*_pnt* operator = (const _pnt &a) { ...copy... return this; };*/ }; class _fac { public: int i0,i1,i2; _fac(){}; _fac(_fac& a){ *this=a; }; ~_fac(){}; _fac* operator = (const _fac *a) { *this=*a; return this; }; /*_fac* operator = (const _fac &a) { ...copy... return this; };*/ }; List<_pnt> pnt; // mesh points List<_fac> fac; // mesh triangles mesh() {} mesh(mesh& a) { *this=a; } ~mesh() {} mesh* operator = (const mesh *a) { *this=*a; return this; } //mesh* operator = (const mesh &a) { ...copy... return this; } void draw(); // draws the mesh with OpenGL void sphere(int n); // init mesh with unit sphere from triangles (n recursion layers) }; //--------------------------------------------------------------------------- void mesh::draw() { int i; _fac *f; // fill glColor3f(0.7,0.7,0.7); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glDepthFunc(GL_LEQUAL); glBegin(GL_TRIANGLES); for (i=0,f=fac.dat;ii0].p); glVertex3dv(pnt.dat[f->i1].p); glVertex3dv(pnt.dat[f->i2].p); } glEnd(); // wireframe glColor3f(0.1,0.3,0.7); glLineWidth(2.0); for (i=0,f=fac.dat;ii0].p); glVertex3dv(pnt.dat[f->i1].p); glVertex3dv(pnt.dat[f->i2].p); glEnd(); } glLineWidth(1.0); } //--------------------------------------------------------------------------- void mesh::sphere(int n) { // init 2 hexagons int i,j,m,i0,i1,i2,j0,j1,j2; double a,da=M_PI/3.0; double *p0,*p1; _pnt p; _fac f,*g; pp[0]= 0.0; pp[1]= 0.0; pp[2]=+1.0; pnt.add(p); pp[2]=-1.0; pnt.add(p); for (i=0,a=0.0;i<6;i++,a+=da) { pp[0]=cos(a); pp[1]=sin(a); pp[2]= 0.0; pnt.add(p); } // top half f.i0=0; f.i1=2; f.i2=3; fac.add(f); f.i0=0; f.i1=3; f.i2=4; fac.add(f); f.i0=0; f.i1=4; f.i2=5; fac.add(f); f.i0=0; f.i1=5; f.i2=6; fac.add(f); f.i0=0; f.i1=6; f.i2=7; fac.add(f); f.i0=0; f.i1=7; f.i2=2; fac.add(f); // botom half f.i0=1; f.i1=3; f.i2=2; fac.add(f); f.i0=1; f.i1=4; f.i2=3; fac.add(f); f.i0=1; f.i1=5; f.i2=4; fac.add(f); f.i0=1; f.i1=6; f.i2=5; fac.add(f); f.i0=1; f.i1=7; f.i2=6; fac.add(f); f.i0=1; f.i1=2; f.i2=7; fac.add(f); // subdivide triangles for (;n>0;n--) // recursion layers for (m=fac.num,i=0;ii0; j0=pnt.num; // i0 i1=g->i1; j1=j0+1; // j0 j2 i2=g->i2; j2=j0+2; // i1 j1 i2 // genere mid points + sphere surface correction distance from (0,0,0) must be 1.0 (radius) for (j=0;j<3;j++) pp[j]=0.5*(pnt[i0].p[j]+pnt[i1].p[j]); a=1.0/sqrt((pp[0]*pp[0])+(pp[1]*pp[1])+(pp[2]*pp[2])); for (j=0;j<3;j++) pp[j]*=a; pnt.add(p); for (j=0;j<3;j++) pp[j]=0.5*(pnt[i1].p[j]+pnt[i2].p[j]); a=1.0/sqrt((pp[0]*pp[0])+(pp[1]*pp[1])+(pp[2]*pp[2])); for (j=0;j<3;j++) pp[j]*=a; pnt.add(p); for (j=0;j<3;j++) pp[j]=0.5*(pnt[i2].p[j]+pnt[i0].p[j]); a=1.0/sqrt((pp[0]*pp[0])+(pp[1]*pp[1])+(pp[2]*pp[2])); for (j=0;j<3;j++) pp[j]*=a; pnt.add(p); // change original fac g->i0=j0; g->i1=j1; g->i2=j2; // add 3 x fac f.i0=i0; f.i1=j0; f.i2=j2; fac.add(f); f.i0=j0; f.i1=i1; f.i2=j1; fac.add(f); f.i0=j2; f.i1=j1; f.i2=i2; fac.add(f); } } //--------------------------------------------------------------------------- 

Fue un poco curioso, así que traté de codificar este uso es simple:

 mesh obj; // somewhere global... obj.sphere(3); // init (call once or on change of n...) obj.draw(); // inside your gl draw scene routine/event... 

Así que aquí está el resumen del resultado

resultado

Los polos superior e inferior se ven lo suficientemente buenos, hay algo de distorsión a lo largo del ecuador, pero parcialmente también puede ser causado por el ojo de pez. Si la forma inicial se alimenta con una geometría de inicio de resultado más cercana a la deseada, entonces puede tener resultados mucho mejores