[scene] Use hierref_t instead of transform_t in hierarchy

Hierarchies are now much closer to being more general in that they are
not tied to 3d transforms. This is a major step to moving the whole
entity/transform system into an ECS.
This commit is contained in:
Bill Currie 2022-10-22 13:04:07 +09:00
parent ac8c6b631e
commit de786ce197
9 changed files with 246 additions and 221 deletions

View file

@ -49,8 +49,6 @@ typedef struct hierarchy_type_s {
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
@ -63,7 +61,7 @@ typedef struct hierarchy_s {
struct scene_s *scene;
uint32_t num_objects;
uint32_t max_objects;
struct transform_s **transform; //FIXME use hierref_t
hierref_t **ref;
struct entity_s **entity; //FIXME should not exist
uint32_t *childCount;
uint32_t *childIndex;

View file

@ -59,23 +59,21 @@ enum {
};
typedef struct transform_s {
hierarchy_t *hierarchy;
struct scene_s *scene; ///< owning scene
uint32_t index; ///< index in hierarchy
int32_t id; ///< scene id
hierref_t ref;
} transform_t;
#define XFORMINLINE GNU89INLINE inline __attribute__((pure))
transform_t *Transform_New (struct scene_s *scene, transform_t *parent);
/* Deletes all child transforms, and transform names */
void Transform_Delete (transform_t *transform);
void Transform_Delete (struct scene_s *scene, transform_t *transform);
transform_t *Transform_NewNamed (struct scene_s *scene, transform_t *parent,
const char *name);
XFORMINLINE uint32_t Transform_ChildCount (const transform_t *transform);
XFORMINLINE transform_t *Transform_GetChild (const transform_t *transform,
uint32_t childIndex);
void Transform_SetParent (transform_t *transform, transform_t *parent);
void Transform_SetParent (struct scene_s *scene,
transform_t *transform, transform_t *parent);
XFORMINLINE transform_t *Transform_GetParent (const transform_t *transform);
void Transform_SetName (transform_t *transform, const char *name);
XFORMINLINE const char *Transform_GetName (const transform_t *transform);
@ -118,57 +116,63 @@ XFORMINLINE
uint32_t
Transform_ChildCount (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
return h->childCount[transform->index];
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
return h->childCount[ref->index];
}
XFORMINLINE
transform_t *
Transform_GetChild (const transform_t *transform, uint32_t childIndex)
{
hierarchy_t *h = transform->hierarchy;
if (childIndex >= h->childCount[transform->index]) {
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
if (childIndex >= h->childCount[ref->index]) {
return 0;
}
return h->transform[h->childIndex[transform->index] + childIndex];
return (transform_t *) h->ref[h->childIndex[ref->index] + childIndex];
}
XFORMINLINE
transform_t *
Transform_GetParent (const transform_t *transform)
{
if (transform->index == 0) {
__auto_type ref = (const hierref_t *) transform;
if (ref->index == 0) {
return 0;
}
hierarchy_t *h = transform->hierarchy;
return h->transform[h->parentIndex[transform->index]];
hierarchy_t *h = ref->hierarchy;
return (transform_t *) h->ref[h->parentIndex[ref->index]];
}
XFORMINLINE
const char *
Transform_GetName (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
char **name = h->components[transform_type_name];
return name[transform->index];
return name[ref->index];
}
XFORMINLINE
uint32_t
Transform_GetTag (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
uint32_t *tag = h->components[transform_type_tag];
return tag[transform->index];
return tag[ref->index];
}
XFORMINLINE
void
Transform_GetLocalMatrix (const transform_t *transform, mat4f_t mat)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *localMatrix = h->components[transform_type_localMatrix];
vec4f_t *src = localMatrix[transform->index];
vec4f_t *src = localMatrix[ref->index];
mat[0] = src[0];
mat[1] = src[1];
mat[2] = src[2];
@ -179,9 +183,10 @@ XFORMINLINE
void
Transform_GetLocalInverse (const transform_t *transform, mat4f_t mat)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *localInverse = h->components[transform_type_localInverse];
vec4f_t *src = localInverse[transform->index];
vec4f_t *src = localInverse[ref->index];
mat[0] = src[0];
mat[1] = src[1];
mat[2] = src[2];
@ -192,9 +197,10 @@ XFORMINLINE
void
Transform_GetWorldMatrix (const transform_t *transform, mat4f_t mat)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
vec4f_t *src = worldMatrix[transform->index];
vec4f_t *src = worldMatrix[ref->index];
mat[0] = src[0];
mat[1] = src[1];
mat[2] = src[2];
@ -205,18 +211,20 @@ XFORMINLINE
const vec4f_t *
Transform_GetWorldMatrixPtr (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
return worldMatrix[transform->index];
return worldMatrix[ref->index];
}
XFORMINLINE
void
Transform_GetWorldInverse (const transform_t *transform, mat4f_t mat)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldInverse = h->components[transform_type_worldInverse];
vec4f_t *src = worldInverse[transform->index];
vec4f_t *src = worldInverse[ref->index];
mat[0] = src[0];
mat[1] = src[1];
mat[2] = src[2];
@ -227,81 +235,90 @@ XFORMINLINE
vec4f_t
Transform_GetLocalPosition (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *localMatrix = h->components[transform_type_localMatrix];
return localMatrix[transform->index][3];
return localMatrix[ref->index][3];
}
XFORMINLINE
vec4f_t
Transform_GetLocalRotation (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
vec4f_t *localRotation = h->components[transform_type_localRotation];
return localRotation[transform->index];
return localRotation[ref->index];
}
XFORMINLINE
vec4f_t
Transform_GetLocalScale (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
vec4f_t *localScale = h->components[transform_type_localScale];
return localScale[transform->index];
return localScale[ref->index];
}
XFORMINLINE
vec4f_t
Transform_GetWorldPosition (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
return worldMatrix[transform->index][3];
return worldMatrix[ref->index][3];
}
XFORMINLINE
vec4f_t
Transform_GetWorldRotation (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
vec4f_t *worldRotation = h->components[transform_type_worldRotation];
return worldRotation[transform->index];
return worldRotation[ref->index];
}
XFORMINLINE
vec4f_t
Transform_GetWorldScale (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
vec4f_t *worldScale = h->components[transform_type_worldScale];
return worldScale[transform->index];
return worldScale[ref->index];
}
XFORMINLINE
vec4f_t
Transform_Forward (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
return worldMatrix[transform->index][0];
return worldMatrix[ref->index][0];
}
XFORMINLINE
vec4f_t
Transform_Right (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
return -worldMatrix[transform->index][1];
return -worldMatrix[ref->index][1];
}
XFORMINLINE
vec4f_t
Transform_Up (const transform_t *transform)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
return worldMatrix[transform->index][2];
return worldMatrix[ref->index][2];
}
///@}

View file

@ -10,9 +10,9 @@
typedef struct scene_resources_s {
PR_RESMAP (entity_t) entities;
PR_RESMAP (hierarchy_t) hierarchies;
PR_RESMAP (transform_t) transforms;
PR_RESMAP (hierref_t) transforms;
} scene_resources_t;
transform_t *__transform_alloc (struct scene_s *scene);
hierref_t *__transform_alloc (struct scene_s *scene);
#endif//__scn_internal_h

View file

@ -93,9 +93,8 @@ rua__scene_get (rua_scene_resources_t *res, pr_ulong_t id, const char *name)
{
rua_scene_t *scene = 0;
if (id <= 0xffffffffu) {
scene = PR_RESGET (res->scene_map, (pr_int_t) id);
}
id &= 0xffffffffu;
scene = PR_RESGET (res->scene_map, (pr_int_t) id);
// scene->prev will be null if the handle is unallocated
if (!scene || !scene->prev) {
@ -288,7 +287,7 @@ bi_Entity_GetTransform (progs_t *pr, void *_res)
entity_t *ent = rua_entity_get (res, ent_id);
// ent_id contains scene id
R_ULONG (pr) = MAKE_ID (ent->transform->id, ent_id);
R_ULONG (pr) = MAKE_ID (ent->transform->ref.id, ent_id);
}
static void
@ -324,7 +323,7 @@ bi_Transform_GetChild (progs_t *pr, void *_res)
transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0));
transform_t *child = Transform_GetChild (transform, P_UINT (pr, 2));
R_UINT (pr) = child ? child->id : 0;
R_UINT (pr) = child ? child->ref.id : 0;
}
static void
@ -333,8 +332,9 @@ bi_Transform_SetParent (progs_t *pr, void *_res)
rua_scene_resources_t *res = _res;
transform_t *transform = rua_transform_get (res, P_ULONG (pr, 0));
transform_t *parent = rua_transform_get (res, P_ULONG (pr, 1));
rua_scene_t *scene = rua_scene_get (res, P_ULONG (pr, 1));
Transform_SetParent (transform, parent);
Transform_SetParent (scene->scene, transform, parent);
}
static void
@ -346,7 +346,7 @@ bi_Transform_GetParent (progs_t *pr, void *_res)
transform_t *parent = Transform_GetParent (transform);
// transform_id contains scene id
R_ULONG (pr) = parent ? MAKE_ID (parent->id, transform_id) : 0;
R_ULONG (pr) = parent ? MAKE_ID (parent->ref.id, transform_id) : 0;
}
static void

View file

@ -41,7 +41,7 @@ void
Camera_GetViewMatrix (const camera_t *camera, mat4f_t view)
{
scene_resources_t *res = camera->scene->resources;
transform_t *transform = PR_RESGET (res->transforms, camera->transform);
transform_t *transform = (transform_t *) PR_RESGET (res->transforms, camera->transform);
vec4f_t rotation = Transform_GetWorldRotation (transform);
vec4f_t position = Transform_GetWorldPosition (transform);
mat4fquat (view, qconjf (rotation));

View file

@ -41,7 +41,7 @@
#include "scn_internal.h"
static component_t transform_component = { .size = sizeof (transform_t *) };
static component_t ref_component = { .size = sizeof (hierref_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) };
@ -52,8 +52,8 @@ hierarchy_UpdateTransformIndices (hierarchy_t *hierarchy, uint32_t start,
int offset)
{
for (size_t i = start; i < hierarchy->num_objects; i++) {
if (hierarchy->transform[i]) {
hierarchy->transform[i]->index += offset;
if (hierarchy->ref[i]) {
hierarchy->ref[i]->index += offset;
}
}
}
@ -84,8 +84,8 @@ Hierarchy_Reserve (hierarchy_t *hierarchy, uint32_t count)
new_max += 15;
new_max &= ~15;
Component_ResizeArray (&transform_component,
(void **) &hierarchy->transform, new_max);
Component_ResizeArray (&ref_component,
(void **) &hierarchy->ref, new_max);
Component_ResizeArray (&entity_component,
(void **) &hierarchy->entity, new_max);
Component_ResizeArray (&childCount_component,
@ -111,8 +111,8 @@ hierarchy_open (hierarchy_t *hierarchy, uint32_t index, uint32_t 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 (&ref_component,
hierarchy->ref, dstIndex, index, count);
Component_MoveElements (&entity_component,
hierarchy->entity, dstIndex, index, count);
Component_MoveElements (&childCount_component,
@ -137,8 +137,8 @@ hierarchy_close (hierarchy_t *hierarchy, uint32_t index, uint32_t count)
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 (&ref_component,
hierarchy->ref, index, srcIndex, count);
Component_MoveElements (&entity_component,
hierarchy->entity, index, srcIndex, count);
Component_MoveElements (&childCount_component,
@ -158,20 +158,20 @@ static void
hierarchy_move (hierarchy_t *dst, const hierarchy_t *src,
uint32_t dstIndex, uint32_t srcIndex, uint32_t count)
{
Component_CopyElements (&transform_component,
dst->transform, dstIndex,
src->transform, srcIndex, count);
Component_CopyElements (&ref_component,
dst->ref, dstIndex,
src->ref, 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]));
memset (&src->ref[srcIndex], 0, count * sizeof(dst->ref[0]));
for (uint32_t i = 0; i < count; i++) {
dst->transform[dstIndex + i]->hierarchy = dst;
dst->transform[dstIndex + i]->index = dstIndex + i;
dst->ref[dstIndex + i]->hierarchy = dst;
dst->ref[dstIndex + i]->index = dstIndex + i;
}
for (uint32_t i = 0; i < dst->type->num_components; i++) {
Component_CopyElements (&dst->type->components[i],
@ -184,8 +184,7 @@ static void
hierarchy_init (hierarchy_t *dst, uint32_t index,
uint32_t parentIndex, uint32_t childIndex, uint32_t count)
{
memset (&dst->transform[index], 0,
count * sizeof(dst->transform[0]));
memset (&dst->ref[index], 0, count * sizeof(dst->ref[0]));
for (uint32_t i = 0; i < count; i++) {
dst->parentIndex[index + i] = parentIndex;
@ -271,13 +270,13 @@ Hierarchy_InsertHierarchy (hierarchy_t *dst, const hierarchy_t *src,
{
uint32_t insertIndex;
if (dstParent == null_transform) {
if (dstParent == nullent) {
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[0] = null_transform;
dst->parentIndex[0] = nullent;
dst->childIndex[0] = 1;
dst->childCount[0] = 0;
insertIndex = 0;
@ -300,9 +299,9 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index)
uint32_t childIndex = hierarchy->childIndex[index];
uint32_t childCount = hierarchy->childCount[index];
uint32_t parentIndex = hierarchy->parentIndex[index];
uint32_t nieceIndex = null_transform;
uint32_t nieceIndex = nullent;
if (parentIndex != null_transform) {
if (parentIndex != nullent) {
uint32_t siblingIndex = hierarchy->childIndex[parentIndex];
siblingIndex += hierarchy->childCount[parentIndex] - 1;
nieceIndex = hierarchy->childIndex[siblingIndex];
@ -316,7 +315,7 @@ hierarchy_remove_children (hierarchy_t *hierarchy, uint32_t index)
if (childCount) {
hierarchy_UpdateTransformIndices (hierarchy, childIndex, -childCount);
hierarchy_UpdateChildIndices (hierarchy, index, -childCount);
if (nieceIndex != null_transform) {
if (nieceIndex != nullent) {
hierarchy_UpdateParentIndices (hierarchy, nieceIndex, -childCount);
}
}
@ -327,13 +326,13 @@ Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index)
{
uint32_t parentIndex = hierarchy->parentIndex[index];
uint32_t childIndex = hierarchy->childIndex[index];
uint32_t siblingIndex = null_transform;
if (parentIndex != null_transform) {
uint32_t siblingIndex = nullent;
if (parentIndex != nullent) {
siblingIndex = hierarchy->childIndex[parentIndex];
}
hierarchy_remove_children (hierarchy, index);
hierarchy_close (hierarchy, index, 1);
if (siblingIndex != null_transform) {
if (siblingIndex != nullent) {
hierarchy_UpdateTransformIndices (hierarchy, index, -1);
hierarchy_UpdateChildIndices (hierarchy, siblingIndex, -1);
hierarchy_UpdateParentIndices (hierarchy, childIndex - 1, -1);
@ -360,7 +359,7 @@ Hierarchy_New (scene_t *scene, const hierarchy_type_t *type, int createRoot)
if (createRoot) {
hierarchy_open (hierarchy, 0, 1);
hierarchy_init (hierarchy, 0, null_transform, 1, 1);
hierarchy_init (hierarchy, 0, nullent, 1, 1);
}
return hierarchy;
@ -376,9 +375,9 @@ Hierarchy_Delete (hierarchy_t *hierarchy)
scene_resources_t *res = hierarchy->scene->resources;
for (uint32_t i = 0; i < hierarchy->num_objects; i++) {
PR_RESFREE (res->transforms, hierarchy->transform[i]);
PR_RESFREE (res->transforms, hierarchy->ref[i]);
}
free (hierarchy->transform);
free (hierarchy->ref);
free (hierarchy->childCount);
free (hierarchy->childIndex);
free (hierarchy->parentIndex);
@ -399,9 +398,9 @@ Hierarchy_Copy (scene_t *scene, const hierarchy_t *src)
Hierarchy_Reserve (dst, count);
for (size_t i = 0; i < count; i++) {
dst->transform[i] = __transform_alloc (scene);
dst->transform[i]->hierarchy = dst;
dst->transform[i]->index = i;
dst->ref[i] = __transform_alloc (scene);
dst->ref[i]->hierarchy = dst;
dst->ref[i]->index = i;
}
Component_CopyElements (&childCount_component,

View file

@ -140,8 +140,8 @@ Scene_CreateEntity (scene_t *scene)
ent->transform = Transform_New (scene, 0);
ent->id = PR_RESINDEX (res->entities, ent);
hierarchy_t *h = ent->transform->hierarchy;
h->entity[ent->transform->index] = ent;
hierarchy_t *h = ent->transform->ref.hierarchy;
h->entity[ent->transform->ref.index] = ent;
QuatSet (1, 1, 1, 1, ent->renderer.colormod);
@ -164,13 +164,13 @@ 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;
hierarchy_t *h = transform->ref.hierarchy;
for (size_t i = 0; i < h->num_objects; i++) {
entity_t *e = h->entity[0];
e->transform = 0;
PR_RESFREE (res->entities, ent);
}
Transform_Delete (transform);
Transform_Delete (scene, transform);
}
void
@ -183,7 +183,7 @@ Scene_DestroyEntity (scene_t *scene, entity_t *ent)
}
// pull the transform out of the hierarchy to make it easier to destory
// all the child entities
Transform_SetParent (ent->transform, 0);
Transform_SetParent (scene, ent->transform, 0);
destroy_entity (scene, ent);
}
@ -204,5 +204,5 @@ transform_t *
Scene_GetTransform (scene_t *scene, int id)
{
scene_resources_t *res = scene->resources;
return PR_RESGET (res->transforms, id);
return (transform_t *) PR_RESGET (res->transforms, id);
}

View file

@ -6,6 +6,7 @@
#include <string.h>
#include <unistd.h>
#include "QF/scene/component.h"
#include "QF/scene/hierarchy.h"
#include "QF/scene/scene.h"
#include "QF/scene/transform.h"
@ -49,7 +50,7 @@ check_hierarchy_size (hierarchy_t *h, uint32_t size)
}
char **name = h->components[transform_type_name];
for (uint32_t i = 0; i < h->num_objects; i++) {
if (h->transform[i]->hierarchy != h) {
if (h->ref[i]->hierarchy != h) {
printf ("transform %d (%s) does not point to hierarchy\n",
i, name[i]);
}
@ -63,7 +64,7 @@ dump_hierarchy (hierarchy_t *h)
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->ref[i]->index, h->parentIndex[i],
h->childIndex[i], h->childCount[i]);
}
puts ("");
@ -73,12 +74,13 @@ static int
check_indices (transform_t *transform, uint32_t index, uint32_t parentIndex,
uint32_t childIndex, uint32_t childCount)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = &transform->ref;
hierarchy_t *h = ref->hierarchy;
char **name = h->components[transform_type_name];
if (transform->index != index) {
if (ref->index != index) {
printf ("%s/%s index incorrect: expect %u got %u\n",
name[transform->index], name[index],
index, transform->index);
name[ref->index], name[index],
index, ref->index);
return 0;
}
if (h->parentIndex[index] != parentIndex) {
@ -109,7 +111,7 @@ test_single_transform (void)
printf ("Transform_New returned null\n");
return 1;
}
if (!(h = transform->hierarchy)) {
if (!(h = transform->ref.hierarchy)) {
printf ("New transform has no hierarchy\n");
return 1;
}
@ -120,7 +122,7 @@ test_single_transform (void)
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 (!check_indices (transform, 0, nullent, 1, 0)) { return 1; }
if (!mat4_equal (localMatrix[0], identity)
|| !mat4_equal (localInverse[0], identity)
@ -137,7 +139,7 @@ test_single_transform (void)
}
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (transform->hierarchy);
Hierarchy_Delete (transform->ref.hierarchy);
return 0;
}
@ -148,17 +150,17 @@ test_parent_child_init (void)
transform_t *parent = Transform_New (scene, 0);
transform_t *child = Transform_New (scene, parent);
if (parent->hierarchy != child->hierarchy) {
if (parent->ref.hierarchy != child->ref.hierarchy) {
printf ("parent and child transforms have separate hierarchies\n");
return 1;
}
if (!check_hierarchy_size (parent->hierarchy, 2)) { return 1; }
if (!check_hierarchy_size (parent->ref.hierarchy, 2)) { return 1; }
if (!check_indices (parent, 0, null_transform, 1, 1)) { return 1; }
if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; }
if (!check_indices (child, 1, 0, 2, 0)) { return 1; }
hierarchy_t *h = parent->hierarchy;
hierarchy_t *h = parent->ref.hierarchy;
mat4f_t *localMatrix = h->components[transform_type_localMatrix];
mat4f_t *localInverse = h->components[transform_type_localInverse];
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
@ -194,7 +196,7 @@ test_parent_child_init (void)
}
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (parent->hierarchy);
Hierarchy_Delete (parent->ref.hierarchy);
return 0;
}
@ -208,28 +210,28 @@ test_parent_child_setparent (void)
Transform_SetName (parent, "parent");
Transform_SetName (child, "child");
if (!check_indices (parent, 0, null_transform, 1, 0)) { return 1; }
if (!check_indices (child, 0, null_transform, 1, 0)) { return 1; }
if (!check_indices (parent, 0, nullent, 1, 0)) { return 1; }
if (!check_indices (child, 0, nullent, 1, 0)) { return 1; }
if (parent->hierarchy == child->hierarchy) {
if (parent->ref.hierarchy == child->ref.hierarchy) {
printf ("parent and child transforms have same hierarchy before"
" set paret\n");
return 1;
}
Transform_SetParent (child, parent);
Transform_SetParent (scene,child, parent);
if (parent->hierarchy != child->hierarchy) {
if (parent->ref.hierarchy != child->ref.hierarchy) {
printf ("parent and child transforms have separate hierarchies\n");
return 1;
}
if (!check_hierarchy_size (parent->hierarchy, 2)) { return 1; }
if (!check_hierarchy_size (parent->ref.hierarchy, 2)) { return 1; }
if (!check_indices (parent, 0, null_transform, 1, 1)) { return 1; }
if (!check_indices (parent, 0, nullent, 1, 1)) { return 1; }
if (!check_indices (child, 1, 0, 2, 0)) { return 1; }
hierarchy_t *h = parent->hierarchy;
hierarchy_t *h = parent->ref.hierarchy;
mat4f_t *localMatrix = h->components[transform_type_localMatrix];
mat4f_t *localInverse = h->components[transform_type_localInverse];
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
@ -265,7 +267,7 @@ test_parent_child_setparent (void)
}
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (parent->hierarchy);
Hierarchy_Delete (parent->ref.hierarchy);
return 0;
}
@ -280,14 +282,14 @@ test_build_hierarchy (void)
transform_t *B = Transform_NewNamed (scene, root, "B");
transform_t *C = Transform_NewNamed (scene, root, "C");
if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 3)) { return 1; }
if (!check_indices (A, 1, 0, 4, 0)) { return 1; }
if (!check_indices (B, 2, 0, 4, 0)) { return 1; }
if (!check_indices (C, 3, 0, 4, 0)) { return 1; }
transform_t *B1 = Transform_NewNamed (scene, B, "B1");
if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 3)) { return 1; }
if (!check_indices ( A, 1, 0, 4, 0)) { return 1; }
if (!check_indices ( B, 2, 0, 4, 1)) { return 1; }
if (!check_indices ( C, 3, 0, 5, 0)) { return 1; }
@ -295,7 +297,7 @@ test_build_hierarchy (void)
transform_t *A1 = Transform_NewNamed (scene, A, "A1");
if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 3)) { return 1; }
if (!check_indices ( A, 1, 0, 4, 1)) { return 1; }
if (!check_indices ( B, 2, 0, 5, 1)) { return 1; }
if (!check_indices ( C, 3, 0, 6, 0)) { return 1; }
@ -307,9 +309,9 @@ test_build_hierarchy (void)
transform_t *B3 = Transform_NewNamed (scene, B, "B3");
transform_t *B2a = Transform_NewNamed (scene, B2, "B2a");
if (!check_hierarchy_size (root->hierarchy, 11)) { return 1; }
if (!check_hierarchy_size (root->ref.hierarchy, 11)) { return 1; }
if (!check_indices (root, 0, null_transform, 1, 3)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 3)) { return 1; }
if (!check_indices ( A, 1, 0, 4, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 6, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 9, 0)) { return 1; }
@ -323,9 +325,9 @@ test_build_hierarchy (void)
transform_t *D = Transform_NewNamed (scene, root, "D");
if (!check_hierarchy_size (root->hierarchy, 12)) { return 1; }
if (!check_hierarchy_size (root->ref.hierarchy, 12)) { return 1; }
if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 10, 0)) { return 1; }
@ -338,12 +340,12 @@ test_build_hierarchy (void)
if (!check_indices (A1a, 10, 5, 12, 0)) { return 1; }
if (!check_indices (B2a, 11, 8, 12, 0)) { return 1; }
dump_hierarchy (root->hierarchy);
dump_hierarchy (root->ref.hierarchy);
transform_t *C1 = Transform_NewNamed (scene, C, "C1");
dump_hierarchy (root->hierarchy);
if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; }
dump_hierarchy (root->ref.hierarchy);
if (!check_hierarchy_size (root->ref.hierarchy, 13)) { return 1; }
if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 10, 1)) { return 1; }
@ -358,7 +360,7 @@ test_build_hierarchy (void)
if (!check_indices (B2a, 12, 8, 13, 0)) { return 1; }
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (root->hierarchy);
Hierarchy_Delete (root->ref.hierarchy);
return 0;
}
@ -382,9 +384,9 @@ test_build_hierarchy2 (void)
transform_t *D = Transform_NewNamed (scene, root, "D");
transform_t *C1 = Transform_NewNamed (scene, C, "C1");
if (!check_hierarchy_size (root->hierarchy, 13)) { return 1; }
if (!check_hierarchy_size (root->ref.hierarchy, 13)) { return 1; }
if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 3)) { return 1; }
if (!check_indices ( C, 3, 0, 10, 1)) { return 1; }
@ -411,10 +413,10 @@ test_build_hierarchy2 (void)
transform_t *Y2a = Transform_NewNamed (scene, Y2, "Y2a");
transform_t *Z1 = Transform_NewNamed (scene, Z, "Z1");
dump_hierarchy (T->hierarchy);
if (!check_hierarchy_size (T->hierarchy, 12)) { return 1; }
dump_hierarchy (T->ref.hierarchy);
if (!check_hierarchy_size (T->ref.hierarchy, 12)) { return 1; }
if (!check_indices ( T, 0, null_transform, 1, 3)) { return 1; }
if (!check_indices ( T, 0, nullent, 1, 3)) { return 1; }
if (!check_indices ( X, 1, 0, 4, 2)) { return 1; }
if (!check_indices ( Y, 2, 0, 6, 3)) { return 1; }
if (!check_indices ( Z, 3, 0, 9, 1)) { return 1; }
@ -427,13 +429,13 @@ test_build_hierarchy2 (void)
if (!check_indices (X1a, 10, 4, 12, 0)) { return 1; }
if (!check_indices (Y2a, 11, 7, 12, 0)) { return 1; }
Transform_SetParent (T, B);
Transform_SetParent (scene,T, B);
dump_hierarchy (root->hierarchy);
dump_hierarchy (root->ref.hierarchy);
if (!check_hierarchy_size (root->hierarchy, 25)) { return 1; }
if (!check_hierarchy_size (root->ref.hierarchy, 25)) { return 1; }
if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 4)) { return 1; }
if (!check_indices ( C, 3, 0, 11, 1)) { return 1; }
@ -459,14 +461,14 @@ test_build_hierarchy2 (void)
if (!check_indices (X1a, 23, 17, 25, 0)) { return 1; }
if (!check_indices (Y2a, 24, 20, 25, 0)) { return 1; }
Transform_SetParent (Y, 0);
Transform_SetParent (scene,Y, 0);
dump_hierarchy (root->hierarchy);
dump_hierarchy (Y->hierarchy);
if (!check_hierarchy_size (root->hierarchy, 20)) { return 1; }
if (!check_hierarchy_size (Y->hierarchy, 5)) { return 1; }
dump_hierarchy (root->ref.hierarchy);
dump_hierarchy (Y->ref.hierarchy);
if (!check_hierarchy_size (root->ref.hierarchy, 20)) { return 1; }
if (!check_hierarchy_size (Y->ref.hierarchy, 5)) { return 1; }
if (!check_indices (root, 0, null_transform, 1, 4)) { return 1; }
if (!check_indices (root, 0, nullent, 1, 4)) { return 1; }
if (!check_indices ( A, 1, 0, 5, 2)) { return 1; }
if (!check_indices ( B, 2, 0, 7, 4)) { return 1; }
if (!check_indices ( C, 3, 0, 11, 1)) { return 1; }
@ -487,15 +489,15 @@ test_build_hierarchy2 (void)
if (!check_indices ( Z1, 18, 15, 20, 0)) { return 1; }
if (!check_indices (X1a, 19, 16, 20, 0)) { return 1; }
if (!check_indices ( Y, 0, null_transform, 1, 3)) { return 1; }
if (!check_indices ( Y, 0, nullent, 1, 3)) { return 1; }
if (!check_indices ( Y1, 1, 0, 4, 0)) { return 1; }
if (!check_indices ( Y2, 2, 0, 4, 1)) { return 1; }
if (!check_indices ( Y3, 3, 0, 5, 0)) { return 1; }
if (!check_indices (Y2a, 4, 2, 5, 0)) { return 1; }
// Delete the hierarchy directly as setparent isn't fully tested
Hierarchy_Delete (root->hierarchy);
Hierarchy_Delete (Y->hierarchy);
Hierarchy_Delete (root->ref.hierarchy);
Hierarchy_Delete (Y->ref.hierarchy);
return 0;
}
@ -534,7 +536,7 @@ test_frames (void)
Transform_SetLocalPosition (B1, (vec4f_t) { 0, 1, 0, 1 });
Transform_SetLocalRotation (B1, (vec4f_t) { -0.5, 0.5, -0.5, 0.5 });
hierarchy_t *h = root->hierarchy;
hierarchy_t *h = root->ref.hierarchy;
mat4f_t *localMatrix = h->components[transform_type_localMatrix];
mat4f_t *localInverse = h->components[transform_type_localInverse];
mat4f_t *worldMatrix = h->components[transform_type_worldMatrix];
@ -704,7 +706,7 @@ test_frames (void)
return 1;
}
Transform_Delete (root);
Transform_Delete (scene,root);
return 0;
}

