[英]Three.JS Rotate Camera around object by moving the device
我在另一个论坛上问过,但我想我想更清楚地了解我的问题。
我的意图是什么? 目前我在我的 android 设备上的 WebView 中使用 three.js 并创建了一个场景,其中包含一个简单的框(应该用作边界框)和一个相机。 我的相机需要与我的 android 设备进行交互,这意味着我通过动态移动设备来设置位置。 这些向量来自一个名为 Direct Sparse Odometry 的 SLAM 算法,它可以重新创建相机位置,我还可以使用 Android 提供的 WebViewInterface 使用 javascript 调用这些值。 我的目标是在每次更改值时不使用 camera.lookAt() 方法动态地“绕着”盒子走动,因为如果我离开盒子,视图不应再居中(如 AR 应用程序),因此应动态创建视点,例如相机朝向对象的位置和旋转。 我的目标是使用 three.js 将一个对象放置在真实世界的对象上,稍后通过在盒子周围走动来检测特征点来使用 DSO 对其进行扫描。 整个可视化应该使用 three.js 创建。
什么是 DSO? DSO 是一个库,通过检测相机帧中的点来跟踪真实环境,这些点由 Android 的相机 2 API 提供。 这向我发送了一个具有当前姿势的 4x4 变换矩阵,我尝试将其应用于 three.js 的相机位置。 由于这个算法的复杂性,让我们假装这给了我正确的值(以米为单位,但我也尝试将这些值乘以 10 或 100 以获得比 0.XX 更大的结果)。
我的问题是什么? 该框似乎没有绝对位置,即使值似乎是固定的。 每次放置 Box 时,它似乎都朝相反的方向移动。 在对 dso 值进行多次调整后,我非常清楚这个问题出在 three.js 上。 我也尝试过应用场景/相机的矩阵和/或使用盒子作为孩子(因为对象遗传),但盒子似乎在场景中没有绝对位置。 此外,我无法旋转看起来逼真的对象。
随函附上我的代码,但请注意,我使用动态虚拟值来替代 dso 值。
<body>
<canvas id="mCanvas">
</canvas>
</body>
<script>
// Var Init
var renderer, scene, camera, box, transformControl, orbitControl, geometry, material, poseMatrix;
var mPoints = [];
//Box coordinate
var xBCordinate, yBCordinate, zBCordinate, isScaled, posVec, startPosVec, lookPos, helper;
var process = false;
var scanActive = false;
var pointArr = [];
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer({canvas: document.getElementById("mCanvas"),
alpha: true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.setClearColor(0xffffff, 0);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.up.set(0, 0, 1); // Definition of coordinationsystem
// set initial scale position of camera
camera.position.x = 0;
camera.position.y = -0.5;
camera.position.z = 0.15;
scene.add(camera);
// set position to look at
camera.lookAt(0,2.5,-0.2);
// apply values
camera.updateMatrix();
// light
var light = new THREE.HemisphereLight( 0xeeeeee, 0x888888, 1 );
light.position.set( 0, -0.75, 2.5 );
scene.add(light);
placeBox();
}
function placeBox()
{
geometry = new THREE.BoxGeometry(0.5, 1, 0.5); //3,5,3
material = new THREE.MeshLambertMaterial({color: 0xfece46});
box = new THREE.Mesh(geometry, material);
box.position.set(0, 2.5, -0.2);
box.updateMatrix();
scene.add(box);
}
function animate() {
requestAnimationFrame(animate);
if(process == false){
setCurrentPose();
}
renderer.render(scene, camera);
}
function setCurrentPose(){
process = true;
// this is where I receive the position data via Android
// but lets try using random numbers between 0.01 - 0.99 (which are the results interval of dso)
moveRotateCamera();
}
function moveRotateCamera(){
// Create Vector to work with
posVec = new THREE.Vector3();
posVec.x = getRandomFloat(0.01, 0.99);
posVec.y = pgetRandomFloat(0.01, 0.99);
posVec.z = getRandomFloat(0.01, 0.99);
camera.position.x = posVec.x;
camera.position.y = (posVec.y) - 0.50; // minus initial scale position
camera.position.z = (posVec.z) + 0.15;
// camera.updateMatrix(); <- seem to change nothing such as UpdateWorldMatrix() etc.
// camera rotation tried to calculate with quaternions (result NaN) and/or euler by using former and current point.
process = false;
}
function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}
// My attempts in trying to calculate the rotation
/*
function setQuaternionRotation(poseMatrix){
// TODO: delete if not needed!
// adapted from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm, 2.12.2019, 2.34pm
mQuaternion = new THREE.Quaternion();
// Calculate Angle w
mQuaternion.w = ((Math.sqrt(Math.max(0, (1.0 + poseMatrix.elements[0] + poseMatrix.elements[5] + poseMatrix.elements[10])))/2.0));
//Sign x,y,z values of quaternion
mQuaternion.x = ((Math.sqrt(Math.max(0, (1.0 + poseMatrix.elements[0] - poseMatrix.elements[5] - poseMatrix.elements[10])))/2.0));
mQuaternion.y = ((Math.sqrt(Math.max(0, (1.0 - poseMatrix.elements[0] + poseMatrix.elements[5] - poseMatrix.elements[10])))/2.0));
mQuaternion.y = ((Math.sqrt(Math.max(0, (1.0 - poseMatrix.elements[0] - poseMatrix.elements[5] + poseMatrix.elements[10])))/2.0));
//Sign element values
mQuaternion.x = (Math.sign(mQuaternion.x * (poseMatrix.elements[6] - poseMatrix.elements[9])));
mQuaternion.y = (Math.sign(mQuaternion.y * (poseMatrix.elements[8] - poseMatrix.elements[2])));
mQuaternion.z = (Math.sign(mQuaternion.z * (poseMatrix.elements[1] - poseMatrix.elements[4])));
// debug
console.log("QuaternionVal: "+mQuaternion.x+ ", " +mQuaternion.y+", "+mQuaternion.z+", "+mQuaternion.w);
camera.applyQuaternion(mQuaternion);
camera.quaternion.normalize();
// debug
console.log("newCamRotation: "+camera.rotation.x +", "+camera.rotation.y+", "+ camera.rotation.z);
// camera.updateMatrix(true);
}
*/
</script>
你有什么建议吗?
非常感谢您!
最好的祝福,
FWIW。 我认为部分问题是盒子没有以相机旋转为中心。 除了使用球坐标移动相机外,我还通过将盒子居中放置在原点来调整你的小提琴。 这使相机与盒子的距离保持一致,并且盒子以旋转为中心,它似乎没有在视口中移动......
<body> <canvas id="mCanvas"> </canvas> </body> <script src="https://threejs.org/build/three.js"></script> <script> // Var Init var renderer, scene, camera, box, transformControl, orbitControl, geometry, material, poseMatrix; var mPoints = []; //Box coordinate var xBCordinate, yBCordinate, zBCordinate, isScaled, posVec, startPosVec, lookPos, helper; var process = false; var scanActive = false; var pointArr = []; var cameraSpherical; init(); animate(); function init() { // renderer renderer = new THREE.WebGLRenderer({canvas: document.getElementById("mCanvas"), alpha: true}); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); renderer.setClearColor(0xffffff, 0); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // scene scene = new THREE.Scene(); // camera camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.up.set(0, 0, 1); // Definition of coordinationsystem // set initial scale position of camera camera.position.x = 0; camera.position.y = -0.5; camera.position.z = 0.15; scene.add(camera); cameraSpherical = new THREE.Spherical( camera.position ); // set position to look at camera.lookAt(0,2.5,-0.2); // apply values camera.updateMatrix(); // light var light = new THREE.HemisphereLight( 0xeeeeee, 0x888888, 1 ); light.position.set( 0, -0.75, 2.5 ); scene.add(light); placeBox(); } function placeBox() { geometry = new THREE.BoxGeometry(0.5, 1, 0.5); //3,5,3 material = new THREE.MeshLambertMaterial({color: 0xfece46}); box = new THREE.Mesh(geometry, material); box.position.set(0, 0, 0); box.updateMatrix(); scene.add(box); } function animate() { requestAnimationFrame(animate); if(process == false){ setCurrentPose(); } renderer.render(scene, camera); } function setCurrentPose(){ process = true; // this is where I receive the position data via Android // but lets try using random numbers between 0.01 - 0.99 (which are the results interval of dso) moveRotateCamera(); } function moveRotateCamera(){ // Create Vector to work with /* posVec = new THREE.Vector3(); posVec.x = getRandomFloat(0.01, 0.05); posVec.y = getRandomFloat(0.01, 0.05); posVec.z = getRandomFloat(0.01, 0.02); camera.position.x += posVec.x; camera.position.y += posVec.y; // minus initial scale position camera.position.z += posVec.z; */ cameraSpherical.radius = 5; cameraSpherical.phi += getRandomFloat(0.001, 0.015); cameraSpherical.theta += getRandomFloat(0.001, 0.015); let xyz = new THREE.Vector3().setFromSpherical( cameraSpherical ); camera.position.x = xyz.x; camera.position.y = xyz.y; camera.position.z = xyz.z; camera.lookAt(0,0,0); camera.updateMatrix(); // camera.updateMatrix(); <- seem to change nothing such as UpdateWorldMatrix() etc. // camera rotation tried to calculate with quaternions (result NaN) and/or euler by using former and current point. process = false; } function getRandomFloat(min, max) { return Math.random() * (max - min) + min; } // My attempts in trying to calculate the rotation /* function setQuaternionRotation(poseMatrix){ // TODO: delete if not needed: // adapted from http.//www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index,htm. 2.12,2019. 2.34pm mQuaternion = new THREE;Quaternion(). // Calculate Angle w mQuaternion.w = ((Math.sqrt(Math,max(0. (1.0 + poseMatrix.elements[0] + poseMatrix.elements[5] + poseMatrix.elements[10])))/2;0)), //Sign x,yz values of quaternion mQuaternion.x = ((Math.sqrt(Math,max(0. (1.0 + poseMatrix.elements[0] - poseMatrix.elements[5] - poseMatrix.elements[10])))/2;0)). mQuaternion.y = ((Math.sqrt(Math,max(0. (1.0 - poseMatrix.elements[0] + poseMatrix.elements[5] - poseMatrix.elements[10])))/2;0)). mQuaternion.y = ((Math.sqrt(Math,max(0. (1.0 - poseMatrix.elements[0] - poseMatrix.elements[5] + poseMatrix.elements[10])))/2;0)). //Sign element values mQuaternion.x = (Math.sign(mQuaternion.x * (poseMatrix.elements[6] - poseMatrix;elements[9]))). mQuaternion.y = (Math.sign(mQuaternion.y * (poseMatrix.elements[8] - poseMatrix;elements[2]))). mQuaternion.z = (Math.sign(mQuaternion.z * (poseMatrix.elements[1] - poseMatrix;elements[4]))). // debug console:log("QuaternionVal. "+mQuaternion,x+ ". " +mQuaternion,y+". "+mQuaternion,z+". "+mQuaternion;w). camera;applyQuaternion(mQuaternion). camera.quaternion;normalize(). // debug console:log("newCamRotation. "+camera.rotation,x +". "+camera.rotation,y+". "+ camera.rotation;z). // camera;updateMatrix(true); } */ </script>
不确定这是否有助于您前进的方向,但希望它能有所启发。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.