Particles to form a custom model

i need to form a custom model by particles.What i want is this https://youtu.be/R4XtWEMrwe0?si=JFgc4Vqdv4Md5vfC .see this

const sphereGeometry = new THREE.SphereGeometry(0.003, 16, 16);
    const particles = [];
    const originalPositions = [];
    const originalMaterials = [];
    const highlightMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });

    loader.load('/mesh3.glb', (gltf) => {
      const model = gltf.scene;
      model.scale.set(0.8, 0.8, 0.8);
      model.position.set(0, -0.7, -1);

      if (model) {
        model.traverse((child) => {
          if (child.isMesh) {
            const vertices = child.geometry.attributes.position;
            for (let i = 0; i < vertices.count; i++) {
              const x = vertices.getX(i);
              const y = vertices.getY(i);
              const z = vertices.getZ(i);
              const randomX = x + (Math.random() - 0.5) * 0.1;
              const randomY = y + (Math.random() - 0.5) * 0.1;
              const randomZ = z + (Math.random() - 0.5) * 0.1;

              const particle = new THREE.Mesh(sphereGeometry, new THREE.MeshStandardMaterial());
              particle.position.set(randomX, randomY, randomZ);
              particle.position.copy(child.localToWorld(particle.position));
              particles.push(particle);
              originalPositions.push(new THREE.Vector3(randomX, randomY, randomZ));
              originalMaterials.push(particle.material.clone());
            }
          }
        });
        scene.add(...particles);
      }
    });

this is what i have now. but it looks bad.

please help if anyone know this.

Since you are using the vertices of the model’s geometry as the data source for your point cloud, you end up with an uneven distribution. Do you mind giving MeshSurfaceSampler a try?

3 Likes

wow you even didn’t use the Points class , it will cause performance problem since you got so many balls on the screen… I wondering what your ‘bad’ means, can u give give more infomations ? is it not so efficient or it’s looks different or something else?
as Mugen said you could get the points position using MeshSurfaceSampler, it will get the point on the mesh surface, and create Points using those position informantion. and then add a Vector3 Uniform to it’s Vertex shader ,it was used for change the points position on fly.

1 Like

yes it works fine. thank you.

let sampler;

    loader.load('/mesh3.glb', (gltf) => {
      const model = gltf.scene;
      model.scale.set(0.8, 0.8, 0.8)
      model.position.set(0, -0.7, -1);
      gltf.scene.traverse((obj) => {
        if (obj.isMesh) {
          sampler = new MeshSurfaceSampler(obj).build();
          const numParticles = 3000;
          const particlePositions = [];
          const particleMaterials = [];

          for (let i = 0; i < numParticles; i++) {
            const sample = new THREE.Vector3();
            sampler.sample(sample);
            const particle = new THREE.Mesh(sphereGeometry, new THREE.MeshStandardMaterial());
            particle.position.copy(sample);
            particle.position.copy(obj.localToWorld(particle.position));
            particles.push(particle);
            originalPositions.push(sample.clone());
            originalMaterials.push(particle.material.clone());
            scene.add(particle);
          }
        }
      });
    });

As @towrabbit mentioned, you should consider to use the Points class for this use case.

If you insist on using meshes, use definitely InstancedMesh to reduce draw calls.

1 Like