- 图片视频格式的检测
将Texture按宽高比降采样,假设图片比例是1:1,那么用于检测格式的texture大小是16x16.
检测的方式是按照三色值差异,
以判断左右格式为例,左右两部分相对应的像素分别进行比较
•遍历后得到八组diff值,diff值累加后求平均作为左右格式判断依据,如果小于经验值,这可认为是左右格式
x = pixel.x /= range.x
y = pixel.y /= range.y
z = pixel.z /= range.z
diff = (x1-x2,y1-y2,z1-z2)
range是最亮像素与最暗像素的差值
然后所得diff值的平方相加即为总差异值,总差异值除以判断的像素数量为单个像素差异值R,取R的元素的平均值用于比较
同理得上下格式的判断结果
同理可得上下格式的差异值
SIMILARITY_THRESHOLD 经验值,0.025,差异值低于改值即为stereo图片
- 手柄拖拽屏幕的实现
2.1 三个事件:OnBeginDrag OnDrag OnEndDrag
2.2 四元数:
求模
N(q) = |q| = x2 + y2 + z2 + w2
求共轭
q=(-x, -y, -z, w)
根据定义易得:(hk) = kh;(在屏幕旋转时有用,后面讲到)
求逆
对于向量逆的定义, q-1 =q/|q|2
对于单位四元素,分母为1,q-1 = q =(-x, -y, -z, w)
无交换律,有结合律
unity里的四元数都是单元四元数,莫均为一,所以共轭与逆一致
2.3 四元数逆在旋转中的意义
问题:将空间点P(1,0,1)绕轴(0,1,0)旋转90度,将会得到点(1,0,-1)
张国强 > MediaApp技术点 > 1获.PNG
•使用四元数计算过程如下:
将点P四维化为 (1,0,1,0)
四元数 q = ( (0,1,0)sin45 , cos45)
计算 qpq-1可得结果P`
•q-1 = (-(0,1,0)sin45,cos45) = ((0,1,0)sin-45,cos-45)
即四元数的逆是按同一旋转轴反方向旋转同一角度
2.4 拖拽屏幕
效果:屏幕始终与双眼平行,看向屏幕时视线与屏幕垂直,拖拽过程中光标在屏幕上的位置不变
2.4.1 实现拖拽
//根据光标的方向得到绕x轴和y轴的旋转角,余弦定理,根据旋转角得到四元数,仅计算水平角度和垂直角度(具体实现未给出,可自行计算)
Quaternion yawPitchRotation = CalculateControllerYawPitchRotation(eventData);
//根据新的光标四元数和上一次的光标四元数,得到新的屏幕的旋转四元数,Quaternion.Inverse(lastYawPitchRotation)会使屏幕先回到上一次旋转之前的状态,再乘以新的光标四元数,就是屏幕新的位置,这样就使光标在屏幕上的点的位置不变,yawPitchRotationDelta 可理解为旋转偏差量
Quaternion yawPitchRotationDelta = yawPitchRotation Quaternion.Inverse(lastYawPitchRotation);
transform.parent.localRotation = yawPitchRotationDelta transform.parent.localRotation;
yawPitchRotation:当前帧手柄相对于相机的旋转
lastYawPitchRotation:上一帧手柄相对于相机的旋转
yawPitchRotationDelta:两帧之间旋转差值
Quaternion.Inverse:取逆
2.4.2 矫正扭转
光标的旋转是一个点的四元数,把点的旋转应用在面上时,由于面与旋转轴的夹角,各部分在旋转相同角度下位移不同,会出现扭转,所以如果要保证屏幕始终平行两眼,在拖拽完成后要进行矫正
Vector3 eulerAngles = transform.parent.localRotation.eulerAngles;
eulerAngles.z = 0.0f;
lastFinalRotation = Quaternion.Euler(eulerAngles);
lastYawPitchRotation = yawPitchRotation;
if (enableRotation)
{
transform.parent.localRotation = lastFinalRotation;
}
3.屏幕反光的实现
•两个元素,灯光颜色和强度
•颜色:计算平均颜色,播放时,每隔多帧计算一次 blit 4x4,得4x4的texture,计算三色的平均值
•强度:设定两个高度临界值,当屏幕位置低于最低值时,灯光完全消失,在临界值之间时,灯光强度与屏幕高度和light高度有关,当屏幕位置大于最高值时,灯光亮度只与light高度有关
float intensity =Mathf.Clamp01((y - heightMin) / (heightMax - heightMin));