繁体   English   中英

三.JS通过移动设备围绕物体旋转相机

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM