2021-11-30 21:29:18 -06:00
// odplot productions is a trademarked name. Project Yugh is a copyrighted property. This code, however, is free to be copy and extended as you see fit.
2022-11-03 16:58:03 -05:00
# include "3pfollow.h"
2021-11-30 21:29:18 -06:00
# include <math.h>
// void ThirdPersonFollow::_ready() {
// Target = dynamic_cast<Spatial*>(get_node(TargetPath));
// ExternalFrame = dynamic_cast<Spatial*>(get_node(ExternalFramePath));
// }
// void ThirdPersonFollow::_process(float delta_time) {
// if (Target != nullptr) {
// // Get the frame of reference
// if (has_node(ExternalFramePath) && get_node(ExternalFramePath) != this)
// TFOR = dynamic_cast<Spatial*>(get_node(ExternalFramePath))->get_global_transform();
// else
// TFOR = Transform(Basis(glm::vec3::RIGHT(), glm::vec3::UP(), glm::vec3::FORWARD()), glm::vec3::ZERO());
// CalculateTargetOffset();
// TargetPosition = CalculatePosition();
// translate(to_local(FrameBasedVectorLerp(get_global_translation(), TargetPosition, PositionSpeeds, delta_time)));
// set_rotation_degrees(get_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time));
// }
// // For rotation
// // TODO: Add rotation offset in properly
// //this->SetActorRotation(FMath::Lerp(this->GetActorRotation(), TargetRotation, RotationSpeed * DeltaTime));
// //this->set_rotation(glm::quat(this->get_rotation().slerp(RotationOffset, RotationSpeed * DeltaTime)).get_euler());
// //set_global_rotation_degrees(get_global_rotation_degrees().linear_interpolate(RotationOffset, RotationSpeed * delta_time));
// // TODO: Figure out how to translate rotation to a global rotation
// }
/*
glm : : vec3 ThirdPersonFollow : : CalculatePosition ( )
{
glm : : vec3 p1 = CalculateCenter ( ) ;
glm : : vec3 p2 =
XDirPosts ? GetPostsOffset ( TFOR . Right ( ) ,
FloatWidths .
x ) : GetExtentsOffset ( TFOR . Right ( ) ,
FloatWidths . x ,
TargetOffset . x ,
AnchorWidths . x ) ;
glm : : vec3 p3 =
YDirPosts ? GetPostsOffset ( TFOR . Up ( ) ,
FloatWidths .
y ) : GetExtentsOffset ( TFOR . Up ( ) ,
FloatWidths . y ,
TargetOffset . y ,
AnchorWidths . y ) ;
glm : : vec3 p4 =
ZDirPosts ? GetPostsOffset ( TFOR . Back ( ) ,
FloatWidths .
z ) : GetExtentsOffset ( TFOR . Back ( ) ,
FloatWidths . z ,
TargetOffset . z ,
AnchorWidths . z ) ;
return p1 + p2 + p3 + p4 ;
}
glm : : vec3 ThirdPersonFollow : : CalculateCenter ( )
{
return Target - > get_global_translation ( ) +
TFOR . TransformDirection ( Offset ) + ( mytransform - > Back ( ) * Distance ) ;
}
glm : : vec3 ThirdPersonFollow : :
GetPostsOffset ( const glm : : vec3 & DirectionVector , float AnchorWidth )
{
float dot = glm : : dot ( Target - > Forward ( ) , DirectionVector ) ;
return DirectionVector * ( dot > = 0 ? AnchorWidth : AnchorWidth * - 1 ) ;
}
glm : : vec3 ThirdPersonFollow : :
GetExtentsOffset ( const glm : : vec3 & DirectionVector , float AnchorWidth ,
float TOffset , float Width )
{
float negated_offset_sign = ( ( 0 < = TOffset ) - ( TOffset < 0 ) ) * - 1.f ;
float TotalWidth = AnchorWidth + Width ;
if ( glm : : abs ( TOffset ) > TotalWidth
& & ! glm : : epsilonEqual ( glm : : abs ( TOffset ) , TotalWidth , 0.5f ) )
return DirectionVector * TotalWidth * negated_offset_sign ;
else {
if ( glm : : abs ( TOffset ) > = AnchorWidth )
return DirectionVector * AnchorWidth * negated_offset_sign ;
else
return DirectionVector * TOffset * - 1.f ;
}
return glm : : vec3 ( 0.f ) ;
}
glm : : vec3 ThirdPersonFollow : : FrameBasedVectorLerp ( const glm : : vec3 & From ,
const glm : : vec3 & To ,
const glm : : vec3 & Speeds ,
float Tick )
{
// Previously "FORTransform.TransformVector(Speeds)
glm : : vec3 TSpeed = glm : : abs ( TFOR . TransformDirection ( Speeds ) ) ;
glm : : vec3 TOffset = glm : : abs ( TFOR . TransformDirection ( TargetOffset ) ) ;
glm : : vec3 TAnchorWidths =
glm : : abs ( TFOR . TransformDirection ( AnchorWidths ) ) ;
glm : : vec3 TFloatWidths =
glm : : abs ( TFOR . TransformDirection ( FloatWidths ) ) ;
// If these are true, that means to use the anchor speed instead of the normal speed.
// True if the offset is beyond the anchor plus the width
bool bUseX = GetLerpParam ( TOffset . x , TAnchorWidths . x , TFloatWidths . x ) ;
bool bUseY = GetLerpParam ( TOffset . y , TAnchorWidths . y , TFloatWidths . y ) ;
bool bUseZ = GetLerpParam ( TOffset . z , TAnchorWidths . z , TFloatWidths . z ) ;
float xAlpha =
glm : : clamp ( ( bUseX ? AnchorSpeed : TSpeed . x ) * Tick , 0.f , 1.f ) ;
float yAlpha =
glm : : clamp ( ( bUseY ? AnchorSpeed : TSpeed . y ) * Tick , 0.f , 1.f ) ;
float zAlpha =
glm : : clamp ( ( bUseZ ? AnchorSpeed : TSpeed . z ) * Tick , 0.f , 1.f ) ;
return VectorLerpPiecewise ( From , To ,
glm : : vec3 ( xAlpha , yAlpha , zAlpha ) ) ;
}
int float_epsilon ( mfloat_t a , mfloat_t b , mfloat_t e )
{
return fabs ( a - b ) < e ;
}
int lerpparam ( float offset , float anchorwidth , float floatwidth )
{
return ( offset > ( anchorwidth + floatwidth ) ) & & ! float_epsilon ( anchorwidth + floatwidth , offset , 0.5f ) ;
}
mfloat_t * vec3lerp ( mfloat_t from [ 3 ] , mfloat_t to [ 3 ] , mfloat_t a [ 3 ] )
{
from [ 0 ] = from [ 0 ] + ( to [ 0 ] - from [ 0 ] ) * a [ 0 ] ;
from [ 1 ] = from [ 1 ] + ( to [ 1 ] - from [ 1 ] ) * a [ 1 ] ;
from [ 2 ] = from [ 2 ] + ( to [ 2 ] - from [ 2 ] ) * a [ 2 ] ;
}
void follow_calctargets ( )
{
}
void ThirdPersonFollow : : CalculateTargets ( )
{
// For translation
TargetPosition = CalculatePosition ( ) ;
// For rotation
// TODO: Check of this implementation is the same as UKismetMath FindLookAtRotation
TargetRotation =
RemoveLockedRotation ( glm : : quat
( mytransform - >
get_global_transform ( ) - > get_origin ( ) -
Target - >
get_global_transform ( ) - > get_origin ( ) ) ) ;
}
follow_removelockedrot ( )
{
}
glm : : quat ThirdPersonFollow : :
RemoveLockedRotation ( const glm : : quat & CurrentRotation )
{
glm : : vec3 NewRotator ;
glm : : vec3 CurrentRotator = glm : : eulerAngles ( CurrentRotation ) ;
//
NewRotator . x =
LockRoll ? mytransform - > get_rotation ( ) . x : CurrentRotator . x ;
NewRotator . y =
LockPitch ? mytransform - > get_rotation ( ) . y : CurrentRotator . y ;
NewRotator . z =
LockYaw ? mytransform - > get_rotation ( ) . z : CurrentRotator . z ;
return glm : : quat ( NewRotator ) ;
}
// The target offset is the value of where the target is compared to where he "should" be based on where
// the camera is. It is what the camera needs to move to be centered on the target
void ThirdPersonFollow : : CalculateTargetOffset ( )
{
glm : : vec3 p1 =
( mytransform - > Forward ( ) * Distance ) +
TFOR . TransformDirection ( Offset ) +
mytransform - > get_global_translation ( ) ;
glm : : vec3 p2 =
TFOR . InverseTransformDirection ( Target - > get_global_translation ( ) ) ;
glm : : vec3 p3 = TFOR . InverseTransformDirection ( p1 ) ;
TargetOffset = p2 - p3 ;
}
void follow_targetoffset ( )
{
mfloat_t p1 [ 3 ] , p2 [ 3 ] , p3 [ 3 ] = { 0 } ;
}
*/