Reputation: 836
We are "porting/updating" an old project that uses SDL to render and we are changing the code to use matrix transformations etc..
The main problem is that SDL coordinate system is top-left (0,0) and we would like it to be the center of the window.
We are using this to render:
const auto modelMatrix = (Matrix3::translation(tr.position) * Matrix3::rotation(Magnum::Deg(tr.rotation))) * Matrix3::scaling(tr.scale);
const auto mvpMatrix = viewProjectionMatrix * modelMatrix;
SDL_SetRenderDrawColor(renderer, 0xFF, 0x0, 0x0, 0xFF);
Magnum::Vector2i winSize;
SDL_GetWindowSize(window, &winSize.x(), &winSize.y());
SDL_RenderDrawPointF(renderer, mvpMatrix.translation().x() + (winSize.x() /2), mvpMatrix.translation().y() + (winSize.y() /2));
This is what we tried and seems to "work", because when we have the correct world position in mvpMatrix.translation() we offset that with the (winSize / 2) to let SDL render it to the center of the screen.
We are not happy with this solution and we are not pretty sure if it would work in all scenarios. Is there another way to make this to work? Modifying the Projection Matrix?
Upvotes: 2
Views: 3043
Reputation: 836
We ended doing this conversion:
(IMPORTANT: We inverted the Y axis too here)!
Magnum::Vector2 convertHomogenousCoordsToSDL(SDL_Window* window, const Matrix3& MVP, Magnum::Vector2 vertex) {
// get vertex in homogenous coords
vertex = MVP.transformPoint(vertex);
// now convert from homogenous coords 0,0 center and y-axis up to SDL screen coords
Vector2i winSize;
SDL_GetWindowSize(window, &winSize.x(), &winSize.y());
auto winSizeHalf = Vector2(winSize) / 2.f;
auto matrixChangeCoords = Matrix3::translation(winSizeHalf) * Matrix3::scaling({ winSizeHalf.x(), -winSizeHalf.y() });
vertex = matrixChangeCoords.transformPoint(vertex);
return vertex;
}
Now we can convert any point in our space to SDL window space like this:
const auto modelMatrix = (Matrix3::translation(tr.position) * Matrix3::rotation(Magnum::Deg(tr.rotation))) * Matrix3::scaling(tr.scale);
const auto mvpMatrix = viewProjectionMatrix * modelMatrix;
SDL_SetRenderDrawColor(renderer, 0xFF, 0x0, 0x0, 0xFF);
const auto vertexPosition = helpers::convertHomogenousCoordsToSDL(window, mvpMatrix, { 0,0 });
SDL_RenderDrawPointF(renderer, vertexPosition.x(), vertexPosition.y());
I will not accept this answer to see if something could be improved here!
(EDIT) Encapsulating it and setting the transformation in the ProjectionMatrix like @keltar said in the comments
Magnum::Vector2i framebufferSize(SDL_Window* window) {
Vector2i winSize;
SDL_GetWindowSize(window, &winSize.x(), &winSize.y());
return winSize;
}
Magnum::Matrix3 projectionMatrixToSDLSpace(SDL_Window* window, const Vector2& cameraSize) {
const Vector2 winSizeHalf = Vector2(framebufferSize(window)) / 2.f;
return Matrix3::translation(winSizeHalf) * Matrix3::scaling({ winSizeHalf.x(), -winSizeHalf.y() }) * Magnum::Matrix3::projection(cameraSize);
}
Upvotes: 1