rotating cubes2

This commit is contained in:
Dennis Eichhorn 2024-09-12 01:30:46 +02:00
parent 8335444c03
commit c7c7686827
12 changed files with 561 additions and 95 deletions

View File

@ -12,11 +12,12 @@
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "../object/Vertex.h" #include "../object/Vertex.h"
#include "../stdlib/HashMap.h" #include "../stdlib/HashMap.h"
#include "AssetType.h"
#define MAX_ASSET_NAME_LENGTH 32 #define MAX_ASSET_NAME_LENGTH 32
struct Asset { 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) // This is is only an internal id and NOT the same as a db id (e.g. player id)
uint64 internal_id; uint64 internal_id;
@ -25,9 +26,9 @@ struct Asset {
char name[MAX_ASSET_NAME_LENGTH]; 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 // e.g. textures
int reference_count; int reference_count;
@ -36,26 +37,26 @@ struct Asset {
uint64 ram_size; uint64 ram_size;
uint64 vram_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 // For textures for example a 128x128 is of size 1 but 256x256 is of size 4
uint32 size; uint32 size;
// Describes if the memory is currently available in ram/vram // 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_ram;
bool is_vram; bool is_vram;
Asset* next; Asset* next;
Asset* prev; 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 // This allows us to quickly update the other entities
// Example: A player pulls N mobs // Example: A player pulls N mobs
// @bug This means there are hard limits on how many mobs can be pulled by a player // @bug This means there are hard limits on how many mobs can be pulled by a player
Asset* entity_references[50]; Asset* references[50];
bool free_entity_references[50]; uint64 free_references; // bits show which is free
// Actual memory address // Actual memory address and specific asset data
byte* self; byte* self;
}; };

View File

@ -12,7 +12,6 @@
#include <string.h> #include <string.h>
#include "../stdlib/Types.h" #include "../stdlib/Types.h"
#include "Asset.h" #include "Asset.h"
#include "AssetType.h"
#include "../memory/ChunkMemory.h" #include "../memory/ChunkMemory.h"
#include "../utils/TestUtils.h" #include "../utils/TestUtils.h"
#include "../stdlib/HashMap.h" #include "../stdlib/HashMap.h"

View File

@ -6,8 +6,8 @@
* @version 1.0.0 * @version 1.0.0
* @link https://jingga.app * @link https://jingga.app
*/ */
#ifndef TOS_ASSET_TYPES_H #ifndef TOS_ASSET_TYPE_H
#define TOS_ASSET_TYPES_H #define TOS_ASSET_TYPE_H
enum AssetType { enum AssetType {
ASSET_TYPE_OBJ, ASSET_TYPE_OBJ,

View File

@ -22,20 +22,26 @@ struct Camera {
v4_f32 orientation; v4_f32 orientation;
float speed; float speed;
float sensitivity;
float zoom; 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 // you can have up to 4 camera movement inputs at the same time
void camera_movement(Camera* camera, CameraMovement* movement, float dt) void camera_movement(Camera* camera, CameraMovement* movement, float dt)
{ {
f32 velocity = camera->speed * dt; f32 velocity = camera->speed * dt;
bool has_pos = false; bool has_pos = false;
v4_f32 pos; v4_f32 pos = {};
bool has_view = false; bool has_view = false;
v3_f32 view; v3_f32 view = {};
v4_f32 quaternion; v4_f32 quaternion = {};
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
switch(movement[i]) { switch(movement[i]) {

89
entity/Entity.h Normal file
View File

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

View File

@ -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 <string.h>
#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

21
entity/EntityType.h Normal file
View File

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

View File

@ -10,63 +10,64 @@
#define TOS_GPUAPI_OPENGL_SHADER_UTILS_H #define TOS_GPUAPI_OPENGL_SHADER_UTILS_H
#include "../../stdlib/Types.h" #include "../../stdlib/Types.h"
#include "../../math/matrix/MatrixFloat32.h"
inline 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); gl->glUniform1i(gl->glGetUniformLocation(id, name), (int) value);
} }
inline 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); gl->glUniform1i(gl->glGetUniformLocation(id, name), value);
} }
inline 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); gl->glUniform1f(gl->glGetUniformLocation(id, name), value);
} }
inline 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); gl->glUniform2fv(gl->glGetUniformLocation(id, name), 1, value);
} }
inline 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); gl->glUniform3fv(gl->glGetUniformLocation(id, name), 1, value);
} }
inline 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); gl->glUniform4fv(gl->glGetUniformLocation(id, name), 1, value);
} }
inline 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); gl->glUniformMatrix2fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value);
} }
inline 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); gl->glUniformMatrix3fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value);
} }
inline 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); gl->glUniformMatrix4fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value);
} }
inline 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; GLint success;
gl->glGetProgramiv(id, GL_LINK_STATUS, &success); gl->glGetProgramiv(id, GL_LINK_STATUS, &success);
@ -76,7 +77,7 @@ void shader_check_link_errors(OpenGL* gl, uint32 id, char* log)
} }
inline 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; GLint success;
gl->glGetShaderiv(id, GL_COMPILE_STATUS, &success); gl->glGetShaderiv(id, GL_COMPILE_STATUS, &success);

