• 🏆 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] Spin 3D

Status
Not open for further replies.
Level 17
Joined
Jul 17, 2011
Messages
1,864
it will be easiest to just store each unit's coordinates and each time you rotate it simply set its xyz to those coordinates if you want to have a repetative spin. if you want to make it random then just make a bigger array of points
unit[1]'s polar offset can be towards 30 degrees and 30 z
unit[2]'s offset can be towards 40 degrees and 40 z etc..
then just simply increase these for each unit until you hit a limit of 90 z or something
this is probly more efficient since you wont need to multiply matrices or anything like that :thumbs_up:
 
Level 7
Joined
Jan 30, 2011
Messages
267
ok i made this system:
JASS:
library Spin3D
    struct Spin extends array
        private static constant real timeout = 0.03125
    
        private static thistype counter = 0
        private static thistype firstToRecycle = 0
        private        thistype nextToRecycle
        private        boolean isAllocated
        
        private static thistype first = 0
        private        thistype next
    
    
        private unit spinner
        private unit pivotUnit
                real xOffset
                real yOffset
                real zOffset
        
        private real sin_a
        private real cos_a
        private real sin_b
        private real cos_b
        private real sin_t
        private real cos_t
        
        private real x
        private real y
        
        private static method allocate takes nothing returns thistype
            local thistype this
            if firstToRecycle == 0 then
                set counter = counter+1
                set this = counter
            else
                set this = thistype.firstToRecycle
                set thistype.firstToRecycle = this.nextToRecycle
                set this.nextToRecycle = 0 
            endif
            set next = thistype.first
            set thistype.first = this

            return this
        endmethod
    
        
        public static method add takes real azimuthAngle, real elevationAngle, unit spinner, real spinsPerSec, real distance, unit pivotUnit, real xOffset, real yOffset, real zOffset returns thistype
            local real theta
            local thistype this = thistype.allocate()
            
            set this.spinner = spinner
            set this.pivotUnit = pivotUnit
            
            set theta      = 2*bj_PI*(thistype.timeout/spinsPerSec)            
            set this.cos_t = Cos(theta)
            set this.sin_t = Sin(theta)
            set this.cos_a = Cos(elevationAngle*bj_DEGTORAD)
            set this.sin_a = Sin(elevationAngle*bj_DEGTORAD)
            set this.cos_b = Cos(azimuthAngle*bj_DEGTORAD)
            set this.sin_b = Sin(azimuthAngle*bj_DEGTORAD)
            
            set this.x =  distance // this.cos_a*this.cos_b*distance
            set this.y =  0        // -this.sin_b*distance
            
            set this.xOffset = xOffset
            set this.yOffset = yOffset
            set this.zOffset = zOffset
            
            call UnitAddAbility   (spinner, 'Amrf')
            call UnitRemoveAbility(spinner, 'Amrf')
            call SetUnitPathing   (spinner, false)
            
            return this
        endmethod
        
        private method deallocate takes nothing returns nothing
            set first = this.next
            set this.next = 0
        
            set nextToRecycle = thistype.firstToRecycle
            set thistype.firstToRecycle = this        
        endmethod
        
        public method destroy takes nothing returns nothing      
            set cos_t = 0
            set sin_t = 0
            set cos_a = 0
            set sin_a = 0
            set cos_b = 0
            set sin_b = 0
            
            set x = 0
            set y = 0
            
            set xOffset = 0
            set xOffset = 0
            set zOffset = 0
            
            set spinner = null
            set pivotUnit = null
            
            call this.deallocate()
        endmethod
        
        private static method doSpins takes nothing returns nothing
            local real xt 
            local thistype this = first
            
            loop
                exitwhen this == 0
                
                set xt = cos_t*x - sin_t*y
                set y  = sin_t*x + cos_t*y
                set x  = xt
                
                call SetUnitX(spinner, GetUnitX(pivotUnit) + xOffset + ( cos_a*cos_b*x - sin_b*y))
                call SetUnitY(spinner, GetUnitY(pivotUnit) + yOffset + ( cos_a*sin_b*x + cos_b*y))                
                call SetUnitFlyHeight(spinner, GetUnitFlyHeight(pivotUnit) + ( sin_a*x + zOffset),0)        
                
                set this = this.next
            endloop
        endmethod
        
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), timeout, true, function thistype.doSpins)
            set thistype(0).next = 0
            set thistype(0).nextToRecycle = 0
        endmethod
    endstruct    
endlibrary

private static constant real timeout defines the frequency of the moves
the closer to 0 it is, the swifter the move looks but also the worse the performance is

explanation:
The system allows you to to spin units around other units 3D-wise with offset
This method makes a unit spin:
JASS:
Spin spin = Spin3D.add(azimuthAngle, elevationAngle, spinner, spinsPerSec,
           distance, pivotUnit, xOffset, yOffset, zOffset)
The parameters:
spinner is the unit thats being spinned around a point
the coordinates of the pivotUnit added to the 3 offset coordinates make the spin point (xOffset = 0, yOffset = 0, zOffset = 100 will make the spinner spin around a point 100 units above the pivotUnit, which we call the spinpoint)
spinsPerSec is self explanatory (if you make it negative, it will spin into the other direction)
distance is the distance to the spinpoint

now for the 2 parameters that make the 3D spin: elevationAngle and azimuthAngle
imagine you look at the spinpoint from above (vertically)
then imagine a circle around the spinpoint with radius = distance
the spinner is spinning clockwise along this circle when azimuthAngle and elevationAngle are both 0
when you put other values into azimuthAngle and elevationAngle the circles orientation will change:
we call the elevationPoint the right border of the circle

the azimuthAngle now moves the elevationPoint anti-clockwise on the circle
the elevationAngle grabs the circle at the elevationPoint and lifts it into the air, so that the other side of the circle goes downwards

i've included a testmap
credits to Frankster, who created the fireball model used in the testmap

EDIT: changed local thistype this = 0 to this = 1 in method doSpins
 

Attachments

  • Spin3D.w3x
    30.6 KB · Views: 63
Last edited:
Level 7
Joined
Jan 30, 2011
Messages
267
your welcome ;)
beside that i found a little mistake in my system:
in doSpins the iteration starts at this = 0, but it has to start at this = 1 (fixed it)
beside that i forgot to mention that it should be possible to change the 3 offset variables while a unit is spinning, thats why theyre not private (though i didnt test^^)
 
Level 7
Joined
Jan 30, 2011
Messages
267
with a diagonal spin u mean a spin thats not 100% vertically? so a spin unlike the spins in my example map?
just try different values for elevation angle then
elevationangle = 90 will make it vertically, elevationangle = 45 is 1 possibility for a diagonal
 
Level 7
Joined
Jan 30, 2011
Messages
267
edited my system:
the method destroy was total shit^^
it transferred the data of the last object to the one that got destroy
this of course totally messes up the object reference of the last one
replaced it with a usual linked list system
 
Status
Not open for further replies.
Top