Jump to content

rotate the image 180 degrees


marcelluss

Recommended Posts

Hello dear friends, I had an idea to create some idea related to the rotation of the element, let's say the dxDrawRectangle of the plate by 180 degrees and at the same time with a clear rotation effect!

below is an example, this effect is needed on the player's reflection of this plate, namely on the screen on the graphic design, and not in the world, if you understand me of course

 

spacer.png

Link to comment

Hello marcelluss,

I recommend you to implement an aftershadow to put emphasis on the rotational transition. To achieve this effect you should remember a set of drawing parameters for the rectangle in the time between now and not too distant into the past. The time can be either modelled by the passed-frame count or any time function inside MTA. Then you will have to draw N amount of rectangles instead of a single one. The older the rectangle is the less alpha level it should be rendered with (multiply the original alpha with a new factor).

To get the basic rotation working you need to use the dxDrawMaterialPrimitive3D function in connection with a HLSL pixel shader. First you determine the center point of the rectangle on the screen to draw. Based on that you apply a "3D" matrix in screen-space coordinates around the previously calculated center point and set a decent rotation to it. Also we define an arbitrary distance D in pixels that the image should be away from the camera (minimum is half of the biggest side length of the rectangle). Calculate the 4 rectangle corner points (RCP) of the 3D screen space rotation, finally to calculate the virtual distance VD of each point to the virtual camera (taking D into account), calculating the fraction PS = VD/D and dividing the X,Y coordinates by PS to modell a frustum-based projection ... (you can look further down a post to see a method using dxDrawMaterialPrimitive)

Next we assume that there is no 3D world space software-side vertex clipping being performed by either MTA or the used drawing code (see Remarks). Push the rectangle as draw-call with coordinate z=0 to the Direct3D 9 rasterizer. Inside of the vertex shader we have to multiply the inverse of the D3D9 projection matrix with the received position coordinate (to nullify the multiplication that D3D9 performs by-spec for each vertex). Thus we have received the screen-space coordinates as pushed into the Lua MTA draw-call. Then we do apply the screen-space Direct3D 9 rasterization cross-hair to it, inside of the same vertex shader, as demonstrated by the following image:

d3d9_screen_space_transformation.png

Inside of the pixel shader we set the depth of the vertex to 0. We also disable the depth-test comparison by setting the ZFunc to Never while having depth enabled (maybe optional).

And that should be it. Hopefully this is of help to you.

Good luck! ?

Edited by The_GTA
  • Like 1
Link to comment
9 hours ago, The_GTA said:

Hello marcelluss,

I recommend you to implement an aftershadow to put emphasis on the rotational transition. To achieve this effect you should remember a set of drawing parameters for the rectangle in the time between now and not too distant into the past. The time can be either modelled by the passed-frame count or any time function inside MTA. Then you will have to draw N amount of rectangles instead of a single one. The older the rectangle is the less alpha level it should be rendered with (multiply the original alpha with a new factor).

To get the basic rotation working you need to use the dxDrawMaterialPrimitive3D function in connection with a HLSL pixel shader. First you determine the center point of the rectangle on the screen to draw. Based on that you apply a "3D" matrix in screen-space coordinates around the previously calculated center point and set a decent rotation to it. Calculate the 4 rectangle corner points (RCP) of the 3D screen space rotation. Next we assume that there is no 3D world space software-side vertex clipping being performed by either MTA or the used drawing code (see Remarks). Push the rectangle as draw-call with coordinate z=0 to the Direct3D 9 rasterizer. Inside of the vertex shader we have to multiply the inverse of the D3D9 projection matrix with the received position coordinate (to nullify the multiplication that D3D9 performs by-spec for each vertex). Thus we have received the screen-space coordinates as pushed into the Lua MTA draw-call. Then we do apply the screen-space Direct3D 9 rasterization cross-hair to it, inside of the same vertex shader, as demonstrated by the following image:

d3d9_screen_space_transformation.png

Inside of the pixel shader we set the depth of the vertex to 0. We also disable the depth-test comparison by setting the ZFunc to Never while having depth enabled (maybe optional).

And that should be it. Hopefully this is of help to you.

Good luck! ?

I'm sorry I didn't understand a lot about this function, just not when I didn't work with it, and another question is, isn't this a 3d function? I just need to do it on 2d in terms of drawing it not in the world, namely on the player's screen as a picture (dxDrawImage) and in terms of making such an animation for it, or I misunderstood again and if it's not difficult for you, you can throw off a small example of how to do this just didn't work with this function

Link to comment
1 hour ago, marcelluss said:

