#include "transform.h" #include "../common/log.h" #include "../common/array.h" #include "entity.h" #include "../common/utils.h" #include "../common/num_types.h" #include "bounding_volumes.h" #include "geometry.h" #include #include #include void transform_init(struct Entity* entity, struct Entity* parent) { struct Transform* transform = &entity->transform; vec3_fill(&transform->position, 0.f, 0.f, 0.f); vec3_fill(&transform->scale, 1.f, 1.f, 1.f); quat_identity(&transform->rotation); mat4_identity(&transform->trans_mat); transform->children = array_new(struct Entity*); transform->parent = NULL; if(parent) transform_parent_set(entity, parent, false); transform_update_transmat(entity); } void transform_child_add(struct Entity* parent, struct Entity* child, bool update_transmat) { struct Transform* parent_transform = &parent->transform; struct Transform* child_transform = &child->transform; /* Check if already added */ for(int i = 0; i < array_len(parent_transform->children); i++) { if(parent_transform->children[i] == child) { log_warning("Parent : %s already has a child named %s", parent->name, parent_transform->children[i]->name); return; } } struct Entity** new_child_loc = array_grow(parent_transform->children, struct Entity*); *new_child_loc = child; child_transform->parent = parent; if(update_transmat) transform_update_transmat(child); } bool transform_child_remove(struct Entity* parent, struct Entity* child) { bool success = false; struct Transform* parent_transform = &parent->transform; for(int i = 0; i < array_len(parent_transform->children); i++) { if(parent_transform->children[i] == child) { array_remove_at(parent_transform->children, i); child->transform.parent = NULL; success = true; return success; }; } return success; } void transform_parent_set(struct Entity* child, struct Entity* parent, bool update_transmat) { if(child->transform.parent == NULL) { transform_child_add(parent, child, false); } else { transform_child_remove(parent, child); transform_child_add(parent, child, false); } if(update_transmat) transform_update_transmat(child); } void transform_copy(struct Entity* copy_to, struct Entity* copy_from, bool copy_parent) { /* Bear in mind that we can't copy the children because that would mean those children have more than one parent and we don't support that.*/ struct Entity* current_parent = copy_to->transform.parent; struct Entity** current_children = copy_to->transform.children; memcpy(©_to->transform, ©_from->transform, sizeof(struct Transform)); if(copy_parent) { transform_child_remove(current_parent, copy_to); transform_parent_set(copy_to, copy_from->transform.parent, true); } else { copy_to->transform.parent = current_parent; } copy_to->transform.is_modified = true; copy_to->transform.children = current_children; transform_update_transmat(copy_to); } void transform_translate(struct Entity* entity, vec3* amount, enum Transform_Space space) { struct Transform* transform = &entity->transform; vec3 translation_amount; vec3_assign(&translation_amount, amount); if(space == TS_LOCAL) { quat_mul_vec3(&translation_amount, &transform->rotation, &translation_amount); } else if(space == TS_PARENT) { struct Entity* parent = transform->parent; if(parent) { struct Transform* parent_tran = &parent->transform; quat_mul_vec3(&translation_amount, &parent_tran->rotation, &translation_amount); } } vec3_add(&transform->position, &transform->position, &translation_amount); transform_update_transmat(entity); } void transform_rotate(struct Entity* entity, vec3* axis, float angle, enum Transform_Space space) { struct Transform* transform = &entity->transform; quat new_rot; quat_identity(&new_rot); quat_axis_angle(&new_rot, axis, angle); if(space == TS_LOCAL) quat_mul(&transform->rotation, &transform->rotation, &new_rot); else quat_mul(&transform->rotation, &new_rot, &transform->rotation); quat_norm(&transform->rotation, &transform->rotation); transform_update_transmat(entity); } void transform_scale(struct Entity* entity, vec3* scale) { struct Transform* transform = &entity->transform; vec3_assign(&transform->scale, scale); transform_update_transmat(entity); } void transform_get_forward(struct Entity* entity, vec3* res) { struct Transform* transform = &entity->transform; vec3_fill(res, 0.f, 0.f, -1.f); quat_get_forward_rh(res, &transform->rotation); } void transform_get_lookat(struct Entity* entity, vec3* res) { struct Transform* transform = &entity->transform; transform_get_forward(entity, res); vec3_add(res, &transform->position, res); } void transform_get_absolute_forward(struct Entity* entity, vec3* res) { quat abs_rot; quat_identity(&abs_rot); transform_get_absolute_rotation(entity, &abs_rot); quat_get_forward_rh(res, &abs_rot); } void transform_get_absolute_lookat(struct Entity* entity, vec3* res) { vec3 abs_position = {0.f, 0.f, 0.f}; transform_get_absolute_position(entity, &abs_position); transform_get_absolute_forward(entity, res); vec3_add(res, &abs_position, res); } void transform_get_up(struct Entity* entity, vec3* res) { struct Transform* transform = &entity->transform; vec3_fill(res, 0.f, 1.f, 0.f); quat_get_up(res, &transform->rotation); } void transform_get_absolute_up(struct Entity* entity, vec3* res) { quat abs_rot; quat_identity(&abs_rot); transform_get_absolute_rotation(entity, &abs_rot); quat_get_up(res, &abs_rot); } void transform_get_absolute_right(struct Entity* entity, vec3* res) { quat abs_rot; quat_identity(&abs_rot); transform_get_absolute_rotation(entity, &abs_rot); quat_get_right(res, &abs_rot); } void transform_get_right(struct Entity* entity, vec3* res) { struct Transform* transform = &entity->transform; vec3_fill(res, 1.f, 0.f, 0.f); quat_get_right(res, &transform->rotation); } void transform_update_transmat(struct Entity* entity) { static mat4 scale, translation, rotation; struct Transform* transform = &entity->transform; mat4_identity(&scale); mat4_identity(&translation); mat4_identity(&rotation); mat4_identity(&transform->trans_mat); mat4_scale(&scale, transform->scale.x, transform->scale.y, transform->scale.z); mat4_translate(&translation, transform->position.x, transform->position.y, transform->position.z); mat4_from_quat(&rotation, &transform->rotation); mat4_mul(&transform->trans_mat, &transform->trans_mat, &translation); mat4_mul(&transform->trans_mat, &transform->trans_mat, &rotation); mat4_mul(&transform->trans_mat, &transform->trans_mat, &scale); if(transform->parent) { struct Transform* parent_tran = &transform->parent->transform; mat4_mul(&transform->trans_mat, &parent_tran->trans_mat, &transform->trans_mat); } entity_update_derived_bounding_box(entity); /* Update all children */ int children = array_len(transform->children); if(children > 0) { for(int i = 0; i < children; i++) transform_update_transmat(entity->transform.children[i]); } transform->is_modified = true; } void transform_destroy(struct Entity* entity) { struct Transform* transform = &entity->transform; // Remove children if(transform->children) { int children = array_len(transform->children); if(children > 0) { for(int i = 0; i < children; i++) { struct Entity* child = transform->children[i]; child->flags |= EF_MARKED_FOR_DELETION; child->transform.parent = NULL; } } array_free(transform->children); } // Remove this entity from parent's children if(transform->parent) transform_child_remove(entity->transform.parent, entity); /* Remove transform */ vec3_fill(&transform->position, 0.f, 0.f, 0.f); vec3_fill(&transform->scale, 1.f, 1.f, 1.f); quat_identity(&transform->rotation); mat4_identity(&transform->trans_mat); transform->parent = NULL; transform->children = NULL; transform->is_modified = false; } void transform_set_position(struct Entity* entity, vec3* new_position) { struct Transform* transform = &entity->transform; vec3_assign(&transform->position, new_position); transform_update_transmat(entity); } void transform_get_absolute_position(struct Entity* entity, vec3* res) { res->x = entity->transform.trans_mat.mat[12]; res->y = entity->transform.trans_mat.mat[13]; res->z = entity->transform.trans_mat.mat[14]; } void transform_get_absolute_scale(struct Entity* entity, vec3* res) { struct Transform* transform = &entity->transform; vec3_assign(res, &transform->scale); bool done = false; struct Entity* parent = transform->parent; while(!done) { if(!parent) { done = true; break; } vec3_mul(res, res, &parent->transform.scale); parent = parent->transform.parent; } } void transform_get_absolute_rotation(struct Entity* entity, quat* res) { quat_assign(res, &entity->transform.rotation); bool done = false; struct Entity* parent = entity->transform.parent; while(!done) { if(!parent) { done = true; break; } //quat_mul(res, res, &parent->transform.rotation); quat_mul(res, &parent->transform.rotation, res); parent = parent->transform.parent; } } void transform_reset(struct Entity* entity) { /* Does remove/change parent or children, only modifies that transformation data */ vec3_fill(&entity->transform.position, 0.f, 0.f, 0.f); vec3_fill(&entity->transform.scale, 0.f, 0.f, 0.f); quat_identity(&entity->transform.rotation); transform_update_transmat(entity); }