Wc3C.net

Wc3C.net (http://www.wc3c.net/forums.php)
-   Scripts (http://www.wc3c.net/forumdisplay.php?f=737)
-   -   Vector (http://www.wc3c.net/showthread.php?t=87027)

Anitarf 09-03-2006 05:55 PM

Vector
 
3 Attachment(s)
Attachment 12013This is a set of function intended for spatial geometric calculations. They can be used as a basis for projectile movement, collision detection and other similar operations in 3D space. The functions operate with "vector objects" - integers that represent the index of a vector in a set of arrays. Those arrays store the three coordinates of a vector. The system can do many vector operations, from addition to projection, as well as getting terrain normals and collision detection.

These functions were first used in my and iNfraNe's Blizzard's sports map contest entry Dwarven Downhill.

Update: I have finished making a vJass version of this system. Vectors are implemented as a struct and all the operations that can be done with them have been greatly optimized. The vector methods should now be several times faster than the old functions. The post still contains the original non-vJass map if anyone needs it.

Collapse Vector:
library Vector

//*****************************************************************
//*  VECTOR LIBRARY
//*
//*  written by: Anitarf
//*
//*  The library contains a struct named vector, which represents a
//*  point in 3D space. As such, it has three real members, one for
//*  each coordinate: x, y, z. It also has the following methods:
//*
//*        static method create takes real x, real y, real z returns vector
//*  Creates a new vector with the given coordinates.
//*
//*        method getLength takes nothing returns real
//*  Returns the length of the vector it is called on.
//*
//*        static method sum takes vector augend, vector addend returns vector
//*  Returns the sum of two vectors as a new vector.
//*
//*        method add takes vector addend returns nothing
//*  Similar to sum, except that it doesn't create a new vector for the result,
//*  but changes the vector it is called on by adding the "added" to it.
//*
//*        static method difference takes vector minuend, vector subtrahend returns vector
//*  Returns the difference between two vectors as a new vector.
//*
//*        method subtract takes vector subtrahend returns nothing
//*  Similar to difference, except that it doesn't create a new vector for the result,
//*  but changes the vector it is called on by subtracting the "subtrahend" from it.
//*
//*        method scale takes real factor returns nothing
//*  Scales the vector it is called on by the given factor.
//*
//*        method setLength takes real length returns nothing
//*  Sets the length of the vector it is called on to the given value, maintaining its orientation.
//*
//*        static method dotProduct takes vector a, vector b returns real
//*  Calculates the dot product (also called scalar product) of two vectors.
//*
//*        static method crossProduct takes vector a, vector b returns vector
//*  Calculates the cross product (also called vector product) of two vectors
//*  and returns it as a new vector.
//*
//*        static method tripleProductScalar takes vector a, vector b, vector c returns real
//*  Calculates the triple scalar product of three vectors.
//*
//*        static method tripleProductVector takes vector a, vector b, vector c returns vector
//*  Calculates the triple vector product of three vectors and returns it as a new vector.
//*
//*
//*        static method projectionVector takes vector projected, vector direction returns vector
//*  Calculates the projection of the vector "projected" onto the vector "direction"
//*  and returns it as a new vector.
//*  Returns null if the vector "direction" has a length of 0.
//*
//*        method projectVector takes vector direction returns nothing
//*  Projects the vector it is called on onto the vector "direction".
//*  Does nothing if the vector "direction" has a length of 0.
//*
//*        static method projectionPlane takes vector projected, vector normal returns vector
//*  Calculates the projection of the vector "projected" onto a plane defined by
//*  its normal vector and returns it as a new vector.
//*  Returns null if the vector "normal" has a length of 0.
//*
//*        method projectPlane takes vector normal returns nothing
//*  Projects the vector it is called on onto a plane defined by its normal vector.
//*  Does nothing if the vector "normal" has a length of 0.
//*
//*        static method getAngle takes vector a, vector b returns real
//*  Returns the angle between two vectors, in radians, returns a value between 0 and pi.
//*  Returns 0.0 if any of the vectors are 0 units long.
//*
//*        method rotate takes vector axis, real angle returns nothing
//*  Rotates the vector it is called on around the axis defined by the vector "axis"
//*  by the given angle, which should be input in radians.
//*  Does nothing if axis is 0 units long.
//*
//*
//*        static method createTerrainPoint takes real x, real y returns vector
//*  Creates a vector to the given terrain coordinate, taking its z height into account.
//*
//*        method getTerrainPoint takes real x, real y returns nothing
//*  Sets the vector it is called on to the given terrain coordinate, taking its z height into account.
//*
//*        static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
//*  Creates the normal vector of the terrain at given coordinates. "sampleRadius" defines
//*  how far apart the reference points will be, if they are further apart, the result will
//*  be an impression of smoother terrain; normaly the value should be between 0 and 128.
//*
//*        method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
//*  Sets the vector it is called on to the normal of the terrain at given coordinates.
//*
//*
//*        method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
//*  Determines if a point is within a given cylinder. The cylinder's origin vector points
//*  to the center of one of the two paralel circular sides, and the height vector points
//*  from the origin point to the center of the other of the two paralel circular sides.
//*  Returns false if the point is not in the cylinder or if the vector cylinderHeight is 0 units long.
//*
//*        method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
//*  Determines if a point is within a given cone. The cone's origin vector points to the
//*  center of the circular side, and the height vector points from the origin point to
//*  the tip of the cone.
//*  Returns false if the point is not in the cylinder or if the vector coneHeight is 0 units long.
//*
//*        method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
//*  Determines if a point is within a give sphere. The sphere's origin vector points to the
//*  center of the sphere.
//*  Returns false if the point is not in the sphere.
//*****************************************************************

    struct vector
        real x
        real y
        real z
        
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate()
            set v.x=x
            set v.y=y
            set v.z=z
            return v
        endmethod
        
        method getLength takes nothing returns real
          return SquareRoot(.x*.x + .y*.y + .z*.z)
        endmethod
        
        static method sum takes vector augend, vector addend returns vector
            local vector v = vector.allocate()
            set v.x = augend.x+addend.x
            set v.y = augend.y+addend.y
            set v.z = augend.z+addend.z
            return v
        endmethod
        method add takes vector addend returns nothing
            set this.x=this.x+addend.x
            set this.y=this.y+addend.y
            set this.z=this.z+addend.z
        endmethod
        
        static method difference takes vector minuend, vector subtrahend returns vector
            local vector v = vector.allocate()
            set v.x = minuend.x-subtrahend.x
            set v.y = minuend.y-subtrahend.y
            set v.z = minuend.z-subtrahend.z
            return v
        endmethod
        method subtract takes vector subtrahend returns nothing
            set this.x=this.x-subtrahend.x
            set this.y=this.y-subtrahend.y
            set this.z=this.z-subtrahend.z
        endmethod
        
        method scale takes real factor returns nothing
            set this.x=this.x*factor
            set this.y=this.y*factor
            set this.z=this.z*factor
        endmethod
        
        method setLength takes real length returns nothing
            local real l = SquareRoot(.x*.x + .y*.y + .z*.z)
            if l == 0.0 then
                debug call BJDebugMsg("vector.setLength error: The length of the vector is 0.0!")
                return
            endif
            set l = length/l
            set this.x = this.x*l
            set this.y = this.y*l
            set this.z = this.z*l
        endmethod
        
        static method dotProduct takes vector a, vector b returns real
            return (a.x*b.x+a.y*b.y+a.z*b.z)
        endmethod
        
        static method crossProduct takes vector a, vector b returns vector
            local vector v = vector.allocate()
            set v.x = a.y*b.z - a.z*b.y
            set v.y = a.z*b.x - a.x*b.z
            set v.z = a.x*b.y - a.y*b.x
            return v
        endmethod

        static method tripleProductScalar takes vector a, vector b, vector c returns real
            return ((a.y*b.z - a.z*b.y)*c.x+(a.z*b.x - a.x*b.z)*c.y+(a.x*b.y - a.y*b.x)*c.z)
        endmethod

        static method tripleProductVector takes vector a, vector b, vector c returns vector
            local vector v = vector.allocate()
            local real n = a.x*c.x+a.y*c.y+a.z*c.z
            local real m = a.x*b.x+a.y*b.y+a.z*b.z
            set v.x = b.x*n-c.x*m
            set v.y = b.y*n-c.y*m
            set v.z = b.z*n-c.z*m
            return v
        endmethod

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

        static method projectionVector takes vector projected, vector direction returns vector
            local vector v = vector.allocate()
            local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
            if l == 0.0 then
                call v.destroy()
                debug call BJDebugMsg("vector.projectionVector error: The length of the direction vector is 0.0!")
                return 0
            endif
            set l = (projected.x*direction.x+projected.y*direction.y+projected.z*direction.z) / l
            set v.x = direction.x*l
            set v.y = direction.y*l
            set v.z = direction.z*l
            return v
        endmethod
        method projectVector takes vector direction returns nothing
            local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
            if l == 0.0 then
                debug call BJDebugMsg("vector.projectVector error: The length of the direction vector is 0.0!")
                return
            endif
            set l = (this.x*direction.x+this.y*direction.y+this.z*direction.z) / l
            set this.x = direction.x*l
            set this.y = direction.y*l
            set this.z = direction.z*l
        endmethod

        static method projectionPlane takes vector projected, vector normal returns vector
            local vector v = vector.allocate()
            local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
            if l == 0.0 then
                call v.destroy()
                debug call BJDebugMsg("vector.projectionPlane error: The length of the normal vector is 0.0!")
                return 0
            endif
            set l = (projected.x*normal.x+projected.y*normal.y+projected.z*normal.z) / l
            set v.x = projected.x - normal.x*l
            set v.y = projected.y - normal.y*l
            set v.z = projected.z - normal.z*l
            return v
        endmethod
        method projectPlane takes vector normal returns nothing
            local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
            if l == 0.0 then
                debug call BJDebugMsg("vector.projectPlane error: The length of the normal vector is 0.0!")
                return
            endif
            set l = (this.x*normal.x+this.y*normal.y+this.z*normal.z) / l
            set this.x = this.x - normal.x*l
            set this.y = this.y - normal.y*l
            set this.z = this.z - normal.z*l
        endmethod

        static method getAngle takes vector a, vector b returns real
            local real l = SquareRoot(a.x*a.x + a.y*a.y + a.z*a.z)*SquareRoot(b.x*b.x + b.y*b.y + b.z*b.z)
            if l == 0 then
                debug call BJDebugMsg("vector.getAngle error: The length of at least one of the vectors is 0.0!")
                return 0.0
            endif
            return Acos((a.x*b.x+a.y*b.y+a.z*b.z)/l) //angle is returned in radians
        endmethod
        
        method rotate takes vector axis, real angle returns nothing //angle is taken in radians
            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 = axis.x*axis.x+axis.y*axis.y+axis.z*axis.z //axis length^2
            local real f
            local real c = Cos(angle)
            local real s = Sin(angle)
            if al == 0.0 then
                debug call BJDebugMsg("vector.rotate error: The length of the axis vector is 0.0!")
                return
            endif
            set f = (this.x*axis.x+this.y*axis.y+this.z*axis.z) / al
            set zx = axis.x*f
            set zy = axis.y*f
            set zz = axis.z*f //axis component of rotated vector
            set xx = this.x-zx
            set xy = this.y-zy
            set xz = this.z-zz //component of vector perpendicular to axis
            set al = SquareRoot(al)
            set yx = (axis.y*xz - axis.z*xy)/al
            set yy = (axis.z*xx - axis.x*xz)/al //y same length as x by using cross product and dividing with axis length
            set yz = (axis.x*xy - axis.y*xx)/al //x,y - coordinate system in which we rotate
            set this.x=xx*c+yx*s+zx
            set this.y=xy*c+yy*s+zy
            set this.z=xz*c+yz*s+zz
        endmethod
        
// ================================================================

        private static location loc = Location(0.0,0.0)

        static method createTerrainPoint takes real x, real y returns vector
            local vector v = vector.allocate()
            call MoveLocation(vector.loc,x,y)
            set v.x=x
            set v.y=y
            set v.z=GetLocationZ(loc)
            return v
        endmethod
        method getTerrainPoint takes real x, real y returns nothing
            call MoveLocation(vector.loc,x,y)
            set this.x=x
            set this.y=y
            set this.z=GetLocationZ(loc)
        endmethod

        static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
            local vector v = vector.allocate()
            local real zx
            local real zy
            call MoveLocation(vector.loc, x-sampleRadius, y)
            set zx=GetLocationZ(vector.loc)
            call MoveLocation(vector.loc, x+sampleRadius, y)
            set zx=zx-GetLocationZ(vector.loc)
            call MoveLocation(vector.loc, x, y-sampleRadius)
            set zy=GetLocationZ(vector.loc)
            call MoveLocation(vector.loc, x, y+sampleRadius)
            set zy=zy-GetLocationZ(vector.loc)
            set sampleRadius=2*sampleRadius
            set v.x = zx*sampleRadius
            set v.y = zy*sampleRadius
            set v.z = sampleRadius*sampleRadius
            return v
        endmethod
        method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
            local real zx
            local real zy
            call MoveLocation(vector.loc, x-sampleRadius, y)
            set zx=GetLocationZ(vector.loc)
            call MoveLocation(vector.loc, x+sampleRadius, y)
            set zx=zx-GetLocationZ(vector.loc)
            call MoveLocation(vector.loc, x, y-sampleRadius)
            set zy=GetLocationZ(vector.loc)
            call MoveLocation(vector.loc, x, y+sampleRadius)
            set zy=zy-GetLocationZ(vector.loc)
            set sampleRadius=2*sampleRadius
            set this.x = zx*sampleRadius
            set this.y = zy*sampleRadius
            set this.z = sampleRadius*sampleRadius
        endmethod

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

        method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
            local real l

            local real x = this.x-cylinderOrigin.x
            local real y = this.y-cylinderOrigin.y
            local real z = this.z-cylinderOrigin.z
            if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z < 0.0 then //point below cylinder
                return false
            endif
            
            set x = x-cylinderHeight.x
            set y = y-cylinderHeight.y
            set z = z-cylinderHeight.z
            if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z > 0.0 then //point above cylinder
                return false
            endif
            
            set l = cylinderHeight.x*cylinderHeight.x+cylinderHeight.y*cylinderHeight.y+cylinderHeight.z*cylinderHeight.z
            if l == 0.0 then
                debug call BJDebugMsg("vector.isInCylinder error: The length of the cylinderHeight vector is 0.0!")
                return false
            endif
            set l = (x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z) / l
            set x = x - cylinderHeight.x*l
            set y = y - cylinderHeight.y*l
            set z = z - cylinderHeight.z*l
            if x*x+y*y+z*z > cylinderRadius*cylinderRadius then //point outside cylinder
                return false
            endif
            
            return true
        endmethod

        method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
            local real l

            local real x = this.x-coneOrigin.x
            local real y = this.y-coneOrigin.y
            local real z = this.z-coneOrigin.z
            if x*coneHeight.x+y*coneHeight.y+z*coneHeight.z < 0.0 then //point below cone
                return false
            endif
            
            set l = coneHeight.x*coneHeight.x+coneHeight.y*coneHeight.y+coneHeight.z*coneHeight.z
            if l == 0.0 then
                debug call BJDebugMsg("vector.isInCone error: The length of the coneHeight vector is 0.0!")
                return false
            endif
            set l = (x*coneHeight.x+y*coneHeight.y+z*coneHeight.z) / l
            set x = x - coneHeight.x*l
            set y = y - coneHeight.y*l
            set z = z - coneHeight.z*l
            if SquareRoot(x*x+y*y+z*z) > coneRadius*(1.0-l) then //point outside cone
                return false
            endif
            
            return true
        endmethod

        method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
            if sphereRadius*sphereRadius < ((this.x-sphereOrigin.x)*(this.x-sphereOrigin.x)+(this.y-sphereOrigin.y)*(this.y-sphereOrigin.y)+(this.z-sphereOrigin.z)*(this.z-sphereOrigin.z)) then
                return false
            endif
            return true
        endmethod
    endstruct

endlibrary
library VectorLib requires Vector // For backwards compatibility.
endlibrary

karukef 09-03-2006 08:39 PM

Extremely useful. Thanks a lot for making this for everyone to use!

Just looked it over, and it even has TerrainNormal, that's smooth :)

Had lot's of fun watching the bouncy ball forever and ever. Well, until it's always growing momentum med it bounce itself out of existance, dunno where it went. At one point it slid along the ground, painting it with 100+ bounce art effect. But in general, very smooth.

PipeDream 09-03-2006 10:11 PM

Finally you submit this! The demonstration is beautiful. Approved.

Constant accelerations produces parabolas. That very simple integration method will always increase or decrease energy since it can only exactly reproduce lines. If you flip the order of adding velocity/acceleration to position/velocity you'll see it decay instead of grow. Since the solution is exactly a parabola you can use an explicit formula.
But if you want to be generic to non constant acceleration you can get the same exact integration of constant acceleration with a tiny bit more complexity:
Collapse JASS:
    local integer k1v //unoptimized Runge Kutta 2
    local integer k1x //Takes a trial half sized step
    local integer k2v //computes derivatives in middle of interval
    local integer k2x //uses those values to step from beginning to end

    set k1v = VectorAmplify(vectors[4],BouncyPeriod()*.5)
    set k1x = VectorAmplify(vectors[3],BouncyPeriod()*.5)

    set k2v = VectorAmplify(vectors[4],BouncyPeriod()) //recompute acceleration if it's time or position dependent
    set k2x = VectorSum(k1v,vectors[3])
    call VectorScale(k2x,BouncyPeriod())
 
    call VectorAdd(vectors[2],k2x)
    call VectorAdd(vectors[3],k2v)
    
    call VectorDestroy(k1v)
    call VectorDestroy(k1x)
    call VectorDestroy(k2v)
    call VectorDestroy(k2x)
And remove the scale of BouncyPeriod() from the initial state. This is a somewhat less interesting demonstration since it doesn't grow in energy and because of that the skidding karukef mentions occurs more frequently.

In general for spells the lack of conservation in the simple integrator is not a problem, but it will become one as you increase the time step. .01 is smaller than what is necessary for visually smooth. With this integrator you can safely increase to a less aggressive .03-.05.

Anitarf 09-04-2006 07:27 AM

Quote:

Originally Posted by PipeDream
That very simple integration method will always increase or decrease energy since it can only exactly reproduce lines. If you flip the order of adding velocity/acceleration to position/velocity you'll see it decay instead of grow.

Yes, I noticed that, but I didn't want to overdo things for the purpose of a sample. I just decreased the period from 0.02 to 0.01 and hoped nobody would be bored enough to watch the ball long enough to see it bounce out of the arena.

Quote:

This is a somewhat less interesting demonstration since it doesn't grow in energy and because of that the skidding karukef mentions occurs more frequently.
That can be fixed by increasing the starting velocity. The skidding occurs when the ball lands on a wall close to the ground and bounces out with a near flat velocity. The chances of that happening reduce consderably with longer bounces.

Quote:

In general for spells the lack of conservation in the simple integrator is not a problem, but it will become one as you increase the time step. .01 is smaller than what is necessary for visually smooth. With this integrator you can safely increase to a less aggressive .03-.05.
Mostly, I think spells won't even want to conserve the speed, few objects bounce perfectly so I imagine users would want to scale down the speed with every bounce anyway.

But in the end, it's up to the users to decide how to utilize these functions, for simple projectile parabola approximations or more detailed and complex physical models.

Toadcop 09-04-2006 11:55 AM

Anitarf - cool =) as for me your map (on the contest) was the best (after my XGM-Soccer ;) ) real nice physic but have some problems with camera + how i remember you have a constant vector for "pushing" it was 0 degree... or not i don't remeber you must make it more terrain orintainted and not constant !

PS the only real sys what i respect... because of usage of GetLocationZ(). my TPC use it for Z correction.

Anitarf - i all ready use it in my TPC =) for create more reallystic "bounces" but really the hole sys is to simple (i mean your example) but it's not areal problem + the performance is great !