I'm sorry I didn't understand a lot about this function, just not when I didn't work with it, and another question is, isn't this a 3d function? I just need to do it on 2d in terms of drawing it not in the world, namely on the player's screen as a picture (dxDrawImage) and in terms of making such an animation for it, or I misunderstood again and if it's not difficult for you, you can throw off a small example of how to do this just didn't work with this function

Actually, you are providing a good assertion here. Instead of the 3D variant you can instead just use the dxDrawMaterialPrimitive function which is the 2D variant. And in that case you can entirely skip the shader part, directly passing the image as material parameter. You can also skip the Direct3D 9 specific projection stuff I posted above. But you do have to perform the steps up to the screen-space matrix rotation, then just pass the vertices to the 2D draw-call. Do you think you'd be up to the task?

EDIT: on a second note, I think I found a fundamental flaw with this approach: the projection that is necessary for your animation to work is not applied. So I have to fix my approach a little. Sorry about that.

Edited by The_GTA
Link to comment
24 minutes ago, The_GTA said:

Actually, you are providing a good assertion here. Instead of the 3D variant you can instead just use the dxDrawMaterialPrimitive function which is the 2D variant. And in that case you can entirely skip the shader part, directly passing the image as material parameter. You can also skip the Direct3D 9 specific projection stuff I posted above. But you do have to perform the steps up to the screen-space matrix rotation, then just pass the vertices to the 2D draw-call. Do you think you'd be up to the task?

as I think without an example I will not understand xD

25 minutes ago, The_GTA said:

Actually, you are providing a good assertion here. Instead of the 3D variant you can instead just use the dxDrawMaterialPrimitive function which is the 2D variant. And in that case you can entirely skip the shader part, directly passing the image as material parameter. You can also skip the Direct3D 9 specific projection stuff I posted above. But you do have to perform the steps up to the screen-space matrix rotation, then just pass the vertices to the 2D draw-call. Do you think you'd be up to the task?

I understood the basic principle that you are trying to convey to me, but I did not work with matrices from the word at all and if you... unless of course it is not difficult for you to show by example how it is done at least a small part of the work I would continue to do myself further

Link to comment

I am deeply sorry marcelluss but you have to take my word for it. This involves creating an entirely new thing not yet present inside of MTA. If you are not the one to follow my instructions then please do wait for anyone else to follow you up on it.

Link to comment
16 hours ago, The_GTA said:

Actually, you are providing a good assertion here. Instead of the 3D variant you can instead just use the dxDrawMaterialPrimitive function which is the 2D variant. And in that case you can entirely skip the shader part, directly passing the image as material parameter. You can also skip the Direct3D 9 specific projection stuff I posted above. But you do have to perform the steps up to the screen-space matrix rotation, then just pass the vertices to the 2D draw-call. Do you think you'd be up to the task?

EDIT: on a second note, I think I found a fundamental flaw with this approach: the projection that is necessary for your animation to work is not applied. So I have to fix my approach a little. Sorry about that.

yesterday, after sitting and thinking about how it could be implemented, I came to an interesting conclusion based on the image in Photoshop! By changing the two starting points, I got the effect that I wanted to see, that is, the rotation effect! But the problem is this: I tried to figure out the dxDrawMaterialPrimitive function and didn't understand how to use it a bit, I also tried to find examples of work on the Internet. The problem is that I can't connect the 4 points I need, I can only make a triangle... Could you explain to me a little principle of correct operation and connection of points using this function?

Link to comment
1 hour ago, marcelluss said:

Could you explain to me a little principle of correct operation and connection of points using this function?

Sure, I think it is helpful to take a look at the MTA wiki's illustration of the pType parameter for said function:

MTAsa_primitives.png

In this image you see the way that the points which you pass into the function are connected to shapes. The incremental set of numbers corresponds to the order in which you pass the points into the function. Vertex is just another word for a point.

I am puzzled about the exact capacity of your question. Is there still anything that is unclear to you about the function's operation? It could be helpful to ask further specific questions. I do acknowledge that you appear to lack a certain capacity about visual to mathematical model translation.

Edited by The_GTA
Link to comment
31 minutes ago, The_GTA said:

Sure, I think it is helpful to take a look at the MTA wiki's illustration of the pType parameter for said function:

MTAsa_primitives.png

In this image you see the way that the points which you pass into the function are connected to shapes. The incremental set of numbers corresponds to the order in which you pass the points into the function. Vertex is just another word for a point.

I am puzzled about the exact capacity of your question. Is there still anything that is unclear to you about the function's operation? It could be helpful to ask further specific questions. I do acknowledge that you appear to lack a certain capacity about visual to mathematical model translation.

