gpt4 book ai didi

javascript - Three.js:Raycast 具有空的相交数组

转载 作者:行者123 更新时间:2023-12-03 03:31:31 25 4
gpt4 key购买 nike

我将此示例用于我的 WebGL 全景立方体:https://threejs.org/examples/?q=pano#webgl_panorama_equirectangular

我想知道用户点击了哪个立方体,我发现我可以使用 Raycaster 来实现此目的。根据文档我添加了以下功能:

    function onMouseDown( event ) {
event.preventDefault();

var mouseVector = new THREE.Vector3(
( event.clientX / window.innerWidth ) * 2 - 1,
- ( event.clientY / window.innerHeight ) * 2 + 1,
1 );

//projector.unprojectVector( mouseVector, camera );
mouseVector.unproject( camera );
var raycaster = new THREE.Raycaster( camera.position, mouseVector.sub( camera.position ).normalize() );

// create an array containing all objects in the scene with which the ray intersects
var intersects = raycaster.intersectObjects( scene.children );
console.log(intersects);
if (intersects.length>0){
console.log("Intersected object:", intersects.length);
intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
}
// ...

但是相交始终为空。我的场景定义为

scene = new THREE.Scene();

并添加了 skyBox:

var skyBox = new THREE.Mesh( new THREE.CubeGeometry( 1, 1, 1 ), materials );
skyBox.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, - 1 ) );
scene.add( skyBox );

我看过与此问题相关的类似帖子,但不知道如何应用于此示例。任何指示表示赞赏。

最佳答案

尝试将其添加到您的 Material 定义中:

var materials = new THREE.SomeMaterial({
/* other settings */,
side: THREE.DoubleSide
});

Raycaster 不会与背面相交,除非 side 属性设置为 THREE.BackSideTHREE.DoubleSide。尽管缩放在技术上会反转面方向,但顶点顺序保持不变,这对 Raycaster 来说很重要。

一些进一步的解释

下面的代码片段显示了从位于天空盒中心的摄像机转换的光线(按 -Z 比例反转)的外观。

盒子本身看起来很奇怪,因为它已经进行了 -Z 缩放,并且法线不再与 Material 匹配。但这不在这里也不在那里。

绿色箭头代表原始光线。红色箭头表示在 Mesh.raycast 函数内该光线会发生什么,该函数会将对象世界矩阵的逆矩阵应用于光线,但不应用于对象的几何体。这是一个完全不同的问题。

我要说的是,在Mesh.raycast中,它不会影响顶点/索引顺序,因此当它检查网格的三 Angular 形时,它们仍然保持原始顺序。对于标准 BoxGeometry/BoxBufferGeometry,这意味着所有面都从几何原点面向外。

这意味着光线(无论变换矩阵如何影响它们)仍在尝试与这些三 Angular 形的背面相交,除非 Material 设置为THREE.DoubleSide,否则这将不起作用。 (它也可以设置为 THREE.BackSide,但 -Z 比例会破坏它。)

如果 -Z 缩放框未设置为 THREE.DoubleSide(默认),单击任一光线转换按钮将产生 0 相交。单击“设置 THREE.DoubleSide”按钮并重试 - 现在它将相交。

var renderer, scene, camera, controls, stats;

var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000,
ray1, ray2, mesh;

function populateScene(){
var cubeGeo = new THREE.BoxBufferGeometry(10, 10, 10),
cubeMat = new THREE.MeshPhongMaterial({ color: "red", transparent: true, opacity: 0.5 });
mesh = new THREE.Mesh(cubeGeo, cubeMat);
mesh.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, -1 ) );
mesh.updateMatrixWorld(true);
scene.add(mesh);

var dir = new THREE.Vector3(0.5, 0.5, 1);
dir.normalize();
ray1 = new THREE.Ray(new THREE.Vector3(), dir);

var arrow1 = new THREE.ArrowHelper(ray1.direction, ray1.origin, 20, 0x00ff00);
scene.add(arrow1);

var inverseMatrix = new THREE.Matrix4();
inverseMatrix.getInverse(mesh.matrixWorld);

ray2 = ray1.clone();
ray2.applyMatrix4(inverseMatrix);

var arrow2 = new THREE.ArrowHelper(ray2.direction, ray2.origin, 20, 0xff0000);
scene.add(arrow2);
}

function init() {
document.body.style.backgroundColor = "slateGray";

renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });

document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
scene.add(camera);

controls = new THREE.TrackballControls(camera, renderer.domElement);
controls.dynamicDampingFactor = 0.5;
controls.rotateSpeed = 3;

var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);

stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);

resize();
window.onresize = resize;

populateScene();

animate();

var rayCaster = new THREE.Raycaster();
document.getElementById("greenCast").addEventListener("click", function(){
rayCaster.ray.copy(ray1);
alert(rayCaster.intersectObject(mesh).length + " intersections!");
});
document.getElementById("redCast").addEventListener("click", function(){
rayCaster.ray.copy(ray2);
alert(rayCaster.intersectObject(mesh).length + " intersections!");
});
document.getElementById("setSide").addEventListener("click", function(){
mesh.material.side = THREE.DoubleSide;
mesh.material.needsUpdate = true;
});
}

function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
controls.handleResize();
}
}

function render() {
renderer.render(scene, camera);
}

function animate() {
requestAnimationFrame(animate);
render();
controls.update();
stats.update();
}

function threeReady() {
init();
}

(function () {
function addScript(url, callback) {
callback = callback || function () { };
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}

addScript("https://threejs.org/build/three.js", function () {
addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function () {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function () {
threeReady();
})
})
})
})();
body{
text-align: center;
}
<input id="greenCast" type="button" value="Cast Green">
<input id="redCast" type="button" value="Cast Red">
<input id="setSide" type="button" value="Set THREE.DoubleSide">

关于javascript - Three.js:Raycast 具有空的相交数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46077134/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com