A simple vector lua library for everyone for 3D!

This is a fork of the brinevector (2D only)

I personally like brinevector, because it uses ffi to make structs for vectors instead of using tables, which makes it faster and more efficient, but I also need this for bump3dpd which needs x,y,z.

BrineVector3D was written for LOVE2D and is accelerated by the ffi module in luajit, but can be used for any luajit program.

installation

Paste the `brinevector3D.lua`

file and its accompanying `BRINEVECTOR_LICENSE3D`

into your project.

Simply `require`

the file in your projects and give the returned table a name

`Vector3D = require "brinevector3D"`

Or,

`local Vector3D = require “brinevector3D”`

You can replace `Vector3D`

with any name you wish to use. Even `V`

, for brevity. If you gave it any other name than `Vector3D`

, in all code examples that follow, replace `Vector3D`

with whatever name you gave it in the `require`

call.

usage

Here is an overview of all the features, properties, and methods of this library all in one place, and for most people, is everything they need to use this library.

For beginners, or for anyone who wants more details, read the sections down below.

To create a new vector, just call the module directly

`local myVec = Vector3D(3,4,5) --x = 3, y = 4, z = 5`

where

- the first argument will be the x-component of the new vector,
- and the second argument will be the y-component of the new vector.

If no arguments are given, then it defaults to creating a zero-vector. (x component equals `0`

and y component equals `0`

and z component equals `0`

). Thus

`local zVec = Vector3D()`

is equivalent to

`local zVec = Vector3D(0,0,0)`

NOTE: You can also just use this for 2D Vectors like `local myVector = Vector3D(32,32)`

, but c'mon, use the original brinevector for that

Getting the x,y, and z components of a vector works as you expect.

If you have

`local myVec = Vector3D(3,4,5)`

then `myVec.x`

and `myVec.y`

and `myVec.z`

will return the x,y, and z components of `myVec`

, respectively. (`3`

and `4`

and `5`

)

```
print ( myVec.x ) -- prints "3"
print ( myVec.y ) -- prints "4"
print ( myVec.z ) -- prints “5”
```

Assigning and modifying the x,y and z components is also straightforward

```
myVec.x = 10
myVec.y = 20
myVec.z = 30
```

will set the x component of `myVec`

to `10`

and the y component to `20`

and z component to `30`

When using `tostring`

or `print`

on a vector, it will display in a readable format with 4 decimal places for each component. Thus,

```
local myVec = Vector3D(3,4,5)
print(myVec)
```

You can add and subtract vectors using `+`

and `-`

If you have

```
local a = Vector3D(3,4,5)
local b = Vector3D(1,2,3)
```

then

```
a + b -- returns a vector <4,6,8>
a - b -- returns a vector <2,2,2>
b - a -- returns a vector <-2,-2,-2>
a = a + b -- a then becomes <4,6,8>
```

There are a few different types of vector multiplication. The simplest is multiplication of a vector with a number.

```
local a = Vector3D(3,4,5)
a * 5 -- returns <15,20,25>
a * -1 -- returns <-3,-4,-5>
local c = a * 2 -- instantiates a new vector with values <6,8,10>
```

Multiplying two vectors together with the operator `*`

performs the dot product, which returns a single number.

```
local a = Vector3D(1,2,3)
local b = Vector3D(3,4,5)
a * b -- results with (a.x * b.x) + (a.y * b.y) + (a.z * b.z), which is 19
```

In some cases, you might want to get a vector whose x component is the product of two other vectors' x components, and whose y component is the product of their y components. (ie. "Component-wise" or "Freshman" multiplication)

```
local a = Vector3D(3,4,5)
local b = Vector3D(1,-1,1)
local c = Vector3D(a.x * b.x, a.y * b.y, a.z * b.z) -- c becomes <3,-4,5>
```

There really isn't a predefined mathematical symbol for this, so I chose the `%`

operator, as it has no uses with vectors otherwise. Thus the above example can also be written more succinctly as

`local c = a % b -- c becomes <3,-4,5>`

If that makes you uncomfortable because % to you can only mean modulo, then alternatively you can use

`local c = a:hadamard(b) -- c becomes <3,-4,5>`

Dividing a vector `V`

with a scalar `x`

, is exactly equivalent to multiplying `V`

with `1/x`

. Thus,

```
local a = Vector3D(3,4,5)
a / 5 -- returns <0.6,0.8,1>
```

In mathematics, there is no rule for dividing a vector with another vector, and so trying

```
local a = Vector3D(1,1,1)
local b = Vector3D(5,5,1)
a / b
```

produces an error: `must divide by a scalar`

A vector preceded by the unary minus operation (like `-v`

, where `v`

is a vector) is exactly equivalent to `v * -1`

```
local a = Vector3D(3,4,5)
-a -- returns <-3,-4,-5>
-a * 5 -- returns <-15,-20,-25>
```

For maximum convenience and ease of use, the most common properties of a vector are accessed just like any members of a table, * without having to call any methods* like in other libraries.

These are:

`length`

`angle`

`normalized`

`length2`

You can access the length of a vector with `.length`

. Thus if you have

