1

My math knowledge is quite depressing unfortunately, but I really want to understand the code which I have to control the Actor by dragging it with the mouse. This code also works as the way to place object in the world with mouse click on the screen.

First of all - the code works great, it is the question more about vector algebra rather than Unreal Engine. I am so lost that I even don't know how to properly name the variables lol

So, here is the code I've converted from one of the Blueprint examples I found which implements the functionality I need:

    FVector WorldLocation;
    FVector WorldDirection;
    PlayerController->DeprojectMousePositionToWorld(WorldLocation, WorldDirection);

    // Have no idea how it works but it works! I really need to learn more about vector Algebra :(((
    float DistanceAboveGround = 200.0f;
    float NotSureWhyThisValue = -1.0f;
    float WhyThisOperation = WorldLocation.Z / WorldDirection.Z + DistanceAboveGround;

    FVector IsThisNewWorldDirection = WorldDirection * WhyThisOperation * NotSureWhyThisValue;
    FVector ActorWorldLocation = WorldLocation + IsThisNewWorldDirection;            
    // end of "Have no idea how it works" code
    Capsule->SetWorldLocation(ActorWorldLocation);

If somebody can please explain me why I need to do these operations starring from // Have no idea.. comment line? If I can understand even how to properly name "NotSureWhyThisValue", "WhatDoesItMean", "WhyThisOperation" and "IsThisNewWorldDirection?" that will be a huge improvement for me, the perfect case would be to explain each line though...

Thanks in advance!

paxer
  • 961
  • 10
  • 17
  • Is this only supposed to calculate the actor height value? – Tagger5926 Nov 19 '19 at 01:11
  • 1
    the code works, I use it in Tick and can drag my actor with the changing mouse position. One thing might help to understand the Unreal scene - it is an RTS kind of game, so imagine Starcraft 3 and I am spawning an actor on the map with the mouse click. – paxer Nov 19 '19 at 01:22

1 Answers1

1

This is just a reimplementation of FMath::LinePlaneIntersection that just takes certain shortcuts because the plane's normal is (0,0,1):

FVector WorldLocation;
FVector WorldDirection;
float DistanceAboveGround = 200.0f;

PlayerController->DeprojectMousePositionToWorld(WorldLocation, WorldDirection); 

FVector PlaneOrigin(0.0f, 0.0f, DistanceAboveGround);

FVector ActorWorldLocation = FMath::LinePlaneIntersection(
            WorldLocation,
            WorldLocation + WorldDirection,
            PlaneOrigin,
            FVector::UpVector);

Capsule->SetWorldLocation(ActorWorldLocation);

See this answer by Bas Smit here if you want to better understand the math (copied below):

Vector3 Intersect(Vector3 planeP, Vector3 planeN, Vector3 rayP, Vector3 rayD)
{
    var d = Vector3.Dot(planeP, -planeN);
    var t = -( d 
            + rayP.z * planeN.z 
            + rayP.y * planeN.y 
            + rayP.x * planeN.x) 
          / (rayD.z * planeN.z 
            + rayD.y * planeN.y 
            + rayD.x * planeN.x);
    return rayP + t * rayD;
}

Basically, WhyThisOperation turns out to be -t, then it gets multiplied by -1 to make it t, then it gets multiplied by WorldDirection (rayD) and added to WorldPosition (rayP) to get the intersection point.

Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • 1
    this looks much cleaner thanks! One question why we need to "WorldLocation + WorldDirection" here? – paxer Nov 19 '19 at 01:28
  • @paxer I edited my question to better explain the code you gave. In my code you need to have a 2nd point on the line for that function and adding the origin and the direction gives you another point on the line :) – Ruzihm Nov 19 '19 at 01:49