Three.js (+ React) 基于位置的 AR - 相机配置?
Location based AR with Three.js (+ React) - camera configuration?
我想使用基于位置的标记来增强固定网络摄像头的图像。这将添加到已经在其他部分使用 three.js(通过 react-three-fiber)的现有 React 应用程序,因此这些技术将被重用。
虽然计算标记(已知位置)相对于相机(已知位置)的位置很容易,但我正在为相机的配置而苦苦挣扎为了在 "real" 对象和 AR 标记之间获得良好的视觉匹配。
我创建了一个 codesandbox with an artificial example 来说明挑战。
这是我配置相机的尝试:
const camera = {
position: [0, 1.5, 0],
fov: 85,
near: 0.005,
far: 1000
};
const bearing = 109; // degrees
<Canvas camera={camera}>
<Scene bearing={bearing}/>
</Canvas>
在场景组件的下方,我根据网络摄像头的方位旋转摄像头,如下所示:
...
const rotation = { x: 0, y: bearing * -1, z: 0 };
camera.rotation.x = (rotation.x * Math.PI) / 180;
camera.rotation.y = (rotation.y * Math.PI) / 180;
camera.rotation.z = (rotation.z * Math.PI) / 180;
...
任何 tips/thoughts 关于如何配置相机以很好地匹配 three.js 盒子和现实生活中的物体?
作为一名 GIS 开发者,我可以就这个问题给出一些提示:
- 大多数 3D 图形 API(例如 OpenGL/WebGL,Three.js 是其包装器)期望所有坐标都在需要的线性 Cartesian space, but here the input data (the markers and camera locations) are given in Latitude and Longitude (degrees as floating point numbers). These are Spherical 坐标中先变形
- 因此,要将我们的球面经纬度坐标转换为线性坐标 space,我们需要首先决定我们要在哪个坐标系中工作。存在许多坐标参考系用于各种目的,但为了为简单起见,我们将只使用所谓的 Web Mercator Projection (defined by the identifier code EPSG:3857) 作为我们的目标参考系统。这会将我们的值从度数转换为米数。
- 有几种方法可以实现这种转换,例如使用名为 Proj4js or some helper functions of web mapping libraries such as Leaflet or OpenLayers 的 JS 库。
- 示例:
var xy = proj4( "EPSG:4326", "EPSG:3857", [ lon, lat ] );
- 一旦我们有了以米为单位的坐标,重要的是将标记位置与相机位置相关联。否则我们会得到非常大的坐标值。所以我的建议是将相机放在场景原点 (0, 0, 0) 并通过增量向量定位标记。
- 示例:
var position = new THREE.Vector3( camXY[ 0 ] - markerXY[ 0 ], 0.0, markerXY[ 1 ] - camXY[ 1 ] );
- 然后您可以根据给定的航向和俯仰旋转相机,如果视野正确,它应该或多或少对齐。
我想使用基于位置的标记来增强固定网络摄像头的图像。这将添加到已经在其他部分使用 three.js(通过 react-three-fiber)的现有 React 应用程序,因此这些技术将被重用。
虽然计算标记(已知位置)相对于相机(已知位置)的位置很容易,但我正在为相机的配置而苦苦挣扎为了在 "real" 对象和 AR 标记之间获得良好的视觉匹配。
我创建了一个 codesandbox with an artificial example 来说明挑战。
这是我配置相机的尝试:
const camera = {
position: [0, 1.5, 0],
fov: 85,
near: 0.005,
far: 1000
};
const bearing = 109; // degrees
<Canvas camera={camera}>
<Scene bearing={bearing}/>
</Canvas>
在场景组件的下方,我根据网络摄像头的方位旋转摄像头,如下所示:
...
const rotation = { x: 0, y: bearing * -1, z: 0 };
camera.rotation.x = (rotation.x * Math.PI) / 180;
camera.rotation.y = (rotation.y * Math.PI) / 180;
camera.rotation.z = (rotation.z * Math.PI) / 180;
...
任何 tips/thoughts 关于如何配置相机以很好地匹配 three.js 盒子和现实生活中的物体?
作为一名 GIS 开发者,我可以就这个问题给出一些提示:
- 大多数 3D 图形 API(例如 OpenGL/WebGL,Three.js 是其包装器)期望所有坐标都在需要的线性 Cartesian space, but here the input data (the markers and camera locations) are given in Latitude and Longitude (degrees as floating point numbers). These are Spherical 坐标中先变形
- 因此,要将我们的球面经纬度坐标转换为线性坐标 space,我们需要首先决定我们要在哪个坐标系中工作。存在许多坐标参考系用于各种目的,但为了为简单起见,我们将只使用所谓的 Web Mercator Projection (defined by the identifier code EPSG:3857) 作为我们的目标参考系统。这会将我们的值从度数转换为米数。
- 有几种方法可以实现这种转换,例如使用名为 Proj4js or some helper functions of web mapping libraries such as Leaflet or OpenLayers 的 JS 库。
- 示例:
var xy = proj4( "EPSG:4326", "EPSG:3857", [ lon, lat ] );
- 一旦我们有了以米为单位的坐标,重要的是将标记位置与相机位置相关联。否则我们会得到非常大的坐标值。所以我的建议是将相机放在场景原点 (0, 0, 0) 并通过增量向量定位标记。
- 示例:
var position = new THREE.Vector3( camXY[ 0 ] - markerXY[ 0 ], 0.0, markerXY[ 1 ] - camXY[ 1 ] );
- 然后您可以根据给定的航向和俯仰旋转相机,如果视野正确,它应该或多或少对齐。