tes3vector3⚓︎

A simple trio of floating-point numbers.

Properties⚓︎

`b`⚓︎

The third value in the vector. An alias for `z`.

Returns:

• `result` (number)

`g`⚓︎

The second value in the vector. An alias for `y`.

Returns:

• `result` (number)

`r`⚓︎

The first value in the vector. An alias for `x`.

Returns:

• `result` (number)

`x`⚓︎

The first value in the vector.

Returns:

• `result` (number)

`y`⚓︎

The second value in the vector.

Returns:

• `result` (number)

`z`⚓︎

The third value in the vector.

Returns:

• `result` (number)

Methods⚓︎

`__tostring`⚓︎

Converts the vector to a string with 2 decimal places.

``````local result = myObject:__tostring()
``````

Returns:

• `result` (string)

`angle`⚓︎

The returns the angle between the two vectors in radians.

``````local result = myObject:angle(vec)
``````

Parameters:

Returns:

• `result` (number)

`copy`⚓︎

Creates a copy of the vector.

``````local result = myObject:copy()
``````

Returns:

`cross`⚓︎

Calculates the cross product with another vector.

``````local result = myObject:cross(vec)
``````

Parameters:

Returns:

`distance`⚓︎

Calculates the distance to another vector in the standard way, i.e., using the Euclidean distance.

``````local result = myObject:distance(vec)
``````

Parameters:

Returns:

• `result` (number)

`distanceChebyshev`⚓︎

Calculates the distance to another vector, using the Chebyshev metric, which is defined as

``````math.max(math.abs(v1.x - v2.x), math.abs(v1.y - v2.y), math.abs(v1.z - v2.z))
``````

This is useful for ensuring that the x, y, and z coordinates between two vectors are all (independently) within a certain distance from each other.

Here is a geometric description of the difference between the normal distance and the Chebyshev distance for two `tes3vector3`s `v1` and `v2`:

• If `v1:distance(v2) <= 1`, then `v2` is contained in a sphere around `v1` with radius 1 (i.e. diameter 2).
• If `v1:distanceChebyshev(v2) <= 1`, then `v2` is contained within a cube centered around `v1`, where the cube has length 2.
``````local result = myObject:distanceChebyshev(vec)
``````

Parameters:

Returns:

• `result` (number)

`distanceManhattan`⚓︎

Calculates the distance to another vector, using the Manhattan (i.e. city block) metric. In the two-dimensional case, the Manhattan metric can be thought of as the distance that two taxis will have to travel if they're following a grid system. The formula for the Manhattan distance is

``````math.abs(v1.x - v2.x) + math.abs(v1.y - v2.y) + math.abs(v1.z - v2.z)
``````

This is useful for checking how far you'd actually have to move if you're only allowed to move along one axis at a time.

``````local result = myObject:distanceManhattan(vec)
``````

Parameters:

Returns:

• `result` (number)

`distanceXY`⚓︎

Calculates the distance between the XY-coordinates of two vectors.

This method offers a way of calculating distances between vectors in situations where it's more convenient to ignore the z-coordinates.

``````local result = myObject:distanceXY(vec)
``````

Parameters:

Returns:

• `result` (number)
Example: Items on bookshelves.

Let's say you want to make a function that checks if two ingredients are close together. This will involve looking at the distance between two `tes3reference`s.

One way to do this would be to use the normal `tes3vector3:distance` method, but this has a drawback: it doesn't work consistently with ingredients on bookshelves. If two ingredients are on the same shelf, their `z`-coordinates contribute very little to the distance between them, while the situation is reversed for ingredients on different shelves.

This problem is remedied by using `tes3vector3:distanceXY` as follows:

``````-- Check if two items are on the same bookshelf
---@param ref1 tes3reference reference to one ingredient
---@param ref2 tes3reference reference to another ingredient
local function isOnSameShelf(ref1, ref2)
local maxDistXY = 75 -- XY tolerance
local maxDistZ = 150 -- Z tolerance

-- distanceXY ignores the Z coordinate, which has the effect of
-- "pretending" `ref1` and `ref2` are on the same shelf
local distanceXY = ref1.position:distanceXY(ref2.position)
-- check the height difference separately, to make sure it's not too crazy
-- for example, if we're inside a building, this would make sure that
--  `ref1` and `ref2` are on the same floor of the building.
local distanceZ = ref1.position:heightDifference(ref2.position)

return distanceXY <= maxDistXY and distanceZ <= maxDistZ
end
``````

`dot`⚓︎

Calculates the dot product with another vector.

``````local result = myObject:dot(vec)
``````

Parameters:

Returns:

• `result` (number)
Example: The visualization of vector reflection

outDirection = inDirection - (normal * inDirection:dot(normal) * 2)

``````---@type niSwitchNode, niSwitchNode, niCamera
local lineIn, lineOut, camera
local verticalOffset = tes3vector3.new(0, 0, -30)

