- Joined
- Jan 9, 2019
- Messages
- 102
JASS:
library VectorBase requires Alloc
//== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
// _______________
// # VectorBase
// v4.1b, by Overfrost
// ----------------------------
//
// - basically implements Cartesian coordinate system (x,y,z)
//
// - but also spherical system (s,p,t) - sphere-radius, azimuth, zenith angle
//
// - and also cylindrical system (r,p,z) - radius, azimuth, z
//
// - for 2d, both Cartesian(x,y) and polar(r,p) systems can be used
//
// - only (x,y,z) are actually stored, all others are computed on the fly
//
// - has two available struct-modules for implementing vector-usage
// and one struct for basic vector uses
//
// _______________________
// # Technical Details:
//
// - as mentioned above, only stores (x,y,z) values, but also the boolean .inverted
// which helps in storing (theta) that gets within (PI, 2*PI) range, because
// (x,y,z) alone can only handle (theta) within [0, PI] range and not outside that
//
// - only (theta) assignments can automatically change .inverted, this includes .rotate
//
// - other assignments do change (theta), but they always change (theta) to a value
// within [0, PI] range, therefore never triggering any inversions, moreover,
// if .inverted is already true, these assignments will not revert .inverted to false
//
// - angles are in radians
//
// - more info at (hiveworkshop.com/threads/vectorbase.311604)
//
// ______________
// # Requires:
//
// - Alloc (Best)
// github.com/nestharus/JASS/tree/master/jass/Systems/Alloc/Standard
//
//== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
//! novjass
//
module VectorBase
//--------------
// Coordinates
//
real x
real y
real z
//
//-------------
// Magnitudes
//
real s // sigma, spherical radius, 3d length
real r // rho, polar radius, hypotenuse of (x,y)
//
//-------------
// Directions
//
real p // phi, azimuth, xy-angle
real t // theta, declination angle, zr-angle
// - .t is 0 if the vector is directly facing towards the sky
// - both are in radians, and preserves 3d-magnitude
//
boolean inverted
// - only affects .p and .t and doesn't affect (x,y,z)
// - if .inverted is true:
// - .p returns the opposite direction of what it's supposed to return
// - .t refers to the inverted .p instead of the actual .p of (x,y,z)
// - .inverted automatically becomes true when .t gets within (PI, 2*PI) range
// and automatically becomes false when it gets out from that range
//
//---------------
// Helper Macro
//
textmacro VECTOR_BASE_RESET takes INSTANCE
// - sets .x, .y, .z of INSTANCE to 0, and .inverted to false
// - the other fields are pseudo fields, so there's no need to reset them
// - to be used inside a function
// - (this is completely optional and here for ease-of-use only)
//
//
module VectorExt
implement VectorBase
//---------------------
// 3D Multi-assigners
//
method xyz takes real x, real y, real z returns thistype(this)
method spt takes real s, real p, real t returns thistype(this)
method rpz takes real r, real p, real z returns thistype(this)
// - spt and rpz are faster than their separated counterparts
//
//---------------------
// 2D Multi-assigners
//
method xy takes real x, real y returns thistype(this)
method rp takes real r, real p returns thistype(this)
// - both ignores z completely
//
//------------------
// Quick-assigners
//
method revert takes nothing returns thistype(this)
// - sets .inverted to false
//
method invert takes nothing returns thistype(this)
// - inverts .inverted (e.g. true -> false or false -> true)
//
//----------
// Rotator
//
method rotate takes real p, real t returns thistype(this)
// - rotates the vector by both phi and theta
// - if t = 0, the rotation will only affect (x,y)
//
//
struct Vector extends array
implement VectorExt
//----------------
// Static Fields
//
readonly static thistype temp
// - a global instance to be used locally
// - must not be deallocated
//
//-------------
// Allocators
//
static method create takes nothing returns thistype
//
static method unit2 takes real p returns thistype
static method unit3 takes real p, real t returns thistype
// - both creates and returns a vector unit
// - the vector unit has phi/theta as directions and 1 as sphere-radius
//
//---------------
// Deallocators
//
method lock takes nothing returns thistype(this)
method unlock takes nothing returns thistype
// - unlock replaces destroy, it returns 0 if it destroys, (this) otherwise
//
//! endnovjass
//== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ==== ====
//
module VectorBase
//----------------
// stored fields
real x
real y
real z
//
boolean inverted
//-------------
// macroscope
//! textmacro P_VECTOR_BASE_MACROSCOPE takes S, R, P, T
//----------------
// pseudo fields
method operator s takes nothing returns real
return $S$
endmethod
method operator r takes nothing returns real
return $R$
endmethod
//
method operator p takes nothing returns real
if (inverted) then
return $P$ + 3.141592654
endif
return $P$
endmethod
method operator t takes nothing returns real
if (inverted) then
return 6.283185307 - $T$
endif
return $T$
endmethod
//----------------------
// magnitude assigners
method operator s= takes real aS returns nothing
local real lP = $P$
local real lT = $T$
//
set x = aS*Sin(lT)*Cos(lP)
set y = aS*Sin(lT)*Sin(lP)
set z = aS*Cos(lT)
endmethod
method operator r= takes real aR returns nothing
local real lS = $S$
local real lP = $P$
//
set x = aR*Cos(lP)
set y = aR*Sin(lP)
set z = SquareRoot(lS*lS - aR*aR)
endmethod
//----------------------
// direction assigners
method operator p= takes real aP returns nothing
local real lR = $R$
//
if (inverted) then
set aP = aP + 3.141592654
endif
//
set x = lR*Cos(aP)
set y = lR*Sin(aP)
endmethod
method operator t= takes real aT returns nothing
local real lS = $S$
local real lP
//
if (inverted) then
set lP = $P$ + 3.141592654
else
set lP = $P$
endif
//
//
//! endtextmacro
//! runtextmacro P_VECTOR_BASE_MACROSCOPE("SquareRoot(x*x + y*y + z*z)", "SquareRoot(x*x + y*y)", "Atan2(y, x)", "Atan2(SquareRoot(x*x + y*y), z)")
//
set x = lS*Sin(aT)*Cos(lP)
set y = lS*Sin(aT)*Sin(lP)
set z = lS*Cos(aT)
//
//! textmacro P_VECTOR_BASE_INVERT takes T
//
set $T$ = $T$ - R2I($T$*.159154943)*6.283185307 // .159154943 = 1 / 2*PI
if ($T$ < 0) then
set $T$ = $T$ + 6.283185307
endif
//
if ($T$ > 3.141592654) then
set inverted = true
else
set inverted = false
endif
//
//! endtextmacro
//! runtextmacro P_VECTOR_BASE_INVERT("aT")
endmethod
endmodule
module VectorExt
implement VectorBase
//---------------------
// 3d multi-assigners
method xyz takes real aX, real aY, real aZ returns thistype
set x = aX
set y = aY
set z = aZ
//
return this
endmethod
//
method spt takes real aS, real aP, real aT returns thistype
//! textmacro P_VECTOR_BASE_SET_SPT takes S_MUL, P, T
//
set x = $S_MUL$Sin($T$)*Cos($P$)
set y = $S_MUL$Sin($T$)*Sin($P$)
set z = $S_MUL$Cos($T$)
//
//! endtextmacro
//! runtextmacro P_VECTOR_BASE_SET_SPT("aS*", "aP", "aT")
//
//! runtextmacro P_VECTOR_BASE_INVERT("aT")
//
return this
endmethod
//
method rpz takes real aR, real aP, real aZ returns thistype
//! textmacro P_VECTOR_BASE_SET_RPZ takes R_MUL, P, Z
//
set x = $R_MUL$Cos($P$)
set y = $R_MUL$Sin($P$)
set z = $Z$
//
//! endtextmacro
//! runtextmacro P_VECTOR_BASE_SET_RPZ("aR*", "aP", "aZ")
//
return this
endmethod
//---------------------
// 2d multi-assigners
method xy takes real aX, real aY returns thistype
set x = aX
set y = aY
//
return this
endmethod
//
method rp takes real aR, real aP returns thistype
set x = aR*Cos(aP)
set y = aR*Sin(aP)
//
return this
endmethod
//----------------------------
// inversion quick-assigners
method revert takes nothing returns thistype
set inverted = false
//
return this
endmethod
method invert takes nothing returns thistype
set inverted = (not inverted)
//
return this
endmethod
//----------
// rotator
method rotate takes real aP, real aT returns thistype
local real lZ = z
local real lR = SquareRoot(x*x + y*y)
local real lP = Atan2(y, x) + aP
//
if (inverted) then
set aT = -aT
endif
//
set z = lZ*Cos(aT) - lR*Sin(aT)
set lR = lZ*Sin(aT) + lR*Cos(aT)
//
set x = lR*Cos(lP)
set y = lR*Sin(lP)
//
if (inverted) then
set lP = lP - R2I((lP + 3.141592654)*.159154943)*6.283185307 + 3.141592654
else
set lP = lP - R2I(lP*.159154943)*6.283185307
endif
//
set lZ = Atan2(y, x)
if (lZ == lP or (lZ + 6.283185307) == lP or (lZ - 6.283185307) == lP) then
set inverted = false
else
set inverted = true
endif
//
return this
endmethod
endmodule
//
//! textmacro VECTOR_BASE_RESET takes INSTANCE
//
set $INSTANCE$.x = 0
set $INSTANCE$.y = 0
set $INSTANCE$.z = 0
//
set $INSTANCE$.inverted = false
//
//! endtextmacro
//
struct Vector extends array
implement Alloc
implement VectorExt
//----------------
// temp instance
static method operator temp takes nothing returns thistype
return 0
endmethod //inlines
//
private integer pLock
//
static method create takes nothing returns thistype
//! textmacro P_VECTOR_BASE_CREATE
//
local thistype this = allocate()
set pLock = 0
//
//! endtextmacro
//! runtextmacro P_VECTOR_BASE_CREATE()
//
//! runtextmacro VECTOR_BASE_RESET("this")
//
return this
endmethod
//
static method unit2 takes real aP returns thistype
//! runtextmacro P_VECTOR_BASE_CREATE()
//
//! runtextmacro P_VECTOR_BASE_SET_RPZ("", "aP", "0")
//
return this
endmethod
static method unit3 takes real aP, real aT returns thistype
//! runtextmacro P_VECTOR_BASE_CREATE()
//
//! runtextmacro P_VECTOR_BASE_SET_SPT("", "aP", "aT")
//! runtextmacro P_VECTOR_BASE_INVERT("aT")
//
return this
endmethod
//
method lock takes nothing returns thistype
set pLock = pLock + 1
//
return this
endmethod
method unlock takes nothing returns thistype
set pLock = pLock - 1
if (pLock < 0) then
call deallocate()
return 0
endif
return this
endmethod
endstruct
endlibrary
JASS:
scope WeirdElementalOddity initializer pgInit
//
globals
private timer pgTimer = CreateTimer()
//
private effect pgElec
private effect pgCold // note that this one's effect jumps around on its own already
private effect pgFire
//
private Vector pgBase
private Vector pgMoon
private Vector pgLune
//
private real pgPhi = 0
endglobals
//
private function pgOnExpire takes nothing returns nothing
set pgPhi = pgPhi + 0.01
call Vector.temp.rpz(400, pgPhi, 0)
//
set pgBase.t = pgBase.t + 0.02
set pgBase.p = pgBase.p + 0.3
//
call pgMoon.rotate( 0.4, 0.03) // these and above produce the same result
call pgLune.rotate(-0.5, 0.04)
//
call BlzSetSpecialEffectPosition(pgElec, pgBase.x + Vector.temp.x, pgBase.y + Vector.temp.y, pgBase.z + 200)
call BlzSetSpecialEffectPosition(pgCold, pgMoon.x + Vector.temp.x, pgMoon.y + Vector.temp.y, pgMoon.z + 200)
call BlzSetSpecialEffectPosition(pgFire, pgLune.x + Vector.temp.x, pgLune.y + Vector.temp.y, pgLune.z + 200)
endfunction
//
private function pgInit takes nothing returns nothing
set pgElec = AddSpecialEffect("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", 32256, 32256)
set pgCold = AddSpecialEffect("Abilities\\Weapons\\ZigguratFrostMissile\\ZigguratFrostMissile.mdl", 32256, 32256)
set pgFire = AddSpecialEffect("Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl", 32256, 32256)
//
set pgBase = Vector.create().spt(40, 0, 0)
set pgMoon = Vector.create().rp(60, 0)
set pgLune = Vector.create().rp(50, 3.141592654)
//
call TimerStart(pgTimer, 0.03125, true, function pgOnExpire)
//
call FogEnable(false)
call FogMaskEnable(false)
endfunction
endscope
Changelog:
- v4.1b: Optimized t assignment a little.
- v4.1a:
- Re-optimized the script by using textmacros instead of function calls.
- Optimized temp.- v4.0a:
- Swapped the terms phi and theta, and also rho and side. This includes renaming most of the API.
- Renamed VECTOR_BASE_INSTANCE_RESET to VECTOR_BASE_RESET.
- Removed getR, getT, getP, and getS.
- Added temp as a shared local instance.
- Changed the return type of lock and unlock to thistype.- v3.0b: Fixed t and p assignment methods.
- v3.0a:
- Added inverted, invert, and revert.
- Added phi's directional inversion system to allow more practical uses of rotate.
- Also added an optional textmacro for initializing VectorBase's default values.
- Rewritten some of the documentation and comments.- v2.2c: Added important section in documentation.
- v2.2b: Renamed private/local variables to longer names.
- v2.2a: Changed requirement from AllocFast to Alloc.
- v2.1a: Added static methods getR, getT, getP, and getS.
- v2.0a: Removed all module methods but rotate and multi-assigners.
- v1.0b: Reworded some terms in documentation to better clarify things.
References:
- Wikipedia, coordinate systems, Spherical, Cylindrical, Polar.
Last edited: