set minimum distance from two meshes in THREE.JS

Viewed 170

I have this code that generates some clouds in random position, rotation and random scale. Since they can be generated next to another, or next to another mesh, they can clip together. I want to set a minimum distance, like if(cloud position x and z is < 10 FROM ANOTHER CLOUD) then set distance how can I do? Here's the code:

for(let i = 0; i < 10; i+= 1){

loader.load('/clouds/clouds2/scene.gltf', function (clouds2) {


 
 const cloud = clouds2.scene

 const child1 = cloud.children[0].children[0].children[0].children[2].children[0]
 const child2 = cloud.children[0].children[0].children[0].children[3].children[0]
 const child3 = cloud.children[0].children[0].children[0].children[4].children[0]
 
 child1.material = new THREE.MeshStandardMaterial({ emissive: 'white', emissiveIntensity: 0.3})
 child2.material = new THREE.MeshStandardMaterial({ emissive: 'white', emissiveIntensity: 0.3})
 child3.material = new THREE.MeshStandardMaterial({ emissive: 'white', emissiveIntensity: 0.3})

 cloud.scale.x = (Math.random() * (0.06 - 0.04 ) + 0.04)
 cloud.scale.y = (Math.random() * (0.06 - 0.04 ) + 0.04)
 cloud.scale.z = (Math.random() * (0.06 - 0.04 ) + 0.04)

 cloud.position.x = (Math.random() - 0.5) * 500
 cloud.position.y = (Math.random() + 80)
 cloud.position.z = (Math.random() - 1) * 500

 cloud.rotation.x = Math.random()
 cloud.rotation.y = Math.random() 
 cloud.rotation.z = Math.random() 

 scene.add(cloud)


})
}
1 Answers

First, there is no shame in placing things statically, and then using random values to create variance. For example, consider a set of 4 clouds arranged at the corners of a square. If you then modified their positions with fixed-range random values, you would get a random effect while still maintaining separation.

const clouds = [...] // cloud meshes
const maxChange = ... // the maximum amount of position change in one direction

const staticPositions = [
  new THREE.Vector3(...),
  new THREE.Vector3(...),
  new THREE.Vector3(...),
  new THREE.Vector3(...)
]

for(let i = 0; i < 4; ++i){

  let cloud = clouds[i]

  cloud.position.copy(staticPositions[i])

  // random variance
  cloud.position.x += (Math.random() * (maxChange * 2)) - maxChange
  cloud.position.y += (Math.random() * (maxChange * 2)) - maxChange
  cloud.position.z += (Math.random() * (maxChange * 2)) - maxChange

}

But if you really want to go full random, then you will need to check the new position against all other clouds before committing to it.

const clouds = [...] // cloud meshes
const minDistanceSquared = ... // the minimum (squared) distance allowed between clouds

// checks if a cloud is far enough away from all other clouds
function isFarEnoughAway(cloud){
  let retVal = true

  for(let i = 0, l = clouds.length; i < l && retVal; ++i){
    if(cloud !== clouds[i] && cloud.position.distanceToSquared(clouds[i].position) < minDistSquared){
      retVal = false
    }
  }

  return retVal
}
Related