Unity3D中球直角坐标与球极坐标映射
- 极坐标与直角坐标映射
- Unity坐标系下映射
- 二维纹理坐标转球直角坐标
- 球直角坐标转球极坐标
- 球极坐标转球直角坐标
- 球直角坐标转二维纹理坐标
- 验证
极坐标与直角坐标映射
球坐标系(r,θ,φ)与直角坐标系(x,y,z)的转换关系:
x=rsinθcosφ.
y=rsinθsinφ.
z=rcosθ.
反之,直角坐标系(x,y,z)与球坐标系(r,θ,φ)的转换关系为:
假设P(x,y,z)为空间内一点,则点P也可用这样三个有次序的数(r,θ,φ)来确定,其中r为原点O与点P间的距离;θ为有向线段OP与z轴正向的夹角;φ为从正z轴来看自x轴按逆时针方向转到OM所转过的角,这里M为点P在xOy面上的投影。
Unity坐标系下映射
Unity坐标系如下:
具体关系请参考:Unity3D中二维纹理与球坐标映射
二维纹理坐标转球直角坐标
//Vector2 viewPoint为二维纹理坐标,w、h为纹理宽高,r为球半径
x_pos = viewPoint.x / (float)w * (2 * M_PI) - M_PI;
y_pos = viewPoint.y / (float)h * (M_PI) - M_PI_2;//注意原点在左下角
Nx = (float)(Math.Cos(y_pos) * Math.Cos(x_pos))*r;
Nz = -1.0f * (float)(Math.Cos(y_pos) * Math.Sin(x_pos))*r;
Ny = (float)Math.Sin(y_pos)*r;
球直角坐标转球极坐标
angel_theta = (float)Math.Acos(Ny / r);//半径为r,弧度值
angel_phi = (float)Math.Atan(Nz / Nx);
球极坐标转球直角坐标
//Vector3 top_s为球直角坐标
top_s.x = (float)(Math.Sin(angel_theta) * Math.Cos(angel_phi))*r;
top_s.z = (float)(Math.Sin(angel_theta) * Math.Sin(angel_phi))*r;
top_s.y = (float)Math.Cos(angel_theta) * r;
球直角坐标转二维纹理坐标
//Vector2 top、viewPoint为二维纹理坐标,w、h为图像宽高,r为圆球半径
top.x = (float)(Math.Atan(-1.0f*top_s.z / top_s.x) / 2.000f / M_PI+0.500f);//纹理坐标,原点在左下角
top.y = (float)(Math.Asin(top_s.y / r) / M_PI + 0.500f);
viewPoint.x = (Int32)(top.x * w);
viewPoint.y = (Int32)(top.y * h);
验证
我们将二维纹理坐标上的点转换到球极坐标,对球极坐标进行角度的操作,再映射会二维纹理坐标,对其进行验证:
x_pos = viewPoint.x / (float)w * (2 * M_PI) - M_PI;
y_pos = viewPoint.y / (float)h * (M_PI) - M_PI_2;//注意原点在左下角
Nx = (float)(Math.Cos(y_pos) * Math.Cos(x_pos))*l;//球半径l
Nz = -1.0f * (float)(Math.Cos(y_pos) * Math.Sin(x_pos))*l;
Ny = (float)Math.Sin(y_pos)*l;
angel_theta = (float)Math.Acos(Ny/l);//半径为1,弧度值
angel_phi = (float)Math.Atan(Nz / Nx);
angel_alpha = (float)Math.Asin(1.0f);//改变角度为90°
//将图像向上旋转90°
top_s.x = (float)(Math.Sin(angel_theta - angel_alpha) * Math.Cos(angel_phi))*l;
top_s.z = (float)(Math.Sin(angel_theta - angel_alpha) * Math.Sin(angel_phi))*l;
top_s.y = (float)Math.Cos(angel_theta - angel_alpha) * l;
top.x = (float)(Math.Atan(-1.0f*top_s.z / top_s.x) / 2.000f / M_PI+0.500f);//纹理坐标,原点在左下角
top.y = (float)(Math.Asin(top_s.y/l) / M_PI + 0.500f);
viewPoint.x = (Int32)(top.x * w);
viewPoint.y = (Int32)(top.y * h);
输入视点坐标(1000.0f, 0.0f, 0.0f),视点图像如下:
变换后图像如下:
图像向上旋转了90°