【问题标题】:what's wrong with it - or how to find correct THREE.PerspectiveCamera settings有什么问题 - 或如何找到正确的 THREE.PerspectiveCamera 设置
【发布时间】:2017-03-12 00:26:33
【问题描述】:

我有一个简单的 THREE.Scene,其中主要内容是一个 THREE.Line 网格,它可视化相机将遵循的一些脚本动画的基于关键帧的路径。然后有一个基于 THREE.SphereGeometry 的网格,始终重新定位到当前相机位置。

当前错误的结果如下所示(分形背景是独立渲染的,但使用相同的关键帧输入 - 最终的想法是“相机路径”可视化最终以与相应分形背景相同的比例/投影结束。 ..):

base 是一个关键帧数组,每个关键帧代表特定相机位置/方向的 modelViewMatrix,并直接用于驱动背景的 vertexshader,例如:

  varying vec3 eye, dir;
  void main()   {
    gl_Position = vec4(position, 1.0);
    eye = vec3(modelViewMatrix[3]);
    dir = vec3(modelViewMatrix * vec4(position.x , position.y , 1, 0));
  }

(据我的理解,“eye”基本上是相机位置,而“dir”反映了相机的方向,并且在光线行进期间使用它的方式隐含地导致透视投影)

各自的网格对象是这样创建的:

visualizeCameraPath: function(scene) {
        // debug: visualize the camera path
        var n= this.getNumberOfKeyFrames();

        var material = new THREE.LineBasicMaterial({
            color: 0xffffff
        });

        var geometry = new THREE.Geometry();
        for (var i= 0; i<n; i++) {
            var m= this.getKeyFrameMatrix(true, i);

            var pos= new THREE.Vector3();
            var q= new THREE.Quaternion();
            var scale= new THREE.Vector3();
            m.decompose(pos,q,scale);

            geometry.vertices.push( new THREE.Vector3( pos.x, pos.y, pos.z ));          
        }

        this.camPath = new THREE.Line( geometry, material );
        this.camPath.frustumCulled = false; // Avoid getting clipped - does not seem to help one little bit
        scene.add( this.camPath );


        var radius= 0.04;
        var g = new THREE.SphereGeometry(radius, 10, 10, 0, Math.PI * 2, 0, Math.PI * 2);

        this.marker = new THREE.Mesh(g, new THREE.MeshNormalMaterial());
        scene.add(this.marker);
    }

为了播放动画,我像这样更新相机和标记位置(我想我如何直接在“shadowCamera”上使用输入矩阵“m”已经是错误的了 - 尽管我认为它包含正确的位置):

syncShadowCamera(m) {
    var pos= new THREE.Vector3();
    var q= new THREE.Quaternion();
    var scale= new THREE.Vector3();
    m.decompose(pos,q,scale);

    this.applyMatrix(m, this.shadowCamera);     // also sets camera position to "pos"


    // highlight current camera-position on the camera-path-line        
    if (this.marker != null) this.marker.position.set(pos.x, pos.y, pos.z);

},

applyMatrix: function(m, targetObj3d) {
    var pos= new THREE.Vector3();
    var q= new THREE.Quaternion();
    var scale= new THREE.Vector3();
    m.decompose(pos,q,scale);

    targetObj3d.position.set(pos.x, pos.y, pos.z);
    targetObj3d.quaternion.set(q.x, q.y, q.z, q.w);
    targetObj3d.scale= scale;

    targetObj3d.updateMatrix(); // this.matrix.compose( this.position, this.quaternion, this.scale );   
    targetObj3d.updateMatrixWorld(true);
},

我在相机方面尝试了多种方法,屏幕截图反映了禁用“this.projectionMatrix”的输出(参见下面的代码)。

createShadowCamera: function() {        
    var speed = 0.00039507;
    var z_near = Math.abs(speed);
    var z_far = speed * 65535.0;
    var fH = Math.tan( this.FOV_Y * Math.PI / 360.0 ) * z_near;
    var fW = Math.tan( this.FOV_X * Math.PI / 360.0 ) * z_near;
    // orig opengl used: glFrustum(-fW, fW, -fH, fH, z_near, z_far);

    var camera= new THREE.PerspectiveCamera();          
    camera.updateProjectionMatrix =  function() {
    //  this.projectionMatrix.makePerspective( -fW, fW, fH, -fH, z_near, z_far );
        this.projectionMatrix= new THREE.Matrix4();     // hack: fallback to no projection
    };
    camera.updateProjectionMatrix();
    return camera;
},

我最初的尝试是使用与分形背景的 opengl 着色器相同的设置(参见上面的 glFrustum)。不幸的是,我似乎还没有成功地将输入“modelViewMatrix”(以及由着色器中的光线行进隐式执行的投影)映射到等效的 THREE.PerspectiveCamera 设置(orientation/projectionMatrix)。

这里有没有矩阵计算专家,知道如何获得正确的变换?

【问题讨论】:

    标签: three.js raymarching


    【解决方案1】:

    我终于找到了一种可行的方法。

    实际上问题由两部分组成:

    1) modelViewMatrix 的行与列主要顺序:顶点着色器所期望的顺序与其余 THREE.js 所期望的顺序相反..

    2) Object3D-hierarchy:即场景、网格、几何、线顶点 + 相机:将 modelViewMatrix 数据放在哪里,以便它创建所需的结果(即与旧的血腥 opengl 应用程序产生的结果相同):我是对我在这里找到的 hack 不满意 - 但到目前为止,它似乎是唯一可行的:

    • 我没有触摸相机。它停留在 0/0/0
    • 我直接移动我的“线”的所有顶点 - 几何相对于真实相机位置(参见 modelViewMatrix 中的“位置”)
    • 然后我在包含我的“线”几何图形的网格上禁用“matrixAutoUpdate”,并将 modelViewMatrix(我首先在其中将“位置”归零)复制到“矩阵”字段中。

    BINGO.. 然后就可以了。 (我通过旋转/移动相机或移动/旋转任何涉及的 Object3D 来获得相同结果的所有尝试都失败了......)

    编辑:我找到了一种比更新顶点更好的方法,并且至少将所有操作保持在网格级别(我仍在移动世界 - 就像旧的 OpenGL 应用程序所做的那样......)。要获得正确的平移/旋转顺序,还可以使用(“m”仍然是原始的 OpenGL modelViewMatrix - 具有 0/0/0 位置信息):

    var t= new THREE.Matrix4().makeTranslation(-cameraPos.x, -cameraPos.y, -cameraPos.z);
    t.premultiply ( m );
    
    obj3d.matrixAutoUpdate=false;
    obj3d.matrix.copy(t);
    

    如果有人知道一种更好的方法(即在无需直接操作对象矩阵的情况下更新相机),我当然很想听听。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多