我一起使用THREE.js和Aframe(在Exokit中),并且有一个用于“自拍相机”的组件。我有一个奇怪的问题,当我进入VR时,摄像头旋转由头部旋转接管。我了解相机的旋转方式在THREE.js(ArrayCamera)的最新版本中已发生了变化,但我认为这仅影响主相机,而不影响场景中的所有相机。
下面是我的hacky组件,在2D模式下可以正常工作,但在VR中会混乱。最糟糕的事情是它与头部相连是很好的,照相机本身还是主照相机的子对象,因此打开时它会出现在用户面部的前面,并随着头部旋转而移动-但它会关闭在VR中的角度,例如其指向下方和向左一点。
以下是一些有望证明该问题的屏幕截图:
编辑:需要10个代表才能发布图片,因此这里是网址
非常感谢任何帮助!
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;
}
});
答案 0 :(得分:0)
渲染之前必须禁用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;