Files
three.js/examples/webgl_collisions_primitives.html
T

251 lines
5.5 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<title>three.js webgl - intersection: ray with sphere/AABB/plane</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
#oldie {
background-color: #ddd !important
}
#info {
position: absolute;
top: 30px;
left: 150px;
width: 800px;
color: #000000;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: left;
z-index: 100;
}
#options {
position: absolute;
top: 10px;
left: 150px;
width: 800px;
color: #000000;
padding: 5px;
font-family: Monospace;
font-size: 13px;
text-align: left;
z-index: 100;
}
</style>
<script src="../build/Three.js"></script>
<script src="js/RequestAnimationFrame.js"></script>
<script src="js/Stats.js"></script>
<script>
var camera, scene, projector, renderer,
info, mouse = { x: 0, y: 0 }, sun;
var theta = 0;
var camdist = 1500;
var geoms = [];
function init () {
container = document.createElement( 'div' );
document.body.appendChild( container );
info = document.getElementById( "info" );
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
scene = new THREE.Scene();
projector = new THREE.Projector();
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
var ambientLight = new THREE.AmbientLight( 0x606060 );
scene.add( ambientLight );
sun = new THREE.DirectionalLight( 0xffffff );
scene.add( sun );
makeWall(240);
makeWall(120);
makeWall(0);
makeWall(-120);
makeWall(-240);
plane = new THREE.Mesh( new THREE.PlaneGeometry( 30000, 30000, 10, 10 ), new THREE.MeshLambertMaterial( { color: 0x003300 } ) );
plane.position.y = - 480;
plane.rotation.x = Math.PI / - 2;
scene.add( plane );
geoms.push( plane );
var cplane = new THREE.PlaneCollider( plane.position, new THREE.Vector3( 0, 1, 0 ) );
cplane.mesh = plane;
THREE.Collisions.colliders.push( cplane );
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild( stats.domElement );
container.onmousemove = onDocumentMouseMove;
animate();
}
function makeWall(z){
var mx = 120 * 2;
for ( var i = -mx; i <= mx; i += 120 ) {
for ( var j = -mx; j <= mx; j += 120 ) {
if ( Math.random() > 0.5 )
createCube( 100, new THREE.Vector3( j, i, z ) );
else
createSphere( 50, new THREE.Vector3( j, i, z ) );
}
}
}
function createCube( s, p ) {
var cube = new THREE.Mesh(new THREE.CubeGeometry( s, s, s ), new THREE.MeshLambertMaterial( { color: 0x003300 } ) );
cube.position = p;
scene.add(cube);
geoms.push(cube);
THREE.Collisions.colliders.push(THREE.CollisionUtils.MeshAABB(cube, p));
}
function createSphere( rad, p ) {
var sphere = new THREE.Mesh( new THREE.SphereGeometry( rad, 10, 10 ), new THREE.MeshLambertMaterial( { color: 0x003300 } ) );
sphere.position = p;
scene.add(sphere);
geoms.push(sphere);
var sc = new THREE.SphereCollider(p, rad);
sc.mesh = sphere;
THREE.Collisions.colliders.push(sc);
}
function onDocumentMouseMove(event){
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
function animate(){
requestAnimationFrame( animate );
var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
projector.unprojectVector( vector, camera );
var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
for ( var i = 0; i < geoms.length; i ++ ) {
geoms[ i ].material.color.setHex( 0x007700 );
}
if ( !document.getElementById( "nearest" ).checked ) {
// Raycast all
ts = new Date().getTime();
var cs = THREE.Collisions.rayCastAll( ray );
tt = new Date().getTime() - ts;
if ( cs.length > 0 ) {
info.innerHTML = cs.length + " colliders found in " + tt;
for ( var i = 0; i < cs.length; i ++ ) {
cs[ i ].mesh.material.color.setHex( 0xaa0000 );
}
} else {
info.innerHTML = "No intersection";
}
} else {
// Raycast nearest
ts = new Date().getTime();
var c = THREE.Collisions.rayCastNearest( ray );
tt = new Date().getTime() - ts;
if ( c ) {
info.innerHTML = "Found in " + tt + " @ distance " + c.distance;
c.mesh.material.color.setHex( 0xaa0000 );
} else {
info.innerHTML = "No intersection";
}
}
camera.position.x = camdist * Math.cos(theta);
camera.position.z = camdist * Math.sin(theta);
camera.position.y = camdist / 2 * Math.sin(theta * 2);
camera.lookAt( scene.position );
sun.position.copy( camera.position );
sun.position.normalize();
theta += 0.005;
renderer.render( scene, camera );
stats.update();
}
function vts(v){
if (!v)
return "undefined<br>";
else
return v.x + " , " + v.y + " , " + v.z + "<br>";
}
</script>
</head>
<body onload="init();">
<div id="info">
</div>
<div id="options">
<input type="checkbox" id="nearest" checked/> Nearest collider only
<br/>
</div>
</body>
</html>