Android 使用滚动的opengl ES围绕场景旋转摄影机
我正在尝试使用触摸(滚动)在场景周围旋转相机: 摄影机在渲染中移动,如下所示:Android 使用滚动的opengl ES围绕场景旋转摄影机,android,matrix,opengl-es,opengl-es-2.0,touch-event,Android,Matrix,Opengl Es,Opengl Es 2.0,Touch Event,我正在尝试使用触摸(滚动)在场景周围旋转相机: 摄影机在渲染中移动,如下所示: public class SceneRenderer implements GLSurfaceView.Renderer { private float[] viewMatrix = new float[16]; @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { Matrix.set
public class SceneRenderer implements GLSurfaceView.Renderer {
private float[] viewMatrix = new float[16];
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 3f,
0f, 0f, 0f, 0f, 1.0f, 0.0f);
}
...
// movement of camera
public synchronized void setMotion(float xDistance, float yDistance) {
Matrix.rotateM(viewMatrix, 0, -xDistance * 0.1f, 0, 1, 0);
Matrix.rotateM(viewMatrix, 0, -yDistance * 0.1f, 1, 0, 0);
}
}
这在一开始效果很好。但随后相机开始旋转,并不像预期的那样。如何使用滚动使相机相对于场景(对象)的中心正确移动?也许有人解决了类似的问题
谢谢你的回答/评论
解决方案:
private float kx = 0f;
private float ky = 0f;
private float radius = 3.0f;
private float x, y, z = 0f;
...
public synchronized void setMotion(float xDistance, float yDistance) {
kx = kx + xDistance * 0.001f;
x = (float) (radius * Math.sin(kx));
z = (float) (radius * Math.cos(kx));
ky = ky + yDistance * 0.001f;
y = (float) (radius * Math.sin(ky));
Matrix.setLookAtM(viewMatrix, 0, x, -y, z, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
}
但是,使用这种方法,相机在沿Y轴旋转时会远离场景。在矩阵代数中,顺序确实很重要。因为增量旋转交错矩阵和中断顺序,所以它不会像您期望的那样工作。因此,您需要根据每次setMotion()调用的累积增量x/y重建视图矩阵,以便始终按如下正确顺序应用旋转
public class SceneRenderer implements GLSurfaceView.Renderer {
private float[] viewMatrix = new float[16];
private float cumulativeX = 0.0f;
private float cumulativeY = 0.0f;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 3f,
0f, 0f, 0f, 0f, 1.0f, 0.0f);
cumulativeX = 0.0f;
cumulativeY = 0.0f;
}
...
// movement of camera
public synchronized void setMotion(float xDistance, float yDistance) {
cumulativeX += xDistance;
cumulativeY += yDistance;
Matrix.setLookAtM(viewMatrix, 0, 0f, 0f, 3f,
0f, 0f, 0f, 0f, 1.0f, 0.0f);
//Matrix.rotateM(viewMatrix, 0, -cumulativeX * 0.1f, 0, 1, 0);
//Matrix.rotateM(viewMatrix, 0, -cumulativeY * 0.1f, 1, 0, 0);
Matrix.rotateM(viewMatrix, 0, -cumulativeY * 0.1f, 1, 0, 0);
Matrix.rotateM(viewMatrix, 0, -cumulativeX * 0.1f, 0, 1, 0);
}
}
附录:仅由setLookAtM构成视图矩阵
当然,只有使用setLookAtM才能实现同样的效果。若要使视点保持恒定距离,请向内移动视点。并调整向上方向
public synchronized void setMotion(float xDistance, float yDistance) {
kx = kx + xDistance * 0.001f;
ky = ky + yDistance * 0.001f;
x = (float) (radius * Math.cos(ky) * Math.sin(kx));
z = (float) (radius * Math.cos(ky) * Math.cos(kx));
y = (float) (radius * Math.sin(ky));
float[] up =
{
(float) (Math.sin(ky) * Math.sin(kx)),
(float) (Math.cos(ky)),
(float) (Math.sin(ky) * Math.cos(kx)),
};
Matrix.setLookAtM(viewMatrix, 0,
x, -y, z,
0f, 0f, 0f,
up[0], up[1], up[2]
);
}
谢谢你的回答!但问题是,在初始旋转之后,场景开始沿其他轴旋转。我在文章中添加了“自解”,但它会使相机在沿Y轴旋转时远离场景。再次感谢你的回答!根据解决方案,旋转顺序应为X轴>Y轴。不管怎样,我还是更新了答案。如果您想使用setLookAtM解决方案,请参阅附录。非常感谢。
public synchronized void setMotion(float xDistance, float yDistance) {
kx = kx + xDistance * 0.001f;
ky = ky + yDistance * 0.001f;
x = (float) (radius * Math.cos(ky) * Math.sin(kx));
z = (float) (radius * Math.cos(ky) * Math.cos(kx));
y = (float) (radius * Math.sin(ky));
float[] up =
{
(float) (Math.sin(ky) * Math.sin(kx)),
(float) (Math.cos(ky)),
(float) (Math.sin(ky) * Math.cos(kx)),
};
Matrix.setLookAtM(viewMatrix, 0,
x, -y, z,
0f, 0f, 0f,
up[0], up[1], up[2]
);
}