Three.js Get all meshes by name property value.

Viewed 7532

I have a simple Three.js scene in which i have generated some meshes. Some of these have name property = 'quadrant'. I just want get all the meshes named 'quadrant' in any way. i used scene.getObjectByName("quadrant"); and it works but return me only the first element named 'quadrant' finded. how can i do?

1 Answers

i did some digging to clarify this for myself too. So, long story short, you wont be able to access all meshes using getObjectByName method. It doesn't work like class selector in css. Three.JS documentation points out:

.getObjectByName ( name : String ) -- Searches through the object's children and returns the first with a matching name.

So, you have 2 options:

  • Give each mesh unique name
  • traverse through scene's objects

I made code snippet with animation and material modification, because it wasn't clear what you want to achieve.

Example contains:

  • How tu use getObjectByName method for one object to modify it's material
  • How to traverse through scene's children and check if they have "quadrant" name

So, in short:

scene.traverse(function(child) {
  if (child.name === "quadrant") {
    child.material = ClassMaterial; //apply same material to all meshes
  }
});

Hope solution is clear, good luck.

More detailed example:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;

var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({
  color: 0x00ff00
});

var UniceMaterial = new THREE.MeshBasicMaterial({
  color: 0xffff00
});
var ClassMaterial = new THREE.MeshBasicMaterial({
  color: 0x00ffff
});


for (j = 0; j < 10; j++) {
  var cube = new THREE.Mesh(geometry, material);
  cube.name = "demo";
  cube.myid = j;
  cube.position.x = j * -2;
  cube.position.y = j - 2;
  cube.position.z = j / 100;
  scene.add(cube);
}

for (i = 0; i < 10; i++) {
  var cube = new THREE.Mesh(geometry, material);
  cube.name = "quadrant";
  cube.myid = i;
  cube.position.x = i * 2;
  cube.position.y = i + 2;
  cube.position.z = i / 100;
  scene.add(cube);
}

for (i = 0; i < 4; i++) {
  var cube = new THREE.Mesh(geometry, material);
  cube.name = "quadrant" + 1;
  cube.myid = i;
  cube.position.x = 0;
  cube.position.y = i * -4;
  cube.position.z = i / 100;
  scene.add(cube);
}


scene.traverse(function(child) {
  //if (child instanceof THREE.Mesh) {
  if (child.name === "quadrant") {
    child.material = ClassMaterial;
    //console.log (child);
  }
  //child.material = ClassMaterial;
  //}
});

ObjectWithGetMethod = scene.getObjectByName("quadrant1");
ObjectWithGetMethod.material = UniceMaterial;

var animate = function() {
  requestAnimationFrame(animate);

  scene.traverse(function(cube) {
    if (cube.name === "demo") {
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
    }
  });

  //despite you try to select  "quadrant" it animates last added cube:
  if (cube.name = "quadrant") {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
  }

  renderer.render(scene, camera);
};

animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/90/three.min.js"></script>
<html>

<head>
  <title>My first three.js app</title>
  <style>
    body {
      margin: 0;
    }
    
    canvas {
      width: 100%;
      height: 100%
    }
  </style>
</head>

<body>


</body>

</html>

Related