feat: implemented MeshRenderEntity
This commit is contained in:
parent
dda35f69f0
commit
2be8b21372
BIN
resources/spacefighter.glb
Normal file
BIN
resources/spacefighter.glb
Normal file
Binary file not shown.
|
@ -46,7 +46,7 @@ void CameraNodeExitTree(CameraNode *self) {
|
||||||
Camera3D CameraNodeGetCamera(CameraNode *self) {
|
Camera3D CameraNodeGetCamera(CameraNode *self) {
|
||||||
// Get the global transform matrix of the parent transformable
|
// Get the global transform matrix of the parent transformable
|
||||||
Transform global_transform = self->transform.tc->get_global_transform(self->transform.data);
|
Transform global_transform = self->transform.tc->get_global_transform(self->transform.data);
|
||||||
Matrix mat = TransformGetMatrix(&global_transform);
|
Matrix mat = TransformGetMatrix(global_transform);
|
||||||
// get the forward row from the matrix
|
// get the forward row from the matrix
|
||||||
Vector3 forward = MATRIX_FORWARD(mat);
|
Vector3 forward = MATRIX_FORWARD(mat);
|
||||||
// construct a new camera at the global transform location and facing the forward vector
|
// construct a new camera at the global transform location and facing the forward vector
|
||||||
|
|
50
src/core/mesh_render_entity.c
Normal file
50
src/core/mesh_render_entity.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#include "mesh_render_entity.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
|
START_REFLECT(MeshRenderEntity);
|
||||||
|
REFLECT_TYPECLASS(MeshRenderEntity, Drop);
|
||||||
|
REFLECT_TYPECLASS(MeshRenderEntity, SceneNodeEntity);
|
||||||
|
REFLECT_TYPECLASS(MeshRenderEntity, Renderable);
|
||||||
|
END_REFLECT(MeshRenderEntity);
|
||||||
|
|
||||||
|
impl_SceneNodeEntity_defaults(MeshRenderEntity)
|
||||||
|
impl_SceneNodeEntity_for(MeshRenderEntity,
|
||||||
|
MeshRenderEntityEnterTree,
|
||||||
|
MeshRenderEntityExitTree,
|
||||||
|
MeshRenderEntity_default_tick
|
||||||
|
)
|
||||||
|
|
||||||
|
impl_Drop_for(MeshRenderEntity,
|
||||||
|
DestroyMeshRenderEntity
|
||||||
|
)
|
||||||
|
|
||||||
|
impl_Renderable_for(MeshRenderEntity,
|
||||||
|
MeshRenderEntityDraw
|
||||||
|
)
|
||||||
|
|
||||||
|
SceneNode *CreateMeshRenderEntity(char const *resource_path) {
|
||||||
|
MeshRenderEntity *self = new(MeshRenderEntity);
|
||||||
|
GetModelResource(resource_path, &self->model);
|
||||||
|
return CreateSceneNode(MeshRenderEntity_as_SceneNodeEntity(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyMeshRenderEntity(MeshRenderEntity *self) {
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshRenderEntityEnterTree(MeshRenderEntity *self) {
|
||||||
|
SceneNodeEntity parent_entity = self->node->parent->entity;
|
||||||
|
self->transform = TC_CAST(parent_entity, Transformable);
|
||||||
|
LoadResource(self->model.handle);
|
||||||
|
AddRenderable(MeshRenderEntity_as_Renderable(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshRenderEntityExitTree(MeshRenderEntity *self) {
|
||||||
|
ReleaseResource(self->model.handle);
|
||||||
|
RemoveRenderable(MeshRenderEntity_as_Renderable(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshRenderEntityDraw(MeshRenderEntity *self) {
|
||||||
|
self->model.resource->transform = TransformGetMatrix(self->transform.tc->get_global_transform(self->transform.data));
|
||||||
|
DrawModel(*self->model.resource, (Vector3){0.f, 0.f, 0.f}, 1.f, WHITE);
|
||||||
|
}
|
30
src/core/mesh_render_entity.h
Normal file
30
src/core/mesh_render_entity.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef MESH_RENDER_ENTITY_H
|
||||||
|
#define MESH_RENDER_ENTITY_H
|
||||||
|
|
||||||
|
#include "renderable.h"
|
||||||
|
#include "resources.h"
|
||||||
|
#include "scene_node_entity.h"
|
||||||
|
#include "transformable.h"
|
||||||
|
#include "utils/drop.h"
|
||||||
|
#include "utils/mirror.h"
|
||||||
|
|
||||||
|
typedef struct MeshRenderEntity {
|
||||||
|
SceneNode *node;
|
||||||
|
Transformable transform;
|
||||||
|
ModelResource model;
|
||||||
|
} MeshRenderEntity;
|
||||||
|
|
||||||
|
extern SceneNode *CreateMeshRenderEntity(char const *resource_path);
|
||||||
|
extern void DestroyMeshRenderEntity(MeshRenderEntity *self);
|
||||||
|
|
||||||
|
extern void MeshRenderEntityEnterTree(MeshRenderEntity *self);
|
||||||
|
extern void MeshRenderEntityExitTree(MeshRenderEntity *self);
|
||||||
|
|
||||||
|
extern void MeshRenderEntityDraw(MeshRenderEntity *self);
|
||||||
|
|
||||||
|
DECL_REFLECT(MeshRenderEntity);
|
||||||
|
decl_typeclass_impl(Drop, MeshRenderEntity);
|
||||||
|
decl_typeclass_impl(SceneNodeEntity, MeshRenderEntity);
|
||||||
|
decl_typeclass_impl(Renderable, MeshRenderEntity);
|
||||||
|
|
||||||
|
#endif // !MESH_RENDER_ENTITY_H
|
|
@ -1,31 +1,178 @@
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "stdint.h"
|
#include "stdbool.h"
|
||||||
|
#include "utils/hash_map.h"
|
||||||
#include "utils/dictionary.h"
|
#include "utils/dictionary.h"
|
||||||
#include "utils/debug.h"
|
#include "utils/debug.h"
|
||||||
|
#include "utils/strutil.h"
|
||||||
|
|
||||||
char const *RESOURCE_DIRECTORY = "resources";
|
char const *RESOURCE_DIRECTORY = "resources";
|
||||||
|
|
||||||
|
typedef enum ResourceType {
|
||||||
|
RESOURCE_MODEL, RESOURCE_TEXTURE,
|
||||||
|
RESOURCE_MAX
|
||||||
|
} ResourceType;
|
||||||
|
|
||||||
|
typedef struct ResourceContainer {
|
||||||
|
char const *path;
|
||||||
|
char const *name;
|
||||||
|
unsigned use_counter;
|
||||||
|
bool is_loaded;
|
||||||
|
ResourceType type;
|
||||||
|
union {
|
||||||
|
Model model;
|
||||||
|
Texture texture;
|
||||||
|
};
|
||||||
|
} ResourceContainer;
|
||||||
|
|
||||||
|
typedef void (*LoadResourceFn)(ResourceContainer *resource);
|
||||||
|
typedef void (*UnloadResourceFn)(ResourceContainer *resource);
|
||||||
|
|
||||||
|
static void Internal_LoadModelResource(ResourceContainer *resource);
|
||||||
|
static void Internal_UnloadModelResource(ResourceContainer *resource);
|
||||||
|
static void Internal_LoadTextureResource(ResourceContainer *resource);
|
||||||
|
static void Internal_UnloadTextureResource(ResourceContainer *resource);
|
||||||
|
|
||||||
|
LoadResourceFn g_load_functions[] = {Internal_LoadModelResource, Internal_LoadTextureResource};
|
||||||
|
UnloadResourceFn g_unload_functions[] = {Internal_UnloadModelResource, Internal_UnloadTextureResource};
|
||||||
|
|
||||||
|
static HashMap g_resource_map;
|
||||||
|
static FilePathList g_resource_files;
|
||||||
|
|
||||||
|
//! hash function for hashmaps with char* as key type.
|
||||||
|
static uintptr_t HashMapHashString(char const **str_ptr) {
|
||||||
|
return strhash(*str_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Use file extensions to figure out the
|
||||||
|
static ResourceType ResourceGetTypeFromPath(char const *path) {
|
||||||
|
// Texture files
|
||||||
|
if(IsFileExtension(path, ".png")) return RESOURCE_TEXTURE;
|
||||||
|
if(IsFileExtension(path, ".jpg")) return RESOURCE_TEXTURE;
|
||||||
|
if(IsFileExtension(path, ".jpeg")) return RESOURCE_TEXTURE;
|
||||||
|
// Model files
|
||||||
|
if(IsFileExtension(path, ".glb")) return RESOURCE_MODEL;
|
||||||
|
if(IsFileExtension(path, ".gltf")) return RESOURCE_MODEL;
|
||||||
|
return RESOURCE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Find which resource directory to use: Relative to working directory, or relative to application directory
|
||||||
|
//! Working directory resources are only supposed to be used for debugging.
|
||||||
static inline
|
static inline
|
||||||
void InitializeResourceDirectory() {
|
void Internal_InitializeResourceDirectory() {
|
||||||
// if there is a resource directory in the working directory, prioritize that for debugging
|
// if there is a resource directory in the working directory, prioritize that for debugging
|
||||||
if(DirectoryExists(RESOURCE_DIRECTORY)) {
|
if(DirectoryExists(RESOURCE_DIRECTORY)) {
|
||||||
ChangeDirectory(TextFormat("%s/%s", GetWorkingDirectory(), RESOURCE_DIRECTORY));
|
ChangeDirectory(TextFormat("%s/%s", GetWorkingDirectory(), RESOURCE_DIRECTORY));
|
||||||
LOG_WARNING("Using working dir resources, this is possible for debug purposes.");
|
LOG_WARNING("Using working dir resources, this is intended for debug purposes only.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// check application installation directory for a resource directory
|
// check application installation directory for a resource directory
|
||||||
// this is the default running environment
|
// this is the default running environment
|
||||||
char const *installation_resource_dir = TextFormat(GetApplicationDirectory(), RESOURCE_DIRECTORY);
|
char const *installation_resource_dir = TextFormat("%s/%s", GetApplicationDirectory(), RESOURCE_DIRECTORY);
|
||||||
if(DirectoryExists(installation_resource_dir)) {
|
if(DirectoryExists(installation_resource_dir)) {
|
||||||
ChangeDirectory(installation_resource_dir);
|
ChangeDirectory(installation_resource_dir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UNREACHABLE("Failed to find resource directory");
|
UNREACHABLE("Failed to find a valid resource directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void Internal_IndexResourceDirectory() {
|
||||||
|
g_resource_files = LoadDirectoryFilesEx(GetWorkingDirectory(), NULL, true);
|
||||||
|
g_resource_map = hash_map_from_types(char const *, ResourceContainer, HashMapHashString);
|
||||||
|
ResourceContainer placeholder;
|
||||||
|
for(size_t i = 0; i < g_resource_files.count; ++i) {
|
||||||
|
placeholder = (ResourceContainer){
|
||||||
|
.is_loaded = false,
|
||||||
|
.use_counter = 0,
|
||||||
|
.path = g_resource_files.paths[i],
|
||||||
|
.name = GetFileName(g_resource_files.paths[i]),
|
||||||
|
.type = ResourceGetTypeFromPath(g_resource_files.paths[i])
|
||||||
|
};
|
||||||
|
// only index resources that the engine knows how to load
|
||||||
|
if(placeholder.type != RESOURCE_MAX) {
|
||||||
|
LOG_INFO("Internal_IndexResourceDirectory: Indexing %s as %s", placeholder.path, placeholder.name);
|
||||||
|
hash_map_insert(&g_resource_map, &placeholder.name, &placeholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeResourceSubsystem() {
|
void InitializeResourceSubsystem() {
|
||||||
InitializeResourceDirectory();
|
Internal_InitializeResourceDirectory();
|
||||||
|
Internal_IndexResourceDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CleanResourceSubsystem() {
|
void CleanResourceSubsystem() {
|
||||||
|
List resources = hash_map_values(&g_resource_map);
|
||||||
|
list_foreach(ResourceContainer *,resource, &resources)
|
||||||
|
g_unload_functions[resource->type](resource);
|
||||||
|
hash_map_empty(&g_resource_map);
|
||||||
|
UnloadDirectoryFiles(g_resource_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetModelResource(char const *path, ModelResource *out) {
|
||||||
|
ResourceContainer *container = hash_map_get_as(ResourceContainer, &g_resource_map, &path);
|
||||||
|
*out = ResourceEmpty(Model);
|
||||||
|
// assert some assumptions about the found resource
|
||||||
|
ASSERT_RETURN(container != NULL, false, "GetTextureResource: Resource %s not in index.", path);
|
||||||
|
ASSERT_RETURN(container->type == RESOURCE_MODEL, false, "GetTextureResource: Resource %s is not a Texture.", path);
|
||||||
|
++container->use_counter;
|
||||||
|
*out = (ModelResource) {
|
||||||
|
.handle = container,
|
||||||
|
.resource = &container->model
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetTextureResource(char const *path, TextureResource *out) {
|
||||||
|
ResourceContainer *container = hash_map_get_as(ResourceContainer, &g_resource_map, &path);
|
||||||
|
*out = ResourceEmpty(Texture);
|
||||||
|
// assert some assumptions about the found resource
|
||||||
|
ASSERT_RETURN(container != NULL, false, "GetTextureResource: Resource %s not in index.", path);
|
||||||
|
ASSERT_RETURN(container->type != RESOURCE_TEXTURE, false, "GetTextureResource: Resource %s is not a Texture.", path);
|
||||||
|
*out = (TextureResource) {
|
||||||
|
.handle = container,
|
||||||
|
.resource = &container->texture
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsResourceLoaded(ResourceHandle handle) {
|
||||||
|
return handle->is_loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadResource(ResourceHandle handle) {
|
||||||
|
ASSERT_RETURN(handle != NULL,, "LoadResource: Resource handle invalid");
|
||||||
|
g_load_functions[handle->type](handle);
|
||||||
|
handle->is_loaded = true;
|
||||||
|
++handle->use_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReleaseResource(ResourceHandle handle) {
|
||||||
|
ASSERT_RETURN(handle != NULL,, "ReleaseResource: Resource handle invalid");
|
||||||
|
ASSERT_RETURN_WARN(handle->is_loaded,, "ReleaseResource: Resource %s is not loaded.", handle->path);
|
||||||
|
g_unload_functions[handle->type](handle);
|
||||||
|
handle->is_loaded = false;
|
||||||
|
--handle->use_counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void Internal_LoadModelResource(ResourceContainer *resource) {
|
||||||
|
resource->model = LoadModel(resource->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void Internal_UnloadModelResource(ResourceContainer *resource) {
|
||||||
|
UnloadModel(resource->model);
|
||||||
|
resource->model = (Model){0};
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void Internal_LoadTextureResource(ResourceContainer *resource) {
|
||||||
|
resource->texture = LoadTexture(resource->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void Internal_UnloadTextureResource(ResourceContainer *resource) {
|
||||||
|
UnloadTexture(resource->texture);
|
||||||
|
resource->texture = (Texture){0};
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,30 @@
|
||||||
#define RESOURCES_H
|
#define RESOURCES_H
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "stdbool.h"
|
||||||
|
|
||||||
|
typedef struct ResourceContainer* ResourceHandle;
|
||||||
|
#define ResourceType(T) typedef struct T##Resource { ResourceHandle handle; T *resource; } T##Resource
|
||||||
|
#define ResourceEmpty(T) ((T##Resource){.handle = NULL, .resource = NULL})
|
||||||
|
|
||||||
|
ResourceType(Model);
|
||||||
|
ResourceType(Texture);
|
||||||
|
|
||||||
//! Allocate and initialize memory required to operate resource subsystem
|
//! Allocate and initialize memory required to operate resource subsystem
|
||||||
extern void InitializeResourceSubsystem();
|
extern void InitializeResourceSubsystem();
|
||||||
//! Clean and shut down resource subsystem, all resource calls are invalid after this
|
//! Clean and shut down resource subsystem, all resource calls are invalid after this
|
||||||
extern void CleanResourceSubsystem();
|
extern void CleanResourceSubsystem();
|
||||||
|
//! Get model from resources.
|
||||||
|
extern bool GetModelResource(char const *path, ModelResource *out);
|
||||||
|
//! Get indexed texture from resources.
|
||||||
|
extern bool GetTextureResource(char const *path, TextureResource *out);
|
||||||
|
|
||||||
|
//! Check if a resource is loaded or not.
|
||||||
|
extern bool IsResourceLoaded(ResourceHandle handle);
|
||||||
|
//! Load a resource using a handle returned from Get{Type}Resource, increments use count.
|
||||||
|
extern void LoadResource(ResourceHandle resource);
|
||||||
|
//! Release a resource using a handle returned from Get{Type}Resource, increments use count.
|
||||||
|
extern void ReleaseResource(ResourceHandle handle);
|
||||||
|
|
||||||
#endif // !RESOURCES_H
|
#endif // !RESOURCES_H
|
||||||
|
|
|
@ -9,45 +9,45 @@ Transform TransformIdentity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Matrix TransformGetMatrix(Transform const *self) {
|
Matrix TransformGetMatrix(Transform self) {
|
||||||
Matrix mat = MatrixScale(self->scale.x, self->scale.y, self->scale.z);
|
Matrix mat = MatrixScale(self.scale.x, self.scale.y, self.scale.z);
|
||||||
mat = MatrixMultiply(mat, QuaternionToMatrix(self->rotation));
|
mat = MatrixMultiply(mat, QuaternionToMatrix(self.rotation));
|
||||||
mat.m12 = self->translation.x;
|
mat.m12 = self.translation.x;
|
||||||
mat.m13 = self->translation.y;
|
mat.m13 = self.translation.y;
|
||||||
mat.m14 = self->translation.z;
|
mat.m14 = self.translation.z;
|
||||||
return mat;
|
return mat;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 TransformPosition(Transform const *self, Vector3 local_pos) {
|
Vector3 TransformPosition(Transform self, Vector3 local_pos) {
|
||||||
return Vector3Add(TransformDirection(self, local_pos), self->translation);
|
return Vector3Add(TransformDirection(self, local_pos), self.translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 TransformDirection(Transform const *self, Vector3 local_direction) {
|
Vector3 TransformDirection(Transform self, Vector3 local_direction) {
|
||||||
Matrix const m = TransformGetMatrix(self);
|
Matrix const m = TransformGetMatrix(self);
|
||||||
return Vector3Add(Vector3Add(Vector3Scale(MATRIX_RIGHT(m), local_direction.x), Vector3Scale(MATRIX_UP(m), local_direction.y)), Vector3Scale(MATRIX_FORWARD(m), local_direction.z));
|
return Vector3Add(Vector3Add(Vector3Scale(MATRIX_RIGHT(m), local_direction.x), Vector3Scale(MATRIX_UP(m), local_direction.y)), Vector3Scale(MATRIX_FORWARD(m), local_direction.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 TransformScale(Transform const *self, Vector3 local_scale) {
|
Vector3 TransformScale(Transform self, Vector3 local_scale) {
|
||||||
return Vector3Multiply(self->scale, TransformDirection(self, local_scale));
|
return Vector3Multiply(self.scale, TransformDirection(self, local_scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion TransformRotation(Transform const *self, Quaternion local_rotation) {
|
Quaternion TransformRotation(Transform self, Quaternion local_rotation) {
|
||||||
return QuaternionMultiply(self->rotation, local_rotation);
|
return QuaternionMultiply(self.rotation, local_rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform TransformTransform(Transform const *self, Transform const *other) {
|
Transform TransformTransform(Transform self, Transform other) {
|
||||||
return (Transform) {
|
return (Transform) {
|
||||||
.translation = TransformPosition(self, other->translation),
|
.translation = TransformPosition(self, other.translation),
|
||||||
.scale = TransformScale(self, other->scale),
|
.scale = TransformScale(self, other.scale),
|
||||||
.rotation = TransformRotation(self, other->rotation)
|
.rotation = TransformRotation(self, other.rotation)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 InverseTransformPosition(Transform const *self, Vector3 global_pos) {
|
Vector3 InverseTransformPosition(Transform self, Vector3 global_pos) {
|
||||||
return Vector3Subtract(InverseTransformDirection(self, global_pos), self->translation);
|
return Vector3Subtract(InverseTransformDirection(self, global_pos), self.translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 InverseTransformDirection(Transform const *self, Vector3 global_direction) {
|
Vector3 InverseTransformDirection(Transform self, Vector3 global_direction) {
|
||||||
Matrix const mat = TransformGetMatrix(self);
|
Matrix const mat = TransformGetMatrix(self);
|
||||||
return (Vector3){
|
return (Vector3){
|
||||||
Vector3DotProduct(MATRIX_RIGHT(mat), Vector3Scale(VECTOR3_RIGHT, global_direction.x)),
|
Vector3DotProduct(MATRIX_RIGHT(mat), Vector3Scale(VECTOR3_RIGHT, global_direction.x)),
|
||||||
|
@ -56,18 +56,18 @@ Vector3 InverseTransformDirection(Transform const *self, Vector3 global_directio
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 InverseTransformScale(Transform const *self, Vector3 global_scale) {
|
Vector3 InverseTransformScale(Transform self, Vector3 global_scale) {
|
||||||
return Vector3Multiply(Vector3Invert(self->scale), InverseTransformDirection(self, global_scale));
|
return Vector3Multiply(Vector3Invert(self.scale), InverseTransformDirection(self, global_scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
Quaternion InverseTransformRotation(Transform const *self, Quaternion global_rotation) {
|
Quaternion InverseTransformRotation(Transform self, Quaternion global_rotation) {
|
||||||
return QuaternionMultiply(QuaternionInvert(self->rotation), global_rotation);
|
return QuaternionMultiply(QuaternionInvert(self.rotation), global_rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform InverseTransformTransform(Transform const *self, Transform const *other) {
|
Transform InverseTransformTransform(Transform self, Transform other) {
|
||||||
return (Transform) {
|
return (Transform) {
|
||||||
.translation = InverseTransformPosition(self, other->translation),
|
.translation = InverseTransformPosition(self, other.translation),
|
||||||
.scale = InverseTransformScale(self, other->scale),
|
.scale = InverseTransformScale(self, other.scale),
|
||||||
.rotation = InverseTransformRotation(self, other->rotation)
|
.rotation = InverseTransformRotation(self, other.rotation)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,19 +28,19 @@ typedef struct Transformable {
|
||||||
} Transformable;
|
} Transformable;
|
||||||
|
|
||||||
extern Transform TransformIdentity();
|
extern Transform TransformIdentity();
|
||||||
extern Matrix TransformGetMatrix(Transform const *self);
|
extern Matrix TransformGetMatrix(Transform self);
|
||||||
|
|
||||||
extern Vector3 TransformPosition(Transform const *self, Vector3 local_pos);
|
extern Vector3 TransformPosition(Transform self, Vector3 local_pos);
|
||||||
extern Vector3 TransformDirection(Transform const *self, Vector3 local_direction);
|
extern Vector3 TransformDirection(Transform self, Vector3 local_direction);
|
||||||
extern Vector3 TransformScale(Transform const *self, Vector3 local_scale);
|
extern Vector3 TransformScale(Transform self, Vector3 local_scale);
|
||||||
extern Quaternion TransformRotation(Transform const *self, Quaternion local_rotation);
|
extern Quaternion TransformRotation(Transform self, Quaternion local_rotation);
|
||||||
extern Transform TransformTransform(Transform const *self, Transform const *other);
|
extern Transform TransformTransform(Transform self, Transform other);
|
||||||
|
|
||||||
extern Vector3 InverseTransformPosition(Transform const *self, Vector3 global_pos);
|
extern Vector3 InverseTransformPosition(Transform self, Vector3 global_pos);
|
||||||
extern Vector3 InverseTransformDirection(Transform const *self, Vector3 global_direction);
|
extern Vector3 InverseTransformDirection(Transform self, Vector3 global_direction);
|
||||||
extern Vector3 InverseTransformScale(Transform const *self, Vector3 global_scale);
|
extern Vector3 InverseTransformScale(Transform self, Vector3 global_scale);
|
||||||
extern Quaternion InverseTransformRotation(Transform const *self, Quaternion quat);
|
extern Quaternion InverseTransformRotation(Transform self, Quaternion quat);
|
||||||
extern Transform InverseTransformTransform(Transform const *self, Transform const *other);
|
extern Transform InverseTransformTransform(Transform self, Transform other);
|
||||||
|
|
||||||
#define MATRIX_UP(self_) ((Vector3){self_.m0, self_.m1, self_.m2})
|
#define MATRIX_UP(self_) ((Vector3){self_.m0, self_.m1, self_.m2})
|
||||||
#define MATRIX_RIGHT(self_) ((Vector3){self_.m4, self_.m5, self_.m6})
|
#define MATRIX_RIGHT(self_) ((Vector3){self_.m4, self_.m5, self_.m6})
|
||||||
|
@ -66,7 +66,7 @@ static void T##_set_global_transform_GEN_(T* self, Transform value) {\
|
||||||
self->transform = value;\
|
self->transform = value;\
|
||||||
} else {\
|
} else {\
|
||||||
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
||||||
self->transform = InverseTransformTransform(&parent_global, &value); /* Use parent transform to transform the local transform to the new global transform */\
|
self->transform = InverseTransformTransform(parent_global, value); /* Use parent transform to transform the local transform to the new global transform */\
|
||||||
}\
|
}\
|
||||||
}\
|
}\
|
||||||
static void T##_force_update_GEN_(T *self) {\
|
static void T##_force_update_GEN_(T *self) {\
|
||||||
|
@ -75,7 +75,7 @@ static void T##_force_update_GEN_(T *self) {\
|
||||||
return;\
|
return;\
|
||||||
}\
|
}\
|
||||||
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
Transform parent_global = self->parent_transformable.tc->get_global_transform(self->parent_transformable.data);\
|
||||||
self->global_transform = TransformTransform(&parent_global, &self->transform);\
|
self->global_transform = TransformTransform(parent_global, self->transform);\
|
||||||
}\
|
}\
|
||||||
static unsigned char T##_get_dirty_bit_GEN_(T *self) { return self->dirty_bit; }\
|
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; }\
|
static Transformable T##_get_parent_transformable_GEN_(T *self) { return self->parent_transformable; }\
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "core/engine_loop.h"
|
#include "core/engine_loop.h"
|
||||||
#include "core/scene.h"
|
#include "core/scene.h"
|
||||||
#include "core/transform_node.h"
|
#include "core/transform_node.h"
|
||||||
|
#include "core/mesh_render_entity.h"
|
||||||
#include "utils/debug.h"
|
#include "utils/debug.h"
|
||||||
|
|
||||||
Scene *CreateInitialScene() {
|
Scene *CreateInitialScene() {
|
||||||
|
@ -28,6 +29,7 @@ Scene *CreateInitialScene() {
|
||||||
SceneNodeAddChild(camera_parent_parent, camera_parent);
|
SceneNodeAddChild(camera_parent_parent, camera_parent);
|
||||||
SceneNodeAddChild(camera_parent, CreateCameraNode());
|
SceneNodeAddChild(camera_parent, CreateCameraNode());
|
||||||
SceneNodeAddChild(camera_parent, CreateTestObject());
|
SceneNodeAddChild(camera_parent, CreateTestObject());
|
||||||
|
SceneNodeAddChild(root, CreateMeshRenderEntity("spacefighter.glb"));
|
||||||
return CreateScene(root);
|
return CreateScene(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue