In my small DirectX12 engine, I've already implemented parent-child relationship between game objects. But there was a problem with the transformation of objects. I have written two functions to get global and local matrices. During the deletion of the old parent and the addition of a new one, I assign a new local transformation to the object so that the global matrices are calculated correctly and the child is moved during the parent's movement. But the child object loses its original coordinates when I do this. I read that to get a local transformation of a child object, you need to multiply its global matrix by the inverted matrix of the parent. For some reason it doesn't work.
struct TransformComponent { glm::vec3 Translation = { 0.0f, 0.0f, 0.0f }; glm::vec3 Rotation = { 0.0f, 0.0f, 0.0f }; glm::vec3 Scale = { 1.0f, 1.0f, 1.0f }; glm::mat4 GetLocalTransform() { glm::mat4 rotation = glm::toMat4(glm::quat(glm::vec3(glm::radians(Rotation.x), glm::radians(Rotation.y), glm::radians(Rotation.z)))); return glm::translate(glm::mat4(1.f), Translation) * rotation * glm::scale(glm::mat4(1.0f), Scale); } glm::mat4 GetGlobalTransform(entt::entity entity, entt::registry& registry) { auto parent = registry.get<RelationshipComponent>(entity).Parent; glm::mat4 result = glm::mat4(1.f); if (parent == entt::null) { result = GetLocalTransform(); } else { glm::mat4 transform = glm::mat4(1.f); auto curr = entity; while (curr != entt::null) { glm::mat4 currLocalTransform = registry.get<TransformComponent>(curr).GetLocalTransform(); transform = currLocalTransform * transform; curr = registry.get<RelationshipComponent>(curr).Parent; } result = transform; } return result; } glm::mat4 GetLocalTransform(entt::entity entity, entt::registry& registry) { entt::entity parent = registry.get<RelationshipComponent>(entity).Parent; glm::mat4 globalParentTransform = registry.get<TransformComponent>(parent).GetGlobalTransform(parent, registry); return glm::inverse(globalParentTransform) * GetGlobalTransform(entity, registry); } }; void Entity::AddParent(Entity parent) { ... auto& tc = GetComponent<TransformComponent>(); glm::mat4 localTransform = tc.GetLocalTransform(m_EntityHandle, m_Scene->GetRegistry()); glm::vec3 scale; glm::quat rotation; glm::vec3 translation; glm::vec3 skew; glm::vec4 perspective; glm::decompose(localTransform, scale, rotation, translation, skew, perspective); tc.Translation = translation; tc.Scale = scale; glm::vec3 eulerAngles = glm::eulerAngles(rotation); tc.Rotation = glm::vec3(glm::degrees(eulerAngles.x), glm::degrees(eulerAngles.y), glm::degrees(eulerAngles.z)); } void TestApplication::RenderScene(...) { ... auto& meshTransform = transformComponent.GetLocalTransform(); auto& meshComponent = m_Scene->GetRegistry().get<MeshComponent>(meshEnt); auto& model = meshComponent.m_Model; if (!model || !model->IsLoaded()) continue; MatricesCB mtxCb; mtxCb.modelMat = transformComponent.GetGlobalTransform(meshEnt, m_Scene->GetRegistry()); ... } ```