`local myVec = Vector3D(3,4,5)`

then

`myVec.length`

produces `5`

. Even if you edit the vector later on, accessing the `length`

property automatically computes the new length. This makes code shorter and more understandable. This is true for all the other special properties. They are generated on the fly when you ask for them.

```
local myVec = Vector3D(3,4,5)
local a = myVec.length -- a becomes '5'
myVec = myVec * 3 -- myVec is now <9,12>
local b = myVec.length -- b becomes '15'
```

Notice how you don't need to use a method like `a:length()`

or `a:getLength()`

. You simply use `a.length`

Using `.angle`

gives the angle of a vector in radians

```
local myVec = Vector3D(1,1)
myVec.angle -- produces PI/4 radians, or 0.78539816339744828
```

Using `.normalized`

gives the normalized vector of a given vector. That is, a vector with the same angle as the original, but whose length is `1`

.

```
local myVec = Vector3D(3,4)
local myVecN = myVec.normalized -- myVecN becomes <0.6,0.8>
myVecN.length -- is '1'
```

For most purposes (like comparing the lengths of vectors) you only need to compare the squares of the lengths of the vectors. This is because to get the length, any library needs to call `math.sqrt`

. This can be slow, and so if you're conscious about performance, you can use `.length2`

, which returns the length of a vector squared

```
-- compare the lengths of two vectors
local bakery = Vector3D(3,4)
local restaurant = Vector3D(10,10)
if bakery.length2 < restaurant.length2 then
print("The bakery is closer")
elseif bakery.length2 > restaurant.length2 then
print("The restaurant is closer")
end
-- outputs “The bakery is closer”
```

If you prefer getting the above properties with methods instead like in other libraries, you can always still use the following:

`myVec:getLength()`

-- equivalent to`myVec.length`

`myVec:getAngle()`

-- equivalent to`myVec.angle`

`myVec:getNormalized()`

-- equivalent to`myVec.normalized`

`myVec:getLengthSquared()`

-- equivalent to`myVec.length2`

`myVec:angled( angle )`

This returns a vector whose length is the same as `myVec`

but whose angle is set to `angle`

(in radians). For example,

```
local a = Vector3D(3,4)
local b = a:angled(0)
```

will set `b`

to a vector with length `5`

and whose angle is `0`

. ie. `<5,0>`

This is equivalent to

```
local a = Vector3D(3,4)
local b = Vector3D(a.length*math.cos(0), a.length*math.cos(0))
```

`myVec:trim( length )`

This returns a vector with the same angle as `myVec`

, but whose length is "trimmed" down to `length`

only if it is longer than `length`

.

That is, if the length of `myVec`

is greater than `length`

, then the returned vector will have length `length`

. If the length of `myVec`

is less than `length`

then it will return a vector identical to `myVec`

`local a = myVec:trim( 10 )`

is equivalent to the following code:

```
local a = Vector3D(myVec.x, myVec.y)
if a.length > 10 then
a = a.normalized * 10
end
```

This is useful for applying max velocity to an accelerating object. For example if you're updating the velocity `vel`

of an object with acceleration `acc`

, and whose speed must be capped to `MAXSPEED`

, you can write,

`vel = (vel + acc):trim(MAXSPEED)`

instead of

```
vel = vel + acc
if vel.length > MAXSPEED then
vel = vel.normalized * MAXSPEED
end
```

`myVec:hadamard( otherVec )`

This returns a vector that is the result of a component-wise multiplication between `myVec`

and `otherVec`

. Thus `a = b:hadamard(c)`

is equivalent to

`a = Vector3D( b.x * c.x, b.y * c.y )`

Alternatively, you can use `a = b % c`

.

`myVec:split( )`

This returns two values: the x component of the vector, and the y component of the vector. Thus,

`local x, y = myVec:split()`

is equivalent to

`local x, y = myVec.x, myVec.y`

Vector3Ds can also be directly modified through their `length`

and `angle`

properties. This makes for some very short code.

If you have

`myVec = Vector3D(3,4)`

, and you want to modify it such that it keeps its direction but its length changes to `20`

, then you can simply do

`myVec.length = 20`

And now if you inspect `myVec`

,

`“Vector3D{12.0000,16.0000}”`

This is equivalent to

`myVec = myVec.normalized * 20`

Similarly, if you have a vector

`myUnitVec = Vector3D(1,0)`

And you want it to point to an angle called `someangle`

, but still have a length of 1, then simply do

`myUnitVec.angle = someangle`

This is equivalent to

`myUnitVec = myUnitVec:angled(someangle)`

`==`

Vector3Ds can be compared with any other data using `==`

.

`myVec == something`

will only return `true`

if

`something`

is another vector and`something.x`

==`myVec.x`

and`something.y`

==`myVec.y`

`something.z`

==`myVec.z`

Otherwise, it will return `false`

Use

to check if **Vector3D.isVector3D(x)**`x`

is a vector instantiated from the table returned by `require "brinevector"`

.

You can look at more functionalities in the original brinevector

Author: flamendless

Source Code: https://github.com/flamendless/brinevector3D

1.10 GEEK