PS the best system which i have ever seen ! (non my sys =) )
+10000 rep :D !!!

ArchWorm 11-11-2006 04:57 PM

Anitarf, let me introduce Toadcop. He made a system, Toadcop's projectile creator. I don't feel like searching for it, I remember seeing a link at Infrane's PS. And his system allows to create dynamically moving projectiles with effects such as bounce, and other stuff...
I must admit that your sys is easier than TPC, I will not judge is it better, but it's easier.
Toadcop, anytime you need help with english, drop me a PM.

iNfraNe 11-11-2006 08:20 PM

This system is not made for moving objects dynamically. This is for is using mathematical vectors, the demo map just has a moving ball to demonstrate the use.
While this system is VERY usefull it is not a dynamically moving system on its own. My system uses these functions to calculate stuff.

ArchWorm 11-21-2006 12:48 PM

iNfraNe, I see, but I said it about geometrical base of these systems.

xombie 12-20-2006 05:04 AM

ArchWorm look a poopie!
I noticed that by VECTOR he means SCALAR. A vector is a magnitude and direction combined, whilst a scalar is simply magnitude. For clarity, what he is doing is creating an x,y,Ø vector, and a 'z' scalar (for height).

I will be releasing one of this humdingers not to compete with this one, but simply to polish up my math skills. GJ on this system I love the idea.

