math 3d geometry

math - Convertir un cilindro en una esfera sin pellizcar los polos



3d geometry (1)

Estoy trabajando en generar un planeta hecho de una cuadrícula hexagonal. Los postes 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 / triángulos 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, ahora solo estoy usando: vertices[i] = vertices[i].normalized * radius;

Imagen para visualizar el problema tal como está actualmente.

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


En lugar de mapear 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 hace la mitad solamente y refleja el otro cuando todo está hecho ...

  2. luego subdividir recursivamente los triángulos

    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 un número válido 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

    Entonces tome los otros 6 puntos y calcule las coordenadas promedio que le dan el punto para el medio ...

Algo como esto:

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 de hexágono)

//--------------------------------------------------------------------------- #include <math.h> #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;i<fac.num;i++,f++) { glVertex3dv(pnt.dat[f->i0].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;i<fac.num;i++,f++) { glBegin(GL_LINE_LOOP); glVertex3dv(pnt.dat[f->i0].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; p.p[0]= 0.0; p.p[1]= 0.0; p.p[2]=+1.0; pnt.add(p); p.p[2]=-1.0; pnt.add(p); for (i=0,a=0.0;i<6;i++,a+=da) { p.p[0]=cos(a); p.p[1]=sin(a); p.p[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;i<m;i++)// scan through all original faces { g=&fac[i]; // point indexes i0=g->i0; 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++) p.p[j]=0.5*(pnt[i0].p[j]+pnt[i1].p[j]); a=1.0/sqrt((p.p[0]*p.p[0])+(p.p[1]*p.p[1])+(p.p[2]*p.p[2])); for (j=0;j<3;j++) p.p[j]*=a; pnt.add(p); for (j=0;j<3;j++) p.p[j]=0.5*(pnt[i1].p[j]+pnt[i2].p[j]); a=1.0/sqrt((p.p[0]*p.p[0])+(p.p[1]*p.p[1])+(p.p[2]*p.p[2])); for (j=0;j<3;j++) p.p[j]*=a; pnt.add(p); for (j=0;j<3;j++) p.p[j]=0.5*(pnt[i2].p[j]+pnt[i0].p[j]); a=1.0/sqrt((p.p[0]*p.p[0])+(p.p[1]*p.p[1])+(p.p[2]*p.p[2])); for (j=0;j<3;j++) p.p[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); } } //---------------------------------------------------------------------------

Era un poco curioso, así que intenté 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 de resultados

los polos superior e inferior se ven lo suficientemente bien, hay cierta distorsión a lo largo de los ecuadores, pero en parte también puede ser causada por el ojo de pez. Si la forma inicial se alimenta con una geometría de inicio más cercana al resultado deseado, entonces puede tener resultados mucho mejores