我建议使用球面三角网格而不是圆柱形到球形的映射...
首先从两个六边形开始
每个六边形从极点开始,到赤道结束,或者只做一半,在全部完成后镜像另一半...
然后递归地将三角形细分
所以将线段分成一半,并将中点坐标更改为与球面表面对齐。这将创建一个三角形球体。将其细分为合法的网格点数以形成六边形并具有足够的网格点。
将六边形中点坐标改回六边形平面上
因此,需要取另外6个点并计算平均坐标,这将为您提供中心点...
类似这样:
![hexagonation](https://istack.dev59.com/d5zwu.webp)
更多想法请查看此处:
[编辑1] 三角剖分(无六边形修正)
#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; }; };
class _fac { public: int i0,i1,i2; _fac(){}; _fac(_fac& a){ *this=a; }; ~_fac(){}; _fac* operator = (const _fac *a) { *this=*a; return this; }; };
List<_pnt> pnt;
List<_fac> fac;
mesh() {}
mesh(mesh& a) { *this=a; }
~mesh() {}
mesh* operator = (const mesh *a) { *this=*a; return this; }
void draw();
void sphere(int n);
};
void mesh::draw()
{
int i;
_fac *f;
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();
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)
{
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);
}
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);
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);
for (;n>0;n--)
for (m=fac.num,i=0;i<m;i++)
{
g=&fac[i];
i0=g->i0; j0=pnt.num;
i1=g->i1; j1=j0+1;
i2=g->i2; j2=j0+2;
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);
g->i0=j0; g->i1=j1; g->i2=j2;
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);
}
}
我有点好奇,所以尝试编码,使用方法很简单:
mesh obj; // somewhere global...
obj.sphere(3); // init (call once or on change of n...)
obj.draw(); // inside your gl draw scene routine/event...
以下是结果概述:
![result](https://istack.dev59.com/JWkjH.webp)
顶部和底部极点看起来足够好,赤道周围存在一些畸变,但这可能也是由于鱼眼造成的。如果将初始形状与所需结果的起始几何形状更接近,则可能会有更好的结果。