使用 THREE.Raycaster - 我总是得到 id 8?
Using THREE.Raycaster - I get always the id 8?
我想创建一个显示一定数量 "THREE.Meshes" 的仪表板。当我用鼠标点击其中一个时,我想调用一个函数来识别我点击的内容。
我的问题:
我总是从 "callFromTitleWithId" 函数中得到 ID:8 。我用鼠标点击选择了哪一个都没有关系。
也许有人可以帮忙,我找不到错误:(
这是完整的示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TEST</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
body { margin: 0;
background: black; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<!-- Bibs -->
<script src="../extlib/webthree/build/three.js"></script>
<script>
document.addEventListener('mousedown', onDocumentMouseDown, false);
var arrayTiles = [];
//[SCREEN]
var SCREEN_WIDTH = window.innerWidth - 5;
var SCREEN_HEIGHT = window.innerHeight - 5;
screenOrientationValue=0;
//RayCaster für Objekte
var raycaster2 = new THREE.Raycaster(new THREE.Vector3(0,0,35),new THREE.Vector3(0,0,1));
var mouse2 = new THREE.Vector2();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
document.body.appendChild( renderer.domElement );
var sceneWorld = new THREE.Scene();
sceneWorld.add( new THREE.AxesHelper(50) );
createTiles(sceneWorld);
var camera= new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,35);
var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
sceneWorld.add( light2 );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( sceneWorld, camera);
sceneUpdate();
};
animate();
function sceneUpdate()
{
//Update
}
function callFromTitleWithId(titleId)
{
console.log("ID:"+titleId);
}
function onDocumentMouseDown(event)
{
event.preventDefault();
mouse2.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse2.y = - (event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster2.setFromCamera(mouse2, camera);
var intersects2 = raycaster2.intersectObjects(arrayTiles,true);
if (intersects2.length > 0) {
console.log('Maus: X:'+mouse2.x+' Y:'+mouse2.y);
console.log("intersects:" + intersects2[0].object);
console.log("distance:" + intersects2[0].distance);
console.log("face:" + intersects2[0].face);
console.log("faceIndex:" + intersects2[0].faceIndex);
console.log("faceIndex y:" + intersects2[0].point.y);
console.log("faceIndex x:" + intersects2[0].point.x);
intersects2[0].object.callback();
}
}
function createTiles(sceneWorld)
{
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var materialSide = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var materialsTiles = [materialSide, // Left side
materialSide, // Right side
materialSide, // Top side ---> THIS IS THE FRONT
materialSide, // Bottom side --> THIS IS THE BACK
material, // Front side
materialSide // Back side
];
var maxTileSizeWidth=11;
var maxTileSizeHeight=8;
var distanceBetween=2;
var distanceBorderLeft=-1;
var countInColumns=2;
var countInRow = 4;
var startCoordinatesX = ((((countInColumns * maxTileSizeWidth)+(countInColumns-6.5)*distanceBetween)/2))*-1;
var startCoordinatesY = 20;
var actualCoordinatesX = startCoordinatesX;
var actualCoordinatesY = startCoordinatesY;
//id for test
var idNumberForTest=0;
let r;
for(r=1; r<=countInRow; r++ )
{
let i;
for(i=1; i<=countInColumns; i++ )
{
var geometry = new THREE.BoxGeometry(maxTileSizeWidth, maxTileSizeHeight, 1 );
var tileX = new THREE.Mesh( geometry, materialsTiles );
tileX.position.set(actualCoordinatesX,actualCoordinatesY,0);
//Change actualCoordinates X
actualCoordinatesX = actualCoordinatesX + maxTileSizeWidth + distanceBetween;
idNumberForTest=idNumberForTest + 1;
tileX.callback = function(){callFromTitleWithId(idNumberForTest+'')};
arrayTiles.push(tileX);
sceneWorld.add( tileX );
}
actualCoordinatesY = actualCoordinatesY - (maxTileSizeHeight+1);
actualCoordinatesX = startCoordinatesX;
}
}
</script>
</body>
</html>
`
问题是 idNumberForTest
对所有对象都是相等的。回调函数总是引用同一个变量。除了使用回调函数,您还可以像这样存储单击的网格的 ID:
tileX.userData.id = idNumberForTest;
这样,正确的ID就分配给了相应的对象。查看以下实时示例,了解这种方法的实际应用。
document.addEventListener('mousedown', onDocumentMouseDown, false);
var arrayTiles = [];
//[SCREEN]
var SCREEN_WIDTH = window.innerWidth - 5;
var SCREEN_HEIGHT = window.innerHeight - 5;
screenOrientationValue=0;
//RayCaster für Objekte
var raycaster2 = new THREE.Raycaster(new THREE.Vector3(0,0,35),new THREE.Vector3(0,0,1));
var mouse2 = new THREE.Vector2();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
document.body.appendChild( renderer.domElement );
var sceneWorld = new THREE.Scene();
sceneWorld.add( new THREE.AxesHelper(50) );
createTiles(sceneWorld);
var camera= new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,35);
var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
sceneWorld.add( light2 );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( sceneWorld, camera);
sceneUpdate();
};
animate();
function sceneUpdate()
{
//Update
}
function callFromTitleWithId(titleId)
{
console.log("ID:"+titleId);
}
function onDocumentMouseDown(event)
{
event.preventDefault();
mouse2.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse2.y = - (event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster2.setFromCamera(mouse2, camera);
console.log( arrayTiles );
var intersects2 = raycaster2.intersectObjects(arrayTiles,true);
if (intersects2.length > 0) {
console.log('Maus: X:'+mouse2.x+' Y:'+mouse2.y);
console.log("intersects:" + intersects2[0].object);
console.log("distance:" + intersects2[0].distance);
console.log("face:" + intersects2[0].face);
console.log("faceIndex:" + intersects2[0].faceIndex);
console.log("faceIndex y:" + intersects2[0].point.y);
console.log("faceIndex x:" + intersects2[0].point.x);
console.log("ID:", intersects2[0].object.userData.id);
}
}
function createTiles(sceneWorld)
{
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var materialSide = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var materialsTiles = [materialSide, // Left side
materialSide, // Right side
materialSide, // Top side ---> THIS IS THE FRONT
materialSide, // Bottom side --> THIS IS THE BACK
material, // Front side
materialSide // Back side
];
var maxTileSizeWidth=11;
var maxTileSizeHeight=8;
var distanceBetween=2;
var distanceBorderLeft=-1;
var countInColumns=2;
var countInRow = 4;
var startCoordinatesX = ((((countInColumns * maxTileSizeWidth)+(countInColumns-6.5)*distanceBetween)/2))*-1;
var startCoordinatesY = 20;
var actualCoordinatesX = startCoordinatesX;
var actualCoordinatesY = startCoordinatesY;
//id for test
var idNumberForTest=0;
let r;
for(r=1; r<=countInRow; r++ )
{
let i;
for(i=1; i<=countInColumns; i++ )
{
var geometry = new THREE.BoxGeometry(maxTileSizeWidth, maxTileSizeHeight, 1 );
var tileX = new THREE.Mesh( geometry, materialsTiles );
tileX.position.set(actualCoordinatesX,actualCoordinatesY,0);
//Change actualCoordinates X
actualCoordinatesX = actualCoordinatesX + maxTileSizeWidth + distanceBetween;
idNumberForTest=idNumberForTest + 1;
arrayTiles.push(tileX);
tileX.userData.id = idNumberForTest;
sceneWorld.add( tileX );
}
actualCoordinatesY = actualCoordinatesY - (maxTileSizeHeight+1);
actualCoordinatesX = startCoordinatesX;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
我想创建一个显示一定数量 "THREE.Meshes" 的仪表板。当我用鼠标点击其中一个时,我想调用一个函数来识别我点击的内容。
我的问题: 我总是从 "callFromTitleWithId" 函数中得到 ID:8 。我用鼠标点击选择了哪一个都没有关系。
也许有人可以帮忙,我找不到错误:(
这是完整的示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TEST</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
body { margin: 0;
background: black; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<!-- Bibs -->
<script src="../extlib/webthree/build/three.js"></script>
<script>
document.addEventListener('mousedown', onDocumentMouseDown, false);
var arrayTiles = [];
//[SCREEN]
var SCREEN_WIDTH = window.innerWidth - 5;
var SCREEN_HEIGHT = window.innerHeight - 5;
screenOrientationValue=0;
//RayCaster für Objekte
var raycaster2 = new THREE.Raycaster(new THREE.Vector3(0,0,35),new THREE.Vector3(0,0,1));
var mouse2 = new THREE.Vector2();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
document.body.appendChild( renderer.domElement );
var sceneWorld = new THREE.Scene();
sceneWorld.add( new THREE.AxesHelper(50) );
createTiles(sceneWorld);
var camera= new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,35);
var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
sceneWorld.add( light2 );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( sceneWorld, camera);
sceneUpdate();
};
animate();
function sceneUpdate()
{
//Update
}
function callFromTitleWithId(titleId)
{
console.log("ID:"+titleId);
}
function onDocumentMouseDown(event)
{
event.preventDefault();
mouse2.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse2.y = - (event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster2.setFromCamera(mouse2, camera);
var intersects2 = raycaster2.intersectObjects(arrayTiles,true);
if (intersects2.length > 0) {
console.log('Maus: X:'+mouse2.x+' Y:'+mouse2.y);
console.log("intersects:" + intersects2[0].object);
console.log("distance:" + intersects2[0].distance);
console.log("face:" + intersects2[0].face);
console.log("faceIndex:" + intersects2[0].faceIndex);
console.log("faceIndex y:" + intersects2[0].point.y);
console.log("faceIndex x:" + intersects2[0].point.x);
intersects2[0].object.callback();
}
}
function createTiles(sceneWorld)
{
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var materialSide = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var materialsTiles = [materialSide, // Left side
materialSide, // Right side
materialSide, // Top side ---> THIS IS THE FRONT
materialSide, // Bottom side --> THIS IS THE BACK
material, // Front side
materialSide // Back side
];
var maxTileSizeWidth=11;
var maxTileSizeHeight=8;
var distanceBetween=2;
var distanceBorderLeft=-1;
var countInColumns=2;
var countInRow = 4;
var startCoordinatesX = ((((countInColumns * maxTileSizeWidth)+(countInColumns-6.5)*distanceBetween)/2))*-1;
var startCoordinatesY = 20;
var actualCoordinatesX = startCoordinatesX;
var actualCoordinatesY = startCoordinatesY;
//id for test
var idNumberForTest=0;
let r;
for(r=1; r<=countInRow; r++ )
{
let i;
for(i=1; i<=countInColumns; i++ )
{
var geometry = new THREE.BoxGeometry(maxTileSizeWidth, maxTileSizeHeight, 1 );
var tileX = new THREE.Mesh( geometry, materialsTiles );
tileX.position.set(actualCoordinatesX,actualCoordinatesY,0);
//Change actualCoordinates X
actualCoordinatesX = actualCoordinatesX + maxTileSizeWidth + distanceBetween;
idNumberForTest=idNumberForTest + 1;
tileX.callback = function(){callFromTitleWithId(idNumberForTest+'')};
arrayTiles.push(tileX);
sceneWorld.add( tileX );
}
actualCoordinatesY = actualCoordinatesY - (maxTileSizeHeight+1);
actualCoordinatesX = startCoordinatesX;
}
}
</script>
</body>
</html>
`
问题是 idNumberForTest
对所有对象都是相等的。回调函数总是引用同一个变量。除了使用回调函数,您还可以像这样存储单击的网格的 ID:
tileX.userData.id = idNumberForTest;
这样,正确的ID就分配给了相应的对象。查看以下实时示例,了解这种方法的实际应用。
document.addEventListener('mousedown', onDocumentMouseDown, false);
var arrayTiles = [];
//[SCREEN]
var SCREEN_WIDTH = window.innerWidth - 5;
var SCREEN_HEIGHT = window.innerHeight - 5;
screenOrientationValue=0;
//RayCaster für Objekte
var raycaster2 = new THREE.Raycaster(new THREE.Vector3(0,0,35),new THREE.Vector3(0,0,1));
var mouse2 = new THREE.Vector2();
var renderer = new THREE.WebGLRenderer();
renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
document.body.appendChild( renderer.domElement );
var sceneWorld = new THREE.Scene();
sceneWorld.add( new THREE.AxesHelper(50) );
createTiles(sceneWorld);
var camera= new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(0,0,35);
var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
sceneWorld.add( light2 );
var animate = function () {
requestAnimationFrame( animate );
renderer.render( sceneWorld, camera);
sceneUpdate();
};
animate();
function sceneUpdate()
{
//Update
}
function callFromTitleWithId(titleId)
{
console.log("ID:"+titleId);
}
function onDocumentMouseDown(event)
{
event.preventDefault();
mouse2.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse2.y = - (event.clientY / renderer.domElement.clientHeight) * 2 + 1;
raycaster2.setFromCamera(mouse2, camera);
console.log( arrayTiles );
var intersects2 = raycaster2.intersectObjects(arrayTiles,true);
if (intersects2.length > 0) {
console.log('Maus: X:'+mouse2.x+' Y:'+mouse2.y);
console.log("intersects:" + intersects2[0].object);
console.log("distance:" + intersects2[0].distance);
console.log("face:" + intersects2[0].face);
console.log("faceIndex:" + intersects2[0].faceIndex);
console.log("faceIndex y:" + intersects2[0].point.y);
console.log("faceIndex x:" + intersects2[0].point.x);
console.log("ID:", intersects2[0].object.userData.id);
}
}
function createTiles(sceneWorld)
{
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var materialSide = new THREE.MeshBasicMaterial( {color: 0xffff00} );
var materialsTiles = [materialSide, // Left side
materialSide, // Right side
materialSide, // Top side ---> THIS IS THE FRONT
materialSide, // Bottom side --> THIS IS THE BACK
material, // Front side
materialSide // Back side
];
var maxTileSizeWidth=11;
var maxTileSizeHeight=8;
var distanceBetween=2;
var distanceBorderLeft=-1;
var countInColumns=2;
var countInRow = 4;
var startCoordinatesX = ((((countInColumns * maxTileSizeWidth)+(countInColumns-6.5)*distanceBetween)/2))*-1;
var startCoordinatesY = 20;
var actualCoordinatesX = startCoordinatesX;
var actualCoordinatesY = startCoordinatesY;
//id for test
var idNumberForTest=0;
let r;
for(r=1; r<=countInRow; r++ )
{
let i;
for(i=1; i<=countInColumns; i++ )
{
var geometry = new THREE.BoxGeometry(maxTileSizeWidth, maxTileSizeHeight, 1 );
var tileX = new THREE.Mesh( geometry, materialsTiles );
tileX.position.set(actualCoordinatesX,actualCoordinatesY,0);
//Change actualCoordinates X
actualCoordinatesX = actualCoordinatesX + maxTileSizeWidth + distanceBetween;
idNumberForTest=idNumberForTest + 1;
arrayTiles.push(tileX);
tileX.userData.id = idNumberForTest;
sceneWorld.add( tileX );
}
actualCoordinatesY = actualCoordinatesY - (maxTileSizeHeight+1);
actualCoordinatesX = startCoordinatesX;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>