← Back to file list Raw

src/CPhysicalEntity.cpp

#include "CPhysicalEntity.h"
#include "CEngine.h"
#include "CGame.h"
#include "CResourcesManager.h"
#include "CTransformable.h"
void CPhysicalEntity::V_Init()
{
if(!WorldUnit)
{
auto opt_worldId = GetEntity()->GetInitParam<int>("phys_worldid");
auto opt_collision = GetEntity()->GetInitParam<std::string>("phys_collision");
auto opt_type = GetEntity()->GetInitParam<std::string>("phys_type");
if(!opt_worldId.has_value() || !opt_collision.has_value() || !opt_type.has_value()) { return; }
auto opt_mass = GetEntity()->GetInitParam<float>("phys_mass");
CTransform start_transform;
float mass = 100.0f;
if(opt_mass.has_value()) { mass = opt_mass.value(); }
auto opt_start_position = GetEntity()->GetInitParam<glm::vec3>("phys_position");
auto opt_start_quat = GetEntity()->GetInitParam<glm::quat>("phys_rotation");
auto opt_start_euler = GetEntity()->GetInitParam<CAngles>("phys_euler");
if(opt_start_position.has_value())
{
start_transform.SetPosition(opt_start_position.value());
}
else
{
start_transform.SetPosition(glm::vec3(0, 0, 0));
}
if(opt_start_quat.has_value())
{
start_transform.SetRotation(opt_start_quat.value());
}
if(opt_start_euler.has_value())
{
start_transform.GetEulerRotation().SetRotation(opt_start_euler.value());
}
if(!opt_start_quat.has_value() && !opt_start_euler.has_value())
{
start_transform.SetRotation(glm::identity<glm::quat>());
}
start_transform.SetScale(glm::vec3(1, 1, 1));
auto game = CEngine::GetInstance()->Components.GetComponentTyped<CGame>();
auto resman = CEngine::GetInstance()->Components.GetComponentTyped<CResourcesManager>();
auto world = game->PhysicsEngine->GetWorld(opt_worldId.value());
if(!world)
{
Log::ErrInstance() << "No world for physical entity\n";
return;
}
auto _col = resman->GetOrCreate("collision", opt_collision.value());
if(!_col)
{
Log::ErrInstance() << "No collision for physical entity\n";
return;
}
_col->Wait();
auto col = std::dynamic_pointer_cast<CCollision>(_col);
if(!_col)
{
Log::ErrInstance() << "No collision for physical entity (2)\n";
return;
}
std::string type = opt_type.value();
if(type == "rigid")
{
WorldUnit = world->CreateRigidBody(col, start_transform, mass); //TODO remove on destructor
}
else if(type == "kinematic")
{
WorldUnit = world->CreateKinematicBody(col, start_transform); //TODO remove on destructor
}
else if(type == "ghost")
{
WorldUnit = world->CreateGhostBody(col, start_transform); //TODO remove on destructor
}
else
{
Log::ErrInstance() << "Unknown physical type\n";
}
Log::Instance() << "Created local physical with mass of " << mass << Log::Endl;
}
WorldUnit->GetTransformCallback() += [this](CTransformBase::CMeasurePack oldpack, CTransformBase* _this) -> void
{
auto transformable = GetEntity()->Components.GetComponentTyped<CTransformable>();
if(transformable && WorldUnit->IsUpdatingInternalTransform())
{
transformable->Transform.SetPRS(_this->GetPRS());
}
};
auto entity = GetEntity();
auto transformable = entity->Components.GetComponentTyped<CTransformable>();
if(!transformable)
{
entity->Components.CreateComponent<CTransformable>();
transformable = entity->Components.GetComponentTyped<CTransformable>();
}
transformable->Transform.OnTransformChanged += [this](CTransformBase::CMeasurePack oldpack, CTransformBase* _this) -> void
{
auto transformable = GetEntity()->Components.GetComponentTyped<CTransformable>();
if(transformable && !WorldUnit->IsUpdatingInternalTransform())
{
WorldUnit->SetTransform(transformable->Transform);
auto rigidBody = dynamic_cast<CRigidBody*>(WorldUnit);
if(rigidBody)
{
rigidBody->Activate();
}
}
};
}
#pragma pack(push, 1)
struct PhysicalFlags
{
unsigned int Type : 2;
unsigned int __unused : 6;
};
#pragma pack(pop)
void CPhysicalEntity::FullPack(CBufferWrapper& packet)
{
auto colName = WorldUnit->GetCollision()->Name;
auto rigid = dynamic_cast<CRigidBody*>(WorldUnit);
float mass = 0.0f;
if(rigid)
{
mass = rigid->GetMass();
}
auto trans = WorldUnit->GetTransform();
auto rigidBody = dynamic_cast<CRigidBody*>(WorldUnit);
auto kinematicBody = dynamic_cast<CKinematicBody*>(WorldUnit);
auto ghostBody = dynamic_cast<CGhostBody*>(WorldUnit);
PhysicalFlags flags;
if(rigidBody) { flags.Type = 0; }
else if(kinematicBody) { flags.Type = 1; }
else if(ghostBody) { flags.Type = 2; }
Log::Instance() << "Write Physical Flag: " << flags.Type << Log::Endl;
packet.WriteLenString<std::uint8_t, std::string>(colName);
packet.Write<float>(mass);
packet.Write<PhysicalFlags>(flags);
packet.Write<glm::vec3>(trans.GetPosition());
packet.Write<glm::quat>(trans.GetRotation());
}
void CPhysicalEntity::FullUnpack(CBufferWrapper& packet)
{
auto colName = packet.ReadLenString<std::uint8_t, std::string>();
auto mass = packet.Read<float>();
auto flags = packet.Read<PhysicalFlags>();
auto pos = packet.Read<glm::vec3>();
auto rot = packet.Read<glm::quat>();
auto game = CEngine::GetInstance()->Components.GetComponentTyped<CGame>();
auto resman = CEngine::GetInstance()->Components.GetComponentTyped<CResourcesManager>();
auto world = game->PhysicsEngine->GetWorld(0); //TODO not zero
CTransform start_transform;
start_transform.SetPRS
(
{
pos,
rot,
glm::vec3(1, 1, 1)
}
);
if(!world)
{
Log::ErrInstance() << "No world for physical entity\n";
return;
}
auto _col = resman->GetOrCreate("collision", colName + ".ecol");
if(!_col)
{
Log::ErrInstance() << "No collision for physical entity\n";
return;
}
auto col = std::dynamic_pointer_cast<CCollision>(_col);
//col->Wait();
if(!col)
{
Log::ErrInstance() << "No collision for physical entity (2)\n";
return;
}
Log::Instance() << "Read Physical Flag: " << flags.Type << Log::Endl;
if(flags.Type == 0)
{
WorldUnit = world->CreateRigidBody(col, start_transform, mass); //TODO remove on destructor
}
else if(flags.Type == 1)
{
WorldUnit = world->CreateKinematicBody(col, start_transform); //TODO remove on destructor
}
else if(flags.Type == 2)
{
WorldUnit = world->CreateGhostBody(col, start_transform); //TODO remove on destructor
}
else
{
Log::ErrInstance() << "Unknown physical type\n";
}
//WorldUnit = world->CreateRigidBody(col, start_transform, mass); //TODO remove on destructor
}
LINK_SOL_USERTYPE(CPhysicalEntity);
LINK_ENTITY_COMPONENT_TO_CLASS(CPhysicalEntity, physical);