mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 20:41:20 +00:00
[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:
parent
f16fc15605
commit
8464d71264
9 changed files with 763 additions and 501 deletions
124
include/QF/scene/component.h
Normal file
124
include/QF/scene/component.h
Normal 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
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
///@}
|
||||
|
|
|
@ -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
32
libs/scene/component.c
Normal 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"
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue