3D:从极坐标创建球体时避免在极点处捏住

时间:2016-10-05 18:31:43

标签: math three.js geometry quaternions polar-coordinates

我正在使用维基百科的spherical coordinate system article创建一个由Three.js中的粒子组成的球体。基于这篇文章,我创建了一个小Polarizer类,它使用setPolar(rho, theta, phi)获取极坐标,并返回其对应的x,y,z

这里是setPolar()功能:

// Rho: radius
// theta θ: polar angle on Y axis
// phi φ: azimuthal angle on Z axis

Polarizer.prototype.setPolar = function(rho, theta, phi){
  // Limit values to zero
  this.rho = Math.max(0, rho);
  this.theta = Math.max(0, theta);
  this.phi = Math.max(0, phi);

  // Calculate x,y,z
  this.x = this.rho * Math.sin(this.theta) * Math.sin(this.phi);
  this.y = this.rho * Math.cos(this.theta);
  this.z = this.rho * Math.sin(this.theta) * Math.cos(this.phi);

  return this;
}

我用它来定位我的粒子如下:

var tempPolarizer = new Polarizer();

for(var i = 0; i < geometry.vertices.length; i++){
  tempPolarizer.setPolar(
    50,                         // Radius of 50
    Math.random() * Math.PI,    // Theta ranges from 0 - PI
    Math.random() * 2 * Math.PI // Phi ranges from 0 - 2PI
  );

  // Set new vertex positions
  geometry.vertices[i].set(
    tempPolarizer.x,
    tempPolarizer.y,
    tempPolarizer.z
  );
}

它非常有效,除了我得到高粒子密度,或者“捏”&#34;在两极:

PolarPinching

我很难避免如何避免这种情况发生。我想把加权随机数传递给纬度,但是我希望在没有经度减速和在极点聚集的情况下为粒子设置动画。

是否有不同的公式来生成一个球体,其中两极不会增加重量?我应该使用四元数吗?

2 个答案:

答案 0 :(得分:2)

  1. 随机统一采样

    在单位立方体中使用随机点,将其作为矢量处理并将其长度设置为球体的半径。例如C ++中的类似内容:

    x = 2.0*Random()-1.0; 
    y = 2.0*Random()-1.0; 
    z = 2.0*Random()-1.0; 
    m=r/sqrt(x*x+y*y+z*z);
    x*=m;
    y*=m;
    z*=m;
    

    其中<0.0,1.0>中的随机返回数。有关详细信息,请参阅:

  2. 统一非随机抽样

    参见相关的质量保证

答案 1 :(得分:1)

为了避免极点处的高密度,我不得不降低θ(纬度)着陆接近0和PI的可能性。我的输入

对于theta,

Math.random() * Math.PI,给出了所有值(橙色)的相等可能性。

Math.acos((Math.random() * 2) - 1)完美地对输出进行加权以使0和PI在球体表面上的可能性降低(黄色)

enter image description here

enter image description here

现在我甚至不知道两极在哪里!