它有什么问题 - 或者如何找到正确的THREE.PerspectiveCamera设置

时间:2017-03-12 00:26:34

标签: three.js raymarching

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

当前的错误结果看起来像这样(分形背景是独立渲染的,但使用相同的关键帧输入 - 最终的想法是"摄像机路径"可视化最终以相同的比例/投影结果各自的分形背景......): visualized camera path

基础是一个关键帧数组,每个关键帧代表特定相机位置/方向的modelViewMatrix,并直接用于驱动背景的顶点着色器,例如:

  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));
  }

(我的理解是"眼睛"基本上是相机的位置,而#34; 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);
    }

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

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);
},

我已经尝试了多个关于相机的内容,截图反映了输出已禁用&#34; this.projectionMatrix&#34; (见下面的代码)。

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)。不幸的是,我似乎已经设法正确映射输入&#34; modelViewMatrix&#34; (以及由着色器中的光线跟踪隐式执行的投影)等效于THREE.PerspectiveCamera设置(orientation / projectionMatrix)。

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

1 个答案:

答案 0 :(得分:0)

最后我找到了一个有效的黑客。

enter image description here 实际上问题是由两部分组成的:

1)modelViewMatrix的行 - 列 - 主要顺序:顶点着色器预期的顺序是剩余THREE.js所期望的对象。

2)Object3D-hierarchy:即场景,网格,几何,线顶点+相机:放置modelViewMatrix数据的位置,以便创建所需的结果(即与旧的血腥opengl应用程序生成的结果相同):我是我对这里发现的黑客不满意 - 但到目前为止它是唯一似乎有用的黑客:

  • 我不接触相机..它停留在0/0/0
  • 我直接移动我的&#34; line&#34; -Geometry的所有顶点相对于真实的摄像机位置(参见&#34;位置&#34;来自modelViewMatrix)
  • 然后我禁用&#34; matrixAutoUpdate&#34;在包含我的&#34;线&#34;的网格上几何并复制modelViewMatrix(其中我首先将&#34;位置&#34;归零)到&#34;矩阵&#34;字段。

BINGO ..那就行了。 (我通过旋转/移动相机或移动/旋转所涉及的任何Object3D来实现相同结果的所有尝试都失败了。)

编辑:我找到了一种比更新顶点更好的方法,至少保持网格级别的所有操作(我仍然在移动世界 - 就像旧的OpenGL应用程序本来会做的那样......)。要获得正确的平移/旋转序列,也可以使用(&#34; m&#34;仍然是原始的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);

如果有人知道一种更好的方法(一种更新相机而不必直接操纵对象矩阵),我当然有兴趣听到它。