【发布时间】:2013-07-14 00:51:08
【问题描述】:
我在 three.js 中有一个 3D 场景,我需要在其中获取源对象 X 范围内的对象数组。目前,我正在使用的示例是在 for 循环中利用光线投射,该循环迭代场景中存在的“可碰撞对象”数组。我觉得必须有更好的方法来处理这个问题,因为如果数组中的每个对象都必须从自身投射到数组中的每个其他对象,这种方法会成倍地复杂。随着可碰撞对象数组的增长,这会对性能产生巨大影响。
//hold collidable objects
var collidableObjects = [];
var scene = new THREE.Scene();
var cubeGeo = new THREE.CubeGeometry( 10 , 10 , 10 );
var materialA = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var materialB = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cubeA = new THREE.Mesh( cubeGeo , materialA );
collidableObjects.push( cubeA );
scene.add( cubeA );
//Change this variable to a larger number to see the processing time explode
var range = 100;
for( var x = 0 ; x < range ; x += 20 ) {
for( var z = 0; z < range ; z += 20 ) {
if( x === 0 && z === 0 ) continue;
var cube = new THREE.Mesh( cubeGeo , materialB );
scene.add( cube );
cube.position.x = x;
cube.position.z = z;
collidableObjects.push( cube );
var cube = cube.clone();
scene.add( cube );
cube.position.x = x * -1;
cube.position.z = z;
collidableObjects.push( cube );
var cube = cube.clone();
scene.add( cube );
cube.position.x = x;
cube.position.z = z * -1;
collidableObjects.push( cube );
var cube = cube.clone();
scene.add( cube );
cube.position.x = x * -1;
cube.position.z = z * -1;
collidableObjects.push( cube );
}
}
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera.position.y = 200;
camera.lookAt( scene.position );
function render() {
//requestAnimationFrame(render);
renderer.render(scene, camera);
console.log( getObjectsWithinRange( cubeA , 30 ) );
}
function getObjectsWithinRange( source , range ) {
var startTime = new Date().getTime();
var inRange = [];
for( var i = 0; i < collidableObjects.length ; ++i ) {
var ray = new THREE.Raycaster( source.position , collidableObjects[i].position , 0 , range );
if( ( obj = ray.intersectObject( collidableObjects[i] ) ) && obj.length ) {
inRange.push( obj[0] );
}
}
var endTime = new Date().getTime();
console.log( 'Processing Time: ' , endTime - startTime );
return inRange;
}
render();
You can see the JSfiddle of this here.
如果您将指示的变量更改为更大的数字,例如 200,那么您会看到处理时间开始失控。我觉得必须有一种更简单的方法来减少这样做的数组I looked at the documentation for the Raycaster of three.js,我注意到near 和far 属性都说“这个值表示可以根据距离丢弃哪些对象。”所以我认为有一些内部函数用于在投射所有光线之前根据距离细化结果。
I did a little digging on this and came up with a single function inside of Ray.js.
distanceToPoint: function () {
var v1 = new THREE.Vector3();
return function ( point ) {
var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
// point behind the ray
if ( directionDistance < 0 ) {
return this.origin.distanceTo( point );
}
v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
return v1.distanceTo( point );
};
}(),
我想我正在寻找一种更好的方法来获取场景中位于源对象 X 半径内的所有对象。我什至不需要使用 Raycasting,因为我对网格碰撞不感兴趣,而只是源对象 X 半径内的对象列表。由于场景的设置方式,我什至不需要递归到这些对象的子对象。所以我觉得必须有一些内部函数或简单地使用THREE.Vector3 对象和数学来按距离细化它们的东西。在这种情况下,这必须比 Raycasting 便宜得多。如果在 three.js 中已经有一个函数可以处理这个问题,我不想从头开始重新创建一个。我也意识到这可能是一个非常冗长的问题,因为很可能是单行答案,但我想确保我有所有的细节和其他东西,以防其他人稍后搜索它。
【问题讨论】:
-
Three.js r.59 有一个octree example。
-
@WestLangley 哇,我什至没有看到,但是根据我在渲染器中看到的,该示例可能具有一些可能被证明有用的功能 :) 谢谢,我会看看那
标签: three.js raycasting radial