• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] OrientEffect

Working with yaw, pitch, and roll to adjust the orientation of a special effect to a desired direction is tedious, especially since Blizzard defined yaw and roll incorrectly, swapped their definitions, and the order in which they are applied.

This small function takes care of the math required to find the correct yaw, pitch, and roll angles and allows you to orient a special effect directly towards an input vector.

JASS:
library OrientEffect

//============================================================================================
//OrientEffect by Cyclotrutan
//============================================================================================

//This function sets the orientation of a special effect such that it points towards the input
//direction. The special effect model must be pointing towards x-direction by default, such as
//most missile models. It will not work on vertically oriented effects such as StarfallCaster.

//Using the standard definition of yaw, pitch, and roll (which is different from Blizzard's
//definition), the special effect's intrinsic rotation will correspond to roll = 0. As a
//result, there is a discontinuity when the special effect is oriented towards the z-axis.

//There are three possible input functions:

//OrientEffectVector(whichEffect,x,y,z) orients the special effect in the direction of a
//vector with arbitrary length.

//OrientEffectCoordinates(whichEffect,x,y,z) subtracts the special effect's own position and
//orients the special effect in the direction of the input coordinates on the map.

//OrientEffectAngle(whichEffect,phi,theta) orients the special effect towards the azimuthal
//angle phi ranging from 0 to 2pi and the polar angle theta ranging from -pi/2 to pi/2.

//============================================================================================

private function OrientEffect takes effect whichEffect, real x, real y, real z returns nothing
    local real norm
    local real yaw //normal people yaw, blizzard roll
    local real pitch
    local real roll //normal people roll, blizzard yaw
    local real N
    local real cp

    set norm = 1.00001*SquareRoot(x*x + y*y + z*z)

    if norm == 0 then
        return
    endif

    set x = x/norm
    set y = y/norm
    set z = z/norm

    set N = SquareRoot(x*x + y*y)

    if N == 0 then
        if z > 0 then
            call BlzSetSpecialEffectOrientation( whichEffect , 0 , -bj_PI/2 , 0 )
        else
            call BlzSetSpecialEffectOrientation( whichEffect , 0 , bj_PI/2 , 0 )
        endif
        return
    endif

    if y >= 0 then
        set pitch = -Asin(x*z/N)
        set cp = Cos(pitch)
        set roll = Asin(y*z/(N*cp))
        set yaw = Acos(x/cp)
    else
        set pitch = Asin(x*z/N) + bj_PI
        set cp = Cos(pitch)
        set roll = -Asin(y*z/(N*cp)) + bj_PI
        set yaw = Acos(x/cp)
    endif

    call BlzSetSpecialEffectOrientation( whichEffect , roll , pitch , yaw )
endfunction

function OrientEffectVector takes effect whichEffect, real x, real y, real z returns nothing
    call OrientEffect(whichEffect , x , y , z)
endfunction

function OrientEffectCoordinates takes effect whichEffect, real x, real y, real z returns nothing
    call OrientEffect(whichEffect , x - BlzGetLocalSpecialEffectX(whichEffect) , y - BlzGetLocalSpecialEffectY(whichEffect) , z - BlzGetLocalSpecialEffectZ(whichEffect))
endfunction

function OrientEffectAngle takes effect whichEffect, real phi, real theta returns nothing
    call OrientEffect(whichEffect , Cos(phi)*Cos(theta) , Sin(phi)*Cos(theta) , Sin(theta))
endfunction

endlibrary
 
Last edited:
Level 38
Joined
Feb 27, 2007
Messages
4,951
since Blizzard defined yaw and roll incorrectly, swapped their definitions, and the order in which they are applied
Not really a question to you but is there some reason Blizzard cannot change this now?? Those natives are relatively new and it seems preposterous for it not to be fixed when we have people like @Kam and @MindWorX around here all the time.
 
I think my version is more efficient: wurstbin
I don't use wurst, so I translated your version into JASS code so I could use it in my test map. I made a direct comparison of the two methods. While yours is more efficient, mine seems to be more accurate. You can see the left spear flouncing around slightly.

If I made an error during the translation, tell me.
 

Attachments

  • YawPitchRollDemo.w3x
    19.7 KB · Views: 80
It is not incorrect at the angles (I assume you mean 0, pi/2 etc.), but in between. put the two spears in my test map above each other and you'll see it.

I don't know how you derived your formula. I derived mine by expressing the transformed vectors as a function of yaw, pitch, roll, then solving for them analytically. So I know it is correct. It might very well be possible that you can arrive at the correct solution with an easier formula, but yours doesn't seem to do that. I think it is just approximately correct.
 
Last edited:
Level 14
Joined
Jan 16, 2009
Messages
716
It is not incorrect at the angles (I assume you mean 0, pi/2 etc.), but in between. put the two spears in my test map above each other and you'll see it.

Yeah I know I have done so myself.

I don't know how you derived your formula. I think it is just approximately correct.

Yeah it's probably just an approximation. I am trying to see if I can improve it while keeping the low cost of it. In any case, I think it would be great to have both functions since the difference is unnoticeable with a moving missile and you want the efficiency with projectiles.

You can also improve the performance of your function. You have two Cos(pitch) in a row. Not sure if the 1.00001 is useful since there is a baked in epsilon check with the jass comparators and the accuracy is about 0.001. Not sure if there is more, I haven't looked too much into it.
 
I inserted an interim result for the Cos and replaced the Atan2 with a simple y >= 0. The 1.00001 is to prevent the arcus functions from receiving arguments out of their defined range. I figured that adding this factor is easier than adding twenty-thousand IFs. If I made the number any closer to 1, the spear would start to flicker.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Sorry, so if the issue with the swapped parameters has been fixed, then this will need to be updated to reverse the swapping of the parameters. I haven't played around with the new effect natives, yet, but I am going to be looking into them in the near future for some other stuff I'm working on.

Do we have any Lua missile systems which use the effect natives already?
 

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,864
Do we have any Lua missile systems which use the effect natives already?
I feel like this one looks pretty good to be honest.
 
Top