Snippet Vectors

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Dirac:
1. I think that has already been answered for you
http://www.thehelper.net/forums/show...LocInclination

1. The math seams different. There is no v.z = sampleRadius*sampleRadius in your thing.

And you didn't address my other questions:
"Is this the same thing as calculating a "surface normal"? Why isn't the resultant vector normalized?
 

Bribe

vJass errors are legion
Reaction score
67
A better question would have been why is he using a local location instead of a global, why it is a memory leak when used and why he doesn't even null the handle.

Just use Anitarf's Vector or get him to add the features you want, or make an extension to his vector. Too many vector libraries and most of them are better left unused.
 

krainert

Member
Reaction score
10
Ugh, sorry guy, I forgot to check back.

A better question would have been why is he using a local location instead of a global, why it is a memory leak when used and why he doesn't even null the handle.
People requested the addition of miscellaneous functionality found in Anitarf's Vector library, and I used his base implementation in my code. That was a while back, though, so I might have missed some leaks.

Just use Anitarf's Vector [...]
This library seems fairly used (and hence reliable), but looking at Anitarf's code, its terrain normal function is borderline identical to mine. Hence, you might want to let him know if there is a leak in my implementation since it is then highly likely to be present in his as well.
EDIT: Nope, Anitarf knew better ;)

Anyway, I'll just have a look at the terrain normal algorithm and see if I can make some sense of it.
What did you mean by nulling the handle, and which memory leak are you referring to, precisely?
EDIT: Regarding the memory leak and the local/global location: I guess I found my answer here: http://www.thehelper.net/forums/showthread.php/167173-GetLocInclination?p=1371335#post1371335 (as referenced)
Also, by the way, noticed any other flaws I should look at, Bribe?

Thanks for the input.
 

luorax

Invasion in Duskwood
Reaction score
67
JASS:
static method createTerrainNormal takes real x, real y, real sampleRadius returns Vector3D
    local Vector3D v = Vector3D.allocate()
    local real zx
    local real zy
    local location loc = Location(0.0, 0.0)
    call MoveLocation(loc, x-sampleRadius, y)
    set zx = GetLocationZ(loc)
    call MoveLocation(loc, x+sampleRadius, y)
    set zx = zx-GetLocationZ(loc)
    call MoveLocation(loc, x, y-sampleRadius)
    set zy = GetLocationZ(loc)
    call MoveLocation(loc, x, y+sampleRadius)
    set zy = zy-GetLocationZ(loc)
    set sampleRadius = 2*sampleRadius
    set v.x = zx*sampleRadius
    set v.y = zy*sampleRadius
    set v.z = sampleRadius*sampleRadius
    return v
endmethod


This leaks, since location variables must be nulled and the location is actually never destroyed. Also:

JASS:
private static location loc=Location(0.,0.)
static method createTerrainNormal takes real x, real y, real sampleRadius returns Vector3D
    local Vector3D v = Vector3D.allocate()
    local real zx
    local real zy
    call MoveLocation(thistype.loc,x-sampleRadius,y)
    set zx=GetLocationZ(thistype.loc)
    call MoveLocation(thistype.loc,x+sampleRadius,y)
    set zx=zx-GetLocationZ(thistype.loc)
    call MoveLocation(thistype.loc,x,y-sampleRadius)
    set zy=GetLocationZ(thistype.loc)
    call MoveLocation(thistype.loc,x,y+sampleRadius)
    set zy=zy-GetLocationZ(thistype.loc)
    set sampleRadius=2*sampleRadius
    set v.x=zx*sampleRadius
    set v.y=zy*sampleRadius
    set v.z=sampleRadius*sampleRadius
    return v
endmethod
 

krainert

Member
Reaction score
10
Aha, thanks.

I'll just read up on JASS optimization (which I should've probably done in the first place) and optimize the library. Then I'll get back to you!
 

krainert

Member
Reaction score
10
Right.

