From 8464d712645a5a51684c9d87221dc01eefb74b34 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 10 Oct 2022 02:00:33 +0900 Subject: [PATCH] [scene] Move hierarchies to an ECS-based system This is the beginning of adding ECS to QF. While the previous iteration of hierarchies was a start in the direction towards ECS, this pulls most of the 3d-specific transform stuff out of the hierarchy "objects", making all the matrices and vectors/quaternions actual components (in the ECS sense). There's more work to be done with respect to the transform and entity members of hierarchy_t (entity should probably go away entirely, and transform should become hierref_t (or whatever its final name becomes), but I wanted to get things working sooner than later. The motivation for the effort was to allow views to use hierarchy_t, which should be possible once I get entity and transform sorted out. I am really glad I already had automated tests for hierarchies, as things proved to be a little tricky to get working due to forgetting why certain things were there. --- include/QF/scene/component.h | 124 ++++++++ include/QF/scene/hierarchy.h | 42 +-- include/QF/scene/transform.h | 72 +++-- libs/scene/Makemodule.am | 1 + libs/scene/component.c | 32 ++ libs/scene/hierarchy.c | 489 +++++++++++-------------------- libs/scene/scene.c | 8 +- libs/scene/test/test-hierarchy.c | 216 +++++++------- libs/scene/transform.c | 280 +++++++++++++++--- 9 files changed, 763 insertions(+), 501 deletions(-) create mode 100644 include/QF/scene/component.h create mode 100644 libs/scene/component.c diff --git a/include/QF/scene/component.h b/include/QF/scene/component.h new file mode 100644 index 000000000..472851ee3 --- /dev/null +++ b/include/QF/scene/component.h @@ -0,0 +1,124 @@ +/* + component.h + + Component management + + Copyright (C) 2022 Bill Currie + + Author: Bill Currie + Date: 2022/10/07 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ + +#ifndef __QF_scene_component_h +#define __QF_scene_component_h + +#include +#include + +#include "QF/qtypes.h" + +/** \defgroup entity Hierarchy management + \ingroup utils +*/ +///@{ + +#define null_transform (~0u) + +typedef struct component_s { + size_t size; + void (*create) (void *); + void (*destroy) (void *); + const char *name; +} component_t; + +#define COMPINLINE GNU89INLINE inline + +COMPINLINE void Component_ResizeArray (const component_t *component, + void **array, uint32_t count); +COMPINLINE void Component_MoveElements (const component_t *component, + void *array, uint32_t dstIndex, + uint32_t srcIndex, uint32_t count); +COMPINLINE void Component_CopyElements (const component_t *component, + void *dstArray, uint32_t dstIndex, + const void *srcArray, uint32_t srcIndex, + uint32_t count); +COMPINLINE void Component_CreateElements (const component_t *component, + void *array, + uint32_t index, uint32_t count); + +#undef COMPINLINE +#ifndef IMPLEMENT_COMPONENT_Funcs +#define COMPINLINE GNU89INLINE inline +#else +#define COMPINLINE VISIBLE +#endif + +COMPINLINE +void +Component_ResizeArray (const component_t *component, + void **array, uint32_t count) +{ + *array = realloc (*array, count * component->size); +} + +COMPINLINE +void +Component_MoveElements (const component_t *component, + void *array, uint32_t dstIndex, uint32_t srcIndex, + uint32_t count) +{ + __auto_type dst = (byte *) array + dstIndex * component->size; + __auto_type src = (byte *) array + srcIndex * component->size; + memmove (dst, src, count * component->size); +} + +COMPINLINE +void +Component_CopyElements (const component_t *component, + void *dstArray, uint32_t dstIndex, + const void *srcArray, uint32_t srcIndex, + uint32_t count) +{ + __auto_type dst = (byte *) dstArray + dstIndex * component->size; + __auto_type src = (byte *) srcArray + srcIndex * component->size; + memcpy (dst, src, count * component->size); +} + +COMPINLINE +void +Component_CreateElements (const component_t *component, void *array, + uint32_t index, uint32_t count) +{ + if (component->create) { + for (uint32_t i = index; count-- > 0; i++) { + __auto_type dst = (byte *) array + i * component->size; + component->create (dst); + } + } else { + __auto_type dst = (byte *) array + index * component->size; + memset (dst, 0, count * component->size); + } +} + +///@} + +#endif//__QF_scene_component_h diff --git a/include/QF/scene/hierarchy.h b/include/QF/scene/hierarchy.h index 4ac088591..47d946540 100644 --- a/include/QF/scene/hierarchy.h +++ b/include/QF/scene/hierarchy.h @@ -42,36 +42,42 @@ */ ///@{ +/** Descriptors for components attached to every entity in the hierarchy. +*/ +typedef struct hierarchy_type_s { + uint32_t num_components; + const struct component_s *components; +} hierarchy_type_t; + #define null_transform (~0u) +typedef struct hierref_s { + struct hierarchy_s *hierarchy; + uint32_t index; ///< index in hierarchy + int32_t id; ///< scene id +} hierref_t; + typedef struct hierarchy_s { struct hierarchy_s *next; struct hierarchy_s **prev; struct scene_s *scene; - xformset_t transform; - entityset_t entity; - uint32set_t childCount; - uint32set_t childIndex; - uint32set_t parentIndex; - stringset_t name; - uint32set_t tag; - byteset_t modified; - mat4fset_t localMatrix; - mat4fset_t localInverse; - mat4fset_t worldMatrix; - mat4fset_t worldInverse; - vec4fset_t localRotation; - vec4fset_t localScale; - vec4fset_t worldRotation; - vec4fset_t worldScale; + uint32_t num_objects; + uint32_t max_objects; + struct transform_s **transform; //FIXME use hierref_t + struct entity_s **entity; //FIXME should not exist + uint32_t *childCount; + uint32_t *childIndex; + uint32_t *parentIndex; + const hierarchy_type_t *type; + void **components; } hierarchy_t; -hierarchy_t *Hierarchy_New (struct scene_s *scene, int createRoot); +hierarchy_t *Hierarchy_New (struct scene_s *scene, + const hierarchy_type_t *type, int createRoot); void Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count); hierarchy_t *Hierarchy_Copy (struct scene_s *scene, const hierarchy_t *src); void Hierarchy_Delete (hierarchy_t *hierarchy); -void Hierarchy_UpdateMatrices (hierarchy_t *hierarchy); uint32_t Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot); void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index); diff --git a/include/QF/scene/transform.h b/include/QF/scene/transform.h index 66f552df8..3bd933168 100644 --- a/include/QF/scene/transform.h +++ b/include/QF/scene/transform.h @@ -42,6 +42,22 @@ */ ///@{ +enum { + transform_type_name, + transform_type_tag, + transform_type_modified, + transform_type_localMatrix, + transform_type_localInverse, + transform_type_worldMatrix, + transform_type_worldInverse, + transform_type_localRotation, + transform_type_localScale, + transform_type_worldRotation, + transform_type_worldScale, + + transform_type_count +}; + typedef struct transform_s { hierarchy_t *hierarchy; struct scene_s *scene; ///< owning scene @@ -103,7 +119,7 @@ uint32_t Transform_ChildCount (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->childCount.a[transform->index]; + return h->childCount[transform->index]; } XFORMINLINE @@ -111,10 +127,10 @@ transform_t * Transform_GetChild (const transform_t *transform, uint32_t childIndex) { hierarchy_t *h = transform->hierarchy; - if (childIndex >= h->childCount.a[transform->index]) { + if (childIndex >= h->childCount[transform->index]) { return 0; } - return h->transform.a[h->childIndex.a[transform->index] + childIndex]; + return h->transform[h->childIndex[transform->index] + childIndex]; } XFORMINLINE @@ -125,7 +141,7 @@ Transform_GetParent (const transform_t *transform) return 0; } hierarchy_t *h = transform->hierarchy; - return h->transform.a[h->parentIndex.a[transform->index]]; + return h->transform[h->parentIndex[transform->index]]; } XFORMINLINE @@ -133,7 +149,8 @@ const char * Transform_GetName (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->name.a[transform->index]; + char **name = h->components[transform_type_name]; + return name[transform->index]; } XFORMINLINE @@ -141,7 +158,8 @@ uint32_t Transform_GetTag (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->tag.a[transform->index]; + uint32_t *tag = h->components[transform_type_tag]; + return tag[transform->index]; } XFORMINLINE @@ -149,7 +167,8 @@ void Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->localMatrix.a[transform->index]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *src = localMatrix[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -161,7 +180,8 @@ void Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->localInverse.a[transform->index]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + vec4f_t *src = localInverse[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -173,7 +193,8 @@ void Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->worldMatrix.a[transform->index]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + vec4f_t *src = worldMatrix[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -185,7 +206,8 @@ const vec4f_t * Transform_GetWorldMatrixPtr (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index]; } XFORMINLINE @@ -193,7 +215,8 @@ void Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat) { hierarchy_t *h = transform->hierarchy; - vec4f_t *src = h->worldInverse.a[transform->index]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *src = worldInverse[transform->index]; mat[0] = src[0]; mat[1] = src[1]; mat[2] = src[2]; @@ -205,7 +228,8 @@ vec4f_t Transform_GetLocalPosition (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->localMatrix.a[transform->index][3]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + return localMatrix[transform->index][3]; } XFORMINLINE @@ -213,7 +237,8 @@ vec4f_t Transform_GetLocalRotation (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->localRotation.a[transform->index]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + return localRotation[transform->index]; } XFORMINLINE @@ -221,7 +246,8 @@ vec4f_t Transform_GetLocalScale (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->localScale.a[transform->index]; + vec4f_t *localScale = h->components[transform_type_localScale]; + return localScale[transform->index]; } XFORMINLINE @@ -229,7 +255,8 @@ vec4f_t Transform_GetWorldPosition (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][3]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index][3]; } XFORMINLINE @@ -237,7 +264,8 @@ vec4f_t Transform_GetWorldRotation (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldRotation.a[transform->index]; + vec4f_t *worldRotation = h->components[transform_type_worldRotation]; + return worldRotation[transform->index]; } XFORMINLINE @@ -245,7 +273,8 @@ vec4f_t Transform_GetWorldScale (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldScale.a[transform->index]; + vec4f_t *worldScale = h->components[transform_type_worldScale]; + return worldScale[transform->index]; } XFORMINLINE @@ -253,7 +282,8 @@ vec4f_t Transform_Forward (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][0]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index][0]; } XFORMINLINE @@ -261,7 +291,8 @@ vec4f_t Transform_Right (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return -h->worldMatrix.a[transform->index][1]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return -worldMatrix[transform->index][1]; } XFORMINLINE @@ -269,7 +300,8 @@ vec4f_t Transform_Up (const transform_t *transform) { hierarchy_t *h = transform->hierarchy; - return h->worldMatrix.a[transform->index][2]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + return worldMatrix[transform->index][2]; } ///@} diff --git a/libs/scene/Makemodule.am b/libs/scene/Makemodule.am index cbd89b1be..b1778c200 100644 --- a/libs/scene/Makemodule.am +++ b/libs/scene/Makemodule.am @@ -9,6 +9,7 @@ libs_scene_libQFscene_la_LIBADD= $(scene_deps) libs_scene_libQFscene_la_DEPENDENCIES= $(scene_deps) libs_scene_libQFscene_la_SOURCES= \ libs/scene/camera.c \ + libs/scene/component.c \ libs/scene/entity.c \ libs/scene/hierarchy.c \ libs/scene/light.c \ diff --git a/libs/scene/component.c b/libs/scene/component.c new file mode 100644 index 000000000..85ddc0cf9 --- /dev/null +++ b/libs/scene/component.c @@ -0,0 +1,32 @@ +/* + component.c + + Component handling + + Copyright (C) 2022 Bill Currke + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define IMPLEMENT_COMPONENT_Funcs +#include "QF/scene/component.h" diff --git a/libs/scene/hierarchy.c b/libs/scene/hierarchy.c index 17c161d70..092a3bf3b 100644 --- a/libs/scene/hierarchy.c +++ b/libs/scene/hierarchy.c @@ -35,18 +35,25 @@ # include #endif +#include "QF/scene/component.h" #include "QF/scene/hierarchy.h" #include "QF/scene/transform.h" #include "scn_internal.h" +static component_t transform_component = { .size = sizeof (transform_t *) }; +static component_t entity_component = { .size = sizeof (entity_t *) }; +static component_t childCount_component = { .size = sizeof (uint32_t) }; +static component_t childIndex_component = { .size = sizeof (uint32_t) }; +static component_t parentIndex_component = { .size = sizeof (uint32_t) }; + static void hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - for (size_t i = start; i < hierarchy->transform.size; i++) { - if (hierarchy->transform.a[i]) { - hierarchy->transform.a[i]->index += offset; + for (size_t i = start; i < hierarchy->num_objects; i++) { + if (hierarchy->transform[i]) { + hierarchy->transform[i]->index += offset; } } } @@ -55,8 +62,8 @@ static void hierarchy_UpdateChildIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - for (size_t i = start; i < hierarchy->childIndex.size; i++) { - hierarchy->childIndex.a[i] += offset; + for (size_t i = start; i < hierarchy->num_objects; i++) { + hierarchy->childIndex[i] += offset; } } @@ -64,127 +71,86 @@ static void hierarchy_UpdateParentIndices (hierarchy_t *hierarchy, uint32_t start, int offset) { - for (size_t i = start; i < hierarchy->parentIndex.size; i++) { - hierarchy->parentIndex.a[i] += offset; + for (size_t i = start; i < hierarchy->num_objects; i++) { + hierarchy->parentIndex[i] += offset; } } -static void -hierarchy_calcLocalInverse (hierarchy_t *h, uint32_t index) -{ - // This takes advantage of the fact that localMatrix is a simple - // homogenous scale/rotate/translate matrix with no shear - vec4f_t x = h->localMatrix.a[index][0]; - vec4f_t y = h->localMatrix.a[index][1]; - vec4f_t z = h->localMatrix.a[index][2]; - vec4f_t t = h->localMatrix.a[index][3]; - - // "one" is to ensure both the scalar and translation have 1 in their - // fourth components - vec4f_t one = { 0, 0, 0, 1 }; - vec4f_t nx = { x[0], y[0], z[0], 0 }; - vec4f_t ny = { x[1], y[1], z[1], 0 }; - vec4f_t nz = { x[2], y[2], z[2], 0 }; - vec4f_t nt = one - t[0] * nx - t[1] * ny - t[2] * nz; - // vertical dot product!!! - vec4f_t s = 1 / (nx * nx + ny * ny + nz * nz + one); - h->localInverse.a[index][0] = nx * s; - h->localInverse.a[index][1] = ny * s; - h->localInverse.a[index][2] = nz * s; - h->localInverse.a[index][3] = nt * s; -} - void -Hierarchy_UpdateMatrices (hierarchy_t *h) +Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) { - for (size_t i = 0; i < h->localInverse.size; i++) { - if (h->modified.a[i]) { - hierarchy_calcLocalInverse (h, i); - } - } - if (h->modified.a[0]) { - memcpy (h->worldMatrix.a[0], - h->localMatrix.a[0], sizeof (mat4_t)); - memcpy (h->worldInverse.a[0], - h->localInverse.a[0], sizeof (mat4_t)); - h->worldRotation.a[0] = h->localRotation.a[0]; - h->worldScale.a[0] = h->localScale.a[0]; - } - for (size_t i = 1; i < h->worldMatrix.size; i++) { - uint32_t parent = h->parentIndex.a[i]; + if (hierarchy->num_objects + count > hierarchy->max_objects) { + uint32_t new_max = hierarchy->num_objects + count; + new_max += 15; + new_max &= ~15; - if (h->modified.a[i] || h->modified.a[parent]) { - mmulf (h->worldMatrix.a[i], - h->worldMatrix.a[parent], h->localMatrix.a[i]); - h->modified.a[i] = 1; - } - } - for (size_t i = 1; i < h->worldInverse.size; i++) { - uint32_t parent = h->parentIndex.a[i]; + Component_ResizeArray (&transform_component, + (void **) &hierarchy->transform, new_max); + Component_ResizeArray (&entity_component, + (void **) &hierarchy->entity, new_max); + Component_ResizeArray (&childCount_component, + (void **) &hierarchy->childCount, new_max); + Component_ResizeArray (&childIndex_component, + (void **) &hierarchy->childIndex, new_max); + Component_ResizeArray (&parentIndex_component, + (void **) &hierarchy->parentIndex, new_max); - if (h->modified.a[i] || h->modified.a[parent]) { - mmulf (h->worldInverse.a[i], - h->localInverse.a[i], h->worldInverse.a[parent]); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_ResizeArray (&hierarchy->type->components[i], + &hierarchy->components[i], new_max); } + hierarchy->max_objects = new_max; } - for (size_t i = 1; i < h->worldRotation.size; i++) { - uint32_t parent = h->parentIndex.a[i]; - if (h->modified.a[i] || h->modified.a[parent]) { - h->worldRotation.a[i] = qmulf (h->worldRotation.a[parent], - h->localRotation.a[i]); - } - } - for (size_t i = 1; i < h->worldScale.size; i++) { - uint32_t parent = h->parentIndex.a[i]; - if (h->modified.a[i] || h->modified.a[parent]) { - h->worldScale.a[i] = m3vmulf (h->worldMatrix.a[parent], - h->localScale.a[i]); - } - } - memset (h->modified.a, 0, h->modified.size); } static void hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t count) { - DARRAY_OPEN_AT (&hierarchy->transform, index, count); - DARRAY_OPEN_AT (&hierarchy->entity, index, count); - DARRAY_OPEN_AT (&hierarchy->childCount, index, count); - DARRAY_OPEN_AT (&hierarchy->childIndex, index, count); - DARRAY_OPEN_AT (&hierarchy->parentIndex, index, count); - DARRAY_OPEN_AT (&hierarchy->name, index, count); - DARRAY_OPEN_AT (&hierarchy->tag, index, count); - DARRAY_OPEN_AT (&hierarchy->modified, index, count); - DARRAY_OPEN_AT (&hierarchy->localMatrix, index, count); - DARRAY_OPEN_AT (&hierarchy->localInverse, index, count); - DARRAY_OPEN_AT (&hierarchy->worldMatrix, index, count); - DARRAY_OPEN_AT (&hierarchy->worldInverse, index, count); - DARRAY_OPEN_AT (&hierarchy->localRotation, index, count); - DARRAY_OPEN_AT (&hierarchy->localScale, index, count); - DARRAY_OPEN_AT (&hierarchy->worldRotation, index, count); - DARRAY_OPEN_AT (&hierarchy->worldScale, index, count); + Hierarchy_Reserve (hierarchy, count); + + hierarchy->num_objects += count; + uint32_t dstIndex = index + count; + count = hierarchy->num_objects - index - count; + Component_MoveElements (&transform_component, + hierarchy->transform, dstIndex, index, count); + Component_MoveElements (&entity_component, + hierarchy->entity, dstIndex, index, count); + Component_MoveElements (&childCount_component, + hierarchy->childCount, dstIndex, index, count); + Component_MoveElements (&childIndex_component, + hierarchy->childIndex, dstIndex, index, count); + Component_MoveElements (&parentIndex_component, + hierarchy->parentIndex, dstIndex, index, count); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_MoveElements (&hierarchy->type->components[i], + hierarchy->components[i], + dstIndex, index, count); + } } static void hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count) { - if (count) { - DARRAY_CLOSE_AT (&hierarchy->transform, index, count); - DARRAY_CLOSE_AT (&hierarchy->entity, index, count); - DARRAY_CLOSE_AT (&hierarchy->childCount, index, count); - DARRAY_CLOSE_AT (&hierarchy->childIndex, index, count); - DARRAY_CLOSE_AT (&hierarchy->parentIndex, index, count); - DARRAY_CLOSE_AT (&hierarchy->name, index, count); - DARRAY_CLOSE_AT (&hierarchy->tag, index, count); - DARRAY_CLOSE_AT (&hierarchy->modified, index, count); - DARRAY_CLOSE_AT (&hierarchy->localMatrix, index, count); - DARRAY_CLOSE_AT (&hierarchy->localInverse, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldMatrix, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldInverse, index, count); - DARRAY_CLOSE_AT (&hierarchy->localRotation, index, count); - DARRAY_CLOSE_AT (&hierarchy->localScale, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldRotation, index, count); - DARRAY_CLOSE_AT (&hierarchy->worldScale, index, count); + if (!count) { + return; + } + hierarchy->num_objects -= count; + uint32_t srcIndex = index + count; + count = hierarchy->num_objects - index; + Component_MoveElements (&transform_component, + hierarchy->transform, index, srcIndex, count); + Component_MoveElements (&entity_component, + hierarchy->entity, index, srcIndex, count); + Component_MoveElements (&childCount_component, + hierarchy->childCount, index, srcIndex, count); + Component_MoveElements (&childIndex_component, + hierarchy->childIndex, index, srcIndex, count); + Component_MoveElements (&parentIndex_component, + hierarchy->parentIndex, index, srcIndex, count); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + Component_MoveElements (&hierarchy->type->components[i], + hierarchy->components[i], + index, srcIndex, count); } } @@ -192,29 +158,25 @@ static void hierarchy_move (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstIndex, uint32_t srcIndex, uint32_t count) { - memcpy (&dst->transform.a[dstIndex], &src->transform.a[srcIndex], - count * sizeof(dst->transform.a[0])); - memset (&src->transform.a[srcIndex], 0, - count * sizeof(dst->transform.a[0])); - memcpy (&dst->entity.a[dstIndex], &src->entity.a[srcIndex], - count * sizeof(dst->entity.a[0])); - memcpy (&dst->name.a[dstIndex], &src->name.a[srcIndex], - count * sizeof(dst->name.a[0])); - memcpy (&dst->tag.a[dstIndex], &src->tag.a[srcIndex], - count * sizeof(dst->tag.a[0])); - memset (&dst->modified.a[dstIndex], 1, count * sizeof(dst->modified.a[0])); - memcpy (&dst->localMatrix.a[dstIndex], &src->localMatrix.a[srcIndex], - count * sizeof(dst->localMatrix.a[0])); - memcpy (&dst->localInverse.a[dstIndex], &src->localInverse.a[srcIndex], - count * sizeof(dst->localInverse.a[0])); - memcpy (&dst->localRotation.a[dstIndex], &src->localRotation.a[srcIndex], - count * sizeof(dst->localRotation.a[0])); - memcpy (&dst->localScale.a[dstIndex], &src->localScale.a[srcIndex], - count * sizeof(dst->localScale.a[0])); + Component_CopyElements (&transform_component, + dst->transform, dstIndex, + src->transform, srcIndex, count); + Component_CopyElements (&entity_component, + dst->entity, dstIndex, + src->entity, srcIndex, count); + // Actually move (as in C++ move semantics) source hierarchy object + // references so that their indices do not get updated when the objects + // are removed from the source hierarcy + memset (&src->transform[srcIndex], 0, count * sizeof(dst->transform[0])); for (uint32_t i = 0; i < count; i++) { - dst->transform.a[dstIndex + i]->hierarchy = dst; - dst->transform.a[dstIndex + i]->index = dstIndex + i; + dst->transform[dstIndex + i]->hierarchy = dst; + dst->transform[dstIndex + i]->index = dstIndex + i; + } + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CopyElements (&dst->type->components[i], + dst->components[i], dstIndex, + src->components[i], srcIndex, count); } } @@ -222,22 +184,17 @@ static void hierarchy_init (hierarchy_t *dst, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t count) { - memset (&dst->transform.a[index], 0, - count * sizeof(dst->transform.a[0])); - memset (&dst->entity.a[index], 0, count * sizeof(dst->entity.a[0])); - memset (&dst->name.a[index], 0, count * sizeof(dst->name.a[0])); - memset (&dst->tag.a[index], 0, count * sizeof(dst->tag.a[0])); - memset (&dst->modified.a[index], 1, count * sizeof(dst->modified.a[0])); + memset (&dst->transform[index], 0, + count * sizeof(dst->transform[0])); for (uint32_t i = 0; i < count; i++) { - mat4fidentity (dst->localMatrix.a[index]); - mat4fidentity (dst->localInverse.a[index]); - dst->localRotation.a[index] = (vec4f_t) { 0, 0, 0, 1 }; - dst->localScale.a[index] = (vec4f_t) { 1, 1, 1, 1 }; - - dst->parentIndex.a[index + i] = parentIndex; - dst->childCount.a[index + i] = 0; - dst->childIndex.a[index + i] = childIndex; + dst->parentIndex[index + i] = parentIndex; + dst->childCount[index + i] = 0; + dst->childIndex[index + i] = childIndex; + } + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CreateElements (&dst->type->components[i], + dst->components[i], index, count); } } @@ -245,34 +202,33 @@ static uint32_t hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot, uint32_t count) { - uint32_t insertIndex; // where the transforms will be inserted - uint32_t childIndex; // where the transforms' children will inserted + uint32_t insertIndex; // where the objects will be inserted + uint32_t childIndex; // where the objects' children will inserted - // The newly added transforms are always last children of the parent - // transform - insertIndex = dst->childIndex.a[dstParent] + dst->childCount.a[dstParent]; - - // By design, all of a transform's children are in one contiguous block, - // and the blocks of children for each transform are ordered by their - // parents. Thus the child index of each transform increases monotonically + // The newly added objects are always last children of the parent + // object + insertIndex = dst->childIndex[dstParent] + dst->childCount[dstParent]; + // By design, all of a object's children are in one contiguous block, + // and the blocks of children for each object are ordered by their + // parents. Thus the child index of each object increases monotonically // for each child index in the array, regardless of the level of the owning - // transform (higher levels always come before lower levels). + // object (higher levels always come before lower levels). uint32_t neighbor = insertIndex - 1; // insertIndex never zero - childIndex = dst->childIndex.a[neighbor] + dst->childCount.a[neighbor]; + childIndex = dst->childIndex[neighbor] + dst->childCount[neighbor]; - // Any transforms that come after the inserted transforms need to have + // Any objects that come after the inserted objects need to have // thier indices adjusted. hierarchy_UpdateTransformIndices (dst, insertIndex, count); - // The parent transform's child index is not affected, but the child - // indices of all transforms immediately after the parent transform are. + // The parent object's child index is not affected, but the child + // indices of all objects immediately after the parent object are. hierarchy_UpdateChildIndices (dst, dstParent + 1, count); hierarchy_UpdateParentIndices (dst, childIndex, count); - // The beginning of the block of children for the new transforms was - // computed from the pre-insert indices of the related transforms, thus - // the index must be updated by the number of transforms being inserted + // The beginning of the block of children for the new objects was + // computed from the pre-insert indices of the related objects, thus + // the index must be updated by the number of objects being inserted // (it would have been updated thusly if the insert was done before - // updating the indices of the other transforms). + // updating the indices of the other objects). childIndex += count; hierarchy_open (dst, insertIndex, count); @@ -282,12 +238,12 @@ hierarchy_insert (hierarchy_t *dst, const hierarchy_t *src, hierarchy_init (dst, insertIndex, dstParent, childIndex, count); } for (uint32_t i = 0; i < count; i++) { - dst->parentIndex.a[insertIndex + i] = dstParent; - dst->childIndex.a[insertIndex + i] = childIndex; - dst->childCount.a[insertIndex + i] = 0; + dst->parentIndex[insertIndex + i] = dstParent; + dst->childIndex[insertIndex + i] = childIndex; + dst->childCount[insertIndex + i] = 0; } - dst->childCount.a[dstParent] += count; + dst->childCount[dstParent] += count; return insertIndex; } @@ -296,8 +252,8 @@ hierarchy_insert_children (hierarchy_t *dst, const hierarchy_t *src, uint32_t dstParent, uint32_t srcRoot) { uint32_t insertIndex; - uint32_t childIndex = src->childIndex.a[srcRoot]; - uint32_t childCount = src->childCount.a[srcRoot]; + uint32_t childIndex = src->childIndex[srcRoot]; + uint32_t childCount = src->childCount[srcRoot]; if (childCount) { insertIndex = hierarchy_insert (dst, src, dstParent, @@ -316,47 +272,46 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src, uint32_t insertIndex; if (dstParent == null_transform) { - if (dst->transform.size) { + if (dst->num_objects) { Sys_Error ("attempt to insert root in non-empty hierarchy"); } hierarchy_open (dst, 0, 1); hierarchy_move (dst, src, 0, srcRoot, 1); - dst->parentIndex.a[0] = null_transform; - dst->childIndex.a[0] = 1; - dst->childCount.a[0] = 0; + dst->parentIndex[0] = null_transform; + dst->childIndex[0] = 1; + dst->childCount[0] = 0; insertIndex = 0; } else { - if (!dst->transform.size) { + if (!dst->num_objects) { Sys_Error ("attempt to insert non-root in empty hierarchy"); } insertIndex = hierarchy_insert (dst, src, dstParent, srcRoot, 1); } - // if src is null, then inserting a new transform which has no children + // if src is null, then inserting a new object which has no children if (src) { hierarchy_insert_children (dst, src, insertIndex, srcRoot); } - Hierarchy_UpdateMatrices (dst); return insertIndex; } static void hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) { - uint32_t childIndex = hierarchy->childIndex.a[index]; - uint32_t childCount = hierarchy->childCount.a[index]; - uint32_t parentIndex = hierarchy->parentIndex.a[index]; + uint32_t childIndex = hierarchy->childIndex[index]; + uint32_t childCount = hierarchy->childCount[index]; + uint32_t parentIndex = hierarchy->parentIndex[index]; uint32_t nieceIndex = null_transform; if (parentIndex != null_transform) { - uint32_t siblingIndex = hierarchy->childIndex.a[parentIndex]; - siblingIndex += hierarchy->childCount.a[parentIndex] - 1; - nieceIndex = hierarchy->childIndex.a[siblingIndex]; + uint32_t siblingIndex = hierarchy->childIndex[parentIndex]; + siblingIndex += hierarchy->childCount[parentIndex] - 1; + nieceIndex = hierarchy->childIndex[siblingIndex]; } for (uint32_t i = childCount; i-- > 0; ) { hierarchy_remove_children (hierarchy, childIndex + i); } hierarchy_close (hierarchy, childIndex, childCount); - hierarchy->childCount.a[index] = 0; + hierarchy->childCount[index] = 0; if (childCount) { hierarchy_UpdateTransformIndices (hierarchy, childIndex, -childCount); @@ -370,11 +325,11 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index) void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) { - uint32_t parentIndex = hierarchy->parentIndex.a[index]; - uint32_t childIndex = hierarchy->childIndex.a[index]; + uint32_t parentIndex = hierarchy->parentIndex[index]; + uint32_t childIndex = hierarchy->childIndex[index]; uint32_t siblingIndex = null_transform; if (parentIndex != null_transform) { - siblingIndex = hierarchy->childIndex.a[parentIndex]; + siblingIndex = hierarchy->childIndex[parentIndex]; } hierarchy_remove_children (hierarchy, index); hierarchy_close (hierarchy, index, 1); @@ -386,10 +341,10 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index) } hierarchy_t * -Hierarchy_New (scene_t *scene, int createRoot) +Hierarchy_New (scene_t *scene, const hierarchy_type_t *type, int createRoot) { scene_resources_t *res = scene->resources; - hierarchy_t *hierarchy = PR_RESNEW_NC (res->hierarchies); + hierarchy_t *hierarchy = PR_RESNEW (res->hierarchies); hierarchy->scene = scene; hierarchy->prev = &scene->hierarchies; @@ -399,23 +354,9 @@ Hierarchy_New (scene_t *scene, int createRoot) } scene->hierarchies = hierarchy; - size_t grow = 16; - DARRAY_INIT (&hierarchy->transform, grow); - DARRAY_INIT (&hierarchy->entity, grow); - DARRAY_INIT (&hierarchy->childCount, grow); - DARRAY_INIT (&hierarchy->childIndex, grow); - DARRAY_INIT (&hierarchy->parentIndex, grow); - DARRAY_INIT (&hierarchy->name, grow); - DARRAY_INIT (&hierarchy->tag, grow); - DARRAY_INIT (&hierarchy->modified, grow); - DARRAY_INIT (&hierarchy->localMatrix, grow); - DARRAY_INIT (&hierarchy->localInverse, grow); - DARRAY_INIT (&hierarchy->worldMatrix, grow); - DARRAY_INIT (&hierarchy->worldInverse, grow); - DARRAY_INIT (&hierarchy->localRotation, grow); - DARRAY_INIT (&hierarchy->localScale, grow); - DARRAY_INIT (&hierarchy->worldRotation, grow); - DARRAY_INIT (&hierarchy->worldScale, grow); + hierarchy->type = type; + hierarchy->components = calloc (hierarchy->type->num_components, + sizeof (void *)); if (createRoot) { hierarchy_open (hierarchy, 0, 1); @@ -434,131 +375,47 @@ Hierarchy_Delete (hierarchy_t *hierarchy) *hierarchy->prev = hierarchy->next; scene_resources_t *res = hierarchy->scene->resources; - for (size_t i = 0; i < hierarchy->transform.size; i++) { - PR_RESFREE (res->transforms, hierarchy->transform.a[i]); + for (uint32_t i = 0; i < hierarchy->num_objects; i++) { + PR_RESFREE (res->transforms, hierarchy->transform[i]); } - DARRAY_CLEAR (&hierarchy->transform); - DARRAY_CLEAR (&hierarchy->entity); - DARRAY_CLEAR (&hierarchy->childCount); - DARRAY_CLEAR (&hierarchy->childIndex); - DARRAY_CLEAR (&hierarchy->parentIndex); - DARRAY_CLEAR (&hierarchy->name); - DARRAY_CLEAR (&hierarchy->tag); - DARRAY_CLEAR (&hierarchy->modified); - DARRAY_CLEAR (&hierarchy->localMatrix); - DARRAY_CLEAR (&hierarchy->localInverse); - DARRAY_CLEAR (&hierarchy->worldMatrix); - DARRAY_CLEAR (&hierarchy->worldInverse); - DARRAY_CLEAR (&hierarchy->localRotation); - DARRAY_CLEAR (&hierarchy->localScale); - DARRAY_CLEAR (&hierarchy->worldRotation); - DARRAY_CLEAR (&hierarchy->worldScale); + free (hierarchy->transform); + free (hierarchy->childCount); + free (hierarchy->childIndex); + free (hierarchy->parentIndex); + for (uint32_t i = 0; i < hierarchy->type->num_components; i++) { + free (hierarchy->components[i]); + } + free (hierarchy->components); + PR_RESFREE (res->hierarchies, hierarchy); } -void -Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count) -{ - size_t size = hierarchy->transform.size; - - DARRAY_RESIZE (&hierarchy->transform, size + count); - DARRAY_RESIZE (&hierarchy->entity, size + count); - DARRAY_RESIZE (&hierarchy->childCount, size + count); - DARRAY_RESIZE (&hierarchy->childIndex, size + count); - DARRAY_RESIZE (&hierarchy->parentIndex, size + count); - DARRAY_RESIZE (&hierarchy->name, size + count); - DARRAY_RESIZE (&hierarchy->tag, size + count); - DARRAY_RESIZE (&hierarchy->modified, size + count); - DARRAY_RESIZE (&hierarchy->localMatrix, size + count); - DARRAY_RESIZE (&hierarchy->localInverse, size + count); - DARRAY_RESIZE (&hierarchy->worldMatrix, size + count); - DARRAY_RESIZE (&hierarchy->worldInverse, size + count); - DARRAY_RESIZE (&hierarchy->localRotation, size + count); - DARRAY_RESIZE (&hierarchy->localScale, size + count); - DARRAY_RESIZE (&hierarchy->worldRotation, size + count); - DARRAY_RESIZE (&hierarchy->worldScale, size + count); - - DARRAY_RESIZE (&hierarchy->transform, size); - DARRAY_RESIZE (&hierarchy->entity, size); - DARRAY_RESIZE (&hierarchy->childCount, size); - DARRAY_RESIZE (&hierarchy->childIndex, size); - DARRAY_RESIZE (&hierarchy->parentIndex, size); - DARRAY_RESIZE (&hierarchy->name, size); - DARRAY_RESIZE (&hierarchy->tag, size); - DARRAY_RESIZE (&hierarchy->modified, size); - DARRAY_RESIZE (&hierarchy->localMatrix, size); - DARRAY_RESIZE (&hierarchy->localInverse, size); - DARRAY_RESIZE (&hierarchy->worldMatrix, size); - DARRAY_RESIZE (&hierarchy->worldInverse, size); - DARRAY_RESIZE (&hierarchy->localRotation, size); - DARRAY_RESIZE (&hierarchy->localScale, size); - DARRAY_RESIZE (&hierarchy->worldRotation, size); - DARRAY_RESIZE (&hierarchy->worldScale, size); -} - hierarchy_t * Hierarchy_Copy (scene_t *scene, const hierarchy_t *src) { - hierarchy_t *dst = Hierarchy_New (scene, 0); - size_t count = src->transform.size; + hierarchy_t *dst = Hierarchy_New (scene, src->type, 0); + size_t count = src->num_objects; - DARRAY_RESIZE (&dst->transform, count); - DARRAY_RESIZE (&dst->entity, count); - DARRAY_RESIZE (&dst->childCount, count); - DARRAY_RESIZE (&dst->childIndex, count); - DARRAY_RESIZE (&dst->parentIndex, count); - DARRAY_RESIZE (&dst->name, count); - DARRAY_RESIZE (&dst->tag, count); - DARRAY_RESIZE (&dst->modified, count); - DARRAY_RESIZE (&dst->localMatrix, count); - DARRAY_RESIZE (&dst->localInverse, count); - DARRAY_RESIZE (&dst->worldMatrix, count); - DARRAY_RESIZE (&dst->worldInverse, count); - DARRAY_RESIZE (&dst->localRotation, count); - DARRAY_RESIZE (&dst->localScale, count); - DARRAY_RESIZE (&dst->worldRotation, count); - DARRAY_RESIZE (&dst->worldScale, count); + Hierarchy_Reserve (dst, count); for (size_t i = 0; i < count; i++) { - dst->transform.a[i] = __transform_alloc (scene); - dst->transform.a[i]->hierarchy = dst; - dst->transform.a[i]->index = i; + dst->transform[i] = __transform_alloc (scene); + dst->transform[i]->hierarchy = dst; + dst->transform[i]->index = i; } - for (size_t i = 0; i < count; i++) { - dst->entity.a[i] = 0; // FIXME clone entity + + Component_CopyElements (&childCount_component, + dst->childCount, 0, src->childCount, 0, count); + Component_CopyElements (&childIndex_component, + dst->childIndex, 0, src->childIndex, 0, count); + Component_CopyElements (&parentIndex_component, + dst->parentIndex, 0, src->parentIndex, 0, count); + for (uint32_t i = 0; i < dst->type->num_components; i++) { + Component_CopyElements (&dst->type->components[i], + dst->components[i], 0, + src->components[i], 0, count); } - memcpy (dst->childCount.a, src->childCount.a, - count * sizeof(dst->childCount.a[0])); - memcpy (dst->childIndex.a, src->childIndex.a, - count * sizeof(dst->childIndex.a[0])); - memcpy (dst->parentIndex.a, src->parentIndex.a, - count * sizeof(dst->parentIndex.a[0])); - for (size_t i = 0; i < count; i++) { - // use the transform code so string allocation remains consistent - // regardless how it changes. - Transform_SetName (dst->transform.a[i], src->name.a[i]); - } - memcpy (dst->tag.a, src->tag.a, - count * sizeof(dst->tag.a[0])); - memcpy (dst->modified.a, src->modified.a, - count * sizeof(dst->modified.a[0])); - memcpy (dst->localMatrix.a, src->localMatrix.a, - count * sizeof(dst->localMatrix.a[0])); - memcpy (dst->localInverse.a, src->localInverse.a, - count * sizeof(dst->localInverse.a[0])); - memcpy (dst->worldMatrix.a, src->worldMatrix.a, - count * sizeof(dst->worldMatrix.a[0])); - memcpy (dst->worldInverse.a, src->worldInverse.a, - count * sizeof(dst->worldInverse.a[0])); - memcpy (dst->localRotation.a, src->localRotation.a, - count * sizeof(dst->localRotation.a[0])); - memcpy (dst->localScale.a, src->localScale.a, - count * sizeof(dst->localScale.a[0])); - memcpy (dst->worldRotation.a, src->worldRotation.a, - count * sizeof(dst->worldRotation.a[0])); - memcpy (dst->worldScale.a, src->worldScale.a, - count * sizeof(dst->localScale.a[0])); - // Just in case the source hierarchy has modified transforms - Hierarchy_UpdateMatrices (dst); + // Just in case the source hierarchy has modified objects + //Hierarchy_UpdateMatrices (dst); return dst; } diff --git a/libs/scene/scene.c b/libs/scene/scene.c index 09f2d16bb..215eb7b5e 100644 --- a/libs/scene/scene.c +++ b/libs/scene/scene.c @@ -141,7 +141,7 @@ Scene_CreateEntity (scene_t *scene) ent->id = PR_RESINDEX (res->entities, ent); hierarchy_t *h = ent->transform->hierarchy; - h->entity.a[ent->transform->index] = ent; + h->entity[ent->transform->index] = ent; QuatSet (1, 1, 1, 1, ent->renderer.colormod); @@ -165,8 +165,8 @@ destroy_entity (scene_t *scene, entity_t *ent) // Transform_Delete takes care of all hierarchy stuff (transforms // themselves, name strings, hierarchy table) hierarchy_t *h = transform->hierarchy; - for (size_t i = 0; i < h->entity.size; i++) { - entity_t *e = h->entity.a[0]; + for (size_t i = 0; i < h->num_objects; i++) { + entity_t *e = h->entity[0]; e->transform = 0; PR_RESFREE (res->entities, ent); } @@ -193,7 +193,7 @@ Scene_FreeAllEntities (scene_t *scene) while (scene->hierarchies) { hierarchy_t *h = scene->hierarchies; // deleting the root entity deletes all child entities - entity_t *ent = h->entity.a[0]; + entity_t *ent = h->entity[0]; destroy_entity (scene, ent); } scene_resources_t *res = scene->resources; diff --git a/libs/scene/test/test-hierarchy.c b/libs/scene/test/test-hierarchy.c index c8adb529e..47fdf0814 100644 --- a/libs/scene/test/test-hierarchy.c +++ b/libs/scene/test/test-hierarchy.c @@ -43,30 +43,15 @@ mat4_equal (const mat4f_t a, const mat4f_t b) static int check_hierarchy_size (hierarchy_t *h, uint32_t size) { - if (h->transform.size != size - || h->entity.size != size - || h->childCount.size != size - || h->childIndex.size != size - || h->parentIndex.size != size - || h->name.size != size - || h->tag.size != size - || h->modified.size != size - || h->localMatrix.size != size - || h->localInverse.size != size - || h->worldMatrix.size != size - || h->worldInverse.size != size - || h->localRotation.size != size - || h->localScale.size != size - || h->worldRotation.size != size - || h->worldScale.size != size) { - printf ("hierarchy does not have exactly %u" - " transform or array sizes are inconsistent\n", size); + if (h->num_objects != size) { + printf ("hierarchy does not have exactly %u transform\n", size); return 0; } - for (size_t i = 0; i < h->transform.size; i++) { - if (h->transform.a[i]->hierarchy != h) { - printf ("transform %zd (%s) does not point to hierarchy\n", - i, h->name.a[i]); + char **name = h->components[transform_type_name]; + for (uint32_t i = 0; i < h->num_objects; i++) { + if (h->transform[i]->hierarchy != h) { + printf ("transform %d (%s) does not point to hierarchy\n", + i, name[i]); } } return 1; @@ -75,10 +60,11 @@ check_hierarchy_size (hierarchy_t *h, uint32_t size) static void dump_hierarchy (hierarchy_t *h) { - for (size_t i = 0; i < h->transform.size; i++) { - printf ("%2zd: %5s %2u %2u %2u %2u\n", i, h->name.a[i], - h->transform.a[i]->index, h->parentIndex.a[i], - h->childIndex.a[i], h->childCount.a[i]); + char **name = h->components[transform_type_name]; + for (uint32_t i = 0; i < h->num_objects; i++) { + printf ("%2d: %5s %2u %2u %2u %2u\n", i, name[i], + h->transform[i]->index, h->parentIndex[i], + h->childIndex[i], h->childCount[i]); } puts (""); } @@ -88,25 +74,26 @@ check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex, uint32_t childIndex, uint32_t childCount) { hierarchy_t *h = transform->hierarchy; + char **name = h->components[transform_type_name]; if (transform->index != index) { printf ("%s/%s index incorrect: expect %u got %u\n", - h->name.a[transform->index], h->name.a[index], + name[transform->index], name[index], index, transform->index); return 0; } - if (h->parentIndex.a[index] != parentIndex) { + if (h->parentIndex[index] != parentIndex) { printf ("%s parent index incorrect: expect %u got %u\n", - h->name.a[index], parentIndex, h->parentIndex.a[index]); + name[index], parentIndex, h->parentIndex[index]); return 0; } - if (h->childIndex.a[index] != childIndex) { + if (h->childIndex[index] != childIndex) { printf ("%s child index incorrect: expect %u got %u\n", - h->name.a[index], childIndex, h->childIndex.a[index]); + name[index], childIndex, h->childIndex[index]); return 0; } - if (h->childCount.a[index] != childCount) { + if (h->childCount[index] != childCount) { printf ("%s child count incorrect: expect %u got %u\n", - h->name.a[index], childCount, h->childCount.a[index]); + name[index], childCount, h->childCount[index]); return 0; } return 1; @@ -126,19 +113,25 @@ test_single_transform (void) printf ("New transform has no hierarchy\n"); return 1; } + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; if (!check_hierarchy_size (h, 1)) { return 1; } if (!check_indices (transform, 0, null_transform, 1, 0)) { return 1; } - if (!mat4_equal (h->localMatrix.a[0], identity) - || !mat4_equal (h->localInverse.a[0], identity) - || !mat4_equal (h->worldMatrix.a[0], identity) - || !mat4_equal (h->worldInverse.a[0], identity)) { + if (!mat4_equal (localMatrix[0], identity) + || !mat4_equal (localInverse[0], identity) + || !mat4_equal (worldMatrix[0], identity) + || !mat4_equal (worldInverse[0], identity)) { printf ("New transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[0], identity[3]) - || !vec4_equal (h->localScale.a[0], one)) { + if (!vec4_equal (localRotation[0], identity[3]) + || !vec4_equal (localScale[0], one)) { printf ("New transform rotation or scale not identity\n"); return 1; } @@ -166,30 +159,36 @@ test_parent_child_init (void) if (!check_indices (child, 1, 0, 2, 0)) { return 1; } hierarchy_t *h = parent->hierarchy; - if (!mat4_equal (h->localMatrix.a[0], identity) - || !mat4_equal (h->localInverse.a[0], identity) - || !mat4_equal (h->worldMatrix.a[0], identity) - || !mat4_equal (h->worldInverse.a[0], identity)) { + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + if (!mat4_equal (localMatrix[0], identity) + || !mat4_equal (localInverse[0], identity) + || !mat4_equal (worldMatrix[0], identity) + || !mat4_equal (worldInverse[0], identity)) { printf ("Parent transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[0], identity[3]) - || !vec4_equal (h->localScale.a[0], one)) { + if (!vec4_equal (localRotation[0], identity[3]) + || !vec4_equal (localScale[0], one)) { printf ("Parent transform rotation or scale not identity\n"); return 1; } - if (!mat4_equal (h->localMatrix.a[1], identity) - || !mat4_equal (h->localInverse.a[1], identity) - || !mat4_equal (h->worldMatrix.a[1], identity) - || !mat4_equal (h->worldInverse.a[1], identity)) { + if (!mat4_equal (localMatrix[1], identity) + || !mat4_equal (localInverse[1], identity) + || !mat4_equal (worldMatrix[1], identity) + || !mat4_equal (worldInverse[1], identity)) { printf ("Child transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[1], identity[3]) - || !vec4_equal (h->localScale.a[1], one)) { + if (!vec4_equal (localRotation[1], identity[3]) + || !vec4_equal (localScale[1], one)) { printf ("Child transform rotation or scale not identity\n"); return 1; } @@ -231,30 +230,36 @@ test_parent_child_setparent (void) if (!check_indices (child, 1, 0, 2, 0)) { return 1; } hierarchy_t *h = parent->hierarchy; - if (!mat4_equal (h->localMatrix.a[0], identity) - || !mat4_equal (h->localInverse.a[0], identity) - || !mat4_equal (h->worldMatrix.a[0], identity) - || !mat4_equal (h->worldInverse.a[0], identity)) { + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + if (!mat4_equal (localMatrix[0], identity) + || !mat4_equal (localInverse[0], identity) + || !mat4_equal (worldMatrix[0], identity) + || !mat4_equal (worldInverse[0], identity)) { printf ("Parent transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[0], identity[3]) - || !vec4_equal (h->localScale.a[0], one)) { + if (!vec4_equal (localRotation[0], identity[3]) + || !vec4_equal (localScale[0], one)) { printf ("Parent transform rotation or scale not identity\n"); return 1; } - if (!mat4_equal (h->localMatrix.a[1], identity) - || !mat4_equal (h->localInverse.a[1], identity) - || !mat4_equal (h->worldMatrix.a[1], identity) - || !mat4_equal (h->worldInverse.a[1], identity)) { + if (!mat4_equal (localMatrix[1], identity) + || !mat4_equal (localInverse[1], identity) + || !mat4_equal (worldMatrix[1], identity) + || !mat4_equal (worldInverse[1], identity)) { printf ("Child transform matrices not identity\n"); return 1; } - if (!vec4_equal (h->localRotation.a[1], identity[3]) - || !vec4_equal (h->localScale.a[1], one)) { + if (!vec4_equal (localRotation[1], identity[3]) + || !vec4_equal (localScale[1], one)) { printf ("Child transform rotation or scale not identity\n"); return 1; } @@ -530,65 +535,70 @@ test_frames (void) Transform_SetLocalRotation (B1, (vec4f_t) { -0.5, 0.5, -0.5, 0.5 }); hierarchy_t *h = root->hierarchy; - for (size_t i = 0; i < h->transform.size; i++) { + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + char **name = h->components[transform_type_name]; + for (uint32_t i = 0; i < h->num_objects; i++) { mat4f_t res; - mmulf (res, h->localMatrix.a[i], h->localInverse.a[i]); + mmulf (res, localMatrix[i], localInverse[i]); if (!mat4_equal (res, identity)) { printf ("%s: localInverse not inverse of localMatrix\n", - h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 3)); + name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 3)); printf ("r: " VEC4F_FMT "\n", MAT4_ROW(res, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 2)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 3)); return 1; } - puts (h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->localInverse.a[i], 3)); + puts (name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(localInverse[i], 3)); } - for (size_t i = 0; i < h->transform.size; i++) { + for (uint32_t i = 0; i < h->num_objects; i++) { mat4f_t res; - mmulf (res, h->worldMatrix.a[i], h->worldInverse.a[i]); + mmulf (res, worldMatrix[i], worldInverse[i]); if (!mat4_equal (res, identity)) { printf ("%s: worldInverse not inverse of worldMatrix\n", - h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 3)); + name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 3)); printf ("r: " VEC4F_FMT "\n", MAT4_ROW(res, 0)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 1)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 2)); printf (" " VEC4F_FMT "\n", MAT4_ROW(res, 3)); return 1; } - puts (h->name.a[i]); - printf ("l: " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldMatrix.a[i], 3)); - printf ("i: " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 0)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 1)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 2)); - printf (" " VEC4F_FMT "\n", MAT4_ROW(h->worldInverse.a[i], 3)); + puts (name[i]); + printf ("l: " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldMatrix[i], 3)); + printf ("i: " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 0)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 1)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 2)); + printf (" " VEC4F_FMT "\n", MAT4_ROW(worldInverse[i], 3)); } if (!check_vector (root, Transform_GetLocalPosition, diff --git a/libs/scene/transform.c b/libs/scene/transform.c index 7048536de..82ad54557 100644 --- a/libs/scene/transform.c +++ b/libs/scene/transform.c @@ -37,12 +37,102 @@ #define IMPLEMENT_TRANSFORM_Funcs +#include "QF/scene/component.h" #include "QF/scene/hierarchy.h" #include "QF/scene/scene.h" #include "QF/scene/transform.h" #include "scn_internal.h" +static void +transform_mat4f_identity (void *_mat) +{ + vec4f_t *mat = _mat; + mat4fidentity (mat); +} + +static void +transform_rotation_identity (void *_rot) +{ + vec4f_t *rot = _rot; + *rot = (vec4f_t) { 0, 0, 0, 1 }; +} + +static void +transform_scale_identity (void *_scale) +{ + vec4f_t *scale = _scale; + *scale = (vec4f_t) { 1, 1, 1, 1 }; +} + +static void +transform_modified_init (void *_modified) +{ + byte *modified = _modified; + *modified = 1; +} + +static const component_t transform_components[transform_type_count] = { + [transform_type_name] = { + .size = sizeof (char *), + .name = "Name", + }, + [transform_type_tag] = { + .size = sizeof (uint32_t), + .name = "Tag", + }, + [transform_type_modified] = { + .size = sizeof (byte), + .create = transform_modified_init, + .name = "Modified", + }, + [transform_type_localMatrix] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "Local Matrix", + }, + [transform_type_localInverse] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "Local Inverse", + }, + [transform_type_worldMatrix] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "World Matrix", + }, + [transform_type_worldInverse] = { + .size = sizeof (mat4f_t), + .create = transform_mat4f_identity, + .name = "World Inverse", + }, + [transform_type_localRotation] = { + .size = sizeof (vec4f_t), + .create = transform_rotation_identity, + .name = "Local Rotation", + }, + [transform_type_localScale] = { + .size = sizeof (vec4f_t), + .create = transform_scale_identity, + .name = "Local Scale", + }, + [transform_type_worldRotation] = { + .size = sizeof (vec4f_t), + .create = transform_rotation_identity, + .name = "World Rotation", + }, + [transform_type_worldScale] = { + .size = sizeof (vec4f_t), + .create = transform_scale_identity, + .name = "World Scale", + }, +}; + +static const hierarchy_type_t transform_type = { + .num_components = transform_type_count, + .components = transform_components, +}; + transform_t * __transform_alloc (scene_t *scene) { @@ -55,6 +145,93 @@ __transform_alloc (scene_t *scene) return transform; } +static void +transform_calcLocalInverse (hierarchy_t *h, uint32_t index) +{ + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + // This takes advantage of the fact that localMatrix is a simple + // homogenous scale/rotate/translate matrix with no shear + vec4f_t x = localMatrix[index][0]; + vec4f_t y = localMatrix[index][1]; + vec4f_t z = localMatrix[index][2]; + vec4f_t t = localMatrix[index][3]; + + // "one" is to ensure both the scalar and translation have 1 in their + // fourth components + vec4f_t one = { 0, 0, 0, 1 }; + vec4f_t nx = { x[0], y[0], z[0], 0 }; + vec4f_t ny = { x[1], y[1], z[1], 0 }; + vec4f_t nz = { x[2], y[2], z[2], 0 }; + vec4f_t nt = one - t[0] * nx - t[1] * ny - t[2] * nz; + // vertical dot product!!! + vec4f_t s = 1 / (nx * nx + ny * ny + nz * nz + one); + localInverse[index][0] = nx * s; + localInverse[index][1] = ny * s; + localInverse[index][2] = nz * s; + localInverse[index][3] = nt * s; +} + +static void +Transform_UpdateMatrices (hierarchy_t *h) +{ + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + mat4f_t *localInverse = h->components[transform_type_localInverse]; + mat4f_t *worldMatrix = h->components[transform_type_worldMatrix]; + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + vec4f_t *worldRotation = h->components[transform_type_worldRotation]; + vec4f_t *worldScale = h->components[transform_type_worldScale]; + byte *modified = h->components[transform_type_modified]; + + for (uint32_t i = 0; i < h->num_objects; i++) { + if (modified[i]) { + transform_calcLocalInverse (h, i); + } + } + if (modified[0]) { + memcpy (worldMatrix[0], + localMatrix[0], sizeof (mat4_t)); + memcpy (worldInverse[0], + localInverse[0], sizeof (mat4_t)); + worldRotation[0] = localRotation[0]; + worldScale[0] = localScale[0]; + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + + if (modified[i] || modified[parent]) { + mmulf (worldMatrix[i], + worldMatrix[parent], localMatrix[i]); + modified[i] = 1; + } + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + + if (modified[i] || modified[parent]) { + mmulf (worldInverse[i], + localInverse[i], worldInverse[parent]); + } + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + if (modified[i] || modified[parent]) { + worldRotation[i] = qmulf (worldRotation[parent], + localRotation[i]); + } + } + for (size_t i = 1; i < h->num_objects; i++) { + uint32_t parent = h->parentIndex[i]; + if (modified[i] || modified[parent]) { + worldScale[i] = m3vmulf (worldMatrix[parent], + localScale[i]); + } + } + memset (modified, 0, h->num_objects); +} + transform_t * Transform_New (scene_t *scene, transform_t *parent) { @@ -65,11 +242,11 @@ Transform_New (scene_t *scene, transform_t *parent) transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0, parent->index, 0); } else { - transform->hierarchy = Hierarchy_New (scene, 1); + transform->hierarchy = Hierarchy_New (scene, &transform_type, 1); transform->index = 0; } - transform->hierarchy->transform.a[transform->index] = transform; - Hierarchy_UpdateMatrices (transform->hierarchy); + transform->hierarchy->transform[transform->index] = transform; + Transform_UpdateMatrices (transform->hierarchy); return transform; } @@ -102,7 +279,7 @@ Transform_SetParent (transform_t *transform, transform_t *parent) Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy, parent->index, index); Hierarchy_RemoveHierarchy (hierarchy, index); - if (!hierarchy->name.size) { + if (!hierarchy->num_objects) { Hierarchy_Delete (hierarchy); } } else { @@ -114,72 +291,89 @@ Transform_SetParent (transform_t *transform, transform_t *parent) hierarchy_t *hierarchy = transform->hierarchy; uint32_t index = transform->index; - hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene, 0); + hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene, + &transform_type, 0); Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform, index); Hierarchy_RemoveHierarchy (hierarchy, index); } + hierarchy_t *h = transform->hierarchy; + byte *modified = h->components[transform_type_modified]; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void -Transform_SetName (transform_t *transform, const char *name) +Transform_SetName (transform_t *transform, const char *_name) { hierarchy_t *h = transform->hierarchy; + char **name = h->components[transform_type_name]; //FIXME create a string pool (similar to qfcc's, or even move that to util) - if (h->name.a[transform->index]) { - free (h->name.a[transform->index]); + if (name[transform->index]) { + free (name[transform->index]); } - h->name.a[transform->index] = strdup (name); + name[transform->index] = strdup (_name); } void -Transform_SetTag (transform_t *transform, uint32_t tag) +Transform_SetTag (transform_t *transform, uint32_t _tag) { hierarchy_t *h = transform->hierarchy; - h->tag.a[transform->index] = tag; + uint32_t *tag = h->components[transform_type_tag]; + tag[transform->index] = _tag; } void Transform_SetLocalPosition (transform_t *transform, vec4f_t position) { hierarchy_t *h = transform->hierarchy; - h->localMatrix.a[transform->index][3] = position; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + byte *modified = h->components[transform_type_modified]; + localMatrix[transform->index][3] = position; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation) { hierarchy_t *h = transform->hierarchy; - vec4f_t scale = h->localScale.a[transform->index]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + byte *modified = h->components[transform_type_modified]; + vec4f_t scale = localScale[transform->index]; mat4f_t mat; mat4fquat (mat, rotation); - h->localRotation.a[transform->index] = rotation; - h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; - h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; - h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + localRotation[transform->index] = rotation; + localMatrix[transform->index][0] = mat[0] * scale[0]; + localMatrix[transform->index][1] = mat[1] * scale[1]; + localMatrix[transform->index][2] = mat[2] * scale[2]; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void Transform_SetLocalScale (transform_t *transform, vec4f_t scale) { hierarchy_t *h = transform->hierarchy; - vec4f_t rotation = h->localRotation.a[transform->index]; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + byte *modified = h->components[transform_type_modified]; + vec4f_t rotation = localRotation[transform->index]; mat4f_t mat; mat4fquat (mat, rotation); - h->localScale.a[transform->index] = scale; - h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; - h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; - h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + localScale[transform->index] = scale; + localMatrix[transform->index][0] = mat[0] * scale[0]; + localMatrix[transform->index][1] = mat[1] * scale[1]; + localMatrix[transform->index][2] = mat[2] * scale[2]; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); } void @@ -187,8 +381,9 @@ Transform_SetWorldPosition (transform_t *transform, vec4f_t position) { if (transform->index) { hierarchy_t *h = transform->hierarchy; - uint32_t parent = h->parentIndex.a[transform->index]; - position = mvmulf (h->worldInverse.a[parent], position); + mat4f_t *worldInverse = h->components[transform_type_worldInverse]; + uint32_t parent = h->parentIndex[transform->index]; + position = mvmulf (worldInverse[parent], position); } Transform_SetLocalPosition (transform, position); } @@ -198,8 +393,9 @@ Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation) { if (transform->index) { hierarchy_t *h = transform->hierarchy; - uint32_t parent = h->parentIndex.a[transform->index]; - rotation = qmulf (qconjf (h->worldRotation.a[parent]), rotation); + vec4f_t *worldRotation = h->components[transform_type_worldRotation]; + uint32_t parent = h->parentIndex[transform->index]; + rotation = qmulf (qconjf (worldRotation[parent]), rotation); } Transform_SetLocalRotation (transform, rotation); } @@ -209,16 +405,20 @@ Transform_SetLocalTransform (transform_t *transform, vec4f_t scale, vec4f_t rotation, vec4f_t position) { hierarchy_t *h = transform->hierarchy; + mat4f_t *localMatrix = h->components[transform_type_localMatrix]; + vec4f_t *localRotation = h->components[transform_type_localRotation]; + vec4f_t *localScale = h->components[transform_type_localScale]; + byte *modified = h->components[transform_type_modified]; mat4f_t mat; mat4fquat (mat, rotation); position[3] = 1; - h->localRotation.a[transform->index] = rotation; - h->localScale.a[transform->index] = scale; - h->localMatrix.a[transform->index][0] = mat[0] * scale[0]; - h->localMatrix.a[transform->index][1] = mat[1] * scale[1]; - h->localMatrix.a[transform->index][2] = mat[2] * scale[2]; - h->localMatrix.a[transform->index][3] = position; - h->modified.a[transform->index] = 1; - Hierarchy_UpdateMatrices (h); + localRotation[transform->index] = rotation; + localScale[transform->index] = scale; + localMatrix[transform->index][0] = mat[0] * scale[0]; + localMatrix[transform->index][1] = mat[1] * scale[1]; + localMatrix[transform->index][2] = mat[2] * scale[2]; + localMatrix[transform->index][3] = position; + modified[transform->index] = 1; + Transform_UpdateMatrices (h); }