prosperon/source/engine/3d/3pfollow.c

221 lines
6.6 KiB
C
Raw Normal View History

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.
#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};
}
*/