c++ - 在 OpenGL 中编程特定的 3d(星形)模型?
问题描述
如何创建以下模型:
从第一张图开始。它可以完全在 OpenGL 中编程,还是应该使用 3d Studio Max 或 Unity 等其他软件?是否应该使用一些特定的算法?
解决方案
是的,这可以在C++/OpenGL中完成
创建从中心发射的随机曲线
简单的 3D 二次多项式曲线将符合要求。
将曲线转换为圆锥
只需沿每条曲线插入点并将其用作圆锥切片的中心。方向由曲线上的上一个或下一个点设置。插入圆锥切片并将它们的点添加到某个点列表中。看:
创建面
只需使用任何原语连接计算点以形成锥体...我建议
GL_QUAD
...核
如果您还想添加核心(核?),可以将其作为球体完成,在其表面添加一些噪声,并可能进行一些过滤以使其平滑一点...
这里简单的曲线生成 C++ 示例:
List<double> pnt;
void spicule_init()
{
double t,tt,x,y,z;
double a0[3],a1[3],a2[3];
int ix0,ix,i,j;
Randomize();
for (i=0;i<20;i++) // cones
{
// random quadratic 3D curve coeff
for (j=0;j<3;j++)
{
a0[j]=0.0; // center (0,0,0)
a1[j]=2.0*(Random()-0.5); // main direction
a2[j]=1.0*(Random()-0.5); // curvature
}
// curve interpolation
ix0=pnt.num;
for (t=0.0;t<=1.0;t+=0.04)
for (tt=t*t,j=0;j<3;j++)
pnt.add(a0[j]+(a1[j]*t)+(a2[j]*tt));
}
}
生成点预览:
[Edit1]添加圆锥、法线和面时,它看起来像这样:
它远非完美,但我认为这是一个很好的起点。只需调整半径r
和曲线系数a1[],a2[]
即可获得所需的形状......并且可能会添加核心或检查自相交,我懒得这样做......
这里更新的 C++/GL 代码:
//---------------------------------------------------------------------------
List<double> pnt,nor; // points, normals
List<int> fac; // QUAD faces
//---------------------------------------------------------------------------
void Circle3D(List<double> &pnt,List<double> &nor,double *p0,double *n0,double r,int N)
{
int i;
double a,da=divide(pi2,N),p[3],dp[3],x[3],y[3];
vector_ld(x,1.0,0.0,0.0); if (fabs(vector_mul(x,n0)>0.7)) vector_ld(x,0.0,1.0,0.0);
vector_mul(x,x,n0); vector_one(x,x);
vector_mul(y,x,n0); vector_one(y,y);
for (a=0.0,i=0;i<N;i++,a+=da)
{
vector_mul( p,x,cos(a));
vector_mul(dp,y,sin(a));
vector_add(p,p,dp); nor.add(p[0]); nor.add(p[1]); nor.add(p[2]);
vector_mul(p,p,r);
vector_add(p,p,p0); pnt.add(p[0]); pnt.add(p[1]); pnt.add(p[2]);
}
}
//---------------------------------------------------------------------------
void spicule_init() // generate random spicule mesh
{
const int N=36; // points/circle
const int N3=3*N;
double t,tt,x,y,z,r;
double a0[3],a1[3],a2[3];
double p[3],n[3];
int e,i,j,i00,i01,i10,i11;
Randomize();
pnt.num=0; nor.num=0; fac.num=0;
for (i=0;i<20;i++) // cones
{
// random quadratic 3D curve coeff
for (j=0;j<3;j++)
{
a0[j]=0.0; // center (0,0,0)
a1[j]=2.0*(Random()-0.5); // main direction and size
a2[j]=1.0*(Random()-0.5); // curvature
}
// curve interpolation
vector_ld(n,0.0,0.0,0.0);
for (e=0,t=0.05;t<=1.0;t+=0.05)
{
// points,normals
for (tt=t*t,j=0;j<3;j++) p[j]=a0[j]+(a1[j]*t)+(a2[j]*tt);
r=0.15*(1.0-pow(t,0.1)); // radius is shrinking with t
vector_sub(n,p,n); // normal is p(t)-p(t-dt)
Circle3D(pnt,nor,p,n,r,N); // add circle to pnt (N points)
vector_copy(n,p); // remember last point
// faces
if (!e){ e=1; continue; } // ignore first slice of cone
i00=pnt.num- 3; i10=i00-N3;
i01=pnt.num-N3; i11=i01-N3;
for (j=0;j<N;j++)
{
fac.add(i00);
fac.add(i01);
fac.add(i11);
fac.add(i10);
i00=i01; i01+=3;
i10=i11; i11+=3;
}
}
}
}
//---------------------------------------------------------------------------
void spicule_draw() // render generated spicule
{
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
int i,j;
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
for (i=0;i<fac.num;i++)
{
j=fac.dat[i];
glNormal3dv(nor.dat+j);
glVertex3dv(pnt.dat+j);
}
glEnd();
}
//---------------------------------------------------------------------------
如果您不知道如何计算交叉/点积或绝对值等矢量运算,请参阅:
// cross product: W = U x V
W.x=(U.y*V.z)-(U.z*V.y)
W.y=(U.z*V.x)-(U.x*V.z)
W.z=(U.x*V.y)-(U.y*V.x)
// dot product: a = (U.V)
a=U.x*V.x+U.y*V.y+U.z*V.z
// abs of vector a = |U|
a=sqrt((U.x*U.x)+(U.y*U.y)+(U.z*U.z))
vector_mul(a[3],b[3],c[3])
是叉积a = b x c
a = vector_mul(b[3],c[3])
是点积a = (b.c)
vector_one(a[3],b[3])
是单位向量a = b/|b|
vector_copy(a[3],b[3])
只是复制a = b
vector_add(a[3],b[3],c[3])
是加a = b + c
vector_sub(a[3],b[3],c[3])
是减a = b - c
vector_neg(a[3],b[3])
是否定a = -b
vector_ld(a[3],x,y,z)
只是加载a = (x,y,z)
也可以在这里找到一些(如果不是全部)使用的向量数学:
我也使用我的动态列表模板,所以:
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
推荐阅读
- azure - Azure SQL API 是否支持 xml 查询?
- maven - (误报)使用 gitlab-ci 运行 docker-compose:构建作业失败但管道成功
- java - JTable排序器对整数和双精度排序不正确
- excel - VBA复选框取消选中事件和多个范围加载到列表框
- python - 在 Tkinter 文件对话框中选择文件后出现“不本地化”警告
- types - 尝试将常规浮点值添加到具有浮点的类型
. F# - mongodb - 单个成员副本集可以吗?
- python - 如何在Python中提取括号之间的值
- angularjs - 如何动态绑定自定义 AngularJS 模态?
- c# - 如何:MSAL 和 ASP.NET MVC Web 应用程序配置?