[英]Repartition of points in an ellipsoid PointCloud with Three.js
我最近开始尝试Three.js。 我尝试使用PointCloud对象创建粒子的椭球云。
我使用椭圆形的参数方程生成随机点,如下所示:
var vertex = new THREE.Vector3();
u = Math.random() * 2 * Math.PI;
v = Math.random() * Math.PI;
vertex.x = Math.random() * a * Math.cos(u) * Math.sin(v);
vertex.y = Math.random() * b * Math.sin(u) * Math.sin(v);
vertex.z = Math.random() * c * Math.cos(v);
但是,当我渲染云时,我注意到椭圆形的轴周围聚集了异常数量的粒子。
我想知道这是否与Math.random()函数的分布有关,还是我缺少什么? 请帮助我理解这一点。
您可以在这里查看它,并制作了一个屏幕截图 ,以防浏览器上的外观不同。
编辑:代码已被@ severin-pappadeux建议修改,以避免点分布不正确,但问题仍然存在。
编辑:我修改了使用Math.random()设置顶点长度的部分,这是:
vertex.x = Math.random() * a * wx;
vertex.y = Math.random() * b * wy;
vertex.z = Math.random() * c * wz;
至:
vertex.x = (Math.random() + 0.1) * a * wx;
vertex.y = (Math.random() + 0.1) * b * wy;
vertex.z = (Math.random() + 0.1) * c * wz;
并且颗粒更均匀地分布。 更有意思的是,它不会在轴所在的位置形成“十字形孔”,这是我希望的,因为Math.random()+ 0.1不会产生低于0.1的任何值。 因此,即使我仍然希望有一个好的答案,这种小技巧也可以解决我的问题。
分布显然在角度上是不均匀的。 您所看到的等同于http://mathworld.wolfram.com/SpherePointPicking.html的效果。 可以尝试建立单位均一的球面矢量,并使它与椭圆相交以生成顶点。 沿线的东西
phi = 2.0 * Math.PI * Math.random();
csth = 2.0 * Math.random() - 1.0;
snth = Math.sqrt((1.0 - csth)*(1.0 + csth));
wx = snth * Math.sin(phi);
wy = snth * Math.cos(phi);
wz = csth;
(wx,wy,wz)
是单位向量。 用距离s*(wx,wy,wz)
建立ray。 将来自(0,0,0)的光线与椭圆相交,并找到您的顶点
UPDATE
没有意识到问题是关于给定数量的制服。 无论如何要在单位球体内变得均匀,必须添加半径采样:
r = Math.pow( Math.random(), 1.0/3.0 ); // is there cubic root sqrt3() function?
那么球体内的点将是(r*wx, r*wy, r*wz)
并可以相应地用(a, b, c)
缩放
您要创建均匀分布在3D椭圆体内的随机点云。
首先,在立方体内部生成一个随机点,并忽略嵌入球体外部的点。
vertex.x = 2 * Math.random() - 1;
vertex.y = 2 * Math.random() - 1;
vertex.z = 2 * Math.random() - 1;
if ( vertex.length() < 1 ) geometry.vertices.push( vertex );
现在,您将在球体内具有统一点。 要创建椭球,请在创建点云后对其进行缩放。
var pointCloud = new THREE.Points( geometry, material );
pointCloud.scale.set( a, b, c );
three.js r.86
我最终使用了@WestLangley的解决方案,该解决方案的实现方式如下(由@Atrahasis建议):
while(geometry.vertices.length < 20000) {
var vertex = new THREE.Vector3();
vertex.x = 2 * Math.random() - 1;
vertex.y = 2 * Math.random() - 1;
vertex.z = 2 * Math.random() - 1;
if(vertex.length() < 1) geometry.vertices.push(vertex);
}
您可以在此处看到完整的代码(根据我的观察,在Firefox上比在Chrome上看起来更好)
温馨提示:从Github导入Codepen / JSFiddle等原始js文件在Chrome上将无法正常工作,因为该文件的MIME类型为“文本/纯文本”,因此浏览器无法执行。 关键是要替换http://raw.github.com/
与部分http://rawgit.com/
所以OrbitControls.js,我改变https://raw.githubusercontent.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
到https://rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js
!
感谢@SeverinPappadeux所做的有趣的贡献。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.