0

It sounds easy for me until I tried

The implementation uses lib igl but the problem is not there but in my lack of math knowledge :-\

Eigen::MatrixXd p;
const int size = 128;
p.resize(size * size, 3);
int index = 0;

for (int y = 0; y < size; y++)
{
  double ypos = (double(y) / double(size - 1)) - 0.5;
  for (int x = 0; x < size; x++)
  {
    double xpos = (double(x) / double(size - 1)) - 0.5;

    const double sphericalTheta = xpos * (pi / 2.0);
    const double sphericalPhi = ypos * (pi / 2.0);

    const double mX = cos(sphericalPhi) * sin(sphericalTheta);
    const double mY = cos(sphericalPhi) * cos(sphericalTheta);
    const double mZ = sin(sphericalPhi);
    p(index, 0) = mX;
    p(index, 1) = mY;
    p(index, 2) = mZ;
    index++;
  }
}

Eigen::MatrixXi f;
igl::write_triangle_mesh(path, p, f);

I was thinking that it could create a "face" of a sphere, I mean that using that piece 6 times rotated I could create a sphere but it doesn't work take a look at 3 patches together Doesn't match

Frank Escobar
  • 368
  • 4
  • 20
  • I do not see any input data (3 patches) mentioned in title.... What I see is weirdly complicated looping through 2 parametric angles in spherical coordinates and computing a grid of sphere surface points. However your angle ranges are wrong. They should be `sphericalPhi = < -M_PI/2 , +M_PI/2> ` and `sphericalTheta = <0 , 2*M_PI>` but yours are the same and if I see ti right they are: `< - M_PI/4 , + M_PI/4 >` – Spektre May 12 '20 at 07:36
  • They are M_Pi/4 since each patch needs to be used to project a cube face texture, obviously creating a simple sphere is much easier than that code, but it is needed to be done like that since it should be integrated into other code. – Frank Escobar May 12 '20 at 08:05
  • I see... but your code does not contain the 3 patches combinations generation just one ... you are rotating them by wrong axis and by wrong angle ... I am also not convinced that you have the angle ranges OK... If you have 6 slices then longitude size should be `2*M_PI/6` not `M_PI/2` and latitude should be `< -M_PI/2 , + M_PI/2 >` unless you have different configuration but still it must be divided by 6 and 1 or by 3 and 2... – Spektre May 12 '20 at 08:29
  • The image represents the same patch placed 3 times by rotating it by 90º – Frank Escobar May 12 '20 at 08:47
  • That is my point you have 6 patches so either they should be 360/6=60deg rotated between each other or you have 2*3 patches rotated by 360/3=120deg and 90 deg in the other axis ... what you have is neither. Also for both cases patch size must be different than you have now ... – Spektre May 12 '20 at 09:15
  • 6 patches means 4 in "horizontal" and 2 caps no 6 in "horizontal – Frank Escobar May 12 '20 at 09:19
  • I do not follow if you do 3 patches per hemisphere then its `6 = 3*2` where do you get your `4` ? for example this is [5*2 patches](https://stackoverflow.com/a/46787885/2521214) ... no matter what you do 6 is not divisible by 4 so you can not have 4 patches symmetry anywhere – Spektre May 12 '20 at 09:45
  • It is more similar to https://math.stackexchange.com/questions/74941/how-do-you-parameterize-a-sphere-so-that-there-are-6-faces – Frank Escobar May 12 '20 at 09:45
  • You should edit your question and add all the info in there .... what shape of the section you want to have? I would project inscribed cube onto sphere surface ... the spherical to cartesian conversion formula angle parameters will not be linear on the edges!!! so your current for loop will be obsolete... however if you want just equal area then triangular or double triangular patches like you have now is easier ... but then the rotations and angles would be like I suggested – Spektre May 12 '20 at 09:48

1 Answers1

0

So simply project a cube onto sphere ...

  1. create cube as a NxN grid of points in range <-1,+1>

    so simply each face of cube is NxN regular grid of points. Each face have its own color. Each point has its position and normal.

  2. project all points to sphere surface.

    simply normalize the points size to radius of your sphere. And recompute the normals (unit vector of point)

Here small GL/C++ example:

//---------------------------------------------------------------------------
List<double> pnt;       // (x,y,z) all points
List<double> nor;       // (x,y,z) per point
List<int   > fac;       // (ix,p0,p1,p2) per triangle
List<double> col;       // (r,g,b) per ix

void sphere_init()
    {
    int i,j,n=10,n3=3*n,i0,i1,ix;
    double x,y,z,d=2.0/double(n-1);

    // clear mesh
    pnt.num=0;
    nor.num=0;
    fac.num=0;
    col.num=0;

    #define face0                \
        for (j=0;j<n-1;j++)      \
         for (i=0;i<n-1;i++)     \
            {                    \
            i1=i0+(3*(i+(j*n))); \
            fac.add(ix);         \
            fac.add(i1+n3+0);    \
            fac.add(i1   +3);    \
            fac.add(i1   +0);    \
            fac.add(ix);         \
            fac.add(i1+n3+0);    \
            fac.add(i1+n3+3);    \
            fac.add(i1   +3);    \
            }

    #define face1                \
        for (j=0;j<n-1;j++)      \
         for (i=0;i<n-1;i++)     \
            {                    \
            i1=i0+(3*(i+(j*n))); \
            fac.add(ix);         \
            fac.add(i1+n3+0);    \
            fac.add(i1   +0);    \
            fac.add(i1   +3);    \
            fac.add(ix);         \
            fac.add(i1+n3+3);    \
            fac.add(i1+n3+0);    \
            fac.add(i1   +3);    \
            }

    // init cube faces as 6 x N x N grid of points
    ix=0; z=-1.0; i0=pnt.num;
    col.add(0.0); 
    col.add(0.0); 
    col.add(1.0);
    for (y=-1.0,j=0;j<n;j++,y+=d)
     for (x=-1.0,i=0;i<n;i++,x+=d)
        {
        pnt.add(x); nor.add( 0.0);
        pnt.add(y); nor.add( 0.0);
        pnt.add(z); nor.add(-1.0);
        }
    face0;

    ix+=3; z=+1.0; i0=pnt.num;
    col.add(0.2); 
    col.add(0.2); 
    col.add(1.0);
    for (y=-1.0,j=0;j<n;j++,y+=d)
     for (x=-1.0,i=0;i<n;i++,x+=d)
        {
        pnt.add(x); nor.add( 0.0);
        pnt.add(y); nor.add( 0.0);
        pnt.add(z); nor.add(+1.0);
        }
    face1;

    ix+=3; x=-1.0; i0=pnt.num;
    col.add(1.0);
    col.add(0.0);
    col.add(0.0);
    for (y=-1.0,j=0;j<n;j++,y+=d)
     for (z=-1.0,i=0;i<n;i++,z+=d)
        {
        pnt.add(x); nor.add(-1.0);
        pnt.add(y); nor.add( 0.0);
        pnt.add(z); nor.add( 0.0);
        }
    face1;

    ix+=3; x=+1.0; i0=pnt.num;
    col.add(1.0); 
    col.add(0.2); 
    col.add(0.2);
    for (y=-1.0,j=0;j<n;j++,y+=d)
     for (z=-1.0,i=0;i<n;i++,z+=d)
        {
        pnt.add(x); nor.add(+1.0);
        pnt.add(y); nor.add( 0.0);
        pnt.add(z); nor.add( 0.0);
        }
    face0;

    ix+=3; y=-1.0; i0=pnt.num;
    col.add(0.0); 
    col.add(1.0); 
    col.add(0.0);
    for (x=-1.0,j=0;j<n;j++,x+=d)
     for (z=-1.0,i=0;i<n;i++,z+=d)
        {
        pnt.add(x); nor.add( 0.0);
        pnt.add(y); nor.add(-1.0);
        pnt.add(z); nor.add( 0.0);
        }
    face0;

    ix+=3; y=+1.0; i0=pnt.num;
    col.add(0.2); 
    col.add(1.0); 
    col.add(0.2);
    for (x=-1.0,j=0;j<n;j++,x+=d)
     for (z=-1.0,i=0;i<n;i++,z+=d)
        {
        pnt.add(x); nor.add( 0.0);
        pnt.add(y); nor.add(+1.0);
        pnt.add(z); nor.add( 0.0);
        }
    face1;

    // project to sphere
    for (i=0;i<pnt.num;i+=3)
        {
        x=pnt.dat[i+0];
        y=pnt.dat[i+1];
        z=pnt.dat[i+2];
        d=sqrt((x*x)+(y*y)+(z*z));
        if (d>1e-10) d=1.0/d;
        x*=d; nor.dat[i+0]=x; pnt.dat[i+0]=x;
        y*=d; nor.dat[i+1]=y; pnt.dat[i+1]=y;
        z*=d; nor.dat[i+2]=z; pnt.dat[i+2]=z;
        }
    #undef face0
    #undef face1
    }
void sphere_draw()
    {
    glEnable(GL_CULL_FACE);
    glFrontFace(GL_CCW);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_COLOR_MATERIAL);
    int i,ix;
    glBegin(GL_TRIANGLES);
    for (i=0;i<fac.num;)
        {
        ix=fac.dat[i]; i++;
        glColor3dv(col.dat+ix);
        glNormal3dv(nor.dat+fac.dat[i]); glVertex3dv(pnt.dat+fac.dat[i]); i++;
        glNormal3dv(nor.dat+fac.dat[i]); glVertex3dv(pnt.dat+fac.dat[i]); i++;
        glNormal3dv(nor.dat+fac.dat[i]); glVertex3dv(pnt.dat+fac.dat[i]); i++;
        }
    glEnd();
    }

I also use mine dynamic list template so:


List<double> xxx; is the same as double xxx[];
xxx.add(5); adds 5 to end of the list
xxx[7] access array element (safe)
xxx.dat[7] access array element (unsafe but fast direct access)
xxx.num is the actual used size of the array
xxx.reset() clears the array and set xxx.num=0
xxx.allocate(100) preallocate space for 100 items

Here preview:

preview

Community
  • 1
  • 1
Spektre
  • 49,595
  • 11
  • 110
  • 380