three.js 场景中仅显示一个粒子
only one particle showing in the scene with three.js
我正在尝试创建一个粒子随机漂浮在其表面的球体。它会移动取决于 mousemove 上的位置。
像这样
奇怪的是,canvas上只显示一个粒子。我正在使用 console.log(vertices)
进行调试,但它清楚地显示了数组中的所有 vertices
。
问题出在你的循环上。您只在循环外为 theta
和 phi
赋值一次,然后为所有 1600 个顶点赋予相同的值:
const theta = Math.acos(THREE.Math.randFloatSpread(2));
const phi = THREE.Math.randFloatSpread(360);
for (let i = 0; i < 1600; i++) {
const vertex = new THREE.Vector3();
vertex.x = distance * Math.sin(theta) * Math.cos(phi);
vertex.y = distance * Math.sin(theta) * Math.sin(phi);
vertex.z = distance * Math.cos(theta);
vertices.push(vertex.x, vertex.y, vertex.z);
}
当您使用 console.log(vertices)
时,查看 x, y, z
值,您会发现它们全部重复。
你应该做的是re-assign一个新的theta
和一个新的phi
在循环中,所以每个顶点都有一个唯一的位置:
let theta, phi;
let x, y, z;
for (let i = 0; i < 1600; i++) {
theta = Math.acos(THREE.Math.randFloatSpread(2));
phi = THREE.Math.randFloatSpread(360);
x = distance * Math.sin(theta) * Math.cos(phi);
y = distance * Math.sin(theta) * Math.sin(phi);
z = distance * Math.cos(theta);
vertices.push(x, y, z);
}
您也不需要在每次迭代时创建一个 THREE.Vector3()
,创建 1600 个 Vector3
只是为了立即丢弃是非常低效的。相反,您可以 re-use 相同的 x, y, z
变量来避免所有这些对象构造成本。
See here for a working demo 你的例子。我还将磅值缩小到 1。
只是一个小评论,不是答案(@Marquizzo 的所有荣誉)
从r133
开始,有了THREE.Vector3()
的方法.randomDirection()
,可以帮助我们更方便地在球体上设置点。
因此,粒子实例化的全部代码为:
const distance = Math.min(200, window.innerWidth / 16);
let vertices = new Array(1600).fill().map((v) => {
return new THREE.Vector3().randomDirection().setLength(distance);
});
const geometry = new THREE.BufferGeometry().setFromPoints(vertices);
const material = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const particles = new THREE.Points(geometry, material);
我正在尝试创建一个粒子随机漂浮在其表面的球体。它会移动取决于 mousemove 上的位置。
像这样
奇怪的是,canvas上只显示一个粒子。我正在使用 console.log(vertices)
进行调试,但它清楚地显示了数组中的所有 vertices
。
问题出在你的循环上。您只在循环外为 theta
和 phi
赋值一次,然后为所有 1600 个顶点赋予相同的值:
const theta = Math.acos(THREE.Math.randFloatSpread(2));
const phi = THREE.Math.randFloatSpread(360);
for (let i = 0; i < 1600; i++) {
const vertex = new THREE.Vector3();
vertex.x = distance * Math.sin(theta) * Math.cos(phi);
vertex.y = distance * Math.sin(theta) * Math.sin(phi);
vertex.z = distance * Math.cos(theta);
vertices.push(vertex.x, vertex.y, vertex.z);
}
当您使用 console.log(vertices)
时,查看 x, y, z
值,您会发现它们全部重复。
你应该做的是re-assign一个新的theta
和一个新的phi
在循环中,所以每个顶点都有一个唯一的位置:
let theta, phi;
let x, y, z;
for (let i = 0; i < 1600; i++) {
theta = Math.acos(THREE.Math.randFloatSpread(2));
phi = THREE.Math.randFloatSpread(360);
x = distance * Math.sin(theta) * Math.cos(phi);
y = distance * Math.sin(theta) * Math.sin(phi);
z = distance * Math.cos(theta);
vertices.push(x, y, z);
}
您也不需要在每次迭代时创建一个 THREE.Vector3()
,创建 1600 个 Vector3
只是为了立即丢弃是非常低效的。相反,您可以 re-use 相同的 x, y, z
变量来避免所有这些对象构造成本。
See here for a working demo 你的例子。我还将磅值缩小到 1。
只是一个小评论,不是答案(@Marquizzo 的所有荣誉)
从r133
开始,有了THREE.Vector3()
的方法.randomDirection()
,可以帮助我们更方便地在球体上设置点。
因此,粒子实例化的全部代码为:
const distance = Math.min(200, window.innerWidth / 16);
let vertices = new Array(1600).fill().map((v) => {
return new THREE.Vector3().randomDirection().setLength(distance);
});
const geometry = new THREE.BufferGeometry().setFromPoints(vertices);
const material = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const particles = new THREE.Points(geometry, material);