Ø = Theta (angle)

Edit: When going through it I was so confused how he incorporated height with vectors, but now I see they are just scalars.
Edit: Oops sorry, I see the vectors now. This point has just been proven useless 'hoorah'

PipeDream 12-20-2006 10:46 AM

A vector is not a magnitude and direction, it's something you can add with other vectors and scale. E.g., the real number line is a vector space, but the vectors have only one component. The scalars are the things you scale the vectors with, they can be either real or complex numbers. This package implements a three dimensional real vector space. All three components are part of the vector, but "x","y" and "z" are scalars, as they prescribe how much unit vector to scale and add to the mix.

The vectors this system implements can be represented as magnitude and direction. For these two concepts you need a little more structure than the addition/scaling a vector space gives you. Once you add a dot product that maps two vectors to a scalar you can measure lengths and angles and think about a magnitude/direction representation. In practice you don't use that for actual computations since it's a nightmarish mess.

xombie 12-20-2006 11:21 AM

I don't even know why I bothered doubting him lol, I should have automatically known he was right.

------------------------------------------------------------------------------------------------------------------------

I haven't gotten around to learning anything 3D in mathematics or physics (I'm in grade 12, and I take AP Calculus -- basically means 1st year university calculus), my knowledge in the area of this is very scarce, and would appreciate learning. I've figured out a rough outline using a pen and paper on how this goes about working, but I would appreciate it if you or Anitarf could PM me a simple but thorough explanation of everything that is going on in this system. I could try to talk to Anitarf sometime on BNet but things like this intrigue me and I'd like to learn more.

