将圆柱体变成球体而不会在杆上捏住

时间:2015-03-18 15:34:19

标签: math 3d geometry

我正致力于生成由六边形网格构成的行星。不需要极点 - 使这更容易一些。有没有更好的方法将圆柱体转变为具有均匀六边形/三角形的球体?

这是所需的步骤:

  1. 生成六边形的二维平面(确定)
  2. 将飞机变成圆柱(ok)
  3. 将气缸转变为球体/地圈(有点作品)
  4. 对于第2步,我只使用Sin和Cos将顶点移动到圆形中。 对于第3步,我现在只使用:vertices[i] = vertices[i].normalized * radius;

    图像可视化当前的问题。

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

1 个答案:

答案 0 :(得分:5)

我会进行球体三角测量而不是圆柱到球体的映射......

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

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

  2. 然后递归细分三角形

    将线分割为一半并更改中点坐标以与球体表面对齐。这将创建三角形球体。细分有效点数以形成六边形并具有足够的网格点。

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

    因此,取另外6点并计算平均坐标,为中间点提供点...

  4. 这样的事情:

    hexagonation

    了解更多想法:

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

    有点好奇,所以我尝试编码这种用法很简单:

    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

    顶部和底部的杆看起来足够好,沿着赤道存在一些变形但部分地也可能由鱼眼引起。如果初始形状是更接近所需结果开始几何形状的进给,那么它可能有更好的结果