首页 > 解决方案 > 我如何在世界空间中移动这些顶点而不是在本地空间中移动?

问题描述

我正在使用“Dynamic Batch Renderer System”,并且我有一个具有函数的“Object.cpp”,当它被调用时,它返回批处理在屏幕上渲染“Quad”所需的数据(我也是我会提到这是在 3D 空间中,所以存在 Z 移动、Z 缩放和 XY 旋转)。

对于数学计算,我使用的是GLM 库

渲染效果很好,批次也很好,问题是运动。旋转实际上按照我想要的方式工作,但是我不满意的是运动,因为它在对象的“局部空间”中移动。这意味着,例如,如果我在 Y 轴上将批次内的对象旋转 90°,则 X 移动变为 Z 移动,并且 Z 移动变为 X 移动

我一直在寻找答案,但我找不到任何东西。我认为问题可能来自允许对象正确旋转的“rotationMatrix”,但我不知道是否需要添加额外的“功能”才能将对象移动到“世界空间”而不是“本地空间”,如果有,我不知道“功能”是什么。

现在我将把“Object.cpp”的整个代码放在这里,这样你们就可以看到它是如何工作的。

Object::Object(glm::vec3 pos, glm::vec3 rot, glm::vec3 sca, int ObjId)
            : translationMatrix(glm::mat4(0)), rotationMatrix(glm::mat4(0))
        {
            id = ObjId;
            position = pos;
            lastPosition = pos + glm::vec3(1.0f);
            scale = sca;
            rotation = rot;
            lastRotation = rot + glm::vec3(1.0f);
        }
    
        glm::mat4 One(1.0f);
        Vertex* Object::UpdateObject(Vertex* target)
        {
            if (lastPosition != position)
            {
                translationMatrix = glm::translate(glm::identity<glm::mat4>(), -position);
                lastPosition = position;
            }

            if (lastRotation != rotation)
            {
                glm::mat4 rotMatrixTemp(1.0f);
                rotMatrixTemp = glm::rotate(rotMatrixTemp, glm::radians(rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
                rotMatrixTemp = glm::rotate(rotMatrixTemp, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
                rotMatrixTemp = glm::rotate(rotMatrixTemp, glm::radians(rotation.z + 180.0f), glm::vec3(0.0f, 0.0f, 1.0f));

                rotationMatrix = -translationMatrix * rotMatrixTemp * translationMatrix;
                lastRotation = rotation;
            }

            float x = 1.0f, y = 1.0f;
            if (flipX)
                x *= -1;
            if (flipY)
                y *= -1;

            target->position = rotationMatrix * glm::vec4(position.x - 0.5f * scale.x, position.y + 0.5f * scale.y, position.z, 1.0f);
            target->color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
            target->texcoord = glm::vec2(0.0f, y);
            target++;

            target->position = rotationMatrix * glm::vec4(position.x - 0.5f * scale.x, position.y - 0.5f * scale.y, position.z, 1.0f);
            target->color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
            target->texcoord = glm::vec2(0.0f, 0.0f);
            target++;

            target->position = rotationMatrix * glm::vec4(position.x + 0.5f * scale.x, position.y - 0.5f * scale.y, position.z, 1.0f);
            target->color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
            target->texcoord = glm::vec2(x, 0.0f);
            target++;

            target->position = rotationMatrix * glm::vec4(position.x + 0.5f * scale.x, position.y + 0.5f * scale.y, position.z, 1.0f);
            target->color = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f);
            target->texcoord = glm::vec2(x, y);
            target++;

            return target;
        }

所以,回顾一下,我想要完成的是在“世界空间”而不是“局部空间”中移动这些对象(同时,如果可能的话,将旋转系统保持在“局部空间”中。因为否则对象的中心总是 (0, 0, 0) 而不是它自己的位置)。

标签: c++openglglm-mathindicesvertex

解决方案


要在世界中以给定的方向定位对象,通常先应用旋转,然后再应用平移,除非您确实在平移后尝试围绕原点旋转对象。所以要么检查一下,要么确保你有充分的理由让 translationMatrix 在

rotationMatrix = -translationMatrix * rotMatrixTemp * translationMatrix

因为看起来你在 if 块内外都有翻译逻辑


推荐阅读