一种基于视觉误差产生的裸眼3d,与传统的双眼产生的不同的图像差形成距离感不同,这种裸眼是依赖3d的“离轴投影”,离轴投影将产生“非对称相机”视锥体。
实现原理
3d相机机制
var te = [];
var x = 2 * near / ( right - left );
var y = 2 * near / ( top - bottom );
var a = ( right + left ) / ( right - left );
var b = ( top + bottom ) / ( top - bottom );
var c = - ( far + near ) / ( far - near );
var d = - 2 * far * near / ( far - near );
te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
当然,这种裸眼3d效果,一般情况下肯定是需要搭配陀螺仪进行使用,于是一开始我也简单的绑定了陀螺仪效果,因为感觉那似乎不是很困难。
但是按照平时的陀螺仪绑定的方式,一直无法实现“真实”的裸眼3d效果。
这个效果是合成的,文末有链接
后来发现,这是裸眼3d效果的第二个难点:
手机的朝向与陀螺仪
手机陀螺仪关于参数解释的几张图:
这几张图很容易让人产生误解,当然不是说这几张图是错的。
首先,alpha,beta,gamma的值是以地球坐标为基准的,其中,alpha甚至与手机的朝向没有关系。
也就是说,alpha图也可以画成这样:
这几张手机转动的都是alpha角,而不是只有当手机绕着垂直于屏幕的z轴旋转才触发alpha角。
beta角是手机的y轴与地面的角度值
gamma角是手机的x轴与地面的角度值
alpha与手机的轴无关,beta,gamma值与手机当前yx轴的位置相关
var quaternion = new THREE.Quaternion();
var euler= new THREE.Euler();
euler.set( beta, alpha, - gamma, 'YXZ' );
quaternion.setFromEuler( euler );
四元数可以通过四维投影到三维空间的球体来理解,具体四元数的对应关系可以查看Visualizing quaternions
通过四元数记录手机选择角度,然后将裸眼3d相机位置按照对应转动角度反向转动,即可实现陀螺仪操控的裸眼
假设相机的初始位置是p1,当手机旋转q1值时,此时相机位置在p2处,但是相对手机来说相机依然是在手机的正前方,所以,相机需要逆向转动q1,从p2移到p1,其中p2即为一开始的p1值。
用户视角:
裸眼3d只计算转动值,所以还需要初始化转动前的角度值,即提前记录p1位置。
<script src="https://game.gtimg.cn/images/js/sign/glassfree3d/js/GlassFree3dCamera.js"></script>
new THREE.GlassFree3dCamera(x, y, z, width, height);
使用方法,用GlassFree3dCamera代替正常的相机,其中xyz为裸眼3d相机的坐标,width,height为投影平面的宽高。
camera.initMove();
开启点击事件。
camera.initDeviceOrientation();
开启陀螺仪事件。