void ACinemotusPlayerController::AbsoluteTick(float DeltaTime)
{

	
	TotalYawAbs += addYaw;
	UPrimitiveComponent* prim = GetPawn()->GetMovementComponent()->UpdatedComponent;
	//USceneComponent* sComponent = GetPawn()->GetRootComponent();
	//sComponent->SetRelativeLocation;

	bool SetPrimDirectly = true;
	FQuat finalQuat;

	if (((currentCaptureState&ECinemotusCaptureState::EAbsolute) == ECinemotusCaptureState::EAbsolute) && 
		((currentCaptureState&ECinemotusCaptureState::EAbsoluteOff) == 0))
	{
		finalQuat = FRotator(0, TotalYawAbs, 0).Quaternion()*(HydraLatestData->controllers[CAM_HAND].quat);
	}
	else
	{
		finalQuat =  FRotator(0, addYaw, 0).Quaternion()*prim->GetComponentQuat();
	}
	SetControlRotation(finalQuat.Rotator());
	if (SetPrimDirectly && prim)
	{
		prim->SetWorldLocationAndRotation(prim->GetComponentLocation(), finalQuat);// not sure need
	}


	HandleMovementAbs(DeltaTime, ((currentCaptureState&ECinemotusCaptureState::EAbsolute) == ECinemotusCaptureState::EAbsolute));
}
void URotatingMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	// skip if we don't want component updated when not rendered or if updated component can't move
	if ( ShouldSkipUpdate(DeltaTime) )
	{
		return;
	}

	// Compute new rotation
	const FQuat OldRotation = UpdatedComponent->GetComponentQuat();
	const FQuat DeltaRotation = (RotationRate * DeltaTime).Quaternion();
	const FQuat NewRotation = bRotationInLocalSpace ? (OldRotation * DeltaRotation) : (DeltaRotation * OldRotation);

	// Compute new location
	FVector DeltaLocation = FVector::ZeroVector;
	if (!PivotTranslation.IsZero())
	{
		const FVector OldPivot = OldRotation.RotateVector(PivotTranslation);
		const FVector NewPivot = NewRotation.RotateVector(PivotTranslation);
		DeltaLocation = (OldPivot - NewPivot); // ConstrainDirectionToPlane() not necessary because it's done by MoveUpdatedComponent() below.
	}

	const bool bEnableCollision = false;
	MoveUpdatedComponent(DeltaLocation, NewRotation.Rotator(), bEnableCollision);
}
bool UPerceptionNeuronBPLibrary::NeuronGetReferencePoseLocalBoneRotation(USkeletalMeshComponent *Mesh, FRotator& Rotation, int32 BoneIndex)
{
	if (Mesh == nullptr && Mesh->SkeletalMesh == nullptr)
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Mesh is invalid.")));
		}
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		return false;
	}

	if (BoneIndex > Mesh->LocalAtoms.Num())
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("BoneIndex %d exceeds maximum available bones %d."), BoneIndex, Mesh->LocalAtoms.Num()));
		}
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		return false;
	}

	const FReferenceSkeleton& refskel(Mesh->SkeletalMesh->RefSkeleton);
	FQuat Quat = refskel.GetRefBonePose()[BoneIndex].GetRotation();
	Rotation = Quat.Rotator();

	return true;
}
void UOculusFunctionLibrary::GetPose(FRotator& DeviceRotation, FVector& DevicePosition, FVector& NeckPosition, bool bUseOrienationForPlayerCamera, bool bUsePositionForPlayerCamera, const FVector PositionScale)
{
#if OCULUS_SUPPORTED_PLATFORMS
	FHeadMountedDisplay* OculusHMD = GetOculusHMD();
	if (OculusHMD && OculusHMD->IsHeadTrackingAllowed())
	{
		FQuat OrientationAsQuat;

		OculusHMD->GetCurrentHMDPose(OrientationAsQuat, DevicePosition, bUseOrienationForPlayerCamera, bUsePositionForPlayerCamera, PositionScale);

		DeviceRotation = OrientationAsQuat.Rotator();

		NeckPosition = OculusHMD->GetNeckPosition(OrientationAsQuat, DevicePosition, PositionScale);

		//UE_LOG(LogUHeadMountedDisplay, Log, TEXT("POS: %.3f %.3f %.3f"), DevicePosition.X, DevicePosition.Y, DevicePosition.Z);
		//UE_LOG(LogUHeadMountedDisplay, Log, TEXT("NECK: %.3f %.3f %.3f"), NeckPosition.X, NeckPosition.Y, NeckPosition.Z);
		//UE_LOG(LogUHeadMountedDisplay, Log, TEXT("ROT: sYaw %.3f Pitch %.3f Roll %.3f"), DeviceRotation.Yaw, DeviceRotation.Pitch, DeviceRotation.Roll);
	}
	else
#endif // #if OCULUS_SUPPORTED_PLATFORMS
	{
		DeviceRotation = FRotator::ZeroRotator;
		DevicePosition = FVector::ZeroVector;
	}
}
Beispiel #5
0
/*
* Spawns the hitbox and processes the actors within it
*/
void AHero::AttackTrace()
{
	//Actors that overlap the box stored in this array
	TArray<struct FOverlapResult> OutOverlaps;
	//Orient the box in the direction of the character
	FQuat Rotation = Instigator->GetTransform().GetRotation();
	FVector Start = Instigator->GetTransform().GetLocation() + Rotation.Rotator().Vector() * 100.0f;

	FCollisionShape CollisionHitShape;
	FCollisionQueryParams CollisionParams;
	//Have the hitbox ignore the player
	CollisionParams.AddIgnoredActor(Instigator);

	//Set what will respond to the collision
	FCollisionObjectQueryParams CollisionObjectTypes;
	CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody);
	CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_Pawn);
	CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic);

	//Create the hitbox and get the actors within
	CollisionHitShape = FCollisionShape::MakeBox(FVector(100.0f, 60.0f, 0.5f));
	GetWorld()->OverlapMulti(OutOverlaps, Start, Rotation, CollisionHitShape, CollisionParams, CollisionObjectTypes);

	//Process all hit actors
	for (int i = 0; i < OutOverlaps.Num(); i++)
	{
		if (OutOverlaps[i].GetActor() && !HitActors.Contains(OutOverlaps[i].GetActor()))
		{
			//Check if hit registered
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("hit"));
			//Now call the function that does something to our unfortunate actor...
			ProcessHitActor(OutOverlaps[i].GetActor());
		}
	}
}
void UCustomMovementComponent::UpdateCapsuleRotation(float DeltaTime, const FVector& TargetUpVector, bool bInstantRot, float RotationSpeed)
{
	const FVector CapsuleUp = CapsuleComponent->GetUpVector();
	const FQuat DeltaQuat = FQuat::FindBetween(CapsuleUp, TargetUpVector);
	const FQuat TargetQuat = DeltaQuat * CapsuleComponent->GetComponentRotation().Quaternion();

	CurrentCapsuleRotation = bInstantRot ? TargetQuat.Rotator() : FMath::RInterpTo(CurrentCapsuleRotation, TargetQuat.Rotator(), DeltaTime, RotationSpeed);

	CapsuleComponent->SetWorldRotation(CurrentCapsuleRotation);
}
void ACinemotusPlayerController::RelativeTick(float DeltaTime)
{

	UPrimitiveComponent* prim = GetPawn()->GetMovementComponent()->UpdatedComponent;
	bool SetPrimDirectly = true;
	FQuat finalQuat;
	if ((currentCaptureState & ECinemotusCaptureState::ERelativeRotation) == ECinemotusCaptureState::ERelativeRotation)
	{
		FRotator rot = HydraLatestData->controllers[CAM_HAND].angular_velocity;
		const FQuat OldRotation = prim->GetComponentQuat();//GetControlRotation().Quaternion(); //TODO: hold onto a quaternion potentially
		const FRotator OldRotationRotator = OldRotation.Rotator();
		FRotator worldRotator = FRotator(0, DeadZone(rot.Yaw*DeltaTime, 0.0) + addYaw, 0);
		FRotator worldRotator1 = FRotator(DeadZone(rot.Pitch*DeltaTime, 0.0), 0, 0);
		FRotator localRotator = FRotator(0, 0, DeadZone(rot.Roll*DeltaTime, 0.0));
		const FQuat WorldRot = worldRotator.Quaternion();
		const FQuat pitchRot = worldRotator1.Quaternion();
		const FQuat LocalRot = localRotator.Quaternion();

		////This one does roll around local forward, pitch around world right flattened and yaw around world up
		////			FQuat finalQuat = pitchRot*WorldRot*((OldRotation*LocalRot));

		finalQuat = WorldRot*((OldRotation*LocalRot)*pitchRot);
	}
	else
	{
		finalQuat = FRotator(0, addYaw, 0).Quaternion()*prim->GetComponentQuat();
	}

	SetControlRotation(finalQuat.Rotator());
	if (SetPrimDirectly && prim)
	{
		prim->SetWorldLocationAndRotation(prim->GetComponentLocation(), finalQuat);// not sure need
	}



	HandleMovementAbs(DeltaTime, (currentCaptureState & ECinemotusCaptureState::ERelativeTranslation) == ECinemotusCaptureState::ERelativeTranslation);

}
void UAnimGraphNode_ModifyBone::DoRotation(const USkeletalMeshComponent* SkelComp, FRotator& Rotation, FAnimNode_Base* InOutAnimNode)
{
	FAnimNode_ModifyBone* ModifyBone = static_cast<FAnimNode_ModifyBone*>(InOutAnimNode);

	if (Node.RotationMode != EBoneModificationMode::BMM_Ignore)
	{
		FQuat DeltaQuat = ConvertCSRotationToBoneSpace(SkelComp, Rotation, ModifyBone->ForwardedPose, Node.BoneToModify.BoneName, Node.RotationSpace);

		FQuat PrevQuat(ModifyBone->Rotation);
		FQuat NewQuat = DeltaQuat * PrevQuat;
		ModifyBone->Rotation = NewQuat.Rotator();
		Node.Rotation = ModifyBone->Rotation;
	}
}
void UOSVRInputComponent::InitializeComponent()
{
	Super::InitializeComponent();

	WorldToMetersScale = 100.f;
	UWorld* w = GetWorld();
	if (w != nullptr)
	{
		AWorldSettings* ws = w->GetWorldSettings();
		if (ws != nullptr)
		{
			WorldToMetersScale = ws->WorldToMeters;
		}
	}

	auto InterfaceCollection = IOSVR::Get().GetEntryPoint()->GetInterfaceCollection();

	OSVRInterfaceCollection::RegistrationToken RegToken =
		InterfaceCollection->RegisterOnStateChangedCallback(
			[=](OSVRInterface* Interface, uint32 State)
			{
		/*
		FTransform Pose;
		if (((State & OSVRInterface::POSE_STATE_AVAILABLE) > 0) && Interface->GetPose(Pose, false))
		{
			Pose.ScaleTranslation(WorldToMetersScale);
			OnPoseChanged.Broadcast(Interface->GetName(), Pose);
		}
		*/

		FVector Position;
		if (((State & OSVRInterface::POSITION_STATE_AVAILABLE) > 0) && Interface->GetPosition(Position, false))
			OnPositionChanged.Broadcast(Interface->GetName(), Position * WorldToMetersScale);

		FQuat Orientation;
		if (((State & OSVRInterface::ORIENTATION_STATE_AVAILABLE) > 0) && Interface->GetOrientation(Orientation, false))
			OnOrientationChanged.Broadcast(Interface->GetName(), Orientation.Rotator());

		float Analog;
		if (((State & OSVRInterface::ANALOG_STATE_AVAILABLE) > 0) && Interface->GetAnalogState(Analog, false))
			OnAnalogValueChanged.Broadcast(Interface->GetName(), Analog);

		uint8 Button;
		if (((State & OSVRInterface::BUTTON_STATE_AVAILABLE) > 0) && Interface->GetButtonState(Button, false))
			OnButtonStateChanged.Broadcast(Interface->GetName(), EButtonState::Type(Button));
			});

	RegistrationToken = RegToken.Token;
}
void ABaseCharacter::CheckAttackOverlap(){

	//Overlapping actors for each box spawned will be stored here
	TArray<struct FOverlapResult> OutActorOverlaps;

	//Hit other actors only once
	TArray<AActor*> ProcessedActors;


	//The initial rotation of our box is the same as our character rotation
	FQuat Rotation = GetTransform().GetRotation();
	FVector Start = GetTransform().GetLocation() + Rotation.Rotator().Vector() * 100.0f;

	FCollisionShape CollisionHitShape;
	FCollisionQueryParams CollisionParams;

	//We do not want the character to hit itself, don't store this character in the array, to ignore it's collision
	CollisionParams.AddIgnoredActor(this);

	//Set the channels that will respond to the collision
	FCollisionObjectQueryParams CollisionObjectTypes;
	CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody);
	CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_Pawn);
	//CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic); // uncomment to enable bashing objects

	//Create the box and get the overlapping actors
	CollisionHitShape = FCollisionShape::MakeBox(AttackBox);
	GetWorld()->OverlapMulti(OutActorOverlaps, Start, Rotation, CollisionHitShape, CollisionParams, CollisionObjectTypes);


	AActor* ActorToProcess;
	//Process all hit actors
	for (int i = 0; i < OutActorOverlaps.Num(); ++i)
	{
		ActorToProcess = OutActorOverlaps[i].GetActor();
		//We process each actor only once per Attack execution
		if (ActorToProcess && !ProcessedActors.Contains(ActorToProcess))
		{

			//Add this actor to the array because we are spawning one box per tick and we don't want to hit the same actor twice during the same attack animation
			ProcessedActors.AddUnique(ActorToProcess);

			if ( dynamic_cast<APatrollingEnemyCharacter*>(ActorToProcess) ){
				APatrollingEnemyCharacter* ennemy = (APatrollingEnemyCharacter*)ActorToProcess;
				ennemy->OnHit(this);
			}
		}
	}
}
FRotator UKismetMathLibrary::RLerp(FRotator A, FRotator B, float Alpha, bool bShortestPath)
{
	FRotator DeltaAngle = B - A;

	// if shortest path, we use Quaternion to interpolate instead of using FRotator
	if( bShortestPath )
	{
		FQuat AQuat(A);
		FQuat BQuat(B);

		FQuat Result = FQuat::Slerp(AQuat, BQuat, Alpha);
		Result.Normalize();

		return Result.Rotator();
	}

	return A + Alpha*DeltaAngle;
}
Beispiel #12
0
FRotator ULibraries::GetQRotation()
{
	
	float q1, q2, q3, q4;
	bool sent = FemtoduinoPointer->WriteData("w\n", 32);
	char parse1[10], parse2[10], parse3[10], parse4[10];
	char incomingData[250];
	int dataLength = 250;
	//Sleep(50);
	FemtoduinoPointer->ReadData(incomingData, dataLength);

	_memccpy(&parse1, incomingData,',' ,8);
	_memccpy(&parse2, &incomingData[9],',', 8);
	_memccpy(&parse3, &incomingData[18], ',', 8);
	_memccpy(&parse4, &incomingData[27], ',', 8);



	hexasciitofloat(q1, parse1);
	hexasciitofloat(q2, parse2);
	hexasciitofloat(q3, parse3);
	hexasciitofloat(q4, parse4);
	
	
	FQuat newQ = FQuat(q2,q3,q4,q1);

	if (!hq.Equals(FQuat::Identity))
	{
		return (hq*newQ).Rotator();
	}

	//newQ.Normalize(1.1);
	//FQuat hq = FQuat::Identity;
	//FQuat next = newQ*hq;     //FQuat::Slerp(newQ,current.Quaternion(),.5);
	//FRotator test = next.Rotator();

	return newQ.Rotator();
}
Beispiel #13
0
void VRPNTrackerInputDevice::Update() {
	if(InputDevice){
		{
			FScopeLock ScopeLock(&CritSect);
			InputDevice->mainloop();
		}
		for(auto &InputPair : TrackerMap)
		{
			TrackerInput &Input = InputPair.Value;
			if(Input.TrackerDataDirty)
			{
				// Before firing events, transform the tracker into the right coordinate space

				FVector NewPosition;
				FQuat NewRotation;
				TransformCoordinates(Input, NewPosition, NewRotation);

				FRotator NewRotator = NewRotation.Rotator();

				FAnalogInputEvent AnalogInputEventX(Input.MotionXKey, FSlateApplication::Get().GetModifierKeys(), 0, 0, 0, 0, NewPosition.X);
				FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEventX);
				FAnalogInputEvent AnalogInputEventY(Input.MotionYKey, FSlateApplication::Get().GetModifierKeys(), 0, 0, 0, 0, NewPosition.Y);
				FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEventY);
				FAnalogInputEvent AnalogInputEventZ(Input.MotionZKey, FSlateApplication::Get().GetModifierKeys(), 0, 0, 0, 0, NewPosition.Z);
				FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEventZ);

				FAnalogInputEvent AnalogInputEventRotX(Input.RotationYawKey, FSlateApplication::Get().GetModifierKeys(), 0, 0, 0, 0, NewRotator.Yaw);
				FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEventRotX);
				FAnalogInputEvent AnalogInputEventRotY(Input.RotationPitchKey, FSlateApplication::Get().GetModifierKeys(), 0, 0, 0, 0, NewRotator.Pitch);
				FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEventRotY);
				FAnalogInputEvent AnalogInputEventRotZ(Input.RotationRollKey, FSlateApplication::Get().GetModifierKeys(), 0, 0, 0, 0, NewRotator.Roll);
				FSlateApplication::Get().ProcessAnalogInputEvent(AnalogInputEventRotZ);

				Input.TrackerDataDirty = false;
			}
		}
	}
}
// Read motion data from Axis Neuron
bool UNeuronBPFunctionLibrary::NeuronReadMotion(AThirdPersonNeuronController *Controller, FVector& Translation, FRotator& Rotation, FVector AddTranslation, FRotator AddRotation, int32 BoneIndex, ENeuronSkeletonEnum SkeletonType)
{
	bool bExit = false;

	if (Controller == NULL)
	{
		if (GEngine) 
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Controller is invalid.")));
		}
		bExit = true;
	}
	else if (!Controller->bConnected)
	{
		bExit = true;
	}
	else if (BoneIndex > Controller->BoneNr)
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Boneindex %d exceeds maximum available bones %d."), BoneIndex, Controller->BoneNr));
		}
		bExit = true;
	}
	else if ((BoneIndex * 6) > Controller->FloatCount)
	{	
		bExit = true;
	}

	if (bExit == true)
	{
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		Translation.X = Translation.Y = Translation.Z = 0;
		return false;
	}


	//
	// Translation
	//

	// Read translation values and remove BVH reference position
	float X = Controller->MotionLine[(BoneIndex * 6) + Controller->Skeleton[BoneIndex].XPos] - Controller->Skeleton[BoneIndex].Offset[0];
	float Y = Controller->MotionLine[(BoneIndex * 6) + Controller->Skeleton[BoneIndex].YPos] - Controller->Skeleton[BoneIndex].Offset[1];
	float Z = Controller->MotionLine[(BoneIndex * 6) + Controller->Skeleton[BoneIndex].ZPos] - Controller->Skeleton[BoneIndex].Offset[2];
	
	// Map BVH right hand system to local bone coordinate system
	switch (SkeletonType)
	{
		case ENeuronSkeletonEnum::VE_Neuron:  // Neuron BVH skeleton
		{
			if (BoneIndex == 0)
			{	// Hips
				Translation = FVector(X, -Y, Z);
			}
			else if ((BoneIndex >= 1) && (BoneIndex <= 6))
			{	// Legs
				Translation = FVector(X, Y, -Z);
			}
			else if ((BoneIndex >= 7) && (BoneIndex <= 12))
			{	// Spine,...
				Translation = FVector(X, -Y, -Z);
			}
			else if ((BoneIndex >= 13) && (BoneIndex <= 35))
			{	// Right arm
				Translation = FVector(-Z, X, Y);
			}
			else if ((BoneIndex >= 36) && (BoneIndex <= 58))
			{	// Left arm
				Translation = FVector(Z, -X, Y);
			}
			break;
		}
		case ENeuronSkeletonEnum::VE_TPP_Hero:	// Hero_TPP, Old blue Unreal default skeleton with T-Pose
		case ENeuronSkeletonEnum::VE_Mannequin: // Mannequin, New Unreal default skeleton with A-Pose
		{
			if (BoneIndex == 0)
			{	// Hips
				Translation = FVector(Y, Z, -X);
			}
			// Ignore other bones
		}
	}

	// Add additional translation
	Translation.X += AddTranslation.X;
	Translation.Y += AddTranslation.Y;
	Translation.Z += AddTranslation.Z;
	


	//
	// Rotation 
	//

	// Read rotation values and map to pitch, yaw, roll (y, z, x)
	float XR = Controller->MotionLine[(BoneIndex * 6) + Controller->Skeleton[BoneIndex].XRot] * PI / 180.f;
	float YR = Controller->MotionLine[(BoneIndex * 6) + Controller->Skeleton[BoneIndex].YRot] * PI / 180.f;
	float ZR = Controller->MotionLine[(BoneIndex * 6) + Controller->Skeleton[BoneIndex].ZRot] * PI / 180.f;

	float SX = sin(XR);
	float CX = cos(XR);
	float SY = sin(YR);
	float CY = cos(YR);
	float SZ = sin(ZR);
	float CZ = cos(ZR);

	FMatrix RotMatrix;
	switch (Controller->Skeleton[BoneIndex].RotOrder)
	{
		case XYZ:
		{
			RotMatrix.M[0][0] = CY*CZ;
			RotMatrix.M[0][1] = -CY*SZ;
			RotMatrix.M[0][2] = SY;
			RotMatrix.M[0][3] = 0;
			RotMatrix.M[1][0] = CZ*SX*SY + CX*SZ;
			RotMatrix.M[1][1] = CX*CZ - SX*SY*SZ;
			RotMatrix.M[1][2] = -CY*SX;
			RotMatrix.M[1][3] = 0;
			RotMatrix.M[2][0] = SX*SZ - CX*CZ*SY;
			RotMatrix.M[2][1] = CZ*SX + CX*SY*SZ;
			RotMatrix.M[2][2] = CX*CY;
			RotMatrix.M[2][3] = 0;
			break;
		}
		case ZXY:
		{
			RotMatrix.M[0][0] = CY*CZ - SX*SY*SZ;
			RotMatrix.M[0][1] = -CX*SZ;
			RotMatrix.M[0][2] = CZ*SY + CY*SX*SZ;
			RotMatrix.M[0][3] = 0;
			RotMatrix.M[1][0] = CZ*SX*SY + CY*SZ;
			RotMatrix.M[1][1] = CX*CZ;
			RotMatrix.M[1][2] = SY*SZ - CY*CZ*SX;
			RotMatrix.M[1][3] = 0;
			RotMatrix.M[2][0] = -CX*SY;
			RotMatrix.M[2][1] = SX;
			RotMatrix.M[2][2] = CX*CY;
			RotMatrix.M[2][3] = 0;
			break;
		}
		case YXZ:
		default:
		{
			RotMatrix.M[0][0] = CY*CZ + SX*SY*SZ;
			RotMatrix.M[0][1] = CZ*SX*SY - CY*SZ;
			RotMatrix.M[0][2] = CX*SY;
			RotMatrix.M[0][3] = 0;
			RotMatrix.M[1][0] = CX*SZ;
			RotMatrix.M[1][1] = CX*CZ;
			RotMatrix.M[1][2] = -SX;
			RotMatrix.M[1][3] = 0;
			RotMatrix.M[2][0] = CY*SX*SZ - CZ*SY;
			RotMatrix.M[2][1] = CY*CZ*SX + SY*SZ;
			RotMatrix.M[2][2] = CX*CY;
			RotMatrix.M[2][3] = 0;
			break;
		}
	}

	RotMatrix.M[3][0] = 0;
	RotMatrix.M[3][1] = 0;
	RotMatrix.M[3][2] = 0;
	RotMatrix.M[3][3] = 1;

	// Rotation Matrix => Quaternion and map to each bone coordinate systems dependend on skeleton type
	FQuat Quat = RotMatrix.ToQuat();
	switch (SkeletonType)
	{
		case ENeuronSkeletonEnum::VE_Neuron:  // Neuron BVH skeleton
		{
			if ((BoneIndex >= 1) && (BoneIndex <= 6))
			{	// Legs
				Quat.Z *= -1.f;
			}
			else if ((BoneIndex >= 13) && (BoneIndex <= 35))
			{	// Right Arm
				float X = Quat.X;
				float Y = Quat.Y;
				float Z = Quat.Z;
				Quat.X = -Z;
				Quat.Y = X;
				Quat.Z = Y;
			}
			else if ((BoneIndex >= 36) && (BoneIndex <= 58))
			{	// Left Arm
				float X = Quat.X;
				float Y = Quat.Y;
				float Z = Quat.Z;
				Quat.X = Z;
				Quat.Y = -X;
				Quat.Z = Y;
			}
			else
			{
				Quat.Y *= -1.f;
			}
			break;
		}
		case ENeuronSkeletonEnum::VE_TPP_Hero:	// Hero_TPP, Old blue Unreal default skeleton with T-Pose
		case ENeuronSkeletonEnum::VE_Mannequin: // Mannequin, New Unreal default skeleton with A-Pose
		{
			if ((BoneIndex >= 1) && (BoneIndex <= 3))
			{	// Right Leg
				float X = Quat.X;
				float Y = Quat.Y;
				float Z = Quat.Z;
				Quat.X = -Y;
				Quat.Y = -Z;
				Quat.Z = -X;
			}
			else if (BoneIndex == 16)
			{	// Right Hand
				Quat.Y *= -1.f;
			}
			else if ((BoneIndex >= 13) && (BoneIndex <= 19))
			{	// Right Arm and Thumb
				float Y = Quat.Y;
				float Z = Quat.Z;
				Quat.Y = -Z;
				Quat.Z = -Y;
			}
			else if ((BoneIndex >= 20) && (BoneIndex <= 35))
			{	// Right Finger
				Quat.Y *= -1.f;
			}
			else if (BoneIndex == 39)
			{	// Left Hand
				Quat.Z *= -1.f;
			}
			else if ((BoneIndex >= 36) && (BoneIndex <= 42))
			{	// Left Arm and Thumb
				float Y = Quat.Y;
				float Z = Quat.Z;
				Quat.Y = Z;
				Quat.Z = Y;
			}
			else if ((BoneIndex >= 43) && (BoneIndex <= 58))
			{	// Left Finger
				Quat.Z *= -1.f;
			}
			else
			{	// Left Leg, Hips, Spine, Neck, Head
				float X = Quat.X;
				float Y = Quat.Y;
				float Z = Quat.Z;
				Quat.X = Y;
				Quat.Y = Z;
				Quat.Z = -X;
			}
		}
		break;
	}		
	
	Rotation = Quat.Rotator();
	
	// Add additional rotation
	Rotation.Yaw += AddRotation.Yaw;
	Rotation.Pitch += AddRotation.Pitch;
	Rotation.Roll += AddRotation.Roll;
	
	return true;
}
FQuat FAnimNode_RotationMultiplier::MultiplyQuatBasedOnSourceIndex(const FTransform& RefPoseTransform, const FTransform& LocalBoneTransform, const EBoneAxis Axis, float InMultiplier, const FQuat& ReferenceQuat)
{
	// Find delta angle for source bone.
	FQuat DeltaQuat = ExtractAngle(RefPoseTransform, LocalBoneTransform, Axis);

	// Turn to Axis and Angle
	FVector RotationAxis;
	float	RotationAngle;
	DeltaQuat.ToAxisAndAngle(RotationAxis, RotationAngle);

	const FVector DefaultAxis = GetAxisVector(Axis);

	// See if we need to invert angle - shortest path
	if( (RotationAxis | DefaultAxis) < 0.f )
	{
		RotationAxis = -RotationAxis;
		RotationAngle = -RotationAngle;
	}

	// Make sure it is the shortest angle.
	RotationAngle = FMath::UnwindRadians(RotationAngle);

	// New bone rotation
	FQuat OutQuat = ReferenceQuat * FQuat(RotationAxis, RotationAngle* InMultiplier);
	// Normalize resulting quaternion.
	OutQuat.Normalize();

#if 0 //DEBUG_TWISTBONECONTROLLER
	UE_LOG(LogSkeletalControl, Log, TEXT("\t RefQuat: %s, Rot: %s"), *ReferenceQuat.ToString(), *ReferenceQuat.Rotator().ToString() );
	UE_LOG(LogSkeletalControl, Log, TEXT("\t NewQuat: %s, Rot: %s"), *OutQuat.ToString(), *OutQuat.Rotator().ToString() );
	UE_LOG(LogSkeletalControl, Log, TEXT("\t RollAxis: %s, RollAngle: %f"), *RotationAxis.ToString(), RotationAngle );
#endif

	return OutQuat;
}
FQuat FAnimNode_RotationMultiplier::ExtractAngle(const FTransform& RefPoseTransform, const FTransform& LocalBoneTransform, const EBoneAxis Axis)
{
	// local bone transform with reference rotation
	FTransform ReferenceBoneTransform = RefPoseTransform;
	ReferenceBoneTransform.SetTranslation(LocalBoneTransform.GetTranslation());

	// find delta angle between the two quaternions X Axis.
	const FVector RotationAxis = GetAxisVector(Axis);
	const FVector LocalRotationVector = LocalBoneTransform.GetRotation().RotateVector(RotationAxis);
	const FVector ReferenceRotationVector = ReferenceBoneTransform.GetRotation().RotateVector(RotationAxis);

	const FQuat LocalToRefQuat = FQuat::FindBetween(LocalRotationVector, ReferenceRotationVector);
	checkSlow( LocalToRefQuat.IsNormalized() );

	// Rotate parent bone atom from position in local space to reference skeleton
	// Since our rotation rotates both vectors with shortest arc
	// we're essentially left with a quaternion that has angle difference with reference skeleton version
	const FQuat BoneQuatAligned = LocalToRefQuat* LocalBoneTransform.GetRotation();
	checkSlow( BoneQuatAligned.IsNormalized() );

	// Find that delta angle
	const FQuat DeltaQuat = (ReferenceBoneTransform.GetRotation().Inverse()) * BoneQuatAligned;
	checkSlow( DeltaQuat.IsNormalized() );

#if 0 //DEBUG_TWISTBONECONTROLLER
	UE_LOG(LogSkeletalControl, Log, TEXT("\t ExtractAngle, Bone: %s"), 
		*SourceBone.BoneName.ToString());
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t Bone Quat: %s, Rot: %s, AxisX: %s"), *LocalBoneTransform.GetRotation().ToString(), *LocalBoneTransform.GetRotation().Rotator().ToString(), *LocalRotationVector.ToString() );
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t BoneRef Quat: %s, Rot: %s, AxisX: %s"), *ReferenceBoneTransform.GetRotation().ToString(), *ReferenceBoneTransform.GetRotation().Rotator().ToString(), *ReferenceRotationVector.ToString() );
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t LocalToRefQuat Quat: %s, Rot: %s"), *LocalToRefQuat.ToString(), *LocalToRefQuat.Rotator().ToString() );

	const FVector BoneQuatAlignedX = LocalBoneTransform.GetRotation().RotateVector(RotationAxis);
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t BoneQuatAligned Quat: %s, Rot: %s, AxisX: %s"), *BoneQuatAligned.ToString(), *BoneQuatAligned.Rotator().ToString(), *BoneQuatAlignedX.ToString() );
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t DeltaQuat Quat: %s, Rot: %s"), *DeltaQuat.ToString(), *DeltaQuat.Rotator().ToString() );

	FTransform BoneAtomAligned(BoneQuatAligned, ReferenceBoneTransform.GetTranslation());
	const FQuat DeltaQuatAligned = FQuat::FindBetween(BoneAtomAligned.GetScaledAxis( EAxis::X ), ReferenceBoneTransform.GetScaledAxis( EAxis::X ));
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t DeltaQuatAligned Quat: %s, Rot: %s"), *DeltaQuatAligned.ToString(), *DeltaQuatAligned.Rotator().ToString() );
	FVector DeltaAxis;
	float	DeltaAngle;
	DeltaQuat.ToAxisAndAngle(DeltaAxis, DeltaAngle);
	UE_LOG(LogSkeletalControl, Log, TEXT("\t\t DeltaAxis: %s, DeltaAngle: %f"), *DeltaAxis.ToString(), DeltaAngle );
#endif

	return DeltaQuat;
}
void UStretchGizmoHandleGroup::UpdateGizmoHandleGroup( const FTransform& LocalToWorld, const FBox& LocalBounds, const FVector ViewLocation, bool bAllHandlesVisible, class UActorComponent* DraggingHandle, const TArray< UActorComponent* >& HoveringOverHandles, 
	float AnimationAlpha, float GizmoScale, const float GizmoHoverScale, const float GizmoHoverAnimationDuration, bool& bOutIsHoveringOrDraggingThisHandleGroup )
{
	// Call parent implementation (updates hover animation)
	Super::UpdateGizmoHandleGroup(LocalToWorld, LocalBounds, ViewLocation, bAllHandlesVisible, DraggingHandle, HoveringOverHandles,
		AnimationAlpha, GizmoScale, GizmoHoverScale, GizmoHoverAnimationDuration, bOutIsHoveringOrDraggingThisHandleGroup );

	for (int32 HandleIndex = 0; HandleIndex < Handles.Num(); ++HandleIndex)
	{
		FGizmoHandle& Handle = Handles[ HandleIndex ];

		UStaticMeshComponent* StretchingHandle = Handle.HandleMesh;
		if (StretchingHandle != nullptr)	// Can be null if no handle for this specific placement
		{
			const FTransformGizmoHandlePlacement HandlePlacement = MakeHandlePlacementForIndex( HandleIndex );

			float GizmoHandleScale = GizmoScale;

			const float OffsetFromSide = GizmoHandleScale *
				(0.0f +	// @todo vreditor tweak: Hard coded handle offset from side of primitive
				(1.0f - AnimationAlpha) * 10.0f);	// @todo vreditor tweak: Animation offset

			// Make the handle bigger while hovered (but don't affect the offset -- we want it to scale about it's origin)
			GizmoHandleScale *= FMath::Lerp( 1.0f, GizmoHoverScale, Handle.HoverAlpha );

			FVector HandleRelativeLocation = FVector::ZeroVector;
			for (int32 AxisIndex = 0; AxisIndex < 3; ++AxisIndex)
			{
				if (HandlePlacement.Axes[AxisIndex] == ETransformGizmoHandleDirection::Negative)	// Negative direction
				{
					HandleRelativeLocation[AxisIndex] = LocalBounds.Min[AxisIndex] - OffsetFromSide;
				}
				else if (HandlePlacement.Axes[AxisIndex] == ETransformGizmoHandleDirection::Positive)	// Positive direction
				{
					HandleRelativeLocation[AxisIndex] = LocalBounds.Max[AxisIndex] + OffsetFromSide;
				}
				else // ETransformGizmoHandleDirection::Center
				{
					HandleRelativeLocation[AxisIndex] = LocalBounds.GetCenter()[AxisIndex];
				}
			}

			StretchingHandle->SetRelativeLocation( HandleRelativeLocation );

			int32 CenterHandleCount, FacingAxisIndex, CenterAxisIndex;
			HandlePlacement.GetCenterHandleCountAndFacingAxisIndex( /* Out */ CenterHandleCount, /* Out */ FacingAxisIndex, /* Out */ CenterAxisIndex );

			FRotator Rotator = FRotator::ZeroRotator;
			{
				// Back bottom left
				if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Negative)
				{
					Rotator.Yaw = 0.0f;
					Rotator.Pitch = 0.0f;
				}

				// Back bottom right
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Negative)
				{
					Rotator.Yaw = -90.0f;
					Rotator.Pitch = 0.0f;
				}

				// Back top left
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Positive)
				{
					Rotator.Yaw = 0.0f;
					Rotator.Pitch = -90.0f;
				}

				// Back top right
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Positive)
				{
					Rotator.Yaw = -90.0f;
					Rotator.Pitch = -90.0f;
				}

				// Front bottom left
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Negative)
				{
					Rotator.Yaw = 0.0f;
					Rotator.Pitch = 90.0f;
				}

				// Front bottom right
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Negative)
				{
					Rotator.Yaw = 90.0f;
					Rotator.Pitch = 90.0f;
				}

				// Front top left
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Positive)
				{
					Rotator.Yaw = 0.0f;
					Rotator.Pitch = -180.0f;
				}

				// Front top right
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[1] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[2] == ETransformGizmoHandleDirection::Positive)
				{
					Rotator.Yaw = 180.0f;
					Rotator.Pitch = -90.0f;
				}

				// Back left/right edge
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[1] != ETransformGizmoHandleDirection::Center)
				{
					Rotator.Yaw = 0.0f;
					Rotator.Pitch = 90.0f;
				}

				// Back bottom/top edge
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Negative && HandlePlacement.Axes[2] != ETransformGizmoHandleDirection::Center)
				{
					Rotator.Yaw = 90.0f;
					Rotator.Pitch = 0.0f;
				}

				// Front left/right edge
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[1] != ETransformGizmoHandleDirection::Center)
				{
					Rotator.Yaw = 0.0f;
					Rotator.Pitch = 90.0f;
				}

				// Front bottom/top edge
				else if (HandlePlacement.Axes[0] == ETransformGizmoHandleDirection::Positive && HandlePlacement.Axes[2] != ETransformGizmoHandleDirection::Center)
				{
					Rotator.Yaw = 90.0f;
					Rotator.Pitch = 0.0f;
				}

				else
				{
					// Facing out from center of a face
					if (CenterHandleCount == 2)
					{
						const FQuat GizmoSpaceOrientation = GetAxisVector( FacingAxisIndex, HandlePlacement.Axes[FacingAxisIndex] ).ToOrientationQuat();
						Rotator = GizmoSpaceOrientation.Rotator();
					}

					else
					{
						// One of the left/right bottom or top edges
					}
				}
			}

			StretchingHandle->SetRelativeRotation( Rotator );

			StretchingHandle->SetRelativeScale3D( FVector( GizmoHandleScale ) );

			// Update material
			UpdateHandleColor( FacingAxisIndex, Handle, DraggingHandle, HoveringOverHandles );
		}
	}
}
Beispiel #18
0
void FOculusInput::SendControllerEvents()
{
	const double CurrentTime = FPlatformTime::Seconds();

	// @todo: Should be made configurable and unified with other controllers handling of repeat
	const float InitialButtonRepeatDelay = 0.2f;
	const float ButtonRepeatDelay = 0.1f;
	const float AnalogButtonPressThreshold = TriggerThreshold;

	IOculusRiftPlugin& OculusRiftPlugin = IOculusRiftPlugin::Get();
	ovrSession OvrSession = OculusRiftPlugin.GetSession();
	UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: OvrSession = %p"), OvrSession);
	if (OvrSession)
	{
		ovrInputState OvrInput;
		ovrTrackingState OvrTrackingState;

		const ovrResult OvrRes = ovr_GetInputState(OvrSession, ovrControllerType_Touch, &OvrInput);
		const bool bOvrGCTRes = OculusRiftPlugin.GetCurrentTrackingState(&OvrTrackingState);

		UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ovr_GetInputState() ret = %d, GetCurrentTrackingState ret = %d"), int(OvrRes), int(bOvrGCTRes));

		if (OvrRes == ovrSuccess && bOvrGCTRes)
		{
			UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ConnectedControllerTypes 0x%X"), OvrInput.ConnectedControllerTypes);
			UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ButtonState = 0x%X"), OvrInput.Buttons);
			UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: Touches = 0x%X"), OvrInput.Touches);

			for (FOculusTouchControllerPair& ControllerPair : ControllerPairs)
			{
				for( int32 HandIndex = 0; HandIndex < ARRAY_COUNT( ControllerPair.ControllerStates ); ++HandIndex )
				{
					FOculusTouchControllerState& State = ControllerPair.ControllerStates[ HandIndex ];

					const bool bIsLeft = (HandIndex == (int32)EControllerHand::Left);
					bool bIsCurrentlyTracked = (bIsLeft ? (OvrInput.ConnectedControllerTypes & ovrControllerType_LTouch) != 0 : (OvrInput.ConnectedControllerTypes & ovrControllerType_RTouch) != 0);

#if OVR_TESTING
					bIsCurrentlyTracked = true;
					static float _angle = 0;
					OvrTrackingState.HandPoses[HandIndex].ThePose.Orientation = OVR::Quatf(OVR::Vector3f(0, 0, 1), _angle);
					_angle += 0.1f;

					OvrTrackingState.HandPoses[HandIndex].ThePose = OvrTrackingState.HeadPose.ThePose;
					UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Error, TEXT("SendControllerEvents: OVR_TESTING is enabled!"));
#endif

					if (bIsCurrentlyTracked)
					{
						State.bIsCurrentlyTracked = true;

						const float OvrTriggerAxis = OvrInput.IndexTrigger[HandIndex];
						const float OvrGripAxis = OvrInput.HandTrigger[HandIndex];

						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: IndexTrigger[%d] = %f"), int(HandIndex), OvrTriggerAxis);
						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: HandTrigger[%d] = %f"), int(HandIndex), OvrGripAxis);
						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: ThumbStick[%d] = { %f, %f }"), int(HandIndex), OvrInput.Thumbstick[HandIndex].x, OvrInput.Thumbstick[HandIndex].y );

						if (OvrTriggerAxis != State.TriggerAxis)
						{
							State.TriggerAxis = OvrTriggerAxis;
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_TriggerAxis : FGamepadKeyNames::MotionController_Right_TriggerAxis, ControllerPair.UnrealControllerIndex, State.TriggerAxis);
						}

						if (OvrGripAxis != State.GripAxis)
						{
							State.GripAxis = OvrGripAxis;
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_Grip1Axis : FGamepadKeyNames::MotionController_Right_Grip1Axis, ControllerPair.UnrealControllerIndex, State.GripAxis);
						}

						if (OvrInput.Thumbstick[HandIndex].x != State.ThumbstickAxes.X)
						{
							State.ThumbstickAxes.X = OvrInput.Thumbstick[HandIndex].x;
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_Thumbstick_X : FGamepadKeyNames::MotionController_Right_Thumbstick_X, ControllerPair.UnrealControllerIndex, State.ThumbstickAxes.X);
						}

						if (OvrInput.Thumbstick[HandIndex].y != State.ThumbstickAxes.Y)
						{
							State.ThumbstickAxes.Y = OvrInput.Thumbstick[HandIndex].y;
							// we need to negate Y value to match XBox controllers
							MessageHandler->OnControllerAnalog(bIsLeft ? FGamepadKeyNames::MotionController_Left_Thumbstick_Y : FGamepadKeyNames::MotionController_Right_Thumbstick_Y, ControllerPair.UnrealControllerIndex, -State.ThumbstickAxes.Y);
						}

						for (int32 ButtonIndex = 0; ButtonIndex < (int32)EOculusTouchControllerButton::TotalButtonCount; ++ButtonIndex)
						{
							FOculusButtonState& ButtonState = State.Buttons[ButtonIndex];
							check(!ButtonState.Key.IsNone()); // is button's name initialized?

							// Determine if the button is pressed down
							bool bButtonPressed = false;
							switch ((EOculusTouchControllerButton)ButtonIndex)
							{
							case EOculusTouchControllerButton::Trigger:
								bButtonPressed = State.TriggerAxis >= AnalogButtonPressThreshold;
								break;

							case EOculusTouchControllerButton::Grip:
								bButtonPressed = State.GripAxis >= AnalogButtonPressThreshold;
								break;

							case EOculusTouchControllerButton::XA:
								bButtonPressed = bIsLeft ? (OvrInput.Buttons & ovrButton_X) != 0 : (OvrInput.Buttons & ovrButton_A) != 0;
								break;

							case EOculusTouchControllerButton::YB:
								bButtonPressed = bIsLeft ? (OvrInput.Buttons & ovrButton_Y) != 0 : (OvrInput.Buttons & ovrButton_B) != 0;
								break;

							case EOculusTouchControllerButton::Thumbstick:
								bButtonPressed = bIsLeft ? (OvrInput.Buttons & ovrButton_LThumb) != 0 : (OvrInput.Buttons & ovrButton_RThumb) != 0;
								break;

							default:
								check(0);
								break;
							}

							// Update button state
							if (bButtonPressed != ButtonState.bIsPressed)
							{
								const bool bIsRepeat = false;

								ButtonState.bIsPressed = bButtonPressed;
								if (ButtonState.bIsPressed)
								{
									MessageHandler->OnControllerButtonPressed(ButtonState.Key, ControllerPair.UnrealControllerIndex, bIsRepeat);

									// Set the timer for the first repeat
									ButtonState.NextRepeatTime = CurrentTime + ButtonRepeatDelay;
								}
								else
								{
									MessageHandler->OnControllerButtonReleased(ButtonState.Key, ControllerPair.UnrealControllerIndex, bIsRepeat);
								}
							}

							// Apply key repeat, if its time for that
							if (ButtonState.bIsPressed && ButtonState.NextRepeatTime <= CurrentTime)
							{
								const bool bIsRepeat = true;
								MessageHandler->OnControllerButtonPressed(ButtonState.Key, ControllerPair.UnrealControllerIndex, bIsRepeat);

								// Set the timer for the next repeat
								ButtonState.NextRepeatTime = CurrentTime + ButtonRepeatDelay;
							}
						}

						// Handle Capacitive States
						for (int32 CapTouchIndex = 0; CapTouchIndex < (int32)EOculusTouchCapacitiveAxes::TotalAxisCount; ++CapTouchIndex)
						{
							FOculusTouchCapacitiveState& CapState = State.CapacitiveAxes[CapTouchIndex];

							float CurrentAxisVal = 0.f;
							switch ((EOculusTouchCapacitiveAxes)CapTouchIndex)
							{
							case EOculusTouchCapacitiveAxes::XA:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_X : ovrTouch_A;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::YB:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_Y : ovrTouch_B;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::Thumbstick:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LThumb : ovrTouch_RThumb;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::Trigger:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LIndexTrigger : ovrTouch_RIndexTrigger;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::IndexPointing:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LIndexPointing : ovrTouch_RIndexPointing;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							case EOculusTouchCapacitiveAxes::ThumbUp:
							{
								const uint32 mask = (bIsLeft) ? ovrTouch_LThumbUp : ovrTouch_RThumbUp;
								CurrentAxisVal = (OvrInput.Touches & mask) != 0 ? 1.f : 0.f;
								break;
							}
							default:
								check(0);
							}
							
							if (CurrentAxisVal != CapState.State)
							{
								MessageHandler->OnControllerAnalog(CapState.Axis, ControllerPair.UnrealControllerIndex, CurrentAxisVal);

								CapState.State = CurrentAxisVal;
							}
						}

						const ovrPosef& OvrHandPose = OvrTrackingState.HandPoses[HandIndex].ThePose;
						FVector NewLocation;
						FQuat NewOrientation;
						if (OculusRiftPlugin.PoseToOrientationAndPosition(OvrHandPose, /* Out */ NewOrientation, /* Out */ NewLocation))
						{
							// OK, we have up to date positional data!
							State.Orientation = NewOrientation;
							State.Location = NewLocation;

							UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: HandPOSE[%d]: Pos %.3f %.3f %.3f"), HandIndex, NewLocation.X, NewLocation.Y, NewLocation.Y);
							UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: HandPOSE[%d]: Yaw %.3f Pitch %.3f Roll %.3f"), HandIndex, NewOrientation.Rotator().Yaw, NewOrientation.Rotator().Pitch, NewOrientation.Rotator().Roll);
						}
						else
						{
							// HMD wasn't ready.  This can currently happen if we try to grab motion data before we've rendered at least one frame
							UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: PoseToOrientationAndPosition returned false"));
						}
					}
					else
					{
						// Controller isn't available right now.  Zero out input state, so that if it comes back it will send fresh event deltas
						State = FOculusTouchControllerState((EControllerHand)HandIndex);
						UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT("SendControllerEvents: Controller for the hand %d is not tracked"), int(HandIndex));
					}
				}
			}
		}
	}
	UE_CLOG(OVR_DEBUG_LOGGING, LogOcInput, Log, TEXT(""));
}
// Read motion data from Axis Neuron
// Deprecated
bool UPerceptionNeuronBPLibrary::NeuronReadMotion(APerceptionNeuronController *Controller, FVector& Translation, FRotator& Rotation, FVector AdditionalTranslation, FRotator AdditionalRotation, int32 BoneIndex, ENeuronSkeletonEnum SkeletonType)
{
	if (Controller == nullptr)
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Controller is invalid.")));
		}
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		Translation.X = Translation.Y = Translation.Z = 0;
		return false;
	}
	else if ((Controller->bConnected == false) && (Controller->bPlay == false))
	{
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		Translation.X = Translation.Y = Translation.Z = 0;
		return false;
	}
	else if (BoneIndex >= Controller->Skeleton.BoneNr)
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Boneindex %d exceeds maximum available bones %d."), BoneIndex, Controller->Skeleton.BoneNr));
		}
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		Translation.X = Translation.Y = Translation.Z = 0;
		return false;
	}

	int32 FloatsPerBone = 6; // 3 for x,y,z translation and 3 for x,y,z rotation
	if (Controller->bDisplacement == false)
	{
		FloatsPerBone = 3;	// If there is no displacement (translation) info we have only 3 floats for rotation left
	}

	if ((BoneIndex * FloatsPerBone) > Controller->FloatCount)
	{
		Rotation.Yaw = Rotation.Pitch = Rotation.Roll = 0;
		Translation.X = Translation.Y = Translation.Z = 0;
		return false;
	}


	//
	// Translation
	//

	if (Controller->bDisplacement == true)
	{
		// Read translation values and remove BVH reference position
		float X = Controller->MotionLine[(BoneIndex * FloatsPerBone) + Controller->Skeleton.Bones[BoneIndex].XPos] - Controller->Skeleton.Bones[BoneIndex].Offset[0];
		float Y = Controller->MotionLine[(BoneIndex * FloatsPerBone) + Controller->Skeleton.Bones[BoneIndex].YPos] - Controller->Skeleton.Bones[BoneIndex].Offset[1];
		float Z = Controller->MotionLine[(BoneIndex * FloatsPerBone) + Controller->Skeleton.Bones[BoneIndex].ZPos] - Controller->Skeleton.Bones[BoneIndex].Offset[2];

		// Map BVH right hand system to local bone coordinate system
		switch (SkeletonType)
		{
		case ENeuronSkeletonEnum::VE_Neuron:  // Neuron BVH skeleton
		{
			if (BoneIndex == 0)
			{	// Hips
				Translation = FVector(X, -Y, Z);
			}
			else if ((BoneIndex >= 1) && (BoneIndex <= 6))
			{	// Legs
				Translation = FVector(X, Y, -Z);
			}
			else if ((BoneIndex >= 7) && (BoneIndex <= 12))
			{	// Spine,...
				Translation = FVector(X, -Y, -Z);
			}
			else if ((BoneIndex >= 13) && (BoneIndex <= 35))
			{	// Right arm
				Translation = FVector(-Z, X, Y);
			}
			else if ((BoneIndex >= 36) && (BoneIndex <= 58))
			{	// Left arm
				Translation = FVector(Z, -X, Y);
			}
			break;
		}
		case ENeuronSkeletonEnum::VE_TPP_Hero:	// Hero_TPP, Old blue Unreal default skeleton with T-Pose
		case ENeuronSkeletonEnum::VE_Mannequin: // Mannequin, New Unreal default skeleton with A-Pose
		{
			if (BoneIndex == 0)
			{	// Hips
				Translation = FVector(Y, Z, -X);
			}
			// Ignore other bones
			break;
		}
		case ENeuronSkeletonEnum::VE_Map: // Map to configured bone map
		{
			// Map translation with configured Bonemap
			float Map[3] = { X, Y, Z };

			Translation = FVector(Map[Controller->Bonemap[BoneIndex].XYZ[0]] * Controller->Bonemap[BoneIndex].Sign[0],
				Map[Controller->Bonemap[BoneIndex].XYZ[1]] * Controller->Bonemap[BoneIndex].Sign[1],
				Map[Controller->Bonemap[BoneIndex].XYZ[2]] * Controller->Bonemap[BoneIndex].Sign[2]);
			break;
		}
		case ENeuronSkeletonEnum::VE_UE4: // Map to UE4 world coordinate system
		{
			Translation = FVector(X, Z, Y);
			break;
		}
		case ENeuronSkeletonEnum::VE_None: // Map to nothing, use BVH translation as it is
		default:
		{
			Translation = FVector(X, Y, Z);
			break;
		}
		}
	}
	else
	{
		Translation.X = Translation.Y = Translation.Z = 0;
	}

	// Add additional translation
	Translation.X += AdditionalTranslation.X;
	Translation.Y += AdditionalTranslation.Y;
	Translation.Z += AdditionalTranslation.Z;



	//
	// Rotation 
	//

	// Read rotation values and map to pitch, yaw, roll (y, z, x)
	float XR = Controller->MotionLine[(BoneIndex * FloatsPerBone) + Controller->Skeleton.Bones[BoneIndex].XRot] * PI / 180.f;
	float YR = Controller->MotionLine[(BoneIndex * FloatsPerBone) + Controller->Skeleton.Bones[BoneIndex].YRot] * PI / 180.f;
	float ZR = Controller->MotionLine[(BoneIndex * FloatsPerBone) + Controller->Skeleton.Bones[BoneIndex].ZRot] * PI / 180.f;

	// Calculate Rotation Matrix and map to Quaternion
	FQuat Quat = CalculateQuat(XR, YR, ZR, Controller->Skeleton.Bones[BoneIndex].RotOrder);

	// Map BVH coordinate system to each bone coordinate system dependend on skeleton type
	switch (SkeletonType)
	{
	case ENeuronSkeletonEnum::VE_Neuron:  // Neuron BVH skeleton
	{
		if ((BoneIndex >= 1) && (BoneIndex <= 6))
		{	// Legs
			Quat.Z *= -1.f;
		}
		else if ((BoneIndex >= 13) && (BoneIndex <= 35))
		{	// Right Arm
			float X = Quat.X;
			float Y = Quat.Y;
			float Z = Quat.Z;
			Quat.X = -Z;
			Quat.Y = X;
			Quat.Z = Y;
		}
		else if ((BoneIndex >= 36) && (BoneIndex <= 58))
		{	// Left Arm
			float X = Quat.X;
			float Y = Quat.Y;
			float Z = Quat.Z;
			Quat.X = Z;
			Quat.Y = -X;
			Quat.Z = Y;
		}
		else
		{
			Quat.Y *= -1.f;
		}
		break;
	}
	case ENeuronSkeletonEnum::VE_TPP_Hero:	// Hero_TPP, Old blue Unreal default skeleton with T-Pose
	case ENeuronSkeletonEnum::VE_Mannequin: // Mannequin, New Unreal default skeleton with A-Pose
	{
		if ((BoneIndex >= 1) && (BoneIndex <= 3))
		{	// Right Leg
			float X = Quat.X;
			float Y = Quat.Y;
			float Z = Quat.Z;
			Quat.X = -Y;
			Quat.Y = -Z;
			Quat.Z = -X;
		}
		else if (BoneIndex == 16)
		{	// Right Hand
			Quat.Y *= -1.f;
		}
		else if ((BoneIndex >= 13) && (BoneIndex <= 19))
		{	// Right Arm and Thumb
			float Y = Quat.Y;
			float Z = Quat.Z;
			Quat.Y = -Z;
			Quat.Z = -Y;
		}
		else if ((BoneIndex >= 20) && (BoneIndex <= 35))
		{	// Right Finger
			Quat.Y *= -1.f;
		}
		else if (BoneIndex == 39)
		{	// Left Hand
			Quat.Z *= -1.f;
		}
		else if ((BoneIndex >= 36) && (BoneIndex <= 42))
		{	// Left Arm and Thumb
			float Y = Quat.Y;
			float Z = Quat.Z;
			Quat.Y = Z;
			Quat.Z = Y;
		}
		else if ((BoneIndex >= 43) && (BoneIndex <= 58))
		{	// Left Finger
			Quat.Z *= -1.f;
		}
		else
		{	// Left Leg, Hips, Spine, Neck, Head
			float X = Quat.X;
			float Y = Quat.Y;
			float Z = Quat.Z;
			Quat.X = Y;
			Quat.Y = Z;
			Quat.Z = -X;
		}
		break;
	}
	case ENeuronSkeletonEnum::VE_Map: // Map to configured bone map
	{
		// Map Quat.X/Y/Z with configured Bonemap				
		float Map[3] = { Quat.X, Quat.Y, Quat.Z };

		Quat.X = Map[Controller->Bonemap[BoneIndex].XYZ[0]] * Controller->Bonemap[BoneIndex].Sign[0];
		Quat.Y = Map[Controller->Bonemap[BoneIndex].XYZ[1]] * Controller->Bonemap[BoneIndex].Sign[1];
		Quat.Z = Map[Controller->Bonemap[BoneIndex].XYZ[2]] * Controller->Bonemap[BoneIndex].Sign[2];
		break;
	}
	case ENeuronSkeletonEnum::VE_UE4: // Map to UE4 world coordinate system
	{
		float Y = Quat.Y;
		float Z = Quat.Z;
		Quat.Y = Z;
		Quat.Z = Y;
		break;
	}
	case ENeuronSkeletonEnum::VE_None: // Map to nothing, use BVH rotation as it is
	default:
	{
		// Nothing to do, Quaternion is already BVH
		break;
	}
	}

	// Convert to Rotator
	Rotation = Quat.Rotator();

	// Add additional rotation
	Rotation.Yaw += AdditionalRotation.Yaw;
	Rotation.Pitch += AdditionalRotation.Pitch;
	Rotation.Roll += AdditionalRotation.Roll;
	Rotation.Normalize();

	return true;
}
Beispiel #20
-1
bool VRPNTrackerInputDevice::GetControllerOrientationAndPosition(const int32 ControllerIndex, const EControllerHand DeviceHand, FRotator& OutOrientation, FVector& OutPosition) const
{
	for(auto &InputPair : TrackerMap)
	{
		const TrackerInput &Tracker = InputPair.Value;
		if(Tracker.PlayerIndex == ControllerIndex && Tracker.Hand == DeviceHand)
		{
			if(InputDevice)
			{
				FScopeLock ScopeLock(&CritSect);
				InputDevice->mainloop();
			}

			FVector NewPosition;
			FQuat NewRotation;
			TransformCoordinates(Tracker, NewPosition, NewRotation);

			OutOrientation = NewRotation.Rotator();
			OutPosition = NewPosition;
			return true;
		}
	}

	return false;
}