对于我的项目,我需要在Three.js中进行碰撞测试。在我的CollisionDetection课程中,我试图让Raycaster工作。而且我发现了一些我无法解释但又无法解决的奇怪现象:
我的CollisionDetector适用于Cubes ..但是当我使用Spheres时,它并没有给我相同的结果 - 我错误地期望与立方体相同的结果?或者我会错过其他什么?
这是我的代码:
var renderer, camera, scene;
init();
animate();
function init() {
var container = document.getElementById("scene");
var width = window.innerWidth;
var height = window.innerHeight;
renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
camera = new THREE.OrthographicCamera( 0, width, 0, height, 1, 10000 );
camera.position.z = 300;
scene = new THREE.Scene();
scene.add(camera);
container.appendChild(renderer.domElement);
var geometry = new THREE.SphereGeometry(10,16, 16);
//var geometry = new THREE.CubeGeometry( 10, 10, 10 );
var material1 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
var material2 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
var material3 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
var material4 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
var material5 = new THREE.MeshBasicMaterial( { color: 0xFF3333} );
var element1 = new THREE.Mesh( geometry, material1 );
var element2 = new THREE.Mesh( geometry, material2 );
var element3 = new THREE.Mesh( geometry, material3 );
var element4 = new THREE.Mesh( geometry, material4 );
var element5 = new THREE.Mesh( geometry, material5 );
element1.position.set(200,200,0);
element2.position.set(200,100,0);
element3.position.set(200,300,0);
element4.position.set(100,200,0);
element5.position.set(300,200,0);
scene.add(element1);
scene.add(element2);
scene.add(element3);
scene.add(element4);
scene.add(element5);
var CollisionDetector = new CollisionDetection();
CollisionDetector.addRay(new THREE.Vector3(0, -1, 0));
CollisionDetector.addRay(new THREE.Vector3(0, 1, 0));
CollisionDetector.addRay(new THREE.Vector3(1, 0, 0));
CollisionDetector.addRay(new THREE.Vector3(-1, 0, 0));
CollisionDetector.addElement(element1);
CollisionDetector.addElement(element2);
CollisionDetector.addElement(element3);
CollisionDetector.addElement(element4);
CollisionDetector.addElement(element5);
document.onclick = function(){
CollisionDetector.testElement(element1);
};
}
function CollisionDetection(){
var caster = new THREE.Raycaster();
var rays = [];
var elements = [];
this.testElement = function(element){
for(var i=0; i<rays.length; i++) {
caster.set(element.position, rays[i]);
var hits = caster.intersectObjects(elements, true);
for(var k=0; k<hits.length; k++) {
console.log("hit", hits[k]);
hits[k].object.material.color.setHex(0x0000ff);
}
}
}
this.addRay = function(ray) {
rays.push(ray.normalize());
}
this.addElement = function(element){
elements.push(element);
}
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
或者最好,亲眼看看它的行为:http://jsfiddle.net/mymL5/12/
开启单击光线所击中的每个元素都应变为蓝色,并且所有命中都会在控制台中注册。 注意球体的(imho)奇怪的控制台输出。 另外,为什么较低的球体没有击中,而鞋帮是?
您可以通过评论/取消注释第19/20页
在多维数据集和球体之间切换任何人都可以帮助我吗?我没得到什么?
PS:我是Three.js的新手,所以我可能很蠢。答案 0 :(得分:0)
由于这是与家庭作业相关的,我只会提供一些提示。
您的场景呈现颠倒,因为您的正交相机的参数不正确。
你的球体比你的立方体大。
你的光线正好击中你球体的北极和南极。这些要点有什么不同?
material.side
属性告诉Raycaster
脸部的哪一侧要考虑“前方”。
您的fidde示例正在运行three.js的旧版本(r.54)。
three.js r.58
答案 1 :(得分:0)
增加球体大小。 通过一些非平凡的角度旋转球体(因此它们不会在N / S极点上被击中)。 现在它有效吗? :P
var geometry = new THREE.SphereGeometry(20,17, 17);
element1.position.set(0,0,0);
element2.position.set(0,100,0);
element3.position.set(100,0,0);
element4.position.set(0,-100,0);
element5.position.set(-100,0,0);
element1.rotation.set(0,0,10);
element2.rotation.set(0,0,10);
element3.rotation.set(0,0,10);
element4.rotation.set(0,0,10);
element5.rotation.set(0,0,10);
然而,射线测试应该知道击中三角形的精确顶点或边缘,因此可以将其视为Three.js的改进位置。
答案 2 :(得分:0)
我在Three.js存储库中提交了一个相关问题: https://github.com/mrdoob/three.js/issues/3541