• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[General] Calculation of Yaw, Roll, Pitch and Space Rotation for Effects

Status
Not open for further replies.
Level 7
Joined
Feb 9, 2021
Messages
301
I wanted to ask for some help with the math on Yaw, Roll, Pitch and Space Rotation. Unfortunately, my math skills are not the best. I am building a map on 1.26 and , therefore, I use MemoryHack for these functions. However, calculations in this memory hack are not correct. Therefore, I thought that maybe someone knowledgeable about 3D rotation math can help me.

JASS:
// Effect Rotation API Radians
    function GetObjectYawRad takes integer pObject returns real // Z | Yaw | returns Degrees!
        local integer pMatrix   = 0
        local real r11          = 0.
        local real r21          = 0.
        local real r31          = 0.
        local real yaw          = 0.
        local real pitch        = 0.

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                set r11   = ReadRealFloat( pMatrix + 0x108 )
                set r21   = ReadRealFloat( pMatrix + 0x114 )
                set r31   = ReadRealFloat( pMatrix + 0x120 )
                set pitch = -Asin( r31 ) // Atan2( -r31, SquareRoot( Pow( r32, 2 ) + Pow( r33, 2 ) ) )
                set yaw   = -Atan2( r21, r11 )

                if yaw < 0 then
                    set yaw = 6.28319 + yaw
                endif
            endif
        endif

        return yaw
    endfunction

    function GetObjectPitchRad takes integer pObject returns real // Y | returns Degrees!
        local integer pMatrix   = 0
        local real r31          = 0.
        local real r32          = 0.
        local real r33          = 0.
        local real pitch        = 0.

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                set r31   = ReadRealFloat( pMatrix + 0x120 )
                set r32   = ReadRealFloat( pMatrix + 0x124 )
                set r33   = ReadRealFloat( pMatrix + 0x128 )
                set pitch = -Asin( r31 ) // Atan2( -r31, SquareRoot( Pow( r32, 2 ) + Pow( r33, 2 ) ) )

                if r31 < 0. and r33 > 0. then
                    set pitch = pitch
            elseif r31 < 0. and r33 < 0. then
                    set pitch = 3.14159 - pitch
            elseif r31 > 0. and r33 < 0. then
                    set pitch = 3.14159 - pitch
            elseif r31 > 0. and r33 > 0. then
                    set pitch = 6.28319 + pitch
                endif
            endif
        endif
        
        return pitch
    endfunction

    function GetObjectRollRad takes integer pObject returns real // X | returns Degrees!
        local integer pMatrix   = 0
        local real r31          = 0.
        local real r32          = 0.
        local real r33          = 0.
        local real pitch        = 0.
        local real roll         = 0.

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                set r31     = ReadRealFloat( pMatrix + 0x120 )
                set r32     = ReadRealFloat( pMatrix + 0x124 )
                set r33     = ReadRealFloat( pMatrix + 0x128 )
                set pitch   = -Asin( r31 )
                set roll    = Atan2( r32 / Cos( pitch ), r33 / Cos( pitch ) )

                if roll < 0. then
                    set roll = 6.28319 + roll
                endif
            endif
        endif
        
        return roll
    endfunction

    function GetObjectFacingRad takes integer pObject returns real // Z | Yaw | returns Degrees!
        return GetObjectYawRad( pObject )
    endfunction

    function SetObjectSpaceRotationRad takes integer pObject, real yaw, real pitch, real roll returns nothing
        local integer pMatrix = 0
        local real Sx = Sin( roll )
        local real Sy = Sin( pitch )
        local real Sz = Sin( -yaw )
        local real Cx = Cos( roll )
        local real Cy = Cos( pitch )
        local real Cz = Cos( -yaw )

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                call WriteRealFloat( pMatrix + 0x108, Cy * Cz )
                call WriteRealFloat( pMatrix + 0x10C, -Cy * Sz )
                call WriteRealFloat( pMatrix + 0x110, Sy )
                call WriteRealFloat( pMatrix + 0x114, Cz * Sx * Sy + Cx * Sz )
                call WriteRealFloat( pMatrix + 0x118, Cx * Cz - Sx * Sy * Sz )
                call WriteRealFloat( pMatrix + 0x11C, -Cy * Sx )
                call WriteRealFloat( pMatrix + 0x120, -Cx * Cz * Sy + Sx * Sz )
                call WriteRealFloat( pMatrix + 0x124, Cz * Sx + Cx * Sy * Sz )
                call WriteRealFloat( pMatrix + 0x128, Cx * Cy )
            endif
        endif
    endfunction

    function SetObjectYawRad takes integer pObject, real angle returns nothing // Z Yaw | In Degrees!
        local integer pMatrix   = 0
        local real r31          = 0.
        local real r32          = 0.
        local real r33          = 0.
        local real pitch        = 0.
        local real roll            = 0.

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                set r31       = ReadRealFloat( pMatrix + 0x120 )
                set r32       = ReadRealFloat( pMatrix + 0x124 )
                set r33       = ReadRealFloat( pMatrix + 0x128 )
                set pitch     = -Asin( r31 ) //Atan2( -r31, SquareRoot( Pow( r32, 2 ) + Pow( r33, 2 ) ) )
                set roll     = Atan2( r32 / Cos( pitch ), r33 / Cos( pitch ) )

                call SetObjectSpaceRotationRad( pObject, angle, pitch, roll )
            endif
        endif
    endfunction

    function SetObjectPitchRad takes integer pObject, real angle returns nothing // Y | In Degrees!
        local integer pMatrix   = 0
        local real r11          = 0.
        local real r21          = 0.
        local real r32          = 0.
        local real r33          = 0.
        local real yaw          = 0.
        local real roll            = 0.

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                set r11        = ReadRealFloat( pMatrix + 0x108 )
                set r21        = ReadRealFloat( pMatrix + 0x114 )
                set r32       = ReadRealFloat( pMatrix + 0x124 )
                set r33       = ReadRealFloat( pMatrix + 0x128 )
                set yaw     = Atan2( r21 / Cos( angle ), r11 / Cos( angle ) )
                set roll    = Atan2( r32 / Cos( angle ), r33 / Cos( angle ) )

                call SetObjectSpaceRotationRad( pObject, yaw, angle, roll )
            endif
        endif
    endfunction

    function SetObjectRollRad takes integer pObject, real angle returns nothing // X | In Degrees!
        local integer pMatrix   = 0
        local real r11          = 0.
        local real r21          = 0.
        local real r31          = 0.
        local real yaw          = 0.
        local real pitch        = 0.

        if pObject > 0 then
            set pMatrix = ReadRealMemory( pObject + 0x28 )

            if pMatrix > 0 then
                set r11        = ReadRealFloat( pMatrix + 0x108 )
                set r21        = ReadRealFloat( pMatrix + 0x114 )
                set r31       = ReadRealFloat( pMatrix + 0x120 )
                set pitch     = -Asin( r31 ) // Atan2( -r31, SquareRoot( Pow( r32, 2 ) + Pow( r33, 2 ) ) )
                set yaw     = Atan2( r21 / Cos( pitch ), r11 / Cos( pitch ) )

                call SetObjectSpaceRotationRad( pObject, yaw, pitch, angle )
            endif
        endif
    endfunction

    function SetObjectOrientationRad takes integer pObject, real yaw, real pitch, real roll returns nothing
        if pObject > 0 then
            call SetObjectSpaceRotationRad( pObject, yaw, pitch, roll )
            //call SetObjectRollRad( pObject, roll )
            //call SetObjectPitchRad( pObject, pitch )
            //call SetObjectYawRad( pObject, yaw )
        endif
    endfunction
    //===================================================================
    
    // Effect Rotation API Degrees
    function SetObjectSpaceRotation takes integer pObject, real yaw, real pitch, real roll returns nothing
        call SetObjectSpaceRotationRad( pObject, Deg2Rad( yaw ), Deg2Rad( pitch ), Deg2Rad( roll ) )
    endfunction
    
    function GetObjectYaw takes integer pObject returns real // Z | Yaw | returns Degrees!
        return Rad2Deg( GetObjectYawRad( pObject ) )
    endfunction

    function GetObjectFacing takes integer pObject returns real
        return Rad2Deg( GetObjectFacingRad( pObject ) )
    endfunction
    
    function GetObjectPitch takes integer pObject returns real
        return Rad2Deg( GetObjectPitchRad( pObject ) )
    endfunction

    function GetObjectRoll takes integer pObject returns real
        return Rad2Deg( GetObjectRollRad( pObject ) )
    endfunction

    function SetObjectYaw takes integer pObject, real angle returns nothing
        call SetObjectYawRad( pObject, Deg2Rad( angle ) )
    endfunction

    function SetObjectFacing takes integer pObject, real angle returns nothing
        call SetObjectYawRad( pObject, Deg2Rad( angle ) )
    endfunction

    function SetObjectPitch takes integer pObject, real angle returns nothing
        call SetObjectPitchRad( pObject, Deg2Rad( angle ) )
    endfunction

    function SetObjectRoll takes integer pObject, real angle returns nothing
        call SetObjectRollRad( pObject, Deg2Rad( angle ) )
    endfunction

    function SetObjectOrientation takes integer pObject, real yaw, real pitch, real roll returns nothing
        call SetObjectOrientationRad( pObject, Deg2Rad( yaw ), Deg2Rad( pitch ), Deg2Rad( roll ) )
    endfunction
 