PS.

Until then I'm going to be thoroughly looking through the map getting a better understanding of it - something I should be learning in school but hey! school sucks and doesn't teach you jack.

Edit: Oh shit double-post, I'll fix this.
______________________________________________________________________________________
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Collapse JASS:
function BouncyBallCreate takes nothing returns nothing
    local integer array vectors
    local timer t
    set udg_BouncyBall = CreateUnit(Player(0), 'ewsp', 0.0,0.0,0.0)

  //  make it possible to change the unit's flyheight
    call UnitAddAbility(udg_BouncyBall, 'Amrf')
    call UnitRemoveAbility(udg_BouncyBall, 'Amrf')

  //  create the unit's position vector
    set vectors[1]=VectorCreate(0.0,0.0,100.0)

  //  create the unit's starting speed vector
    set vectors[2]=VectorCreate(GetRandomReal(-100.0, 100.0)*BouncyPeriod(),GetRandomReal(-100.0, 100.0)*BouncyPeriod(),500.0*BouncyPeriod())

  //  create the gravity acceleration vector
    set vectors[3]=VectorCreate(0.0, 0.0, -800.0*BouncyPeriod()*BouncyPeriod())

  //  to avoid having too many variables, we store these vectors into another vector
    set vectors[4]=VectorCreate(I2R(vectors[1]), I2R(vectors[2]), I2R(vectors[3]))
    call SetUnitUserData(udg_BouncyBall, vectors[4])

    set t = CreateTimer()
    call TimerStart(t, BouncyPeriod(), true, function BouncyBallMove )
endfunction
After taking a look at your VectorCreate() function, it seems that you create 4 different vectors, and the 4th one is simply a clone of the first three. Would this not create DOUBLE the vector that you originally intended?

In your fourth vector creation, what do you convert the values to integers for? Also, more specifically than before: In your setting of vectors[1] you give the 'z' a value of 100.00. Later, in vectors[2], you create ANOTHER vector, equal to 5. Then, again, in vectors[3], you add an acceleration of gravity. I'm completely lost as to what you are doing here.

iNfraNe 12-21-2006 04:32 PM

