How to get a socket's position relative to it's parent component?

Hello everybody,

Firstly, there is a question on answers.unrealengine I posted, but I might as well put it here too. :slight_smile:
Link: here

The question is (Hang in there, it’s going to be long :D):

I’m having a bit of a problem getting the relative position of a socket with code.
I’ve tried numerous solutions I could find, but the functions always return an FVector of (0,0,0).

This is how the skeletal mesh’s (is this correct grammar? :D) skeleton looks:

https://dl.dropboxusercontent.com/u/101118701/SkeletonSocket.jpg

So, the problem is with the highlighted socket. Any other socket I have (Except the other turbine socket) works fine and returns the actual relative position, but not those two.

TL;DR How would I get the location of the socket relative to the base socket/bone (in this case, labelled “Chassis”)?

Anyway, here is how I get the positions:


//Vehicle_MovementComp.h
struct ThrusterTransform
{
    FVector direction;
    FVector location;
    FString tag;

    ThrusterTransform(
        FVector direction = FVector::ZeroVector, 
        FVector location = FVector::ZeroVector, 
        FString tag = TEXT("")) :
        direction(direction), location(location), tag(tag) 
    {

    }
};

//Foenix_Pawn.cpp
        //includes Vehicle_MovementComp.h

        //This is unique to every vehicle, this is the pawn's code
        //Fill up movementThrusterSockets array (Type USkeletalMeshSocket*)
        movementThrusterSockets.Add(const_cast<USkeletalMeshSocket*>(foenixMesh->GetSocketByName(FName(TEXT("Turbine_L_S")))));
        movementThrusterSockets.Add(const_cast<USkeletalMeshSocket*>(foenixMesh->GetSocketByName(FName(TEXT("Turbine_R_S")))));
        movementThrusterSockets.Add(const_cast<USkeletalMeshSocket*>(foenixMesh->GetSocketByName(FName(TEXT("steer_fl")))));
        movementThrusterSockets.Add(const_cast<USkeletalMeshSocket*>(foenixMesh->GetSocketByName(FName(TEXT("steer_fr")))));
        movementThrusterSockets.Add(const_cast<USkeletalMeshSocket*>(foenixMesh->GetSocketByName(FName(TEXT("steer_rl")))));
        movementThrusterSockets.Add(const_cast<USkeletalMeshSocket*>(foenixMesh->GetSocketByName(FName(TEXT("steer_rr")))));

        //This is what I want to be universal to every vehicle, this is going to be (hopefully) in the UMovementComponent derived class
        //Right now it is with the above code (as in, in the same file/class)
        //Fill up thrusters array (Type ThrusterTransform*)
        thrusters.SetNum(movementThrusterSockets.Num());
        for (int16 i = 0; i < thrusters.Num(); i++)
        {
            //foenixMesh type is USkeletalMeshComponent
            thrusters*.location = foenixMesh->GetSocketTransform(movementThrusterSockets*->GetFName(), ERelativeTransformSpace::RTS_Actor).GetTranslation();
            thrusters*.direction = movementThrusterSockets*->GetSocketTransform(foenixMesh).GetUnitAxis(EAxis::X);
        }
        //Set thrusters array element tags (this is unique to every vehicle)
        thrusters[0].tag = FString(TEXT("LMainEngine"));
        thrusters[1].tag = FString(TEXT("RMainEngine"));
        thrusters[2].tag = FString(TEXT("RSteeringEngine"));
        thrusters[3].tag = FString(TEXT("LSteeringEngine"));
        thrusters[4].tag = FString(TEXT("LSteeringEngine"));
        thrusters[5].tag = FString(TEXT("RSteeringEngine"));

The problem is with this row:

thrusters*.location = foenixMesh->GetSocketTransform(movementThrusterSockets*->GetFName(), RelativeTransformSpace::RTS_Actor).GetTranslation();

it always returns FVector(0,0,0) for the first two sockets.

Other tries were:


//First:
thrusters*.location = foenixMesh->GetComponentTransform().GetTranslation() + movementThrusterSockets*->RelativeLocation;
//Second
thrusters*.location = foenixMesh->GetComponentLocation() + movementThrusterSockets*->RelativeLocation;

I think the problem is that it’s getting the position relative to the parent socket/bone (the “Turbine_R” bone), which in this case would be FVector(0,0,0), though I don’t understand why it doesn’t return the proper one even when I specify the RTS_Actor parameter.

So the question would be: How would I get the location of the socket relative to the base socket/bone (in this case, labelled “Chassis”)?

I was sure there’s a way to get the Relative location of a Socket to it’s parent mesh… maybe not though.

What you can do is use InverseTransformLocation() to get the World Position in Relative Coordinates. It’s been a while since I’ve needed that function but IIRC it’s relatively easy to use (double check this syntax though)



VectorToTransform.InverseTransformLocation(const FTransform RootTransform);


There is a way to get the relative location of a Socket: rather than calling GetSocketLocation, which indeed returns the World Location of the socket, you can call the GetSocketTransform which has a TransformSpace parameter, allowing you to choose wether you want your coordinates in World Space or Actor (Relative) Space.

Cheers

2 Likes

Very Nice thank you