Hmm it might be hard for us to help on the specifics since it really depends on what those memory values represent. Does your code at least change the roll/pitch/yaw (even if incorrectly), or does it do nothing at all?

If you're developing for 1.26, then have you looked into non-memory-hack solutions? e.g. using a dummy model with animations to control the pitch, and then attaching your effect to it. Here's an example of what it looks like:
 
Level 7
Joined
Feb 9, 2021
Messages
301
Hmm it might be hard for us to help on the specifics since it really depends on what those memory values represent. Does your code at least change the roll/pitch/yaw (even if incorrectly), or does it do nothing at all?

If you're developing for 1.26, then have you looked into non-memory-hack solutions? e.g. using a dummy model with animations to control the pitch, and then attaching your effect to it. Here's an example of what it looks like:
Yes, I checked other solutions. I want to use effects instead of dummies because they lead to better performance. I build the map for a community with weak pcs and some spells can be very effect heavy. Moreover, I want to use the Relativistic Missle Effect version.

Yes, the code change roll/pitch/yaw (just the math is not correct). It seems like SetObjectSpaceRotationRad works correctly. As far as I understand, r11, r21, r32 and r33 are values from Euler Matrix.

Here is some math on the topic, which is beyond my comprehension: http://www.close-range.com/docs/Computing_Euler_angles_from_a_rotation_matrix.pdf

I can try to get the required info about memory values if someone can help me with math. Just let me know exactly what is necessary.
 
Last edited:
Level 7
Joined
Feb 9, 2021
Messages
301
Hmm it might be hard for us to help on the specifics since it really depends on what those memory values represent. Does your code at least change the roll/pitch/yaw (even if incorrectly), or does it do nothing at all?

If you're developing for 1.26, then have you looked into non-memory-hack solutions? e.g. using a dummy model with animations to control the pitch, and then attaching your effect to it. Here's an example of what it looks like:
names of variables are equal to their name in Euler Matrix
 
Status
Not open for further replies.
Top