简体   繁体   中英

only one particle showing in the scene with three.js

I am trying to create a sphere with particles randomly floating on its surface. It will move depends on the position on mousemove. something like this在此处输入图像描述

Strangely, it is only displaying one particle on canvas. I am debugging with console.log(vertices) , but it clearly shows all the vertices in the array.

My code in CodeSandBox

The problem is with your loop. You're assigning a value to theta and phi only once outside your loop, then you give the same value to all 1600 vertices:

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);
}

When you use console.log(vertices) , look at the x, y, z values and you'll see they all repeat.

What you should do is re-assign a new theta and a new phi inside the loop, so each vertex gets a unique position:

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);
}

You also don't need to create a THREE.Vector3() on each iteration, it's pretty inefficient to create 1600 Vector3 s just to be discarded immediately. Instead you can re-use the same x, y, z variables to avoid all those object construction costs.

See here for a working demo of your example. I also scaled down the point size to 1.

Just a small remark, not the answer (all kudos to @Marquizzo)

Since r133 , there is a method .randomDirection() of THREE.Vector3() , which helps us to set points on a sphere in a more convenient way.

Thus, all the code for instantiating of particles is:

    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);

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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