AttachElementsOffsets: Difference between revisions

From Multi Theft Auto: Wiki
Jump to navigation Jump to search
No edit summary
Line 4: Line 4:
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 between "theElement" and "theAttachToObject".
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 between "theElement" and "theAttachToObject".


==Example==
==Solution==
Start freeroam resource and paste this into the console:
The follow code shows how to use offsets calculated in the map editor with 'attachElements':
<syntaxhighlight lang="lua">setpos 1904.7426757813 -2411.1262207031 13.53911781311</syntaxhighlight>
<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


Now, use the following script and look at the plane on the rocket. See how it is off center? It is off center despite the fact you found the positions in the map editor and calculated the offsets. If you commented out the [[attachElements]] line you will see that the plane is created in the correct position in relation to the rocket in terms of '''world coordinates'''.
        local subPos = { -756, 999, 24 }
        local subRot = { 89, 0, 177 }          -- One rotation is zero. See note in attachRotationAdjusted


In this example, if you make "rocketRZ = 0" you will have the correct coordinates. Again, because the offsets are based off "theAttachToElement". If you kept any rotations in the object, it would change the XYZ coordinates "theElement" would need to be attached at.
        -- 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] )


<syntaxhighlight lang="lua">
        -- Attach so they look like what they do in the map editor
--This example illustrates the problem with using the world coordinate math to calculate offsets.
        attachRotationAdjusted ( subObject, mainObject )
--Change rocketRZ to 0 to get the correct position.
    end
)


local rocketX = 1925.022705
local rocketY = -2450.944336
local rocketZ = 18.053474
local rocketRX = 0
local rocketRY = 0
local rocketRZ = 69.61437


local vehX = 1925.112793 --more is forward
function attachRotationAdjusted ( from, to )
local vehY = -2446.260742 -- less is forward
    -- Note: Objects being attached to ('to') should have at least two of their rotations set to zero
local vehZ = 26.692139
    --       Objects being attached ('from') should have at least one of their rotations set to zero
local vehRX = 89.38142
    -- Otherwise it will look all funny
local vehRY = 0.030000
local vehRZ = 177.90356


shuttletable = {}
    local frPosX, frPosY, frPosZ = getElementPosition( from )
shuttletable[1] = createObject ( 17050, rocketX, rocketY, rocketZ, rocketRX, rocketRY, rocketRZ )
    local frRotX, frRotY, frRotZ = getElementRotation( from )
shuttletable[2] = createVehicle ( 519, vehX, vehY, vehZ, vehRX, vehRY, vehRZ )
    local toPosX, toPosY, toPosZ = getElementPosition( to )
    local toRotX, toRotY, toRotZ = getElementRotation( to )
attachOffsetX = vehX-rocketX
    local offsetPosX = frPosX - toPosX
attachOffsetY = vehY-rocketY
    local offsetPosY = frPosY - toPosY
attachOffsetZ = vehZ-rocketZ
    local offsetPosZ = frPosZ - toPosZ
attachOffsetRX = vehRX-rocketRX
    local offsetRotX = frRotX - toRotX
attachOffsetRY = vehRY-rocketRY
    local offsetRotY = frRotY - toRotY
attachOffsetRZ = vehRZ-rocketRZ
    local offsetRotZ = frRotZ - toRotZ


attachElements( shuttletable[2], shuttletable[1], attachOffsetX, attachOffsetY, attachOffsetZ, attachOffsetRX, attachOffsetRY, attachOffsetRZ )</syntaxhighlight>
    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</syntaxhighlight>

Revision as of 00:42, 10 April 2011

This article concerns the note left in attachElements.

Explanation

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 between "theElement" and "theAttachToObject".

Solution

The follow 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