Actually, the 4th vector is being used as a storing method for the other 3. The beauty of this system is that it can link 3 reals to 1 integer. So what the 4th does is link the other 3 vectors to it, so they can be selected trough 1 integer. It actually, unlike the other 3, has nothing mathematical about it.

on an offtopic note: your signature function would crash the WE since its lacking a return statement.

Anitarf 12-21-2006 10:36 PM

What you were looking at is the initialization function. It just creates the three basic vectors that the bouncy ball needs: one to determine it's position, what's it's offset from the origin of the map; another to determine it's speed, how much does it move in one time unit; another to determine it's acceleration, how much does the speed change in one time unit. The fourth one has nothing to do with physics but is used as a data structure. Under it's "coordinates" it stores the IDs of the before mentioned 3 vectors.

Then you have a periodic timer that calls the function that moves the ball every time unit.

MaD[Lion] 12-25-2006 08:53 AM

this system totally owns :D

oninuva 12-25-2006 04:34 PM

So I guess you need to know JASS to use it?

BlinkBoy 12-26-2006 08:42 AM

You should update this system to use JASSHelper's structs, it would make it easier to use.

Chocobo 02-23-2007 08:13 AM

I'm not very familiar with Vectors :p

Collapse JASS:
  //  create the unit's position vector
    set vectors[1]=VectorCreate(0.0,0.0,100.0)

  //  create the unit's starting speed vector
    set vectors[2]=VectorCreate(GetRandomReal(-100.0, 100.0)*BouncyPeriod(),GetRandomReal(-100.0, 100.0)*BouncyPeriod(),500.0*BouncyPeriod())

  //  create the gravity acceleration vector
    set vectors[3]=VectorCreate(0.0, 0.0, -800.0*BouncyPeriod()*BouncyPeriod())

  //  to avoid having too many variables, we store these vectors into another vector
    set vectors[4]=VectorCreate(I2R(vectors[1]), I2R(vectors[2]), I2R(vectors[3]))
    call SetUnitUserData(udg_BouncyBall, vectors[4])

The vectors[1] refers to x?
vectors[2] to y?
vectors[3] to z?

Or not? If not, then the vectors[1] is created at Location(0.00,0.00) at height 100.00, the vectors[2] is created at Location(GetRandomReal(-1.00,1.00),GetRandomReal(-1.00,1.00)) at height 5.00, and the vectors[3] is created at Location(0.00,0.00) at height -0.08?
And then the vectors[4] is created at Location(vectors[1],vectors[2]) at height vectors[3], and udg_BounceBall's custom value is set to vectors[4].


Collapse JASS:
  //  retrieve vector data from unit's custom value
    set vectors[1]=GetUnitUserData(udg_BouncyBall)
    set vectors[2]=R2I(VectorGetX(vectors[1]))
    set vectors[3]=R2I(VectorGetY(vectors[1]))
    set vectors[4]=R2I(VectorGetZ(vectors[1]))

There, the vectors[1] retrieves the custom unit value of udg_BounceBall, and sets vectors[2], vectors[3], and vectors[4] to respectivly X, Y and Z of vectors[1]?


Collapse JASS:
  //  change the ball's position according to it's speed
    call VectorAdd(vectors[2], vectors[3])
  //  change the balls speed by the gravity acceleration
    call VectorAdd(vectors[3], vectors[4])

The vectors[2] and vectors[3] are added (vectors[2]'s X, Y, and Z are respectivly added to vectors[3]'s X, Y, and Z?), and the vectors[3] and vectors[4] are added. vectors[2] is the result of the add, and vectors[3] is the result of the second add?


Collapse JASS:
  //  verify terrain collision
    if h >= VectorGetZ(vectors[2]) then
      //  get terrain normal vector
        set vectors[5]=VectorGetTerrainNormal(VectorGetX(vectors[2]), VectorGetY(vectors[2]), 32.0)
      //  get the component of speed vector that is perpendicular to the terrain
        set vectors[6]=VectorProjectVector(vectors[3], vectors[5])
      //  invert the ball's speed component that's perpendicular to terrain
        call VectorScale(vectors[6], -2.0)
        call VectorAdd(vectors[3], vectors[6])
      //  cleanup the temporary vectors
        call VectorDestroy(vectors[5])
        call VectorDestroy(vectors[6])
      //  add land effect
        set eff = AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", VectorGetX(vectors[2]), VectorGetY(vectors[2]))
        call DestroyEffect(eff)
    endif

There, even with the //informations, I don't understand what does most of lines (the add, scale, and set vectors[index] = blabla). (even with Functions List trigger)

Also, if I change the 32.0 (VectorTerrainGetNormal) to something higher, what happens? And if it is lower? So does for the -2.0 for the VectorScale.


Collapse JASS:
  //  move the ball
    call SetUnitX(udg_BouncyBall, VectorGetX(vectors[2]))
    call SetUnitY(udg_BouncyBall, VectorGetY(vectors[2]))
    call SetUnitFlyHeight(udg_BouncyBall, VectorGetZ(vectors[2])-h, 0.0)

So, we need only vectors[2] to move the ball?

iNfraNe 02-24-2007 06:23 PM

This has been answered on the first page. Vector one stores the adresses on vector2 3 and 4, which are place speed and gravity.

vector2 is increased by the speed (vector3)
and the speed in increased by the gravity (acceleration, vector4)

Then, after that the unit is moved to vector 2, the place.

if you change the 32 in terrainnormal itll take a larger piece of terrain to calculate the vector. a larger number sorta smoothens out the terrain.

ClichesAreSt00pid 07-20-2007 01:43 AM

Can't
Collapse JASS:
        set eff = AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", VectorGetX(vectors[2]), VectorGetY(vectors[2]))
        call DestroyEffect(eff)
be changed to
Collapse JASS:
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", VectorGetX(vectors[2]), VectorGetY(vectors[2])))
in your demo trigger? Makes the eff local variable unecessary.

Anitarf 07-20-2007 02:05 AM

Yes, it can. The demo trigger sucks.

Toadcop 07-20-2007 11:03 AM

btw the feature to store vec into vec is lame... you could simply create 8 16 arrays ^^ but ! it's a allready old sys so no really suggestions + comments. it's just for info (+ you know it self ;))

Doom 10-06-2007 10:59 AM

