我最近开始尝试使用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()函数的分布有关,还是我错过了什么?请帮我理解这一点。
您可以查看here,如果您的浏览器看起来不一样,我就制作了screenshot。
编辑:@ 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的任何值。所以这个小技巧解决了我的问题,即使我仍然对一个好的答案感兴趣。
答案 0 :(得分:2)
角度分布明显不均匀。你看到的相当于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)
的光线。将来自(0,0,0)的此光线与椭圆相交,并找到您的顶点
更新
没有意识到问题是关于给定量的统一。无论如何要在单位球体中获得均匀,必须添加半径采样:
r = Math.pow( Math.random(), 1.0/3.0 ); // is there cubic root sqrt3() function?
然后,球体内的点将为(r*wx, r*wy, r*wz)
,并且可以使用(a, b, c)
答案 1 :(得分:0)
您想要创建一个均匀分布在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
答案 2 :(得分:0)
我最终使用了@ 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);
}
你可以看到完整的代码here(在我看到的情况下,它在Firefox上比在Chrome上看起来更好)
额外提示:从Github导入Codepen / JSFiddle等中的原始js文件将无法在Chrome上运行,因为该文件的MIME类型为“text / plain”,因此浏览器不会执行它。诀窍是用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的有趣贡献。