如何使用Three.js定义相对于矢量路径的粒子云?

时间:2014-07-16 15:13:51

标签: javascript vector graphics three.js particle-system

我一直在研究和玩Three.js中的粒子云示例。大多数使用形状几何来定义粒子场或用于在整个视场中随机分布它们的参数。我想要做的是创建一个粒子云,其中每个粒子都与不可见的矢量路径相对接近。例如,如果我定义了一个轻微弯曲的矢量路径,则所有粒子可能沿着不可见的方向漂浮在一致的半径内,然后可能朝向末端逐渐变细以形成热狗形状的粒子云。所以,我知道如何创建粒子,我知道如何创建矢量路径,如何将这两个东西连接在一起?谢谢!

1 个答案:

答案 0 :(得分:2)

您可以使用两个点定义路径。让这些点为pq,并让v = p - q。位于路径上的任何点M必须满足向量方程

M = (1 - lambda) * p + lambda * q
某些0 <= lambda <= 1

。因此,您可以通过生成随机lambda并在上面的等式中使用其值来生成路径上的随机点:

// p and q are instances of THREE.Vector3
function pointOnPath(p, q) {
   var lambda = Math.random();
   var scaledp = (new THREE.Vector3()).copy(p).multiplyScalar(1 - lambda);
   var scaleq = (new THREE.Vector3()).copy(q).multiplyScalar(lambda);
   var result = (new THREE.Vector3()).addVectors(scaledp, scaledq);
   return result;
} 

接下来,您希望使用一些小半径修改计算的坐标,以便它们围绕路径循环。你可以通过添加一个小的向量偏移量来实现。那我们如何计算那个向量呢?

我们所追求的矢量位于一个垂直于pq之间的平面上。存在满足上述条件的无限数量的向量,其中两个是e1 = (v.y, -v.x, 0)e2 = (v.z, 0, -v.x)lambda * e1 + mu * e2形式的任何向量也将垂直于v。因此,我们只需要生成lambdamu,并且所有内容都已准备就绪。

注意lambdamu必须是区间内的随机数[-1; 1],而不是[0; 1]。由于我们正在归一化offset向量,因此区间[-0.5; 0.5]就足够了,因为归一化将它映射到[-1; 1]

function getVectorOffset(p, q, radius) {
    var v = (new THREE.Vector3()).subVectors(q, p);
    v.normalize();
    var e1 = new THREE.Vector3(v.y, -v.x, 0),
        e2 = new THREE.Vector3(v.z, 0, -v.x);
    e1.normalize();
    e2.normalize();

    var lambda = Math.random() - 0.5,
        mu = Math.random() - 0.5;
    var offset = e1.multiplyScalar(lambda).add(e2.multiplyScalar(mu));
    offset.normalize();
    offset.multiplyScalar(radius) // multiply the compute offset by the radius you'd like it to circle around

    return offset;

}

最后,要生成您想要的点:

function pointOnHotDog(p, q, radius) {
    return pointOnPath(p, q).add(getVectorOffset(p, q, radius));
}

这是一个有效的jsfiddle