|
楼主 |
发表于 2021-3-14 12:53:03
|
显示全部楼层
本帖最后由 pcsms_05jLD97h 于 2021-3-14 18:51 编辑
个人理解,如果错误,请您指出来,及时纠正
1.此函数用于求解z坐标
float OrbitManipulator::tb_project_to_sphere( float r, float x, float y )
{
float d, t, z;
d = sqrt(x*x + y*y);
/* Inside sphere */
if (d < r * 0.70710678118654752440)
{
z = sqrt(r*r - d*d);
} /* On hyperbola */
else
{
t = r / 1.41421356237309504880;
z = t*t / d;
}
return z;
}
传入一个设想的半径,默认是0.8(x y坐标是标准化坐标,范围在-1,1),分两种i情况来求解z坐标
0.70710678118654752440 是cos(PI/2),也就是45度
1.d < r * 0.70710678118654752440 同理 球上一点和xy平面的夹角大于45,使用圆的算法
2.d > r * 0.70710678118654752440 同理 球上一点和xy平面的夹角小于45,使用双曲线算法
2.此函数是求解旋转轴 和 旋转角
void OrbitManipulator::trackball( osg::Vec3d& axis, float& angle, float p1x, float p1y, float p2x, float p2y )
{
/*
* First, figure out z-coordinates for projection of P1 and P2 to
* deformed sphere
*/
osg::Matrixd rotation_matrix(_rotation);
osg::Vec3d uv = Vec3d(0.0f,1.0f,0.0f)*rotation_matrix;
osg::Vec3d sv = Vec3d(1.0f,0.0f,0.0f)*rotation_matrix;
osg::Vec3d lv = Vec3d(0.0f,0.0f,-1.0f)*rotation_matrix;
osg::Vec3d p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y);
osg::Vec3d p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y);
/*
* Now, we want the cross product of P1 and P2
*/
axis = p2^p1;
axis.normalize();
/*
* Figure out how much to rotate around that axis.
*/
float t = (p2 - p1).length() / (2.0 * _trackballSize);
/*
* Avoid problems with out-of-control values...
*/
if (t > 1.0) t = 1.0;
if (t < -1.0) t = -1.0;
angle = inRadians(asin(t));
}
2.1 获取三维空间中的方向向量
float p1x, float p1y, float p2x, float p2y 屏幕坐标标准化后的坐标(-1,1)
tb_project_to_sphere(_trackballSize, p1x, p1y); 间接获取到Z坐标 => 虚拟轨迹球的方向向量
2.2 组合成旋转矩阵
osg::Vec3d uv = Vec3d(0.0f,1.0f,0.0f)*rotation_matrix;
osg::Vec3d sv = Vec3d(1.0f,0.0f,0.0f)*rotation_matrix;
osg::Vec3d lv = Vec3d(0.0f,0.0f,-1.0f)*rotation_matrix;
2.3 获取旋转后的方向向量
osg::Vec3d p1 = sv * p1x + uv * p1y - lv * tb_project_to_sphere(_trackballSize, p1x, p1y);
osg::Vec3d p2 = sv * p2x + uv * p2y - lv * tb_project_to_sphere(_trackballSize, p2x, p2y);
[SV UV LV][PX PY PZ]T = SV*PX + UV*PY + LV*PZ
2.4 获取旋转轴
axis = p2^p1;
axis.normalize();
2.5 获取旋转角度
float t = (p2 - p1).length() / (2.0 * _trackballSize);
相当于圆上两点,连接两点,从圆心做垂线,sin& = ((p2 - p1).length() / 2.0) / _trackballSize); 注释(_trackballSize = r)
防止越界
if (t > 1.0) t = 1.0;
if (t < -1.0) t = -1.0;
反向求出角度
angle = inRadians(asin(t));
|
|