how to let a new unit bounce couse i inpoted the costum script but i dont see how to let a unit bounce and wich unit:( (btw im nto very good whit jass):( and i need a other spot then at the start lcation of red and i need one unity type to bounce

Anitarf 03-03-2008 05:34 PM

Major update: I made a vJass version of vectors, greatly optimised and easier to use. Details in first post.

cohadar 03-04-2008 10:02 AM

Really Nice Job, have some :brew:

The only thing I did not like is that you named the class vector.
I prefer uppercase class names - Vector. (ye I'm silly)

Also you might want to consider using better error messages
Collapse JASS:
"setLength: Attempted to set the length of a vector to zero!"

"projectionVector: Attempted to project onto a vector with no length!"

"projectionPlane: Attempted to project onto an undefined plane!"

"projectPlane: Attempted to project onto an undefined plane!"

"getAngle: Attempted to get angle between vectors with no length!"

"rotate: Attempted to project onto a vector with no length! // This was misleading"

"isInCylinder: Cylinder with no height!"

"isInCone: cone with no height!"

It really helps when you know exactly in what function the error happened, especially with similar or repeating error messages.

Once again great job.

EDIT:
Oh and create one default bouncing ball on startup and maybe display a message:
Press ESC for more balls.

Toadcop 03-04-2008 12:04 PM

NOOOOOOOOOOOOOOOOOOOOOOOOO !
the wisps have fucked setups =\ and it looks like a flying shit.
FIX IT ! (Max Pitch / Roll Angles set to 0) + it would be better to import custom wisp with height offset (Z = 0)

+ imho Archimode missle was better... (due this laks (above))

and the collision algorithm is a mega overkill shit >.< (better simply remove it)
x^2 omg... 30=900 xD loled fuck... or you may educate someone else to use such way of collision detection.

but well the previous version was the mega uber imba +1 *DRINK* it was the begin of Vectors in wc3 (publick). so :pray: Anitarf + iNfraNe

cohadar 03-04-2008 01:08 PM

Quote:

Originally Posted by Toadcop
+ imho Archimode missle was better... (due this laks (above))


Ye I was gonna suggest him to attach some ribbon to the wisp but forgot.

Toadcop 03-04-2008 02:23 PM

cohadar you mean particles ^^ ?
but well the reasons why currebtly wisps suck is the roll and pitch issue on cliffs... TT

Anitarf 03-04-2008 02:45 PM

It's just a lame sample, no need to get upset about it.
Sure, the collision detection is horrible, but I just didn't feel like using a group and doing an enum in range. This works well enough; once your framerate starts dropping, there are usualy enough bouncy balls that they quickly collide and die off.

Toadcop 03-04-2008 04:55 PM

Quote:

once your framerate starts dropping, there are usualy enough bouncy balls that they quickly collide and die off.
thats true ~30 wisp are almost the max.
but anyway awesome stuff need awesome presentation ^^ (thats why grim001 demo was so impressive)

Anitarf 03-04-2008 05:43 PM

Well, for an awesome presentation, wait about a year; I might make a map project out of this.

cohadar 03-05-2008 08:58 AM

Quote:

Originally Posted by Toadcop
thats true ~30 wisp are almost the max.
but anyway awesome stuff need awesome presentation ^^ (thats why grim001 demo was so impressive)


offtopic:
And that is why grim001 never finishes anything....

Toadcop 03-05-2008 05:29 PM

cohadar yes it's true. and also he banned me in AIM xDDDD he's a bad ass xD

ClichesAreSt00pid 06-07-2008 10:38 PM

Great system, forced me to learn vjass too.

Anyways I'm having trouble with one thing that I just can't figure out. I want it to be like a "thrown" bouncy ball from a spell, and the velocity is calculated in XYZ, so how would I make the velocity take the ball towards the target?

I'm also trying to make it so any kind of collision will make it bounce, like trees and stuff, but it's tough and will take time. I'm using items (like vexorian did I think) to check it if you are wondering, just the actual Z height of different models is what makes it difficult.


Edit: Okay figured it out. I just did...well this in the creation part (and many other things, like making the trigger into a spell):

Collapse JASS:
    static method create takes nothing returns bouncyBall
        local bouncyBall b = bouncyBall.allocate()
        local location l = GetSpellTargetLoc()
        local location l2 = GetUnitLoc(GetTriggerUnit())
        local location l3 = PolarProjectionBJ(l2, 600, AngleBetweenPoints(l2, l))
        set b.position = vector.create(GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit()),75.0) //this is the thrower
      //  give the ball a starting velocity
        set b.velocity = vector.create((GetLocationX(l3) - GetLocationX(l2))*MOVE_PERIOD,(GetLocationY(l3) - GetLocationY(l2))*MOVE_PERIOD,600.0*MOVE_PERIOD)
        set b.ball = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'ewsp', 0.0,0.0,0.0)
      //  make it possible to change the unit's flyheight
        call UnitAddAbility(b.ball, 'Amrf')
        call UnitRemoveAbility(b.ball, 'Amrf')
        set balls[ballNum]=b
        set b.spot=ballNum
        set balls[ballNum].duration = 0
        set ballNum=ballNum+1

        call RemoveLocation(l)
        set l = null
        call RemoveLocation(l2)
        set l2 = null
        call RemoveLocation(l3)
        set l3 = null
        return b
    endmethod

Seshiro 08-25-2008 10:41 PM

New Functions for Units
 
Hey,
I've had to add some new methods to your atruct, because i neede them! :D
They all improve working with units and vectors! they are easey to use, and i think, that they're useful!
Collapse JASS:
library VectorLib
    // Credits:
    //  ;- to Waterknight for UnitZ funcs

    function GetFloorHeight takes real x, real y returns real
        local location whichUnitLocation = Location( x, y )
        local real z = GetLocationZ( whichUnitLocation )
        call RemoveLocation( whichUnitLocation )
        set whichUnitLocation = null
        return z
    endfunction

    function GetUnitZ takes unit whichUnit returns real
        local real z = ( GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ) + GetUnitFlyHeight( whichUnit ) )
        set whichUnit = null
        return z
    endfunction



    function SetUnitZ takes unit whichUnit, real z returns nothing
        local boolean whichUnitHasNotAmrf = ( GetUnitAbilityLevel( whichUnit, 'Amrf' ) <= 0 )
        if ( whichUnitHasNotAmrf ) then
            call UnitAddAbility( whichUnit, 'Amrf' )
        endif
        call SetUnitFlyHeight( whichUnit, z - GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ), 0.00 )
        if ( whichUnitHasNotAmrf ) then
            call UnitRemoveAbility( whichUnit, 'Amrf' )
        endif    
        set whichUnit = null
    endfunction

    globals
        private location loc = Location(0.0,0.0)
    endglobals

    struct vector
        real x
        real y
        real z
        
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate()
            set v.x=x
            set v.y=y
            set v.z=z
            return v
        endmethod
        
        static method setUnitVector takes unit c, vector v returns nothing
            call SetUnitX(c,v.x)
            call SetUnitY(c,v.y)
            call SetUnitZ(c,v.z)
            set c = null
        endmethod
        
        method updateUnitVector takes unit u returns nothing
            set this.x = GetUnitX(u)
            set this.y = GetUnitY(u)
            set this.z = GetUnitZ(u)
            set u = null
        endmethod
        
        static method getUnitVector takes unit u returns vector
            local vector v = vector.allocate()
            set v.x = GetUnitX(u)
            set v.y = GetUnitY(u)
            set v.z = GetUnitZ(u)
            set u = null
            return v
        endmethod
        
        method getLength takes nothing returns real
          return SquareRoot(.x*.x + .y*.y + .z*.z)
        endmethod
        
        static method sum takes vector augend, vector addend returns vector
            local vector v = vector.allocate()
            set v.x = augend.x+addend.x
            set v.y = augend.y+addend.y
            set v.z = augend.z+addend.z
            return v
        endmethod
        method add takes vector addend returns nothing
            set this.x=this.x+addend.x
            set this.y=this.y+addend.y
            set this.z=this.z+addend.z
        endmethod
        
        static method difference takes vector minuend, vector subtrahend returns vector
            local vector v = vector.allocate()
            set v.x = minuend.x-subtrahend.x
            set v.y = minuend.y-subtrahend.y
            set v.z = minuend.z-subtrahend.z
            return v
        endmethod
        method subtract takes vector subtrahend returns nothing
            set this.x=this.x-subtrahend.x
            set this.y=this.y-subtrahend.y
            set this.z=this.z-subtrahend.z
        endmethod
        
        method scale takes real factor returns nothing
            set this.x=this.x*factor
            set this.y=this.y*factor
            set this.z=this.z*factor
        endmethod
        
        method setLength takes real length returns nothing
            local real l = SquareRoot(.x*.x + .y*.y + .z*.z)
            if l == 0.0 then
                debug call BJDebugMsg("Attempted to set the length of a vector with no length!")
                return
            endif
            set l = length/l
            set this.x = this.x*l
            set this.y = this.y*l
            set this.z = this.z*l
        endmethod
        
        static method dotProduct takes vector a, vector b returns real
            return (a.x*b.x+a.y*b.y+a.z*b.z)
        endmethod
        
        static method crossProduct takes vector a, vector b returns vector
            local vector v = vector.allocate()
            set v.x = a.y*b.z - a.z*b.y
            set v.y = a.z*b.x - a.x*b.z
            set v.z = a.x*b.y - a.y*b.x
            return v
        endmethod
        
        static method projectionVector takes vector projected, vector direction returns vector
            local vector v = vector.allocate()
            local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
            if l == 0.0 then
                call v.destroy()
                debug call BJDebugMsg("Attempted to project onto a vector with no length!")
                return null
            endif
            set l = (projected.x*direction.x+projected.y*direction.y+projected.z*direction.z) / l
            set v.x = direction.x*l
            set v.y = direction.y*l
            set v.z = direction.z*l
            return v
        endmethod
        method projectVector takes vector direction returns nothing
            local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
            if l == 0.0 then
                debug call BJDebugMsg("Attempted to project onto a vector with no length!")
                return
            endif
            set l = (this.x*direction.x+this.y*direction.y+this.z*direction.z) / l
            set this.x = direction.x*l
            set this.y = direction.y*l
            set this.z = direction.z*l
        endmethod

        static method projectionPlane takes vector projected, vector normal returns vector
            local vector v = vector.allocate()
            local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
            if l == 0.0 then
                call v.destroy()
                debug call BJDebugMsg("Attempted to project onto an undefined plane!")
                return null
            endif
            set l = (projected.x*normal.x+projected.y*normal.y+projected.z*normal.z) / l
            set v.x = projected.x - normal.x*l
            set v.y = projected.y - normal.y*l
            set v.z = projected.z - normal.z*l
            return v
        endmethod
        method projectPlane takes vector normal returns nothing
            local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
            if l == 0.0 then
                debug call BJDebugMsg("Attempted to project onto an undefined plane!")
                return
            endif
            set l = (this.x*normal.x+this.y*normal.y+this.z*normal.z) / l
            set this.x = this.x - normal.x*l
            set this.y = this.y - normal.y*l
            set this.z = this.z - normal.z*l
        endmethod

        static method getAngle takes vector a, vector b returns real
            local real l = SquareRoot(a.x*a.x + a.y*a.y + a.z*a.z)*SquareRoot(b.x*b.x + b.y*b.y + b.z*b.z)
            if l == 0 then
                debug call BJDebugMsg("Attempted to get angle between vectors with no length!")
                return 0.0
            endif
            return Acos((a.x*b.x+a.y*b.y+a.z*b.z)/l) //angle is returned in radians
        endmethod
        
        method rotate takes vector axis, real angle returns nothing //angle is taken in radians
            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 = axis.x*axis.x+axis.y*axis.y+axis.z*axis.z //axis length^2
            local real f
            local real c = Cos(angle)
            local real s = Sin(angle)
            if al == 0.0 then
                debug call BJDebugMsg("Attempted to project onto a vector with no length!")
                return
            endif
            set f = (this.x*axis.x+this.y*axis.y+this.z*axis.z) / al
            set zx = axis.x*f
            set zy = axis.y*f
            set zz = axis.z*f //axis component of rotated vector
            set xx = this.x-zx
            set xy = this.y-zy
            set xz = this.z-zz //component of vector perpendicular to axis
            set al = SquareRoot(al)
            set yx = (axis.y*xz - axis.z*xy)/al
            set yy = (axis.z*xx - axis.x*xz)/al //y same length as x by using cross product and dividing with axis length
            set yz = (axis.x*xy - axis.y*xx)/al //x,y - coordinate system in which we rotate
            set this.x=xx*c+yx*s+zx
            set this.y=xy*c+yy*s+zy
            set this.z=xz*c+yz*s+zz
        endmethod
        
        static method createTerrainPoint takes real x, real y returns vector
            local vector v = vector.allocate()
            call MoveLocation(loc,x,y)
            set v.x=x
            set v.y=y
            set v.z=GetLocationZ(loc)
            return v
        endmethod
        method getTerrainPoint takes real x, real y returns nothing
            call MoveLocation(loc,x,y)
            set this.x=x
            set this.y=y
            set this.z=GetLocationZ(loc)
        endmethod

        static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
            local vector v = vector.allocate()
            local real z1
            local real z2
            local real z3
            local real z4
            call MoveLocation(loc, x-sampleRadius, y)
            set z1=GetLocationZ(loc)
            call MoveLocation(loc, x+sampleRadius, y)
            set z2=GetLocationZ(loc)
            call MoveLocation(loc, x, y-sampleRadius)
            set z3=GetLocationZ(loc)
            call MoveLocation(loc, x, y+sampleRadius)
            set z4=GetLocationZ(loc)
            set sampleRadius=2*sampleRadius
            set v.x = (z1-z2)*sampleRadius
            set v.y = (z3-z4)*sampleRadius
            set v.z = sampleRadius*sampleRadius
            return v
        endmethod
        method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
            local real z1
            local real z2
            local real z3
            local real z4
            call MoveLocation(loc, x-sampleRadius, y)
            set z1=GetLocationZ(loc)
            call MoveLocation(loc, x+sampleRadius, y)
            set z2=GetLocationZ(loc)
            call MoveLocation(loc, x, y-sampleRadius)
            set z3=GetLocationZ(loc)
            call MoveLocation(loc, x, y+sampleRadius)
            set z4=GetLocationZ(loc)
            set sampleRadius=2*sampleRadius
            set this.x = (z1-z2)*sampleRadius
            set this.y = (z3-z4)*sampleRadius
            set this.z = sampleRadius*sampleRadius
        endmethod

        method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
            local real l

            local real x = this.x-cylinderOrigin.x
            local real y = this.y-cylinderOrigin.y
            local real z = this.z-cylinderOrigin.z
            if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z < 0.0 then //point below cylinder
                return false
            endif
            
            set x = x-cylinderHeight.x
            set y = y-cylinderHeight.y
            set z = z-cylinderHeight.z
            if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z > 0.0 then //point above cylinder
                return false
            endif
            
            set l = cylinderHeight.x*cylinderHeight.x+cylinderHeight.y*cylinderHeight.y+cylinderHeight.z*cylinderHeight.z
            if l == 0.0 then
                debug call BJDebugMsg("Cylinder with no height!")
                return false
            endif
            set l = (x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z) / l
            set x = x - cylinderHeight.x*l
            set y = y - cylinderHeight.y*l
            set z = z - cylinderHeight.z*l
            if x*x+y*y+z*z > cylinderRadius*cylinderRadius then //point outside cylinder
                return false
            endif
            
            return true
        endmethod

        method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
            local real l

            local real x = this.x-coneOrigin.x
            local real y = this.y-coneOrigin.y
            local real z = this.z-coneOrigin.z
            if x*coneHeight.x+y*coneHeight.y+z*coneHeight.z < 0.0 then //point below cone
                return false
            endif
            
            set l = coneHeight.x*coneHeight.x+coneHeight.y*coneHeight.y+coneHeight.z*coneHeight.z
            if l == 0.0 then
                debug call BJDebugMsg("cone with no height!")
                return false
            endif
            set l = (x*coneHeight.x+y*coneHeight.y+z*coneHeight.z) / l
            set x = x - coneHeight.x*l
            set y = y - coneHeight.y*l
            set z = z - coneHeight.z*l
            if SquareRoot(x*x+y*y+z*z) > coneRadius*(1.0-l) then //point outside cone
                return false
            endif
            
            return true
        endmethod

        method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
            if sphereRadius*sphereRadius < ((this.x-sphereOrigin.x)*(this.x-sphereOrigin.x)+(this.y-sphereOrigin.y)*(this.y-sphereOrigin.y)+(this.z-sphereOrigin.z)*(this.z-sphereOrigin.z)) then
                return false
            endif
            return true
        endmethod
    endstruct

