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

How to change transformation application order in 'get_camera_matrix()' function #133

Open
dhiahassen opened this issue May 2, 2018 · 2 comments

Comments

@dhiahassen
Copy link

This is get_camera_matrix() function ,i think the order of applying transformations is translation->rotation->scale , i want to re-implement the function so that the order is rotation,scale,translation or rotation,translation,scale or scale,translation,rotation , or scale,rotation,translation ... , it is not so obvious for me , but if i know how it is done , i will be able to fix an issue in sdl_gpu #26


static void get_camera_matrix(float* result)
{
    GPU_CONTEXT_DATA* cdata = (GPU_CONTEXT_DATA*)GPU_GetContextTarget()->context->data;
    GPU_Target* target = cdata->last_target;
    GPU_bool invert = cdata->last_camera_inverted;
	float offsetX, offsetY;

    GPU_MatrixIdentity(result);

    // Now multiply in the projection part
    if(!invert ^ GPU_GetCoordinateMode())
        GPU_MatrixOrtho(result, target->camera.x, target->w + target->camera.x, target->h + target->camera.y, target->camera.y, target->camera.z_near, target->camera.z_far);
    else
        GPU_MatrixOrtho(result, target->camera.x, target->w + target->camera.x, target->camera.y, target->h + target->camera.y, target->camera.z_near, target->camera.z_far);  // Special inverted orthographic projection because tex coords are inverted already for render-to-texture

    // First the modelview part
    offsetX = target->w/2.0f;
    offsetY = target->h/2.0f;
    GPU_MatrixTranslate(result, offsetX, offsetY, 0);
    GPU_MatrixRotate(result, target->camera.angle, 0, 0, 1);
    GPU_MatrixTranslate(result, -offsetX, -offsetY, 0);

    GPU_MatrixTranslate(result, target->camera.x + offsetX, target->camera.y + offsetY, 0);
    GPU_MatrixScale(result, target->camera.zoom_x, target->camera.zoom_y, 1.0f);
    GPU_MatrixTranslate(result, -target->camera.x - offsetX, -target->camera.y - offsetY, 0);

}

@dhiahassen
Copy link
Author

dhiahassen commented May 2, 2018

Finnally i solved that old resisting issue , it was pointed out by several users , anyways , my workaround was , first ; to define a new type :

typedef enum
{
    GPU_TRANSLATE_ROTATE_SCALE,
    GPU_TRANSLATE_SCALE_ROTATE,
    GPU_SCALE_ROTATE_TRANSLATE,
    GPU_SCALE_TRANSLATE_ROTATE,
    GPU_ROTATE_SCALE_TRANSLATE,
    GPU_ROTATE_TRANSLATE_SCALE,
}GPU_TransformationOrderEnum;

then i added a new field of that type to GPU_Camera :

typedef struct GPU_Camera
{
	float x, y, z;
	float angle;
	float zoom_x;
	float zoom_y;
	float z_near, z_far;  // z clipping planes
    GPU_TransformationOrderEnum transformation_order;
} GPU_Camera;

finnally i reimplemented get_camera_matrix() :

#define APPLY_TRANSLATE  GPU_MatrixTranslate(result,- target->camera.x ,- target->camera.y, 0);
#define APPLY_ROTATE \
    GPU_MatrixTranslate(result, offsetX, offsetY, 0); \
    GPU_MatrixRotate(result, target->camera.angle, 0, 0, 1); \
    GPU_MatrixTranslate(result, -offsetX, -offsetY, 0);
#define APPLY_SCALE \
    GPU_MatrixTranslate(result, target->camera.x + offsetX, target->camera.y + offsetY, 0); \
    GPU_MatrixScale(result, target->camera.zoom_x, target->camera.zoom_y, 1.0f); \
    GPU_MatrixTranslate(result, -target->camera.x - offsetX, -target->camera.y - offsetY, 0);


static void get_camera_matrix(float* result)
{
    GPU_CONTEXT_DATA* cdata = (GPU_CONTEXT_DATA*)GPU_GetContextTarget()->context->data;
    GPU_Target* target = cdata->last_target;
    GPU_bool invert = cdata->last_camera_inverted;
	float offsetX, offsetY;

    GPU_MatrixIdentity(result);

    // Now multiply in the projection part
    if(!invert ^ GPU_GetCoordinateMode())
        GPU_MatrixOrtho(result, 0, target->w + 0, target->h + 0, 0, target->camera.z_near, target->camera.z_far);
    else
        GPU_MatrixOrtho(result, 0, target->w + 0, 0, target->h + 0, target->camera.z_near, target->camera.z_far);  // Special inverted orthographic projection because tex coords are inverted already for render-to-texture

    // First the modelview part


    offsetX = target->w/2.0f;
    offsetY = target->h/2.0f;

   switch (target->camera.transformation_order)
   {
    case GPU_TRANSLATE_ROTATE_SCALE:
        APPLY_TRANSLATE
        APPLY_ROTATE
        APPLY_SCALE
    break;
    case GPU_TRANSLATE_SCALE_ROTATE:
        APPLY_TRANSLATE
        APPLY_SCALE
        APPLY_ROTATE
    break;
    case GPU_ROTATE_TRANSLATE_SCALE:
        APPLY_ROTATE
        APPLY_TRANSLATE
        APPLY_SCALE
    break;
    case GPU_ROTATE_SCALE_TRANSLATE:
        APPLY_ROTATE
        APPLY_SCALE
        APPLY_TRANSLATE
    break;
    case GPU_SCALE_TRANSLATE_ROTATE:
        APPLY_SCALE
        APPLY_TRANSLATE
        APPLY_ROTATE
    break;
    case GPU_SCALE_ROTATE_TRANSLATE:
        APPLY_SCALE
        APPLY_ROTATE
        APPLY_TRANSLATE
    break;
   }
}

And :

GPU_Camera GPU_GetDefaultCamera(void)
{
    GPU_Camera cam = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, -100.0f, 100.0f,GPU_TRANSLATE_ROTATE_SCALE};
    return cam;
}

Now the usage is :


GPU_Camera cam = GPU_GetCamera(screen);
     GPU_Camera stored = cam;
     cam.transformation_order = GPU_TRANSLATE_ROTATE_SCALE; // GPU_ROTATE_TRANSLATE_SCALE ...
     cam.angle = ..;
     cam.x = ..;
     cam.y = ...;
     GPU_SetCamera(screen,&cam);
   GPU_RectangleFilled2(screen,GPU_MakeRect(screen->w/2 + 100,screen->h/2,30,30),GPU_MakeColor(255,0,0,255));
   GPU_RectangleFilled2(screen,GPU_MakeRect(screen->w/2 + 0,screen->h/2,100,5),GPU_MakeColor(255,0,0,255));
     GPU_SetCamera(screen,&stored);
```

@grimfang4
Copy link
Owner

At that level of control, I think you might be best off using the matrix functions to construct your own view matrix instead of using GPU_Camera. I'm still willing to build this in, but I'm not totally clear on the use-cases for all of that flexibility.

albertvaka added a commit to albertvaka/sdl-gpu that referenced this issue Oct 4, 2020
Ensure rotation and scale happen after translation, and from the center of the camera.

Fixes grimfang4#133 and grimfang4#124
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

No branches or pull requests

2 participants