我只是在尝试检测下部球体(可拖动的球体)何时与上部球体相交。我敢肯定,有些事情我不理解,不幸的是,什么都没让我想到。
<script src='https://threejs.org/build/three.min.js'></script>
<script src='https://threejs.org/examples/js/controls/DragControls.js'></script>
<script>
window.onload = init;
// Global variables
var renderer, raycaster, mouse,
scene, camera, sphere1, sphere2,
sphere3, sphere4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
function eventful(){ // Where all events happen
new THREE.DragControls([sphere1], camera, renderer.domElement);
window.addEventListener( 'mousemove', onMouseMove, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.SphereBufferGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = drawSphere(); sphere2.position.set(15, 23, 0);
sphere3 = drawSphere(); sphere3.position.set(0, 22, 0);
sphere4 = drawSphere(); sphere4.position.set(-20, 20, 0);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onMouseMove(event){ // Calculate mouse movements
// Pixel coordinates
mouse.x = event.clientX;
mouse.y = event.clientY;
raycasting(renderer, scene, camera);
};
function raycasting(renderer, scene, camera){
raycaster.setFromCamera(sphere1, camera); // Update the picking ray with the camera and mouse movements
intersects = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
for(var i = 0; i < intersects.length; i++){
intersects[i].object.material.color.set(0xff0000);
console.log('Hit on: ', intersects[i]);
}
};
</script>
我唯一能想到的是我对intersectObjects()方法或setFromCamera()的用法,但我不确定。我认为这是有道理的,因为它是在鼠标移动时更新的。我怎么说:“当我移动球体并检测到碰撞时,我希望可拖动球体成为射线投射器”?或者更简单的方法来检测何时发生碰撞。
例如,考虑以下内容:
window.onload = init;
// Global variables
var renderer, raycaster, mouse,
scene, camera, sphere1, sphere2,
sphere3, sphere4;
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
console.log(raycaster);
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
function eventful(){ // Where all events happen
new THREE.DragControls([sphere1], camera, renderer.domElement);
window.addEventListener( 'mousemove', onMouseMove, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.SphereBufferGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
material = new THREE.MeshNormalMaterial();
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = sphere1.clone(); sphere2.position.set(15, 23, 0);
sphere3 = sphere1.clone(); sphere3.position.set(0, 22, 0);
sphere4 = sphere1.clone(); sphere4.position.set(-20, 20, 0);
console.log(sphere1, sphere2, sphere3, sphere4);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onMouseMove(event){ // Calculate mouse movements
// Normalized Coordinate System
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
raycasting(renderer, scene, camera);
};
function raycasting(renderer, scene, camera){
raycaster.setFromCamera(mouse, camera); // Update the picking ray with the camera and mouse movements
intersects = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
for(var i = 0; i < intersects.length; i++){
console.log('Hit on: ', intersects[i].object.uuid);
}
};
在此示例中,光线投射器是。每次有鼠标悬停在 intersectObjects()方法中指定的球体上时,您都会在控制台上看到“命中”消息。
答案 0 :(得分:0)
如果您不是从鼠标光标投射光线,则不需要.setFromCamera()..您只需手动设置光线即可。
您可以使用射线投射检查一个球体是否碰到另一个球体,也可以像这样进行球体->球体相交测试。
var tmp = new THREE.Vector3();
function spheresCollide(centerA,radiusA,centerB,radiusB){
var sqdist = radiusA+radiusB;
sqdist*=sqdist;
tmp.copy(centerB).sub(centerA)
if(tmp.lengthSq()<sqdist)return true;
return false;
}
//centerA and centerB are the vector3 positions of your spheres.. radiusA and B are the sphere radii
要进行光线投射,您需要对每个球体执行以下操作:
rayCaster.ray.origin.copy(sphereA.position);
rayCaster.ray.direction.copy(sphereB.position).sub(sphereA.position).normalize()
intersects = raycaster.intersectObjects([sphereB]);
for(var i = 0; i < intersects.length; i++){
tmp.copy(intersects[i].position).sub(sphereA.position);
if(tmp.length()<(radiusA+radiusB)){
intersects[i].object.material.color.set(0xff0000);
console.log('Hit on: ', intersects[i]);
}
}
答案 1 :(得分:0)
我花了一些时间才能解决这个问题。对移动物体进行光线投射有一些不同之处。射线投射背后的想法是正在投射射线。在此示例中,setFromCamera()方法不会执行操作,因为“球形”应该是射线所来自的对象。
<script src='https://threejs.org/build/three.min.js'></script>
<script src='https://threejs.org/examples/js/controls/DragControls.js'></script>
<script>
window.onload = init;
// Global variables
var renderer, raycaster,
scene, camera, sphere1, sphere2,
sphere3, sphere4, dragControls;
function init(){
// Get WebGL ready
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer = this.renderer;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(0, 0, 100);
camera.lookAt(0, 0, 0);
scene = new THREE.Scene();
// Get set
drawSpheres();
// Go
eventful();
animate();
};
function animate(){
requestAnimationFrame(animate);
renderer.render(scene, camera);
raycasting();
};
function eventful(){ // Where all events happen
dragControls = new THREE.DragControls([sphere1], camera, renderer.domElement);
dragControls.addEventListener('dragstart', onDragStart, false);
dragControls.addEventListener('dragend', onDragEnd, false);
};
function drawSphere(){ // Sphere geometry
var geometry, material, sphere;
geometry = new THREE.CubeGeometry(3,3,3,1,1,1);
material = new THREE.MeshBasicMaterial({
wireframe: true
});
sphere = new THREE.Mesh(geometry, material);
return sphere;
};
function drawSpheres(){ // Draw four corners for the quadrant
sphere1 = drawSphere(); sphere1.position.set(20, 0, 0);
sphere2 = sphere1.clone(); sphere2.position.set(15, 23, 0);
sphere3 = sphere1.clone(); sphere3.position.set(0, 22, 0);
sphere4 = sphere1.clone(); sphere4.position.set(-20, 20, 0);
console.log(sphere1, sphere2, sphere3, sphere4);
scene.add(sphere1, sphere2, sphere3, sphere4);
};
function onDragStart(event){
console.log('on drag start');
};
function onDragEnd(event){
console.log('on drag end');
};
function onMouseMove(event){ // Calculate mouse movements
// Normalized Coordinate System
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
};
//////////////////////////////
//////// RAYCASTING //////////
//////////////////////////////
function raycasting(){ // Blast rays like Cyclops or Superman, but only to measure proximity
var sphere1Origin, // The 3D position of sphere1 when the page loads
vIndex, // Vertex index
sphere1VLength, // The amount of vertices
dVector, // The directions the ray should be pointing to while it is moving
raycaster, // The ray casting from a given point
sphere1Origin = getUpdatedPosition();
sphere1VLength = sphere1.geometry.vertices.length;
for(vIndex = 0; vIndex < sphere1VLength; vIndex++){
dVector = bindRaysToVertices(sphere1, vIndex);
raycaster = raycast(sphere1Origin, dVector);
collided = detectCollision(raycaster, dVector).hasCollided;
if(collided){
console.log('Hit!');
}
}
};
function detectCollision(raycaster, dVector){ // Determines whether there is/are (a) collision(s)
var collisions, // Results of each collisions
collided; // True/False
collisions = raycaster.intersectObjects([sphere2, sphere3, sphere4]);
collided = collisions.length > 0 && collisions[0].distance < dVector.length();
return {
hasCollided: collided,
collisionsList: collisions
};
};
function bindRaysToVertices(sphere1, vIndex){ // Make the geometry blast rays in all directions, while moving
var lVertex, // The re-calculated (updated) vertices for the moving object
gVertex, // The complete representation of the re-calculated (updated) vertices
dVector; // The directions the ray should be pointing to while it is moving
lVertex = sphere1.geometry.vertices[vIndex].clone();
gVertex = lVertex.applyMatrix4(sphere1.matrix);
dVector = gVertex.sub(sphere1.position);
return dVector;
};
function getUpdatedPosition(){
var sphere1Origin, // The 3D position of sphere1 when the page loads
sphere1Origin = sphere1.position.clone();
return sphere1Origin;
};
function raycast(sphere1Origin, dVector){
// Make the sphere cast the ray, through its vertices,
// while moving, using a Normalized Coordinate System
return new THREE.Raycaster(sphere1Origin, toNCS(dVector));
};
function toNCS(dVector){ // To Normalize Coordinate System
return dVector.clone().normalize();
};
</script>
以Stemkoski为例,我决定将多维数据集用作线框,并且如果需要有一个球体,则该多维数据集应位于其中。否则,为了接近检测目的而具有像太阳这样的球体爆炸射线将在计算上昂贵。