Regarding terrain normal:
This function returns an estimated normal vector to the terrain surface at point (x,y) where x and y are parameters of the function. Terrain height values are acquired at points (x-sampleRadius,y), (x+sampleRadius,y), (x,y-sampleRadius), and (x,y+sampleRadius), and the magnitude of the returned vector is 2*sampleRadius*sqrt(zx^2+zy^2) = 2*sampleRadius*sqrt((a-b)^2+(c-d)^2) where a, b, c, and d are the terrain height values at the four sample points, respectively and in the order mentioned. That is, zx=a-b and zy=c-d. To be exact, v=(2*sampleRadius*zx, 2*sampleRadius*zy, 4*sampleRadius^2) where v is the returned estimated normal vector.
Correct?

EDIT: Optimization question: Should I initialize and nullify my static location instance before and after every use, respectively, or leave it untouched? I suppose the different in performance in this case is negligible.

EDIT 2: Regarding optimization: Well, fixing the location thing seems to be all the optimization it needed, amrite?
 

krainert

Member
Reaction score
10
Roger.

Thank you all for putting up with my current display of amateurishness... I'll get back to you once I've run some tests.
 

Trollvottel

never aging title
Reaction score
262
Question:
Am i missing something or is this:
JASS:
  method angle takes Vector3D v returns real
        return Acos(dotProduct(v))
    endmethod


wrong? normally cos(a) = dotproduct / product of lengths <=> a = Acos(dotproduct / product of lengths)

so this would only work for vectors that have a length of 1, right?
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
krainert:
1. This function returns an estimated normal vector to the terrain surface at point (x,y) where x and y are parameters of the function. Terrain height values are acquired at points (x-sampleRadius,y), (x+sampleRadius,y), (x,y-sampleRadius), and (x,y+sampleRadius), and the magnitude of the returned vector is 2*sampleRadius*sqrt(zx^2+zy^2) = 2*sampleRadius*sqrt((a-b)^2+(c-d)^2) where a, b, c, and d are the terrain height values at the four sample points, respectively and in the order mentioned. That is, zx=a-b and zy=c-d. To be exact, v=(2*sampleRadius*zx, 2*sampleRadius*zy, 4*sampleRadius^2) where v is the returned estimated normal vector.

1. Well tnx for translating the script in English but this tells nothing about the underling math that actually make it work.

PS: Kudos to the dude that originally worked it out =).
 

krainert

Member
Reaction score
10
1. Well tnx for translating the script in English but this tells nothing about the underling math that actually make it work.

PS: Kudos to the dude that originally worked it out =).

I actually did most of a proof while trying to sort it out on a whiteboard... I'll upload a pic I took in a bit.

EDIT:
Wauw, it's even more unintelligible than I thought. Have a look, though:
http://peecee.dk/uploads/102011/2011-10-26-20-31-25-710.jpg
 

krainert

Member
Reaction score
10
Here's version 5.0:
JASS:
library Vectors

