threex
Version:
Game Extensions for three.js http://www.threejsgames.com/extensions/
220 lines (185 loc) • 7.9 kB
HTML
<!DOCTYPE html>
<script src='../../../vendor/three.js/build/three.js'></script>
<script src='../threex.flockingcontrols.js'></script>
<!-- include for threex.glowdatgui -->
<script src='../threex.flockingcontrolsdatgui.js'></script>
<script src='../../../vendor/three.js/examples/js/libs/dat.gui.min.js'></script>
<body style='margin: 0px; background-color: #000000; overflow: hidden;'><script>
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var onRenderFcts= [];
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000);
camera.position.z = 20;
// camera.position.z = 2;
//////////////////////////////////////////////////////////////////////////////////
// set 3 point lighting //
//////////////////////////////////////////////////////////////////////////////////
;(function(){
// add a ambient light
var light = new THREE.AmbientLight( 0x020202 )
scene.add( light )
// add a light in front
var light = new THREE.DirectionalLight('white', 1)
light.position.set(0.5, 0.5, 2)
scene.add( light )
// add a light behind
var light = new THREE.DirectionalLight('white', 0.75)
light.position.set(-0.5, -0.5, -2)
scene.add( light )
})()
// var arrow = new THREE.ArrowHelper(new THREE.Vector3(1,0,0), new THREE.Vector3, 1, 'blue')
// scene.add(arrow)
// window.arrow = arrow
//////////////////////////////////////////////////////////////////////////////////
// handle window resize //
//////////////////////////////////////////////////////////////////////////////////
// handle resize events
window.addEventListener( 'resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false);
//////////////////////////////////////////////////////////////////////////////////
// add an object and make it move //
//////////////////////////////////////////////////////////////////////////////////
var geometry = new THREE.CubeGeometry(1,1,1);
var geometry = new THREE.SphereGeometry(0.1);
var geometry = new THREE.CylinderGeometry(0, 0.1, 0.5)
// var geometry = new THREE.CylinderGeometry(0, 0.1, 0.25)
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( Math.PI/2 ) );
// geometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0,0, -0.5 ) );
var material = new THREE.MeshNormalMaterial();
var baseObject3d= new THREE.Mesh( geometry, material );
var mapWidth = 20
var mapHeight = 20
var mapDepth = 0
var bodiesControls = []
var nBodies = 400
// var nBodies = 3
for(var i = 0; i < nBodies; i++){
;(function(){
// create the body
var object3d = baseObject3d.clone()
object3d.material = new THREE.MeshPhongMaterial({
color : 'cyan',
});
scene.add( object3d );
// set body position
object3d.position.x = (Math.random()-0.5)*mapWidth
object3d.position.y = (Math.random()-0.5)*mapHeight
object3d.position.z = (Math.random()-0.5)*mapDepth
// init controls for body
if( i === 0 ) var controls = new THREEx.FlockingControls(object3d, undefined, true)
else var controls = new THREEx.FlockingControls(object3d)
// make sure all controls are on the same ```.opts``` object, it helps dat.gui tunning
if( i !== 0 ) controls.opts = bodiesControls[0].opts
// attach debug if needed
if( controls.debug ) scene.add( controls.debugObject3d )
// centralize all controls in bodiesControls
bodiesControls.push(controls)
// init initial velocity
controls.velocity.x = (Math.random()-0.5)*2
controls.velocity.y = (Math.random()-0.5)*2
controls.velocity.z = (Math.random()-0.5)*2
controls.velocity.z = (Math.random()-0.5)*0
// make object3d look at the velocity
onRenderFcts.push(function(){
object3d.lookAt(object3d.position.clone().add(controls.velocity))
})
object3d.userData.controls = controls
})()
}
//////////////////////////////////////////////////////////////////////////////////
// dat.gui tuning //
//////////////////////////////////////////////////////////////////////////////////
;(function(){
var datGui = new dat.GUI({
autoPlace: false
})
document.body.appendChild(datGui.domElement)
datGui.domElement.style.position = 'absolute'
datGui.domElement.style.top = '0px'
var controls = bodiesControls[0]
new THREEx.addFlockingControls2DatGui(controls, datGui)
//////////////////////////////////////////////////////////////////////////////////
// actions //
//////////////////////////////////////////////////////////////////////////////////
var actions = {
reset : function(){
bodiesControls.forEach(function(controls){
var object3d = controls.object3d
// set body position
object3d.position.x = (Math.random()-0.5)*mapWidth
object3d.position.y = (Math.random()-0.5)*mapHeight
object3d.position.z = (Math.random()-0.5)*mapDepth
// init initial velocity
controls.velocity.x = (Math.random()-0.5)*2
controls.velocity.y = (Math.random()-0.5)*2
controls.velocity.z = (Math.random()-0.5)*2
controls.velocity.z = (Math.random()-0.5)*0
})
}
}
var folder = datGui.addFolder('Actions');
folder.add(actions, 'reset')
folder.open()
})()
//////////////////////////////////////////////////////////////////////////////////
// apply physics //
//////////////////////////////////////////////////////////////////////////////////
setInterval(function(){
bodiesControls.forEach(function(controls, controlsIdx){
controls.computeForces(bodiesControls, controlsIdx)
})
bodiesControls.forEach(function(controls){
controls.applyForces()
})
// clamp all boids within a cube
bodiesControls.forEach(function(controls){
var position = controls.position
if( position.x < mapWidth /2 ) position.x += mapWidth
if( position.x > mapWidth /2 ) position.x -= mapWidth
if( position.y < mapHeight/2 ) position.y += mapHeight
if( position.y > mapHeight/2 ) position.y -= mapHeight
if( position.z < mapDepth /2 ) position.z += mapDepth
if( position.z > mapDepth /2 ) position.z -= mapDepth
})
}, 1000/60)
//////////////////////////////////////////////////////////////////////////////////
// Camera Controls //
//////////////////////////////////////////////////////////////////////////////////
// var mouse = {x : 0, y : 0}
// document.addEventListener('mousemove', function(event){
// mouse.x = (event.clientX / window.innerWidth ) - 0.5
// mouse.y = (event.clientY / window.innerHeight) - 0.5
// }, false)
// onRenderFcts.push(function(delta, now){
// camera.position.x += (mouse.x*5 - camera.position.x) * (delta*3)
// camera.position.y += (mouse.y*5 - camera.position.y) * (delta*3)
// camera.lookAt( scene.position )
// })
//////////////////////////////////////////////////////////////////////////////////
// render the scene //
//////////////////////////////////////////////////////////////////////////////////
onRenderFcts.push(function(){
renderer.render( scene, camera );
})
//////////////////////////////////////////////////////////////////////////////////
// loop runner //
//////////////////////////////////////////////////////////////////////////////////
var lastTimeMsec= null
requestAnimationFrame(function animate(nowMsec){
// keep looping
requestAnimationFrame( animate );
// measure time
lastTimeMsec = lastTimeMsec || nowMsec-1000/60
var deltaMsec = Math.min(200, nowMsec - lastTimeMsec)
lastTimeMsec = nowMsec
// call each update function
onRenderFcts.forEach(function(onRenderFct){
onRenderFct(deltaMsec/1000, nowMsec/1000)
})
})
</script></body>