oh, I'm sorry that I'm bothering you, of course, at the moment I was able to figure out this function and I'm already starting to create the animation I need, as soon as I'm done with this work, I will definitely share my work in this article so that in the future someone will also be able to use it

Link to comment
  • 4 weeks later...
On 12/01/2022 at 19:28, The_GTA said:

Sure, I think it is helpful to take a look at the MTA wiki's illustration of the pType parameter for said function:

MTAsa_primitives.png

In this image you see the way that the points which you pass into the function are connected to shapes. The incremental set of numbers corresponds to the order in which you pass the points into the function. Vertex is just another word for a point.

I am puzzled about the exact capacity of your question. Is there still anything that is unclear to you about the function's operation? It could be helpful to ask further specific questions. I do acknowledge that you appear to lack a certain capacity about visual to mathematical model translation.

Hello again, I did this rotation animation a little differently and even added a 3d looking animation when the mouse is clamped, but there is only one problem that I can't fix for a long time... Namely, it is associated with rotation. The fact is that after turning the interpolation from 0 to -180 degrees and after that, when I hold down the key to view the plate, I have a mirror image on the other side, well, the problem is that in two versions of dxSetShaderTransform, I use different rotation. If possible, help me with an approximate solution, because I've tried many options and I can't figure out how to make it work better.

 

here is an example video

 

local screen = Vector2(guiGetScreenSize());
local px = ( screen.x / 1920 );

local size = Vector2(634*px, 376*px)
local position = Vector2(screen.x / 2 - size.x / 2, screen.y / 2 - size.y / 2);

local target = dxCreateRenderTarget( size.x, size.y, true );
local backTarget = dxCreateRenderTarget( size.x, size.y, true );

local stateRotation = false;
local rotationX = 0;
local tick = nil;

local swithState = false;
local stateRotationHover = true;

function render()
    if isCursorShowing() then
		mx, my = getCursorPosition();

        local rotX = (screen.x / 2) - mx * screen.x;
        local rotY = (screen.y / 2) - my * screen.y;

        if not stateRotation then
            if getKeyState("mouse1") then
                dxSetShaderTransform(maskShader, rotX / 100, -rotY / 100, 0 )

                print(rotX)
            end
        else
            if tick then
                if not stateRotationHover then
                    rotationX = interpolateBetween(
                        0, 0, 0,
                        -180, 0, 0,
                        ( getTickCount() - tick ) / 1000, "Linear"
                    )
                else
                    rotationX = interpolateBetween(
                        -180, 0, 0,
                        0, 0, 0,
                        ( getTickCount() - tick ) / 1000, "Linear"
                    )
                end

                dxSetShaderTransform(maskShader, rotationX, 0, 0 )
            end
        end
    end

    dxSetRenderTarget(target, true);
        if rotationX <= -90 then
            dxDrawImage(size.x, 0, -size.x, size.y, "assets/rect_box2.png", 0, 0, 0);
        else
            dxDrawImage(0, 0, size.x, size.y, "assets/rect_box.png", 0, 0, 0);
        end
    dxSetRenderTarget()
    dxDrawImage(position.x, position.y, size.x, size.y, maskShader);
end

addEventHandler("onClientClick", root, function(btn, state)
    if state == "down" then else return end;

    if isCursor(position.x, position.y, size.x, size.y) then
        if stateRotationHover then
            if not swithState then
                swithState = true;
                stateRotation = true;

                tick = getTickCount();
                stateRotationHover = false;

                setTimer(function()
                    swithState = false;
                    stateRotation = false;
                end, 1000, 1)
            end 
        elseif not stateRotationHover then
            if not swithState then
                swithState = true;
                stateRotation = true;

                tick = getTickCount();
                stateRotationHover = true;

                setTimer(function()
                    swithState = false;
                    stateRotation = false;
                end, 1000, 1)
            end 
        end
    end
end)

addEventHandler("onClientResourceStart", root, function()

    maskShader = dxCreateShader("assets/mask3d.fx");
	maskTexture = dxCreateTexture("assets/rect_box.png");

	dxSetShaderValue( maskShader, "sPicTexture", target );
	dxSetShaderValue( maskShader, "sMaskTexture", maskTexture );

    addEventHandler("onClientRender", root, render);

    showCursor(true);
end)

function isCursor(x, y, w, h)
    if not isCursorShowing() then return false end;

    local mx, my = getCursorPosition();
    mx = mx * screen.x;
    my = my * screen.y;

    if ( mx >= x ) and ( mx <= x + w ) and ( my >= y ) and ( my <= y + h ) then return true end;
end

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...