在 WebVR / WebXR 中锁定相机位置

Locking the camera position in WebVR / WebXR

使用 three.js 将相机位置锁定到 WebVR/WebXR 中的单个点的最佳方法是什么?

用户仍然需要能够旋转他们的头部,但他们的头部移动不应改变相机的位置 (x,y,z)。

您可以在每一帧将相机的位置 xyz 值设置为零以将其锁定到位。但是,请注意,许多用户在观看实际 3D 场景时会感到不舒服。它基本上只对源 material 不支持空间移动的 180/360 度视频查看器有用,但即使在这种情况下,如果有任何浮动 UI 元素进行交互,你也应该使用头部位置.

查看更新以获得简单的解决方案

这个能力被误导了,而且明确地removed from the WebXR spec

他们的位置数据示例的“琐碎”剥离在他们的 360-photos.html example, and it's skyboxMaterial class 的顶点着色器中,该着色器被他们复杂的渲染器吃掉了。

具体来说:

get vertexSource() {
    return `
    uniform int EYE_INDEX;
    uniform vec4 texCoordScaleOffset[2];
    attribute vec3 POSITION;
    attribute vec2 TEXCOORD_0;
    varying vec2 vTexCoord;

    vec4 vertex_main(mat4 proj, mat4 view, mat4 model) {
      vec4 scaleOffset = texCoordScaleOffset[EYE_INDEX];
      vTexCoord = (TEXCOORD_0 * scaleOffset.xy) + scaleOffset.zw;
      // Drop the translation portion of the view matrix
      view[3].xyz = vec3(0.0, 0.0, 0.0);
      vec4 out_vec = proj * view * model * vec4(POSITION, 1.0);

      // Returning the W component for both Z and W forces the geometry depth to
      // the far plane. When combined with a depth func of LEQUAL this makes the
      // sky write to any depth fragment that has not been written to yet.
      return out_vec.xyww;
    }`;
  }

美好而平凡.../s

希望这有帮助,我目前正在解决同样的问题,if/when我克服了它,我会更新这个答案。

更新 2: 正如所承诺的,而不是修改每个着色器以支持此功能。在处理每个 xrPose 的视图时执行以下操作:

    //NOTE: Uses the gl-matrix.js library, albeit slightly modified
    //to add vec3.multiplyBy. Which is used to multiply a vector
    //by a single value.
    
    let dist;
    let poseMaxDist = 0.4; //0.4M or 1.2ft
    
    let calculatedViewPos;
    let viewRotAsQuat;
    let vector;

    let origin = vec3.create();
    let framePose = vec3.create();
    let poseToBounds = vec3.create();
    let elasticTransformMatrix = mat4.create();

    let view = pose.views[viewIdx];
    //If positionDisabled, negate headset position changes, while maintaining
    //eye offset which allows for limited translation as users head does
    //move laterally when looking around.
    if(_positionDisabled){
        //DOMPoint to vec3 easier calculations.
        framePose = vec3.fromValues(
            pose.transform.position.x,
            pose.transform.position.y,
            pose.transform.position.z);

        //Distance from the origin
        dist = vec3.distance(origin, framePose);

        if(dist >= poseMaxDist){
            //calculation 'origin' == A
            //framePose == B
            let AB = vec3.create();
            let AC = vec3.create();
            let C = vec3.create();
            let CB = vec3.create();

            //Vector from origin to pose
            vec3.subtract(AB, framePose, origin);

            //Unit vector from origin to pose
            vec3.normalize(AB, AB);

            //Max allowed vector from origin to pose
            vec3.multiplyBy(AC, AB, poseMaxDist);

            //Limit point from origin to pose using max allowed vector  
            vec3.add(C, origin, AC);
      
            //vector from pose to limit point, use to shift view
            vec3.subtract(poseToBounds, C, framePose);

            //vector from limit point to pose, use to shift origin
            vec3.subtract(CB, framePose, C);

            //Shift calculation 'origin'
            vec3.add(origin, origin, CB);

            //adjust view matrix using the caluclated origin,
            //and the vector from the pose to the limit point.
            calculatedViewPos = vec4.fromValues(
                view.transform.position.x - origin[0] + poseToBounds[0],
                view.transform.position.y - origin[1] + poseToBounds[1],
                view.transform.position.z - origin[2] + poseToBounds[2],
                view.transform.position.w);

        }else{
            //adjust view matrix using the caluclated origin
            calculatedViewPos = vec4.fromValues(
                view.transform.position.x - origin[0],
                view.transform.position.y - origin[1],
                view.transform.position.z - origin[2],
                view.transform.position.w);
        }

        //Changing the DOMPoint to a quat for easier matrix calculation.
        viewRotAsQuat = quat.fromValues(
            view.transform.orientation.x,
            view.transform.orientation.y,
            view.transform.orientation.z,
            view.transform.orientation.w
        );

        mat4.fromRotationTranslation(elasticTransformMatrix, viewRotAsQuat, calculatedViewPos)

        mat4.invert(elasticTransformMatrix, elasticTransformMatrix);
            
        mat4.multiply(modelViewMatrix, elasticTransformMatrix, entity.transformMatrix);

    }else{
        mat4.multiply(modelViewMatrix, view.transform.inverse.matrix, entity.transformMatrix);
    }

仅供参考:您需要优化变量的使用以避免多余的分配。我留下它们是为了更好地可视化每个计算所使用的内容。