使用 CSS3DRenderer 和 jsartoolkit 将 iframe 渲染到 AR 标记上



我希望能够在增强现实标记上覆盖html iframe,但是我无法让CSS3DRenderer显示与WebGLRenderer相同的结果,我不确定我哪里出错了。

WebGL渲染完美,网格跟随标记,这都是魔术,然而CSS3DRenderer将iframe居中在视频的中间,反转和未缩放,并且它以相反的方向旋转。

感谢 three.js 和 artoolkit,这里有一些使用视频输入和两个渲染器的测试代码。

new Promise(function(resolve,reject) {
    var source = document.createElement('video');
    source.autoplay = true;
    source.playsinline = true;
    source.controls = false;
    source.loop = true;
    source.onplay = function(event) {
        resolve(source);
    }
    source.src = 'data/output_4.ogg';
    document.body.appendChild(source);
}).then(function(source) {
    var scene = new THREE.Scene();
    var camera = new THREE.Camera();
    camera.matrixAutoUpdate = false;
    scene.add(camera);
    var material = new THREE.MeshNormalMaterial({
        transparent : true,
        opacity : 0.5,
        side : THREE.DoubleSide
    });
    var geometry = new THREE.PlaneGeometry(1,1);
    var mesh = new THREE.Mesh(geometry,material);
    // mesh.matrixAutoUpdate = false;
    scene.add(mesh);
    var renderer = new THREE.WebGLRenderer({
        antialias : true,
        alpha : true
    });
    renderer.setSize(source.videoWidth,source.videoHeight);
    renderer.setClearColor(new THREE.Color('lightgrey'),0);
    document.body.appendChild(renderer.domElement);
    /*
    cssRenderer
    */
    var cssRenderer = new THREE.CSS3DRenderer();
    cssRenderer.setSize(source.videoWidth,source.videoHeight);
    var cssScene = new THREE.Scene();
    var iframe = document.createElement("iframe");
    iframe.src = "/data/index.html";
    iframe.style.background = "rgb(0,0,0)";
    var iframe3D = new THREE.CSS3DObject(iframe);
    // iframe3D.matrixAutoUpdate = false;
    cssScene.add(iframe3D);
    document.body.appendChild(cssRenderer.domElement);
    /*
    arController
    */
    var cameraParameters = new ARCameraParam();
    var arController = null;
    cameraParameters.onload = function() {
        arController = new ARController(source.videoWidth,source.videoHeight,cameraParameters);
        arController.addEventListener("getMarker",function(event) {
            var modelViewMatrix = new THREE.Matrix4().fromArray(event.data.matrix);
            camera.matrix.getInverse(modelViewMatrix);
            // mesh.matrix.copy(modelViewMatrix);
            // iframe3D.matrix.copy(modelViewMatrix);
        });
        var cameraViewMatrix = new THREE.Matrix4().fromArray(arController.getCameraMatrix());
        camera.projectionMatrix.copy(cameraViewMatrix);
    }
    cameraParameters.load("data/camera_para.dat");
    /*
    animate
    */
    requestAnimationFrame(function animate() {
        requestAnimationFrame(animate);
        if (!arController) {
            return;
        }
        arController.process(source);
        renderer.render(scene,camera);
        cssRenderer.render(cssScene,camera);
    });
});

我曾希望旋转相机而不是物体会提供一个解决方案,唉。就好像我错过了一些需要应用的矩阵转换。

也许相机的 fov 参数有问题,或者变换矩阵被覆盖了,但无论如何我找不到问题所在。所以这里有一个不使用CSS3DRenderer或THREE.js的替代方案。

本质上,我们可以使用标记数据本身的坐标来创建投影矩阵。非常感谢这篇文章,它提供了我需要的大部分代码。

function adjugate(m) { // Compute the adjugate of m
    return [
        m[4]*m[8]-m[7]*m[5],m[7]*m[2]-m[1]*m[8],m[1]*m[5]-m[4]*m[2],
        m[6]*m[5]-m[3]*m[8],m[0]*m[8]-m[6]*m[2],m[3]*m[2]-m[0]*m[5],
        m[3]*m[7]-m[6]*m[4],m[6]*m[1]-m[0]*m[7],m[0]*m[4]-m[3]*m[1]
    ];
}
function multiply(a,b) { // multiply two matrices
    a = [
        a[0],a[3],a[6],
        a[1],a[4],a[7],
        a[2],a[5],a[8]
    ];
    b = [
        b[0],b[3],b[6],
        b[1],b[4],b[7],
        b[2],b[5],b[8]
    ];
    var m = Array(9);
    for (var i = 0; i != 3; ++i) {
        for (var j = 0; j != 3; ++j) {
            var mij = 0;
            for (var k = 0; k != 3; ++k) {
                mij += a[3*i + k]*b[3*k + j];
            }
            m[3*i + j] = mij;
        }
    }
    return [
        m[0],m[3],m[6],
        m[1],m[4],m[7],
        m[2],m[5],m[8]
    ];
}
function apply(m,v) { // multiply matrix and vector
    return [
        m[0]*v[0] + m[3]*v[1] + m[6]*v[2],
        m[1]*v[0] + m[4]*v[1] + m[7]*v[2],
        m[2]*v[0] + m[5]*v[1] + m[8]*v[2]
    ];
}
//
var iframe = document.createElement("iframe");
iframe.src = "data/index.html";
iframe.style.position = "absolute";
iframe.style.left = "0";
iframe.style.top = "0";
iframe.style.transformOrigin = "0 0";
document.querySelector("main").appendChild(iframe);
var s = [
    0,0,1,
    iframe.offsetWidth,0,1,
    0,iframe.offsetHeight,1
];
var v = apply(adjugate(s),[iframe.offsetWidth,iframe.offsetHeight,1]);
s = multiply(s,[
    v[0], 0, 0,
    0, v[1], 0,
    0, 0, v[2]
]);
arController.addEventListener("getMarker",function(event) {
    if (event.data.marker.id === marker) {
        var d = [
            event.data.marker.vertex[(4 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(4 - event.data.marker.dir) % 4][1],1,
            event.data.marker.vertex[(5 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(5 - event.data.marker.dir) % 4][1],1,
            event.data.marker.vertex[(7 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(7 - event.data.marker.dir) % 4][1],1
        ];
        var v = apply(adjugate(d),[event.data.marker.vertex[(6 - event.data.marker.dir) % 4][0],event.data.marker.vertex[(6 - event.data.marker.dir) % 4][1],1]);
        d = multiply(d,[
            v[0],0,0,
            0,v[1],0,
            0,0,v[2]
        ]);
        var t = multiply(d,adjugate(s));
        for (i = 0; i < 9; ++i) {
            t[i] = t[i] / t[8];
            t[i] = Math.abs(t[i]) < Number.EPSILON ? 0 : t[i];
        }
        t = [
            t[0],t[1],0,t[2],
            t[3],t[4],0,t[5],
            0,0,1,0,
            t[6],t[7],0,t[8]
        ];
        iframe.style.transform = "matrix3d(" + t.join(", ") + ")";
    } else {
        // mesh.visible = false;
    }
});

可能是逾期 4 年的答案,但可能对某些人有用。

我创建了一个替代解决方案。你可以在这里查看:https://github.com/jonathanneels/QrA

基本上;QrA使用tilt-js来模拟3D效果(视差),并使用AR.js a-box作为起始对象。iframe由倾斜.js函数推动,AR立方体的.position,.scale和.rotation用作参考。

享受!

相关内容

  • 没有找到相关文章

最新更新