这听起来很简单,直到我试过
实现使用lib igl,但问题不在这里,而是在我缺乏数学知识的情况下:-\\。
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);
我在想它可以创建一个球体的 "面",我的意思是说,使用那块旋转6次的球体,我可以创建一个球体,但这是行不通的,看看3个补丁在一起。
所以简单地将一个立方体投影到球体上......。
创建一个立方体作为一个 NxN
点阵 <-1,+1>
因此,简单地说,立方体的每个面都是 NxN
规则的网格点。每个面都有自己的颜色。每个点都有自己的位置和法线。
将所有点投射到球面上。
简单地将点的大小归一化为球面的半径。并重新计算法线(点的单位向量)。
这里是GLC++的小例子。
//---------------------------------------------------------------------------
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();
}
我的动态列表模板也是这么用的。
List<double> xxx;
是一样的 double xxx[];
xxx.add(5);
补充 5
列表末尾xxx[7]
存取数组元素xxx.dat[7]
访问数组元素(不安全但快速直接访问)。xxx.num
是数组的实际使用大小xxx.reset()
清除阵列并设置 xxx.num=0
xxx.allocate(100)
预留空间 100
物品
在此预览。