Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_RenderTextureRotated should accept angle in different notations #11279

Open
brainstream opened this issue Oct 20, 2024 · 8 comments · May be fixed by #11353
Open

SDL_RenderTextureRotated should accept angle in different notations #11279

brainstream opened this issue Oct 20, 2024 · 8 comments · May be fixed by #11353
Assignees
Milestone

Comments

@brainstream
Copy link

Currently this function only accepts angle in degrees, however most applications already have angles in radians. Also, box2d 3.0 returns rotation as a pair of sine and cosine. So SDL3 could improve performance if SDL_RenderTextureRotated also accepted a pair of sine and cosine. For this purpose, two helper functions should be added that will build such a structure from degrees and radians.

struct SDL_Rotation {
    float sine;
    float cosine;
};

SDL_Rotation SDL_GetRotationFromRadians(double radians);
SDL_Rotation SDL_GetRotationFromDegrees(double degrees);

In case of box2d 3.0 we can use pre-calculated value.

@icculus
Copy link
Collaborator

icculus commented Oct 24, 2024

Want to say no here, unless @slouken feels strongly about it.

Getting degrees from radians is just:

degrees = radians * (180.0f / SDL_PI_F);

@slouken
Copy link
Collaborator

slouken commented Oct 24, 2024

I think we'll pass on this.

@slouken slouken closed this as not planned Won't fix, can't repro, duplicate, stale Oct 24, 2024
@brainstream
Copy link
Author

Want to say no here, unless @slouken feels strongly about it.

Getting degrees from radians is just:

degrees = radians * (180.0f / SDL_PI_F);

When I use box2d, I have a cosine and a sine. So, I need to call atan2 to get radians, and then I need to convert them to degrees. But SDL will perform the reverse operations and calculate radians from degrees, and then sine and cosine. It looks like an overhead.

@AntTheAlchemist
Copy link
Contributor

@brainstream Trying to warp SDL to bend around box2d's limitations doesn't seem like a good solution. I ended up making my own angle system, which ends up passing an angle to SDL as: angle / ANGLE_DIVISOR. Angle overhead is something you can solve outside of SDL.

@slouken slouken reopened this Oct 24, 2024
@slouken
Copy link
Collaborator

slouken commented Oct 24, 2024

That's an interesting optimization. We do convert the angle to sin/cos in every path that handles rotation. We're not going to change the API for the 3.2.0 release, but we can consider this in the future.

@slouken slouken added this to the 3.x milestone Oct 24, 2024
@slouken slouken self-assigned this Oct 24, 2024
@slouken slouken modified the milestones: 3.x, 3.2.0 Oct 24, 2024
@expikr
Copy link
Contributor

expikr commented Oct 26, 2024

For use cases like this where you already have the rotation basis vectors, it make more sense to just let the user specify the affine parallelogram directly.

This allows them to encompass all of flipping, mirroring, stretching, rotating and shearing.

@expikr expikr linked a pull request Oct 28, 2024 that will close this issue
@expikr
Copy link
Contributor

expikr commented Oct 29, 2024

Hhere's how you could use the proposed SDL_RenderTextureAffine with raw cosine and sines, adapted from examples/renderer/08-rotating-textures.c:

SDL_AppResult SDL_AppIterate(void *appstate) {
    const float winspan = SDL_min(WINDOW_WIDTH, WINDOW_HEIGHT);
    const float texspan = SDL_sqrt((float)(texture_width*texture_width + texture_height*texture_height));
    const float scale = winspan / texspan;

    SDL_FRect dst_rect;
    dst_rect.x = 0.5f * WINDOW_WIDTH;
    dst_rect.y = 0.5f * WINDOW_HEIGHT;
    dst_rect.w = 0.5f * texture_width * scale;
    dst_rect.h = 0.5f * texture_height * scale;

    const Uint64 now = SDL_GetTicks();
    const float rad = (((float) ((int) (now % 4000))) / 4000.0f) * SDL_PI_F * 2;
    const float cos = SDL_cos(rad);
    const float sin = SDL_sin(rad);
    const float xx =  cos * dst_rect.w;
    const float xy =  sin * dst_rect.w;
    const float yx = -sin * dst_rect.h;
    const float yy =  cos * dst_rect.h;

    SDL_FPoint origin, right, down;
    origin.x = dst_rect.x - xx - yx;
    origin.y = dst_rect.y - xy - yy;
    right.x  = dst_rect.x + xx - yx;
    right.y  = dst_rect.y + xy - yy;
    down.x   = dst_rect.x - xx + yx;
    down.y   = dst_rect.y - xy + yy;

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
    SDL_RenderClear(renderer);

    SDL_RenderTextureAffine(renderer, texture, NULL, &origin, &right, &down);
    SDL_RenderPresent(renderer);

    return SDL_APP_CONTINUE;
}

@brainstream
Copy link
Author

@expikr It looks great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants