【问题标题】:LWJGL - Rotation and movement = problemsLWJGL - 旋转和移动 = 问题
【发布时间】:2015-10-21 20:39:08
【问题描述】:

长话短说,我正在制作一个 LWJGL 引擎,并且正在绘制一个基本的 QUAD。当我绘制这个 QUAD 并使用键盘侦听器时,它可以完美地向上/向下/向左/向右移动。

但是,当我平移和旋转时,它也可以围绕其中心点旋转,如果将它们一起使用,那么就会出现问题。旋转开始偏离轴心,每次移动时,都会绕着其他地方的一个奇怪点旋转。

我怎样才能使我可以移动 QUAD(与旋转无关)以及旋转它?

编辑 1

我发现这个 QUAD 的一个主要问题是,当我旋转它时,我的整个屏幕(包括文本)都会旋转...

我目前的结果:

运动前

移动后(希望你注意到它在一个圆圈中移动,而不是在我向左移动时只是向左移动。)

代码:

(显示设置)

try {
    Display.setDisplayMode(new DisplayMode(width, height));
    Display.setVSyncEnabled(vsync);
    Display.create();
    open = true;

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    // Sets (0, 0) to the top left corner.
    GL11.glOrtho(0, this.width, this.height, 0, 1, -1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
} catch (LWJGLException e) {
    e.printStackTrace();
}

(键盘监听器)

public void userLogic() {
    if (keyboard.isKeyDown(Keyboard.KEY_A)) {
        rect.setLocation(rect.x - 1, rect.y, rect.width, rect.height);
        rect.setRotation(-1);
    } else if (keyboard.isKeyDown(Keyboard.KEY_D)) {
        rect.setLocation(rect.x + 1, rect.y, rect.width, rect.height);
        rect.setRotation(1);
    } if (keyboard.isKeyDown(Keyboard.KEY_W)) {
        rect.setLocation(rect.x, rect.y - 1, rect.width, rect.height);
    } else if (keyboard.isKeyDown(Keyboard.KEY_S)) {
        rect.setLocation(rect.x, rect.y + 1, rect.width, rect.height);
    }
}

(运动/旋转逻辑)

public void setRotation(float degrees) {
    // TODO: Fix whatever the hell the problem is here.
    GL11.glTranslatef(x + (width / 2), y/* + (height / 2)*/, 0);
    GL11.glRotatef(degrees, 0f, 0f, 1f);
    GL11.glTranslatef(-(x + (width / 2)), -(y/* + (height / 2)*/), 0);
}

public void setLocation(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
}

(绘制 QUAD,(与渲染过程的其余部分分离))

public void render() {
    switch(type) {
    case IMAGE:
        // Not ready yet.
        break;
    case TRIANGLE:
        // Not ready yet.
        break;
    case RECTANGLE:
        GL11.glColor3f(colour.red, colour.green, colour.blue);

        // X, Y, WIDTH, HEIGHT are the QUADS coords, not the displays or anything else's.

        GL11.glBegin(GL11.GL_QUADS);
            GL11.glVertex2f(x, y);
            GL11.glVertex2f(x + width, y);
            GL11.glVertex2f(x + width, y + height);
            GL11.glVertex2f(x, y + height);
        GL11.glEnd();
        break;
    }
}

我们将不胜感激任何帮助,如果您要投反对票,请给出一个理由,以便我可以改进这个问题,或者更好的是,改为评论。

【问题讨论】:

    标签: java rotation logic 2d lwjgl


    【解决方案1】:

    这里的问题是您在 setRotationfunction 中调用 OpenGL 的平移和旋转函数的顺序。调用顺序必须是平移(如果有)-> 旋转(如果有)-> 缩放。无论如何,您都无法更改此调用顺序或将它们混淆。否则你不会得到想要的结果。这是因为 OpenGL 内部处理这些命令的方式。

    将您的 SetRotation 函数更改为

    public void setRotation(float degrees) {
        // TODO: Fix whatever the hell the problem is here.
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        GL11.glTranslatef(x , y , 0);       
        GL11.glRotatef(degrees, 0f, 0f, 1f);
    
    }
    

    你会注意到,如果你添加这些行

    GL11.glTranslatef(x , y, 0);
    

    下面

    GL11.glRotatef(degrees, 0f, 0f, 1f);
    

    ,结果会完全不同。意味着顺序很重要。

    userLogic()函数也存在一些问题。这种情况下,需要创建一个全局变量来存储旋转,然后传递给setRotation()

    float rotValue = 0;
    public void userLogic() {
        if (keyboard.isKeyDown(Keyboard.KEY_A)) {
            rect.setLocation(rect.x - 1, rect.y, rect.width, rect.height);
            rotValue-=.1f;
            rotValue=rotValue<0?rotValue+360:rotValue;
            rect.setRotation(rotValue);
        } else if (keyboard.isKeyDown(Keyboard.KEY_D)) {
            rect.setLocation(rect.x + 1, rect.y, rect.width, rect.height);
            rotValue+=.1f;
            rotValue=rotValue>=360?rotValue-360:rotValue;
            rect.setRotation(rotValue);
        } if (keyboard.isKeyDown(Keyboard.KEY_W)) {
            rect.setLocation(rect.x, rect.y - 1, rect.width, rect.height);
        } else if (keyboard.isKeyDown(Keyboard.KEY_S)) {
            rect.setLocation(rect.x, rect.y + 1, rect.width, rect.height);
        }
    }
    

    最后在render() 函数中,传入以(0,0) 为中心的顶点。 glTranslatef 将负责翻译。

    case RECTANGLE:
            GL11.glColor3f(colour.red, colour.green, colour.blue);
            GL11.glBegin(GL11.GL_QUADS);
            GL11.glVertex2f(-width/2, -height/2);
            GL11.glVertex2f(width/2, -height/2);
            GL11.glVertex2f(width/2, height/2);
            GL11.glVertex2f(-width/2, height/2);
            GL11.glEnd();
            GL11.glMatrixMode(GL11.GL_MODELVIEW); //resetting the rotation
            GL11.glLoadIdentity();  //and translation so that other
                                    //objects are unaffected
                break;
    

    这是我制作的一个简单的 lwjgl 项目,展示了四边形和三角形的平移和旋转 https://gist.github.com/Coditivity/0eedc86447a509f6b5ef

    【讨论】:

    • 这不起作用。所有这一切都是从我整个屏幕的左上角旋转它。我还有一个问题,它不仅会旋转正方形,还会旋转我屏幕上的所有内容!
    • 这是因为您在完成任何操作之前重置了翻译。因此,如果我这样做,添加任何代码都没有意义。
    • 我已经编辑了答案。现在它应该可以工作了。您需要将活动矩阵更改为 MODEL_VIEW 并将其初始化为单位矩阵。由于这些翻译相互抵消,你应该得到一个旋转的正方形。
    • 嗯...什么都没有改变...。我创建了一个名为旋转的int,并使其等于我想要更改的度数。所以它仍然在旋转,但仍然从原点开始......
    • 我添加了一些最终修复。这段代码在我制作的测试 lwjgl 项目上运行良好。我应该测试我之前发布的代码,抱歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 2014-07-02
    相关资源
    最近更新 更多