//********************************************************************************************************************************
//* Vectors
//*  
//*  ABOUT
//*   Author:   krainert
//*   Version:  5.0
//*   
//*  DESCRIPTION
//*   This library provides two vector structs:
//*   - Vector2D representing a two-dimensional vector
//*   - Vector3D representing a three-dimensional vector
//*   Note: All angles are in radians
//*   
//*  STRUCTS
//*   ======== Vector2D ========
//*    -- Description
//*     Represents a two-dimensional vector
//*    -- Methods
//*     static Vector2D create(Vector2D v)                                      - returns a new vector as a clone of &#039;v&#039;
//*     static Vector2D createXY(real x, real y)                                - returns a new vector with x coordinate &#039;x&#039; and y coordinate &#039;y&#039;
//*     static Vector2D createDM(real d, real m)                                - returns a new vector with direction &#039;d&#039; and magnitude &#039;m&#039;
//*     static Vector2D createNull()                                            - returns a new vector with x and y coordinates 0
//*     Vector2D clone()                                                        - returns a new vector as a clone of this vector
//*     real     getX()                                                         - returns the x coordinate of this vector
//*     real     getY()                                                         - returns the y coordinate of this vector
//*     real     getDir()                                                       - returns the direction of this vector
//*     real     getMag()                                                       - returns the magnitude of this vector
//*     Vector2D setX(real x)                                                   - sets the x coordinate of this vector to &#039;x&#039; and returns the result
//*     Vector2D setY(real y)                                                   - sets the y coordinate of this vector to &#039;y&#039; and returns the result
//*     Vector2D setDir(real d)                                                 - sets the direction of this vector to &#039;d&#039; and returns the result
//*     Vector2D setMag(real m)                                                 - sets the magnitude of this vector to &#039;m&#039; and returns the result
//*     real     dotProduct(Vector2D v)                                         - returns the dot product of this vector and &#039;v&#039;
//*     real     angle(Vector2D v)                                              - returns the angle between this vector and &#039;v&#039;
//*     Vector2D unit()                                                         - sets the magnitude of this vector to 1 and returns the result
//*     Vector2D flip()                                                         - sets the x coordinate of this vector to its previous y coordinate and the y coordinate of this vector to its previous x coordinate and returns the result
//*     Vector2D invert()                                                       - sets the x coordinate of this vector to the inverse of its previous x coordinate and the y coordinate of this vector to the inverse of its previous y coordinate and returns the result
//*     Vector2D scale(real s)                                                  - scales this vector by an amount equal to &#039;s&#039; and returns the result
//*     Vector2D add(Vector2D v)                                                - adds &#039;v&#039; to this vector and returns the vector
//*     Vector2D sub(Vector2D v)                                                - subtracts &#039;v&#039; from this vector and returns the result
//*     Vector2D addXY(real x, real y)                                          - adds a vector with x coordinate &#039;x&#039; and y coordinate &#039;y&#039; to this vector and returns the result
//*     Vector2D subXY(real x, real y)                                          - subtracts a vector with x coordinate &#039;x&#039; and y coordinate &#039;y&#039; from this vector and returns the result
//*     Vector2D addDM(real d, real m)                                          - adds a vector with direction &#039;d&#039; and magnitude &#039;m&#039; to this vector and returns the result
//*     Vector2D subDM(real d, real m)                                          - subtracts a vector with direction &#039;d&#039; and magnitude &#039;m&#039; from this vector and returns the result
//*   ======== Vector3D ========
//*    -- Description
//*     Represents a three-dimensional vector
//*    -- Methods
//*     static Vector3D create(Vector3D v)                                      - returns a new vector as a clone of &#039;v&#039;
//*     static Vector3D createXYZ(real x, real y, real z)                       - returns a new vector with x coordinate &#039;x&#039;, y coordinate &#039;y&#039;, and z coordinate &#039;z&#039;
//*     static Vector3D createNull()                                            - returns a new vector with x, y, and z coordinates 0
//*     static Vector3D createTerrainNormal(real x, real y, real sampleRadius)  - returns a new vector representing the normal of the terrain at the location with x coordinate &#039;x&#039; and y coordinate &#039;y&#039; with sample radius &#039;sampleRadius&#039;
//*     Vector3D clone()                                                        - returns a new vector as a clone of this vector
//*     real     getX()                                                         - returns the x coordinate of this vector
//*     real     getY()                                                         - returns the y coordinate of this vector
//*     real     getZ()                                                         - returns the z coordinate of this vector
//*     real     getMag()                                                       - returns the magnitude of this vector
//*     Vector3D setX(real x)                                                   - sets the x coordinate of this vector to &#039;x&#039; and returns the result
//*     Vector3D setY(real y)                                                   - sets the y coordinate of this vector to &#039;y&#039; and returns the result
//*     Vector3D setZ(real z)                                                   - sets the z coordinate of this vector to &#039;z&#039; and returns the result
//*     Vector3D setMag(real m)                                                 - sets the magnitude of this vector to &#039;m&#039; and returns the result
//*     real     dotProduct(Vector3D v)                                         - returns the dot product of this vector and &#039;v&#039;
//*     real     tripleProductScalar(Vector3D v1, Vector3D v2)                  - returns the tripple scalar product of this vector, &#039;v1&#039;, and &#039;v2&#039;
//*     real     angle(Vector3D v)                                              - returns the angle between this vector and &#039;v&#039;
//*     Vector3D crossProduct(Vector3D v)                                       - sets this vector to the cross product of itself and &#039;v&#039; and returns the result
//*     Vector3D tripleProductVector(Vector3D v1, Vector3D v2)                  - sets this vector to the tripple scalar product of itself, &#039;v1&#039;, and &#039;v2&#039; and returns the result
//*     Vector3D projectionVector(Vector3D dir)                                 - sets this vector to the projection of itself onto the line through vector &#039;dir&#039; and returns the result
//*     Vector3D projectionPlane(Vector3D normal)                               - sets this vector to the projection of itself onto the plane with normal vector &#039;normal&#039; and returns the result
//*     Vector3D unit()                                                         - sets the magnitude of this vector to 1 and returns the result
//*     Vector3D invert()                                                       - sets the x coordinate of this vector to the inverse of its previous x coordinate, the y coordinate of this vector to the inverse of its previous y coordinate, and the z coordinate of this vector to the inverse of its previous z coordinate and returns the result
//*     Vector3D scale(real s)                                                  - scales this vector by an amount equal to &#039;s&#039; and returns the result
//*     Vector3D rotate(Vector3D axis, real angle)                              - rotates this vector around the line through &#039;axis&#039; by an amount equal to &#039;angle&#039; and returns the result
//*     Vector3D add(Vector3D v)                                                - adds &#039;v&#039; to this vector and returns the result
//*     Vector3D sub(Vector3D v)                                                - subtracts &#039;v&#039; from this vector and returns the result
//*     Vector3D addXYZ(real x, real y, real z)                                 - adds a vector with x coordinate &#039;x&#039;, y coordinate &#039;y&#039;, and z coordinate &#039;z&#039; to this vector and returns the result
//*     Vector3D subXYZ(real x, real y, real z)                                 - subtracts a vector with x coordinate &#039;x&#039;, y coordinate &#039;y&#039;, and z coordinate &#039;z&#039; from this vector and returns the result
//*     
//*  CHANGELOG
//*   1.0  2011-07-08  Original release
//*   2.0  2011-07-13  vector redesigned and renamed to Vector2D
//*                    Vector3D added
//*   2.1  2011-07-17  modDir, modMag, and accumulative operations added to Vector2D
//*   2.2  2011-08-04  setMag added to Vector3D
//*                    crossProduct, tripleProductScalar, tripleProductVector, projectionVector, projectionPlane, rotate, mRotate, and static createTerrainNormal added to Vector3D
//*                    Note: the implementations of the above methods were inspired by Anitarf&#039;s Vector library
//*                    setMag optimized in Vector2D
//*                    Operator &lt; overloaded for Vector2D: returns true if the magnitude of this vector is lower than the magnitude of the other vector, false otherwise
//*                    Operator &lt; overloaded for Vector3D: returns true if the magnitude of this vector is lower than the magnitude of the other vector, false otherwise
//*                    Operator == overloaded for Vector2D: returns true if the x and y coordinates of this vector are equal to the x and y coordinates of the other vector respectively, false otherwise
//*                    Operator == overloaded for Vector3D: returns true if the x, y, and z coordinates of this vector are equal to the x, y, and z coordinates of the other vector respectively, false otherwise
//*   2.3  2011-08-05  getMag, getDir, setMag, setDir, addXY, subXY, mAddXY, and mSubXY in Vector2D relocated to prevent trigger evaluation
//*                    getMag, setMag, addXYZ, subXYZ, mAddXYZ, and mSubXYZ in Vector3D relocated to prevent trigger evaluation
//*   3.0  2011-10-24  Extensive API modifications and reductions
//*   4.0  2011-10-31  crossProduct, trippleProductVector, projectionVector, and projectionPlane in Vector3D changed into mutators
//*                    Miscellaneous corrections
//*   5.0  2012-01-16  Debug mode exclusive error messages added to Vector2D and Vector3D
//*                    Empty onDestroy methods removed from Vector2D and Vector3D
//*                    Documentation updated
//*   
//********************************************************************************************************************************

