GetElementMatrix: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
mNo edit summary
(Undo revision 67564 by Daddy (talk))
Tag: Undo
 
(14 intermediate revisions by 8 users not shown)
Line 1: Line 1:
{{Client function}}
{{Shared function}}
__NOTOC__  
__NOTOC__  
This function gets an element's transform matrix. This contains 16 float values that multiplied to a point will give you the point transformed. It is most useful for matrix calculations such as calculating offsets. For further information, please refer to a tutorial of matrices in computer graphics programming.
This function gets an [[element]]'s transform [[matrix]]. This contains 16 float values that multiplied to a point will give you the point transformed. It is most useful for matrix calculations such as calculating offsets. For further information, please refer to a tutorial of matrices in computer graphics programming.
{{Note|The matrix returned by this function is [http://bugs.mtasa.com/view.php?id{{=}}6984 not setup correctly for some calculations.] unless the '''legacy''' argument is set to '''false'''}}
{{Note|The [[matrix]] returned by this function is [http://bugs.mtasa.com/view.php?id{{=}}6984 not setup correctly for some calculations] unless the '''legacy''' argument is set to '''''false'''''.}}
{{Tip|''For matrix manipulation which goes beyond the basic examples given on this page, see the [[Lua matrix library]].''}}
{{Tip|''For [[matrix]] manipulation which goes beyond the basic examples given on this page, see the [[Lua matrix library]].'' If you are using MTA: SA 1.4 or higher, using the built-in [[matrix]] class is also recommended.}}
==Syntax==
==Syntax==
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
table getElementMatrix ( element theElement [, bool legacy = true ] )      
table getElementMatrix ( element theElement [, bool legacy = true ] )
</syntaxhighlight>  
</syntaxhighlight>
{{OOP||[[element]]:getMatrix|matrix|setElementMatrix}}


===Required Arguments===  
===Required Arguments===  
*'''theElement:''' The element which you wish to retrieve the matrix for
*'''theElement:''' The [[element]] which you wish to retrieve the [[matrix]] for.


===Optional Arguments===  
===Optional Arguments===  
*'''legacy :''' Set to false to return correctly setup matrix. (i.e. Last column in the first 3 rows set to zero.)
*'''legacy:''' Set to ''false'' to return correctly setup [[matrix]] (i.e. Last column in the first 3 rows set to zero).


===Returns===
===Returns===
Returns a multi-dimensional array containing a 4x4 matrix. Returns false if the element is not streamed in, and not a vehicle or ped.
Returns a multi-dimensional array (which can be transformed into a proper [[matrix]] class using ''Matrix.create'' method) containing a 4x4 matrix. Returns ''false'' if the element is not streamed in, and not a [[vehicle]], [[ped]] or [[object]].


==Example==  
==Example==  
Line 22: Line 23:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function getPositionFromElementOffset(element,offX,offY,offZ)
function getPositionFromElementOffset(element,offX,offY,offZ)
local m = getElementMatrix ( element )  -- Get the matrix
    local m = getElementMatrix ( element )  -- Get the matrix
local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]  -- Apply transform
    local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]  -- Apply transform
local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
    local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
    local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
return x, y, z                              -- Return the transformed point
    return x, y, z                              -- Return the transformed point
end
end


-- Get the position of a point 3 units to the left of the element:
-- Get the position of a point 3 units to the right of the element:
x,y,z = getPositionFromElementOffset(element,3,0,0)
x,y,z = getPositionFromElementOffset(element,3,0,0)


Line 43: Line 44:
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
function getMatrixLeft(m)
function getMatrixLeft(m)
        return m[1][1], m[1][2], m[1][3]
    return m[1][1], m[1][2], m[1][3]
end
end
function getMatrixForward(m)
function getMatrixForward(m)
        return m[2][1], m[2][2], m[2][3]
    return m[2][1], m[2][2], m[2][3]
end
end
function getMatrixUp(m)
function getMatrixUp(m)
        return m[3][1], m[3][2], m[3][3]
    return m[3][1], m[3][2], m[3][3]
end
end
function getMatrixPosition(m)
function getMatrixPosition(m)
        return m[4][1], m[4][2], m[4][3]
    return m[4][1], m[4][2], m[4][3]
end
end


Line 62: Line 63:
</syntaxhighlight>
</syntaxhighlight>


This example allows you to get the element matrix of an element that is outside your stream range.
This example function allows you to get the element matrix of an element that is not streamed in.
<syntaxhighlight lang="lua">
<syntaxhighlight lang="lua">
-- Override normal getElementMatrix with our own version
function getElementMatrix(element)
function getElementMatrix(element)
local rx, ry, rz = getElementRotation(element, "ZXY")
    local rx, ry, rz = getElementRotation(element, "ZXY")
local rx, ry, rz = math.rad(rotX), math.rad(rotY), math.rad(rotZ)
    rx, ry, rz = math.rad(rx), math.rad(ry), math.rad(rz)
local matrix = {}
    local matrix = {}
matrix[1] = {}
    matrix[1] = {}
matrix[1][1] = math.cos(rz)*math.cos(ry) - math.sin(rz)*math.sin(rx)*math.sin(ry)
    matrix[1][1] = math.cos(rz)*math.cos(ry) - math.sin(rz)*math.sin(rx)*math.sin(ry)
matrix[1][2] = math.cos(ry)*math.sin(rz) + math.cos(rz)*math.sin(rx)*math.sin(ry)
    matrix[1][2] = math.cos(ry)*math.sin(rz) + math.cos(rz)*math.sin(rx)*math.sin(ry)
matrix[1][3] = -math.cos(rx)*math.sin(ry)
    matrix[1][3] = -math.cos(rx)*math.sin(ry)
    matrix[1][4] = 1
   
    matrix[2] = {}
    matrix[2][1] = -math.cos(rx)*math.sin(rz)
    matrix[2][2] = math.cos(rz)*math.cos(rx)
    matrix[2][3] = math.sin(rx)
    matrix[2][4] = 1
matrix[2] = {}
    matrix[3] = {}
matrix[2][1] = -math.cos(rx)*math.sin(rz)
    matrix[3][1] = math.cos(rz)*math.sin(ry) + math.cos(ry)*math.sin(rz)*math.sin(rx)
matrix[2][2] = math.cos(rz)*math.cos(rx)
    matrix[3][2] = math.sin(rz)*math.sin(ry) - math.cos(rz)*math.cos(ry)*math.sin(rx)
matrix[2][3] = math.sin(rx)
    matrix[3][3] = math.cos(rx)*math.cos(ry)
    matrix[3][4] = 1
matrix[3] = {}
    matrix[4] = {}
matrix[3][1] = math.cos(rz)*math.sin(ry) + math.cos(ry)*math.sin(rz)*math.sin(rx)
    matrix[4][1], matrix[4][2], matrix[4][3] = getElementPosition(element)
matrix[3][2] = math.sin(rz)*math.sin(ry) - math.cos(rz)*math.cos(ry)*math.sin(rx)
    matrix[4][4] = 1
matrix[3][3] = math.cos(rx)*math.cos(ry)
matrix[4] = {}
    return matrix
matrix[4][1], matrix[4][2], matrix[4][3] = getElementPosition(element) -- this is kinda useless but is used to have the same structure as getElementMatrix
end
</syntaxhighlight>
return matrix
 
 
 
 
<section name="Server side: Front to Front" class="server" show="true">
-- create a Ped (0, 0, 5, 0) and put the player to 10 m of distance, front to front
<syntaxhighlight lang="lua">
function startedThisResource (res)
if getThisResource() == res then
local thePed = createPed ( 287, 0, 0, 5, 0)
local matrix = getElementMatrix(thePed)
nx = 0 * matrix[1][1] + 10 * matrix[2][1] + 0 * matrix[3][1] + 1 * matrix[4][1]
ny = 0 * matrix[1][2] + 10 * matrix[2][2] + 0 * matrix[3][2] + 1 * matrix[4][2]
nz = 0 * matrix[1][3] + 10 * matrix[2][3] + 0 * matrix[3][3] + 1 * matrix[4][3]
for a, z in ipairs(getElementsByType("player")) do
setElementPosition (z, nx, ny, nz)
local playerX, playerY, playerZ = getElementPosition(z)
local pedX, pedY, pedZ = getElementPosition(thePed)
local rotZ = findRotation( playerX, playerY, pedX, pedY )
setElementRotation(z, 0, 0, rotZ)
end
end
end
end
addEventHandler("onResourceStart", getRootElement(), startedThisResource)


local mat = getElementMatrix(element) -- this gives the same result as normal getElementMatrix(element), except that it also works if the element is not streamed in
function findRotation( x1, y1, x2, y2 )
    local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
    return t < 0 and t + 360 or t
end
</syntaxhighlight>
</syntaxhighlight>
</section>


==Changelog==
==Changelog==

Latest revision as of 22:08, 25 December 2020

This function gets an element's transform matrix. This contains 16 float values that multiplied to a point will give you the point transformed. It is most useful for matrix calculations such as calculating offsets. For further information, please refer to a tutorial of matrices in computer graphics programming.

[[{{{image}}}|link=|]] Note: The matrix returned by this function is not setup correctly for some calculations unless the legacy argument is set to false.
[[{{{image}}}|link=|]] Tip: For matrix manipulation which goes beyond the basic examples given on this page, see the Lua matrix library. If you are using MTA: SA 1.4 or higher, using the built-in matrix class is also recommended.

Syntax

table getElementMatrix ( element theElement [, bool legacy = true ] )

OOP Syntax Help! I don't understand this!

Method: element:getMatrix(...)
Variable: .matrix
Counterpart: setElementMatrix


Required Arguments

  • theElement: The element which you wish to retrieve the matrix for.

Optional Arguments

  • legacy: Set to false to return correctly setup matrix (i.e. Last column in the first 3 rows set to zero).

Returns

Returns a multi-dimensional array (which can be transformed into a proper matrix class using Matrix.create method) containing a 4x4 matrix. Returns false if the element is not streamed in, and not a vehicle, ped or object.

Example

This example creates a utility function that turns an offset into a position that is relative to the specified element.

function getPositionFromElementOffset(element,offX,offY,offZ)
    local m = getElementMatrix ( element )  -- Get the matrix
    local x = offX * m[1][1] + offY * m[2][1] + offZ * m[3][1] + m[4][1]  -- Apply transform
    local y = offX * m[1][2] + offY * m[2][2] + offZ * m[3][2] + m[4][2]
    local z = offX * m[1][3] + offY * m[2][3] + offZ * m[3][3] + m[4][3]
    return x, y, z                               -- Return the transformed point
end

-- Get the position of a point 3 units to the right of the element:
x,y,z = getPositionFromElementOffset(element,3,0,0)

-- Get the position of a point 2 units in front of the element:
x,y,z = getPositionFromElementOffset(element,0,2,0)

-- Get the position of a point 1 unit above the element:
x,y,z = getPositionFromElementOffset(element,0,0,1)

This example creates some more matrix utility functions

function getMatrixLeft(m)
    return m[1][1], m[1][2], m[1][3]
end
function getMatrixForward(m)
    return m[2][1], m[2][2], m[2][3]
end
function getMatrixUp(m)
    return m[3][1], m[3][2], m[3][3]
end
function getMatrixPosition(m)
    return m[4][1], m[4][2], m[4][3]
end

local mat = getElementMatrix(element)  -- Get the matrix
x,y,z = getMatrixLeft(mat)     -- Get the matrix left direction
x,y,z = getMatrixForward(mat)  -- Get the matrix forward direction
x,y,z = getMatrixUp(mat)       -- Get the matrix up direction

This example function allows you to get the element matrix of an element that is not streamed in.

function getElementMatrix(element)
    local rx, ry, rz = getElementRotation(element, "ZXY")
    rx, ry, rz = math.rad(rx), math.rad(ry), math.rad(rz)
    local matrix = {}
    matrix[1] = {}
    matrix[1][1] = math.cos(rz)*math.cos(ry) - math.sin(rz)*math.sin(rx)*math.sin(ry)
    matrix[1][2] = math.cos(ry)*math.sin(rz) + math.cos(rz)*math.sin(rx)*math.sin(ry)
    matrix[1][3] = -math.cos(rx)*math.sin(ry)
    matrix[1][4] = 1
    
    matrix[2] = {}
    matrix[2][1] = -math.cos(rx)*math.sin(rz)
    matrix[2][2] = math.cos(rz)*math.cos(rx)
    matrix[2][3] = math.sin(rx)
    matrix[2][4] = 1
	
    matrix[3] = {}
    matrix[3][1] = math.cos(rz)*math.sin(ry) + math.cos(ry)*math.sin(rz)*math.sin(rx)
    matrix[3][2] = math.sin(rz)*math.sin(ry) - math.cos(rz)*math.cos(ry)*math.sin(rx)
    matrix[3][3] = math.cos(rx)*math.cos(ry)
    matrix[3][4] = 1
	
    matrix[4] = {}
    matrix[4][1], matrix[4][2], matrix[4][3] = getElementPosition(element)
    matrix[4][4] = 1
	
    return matrix
end



Click to collapse [-]
Server side: Front to Front

-- create a Ped (0, 0, 5, 0) and put the player to 10 m of distance, front to front

function startedThisResource (res)
	if getThisResource() == res then
		local thePed = createPed ( 287, 0, 0, 5, 0)
		local matrix = getElementMatrix(thePed)
		nx = 0 * matrix[1][1] + 10 * matrix[2][1] + 0 * matrix[3][1] + 1 * matrix[4][1]
		ny = 0 * matrix[1][2] + 10 * matrix[2][2] + 0 * matrix[3][2] + 1 * matrix[4][2]
		nz = 0 * matrix[1][3] + 10 * matrix[2][3] + 0 * matrix[3][3] + 1 * matrix[4][3]
		for a, z in ipairs(getElementsByType("player")) do
			setElementPosition (z, nx, ny, nz)
			local playerX, playerY, playerZ = getElementPosition(z)
			local pedX, pedY, pedZ = getElementPosition(thePed)
			local rotZ = findRotation( playerX, playerY, pedX, pedY ) 
			setElementRotation(z, 0, 0, rotZ)
		end
	end
end
addEventHandler("onResourceStart", getRootElement(), startedThisResource)

function findRotation( x1, y1, x2, y2 ) 
    local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
    return t < 0 and t + 360 or t
end

Changelog

Version Description
1.3.0-9.04186 Added legacy argument

See Also