旋转3D图

时间:2013-09-19 20:41:11

标签: java opengl rotation libgdx

我需要单击鼠标按钮,您可以在2轴上旋转图形。释放鼠标按钮时,图形将在原始位置旋转。通过小转动,一切都按照应有的方式进行,但是在图形的大转动(<180)时,图形不会返回其原始位置。

我没有看到任何错误。帮助我。

public class WaitActionScren extends Base3dGameScreen {

    private static final int DEFAULT_INERT_VALUE = 5;
    private int sumRotateX = 0, sumRotateY = 0;
    private boolean isUp = false;

    /**
     * Constructor.
     * 
     * @param game {@link MagicSphere} instance.
     */
    public WaitActionScren(MagicSphere game) {
        super(game);
    }

    @Override
    public void create() {
        super.create();
        bitmapFontCache.setColor(Color.GREEN);
        Gdx.input.setInputProcessor(new TouchEvents());
    }

    @Override
    public void render(float deltaTime) {
        Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        modelBatch.begin(cam);
        modelBatch.render(instanceSphere, lights);
        modelBatch.end();
    }

    @Override
    public void update(float deltaTime) {
        if (isUp) {
            int inertValue = getInertValue(sumRotateX);
            instanceSphere.transform.rotate(0, 1, 0, inertValue);
            System.err.println("rotate_x : " + inertValue);
            sumRotateX += inertValue;

            inertValue = getInertValue(sumRotateY);
            instanceSphere.transform.rotate(1, 0, 0, inertValue);
            System.err.println("rotate_y : " + inertValue);
            sumRotateY += inertValue;
        }
    }

    // TODO non static.
    private static int getInertValue(int sumRotate) {
        if(sumRotate > 0) {
            if (sumRotate < DEFAULT_INERT_VALUE) {
                return -sumRotate;
            }
            return -DEFAULT_INERT_VALUE;
        }

        if(sumRotate < 0) {
            if (sumRotate > -DEFAULT_INERT_VALUE) {
                return -sumRotate;
            }
            return DEFAULT_INERT_VALUE;
        }

        return 0;
    } 

    @Override
    public void dispose() {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    class TouchEvents implements InputProcessor {
        private int oldX = 0, oldY = 0;

        @Override
        public boolean keyDown(int keycode) {
            return false;
        }

        @Override
        public boolean keyUp(int keycode) {
            return false;
        }

        @Override
        public boolean keyTyped(char character) {
            return false;
        }

        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            return false;
        }

        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            oldX = 0;
            oldY = 0;
            isUp = true;
            return false;
        }

        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            if (oldX != 0 || oldY != 0) {
                float change;
                change = screenX - oldX;
                instanceSphere.transform.rotate(0, 1, 0, change);
                System.err.println("X: " + change);
                sumRotateX += change;
                change = screenY - oldY;
                instanceSphere.transform.rotate(1, 0, 0, change);
                System.err.println("X: " + change);
                sumRotateY += change;
            }
            oldX = screenX;
            oldY = screenY;
            isUp = false;
            return false;
        }

        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            return false;
        }

        @Override
        public boolean scrolled(int amount) {
            return false;
        }

    }
}

2 个答案:

答案 0 :(得分:1)

没有相关的图书馆对我来说很难确定,但我认为你可能会陷入轮换问题的顺序;那就是如果你围绕y轴旋转90度然后围绕z轴旋转90度,这与围绕z旋转然后y旋转不同。所以考虑到你总是旋转大约y然后大约x,当你来撤消一个旋转你并没有真正撤消它时,你正在进行更圆的旋转。

为了证明这一点,让我们从沿x轴指向的矢量开始,我们将围绕y和z旋转90度,但是以不同的顺序

首先关于y然后关于z

enter image description here enter image description here enter image description here

首先关于z然后关于y

enter image description here enter image description here enter image description here

结论

正如您所看到的操作顺序非常重要,因此如果您先旋转x然后y,为了撤消您需要旋转-y然后-x。

答案 1 :(得分:0)

我已经达到了预期的效果。我希望这对某人有用。

public class WaitActionScren extends Base3dGameScreen {

    private static final float DEFAULT_INERT_VALUE = 7f;
    private float sumY = 0;
    private float sumX = 0;
    private boolean isUp = false;

    /**
     * Constructor.
     * 
     * @param game {@link MagicSphere} instance.
     */
    public WaitActionScren(MagicSphere game) {
        super(game);
    }

    @Override
    public void create() {
        super.create();
        bitmapFontCache.setColor(Color.GREEN);
        Gdx.input.setInputProcessor(new TouchEvents());
    }

    @Override
    public void render(float deltaTime) {
        Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        modelBatch.begin(cam);
        modelBatch.render(instanceSphere, lights);
        modelBatch.end();
    }

    @Override
    public void update(float deltaTime) {
        if (isUp) {
            Quaternion rotation = new Quaternion();
            instanceSphere.transform.getRotation(rotation);
            float xInert = getInertValue(sumX);
            float yInert = getInertValue(sumY);
            sumX += xInert;
            sumY += yInert;
            Vector3 v3 = new Vector3(sumY, sumX, 0);
            float len = v3.len();
            v3 = v3.nor();
            rotation.setFromAxis(v3.x, v3.y, v3.z, len);
            instanceSphere.transform.set(rotation);
        }
    }

    private float getInertValue(float sumRotate) {
        if(sumRotate > 0.0f) {
            if (sumRotate < DEFAULT_INERT_VALUE) {
                return -sumRotate;
            }
            return -DEFAULT_INERT_VALUE;
        }

        if(sumRotate < 0.0f) {
            if (sumRotate > -DEFAULT_INERT_VALUE) {
                return -sumRotate;
            }
            return DEFAULT_INERT_VALUE;
        }

        return 0;
    } 

    @Override
    public void dispose() {
    }

    @Override
    public void pause() {
    }

    @Override
    public void resume() {
    }

    class TouchEvents implements InputProcessor {
        private float oldX = 0.0f, oldY = 0.0f;

        @Override
        public boolean keyDown(int keycode) {
            return false;
        }

        @Override
        public boolean keyUp(int keycode) {
            return false;
        }

        @Override
        public boolean keyTyped(char character) {
            return false;
        }

        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            oldX = screenX;
            oldY = screenY;
            return false;
        }

        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            oldX = 0.0f;
            oldY = 0.0f;
            isUp = true;
            return false;
        }

        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            float changeX;
            float changeY;

            changeX = screenX - oldX;
            changeY = screenY - oldY;
            sumX += changeX;
            sumY += changeY;

            Vector3 v3 = new Vector3(sumY, sumX, 0.0f);
            float length = v3.len();
            v3 = v3.nor();
            Quaternion rotation = new Quaternion();
            instanceSphere.transform.getRotation(rotation);
            rotation.setFromAxis(v3.x, v3.y, v3.z, length);
            instanceSphere.transform.set(rotation);

            oldX = screenX;
            oldY = screenY;
            isUp = false;
            return false;
        }

        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            return false;
        }

        @Override
        public boolean scrolled(int amount) {
            return false;
        }
    }
}