View file

@ -133,16 +133,15 @@ static const hierarchy_type_t transform_type = {
.components = transform_components,
};
transform_t *
hierref_t *
__transform_alloc (scene_t *scene)
{
scene_resources_t *res = scene->resources;
transform_t *transform = PR_RESNEW_NC (res->transforms);
transform->scene = scene;
transform->id = PR_RESINDEX (res->transforms, transform);
transform->hierarchy = 0;
transform->index = 0;
return transform;
hierref_t *ref = PR_RESNEW_NC (res->transforms);
ref->id = PR_RESINDEX (res->transforms, ref);
ref->hierarchy = 0;
ref->index = 0;
return ref;
}
static void
@ -235,31 +234,32 @@ Transform_UpdateMatrices (hierarchy_t *h)
transform_t *
Transform_New (scene_t *scene, transform_t *parent)
{
transform_t *transform = __transform_alloc (scene);
hierref_t *transform = __transform_alloc (scene);
__auto_type ref = (hierref_t *) transform;
if (parent) {
transform->hierarchy = parent->hierarchy;
transform->index = Hierarchy_InsertHierarchy (parent->hierarchy, 0,
parent->index, 0);
ref->hierarchy = parent->ref.hierarchy;
ref->index = Hierarchy_InsertHierarchy (parent->ref.hierarchy, 0,
parent->ref.index, 0);
} else {
transform->hierarchy = Hierarchy_New (scene, &transform_type, 1);
transform->index = 0;
ref->hierarchy = Hierarchy_New (scene, &transform_type, 1);
ref->index = 0;
}
transform->hierarchy->transform[transform->index] = transform;
Transform_UpdateMatrices (transform->hierarchy);
return transform;
ref->hierarchy->ref[ref->index] = transform;
Transform_UpdateMatrices (ref->hierarchy);
return (transform_t *) transform;
}
void
Transform_Delete (transform_t *transform)
Transform_Delete (scene_t *scene, transform_t *transform)
{
if (transform->index != 0) {
if (transform->ref.index != 0) {
// The transform is not the root, so pull it out of its current
// hierarchy so deleting it is easier
Transform_SetParent (transform, 0);
Transform_SetParent (scene, transform, 0);
}
// Takes care of freeing the transforms
Hierarchy_Delete (transform->hierarchy);
Hierarchy_Delete (transform->ref.hierarchy);
}
transform_t *
@ -271,118 +271,125 @@ Transform_NewNamed (scene_t *scene, transform_t *parent, const char *name)
}
void
Transform_SetParent (transform_t *transform, transform_t *parent)
Transform_SetParent (scene_t *scene, transform_t *transform,
transform_t *parent)
{
if (parent) {
hierarchy_t *hierarchy = transform->hierarchy;
uint32_t index = transform->index;
Hierarchy_InsertHierarchy (parent->hierarchy, hierarchy,
parent->index, index);
hierarchy_t *hierarchy = transform->ref.hierarchy;
uint32_t index = transform->ref.index;
Hierarchy_InsertHierarchy (parent->ref.hierarchy, hierarchy,
parent->ref.index, index);
Hierarchy_RemoveHierarchy (hierarchy, index);
if (!hierarchy->num_objects) {
Hierarchy_Delete (hierarchy);
}
} else {
// null parent -> make transform root
if (!transform->index) {
if (!transform->ref.index) {
// already root
return;
}
hierarchy_t *hierarchy = transform->hierarchy;
uint32_t index = transform->index;
hierarchy_t *hierarchy = transform->ref.hierarchy;
uint32_t index = transform->ref.index;
hierarchy_t *new_hierarchy = Hierarchy_New (transform->scene,
&transform_type, 0);
Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, null_transform,
hierarchy_t *new_hierarchy = Hierarchy_New (scene, &transform_type, 0);
Hierarchy_InsertHierarchy (new_hierarchy, hierarchy, nullent,
index);
Hierarchy_RemoveHierarchy (hierarchy, index);
}
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
byte *modified = h->components[transform_type_modified];
modified[transform->index] = 1;
modified[ref->index] = 1;
Transform_UpdateMatrices (h);
}
void
Transform_SetName (transform_t *transform, const char *_name)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
char **name = h->components[transform_type_name];
//FIXME create a string pool (similar to qfcc's, or even move that to util)
if (name[transform->index]) {
free (name[transform->index]);
if (name[ref->index]) {
free (name[ref->index]);
}
name[transform->index] = strdup (_name);
name[ref->index] = strdup (_name);
}
void
Transform_SetTag (transform_t *transform, uint32_t _tag)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
uint32_t *tag = h->components[transform_type_tag];
tag[transform->index] = _tag;
tag[ref->index] = _tag;
}
void
Transform_SetLocalPosition (transform_t *transform, vec4f_t position)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->hierarchy;
mat4f_t *localMatrix = h->components[transform_type_localMatrix];
byte *modified = h->components[transform_type_modified];
localMatrix[transform->index][3] = position;
modified[transform->index] = 1;
localMatrix[ref->index][3] = position;
modified[ref->index] = 1;
Transform_UpdateMatrices (h);
}
void
Transform_SetLocalRotation (transform_t *transform, vec4f_t rotation)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->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];
vec4f_t scale = localScale[transform->index];
vec4f_t scale = localScale[ref->index];
mat4f_t mat;
mat4fquat (mat, rotation);
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;
localRotation[ref->index] = rotation;
localMatrix[ref->index][0] = mat[0] * scale[0];
localMatrix[ref->index][1] = mat[1] * scale[1];
localMatrix[ref->index][2] = mat[2] * scale[2];
modified[ref->index] = 1;
Transform_UpdateMatrices (h);
}
void
Transform_SetLocalScale (transform_t *transform, vec4f_t scale)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->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];
vec4f_t rotation = localRotation[transform->index];
vec4f_t rotation = localRotation[ref->index];
mat4f_t mat;
mat4fquat (mat, 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];
modified[transform->index] = 1;
localScale[ref->index] = scale;
localMatrix[ref->index][0] = mat[0] * scale[0];
localMatrix[ref->index][1] = mat[1] * scale[1];
localMatrix[ref->index][2] = mat[2] * scale[2];
modified[ref->index] = 1;
Transform_UpdateMatrices (h);
}
void
Transform_SetWorldPosition (transform_t *transform, vec4f_t position)
{
if (transform->index) {
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
if (ref->index) {
hierarchy_t *h = ref->hierarchy;
mat4f_t *worldInverse = h->components[transform_type_worldInverse];
uint32_t parent = h->parentIndex[transform->index];
uint32_t parent = h->parentIndex[ref->index];
position = mvmulf (worldInverse[parent], position);
}
Transform_SetLocalPosition (transform, position);
@ -391,10 +398,11 @@ Transform_SetWorldPosition (transform_t *transform, vec4f_t position)
void
Transform_SetWorldRotation (transform_t *transform, vec4f_t rotation)
{
if (transform->index) {
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
if (ref->index) {
hierarchy_t *h = ref->hierarchy;
vec4f_t *worldRotation = h->components[transform_type_worldRotation];
uint32_t parent = h->parentIndex[transform->index];
uint32_t parent = h->parentIndex[ref->index];
rotation = qmulf (qconjf (worldRotation[parent]), rotation);
}
Transform_SetLocalRotation (transform, rotation);
@ -404,7 +412,8 @@ void
Transform_SetLocalTransform (transform_t *transform, vec4f_t scale,
vec4f_t rotation, vec4f_t position)
{
hierarchy_t *h = transform->hierarchy;
__auto_type ref = (const hierref_t *) transform;
hierarchy_t *h = ref->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];
@ -413,12 +422,12 @@ Transform_SetLocalTransform (transform_t *transform, vec4f_t scale,
mat4fquat (mat, rotation);
position[3] = 1;
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;
localRotation[ref->index] = rotation;
localScale[ref->index] = scale;
localMatrix[ref->index][0] = mat[0] * scale[0];
localMatrix[ref->index][1] = mat[1] * scale[1];
localMatrix[ref->index][2] = mat[2] * scale[2];
localMatrix[ref->index][3] = position;
modified[ref->index] = 1;
Transform_UpdateMatrices (h);
}