globals
    private constant integer MAX_2D = 8191
    private constant integer MAX_3D = 8191
    debug private constant string ERR_NULL_VECT_DIR = &quot;the direction of null vectors is undefined&quot;
endglobals

struct Vector2D[MAX_2D]
    private real x
    private real y
    
    static if debug then
        static method err takes string message returns nothing
            call BJDebugMsg(&quot;[Vector2D] ERROR: &quot; + message)
        endmethod
    endif
    
    static method create takes thistype v returns thistype
        local thistype r = .allocate()
        set r.x = v.x
        set r.y = v.y
        return r
    endmethod
    
    static method createXY takes real x, real y returns thistype
        local thistype r = .allocate()
        set r.x = x
        set r.y = y
        return r
    endmethod
    
    static method createDM takes real d, real m returns thistype
        local thistype r = .allocate()
        set r.x = Cos(d)*m
        set r.y = Sin(d)*m
        return r
    endmethod
    
    static method createNull takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = 0
        set r.y = 0
        return r
    endmethod
    
    method clone takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = .x
        set r.y = .y
        return r
    endmethod
    
    method getX takes nothing returns real
        return .x
    endmethod
    
    method getY takes nothing returns real
        return .y
    endmethod
    
    method getDir takes nothing returns real
        static if debug then
            if .x == 0 and .y == 0 then
                call err(&quot;getDir(): &quot; + )
            endif
        endif
        return Atan2(.y, .x)
    endmethod
    
    method getMag takes nothing returns real
        return SquareRoot(.x*.x+.y*.y)
    endmethod
    
    method setX takes real x returns thistype
        set .x = x
        return this
    endmethod
    
    method setY takes real y returns thistype
        set .y = y
        return this
    endmethod
    
    method setDir takes real d returns thistype
        local real m
        static if debug then
            if .x == 0 and .y == 0 then
                call err(&quot;setDir(&quot; + R2S(d) + &quot;): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set m = .getMag()
        set .x = Cos(d)*m
        set .y = Sin(d)*m
        return this
    endmethod
    
    method setMag takes real m returns thistype
        local real f
        if m == 0 then
            set .x = 0
            set .y = 0
            return this
        endif
        static if debug then
            if .x == 0 and .y == 0 then
                call err(&quot;setMag(&quot; + R2S(m) + &quot;): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set f = m/.getMag()
        set .x = f*.x
        set .y = f*.y
        return this
    endmethod
    
    method dotProduct takes thistype v returns real
        return .x*v.x+.y*v.y
    endmethod
    
    method angle takes thistype v returns real
        static if debug then
            if (.x == 0 and .y == 0) or (v.x == 0 and v.y == 0) then
                call err(&quot;angle({Vector2D|x=&quot; + v.x + &quot;,y=&quot; + v.y + &quot;}): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        return Acos(.dotProduct(v)/(.getMag()*v.getMag()))
    endmethod
    
    method unit takes nothing returns thistype
        local real m
        static if debug then
            if .x == 0 and .y == 0 then
                call err(&quot;unit(): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set m = .getMag()
        set .x = .x/m
        set .y = .y/m
        return this
    endmethod
    
    method flip takes nothing returns thistype
        local real x = .x
        set .x = .y
        set .y = x
        return this
    endmethod
    
    method invert takes nothing returns thistype
        set .x = -.x
        set .y = -.y
        return this
    endmethod
    
    method scale takes real s returns thistype
        set .x = s*.x
        set .y = s*.y
        return this
    endmethod
    
    method add takes thistype v returns thistype
        set .x = .x+v.x
        set .y = .y+v.y
        return this
    endmethod
    
    method sub takes thistype v returns thistype
        set .x = .x-v.x
        set .y = .y-v.y
        return this
    endmethod
    
    method addXY takes real x, real y returns thistype
        set .x = .x+x
        set .y = .y+y
        return this
    endmethod
    
    method subXY takes real x, real y returns thistype
        set .x = .x-x
        set .y = .y-y
        return this
    endmethod
    
    method addDM takes real d, real m returns thistype
        set .x = .x+Cos(d)*m
        set .y = .y+Sin(d)*m
        return this
    endmethod
    
    method subDM takes real d, real m returns thistype
        set .x = .x-Cos(d)*m
        set .y = .y-Sin(d)*m
        return this
    endmethod
endstruct

struct Vector3D[MAX_3D]
    private static location loc = Location(0., 0.)
    private real x
    private real y
    private real z
    
    static if debug then
        static method err takes string message returns nothing
            call BJDebugMsg(&quot;[Vector3D] ERROR: &quot; + message)
        endmethod
    endif
    
    static method create takes thistype v returns thistype
        local thistype r = .allocate()
        set r.x = v.x
        set r.y = v.y
        set r.z = v.z
        return r
    endmethod
    
    static method createXYZ takes real x, real y, real z returns thistype
        local thistype r = .allocate()
        set r.x = x
        set r.y = y
        set r.z = z
        return r
    endmethod
    
    static method createNull takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = 0
        set r.y = 0
        set r.z = 0
        return r
    endmethod
    
    static method createTerrainNormal takes real x, real y, real sampleRadius returns thistype
        local thistype v = .allocate()
        local real zx
        local real zy
        call MoveLocation(.loc, x-sampleRadius, y)
        set zx = GetLocationZ(.loc)
        call MoveLocation(.loc, x+sampleRadius, y)
        set zx = zx-GetLocationZ(.loc)
        call MoveLocation(.loc, x, y-sampleRadius)
        set zy = GetLocationZ(.loc)
        call MoveLocation(.loc, x, y+sampleRadius)
        set zy = zy-GetLocationZ(.loc)
        set sampleRadius = 2*sampleRadius
        set v.x = zx*sampleRadius
        set v.y = zy*sampleRadius
        set v.z = sampleRadius*sampleRadius
        return v
    endmethod
    
    method clone takes nothing returns thistype
        local thistype r = .allocate()
        set r.x = .x
        set r.y = .y
        set r.z = .z
        return r
    endmethod
    
    method getX takes nothing returns real
        return .x
    endmethod
    
    method getY takes nothing returns real
        return .y
    endmethod
    
    method getZ takes nothing returns real
        return .z
    endmethod
    
    method getMag takes nothing returns real
        return SquareRoot(.x*.x+.y*.y+.z*.z)
    endmethod
    
    method setX takes real x returns thistype
        set .x = x
        return this
    endmethod
    
    method setY takes real y returns thistype
        set .y = y
        return this
    endmethod
    
    method setZ takes real z returns thistype
        set .z = z
        return this
    endmethod
    
    method setMag takes real m returns thistype
        local real f
        if m == 0 then
            set .x = 0
            set .y = 0
            set .z = 0
            return this
        endif
        static if debug then
            if .x == 0 and .y == 0 and .z == 0 then
                call err(&quot;setMag(&quot; + R2S(m) + &quot;): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set f = m/.getMag()
        set .x = f*.x
        set .y = f*.y
        set .z = f*.z
        return this
    endmethod
    
    method dotProduct takes thistype v returns real
        return .x*v.x+.y*v.y+.z*v.z
    endmethod
    
    method tripleProductScalar takes thistype v1, thistype v2 returns real
        return (.y*v1.z - .z*v1.y)*v2.x + (.z*v1.x - .x*v1.z)*v2.y + (.x*v1.y - .y*v1.x)*v2.z
    endmethod
    
    method angle takes thistype v returns real
        static if debug then
            if (.x == 0 and .y == 0 and .z == 0) or (v.x == 0 and v.y == 0 and v.z == 0) then
                call err(&quot;angle({Vector3D|x=&quot; + v.x + &quot;,y=&quot; + v.y + &quot;,z=&quot; + v.z + &quot;}): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        return Acos(.dotProduct(v)/(.getMag()*v.getMag()))
    endmethod
    
    method crossProduct takes thistype v returns thistype
        local real x = .y*v.z - .z*v.y
        local real y = .z*v.x - .x*v.z
        set .z       = .x*v.y - .y*v.x
        set .x = x
        set .y = y
        return this
    endmethod
    
    method tripleProductVector takes thistype v1, thistype v2 returns thistype
        local real x = .y*v1.z - .z*v1.y
        local real y = .z*v1.x - .x*v1.z
        local real z = .x*v1.y - .y*v1.x
        set .x = y*v2.z - z*v2.y
        set .y = z*v2.x - x*v2.z
        set .z = x*v2.y - y*v2.x
        return this
    endmethod
    
    method projectionVector takes thistype dir returns thistype
        local real l
        static if debug then
            if .x == 0 and .y == 0 and .z == 0 then
                call err(&quot;projectionVector({Vector3D|x=0,y=0,z=0}): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set l = (.x*dir.x + .y*dir.y + .z*dir.z) / (dir.x*dir.x + dir.y*dir.y + dir.z*dir.z)
        set .x = dir.x*l
        set .y = dir.y*l
        set .z = dir.z*l
        return this
    endmethod
    
    method projectionPlane takes thistype normal returns thistype
        local real l
        static if debug then
            if .x == 0 and .y == 0 and .z == 0 then
                call err(&quot;projectionPlane({Vector3D|x=0,y=0,z=0}): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set l = (.x*normal.x + .y*normal.y + .z*normal.z) / (normal.x*normal.x + normal.y*normal.y + normal.z*normal.z)
        set .x = .x - normal.x*l
        set .y = .y - normal.y*l
        set .z = .z - normal.z*l
        return this
    endmethod
    
    method unit takes nothing returns thistype
        local real m
        static if debug then
            if .x == 0 and .y == 0 and .z == 0 then
                call err(&quot;unit(): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set m = .getMag()
        set .x = .x/m
        set .y = .y/m
        set .z = .z/m
        return this
    endmethod
    
    method invert takes nothing returns thistype
        set .x = -.x
        set .y = -.y
        set .z = -.z
        return this
    endmethod
    
    method scale takes real s returns thistype
        set .x = s*.x
        set .y = s*.y
        set .z = s*.z
        return this
    endmethod
    
    method rotate takes thistype axis, real angle returns thistype
        local real xx
        local real xy
        local real xz
        local real yx
        local real yy
        local real yz
        local real zx
        local real zy
        local real zz
        local real al
        local real f
        local real c
        local real s
        static if debug then
            if .x == 0 and .y == 0 and .z == 0 then
                call err(&quot;rotate({Vector3D|x=0,y=0,z=0}, &quot; + R2S(angle) + &quot;): &quot; + ERR_NULL_VECT_DIR)
            endif
        endif
        set al = axis.x*axis.x + axis.y*axis.y + axis.z*axis.z
        set f  = (this.x*axis.x + this.y*axis.y + this.z*axis.z) / al
        set c  = Cos(angle)
        set s  = Sin(angle)
        set zx = axis.x*f
        set zy = axis.y*f
        set zz = axis.z*f
        set xx = this.x-zx
        set xy = this.y-zy
        set xz = this.z-zz
        set al = SquareRoot(al)
        set yx = (axis.y*xz - axis.z*xy) / al
        set yy = (axis.z*xx - axis.x*xz) / al
        set yz = (axis.x*xy - axis.y*xx) / al
        set .x = xx*c + yx*s + zx
        set .y = xy*c + yy*s + zy
        set .z = xz*c + yz*s + zz
        return this
    endmethod
    
    method add takes thistype v returns thistype
        set .x = .x+v.x
        set .y = .y+v.y
        set .z = .z+v.z
        return this
    endmethod
    
    method sub takes thistype v returns thistype
        set .x = .x-v.x
        set .y = .y-v.y
        set .z = .z-v.z
        return this
    endmethod
    
    method addXYZ takes real x, real y, real z returns thistype
        set .x = .x+x
        set .y = .y+y
        set .z = .z+z
        return this
    endmethod
    
    method subXYZ takes real x, real y, real z returns thistype
        set .x = .x-x
        set .y = .y-y
        set .z = .z-z
        return this
    endmethod
endstruct

endlibrary


How does it look to you?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top