endlibrary

the new functions are:
  • updateUnitVector: sets the current vector to the one of the unit
  • setUnitVector: sets the vectors of the unit to the vector
  • getUnitVector: the same as update but creates a new vector

and a very very big thanks to Antiarf for such work!

I don't know, wether I'm allowed to do this, if u dislike this, u may tell me and i delete at the moment :) !

Greez

Anitarf 08-26-2008 12:30 AM

Those extra methods you have there don't really fit in my opinion since doing stuff with actual units is outside the scope of this system, that's something you should build on top of the system not in it, also your GetFloorHeight function is obsolete, you also do some odd things in other functions as well, it's all rather unoptimised for a low-level system and we don't want to encourage people to code like that.

So I'm not adding those functions and methods to my first post, but thanks for the suggestions anyway.

akolyt0r 03-24-2009 12:09 PM

<nitpicking
Collapse JASS:
        static constant method dotProduct takes vector a, vector b returns real
            return (a.x*b.x+a.y*b.y+a.z*b.z)
        endmethod

peq 11-24-2009 09:23 PM

I have a request for an operation which I use quite often:
Collapse JASS:
        method addScaled takes vector addend, real scale returns nothing
            set this.x=this.x+addend.x*scale
            set this.y=this.y+addend.y*scale
            set this.z=this.z+addend.z*scale
        endmethod

Its nice to have a function like this if you use vectors for movement as you always need nomething like this:

Collapse JASS:
call position.addScaled(velocity, TimedLoop_PERIOD)

It would be nice if you could add this ;)

Anachron 04-12-2010 09:09 AM

Why don't you have GetXyDistance and GetXyzDistance in the vector library? I think that is important.

Can you please add it or tell me how I can do it?

0zyx0 04-12-2010 11:20 AM

GetXyzDistance could be done by subtracting one of the vectors from the other, and getting the length of the resulting vector. GetXyDistance would be done the same way, but you would have to make sure the two vectors have the same z-component first.

Anachron 04-12-2010 11:28 AM

I still don't get it.
Can you post code that returns the distance as a real?


All times are GMT. The time now is 10:34 AM.

Powered by vBulletin (Copyright ©2000 - 2019, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services