Three.JS通过移动设备围绕对象旋转相机

问题描述 投票:0回答:1

我曾在另一个论坛上提问,但我想我对自己的问题更加清楚。

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

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

我有什么问题?即使值似乎是固定的,该框似乎也没有绝对位置。每次放置盒子时,它似乎都朝相反的方向移动。在对dso值进行了许多调整之后,我非常清楚地发现问题出在three.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个回答
0
投票

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>

不确定是否对您的前进方向有帮助,但希望它能为您提供一些启示。

© www.soinside.com 2019 - 2024. All rights reserved.