【问题标题】:Three.JS Rotate Camera around object by moving the device三.JS通过移动设备围绕物体旋转相机
【发布时间】:2020-05-10 21:16:51
【问题描述】:

我在另一个论坛上问过,但我想我想更清楚地了解我的问题。

我的意图是什么? 目前我在我的android设备上的WebView中使用three.js并创建了一个场景,其中包含一个简单的框(应该用作边界框)和一个相机。我的相机需要与我的 android 设备交互,这意味着我通过动态移动设备来设置位置。这些向量来自一个名为 Direct Sparse Odometry 的 SLAM 算法,该算法重新创建了相机位置,我还可以使用 Android 提供的 WebViewInterface 使用 javascript 调用这些值。我的目标是在每次更改值时不使用 camera.lookAt()-Method 动态地“走动”盒子,因为如果我离开盒子,视图不应该再居中(就像 AR 应用程序一样) ),因此应动态创建视点,例如相机朝向对象的位置和旋转。我的目标是使用 three.js 将对象放置在真实世界对象上,以便稍后使用 DSO 扫描它,方法是在盒子周围走动以检测特征点。整个可视化应该用three.js创建。

什么是 DSO? DSO 是一个通过检测相机帧中的点来跟踪真实环境的库,由 Android 的相机 2 API 提供。这会向我发送一个具有当前姿势的 4x4 变换矩阵,我尝试将其应用于 three.js 的相机位置。由于该算法的复杂性,假设这给了我正确的值(以米为单位,但我也尝试将这些值乘以 10 或 100 以获得大于 0.XX 的结果)。

我的问题是什么? 即使值似乎是固定的,该框似乎也没有绝对位置。每次放置 Box 时,它似乎都会朝相反的方向移动。在对 dso 值进行了多次调整之后,我很清楚这是三个.js 发生的问题。 我还尝试应用场景/相机的矩阵和/或将盒子用作子对象(因为对象遗传),但盒子似乎在场景中没有绝对位置。我也无法旋转看起来很真实的对象。

附上,你会找到我的代码,但是 p 请注意,我使用动态虚拟值来替代 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>

Link to my Fiddle

你有什么建议吗?

非常感谢您!

最好的问候,

【问题讨论】:

    标签: javascript android three.js augmented-reality


    【解决方案1】:

    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,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>

    不确定这是否有助于您朝着前进的方向前进,但希望它能提供一些启示。

    【讨论】:

    • 哇,非常感谢您的回答!这看起来正是我希望它的行为方式。即使我必须通过移动设备来管理旋转,我也会尝试一下。可悲的是,DSO 正在使用与 three.js 不同的协调系统(-y 轴向上,z 轴也反转。)所以旋转的事情似乎更复杂。
    猜你喜欢
    • 2014-01-27
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 2013-03-16
    相关资源
    最近更新 更多