1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Ride into the sunset with the 32nd Modeling Contest. The contest is optionally paired. Best of luck, people!
    Dismiss Notice
  4. This adventure has come to an end. Congratulate our heroes in the 16th Mini Mapping Contest Results.
    Dismiss Notice
  5. From the gates of hell, the 5th Special Effect Contest Results have emerged.
    Dismiss Notice
  6. Race against the odds and Reforge, Don't Refund. The 14th Techtree Contest has begun!
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[vJASS] OrientEffect

Discussion in 'Submissions' started by Cyclotrutan, Mar 8, 2019.

  1. Cyclotrutan

    Cyclotrutan

    Joined:
    Dec 13, 2009
    Messages:
    181
    Resources:
    2
    Maps:
    2
    Resources:
    2
    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.

    Code (vJASS):
    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: Mar 8, 2019
  2. Pyrogasm

    Pyrogasm

    Joined:
    Feb 27, 2007
    Messages:
    3,788
    Resources:
    1
    Spells:
    1
    Resources:
    1
    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.
     
  3. Wareditor

    Wareditor

    Joined:
    Jan 16, 2009
    Messages:
    681
    Resources:
    3
    Maps:
    3
    Resources:
    3
    I think my version is more efficient: wurstbin
     
  4. Cyclotrutan

    Cyclotrutan

    Joined:
    Dec 13, 2009
    Messages:
    181
    Resources:
    2
    Maps:
    2
    Resources:
    2
    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.
     

    Attached Files:

  5. Wareditor

    Wareditor

    Joined:
    Jan 16, 2009
    Messages:
    681
    Resources:
    3
    Maps:
    3
    Resources:
    3
    I notice there is a slight twitch at the angles, I will correct that.
     
  6. Cyclotrutan

    Cyclotrutan

    Joined:
    Dec 13, 2009
    Messages:
    181
    Resources:
    2
    Maps:
    2
    Resources:
    2
    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: Mar 8, 2019
  7. Wareditor

    Wareditor

    Joined:
    Jan 16, 2009
    Messages:
    681
    Resources:
    3
    Maps:
    3
    Resources:
    3
    Yeah I know I have done so myself.

    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.
     
  8. Cyclotrutan

    Cyclotrutan

    Joined:
    Dec 13, 2009
    Messages:
    181
    Resources:
    2
    Maps:
    2
    Resources:
    2
    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.
     
  9. Anachron

    Anachron

    Joined:
    Sep 9, 2007
    Messages:
    6,221
    Resources:
    66
    Icons:
    49
    Packs:
    2
    Tools:
    1
    Maps:
    3
    Spells:
    9
    Tutorials:
    1
    JASS:
    1
    Resources:
    66
    This issue has been fixed, no?
     
  10. Cyclotrutan

    Cyclotrutan

    Joined:
    Dec 13, 2009
    Messages:
    181
    Resources:
    2
    Maps:
    2
    Resources:
    2
    Yes, this is obsolete now.