/** * @file * * @author Mamadou Babaei * * @section LICENSE * * (The MIT License) * * Copyright (c) 2020 - 2022 SenseGlove * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * @section DESCRIPTION * * */ #include "SGCoreImpl/SGVect3DImpl.h" #include "Containers/StringConv.h" #include "Runtime/Launch/Resources/Version.h" #include "SGBuildHacks/SGInclude_Core_Vect3D.h" struct FSGVect3DImpl::FImpl { /************************ * Member variables ************************/ FVect3DType Vect3D; /************************ * Owner object ************************/ FSGVect3DImpl* Owner; /************************ * Constructor / Destructor ************************/ explicit FImpl(FSGVect3DImpl* InOwner); ~FImpl(); /************************ * Default copy constructor & copy assignment operator ************************/ FImpl(const FImpl& Rhs) = default; FImpl& operator=(const FImpl& Rhs) = default; }; const FSGVect3DImpl& FSGVect3DImpl::Zero() { static const FSGVect3DImpl Z(FVect3DType::Zero()); return Z; } bool FSGVect3DImpl::Deserialize(const FString& String, FSGVect3DImpl& OutResult, const ANSICHAR Delimiter) { FVect3DType Vect3D; const bool bReturn = FVect3DType::Deserialize(TCHAR_TO_UTF8(*String), Vect3D, Delimiter); OutResult = FSGVect3DImpl(Vect3D); return bReturn; } FSGVect3DImpl::FSGVect3DImpl() : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { } FSGVect3DImpl::FSGVect3DImpl(const float X, const float Y, const float Z) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { Pimpl->Vect3D = FVect3DType(X, Y, Z); } FSGVect3DImpl::FSGVect3DImpl(const FVect3DType& Vect3D) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { Pimpl->Vect3D = Vect3D; } FSGVect3DImpl::FSGVect3DImpl(const FVector& Vector) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { /// NOTE /// Unreal Engine uses a left-handed, z-up world coordinate system, which yealds clockwise rotations: /// Forward X /// Right Y /// Up Z /// SenseGlove uses a right-handed, z-up corrdinate systenm, which yealds counter-clockwise rotations: /// Forward X /// Right Y /// Up Z FVect3DType Vect3D(Vector.X, -Vector.Y, Vector.Z); /// NOTE /// Unreal Engine uses the Metric System and centimeters as its default unit for measuring distance/length; /// while SenseGlove uses millimeters. Vect3D.Scale(10.0f); Pimpl->Vect3D = MoveTemp(Vect3D); } FSGVect3DImpl::FSGVect3DImpl(const FSGVect3DImpl& Rhs) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{*Rhs.Pimpl}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{*Rhs.Pimpl})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { Pimpl->Owner = this; } FSGVect3DImpl::FSGVect3DImpl(FSGVect3DImpl&& Rhs) noexcept = default; FSGVect3DImpl::~FSGVect3DImpl() = default; FSGVect3DImpl& FSGVect3DImpl::operator=(const FSGVect3DImpl& Rhs) { *Pimpl = *Rhs.Pimpl; Pimpl->Owner = this; return *this; } FSGVect3DImpl& FSGVect3DImpl::operator=(FSGVect3DImpl&& Rhs) noexcept = default; const FSGVect3DImpl::FVect3DType& FSGVect3DImpl::ToVect3D() const { return Pimpl->Vect3D; } FVector FSGVect3DImpl::ToFVector() const { /// NOTE /// Unreal Engine uses a left-handed, z-up world coordinate system, which yealds clockwise rotations: /// Forward X /// Right Y /// Up Z /// SenseGlove uses a right-handed, z-up corrdinate systenm, which yealds counter-clockwise rotations: /// Forward X /// Right Y /// Up Z FVector Vector(Pimpl->Vect3D.GetX(), -Pimpl->Vect3D.GetY(), Pimpl->Vect3D.GetZ()); /// NOTE /// Unreal Engine uses the Metric System and centimeters as its default unit for measuring distance/length; /// while SenseGlove uses millimeters. Vector *= 0.1f; return MoveTemp(Vector); } FSGVect3DImpl FSGVect3DImpl::operator+(const FSGVect3DImpl& Vect3DImpl) const { return FSGVect3DImpl(Pimpl->Vect3D.operator+(Vect3DImpl.ToVect3D())); } FSGVect3DImpl FSGVect3DImpl::operator-(const FSGVect3DImpl& Vect3DImpl) const { return FSGVect3DImpl(Pimpl->Vect3D.operator-(Vect3DImpl.ToVect3D())); } FSGVect3DImpl FSGVect3DImpl::operator*(const float& ScaleFactor) const { return FSGVect3DImpl(Pimpl->Vect3D.operator*(ScaleFactor)); } float FSGVect3DImpl::GetX() const { return Pimpl->Vect3D.GetX(); } void FSGVect3DImpl::SetX(const float X) { Pimpl->Vect3D.SetX(X); } float FSGVect3DImpl::GetY() const { return Pimpl->Vect3D.GetY(); } void FSGVect3DImpl::SetY(const float Y) { Pimpl->Vect3D.SetY(Y); } float FSGVect3DImpl::GetZ() const { return Pimpl->Vect3D.GetZ(); } void FSGVect3DImpl::SetZ(const float Z) { Pimpl->Vect3D.SetZ(Z); } float FSGVect3DImpl::Magnitude() const { return Pimpl->Vect3D.Magnitude(); } void FSGVect3DImpl::Normalize() { Pimpl->Vect3D.Normalize(); } void FSGVect3DImpl::Scale(const float Factor) { Pimpl->Vect3D.Scale(Factor); } float FSGVect3DImpl::DistTo(const FSGVect3DImpl& Vect3DImpl) const { return Pimpl->Vect3D.DistTo(Vect3DImpl.ToVect3D()); } bool FSGVect3DImpl::Equals(const FSGVect3DImpl& Vect3DImpl) const { return Pimpl->Vect3D.Equals(Vect3DImpl.ToVect3D()); } FString FSGVect3DImpl::ToString() const { return UTF8_TO_TCHAR(Pimpl->Vect3D.ToString().c_str()); } FString FSGVect3DImpl::Serialize(const ANSICHAR Delimiter) const { return UTF8_TO_TCHAR(Pimpl->Vect3D.Serialize(Delimiter).c_str()); } FSGVect3DImpl::FImpl::FImpl(FSGVect3DImpl* InOwner) : Owner(InOwner) { } FSGVect3DImpl::FImpl::~FImpl() = default; void FSGVect3DImpl::FImplDeleter::operator()(const FSGVect3DImpl::FImpl* P) const { delete P; }