THRE.js辅助摄像头在VR中随着头部旋转而旋转



我正在一起使用THRE.js和Aframe(在Exokit中),我有一个"自拍相机"的组件。我有一个奇怪的问题,当我进入VR时,相机的旋转被头部的旋转所取代。我知道相机旋转的工作方式在最近版本的THRE.js(ArrayCamera)中发生了变化,但我认为这只影响主相机,而不是场景中的所有相机。

下面是我的破解组件,它在2D模式下运行良好,但在VR模式下会出错。最糟糕的是,它被连接到头部,相机本身是主相机的子对象,所以当打开时,它会出现在用户的面前,并随着头部的旋转而移动——但在VR中,它的偏离角度就像它指向下方和左侧一样。

以下是一些有望证明问题的屏幕截图:

编辑:需要10个代表张贴图片,所以这里是URL而不是

2D模式

VR模式

非常感谢您的帮助!!

AFRAME.registerComponent('selfie-camera', {
schema:{
resolution:{type:'int',default:512},
fov:{type:'int',default:100},
aspect:{type:'number',default:1.5},
near:{type:'number',default:0.001},
far:{type:'number',default:1000}
},
init() {
this.el.addEventListener('loaded',()=>{
this.renderTarget = new THREE.WebGLRenderTarget(this.data.resolution*1.5, this.data.resolution,{ antialias: true });
this.el.getObject3D('mesh').material.map = this.renderTarget.texture;
this.cameraContainer = new THREE.Object3D();
this.el.object3D.add( this.cameraContainer );
this.el.takePicture = this.takePicture.bind(this);
this.el.setSide = this.setSide.bind(this);
this.wider = 1.5;
this.photoMultiplier = 2;
this.canvas = document.createElement('canvas');
});
this.testQuat = new THREE.Quaternion();
this.el.open = this.open.bind(this);
this.el.close = this.close.bind(this);
},
open(){
this.camera = new THREE.PerspectiveCamera( this.data.fov, this.data.aspect, this.data.near, this.data.far );
this.cameraContainer.add(this.camera);
new TWEEN.Tween(this.el.getAttribute('scale'))
.to(new THREE.Vector3(1,1,1), 650)
.easing(TWEEN.Easing.Exponential.Out).start();
},
close(){
new TWEEN.Tween(this.el.getAttribute('scale'))
.to(new THREE.Vector3(0.0000001,0.0000001,0.0000001), 200)
.onComplete(()=>{
this.cameraContainer.remove(this.camera);
delete this.camera;
})
.easing(TWEEN.Easing.Exponential.Out).start();
},
tick(){
if(this.camera){
this.camera.getWorldQuaternion(this.testQuat);
console.log(this.camera.quaternion);
}
this.el.getObject3D('mesh').material.visible = false;
if(this.isTakingPicture) {
this.renderTarget.setSize(this.data.resolution * this.wider * this.photoMultiplier, this.data.resolution * this.photoMultiplier);
}
this.el.sceneEl.renderer.render( this.el.sceneEl.object3D, this.camera, this.renderTarget );
if(this.isTakingPicture){
this.isTakingPicture = false;
this.pictureResolve(this.createImageFromTexture());
this.renderTarget.setSize(this.data.resolution * this.wider, this.data.resolution);
}
this.el.getObject3D('mesh').material.visible = true;
},
setSide(isFront){
let _this = this;
new TWEEN.Tween({y:this.cameraContainer.rotation.y})
.to({y:isFront?Math.PI:0}, 350)
.onUpdate(function(){
_this.cameraContainer.rotation.y = this.y;
})
.easing(TWEEN.Easing.Exponential.Out).start();
},
takePicture(){
return new Promise(resolve=>{
this.isTakingPicture = true;
this.pictureResolve = resolve;
})
},
createImageFromTexture() {
let width = this.data.resolution*this.wider*this.photoMultiplier,
height = this.data.resolution*this.photoMultiplier;
let pixels = new Uint8Array(4 * width * height);
this.el.sceneEl.renderer.readRenderTargetPixels(this.renderTarget, 0, 0, width, height, pixels);
pixels = this.flipPixelsVertically(pixels, width, height);
let imageData = new ImageData(new Uint8ClampedArray(pixels), width, height);
this.canvas.width = width;
this.canvas.height = height;
let context = this.canvas.getContext('2d');
context.putImageData(imageData, 0, 0);
return this.canvas.toDataURL('image/jpeg',100);
},
flipPixelsVertically: function (pixels, width, height) {
let flippedPixels = pixels.slice(0);
for (let x = 0; x < width; ++x) {
for (let y = 0; y < height; ++y) {
flippedPixels[x * 4 + y * width * 4] = pixels[x * 4 + (height - y) * width * 4];
flippedPixels[x * 4 + 1 + y * width * 4] = pixels[x * 4 + 1 + (height - y) * width * 4];
flippedPixels[x * 4 + 2 + y * width * 4] = pixels[x * 4 + 2 + (height - y) * width * 4];
flippedPixels[x * 4 + 3 + y * width * 4] = pixels[x * 4 + 3 + (height - y) * width * 4];
}
}
return flippedPixels;
}
});

渲染前必须禁用VR:

var renderer = this.el.sceneEl.renderer;
var vrEnabled = renderer.vr.enabled;
renderer.vr.enabled = false;
renderer.render(this.el.sceneEl.object3D, this.camera, this.renderTarget);
renderer.vr.enabled = vrEnabled;

最新更新