[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.
This commit is contained in:
Bill Currie 2022-10-10 02:00:33 +09:00
parent f16fc15605
commit 8464d71264
9 changed files with 763 additions and 501 deletions

View file

@ -0,0 +1,124 @@
/*
component.h
Component management
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
Author: Bill Currie <bill@taniwha.org>
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 <string.h>
#include <stdlib.h>
#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

View file

@ -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);

View file

@ -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];
}
///@}

View file

@ -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 \

32
libs/scene/component.c Normal file
View file

@ -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"

View file

@ -35,18 +35,25 @@
# include <strings.h>
#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;
}

View file

@ -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;

View file

@ -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,

View file

@ -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);
}