矩阵 - 旋转原点位于左下角的矩形,就好像原点位于中心一样

发布于 2024-12-16 14:58:31 字数 1667 浏览 1 评论 0原文

我正在做一些 OpenGL 编程,绘制 2D 矩形。我正在使用 OpenGL ES 2.0,所以我不能使用 glTranslate/glRotate 等......必须滚动我自己的矩阵。我希望能够为它们设置旋转和缩放值,缩放或旋转的原点根据“对齐”和“对齐”而变化。这段代码对于旋转来说可以正确工作(但是 x,y 坐标似乎仍然有点偏差),但是我怎样才能让缩放工作呢?看来还是想以左下为原点。

vid.xratio/vid.yratio 是当前屏幕与传入的 x、y、宽度和高度的本地坐标系的比率。例如,如果本地坐标基于 640x480 网格,但你的屏幕当前为 1600x1200,坐标 (238, 185) 将是 (595, 462.5)。

const byte picVerts[] = {0, 0, 1, 0, 1, 1, 0, 1};
//
// DrawPictureSize
//
// Draws a picture on the 2D screen, width and height specified.
//
void DrawPictureSize(float x, float y, float width, float height, float scalex, float scaley, Vector::vector_t *upVec, byte alpha, Texture::texture_t *texture, int halignment, int valignment)
{
    if (!texture)
        return;

    float matrix[16];
    Matrix::LoadIdentity(matrix);

    width *= scalex * vid.xratio;
    height *= scaley * vid.yratio;

    float angle = U_Rad2Deg(atan2(upVec->y, upVec->x)) - 90;

    float xalign = 0;
    float yalign = 0;

    // Move into position
    if (halignment == Font::HALIGN_CENTER)
        xalign = width/2;
    else if (halignment == Font::HALIGN_RIGHT)
        xalign = width;
    if (valignment == Font::VALIGN_CENTER)
        yalign = height/2;
    else if (valignment == Font::VALIGN_TOP)
        yalign = height;

    // Move into position
    Matrix::Translate(matrix, x * vid.xratio, y * vid.yratio, 0.0f);

    // Translate to the origin before doing scaling/rotation
    Matrix::Translate(matrix, xalign, yalign, 0);
    Matrix::Rotate(matrix, angle, 0, 0, 1);
    Matrix::Translate(matrix, -xalign, -yalign, 0);

    // Expand square to image size
    Matrix::Scale(matrix, width, height, 1.0f);

I'm doing some OpenGL programming, drawing 2D rectangles. I am using OpenGL ES 2.0, so I cannot use glTranslate/glRotate, etc... have to roll my own matrix. I want to be able to set a rotation and scale value for them, with the origin of scale or rotation varying depending on the 'halignment' and 'valignment'. This code works correctly for the rotation (however the x, y coords still seem a little off), but how can I get the scaling to work? It still seems to want to use the bottom left as the origin.

vid.xratio/vid.yratio is the ratio of the current screen to the local coordinate system that x, y, width, and height are passed in. So for example, if the local coordinates are based on a 640x480 grid, but your screen is currently 1600x1200, the coordinates (238, 185) will be (595, 462.5).

const byte picVerts[] = {0, 0, 1, 0, 1, 1, 0, 1};
//
// DrawPictureSize
//
// Draws a picture on the 2D screen, width and height specified.
//
void DrawPictureSize(float x, float y, float width, float height, float scalex, float scaley, Vector::vector_t *upVec, byte alpha, Texture::texture_t *texture, int halignment, int valignment)
{
    if (!texture)
        return;

    float matrix[16];
    Matrix::LoadIdentity(matrix);

    width *= scalex * vid.xratio;
    height *= scaley * vid.yratio;

    float angle = U_Rad2Deg(atan2(upVec->y, upVec->x)) - 90;

    float xalign = 0;
    float yalign = 0;

    // Move into position
    if (halignment == Font::HALIGN_CENTER)
        xalign = width/2;
    else if (halignment == Font::HALIGN_RIGHT)
        xalign = width;
    if (valignment == Font::VALIGN_CENTER)
        yalign = height/2;
    else if (valignment == Font::VALIGN_TOP)
        yalign = height;

    // Move into position
    Matrix::Translate(matrix, x * vid.xratio, y * vid.yratio, 0.0f);

    // Translate to the origin before doing scaling/rotation
    Matrix::Translate(matrix, xalign, yalign, 0);
    Matrix::Rotate(matrix, angle, 0, 0, 1);
    Matrix::Translate(matrix, -xalign, -yalign, 0);

    // Expand square to image size
    Matrix::Scale(matrix, width, height, 1.0f);

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

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

发布评论

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

评论(1

纵性 2024-12-23 14:58:31

弄清楚了...这是正确的代码,以防它对其他人有帮助

请注意,我删除了对 vid.xratio 和 vid.yratio 的引用...我所做的是在投影矩阵上调用 Matrix::Ortho 之后,我做:

Matrix::Scale(projMatrix, vid.xratio, vid.yratio, 1.0f);

const byte picVerts[] = {0, 0, 1, 0, 1, 1, 0, 1};
//
// DrawPictureSize
//
// Draws a picture on the 2D screen, width and height specified.
//
// Note: 'Set2D' must be called before this!
//
void DrawPictureSize(float x, float y, float width, float height, float scalex, float scaley, Vector::vector_t *upVec, byte alpha, Texture::texture_t *texture, int halignment, int valignment)
{
    if (!texture)
        return;

    float matrix[16];
    Matrix::LoadIdentity(matrix);

    width *= scalex;
    height *= scaley;

    float angle = U_Rad2Deg(atan2(upVec->y, upVec->x)) - 90;

    float xalign = 0;
    float yalign = 0;

    // Move into position
    if (halignment == Font::HALIGN_CENTER)
        xalign = width/2;
    else if (halignment == Font::HALIGN_RIGHT)
        xalign = width;
    if (valignment == Font::VALIGN_CENTER)
        yalign = height/2;
    else if (valignment == Font::VALIGN_TOP)
        yalign = height;

    // Move into position
    Matrix::Translate(matrix, x - xalign, y - yalign, 0.0f);

    // Translate to the origin before doing rotation
    if (angle != 0.0f)
    {
        Matrix::Translate(matrix, xalign, yalign, 0);
        Matrix::Rotate(matrix, angle, 0, 0, 1);
        Matrix::Translate(matrix, -xalign, -yalign, 0);
    }

    // Expand square to image size
    Matrix::Scale(matrix, width, height, 1.0f);

Figured it out... here is the correct code in case it helps someone else

Note that I removed the references to vid.xratio and vid.yratio... what I do instead, is after calling Matrix::Ortho on the projection matrix, I do:

Matrix::Scale(projMatrix, vid.xratio, vid.yratio, 1.0f);

const byte picVerts[] = {0, 0, 1, 0, 1, 1, 0, 1};
//
// DrawPictureSize
//
// Draws a picture on the 2D screen, width and height specified.
//
// Note: 'Set2D' must be called before this!
//
void DrawPictureSize(float x, float y, float width, float height, float scalex, float scaley, Vector::vector_t *upVec, byte alpha, Texture::texture_t *texture, int halignment, int valignment)
{
    if (!texture)
        return;

    float matrix[16];
    Matrix::LoadIdentity(matrix);

    width *= scalex;
    height *= scaley;

    float angle = U_Rad2Deg(atan2(upVec->y, upVec->x)) - 90;

    float xalign = 0;
    float yalign = 0;

    // Move into position
    if (halignment == Font::HALIGN_CENTER)
        xalign = width/2;
    else if (halignment == Font::HALIGN_RIGHT)
        xalign = width;
    if (valignment == Font::VALIGN_CENTER)
        yalign = height/2;
    else if (valignment == Font::VALIGN_TOP)
        yalign = height;

    // Move into position
    Matrix::Translate(matrix, x - xalign, y - yalign, 0.0f);

    // Translate to the origin before doing rotation
    if (angle != 0.0f)
    {
        Matrix::Translate(matrix, xalign, yalign, 0);
        Matrix::Rotate(matrix, angle, 0, 0, 1);
        Matrix::Translate(matrix, -xalign, -yalign, 0);
    }

    // Expand square to image size
    Matrix::Scale(matrix, width, height, 1.0f);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文