chore: Physics Component abstraction and addition of tests (#1159)

* Make serialize actually virtual

yep

* Abstract to PhysicsComponent

Move shared functionality of all physics related classes to a base class.

Tested that there were no failed to unserialize errors when in main gameplay in Gnarled Forest or in a race.

Tested that 2 players were able to see each other in the above scenarios just fine as well.

* Update PhantomPhysicsComponent.cpp

* Add SimplePhysicsTest

* Add construction test

* Update SimplePhysicsComponentTests.cpp

* remove flags and fix override

* Update VendorComponent.h
This commit is contained in:
David Markowitz 2023-10-09 13:19:38 -07:00 committed by GitHub
parent d8ac148cee
commit ad003634f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 242 additions and 279 deletions

View File

@ -18,6 +18,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"MovingPlatformComponent.cpp"
"PetComponent.cpp"
"PhantomPhysicsComponent.cpp"
"PhysicsComponent.cpp"
"PlayerForcedMovementComponent.cpp"
"PossessableComponent.cpp"
"PossessorComponent.cpp"

View File

@ -15,15 +15,12 @@
#include "LevelProgressionComponent.h"
#include "eStateChangeType.h"
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Component(entity) {
m_Position = {};
m_Rotation = NiQuaternion::IDENTITY;
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : PhysicsComponent(entity) {
m_Velocity = {};
m_AngularVelocity = {};
m_InJetpackMode = false;
m_IsOnGround = true;
m_IsOnRail = false;
m_DirtyPosition = true;
m_DirtyVelocity = true;
m_DirtyAngularVelocity = true;
m_dpEntity = nullptr;
@ -202,26 +199,14 @@ void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
}
void ControllablePhysicsComponent::SetPosition(const NiPoint3& pos) {
if (m_Static) {
return;
}
m_Position.x = pos.x;
m_Position.y = pos.y;
m_Position.z = pos.z;
m_DirtyPosition = true;
if (m_Static) return;
PhysicsComponent::SetPosition(pos);
if (m_dpEntity) m_dpEntity->SetPosition(pos);
}
void ControllablePhysicsComponent::SetRotation(const NiQuaternion& rot) {
if (m_Static) {
return;
}
m_Rotation = rot;
m_DirtyPosition = true;
if (m_Static) return;
PhysicsComponent::SetRotation(rot);
if (m_dpEntity) m_dpEntity->SetRotation(rot);
}

View File

@ -6,7 +6,7 @@
#include "NiPoint3.h"
#include "NiQuaternion.h"
#include "tinyxml2.h"
#include "Component.h"
#include "PhysicsComponent.h"
#include "dpCollisionChecks.h"
#include "PhantomPhysicsComponent.h"
#include "eBubbleType.h"
@ -19,7 +19,7 @@ enum class eStateChangeType : uint32_t;
/**
* Handles the movement of controllable Entities, e.g. enemies and players
*/
class ControllablePhysicsComponent : public Component {
class ControllablePhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
@ -36,26 +36,14 @@ public:
* If the entity is static, this is a no-op.
* @param pos The position to set
*/
void SetPosition(const NiPoint3& pos);
/**
* Returns the current position of the entity
* @return The current position of the entity
*/
const NiPoint3& GetPosition() const { return m_Position; }
void SetPosition(const NiPoint3& pos) override;
/**
* Sets the rotation of this entity, ensures this change is serialized next tick. If the entity is static, this is
* a no-op.
* @param rot the rotation to set
*/
void SetRotation(const NiQuaternion& rot);
/**
* Returns the current rotation of this entity
* @return the current rotation of this entity
*/
const NiQuaternion& GetRotation() const { return m_Rotation; }
void SetRotation(const NiQuaternion& rot) override;
/**
* Sets the current velocity of this entity, ensures that this change is serialized next tick. If the entity is
@ -322,21 +310,6 @@ private:
*/
dpEntity* m_dpEntity;
/**
* Whether or not the position is dirty, forcing a serialization update of the position
*/
bool m_DirtyPosition;
/**
* The current position of the entity
*/
NiPoint3 m_Position;
/**
* The current rotation of the entity
*/
NiQuaternion m_Rotation;
/**
* Whether or not the velocity is dirty, forcing a serialization of the velocity
*/

View File

@ -27,14 +27,13 @@
#include "dpShapeBox.h"
#include "dpShapeSphere.h"
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : Component(parent) {
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
m_Scale = m_Parent->GetDefaultScale();
m_dpEntity = nullptr;
m_EffectInfoDirty = false;
m_PositionInfoDirty = false;
m_IsPhysicsEffectActive = false;
m_EffectType = ePhysicsEffectType::PUSH;
@ -307,18 +306,7 @@ void PhantomPhysicsComponent::CreatePhysics() {
}
void PhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
outBitStream->Write(m_PositionInfoDirty || bIsInitialUpdate);
if (m_PositionInfoDirty || bIsInitialUpdate) {
outBitStream->Write(m_Position.x);
outBitStream->Write(m_Position.y);
outBitStream->Write(m_Position.z);
outBitStream->Write(m_Rotation.x);
outBitStream->Write(m_Rotation.y);
outBitStream->Write(m_Rotation.z);
outBitStream->Write(m_Rotation.w);
m_PositionInfoDirty = false;
}
PhysicsComponent::Serialize(outBitStream, bIsInitialUpdate);
outBitStream->Write(m_EffectInfoDirty || bIsInitialUpdate);
if (m_EffectInfoDirty || bIsInitialUpdate) {
@ -426,13 +414,11 @@ void PhantomPhysicsComponent::SetMax(uint32_t max) {
}
void PhantomPhysicsComponent::SetPosition(const NiPoint3& pos) {
m_Position = pos;
PhysicsComponent::SetPosition(pos);
if (m_dpEntity) m_dpEntity->SetPosition(pos);
}
void PhantomPhysicsComponent::SetRotation(const NiQuaternion& rot) {
m_Rotation = rot;
PhysicsComponent::SetRotation(rot);
if (m_dpEntity) m_dpEntity->SetRotation(rot);
}

View File

@ -11,8 +11,8 @@
#include <vector>
#include "CppScripts.h"
#include "InvalidScript.h"
#include "Component.h"
#include "eReplicaComponentType.h"
#include "PhysicsComponent.h"
class LDFBaseData;
class Entity;
@ -25,7 +25,7 @@ enum class ePhysicsEffectType : uint32_t ;
* trigger gameplay events, for example the bus in Avant Gardens that moves around when the player touches its physics
* body. Optionally this object can also have effects, like the fans in AG.
*/
class PhantomPhysicsComponent : public Component {
class PhantomPhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
@ -75,29 +75,17 @@ public:
*/
void SetPhysicsEffectActive(bool val) { m_IsPhysicsEffectActive = val; m_EffectInfoDirty = true; }
/**
* Returns the position of this physics object
* @return the position of this physics object
*/
const NiPoint3& GetPosition() const { return m_Position; }
/**
* Sets the position of this physics object
* @param pos the position to set
*/
void SetPosition(const NiPoint3& pos);
/**
* Returns the rotation of this physics object
* @return the rotation of this physics object
*/
const NiQuaternion& GetRotation() const { return m_Rotation; }
void SetPosition(const NiPoint3& pos) override;
/**
* Sets the rotation of this physics object
* @param rot the rotation to set
*/
void SetRotation(const NiQuaternion& rot);
void SetRotation(const NiQuaternion& rot) override;
/**
* Returns the effect that's currently active, defaults to 0
@ -134,27 +122,11 @@ public:
void SetMax(uint32_t max);
private:
/**
* The position of the physics object
*/
NiPoint3 m_Position;
/**
* The rotation of the physics object
*/
NiQuaternion m_Rotation;
/**
* A scale to apply to the size of the physics object
*/
float m_Scale;
/**
* Whether or not the position has changed and needs to be serialized
*/
bool m_PositionInfoDirty;
/**
* Whether or not the effect has changed and needs to be serialized
*/

View File

@ -0,0 +1,21 @@
#include "PhysicsComponent.h"
PhysicsComponent::PhysicsComponent(Entity* parent) : Component(parent) {
m_Position = NiPoint3::ZERO;
m_Rotation = NiQuaternion::IDENTITY;
m_DirtyPosition = false;
}
void PhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
outBitStream->Write(bIsInitialUpdate || m_DirtyPosition);
if (bIsInitialUpdate || m_DirtyPosition) {
outBitStream->Write(m_Position.x);
outBitStream->Write(m_Position.y);
outBitStream->Write(m_Position.z);
outBitStream->Write(m_Rotation.x);
outBitStream->Write(m_Rotation.y);
outBitStream->Write(m_Rotation.z);
outBitStream->Write(m_Rotation.w);
if (!bIsInitialUpdate) m_DirtyPosition = false;
}
}

View File

@ -0,0 +1,32 @@
#ifndef __PHYSICSCOMPONENT__H__
#define __PHYSICSCOMPONENT__H__
#include "Component.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
namespace Raknet {
class BitStream;
};
class PhysicsComponent : public Component {
public:
PhysicsComponent(Entity* parent);
virtual ~PhysicsComponent() = default;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
const NiPoint3& GetPosition() const { return m_Position; }
virtual void SetPosition(const NiPoint3& pos) { if (m_Position == pos) return; m_Position = pos; m_DirtyPosition = true; }
const NiQuaternion& GetRotation() const { return m_Rotation; }
virtual void SetRotation(const NiQuaternion& rot) { if (m_Rotation == rot) return; m_Rotation = rot; m_DirtyPosition = true; }
protected:
NiPoint3 m_Position;
NiQuaternion m_Rotation;
bool m_DirtyPosition;
};
#endif //!__PHYSICSCOMPONENT__H__

View File

@ -1,32 +1,16 @@
/*
* Darkflame Universe
* Copyright 2019
* Copyright 2023
*/
#include "RigidbodyPhantomPhysicsComponent.h"
#include "Entity.h"
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent) : Component(parent) {
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
m_IsDirty = true;
}
RigidbodyPhantomPhysicsComponent::~RigidbodyPhantomPhysicsComponent() {
}
void RigidbodyPhantomPhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
outBitStream->Write(m_IsDirty || bIsInitialUpdate);
if (m_IsDirty || bIsInitialUpdate) {
outBitStream->Write(m_Position.x);
outBitStream->Write(m_Position.y);
outBitStream->Write(m_Position.z);
outBitStream->Write(m_Rotation.x);
outBitStream->Write(m_Rotation.y);
outBitStream->Write(m_Rotation.z);
outBitStream->Write(m_Rotation.w);
m_IsDirty = false;
}
PhysicsComponent::Serialize(outBitStream, bIsInitialUpdate);
}

View File

@ -1,71 +1,29 @@
/*
* Darkflame Universe
* Copyright 2019
* Copyright 2023
*/
#ifndef RIGIDBODYPHANTOMPHYSICS_H
#define RIGIDBODYPHANTOMPHYSICS_H
#ifndef __RIGIDBODYPHANTOMPHYSICS_H__
#define __RIGIDBODYPHANTOMPHYSICS_H__
#include "BitStream.h"
#include "dCommonVars.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
#include "Component.h"
#include "PhysicsComponent.h"
#include "eReplicaComponentType.h"
/**
* Component that handles rigid bodies that can be interacted with, mostly client-side rendered. An example is the
* bananas that fall from trees in GF.
*/
class RigidbodyPhantomPhysicsComponent : public Component {
class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
RigidbodyPhantomPhysicsComponent(Entity* parent);
~RigidbodyPhantomPhysicsComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
/**
* Returns the position of this entity
* @return the position of this entity
*/
NiPoint3& GetPosition() { return m_Position; }
/**
* Sets the position of this entity
* @param pos the position to set
*/
void SetPosition(const NiPoint3& pos) { m_Position = pos; m_IsDirty = true; }
/**
* Returns the rotation of this entity
* @return the rotation of this entity
*/
NiQuaternion& GetRotation() { return m_Rotation; }
/**
* Sets the rotation for this entity
* @param rot the rotation to tset
*/
void SetRotation(const NiQuaternion& rot) { m_Rotation = rot; m_IsDirty = true; }
private:
/**
* The position of this entity
*/
NiPoint3 m_Position;
/**
* The rotation of this entity
*/
NiQuaternion m_Rotation;
/**
* Whether or not the component should be serialized
*/
bool m_IsDirty;
};
#endif // RIGIDBODYPHANTOMPHYSICS_H
#endif // __RIGIDBODYPHANTOMPHYSICS_H__

View File

@ -13,10 +13,9 @@
#include "Entity.h"
SimplePhysicsComponent::SimplePhysicsComponent(uint32_t componentID, Entity* parent) : Component(parent) {
SimplePhysicsComponent::SimplePhysicsComponent(uint32_t componentID, Entity* parent) : PhysicsComponent(parent) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();
m_IsDirty = true;
const auto& climbable_type = m_Parent->GetVar<std::u16string>(u"climbable");
if (climbable_type == u"wall") {
@ -54,19 +53,7 @@ void SimplePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIs
} else {
outBitStream->Write0();
}
outBitStream->Write(m_IsDirty || bIsInitialUpdate);
if (m_IsDirty || bIsInitialUpdate) {
outBitStream->Write(m_Position.x);
outBitStream->Write(m_Position.y);
outBitStream->Write(m_Position.z);
outBitStream->Write(m_Rotation.x);
outBitStream->Write(m_Rotation.y);
outBitStream->Write(m_Rotation.z);
outBitStream->Write(m_Rotation.w);
m_IsDirty = false;
}
PhysicsComponent::Serialize(outBitStream, bIsInitialUpdate);
}
uint32_t SimplePhysicsComponent::GetPhysicsMotionState() const {

View File

@ -10,7 +10,7 @@
#include "RakNetTypes.h"
#include "NiPoint3.h"
#include "NiQuaternion.h"
#include "Component.h"
#include "PhysicsComponent.h"
#include "eReplicaComponentType.h"
class Entity;
@ -26,7 +26,7 @@ enum class eClimbableType : int32_t {
/**
* Component that serializes locations of entities to the client
*/
class SimplePhysicsComponent : public Component {
class SimplePhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
@ -35,30 +35,6 @@ public:
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
/**
* Returns the position of this entity
* @return the position of this entity
*/
NiPoint3& GetPosition() { return m_Position; }
/**
* Sets the position of this entity
* @param pos the position to set
*/
void SetPosition(const NiPoint3& pos) { m_Position = pos; m_IsDirty = true; }
/**
* Returns the rotation of this entity
* @return the rotation of this entity
*/
NiQuaternion& GetRotation() { return m_Rotation; }
/**
* Sets the rotation of this entity
* @param rot
*/
void SetRotation(const NiQuaternion& rot) { m_Rotation = rot; m_IsDirty = true; }
/**
* Returns the velocity of this entity
* @return the velocity of this entity
@ -108,17 +84,6 @@ public:
void SetClimbableType(const eClimbableType& value) { m_ClimbableType = value; }
private:
/**
* The current position of the entity
*/
NiPoint3 m_Position = NiPoint3::ZERO;
/**
* The current rotation of the entity
*/
NiQuaternion m_Rotation = NiQuaternion::IDENTITY;
/**
* The current velocity of the entity
*/
@ -134,11 +99,6 @@ private:
*/
bool m_DirtyVelocity = true;
/**
* Whether or not the position has changed
*/
bool m_IsDirty = true;
/**
* The current physics motion state
*/

View File

@ -1,9 +1,7 @@
#include "VehiclePhysicsComponent.h"
#include "EntityManager.h"
VehiclePhysicsComponent::VehiclePhysicsComponent(Entity* parent) : Component(parent) {
m_Position = NiPoint3::ZERO;
m_Rotation = NiQuaternion::IDENTITY;
VehiclePhysicsComponent::VehiclePhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
m_Velocity = NiPoint3::ZERO;
m_AngularVelocity = NiPoint3::ZERO;
m_IsOnGround = true;
@ -14,22 +12,6 @@ VehiclePhysicsComponent::VehiclePhysicsComponent(Entity* parent) : Component(par
m_EndBehavior = GeneralUtils::GenerateRandomNumber<uint32_t>(0, 7);
}
VehiclePhysicsComponent::~VehiclePhysicsComponent() {
}
void VehiclePhysicsComponent::SetPosition(const NiPoint3& pos) {
if (pos == m_Position) return;
m_DirtyPosition = true;
m_Position = pos;
}
void VehiclePhysicsComponent::SetRotation(const NiQuaternion& rot) {
if (rot == m_Rotation) return;
m_DirtyPosition = true;
m_Rotation = rot;
}
void VehiclePhysicsComponent::SetVelocity(const NiPoint3& vel) {
if (vel == m_Velocity) return;
m_DirtyPosition = true;
@ -60,10 +42,6 @@ void VehiclePhysicsComponent::SetRemoteInputInfo(const RemoteInputInfo& remoteIn
m_DirtyRemoteInput = true;
}
void VehiclePhysicsComponent::SetDirtyPosition(bool val) {
m_DirtyPosition = val;
}
void VehiclePhysicsComponent::SetDirtyVelocity(bool val) {
m_DirtyVelocity = val;
}

View File

@ -2,7 +2,7 @@
#include "BitStream.h"
#include "Entity.h"
#include "Component.h"
#include "PhysicsComponent.h"
#include "eReplicaComponentType.h"
struct RemoteInputInfo {
@ -26,41 +26,16 @@ struct RemoteInputInfo {
/**
* Physics component for vehicles.
*/
class VehiclePhysicsComponent : public Component {
class VehiclePhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::VEHICLE_PHYSICS;
VehiclePhysicsComponent(Entity* parentEntity);
~VehiclePhysicsComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
void Update(float deltaTime) override;
/**
* Sets the position
* @param pos the new position
*/
void SetPosition(const NiPoint3& pos);
/**
* Gets the position
* @return the position
*/
const NiPoint3& GetPosition() const { return m_Position; }
/**
* Sets the rotation
* @param rot the new rotation
*/
void SetRotation(const NiQuaternion& rot);
/**
* Gets the rotation
* @return the rotation
*/
const NiQuaternion& GetRotation() const { return m_Rotation; }
/**
* Sets the velocity
* @param vel the new velocity
@ -115,10 +90,6 @@ public:
void SetRemoteInputInfo(const RemoteInputInfo&);
private:
bool m_DirtyPosition;
NiPoint3 m_Position;
NiQuaternion m_Rotation;
bool m_DirtyVelocity;
NiPoint3 m_Velocity;

View File

@ -1,5 +1,6 @@
set(DCOMPONENTS_TESTS
"DestroyableComponentTests.cpp"
"SimplePhysicsComponentTests.cpp"
)
# Get the folder name and prepend it to the files above

View File

@ -0,0 +1,154 @@
#include "GameDependencies.h"
#include <gtest/gtest.h>
#include "BitStream.h"
#include "SimplePhysicsComponent.h"
#include "Entity.h"
#include "eReplicaComponentType.h"
#include "eStateChangeType.h"
class SimplePhysicsTest : public GameDependenciesTest {
protected:
std::unique_ptr<Entity> baseEntity;
SimplePhysicsComponent* simplePhysicsComponent;
CBITSTREAM;
void SetUp() override {
SetUpDependencies();
baseEntity = std::make_unique<Entity>(15, GameDependenciesTest::info);
simplePhysicsComponent = new SimplePhysicsComponent(1, baseEntity.get());
baseEntity->AddComponent(SimplePhysicsComponent::ComponentType, simplePhysicsComponent);
simplePhysicsComponent->SetClimbableType(eClimbableType::CLIMBABLE_TYPE_WALL);
simplePhysicsComponent->SetPosition(NiPoint3(1.0f, 2.0f, 3.0f));
simplePhysicsComponent->SetRotation(NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
simplePhysicsComponent->SetVelocity(NiPoint3(5.0f, 6.0f, 7.0f));
simplePhysicsComponent->SetAngularVelocity(NiPoint3(5.0f, 6.0f, 7.0f));
simplePhysicsComponent->SetPhysicsMotionState(2);
}
void TearDown() override {
TearDownDependencies();
}
};
TEST_F(SimplePhysicsTest, SimplePhysicsSerializeTest) {
simplePhysicsComponent->Serialize(&bitStream, false);
constexpr uint32_t sizeOfStream = 3 + BYTES_TO_BITS(3 * sizeof(NiPoint3)) + BYTES_TO_BITS(1 * sizeof(NiQuaternion)) + 1 * BYTES_TO_BITS(sizeof(uint32_t));
ASSERT_EQ(bitStream.GetNumberOfBitsUsed(), sizeOfStream);
bool dirtyVelocityFlag;
bitStream.Read(dirtyVelocityFlag);
ASSERT_EQ(dirtyVelocityFlag, true);
NiPoint3 velocity;
bitStream.Read(velocity.x);
bitStream.Read(velocity.y);
bitStream.Read(velocity.z);
ASSERT_EQ(velocity, NiPoint3(5.0f, 6.0f, 7.0f));
NiPoint3 angularVelocity;
bitStream.Read(angularVelocity.x);
bitStream.Read(angularVelocity.y);
bitStream.Read(angularVelocity.z);
ASSERT_EQ(angularVelocity, NiPoint3(5.0f, 6.0f, 7.0f));
bool dirtyPhysicsMotionStateFlag;
bitStream.Read(dirtyPhysicsMotionStateFlag);
ASSERT_EQ(dirtyPhysicsMotionStateFlag, true);
uint32_t physicsMotionState;
bitStream.Read(physicsMotionState);
ASSERT_EQ(physicsMotionState, 2.0f);
bool dirtyPositionFlag;
bitStream.Read(dirtyPositionFlag);
ASSERT_EQ(dirtyPositionFlag, true);
NiPoint3 position;
bitStream.Read(position.x);
bitStream.Read(position.y);
bitStream.Read(position.z);
ASSERT_EQ(position, NiPoint3(1.0f, 2.0f, 3.0f));
NiQuaternion rotation;
bitStream.Read(rotation.x);
bitStream.Read(rotation.y);
bitStream.Read(rotation.z);
bitStream.Read(rotation.w);
ASSERT_EQ(rotation, NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
}
TEST_F(SimplePhysicsTest, SimplePhysicsConstructionTest) {
simplePhysicsComponent->Serialize(&bitStream, true);
constexpr uint32_t sizeOfStream = 4 + BYTES_TO_BITS(1 * sizeof(int32_t)) + BYTES_TO_BITS(3 * sizeof(NiPoint3)) + BYTES_TO_BITS(1 * sizeof(NiQuaternion)) + 1 * BYTES_TO_BITS(sizeof(uint32_t));
ASSERT_EQ(bitStream.GetNumberOfBitsUsed(), sizeOfStream);
bool dirtyClimbableTypeFlag;
bitStream.Read(dirtyClimbableTypeFlag);
ASSERT_EQ(dirtyClimbableTypeFlag, true);
int32_t climbableType;
bitStream.Read(climbableType);
ASSERT_EQ(climbableType, 2);
bool dirtyVelocityFlag;
bitStream.Read(dirtyVelocityFlag);
ASSERT_EQ(dirtyVelocityFlag, true);
NiPoint3 velocity;
bitStream.Read(velocity.x);
bitStream.Read(velocity.y);
bitStream.Read(velocity.z);
ASSERT_EQ(velocity, NiPoint3(5.0f, 6.0f, 7.0f));
NiPoint3 angularVelocity;
bitStream.Read(angularVelocity.x);
bitStream.Read(angularVelocity.y);
bitStream.Read(angularVelocity.z);
ASSERT_EQ(angularVelocity, NiPoint3(5.0f, 6.0f, 7.0f));
bool dirtyPhysicsMotionStateFlag;
bitStream.Read(dirtyPhysicsMotionStateFlag);
ASSERT_EQ(dirtyPhysicsMotionStateFlag, true);
uint32_t physicsMotionState;
bitStream.Read(physicsMotionState);
ASSERT_EQ(physicsMotionState, 2.0f);
bool dirtyPositionFlag;
bitStream.Read(dirtyPositionFlag);
ASSERT_EQ(dirtyPositionFlag, true);
NiPoint3 position;
bitStream.Read(position.x);
bitStream.Read(position.y);
bitStream.Read(position.z);
ASSERT_EQ(position, NiPoint3(1.0f, 2.0f, 3.0f));
NiQuaternion rotation;
bitStream.Read(rotation.x);
bitStream.Read(rotation.y);
bitStream.Read(rotation.z);
bitStream.Read(rotation.w);
ASSERT_EQ(rotation, NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
}
TEST_F(SimplePhysicsTest, SimplePhysicsGettersAndSettersTest) {
ASSERT_EQ(simplePhysicsComponent->GetClimabbleType(), eClimbableType::CLIMBABLE_TYPE_WALL);
ASSERT_EQ(simplePhysicsComponent->GetPosition(), NiPoint3(1.0f, 2.0f, 3.0f));
ASSERT_EQ(simplePhysicsComponent->GetRotation(), NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));
ASSERT_EQ(simplePhysicsComponent->GetVelocity(), NiPoint3(5.0f, 6.0f, 7.0f));
ASSERT_EQ(simplePhysicsComponent->GetAngularVelocity(), NiPoint3(5.0f, 6.0f, 7.0f));
ASSERT_EQ(simplePhysicsComponent->GetPhysicsMotionState(), 2);
simplePhysicsComponent->SetClimbableType(eClimbableType::CLIMBABLE_TYPE_LADDER);
simplePhysicsComponent->SetPosition(NiPoint3(4.0f, 5.0f, 6.0f));
simplePhysicsComponent->SetRotation(NiQuaternion(4.0f, 5.0f, 6.0f, 7.0f));
simplePhysicsComponent->SetVelocity(NiPoint3(6.0f, 7.0f, 8.0f));
simplePhysicsComponent->SetAngularVelocity(NiPoint3(6.0f, 7.0f, 8.0f));
simplePhysicsComponent->SetPhysicsMotionState(3);
ASSERT_EQ(simplePhysicsComponent->GetClimabbleType(), eClimbableType::CLIMBABLE_TYPE_LADDER);
ASSERT_EQ(simplePhysicsComponent->GetPosition(), NiPoint3(4.0f, 5.0f, 6.0f));
ASSERT_EQ(simplePhysicsComponent->GetRotation(), NiQuaternion(4.0f, 5.0f, 6.0f, 7.0f));
ASSERT_EQ(simplePhysicsComponent->GetVelocity(), NiPoint3(6.0f, 7.0f, 8.0f));
ASSERT_EQ(simplePhysicsComponent->GetAngularVelocity(), NiPoint3(6.0f, 7.0f, 8.0f));
ASSERT_EQ(simplePhysicsComponent->GetPhysicsMotionState(), 3);
}