-- MWSE ships with a mesh which contains a few useful widgets.
-- These can be used during debugging.
local mesh = tes3.loadMesh("mwse\\widgets.nif") --[[@as niNode]]
local widgets = {
-- 3D coordinate axes
arrows = mesh:getObjectByName("unitArrows") --[[@as niTriShape]],
-- A common switch node that has three almost infinite lines
-- along each coordinate exis
axes = mesh:getObjectByName("axisLines") --[[@as niSwitchNode]],
plane = mesh:getObjectByName("unitPlane") --[[@as niTriShape]],
sphere = mesh:getObjectByName("unitSphere") --[[@as niTriShape]]
}

local root = tes3.worldController.vfxManager.worldVFXRoot
---@cast root niNode

lineIn = widgets.axes:clone() --[[@as niSwitchNode]]
lineOut = lineIn:clone() --[[@as niSwitchNode]]

root:attachChild(lineIn)
root:attachChild(lineOut)
root:update()

-- switchIndex = 0 - x axis (red)
-- switchIndex = 1 - y axis (green)
-- switchIndex = 2 - z axis (blue)
lineIn.switchIndex = 1
lineOut.switchIndex = 1
end

local function simulateCallback()
lineIn.translation = tes3.getPlayerEyePosition() + verticalOffset

local inDirection = camera.worldDirection
local rotation = lineIn.rotation:copy()
rotation:lookAt(inDirection, camera.worldUp)

lineIn.rotation = rotation
lineIn:update()

-- Now get the coordinates for the outLine
--local inDirection = tes3.getPlayerEyeVector()
local hit = tes3.rayTest({
position = lineIn.translation,
direction = inDirection,
returnNormal = true,
returnSmoothNormal = true,
ignore = { tes3.player, tes3.player1stPerson }
})
if not hit then return end

lineOut.translation = hit.intersection

local normal = hit.normal
local outDirection = inDirection - (normal * inDirection:dot(normal) * 2)
outDirection:normalize()
local axis = outDirection:cross(inDirection)
local rotation = tes3matrix33.new()
rotation:lookAt(outDirection, axis:normalized())

lineOut.rotation = rotation
lineOut:update()
end
event.register(tes3.event.simulate, simulateCallback)
``````

`heightDifference`⚓︎

Calculates the vertical distance to another vector.

``````local result = myObject:heightDifference(vec)
``````

Parameters:

Returns:

• `result` (number)

`interpolate`⚓︎

Calculates the interpolated position against the target vector using the `distance` parameter.

``````local result = myObject:interpolate(targetPoint, distance)
``````

Parameters:

• `targetPoint` (tes3vector3)
• `distance` (number)

Returns:

`length`⚓︎

Calculates the length of the vector.

``````local result = myObject:length()
``````

Returns:

• `result` (number)

`lerp`⚓︎

Calculates the interpolated vector between this vector and another, given a transition.

``````local lerpedVector = myObject:lerp(toVector, transition)
``````

Parameters:

• `toVector` (tes3vector3): The vector to interpolate towards.
• `transition` (number): The interpolation value. Must be between `0.0` (closer to this vector) and `1.0` (closer to the other vector).

Returns:

• `lerpedVector` (tes3vector3): The calculated value.

`negate`⚓︎

Negates all values in the vector.

``````myObject:negate()
``````

`normalize`⚓︎

Normalize the vector in-place, or set its components to zero if normalization is not possible. Returns `true` if the vector was successfully normalized.

``````local result = myObject:normalize()
``````

Returns:

• `result` (boolean)

`normalized`⚓︎

Get a normalized copy of the vector.

``````local result = myObject:normalized()
``````

Returns:

`outerProduct`⚓︎

Calculates the outer product with another vector.

``````local result = myObject:outerProduct(vec)
``````

Parameters:

Returns:

`toColor`⚓︎

Converts the vector to `niColor` object.

``````local result = myObject:toColor()
``````

Returns:

Functions⚓︎

`new`⚓︎

Creates a new vector. If no parameters are provided, an empty set will be constructed.

``````local vector = tes3vector3.new(x, y, z)
``````

Parameters:

• `x` (number): Default: `0`.
• `y` (number): Default: `0`.
• `z` (number): Default: `0`.

Returns:

Math Operations⚓︎

Addition (`+`)⚓︎

Left operand type Right operand type Result type Description
tes3vector3 number tes3vector3 Add the given number to each of the vector's components.
tes3vector3 tes3vector3 tes3vector3 Standard vector addition.

Division (`/`)⚓︎

Left operand type Right operand type Result type Description
tes3vector3 number tes3vector3 Divides the vector by a scalar.

Length (`#`)⚓︎

Result type Description
number Evaluates to the vector's length in game units.

Multiplication (`*`)⚓︎

Left operand type Right operand type Result type Description
tes3vector3 tes3vector3 tes3vector3 The per-element multiplication of two vectors, also known as Hadamard product.
tes3vector3 number tes3vector3 Multiplies the vector by a scalar.

Subtraction (`-`)⚓︎

Left operand type Right operand type Result type Description
tes3vector3 number tes3vector3 Subtracts given number from each of the vector's components.
tes3vector3 tes3vector3 tes3vector3 Standard vector subtraction.

Unary minus (`-`)⚓︎

Result type Description
tes3vector3 Swaps the sign of the vector's components.