在 OpenGL 中编程特定的 3d(星形)模型? [关闭]
Posted
技术标签:
【中文标题】在 OpenGL 中编程特定的 3d(星形)模型? [关闭]【英文标题】:Programming a specific 3d (star-like) model in OpenGL? [closed] 【发布时间】:2018-11-30 18:06:40 【问题描述】:如何创建以下模型:
从第一张图纸开始。它可以完全在 OpenGL 中编程,还是应该使用 3d Studio Max 或 Unity 等其他软件?是否有一些特定的算法应该使用?
【问题讨论】:
几周?以前我看到这个确切的图像和问题在这里问几乎相同的是你吗?如果不尝试找到它(我现在可能找不到它......已删除)。无论如何,是的,这可以在 C++/OpenGL 中完成......您可以将网格创建为一组弯曲的圆锥......所以创建一些随机弯曲的路径(使用任何 CUBIC 曲线......像 BEZIER......)然后只是将圆锥叠加到曲线上(使用其点作为圆锥圆的中心)...请参阅Smoothly connecting circle centers 了解如何制作弯曲圆锥... @Spektre:是的,我记得同一个。 @Spektre: 啊there we go. @genpfault 是的,就是这样......你是怎么这么快找到问题的?顺便说一句,我认为这并不太宽泛,因为您甚至可以看到几行 C++ 代码,而且我已经完成了主要的骨架...... @Spektre:个人资料 -> 投票 -> 关闭列表(连同“删除”)是我能够找到列出已删除帖子的少数几个地方之一。我只是回顾了一下可能被删除的问题。我真的希望其他活动提要(尤其是所有操作-> cmets)具有相同的属性:( 【参考方案1】:是的,这可以在 C++/OpenGL
中完成创建从中心发射的随机曲线
简单的 3D 二次多项式曲线可以满足要求。
将曲线转换为圆锥
只需沿每条曲线插入点并将其用作圆锥切片的中心。方向由曲线上的上一个或下一个点设置。插入圆锥切片并将它们的点添加到某个点列表中。见:
Smoothly connecting circle centers创建面孔
只需使用任何原语连接计算点以形成锥体...我建议GL_QUAD
s...
核心
如果您还想添加核心(核?),可以将其做成一个球体,在其表面添加一些噪声,并可能进行一些过滤以使其平滑一点...
这里是简单的曲线生成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)
还可以在这里找到一些(如果不是全部)使用的向量数学:
Understanding 4x4 homogenous transform matrices我也使用我的动态列表模板,所以:
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
项目预分配空间
【讨论】:
我通常只是将我的线性代数外包给GLM,然后收工:) 你好,我想问你如何使用 Random(ize) 函数,因为编译器无法识别它们?我应该包括其他库吗?其次,ide 说 num 不是 List 的一部分?我想问这是为什么?提前致谢! @PeterPetrovRandomize()
和 Random()
是特定于 VCL 的,但您可以使用您拥有的任何功能,例如 random()
IIRC 它位于 conio.h
或 stdio.h
... 任何间隔0-1
上的伪随机生成器会做... Randomize()
只是生成器的一个初始化,Random()
在<0,1>
间隔上返回伪随机值
@PeterPetrov List 是我自己的动态数组类(在答案中描述)您可以使用静态数组或 std::vector 或您可以使用的任何容器...跨度>
以上是关于在 OpenGL 中编程特定的 3d(星形)模型? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何在opengl中计算给定3D点及其2D屏幕位置的投影/模型视图矩阵