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:
- Generar un plano 2D de hexágonos (ok)
- Convierte el avión en un cilindro (ok)
- 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 ...
-
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 ...
-
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.
-
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