97 lines
5 KiB
C
97 lines
5 KiB
C
#ifndef TRANSFORMABLE_H
|
|
#define TRANSFORMABLE_H
|
|
|
|
#include "scene.h"
|
|
#include "utils/mirror.h"
|
|
#include "utils/typeclass_helpers.h"
|
|
#include "raylib.h"
|
|
#include "raymath.h"
|
|
|
|
struct Transformable;
|
|
|
|
typedef struct ITransformable {
|
|
SceneNode *node;
|
|
Transform (*const get_transform)(void*);
|
|
void (*const set_transform)(void*, Transform);
|
|
Transform (*const get_global_transform)(void*);
|
|
void (*const set_global_transform)(void*, Transform);
|
|
void (*const force_update)(void*);
|
|
unsigned char (*const get_dirty_bit)(void*);
|
|
struct Transformable (*const get_parent_transformable)(void*);
|
|
} ITransformable;
|
|
|
|
typedef struct Transformable {
|
|
ITransformable const *tc;
|
|
void *data;
|
|
IMirror const *mirror;
|
|
ISceneNodeEntity const *scene_node_entity;
|
|
} Transformable;
|
|
|
|
extern Transform TransformIdentity();
|
|
extern Matrix TransformGetMatrix(Transform const *self);
|
|
|
|
extern Vector3 TransformPosition(Transform const *self, Vector3 local_pos);
|
|
extern Vector3 TransformDirection(Transform const *self, Vector3 local_direction);
|
|
extern Vector3 TransformScale(Transform const *self, Vector3 local_scale);
|
|
extern Quaternion TransformRotation(Transform const *self, Quaternion local_rotation);
|
|
extern Transform TransformTransform(Transform const *self, Transform const *other);
|
|
|
|
extern Vector3 InverseTransformPosition(Transform const *self, Vector3 global_pos);
|
|
extern Vector3 InverseTransformDirection(Transform const *self, Vector3 global_direction);
|
|
extern Vector3 InverseTransformScale(Transform const *self, Vector3 global_scale);
|
|
extern Quaternion InverseTransformRotation(Transform const *self, Quaternion quat);
|
|
extern Transform InverseTransformTransform(Transform const *self, Transform const *other);
|
|
|
|
#define MATRIX_UP(self_) ((Vector3){self_.m0, self_.m1, self_.m2})
|
|
#define MATRIX_RIGHT(self_) ((Vector3){self_.m4, self_.m5, self_.m6})
|
|
#define MATRIX_FORWARD(self_) ((Vector3){self_.m8, self_.m9, self_.m10})
|
|
|
|
#define VECTOR3_RIGHT ((Vector3){1.f, 0.f, 0.f})
|
|
#define VECTOR3_UP ((Vector3){0.f, 1.f, 0.f})
|
|
#define VECTOR3_FORWARD ((Vector3){0.f, 0.f, 1.f})
|
|
|
|
//! Defines the variables required to implement Transformable. Put at the start of a struct
|
|
#define ExtendsTransformable Transform transform; Transform global_transform; Transformable parent_transformable; unsigned char dirty_bit
|
|
|
|
//! Define transformable getter-setters for type T
|
|
//! Requires member variables: Transform transform; Transform global_transform; Transformable parent_transformable; unsigned char dirty_bit;
|
|
//! Macro implements the interface functions itself to ensure consistent behaviour.
|
|
#define impl_Transformable_for(T)\
|
|
static Transform T##_get_transform_GEN_(T* self) { return self->transform; }\
|
|
static void T##_set_transform_GEN_(T* self, Transform value) { self->transform = value; self->dirty_bit |= 0x1; } /*!< sets local dirty bit */\
|
|
static Transform T##_get_global_transform_GEN_(T* self) { return self->global_transform; }\
|
|
static void T##_set_global_transform_GEN_(T* self, Transform value) {\
|
|
self->global_transform = value;\
|
|
if(tc_is_null(self->parent_transformable)) {\
|
|
self->transform = value;\
|
|
} else {\
|
|
self->parent_transformable.tc->force_update(self->parent_transformable.data); /* Force a transform update for the parent, to ensure its global transform is up-to-date */\
|
|
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
|
self->transform = InverseTransformTransform(&parent_global, &value); /* Use up-to-date parent transform to get the local transform to the new global transform */\
|
|
}\
|
|
}\
|
|
static void T##_force_update_GEN_(T *self) {\
|
|
if(tc_is_null(self->parent_transformable)) {\
|
|
self->global_transform = self->transform;\
|
|
return;\
|
|
}\
|
|
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
|
self->global_transform = TransformTransform(&parent_global, &self->transform);\
|
|
}\
|
|
static unsigned char T##_get_dirty_bit_GEN_(T *self) { return self->dirty_bit; }\
|
|
static Transformable T##_get_parent_transformable_GEN_(T *self) { return self->parent_transformable; }\
|
|
Transformable T##_as_Transformable(T *x) {\
|
|
static ITransformable const tc = {\
|
|
.get_transform = (Transform (*const)(void*)) T##_get_transform_GEN_,\
|
|
.set_transform = (void (*const)(void*,Transform)) T##_set_transform_GEN_,\
|
|
.get_global_transform = (Transform (*const)(void*)) T##_get_global_transform_GEN_,\
|
|
.set_global_transform = (void (*const)(void*,Transform)) T##_set_global_transform_GEN_,\
|
|
.force_update = (void (*const)(void*)) T##_force_update_GEN_,\
|
|
.get_dirty_bit = (unsigned char (*const)(void*)) T##_get_dirty_bit_GEN_,\
|
|
.get_parent_transformable = (Transformable (*const)(void*)) T##_get_parent_transformable_GEN_\
|
|
};\
|
|
return (Transformable){ .tc = &tc, .data = x, .scene_node_entity = T##_as_SceneNodeEntity(x).tc, .mirror = T##_as_Mirror(x).tc };\
|
|
}
|
|
|
|
#endif // !TRANSFORMABLE_H
|