gpt4 book ai didi

javascript - ThreeJS raycaster 关闭,相机和对象的坐标大于 1000000

转载 作者:行者123 更新时间:2023-11-27 23:15:16 27 4
gpt4 key购买 nike

我已经设置了一个光线转换器,以便从我的 Canvas 中执行对象选择。

它适用于camera.position.x和object.position.x的小值,但我的问题是当camera.position.x是一个很大的数字时,它不能很好地工作,在我的例子中是10 000 000 !

实际上,当鼠标指针位于对象右侧整个对象长度时,我会得到 react !我的猜测是,使用如此巨大的数字进行计算会造成这种失真,但无法确定。

                var raycaster = new THREE.Raycaster();
var vector = new THREE.Vector2();

camera.position.x = 11000000;
object.position.x = 11000000;

function onMouseMove( event ) {

vector.x = ( (event.clientX - renderer.domElement.offsetLeft) / renderer.domElement.clientWidth ) * 2 - 1;
vector.y = - ( (event.clientY - renderer.domElement.offsetTop) / renderer.domElement.clientHeight ) * 2 + 1;

raycaster.setFromCamera(vector, camera);

var intersects = raycaster.intersectObjects(scene.children, true);

if(intersects.length>0){
alert("INTERSECTION " + intersects[0].object.userData.name);
}

}canvas.addEventListener('mousemove', onMouseMove, false);

我省略了向场景添加对象和其他一些内容,以便帖子不会太长。例如,当 camera.position.x 和 object.position.x 设置为小于 1 000 000 的某个值时,此方法有效,尽管即使这样也会出现一些失真。

编辑 1

                var scene = new THREE.Scene();

var canvas = document.getElementById('canvas');

var height = canvas.clientHeight;
var width = canvas.clientWidth;

var camera = new THREE.PerspectiveCamera(70, width/height, 1, 1000);

var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
canvas.appendChild(renderer.domElement);

此外,这是我的 html 的一部分,其中“canvas”div 所在的位置,我还尝试了 canvas.offsetLef 而不是 renderer.domElement.offsetLeft 等。

编辑2

<div id="content" ng-controller="ShippingCtrl">

<div id="left_panel">

</div>

<div id="canvas" style="width:900px; height:600px; border:1px solid white">

</div>

<div id="right_pannel">

</div></div>

最佳答案

由于怀疑浮点舍入错误,我在 Matlab 中进行了非投影,以了解不同的实现如何处理它。我从 codepen 中的相机矩阵开始示例

相机投影

 4.951969385147095e-01                         0                         0                         0
0 1.428148031234741e+00 0 0
0 0 -1.001000523567200e+00 -1.000000000000000e+00
0 0 -2.001000404357910e+00 0

相机世界

       1           0           0           0
0 1 0 0
0 0 1 0
4000000 2000000 1000800 1

通过 javascript 通过 Threejs 计算相机投影矩阵的逆

逆相机投影矩阵

    2.0193986892700195                          0                           0                       0  
0 0.700207531452179 0 0
0 0 0 -0.499750018119812
0 0 -1 0.5002500414848328

Matlab计算的相机投影矩阵的逆

 2.019398591193624e+00                         0                         0                         0
0 7.002075262012054e-01 0 0
0 0 0 -4.997500239490878e-01
0 0 -1.000000000000000e+00 5.002500356257574e-01

将矩阵相乘(逆相机投影矩阵 * 相机世界矩阵)

在三个js中

    2.0193986892700195                          0                           0                       0  
0 0.700207531452179 0 0
-1999000.125 -999500.0625 -500149.8125 -0.499750018119812
2001000.125 1000500.0625 500649.25 0.5002500414848328

Matlab中同样的计算

camProjectionInv*camWorld

 2.019398591193624e+00                         0                         0                         0
0 7.002075262012054e-01 0 0
-1.999000095796351e+06 -9.995000478981755e+05 -5.001498239682470e+05 -4.997500239490878e-01
2.001000142503030e+06 1.000500071251515e+06 5.006492356542581e+05 5.002500356257574e-01

为简单起见,使用屏幕中心的点 [0,0,0.5,1.0] 并乘除 w

来自三人

     3599999.783405974,        1799999.891702987,        900796.0640709081

来自Matlab

 4.000000000000000e+06     2.000000000000000e+06     1.000796005991391e+06     1.000000000000000e+00

存在舍入误差的累积。我不太明白 C++ (Matlab) 和 JavaScript (thirdjs) 在处理 IEEE 标准 754 64 位 float 方面有何不同。

对于我的使用来说,保留数据的世界坐标系非常重要,因此为了克服拾取/浮点问题,我只需使用其位置将翻译放置在顶部组节点上,将场景翻译回原点属性并将相机设置为查看该位置。我将相机和 View 信息与场景分开,以便我可以对同一数据实现多个 View 。因此,在我的场景对象上,我实现了

center(): THREE.Vector3 {
let datacenter = this.dataCenter();
let center = datacenter.add(this.sceneLocation);
return center;
}

worldBBox(): THREE.Box3 {
return new THREE.Box3().setFromObject(this.pathsGroup);
}

protected updateScenePosition(): void {
this.sceneLocation = this.dataCenter().negate();
this.scene.position.set(this.sceneLocation.x, this.sceneLocation.y, this.sceneLocation.z);
this.scene.matrixWorldNeedsUpdate=true;
this.scene.updateMatrixWorld(true);
}

protected dataCenter(): THREE.Vector3 {
let dataBBox = this.dataBoundingBox();
let center = dataBBox.max.clone();
center.sub(dataBBox.min);
center.divideScalar(2.0);
center.add(dataBBox.min);
return center;
}

protected dataBoundingBox(): THREE.Box3 {
let bbox = new THREE.Box3().setFromObject(this.pathsGroup);
this.pathsGroup.worldToLocal(bbox.min);
this.pathsGroup.worldToLocal(bbox.max);

return bbox;
}

当一个对象被添加到场景中时,我调用 updateScenePosition,尽管这可能不是绝对必要的,因为新对象可能位于大致相同的区域设置中,并且可见错误可能已经用初始对象进行了补偿。

然后相机更新

centerView():无效{

    this.look = this.bigscene.center().clone();

this.camera.position.set(this.look.x, this.look.y, this.look.z+3600);

this.camera.lookAt(this.look);
this.controls.target.set(this.look.x, this.look.y, this.look.z);

this.light.position.copy(this.camera.position); //headlight
}

关于javascript - ThreeJS raycaster 关闭,相机和对象的坐标大于 1000000,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35873655/

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