저는 OpenGL과 3D 프로그래밍에 상당히 익숙하지만 http://www.cprogramming.com/tutorial/3d/quaternions.html의 튜토리얼에 기반한 쿼터니언을 사용하여 카메라 회전을 구현하기 시작했습니다. 이것은 모두 JOGL을 사용하여 Java로 작성됩니다.OpenGL의 3D 카메라 회전 : 카메라 지터를 방지하는 방법은 무엇입니까?
이런 종류의 질문은 상당히 많이 묻습니다.하지만 저는 주위를 둘러 보았고 작동하는 솔루션을 찾을 수 없어서 코드에 문제가있을 수 있다고 생각했습니다.
그래서 문제는 하나 이상의 축에서 두 개의 다른 연속 회전을 수행 할 때 떨림과 홀수 회전이 발생한다는 것입니다. 축을 따라 첫 번째 회전은 부정적 또는 적극적으로 잘 작동합니다. 그러나 한 축을 따라 양의 방향으로 회전 한 다음 해당 축에서 음의 방향으로 회전하면 회전은 양의 회전과 음의 회전을 교대로하는 것처럼 앞뒤로 움직입니다.
회전을 자동화하면 (예 : 왼쪽으로 500 번 회전 한 다음 오른쪽으로 500 번 회전하면) 제대로 작동하는 것처럼 보이므로 키 누르기와 관련 있다고 생각할 수 있습니다. 그러나 x 축 주위를 회전 한 다음 나중에 y 축을 중심으로 회전하면 더 좋은 단어가없는 경우에도 회전이 올바르지 않습니다.
private void render(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(70, Constants.viewWidth/Constants.viewHeight, 0.1, 30000);
gl.glScalef(1.0f, -1.0f, 1.0f); //flip the y axis
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
camera.rotateCamera();
glu.gluLookAt(camera.getCamX(), camera.getCamY(), camera.getCamZ(), camera.getViewX(), camera.getViewY(), camera.getViewZ(), 0, 1, 0);
drawSceneNodes(gl);
}
private void drawSceneNodes(GL2 gl) {
if (currentEvent != null) {
ArrayList<SceneNode> sceneNodes = currentEvent.getSceneNodes();
for (SceneNode sceneNode : sceneNodes) {
sceneNode.update(gl);
}
}
if (renderQueue.size() > 0) {
currentEvent = renderQueue.remove(0);
}
}
회전은 다음과 같이 카메라 클래스에서 수행됩니다 :
public class Camera {
private double width;
private double height;
private double rotation = 0;
private Vector3D cam = new Vector3D(0, 0, 0);
private Vector3D view = new Vector3D(0, 0, 0);
private Vector3D axis = new Vector3D(0, 0, 0);
private Rotation total = new Rotation(0, 0, 0, 1, true);
public Camera(GL2 gl, Vector3D cam, Vector3D view, int width, int height) {
this.cam = cam;
this.view = view;
this.width = width;
this.height = height;
}
public void rotateCamera() {
if (rotation != 0) {
//generate local quaternion from new axis and new rotation
Rotation local = new Rotation(Math.cos(rotation/2), Math.sin(rotation/2 * axis.getX()), Math.sin(rotation/2 * axis.getY()), Math.sin(rotation/2 * axis.getZ()), true);
//multiply local quaternion and total quaternion
total = total.applyTo(local);
//rotate the position of the camera with the new total quaternion
cam = rotatePoint(cam);
//set next rotation to 0
rotation = 0;
}
}
public Vector3D rotatePoint(Vector3D point) {
//set world centre to origin, i.e. (width/2, height/2, 0) to (0, 0, 0)
point = new Vector3D(point.getX() - width/2, point.getY() - height/2, point.getZ());
//rotate point
point = total.applyTo(point);
//set point in world coordinates, i.e. (0, 0, 0) to (width/2, height/2, 0)
return new Vector3D(point.getX() + width/2, point.getY() + height/2, point.getZ());
}
public void setAxis(Vector3D axis) {
this.axis = axis;
}
public void setRotation(double rotation) {
this.rotation = rotation;
}
}
방법 rotateCamera 어쨌든
, 나는`장면 노드를 '그리기에 대해 다음 디스플레이 루프 렌더러 클래스가 rotatePoint 메소드는 permenant quaternion에서 생성 된 회전 행렬을 단순히 곱하는 반면 새로운 회전 및 이전 회전에서 새로운 permenant quaternions를 생성합니다.
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_W) {
camera.setAxis(new float[] {1, 0, 0});
camera.setRotation(0.1f);
}
if (e.getKeyCode() == KeyEvent.VK_A) {
camera.setAxis(new float[] {0, 1, 0});
camera.setRotation(0.1f);
}
if (e.getKeyCode() == KeyEvent.VK_S) {
camera.setAxis(new float[] {1, 0, 0});
camera.setRotation(-0.1f);
}
if (e.getKeyCode() == KeyEvent.VK_D) {
camera.setAxis(new float[] {0, 1, 0});
camera.setRotation(-0.1f);
}
}
내가 충분한 정보를 제공 한 희망을 다음과 같이
회전의 축과 회전 각도는 간단한 키 입력에 의해 설정됩니다. 어떤 도움이라도 대단히 감사 할 것입니다.
SceneRenderer 클래스는 GLEventListener가 render()를 호출하는 디스플레이 (렌더링 가능한 루프 드로잉 가능)를 구현하므로 렌더링 루프를 구현합니다. 모델 측면에서 업데이트 이벤트를 전달한 다음 렌더링 대기열에 저장합니다. 죄송합니다. Camera 클래스에는 이미 눈의 위치와 그 위치가 저장됩니다 (원래 게시물에 코드를 추가합니다). 위쪽 방향을 정의하는 벡터와 관련 있습니다. 카메라가 회전 할 때 변경해야합니까? 위 방향이 바뀌지 않을 cam의 pos를 회전 한 후에 gluLookAt()를 사용하면 가정합니다. – noise
나는 이것이 고정 소수점 주위를 도는 3 인칭 카메라라고 설명해야합니다. 보이는 시점은 회전 할 때만 변하지 만 카메라가 번역되어 있지만 완전히 별개입니다. 카메라의 위치를 회전시키는 것만으로 충분하지 않습니까? 내가 바보라면 미안해. :) – noise
아, 알겠습니다. 회전 코드는 이해하기가 어렵 기 때문에 가장 먼저해야 할 일은 적절한 벡터 수학 라이브러리를 사용하는 것입니다. 카메라 내부의 모든 것을 구현하는 대신 실제 작업을 수행하는 3D 벡터 및 쿼터니언에 대한 클래스가 있어야합니다. 현재 상태에서는 코드가 실제로하는 일과 코드가 올바르게 작동하는지 여부를 말하는 것이 꽤 어렵습니다. –