From c7c768682745a14c95c27c7c79c5ff43e7d33938 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Sep 2024 01:30:46 +0200 Subject: [PATCH] rotating cubes2 --- asset/Asset.h | 19 +-- asset/AssetManagementSystem.h | 1 - asset/AssetType.h | 4 +- camera/Camera.h | 12 +- entity/Entity.h | 89 ++++++++++++++ entity/EntityComponentSystem.h | 52 ++++++++ entity/EntityType.h | 21 ++++ gpuapi/opengl/ShaderUtils.h | 23 ++-- math/matrix/MatrixFloat32.h | 192 ++++++++++++++++++++++++----- math/matrix/QuaternionFloat32.h | 212 ++++++++++++++++++++++++++------ stdlib/HashMap.h | 24 ++++ stdlib/Mathtypes.h | 7 +- 12 files changed, 561 insertions(+), 95 deletions(-) create mode 100644 entity/Entity.h create mode 100644 entity/EntityComponentSystem.h create mode 100644 entity/EntityType.h diff --git a/asset/Asset.h b/asset/Asset.h index c8dadac..e897d5f 100644 --- a/asset/Asset.h +++ b/asset/Asset.h @@ -12,11 +12,12 @@ #include "../stdlib/Types.h" #include "../object/Vertex.h" #include "../stdlib/HashMap.h" +#include "AssetType.h" #define MAX_ASSET_NAME_LENGTH 32 struct Asset { - // The id is the same as its location in memory/in the ecs array + // The id is the same as its location in memory/in the ams array // This is is only an internal id and NOT the same as a db id (e.g. player id) uint64 internal_id; @@ -25,9 +26,9 @@ struct Asset { char name[MAX_ASSET_NAME_LENGTH]; - uint32 type; + AssetType type; - // Counts the references to this entity + // Counts the references to this asset // e.g. textures int reference_count; @@ -36,26 +37,26 @@ struct Asset { uint64 ram_size; uint64 vram_size; - // Usually 1 but in some cases an ECS may hold entities of variable chunk length + // Usually 1 but in some cases an ams may hold entities of variable chunk length // For textures for example a 128x128 is of size 1 but 256x256 is of size 4 uint32 size; // Describes if the memory is currently available in ram/vram - // E.g. a entity might be uploaded to the gpu and no longer held in ram (or the other way around) + // E.g. an asset might be uploaded to the gpu and no longer held in ram (or the other way around) bool is_ram; bool is_vram; Asset* next; Asset* prev; - // A entity can reference up to N other entities + // An asset can reference up to N other entities // This allows us to quickly update the other entities // Example: A player pulls N mobs // @bug This means there are hard limits on how many mobs can be pulled by a player - Asset* entity_references[50]; - bool free_entity_references[50]; + Asset* references[50]; + uint64 free_references; // bits show which is free - // Actual memory address + // Actual memory address and specific asset data byte* self; }; diff --git a/asset/AssetManagementSystem.h b/asset/AssetManagementSystem.h index afd23ef..46982aa 100644 --- a/asset/AssetManagementSystem.h +++ b/asset/AssetManagementSystem.h @@ -12,7 +12,6 @@ #include #include "../stdlib/Types.h" #include "Asset.h" -#include "AssetType.h" #include "../memory/ChunkMemory.h" #include "../utils/TestUtils.h" #include "../stdlib/HashMap.h" diff --git a/asset/AssetType.h b/asset/AssetType.h index 74a7ca5..4bbbb83 100644 --- a/asset/AssetType.h +++ b/asset/AssetType.h @@ -6,8 +6,8 @@ * @version 1.0.0 * @link https://jingga.app */ -#ifndef TOS_ASSET_TYPES_H -#define TOS_ASSET_TYPES_H +#ifndef TOS_ASSET_TYPE_H +#define TOS_ASSET_TYPE_H enum AssetType { ASSET_TYPE_OBJ, diff --git a/camera/Camera.h b/camera/Camera.h index f767a13..39eb3f8 100644 --- a/camera/Camera.h +++ b/camera/Camera.h @@ -22,20 +22,26 @@ struct Camera { v4_f32 orientation; float speed; + float sensitivity; float zoom; }; +void camera_look_at(Camera* camera, const v3_f32* at) +{ + +} + // you can have up to 4 camera movement inputs at the same time void camera_movement(Camera* camera, CameraMovement* movement, float dt) { f32 velocity = camera->speed * dt; bool has_pos = false; - v4_f32 pos; + v4_f32 pos = {}; bool has_view = false; - v3_f32 view; - v4_f32 quaternion; + v3_f32 view = {}; + v4_f32 quaternion = {}; for (int i = 0; i < 4; i++) { switch(movement[i]) { diff --git a/entity/Entity.h b/entity/Entity.h new file mode 100644 index 0000000..346eea8 --- /dev/null +++ b/entity/Entity.h @@ -0,0 +1,89 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_ENTITY_H +#define TOS_ENTITY_H + +#include "../stdlib/Types.h" +#include "../stdlib/HashMap.h" +#include "EntityType.h" + +#define MAX_ENTITY_NAME_LENGTH 32 + +struct Entity { + // The id is the same as its location in memory/in the ecs array + // This is is only an internal id and NOT the same as a db id (e.g. player id) + uint64 internal_id; + + EntityType type; + + // Counts the references to this entity + // e.g. textures + int reference_count; + + Entity* next; + Entity* prev; + + // A entity can reference up to N other entities + // This allows us to quickly update the other entities + // Example: A player pulls N mobs + // @bug This means there are hard limits on how many mobs can be pulled by a player + Entity* references[50]; + uint64 free_references; // bits show which is free + + Entity* schema; // This entity represents the schema for this entity (most likely stored in a separate ecs) + + // Actual memory address and specific entity data + byte* self; +}; + +struct EntitySchema { + // The id is the same as its location in memory/in the ecs array + // This is is only an internal id and NOT the same as a db id (e.g. player id) + uint64 internal_id; + + // Could be 0 if there is no official id + uint64 official_id; + + char name[MAX_ENTITY_NAME_LENGTH]; + + EntityType type; + + // Counts the references to this entity + // e.g. textures + int reference_count; + + // Describes how much ram/vram the asset uses + // E.g. vram_size = 0 but ram_size > 0 means that it never uses any gpu memory + uint64 ram_size; + uint64 vram_size; + + // Usually 1 but in some cases an ECS may hold entities of variable chunk length + // For textures for example a 128x128 is of size 1 but 256x256 is of size 4 + uint32 size; + + // Describes if the memory is currently available in ram/vram + // E.g. a entity might be uploaded to the gpu and no longer held in ram (or the other way around) + bool is_ram; + bool is_vram; + + EntitySchema* next; + EntitySchema* prev; + + // A entity can reference up to N other entities + // This allows us to quickly update the other entities + // Example: A player pulls N mobs + // @bug This means there are hard limits on how many mobs can be pulled by a player + Entity* references[50]; + uint64 free_references; // bits show which is free + + // Actual memory address and specific schema data + byte* self; +}; + +#endif \ No newline at end of file diff --git a/entity/EntityComponentSystem.h b/entity/EntityComponentSystem.h new file mode 100644 index 0000000..57dd586 --- /dev/null +++ b/entity/EntityComponentSystem.h @@ -0,0 +1,52 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_ENTITY_COMPONENT_SYSTEM_H +#define TOS_ENTITY_COMPONENT_SYSTEM_H + +#include +#include "../stdlib/Types.h" +#include "../memory/ChunkMemory.h" +#include "../utils/TestUtils.h" +#include "../stdlib/HashMap.h" + +#include "Entity.h" + +struct EntityComponentSystem { + // @question is this even necessary or could we integrate this directly into the system here? + HashMap hash_map; + + // The indices of entity_memory and entity_data_memory are always linked + + // General entity memory + ChunkMemory entity_memory; + + // Actual entity data + ChunkMemory entity_data_memory; + + Entity* first; + Entity* last; +}; + +struct EntitySchemaSystem { + // @question is this even necessary or could we integrate this directly into the system here? + HashMap hash_map; + + // The indices of entity_memory and entity_data_memory are always linked + + // General entity memory + ChunkMemory entity_memory; + + // Actual entity data + ChunkMemory entity_data_memory; + + EntitySchema* first; + EntitySchema* last; +}; + +#endif \ No newline at end of file diff --git a/entity/EntityType.h b/entity/EntityType.h new file mode 100644 index 0000000..58bf1ad --- /dev/null +++ b/entity/EntityType.h @@ -0,0 +1,21 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_ENTITY_TYPE_H +#define TOS_ENTITY_TYPE_H + +enum EntityType { + ENTITY_TYPE_MONSTER, + ENTITY_TYPE_NPC, + ENTITY_TYPE_PLAYER, + ENTITY_TYPE_ITEM, + ENTITY_TYPE_OBJ, + ENTITY_TYPE_SIZE +}; + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/ShaderUtils.h b/gpuapi/opengl/ShaderUtils.h index f6713ad..df72bd1 100644 --- a/gpuapi/opengl/ShaderUtils.h +++ b/gpuapi/opengl/ShaderUtils.h @@ -10,63 +10,64 @@ #define TOS_GPUAPI_OPENGL_SHADER_UTILS_H #include "../../stdlib/Types.h" +#include "../../math/matrix/MatrixFloat32.h" inline -void shader_set_value(OpenGL* gl, uint32 id, const char* name, bool value) +void shader_set_value(const OpenGL* gl, uint32 id, const char* name, bool value) { gl->glUniform1i(gl->glGetUniformLocation(id, name), (int) value); } inline -void shader_set_value(OpenGL* gl, uint32 id, const char* name, int value) +void shader_set_value(const OpenGL* gl, uint32 id, const char* name, int value) { gl->glUniform1i(gl->glGetUniformLocation(id, name), value); } inline -void shader_set_value(OpenGL* gl, uint32 id, const char* name, float value) +void shader_set_value(const OpenGL* gl, uint32 id, const char* name, float value) { gl->glUniform1f(gl->glGetUniformLocation(id, name), value); } inline -void shader_set_v2(OpenGL* gl, uint32 id, const char* name, float* value) +void shader_set_v2(const OpenGL* gl, uint32 id, const char* name, const float* value) { gl->glUniform2fv(gl->glGetUniformLocation(id, name), 1, value); } inline -void shader_set_v3(OpenGL* gl, uint32 id, const char* name, float* value) +void shader_set_v3(const OpenGL* gl, uint32 id, const char* name, const float* value) { gl->glUniform3fv(gl->glGetUniformLocation(id, name), 1, value); } inline -void shader_set_v4(OpenGL* gl, uint32 id, const char* name, float* value) +void shader_set_v4(const OpenGL* gl, uint32 id, const char* name, const float* value) { gl->glUniform4fv(gl->glGetUniformLocation(id, name), 1, value); } inline -void shader_set_m2(OpenGL* gl, uint32 id, const char* name, float* value) +void shader_set_m2(const OpenGL* gl, uint32 id, const char* name, const float* value) { gl->glUniformMatrix2fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value); } inline -void shader_set_m3(OpenGL* gl, uint32 id, const char* name, float* value) +void shader_set_m3(const OpenGL* gl, uint32 id, const char* name, const float* value) { gl->glUniformMatrix3fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value); } inline -void shader_set_m4(OpenGL* gl, uint32 id, const char* name, float* value) +void shader_set_m4(const OpenGL* gl, uint32 id, const char* name, const float* value) { gl->glUniformMatrix4fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value); } inline -void shader_check_link_errors(OpenGL* gl, uint32 id, char* log) +void shader_check_link_errors(const OpenGL* gl, uint32 id, char* log) { GLint success; gl->glGetProgramiv(id, GL_LINK_STATUS, &success); @@ -76,7 +77,7 @@ void shader_check_link_errors(OpenGL* gl, uint32 id, char* log) } inline -void shader_check_compile_errors(OpenGL* gl, uint32 id, char* log) +void shader_check_compile_errors(const OpenGL* gl, uint32 id, char* log) { GLint success; gl->glGetShaderiv(id, GL_COMPILE_STATUS, &success); diff --git a/math/matrix/MatrixFloat32.h b/math/matrix/MatrixFloat32.h index 1d23a3c..c1d3eeb 100644 --- a/math/matrix/MatrixFloat32.h +++ b/math/matrix/MatrixFloat32.h @@ -12,6 +12,7 @@ #include "../../stdlib/Intrinsics.h" #include "../../stdlib/Mathtypes.h" #include "../../utils/MathUtils.h" +#include "../../utils/TestUtils.h" #include void mat3_identity(float* matrix) @@ -58,6 +59,8 @@ void mat4_identity(__m128* matrix) // https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula void mat4_rotation(float* matrix, float x, float y, float z, float angle) { + ASSERT_SIMPLE(OMS_ABS(x * x + y * y + z * z - 1.0f) < 0.01) + // @todo replace with quaternions float s = sinf(angle); float c = cosf(angle); @@ -78,22 +81,52 @@ void mat4_rotation(float* matrix, float x, float y, float z, float angle) matrix[0] = mx * x + c; matrix[1] = mxy - zs; matrix[2] = mzx + ys; - matrix[3] = 0; + matrix[3] = 0.0f; matrix[4] = mxy + zs; matrix[5] = my * y + c; matrix[6] = myz - xs; - matrix[7] = 0; + matrix[7] = 0.0f; matrix[8] = mzx - ys; matrix[9] = myz + xs; matrix[10] = mz * z + c; - matrix[11] = 0; + matrix[11] = 0.0f; - matrix[12] = 0; - matrix[13] = 0; - matrix[14] = 0; - matrix[15] = 1; + matrix[12] = 0.0f; + matrix[13] = 0.0f; + matrix[14] = 0.0f; + matrix[15] = 1.0f; +} + +void mat4_rotation(float* matrix, float pitch, float yaw, float roll) +{ + float cos_pitch = cosf(pitch); + float sin_pitch = sinf(pitch); + float cos_yaw = cosf(yaw); + float sin_yaw = sinf(yaw); + float cos_roll = cosf(roll); + float sin_roll = sinf(roll); + + matrix[0] = cos_yaw * cos_roll; + matrix[1] = cos_yaw * sin_roll; + matrix[2] = -sin_yaw; + matrix[3] = 0.0f; + + matrix[4] = sin_pitch * sin_yaw * cos_roll - cos_pitch * sin_roll; + matrix[5] = sin_pitch * sin_yaw * sin_roll + cos_pitch * cos_roll; + matrix[6] = sin_pitch * cos_yaw; + matrix[7] = 0.0f; + + matrix[8] = cos_pitch * sin_yaw * cos_roll + sin_pitch * sin_roll; + matrix[9] = cos_pitch * sin_yaw * sin_roll - sin_pitch * cos_roll; + matrix[10] = cos_pitch * cos_yaw; + matrix[11] = 0.0f; + + matrix[12] = 0.0f; + matrix[13] = 0.0f; + matrix[14] = 0.0f; + matrix[15] = 1.0f; } void mat3vec3_mult(const float* matrix, const float* vector, float* result) @@ -253,25 +286,21 @@ void mat4mat4_mult(const float* a, const float* b, float* result, int steps = 8) ) ); } else { - // Row 0 result[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12]; result[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13]; result[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14]; result[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15]; - // Row 1 result[4] = a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12]; result[5] = a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13]; result[6] = a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14]; result[7] = a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15]; - // Row 2 result[8] = a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12]; result[9] = a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13]; result[10] = a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14]; result[11] = a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15]; - // Row 3 result[12] = a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12]; result[13] = a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13]; result[14] = a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14]; @@ -351,6 +380,8 @@ void mat4mat4_mult_sse(const __m128* a, const __m128* b_transpose, __m128* resul // @performance Consider to replace with 1d array void mat4_frustum_planes(float planes[6][4], float radius, float *matrix) { // @todo make this a setting + // @bug fix to row-major system + // @todo don't use 2d arrays float znear = 0.125; float zfar = radius * 32 + 64; @@ -442,25 +473,25 @@ void mat4_ortho( float tb_delta = top - bottom; float fn_delta = far_dist - near_dist; - matrix[0] = 2 / rl_delta; - matrix[1] = 0; - matrix[2] = 0; - matrix[3] = 0; + matrix[0] = 2.0f / rl_delta; + matrix[1] = 0.0f; + matrix[2] = 0.0f; + matrix[3] = 0.0f; - matrix[4] = 0; - matrix[5] = 2 / tb_delta; - matrix[6] = 0; - matrix[7] = 0; + matrix[4] = 0.0f; + matrix[5] = 2.0f / tb_delta; + matrix[6] = 0.0f; + matrix[7] = 0.0f; - matrix[8] = 0; - matrix[9] = 0; - matrix[10] = -2 / fn_delta; - matrix[11] = 0; + matrix[8] = 0.0f; + matrix[9] = 0.0f; + matrix[10] = -2.0f / fn_delta; + matrix[11] = 0.0f; matrix[12] = -(right + left) / rl_delta; matrix[13] = -(top + bottom) / tb_delta; matrix[14] = -(far_dist + near_dist) / fn_delta; - matrix[15] = 1; + matrix[15] = 1.0f; } void mat4_translate(float* matrix, float dx, float dy, float dz, int steps = 8) @@ -469,12 +500,115 @@ void mat4_translate(float* matrix, float dx, float dy, float dz, int steps = 8) memcpy(temp, matrix, sizeof(float) * 16); alignas(64) float translation_matrix[16]; - translation_matrix[0] = 1; translation_matrix[1] = 0; translation_matrix[2] = 0; translation_matrix[3] = 0; - translation_matrix[4] = 0; translation_matrix[5] = 1; translation_matrix[6] = 0; translation_matrix[7] = 0; - translation_matrix[8] = 0; translation_matrix[9] = 0; translation_matrix[10] = 1; translation_matrix[11] = 0; - translation_matrix[12] = dx; translation_matrix[13] = dy; translation_matrix[14] = dz; translation_matrix[15] = 1; + translation_matrix[0] = 1.0f; translation_matrix[1] = 0.0f; translation_matrix[2] = 0.0f; translation_matrix[3] = dx; + translation_matrix[4] = 0.0f; translation_matrix[5] = 1.0f; translation_matrix[6] = 0.0f; translation_matrix[7] = dy; + translation_matrix[8] = 0.0f; translation_matrix[9] = 0.0f; translation_matrix[10] = 1.0f; translation_matrix[11] = dz; + translation_matrix[12] = 0.0f; translation_matrix[13] = 0.0f; translation_matrix[14] = 0.0f; translation_matrix[15] = 1.0f; - mat4mat4_mult(temp, translation_matrix, matrix, steps); + mat4mat4_mult(temp, translation_matrix, matrix, 1); +} + +void mat4_translation(float* matrix, float dx, float dy, float dz) +{ + matrix[0] = 1.0f; matrix[1] = 0.0f; matrix[2] = 0.0f; matrix[3] = dx; + matrix[4] = 0.0f; matrix[5] = 1.0f; matrix[6] = 0.0f; matrix[7] = dy; + matrix[8] = 0.0f; matrix[9] = 0.0f; matrix[10] = 1.0f; matrix[11] = dz; + matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f; +} + +void mat4_translation_sparse(float* matrix, float dx, float dy, float dz) +{ + matrix[3] = dx; + matrix[7] = dy; + matrix[11] = dz; +} + +// @todo unroll these loops below +void mat4_transpose(const float* matrix, float* transposed) +{ + for (int i = 0; i < 4; ++i) { + for (int j = i + 1; j < 4; ++j) { + int index1 = i * 4 + j; + int index2 = j * 4 + i; + + transposed[index1] = transposed[index2]; + transposed[index2] = matrix[index1]; + } + } +} + +void mat4_transpose(float* matrix) +{ + float temp; + + for (int i = 0; i < 4; ++i) { + for (int j = i + 1; j < 4; ++j) { + int index1 = i * 4 + j; + int index2 = j * 4 + i; + + temp = matrix[index1]; + matrix[index1] = matrix[index2]; + matrix[index2] = temp; + } + } +} + +void mat3_transpose(const float* matrix, float* transposed) +{ + for (int i = 0; i < 3; ++i) { + for (int j = i + 1; j < 3; ++j) { + int index1 = i * 3 + j; + int index2 = j * 3 + i; + + transposed[index1] = transposed[index2]; + transposed[index2] = matrix[index1]; + } + } +} + +void mat3_transpose(float* matrix) +{ + float temp; + + for (int i = 0; i < 3; ++i) { + for (int j = i + 1; j < 3; ++j) { + int index1 = i * 3 + j; + int index2 = j * 3 + i; + + temp = matrix[index1]; + matrix[index1] = matrix[index2]; + matrix[index2] = temp; + } + } +} + +void mat2_transpose(const float* matrix, float* transposed) +{ + for (int i = 0; i < 2; ++i) { + for (int j = i + 1; j < 2; ++j) { + int index1 = i * 2 + j; + int index2 = j * 2 + i; + + transposed[index1] = transposed[index2]; + transposed[index2] = matrix[index1]; + } + } +} + +void mat2_transpose(float* matrix) +{ + float temp; + + for (int i = 0; i < 2; ++i) { + for (int j = i + 1; j < 2; ++j) { + int index1 = i * 2 + j; + int index2 = j * 2 + i; + + temp = matrix[index1]; + matrix[index1] = matrix[index2]; + matrix[index2] = temp; + } + } } #endif \ No newline at end of file diff --git a/math/matrix/QuaternionFloat32.h b/math/matrix/QuaternionFloat32.h index f19b14c..efbd9d4 100644 --- a/math/matrix/QuaternionFloat32.h +++ b/math/matrix/QuaternionFloat32.h @@ -5,6 +5,7 @@ * @license OMS License 2.0 * @version 1.0.0 * @link https://jingga.app + * @link https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html */ #ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H #define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H @@ -12,40 +13,56 @@ #include "../../stdlib/Intrinsics.h" #include "../../stdlib/Mathtypes.h" #include "../../utils/MathUtils.h" +#include "../../utils/TestUtils.h" +inline +void quaternion_unit(v4_f32* quat) +{ + f32 length = sqrtf(quat->w * quat->w + quat->x * quat->x + quat->y * quat->y + quat->z * quat->z); + + quat->w /= length; + quat->x /= length; + quat->y /= length; + quat->z /= length; +} + +inline void quaternion_from_euler(v4_f32* quat, float pitch, float yaw, float roll) { float y = OMS_RAD2DEG(yaw * 0.5f); - float cy = cosf_approx(y); - float sy = sinf_approx(y); + float cy = cosf(y); + float sy = sinf(y); float p = OMS_RAD2DEG(pitch * 0.5f); - float cp = cosf_approx(p); - float sp = sinf_approx(p); + float cp = cosf(p); + float sp = sinf(p); float r = OMS_RAD2DEG(roll * 0.5f); - float cr = cosf_approx(r); - float sr = sinf_approx(r); + float cr = cosf(r); + float sr = sinf(r); quat->w = cr * cp * cy + sr * sp * sy; quat->x = sr * cp * cy - cr * sp * sy; quat->y = cr * sp * cy + sr * cp * sy; quat->z = cr * cp * sy - sr * sp * cy; + + quaternion_unit(quat); } +inline void quaternion_from_euler(v4_f32* quat, const v3_f32* v) { - float y = OMS_RAD2DEG(v->y * 0.5f); - float cy = cosf_approx(y); - float sy = sinf_approx(y); + float y = OMS_RAD2DEG(v->v * 0.5f); + float cy = cosf(y); + float sy = sinf(y); - float p = OMS_RAD2DEG(v->x * 0.5f); - float cp = cosf_approx(p); - float sp = sinf_approx(p); + float p = OMS_RAD2DEG(v->u * 0.5f); + float cp = cosf(p); + float sp = sinf(p); - float r = OMS_RAD2DEG(v->z * 0.5f); - float cr = cosf_approx(r); - float sr = sinf_approx(r); + float r = OMS_RAD2DEG(v->w * 0.5f); + float cr = cosf(r); + float sr = sinf(r); quat->w = cr * cp * cy + sr * sp * sy; quat->x = sr * cp * cy - cr * sp * sy; @@ -53,27 +70,27 @@ void quaternion_from_euler(v4_f32* quat, const v3_f32* v) quat->z = cr * cp * sy - sr * sp * cy; } -void euler_from_quaternion(const v4_f32* quat, v3_f32* v) { +void quaternion_to_euler(const v4_f32* quat, v3_f32* v) { // Pitch float sinp = 2.0f * (quat->w * quat->x + quat->y * quat->z); float cosp = 1.0f - 2.0f * (quat->x * quat->x + quat->y * quat->y); - v->pitch = atan2f_approx(sinp, cosp); + v->pitch = atan2f(sinp, cosp); - // Yaw - float siny = 2.0f * (quat->w * quat->y - quat->z * quat->x); - - if (siny >= 1.0f) { - v->yaw = OMS_PI_OVER_TWO; - } else if (siny <= -1.0f ) { - v->yaw = -OMS_PI_OVER_TWO; + // Check for gimbal lock + float sinp_check = 2.0f * (quat->w * quat->x + quat->y * quat->z); + if (OMS_ABS(sinp_check) >= 0.9999f) { + v->yaw = atan2f(quat->x * quat->z - quat->w * quat->y, quat->w * quat->x + quat->y * quat->z); + v->roll = 0.0f; } else { - v->yaw = asinf_approx(siny); - } + // Yaw + float siny = 2.0f * (quat->w * quat->y - quat->z * quat->x); + v->yaw = asinf(siny); - // Roll - float sinr = 2.0f * (quat->w * quat->z + quat->x * quat->y); - float cosr = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z); - v->roll = atan2f_approx(sinr, cosr); + // Roll + float sinr = 2.0f * (quat->w * quat->z + quat->x * quat->y); + float cosr = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z); + v->roll = atan2f(sinr, cosr); + } } void quaternion_multiply(v4_f32* quat, const v4_f32* quat1, const v4_f32* quat2) @@ -97,21 +114,140 @@ void quaternion_inverse(v4_f32* quat, const v4_f32* quat_origin) { } inline -void quaternion_rotate_euler(v4_f32* quat, const v4_f32* quat_origin, const v4_f32* euler) +void quaternion_to_rotation(f32* matrix, const v4_f32* quat) { - quaternion_multiply(quat, quat_origin, euler); + matrix[0] = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z); + matrix[1] = 2.0f * (quat->x * quat->y - quat->z * quat->w); + matrix[2] = 2.0f * (quat->x * quat->z + quat->y * quat->w); + matrix[3] = 0.0f; + + matrix[4] = 2.0f * (quat->x * quat->y + quat->z * quat->w); + matrix[5] = 1.0f - 2.0f * (quat->x * quat->x + quat->z * quat->z); + matrix[6] = 2.0f * (quat->y * quat->z - quat->x * quat->w); + matrix[7] = 0.0f; + + matrix[8] = 2.0f * (quat->x * quat->z - quat->y * quat->w); + matrix[9] = 2.0f * (quat->y * quat->z + quat->x * quat->w); + matrix[10] = 1.0f - 2.0f * (quat->x * quat->x + quat->y * quat->y); + matrix[11] = 0.0f; + + matrix[12] = 0.0f; + matrix[13] = 0.0f; + matrix[14] = 0.0f; + matrix[15] = 1.0f; } inline -void quaternion_rotate_quaternion(v4_f32* quat, const v4_f32* quat_origin, const v4_f32* quat_rot) +void quaternion_to_rotation(f32* matrix, const v4_f32* quat) { - v4_f32 quat_tmp; - quaternion_multiply(&quat_tmp, quat_rot, quat_origin); + matrix[0] = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z); + matrix[1] = 2.0f * (quat->x * quat->y - quat->z * quat->w); + matrix[2] = 2.0f * (quat->x * quat->z + quat->y * quat->w); - v4_f32 rot_; - quaternion_inverse(&rot_, quat_rot); + matrix[3] = 2.0f * (quat->x * quat->y + quat->z * quat->w); + matrix[4] = 1.0f - 2.0f * (quat->x * quat->x + quat->z * quat->z); + matrix[5] = 2.0f * (quat->y * quat->z - quat->x * quat->w); - quaternion_multiply(quat, &quat_tmp, &rot_); + matrix[6] = 2.0f * (quat->x * quat->z - quat->y * quat->w); + matrix[7] = 2.0f * (quat->y * quat->z + quat->x * quat->w); + matrix[8] = 1.0f - 2.0f * (quat->x * quat->x + quat->y * quat->y); +} + +inline +void quaternion_from_vec(v4_f32* quat, const v4_f32* vec) +{ + quat->x = vec->x; + quat->y = vec->y; + quat->z = vec->z; + quat->w = 0; +} + +inline +void quaternion_from_vec(v4_f32* quat, const v3_f32* vec) +{ + quat->x = vec->x; + quat->y = vec->y; + quat->z = vec->z; + quat->w = 0; +} + +inline +void quaternion_to_vec(v4_f32* vec, const v4_f32* quat) +{ + vec->x = quat->x; + vec->y = quat->y; + vec->z = quat->z; + vec->w = 0.0f; +} + +inline +void quaternion_to_vec(v3_f32* vec, const v4_f32* quat) +{ + vec->x = quat->x; + vec->y = quat->y; + vec->z = quat->z; +} + +// active = point rotated respective to coordinate system +inline +void quaternion_rotate_active(v4_f32* p, const v4_f32* quat, const v4_f32* quat_inv) +{ + ASSERT_SIMPLE(OMS_ABS(x * x + y * y + z * z + w * z - 1.0f) < 0.01); + + v4_f32 p_tmp; + quaternion_multiply(&p_tmp, quat_inv, p); + quaternion_multiply(p, &p_tmp, quat); +} + +// passive = coordinate system is rotated +inline +void quaternion_rotate_passive(v4_f32* p, const v4_f32* quat, const v4_f32* quat_inv) +{ + ASSERT_SIMPLE(OMS_ABS(x * x + y * y + z * z + w * w - 1.0f) < 0.01); + + v4_f32 p_tmp; + quaternion_multiply(&p_tmp, quat, p); + quaternion_multiply(p, &p_tmp, quat_inv); +} + +// Rotation algorithm +// 1. create quat from pitch/yaw/roll +// 2. convert the quat to unit length +// 3. create quat_inv +// 4. create quat from vec +// 5. call quat_rotate_* +// 6. convert quat to vec +// @todo Since this is usually done on multiple vecs, we should probably accept an array of vecs and then use simd +void quaternion_rotate_active(v4_f32* vec, float pitch, float yaw, float roll) +{ + v4_f32 q; + quaternion_from_euler(&q, pitch, yaw, roll); // q is already in unit length + + v4_f32 q_inv; + quaternion_inverse(&q_inv, &q); + + v4_f32 p; + quaternion_from_vec(&p, vec); + + quaternion_rotate_active(&p, &q, &q_inv); + + quaternion_to_vec(vec, &p); +} + +void quaternion_rotate_passive(v4_f32* vec, float pitch, float yaw, float roll) +{ + v4_f32 q; + quaternion_from_euler(&q, pitch, yaw, roll); // q is already in unit length + + v4_f32 q_inv; + quaternion_inverse(&q_inv, &q); + + v4_f32 p; + quaternion_from_vec(&p, vec); + + quaternion_rotate_passive(&p, &q, &q_inv); + + quaternion_to_vec(vec, &p); } #endif \ No newline at end of file diff --git a/stdlib/HashMap.h b/stdlib/HashMap.h index de32217..946090a 100644 --- a/stdlib/HashMap.h +++ b/stdlib/HashMap.h @@ -31,6 +31,13 @@ struct HashEntryInt64 { int64 value; }; +struct HashEntryVoidP { + int64 element_id; + char key[MAX_KEY_LENGTH]; + HashEntryVoidP* next; + void* value; +}; + struct HashEntryFloat { int64 element_id; char key[MAX_KEY_LENGTH]; @@ -70,6 +77,7 @@ void hashmap_create(HashMap* hm, int count, int element_size, RingMemory* ring) hm->buf.alignment = 1; } +// WARNING: element_size = element size + remaining HashEntry data size void hashmap_create(HashMap* hm, int count, int element_size, BufferMemory* buf) { hm->table = (void **) buffer_get_memory(buf, count * sizeof(void *)); @@ -90,6 +98,7 @@ int64 hashmap_get_buffer_size(int count, int element_size) + sizeof(uint64) * CEIL_DIV(count, 64); // free } +// WARNING: element_size = element size + remaining HashEntry data size void hashmap_create(HashMap* hm, int count, int element_size, byte* buf) { hm->table = (void **) buf; @@ -132,6 +141,21 @@ void hashmap_insert(HashMap* hm, const char* key, int64 value) { hm->table[index] = entry; } +void hashmap_insert(HashMap* hm, const char* key, void* value) { + uint64 index = hash_djb2(key) % hm->buf.count; + + int64 element = chunk_reserve(&hm->buf, 1); + HashEntryVoidP* entry = (HashEntryVoidP *) chunk_get_element(&hm->buf, element, true); + entry->element_id = element; + + strncpy(entry->key, key, MAX_KEY_LENGTH); + entry->key[MAX_KEY_LENGTH - 1] = '\0'; + + entry->value = value; + entry->next = (HashEntryVoidP *) hm->table[index]; + hm->table[index] = entry; +} + void hashmap_insert(HashMap* hm, const char* key, float value) { uint64 index = hash_djb2(key) % hm->buf.count; diff --git a/stdlib/Mathtypes.h b/stdlib/Mathtypes.h index 83ae528..7037ae8 100644 --- a/stdlib/Mathtypes.h +++ b/stdlib/Mathtypes.h @@ -119,20 +119,23 @@ struct v3_f32 { f32 x; f32 r; f32 pitch; + f32 u; }; union { f32 y; f32 g; f32 yaw; + f32 v; }; union { f32 z; f32 b; f32 roll; + f32 w; }; }; - f32 v[3]; + f32 vec[3]; }; }; @@ -145,7 +148,7 @@ struct v4_f32 { f32 w; }; - f32 v[4]; + f32 vec[4]; }; };