将圆柱体变成球体而不夹在两极 [英] Turning a cylinder into a sphere without pinching at the poles

查看:38
本文介绍了将圆柱体变成球体而不夹在两极的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力生成一个由六边形网格构成的行星.不需要杆子 - 使这更容易一些.有没有更好的方法可以将圆柱体变成具有统一六边形/三角形的球体?

I'm working on generating a planet made out of a hexagon grid. The poles aren't needed - making this a bit easier. Is there a better way to turn the cylinder into a sphere that would have uniform hexagons/triangles?

这是所需的步骤:

  1. 生成六边形的二维平面(ok)
  2. 将飞机变成圆柱体(ok)
  3. 将圆柱体变成球体/地圈(作品类型)

对于第 2 步,我只是使用 Sin 和 Cos 将顶点移动为圆形.对于第 3 步,现在我只使用:vertices[i] = vertices[i].normalized * radius;

For step 2, I'm just using Sin and Cos to move the vertices into a circular shape. For step 3, right now I'm just using: vertices[i] = vertices[i].normalized * radius;

图像显示当前的问题.

请注意,电线杆是故意切断的.红色部分显示了一个六边形网格的样子.因为它们用于游戏玩法和视觉元素,所以我必须保持它们大致相同的大小和方向.每个十六进制都有一个邻居列表,基本上就像一个图表.

Note that the poles are cut off on purpose. The red parts show what one hexagon mesh looks like. I would have to keep them roughly the same size and orientation since they are used for gameplay and visual elements. Each hex has a list of neighbors and works like a graph basically.

推荐答案

我会做一个球体三角剖分,而不是圆柱到球体的映射...

Instead of cylinder to sphere mapping I would do a sphere triangulation...

  1. 我会先从 2 个六边形开始

每个都从极点开始,在赤道结束,或者只做一半并在完成后镜像另一个......

each start at pole and end on the equator or do the half only and mirror the other when all done...

然后递归细分三角形

因此将线分成两半并更改中点坐标以与球面对齐.这将创建三角球体.细分到有效数量的点,形成六边形并有足够的网格点.

so divide lines to half and change the mid point coordinate to align with sphere surface. This will create triangulated sphere. Subdivide to valid number of points to form hexagons and have enough grid points.

将六边形中点坐标改回六边形平面

所以取其他 6 个点并计算平均坐标,这为您提供中间点 ...

So take the other 6 point and compute average coordinates which gives you the point for middle ...

像这样:

更多想法请看这里:

[edit1] 三角测量(无六边形校正)

//---------------------------------------------------------------------------
#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);
        }
    }
//---------------------------------------------------------------------------

有点好奇所以我试着编码这个用法很简单:

Was a bit curious so I tried to encode this usage is 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...

这里是结果概览

顶极和底极看起来足够好,沿赤道存在一些失真,但部分失真也可能是由鱼眼引起的.如果初始形状更接近于想要的结果起始几何体,那么它可能会有更好的结果

top and bottom poles looks good enough, some distortion is present along the equators but partially it can be caused also by fish-eye. If the initial shape is feed with closer to wanted result start geometry then it may have much better results

这篇关于将圆柱体变成球体而不夹在两极的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