AttachElementsOffsets: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
(Created page with "'''This article concerns the note left in attachElements.''' ==Explanation== The offset coordinates reflect the object space, not the world space. This means that if you wer...")
 
mNo edit summary
 
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
'''This article concerns the note left in [[attachElements]].'''
'''This article concerns the note left in [[attachElements]].'''


==Explanation==
==Problem==
The offset coordinates reflect the object space, not the world space. This means that if you were to calculate coordinate and rotation offsets between "theElement" and "theAttachToElement", they would not always be correct.  
The offset coordinates reflect the object space, not the world space. This means that you cannot simply visualize the attachment in the map editor and calculate the offsets between the 2 sets of world coordinates for "theElement" and "theAttachToObject".


The example script below places a plane facing upward on a silo. The positioning was done manually in the map editor and the coordinates were saved to the script. These coordinates are reflected in the initial creation of objects "shuttletable[1]" and "shuttletable[2]".
For example, if "theAttachToElement" has XYZ rotations, then "theElement" will inherit these rotations. The specified rotation offsets will then be performed from these starting rotation points. Simply put, "theElement" will be rotated twice.


The problem is we will need the offsets of the "theElement" in relation to "theAttachToElement". "theAttachToElement" becomes 0,0,0,0,0,0 and "theElement" will inherit the exact same coordinates and rotation, unless offsets are specified when using the [[attachElements]] function.
==Solution==
The following code shows how to use offsets calculated in the map editor with 'attachElements':
<syntaxhighlight lang="lua">addEventHandler( "onResourceStart", resourceRoot,
    function()
        -- Postion and rotations from the map editor:
        local mainPos = { -756, 995, 14 }
        local mainRot = { 0, 0, 90 }            -- Two rotations are zero. See note in attachRotationAdjusted


==Example==
        local subPos = { -756, 999, 24 }
Start freeroam resource and paste this into the console:
        local subRot = { 89, 0, 177 }          -- One rotation is zero. See note in attachRotationAdjusted
<syntaxhighlight lang="lua">setpos 1904.7426757813 -2411.1262207031 13.53911781311</syntaxhighlight>


Now, use the following script and look at the rocket. See how it is off center? This means the relation to the actual game world coordinate system has changed.
        -- Create the objects
        mainObject = createObject ( 17050, mainPos[1], mainPos[2], mainPos[3], mainRot[1], mainRot[2], mainRot[3] )
        subObject = createVehicle ( 519, subPos[1], subPos[2], subPos[3], subRot[1], subRot[2], subRot[3] )


If you change rocketRZ to 0 (the silo object that the plane in attached to), this will put the rocket in the correct position. So what happened? The silo is "theAttachToElement" and it becomes 0,0,0,0,0,0.  This example is unusual in that you have essentially fixed your problem. The silo looks the same all the way around. Although it is no longer rotated the application still works. However, you will find that to use the correct rotation of the silo ("theAttachToElement"), you will need a different set of X,Y,Z coordinates. 
        -- Attach so they look like what they do in the map editor
        attachRotationAdjusted ( subObject, mainObject )
    end
)


<syntaxhighlight lang="lua">
--This example illustrates the problem with using the world coordinate math to calculate offsets.
--Change rocketRZ to 0 to get the correct position.


local rocketX = 1925.022705
function attachRotationAdjusted ( from, to )
local rocketY = -2450.944336
    -- Note: Objects being attached to ('to') should have at least two of their rotations set to zero
local rocketZ = 18.053474
    --      Objects being attached ('from') should have at least one of their rotations set to zero
local rocketRX = 0
    -- Otherwise it will look all funny
local rocketRY = 0
local rocketRZ = 69.61437


local vehX = 1925.112793 --more is forward
    local frPosX, frPosY, frPosZ = getElementPosition( from )
local vehY = -2446.260742 -- less is forward
    local frRotX, frRotY, frRotZ = getElementRotation( from )
local vehZ = 26.692139
    local toPosX, toPosY, toPosZ = getElementPosition( to )
local vehRX = 89.38142
    local toRotX, toRotY, toRotZ = getElementRotation( to )
local vehRY = 0.030000
    local offsetPosX = frPosX - toPosX
local vehRZ = 177.90356
    local offsetPosY = frPosY - toPosY
    local offsetPosZ = frPosZ - toPosZ
    local offsetRotX = frRotX - toRotX
    local offsetRotY = frRotY - toRotY
    local offsetRotZ = frRotZ - toRotZ


shuttletable = {}
    offsetPosX, offsetPosY, offsetPosZ = applyInverseRotation ( offsetPosX, offsetPosY, offsetPosZ, toRotX, toRotY, toRotZ )
shuttletable[1] = createObject ( 17050, rocketX, rocketY, rocketZ, rocketRX, rocketRY, rocketRZ )
shuttletable[2] = createVehicle ( 519, vehX, vehY, vehZ, vehRX, vehRY, vehRZ )
attachOffsetX = vehX-rocketX
attachOffsetY = vehY-rocketY
attachOffsetZ = vehZ-rocketZ
attachOffsetRX = vehRX-rocketRX
attachOffsetRY = vehRY-rocketRY
attachOffsetRZ = vehRZ-rocketRZ


