我希望能够在增强现实标记上覆盖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用作参考。
享受!