agent

seek, group

by 蔡 育曄

HTML

<div id="info">Agents</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js">


</script>

CSS

#info {
  position: absolute;
  top: 0px;
  width: 100%;
  padding: 10px;
  text-align: center;
  color: #ffff00
}

body {
  overflow: hidden
}

JavaScript

class Agent {
  constructor(pos, mesh) {
    this.pos = pos.clone();
    this.vel = new THREE.Vector3();
    this.force = new THREE.Vector3();
    this.target = new THREE.Vector3(mesh.position);
    this.size = 1;
    this.mesh = mesh;
    this.MAXSPEED = 60;
    this.ARRIVAL_R = 12;
    this.nbhd = [];
  }
  update(dt) {
    this.accumulateForce();
    this.vel.add(this.force.clone().multiplyScalar(dt));
    // velocity modulation
    let diff = this.target.clone().sub(this.pos)
    let dst = diff.length();
    if (dst < this.ARRIVAL_R) {
      this.vel.setLength(dst)
    }
    this.pos.add(this.vel.clone().multiplyScalar(dt))
    this.mesh.position.copy(this.pos)
  }
  distanceTo(otherAgent) {
    return this.pos.distanceTo(otherAgent.pos)
  }
  addNbr(otherAgent) {
    this.nbhd.push(otherAgent)
  }
  setTarget(target) {
    this.target.copy(target)
  }
  targetInducedForce(targetPos) {
    return targetPos.clone().sub(this.pos).normalize().multiplyScalar(this.MAXSPEED).sub(this.vel)
  }

  accumulateForce() {
    // seek
    this.force.copy(this.targetInducedForce(this.target));

    
    // coherence
    if (this.nbhd.length > 0) {
      let sum = new THREE.Vector3();
      for (let i = 0; i < this.nbhd.length; i++) 
        sum.add(this.nbhd[i].pos);
      sum.divideScalar(this.nbhd.length);
      this.force.add(this.targetInducedForce(sum))
    }
  
    // separation
    let push = new THREE.Vector3();
    for (let i = 0; i < this.nbhd.length; i++) {
      let point = this.pos.clone().sub(this.nbhd[i].pos);
      push.add(point.setLength(1 / point.length()))
    }
    this.force.add(push)

  }

}

function findNbhd(agents) {
  let i, j, dst;
  let nAgents = agents.length;
  for (i = 0; i < nAgents - 1; i++) {
    for (j = i + 1; j < nAgents; j++) {
      dst = agents[i].distanceTo(agents[j])
      if (dst < 20) { // NBHD = 20
        agents[i].addNbr(agents[j])
        agents[j].addNbr(agents[i])
      }
    }
  }
}

////////////////////
var camera, scene,...