问题
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
回答1:
So simply project a cube onto sphere ...
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.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:
来源:https://stackoverflow.com/questions/61735571/reconstruct-a-sphere-from-6-patches