简体   繁体   English

旋转3D图

[英]Rotating 3D figure

I need to click the mouse button you can rotate the figure in 2 axes. 我需要单击鼠标按钮,才能沿2个轴旋转图形。 When you release the mouse button Figure be rotated in the original position. 当释放鼠标按钮时,图形将旋转到原始位置。 With a small turning everything goes as it should, but at a heavy rotation (<180) of the figure does not return to its original position. 稍微转弯,一​​切都会按预期进行,但是如果旋转大(<180),图形将不会返回其原始位置。

I do not see any mistakes. 我没有看到任何错误。 Help me. 帮我。

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;
        }

    }
}

Without having the relevant library its hard for me to be sure but I think you might be falling fowl of the order of rotations problem; 没有相关的库,我很难确定,但是我认为您可能不了解轮换顺序问题; that being that if you rotate around the y axis by 90 degrees then about the z axis by 90 degrees that is not the same as rotating around z then y. 也就是说,如果您绕y轴旋转90度,然后绕z轴旋转90度,则与绕z轴旋转y并不相同。 So given that you always rotate about y then about x when you come to undo a rotation you're not really undoing it, you're performing annother rotation. 因此,假设您总是要绕y旋转,然后绕x旋转,则撤消旋转并不是真的要撤消旋转,而是要进行另一次旋转。

To demonstrate this, lets start with a vector pointed along the x axis, and we're going to rotate 90 degrees about y and z, but in different orders 为了说明这一点,让我们从沿x轴指向的向量开始,我们将围绕y和z旋转90度,但顺序不同

First about y then about z 首先关于y然后关于z

在此处输入图片说明在此处输入图片说明在此处输入图片说明

First about z then about y 首先关于z然后关于y

在此处输入图片说明在此处输入图片说明在此处输入图片说明

Conclusion 结论

As you can see the order of operations is very important, so if you first rotate x then y, in order to undo that you need to rotate -y then -x. 如您所见,操作顺序非常重要,因此,如果先旋转x然后将y旋转,要撤消操作,需要先旋转-y然后旋转-x。

I have achieved the desired result. 我已经达到了预期的结果。 I hope this will be useful for someone. 我希望这对某人有用。

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;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM