Files
HydraV3/HydraEngine/source/actor/HydraActorManager.cpp
T
2026-07-17 15:30:29 +01:00

526 lines
18 KiB
C++

//
#include "HydraActorManager.h"
#include "../actor/HydraActor.h"
#include "../engine/HydraEngine.h"
#include "../ecs/HydraEntityManager.h"
#include "../ecs/HydraECS.h"
#include "../ecs/components/HydraPositionComponent.h"
#include "../ecs/systems/HydraTransformSystem.h"
#include "../fileaccess/HydraGLTFLoader.h"
#include "../task/actor/HydraLoadGLTFFileTask.hpp"
#include "../scheduler/HydraTaskScheduler.h"
#include <stdio.h>
HydraActor *const HydraActorManager::GetActor(HydraID actorID)
{
if (actorID < MAX_ACTORS)
{
return m_actors[actorID];
}
return nullptr;
}
std::vector<HydraID> &HydraActorManager::GetChildren(HydraID actor_id)
{
return m_actors[actor_id]->m_children;
}
void HydraActorManager::DeleteActor(HydraID actorID)
{
m_actors_waiting_for_delete.push_back(actorID);
}
void HydraActorManager::_SetActorDeleted(HydraID actorID)
{
if (m_actors[actorID] != nullptr)
{
delete m_actors[actorID];
}
m_actors[actorID] = nullptr;
m_available_actor_ids.push_back(actorID);
}
HydraID HydraActorManager::LoadActor(std::string filename)
{
HydraID actor_id = INVALID_HYDRA_ID;
HydraTaskScheduler* task_scheduler = GetEngine()->TaskScheduler();
HydraID load_task_id = task_scheduler->CreateTask<HydraLoadGLTFFileTask>(HydraThreadAffinity::Render);
HydraLoadGLTFFileTask* load_task = static_cast<HydraLoadGLTFFileTask*>(task_scheduler->GetTask(load_task_id));
load_task->Initialise(filename, &actor_id);
task_scheduler->WaitForTask(load_task_id);
return actor_id;
}
/*
HydraID HydraActorManager::_ProcessGLTFNode(aiScene const *scene, aiNode *parent_node, std::vector<uint32_t>material_lookup)
{
HydraID parent_actor_id = CreateActor<HydraGLTFActor>();
HydraECS *ecs = GetEngine()->ECS();
HydraECSPositionComponent position_component;
aiVector3D tmp_scaling = {};
aiQuaternion tmp_rotation = {};
aiVector3D tmp_position = {};
parent_node->mTransformation.Decompose(tmp_scaling, tmp_rotation, tmp_position);
glm::dvec3 scaling = glm::dvec3(tmp_scaling.x, tmp_scaling.y, tmp_scaling.z);
glm::quat rotation = glm::quat(tmp_rotation.w, tmp_rotation.x, tmp_rotation.y, tmp_rotation.z);
glm::dvec3 position = glm::dvec3(tmp_position.x, tmp_position.y, tmp_position.z);
ecs->AddComponent<HydraECSPositionComponent>(parent_actor_id, position_component);
SetPosition(parent_actor_id, position, rotation, false);
for (uint32_t i_mesh = 0; i_mesh < parent_node->mNumMeshes; i_mesh++)
{
aiMesh *mesh = scene->mMeshes[parent_node->mMeshes[i_mesh]];
_ProcessGLTFMesh(scene, parent_actor_id, mesh, material_lookup);
}
for (uint32_t i_node = 0; i_node < parent_node->mNumChildren; i_node++)
{
HydraID child_actor_id = _ProcessGLTFNode(scene, parent_node->mChildren[i_node], material_lookup);
SetRelationship(parent_actor_id, child_actor_id);
}
return parent_actor_id;
}
void HydraActorManager::_ProcessGLTFMesh(aiScene const *scene, HydraID parent_actor_id, aiMesh *mesh, std::vector<uint32_t>material_lookup)
{
HydraID mesh_actor_id = CreateActor<HydraGLTFActor>();
aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
std::vector<StandardVertexStruct> vertexes;
HydraECS *ecs = GetEngine()->ECS();
HydraECSPositionComponent position_component = {};
ecs->AddComponent<HydraECSPositionComponent>(mesh_actor_id, position_component);
for (uint32_t i_face = 0; i_face < mesh->mNumFaces; i_face++)
{
aiFace face = mesh->mFaces[i_face];
for (uint32_t i_index = 0; i_index < face.mNumIndices; i_index++)
{
uint32_t current_idx = face.mIndices[i_index];
StandardVertexStruct vert = {};
if (mesh->HasPositions())
{
vert.vertex[0] = mesh->mVertices[current_idx].x;
vert.vertex[1] = mesh->mVertices[current_idx].y;
vert.vertex[2] = mesh->mVertices[current_idx].z;
}
if (mesh->HasNormals())
{
vert.normal[0] = mesh->mNormals[current_idx].x;
vert.normal[1] = mesh->mNormals[current_idx].y;
vert.normal[2] = mesh->mNormals[current_idx].z;
}
if (mesh->HasTextureCoords(0))
{
vert.uv[0] = mesh->mTextureCoords[0][current_idx].x;
vert.uv[1] = mesh->mTextureCoords[0][current_idx].y;
}
vert.indexes[0] = mesh_actor_id;
vertexes.push_back(vert);
}
}
HydraMeshManager *mesh_manager = GetEngine()->MeshManager();
HydraID mesh_id = mesh_manager->CreateMesh(mesh_actor_id);
mesh_manager->SetVertexes(mesh_id, vertexes);
mesh_manager->CalculateNormals(mesh_id);
HydraECSMeshComponent mesh_comp;
mesh_comp.mesh_id = mesh_id;
ecs->AddComponent<HydraECSMeshComponent>(mesh_actor_id, mesh_comp);
aiString mat_name;
mat->Get(AI_MATKEY_NAME, mat_name);
HydraID material_id = material_lookup[mesh->mMaterialIndex];
if(material_id != INVALID_HYDRA_ID)
{
HydraECSMaterialComponent mat_comp;
mat_comp.material_id = material_id;
ecs->AddComponent<HydraECSMaterialComponent>(mesh_actor_id, mat_comp);
HydraMaterialStruct const * const mat_data = GetEngine()->MaterialManager()->GetMaterial(material_id);
GetEngine()->BufferManager()->AddMaterial(mesh_actor_id, material_id, *mat_data);
}
mesh_manager->SetMeshWaiting(mesh_id);
//Add renderable component
HydraPipelineManager* pipeline_manager = GetEngine()->PipelineManager();
uint32_t pipeline_id = pipeline_manager->GetPipelineID("FORWARD");
uint32_t shadow_pipeline_id = pipeline_manager->GetPipelineID("SHADOW");
uint32_t deferred_pipeline_id = pipeline_manager->GetPipelineID("DEFERRED");
HydraECSRenderableComponent render_comp;
if(pipeline_id != INVALID_HYDRA_ID)
{
render_comp.pipelines.set(pipeline_id);
}
render_comp.pipelines.set(shadow_pipeline_id);
render_comp.pipelines.set(deferred_pipeline_id);
ecs->AddComponent<HydraECSRenderableComponent>(mesh_actor_id, render_comp);
SetRelationship(parent_actor_id, mesh_actor_id);
}
/// @brief Load all of the scene textures
/// @param scene containing scene
/// @param texture_lookup index of texture in the scene to the Hydra texture ID
void HydraActorManager::_ProcessGLTFTextures(aiScene const *scene, std::vector<uint32_t> &texture_lookup)
{
HydraTextureManager *texture_manager = GetEngine()->TextureManager();
// Make space for the texture lookups
texture_lookup.resize(scene->mNumTextures);
for (uint32_t i_tex = 0; i_tex < scene->mNumTextures; i_tex++)
{
aiTexture *tex = scene->mTextures[i_tex];
// Create a holder for the texture
HydraID texture_id = texture_manager->CreateTexture(0, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, false);
// load the texture data from the scene texture
texture_manager->FillTexture(texture_id, reinterpret_cast<unsigned char *>(tex->pcData), tex->mWidth);
// store the texture id against the scene index for the texture. Materials will have *n where n is the index
texture_lookup[i_tex] = texture_id;
texture_manager->FinaliseTexture(texture_id);
}
}
void HydraActorManager::_ProcessGLTFMaterials(aiScene const *scene,
std::vector<uint32_t>& texture_lookup,
std::vector<uint32_t>& material_lookup,
std::string filename)
{
material_lookup.resize(scene->mNumMaterials);
HydraTextureManager *texture_manager = GetEngine()->TextureManager();
for (uint32_t i_mat = 0; i_mat < scene->mNumMaterials; i_mat++)
{
HydraMaterialStruct material;
aiMaterial *mat = scene->mMaterials[i_mat];
aiColor3D color(0.f, 0.f, 0.f);
aiString name;
mat->Get(AI_MATKEY_COLOR_DIFFUSE, color);
mat->Get(AI_MATKEY_NAME, name);
std::string mat_name = filename + std::to_string(i_mat);
aiTexture diffuse_tex;
uint32_t diffuse_tex_count = mat->GetTextureCount(aiTextureType::aiTextureType_DIFFUSE);
// have to do something here for multiple diffuse textures at some point.
aiString texture_path;
aiTextureMapping texture_mapping;
uint32_t uv_index;
if (diffuse_tex_count > 0)
{
mat->GetTexture(aiTextureType::aiTextureType_DIFFUSE, 0, &texture_path, &texture_mapping, &uv_index);
std::string path = std::string(texture_path.C_Str());
uint32_t texture_index = atoi(path.substr(1).c_str());
HydraID texture_id = texture_lookup[texture_index];
material.diffuse_texture = texture_id;
material.texture_types += static_cast<uint32_t>(HYDRA_TEXTURE_TYPE::DIFFUSE_TEXTURE);
}
material.diffuse_colour = glm::vec4(color.r, color.g, color.b, 1);
HydraID material_id = GetEngine()->MaterialManager()->CreateMaterial(mat_name, material);
material_lookup[i_mat] = material_id;
if (material_id == INVALID_HYDRA_ID)
{
throw std::runtime_error("Could not create material");
}
}
}
*/
HydraID HydraActorManager::_SaveActor(HydraActor *actor)
{
HydraECS *ecs = GetEngine()->ECS();
if (m_available_actor_ids.size() > 0)
{
HydraID id = m_available_actor_ids.front();
m_available_actor_ids.pop_front();
actor->m_id = id;
m_actors[id] = actor;
return id;
}
delete actor;
return INVALID_HYDRA_ID;
}
void HydraActorManager::Initialise(size_t max_actors)
{
m_max_actors = max_actors;
std::lock_guard<std::mutex> lock(m_mutex);
m_actors.resize(max_actors);
for (int i = 0; i < max_actors; i++)
{
m_available_actor_ids.push_back(i);
}
}
void HydraActorManager::TickActors(float delta_t)
{
// std::lock_guard<std::mutex> lock(m_mutex);
// // HydraID barrierID = GetEngine()->TaskScheduler()->CreateBarrier();
// for (int i = 0; i < m_actors_to_tick_fixed.size(); i++)
// {
// HydraID tick_actors_task_id = GetEngine()->TaskScheduler()->CreateTask<HydraFixedTickActorTask>(HydraThreadAffinity::General);
// if (tick_actors_task_id != INVALID_HYDRA_ID)
// {
// ((HydraFixedTickActorTask *)(GetEngine()->TaskScheduler()->GetTask(tick_actors_task_id)))->Initialise(m_actors_to_tick_fixed[i], delta_t);
// GetEngine()->TaskScheduler()->StartTask(tick_actors_task_id);
// }
// }
// GetEngine()->TaskScheduler()->WaitForBarrier(barrierID);
}
void HydraActorManager::InitialiseActor(HydraID actorID)
{
HydraActor *actor = GetActor(actorID);
if (actor != nullptr)
{
// actor->InitialiseComponents();
m_actors_waiting_for_init.push_back(actorID);
}
}
void HydraActorManager::Shutdown()
{
std::lock_guard<std::mutex> lock(m_mutex);
// for (HydraID actor_id = 0; actor_id < MAX_ACTORS; actor_id++)
// {
// if (m_actors[actor_id] != nullptr)
// {
// HydraActor *actor = m_actors[actor_id];
// m_actors[actor_id]->m_status = HydraActorStatus::WAITING_FOR_DELETE;
// _RemoveActorFromTickFixed(actor_id);
// _RemoveActorFromWaiting(actor_id);
// actor->Destroy();
// // for (int i = 0; i < m_actors[actor_id]->m_component_types.size(); i++)
// // {
// // GetEngine()->ComponentManager()->DeleteComponent(m_actors[actor_id]->m_component_types[i], actor_id);
// // }
// // HydraID delete_task_id = GetEngine()->TaskScheduler()->CreateTask<HydraDeleteActorTask>(HydraThreadAffinity::General);
// // HydraDeleteActorTask *task = (HydraDeleteActorTask *)GetEngine()->TaskScheduler()->GetTask(delete_task_id);
// // task->Initialise(actor_id);
// // GetEngine()->TaskScheduler()->WaitForTask(delete_task_id);
// }
// _SetActorDeleted(actor_id);
// }
}
void HydraActorManager::RotateActor(HydraID actorID, float euler_x, float euler_y, float euler_z)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actorID);
pos_comp.orientation[0] += euler_x;
pos_comp.orientation[1] += euler_y;
pos_comp.orientation[2] += euler_z;
pos_comp.needs_update = true;
ecs->GetSystem<HydraTransformSystem>()->UpdateTransform(actorID);
}
void HydraActorManager::SetPosition(HydraID actorID, glm::dvec3 position)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actorID);
pos_comp.position = position;
// if (ecs->HasComponent<HydraECSPhysicsComponent>(actorID))
// {
// HydraECSPhysicsComponent &phys_comp = ecs->GetComponent<HydraECSPhysicsComponent>(actorID);
// // const float* matrix = glm::value_ptr<float>(GetActorPose(actorID));
// phys_comp.physics_definition.pose = GetActorPose(actorID);
// }
if(!pos_comp.needs_update)
{
ecs->GetSystem<HydraTransformSystem>()->UpdateTransform(actorID);
}
}
void HydraActorManager::SetOrientation(HydraID actorID, float x, float y, float z)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actorID);
pos_comp.orientation = glm::vec3(x, y, z);
if(!pos_comp.needs_update)
{
// if (ecs->HasComponent<HydraECSPhysicsComponent>(actorID))
// {
// HydraECSPhysicsComponent &phys_comp = ecs->GetComponent<HydraECSPhysicsComponent>(actorID);
// phys_comp.physics_definition.pose = GetActorPose(actorID);
// }
ecs->GetSystem<HydraTransformSystem>()->UpdateTransform(actorID);
}
}
void HydraActorManager::SetScale(HydraID actor_id, glm::dvec3 scaling)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actor_id);
pos_comp.scale = glm::vec3(scaling);
// if (ecs->HasComponent<HydraECSPhysicsComponent>(actorID))
// {
// HydraECSPhysicsComponent &phys_comp = ecs->GetComponent<HydraECSPhysicsComponent>(actorID);
// phys_comp.physics_definition.pose = GetActorPose(actorID);
// }
if(!pos_comp.needs_update)
{
ecs->GetSystem<HydraTransformSystem>()->UpdateTransform(actor_id);
}
}
void HydraActorManager::SetRelationship(HydraID parent_id, HydraID child_id)
{
HydraActor *parent_actor = GetActor(parent_id);
HydraActor *child_actor = GetActor(child_id);
child_actor->m_parent_id = parent_id;
parent_actor->m_children.push_back(child_id);
}
void HydraActorManager::TranslateActor(HydraID actorID, glm::dvec3 translation)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actorID);
pos_comp.position = pos_comp.position + translation;
// if (ecs->HasComponent<HydraECSPhysicsComponent>(actorID))
// {
// HydraECSPhysicsComponent &phys_comp = ecs->GetComponent<HydraECSPhysicsComponent>(actorID);
// // const float* matrix = glm::value_ptr<float>(GetActorPose(actorID));
// // std::copy(matrix, matrix + 16, phys_comp.physics_definition.pose);
// phys_comp.physics_definition.pose = GetActorPose(actorID);
// }
ecs->GetSystem<HydraTransformSystem>()->UpdateTransform(actorID);
}
void HydraActorManager::AddComponentType(HydraID actorID, uint32_t component_type)
{
if (actorID < m_actors.size())
{
HydraActor *actor = m_actors[actorID];
if (actor != nullptr)
{
actor->m_component_types.push_back(component_type);
actor->m_components_waiting++;
}
}
}
glm::mat4 HydraActorManager::GetActorPose(HydraID actorID)
{
HydraPositionComponent &pos = GetEngine()->ECS()->GetComponent<HydraPositionComponent>(actorID);
glm::mat4 model_matrix = pos.transform;
// if (pos.needs_update)
// {
// glm::mat4 trans_matrix = glm::translate(pos.position);
// glm::mat4 rot_matrix = glm::toMat4(glm::quat(pos.orientation));
// model_matrix = trans_matrix * rot_matrix;
// }
return model_matrix;
}
glm::vec3 HydraActorManager::GetActorOrientation(HydraID actorID)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actorID);
return pos_comp.orientation;
}
glm::vec3 HydraActorManager::GetActorVelocity(HydraID actorID)
{
return glm::dvec3(0, 0, 0);
}
glm::dvec3 HydraActorManager::GetActorPosition(HydraID actorID)
{
HydraECS *ecs = GetEngine()->ECS();
HydraPositionComponent &pos_comp = ecs->GetComponent<HydraPositionComponent>(actorID);
return pos_comp.position;
}
bool HydraActorManager::HasComponentType(HydraID actorID, uint32_t component_type)
{
if (actorID < m_actors.size())
{
HydraActor *actor = m_actors[actorID];
if (actor != nullptr)
{
for (int i = 0; i < actor->m_component_types.size(); i++)
{
if (actor->m_component_types[i] == component_type)
{
return true;
}
}
}
}
return false;
}
void HydraActorManager::RemoveComponentType(HydraID actorID, uint32_t component_type)
{
if (actorID < m_actors.size())
{
HydraActor *actor = m_actors[actorID];
if (actor != nullptr)
{
uint32_t comp_type = static_cast<uint32_t>(component_type);
if (actor->m_component_types.size() > comp_type)
{
actor->m_component_types.erase(actor->m_component_types.begin() + comp_type);
}
}
}
}
HydraID HydraActorManager::GetParent(HydraID actor_id)
{
return m_actors[actor_id]->m_parent_id;
}
HydraID HydraActorManager::GetRoot(HydraID actor_id)
{
HydraID parent_id = GetParent(actor_id);
if(parent_id == INVALID_HYDRA_ID)
{
return actor_id;
}
return GetRoot(parent_id);
}