提交 7aa204e3 编写于 作者: M Mugen87

Examples: Removed THREE.Octree

上级 074290d3
......@@ -61,7 +61,6 @@
[example:webgl_interactive_lines Raycasting to a Line]<br />
[example:webgl_interactive_raycasting_points Raycasting to Points]<br />
[example:webgl_geometry_terrain_raycast Terrain raycasting]<br />
[example:webgl_octree_raycasting Raycasting using an octree]<br />
[example:webgl_interactive_voxelpainter Raycasting to paint voxels]<br />
[example:webgl_raycast_texture Raycast to a Texture]
</div>
......
......@@ -59,7 +59,6 @@
[example:webgl_interactive_lines Raycasting to a Line]<br />
[example:webgl_interactive_raycasting_points Raycasting to Points]<br />
[example:webgl_geometry_terrain_raycast Terrain raycasting]<br />
[example:webgl_octree_raycasting Raycasting using an octree]<br />
[example:webgl_interactive_voxelpainter Raycasting to paint voxels]<br />
[example:webgl_raycast_texture Raycast to a Texture]
</div>
......@@ -136,7 +135,7 @@
<h3>[method:null setFromCamera]( [param:Vector2 coords], [param:Camera camera] )</h3>
<p>
[page:Vector2 coords] —— 在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间。<br />
[page:Camera camera] —— 射线所来源的摄像机。
</p>
<p>
......
......@@ -198,8 +198,6 @@ var files = {
"webgl_multiple_scenes_comparison",
"webgl_multiple_views",
"webgl_nearestneighbour",
"webgl_octree",
"webgl_octree_raycasting",
"webgl_panorama_cube",
"webgl_panorama_dualfisheye",
"webgl_panorama_equirectangular",
......
此差异已折叠。
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - octree</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;
}
</style>
</head>
<body>
<script type="text/javascript" src="../build/three.js"></script>
<script type="text/javascript" src="js/Octree.js"></script>
<script>
var camera,
scene,
renderer,
octree,
geometry = new THREE.BoxBufferGeometry( 50, 50, 50 ),
mesh,
meshes = [],
meshesSearch = [],
meshCountMax = 100,
radius = 500,
radiusMax = radius * 10,
radiusMaxHalf = radiusMax * 0.5,
radiusSearch = 400,
searchMesh,
base = new THREE.Color( 0xff00ff ),
found = new THREE.Color( 0x00ff00 ),
adding = true,
rayCaster = new THREE.Raycaster(),
origin = new THREE.Vector3(),
direction = new THREE.Vector3();
init();
animate();
function init() {
// standard three scene, camera, renderer
scene = new THREE.Scene();
scene.background = new THREE.Color( 0xf0f0f0 );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, radius * 100 );
scene.add( camera );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// create octree
octree = new THREE.Octree( {
// when undeferred = true, objects are inserted immediately
// instead of being deferred until next octree.update() call
// this may decrease performance as it forces a matrix update
undeferred: false,
// set the max depth of tree
depthMax: Infinity,
// max number of objects before nodes split or merge
objectsThreshold: 8,
// percent between 0 and 1 that nodes will overlap each other
// helps insert objects that lie over more than one node
overlapPct: 0.15,
// pass the scene to visualize the octree
scene: scene
} );
// create object to show search radius and add to scene
searchMesh = new THREE.Mesh(
new THREE.SphereBufferGeometry( radiusSearch ),
new THREE.MeshBasicMaterial( { color: 0x00FF00, transparent: true, opacity: 0.4 } )
);
scene.add( searchMesh );
// info
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '0';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.padding = '10px';
info.style.background = '#FFFFFF';
info.innerHTML = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - octree (sparse & dynamic) - by <a href="http://github.com/collinhover/threeoctree" target="_blank" rel="noopener">collinhover</a>';
document.body.appendChild( info );
}
function animate() {
// note: three.js includes requestAnimationFrame shim
requestAnimationFrame( animate );
// modify octree structure by adding/removing objects
modifyOctree();
// search octree at random location
searchOctree();
// render results
render();
// update octree to add deferred objects
octree.update();
}
function modifyOctree() {
// if is adding objects to octree
if ( adding === true ) {
// create new object
mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: new THREE.Color( base ) } ) );
// give new object a random position in radius
mesh.position.set(
Math.random() * radiusMax - radiusMaxHalf,
Math.random() * radiusMax - radiusMaxHalf,
Math.random() * radiusMax - radiusMaxHalf
);
// add new object to octree and scene
octree.add( mesh );
scene.add( mesh );
// store object for later
meshes.push( mesh );
// if at max, stop adding
if ( meshes.length === meshCountMax ) {
adding = false;
}
} else { // else remove objects from octree
// get object
mesh = meshes.shift();
// remove from scene and octree
scene.remove( mesh );
octree.remove( mesh );
// if no more objects, start adding
if ( meshes.length === 0 ) {
adding = true;
}
}
/*
// octree details to console
console.log( ' OCTREE: ', octree );
console.log( ' ... depth ', octree.depth, ' vs depth end?', octree.depth_end() );
console.log( ' ... num nodes: ', octree.node_count_end() );
console.log( ' ... total objects: ', octree.object_count_end(), ' vs tree objects length: ', octree.objects.length );
// print full octree structure to console
octree.to_console();
*/
}
function searchOctree() {
var i, il;
// revert previous search objects to base color
for ( i = 0, il = meshesSearch.length; i < il; i ++ ) {
meshesSearch[ i ].object.material.color.copy( base );
}
// new search position
searchMesh.position.set(
Math.random() * radiusMax - radiusMaxHalf,
Math.random() * radiusMax - radiusMaxHalf,
Math.random() * radiusMax - radiusMaxHalf
);
// search octree from search mesh position with search radius
// optional third parameter: boolean, if should sort results by object when using faces in octree
// optional fourth parameter: vector3, direction of search when using ray (assumes radius is distance/far of ray)
origin.copy( searchMesh.position );
direction.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 ).normalize();
rayCaster.set( origin, direction );
meshesSearch = octree.search( rayCaster.ray.origin, radiusSearch, true, rayCaster.ray.direction );
rayCaster.intersectOctreeObjects( meshesSearch );
// set color of all meshes found in search
for ( i = 0, il = meshesSearch.length; i < il; i ++ ) {
meshesSearch[ i ].object.material.color.copy( found );
}
}
function render() {
var timer = - Date.now() / 5000;
camera.position.x = Math.cos( timer ) * 10000;
camera.position.z = Math.sin( timer ) * 10000;
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>three.js webgl - octree raycasting</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;
}
</style>
</head>
<body>
<script type="text/javascript" src="../build/three.js"></script>
<script type="text/javascript" src="js/Octree.js"></script>
<script type="text/javascript" src="js/controls/TrackballControls.js"></script>
<script type="text/javascript" src="js/libs/stats.min.js"></script>
<script>
var camera, scene, renderer;
var controls, stats;
var tracker;
var octree;
var objects = [];
var totalFaces = 0;
var simpleMeshCount = 5000;
var radius = 100;
var radiusMax = radius * 10;
var radiusMaxHalf = radiusMax * 0.5;
var baseColor = 0x333333;
var intersectColor = 0x00D66B;
var useOctree = true;
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersected;
init();
animate();
function init() {
// standard three scene, camera, renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, radius * 100 );
camera.position.z = radius * 10;
scene.add( camera );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
// create octree
octree = new THREE.Octree( {
// uncomment below to see the octree (may kill the fps)
//scene: scene,
// when undeferred = true, objects are inserted immediately
// instead of being deferred until next octree.update() call
// this may decrease performance as it forces a matrix update
undeferred: false,
// set the max depth of tree
depthMax: Infinity,
// max number of objects before nodes split or merge
objectsThreshold: 8,
// percent between 0 and 1 that nodes will overlap each other
// helps insert objects that lie over more than one node
overlapPct: 0.15
} );
// lights
var ambient = new THREE.AmbientLight( 0x101010 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set( 1, 1, 2 ).normalize();
scene.add( directionalLight );
// create all objects
var simpleGeometry = new THREE.BoxGeometry( 1, 1, 1 );
for ( var i = 0; i < simpleMeshCount - 1; i ++ ) {
totalFaces += simpleGeometry.faces.length;
var simpleMaterial = new THREE.MeshBasicMaterial();
simpleMaterial.color.setHex( baseColor );
modifyOctree( simpleGeometry, simpleMaterial, false, true, true, true );
}
// camera controls
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
// info
var info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '0';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.padding = '10px';
info.style.background = '#FFFFFF';
info.innerHTML = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - octree (raycasting performance) - by <a href="http://github.com/collinhover/threeoctree" target="_blank" rel="noopener">collinhover</a>)</small>';
document.body.appendChild( info );
// stats
stats = new Stats();
document.body.appendChild( stats.dom );
// bottom container
var container = document.createElement( 'div' );
container.style.position = 'absolute';
container.style.bottom = '0';
container.style.width = '100%';
container.style.textAlign = 'center';
document.body.appendChild( container );
// tracker
tracker = document.createElement( 'div' );
tracker.style.width = '100%';
tracker.style.padding = '10px';
tracker.style.background = '#FFFFFF';
container.appendChild( tracker );
// octree use toggle
var toggle = document.createElement( 'div' );
toggle.style.position = 'absolute';
toggle.style.bottom = '100%';
toggle.style.width = '100%';
toggle.style.padding = '10px';
toggle.style.background = '#FFFFFF';
container.appendChild( toggle );
var checkbox = document.createElement( 'input' );
checkbox.type = "checkbox";
checkbox.name = "octreeToggle";
checkbox.value = "value";
checkbox.id = "octreeToggle";
checkbox.checked = true;
var label = document.createElement( 'label' );
label.htmlFor = "octreeToggle";
label.appendChild( document.createTextNode( 'Use Octree' ) );
toggle.appendChild( checkbox );
toggle.appendChild( label );
// events
checkbox.addEventListener( 'click', toggleOctree, false );
renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
window.addEventListener( 'resize', onWindowResize, false );
}
function toggleOctree() {
useOctree = ! useOctree;
}
function animate() {
// note: three.js includes requestAnimationFrame shim
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
controls.update();
renderer.render( scene, camera );
// update octree post render
// this ensures any objects being added
// have already had their matrices updated
octree.update();
}
function modifyOctree( geometry, material, useFaces, randomPosition, randomRotation, randomScale ) {
var mesh;
if ( geometry ) {
// create new object
mesh = new THREE.Mesh( geometry, material );
// give new object a random position, rotation, and scale
if ( randomPosition ) {
mesh.position.set( Math.random() * radiusMax - radiusMaxHalf, Math.random() * radiusMax - radiusMaxHalf, Math.random() * radiusMax - radiusMaxHalf );
}
if ( randomRotation ) {
mesh.rotation.set( Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI );
}
if ( randomScale ) {
mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * radius * 0.1 + radius * 0.05;
}
// add new object to octree and scene
// NOTE: octree object insertion is deferred until after the next render cycle
octree.add( mesh, { useFaces: useFaces } );
scene.add( mesh );
// store object
objects.push( mesh );
/*
// octree details to console
console.log( ' ============================================================================================================');
console.log( ' OCTREE: ', octree );
console.log( ' ... depth ', octree.depth, ' vs depth end?', octree.depthEnd() );
console.log( ' ... num nodes: ', octree.nodeCountEnd() );
console.log( ' ... total objects: ', octree.objectCountEnd(), ' vs tree objects length: ', octree.objects.length );
console.log( ' ============================================================================================================');
console.log( ' ');
// print full octree structure to console
octree.toConsole();
*/
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function onDocumentMouseMove( event ) {
event.preventDefault();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var octreeObjects;
var numObjects;
var numFaces = 0;
var intersections;
if ( useOctree ) {
octreeObjects = octree.search( raycaster.ray.origin, raycaster.ray.far, true, raycaster.ray.direction );
intersections = raycaster.intersectOctreeObjects( octreeObjects );
numObjects = octreeObjects.length;
for ( var i = 0, il = numObjects; i < il; i ++ ) {
numFaces += octreeObjects[ i ].faces.length;
}
} else {
intersections = raycaster.intersectObjects( objects );
numObjects = objects.length;
numFaces = totalFaces;
}
if ( intersections.length > 0 ) {
if ( intersected != intersections[ 0 ].object ) {
if ( intersected ) intersected.material.color.setHex( baseColor );
intersected = intersections[ 0 ].object;
intersected.material.color.setHex( intersectColor );
}
document.body.style.cursor = 'pointer';
} else if ( intersected ) {
intersected.material.color.setHex( baseColor );
intersected = null;
document.body.style.cursor = 'auto';
}
// update tracker
tracker.innerHTML = ( useOctree ? 'Octree search' : 'Search without octree' ) + ' using infinite ray from camera found [ ' + numObjects + ' / ' + objects.length + ' ] objects, [ ' + numFaces + ' / ' + totalFaces + ' ] faces, and [ ' + intersections.length + ' ] intersections.';
}
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册