# Working with vectors and quaternions in Lua scripts

Lua scripts support manipulation with built in vectors and quaternions (and their parts) which are used when manipulating object's placement and velocities. This document describes those types and how to manipulate object of those types from Lua scripts.

*Vector3f*

*Vector3f* describes a point in 3D space. In scripts, *Vector3f* can be obtained as a return value from some script function or can be created using *mthVector3f* function (it accepts 3 values, x, y and z components of the vector, respectfully). *Vector3f* has three members: *x*, *y*, and *x*. Lets illustrate creation and manipulation of *Vector3f* objects on a simple example:

-- create a new Vector3f object and store it in local variable vPos local vPos = mthVector3f(3, 4.5, 7.8) -- print components of vPos print("vPos = (" .. vPos.x .. "," .. vPos.y .. "," .. vPos.z .. ")") -- set x component of vPos to 30 vPos.x = 30 -- add 5.6 to y component of vPos vPos.y = vPos.y + 5.6 -- subtract 10 from z component of vPos vPos.z = vPos.z - 10 -- print components of vPos once again print("vPos = (" .. vPos.x .. "," .. vPos.y .. "," .. vPos.z .. ")")

It is also possible to perform simple operation with *Vector3f*: you can multiply or divide a *Vector3f* with a scalar (a number). When multiplying a *Vector3f* with a scalar, all components (x,y,z) are multiplied with it; when dividing a *Vector3f* with a scalar, all components are divided by it. You can also compare vectors for equality and inequality, using Lua == and ~= operators. Let's illustrate this on an example:

-- create a Vector3f local vPos = mthVector3f(3, 6, 9) -- print components of vPos print("vPos = (" .. vPos.x .. "," .. vPos.y .. "," .. vPos.z .. ")") -- multiply vPos with 3 vPos = 3*vPos -- same as vPos*3 -- print components of vPos (should print "vPos = (9,18,27) print("vPos = (" .. vPos.x .. "," .. vPos.y .. "," .. vPos.z .. ")") -- divide vPos with 3 vPos = vPos/3 -- print components of vPos (should print "vPos = (3,6,9) print("vPos = (" .. vPos.x .. "," .. vPos.y .. "," .. vPos.z .. ")") -- compare vPos with a couple of vectors local vPos2 = mthVector3f(3, 7, 9) if vPos == vPos2 then print("vPos == vPos2") -- should not be printed end if vPos ~= vPos2 then print("vPos ~= vPos2") -- should be printed end if vPos == mthVector3f(3, 6, 9) then print("vPos == mthVector3f(3, 6, 9)") -- should be printed end

*Quaternion4f*

Quaternion is usually used to specify orientations of objects or directions. In script code, quaternion are mostly constructed by specifying heading, pitch and banking angles. They are not intended to be directly modified as quaternions. Quaternions objects in script code have a dual nature: they are quaternions if used as quaternions, but they can also be used by manipulating heading, pitch and banking angles. Most of the users should only use * h*,

*and*

**p***(heading, pitch and banking; *in radians!*) members of*

**b***Quaternion4f*in script code and completely ignore the 'real' quaternion members (

*x*,

*y*,

*z*and

*w*).

*Quaternion4f*type in scripts also provides operators for addition, subtraction, multiplication and division but they are intended to be used by users that are familiar with quaternion internals and will not be explained here. If you wish to create a new

*Quaternion4f*object, you can do so using the

*function; function takes three arguments, heading, pitch and banking angles, respectively.*

**mthHPBToQuaternion**We can illustrate use of quaternions on an example:

-- create a quaternion specifying heading of 45 degrees, pitch of 10 degrees and banking of 5 degrees local qRotation = mthHPBToQuaternion(mthDegToRad(45), mthDegToRad(10), mthDegToRad(5)) -- print heading, pitch and banking angles (watch out, they are in radians!) print("qRotation = (" .. qRotation.h .. ", " .. qRotation.p .. ", " .. qRotation.b .. ")") -- modify quaternion through members (set them to 30, 15 and 25 degrees, respectfully) qRotation.h = mthDegToRad(30) qRotation.p = mthDegToRad(15) qRotation.b = mthDegToRad(25) -- print heading, pitch and banking angles (watch out, they are in radians!) print("qRotation = (" .. qRotation.h .. ", " .. qRotation.p .. ", " .. qRotation.b .. ")")

*QuatVect*

*QuatVect* is a pair of a *Quaternion4f* and a *Vector3f*. It is commonly used to specify placement of objects in 3D space. When you wish to obtain entity's placement, you typically use entity's * GetPlacement* member function which returns

*QuatVect*object. Also, when you wish to set entity's placement, you typically use entity's

*member function which receives a*

**SetPlacement***QuatVect*object which provides new placement. You can directly access vector part (using

*,*

**vx***and*

**vy***members) and quaternion part (using*

**vz***,*

**qh***and*

**qp***members) of a*

**qb***QuatVect*. You can also obtain

*Vector3f*part using the

*member function; set the*

**GetVect***Vector3f*part using the

*function; obtain*

**SetVect***Quaternion4f*part using the

*member function; set the*

**GetQuat***Quaternion4f*part using the

*function.*

**SetQuat**You can create new *QuatVect* object using the * mthQuatVect* function which takes two parameters, a

*Quaternion4f*and a

*Vector3f*, respectfully.

Lets illustrate the uses of *QuatVect* on an example:

-- create a QuatVect local qvPlacement = mthQuatVect(mthHPBToQuaternion(mthDegToRad(20), mthDegToRad(5), mthDegToRad(15)), mthVector3f(5, 10, 20)) -- print components of QuatVect print("qvPlacement.q = (" .. qvPlacement.qh .. ", " .. qvPlacement.qp .. ", " .. qvPlacement.qb .. "), qvPlacement.v = (" .. qvPlacement.vx .. ", " .. qvPlacement.vy .. ", " .. qvPlacement.vz .. ")") -- add 5 degrees to each quaternion component qvPlacement.qh = qvPlacement.qh + mthDegToRad(5) qvPlacement.qp = qvPlacement.qp + mthDegToRad(5) qvPlacement.qb = qvPlacement.qb + mthDegToRad(5) -- add 5 meters to each vector component qvPlacement.vx = qvPlacement.vx + 5 qvPlacement.vy = qvPlacement.vy + 5 qvPlacement.vz = qvPlacement.vz + 5 -- print components of QuatVect print("qvPlacement.q = (" .. qvPlacement.qh .. ", " .. qvPlacement.qp .. ", " .. qvPlacement.qb .. "), qvPlacement.v = (" .. qvPlacement.vx .. ", " .. qvPlacement.vy .. ", " .. qvPlacement.vz .. ")") -- set QuatVect as placement of static model entity 'treeModel' treeModel:SetPlacement(qvPlacement) -- get placement of 'barrelModel' into qvPlacement variable qvPlacement = barrelModel:GetPlacement() -- print components of QuatVect print("qvPlacement.q = (" .. qvPlacement.qh .. ", " .. qvPlacement.qp .. ", " .. qvPlacement.qb .. "), qvPlacement.v = (" .. qvPlacement.vx .. ", " .. qvPlacement.vy .. ", " .. qvPlacement.vz .. ")")