增加多屏显示,视频播放
This commit is contained in:
+329
@@ -0,0 +1,329 @@
|
||||
// Copyright 2015-2023 Rodrigo Villani Pereira
|
||||
|
||||
#include "KinectThread.h"
|
||||
|
||||
#include "HAL/RunnableThread.h"
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
ThreadFrameBuffer
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
using namespace NeoKinect;
|
||||
|
||||
FThreadFrameBuffer::~FThreadFrameBuffer()
|
||||
{
|
||||
DeallocateBuffers();
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::Configure(
|
||||
KinectFrameType Frame,
|
||||
KinectPixelFormat Format,
|
||||
KinectCoordinateSpace Space,
|
||||
bool IsRemapped)
|
||||
{
|
||||
this->FrameType = Frame;
|
||||
this->PixelFormat = Format;
|
||||
this->TargetSpace = Space;
|
||||
this->bRemapped = IsRemapped;
|
||||
}
|
||||
|
||||
bool FThreadFrameBuffer::AllocateBuffers(uint32 Size)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*FString::Printf(TEXT("Kinect_AllocateBuffers_%d"), FrameType));
|
||||
|
||||
if (IsAllocated())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Buffer = new uint8[Size];
|
||||
BackBuffer = new uint8[Size];
|
||||
return Buffer && BackBuffer;
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::DeallocateBuffers()
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*FString::Printf(TEXT("Kinect_DeallocateBuffers_%d"), FrameType));
|
||||
|
||||
bIsNew = false;
|
||||
|
||||
if (Buffer)
|
||||
{
|
||||
Lock();
|
||||
delete[] Buffer;
|
||||
Buffer = nullptr;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
if (BackBuffer)
|
||||
{
|
||||
LockWrite();
|
||||
delete[] BackBuffer;
|
||||
BackBuffer = nullptr;
|
||||
UnlockWrite();
|
||||
}
|
||||
}
|
||||
|
||||
bool FThreadFrameBuffer::IsAllocated() const
|
||||
{
|
||||
return Buffer && BackBuffer;
|
||||
}
|
||||
|
||||
const uint8* FThreadFrameBuffer::GetReadBuffer(bool bConsume /*= true*/)
|
||||
{
|
||||
if (bConsume)
|
||||
{
|
||||
if (Buffer && bIsNew)
|
||||
{
|
||||
bIsNew = false;
|
||||
return Buffer;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
uint8* FThreadFrameBuffer::GetWriteBuffer() const
|
||||
{
|
||||
return BackBuffer;
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::SetDirty()
|
||||
{
|
||||
SwapBuffers();
|
||||
bIsNew = true;
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::SwapBuffers()
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*FString::Printf(TEXT("Kinect_SwapBuffers_%d"), FrameType));
|
||||
|
||||
Lock();
|
||||
|
||||
uint8* Temp = Buffer;
|
||||
Buffer = BackBuffer;
|
||||
BackBuffer = Temp;
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
bool FThreadFrameBuffer::TryLock()
|
||||
{
|
||||
return ReadMutex.TryLock();
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::Lock()
|
||||
{
|
||||
ReadMutex.Lock();
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::Unlock()
|
||||
{
|
||||
ReadMutex.Unlock();
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::LockWrite()
|
||||
{
|
||||
WriteMutex.Lock();
|
||||
}
|
||||
|
||||
void FThreadFrameBuffer::UnlockWrite()
|
||||
{
|
||||
WriteMutex.Unlock();
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
KinectThread
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
||||
FKinectThread* FKinectThread::Runnable = nullptr;
|
||||
FCriticalSection FKinectThread::BodiesFacesCritSec;
|
||||
|
||||
FThreadFrameBuffer FKinectThread::FrameBuffers[static_cast<uint64>(EKinectFrame::Count)];
|
||||
bool FKinectThread::bUseBodyTracking = false;
|
||||
bool FKinectThread::bUseFaceTracking = false;
|
||||
|
||||
FKinectThread::FKinectThread(KinectSensor *pSensor) :
|
||||
pKinect(pSensor),
|
||||
bBodiesDirty(false),
|
||||
bFacesDirty(false)
|
||||
{
|
||||
Thread = FRunnableThread::Create(this, TEXT("FKinectThread")); // Windows give 8MB memory by default
|
||||
if (!Thread)
|
||||
UE_LOG(KinectThreadLog, Error, TEXT("Failed to create Kinect thread!"));
|
||||
}
|
||||
|
||||
FKinectThread::~FKinectThread()
|
||||
{
|
||||
if (Thread) delete Thread;
|
||||
Thread = nullptr;
|
||||
}
|
||||
|
||||
FKinectThread* FKinectThread::InitKinectPolling(KinectSensor *pSensor)
|
||||
{
|
||||
// Create new instance of thread if it does not exist and the platform
|
||||
// supports multi threading.
|
||||
if (!Runnable && FPlatformProcess::SupportsMultithreading())
|
||||
{
|
||||
Runnable = new FKinectThread(pSensor);
|
||||
}
|
||||
return Runnable;
|
||||
}
|
||||
|
||||
void FKinectThread::EnsureCompletion()
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(Kinect_EnsureThreadCompletion)
|
||||
|
||||
Stop();
|
||||
if (Thread)
|
||||
Thread->WaitForCompletion();
|
||||
}
|
||||
|
||||
void FKinectThread::Shutdown()
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(Kinect_ShutdownThread)
|
||||
|
||||
if (Runnable)
|
||||
{
|
||||
Runnable->EnsureCompletion();
|
||||
delete Runnable;
|
||||
Runnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const KinectBody* FKinectThread::GetBodiesData()
|
||||
{
|
||||
if (bBodiesDirty)
|
||||
{
|
||||
bBodiesDirty = false;
|
||||
return Bodies;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const KinectFace* FKinectThread::GetFacesData()
|
||||
{
|
||||
if (bFacesDirty)
|
||||
{
|
||||
bFacesDirty = false;
|
||||
return Faces;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FKinectThread::Init()
|
||||
{
|
||||
UE_LOG(KinectThreadLog, Log, TEXT("Kinect thread initialized."));
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 FKinectThread::Run()
|
||||
{
|
||||
constexpr float UpdateInterval = 1.f / cDesiredFPS;
|
||||
|
||||
UE_LOG(KinectThreadLog, Log, TEXT("Kinect thread running."));
|
||||
|
||||
// while not told to stop this thread
|
||||
while (StopTaskCounter.GetValue() == 0)
|
||||
{
|
||||
// try locking any frames necessary
|
||||
constexpr int FrameTypesCount = static_cast<int>(KinectFrameType::Count);
|
||||
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(KinectThread_Run)
|
||||
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(Kinect_LockFrames)
|
||||
for (int i = 0; i < FrameTypesCount; ++i)
|
||||
{
|
||||
const KinectFrameType FrameType = static_cast<KinectFrameType>(i);
|
||||
if (pKinect->GetIsUsingFrame(FrameType))
|
||||
{
|
||||
pKinect->LockLatestFrame(FrameType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bUseBodyTracking)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(Kinect_GetBodyData)
|
||||
// process bodies before face tracking - face tracking depends on bodies data
|
||||
BodiesFacesCritSec.Lock();
|
||||
if (pKinect->GetLatestFrameData(Bodies))
|
||||
{
|
||||
bBodiesDirty = true;
|
||||
}
|
||||
BodiesFacesCritSec.Unlock();
|
||||
}
|
||||
|
||||
if (bUseFaceTracking)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(Kinect_GetFaceData)
|
||||
// process face tracking
|
||||
BodiesFacesCritSec.Lock();
|
||||
if (pKinect->GetLatestFrameData(Faces))
|
||||
{
|
||||
bFacesDirty = true;
|
||||
}
|
||||
BodiesFacesCritSec.Unlock();
|
||||
}
|
||||
|
||||
// update any necessary buffers
|
||||
for (FThreadFrameBuffer& FrameBuffer : FrameBuffers)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*FString::Printf(TEXT("Kinect_UpdateBuffer_%d"), FrameBuffer.FrameType));
|
||||
if (FrameBuffer.IsAllocated() && pKinect->GetIsFrameLocked(FrameBuffer.FrameType))
|
||||
{
|
||||
FrameBuffer.LockWrite();
|
||||
// If this is a remapped type, use the correct function.
|
||||
// If the update works, marks buffer as new
|
||||
if (FrameBuffer.bRemapped)
|
||||
{
|
||||
if (pKinect->GetRemappedFrameData(
|
||||
FrameBuffer.FrameType, FrameBuffer.TargetSpace,
|
||||
FrameBuffer.GetWriteBuffer(), FrameBuffer.PixelFormat))
|
||||
{
|
||||
FrameBuffer.SetDirty();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8* Buffer = FrameBuffer.GetWriteBuffer();
|
||||
if (pKinect->GetLatestFrameData(
|
||||
FrameBuffer.FrameType, Buffer,
|
||||
FrameBuffer.PixelFormat))
|
||||
{
|
||||
FrameBuffer.SetDirty();
|
||||
}
|
||||
}
|
||||
FrameBuffer.UnlockWrite();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(Kinect_UnlockFrames)
|
||||
// unlock frames
|
||||
for (int i = 0; i < FrameTypesCount; ++i)
|
||||
{
|
||||
pKinect->UnlockLatestFrame(static_cast<KinectFrameType>(i));
|
||||
}
|
||||
}
|
||||
|
||||
// give time for Kinect to update its frames.
|
||||
FPlatformProcess::Sleep(UpdateInterval);
|
||||
}
|
||||
|
||||
// ended successfully!
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FKinectThread::Stop()
|
||||
{
|
||||
StopTaskCounter.Increment();
|
||||
}
|
||||
|
||||
void FKinectThread::Exit()
|
||||
{
|
||||
UE_LOG(KinectThreadLog, Log, TEXT("Kinect thread ended."));
|
||||
}
|
||||
+547
@@ -0,0 +1,547 @@
|
||||
// Copyright 2015-2023 Rodrigo Villani Pereira
|
||||
|
||||
#include "NeoKinectBody.h"
|
||||
|
||||
#include "Helpers/GuardedNeoKinect.h"
|
||||
|
||||
#include "NeoKinectManager.h"
|
||||
|
||||
UNeoKinectBody::UNeoKinectBody()
|
||||
: BodyIndex(0),
|
||||
TrackingId(0),
|
||||
bIsTracked(false),
|
||||
bIsRestricted(false),
|
||||
HandLeftState(EKinectHandState::NotTracked),
|
||||
HandLeftTrackingState(EKinectTrackingState::NotTracked),
|
||||
HandRightState(EKinectHandState::NotTracked),
|
||||
HandRightTrackingState(EKinectTrackingState::NotTracked),
|
||||
LeanTrackingState(EKinectTrackingState::NotTracked),
|
||||
Lean(FVector2D(0.f, 0.f))
|
||||
{
|
||||
using namespace NeoKinect;
|
||||
|
||||
Joints.SetNum(KinectJointCount);
|
||||
|
||||
for (int32 JointIdx = 0; JointIdx < KinectJointCount; ++JointIdx)
|
||||
{
|
||||
Joints[JointIdx].Type = static_cast<EKinectJointType>(JointIdx);
|
||||
}
|
||||
}
|
||||
|
||||
UNeoKinectBody::~UNeoKinectBody()
|
||||
{
|
||||
Joints.Empty();
|
||||
}
|
||||
|
||||
void UNeoKinectBody::GetHandStateAsExec(EKinectBodySide Hand, EKinectHandState& States)
|
||||
{
|
||||
if (Hand == EKinectBodySide::Left)
|
||||
{
|
||||
States = HandLeftState;
|
||||
}
|
||||
else
|
||||
{
|
||||
States = HandRightState;
|
||||
}
|
||||
}
|
||||
|
||||
EKinectHandState UNeoKinectBody::GetHandState(EKinectBodySide Hand) const
|
||||
{
|
||||
if (Hand == EKinectBodySide::Left)
|
||||
return HandLeftState;
|
||||
else
|
||||
return HandRightState;
|
||||
}
|
||||
|
||||
void UNeoKinectBody::GetHandConfidenceAsExec(EKinectBodySide Hand, EKinectTrackingState& States)
|
||||
{
|
||||
if (Hand == EKinectBodySide::Left)
|
||||
{
|
||||
States = HandLeftTrackingState;
|
||||
}
|
||||
else
|
||||
{
|
||||
States = HandRightTrackingState;
|
||||
}
|
||||
}
|
||||
|
||||
EKinectTrackingState UNeoKinectBody::GetHandConfidence(EKinectBodySide Hand) const
|
||||
{
|
||||
if (Hand == EKinectBodySide::Left)
|
||||
return HandLeftTrackingState;
|
||||
else
|
||||
return HandRightTrackingState;
|
||||
}
|
||||
|
||||
void UNeoKinectBody::GetLeanConfidenceAsExec(EKinectTrackingState& States)
|
||||
{
|
||||
States = LeanTrackingState;
|
||||
}
|
||||
|
||||
TArray<FKinectJoint> UNeoKinectBody::GetJoints()
|
||||
{
|
||||
return Joints;
|
||||
}
|
||||
|
||||
FVector UNeoKinectBody::GetJointLocation(EKinectJointType Joint)
|
||||
{
|
||||
return Joints[static_cast<int32>(Joint)].Location;
|
||||
}
|
||||
|
||||
FRotator UNeoKinectBody::GetJointOrientation(EKinectJointType Joint)
|
||||
{
|
||||
return Joints[static_cast<int32>(Joint)].Orientation;
|
||||
}
|
||||
|
||||
FVector UNeoKinectBody::GetJointLocationColor(EKinectJointType Joint)
|
||||
{
|
||||
return Joints[static_cast<int32>(Joint)].ColorLocation;
|
||||
}
|
||||
|
||||
FRotator UNeoKinectBody::GetJointOrientationColor(EKinectJointType Joint)
|
||||
{
|
||||
return Joints[static_cast<int32>(Joint)].ColorOrientation;
|
||||
}
|
||||
|
||||
void UNeoKinectBody::GetJointConfidenceAsExec(EKinectJointType Joint, EKinectTrackingState& States)
|
||||
{
|
||||
States = Joints[static_cast<int32>(Joint)].Confidence;
|
||||
}
|
||||
|
||||
EKinectTrackingState UNeoKinectBody::GetJointConfidence(EKinectJointType Joint)
|
||||
{
|
||||
return Joints[static_cast<int32>(Joint)].Confidence;
|
||||
}
|
||||
|
||||
float UNeoKinectBody::GetJointsDistance(EKinectJointType JointA, EKinectJointType JointB)
|
||||
{
|
||||
return FVector::Dist(Joints[static_cast<int32>(JointB)].Location, Joints[static_cast<int32>(JointA)].Location);
|
||||
}
|
||||
|
||||
float UNeoKinectBody::GetBoneLength(EKinectJointType Joint)
|
||||
{
|
||||
const FVector p1 = Joints[static_cast<int32>(Joint)].Location;
|
||||
switch (Joint)
|
||||
{
|
||||
case EKinectJointType::SpineBase:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineMid)].Location);
|
||||
case EKinectJointType::SpineMid:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineBase)].Location);
|
||||
case EKinectJointType::Neck:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineShoulder)].Location);
|
||||
case EKinectJointType::Head:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::Neck)].Location);
|
||||
case EKinectJointType::ShoulderLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineShoulder)].Location);
|
||||
case EKinectJointType::ElbowLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::ShoulderLeft)].Location);
|
||||
case EKinectJointType::WristLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::ElbowLeft)].Location);
|
||||
case EKinectJointType::HandLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::WristLeft)].Location);
|
||||
case EKinectJointType::ShoulderRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineShoulder)].Location);
|
||||
case EKinectJointType::ElbowRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::ShoulderRight)].Location);
|
||||
case EKinectJointType::WristRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::ElbowRight)].Location);
|
||||
case EKinectJointType::HandRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::WristRight)].Location);
|
||||
case EKinectJointType::HipLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineBase)].Location);
|
||||
case EKinectJointType::KneeLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::HipLeft)].Location);
|
||||
case EKinectJointType::AnkleLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::KneeLeft)].Location);
|
||||
case EKinectJointType::FootLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::AnkleLeft)].Location);
|
||||
case EKinectJointType::HipRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineBase)].Location);
|
||||
case EKinectJointType::KneeRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::HipRight)].Location);
|
||||
case EKinectJointType::AnkleRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::KneeRight)].Location);
|
||||
case EKinectJointType::FootRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::AnkleRight)].Location);
|
||||
case EKinectJointType::SpineShoulder:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::SpineMid)].Location);
|
||||
case EKinectJointType::HandTipLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::WristLeft)].Location);
|
||||
case EKinectJointType::ThumbLeft:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::HandLeft)].Location);
|
||||
case EKinectJointType::HandTipRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::WristRight)].Location);
|
||||
case EKinectJointType::ThumbRight:
|
||||
return FVector::Dist(p1, Joints[static_cast<int32>(EKinectJointType::HandRight)].Location);
|
||||
default:
|
||||
return 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
float UNeoKinectBody::JointDotVector(EKinectJointType Joint, FVector Vector)
|
||||
{
|
||||
Vector.Normalize();
|
||||
return FVector::DotProduct(
|
||||
Vector,
|
||||
FRotationMatrix(Joints[static_cast<int32>(Joint)].Orientation).GetScaledAxis(EAxis::Z));
|
||||
}
|
||||
|
||||
void UNeoKinectBody::UpdateFromKinectBody(const NeoKinect::KinectBody& kBody, const NeoKinect::KinectSensor& Sensor)
|
||||
{
|
||||
using namespace NeoKinect;
|
||||
|
||||
// For throwing BeginTrack/Lost events after update
|
||||
bool bWasTracked = bIsTracked;
|
||||
|
||||
ClippedEdges.Left = kBody.clippedEdges.left;
|
||||
ClippedEdges.Right = kBody.clippedEdges.right;
|
||||
ClippedEdges.Top = kBody.clippedEdges.top;
|
||||
ClippedEdges.Bottom = kBody.clippedEdges.bottom;
|
||||
|
||||
bIsTracked = kBody.isTracked;
|
||||
bIsRestricted = kBody.isRestricted;
|
||||
TrackingId = kBody.trackingId;
|
||||
|
||||
HandLeftState = static_cast<EKinectHandState>(kBody.handLeftState);
|
||||
HandLeftTrackingState = static_cast<EKinectTrackingState>(kBody.handLeftTrackingState);
|
||||
|
||||
HandRightState = static_cast<EKinectHandState>(kBody.handRightState);
|
||||
HandRightTrackingState = static_cast<EKinectTrackingState>(kBody.handRightTrackingState);
|
||||
|
||||
LeanTrackingState = static_cast<EKinectTrackingState>(kBody.leanTrackingState);
|
||||
Lean.Set(kBody.lean.x, kBody.lean.y);
|
||||
|
||||
// update joints only if being tracked
|
||||
if (bIsTracked)
|
||||
{
|
||||
// camera space joints transforms
|
||||
for (int32 j = 0; j < KinectJointCount; ++j)
|
||||
{
|
||||
FKinectJoint& uJoint = Joints[j];
|
||||
KinectJoint joint = kBody.joints[j];
|
||||
|
||||
uJoint.Confidence = static_cast<EKinectTrackingState>(joint.trackingState);
|
||||
uJoint.Location.Set(
|
||||
joint.position.Z * 100.f,
|
||||
-joint.position.X * 100.f,
|
||||
joint.position.Y * 100.f);
|
||||
|
||||
// Quaternion conversion from Kinect camera's coord system to Unreal's
|
||||
FQuat Quat = FQuat(
|
||||
-joint.orientation.z,
|
||||
joint.orientation.x,
|
||||
-joint.orientation.y,
|
||||
joint.orientation.w
|
||||
);
|
||||
// In order to match the joints orientations to Unreal Mannequin, we
|
||||
// still have some problems:
|
||||
// - Kinect's bones extend along its UP axis, which is Z in Unreal.
|
||||
// But Unreal's Mannequin skeleton's bones extend along X (as it is
|
||||
// in Maya). So we re-create the orientation swapping the axes.
|
||||
//
|
||||
// - Some bones extend towards X, some against it. That's good for doing
|
||||
// mirrored rotations in the animation software, so we'll keep it here
|
||||
// by flipping some axes.
|
||||
//
|
||||
// - The pelvis and spine bones front axis is the same as the limbs side axis.
|
||||
// In the Mannequin these match up, so we'll have to invert some here.
|
||||
#define JNT_ID(Name) static_cast<uint8>(EKinectJointType::Name)
|
||||
|
||||
uint8 JointIndex = static_cast<uint8>(uJoint.Type);
|
||||
|
||||
if (JointIndex <= JNT_ID(Head) || JointIndex == JNT_ID(SpineShoulder))
|
||||
{ // for spine bones
|
||||
uJoint.Orientation = FRotationMatrix::MakeFromXZ(
|
||||
Quat.GetAxisZ(),
|
||||
Quat.GetAxisY()).Rotator();
|
||||
}
|
||||
else if (JointIndex <= JNT_ID(WristLeft)
|
||||
|| JointIndex >= JNT_ID(HipRight) && JointIndex <= JNT_ID(FootRight))
|
||||
{ // for left arm and right leg
|
||||
uJoint.Orientation = FRotationMatrix::MakeFromXZ(
|
||||
Quat.GetAxisZ(),
|
||||
Quat.GetAxisX()).Rotator();
|
||||
}
|
||||
else if ( (JointIndex >= JNT_ID(ShoulderRight) && JointIndex <= JNT_ID(WristRight))
|
||||
|| (JointIndex >= JNT_ID(HipLeft) && JointIndex <= JNT_ID(FootLeft))
|
||||
|| JointIndex == JNT_ID(HandTipRight) || JointIndex == JNT_ID(ThumbRight)
|
||||
)
|
||||
{ // for right arm and left leg
|
||||
uJoint.Orientation = FRotationMatrix::MakeFromXZ(
|
||||
-Quat.GetAxisZ(),
|
||||
-Quat.GetAxisX()).Rotator();
|
||||
}
|
||||
else if (JointIndex == JNT_ID(HandTipLeft) || JointIndex == JNT_ID(ThumbLeft))
|
||||
{ // Left hand
|
||||
uJoint.Orientation = FRotationMatrix::MakeFromXZ(
|
||||
Quat.GetAxisZ(),
|
||||
Quat.GetAxisX()).Rotator();
|
||||
}
|
||||
else if (JointIndex == JNT_ID(HandLeft))
|
||||
{ // left hand
|
||||
uJoint.Orientation = FRotationMatrix::MakeFromXZ(
|
||||
Quat.GetAxisZ(),
|
||||
-Quat.GetAxisX()).Rotator();
|
||||
}
|
||||
else if (JointIndex == JNT_ID(HandRight))
|
||||
{ // right hand
|
||||
uJoint.Orientation = FRotationMatrix::MakeFromXZ(
|
||||
-Quat.GetAxisZ(),
|
||||
Quat.GetAxisX()).Rotator();
|
||||
}
|
||||
#undef JNT_ID
|
||||
|
||||
} // camera space joints transforms
|
||||
|
||||
if (UNeoKinectManager::IsUsingJointsColorSpaceTransforms())
|
||||
{
|
||||
// color space with depth joints transforms
|
||||
for (int32 j = 0; j < KinectJointCount; ++j)
|
||||
{
|
||||
FKinectJoint& uJoint = Joints[j];
|
||||
KinectJoint joint = kBody.joints[j];
|
||||
|
||||
// Convert camera space location to color space with depth
|
||||
Vector3 ColorDepthLocation = UNeoKinectManager::CameraLocationToColorWithDepth(Vector3(joint.position));
|
||||
if (ColorDepthLocation.IsZero())
|
||||
{
|
||||
// fallback for when the joint can not be seen in color camera
|
||||
if (uJoint.Type == EKinectJointType::SpineBase) // oh shit! Our reference is gone!
|
||||
{
|
||||
uJoint.ColorLocation = uJoint.Location;
|
||||
continue;
|
||||
}
|
||||
|
||||
FKinectJoint &SpineBase = Joints[static_cast<int32>(EKinectJointType::SpineBase)];
|
||||
uJoint.ColorLocation = SpineBase.ColorLocation + uJoint.Location - SpineBase.Location;
|
||||
continue;
|
||||
}
|
||||
|
||||
uJoint.ColorLocation.Set(
|
||||
ColorDepthLocation.z * 100.0f,
|
||||
-ColorDepthLocation.x * 100.0f,
|
||||
ColorDepthLocation.y * 100.0f);
|
||||
} // color space with depth joints transforms
|
||||
|
||||
// orientations in color space with depth
|
||||
#define JOINT(Name) Joints[static_cast<int32>(EKinectJointType::Name)]
|
||||
#define J_DIR(FromJoint, ToJoint) JOINT(ToJoint).ColorLocation - JOINT(FromJoint).ColorLocation
|
||||
#define J_ROT(JointName, Twist) JOINT(JointName).ColorOrientation = FRotationMatrix::MakeFromX##Twist(XDir, Twist##Dir).Rotator()
|
||||
|
||||
FVector XDir, YDir, ZDir, Dir1, Dir2;
|
||||
FQuat Rot1, Rot2, RLerp;
|
||||
float JointsDot;
|
||||
|
||||
// Spine Base
|
||||
XDir = J_DIR(SpineBase, SpineMid);
|
||||
ZDir = J_DIR(HipLeft, HipRight);
|
||||
J_ROT(SpineBase, Z);
|
||||
|
||||
// Spine Middle
|
||||
// same XDir
|
||||
ZDir = (ZDir + J_DIR(ShoulderLeft, ShoulderRight)) / 2.0f; // intermediary between hip and shoulders twist
|
||||
J_ROT(SpineMid, Z);
|
||||
|
||||
// Spine Shoulder
|
||||
XDir = J_DIR(SpineMid, SpineShoulder);
|
||||
ZDir = J_DIR(ShoulderLeft, ShoulderRight);
|
||||
J_ROT(SpineShoulder, Z);
|
||||
|
||||
// Neck
|
||||
XDir = J_DIR(SpineShoulder, Neck);
|
||||
// same ZDir
|
||||
J_ROT(Neck, Z);
|
||||
|
||||
// Head
|
||||
XDir = J_DIR(Neck, Head);
|
||||
// same ZDir
|
||||
J_ROT(Head, Z);
|
||||
|
||||
// shoulder left
|
||||
XDir = J_DIR(SpineShoulder, ShoulderLeft);
|
||||
ZDir = J_DIR(SpineMid, SpineShoulder);
|
||||
J_ROT(ShoulderLeft, Z);
|
||||
|
||||
// elbow left
|
||||
XDir = J_DIR(ShoulderLeft, ElbowLeft);
|
||||
// interpolate between a rot for fully stretched arm and one for bent
|
||||
Dir1 = FVector::CrossProduct(J_DIR(ElbowLeft, WristLeft), J_DIR(ElbowLeft, ShoulderLeft)); // bent
|
||||
Rot1 = FRotationMatrix::MakeFromXZ(XDir, Dir1).ToQuat(); // bent
|
||||
Dir2 = FRotationMatrix(JOINT(ShoulderLeft).ColorOrientation).GetScaledAxis(EAxis::Y); // stretched
|
||||
Rot2 = FRotationMatrix::MakeFromXY(XDir, Dir2).ToQuat(); // stretched
|
||||
Dir1 = J_DIR(ShoulderLeft, ElbowLeft); Dir2 = J_DIR(ElbowLeft, WristLeft);
|
||||
Dir1.Normalize(); Dir2.Normalize();
|
||||
JointsDot = FVector::DotProduct(Dir1, Dir2);
|
||||
RLerp = FQuat::Slerp(Rot2, Rot1,
|
||||
FMath::Clamp(FMath::Acos(JointsDot) / 0.349f /*~20°*/, 0.f, 1.f)
|
||||
);
|
||||
RLerp.Normalize();
|
||||
JOINT(ElbowLeft).ColorOrientation = RLerp.Rotator();
|
||||
|
||||
// wrist left
|
||||
XDir = J_DIR(ElbowLeft, WristLeft);
|
||||
YDir = J_DIR(HandLeft, ThumbLeft);
|
||||
J_ROT(WristLeft, Y);
|
||||
|
||||
// hand left
|
||||
XDir = J_DIR(WristLeft, HandTipLeft);
|
||||
ZDir = J_DIR(ThumbLeft, HandLeft);
|
||||
J_ROT(HandLeft, Z);
|
||||
|
||||
// hand tip Left
|
||||
JOINT(HandTipLeft).ColorOrientation = JOINT(HandLeft).ColorOrientation;
|
||||
|
||||
// thumb left
|
||||
XDir = J_DIR(HandLeft, ThumbLeft);
|
||||
YDir = FRotationMatrix(JOINT(HandLeft).ColorOrientation).GetScaledAxis(EAxis::Y);
|
||||
J_ROT(ThumbLeft, Y);
|
||||
|
||||
// shoulder right
|
||||
XDir = J_DIR(ShoulderRight, SpineShoulder);
|
||||
ZDir = J_DIR(SpineShoulder, SpineMid);
|
||||
J_ROT(ShoulderRight, Z);
|
||||
|
||||
// elbow right
|
||||
XDir = J_DIR(ElbowRight, ShoulderRight);
|
||||
// interpolate between a rot for fully stretched arm and one for bent
|
||||
Dir1 = FVector::CrossProduct(J_DIR(ElbowRight, WristRight), J_DIR(ElbowRight, ShoulderRight)); // bent
|
||||
Rot1 = FRotationMatrix::MakeFromXZ(XDir, Dir1).ToQuat(); // bent
|
||||
Dir2 = FRotationMatrix(JOINT(ShoulderRight).ColorOrientation).GetScaledAxis(EAxis::Y); // stretched
|
||||
Rot2 = FRotationMatrix::MakeFromXY(XDir, Dir2).ToQuat(); // stretched
|
||||
Dir1 = J_DIR(ShoulderRight, ElbowRight); Dir2 = J_DIR(ElbowRight, WristRight);
|
||||
Dir1.Normalize(); Dir2.Normalize();
|
||||
JointsDot = FVector::DotProduct(Dir1, Dir2);
|
||||
RLerp = FQuat::Slerp(Rot2, Rot1,
|
||||
FMath::Clamp(FMath::Acos(JointsDot) / 0.349f /*~20°*/, 0.f, 1.f)
|
||||
);
|
||||
RLerp.Normalize();
|
||||
JOINT(ElbowRight).ColorOrientation = RLerp.Rotator();
|
||||
|
||||
// wrist right
|
||||
XDir = J_DIR(WristRight, ElbowRight);
|
||||
YDir = J_DIR(ThumbRight, HandRight);
|
||||
J_ROT(WristRight, Y);
|
||||
|
||||
// hand right
|
||||
XDir = J_DIR(HandTipRight, WristRight);
|
||||
ZDir = -YDir;
|
||||
J_ROT(HandRight, Z);
|
||||
|
||||
// hand tip right
|
||||
JOINT(HandTipRight).ColorOrientation = JOINT(HandRight).ColorOrientation;
|
||||
|
||||
// thumb right
|
||||
XDir = J_DIR(ThumbRight, HandRight);
|
||||
YDir = FRotationMatrix(JOINT(HandRight).ColorOrientation).GetScaledAxis(EAxis::Y);
|
||||
J_ROT(ThumbRight, Y);
|
||||
|
||||
// Hip Left
|
||||
XDir = J_DIR(HipLeft, SpineBase);
|
||||
ZDir = J_DIR(SpineMid, SpineBase);
|
||||
J_ROT(HipLeft, Z);
|
||||
|
||||
// Knee left
|
||||
XDir = J_DIR(KneeLeft, HipLeft);
|
||||
Dir1 = FVector::CrossProduct(J_DIR(KneeLeft, AnkleLeft), J_DIR(KneeLeft, HipLeft)); // bent
|
||||
Rot1 = FRotationMatrix::MakeFromXZ(XDir, Dir1).ToQuat(); // bent
|
||||
Dir2 = FRotationMatrix(JOINT(SpineMid).ColorOrientation).GetScaledAxis(EAxis::Y); // stretched
|
||||
Rot2 = FRotationMatrix::MakeFromXY(XDir, Dir2).ToQuat(); // stretched
|
||||
Dir1 = J_DIR(HipLeft, KneeLeft); Dir2 = J_DIR(KneeLeft, AnkleLeft);
|
||||
Dir1.Normalize(); Dir2.Normalize();
|
||||
JointsDot = FVector::DotProduct(Dir1, Dir2);
|
||||
RLerp = FQuat::Slerp(Rot2, Rot1, FMath::Clamp((FMath::Acos(JointsDot) - 0.2618f) / 0.5236f, 0.f, 1.f));
|
||||
RLerp.Normalize();
|
||||
JOINT(KneeLeft).ColorOrientation = RLerp.Rotator();
|
||||
|
||||
// ankle left
|
||||
XDir = J_DIR(AnkleLeft, KneeLeft);
|
||||
ZDir = FRotationMatrix(JOINT(KneeLeft).ColorOrientation).GetScaledAxis(EAxis::Z);
|
||||
J_ROT(AnkleLeft, Z);
|
||||
|
||||
// foot left
|
||||
// same X and Z dirs
|
||||
J_ROT(FootLeft, Z);
|
||||
|
||||
// hip right
|
||||
XDir = J_DIR(SpineBase, HipRight);
|
||||
ZDir = J_DIR(SpineBase, SpineMid);
|
||||
J_ROT(HipRight, Z);
|
||||
|
||||
// Knee Right
|
||||
XDir = J_DIR(HipRight, KneeRight);
|
||||
Dir1 = FVector::CrossProduct(J_DIR(KneeRight, AnkleRight), J_DIR(KneeRight, HipRight)); // bent
|
||||
Rot1 = FRotationMatrix::MakeFromXZ(XDir, Dir1).ToQuat(); // bent
|
||||
Dir2 = -FRotationMatrix(JOINT(SpineMid).ColorOrientation).GetScaledAxis(EAxis::Y); // stretched
|
||||
Rot2 = FRotationMatrix::MakeFromXY(XDir, Dir2).ToQuat(); // stretched
|
||||
Dir1 = J_DIR(HipRight, KneeRight); Dir2 = J_DIR(KneeRight, AnkleRight);
|
||||
Dir1.Normalize(); Dir2.Normalize();
|
||||
JointsDot = FVector::DotProduct(Dir1, Dir2);
|
||||
RLerp = FQuat::Slerp(Rot2, Rot1, FMath::Clamp((FMath::Acos(JointsDot) - 0.2618f) / 0.5236f, 0.f, 1.f));
|
||||
RLerp.Normalize();
|
||||
JOINT(KneeRight).ColorOrientation = RLerp.Rotator();
|
||||
|
||||
// Ankle right
|
||||
XDir = J_DIR(KneeRight, AnkleRight);
|
||||
ZDir = FRotationMatrix(JOINT(KneeRight).ColorOrientation).GetScaledAxis(EAxis::Z);
|
||||
J_ROT(AnkleRight, Z);
|
||||
|
||||
// foot right
|
||||
// same X and Z dirs
|
||||
J_ROT(FootRight, Z);
|
||||
#undef JOINT
|
||||
#undef J_DIR
|
||||
#undef J_ROT
|
||||
} // if (bUsingJointsColorSpaceTransforms)
|
||||
} // if (bIsTracked)
|
||||
|
||||
if (bWasTracked != bIsTracked)
|
||||
{
|
||||
if (bIsTracked)
|
||||
OnBodyBeginTrack.Broadcast(BodyIndex);
|
||||
else
|
||||
OnBodyLost.Broadcast(BodyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void UNeoKinectBody::Reset()
|
||||
{
|
||||
using namespace NeoKinect;
|
||||
|
||||
ClippedEdges.Left =
|
||||
ClippedEdges.Right =
|
||||
ClippedEdges.Top =
|
||||
ClippedEdges.Bottom = false;
|
||||
|
||||
bIsTracked = false;
|
||||
bIsRestricted = false;
|
||||
TrackingId = 0Ui64;
|
||||
|
||||
HandLeftState = EKinectHandState::NotTracked;
|
||||
HandLeftTrackingState = EKinectTrackingState::NotTracked;
|
||||
|
||||
HandRightState = EKinectHandState::NotTracked;
|
||||
HandRightTrackingState = EKinectTrackingState::NotTracked;
|
||||
|
||||
LeanTrackingState = EKinectTrackingState::NotTracked;
|
||||
Lean.Set(0.f, 0.f);
|
||||
|
||||
if (Joints.Num() != KinectJointCount)
|
||||
return;
|
||||
|
||||
for (int32 j = 0; j < KinectJointCount; ++j)
|
||||
{
|
||||
if (!Joints.IsValidIndex(j))
|
||||
continue;
|
||||
FKinectJoint& Joint = Joints[j];
|
||||
|
||||
Joint.Confidence = EKinectTrackingState::NotTracked;
|
||||
Joint.Location.Set(0.f, 0.f, 0.f);
|
||||
Joint.ColorLocation.Set(0.f, 0.f, 0.f);
|
||||
Joint.Orientation.Roll =
|
||||
Joint.Orientation.Pitch =
|
||||
Joint.Orientation.Yaw = 0.f;
|
||||
Joint.ColorOrientation.Roll =
|
||||
Joint.ColorOrientation.Pitch =
|
||||
Joint.ColorOrientation.Yaw = 0.f;
|
||||
}
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
// Copyright 2015-2023 Rodrigo Villani Pereira
|
||||
|
||||
#include "NeoKinectFace.h"
|
||||
#include "NeoKinectBody.h"
|
||||
#include "NeoKinectManager.h"
|
||||
|
||||
void FIntBoundingBox::FromRectI(const RectI& Rect)
|
||||
{
|
||||
Left = Rect.Left;
|
||||
Top = Rect.Top;
|
||||
Right = Rect.Right;
|
||||
Bottom = Rect.Bottom;
|
||||
}
|
||||
|
||||
void FFacePoints2D::FromKinectFacePoints(const NeoKinect::KinectFacePoints& Points)
|
||||
{
|
||||
LeftEye.X = Points.leftEye.x;
|
||||
LeftEye.Y = Points.leftEye.y;
|
||||
|
||||
RightEye.X = Points.rightEye.x;
|
||||
RightEye.Y = Points.rightEye.y;
|
||||
|
||||
Nose.X = Points.nose.x;
|
||||
Nose.Y = Points.nose.y;
|
||||
|
||||
LeftMouthCorner.X = Points.leftMouthCorner.x;
|
||||
LeftMouthCorner.Y = Points.leftMouthCorner.y;
|
||||
|
||||
RightMouthCorner.X = Points.rightMouthCorner.x;
|
||||
RightMouthCorner.Y = Points.rightMouthCorner.y;
|
||||
}
|
||||
|
||||
void FFacePoints3D::FromKinectFacePoints(const NeoKinect::KinectFacePoints& ColorPoints)
|
||||
{
|
||||
NeoKinect::Vector3 Location = UNeoKinectManager::ColorWithDepthFromColorOnly(ColorPoints.leftEye) * 100.f;
|
||||
LeftEye.Set(-Location.z, Location.x, Location.y);
|
||||
|
||||
Location = UNeoKinectManager::ColorWithDepthFromColorOnly(ColorPoints.rightEye) * 100.f;
|
||||
RightEye.Set(-Location.z, Location.x, Location.y);
|
||||
|
||||
Location = UNeoKinectManager::ColorWithDepthFromColorOnly(ColorPoints.nose) * 100.f;
|
||||
Nose.Set(-Location.z, Location.x, Location.y);
|
||||
|
||||
Location = UNeoKinectManager::ColorWithDepthFromColorOnly(ColorPoints.leftMouthCorner) * 100.f;
|
||||
LeftMouthCorner.Set(-Location.z, Location.x, Location.y);
|
||||
|
||||
Location = UNeoKinectManager::ColorWithDepthFromColorOnly(ColorPoints.rightMouthCorner) * 100.f;
|
||||
RightMouthCorner.Set(-Location.z, Location.x, Location.y);
|
||||
}
|
||||
|
||||
UNeoKinectFace::UNeoKinectFace()
|
||||
: Index(INDEX_NONE)
|
||||
, bIsTracked(false)
|
||||
, TrackingId(INDEX_NONE)
|
||||
, IsEngaged(EDetectionResult::Unknown)
|
||||
, IsHappy(EDetectionResult::Unknown)
|
||||
, IsLookingAway(EDetectionResult::Unknown)
|
||||
, IsMouthMoved(EDetectionResult::Unknown)
|
||||
, IsMouthOpen(EDetectionResult::Unknown)
|
||||
, IsLeftEyeClosed(EDetectionResult::Unknown)
|
||||
, IsRightEyeClosed(EDetectionResult::Unknown)
|
||||
, IsWearingGlasses(EDetectionResult::Unknown)
|
||||
{}
|
||||
|
||||
UNeoKinectFace::~UNeoKinectFace()
|
||||
{}
|
||||
|
||||
void UNeoKinectFace::GetEyeClosedAsExec(EKinectBodySide Eye, EDetectionResult& Result)
|
||||
{
|
||||
if (Eye == EKinectBodySide::Left)
|
||||
{
|
||||
Result = IsLeftEyeClosed;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = IsRightEyeClosed;
|
||||
}
|
||||
}
|
||||
|
||||
EDetectionResult UNeoKinectFace::GetEyeClosed(EKinectBodySide Eye) const
|
||||
{
|
||||
if (Eye == EKinectBodySide::Left)
|
||||
return IsLeftEyeClosed;
|
||||
|
||||
return IsRightEyeClosed;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::GetIsEngagedAsExec(EDetectionResult& Result)
|
||||
{
|
||||
Result = IsEngaged;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::GetIsHappyAsExec(EDetectionResult& Result)
|
||||
{
|
||||
Result = IsHappy;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::GetIsLookingAwayAsExec(EDetectionResult& Result)
|
||||
{
|
||||
Result = IsLookingAway;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::GetIsMouthMovedAsExec(EDetectionResult& Result)
|
||||
{
|
||||
Result = IsMouthMoved;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::GetIsMouthOpenAsExec(EDetectionResult& Result)
|
||||
{
|
||||
Result = IsMouthOpen;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::GetIsWearingGlassesAsExec(EDetectionResult& Result)
|
||||
{
|
||||
Result = IsWearingGlasses;
|
||||
}
|
||||
|
||||
bool UNeoKinectFace::IsFromBody(const UNeoKinectBody* Body) const
|
||||
{
|
||||
return Body->TrackingId == TrackingId;
|
||||
}
|
||||
|
||||
void UNeoKinectFace::UpdateFromKinectFace(const NeoKinect::KinectFace& kFace)
|
||||
{
|
||||
const bool bWasTracked = bIsTracked;
|
||||
|
||||
bIsTracked = kFace.bIsTracked;
|
||||
TrackingId = kFace.trackingId;
|
||||
|
||||
ColorBoundingBox.FromRectI(kFace.boxColor);
|
||||
InfraredBoundingBox.FromRectI(kFace.boxInfrared);
|
||||
|
||||
ColorAlignmentPoints.FromKinectFacePoints(kFace.pointsColor);
|
||||
InfraredAlignmentPoints.FromKinectFacePoints(kFace.pointsInfrared);
|
||||
ColorWithDepthAlignmentPoints.FromKinectFacePoints(kFace.pointsColor);
|
||||
|
||||
/* Camera space face transform */
|
||||
Location.Set(
|
||||
kFace.pivot.Z * 100.f,
|
||||
-kFace.pivot.X * 100.f,
|
||||
kFace.pivot.Y * 100.f);
|
||||
|
||||
const FQuat Quat = FQuat(
|
||||
-kFace.rotation.z,
|
||||
kFace.rotation.x,
|
||||
-kFace.rotation.y,
|
||||
kFace.rotation.w
|
||||
);
|
||||
Orientation = FRotationMatrix::MakeFromXZ(
|
||||
Quat.GetAxisZ(),
|
||||
-Quat.GetAxisY()).Rotator();
|
||||
|
||||
/* Color space face location */
|
||||
if (UNeoKinectManager::IsUsingJointsColorSpaceTransforms())
|
||||
{
|
||||
using namespace NeoKinect;
|
||||
// Convert camera space location to color space with depth
|
||||
const Vector3 ColorDepthLocation = UNeoKinectManager::CameraLocationToColorWithDepth(Vector3(kFace.pivot));
|
||||
if (ColorDepthLocation.IsZero())
|
||||
{
|
||||
ColorLocation = Location;
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorLocation.Set(
|
||||
ColorDepthLocation.z * 100.0f,
|
||||
-ColorDepthLocation.x * 100.0f,
|
||||
ColorDepthLocation.y * 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
IsEngaged = static_cast<EDetectionResult>(kFace.isEngaged);
|
||||
IsHappy = static_cast<EDetectionResult>(kFace.isHappy);
|
||||
IsLookingAway = static_cast<EDetectionResult>(kFace.isLookingAway);
|
||||
IsMouthMoved = static_cast<EDetectionResult>(kFace.isMouthMoved);
|
||||
IsMouthOpen = static_cast<EDetectionResult>(kFace.isMouthOpen);
|
||||
IsLeftEyeClosed = static_cast<EDetectionResult>(kFace.isLeftEyeClosed);
|
||||
IsRightEyeClosed = static_cast<EDetectionResult>(kFace.isRightEyeClosed);
|
||||
IsWearingGlasses = static_cast<EDetectionResult>(kFace.isWearingGlasses);
|
||||
|
||||
if (bWasTracked != bIsTracked)
|
||||
{
|
||||
if (bIsTracked)
|
||||
OnFaceBeginTrack.Broadcast(Index);
|
||||
else
|
||||
OnFaceLost.Broadcast(Index);
|
||||
}
|
||||
}
|
||||
|
||||
void UNeoKinectFace::Reset()
|
||||
{
|
||||
bIsTracked = false;
|
||||
TrackingId = 0ULL;
|
||||
|
||||
ColorBoundingBox = FIntBoundingBox();
|
||||
InfraredBoundingBox = FIntBoundingBox();
|
||||
|
||||
ColorAlignmentPoints = FFacePoints2D();
|
||||
InfraredAlignmentPoints = FFacePoints2D();
|
||||
|
||||
Location.Set(0.f, 0.f, 0.f);
|
||||
ColorLocation = Location;
|
||||
|
||||
Orientation.Yaw =
|
||||
Orientation.Pitch =
|
||||
Orientation.Roll = 0.f;
|
||||
|
||||
IsEngaged =
|
||||
IsHappy =
|
||||
IsLookingAway =
|
||||
IsMouthMoved =
|
||||
IsMouthOpen =
|
||||
IsLeftEyeClosed =
|
||||
IsRightEyeClosed =
|
||||
IsWearingGlasses = EDetectionResult::Unknown;
|
||||
}
|
||||
+1311
File diff suppressed because it is too large
Load Diff
+5
@@ -0,0 +1,5 @@
|
||||
// Copyright 2015-2023 Rodrigo Villani Pereira
|
||||
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
IMPLEMENT_MODULE(FDefaultModuleImpl, NeoKinectUnreal)
|
||||
Reference in New Issue
Block a user