繁体   English   中英

使用Three.js在椭球PointCloud中对点进行分区

[英]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.jshttps://rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js

感谢@SeverinPappadeux所做的有趣的贡献。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM