矩阵变换问题 - Z 轴旋转倾斜

发布于 2024-09-09 20:20:42 字数 3922 浏览 1 评论 0原文

对于我正在制作的一个简单的 2d 游戏,我尝试使用矩阵绕 z 轴旋转精灵。我显然做错了什么,因为当我尝试旋转精灵时,它看起来像是围绕屏幕原点(底部,左侧)而不是精灵原点旋转。我很困惑,因为我的四边形已经在原点了,所以我认为我不需要翻译 ->旋转并平移回来。这是一个代码片段和一个小视频或错误的转换

void MatrixMultiply(
MATRIX      &mOut,
const MATRIX    &mA,
const MATRIX    &mB);
/*!***************************************************************************
@Function           TransTransformArray
@Output         pTransformedVertex  Destination for transformed vectors
@Input              pV                  Input vector    array
@Input              nNumberOfVertices   Number of vectors to transform
@Input              pMatrix             Matrix to transform the vectors of input vector (e.g. use 1 for position, 0 for normal)
@Description        Transform all vertices in pVertex by pMatrix and store them in
                pTransformedVertex
                - pTransformedVertex is the pointer that will receive transformed vertices.
                - pVertex is the pointer to untransformed object vertices.
                - nNumberOfVertices is the number of vertices of the object.
                - pMatrix is the matrix used to transform the object.
*****************************************************************************/
void TransTransformArray(
VECTOR3     * const pTransformedVertex,
const VECTOR3   * const pV,
const int     nNumberOfVertices,
const MATRIX    * const pMatrix);


RenderQuad CreateRenderQuad(
    const Texture2D & texture,
    float x,
    float y,
    float scaleX, 
    float scaleY,
    float rotateRadians,
    int   zIndex,
    const Color & color,
    const Quad2 & textureCoord,
    const char * name
) {
    MATRIX mT;
    MATRIX mS;
    MATRIX concat;  
    MATRIX mR;

    MatrixTranslation(mT, x, y, 0.0f);
    MatrixRotationZ(mR, rotateRadians);
    MatrixScaling(mS, scaleX, scaleY, 1.0f);

    VECTOR3 quad[] = {
        {-0.5f, 0.5f, 0.f}, //tl
        {0.5f, 0.5f, 0.f}, //tr
        {-0.5, -0.5f, 0.0f}, //bl
        {0.5f, -0.5f, 0.0f}, //br
    };

    MatrixMultiply(concat, mR, mT);
    MatrixMultiply(concat, concat, mS);
    // apply to all the points in the quad
    TransTransformArray(quad, quad, 4, &concat);

==更新:

这里是结构和渲染代码:

我正在使用 oolongengine code.google.com/p/oolongengine/source/browse/trunk/Oolong%20Engine2/Math/Matrix.cpp 中的矩阵类,

我转换所有四边形,然后使用OpenGL。这是我的数据结构和渲染代码:

typedef struct _RenderData {
    VECTOR3        vertex;
    RenderColor3D      color;
    RenderTextureCoord textureCoord;
    float              zIndex;
    GLuint             textureId;
} RenderData;

typedef struct _RenderQuad {
    //! top left
    RenderData  tl;
    //! top right
    RenderData  tr;
    //! bottom left
    RenderData  bl;        
    //! bottom right
    RenderData  br;

    float zIndex;

    Texture2D * texture; // render quad draws a source rect from here

    ESpriteBlendMode blendMode;

} RenderQuad ;

/// Draw
class QuadBatch {
   GLushort *              m_indices;
   const Texture2D *       m_texture;
   GLuint                   m_vbos[2];
   RenderData *            m_vertices; 
};

QuadBatch::Draw () {
    int offset = (int)&m_vertices[startIndex];

            // vertex
            int diff = offsetof( RenderData, vertex);
            glVertexPointer(3, GL_FLOAT, kRenderDataSize, (void*) (offset + diff) );

            // color
            diff = offsetof( RenderData, color);
            glColorPointer(4, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));

            // tex coords
            diff = offsetof( RenderData, textureCoord);
            glTexCoordPointer(2, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));

            // each quad has 6 indices

            glDrawElements(GL_TRIANGLES, vertexCount * elementMultiplier, GL_UNSIGNED_SHORT, m_indices);

For a simple 2d game I'm making I'm trying to rotate sprites around the z axis using matrices. I'm clearly doing something wrong as when I attempt to rotate my sprite it looks like it's being rotated around the screen origin (bottom, left) and not the sprite origin. I'm confused as my quad is at the origin already so I didn't think I need to translate -> rotate and translate back. Here's a code snippet and a small video or the erroneous transformation

void MatrixMultiply(
MATRIX      &mOut,
const MATRIX    &mA,
const MATRIX    &mB);
/*!***************************************************************************
@Function           TransTransformArray
@Output         pTransformedVertex  Destination for transformed vectors
@Input              pV                  Input vector    array
@Input              nNumberOfVertices   Number of vectors to transform
@Input              pMatrix             Matrix to transform the vectors of input vector (e.g. use 1 for position, 0 for normal)
@Description        Transform all vertices in pVertex by pMatrix and store them in
                pTransformedVertex
                - pTransformedVertex is the pointer that will receive transformed vertices.
                - pVertex is the pointer to untransformed object vertices.
                - nNumberOfVertices is the number of vertices of the object.
                - pMatrix is the matrix used to transform the object.
*****************************************************************************/
void TransTransformArray(
VECTOR3     * const pTransformedVertex,
const VECTOR3   * const pV,
const int     nNumberOfVertices,
const MATRIX    * const pMatrix);


RenderQuad CreateRenderQuad(
    const Texture2D & texture,
    float x,
    float y,
    float scaleX, 
    float scaleY,
    float rotateRadians,
    int   zIndex,
    const Color & color,
    const Quad2 & textureCoord,
    const char * name
) {
    MATRIX mT;
    MATRIX mS;
    MATRIX concat;  
    MATRIX mR;

    MatrixTranslation(mT, x, y, 0.0f);
    MatrixRotationZ(mR, rotateRadians);
    MatrixScaling(mS, scaleX, scaleY, 1.0f);

    VECTOR3 quad[] = {
        {-0.5f, 0.5f, 0.f}, //tl
        {0.5f, 0.5f, 0.f}, //tr
        {-0.5, -0.5f, 0.0f}, //bl
        {0.5f, -0.5f, 0.0f}, //br
    };

    MatrixMultiply(concat, mR, mT);
    MatrixMultiply(concat, concat, mS);
    // apply to all the points in the quad
    TransTransformArray(quad, quad, 4, &concat);

== Update:

here's the structs and render code:

I'm using the matrix class from the oolongengine code.google.com/p/oolongengine/source/browse/trunk/Oolong%20Engine2/Math/Matrix.cpp

I transform all the quads then later render them using OpenGL. Here are my data structs and render code:

typedef struct _RenderData {
    VECTOR3        vertex;
    RenderColor3D      color;
    RenderTextureCoord textureCoord;
    float              zIndex;
    GLuint             textureId;
} RenderData;

typedef struct _RenderQuad {
    //! top left
    RenderData  tl;
    //! top right
    RenderData  tr;
    //! bottom left
    RenderData  bl;        
    //! bottom right
    RenderData  br;

    float zIndex;

    Texture2D * texture; // render quad draws a source rect from here

    ESpriteBlendMode blendMode;

} RenderQuad ;

/// Draw
class QuadBatch {
   GLushort *              m_indices;
   const Texture2D *       m_texture;
   GLuint                   m_vbos[2];
   RenderData *            m_vertices; 
};

QuadBatch::Draw () {
    int offset = (int)&m_vertices[startIndex];

            // vertex
            int diff = offsetof( RenderData, vertex);
            glVertexPointer(3, GL_FLOAT, kRenderDataSize, (void*) (offset + diff) );

            // color
            diff = offsetof( RenderData, color);
            glColorPointer(4, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));

            // tex coords
            diff = offsetof( RenderData, textureCoord);
            glTexCoordPointer(2, GL_FLOAT, kRenderDataSize, (void*)(offset + diff));

            // each quad has 6 indices

            glDrawElements(GL_TRIANGLES, vertexCount * elementMultiplier, GL_UNSIGNED_SHORT, m_indices);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不…忘初心 2024-09-16 20:20:42

根据定义,“旋转”是围绕原点 (0,0,0) 的。如果您想要不同的旋转轴,则必须应用平移组件。假设您要围绕 a 轴应用旋转 R。应用于任意向量 x 的变换为:

x--> a + R(x - a) = Rx + (a - Ra)

(这可能需要一些凝视才能消化)。因此,应用旋转后(正如您所观察到的,旋转围绕原点旋转),您必须添加常数向量 (a - Ra)。

[编辑:]这个答案与语言和平台无关——无论你看什么,数学都是一样的。特定的库包含不同的结构和 API 来应用转换。例如,DirectX 和 OpenGL 都维护 4x4 矩阵变换,以将旋转和平移统一为单个矩阵乘法(通过称为齐次坐标的装置)。

'Rotation', by definition, is around the origin (0,0,0). If you want a different axis of rotation, you have to apply a Translation component. Say you want to apply a rotation R around an axis a. The transformation to apply to an arbitrary vector x is:

x --> a + R(x - a) = Rx + (a - Ra)

(This might take some staring to digest). So, after applying your rotation - which, as you observed, rotates around the origin - you have to add the constant vector (a - Ra).

[Edit:] This answer is language and platform agnostic - the math is the same wherever you look. Specific libraries contain different structures and API to apply transformations. Both DirectX and OpenGL, for example, maintain 4x4 matrix transforms, to unify rotations and translations into a single matrix multiplication (via an apparatus called homogeneous coordinates).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文