View File

@ -12,6 +12,7 @@
#include "../../stdlib/Intrinsics.h" #include "../../stdlib/Intrinsics.h"
#include "../../stdlib/Mathtypes.h" #include "../../stdlib/Mathtypes.h"
#include "../../utils/MathUtils.h" #include "../../utils/MathUtils.h"
#include "../../utils/TestUtils.h"
#include <math.h> #include <math.h>
void mat3_identity(float* matrix) void mat3_identity(float* matrix)
@ -58,6 +59,8 @@ void mat4_identity(__m128* matrix)
// https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula // https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula
void mat4_rotation(float* matrix, float x, float y, float z, float angle) 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 // @todo replace with quaternions
float s = sinf(angle); float s = sinf(angle);
float c = cosf(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[0] = mx * x + c;
matrix[1] = mxy - zs; matrix[1] = mxy - zs;
matrix[2] = mzx + ys; matrix[2] = mzx + ys;
matrix[3] = 0; matrix[3] = 0.0f;
matrix[4] = mxy + zs; matrix[4] = mxy + zs;
matrix[5] = my * y + c; matrix[5] = my * y + c;
matrix[6] = myz - xs; matrix[6] = myz - xs;
matrix[7] = 0; matrix[7] = 0.0f;
matrix[8] = mzx - ys; matrix[8] = mzx - ys;
matrix[9] = myz + xs; matrix[9] = myz + xs;
matrix[10] = mz * z + c; matrix[10] = mz * z + c;
matrix[11] = 0; matrix[11] = 0.0f;
matrix[12] = 0; matrix[12] = 0.0f;
matrix[13] = 0; matrix[13] = 0.0f;
matrix[14] = 0; matrix[14] = 0.0f;
matrix[15] = 1; 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) 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 { } else {
// Row 0
result[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12]; 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[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[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]; 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[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[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[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]; 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[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[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[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]; 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[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[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]; 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 // @performance Consider to replace with 1d array
void mat4_frustum_planes(float planes[6][4], float radius, float *matrix) { void mat4_frustum_planes(float planes[6][4], float radius, float *matrix) {
// @todo make this a setting // @todo make this a setting
// @bug fix to row-major system
// @todo don't use 2d arrays
float znear = 0.125; float znear = 0.125;
float zfar = radius * 32 + 64; float zfar = radius * 32 + 64;
@ -442,25 +473,25 @@ void mat4_ortho(
float tb_delta = top - bottom; float tb_delta = top - bottom;
float fn_delta = far_dist - near_dist; float fn_delta = far_dist - near_dist;
matrix[0] = 2 / rl_delta; matrix[0] = 2.0f / rl_delta;
matrix[1] = 0; matrix[1] = 0.0f;
matrix[2] = 0; matrix[2] = 0.0f;
matrix[3] = 0; matrix[3] = 0.0f;
matrix[4] = 0; matrix[4] = 0.0f;
matrix[5] = 2 / tb_delta; matrix[5] = 2.0f / tb_delta;
matrix[6] = 0; matrix[6] = 0.0f;
matrix[7] = 0; matrix[7] = 0.0f;
matrix[8] = 0; matrix[8] = 0.0f;
matrix[9] = 0; matrix[9] = 0.0f;
matrix[10] = -2 / fn_delta; matrix[10] = -2.0f / fn_delta;
matrix[11] = 0; matrix[11] = 0.0f;
matrix[12] = -(right + left) / rl_delta; matrix[12] = -(right + left) / rl_delta;
matrix[13] = -(top + bottom) / tb_delta; matrix[13] = -(top + bottom) / tb_delta;
matrix[14] = -(far_dist + near_dist) / fn_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) 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); memcpy(temp, matrix, sizeof(float) * 16);
alignas(64) float translation_matrix[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[0] = 1.0f; translation_matrix[1] = 0.0f; translation_matrix[2] = 0.0f; translation_matrix[3] = dx;
translation_matrix[4] = 0; translation_matrix[5] = 1; translation_matrix[6] = 0; translation_matrix[7] = 0; translation_matrix[4] = 0.0f; translation_matrix[5] = 1.0f; translation_matrix[6] = 0.0f; translation_matrix[7] = dy;
translation_matrix[8] = 0; translation_matrix[9] = 0; translation_matrix[10] = 1; translation_matrix[11] = 0; translation_matrix[8] = 0.0f; translation_matrix[9] = 0.0f; translation_matrix[10] = 1.0f; translation_matrix[11] = dz;
translation_matrix[12] = dx; translation_matrix[13] = dy; translation_matrix[14] = dz; translation_matrix[15] = 1; 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 #endif

View File

@ -5,6 +5,7 @@
* @license OMS License 2.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link https://jingga.app * @link https://jingga.app
* @link https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html
*/ */
#ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H #ifndef TOS_MATH_MATRIX_QUATERNION_FLOAT32_H
#define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H #define TOS_MATH_MATRIX_QUATERNION_FLOAT32_H
@ -12,40 +13,56 @@
#include "../../stdlib/Intrinsics.h" #include "../../stdlib/Intrinsics.h"
#include "../../stdlib/Mathtypes.h" #include "../../stdlib/Mathtypes.h"
#include "../../utils/MathUtils.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) void quaternion_from_euler(v4_f32* quat, float pitch, float yaw, float roll)
{ {
float y = OMS_RAD2DEG(yaw * 0.5f); float y = OMS_RAD2DEG(yaw * 0.5f);
float cy = cosf_approx(y); float cy = cosf(y);
float sy = sinf_approx(y); float sy = sinf(y);
float p = OMS_RAD2DEG(pitch * 0.5f); float p = OMS_RAD2DEG(pitch * 0.5f);
float cp = cosf_approx(p); float cp = cosf(p);
float sp = sinf_approx(p); float sp = sinf(p);
float r = OMS_RAD2DEG(roll * 0.5f); float r = OMS_RAD2DEG(roll * 0.5f);
float cr = cosf_approx(r); float cr = cosf(r);
float sr = sinf_approx(r); float sr = sinf(r);
quat->w = cr * cp * cy + sr * sp * sy; quat->w = cr * cp * cy + sr * sp * sy;
quat->x = sr * cp * cy - cr * sp * sy; quat->x = sr * cp * cy - cr * sp * sy;
quat->y = cr * sp * cy + sr * cp * sy; quat->y = cr * sp * cy + sr * cp * sy;
quat->z = cr * cp * sy - sr * sp * cy; quat->z = cr * cp * sy - sr * sp * cy;
quaternion_unit(quat);
} }
inline
void quaternion_from_euler(v4_f32* quat, const v3_f32* v) void quaternion_from_euler(v4_f32* quat, const v3_f32* v)
{ {
float y = OMS_RAD2DEG(v->y * 0.5f); float y = OMS_RAD2DEG(v->v * 0.5f);
float cy = cosf_approx(y); float cy = cosf(y);
float sy = sinf_approx(y); float sy = sinf(y);
float p = OMS_RAD2DEG(v->x * 0.5f); float p = OMS_RAD2DEG(v->u * 0.5f);
float cp = cosf_approx(p); float cp = cosf(p);
float sp = sinf_approx(p); float sp = sinf(p);
float r = OMS_RAD2DEG(v->z * 0.5f); float r = OMS_RAD2DEG(v->w * 0.5f);
float cr = cosf_approx(r); float cr = cosf(r);
float sr = sinf_approx(r); float sr = sinf(r);
quat->w = cr * cp * cy + sr * sp * sy; quat->w = cr * cp * cy + sr * sp * sy;
quat->x = sr * cp * cy - cr * 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; 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 // Pitch
float sinp = 2.0f * (quat->w * quat->x + quat->y * quat->z); 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); 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 // Check for gimbal lock
float siny = 2.0f * (quat->w * quat->y - quat->z * quat->x); float sinp_check = 2.0f * (quat->w * quat->x + quat->y * quat->z);
if (OMS_ABS(sinp_check) >= 0.9999f) {
if (siny >= 1.0f) { v->yaw = atan2f(quat->x * quat->z - quat->w * quat->y, quat->w * quat->x + quat->y * quat->z);
v->yaw = OMS_PI_OVER_TWO; v->roll = 0.0f;
} else if (siny <= -1.0f ) {
v->yaw = -OMS_PI_OVER_TWO;
} else { } else {
v->yaw = asinf_approx(siny); // Yaw
} float siny = 2.0f * (quat->w * quat->y - quat->z * quat->x);
v->yaw = asinf(siny);
// Roll // Roll
float sinr = 2.0f * (quat->w * quat->z + quat->x * quat->y); 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); float cosr = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z);
v->roll = atan2f_approx(sinr, cosr); v->roll = atan2f(sinr, cosr);
}
} }
void quaternion_multiply(v4_f32* quat, const v4_f32* quat1, const v4_f32* quat2) 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 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 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; matrix[0] = 1.0f - 2.0f * (quat->y * quat->y + quat->z * quat->z);
quaternion_multiply(&quat_tmp, quat_rot, quat_origin); 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_; matrix[3] = 2.0f * (quat->x * quat->y + quat->z * quat->w);
quaternion_inverse(&rot_, quat_rot); 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 #endif

View File

@ -31,6 +31,13 @@ struct HashEntryInt64 {
int64 value; int64 value;
}; };
struct HashEntryVoidP {
int64 element_id;
char key[MAX_KEY_LENGTH];
HashEntryVoidP* next;
void* value;
};
struct HashEntryFloat { struct HashEntryFloat {
int64 element_id; int64 element_id;
char key[MAX_KEY_LENGTH]; 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; 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) void hashmap_create(HashMap* hm, int count, int element_size, BufferMemory* buf)
{ {
hm->table = (void **) buffer_get_memory(buf, count * sizeof(void *)); 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 + 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) void hashmap_create(HashMap* hm, int count, int element_size, byte* buf)
{ {
hm->table = (void **) buf; hm->table = (void **) buf;
@ -132,6 +141,21 @@ void hashmap_insert(HashMap* hm, const char* key, int64 value) {
hm->table[index] = entry; 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) { void hashmap_insert(HashMap* hm, const char* key, float value) {
uint64 index = hash_djb2(key) % hm->buf.count; uint64 index = hash_djb2(key) % hm->buf.count;

View File

@ -119,20 +119,23 @@ struct v3_f32 {
f32 x; f32 x;
f32 r; f32 r;
f32 pitch; f32 pitch;
f32 u;
}; };
union { union {
f32 y; f32 y;
f32 g; f32 g;
f32 yaw; f32 yaw;
f32 v;
}; };
union { union {
f32 z; f32 z;
f32 b; f32 b;
f32 roll; f32 roll;
f32 w;
}; };
}; };
f32 v[3]; f32 vec[3];
}; };
}; };
@ -145,7 +148,7 @@ struct v4_f32 {
f32 w; f32 w;
}; };
f32 v[4]; f32 vec[4];
}; };
}; };