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:
vec
(tes3vector3)
Returns:
result
(number)
copy
⚓︎
Creates a copy of the vector.
local result = myObject:copy()
Returns:
result
(tes3vector3)
cross
⚓︎
Calculates the cross product with another vector.
local result = myObject:cross(vec)
Parameters:
vec
(tes3vector3)
Returns:
result
(tes3vector3)
distance
⚓︎
Calculates the distance to another vector in the standard way, i.e., using the Euclidean distance.
local result = myObject:distance(vec)
Parameters:
vec
(tes3vector3)
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
, thenv2
is contained in a sphere aroundv1
with radius 1 (i.e. diameter 2). - If
v1:distanceChebyshev(v2) <= 1
, thenv2
is contained within a cube centered aroundv1
, where the cube has length 2.
local result = myObject:distanceChebyshev(vec)
Parameters:
vec
(tes3vector3)
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:
vec
(tes3vector3)
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:
vec
(tes3vector3)
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:
vec
(tes3vector3)
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)
local function onLoaded()
-- 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
camera = tes3.worldController.worldCamera.cameraData.camera
end
event.register(tes3.event.loaded, onLoaded)
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:
vec
(tes3vector3)
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:
result
(tes3vector3)
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 between0.0
(closer to this vector) and1.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:
result
(tes3vector3)
outerProduct
⚓︎
Calculates the outer product with another vector.
local result = myObject:outerProduct(vec)
Parameters:
vec
(tes3vector3)
Returns:
result
(tes3matrix33)
toColor
⚓︎
Converts the vector to niColor
object.
local result = myObject:toColor()
Returns:
result
(niColor)
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:
vector
(tes3vector3)
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. |