attachElements( shuttletable[2], shuttletable[1], attachOffsetX, attachOffsetY, attachOffsetZ, attachOffsetRX, attachOffsetRY, attachOffsetRZ )</syntaxhighlight>
    attachElements( from, to, offsetPosX, offsetPosY, offsetPosZ, offsetRotX, offsetRotY, offsetRotZ )
end
 
 
function applyInverseRotation ( x,y,z, rx,ry,rz )
    -- Degress to radians
    local DEG2RAD = (math.pi * 2) / 360
    rx = rx * DEG2RAD
    ry = ry * DEG2RAD
    rz = rz * DEG2RAD
 
    -- unrotate each axis
    local tempY = y
    y =  math.cos ( rx ) * tempY + math.sin ( rx ) * z
    z = -math.sin ( rx ) * tempY + math.cos ( rx ) * z
 
    local tempX = x
    x =  math.cos ( ry ) * tempX - math.sin ( ry ) * z
    z =  math.sin ( ry ) * tempX + math.cos ( ry ) * z
 
    tempX = x
    x =  math.cos ( rz ) * tempX + math.sin ( rz ) * y
    y = -math.sin ( rz ) * tempX + math.cos ( rz ) * y
 
    return x, y, z
end</syntaxhighlight>
 
[[Category:Scripting Concepts]]

Latest revision as of 10:42, 13 July 2024

This article concerns the note left in attachElements.

Problem

The offset coordinates reflect the object space, not the world space. This means that you cannot simply visualize the attachment in the map editor and calculate the offsets between the 2 sets of world coordinates for "theElement" and "theAttachToObject".

For example, if "theAttachToElement" has XYZ rotations, then "theElement" will inherit these rotations. The specified rotation offsets will then be performed from these starting rotation points. Simply put, "theElement" will be rotated twice.

Solution

The following code shows how to use offsets calculated in the map editor with 'attachElements':

addEventHandler( "onResourceStart", resourceRoot,
    function()
        -- Postion and rotations from the map editor:
        local mainPos = { -756, 995, 14 }
        local mainRot = { 0, 0, 90 }            -- Two rotations are zero. See note in attachRotationAdjusted

        local subPos = { -756, 999, 24 }
        local subRot = { 89, 0, 177 }           -- One rotation is zero. See note in attachRotationAdjusted

        -- Create the objects
        mainObject = createObject ( 17050, mainPos[1], mainPos[2], mainPos[3], mainRot[1], mainRot[2], mainRot[3] )
        subObject = createVehicle ( 519, subPos[1], subPos[2], subPos[3], subRot[1], subRot[2], subRot[3] )

        -- Attach so they look like what they do in the map editor
        attachRotationAdjusted ( subObject, mainObject )
    end
)


function attachRotationAdjusted ( from, to )
    -- Note: Objects being attached to ('to') should have at least two of their rotations set to zero
    --       Objects being attached ('from') should have at least one of their rotations set to zero
    -- Otherwise it will look all funny

    local frPosX, frPosY, frPosZ = getElementPosition( from )
    local frRotX, frRotY, frRotZ = getElementRotation( from )
    local toPosX, toPosY, toPosZ = getElementPosition( to )
    local toRotX, toRotY, toRotZ = getElementRotation( to )
    local offsetPosX = frPosX - toPosX
    local offsetPosY = frPosY - toPosY
    local offsetPosZ = frPosZ - toPosZ
    local offsetRotX = frRotX - toRotX
    local offsetRotY = frRotY - toRotY
    local offsetRotZ = frRotZ - toRotZ

    offsetPosX, offsetPosY, offsetPosZ = applyInverseRotation ( offsetPosX, offsetPosY, offsetPosZ, toRotX, toRotY, toRotZ )

    attachElements( from, to, offsetPosX, offsetPosY, offsetPosZ, offsetRotX, offsetRotY, offsetRotZ )
end


function applyInverseRotation ( x,y,z, rx,ry,rz )
    -- Degress to radians
    local DEG2RAD = (math.pi * 2) / 360
    rx = rx * DEG2RAD
    ry = ry * DEG2RAD
    rz = rz * DEG2RAD

    -- unrotate each axis
    local tempY = y
    y =  math.cos ( rx ) * tempY + math.sin ( rx ) * z
    z = -math.sin ( rx ) * tempY + math.cos ( rx ) * z

    local tempX = x
    x =  math.cos ( ry ) * tempX - math.sin ( ry ) * z
    z =  math.sin ( ry ) * tempX + math.cos ( ry ) * z

    tempX = x
    x =  math.cos ( rz ) * tempX + math.sin ( rz ) * y
    y = -math.sin ( rz ) * tempX + math.cos ( rz ) * y

    return x, y, z
end