diff --git a/animation/Animation.h b/animation/Animation.h index 9d87e93..b417785 100644 --- a/animation/Animation.h +++ b/animation/Animation.h @@ -10,17 +10,20 @@ #ifndef TOS_ANIMATION_H #define TOS_ANIMATION_H -#include #include "../utils/MathUtils.h" #include "AnimationEaseType.h" inline -float lerp_approx(float a, float b, float t) +float lerp(float a, float b, float t) { return a + t * (b - a); } +float smoothstep(float t) { + return t * t * (3 - 2 * t); +} + float anim_ease(float t, AnimationEaseType type) { switch(type) { case ANIMATION_EASE_IN_SINE: { @@ -182,6 +185,11 @@ float anim_ease_out_quart(float t) { return 1 - pow(1 - t, 4); } +inline +float anim_ease_in_perlin(float t) { + return t * t * t * (t * (t * 6 - 15) + 10); +} + inline float anim_ease_in_out_quart(float t) { return t < 0.5 diff --git a/asset/Asset.h b/asset/Asset.h index 4949b55..c8dadac 100644 --- a/asset/Asset.h +++ b/asset/Asset.h @@ -10,20 +10,22 @@ #define TOS_ASSET_H #include "../stdlib/Types.h" +#include "../object/Vertex.h" +#include "../stdlib/HashMap.h" + +#define MAX_ASSET_NAME_LENGTH 32 struct Asset { - // A id of 0 means the entity is no longer alive // 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) - uint32 internal_id; - uint32 type; + uint64 internal_id; // Could be 0 if there is no official id - uint32 official_id; + uint64 official_id; - uint32 vao; // vertex buffer - uint32 vbo; // index buffer - uint32 ebo; // input layout + char name[MAX_ASSET_NAME_LENGTH]; + + uint32 type; // Counts the references to this entity // e.g. textures @@ -31,8 +33,8 @@ struct Asset { // 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 - uint32 ram_size; - uint32 vram_size; + 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 diff --git a/asset/AssetManagementSystem.h b/asset/AssetManagementSystem.h index b0b2f4b..afd23ef 100644 --- a/asset/AssetManagementSystem.h +++ b/asset/AssetManagementSystem.h @@ -15,6 +15,7 @@ #include "AssetType.h" #include "../memory/ChunkMemory.h" #include "../utils/TestUtils.h" +#include "../stdlib/HashMap.h" // The major asset types should have their own asset component system // All other entities are grouped together in one asset component system @@ -22,6 +23,8 @@ // @bug This means players might not be able to transition from one area to another?! struct AssetManagementSystem { + HashMap hash_map; + // The indices of asset_memory and asset_data_memory are always linked // General asset memory @@ -34,7 +37,66 @@ struct AssetManagementSystem { Asset* last; }; -int ams_get_vram_usage(AssetManagementSystem* ams) +void ams_create(AssetManagementSystem* ams, BufferMemory* buf, int chunk_size, int count) +{ + // setup hash_map + hashmap_create(&ams->hash_map, count, sizeof(HashEntryInt64), buf); + + // setup asset_memory + ams->asset_memory.count = count; + ams->asset_memory.chunk_size = sizeof(Asset); + ams->asset_memory.last_pos = -1; + ams->asset_memory.alignment = 1; + ams->asset_memory.memory = buffer_get_memory(buf, sizeof(Asset) * count); + ams->asset_memory.free = (uint64 *) buffer_get_memory(buf, CEIL_DIV(count, 64) * sizeof(uint64)); + + // setup asset_data_memory + ams->asset_data_memory.count = count; + ams->asset_data_memory.chunk_size = chunk_size; + ams->asset_data_memory.last_pos = -1; + ams->asset_data_memory.alignment = 1; + ams->asset_data_memory.memory = buffer_get_memory(buf, chunk_size * count); + ams->asset_data_memory.free = (uint64 *) buffer_get_memory(buf, CEIL_DIV(count, 64) * sizeof(uint64)); + + ams->first = NULL; + ams->last = NULL; +} + +inline +int64 ams_get_buffer_size(int count, int chunk_size) +{ + return hashmap_get_buffer_size(count, sizeof(HashEntryInt64)) // hash map + + sizeof(Asset) * count + CEIL_DIV(count, 64) * sizeof(uint64) // asset_memory + + chunk_size * count + CEIL_DIV(count, 64) * sizeof(uint64); // asset_data_memory +} + +// WARNING: buf size see ams_get_buffer_size +void ams_create(AssetManagementSystem* ams, byte* buf, int chunk_size, int count) +{ + // setup hash_map + hashmap_create(&ams->hash_map, count, sizeof(HashEntryInt64), buf); + + // setup asset_memory + ams->asset_memory.count = count; + ams->asset_memory.chunk_size = sizeof(Asset); + ams->asset_memory.last_pos = -1; + ams->asset_memory.alignment = 1; + ams->asset_memory.memory = buf; + ams->asset_memory.free = (uint64 *) (ams->asset_memory.memory + sizeof(Asset) * count); + + // setup asset_data_memory + ams->asset_data_memory.count = count; + ams->asset_data_memory.chunk_size = chunk_size; + ams->asset_data_memory.last_pos = -1; + ams->asset_data_memory.alignment = 1; + ams->asset_data_memory.memory = (byte *) (ams->asset_data_memory.free + CEIL_DIV(count, 64)); + ams->asset_data_memory.free = (uint64 *) (ams->asset_data_memory.memory + chunk_size * count); + + ams->first = NULL; + ams->last = NULL; +} + +uint64 ams_get_vram_usage(AssetManagementSystem* ams) { uint64 size = 0; for (int i = 0; i < ams->asset_memory.count; ++i) { @@ -44,29 +106,57 @@ int ams_get_vram_usage(AssetManagementSystem* ams) return size; } -void asset_delete(AssetManagementSystem* ams, Asset* asset) +void ams_free_asset(AssetManagementSystem* ams, Asset* asset) { asset->prev->next = asset->next; asset->next->prev = asset->prev; - for (int i = 0; i < asset->size; ++i) { - chunk_element_free(&ams->asset_memory, asset->internal_id + i); - chunk_element_free(&ams->asset_data_memory, asset->internal_id + i); + hashmap_delete_entry(&ams->hash_map, asset->name); + + for (uint32 i = 0; i < asset->size; ++i) { + chunk_free_element(&ams->asset_memory, asset->internal_id + i); + chunk_free_element(&ams->asset_data_memory, asset->internal_id + i); } } +Asset* ams_get_asset(AssetManagementSystem* ams, uint64 element) +{ + return (Asset *) chunk_get_element(&ams->asset_memory, element, false); +} + +Asset* ams_get_asset(AssetManagementSystem* ams, const char* key) +{ + HashEntryInt64* entry = (HashEntryInt64 *) hashmap_get_entry(&ams->hash_map, key); + if (entry == NULL) { + return NULL; + } + + return (Asset *) chunk_get_element(&ams->asset_memory, entry->value, false); +} + // @todo implement defragment command to optimize memory layout since the memory layout will become fragmented over time -Asset* asset_reserve(AssetManagementSystem* ams, uint64 elements = 1) +Asset* ams_reserve_asset(AssetManagementSystem* ams, const char* name, uint64 elements = 1) { int64 free_asset = chunk_reserve(&ams->asset_memory, elements, true); - ASSERT_SIMPLE(free_asset >= 0); + if (free_asset < 0) { + ASSERT_SIMPLE(free_asset >= 0); + return NULL; + } + + size_t name_length = strlen(name); + ASSERT_SIMPLE(name_length < MAX_ASSET_NAME_LENGTH - 1); + + Asset* asset = (Asset *) chunk_get_element(&ams->asset_memory, free_asset); + asset->internal_id = free_asset; + + strncpy(asset->name, name, name_length); + asset->name[name_length] = '\0'; + + hashmap_insert(&ams->hash_map, name, free_asset); chunk_reserve_index(&ams->asset_data_memory, free_asset, elements, true); - - Asset* asset = (Asset *) chunk_get_memory(&ams->asset_memory, free_asset); - asset->internal_id = free_asset; - asset->self = chunk_get_memory(&ams->asset_data_memory, free_asset); + asset->self = chunk_get_element(&ams->asset_data_memory, free_asset); asset->ram_size = ams->asset_memory.chunk_size * elements; // @performance Do we really want a double linked list. Are we really using this feature or is the free_index enough? diff --git a/compression/LZP.h b/compression/LZP.h index 93aba69..bce968e 100644 --- a/compression/LZP.h +++ b/compression/LZP.h @@ -10,6 +10,7 @@ #define TOS_COMPRESSION_LZP_H #include +#include #include "../stdlib/Types.h" @@ -101,4 +102,94 @@ uint32 decode_lzp(const byte* in, size_t length, byte* out) return out_pos; } +int find_longest_match(char *window, int window_start, char *buffer, int buffer_size, int *match_position) { + int best_length = 0; + int best_offset = 0; + + for (int i = window_start; i < 4096 && i < buffer_size; ++i) { + int length = 0; + + while (length < 18 && + i + length < 4096 && + buffer[length] == window[i + length]) { + length++; + } + + if (length > best_length) { + best_length = length; + best_offset = i; + } + } + + *match_position = best_offset; + + return best_length; +} + +uint32 encode_lzp3(const byte* in, size_t length, byte* out) { + char window[4096] = {0}; + int window_start = 0; + + int out_size = 0; + + int i = 0; + while (i < length) { + int match_position = 0; + int match_length = find_longest_match(window, window_start, (char *)&in[i], (int) (length - i), &match_position); + + if (match_length > 2) { + out[out_size++] = 0xFF; + out[out_size++] = match_position & 0xFF; + out[out_size++] = match_length & 0xFF; + + i += match_length; + } else { + out[out_size++] = in[i]; + ++i; + } + + int shift_length = match_length > 0 ? match_length : 1; + memmove(window, window + shift_length, 4096 - shift_length); + memcpy(window + (4096 - shift_length), &in[i - shift_length], shift_length); + window_start = (window_start + shift_length) >= 4096 ? 0 : window_start + shift_length; + } + + return out_size; +} + +uint32 decode_lzp3(const byte* in, size_t length, byte* out) { + char window[4096] = {0}; + int window_start = 0; + + int out_size = 0; + + int i = 0; + while (i < length) { + if (in[i] == 0xFF) { + int match_position = in[i + 1]; + int match_length = in[i + 2]; + + for (int j = 0; j < match_length; j++) { + out[out_size++] = window[(match_position + j) % 4096]; + } + + memmove(window, window + match_length, 4096 - match_length); + memcpy(window + (4096 - match_length), &out[out_size - match_length], match_length); + window_start = (window_start + match_length) >= 4096 ? 0 : window_start + match_length; + + i += 3; + } else { + out[out_size++] = in[i]; + + memmove(window, window + 1, 4096 - 1); + window[4096 - 1] = in[i]; + window_start = (window_start + 1) >= 4096 ? 0 : window_start + 1; + + ++i; + } + } + + return out_size; +} + #endif \ No newline at end of file diff --git a/gpuapi/direct3d/UtilsDirect3d.h b/gpuapi/direct3d/DirectXUtils.h similarity index 98% rename from gpuapi/direct3d/UtilsDirect3d.h rename to gpuapi/direct3d/DirectXUtils.h index e6c71ba..3ccf3a1 100644 --- a/gpuapi/direct3d/UtilsDirect3d.h +++ b/gpuapi/direct3d/DirectXUtils.h @@ -6,8 +6,8 @@ * @version 1.0.0 * @link https://jingga.app */ -#ifndef TOS_GPUAPI_DIRECT3D_UTILS -#define TOS_GPUAPI_DIRECT3D_UTILS +#ifndef TOS_GPUAPI_DIRECTX_UTILS_H +#define TOS_GPUAPI_DIRECTX_UTILS_H #include #include @@ -60,7 +60,7 @@ void window_create(Window* window, void* proc) wc.style = CS_OWNDC; wc.lpfnWndProc = wndproc; wc.hInstance = hinstance; - wc.lpszClassName = (LPCWSTR) window->name; + wc.lpszClassName = (LPCSTR) window->name; RegisterClassEx(&wc); diff --git a/gpuapi/opengl/Opengl.h b/gpuapi/opengl/Opengl.h new file mode 100644 index 0000000..7b1df41 --- /dev/null +++ b/gpuapi/opengl/Opengl.h @@ -0,0 +1,738 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_OPENGL_H +#define TOS_GPUAPI_OPENGL_H + +#include + +// @todo remove some of the unused consts below + +// +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_RESCALE_NORMAL 0x803A +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E + +// +#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE +#define GL_FOG_COORD GL_FOG_COORDINATE +#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING +#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER +#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE +#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE +#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE +#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA +#define GL_SRC0_RGB GL_SOURCE0_RGB +#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA +#define GL_SRC1_RGB GL_SOURCE1_RGB +#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA +#define GL_SRC2_RGB GL_SOURCE2_RGB +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 + +// +#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_POINT_SPRITE 0x8861 +#define GL_COORD_REPLACE 0x8862 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 + +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_SUBTRACT 0x84E7 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_NORMAL_MAP 0x8511 +#define GL_REFLECTION_MAP 0x8512 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_RGB 0x8582 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_MULTISAMPLE_BIT 0x20000000 + +// +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B + +// +#define GL_CLIP_DISTANCE0 GL_CLIP_PLANE0 +#define GL_CLIP_DISTANCE1 GL_CLIP_PLANE1 +#define GL_CLIP_DISTANCE2 GL_CLIP_PLANE2 +#define GL_CLIP_DISTANCE3 GL_CLIP_PLANE3 +#define GL_CLIP_DISTANCE4 GL_CLIP_PLANE4 +#define GL_CLIP_DISTANCE5 GL_CLIP_PLANE5 +#define GL_COMPARE_REF_TO_TEXTURE GL_COMPARE_R_TO_TEXTURE_ARB +#define GL_MAX_CLIP_DISTANCES GL_MAX_CLIP_PLANES +#define GL_MAX_VARYING_COMPONENTS GL_MAX_VARYING_FLOATS +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_DEPTH_BUFFER 0x8223 +#define GL_STENCIL_BUFFER 0x8224 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 + +// +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_FORMAT 0x8C2E +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_RED_SNORM 0x8F90 +#define GL_RG_SNORM 0x8F91 +#define GL_RGB_SNORM 0x8F92 +#define GL_RGBA_SNORM 0x8F93 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 + +// +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 + +// +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_RGB10_A2UI 0x906F + +// +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_PROGRAM_TEXTURE_GATHER_COMPONENTS 0x8F9F +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F + +// +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 + +// +#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9 +#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E + +// +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A + +// +#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008 +#define GL_PARAMETER_BUFFER 0x80EE +#define GL_PARAMETER_BUFFER_BINDING 0x80EF +#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC +#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED +#define GL_VERTICES_SUBMITTED 0x82EE +#define GL_PRIMITIVES_SUBMITTED 0x82EF +#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0 +#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1 +#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2 +#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3 +#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4 +#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5 +#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6 +#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7 +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF +#define GL_POLYGON_OFFSET_CLAMP 0x8E1B +#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551 +#define GL_SPIR_V_BINARY 0x9552 +#define GL_SPIR_V_EXTENSIONS 0x9553 +#define GL_NUM_SPIR_V_EXTENSIONS 0x9554 + +// +#define GL_MULTISAMPLE_3DFX 0x86B2 +#define GL_SAMPLE_BUFFERS_3DFX 0x86B3 +#define GL_SAMPLES_3DFX 0x86B4 +#define GL_MULTISAMPLE_BIT_3DFX 0x20000000 + +// +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8 +#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9 +#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA +#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB +#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC +#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD +#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE +#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF +#define GL_COLOR_INDEX1_EXT 0x80E2 +#define GL_COLOR_INDEX2_EXT 0x80E3 +#define GL_COLOR_INDEX4_EXT 0x80E4 +#define GL_COLOR_INDEX8_EXT 0x80E5 +#define GL_COLOR_INDEX12_EXT 0x80E6 +#define GL_COLOR_INDEX16_EXT 0x80E7 +#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED +#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 +#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B + +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C +#define GL_MAX_IMAGE_SAMPLES 0x906D +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF + +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 +#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 +#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 +#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A +#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B +#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C +#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D +#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E +#define GL_IMAGE_1D_EXT 0x904C +#define GL_IMAGE_2D_EXT 0x904D +#define GL_IMAGE_3D_EXT 0x904E +#define GL_IMAGE_2D_RECT_EXT 0x904F +#define GL_IMAGE_CUBE_EXT 0x9050 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_IMAGE_1D_ARRAY_EXT 0x9052 +#define GL_IMAGE_2D_ARRAY_EXT 0x9053 +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 +#define GL_INT_IMAGE_1D_EXT 0x9057 +#define GL_INT_IMAGE_2D_EXT 0x9058 +#define GL_INT_IMAGE_3D_EXT 0x9059 +#define GL_INT_IMAGE_2D_RECT_EXT 0x905A +#define GL_INT_IMAGE_CUBE_EXT 0x905B +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D +#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 +#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C +#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D +#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E +#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF + +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 + +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B + +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD + +typedef char GLchar; +typedef ptrdiff_t GLsizeiptr; +typedef ptrdiff_t GLintptr; + +#if _WIN32 + #include "OpenglWin32.h" +#else + #include "OpenglLinux.h" +#endif + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/OpenglLinux.h b/gpuapi/opengl/OpenglLinux.h new file mode 100644 index 0000000..3c72bd5 --- /dev/null +++ b/gpuapi/opengl/OpenglLinux.h @@ -0,0 +1,23 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_OPENGL_LINUX_H +#define TOS_GPUAPI_OPENGL_LINUX_H + +typedef void type_glTexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void type_glBindFramebuffer(GLenum target, GLuint framebuffer); +typedef void type_glGenFramebuffers(GLsizei n, GLuint *framebuffer); +typedef void type_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef GLenum type_glCheckFramebufferStatus(GLenum target); +typedef void type_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void type_glAttachShader(GLuint program, GLuint shader); +typedef void type_glCompileShader(GLuint shader); + +// @todo continue + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/OpenglUtils.h b/gpuapi/opengl/OpenglUtils.h new file mode 100644 index 0000000..45dda7b --- /dev/null +++ b/gpuapi/opengl/OpenglUtils.h @@ -0,0 +1,511 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_OPENGL_UTILS_H +#define TOS_GPUAPI_OPENGL_UTILS_H + +#include "../../stdlib/Types.h" +#include "../../memory/RingMemory.h" +#include "../../utils/TestUtils.h" +#include "../../models/Attrib.h" +#include "../../object/Texture.h" + +#include "../RenderUtils.h" +#include "Opengl.h" + +#ifdef _WIN32 + #include + #include "../../platform/win32/UtilsWin32.h" + #include "../../platform/win32/Window.h" +#endif + +/* +struct Window { + bool is_fullscreen; + int32 width; + int32 height; + char name[32]; + + int32 x; + int32 y; + + GLFWwindow* hwnd_lib; + + #ifdef _WIN32 + HWND hwnd; + #endif +}; +*/ + +/* +inline +void window_create(Window* window, void*) +{ + //GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + window->hwnd_lib = glfwCreateWindow( + window->width, + window->height, + window->name, + NULL, + NULL + ); + + ASSERT_SIMPLE(window->hwnd_lib); + + //glfwSetInputMode(window->hwnd_lib, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + glfwMakeContextCurrent(window->hwnd_lib); + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + + #if GLFW_EXPOSE_NATIVE_WIN32 + window->hwnd = glfwGetWin32Window(window->hwnd_lib); + #endif +} + +inline +void window_open(Window* window) +{ + glfwMakeContextCurrent(window->hwnd_lib); + glViewport(window->x, window->y, window->width, window->height); + glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); +} + +inline +void window_close(Window* window) +{ + glfwWindowShouldClose(window->hwnd_lib); +} +*/ + +inline +uint32 get_texture_data_type(uint32 texture_data_type) +{ + switch (texture_data_type) { + case TEXTURE_DATA_TYPE_2D: { + return GL_TEXTURE_2D; + } + case TEXTURE_DATA_TYPE_1D: { + return GL_TEXTURE_1D; + } + case TEXTURE_DATA_TYPE_3D: { + return GL_TEXTURE_3D; + } + case TEXTURE_DATA_TYPE_1D_ARRAY: { + return GL_TEXTURE_1D_ARRAY; + } + case TEXTURE_DATA_TYPE_2D_ARRAY: { + return GL_TEXTURE_2D_ARRAY; + } + case TEXTURE_DATA_TYPE_2D_MULTISAMPLED: { + return GL_TEXTURE_2D_MULTISAMPLE; + } + case TEXTURE_DATA_TYPE_2D_MULTISAMPLED_ARRAY: { + return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; + } + default: { + return GL_TEXTURE_2D; + } + } +} + +// 1. prepare_texture +// 2. define wrap +// 3. define filter +// 4. load_texture_to_gpu + +inline +void prepare_texture(OpenGL* gl, Texture* texture, uint32 texture_unit) +{ + uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); + + glGenTextures(1, (GLuint *) &texture->id); + gl->glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(texture_data_type, (GLuint) texture->id); +} + +inline +void load_texture_to_gpu(OpenGL* gl, const Texture* texture, int mipmap_level = 0) +{ + uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); + glTexImage2D( + texture_data_type, mipmap_level, GL_RGBA, + texture->image.width, texture->image.height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, + texture->image.pixels + ); + + if (mipmap_level > -1) { + gl->glGenerateMipmap(GL_TEXTURE_2D); + } +} + +inline +void texture_use(OpenGL* gl, const Texture* texture, uint32 texture_unit) +{ + gl->glActiveTexture(GL_TEXTURE0 + texture_unit); + glBindTexture(GL_TEXTURE_2D, (GLuint) texture->id); +} + +GLuint shader_make(OpenGL* gl, GLenum type, const char *source, RingMemory* ring) +{ + GLuint shader = gl->glCreateShader(type); + gl->glShaderSource(shader, 1, (GLchar **) &source, NULL); + gl->glCompileShader(shader); + + GLint status; + gl->glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + if (status == GL_FALSE) { + ASSERT_SIMPLE(false); + + GLint length; + gl->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); + + GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); + + gl->glGetShaderInfoLog(shader, length, NULL, info); + + // @todo log + } + + return shader; +} + +GLuint shader_load(OpenGL* gl, GLenum type, const char *path, RingMemory* ring) { + uint64 temp = ring->pos; + + FileBody file; + + // @todo consider to accept file as parameter and load file before + file_read(path, &file, ring); + GLuint result = shader_make(gl, type, (const char *) file.content, ring); + + // We can immediately dispose of it we can also reset our ring memory position + ring->pos = temp; + + return result; +} + +GLuint program_make(OpenGL* gl, GLuint shader1, GLuint shader2, RingMemory* ring) { + GLuint program = gl->glCreateProgram(); + + gl->glAttachShader(program, shader1); + gl->glAttachShader(program, shader2); + gl->glLinkProgram(program); + + GLint status; + gl->glGetProgramiv(program, GL_LINK_STATUS, &status); + + if (status == GL_FALSE) { + ASSERT_SIMPLE(false); + + GLint length; + gl->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); + + GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); + + gl->glGetProgramInfoLog(program, length, NULL, info); + + // @todo use global logger + fprintf(stderr, "glLinkProgram failed: %s\n", info); + } + + // @question really? + gl->glDetachShader(program, shader1); + gl->glDetachShader(program, shader2); + + // @question really? + gl->glDeleteShader(shader1); + gl->glDeleteShader(shader2); + + return program; +} + +GLuint program_load(OpenGL* gl, const char *path1, const char *path2, RingMemory* ring) { + GLuint shader1 = shader_load(gl, GL_VERTEX_SHADER, path1, ring); + GLuint shader2 = shader_load(gl, GL_FRAGMENT_SHADER, path2, ring); + GLuint program = program_make(gl, shader1, shader2, ring); + + return program; +} + +inline +void shader_use(OpenGL* gl, uint32 id) +{ + gl->glUseProgram(id); +} + +inline +void draw_triangles_3d(OpenGL* gl, VertexRef* vertices, GLuint buffer, int count) { + gl->glBindBuffer(GL_ARRAY_BUFFER, buffer); + + // position attribute + gl->glVertexAttribPointer(vertices->position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) 0); + gl->glEnableVertexAttribArray(vertices->position); + + // normal attribute + gl->glVertexAttribPointer(vertices->normal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) (sizeof(float) * 3)); + gl->glEnableVertexAttribArray(vertices->normal); + + // texture coord attribute + gl->glVertexAttribIPointer(vertices->tex_coord, 2, GL_UNSIGNED_INT, sizeof(Vertex3D), (void *) (sizeof(float) * 6)); + gl->glEnableVertexAttribArray(vertices->tex_coord); + + // color attribute + gl->glVertexAttribPointer(vertices->color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) (sizeof(float) * 8)); + gl->glEnableVertexAttribArray(vertices->color); + + glDrawArrays(GL_TRIANGLES, 0, count); + + gl->glDisableVertexAttribArray(vertices->position); + gl->glDisableVertexAttribArray(vertices->normal); + gl->glDisableVertexAttribArray(vertices->tex_coord); + gl->glDisableVertexAttribArray(vertices->color); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +inline +void draw_triangles_3d_textureless(OpenGL* gl, VertexRef* vertices, GLuint buffer, int count) { + gl->glBindBuffer(GL_ARRAY_BUFFER, buffer); + + // position attribute + gl->glVertexAttribPointer(vertices->position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) 0); + gl->glEnableVertexAttribArray(vertices->position); + + // normal attribute + gl->glVertexAttribPointer(vertices->normal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) (sizeof(float) * 3)); + gl->glEnableVertexAttribArray(vertices->normal); + + // color attribute + gl->glVertexAttribPointer(vertices->color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) (sizeof(float) * 8)); + gl->glEnableVertexAttribArray(vertices->color); + + glDrawArrays(GL_TRIANGLES, 0, count); + + gl->glDisableVertexAttribArray(vertices->position); + gl->glDisableVertexAttribArray(vertices->normal); + gl->glDisableVertexAttribArray(vertices->color); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +inline +void draw_triangles_3d_colorless(OpenGL* gl, VertexRef* vertices, GLuint buffer, int count) { + gl->glBindBuffer(GL_ARRAY_BUFFER, buffer); + + // position attribute + gl->glVertexAttribPointer(vertices->position, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) 0); + gl->glEnableVertexAttribArray(vertices->position); + + // normal attribute + gl->glVertexAttribPointer(vertices->normal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex3D), (void *) (sizeof(float) * 3)); + gl->glEnableVertexAttribArray(vertices->normal); + + // texture coord attribute + gl->glVertexAttribIPointer(vertices->tex_coord, 2, GL_UNSIGNED_INT, sizeof(Vertex3D), (void *) (sizeof(float) * 6)); + gl->glEnableVertexAttribArray(vertices->tex_coord); + + glDrawArrays(GL_TRIANGLES, 0, count); + + gl->glDisableVertexAttribArray(vertices->position); + gl->glDisableVertexAttribArray(vertices->normal); + gl->glDisableVertexAttribArray(vertices->tex_coord); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +inline +void draw_triangles_2d(OpenGL* gl, VertexRef* vertices, GLuint buffer, int count) { + gl->glBindBuffer(GL_ARRAY_BUFFER, buffer); + + // position attribute + gl->glVertexAttribPointer(vertices->position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void *) 0); + gl->glEnableVertexAttribArray(vertices->position); + + // texture coord attribute + gl->glVertexAttribIPointer(vertices->tex_coord, 2, GL_UNSIGNED_INT, sizeof(Vertex2D), (void *) (sizeof(float) * 2)); + gl->glEnableVertexAttribArray(vertices->tex_coord); + + // color attribute + gl->glVertexAttribPointer(vertices->color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void *) (sizeof(float) * 4)); + gl->glEnableVertexAttribArray(vertices->color); + + glDrawArrays(GL_TRIANGLES, 0, count); + + gl->glDisableVertexAttribArray(vertices->position); + gl->glDisableVertexAttribArray(vertices->tex_coord); + gl->glDisableVertexAttribArray(vertices->color); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +inline +void draw_triangles_2d_textureless(OpenGL* gl, VertexRef* vertices, GLuint buffer, int count) { + gl->glBindBuffer(GL_ARRAY_BUFFER, buffer); + + // position attribute + gl->glVertexAttribPointer(vertices->position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void *) 0); + gl->glEnableVertexAttribArray(vertices->position); + + // color attribute + gl->glVertexAttribPointer(vertices->color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void *) (sizeof(float) * 4)); + gl->glEnableVertexAttribArray(vertices->color); + + glDrawArrays(GL_TRIANGLES, 0, count); + + gl->glDisableVertexAttribArray(vertices->position); + gl->glDisableVertexAttribArray(vertices->color); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +inline +void draw_triangles_2d_colorless(OpenGL* gl, VertexRef* vertices, GLuint buffer, int count) { + gl->glBindBuffer(GL_ARRAY_BUFFER, buffer); + + // position attribute + gl->glVertexAttribPointer(vertices->position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), (void *) 0); + gl->glEnableVertexAttribArray(vertices->position); + + // texture coord attribute + gl->glVertexAttribIPointer(vertices->tex_coord, 2, GL_UNSIGNED_INT, sizeof(Vertex2D), (void *) (sizeof(float) * 2)); + gl->glEnableVertexAttribArray(vertices->tex_coord); + + glDrawArrays(GL_TRIANGLES, 0, count); + + gl->glDisableVertexAttribArray(vertices->position); + gl->glDisableVertexAttribArray(vertices->tex_coord); + + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +inline +void draw_text(OpenGL* gl, VertexRef* vertices, GLuint buffer, int length) +{ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + draw_triangles_2d(gl, vertices, buffer, length * 6); + glDisable(GL_BLEND); +} + +GLuint gen_text_buffer(float x, float y, float n, const char *text) { + size_t length = strlen(text); + GLfloat *data = NULL; //malloc_faces(4, length); // sizeof(GLfloat) * 6 * 4 * length + + for (int i = 0; i < length; i++) { + make_character(data + i * 24, x, y, n / 2, n, text[i]); + x += n; + } + + return 0; //gen_faces(4, length, data); +} + +inline +void render_text(OpenGL* gl, Attrib* attrib, int justify, float x, float y, float n, const char *text) +{ + float matrix[16]; + //set_matrix_2d(matrix, g->width, g->height); + + gl->glUseProgram(attrib->program); + gl->glUniformMatrix4fv(attrib->matrix, 1, GL_FALSE, matrix); + gl->glUniform1i(attrib->sampler, 1); + gl->glUniform1i(attrib->extra1, 0); + + size_t length = strlen(text); + x -= n * justify * (length - 1) / 2; + + GLuint buffer = gen_text_buffer(x, y, n, text); + draw_text(gl, &attrib->vertices, buffer, (int) length); + + gl->glDeleteBuffers(1, &buffer); +} + +inline +int calculate_face_size(int components, int faces) +{ + return sizeof(GLfloat) * 6 * components * faces; +} + +// generates faces +// data is no longer needed after this +inline +uint32 gpuapi_buffer_generate(OpenGL* gl, int size, void* data) +{ + uint32 vbo; + + gl->glGenBuffers(1, &vbo); + gl->glBindBuffer(GL_ARRAY_BUFFER, vbo); + gl->glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + + return vbo; +} + +inline +uint32 gpuapi_buffer_element_generate(OpenGL* gl, int size, uint32 *data) +{ + uint32 ebo; + + gl->glGenBuffers(1, &ebo); + gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); + gl->glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); + + return ebo; +} + +inline +uint32 gpuapi_vertex_array_generate(OpenGL* gl) +{ + uint32 vao; + gl->glGenVertexArrays(1, &vao); + gl->glBindVertexArray(vao); + + return vao; +} + +inline +void gpuapi_unbind_all(OpenGL* gl) +{ + gl->glBindBuffer(GL_ARRAY_BUFFER, 0); + gl->glBindVertexArray(0); +} + +inline +void gpuapi_buffer_delete(OpenGL* gl, GLuint buffer) +{ + gl->glDeleteBuffers(1, &buffer); +} + +int get_gpu_free_memory() +{ + GLint available = 0; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &available); + + if (available != 0) { + return available; + } + + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &available); + + return available; +} + +/* +void render_9_patch(GLuint texture, + int imgWidth, int imgHeight, + int img_x1, int img_x2, + int img_y1, int img_y2, + int renderWidth, int renderHeight, + int repeat +) +{ + +} +*/ + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/OpenglWin32.h b/gpuapi/opengl/OpenglWin32.h new file mode 100644 index 0000000..3a659fa --- /dev/null +++ b/gpuapi/opengl/OpenglWin32.h @@ -0,0 +1,342 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_OPENGL_WIN32_H +#define TOS_GPUAPI_OPENGL_WIN32_H + +#include +#include "../../platform/win32/Window.h" +#include "../../stdlib/Types.h" + +typedef void WINAPI type_glTexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void WINAPI type_glBindFramebuffer(GLenum target, GLuint framebuffer); +typedef void WINAPI type_glGenFramebuffers(GLsizei n, GLuint *framebuffers); +typedef void WINAPI type_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef GLenum WINAPI type_glCheckFramebufferStatus(GLenum target); +typedef void WINAPI type_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void WINAPI type_glAttachShader(GLuint program, GLuint shader); +typedef void WINAPI type_glCompileShader(GLuint shader); +typedef GLuint WINAPI type_glCreateProgram(void); +typedef GLuint WINAPI type_glCreateShader(GLenum type); +typedef void WINAPI type_glLinkProgram(GLuint program); +typedef void WINAPI type_glShaderSource(GLuint shader, GLsizei count, GLchar **string, GLint *length); +typedef void WINAPI type_glUseProgram(GLuint program); +typedef void WINAPI type_glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void WINAPI type_glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void WINAPI type_glValidateProgram(GLuint program); +typedef void WINAPI type_glGetProgramiv(GLuint program, GLenum pname, GLint *params); +typedef GLint WINAPI type_glGetUniformLocation(GLuint program, const GLchar *name); +typedef void WINAPI type_glUniform4fv(GLint location, GLsizei count, const GLfloat *value); +typedef void WINAPI type_glUniform1i(GLint location, GLint v0); +typedef void WINAPI type_glUniform1f(GLint location, GLfloat v0); +typedef void WINAPI type_glUniform2fv(GLint location, GLsizei count, const GLfloat *value); +typedef void WINAPI type_glUniform3fv(GLint location, GLsizei count, const GLfloat *value); +typedef void WINAPI type_glEnableVertexAttribArray(GLuint index); +typedef void WINAPI type_glDisableVertexAttribArray(GLuint index); +typedef GLint WINAPI type_glGetAttribLocation(GLuint program, const GLchar *name); +typedef void WINAPI type_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +typedef void WINAPI type_glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void WINAPI type_glBindVertexArray(GLuint array); +typedef void WINAPI type_glGenVertexArrays(GLsizei n, GLuint *arrays); +typedef void WINAPI type_glBindBuffer(GLenum target, GLuint buffer); +typedef void WINAPI type_glGenBuffers(GLsizei n, GLuint *buffers); +typedef void WINAPI type_glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage); +typedef void WINAPI type_glActiveTexture(GLenum texture); +typedef void WINAPI type_glDeleteProgram(GLuint program); +typedef void WINAPI type_glDeleteShader(GLuint shader); +typedef void WINAPI type_glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers); +typedef void WINAPI type_glDrawBuffers(GLsizei n, const GLenum *bufs); +typedef void WINAPI type_glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void WINAPI type_glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void WINAPI type_glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void WINAPI type_glGenerateMipmap(GLenum target); +typedef void WINAPI type_glDetachShader(GLuint program, GLuint shader); +typedef void WINAPI type_glDeleteBuffers(GLsizei n, const GLuint* buffers); +typedef void WINAPI type_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void WINAPI type_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void WINAPI type_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +typedef void WINAPI type_glGetShaderiv(GLuint shader, GLenum pname, GLint* param); +//typedef void WINAPI type_glTexImage2D(GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations); + +#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 +#define WGL_CONTEXT_FLAGS_ARB 0x2094 +#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 + +#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 +#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 + +#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 + +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_PIXEL_TYPE_ARB 0x2013 + +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_FULL_ACCELERATION_ARB 0x2027 + +#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 + +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_DEPTH_BITS_ARB 0x2022 + +typedef HGLRC WINAPI wgl_create_context_attribs_arb(HDC hDC, HGLRC hShareContext, const int *attribList); +typedef BOOL WINAPI wgl_get_pixel_format_attrib_iv_arb(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL WINAPI wgl_get_pixel_format_attrib_fv_arb(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL WINAPI wgl_choose_pixel_format_arb(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +typedef const char * WINAPI wgl_get_extensions_string_ext(void); + +struct OpenGL { + type_glTexImage2DMultisample* glTexImage2DMultisample; + type_glBindFramebuffer* glBindFramebuffer; + type_glGenFramebuffers* glGenFramebuffers; + type_glFramebufferTexture2D* glFramebufferTexture2D; + type_glCheckFramebufferStatus* glCheckFramebufferStatus; + type_glBlitFramebuffer* glBlitFramebuffer; + type_glAttachShader* glAttachShader; + type_glCompileShader* glCompileShader; + type_glCreateProgram* glCreateProgram; + type_glCreateShader* glCreateShader; + type_glLinkProgram* glLinkProgram; + type_glShaderSource* glShaderSource; + type_glUseProgram* glUseProgram; + type_glGetProgramInfoLog* glGetProgramInfoLog; + type_glGetShaderInfoLog* glGetShaderInfoLog; + type_glValidateProgram* glValidateProgram; + type_glGetProgramiv* glGetProgramiv; + type_glGetUniformLocation* glGetUniformLocation; + type_glUniform4fv* glUniform4fv; + type_glUniform1i* glUniform1i; + type_glUniform1f* glUniform1f; + type_glUniform2fv* glUniform2fv; + type_glUniform3fv* glUniform3fv; + type_glEnableVertexAttribArray* glEnableVertexAttribArray; + type_glDisableVertexAttribArray* glDisableVertexAttribArray; + type_glGetAttribLocation* glGetAttribLocation; + type_glVertexAttribPointer* glVertexAttribPointer; + type_glVertexAttribIPointer* glVertexAttribIPointer; + type_glBindVertexArray* glBindVertexArray; + type_glGenVertexArrays* glGenVertexArrays; + type_glBindBuffer* glBindBuffer; + type_glGenBuffers* glGenBuffers; + type_glBufferData* glBufferData; + type_glActiveTexture* glActiveTexture; + type_glDeleteProgram* glDeleteProgram; + type_glDeleteShader* glDeleteShader; + type_glDeleteFramebuffers* glDeleteFramebuffers; + type_glDrawBuffers* glDrawBuffers; + type_glTexImage3D* glTexImage3D; + type_glTexSubImage3D* glTexSubImage3D; + type_glDrawElementsBaseVertex* glDrawElementsBaseVertex; + type_glGenerateMipmap* glGenerateMipmap; + type_glDetachShader* glDetachShader; + type_glDeleteBuffers* glDeleteBuffers; + type_glUniformMatrix2fv* glUniformMatrix2fv; + type_glUniformMatrix3fv* glUniformMatrix3fv; + type_glUniformMatrix4fv* glUniformMatrix4fv; + type_glGetShaderiv* glGetShaderiv; + + wgl_choose_pixel_format_arb* wglChoosePixelFormatARB; + wgl_create_context_attribs_arb* wglCreateContextAttribsARB; + wgl_get_extensions_string_ext* wglGetExtensionsStringEXT; +}; + +void set_pixel_format(HDC hdc, OpenGL* gl) +{ + int suggested_pixel_format_idx = 0; + unsigned int extended_pick = 0; + + if (gl->wglChoosePixelFormatARB) { + int attr_list[] = { + WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_SUPPORT_OPENGL_ARB, GL_TRUE, + WGL_DOUBLE_BUFFER_ARB, GL_TRUE, + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE, + 0, + }; + + gl->wglChoosePixelFormatARB(hdc, attr_list, 0, 1, &suggested_pixel_format_idx, &extended_pick); + } + + if(!extended_pick) { + PIXELFORMATDESCRIPTOR desired_pixel_format = {}; + desired_pixel_format.nSize = sizeof(desired_pixel_format); + desired_pixel_format.nVersion = 1; + desired_pixel_format.iPixelType = PFD_TYPE_RGBA; + desired_pixel_format.dwFlags = PFD_SUPPORT_OPENGL|PFD_DRAW_TO_WINDOW|PFD_DOUBLEBUFFER; + desired_pixel_format.cColorBits = 32; + desired_pixel_format.cAlphaBits = 8; + desired_pixel_format.cDepthBits = 24; + desired_pixel_format.iLayerType = PFD_MAIN_PLANE; + + suggested_pixel_format_idx = ChoosePixelFormat(hdc, &desired_pixel_format); + } + + PIXELFORMATDESCRIPTOR suggested_pixel_format; + DescribePixelFormat(hdc, suggested_pixel_format_idx, sizeof(suggested_pixel_format), &suggested_pixel_format); + SetPixelFormat(hdc, suggested_pixel_format_idx, &suggested_pixel_format); +} + +bool gl_extensions_load(OpenGL* gl) +{ + WNDCLASSA wc = {}; + + wc.lpfnWndProc = DefWindowProcA; + wc.hInstance = GetModuleHandle(0); + wc.lpszClassName = "WGLLoader"; + + if (!RegisterClassA(&wc)) { + return false; + } + + HWND window = CreateWindowExA( + 0, + wc.lpszClassName, + "ExtensionLoader", + 0, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + 0, + 0, + wc.hInstance, + 0 + ); + + HDC hdc = GetDC(window); + set_pixel_format(hdc, gl); + + HGLRC openGLRC = wglCreateContext(hdc); + + if (!wglMakeCurrent(hdc, openGLRC) || !gl->wglGetExtensionsStringEXT) { + return false; + } + + char *extension = (char *) gl->wglGetExtensionsStringEXT(); + char *pos = extension; + + while(*pos) { + while(*pos == ' ' || *pos == '\t' || *pos == '\r' || *pos == '\n') { + ++pos; + } + + char *end = pos; + while(*end && !(*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) { + ++end; + } + + umm count = end - pos; + + // OpenGL->SupportsSRGBFramebuffer = strcmp(count, pos, "WGL_EXT_framebuffer_sRGB") == 0 || strcmp(count, pos, "WGL_ARB_framebuffer_sRGB") == 0; + + pos = end; + } + + wglMakeCurrent(0, 0); + + wglDeleteContext(openGLRC); + ReleaseDC(window, hdc); + DestroyWindow(window); + + return true; +} + +const int win32_opengl_attribs[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, 4, + WGL_CONTEXT_MINOR_VERSION_ARB, 6, + WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + 0, +}; + +void opengl_init(Window* window, OpenGL* gl) +{ + gl_extensions_load(gl); + + gl->wglChoosePixelFormatARB = (wgl_choose_pixel_format_arb *) wglGetProcAddress("wglChoosePixelFormatARB"); + gl->wglCreateContextAttribsARB = (wgl_create_context_attribs_arb *) wglGetProcAddress("wglCreateContextAttribsARB"); + gl->wglGetExtensionsStringEXT = (wgl_get_extensions_string_ext *) wglGetProcAddress("wglGetExtensionsStringEXT"); + + set_pixel_format(window->hdc, gl); + + HGLRC openGLRC = 0; + if (gl->wglCreateContextAttribsARB) { + openGLRC = gl->wglCreateContextAttribsARB(window->hdc, 0, win32_opengl_attribs); + } + + if (!openGLRC) { + openGLRC = wglCreateContext(window->hdc); + } + + if(!wglMakeCurrent(window->hdc, openGLRC)) { + return; + } + + gl->glTexImage2DMultisample = (type_glTexImage2DMultisample *) wglGetProcAddress("glTexImage2DMultisample"); + gl->glBindFramebuffer = (type_glBindFramebuffer *) wglGetProcAddress("glBindFramebuffer"); + gl->glGenFramebuffers = (type_glGenFramebuffers *) wglGetProcAddress("glGenFramebuffers"); + gl->glFramebufferTexture2D = (type_glFramebufferTexture2D *) wglGetProcAddress("glFramebufferTexture2D"); + gl->glCheckFramebufferStatus = (type_glCheckFramebufferStatus *) wglGetProcAddress("glCheckFramebufferStatus"); + gl->glBlitFramebuffer = (type_glBlitFramebuffer *) wglGetProcAddress("glBlitFramebuffer"); + gl->glAttachShader = (type_glAttachShader *) wglGetProcAddress("glAttachShader"); + gl->glCompileShader = (type_glCompileShader *) wglGetProcAddress("glCompileShader"); + gl->glCreateProgram = (type_glCreateProgram *) wglGetProcAddress("glCreateProgram"); + gl->glCreateShader = (type_glCreateShader *) wglGetProcAddress("glCreateShader"); + gl->glLinkProgram = (type_glLinkProgram *) wglGetProcAddress("glLinkProgram"); + gl->glShaderSource = (type_glShaderSource *) wglGetProcAddress("glShaderSource"); + gl->glUseProgram = (type_glUseProgram *) wglGetProcAddress("glUseProgram"); + gl->glGetProgramInfoLog = (type_glGetProgramInfoLog *) wglGetProcAddress("glGetProgramInfoLog"); + gl->glGetShaderInfoLog = (type_glGetShaderInfoLog *) wglGetProcAddress("glGetShaderInfoLog"); + gl->glValidateProgram = (type_glValidateProgram *) wglGetProcAddress("glValidateProgram"); + gl->glGetProgramiv = (type_glGetProgramiv *) wglGetProcAddress("glGetProgramiv"); + gl->glGetUniformLocation = (type_glGetUniformLocation *) wglGetProcAddress("glGetUniformLocation"); + gl->glUniform4fv = (type_glUniform4fv *) wglGetProcAddress("glUniform4fv"); + gl->glUniform1i = (type_glUniform1i *) wglGetProcAddress("glUniform1i"); + gl->glUniform1f = (type_glUniform1f *) wglGetProcAddress("glUniform1f"); + gl->glUniform2fv = (type_glUniform2fv *) wglGetProcAddress("glUniform2fv"); + gl->glUniform3fv = (type_glUniform3fv *) wglGetProcAddress("glUniform3fv"); + gl->glEnableVertexAttribArray = (type_glEnableVertexAttribArray *) wglGetProcAddress("glEnableVertexAttribArray"); + gl->glDisableVertexAttribArray = (type_glDisableVertexAttribArray *) wglGetProcAddress("glDisableVertexAttribArray"); + gl->glGetAttribLocation = (type_glGetAttribLocation *) wglGetProcAddress("glGetAttribLocation"); + gl->glVertexAttribPointer = (type_glVertexAttribPointer *) wglGetProcAddress("glVertexAttribPointer"); + gl->glVertexAttribIPointer = (type_glVertexAttribIPointer *) wglGetProcAddress("glVertexAttribIPointer"); + gl->glBindVertexArray = (type_glBindVertexArray *) wglGetProcAddress("glBindVertexArray"); + gl->glGenVertexArrays = (type_glGenVertexArrays *) wglGetProcAddress("glGenVertexArrays"); + gl->glBindBuffer = (type_glBindBuffer *) wglGetProcAddress("glBindBuffer"); + gl->glGenBuffers = (type_glGenBuffers *) wglGetProcAddress("glGenBuffers"); + gl->glBufferData = (type_glBufferData *) wglGetProcAddress("glBufferData"); + gl->glActiveTexture = (type_glActiveTexture *) wglGetProcAddress("glActiveTexture"); + gl->glDeleteProgram = (type_glDeleteProgram *) wglGetProcAddress("glDeleteProgram"); + gl->glDeleteShader = (type_glDeleteShader *) wglGetProcAddress("glDeleteShader"); + gl->glDeleteFramebuffers = (type_glDeleteFramebuffers *) wglGetProcAddress("glDeleteFramebuffers"); + gl->glDrawBuffers = (type_glDrawBuffers *) wglGetProcAddress("glDrawBuffers"); + gl->glTexImage3D = (type_glTexImage3D *) wglGetProcAddress("glTexImage3D"); + gl->glTexSubImage3D = (type_glTexSubImage3D *) wglGetProcAddress("glTexSubImage3D"); + gl->glDrawElementsBaseVertex = (type_glDrawElementsBaseVertex *) wglGetProcAddress("glDrawElementsBaseVertex"); + gl->glGenerateMipmap = (type_glGenerateMipmap *) wglGetProcAddress("glGenerateMipmap"); + gl->glDetachShader = (type_glDetachShader *) wglGetProcAddress("glDetachShader"); + gl->glDeleteBuffers = (type_glDeleteBuffers *) wglGetProcAddress("glDeleteBuffers"); + gl->glUniformMatrix2fv = (type_glUniformMatrix2fv *) wglGetProcAddress("glUniformMatrix2fv"); + gl->glUniformMatrix3fv = (type_glUniformMatrix3fv *) wglGetProcAddress("glUniformMatrix3fv"); + gl->glUniformMatrix4fv = (type_glUniformMatrix4fv *) wglGetProcAddress("glUniformMatrix4fv"); + gl->glGetShaderiv = (type_glGetShaderiv *) wglGetProcAddress("glGetShaderiv"); + + // @todo now do: OpenGLInit +} + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/ShaderUtils.h b/gpuapi/opengl/ShaderUtils.h index 20905c0..f6713ad 100644 --- a/gpuapi/opengl/ShaderUtils.h +++ b/gpuapi/opengl/ShaderUtils.h @@ -9,82 +9,79 @@ #ifndef TOS_GPUAPI_OPENGL_SHADER_UTILS_H #define TOS_GPUAPI_OPENGL_SHADER_UTILS_H -#include "../../../EngineDependencies/opengl/glew/include/GL/glew.h" -#include "../../../EngineDependencies/opengl/glfw/include/glfw3.h" - #include "../../stdlib/Types.h" inline -void shader_set_value(uint32 id, const char* name, bool value) +void shader_set_value(OpenGL* gl, uint32 id, const char* name, bool value) { - glUniform1i(glGetUniformLocation(id, name), (int) value); + gl->glUniform1i(gl->glGetUniformLocation(id, name), (int) value); } inline -void shader_set_value(uint32 id, const char* name, int value) +void shader_set_value(OpenGL* gl, uint32 id, const char* name, int value) { - glUniform1i(glGetUniformLocation(id, name), value); + gl->glUniform1i(gl->glGetUniformLocation(id, name), value); } inline -void shader_set_value(uint32 id, const char* name, float value) +void shader_set_value(OpenGL* gl, uint32 id, const char* name, float value) { - glUniform1f(glGetUniformLocation(id, name), value); + gl->glUniform1f(gl->glGetUniformLocation(id, name), value); } inline -void shader_set_v2(uint32 id, const char* name, float* value) +void shader_set_v2(OpenGL* gl, uint32 id, const char* name, float* value) { - glUniform2fv(glGetUniformLocation(id, name), 1, value); + gl->glUniform2fv(gl->glGetUniformLocation(id, name), 1, value); } inline -void shader_set_v3(uint32 id, const char* name, float* value) +void shader_set_v3(OpenGL* gl, uint32 id, const char* name, float* value) { - glUniform3fv(glGetUniformLocation(id, name), 1, value); + gl->glUniform3fv(gl->glGetUniformLocation(id, name), 1, value); } inline -void shader_set_v4(uint32 id, const char* name, float* value) +void shader_set_v4(OpenGL* gl, uint32 id, const char* name, float* value) { - glUniform4fv(glGetUniformLocation(id, name), 1, value); + gl->glUniform4fv(gl->glGetUniformLocation(id, name), 1, value); } inline -void shader_set_m2(uint32 id, const char* name, float* value) +void shader_set_m2(OpenGL* gl, uint32 id, const char* name, float* value) { - glUniformMatrix2fv(glGetUniformLocation(id, name), 1, GL_FALSE, value); + gl->glUniformMatrix2fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value); } inline -void shader_set_m3(uint32 id, const char* name, float* value) +void shader_set_m3(OpenGL* gl, uint32 id, const char* name, float* value) { - glUniformMatrix3fv(glGetUniformLocation(id, name), 1, GL_FALSE, value); + gl->glUniformMatrix3fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value); } inline -void shader_set_m4(uint32 id, const char* name, float* value) +void shader_set_m4(OpenGL* gl, uint32 id, const char* name, float* value) { - glUniformMatrix4fv(glGetUniformLocation(id, name), 1, GL_FALSE, value); + gl->glUniformMatrix4fv(gl->glGetUniformLocation(id, name), 1, GL_FALSE, value); } inline -void shader_check_link_errors(uint32 id, char* log) +void shader_check_link_errors(OpenGL* gl, uint32 id, char* log) { GLint success; - glGetProgramiv(id, GL_LINK_STATUS, &success); + gl->glGetProgramiv(id, GL_LINK_STATUS, &success); if (!success) { - glGetProgramInfoLog(id, 1024, NULL, log); + gl->glGetProgramInfoLog(id, 1024, NULL, log); } } inline -void shader_check_compile_errors(uint32 id, char* log) +void shader_check_compile_errors(OpenGL* gl, uint32 id, char* log) { GLint success; - glGetShaderiv(id, GL_COMPILE_STATUS, &success); + gl->glGetShaderiv(id, GL_COMPILE_STATUS, &success); if (!success) { - glGetShaderInfoLog(id, 1024, NULL, log); + gl->glGetShaderInfoLog(id, 1024, NULL, log); } } diff --git a/gpuapi/opengl/UIOpengl.h b/gpuapi/opengl/UIOpengl.h index acbb001..1391790 100644 --- a/gpuapi/opengl/UIOpengl.h +++ b/gpuapi/opengl/UIOpengl.h @@ -15,8 +15,7 @@ #include "../../ui/UIButton.h" #include "../../ui/UIWindow.h" -#include "../../../EngineDependencies/opengl/glew/include/GL/glew.h" -#include "../../../EngineDependencies/opengl/glfw/include/glfw3.h" +#include void render_button(UIButton* btn) { diff --git a/gpuapi/opengl/UtilsOpengl.h b/gpuapi/opengl/UtilsOpengl.h deleted file mode 100644 index 175ecc6..0000000 --- a/gpuapi/opengl/UtilsOpengl.h +++ /dev/null @@ -1,392 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_GPUAPI_OPENGL_UTILS_H -#define TOS_GPUAPI_OPENGL_UTILS_H - -#include "../../stdlib/Types.h" -#include "../../memory/RingMemory.h" -#include "../../utils/TestUtils.h" -#include "../../models/Attrib.h" -#include "../../models/Texture.h" - -#include "../RenderUtils.h" -#include "../../../EngineDependencies/opengl/glew/include/GL/glew.h" -#include "../../../EngineDependencies/opengl/glfw/include/glfw3.h" - -#if GLFW_EXPOSE_NATIVE_WIN32 - #include "../../../EngineDependencies/opengl/glfw/include/glfw3native.h" -#endif - -#ifdef _WIN32 - #include - #include "../../platform/win32/UtilsWin32.h" -#endif - -struct Window { - bool is_fullscreen; - int32 width; - int32 height; - char name[32]; - - int32 x; - int32 y; - - GLFWwindow* hwnd_lib; - - #ifdef _WIN32 - HWND hwnd; - #endif -}; - -inline -void window_create(Window* window, void*) -{ - //GLFWmonitor *monitor = glfwGetPrimaryMonitor(); - window->hwnd_lib = glfwCreateWindow( - window->width, - window->height, - window->name, - NULL, - NULL - ); - - ASSERT_SIMPLE(window->hwnd_lib); - - //glfwSetInputMode(window->hwnd_lib, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - - glfwMakeContextCurrent(window->hwnd_lib); - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - - #if GLFW_EXPOSE_NATIVE_WIN32 - window->hwnd = glfwGetWin32Window(window->hwnd_lib); - #endif -} - -inline -void window_open(Window* window) -{ - glfwMakeContextCurrent(window->hwnd_lib); - glViewport(window->x, window->y, window->width, window->height); - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); -} - -inline -void window_close(Window* window) -{ - glfwWindowShouldClose(window->hwnd_lib); -} - -inline -uint32 get_texture_data_type(uint32 texture_data_type) -{ - switch (texture_data_type) { - case TEXTURE_DATA_TYPE_2D: { - return GL_TEXTURE_2D; - } - case TEXTURE_DATA_TYPE_1D: { - return GL_TEXTURE_1D; - } - case TEXTURE_DATA_TYPE_3D: { - return GL_TEXTURE_3D; - } - case TEXTURE_DATA_TYPE_1D_ARRAY: { - return GL_TEXTURE_1D_ARRAY; - } - case TEXTURE_DATA_TYPE_2D_ARRAY: { - return GL_TEXTURE_2D_ARRAY; - } - case TEXTURE_DATA_TYPE_2D_MULTISAMPLED: { - return GL_TEXTURE_2D_MULTISAMPLE; - } - case TEXTURE_DATA_TYPE_2D_MULTISAMPLED_ARRAY: { - return GL_TEXTURE_2D_MULTISAMPLE_ARRAY; - } - default: { - return GL_TEXTURE_2D; - } - } -} - -// 1. prepare_texture -// 2. define wrap -// 3. define filter -// 4. load_texture_to_gpu - -inline -void prepare_texture(TextureFile* texture, uint32 texture_unit) -{ - uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); - - glGenTextures(1, (GLuint *) &texture->id); - glActiveTexture(GL_TEXTURE0 + texture_unit); - glBindTexture(texture_data_type, (GLuint) texture->id); -} - -inline -void load_texture_to_gpu(const TextureFile* texture, int mipmap_level = 0) -{ - uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); - glTexImage2D( - texture_data_type, mipmap_level, GL_RGBA, - texture->image.width, texture->image.height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, - texture->image.pixels - ); - - if (mipmap_level > -1) { - glGenerateMipmap(GL_TEXTURE_2D); - } -} - -inline -void texture_use(const TextureFile* texture, uint32 texture_unit) -{ - glActiveTexture(GL_TEXTURE0 + texture_unit); - glBindTexture(GL_TEXTURE_2D, (GLuint) texture->id); -} - -GLuint make_shader(GLenum type, const char *source, RingMemory* ring) -{ - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, NULL); - glCompileShader(shader); - - GLint status; - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - - if (status == GL_FALSE) { - GLint length; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); - - GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); - - glGetShaderInfoLog(shader, length, NULL, info); - - // @todo log - } - - return shader; -} - -GLuint load_shader(GLenum type, const char *path, RingMemory* ring) { - uint64 temp = ring->pos; - - // @bug potential bug for shaders > 4 mb - FileBody file; - file.content = ring_get_memory(ring, MEGABYTE * 4); - - // @todo consider to accept file as parameter and load file before - file_read(path, &file); - GLuint result = make_shader(type, (const char *) file.content, ring); - - // 4 mb of memory reservation is a lot and since we immediately can dispose of it - // we can also reset our ring memory position - ring->pos = temp; - - return result; -} - -GLuint make_program(GLuint shader1, GLuint shader2, RingMemory* ring) { - GLuint program = glCreateProgram(); - - glAttachShader(program, shader1); - glAttachShader(program, shader2); - glLinkProgram(program); - - GLint status; - glGetProgramiv(program, GL_LINK_STATUS, &status); - - if (status == GL_FALSE) { - GLint length; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); - - GLchar *info = (GLchar *) ring_get_memory(ring, length * sizeof(GLchar)); - - glGetProgramInfoLog(program, length, NULL, info); - - // @todo use global logger - fprintf(stderr, "glLinkProgram failed: %s\n", info); - } - - // @question really? - glDetachShader(program, shader1); - glDetachShader(program, shader2); - - // @question really? - glDeleteShader(shader1); - glDeleteShader(shader2); - - return program; -} - -GLuint load_program(const char *path1, const char *path2, RingMemory* ring) { - GLuint shader1 = load_shader(GL_VERTEX_SHADER, path1, ring); - GLuint shader2 = load_shader(GL_FRAGMENT_SHADER, path2, ring); - GLuint program = make_program(shader1, shader2, ring); - - return program; -} - -inline -void shader_use(uint32 id) -{ - glUseProgram(id); -} - -void draw_triangles_3d(Attrib *attrib, GLuint buffer, int count) { - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glEnableVertexAttribArray(attrib->position); - glEnableVertexAttribArray(attrib->normal); - glEnableVertexAttribArray(attrib->uv); - glVertexAttribPointer(attrib->position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, 0); - glVertexAttribPointer(attrib->normal, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLvoid *)(sizeof(GLfloat) * 3)); - glVertexAttribPointer(attrib->uv, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLvoid *)(sizeof(GLfloat) * 6)); - glDrawArrays(GL_TRIANGLES, 0, count); - glDisableVertexAttribArray(attrib->position); - glDisableVertexAttribArray(attrib->normal); - glDisableVertexAttribArray(attrib->uv); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -void draw_triangles_2d(Attrib *attrib, GLuint buffer, size_t count) { - glBindBuffer(GL_ARRAY_BUFFER, buffer); - glEnableVertexAttribArray(attrib->position); - glEnableVertexAttribArray(attrib->uv); - glVertexAttribPointer(attrib->position, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, 0); - glVertexAttribPointer(attrib->uv, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, (GLvoid *)(sizeof(GLfloat) * 2)); - glDrawArrays(GL_TRIANGLES, 0, (GLsizei) count); - glDisableVertexAttribArray(attrib->position); - glDisableVertexAttribArray(attrib->uv); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - -inline -void draw_text(Attrib *attrib, GLuint buffer, size_t length) -{ - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - draw_triangles_2d(attrib, buffer, length * 6); - glDisable(GL_BLEND); -} - -GLuint gen_text_buffer(float x, float y, float n, const char *text) { - size_t length = strlen(text); - GLfloat *data = NULL; //malloc_faces(4, length); // sizeof(GLfloat) * 6 * 4 * length - - for (int i = 0; i < length; i++) { - make_character(data + i * 24, x, y, n / 2, n, text[i]); - x += n; - } - - return 0; //gen_faces(4, length, data); -} - -inline -void render_text(Attrib *attrib, int justify, float x, float y, float n, const char *text) -{ - float matrix[16]; - //set_matrix_2d(matrix, g->width, g->height); - - glUseProgram(attrib->program); - glUniformMatrix4fv(attrib->matrix, 1, GL_FALSE, matrix); - glUniform1i(attrib->sampler, 1); - glUniform1i(attrib->extra1, 0); - - size_t length = strlen(text); - x -= n * justify * (length - 1) / 2; - - GLuint buffer = gen_text_buffer(x, y, n, text); - draw_text(attrib, buffer, length); - - glDeleteBuffers(1, &buffer); -} - -inline -int calculate_face_size(int components, int faces) -{ - return sizeof(GLfloat) * 6 * components * faces; -} - -// generates faces -// data is no longer needed after this -inline -uint32 gpuapi_buffer_generate(int size, f32 *data) -{ - uint32 vbo; - - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); - - return vbo; -} - -inline -uint32 gpuapi_buffer_element_generate(int size, uint32 *data) -{ - uint32 ebo; - - glGenBuffers(1, &ebo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); - - return ebo; -} - -inline -uint32 gpuapi_vertex_array_generate() -{ - uint32 vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - return vao; -} - -inline -void gpuapi_unbind_all() -{ - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -inline -void gpuapi_buffer_delete(GLuint buffer) -{ - glDeleteBuffers(1, &buffer); -} - -int get_gpu_free_memory() -{ - GLint available = 0; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &available); - - if (available != 0) { - return available; - } - - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &available); - - return available; -} - -/* -void render_9_patch(GLuint texture, - int imgWidth, int imgHeight, - int img_x1, int img_x2, - int img_y1, int img_y2, - int renderWidth, int renderHeight, - int repeat -) -{ - -} -*/ - -#endif \ No newline at end of file diff --git a/hash/GeneralHash.h b/hash/GeneralHash.h new file mode 100644 index 0000000..06fb55f --- /dev/null +++ b/hash/GeneralHash.h @@ -0,0 +1,108 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_HASH_GENERAL_H +#define TOS_HASH_GENERAL_H + +#include "../stdlib/Types.h" + +uint64 hash_djb2(const char* key) { + uint64 hash = 5381; + int c; + + while ((c = *key++)) { + hash = ((hash << 5) + hash) + c; + } + + return hash; +} + +uint64 hash_sdbm(const byte* key) +{ + uint64 hash = 0; + int c; + + while (c = *key++) { + hash = c + (hash << 6) + (hash << 16) - hash; + } + + return hash; +} + +uint64 hash_lose_lose(const byte* key) +{ + uint64 hash = 0; + int c; + + while (c = *key++) { + hash += c; + } + + return hash; +} + +uint64 hash_polynomial_rolling(const char* str) { + const int p = 31; + const int m = 1000000009; + uint64 hash = 0; + uint64 p_pow = 1; + + while (*str) { + hash = (hash + (*str - 'a' + 1) * p_pow) % m; + p_pow = (p_pow * p) % m; + str++; + } + + return hash; +} + +uint64 hash_fnv1a(const char* str) { + const uint64 FNV_OFFSET_BASIS = 14695981039346656037UL; + const uint64 FNV_PRIME = 1099511628211UL; + uint64 hash = FNV_OFFSET_BASIS; + + while (*str) { + hash ^= (byte) *str; + hash *= FNV_PRIME; + str++; + } + + return hash; +} + +uint32 hash_oat(const char* str) +{ + uint32 h = 0; + + while(*str) { + h += *str++; + h += (h << 10); + h ^= (h >> 6); + } + + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; +} + +uint32 hash_ejb(const char* str) +{ + const uint32 PRIME1 = 37; + const uint32 PRIME2 = 1048583; + uint32 h = 0; + + while (*str) { + h = h * PRIME1 ^ (*str++ - ' '); + } + + return h % PRIME2; +} + +#endif \ No newline at end of file diff --git a/image/Bitmap.h b/image/Bitmap.h index 389a71a..ebef356 100644 --- a/image/Bitmap.h +++ b/image/Bitmap.h @@ -43,12 +43,6 @@ struct DIB_BITMAPCOREHEADER { #define DIB_BITMAP_TYPE_OS21XBITMAPHEADER DIB_BITMAP_TYPE_BITMAPCOREHEADER #define DIB_OS21XBITMAPHEADER DIB_BITMAPCOREHEADER -#define DIB_BITMAP_TYPE_OS22XBITMAPHEADER 64 -struct DIB_OS22XBITMAPHEADER { - // @todo implement - // They don't use a size as first value? how do I know if this is the correct header? -}; - #define DIB_BITMAP_TYPE_BITMAPINFOHEADER 40 struct DIB_BITMAPINFOHEADER { uint32 size; @@ -58,12 +52,37 @@ struct DIB_BITMAPINFOHEADER { uint16 bits_per_pixel; uint32 compression_method; uint32 raw_image_size; - //int32 horizontal_ppm; - //int32 vertical_ppm; + int32 horizontal_ppm; + int32 vertical_ppm; uint32 color_palette; uint32 important_colors; }; +#define DIB_BITMAP_TYPE_OS22XBITMAPHEADER 64 +// OR BITMAPINFOHEADER2 +struct DIB_OS22XBITMAPHEADER { + uint32 size; + int32 width; + int32 height; + uint16 color_planes; + uint16 bits_per_pixel; + uint32 compression_method; + uint32 raw_image_size; + int32 horizontal_ppm; + int32 vertical_ppm; + uint32 color_palette; + uint32 important_colors; + + uint16 units; + uint16 padding; + uint16 bit_direction; + uint16 halftoning_algorithm; + int32 halftoning_parameter_1; + int32 halftoning_parameter_2; + int32 color_encoding; + int32 application_identifier; +}; + #define DIB_BITMAPINFOHEADER_COMPRESSION_BI_RGB 0x0000 #define DIB_BITMAPINFOHEADER_COMPRESSION_BI_RLE8 0x0001 #define DIB_BITMAPINFOHEADER_COMPRESSION_BI_RLE4 0x0002 @@ -90,16 +109,16 @@ struct DIB_BITMAPV3INFOHEADER { }; -struct CIEXYZ { +struct TOS_CIEXYZ { int32 ciexyzX; int32 ciexyzY; int32 ciexyzZ; }; -struct CIEXYZTRIPLE { - CIEXYZ ciexyzRed; - CIEXYZ ciexyzGreen; - CIEXYZ ciexyzBlue; +struct TOS_CIEXYZTRIPLE { + TOS_CIEXYZ ciexyzRed; + TOS_CIEXYZ ciexyzGreen; + TOS_CIEXYZ ciexyzBlue; }; #define DIB_BITMAP_TYPE_BITMAPV4HEADER 108 @@ -111,8 +130,8 @@ struct DIB_BITMAPV4HEADER { uint16 bits_per_pixel; int32 compression_method; int32 raw_image_size; - //int32 horizontal_ppm; - //int32 vertical_ppm; + int32 horizontal_ppm; + int32 vertical_ppm; uint32 color_palette; uint32 important_colors; @@ -121,7 +140,7 @@ struct DIB_BITMAPV4HEADER { int32 bV4BlueMask; int32 bV4AlphaMask; int32 bV4CSType; - CIEXYZTRIPLE bV4Endpoints; + TOS_CIEXYZTRIPLE bV4Endpoints; int32 bV4GammaRed; int32 bV4GammaGreen; int32 bV4GammaBlue; @@ -136,8 +155,8 @@ struct DIB_BITMAPV5HEADER { uint16 bits_per_pixel; int32 compression_method; int32 raw_image_size; - //int32 horizontal_ppm; - //int32 vertical_ppm; + int32 horizontal_ppm; + int32 vertical_ppm; uint32 color_palette; uint32 important_colors; @@ -146,7 +165,7 @@ struct DIB_BITMAPV5HEADER { int32 bV5BlueMask; int32 bV5AlphaMask; int32 bV5CSType; - CIEXYZTRIPLE bV5Endpoints; + TOS_CIEXYZTRIPLE bV5Endpoints; int32 bV5GammaRed; int32 bV5GammaGreen; int32 bV5GammaBlue; @@ -158,7 +177,7 @@ struct DIB_BITMAPV5HEADER { struct Bitmap { BitmapHeader header; - byte dib_header_type; + uint32 dib_header_type; DIB_BITMAPINFOHEADER dib_header; // Despite the different header types we use this one for simplicity uint32* extra_bit_mask; // 3-4 = 12-16 bytes byte color_table_size; @@ -215,6 +234,7 @@ void generate_default_bitmap_references(const FileBody* file, Bitmap* bitmap) case DIB_BITMAP_TYPE_BITMAPV4HEADER: case DIB_BITMAP_TYPE_BITMAPV3INFOHEADER: case DIB_BITMAP_TYPE_BITMAPV2INFOHEADER: + case DIB_BITMAP_TYPE_OS22XBITMAPHEADER: case DIB_BITMAP_TYPE_BITMAPINFOHEADER: { bitmap->dib_header.size = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset))); bitmap->dib_header.width = SWAP_ENDIAN_LITTLE(*((int32 *) (dib_header_offset + 4))); @@ -223,6 +243,8 @@ void generate_default_bitmap_references(const FileBody* file, Bitmap* bitmap) bitmap->dib_header.bits_per_pixel = SWAP_ENDIAN_LITTLE(*((uint16 *) (dib_header_offset + 14))); bitmap->dib_header.compression_method = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset + 16))); bitmap->dib_header.raw_image_size = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset + 20))); + bitmap->dib_header.horizontal_ppm = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset + 24))); + bitmap->dib_header.vertical_ppm = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset + 28))); bitmap->dib_header.color_palette = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset + 32))); bitmap->dib_header.important_colors = SWAP_ENDIAN_LITTLE(*((uint32 *) (dib_header_offset + 36))); diff --git a/image/Image.cpp b/image/Image.cpp index 6fc4ad2..a6e8282 100644 --- a/image/Image.cpp +++ b/image/Image.cpp @@ -10,10 +10,6 @@ #define TOS_IMAGE_C #include "../utils/StringUtils.h" -#include "Image.h" -#include "Tga.h" -#include "Bitmap.h" -#include "Png.h" #include "../memory/RingMemory.h" #if _WIN32 @@ -22,15 +18,15 @@ #include "../platform/linux/UtilsLinux.h" #endif +#include "Image.h" +#include "Tga.h" +#include "Bitmap.h" +#include "Png.h" + void image_from_file(RingMemory* ring, const char* path, Image* image) { - char full_path[MAX_PATH]; - if (*path == '.') { - relative_to_absolute(path, full_path); - } - FileBody file; - file_read(full_path, &file, ring); + file_read(path, &file, ring); if (str_ends_with(path, ".png")) { image_png_generate(&file, image); diff --git a/image/Png.h b/image/Png.h index d70fa66..a710f77 100644 --- a/image/Png.h +++ b/image/Png.h @@ -128,9 +128,10 @@ void huffman_png_compute(uint32 symbol_count, uint32* symbol_code_length, PngHuf } } +inline PngHuffmanEntry huffman_png_decode(PngHuffman* huff, const byte* data, int pos) { - uint32 index = get_bits(data, huff->max_code_length, pos); + uint32 index = (uint32) get_bits(data, huff->max_code_length, pos); return huff->entries[index]; } @@ -142,7 +143,7 @@ void png_filter_reconstruct(uint32 width, uint32 height, const byte* decompresse for (uint32 y = 0; y < height; ++y) { byte filter = *decompressed; - byte* current_row = ; + byte* current_row = 0; // @todo need actual value switch (filter) { case 0: { @@ -240,6 +241,7 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) int i = 33; // r is the re-shift value in case we need to go back + // @todo r unused? int r = 0; // b is the current bit to read @@ -290,11 +292,11 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) // DEFLATE Algorithm // @bug the following 3 lines are wrong, they don't have to start at a bit 0/1 // A block doesn't have to start at an byte boundary - byte BFINAL = get_bits(src_data->content + i, 1, b); + byte BFINAL = (byte) get_bits(src_data->content + i, 1, b); i += (b > 7 - 1); b = (b + 1) & 7; - byte BTYPE = get_bits(src_data->content + i, 2, b); + byte BTYPE = (byte) get_bits(src_data->content + i, 2, b); i += (b > 7 - 2); b = (b + 2) & 7; @@ -305,6 +307,8 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) } uint16 len = *((uint16 *) (src_data->content + i + 1)); + + // @todo nlen unused? uint16 nlen = *((uint16 *) (src_data->content + i + 3)); memcpy(image->pixels + out_pos, src_data->content + i + 5, len); @@ -324,15 +328,15 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) if (BTYPE == 2) { // Compressed with dynamic Huffman code - huffman_literal = get_bits(src_data->content + i, 5, b); + huffman_literal = (uint32) get_bits(src_data->content + i, 5, b); i += (b > 7 - 5); b = (b + 5) & 7; - huffman_dist = get_bits(src_data->content + i, 5, b); + huffman_dist = (uint32) get_bits(src_data->content + i, 5, b); i += (b > 7 - 5); b = (b + 5) & 7; - uint32 huffman_code_length = get_bits(src_data->content + i, 4, b); + uint32 huffman_code_length = (uint32) get_bits(src_data->content + i, 4, b); i += (b > 7 - 4); b = (b + 4) & 7; @@ -343,7 +347,7 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) uint32 huffman_code_length_table[19] = {}; for (uint32 j = 0; j < huffman_code_length; ++j) { - huffman_code_length_table[HUFFMAN_CODE_LENGTH_ALPHA[j]] = get_bits(src_data->content + i, 3, b); + huffman_code_length_table[HUFFMAN_CODE_LENGTH_ALPHA[j]] = (uint32) get_bits(src_data->content + i, 3, b); i += (b > 7 - 3); b = (b + 3) & 7; } @@ -367,17 +371,17 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) if (encoded_length <= 15) { rep_val = encoded_length; } else if (encoded_length == 16) { - rep_count = 3 + get_bits(src_data->content + i, 2, b); + rep_count = 3 + (uint32) get_bits(src_data->content + i, 2, b); i += (b > 7 - 2); b = (b + 2) & 7; rep_val = literal_length_dist_table[literal_length_count - 1]; } else if (encoded_length == 17) { - rep_count = 3 + get_bits(src_data->content + i, 3, b); + rep_count = 3 + (uint32) get_bits(src_data->content + i, 3, b); i += (b > 7 - 3); b = (b + 3) & 7; } else if (encoded_length == 18) { - rep_count = 11 + get_bits(src_data->content + i, 7, b); + rep_count = 11 + (uint32) get_bits(src_data->content + i, 7, b); i += (b > 7 - 7); b = (b + 7) & 7; } @@ -423,7 +427,7 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) uint32 length = length_tab.symbol; if (length_tab.bits_used) { - uint32 extra_bits = get_bits(src_data->content + i, length_tab.bits_used, b); + uint32 extra_bits = (uint32) get_bits(src_data->content + i, length_tab.bits_used, b); i += (b + length_tab.bits_used) / 8; b = (b + length_tab.bits_used) & 7; @@ -440,7 +444,7 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) uint32 dist = dist_tab.symbol; if (dist_tab.bits_used) { - uint32 extra_bits = get_bits(src_data->content + i, dist_tab.bits_used, b); + uint32 extra_bits = (uint32) get_bits(src_data->content + i, dist_tab.bits_used, b); i += (b + dist_tab.bits_used) / 8; b = (b + dist_tab.bits_used) & 7; @@ -461,7 +465,7 @@ bool image_png_generate(const FileBody* src_data, Image* image, int steps = 8) image->height = src.ihdr.height; // @todo fix pixels parameter - png_filter_reconstruct(image->width, image->height, image->pixels, image->pixels, steps); + png_filter_reconstruct(image->width, image->height, (byte *) image->pixels, (byte *) image->pixels, steps); return true; } diff --git a/math/matrix/MatrixFloat32.h b/math/matrix/MatrixFloat32.h index 97de20e..1d23a3c 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 void mat3_identity(float* matrix) { @@ -20,6 +21,11 @@ void mat3_identity(float* matrix) matrix[6] = 0.0f; matrix[7] = 0.0f; matrix[8] = 1.0f; } +void mat3_identity_sparse(float* matrix) +{ + matrix[0] = 1.0f; matrix[4] = 1.0f; matrix[8] = 1.0f; +} + void mat3_identity(__m128* matrix) { matrix[0] = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); @@ -35,6 +41,11 @@ void mat4_identity(float* matrix) matrix[12] = 0.0f; matrix[13] = 0.0f; matrix[14] = 0.0f; matrix[15] = 1.0f; } +void mat4_identity_sparse(float* matrix) +{ + matrix[0] = 1.0f; matrix[5] = 1.0f; matrix[10] = 1.0f; matrix[15] = 1.0f; +} + void mat4_identity(__m128* matrix) { matrix[0] = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); @@ -43,28 +54,22 @@ void mat4_identity(__m128* matrix) matrix[3] = _mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f); } -void mat4_translate(float* matrix, float dx, float dy, float dz) -{ - matrix[0] = 1; matrix[1] = 0; matrix[2] = 0; matrix[3] = 0; - matrix[4] = 0; matrix[5] = 1; matrix[6] = 0; matrix[7] = 0; - matrix[8] = 0; matrix[9] = 0; matrix[10] = 1; matrix[11] = 0; - matrix[12] = dx; matrix[13] = dy; matrix[14] = dz; matrix[15] = 1; -} - // x, y, z need to be normalized -void mat4_rotate(float* matrix, float x, float y, float z, float angle) +// https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula +void mat4_rotation(float* matrix, float x, float y, float z, float angle) { - float s = sinf_approx(angle); - float c = cosf_approx(angle); + // @todo replace with quaternions + float s = sinf(angle); + float c = cosf(angle); float m = 1 - c; float mx = m * x; float my = m * y; float mz = m * z; - float zs = z * s; float xs = x * s; float ys = y * s; + float zs = z * s; float mxy = mx * y; float mzx = mz * x; @@ -118,7 +123,7 @@ void mat3vec3_mult_sse(const float* matrix, const float* vector, float* result) __m128 dot = _mm_dp_ps(row, vec, 0xF1); - result[i] = _mm_cvtss(dot); + result[i] = _mm_cvtss_f32(dot); } } @@ -128,7 +133,7 @@ void mat3vec3_mult_sse(const __m128* matrix, const __m128* vector, float* result for (int i = 0; i < 3; ++i) { __m128 dot = _mm_dp_ps(matrix[i], *vector, 0xF1); - result[i] = _mm_cvtss(dot); + result[i] = _mm_cvtss_f32(dot); } } @@ -157,7 +162,7 @@ void mat4vec4_mult_sse(const float* matrix, const float* vector, float* result) __m128 row = _mm_loadu_ps(&matrix[i * 4]); __m128 dot = _mm_dp_ps(row, vec, 0xF1); - result[i] = _mm_cvtss(dot); + result[i] = _mm_cvtss_f32(dot); } } @@ -167,7 +172,7 @@ void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, float* result for (int i = 0; i < 4; ++i) { __m128 dot = _mm_dp_ps(matrix[i], *vector, 0xF1); - result[i] = _mm_cvtss(dot); + result[i] = _mm_cvtss_f32(dot); } } @@ -179,101 +184,99 @@ void mat4vec4_mult_sse(const __m128* matrix, const __m128* vector, __m128* resul } } -void mat4mat4_mult(const float* a, const float* b, float* result) +void mat4mat4_mult(const float* a, const float* b, float* result, int steps = 8) { - // 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]; + if (steps > 1) { + // @todo check http://fhtr.blogspot.com/2010/02/4x4-float-matrix-multiplication-using.html + // @question could simple mul add sse be faster? + // Load rows of matrix a + __m128 a_1 = _mm_loadu_ps(a); + __m128 a_2 = _mm_loadu_ps(&a[4]); + __m128 a_3 = _mm_loadu_ps(&a[8]); + __m128 a_4 = _mm_loadu_ps(&a[12]); - // 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]; + // Load columns of matrix b + __m128 b_1 = _mm_loadu_ps(b); + __m128 b_2 = _mm_loadu_ps(&b[4]); + __m128 b_3 = _mm_loadu_ps(&b[8]); + __m128 b_4 = _mm_loadu_ps(&b[12]); - // 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]; + _mm_storeu_ps(&result[0], + _mm_add_ps( + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(0, 0, 0, 0)), b_1), + _mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(1, 1, 1, 1)), b_2) + ), + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(2, 2, 2, 2)), b_3), + _mm_mul_ps(_mm_shuffle_ps(a_1, a_1, _MM_SHUFFLE(3, 3, 3, 3)), b_4) + ) + ) + ); - // 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]; - result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15]; -} + _mm_storeu_ps(&result[4], + _mm_add_ps( + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(0, 0, 0, 0)), b_1), + _mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(1, 1, 1, 1)), b_2) + ), + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(2, 2, 2, 2)), b_3), + _mm_mul_ps(_mm_shuffle_ps(a_2, a_2, _MM_SHUFFLE(3, 3, 3, 3)), b_4) + ) + ) + ); -void mat4mat4_mult_sse(const float* a, const float* b, float* result) -{ - // @todo check http://fhtr.blogspot.com/2010/02/4x4-float-matrix-multiplication-using.html - // @question could simple mul add sse be faster? - __m128 a_1 = _mm_loadu_ps(a); - __m128 a_2 = _mm_loadu_ps(&a[4]); - __m128 a_3 = _mm_loadu_ps(&a[8]); - __m128 a_4 = _mm_loadu_ps(&a[12]); + _mm_storeu_ps(&result[8], + _mm_add_ps( + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(0, 0, 0, 0)), b_1), + _mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(1, 1, 1, 1)), b_2) + ), + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(2, 2, 2, 2)), b_3), + _mm_mul_ps(_mm_shuffle_ps(a_3, a_3, _MM_SHUFFLE(3, 3, 3, 3)), b_4) + ) + ) + ); - __m128 b_1 = _mm_loadu_ps(b); - __m128 b_2 = _mm_loadu_ps(&b[4]); - __m128 b_3 = _mm_loadu_ps(&b[8]); - __m128 b_4 = _mm_loadu_ps(&b[12]); - _MM_TRANSPOSE4_PS(b_1, b_2, b_3, b_4); + _mm_storeu_ps(&result[12], + _mm_add_ps( + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(0, 0, 0, 0)), b_1), + _mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(1, 1, 1, 1)), b_2) + ), + _mm_add_ps( + _mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(2, 2, 2, 2)), b_3), + _mm_mul_ps(_mm_shuffle_ps(a_4, a_4, _MM_SHUFFLE(3, 3, 3, 3)), b_4) + ) + ) + ); + } 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]; - __m128 dot; + // 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]; - // b1 - dot = _mm_dp_ps(a_1, b_1, 0xF1); - result[0] = _mm_cvtss(dot); + // 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]; - dot = _mm_dp_ps(a_2, b_1, 0xF1); - result[1] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_3, b_1, 0xF1); - result[2] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_4, b_1, 0xF1); - result[3] = _mm_cvtss(dot); - - // b2 - dot = _mm_dp_ps(a_1, b_2, 0xF1); - result[4] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_2, b_2, 0xF1); - result[5] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_3, b_2, 0xF1); - result[6] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_4, b_2, 0xF1); - result[7] = _mm_cvtss(dot); - - // b3 - dot = _mm_dp_ps(a_1, b_3, 0xF1); - result[8] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_2, b_3, 0xF1); - result[9] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_3, b_3, 0xF1); - result[10] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_4, b_3, 0xF1); - result[11] = _mm_cvtss(dot); - - // b4 - dot = _mm_dp_ps(a_1, b_4, 0xF1); - result[12] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_2, b_4, 0xF1); - result[13] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_3, b_4, 0xF1); - result[14] = _mm_cvtss(dot); - - dot = _mm_dp_ps(a_4, b_4, 0xF1); - result[15] = _mm_cvtss(dot); + // 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]; + result[15] = a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15]; + } } void mat4mat4_mult_sse(const __m128* a, const __m128* b_transposed, float* result) @@ -283,55 +286,55 @@ void mat4mat4_mult_sse(const __m128* a, const __m128* b_transposed, float* resul // @question could simple mul add sse be faster? // b1 dot = _mm_dp_ps(a[0], b_transposed[0], 0xF1); - result[0] = _mm_cvtss(dot); + result[0] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[1], b_transposed[0], 0xF1); - result[1] = _mm_cvtss(dot); + result[1] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[2], b_transposed[0], 0xF1); - result[2] = _mm_cvtss(dot); + result[2] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[3], b_transposed[0], 0xF1); - result[3] = _mm_cvtss(dot); + result[3] = _mm_cvtss_f32(dot); // b2 dot = _mm_dp_ps(a[0], b_transposed[1], 0xF1); - result[4] = _mm_cvtss(dot); + result[4] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[1], b_transposed[1], 0xF1); - result[5] = _mm_cvtss(dot); + result[5] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[2], b_transposed[1], 0xF1); - result[6] = _mm_cvtss(dot); + result[6] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[3], b_transposed[1], 0xF1); - result[7] = _mm_cvtss(dot); + result[7] = _mm_cvtss_f32(dot); // b3 dot = _mm_dp_ps(a[0], b_transposed[2], 0xF1); - result[8] = _mm_cvtss(dot); + result[8] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[1], b_transposed[2], 0xF1); - result[9] = _mm_cvtss(dot); + result[9] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[2], b_transposed[2], 0xF1); - result[10] = _mm_cvtss(dot); + result[10] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[3], b_transposed[2], 0xF1); - result[11] = _mm_cvtss(dot); + result[11] = _mm_cvtss_f32(dot); // b4 dot = _mm_dp_ps(a[0], b_transposed[3], 0xF1); - result[12] = _mm_cvtss(dot); + result[12] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[1], b_transposed[3], 0xF1); - result[13] = _mm_cvtss(dot); + result[13] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[2], b_transposed[3], 0xF1); - result[14] = _mm_cvtss(dot); + result[14] = _mm_cvtss_f32(dot); dot = _mm_dp_ps(a[3], b_transposed[3], 0xF1); - result[15] = _mm_cvtss(dot); + result[15] = _mm_cvtss_f32(dot); } void mat4mat4_mult_sse(const __m128* a, const __m128* b_transpose, __m128* result) @@ -384,10 +387,11 @@ void mat4_frustum_planes(float planes[6][4], float radius, float *matrix) { planes[5][3] = zfar * m[15] - m[14]; } -void mat4_frustum( - float *matrix, float left, float right, float bottom, - float top, float znear, float zfar) -{ +void mat4_frustum_sparse( + float *matrix, + float left, float right, float bottom, float top, + float znear, float zfar + ) { float temp, temp2, temp3, temp4; temp = 2.0f * znear; temp2 = right - left; @@ -395,41 +399,45 @@ void mat4_frustum( temp4 = zfar - znear; matrix[0] = temp / temp2; - matrix[1] = 0.0; - matrix[2] = 0.0; - matrix[3] = 0.0; + //matrix[1] = 0.0f; + //matrix[2] = 0.0f; + //matrix[3] = 0.0f; - matrix[4] = 0.0; + //matrix[4] = 0.0f; matrix[5] = temp / temp3; - matrix[6] = 0.0; - matrix[7] = 0.0; + //matrix[6] = 0.0f; + //matrix[7] = 0.0f; matrix[8] = (right + left) / temp2; matrix[9] = (top + bottom) / temp3; - matrix[10] = (-zfar - znear) / temp4; - matrix[11] = -1.0; + matrix[10] = -(zfar + znear) / temp4; + matrix[11] = -1.0f; - matrix[12] = 0.0; - matrix[13] = 0.0; + //matrix[12] = 0.0f; + //matrix[13] = 0.0f; matrix[14] = (-temp * zfar) / temp4; - matrix[15] = 0.0; + //matrix[15] = 0.0f; } -void mat4_perspective( +// fov needs to be in rad +void mat4_perspective_sparse( float *matrix, float fov, float aspect, float znear, float zfar) { + ASSERT_SIMPLE(znear > 0.0f); + float ymax, xmax; - ymax = znear * tanf_approx(fov * OMS_PI / 360.0f); + ymax = znear * tanf(fov * 0.5f); xmax = ymax * aspect; - mat4_frustum(matrix, -xmax, xmax, -ymax, ymax, znear, zfar); + mat4_frustum_sparse(matrix, -xmax, xmax, -ymax, ymax, znear, zfar); } void mat4_ortho( float *matrix, - float left, float right, float bottom, float top, float near_dist, float far_dist) -{ + float left, float right, float bottom, float top, + float near_dist, float far_dist +) { float rl_delta = right - left; float tb_delta = top - bottom; float fn_delta = far_dist - near_dist; @@ -455,4 +463,18 @@ void mat4_ortho( matrix[15] = 1; } +void mat4_translate(float* matrix, float dx, float dy, float dz, int steps = 8) +{ + alignas(64) float temp[16]; + 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; + + mat4mat4_mult(temp, translation_matrix, matrix, steps); +} + #endif \ No newline at end of file diff --git a/memory/Allocation.h b/memory/Allocation.h new file mode 100644 index 0000000..009e765 --- /dev/null +++ b/memory/Allocation.h @@ -0,0 +1,113 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_MEMORY_ALLOCATION_H +#define TOS_MEMORY_ALLOCATION_H + +#include + +#if _WIN32 + #include + + inline + void* aligned_alloc(size_t alignment, size_t size) { + return _aligned_malloc(size, alignment); + } + + inline + void aligned_free(void* ptr) { + _aligned_free(ptr); + ptr = NULL; + } + + inline + void* playform_alloc(size_t size) + { + return VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + } + + inline + void* playform_alloc_aligned(size_t size, int alignment) + { + void* ptr = VirtualAlloc(NULL, size + alignment + sizeof(void*), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + + void* aligned_ptr = (void*)(((uintptr_t)ptr + alignment + sizeof(void*) - 1) & ~(alignment - 1)); + ((void**) aligned_ptr)[-1] = ptr; + + return aligned_ptr; + } + + inline + void platform_free(void* ptr, size_t) { + VirtualFree(ptr, 0, MEM_RELEASE); + ptr = NULL; + } + + inline + void platform_aligned_free(void* aligned_ptr, size_t) { + void* ptr = ((void**) aligned_ptr)[-1]; + VirtualFree(ptr, 0, MEM_RELEASE); + aligned_ptr = NULL; + } +#else + #include + #include + + inline + void aligned_free(void* ptr) { + free(ptr); + ptr = NULL; + } + + inline + void* playform_alloc(size_t size) + { + // Get the system page size + size_t page_size = sysconf(_SC_PAGESIZE); + + // Round up to the nearest page size + size = (size + page_size - 1) & ~(page_size - 1); + + return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + + inline + void* playform_alloc_aligned(size_t size, int alignment) + { + // Get the system page size + size_t page_size = sysconf(_SC_PAGESIZE); + if (alignment < page_size) { + alignment = page_size; + } + + // Round up to the nearest alignment boundary + size = (size + alignment - 1) & ~(alignment - 1); + + void* ptr = mmap(NULL, size + alignment + sizeof(void*), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + void* aligned_ptr = (void*)(((uintptr_t)ptr + alignment + sizeof(void*) - 1) & ~(alignment - 1)); + ((void**) aligned_ptr)[-1] = ptr; + + return aligned_ptr; + } + + inline + void platform_free(void* ptr, size_t size) { + munmap(ptr, size); + ptr = NULL; + } + + inline + void platform_aligned_free(void* aligned_ptr, size_t size) { + void* ptr = ((void**) aligned_ptr)[-1]; + munmap(ptr, size + ((uintptr_t)aligned_ptr - (uintptr_t)ptr)); + aligned_ptr = NULL; + } +#endif + +#endif \ No newline at end of file diff --git a/memory/BufferMemory.h b/memory/BufferMemory.h index 054ccec..9751024 100644 --- a/memory/BufferMemory.h +++ b/memory/BufferMemory.h @@ -11,23 +11,54 @@ #include #include "../stdlib/Types.h" -#include "MathUtils.h" -#include "TestUtils.h" +#include "../utils/MathUtils.h" +#include "../utils/TestUtils.h" +#include "Allocation.h" struct BufferMemory { byte* memory; uint64 size; uint64 pos; + int alignment; }; inline -byte* buffer_get_memory(BufferMemory* buf, uint64 size, byte aligned = 1, bool zeroed = false) +void buffer_alloc(BufferMemory* buf, uint64 size, int alignment = 1) +{ + buf->memory = alignment < 2 + ? (byte *) playform_alloc(size) + : (byte *) playform_alloc_aligned(size, alignment); + + buf->alignment = alignment; + buf->size = size; +} + +inline +void buffer_free(BufferMemory* buf) +{ + if (buf->alignment < 2) { + platform_free(buf->memory, buf->size); + } else { + platform_aligned_free(buf->memory, buf->size); + } +} + +inline +void buffer_reset(BufferMemory* buf) +{ + // @bug arent we wasting element 0 (see get_memory, we are not using 0 only next element) + buf->pos = 0; +} + +inline +byte* buffer_get_memory(BufferMemory* buf, uint64 size, int aligned = 1, bool zeroed = false) { ASSERT_SIMPLE(size <= buf->size); - if (aligned > 1 && buf->pos > 0) { - buf->pos = ROUND_TO_NEAREST(buf->pos, aligned); + if (aligned > 1) { + uintptr_t address = (uintptr_t) buf->memory; + buf->pos += (aligned - ((address + buf->pos) & (aligned - 1))) % aligned; } size = ROUND_TO_NEAREST(size, aligned); diff --git a/memory/ChunkMemory.h b/memory/ChunkMemory.h index 6d69bf4..29becf3 100644 --- a/memory/ChunkMemory.h +++ b/memory/ChunkMemory.h @@ -11,50 +11,81 @@ #include #include "../stdlib/Types.h" -#include "MathUtils.h" +#include "../utils/MathUtils.h" +#include "Allocation.h" struct ChunkMemory { byte* memory; uint64 count; uint64 chunk_size; - uint64 last_pos = -1; + int64 last_pos; + int alignment; // length = count // free describes which locations are used and which are free - // @performance using uint32 or even uint64 might be faster - // since we can check for free elements faster if the memory is almost filled - // at the moment we can only check 8 elements at a time uint64* free; }; inline -byte* chunk_get_memory(ChunkMemory* buf, uint64 element) +void chunk_alloc(ChunkMemory* buf, uint64 count, uint64 chunk_size, int alignment = 1) { - return buf->memory + element * buf->chunk_size; + buf->memory = alignment < 2 + ? (byte *) playform_alloc(count * chunk_size + sizeof(buf->free) * CEIL_DIV(count, 64)) + : (byte *) playform_alloc_aligned(count * chunk_size + sizeof(buf->free) * CEIL_DIV(count, 64), alignment); + + buf->count = count; + buf->chunk_size = chunk_size; + buf->last_pos = -1; + buf->alignment = alignment; + buf->free = (uint64 *) (buf->memory + count * chunk_size); +} + +inline +void chunk_free(ChunkMemory* buf) +{ + if (buf->alignment < 2) { + platform_free(buf->memory, buf->count * buf->chunk_size); + } else { + platform_aligned_free(buf->memory, buf->count * buf->chunk_size); + } +} + +inline +byte* chunk_get_element(ChunkMemory* buf, uint64 element, bool zeroed = false) +{ + byte* offset = buf->memory + element * buf->chunk_size; + + if (zeroed) { + memset((void *) offset, 0, buf->chunk_size); + } + + return offset; } /** * In some cases we know exactly which index is free */ -void chunk_reserve_index(ChunkMemory* buf, int64 index, int elements = 1, bool zeroed = false) +void chunk_reserve_index(ChunkMemory* buf, int64 index, int64 elements = 1, bool zeroed = false) { - int byte_index = index / 64; + int64 byte_index = index / 64; int bit_index = index % 64; // Mark the bits as reserved for (int j = 0; j < elements; ++j) { - int current_byte_index = byte_index + (bit_index + j) / 64; + int64 current_byte_index = byte_index + (bit_index + j) / 64; int current_bit_index = (bit_index + j) % 64; - buf->free[current_byte_index] |= (1 << current_bit_index); + buf->free[current_byte_index] |= (1LL << current_bit_index); } if (zeroed) { memset(buf->memory + index * buf->chunk_size, 0, elements * buf->chunk_size); } + + buf->last_pos = index; } -int64 chunk_reserve(ChunkMemory* buf, int elements = 1, bool zeroed = false) +int64 chunk_reserve(ChunkMemory* buf, uint64 elements = 1, bool zeroed = false) { int64 byte_index = (buf->last_pos + 1) / 64; int bit_index; @@ -63,9 +94,15 @@ int64 chunk_reserve(ChunkMemory* buf, int elements = 1, bool zeroed = false) byte mask; int i = 0; - while (free_element < 0 && i < (buf->count + 7) / 64) { + int64 max_bytes = (buf->count + 7) / 64; + + while (free_element < 0 && i < buf->count) { ++i; + if (byte_index >= max_bytes) { + byte_index = 0; + } + if (buf->free[byte_index] == 0xFF) { ++byte_index; @@ -78,7 +115,7 @@ int64 chunk_reserve(ChunkMemory* buf, int elements = 1, bool zeroed = false) // Check if there are 'elements' consecutive free bits for (int j = 0; j < elements; ++j) { - int current_byte_index = byte_index + (bit_index + j) / 64; + uint64 current_byte_index = byte_index + (bit_index + j) / 64; int current_bit_index = (bit_index + j) % 64; if (current_byte_index >= (buf->count + 7) / 64) { @@ -98,9 +135,9 @@ int64 chunk_reserve(ChunkMemory* buf, int elements = 1, bool zeroed = false) // Mark the bits as reserved for (int j = 0; j < elements; ++j) { - int current_byte_index = byte_index + (bit_index + j) / 64; + int64 current_byte_index = byte_index + (bit_index + j) / 64; int current_bit_index = (bit_index + j) % 64; - buf->free[current_byte_index] |= (1 << current_bit_index); + buf->free[current_byte_index] |= (1LL << current_bit_index); } break; @@ -119,21 +156,27 @@ int64 chunk_reserve(ChunkMemory* buf, int elements = 1, bool zeroed = false) memset(buf->memory + free_element * buf->chunk_size, 0, elements * buf->chunk_size); } + buf->last_pos = free_element; + return free_element; } byte* chunk_find_free(ChunkMemory* buf) { - int byte_index = (buf->last_pos + 1) / 64; + int64 byte_index = (buf->last_pos + 1) / 64; int bit_index; int64 free_element = -1; byte mask; int i = 0; - int max_loop = buf->count * buf->chunk_size; + int64 max_bytes = (buf->count + 7) / 64; + + while (free_element < 0 && i < buf->count) { + if (byte_index >= max_bytes) { + byte_index = 0; + } - while (free_element < 0 && i < max_loop) { if (buf->free[byte_index] == 0xFF) { ++i; ++byte_index; @@ -148,6 +191,8 @@ byte* chunk_find_free(ChunkMemory* buf) mask = 1 << bit_index; if ((buf->free[byte_index] & mask) == 0) { free_element = byte_index * 64 + bit_index; + buf->free[byte_index] |= (1LL << bit_index); + break; } } @@ -157,15 +202,13 @@ byte* chunk_find_free(ChunkMemory* buf) return NULL; } - buf->free[byte_index] |= (1 << bit_index); - return buf->memory + free_element * buf->chunk_size; } inline -void chunk_element_free(ChunkMemory* buf, uint64 element) +void chunk_free_element(ChunkMemory* buf, uint64 element) { - int byte_index = element / 64; + int64 byte_index = element / 64; int bit_index = element % 64; buf->free[byte_index] &= ~(1 << bit_index); diff --git a/memory/RingMemory.h b/memory/RingMemory.h index 7aa8f7a..6a9f395 100644 --- a/memory/RingMemory.h +++ b/memory/RingMemory.h @@ -11,32 +11,86 @@ #include #include "../stdlib/Types.h" -#include "MathUtils.h" -#include "TestUtils.h" +#include "../utils/MathUtils.h" +#include "../utils/TestUtils.h" +#include "Allocation.h" +#include "BufferMemory.h" struct RingMemory { byte* memory; uint64 size; uint64 pos; + int alignment; // The following two indices are only used in special cases such as iterating through a portion // of the ring memory. In such cases it may be necessary to know where the start and end are. // Examples for such cases are if a worker thread is pulling data from this ring memory in chunks. + + // @question Is it guaranteed that if a thread realizes end changed, that also the memory is changed + // or is it possible that end changed but it still has old *memory in the cache? + // if yes we need to also check and wait for *memory != NULL and obviously set the memory to NULL + // after using it. uint64 start; uint64 end; }; +inline +void ring_alloc(RingMemory* ring, uint64 size, int alignment = 1) +{ + ring->memory = alignment < 2 + ? (byte *) playform_alloc(size) + : (byte *) playform_alloc_aligned(size, alignment); + + ring->size = size; + ring->pos = 0; + ring->alignment = alignment; + ring->start = 0; + ring->end = 0; +} + +inline +void ring_create(RingMemory* ring, BufferMemory* buf, uint64 size, int alignment = 1) +{ + ring->memory = buffer_get_memory(buf, size, alignment); + + ring->size = size; + ring->pos = 0; + ring->alignment = alignment; + ring->start = 0; + ring->end = 0; +} + +inline +void ring_free(RingMemory* buf) +{ + if (buf->alignment < 2) { + platform_free(buf->memory, buf->size); + } else { + platform_aligned_free(buf->memory, buf->size); + } +} + inline uint64 ring_calculate_position(const RingMemory* ring, uint64 pos, uint64 size, byte aligned = 1) { - if (aligned > 1 && ring->pos > 0) { - pos = ROUND_TO_NEAREST(pos, aligned); + if (aligned) { + uintptr_t address = (uintptr_t) ring->memory; + int64 adjustment = (aligned - ((address + ring->pos) & (aligned - 1))) % aligned; + + pos += adjustment; } size = ROUND_TO_NEAREST(size, aligned); if (pos + size > ring->size) { pos = 0; + + if (aligned > 1) { + uintptr_t address = (uintptr_t) ring->memory; + int64 adjustment = (aligned - ((address + ring->pos) & (aligned - 1))) % aligned; + + pos += adjustment; + } } return pos; @@ -46,13 +100,23 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 1, bool zero { ASSERT_SIMPLE(size <= ring->size); - if (aligned > 1 && ring->pos > 0) { - ring->pos = ROUND_TO_NEAREST(ring->pos, aligned); + if (aligned > 1) { + uintptr_t address = (uintptr_t) ring->memory; + int64 adjustment = (aligned - ((address + ring->pos) & (aligned - 1))) % aligned; + + ring->pos += adjustment; } size = ROUND_TO_NEAREST(size, aligned); if (ring->pos + size > ring->size) { ring->pos = 0; + + if (aligned > 1) { + uintptr_t address = (uintptr_t) ring->memory; + int64 adjustment = (aligned - ((address + ring->pos) & (aligned - 1))) % aligned; + + ring->pos += adjustment; + } } byte* offset = (byte *) (ring->memory + ring->pos); @@ -68,11 +132,9 @@ byte* ring_get_memory(RingMemory* ring, uint64 size, byte aligned = 1, bool zero // Used if the ring only contains elements of a certain size // This way you can get a certain element inline -byte *ring_get_element(const RingMemory* ring, uint64 element_count, uint64 element, uint64 size) +byte* ring_get_element(const RingMemory* ring, uint64 element_count, uint64 element, uint64 size) { - uint64 index = (element % element_count) - 1; - index = index < 0 ? element_count : index; - + int64 index = (element % element_count) - 1; return ring->memory + index * size; } diff --git a/models/Attrib.h b/models/Attrib.h index 88de5c1..b813664 100644 --- a/models/Attrib.h +++ b/models/Attrib.h @@ -10,13 +10,12 @@ #define TOS_ATTRIB_H #if OPENGL - #include "../../EngineDependencies/opengl/glew/include/GL/glew.h" + #include "../gpuapi/opengl/Opengl.h" + #include "../object/Vertex.h" struct Attrib { GLuint program; - GLuint position; - GLuint normal; - GLuint uv; + VertexRef vertices; GLuint matrix; GLuint sampler; GLuint camera; diff --git a/models/chat/ChatType.h b/models/chat/ChatType.h index 5ecdfb2..c94a07a 100644 --- a/models/chat/ChatType.h +++ b/models/chat/ChatType.h @@ -10,11 +10,17 @@ #define TOS_MODELS_CHAT_TYPE_H enum ChatType { - CHAT_TYPE_LOCAL, - CHAT_TYPE_GLOBAL, - CHAT_TYPE_PLAYER, - CHAT_TYPE_GROUP, - CHAT_TYPE_GUILD + CHAT_TYPE_MIXED = 1, + CHAT_TYPE_LOCAL = 2, + CHAT_TYPE_GLOBAL = 4, + CHAT_TYPE_PLAYER = 8, + CHAT_TYPE_GROUP = 16, + CHAT_TYPE_GUILD = 32, + CHAT_TYPE_AUCTION_HOUSE = 64, + CHAT_TYPE_TRADE = 128, + CHAT_TYPE_PRIVATE = 256, // e.g. direct messages, also used in raid finders etc. + CHAT_TYPE_FRIENDS = 512, + CHAT_TYPE_CHAT_ROOM = 1024 }; #endif \ No newline at end of file diff --git a/models/mob/skill/definitions/fear.cfg b/models/mob/skill/definitions/fear.cfg new file mode 100644 index 0000000..3378972 --- /dev/null +++ b/models/mob/skill/definitions/fear.cfg @@ -0,0 +1 @@ +# makes feared run from caster/target? \ No newline at end of file diff --git a/models/settings/Settings.h b/models/settings/Settings.h index 8fb2ebc..1619db5 100644 --- a/models/settings/Settings.h +++ b/models/settings/Settings.h @@ -101,7 +101,7 @@ struct CSettings { byte gpu_api = SETTING_TYPE_GPU_API_NONE; byte gpu_type = SETTING_TYPE_GPU_MEDIUM; byte gpu_fps = SETTING_TYPE_UNLIMITED; - byte gpu_memory = 4; + byte gpu_memory = 4; // how much vram are we using on the gpu byte gpu_aspect_ratio; byte gpu_resolution; @@ -145,9 +145,6 @@ struct CSettings { byte gpu_footprint_quality; // mostly used for snow, sand mud bool gpu_screen_effects; // e.g. water droplets/dust/freezing on screen - byte gpu_memory = 7; - byte cpu_memory = 10; - bool gpu_raytracing = false; bool gpu_lense_effect = true; bool gpu_fog_effect = true; @@ -414,6 +411,14 @@ struct CSettings { byte hotkeys_marker_3 = 0x33; // 3 byte hotkeys_marker_4 = 0x34; // 4 byte hotkeys_marker_5 = 0x35; // 5 + + // Camera settings/positions + // Makes it easy to switch to customizable camera positions + byte hotkeys_camera_1 = 0x0; + byte hotkeys_camera_2 = 0x0; + byte hotkeys_camera_3 = 0x0; + + // @todo implement the actual camera settings }; #endif \ No newline at end of file diff --git a/noise/FractalNoise.h b/noise/FractalNoise.h new file mode 100644 index 0000000..7d8439b --- /dev/null +++ b/noise/FractalNoise.h @@ -0,0 +1,15 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_NOISE_FRACTAL_H +#define TOS_NOISE_FRACTAL_H + +#include + +#endif \ No newline at end of file diff --git a/models/mob/skill/definitions/beam b/noise/PerlinNoise.h similarity index 100% rename from models/mob/skill/definitions/beam rename to noise/PerlinNoise.h diff --git a/noise/SimplexNoise.h b/noise/SimplexNoise.h new file mode 100644 index 0000000..5ad553c --- /dev/null +++ b/noise/SimplexNoise.h @@ -0,0 +1,221 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_NOISE_SIMPLEX_H +#define TOS_NOISE_SIMPLEX_H + +#include + +#define SIMPLEX_NOISE_F2 0.5 * (sqrt(3.0) - 1.0) +#define SIMPLEX_NOISE_G2 (3.0 - sqrt(3.0)) / 6.0 + +static const int perm[512] = { + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142, + + 151,160,137,91,90,15, + 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142, +}; + +static const int grad3_2[12][2] = { + {1,1}, {-1,1}, {1,-1}, {-1,-1}, + {1,0}, {-1,0}, {1,0}, {-1,0}, + {0,1}, {0,-1}, {0,1}, {0,-1} +}; + +static const int grad3_3[12][3] = { + {1,1,0}, {-1,1,0}, {1,-1,0}, {-1,-1,0}, + {1,0,1}, {-1,0,1}, {1,0,-1}, {-1,0,-1}, + {0,1,1}, {0,-1,1}, {0,1,-1}, {0,-1,-1} +}; + +static inline double simplex_noise_dot2(const int* g, double x, double y) { + return g[0] * x + g[1] * y; +} + +static inline double simplex_noise_dot3(const int* g, double x, double y, double z) { + return g[0] * x + g[1] * y + g[2] * z; +} + +double simplex_noise_2d(double x, double y) { + double n0, n1, n2; // Noise contributions from the three corners + + // Skew the input space to determine which simplex cell we're in + double s = (x + y) * SIMPLEX_NOISE_F2; // Hairy factor for 2D + int i = floor(x + s); + int j = floor(y + s); + + double t = (i + j) * SIMPLEX_NOISE_G2; + double X0 = i - t; // Unskew the cell origin back to (x, y) space + double Y0 = j - t; + double x0 = x - X0; // The x, y distances from the cell origin + double y0 = y - Y0; + + // For the 2D case, the simplex shape is an equilateral triangle. + // Determine which simplex we are in. + int i1, j1; // Offsets for the second (middle) corner of simplex in (i, j) + if (x0 > y0) { + i1 = 1; j1 = 0; // Lower triangle, XY order + } else { + i1 = 0; j1 = 1; // Upper triangle, YX order + } + + // A step of (1, 0) in (i, j) means a step of (1 - c, -c) in (x, y), and + // a step of (0, 1) in (i, j) means a step of (-c, 1 - c) in (x, y), where + // c = (3 - sqrt(3)) / 6 + + double x1 = x0 - i1 + SIMPLEX_NOISE_G2; // Offsets for middle corner in (x, y) unskewed coords + double y1 = y0 - j1 + SIMPLEX_NOISE_G2; + double x2 = x0 - 1.0 + 2.0 * SIMPLEX_NOISE_G2; // Offsets for last corner in (x, y) unskewed coords + double y2 = y0 - 1.0 + 2.0 * SIMPLEX_NOISE_G2; + + // Work out the hashed gradient indices of the three simplex corners + int ii = i & 255; + int jj = j & 255; + int gi0 = perm[ii + perm[jj]] % 12; + int gi1 = perm[ii + i1 + perm[jj + j1]] % 12; + int gi2 = perm[ii + 1 + perm[jj + 1]] % 12; + + // Calculate the contribution from the three corners + double t0 = 0.5 - x0 * x0 - y0 * y0; + if (t0 < 0) { + n0 = 0.0; + } else { + t0 *= t0; + n0 = t0 * t0 * simplex_noise_dot2(grad3_2[gi0], x0, y0); // (x,y) of grad3_2 used for 2D gradient + } + + double t1 = 0.5 - x1 * x1 - y1 * y1; + if (t1 < 0) { + n1 = 0.0; + } else { + t1 *= t1; + n1 = t1 * t1 * simplex_noise_dot2(grad3_2[gi1], x1, y1); + } + + double t2 = 0.5 - x2 * x2 - y2 * y2; + if (t2 < 0) { + n2 = 0.0; + } else { + t2 *= t2; + n2 = t2 * t2 * simplex_noise_dot2(grad3_2[gi2], x2, y2); + } + + // Add contributions from each corner to get the final noise value. + // The result is scaled to return values in the interval [-1,1]. + return 70.0 * (n0 + n1 + n2); +} + +double simplex_noise_3d(double x, double y, double z) { + double n0, n1, n2, n3; // Noise contributions from the four corners + + // Skew the input space to determine which simplex cell we're in + double s = (x + y + z) * SIMPLEX_NOISE_F2; // Skew factor for 3D + int i = floor(x + s); + int j = floor(y + s); + int k = floor(z + s); + + double t = (i + j + k) * SIMPLEX_NOISE_G2; + double X0 = i - t; // Unskew the cell origin back to (x, y, z) space + double Y0 = j - t; + double Z0 = k - t; + double x0 = x - X0; // The x, y, z distances from the cell origin + double y0 = y - Y0; + double z0 = z - Z0; + + // For the 3D case, the simplex shape is a slightly irregular tetrahedron. + // Determine which simplex we are in. + int i1, j1, k1; // Offsets for second corner of simplex in (i, j, k) + int i2, j2, k2; // Offsets for third corner of simplex in (i, j, k) + + if (x0 >= y0) { + if (y0 >= z0) { + i1 = 1; j1 = 0; k1 = 0; // X Y Z order + i2 = 1; j2 = 1; k2 = 0; + } else if (x0 >= z0) { + i1 = 1; j1 = 0; k1 = 0; // X Z Y order + i2 = 1; j2 = 0; k2 = 1; + } else { + i1 = 0; j1 = 0; k1 = 1; // Z X Y order + i2 = 1; j2 = 0; k2 = 1; + } + } else { // x0 < y0 + if (y0 < z0) { + i1 = 0; j1 = 0; k1 = 1; // Z Y X order + i2 = 0; j2 = 1; k2 = 1; + } else if (x0 < z0) { + i1 = 0; j1 = 1; k1 = 0; // Y Z X order + i2 = 0; j2 = 1; k2 = 1; + } else { + i1 = 0; j1 = 1; k1 = 0; // Y X Z order + i2 = 1; j2 = 1; k2 = 0; + } + } + + // Offsets for second corner in (x, y, z) unskewed coords + double x1 = x0 - i1 + SIMPLEX_NOISE_G2; + double y1 = y0 - j1 + SIMPLEX_NOISE_G2; + double z1 = z0 - k1 + SIMPLEX_NOISE_G2; + // Offsets for third corner in (x, y, z) unskewed coords + double x2 = x0 - i2 + 2.0 * SIMPLEX_NOISE_G2; + double y2 = y0 - j2 + 2.0 * SIMPLEX_NOISE_G2; + double z2 = z0 - k2 + 2.0 * SIMPLEX_NOISE_G2; + // Offsets for last corner in (x, y, z) unskewed coords + double x3 = x0 - 1.0 + 3.0 * SIMPLEX_NOISE_G2; + double y3 = y0 - 1.0 + 3.0 * SIMPLEX_NOISE_G2; + double z3 = z0 - 1.0 + 3.0 * SIMPLEX_NOISE_G2; + + // Work out the hashed gradient indices of the four simplex corners + int ii = i & 255; + int jj = j & 255; + int kk = k & 255; + int gi0 = perm[ii + perm[jj + perm[kk]]] % 12; + int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12; + int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12; + int gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]] % 12; + + // Calculate the contribution from the four corners + double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; + if (t0 < 0) { + n0 = 0.0; + } else { + t0 *= t0; + n0 = t0 * t0 * simplex_noise_dot3(grad3_3[gi0], x0, y0, z0); + } + + double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; + if (t1 < 0) { + n1 = 0.0; + } else { + t1 *= t1; + n1 = t1 * t1 * simplex_noise_dot3(grad3_3[gi1], x1, y1, z1); + } + + double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; + if (t2 < 0) { + n2 = 0.0; + } else { + t2 *= t2; + n2 = t2 * t2 * simplex_noise_dot3(grad3_3[gi2], x2, y2, z2); + } + + double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; + if (t3 < 0) { + n3 = 0.0; + } else { + t3 *= t3; + n3 = t3 * t3 * simplex_noise_dot3(grad3_3[gi3], x3, y3, z3); + } + + // Add contributions from each corner to get the final noise value. + // The result is scaled to return values in the interval [-1,1]. + return 32.0 * (n0 + n1 + n2 + n3); +} + +#endif \ No newline at end of file diff --git a/noise/ValueNoise.h b/noise/ValueNoise.h new file mode 100644 index 0000000..dbc61b8 --- /dev/null +++ b/noise/ValueNoise.h @@ -0,0 +1,111 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_NOISE_VALUE_H +#define TOS_NOISE_VALUE_H + +#include +#include + +#include "../animation/Animation.h" + +// Initialize the grid with random values +void initialize_value_noise_2d(float* grid, int grid_size) { + for (int i = 0; i < grid_size * grid_size; ++i) { + grid[i] = (float) rand() / (float) RAND_MAX; + } +} + +void initialize_value_noise_3d(float* grid, int rows, int cols, int depth) { + for (int i = 0; i < rows * cols * depth; ++i) { + grid[i] = (float) rand() / (float) RAND_MAX; + } +} + +// @todo whenever we actually need this and we want to iterate over all x,y,z of a grid we will NOT iterate value_noise_2d. +// this would be way to slow!!! +// Instead we need to implement a simd version that performs the algorithm in value_noise_2d with a step size of 16/8/4 + +float value_noise_2d(float* grid, float x, float y, int rows, int cols) { + int grid_size = rows * cols; + + // Calculate grid cell coordinates + int x0 = (int) floor(x) % grid_size; + int y0 = (int) floor(y) % grid_size; + int x1 = (x0 + 1) % grid_size; + int y1 = (y0 + 1) % grid_size; + + // Calculate interpolation weights + float tx = x - floor(x); + float ty = y - floor(y); + + // Smooth the weights using smoothstep function + tx = smoothstep(tx); + ty = smoothstep(ty); + + // Interpolate the four corner values + float v00 = grid[y0 * rows + x0]; + float v10 = grid[y0 * rows + x1]; + float v01 = grid[y1 * rows + x0]; + float v11 = grid[y1 * rows + x1]; + + // Interpolate along x direction + float v0 = lerp(v00, v10, tx); + float v1 = lerp(v01, v11, tx); + + // Interpolate along y direction and return the final noise value + return lerp(v0, v1, ty); +} + +float value_noise_3d(float* grid, float x, float y, float z, int rows, int cols, int depth) { + int grid_size = rows * cols * depth; + + // Calculate grid cell coordinates + int x0 = (int) floor(x) % grid_size; + int y0 = (int) floor(y) % grid_size; + int z0 = (int) floor(z) % grid_size; + int x1 = (x0 + 1) % grid_size; + int y1 = (y0 + 1) % grid_size; + int z1 = (z0 + 1) % grid_size; + + // Calculate interpolation weights + float tx = x - floor(x); + float ty = y - floor(y); + float tz = z - floor(z); + + // Smooth the weights using smoothstep function + tx = smoothstep(tx); + ty = smoothstep(ty); + tz = smoothstep(tz); + + // Interpolate the eight corner values + float v000 = grid[(y0 * rows + x0) * cols + z0]; + float v100 = grid[(y0 * rows + x1) * cols + z0]; + float v010 = grid[(y1 * rows + x0) * cols + z0]; + float v110 = grid[(y1 * rows + x1) * cols + z0]; + float v001 = grid[(y0 * rows + x0) * cols + z1]; + float v101 = grid[(y0 * rows + x1) * cols + z1]; + float v011 = grid[(y1 * rows + x0) * cols + z1]; + float v111 = grid[(y1 * rows + x1) * cols + z1]; + + // Interpolate along x direction + float v00 = lerp(v000, v100, tx); + float v10 = lerp(v010, v110, tx); + float v01 = lerp(v001, v101, tx); + float v11 = lerp(v011, v111, tx); + + // Interpolate along y direction + float v0 = lerp(v00, v10, ty); + float v1 = lerp(v01, v11, ty); + + // Interpolate along z direction and return the final noise value + return lerp(v0, v1, tz); +} + +#endif \ No newline at end of file diff --git a/noise/WorleyNoise.h b/noise/WorleyNoise.h new file mode 100644 index 0000000..a75bd0b --- /dev/null +++ b/noise/WorleyNoise.h @@ -0,0 +1,117 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_NOISE_WORLEY_H +#define TOS_NOISE_WORLEY_H + +#include +#include + +#include "../stdlib/Mathtypes.h" + +#define WORLEY_FEATURE_POINTS 4 + +void generate_feature_points_2d(v2_f32* points, int feature_points, int rows, int cols) { + for (int i = 0; i < rows * cols * feature_points; ++i) { + points[i].x = (float) rand() / RAND_MAX; + points[i].y = (float) rand() / RAND_MAX; + } +} + +void generate_feature_points_3d(v3_f32* points, int feature_points, int rows, int cols, int depth) { + for (int i = 0; i < rows * cols * depth * feature_points; ++i) { + points[i].x = (float) rand() / RAND_MAX; + points[i].y = (float) rand() / RAND_MAX; + points[i].z = (float) rand() / RAND_MAX; + } +} + +float distance_squared_2d(float x1, float y1, float x2, float y2) { + return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); +} + +float distance_squared_3d(float x1, float y1, float z1, float x2, float y2, float z2) { + return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1); +} + +float worley_noise_2d(v2_f32* points, int feature_points, float x, float y, int rows, int cols) { + int grid_size = rows * cols; + + int cell_x = (int) floor(x); + int cell_y = (int) floor(y); + + float min_dist_squared = INFINITY; + + // Check the surrounding cells and the current cell + for (int i = -1; i <= 1; ++i) { + for (int j = -1; j <= 1; ++j) { + int neighbor_x = cell_x + i; + int neighbor_y = cell_y + j; + + // Ensure the neighboring cell is within bounds + if (neighbor_x < 0 || neighbor_x >= cols + || neighbor_y < 0 || neighbor_y >= rows + ) { + continue; + } + + for (int p = 0; p < feature_points; p++) { + v2_f32 fp = points[(neighbor_y * rows + neighbor_x) * cols + p]; + float dist_squared = distance_squared_2d(x, y, fp.x, fp.y); + + if (dist_squared < min_dist_squared) { + min_dist_squared = dist_squared; + } + } + } + } + + return sqrt(min_dist_squared); +} + +float worley_noise_3d(v3_f32* points, int feature_points, float x, float y, float z, int rows, int cols, int depth) { + int grid_size = rows * cols * depth; + + int cell_x = (int) floor(x); + int cell_y = (int) floor(y); + int cell_z = (int) floor(z); + + float min_dist_squared = INFINITY; + + // Check the surrounding cells and the current cell + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + for (int k = -1; k <= 1; k++) { + int neighbor_x = cell_x + i; + int neighbor_y = cell_y + j; + int neighbor_z = cell_z + k; + + // Ensure the neighboring cell is within bounds + if (neighbor_x < 0 || neighbor_x >= cols + || neighbor_y < 0 || neighbor_y >= rows + || neighbor_z < 0 || neighbor_z >= depth + ) { + continue; + } + + for (int p = 0; p < feature_points; ++p) { + v3_f32 fp = points[((neighbor_y * rows + neighbor_x) * cols + neighbor_z) * depth + p]; + float dist_squared = distance_squared_3d(x, y, z, fp.x, fp.y, fp.z); + + if (dist_squared < min_dist_squared) { + min_dist_squared = dist_squared; + } + } + } + } + } + + return sqrt(min_dist_squared); +} + +#endif \ No newline at end of file diff --git a/object/Animation.h b/object/Animation.h new file mode 100644 index 0000000..776fb73 --- /dev/null +++ b/object/Animation.h @@ -0,0 +1,48 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_ANIMATION_H +#define TOS_OBJECT_ANIMATION_H + +#include "../stdlib/Types.h" +#include "../memory/RingMemory.h" + +#if _WIN32 + #include "../platform/win32/UtilsWin32.h" +#else + #include "../platform/linux/UtilsLinux.h" +#endif + +struct Skeleton { + +}; + +struct Animation { + +}; + +void animation_from_file_txt( + RingMemory*, + const char*, + Animation* +) +{ + +} + +void animation_from_file() +{ + +} + +void animation_to_file() +{ + +} + +#endif \ No newline at end of file diff --git a/object/FaceType.h b/object/FaceType.h new file mode 100644 index 0000000..783ba1a --- /dev/null +++ b/object/FaceType.h @@ -0,0 +1,20 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_FACE_TYPE_H +#define TOS_OBJECT_FACE_TYPE_H + +enum FaceType { + FACE_TYPE_VERTICES = 1, + FACE_TYPE_TEXTURES = 2, + FACE_TYPE_NORMALS = 4, + FACE_TYPE_COLORS = 8, + FACE_TYPE_ALL = 15 +}; + +#endif \ No newline at end of file diff --git a/object/Hitbox.h b/object/Hitbox.h new file mode 100644 index 0000000..00e882c --- /dev/null +++ b/object/Hitbox.h @@ -0,0 +1,44 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_HITBOX_H +#define TOS_OBJECT_HITBOX_H + +#include "../stdlib/Types.h" +#include "../memory/RingMemory.h" + +#if _WIN32 + #include "../platform/win32/UtilsWin32.h" +#else + #include "../platform/linux/UtilsLinux.h" +#endif + +struct Hitbox { + +}; + +void hitbox_from_file_txt( + RingMemory*, + const char*, + Hitbox* +) +{ + +} + +void hitbox_from_file() +{ + +} + +void hitbox_to_file() +{ + +} + +#endif \ No newline at end of file diff --git a/object/Material.h b/object/Material.h new file mode 100644 index 0000000..565d093 --- /dev/null +++ b/object/Material.h @@ -0,0 +1,44 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_MATERIAL_H +#define TOS_OBJECT_MATERIAL_H + +#include "../stdlib/Types.h" +#include "../memory/RingMemory.h" + +#if _WIN32 + #include "../platform/win32/UtilsWin32.h" +#else + #include "../platform/linux/UtilsLinux.h" +#endif + +struct Material { + +}; + +void material_from_file_txt( + RingMemory*, + const char*, + Material* +) +{ + +} + +void material_from_file() +{ + +} + +void material_to_file() +{ + +} + +#endif \ No newline at end of file diff --git a/object/Materials.md b/object/Materials.md new file mode 100644 index 0000000..7bc819c --- /dev/null +++ b/object/Materials.md @@ -0,0 +1,26 @@ +| Name | Ambient | | | Diffuse | | | Specular | | | Shininess | +|----------------|----------|----------|----------|----------|------------|------------|------------|------------|------------|------------| +| emerald | 0.0215 | 0.1745 | 0.0215 | 0.07568 | 0.61424 | 0.07568 | 0.633 | 0.727811 | 0.633 | 0.6 | +| jade | 0.135 | 0.2225 | 0.1575 | 0.54 | 0.89 | 0.63 | 0.316228 | 0.316228 | 0.316228 | 0.1 | +| obsidian | 0.05375 | 0.05 | 0.06625 | 0.18275 | 0.17 | 0.22525 | 0.332741 | 0.328634 | 0.346435 | 0.3 | +| pearl | 0.25 | 0.20725 | 0.20725 | 1 | 0.829 | 0.829 | 0.296648 | 0.296648 | 0.296648 | 0.088 | +| ruby | 0.1745 | 0.01175 | 0.01175 | 0.61424 | 0.04136 | 0.04136 | 0.727811 | 0.626959 | 0.626959 | 0.6 | +| turquoise | 0.1 | 0.18725 | 0.1745 | 0.396 | 0.74151 | 0.69102 | 0.297254 | 0.30829 | 0.306678 | 0.1 | +| brass | 0.329412 | 0.223529 | 0.027451 | 0.780392 | 0.568627 | 0.113725 | 0.992157 | 0.941176 | 0.807843 | 0.21794872 | +| bronze | 0.2125 | 0.1275 | 0.054 | 0.714 | 0.4284 | 0.18144 | 0.393548 | 0.271906 | 0.166721 | 0.2 | +| chrome | 0.25 | 0.25 | 0.25 | 0.4 | 0.4 | 0.4 | 0.774597 | 0.774597 | 0.774597 | 0.6 | +| copper | 0.19125 | 0.0735 | 0.0225 | 0.7038 | 0.27048 | 0.0828 | 0.256777 | 0.137622 | 0.086014 | 0.1 | +| gold | 0.24725 | 0.1995 | 0.0745 | 0.75164 | 0.60648 | 0.22648 | 0.628281 | 0.555802 | 0.366065 | 0.4 | +| silver | 0.19225 | 0.19225 | 0.19225 | 0.50754 | 0.50754 | 0.50754 | 0.508273 | 0.508273 | 0.508273 | 0.4 | +| black plastic | 0 | 0 | 0 | 0.01 | 0.01 | 0.01 | 0.5 | 0.5 | 0.5 | 0.25 | +| cyan plastic | 0 | 0.1 | 0.06 | 0 | 0.50980392 | 0.50980392 | 0.50196078 | 0.50196078 | 0.50196078 | 0.25 | +| green plastic | 0 | 0 | 0 | 0.1 | 0.35 | 0.1 | 0.45 | 0.55 | 0.45 | 0.25 | +| red plastic | 0 | 0 | 0 | 0.5 | 0 | 0 | 0.7 | 0.6 | 0.6 | 0.25 | +| white plastic | 0 | 0 | 0 | 0.55 | 0.55 | 0.55 | 0.7 | 0.7 | 0.7 | 0.25 | +| yellow plastic | 0 | 0 | 0 | 0.5 | 0.5 | 0 | 0.6 | 0.6 | 0.5 | 0.25 | +| black rubber | 0.02 | 0.02 | 0.02 | 0.01 | 0.01 | 0.01 | 0.4 | 0.4 | 0.4 | 0.078125 | +| cyan rubber | 0 | 0.05 | 0.05 | 0.4 | 0.5 | 0.5 | 0.04 | 0.7 | 0.7 | 0.078125 | +| green rubber | 0 | 0.05 | 0 | 0.4 | 0.5 | 0.4 | 0.04 | 0.7 | 0.04 | 0.078125 | +| red rubber | 0.05 | 0 | 0 | 0.5 | 0.4 | 0.4 | 0.7 | 0.04 | 0.04 | 0.078125 | +| white rubber | 0.05 | 0.05 | 0.05 | 0.5 | 0.5 | 0.5 | 0.7 | 0.7 | 0.7 | 0.078125 | +| yellow rubber | 0.05 | 0.05 | 0 | 0.5 | 0.5 | 0.4 | 0.7 | 0.7 | 0.04 | 0.078125 | diff --git a/object/Mesh.h b/object/Mesh.h new file mode 100644 index 0000000..b9e5cc7 --- /dev/null +++ b/object/Mesh.h @@ -0,0 +1,82 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_MESH_H +#define TOS_OBJECT_MESH_H + +#include "Vertex.h" +#include "FaceType.h" +#include "../stdlib/Types.h" + +#include "../memory/RingMemory.h" + +// @todo how to handle different objects and groups? +// maybe make a mesh hold other meshes? +// @todo handle vertice arrays where for example no texture coordinates are defined/used +struct Mesh { + byte* data; // memory owner that subdevides into the pointers below + + uint32 object; + + uint32 group_count; + uint32* groups; + + // the following section allows us to create 2 types of data + // Interleaved: [position normal tex_coord] [color] (elements depend on vertex_type) + // Separate: [position] [normal] [tex_coord] [color] (separate array for elements) + uint32 vertex_type; + uint32 vertex_count; // can mean only position or combination of position, normal, tex, ... + uint32 normal_count; + uint32 tex_coord_count; + uint32 color_count; + float* vertices; + + // The following references only exist in some situations + // depends on the settings above + float* normals; + float* tex_coords; + float* colors; + + uint32 face_type; + uint32 face_count; + uint32 face_normal_count; + uint32 face_tex_coord_count; + uint32 face_color_count; + uint32* faces; + + // The following references only exist in some situations + // depends on the settings above + uint32* face_textures; + uint32* face_normals; + uint32* face_colors; + + // @todo this only works if you have sub meshes e.g. one for body, one for hat, one for weapon etc. + uint32 vertex_ref; + uint32 vao; + uint32 vbo; + uint32 ebo; + + uint32 material_count; + uint32* materials; + + uint32 texture; + + uint32 animation_count; + uint32* animations; + + uint32 hitbox_count; + uint32* hitboxes; + + uint32 audio_count; + uint32* audios; + + uint32 mesh_count; + Mesh* meshes; +}; + +#endif \ No newline at end of file diff --git a/object/Object.h b/object/Object.h new file mode 100644 index 0000000..96bd386 --- /dev/null +++ b/object/Object.h @@ -0,0 +1,943 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_H +#define TOS_OBJECT_H + +#include "Vertex.h" +#include "../stdlib/Types.h" +#include "../memory/RingMemory.h" +#include "../utils/EndianUtils.h" +#include "../compression/LZP.h" + +#if _WIN32 + #include "../platform/win32/UtilsWin32.h" +#else + #include "../platform/linux/UtilsLinux.h" +#endif + +#include "Mesh.h" +#include "../stdlib/simd/SIMD_I32.h" + +// @todo also handle textures etc. +void object_from_file_txt( + RingMemory* ring, + const char* path, + Mesh* mesh +) +{ + FileBody file; + file_read(path, &file, ring); + + char* pos = (char *) file.content; + + int object_index = 0; + int group_index = 0; + + mesh->vertices = (float *) mesh->data; + + mesh->vertex_count = 0; + mesh->normal_count = 0; + mesh->tex_coord_count = 0; + mesh->color_count = 0; + + mesh->face_count = 0; + mesh->face_normal_count = 0; + mesh->face_tex_coord_count = 0; + mesh->face_color_count = 0; + + uint32 temp_color_count = 0; + + while (*pos != '\0') { + while (*pos == ' ') { + ++pos; + } + + if (*pos == '\n') { + ++pos; + continue; + } + + // Parse type + // WARNING: The code below could fail if [1] is outside of range + // However that should never happen for well formed files + int state = 0; + if (*pos == 'v' && pos[1] == ' ') { + state = 1; + } else if (*pos == 'v' && pos[1] == 'n') { + state = 2; + } else if (*pos == 'v' && pos[1] == 't') { + state = 3; + } else if (*pos == 'v' && pos[1] == 'p') { + state = 4; + } else if (*pos == 'o' && pos[1] == ' ') { + state = 5; + } else if (*pos == 's' && pos[1] == ' ') { + state = 6; + } else if (*pos == 'f' && pos[1] == ' ') { + state = 7; + } else if (*pos == 'g' && pos[1] == ' ') { + state = 8; + } else if (*pos == 'l' && pos[1] == ' ') { + state = 9; + } else if (*pos == 'm' && pos[1] == 't') { + state = 10; + } else if (*pos == 'h' && pos[1] == 'i') { + state = 11; + } else if (*pos == 'a' && pos[1] == 'n') { + state = 12; + } else if (*pos == 'u' && pos[3] == 'm') { + state = 13; + } else if (*pos == 'u' && pos[3] == 'h') { + state = 14; + } else { + // not supported or comment + while (*pos != '\n' && *pos != '\0') { + ++pos; + } + } + + // move past keyword + while (*pos != ' ' && *pos != '\n' && *pos != '\0') { + ++pos; + } + + // move past whitespaces and newline + bool is_next_line = false; + while (*pos == ' ' || *pos == '\n') { + is_next_line |= *pos == '\n'; + ++pos; + } + + if (*pos == '\0' || is_next_line) { + continue; + } + + // NOTE: we always load a file in the format: POSITON + NORMAL + TEXTURE + COLOR + // EVEN if some of the data is missing. This is necessary to keep the memory kinda in line. + // The actual binary file later will have the minimized layout. + + // handle data types + switch (state) { + case 0: break; + case 1: { + // 'v' + if (mesh->vertex_count == 0) { + mesh->vertex_type |= VERTEX_TYPE_POSITION; + } + + mesh->vertices[mesh->vertex_count * 3] = strtof(pos, &pos); ++pos; + mesh->vertices[mesh->vertex_count * 3 + 1] = strtof(pos, &pos); ++pos; + mesh->vertices[mesh->vertex_count * 3 + 2] = strtof(pos, &pos); ++pos; + + // has color information + // @todo Move to own case statement // 'co' + if (*pos != '\n' && pos[1] != ' ' && pos[1] != '\n') { + if (mesh->vertex_count == 0) { + mesh->vertex_type |= VERTEX_TYPE_COLOR; + } + + mesh->vertices[mesh->vertex_count * 12 + 8] = strtof(pos, &pos); ++pos; + mesh->vertices[mesh->vertex_count * 12 + 9] = strtof(pos, &pos); ++pos; + mesh->vertices[mesh->vertex_count * 12 + 10] = strtof(pos, &pos); ++pos; + + // handle optional alpha [a] + if (*pos != '\n' && pos[1] != ' ' && pos[1] != '\n') { + mesh->vertices[mesh->vertex_count * 12 + 11] = strtof(pos, &pos); ++pos; + } else { + mesh->vertices[mesh->vertex_count * 12 + 11] = 1.0f; + } + + ++temp_color_count; + } + + ++mesh->vertex_count; + } break; + case 2: { + // 'vn' + // @bug This requires normals to be defined before textures + if (mesh->normal_count == 0) { + mesh->normals = mesh->vertices + mesh->vertex_count * 3; + } + + mesh->normals[mesh->normal_count * 3] = strtof(pos, &pos); ++pos; + mesh->normals[mesh->normal_count * 3 + 1] = strtof(pos, &pos); ++pos; + mesh->normals[mesh->normal_count * 3 + 2] = strtof(pos, &pos); ++pos; + + ++mesh->normal_count; + } break; + case 3: { + // 'vt' + if (mesh->tex_coord_count == 0) { + mesh->tex_coords = mesh->vertices + mesh->vertex_count * 3 + mesh->normal_count * 3; + } + + mesh->tex_coords[mesh->tex_coord_count * 2] = strtof(pos, &pos); ++pos; + mesh->tex_coords[mesh->tex_coord_count * 2 + 1] = strtof(pos, &pos); ++pos; + + ++mesh->tex_coord_count; + } break; + case 4: { + // 'vp' + strtof(pos, &pos); ++pos; + + // handle optional [v] + if (*pos != '\n' && pos[1] != ' ' && pos[1] != '\n') { + strtof(pos, &pos); ++pos; + + // handle optional [w] + if (*pos != '\n' && pos[1] != ' ' && pos[1] != '\n') { + strtof(pos, &pos); ++pos; + } + } + } break; + case 5: { + // 'o' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + + ++object_index; + } break; + case 6: { + // 's' + strtol(pos, &pos, 10); ++pos; + } break; + case 7: { + // 'f' + if (mesh->face_count == 0) { + mesh->faces = (uint32 *) (mesh->vertices + mesh->vertex_count * 3 + mesh->normal_count * 3 + mesh->tex_coord_count * 2 + mesh->color_count * 4); + } + + int ftype = 0; + char* tmp = pos; + while (*tmp != ' ') { + if (*tmp++ == '/') { + ++ftype; + + if (*tmp++ == '/') { + ftype = 3; + break; + } + } + } + + const int max_blocks = 3; // @todo this could actually be N. Might have to change in the future + int block = 0; + + while (*pos != '\0' && *pos != '\n') { + if (ftype == 0) { + // v1 v2 v3 ... + if (mesh->face_count == 0) { + mesh->face_type = FACE_TYPE_VERTICES; + } + + mesh->faces[(mesh->face_count * max_blocks * 1) + block] = strtol(pos, &pos, 10) - 1; ++pos; + } else if (ftype == 1) { + // v1/vt1 v2/vt2 v3/vt3 ... + if (mesh->face_count == 0) { + mesh->face_type = FACE_TYPE_VERTICES | FACE_TYPE_TEXTURES; + } + + mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2] = strtol(pos, &pos, 10) - 1; ++pos; + mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2 + 1] = strtol(pos, &pos, 10) - 1; ++pos; + } else if (ftype == 2) { + // v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 ... + if (mesh->face_count == 0) { + mesh->face_type = FACE_TYPE_VERTICES | FACE_TYPE_TEXTURES | FACE_TYPE_NORMALS; + } + + mesh->faces[(mesh->face_count * max_blocks * 3) + block * 3] = strtol(pos, &pos, 10) - 1; ++pos; + mesh->faces[(mesh->face_count * max_blocks * 3) + block * 3 + 1] = strtol(pos, &pos, 10) - 1; ++pos; + mesh->faces[(mesh->face_count * max_blocks * 3) + block * 3 + 2] = strtol(pos, &pos, 10) - 1; ++pos; + } else if (ftype == 3) { + // v1//vn1 v2//vn2 v3//vn3 ... + if (mesh->face_count == 0) { + mesh->face_type = FACE_TYPE_VERTICES | FACE_TYPE_NORMALS; + } + + mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2] = strtol(pos, &pos, 10) - 1; ++pos; + ++pos; + mesh->faces[(mesh->face_count * max_blocks * 2) + block * 2 + 1] = strtol(pos, &pos, 10) - 1; ++pos; + } + + ++block; + } + + ++mesh->face_count; + } break; + case 8: { + // 'g' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + + ++group_index; + } break; + case 9: { + //l + while (*pos != '\0' && *pos != '\n') { + strtol(pos, &pos, 10); ++pos; + } + } break; + case 10: { + // 'mtllib' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + } break; + case 11: { + // 'hitlib' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + } break; + case 12: { + // 'anilib' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + } break; + case 13: { + // 'usemtl' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + } break; + case 14: { + // 'usehit' + char text[100]; + int i = 0; + while (*pos != '\0' && *pos != ' ') { + text[i++] = *pos++; + } + text[i] = '\0'; + } break; + } + } +} + +enum ObjectLoadingRestriction { + OBJECT_LOADING_RESTRICTION_POSITION = 1, + OBJECT_LOADING_RESTRICTION_NORMAL = 2, + OBJECT_LOADING_RESTRICTION_TEXTURE = 4, + OBJECT_LOADING_RESTRICTION_COLOR = 8, + OBJECT_LOADING_RESTRICTION_FACES = 16, + OBJECT_LOADING_RESTRICTION_EVERYTHING = 31 +}; + +// @todo sometimes we don't care about some data, we should have an option which defines which data should be loaded +// this can improve performance for algorithms on this. e.g.: +// on the server side we only care about the vertex positions for collision (no normals, no color, ...) +int32 object_from_file( + RingMemory* ring, + const char* path, + Mesh* mesh, + const char* group = NULL, + int load_format = OBJECT_LOADING_RESTRICTION_EVERYTHING, + int size = 8 +) +{ + FileBody file; + file_read(path, &file, ring); + + byte* pos = file.content; + + // Read base data + mesh->vertex_type = *((int *) pos); + pos += sizeof(mesh->vertex_type); + + mesh->vertex_count = *((int *) pos); + pos += sizeof(mesh->vertex_count); + + mesh->normal_count = *((int *) pos); + pos += sizeof(mesh->normal_count); + + mesh->tex_coord_count = *((int *) pos); + pos += sizeof(mesh->tex_coord_count); + + mesh->color_count = *((int *) pos); + pos += sizeof(mesh->color_count); + + #if !_WIN32 && !__LITTLE_ENDIAN + mesh->vertex_type = endian_swap(mesh->vertex_type); + mesh->verted_count = endian_swap(mesh->verted_count); + mesh->normal_count = endian_swap(mesh->normal_count); + mesh->tex_coord_count = endian_swap(mesh->tex_coord_count); + mesh->color_count = endian_swap(mesh->color_count); + #endif + + int32 vertex_size = 0; + if (mesh->vertex_type & VERTEX_TYPE_POSITION) { + vertex_size += 3; + } + + if (mesh->vertex_type & VERTEX_TYPE_NORMAL) { + vertex_size += 3; + } + + if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) { + vertex_size += 2; + } + + if (mesh->vertex_type & VERTEX_TYPE_COLOR) { + vertex_size += 4; + } + + int offset = 0; + if (mesh->vertex_count > 0) { + memcpy(mesh->data, pos, sizeof(float) * vertex_size * mesh->vertex_count); + mesh->vertices = (float *) mesh->data; + + pos += sizeof(float) * vertex_size * mesh->vertex_count; + offset += sizeof(float) * vertex_size * mesh->vertex_count; + } + + if (mesh->normal_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(float) * 3 * mesh->normal_count); + mesh->normals = (float *) (mesh->data + offset); + + pos += sizeof(float) * 3 * mesh->normal_count; + offset += sizeof(float) * 3 * mesh->normal_count; + } + + if (mesh->tex_coord_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(float) * 3 * mesh->tex_coord_count); + mesh->tex_coords = (float *) (mesh->data + offset); + + pos += sizeof(float) * 2 * mesh->tex_coord_count; + offset += sizeof(float) * 2 * mesh->tex_coord_count; + } + + if (mesh->color_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(float) * 4 * mesh->color_count); + mesh->colors = (float *) (mesh->data + offset); + + pos += sizeof(float) * 4 * mesh->color_count; + offset += sizeof(float) * 4 * mesh->color_count; + } + + // Read face data + mesh->face_type = *((int *) pos); + pos += sizeof(mesh->face_type); + + mesh->face_count = *((int *) pos); + pos += sizeof(mesh->face_count); + + mesh->face_normal_count = *((int *) pos); + pos += sizeof(mesh->face_normal_count); + + mesh->face_tex_coord_count = *((int *) pos); + pos += sizeof(mesh->face_tex_coord_count); + + mesh->face_color_count = *((int *) pos); + pos += sizeof(mesh->face_color_count); + + #if !_WIN32 && !__LITTLE_ENDIAN + mesh->face_type = endian_swap(mesh->face_type); + mesh->face_count = endian_swap(mesh->face_count); + mesh->face_normal_count = endian_swap(mesh->face_normal_count); + mesh->face_tex_coord_count = endian_swap(mesh->face_tex_coord_count); + mesh->face_color_count = endian_swap(mesh->face_color_count); + #endif + + int face_size = 0; + if (mesh->face_type & FACE_TYPE_VERTICES) { + face_size += 3; + } + + if ((mesh->face_type & FACE_TYPE_NORMALS)) { + face_size += 3; + } + + if ((mesh->face_type & FACE_TYPE_TEXTURES)) { + face_size += 3; + } + + if ((mesh->face_type & FACE_TYPE_COLORS)) { + face_size += 3; + } + + // faces can be either in the form + // f: v/vt/vn ... + // or: + // f: v ... + // f: vn ... + // f: vt ... + if (mesh->face_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(uint32) * face_size * mesh->face_count); + mesh->faces = (uint32 *) (mesh->data + offset); + + pos += sizeof(uint32) * face_size * mesh->face_count; + offset += sizeof(uint32) * face_size * mesh->face_count; + } + + if (mesh->face_normal_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(uint32) * 3 * mesh->face_normal_count); + mesh->face_normals = (uint32 *) (mesh->data + offset); + + pos += sizeof(uint32) * 3 * mesh->face_normal_count; + offset += sizeof(uint32) * 3 * mesh->face_normal_count; + } + + if (mesh->face_tex_coord_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(uint32) * 3 * mesh->face_tex_coord_count); + mesh->face_textures = (uint32 *) (mesh->data + offset); + + pos += sizeof(uint32) * 3 * mesh->face_tex_coord_count; + offset += sizeof(uint32) * 3 * mesh->face_tex_coord_count; + } + + if (mesh->face_color_count > 0) { + memcpy(mesh->data + offset, pos, sizeof(uint32) * 3 * mesh->face_color_count); + mesh->face_colors = (uint32 *) (mesh->data + offset); + + pos += sizeof(uint32) * 3 * mesh->face_color_count; + offset += sizeof(uint32) * 3 * mesh->face_color_count; + } + + SWAP_ENDIAN_LITTLE_SIMD( + (int *) mesh->data, + (int *) mesh->data, + offset / 4, // everything is 4 bytes -> super easy to swap + steps + ); + + return offset; +} + +void object_to_file( + RingMemory* ring, + const char* path, + const Mesh* mesh, + int vertex_save_format = VERTEX_TYPE_POSITION, + int face_save_format = FACE_TYPE_VERTICES, + int size = 8 +) +{ + FileBody file; + + // Temporary file size for buffer + file.size = sizeof(mesh) + sizeof(Vertex3D) * mesh->vertex_count + sizeof(float) * 12 * mesh->vertex_count + 4096; + + file.content = ring_get_memory(ring, file.size, 64); + byte* pos = file.content; + + // vertices + memcpy(pos, &vertex_save_format, sizeof(vertex_save_format)); + pos += sizeof(vertex_save_format); + + memcpy(pos, &mesh->vertex_count, sizeof(mesh->vertex_count)); + pos += sizeof(mesh->vertex_count); + + // We are can save the mesh in a different format from the current format -> need to adjust some values + uint32 normal_count = mesh->normal_count == 0 && (mesh->vertex_type & VERTEX_TYPE_NORMAL) + ? mesh->vertex_count + : mesh->normal_count; + + memcpy(pos, &normal_count, sizeof(mesh->normal_count)); + pos += sizeof(mesh->normal_count); + + uint32 tex_coord_count = mesh->tex_coord_count == 0 && (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) + ? mesh->vertex_count + : mesh->tex_coord_count; + + memcpy(pos, &tex_coord_count, sizeof(mesh->tex_coord_count)); + pos += sizeof(mesh->tex_coord_count); + + uint32 color_count = mesh->color_count == 0 && (mesh->vertex_type & VERTEX_TYPE_COLOR) + ? mesh->vertex_count + : mesh->color_count; + + memcpy(pos, &color_count, sizeof(mesh->color_count)); + pos += sizeof(mesh->color_count); + + // verticies + if (mesh->vertex_count > 0) { + int vertex_size = 0; + if (mesh->vertex_type & VERTEX_TYPE_POSITION) { + vertex_size += 3; + } + + if (mesh->vertex_type & VERTEX_TYPE_NORMAL) { + vertex_size += 3; + } + + if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) { + vertex_size += 2; + } + + if (mesh->vertex_type & VERTEX_TYPE_COLOR) { + vertex_size += 4; + } + + int out_vertex_size = 0; + if (vertex_save_format & VERTEX_TYPE_POSITION) { + out_vertex_size += 3; + } + + if (vertex_save_format & VERTEX_TYPE_NORMAL) { + out_vertex_size += 3; + } + + if (vertex_save_format & VERTEX_TYPE_TEXTURE_COORD) { + out_vertex_size += 2; + } + + if (vertex_save_format & VERTEX_TYPE_COLOR) { + out_vertex_size += 4; + } + + if ((mesh->vertex_type == VERTEX_TYPE_ALL && vertex_save_format == VERTEX_TYPE_ALL) + || (mesh->vertex_type == VERTEX_TYPE_POSITION && vertex_save_format == VERTEX_TYPE_POSITION) + ) { + // data is the same as in the array + memcpy(pos, mesh->vertices, vertex_size * sizeof(float) * mesh->vertex_count); + pos += vertex_size * sizeof(float) * mesh->vertex_count; + } else { + float* temp = mesh->vertices; + float* end = mesh->vertices + mesh->vertex_count * vertex_size; + + int offset; + + byte* vertice_start = pos; + + // @bug index gets increased every iteration BUT different groups and objects in the source may have different data + // This comes again down to how to handle hierarchal data with multiple groups and objects + int index = 0; + + // iterate over all vertices to create new output format + while (temp < end) { + // @question why do I even need offset? couldn't I just directly manipulate temp? + offset = 0; + + // First we save everything in one large array if that is the setting + if (vertex_save_format & VERTEX_TYPE_POSITION) { + if (mesh->vertex_type & VERTEX_TYPE_POSITION) { + memcpy(pos, temp, sizeof(float) * 3); + pos += sizeof(float) * 3; + + offset += 3; + } else { + memset(pos, 0, sizeof(float) * 3); + pos += sizeof(float) * 3; + } + } + + // We want separate arrays for some data + if ((mesh->vertex_type & VERTEX_TYPE_NORMAL) && !(vertex_save_format & VERTEX_TYPE_NORMAL)) { + // go to end of vertices * shift by previous array sizes + shift by current vertex -> creates one continous array with this data + memcpy(vertice_start + + sizeof(float) * out_vertex_size * mesh->vertex_count + + index * sizeof(float) * 3, temp + offset, sizeof(float) * 3); + + offset += 3; + } else if (vertex_save_format & VERTEX_TYPE_NORMAL) { + if (mesh->vertex_type & VERTEX_TYPE_NORMAL) { + memcpy(pos, temp + offset, sizeof(float) * 3); + pos += sizeof(float) * 3; + + offset += 3; + } else { + memset(pos, 0, sizeof(float) * 3); + pos += sizeof(float) * 3; + } + } + + // We want separate arrays for some data + if ((mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) && !(vertex_save_format & VERTEX_TYPE_TEXTURE_COORD)) { + // go to end of vertices * shift by previous array sizes + shift by current vertex -> creates one continous array with this data + memcpy(vertice_start + + sizeof(float) * out_vertex_size * mesh->vertex_count + + sizeof(float) * normal_count * 3 + + index * sizeof(float) * 3, temp + offset, sizeof(float) * 3); + + offset += 2; + } else if (vertex_save_format & VERTEX_TYPE_TEXTURE_COORD) { + if (mesh->vertex_type & VERTEX_TYPE_TEXTURE_COORD) { + memcpy(pos, temp + offset, sizeof(float) * 2); + pos += sizeof(float) * 2; + + offset += 2; + } else { + memset(pos, 0, sizeof(float) * 2); + pos += sizeof(float) * 2; + } + } + + // We want separate arrays for some data + if ((mesh->vertex_type & VERTEX_TYPE_COLOR) && !(vertex_save_format & VERTEX_TYPE_COLOR)) { + // go to end of vertices * shift by previous array sizes + shift by current vertex -> creates one continous array with this data + memcpy(vertice_start + + sizeof(float) * out_vertex_size * mesh->vertex_count + + sizeof(float) * normal_count * 3 + + sizeof(float) * tex_coord_count * 2 + + index * sizeof(float) * 4, temp + offset, sizeof(float) * 4); + + offset += 4; + } else if (vertex_save_format & VERTEX_TYPE_COLOR) { + if (mesh->vertex_type & VERTEX_TYPE_COLOR) { + memcpy(pos, temp + offset, sizeof(float) * 4); + pos += sizeof(float) * 4; + + offset += 4; + } else { + memset(pos, 0, sizeof(float) * 4); + pos += sizeof(float) * 4; + } + } + + temp += offset; + ++index; + } + } + + // check if we have clean array data already -> output this array data directly + if (mesh->normals && mesh->normal_count > 0) { + memcpy(pos, mesh->normals, mesh->normal_count * sizeof(float) * 3); + pos += mesh->normal_count * sizeof(float) * 3; + } + + if (mesh->tex_coords && mesh->tex_coord_count > 0) { + memcpy(pos, mesh->tex_coords, mesh->tex_coord_count * sizeof(float) * 2); + pos += mesh->tex_coord_count * sizeof(float) * 2; + } + + if (mesh->colors && mesh->color_count > 0) { + memcpy(pos, mesh->colors, mesh->color_count * sizeof(float) * 4); + pos += mesh->color_count * sizeof(float) * 4; + } + } + + // faces/indices + memcpy(pos, &face_save_format, sizeof(face_save_format)); + pos += sizeof(face_save_format); + + memcpy(pos, &mesh->face_count, sizeof(mesh->face_count)); + pos += sizeof(mesh->face_count); + + // We are can save the mesh in a different format from the current format -> need to adjust some values + uint32 face_normal_count = mesh->face_normal_count == 0 && (mesh->face_type & FACE_TYPE_NORMALS) + ? mesh->face_count + : mesh->face_normal_count; + + memcpy(pos, &face_normal_count, sizeof(mesh->face_normal_count)); + pos += sizeof(mesh->face_normal_count); + + uint32 face_tex_coord_count = mesh->face_tex_coord_count == 0 && (mesh->face_type & FACE_TYPE_TEXTURES) + ? mesh->face_count + : mesh->face_tex_coord_count; + + memcpy(pos, &face_tex_coord_count, sizeof(mesh->face_tex_coord_count)); + pos += sizeof(mesh->face_tex_coord_count); + + uint32 face_color_count = mesh->face_color_count == 0 && (mesh->face_type & FACE_TYPE_COLORS) + ? mesh->face_count + : mesh->face_color_count; + + memcpy(pos, &face_color_count, sizeof(mesh->face_color_count)); + pos += sizeof(mesh->face_color_count); + + if (mesh->face_count > 0) { + // WARNING: Carefull, we again assume only 3 elements per face + + int face_size = 0; + if (mesh->face_type & FACE_TYPE_VERTICES) { + face_size += 3; + } + + if (mesh->face_type & FACE_TYPE_NORMALS) { + face_size += 3; + } + + if (mesh->face_type & FACE_TYPE_TEXTURES) { + face_size += 3; + } + + if (mesh->face_type & FACE_TYPE_COLORS) { + face_size += 3; + } + + int out_face_size = 0; + if (face_save_format & FACE_TYPE_VERTICES) { + out_face_size += 3; + } + + if (face_save_format & FACE_TYPE_NORMALS) { + out_face_size += 3; + } + + if (face_save_format & FACE_TYPE_TEXTURES) { + out_face_size += 3; + } + + if (face_save_format & FACE_TYPE_COLORS) { + out_face_size += 3; + } + + if ((mesh->face_type == FACE_TYPE_ALL && face_save_format == FACE_TYPE_ALL) + || (mesh->face_type == FACE_TYPE_VERTICES && face_save_format == FACE_TYPE_VERTICES) + ) { + // data is the same as in the array + memcpy(pos, mesh->faces, face_size * sizeof(uint32) * mesh->face_count); + pos += face_size * sizeof(uint32) * mesh->face_count; + } else { + uint32* temp = mesh->faces; + uint32* end = mesh->faces + mesh->face_count * face_size; + + int offset; + + byte* face_start = pos; + + // @bug index gets increased every iteration BUT different groups and objects in the source may have different data + // This comes again down to how to handle hierarchal data with multiple groups and objects + int index = 0; + + // iterate over all faces to create new output format + // one iteration represents 1 block (a block could be v/vt/vn or, v, or v//vn, ...) + while (temp < end) { + // @question why do I even need offset? couldn't I just directly manipulate temp? + offset = 0; + + // First we save everything in one large array if that is the setting + if (face_save_format & FACE_TYPE_VERTICES) { + if (mesh->face_type & FACE_TYPE_VERTICES) { + memcpy(pos, temp, sizeof(uint32)); + pos += sizeof(uint32); + + offset += 1; + } else { + memset(pos, 0, sizeof(float)); + pos += sizeof(float); + } + } + + // We want separate arrays for some data + if (mesh->face_type & FACE_TYPE_NORMALS && !(face_save_format & FACE_TYPE_NORMALS)) { + // go to end of faces * shift by previous array sizes + shift by current face -> creates one continous array with this data + memcpy(face_start + + sizeof(uint32) * out_face_size * mesh->face_count + + index * sizeof(uint32), temp + offset, sizeof(uint32)); + + offset += 1; + } else if (face_save_format & FACE_TYPE_NORMALS) { + if (mesh->face_type & FACE_TYPE_NORMALS) { + memcpy(pos, temp + offset, sizeof(uint32)); + pos += sizeof(uint32); + + offset += 1; + } else { + memset(pos, 0, sizeof(uint32)); + pos += sizeof(uint32); + } + } + + // We want separate arrays for some data + if (mesh->face_type & FACE_TYPE_TEXTURES && !(face_save_format & FACE_TYPE_TEXTURES)) { + // go to end of faces * shift by previous array sizes + shift by current face -> creates one continous array with this data + memcpy(face_start + + sizeof(uint32) * out_face_size * mesh->face_count + + sizeof(uint32) * 3 * face_normal_count + + index * sizeof(uint32), temp + offset, sizeof(uint32)); + + offset += 1; + } else if (face_save_format & FACE_TYPE_TEXTURES) { + if (mesh->face_type & FACE_TYPE_TEXTURES) { + memcpy(pos, temp + offset, sizeof(uint32)); + pos += sizeof(uint32); + + offset += 1; + } else { + memset(pos, 0, sizeof(uint32)); + pos += sizeof(uint32); + } + } + + // We want separate arrays for some data + if (mesh->face_type & VERTEX_TYPE_COLOR && !(face_save_format & VERTEX_TYPE_COLOR)) { + // go to end of faces * shift by previous array sizes + shift by current face -> creates one continous array with this data + memcpy(face_start + + sizeof(uint32) * out_face_size * mesh->face_count + + sizeof(uint32) * 3 * face_normal_count + + sizeof(uint32) * 3 * face_tex_coord_count + + index * sizeof(uint32), temp + offset, sizeof(uint32)); + + offset += 1; + } else if (face_save_format & VERTEX_TYPE_COLOR) { + if (mesh->face_type & VERTEX_TYPE_COLOR) { + memcpy(pos, temp + offset, sizeof(uint32)); + pos += sizeof(uint32); + + offset += 1; + } else { + memset(pos, 0, sizeof(uint32)); + pos += sizeof(uint32); + } + } + + temp += offset; + ++index; + } + } + + // check if we have clean array data already -> output this array data directly + if (mesh->face_normals && mesh->face_normal_count > 0) { + memcpy(pos, mesh->face_normals, mesh->face_normal_count * sizeof(uint32) * 3); + pos += mesh->face_normal_count * sizeof(uint32) * 3; + } + + if (mesh->face_textures && mesh->face_tex_coord_count > 0) { + memcpy(pos, mesh->face_textures, mesh->face_tex_coord_count * sizeof(uint32) * 3); + pos += mesh->face_tex_coord_count * sizeof(uint32) * 3; + } + + if (mesh->face_colors && mesh->face_color_count > 0) { + memcpy(pos, mesh->face_colors, mesh->face_color_count * sizeof(uint32) * 3); + pos += mesh->face_color_count * sizeof(uint32) * 3; + } + } + + file.size = pos - file.content; + + SWAP_ENDIAN_LITTLE_SIMD( + (int *) file.content, + (int *) file.content, + (pos - file.content) / 4, // everything in here is 4 bytes -> super easy to swap + steps + ); + + /* + FileBody file2; + file2.content = ring_get_memory(ring, file.size, 64); + file2.size = encode_lzp(file.content, file.size, file2.content); + + file_write(path, &file2); + */ + + file_write(path, &file); +} + +#endif \ No newline at end of file diff --git a/models/Texture.h b/object/Texture.h similarity index 86% rename from models/Texture.h rename to object/Texture.h index 8a53c67..b4ba7f3 100644 --- a/models/Texture.h +++ b/object/Texture.h @@ -34,12 +34,13 @@ #include "../stdlib/Types.h" #include "../image/Image.h" -#include "Attrib.h" +#include "../models/Attrib.h" -struct TextureFile { +struct Texture { uint64 id; - // @question Should the texture hold the texture unit? If yes remember to update prepare_texture() + // @question Should the texture hold the texture unit? + // If yes remember to update prepare_texture() byte texture_data_type; @@ -51,9 +52,7 @@ struct TextureFile { Image image; - #if OPENGL - Attrib attrib; - #endif + int32 texture_ref; }; #endif \ No newline at end of file diff --git a/object/Vertex.h b/object/Vertex.h new file mode 100644 index 0000000..645bf1a --- /dev/null +++ b/object/Vertex.h @@ -0,0 +1,43 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_OBJECT_VERTEX_H +#define TOS_OBJECT_VERTEX_H + +#include "../stdlib/Types.h" + +struct Vertex3D { + float position[3]; + float normal[3]; + uint32 tex_coord[2]; + float color[4]; +}; + +struct Vertex2D { + float position[2]; + uint32 tex_coord[2]; + float color[4]; +}; + +struct VertexRef { + uint32 position; + uint32 normal; + uint32 tex_coord; + uint32 color; + uint32 index; +}; + +enum VertexType { + VERTEX_TYPE_POSITION = 1, + VERTEX_TYPE_NORMAL = 2, + VERTEX_TYPE_TEXTURE_COORD = 4, + VERTEX_TYPE_COLOR = 8, + VERTEX_TYPE_ALL = 15 +}; + +#endif \ No newline at end of file diff --git a/particle/Particle.h b/particle/Particle.h new file mode 100644 index 0000000..4c7bd59 --- /dev/null +++ b/particle/Particle.h @@ -0,0 +1,19 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PARTICLE_H +#define TOS_PARTICLE_H + +#include "../stdlib/Mathtypes.h" + +struct Particle { + v3_f32 position; +}; + +#endif \ No newline at end of file diff --git a/pathfinding/Metric2d.h b/pathfinding/Metric2d.h new file mode 100644 index 0000000..324f8bb --- /dev/null +++ b/pathfinding/Metric2d.h @@ -0,0 +1,69 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PATHFINDING_METRIC2D_H +#define TOS_PATHFINDING_METRIC2D_H + +#include +#include + +#include "../stdlib/Mathtypes.h" +#include "../utils/MathUtils.h" +#include "../memory/RingMemory.h" + +float manhattan_2d(v2_f32 a, v2_f32 b) { + return fabs(a.x - b.x) + fabs(a.y - b.y); +} + +float euclidean_2d(v2_f32 a, v2_f32 b) { + float dx = fabs(a.x - b.x); + float dy = fabs(a.y - b.y); + + return sqrt(dx * dx + dy * dy); +} + +float octile_2d(v2_f32 a, v2_f32 b) { + float dx = fabs(a.x - b.x); + float dy = fabs(a.y - b.y); + + return dx < dy + ? (SQRT_2 - 1) * dx + dy + : (SQRT_2 - 1) * dy + dx; +} + +float chebyshev_2d(v2_f32 a, v2_f32 b) { + float dx = fabs(a.x - b.x); + float dy = fabs(a.y - b.y); + + return fmax(dx, dy); +} + +float minkowski_2d(v2_f32 a, v2_f32 b, int lambda) { + float dx = fabs(a.x - b.x); + float dy = fabs(a.y - b.y); + + return pow(pow(dx, lambda) + pow(dy, lambda), 1.0 / lambda); +} + +float canberra_2d(v2_f32 a, v2_f32 b) { + return (fabs(a.x - b.x) / (fabs(a.x) + fabs(b.x))) + + (fabs(a.y - b.y) / (fabs(a.y) + fabs(b.y))); +} + +float bray_curtis_2d(v2_f32 a, v2_f32 b) { + return (fabs(a.x - b.x) + fabs(a.y - b.y)) + / ((a.x + b.x) + (a.y + b.y)); +} + +float angular_separation_2d(v2_f32 a, v2_f32 b) { + return (a.x * b.x + a.y * b.y) + / (sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y)); +} + +#endif \ No newline at end of file diff --git a/pathfinding/Metric3d.h b/pathfinding/Metric3d.h new file mode 100644 index 0000000..c45b2f5 --- /dev/null +++ b/pathfinding/Metric3d.h @@ -0,0 +1,90 @@ +/** + * Jingga + * + * @package Utils + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_PATHFINDING_METRIC3D_H +#define TOS_PATHFINDING_METRIC3D_H + +#include +#include + +#include "../stdlib/Mathtypes.h" +#include "../memory/RingMemory.h" + +// Manhattan distance for 3D +float manhattan_3d(v3_f32 a, v3_f32 b) { + return fabs(a.x - b.x) + + fabs(a.y - b.y) + + fabs(a.z - b.z); +} + +// Euclidean distance for 3D +float euclidean_3d(v3_f32 a, v3_f32 b) { + float dx = a.x - b.x; + float dy = a.y - b.y; + float dz = a.z - b.z; + + return sqrt(dx * dx + dy * dy + dz * dz); +} + +// Chebyshev distance for 3D +float chebyshev_3d(v3_f32 a, v3_f32 b) { + float dx = fabs(a.x - b.x); + float dy = fabs(a.y - b.y); + float dz = fabs(a.z - b.z); + + return fmax(fmax(dx, dy), dz); +} + +// Minkowski distance for 3D +float minkowski_3d(v3_f32 a, v3_f32 b, int lambda) { + float dx = fabs(a.x - b.x); + float dy = fabs(a.y - b.y); + float dz = fabs(a.z - b.z); + + return pow( + pow(dx, lambda) + + pow(dy, lambda) + + pow(dz, lambda), + 1.0 / lambda + ); +} + +// Canberra distance for 3D +float canberra_3d(v3_f32 a, v3_f32 b) { + return fabs(a.x - b.x) / (fabs(a.x) + fabs(b.x)) + + fabs(a.y - b.y) / (fabs(a.y) + fabs(b.y)) + + fabs(a.z - b.z) / (fabs(a.z) + fabs(b.z)); +} + +// Bray-Curtis distance for 3D +float bray_curtis_3d(v3_f32 a, v3_f32 b) { + return (fabs(a.x - b.x) + fabs(a.y - b.y) + fabs(a.z - b.z)) + / ((a.x + b.x) + (a.y + b.y) + (a.z + b.z)); +} + +// Angular separation for 3D +float angular_separation_3d(v3_f32 a, v3_f32 b) { + return (a.x * b.x + a.y * b.y + a.z * b.z) + / (sqrt(a.x * a.x + a.y * a.y + a.z * a.z) * sqrt(b.x * b.x + b.y * b.y + b.z * b.z)); +} + +// Hamming distance for arrays +int hamming(int* a, int* b, int size) { + int dist = 0; + + for (int i = 0; i < size; ++i) { + if (a[i] != b[i]) { + ++dist; + } + } + + return dist; +} + +#endif \ No newline at end of file diff --git a/platform/linux/UtilsLinux.h b/platform/linux/UtilsLinux.h index 3080bf8..a08b819 100644 --- a/platform/linux/UtilsLinux.h +++ b/platform/linux/UtilsLinux.h @@ -52,6 +52,29 @@ int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...) { return result; } +inline void relative_to_absolute(const char* rel, char* path) +{ + const char* temp = rel; + if (temp[0] == '.' && temp[1] == '/') { + temp += 2; + } + + char self_path[MAX_PATH]; + ssize_t count = readlink("/proc/self/exe", self_path, MAX_PATH - 1); + if (count == -1) { + return; + } + self_path[count] = '\0'; + + char* last = strrchr(self_path, '/'); + if (last != NULL) { + *(last + 1) = '\0'; + } + + snprintf(path, MAX_PATH, "%s%s", self_path, temp); +} + +// @todo implement relative path support, similar to UtilsWin32 inline uint64 file_size(const char* filename) { struct stat st; @@ -209,28 +232,6 @@ void self_path(char* path) { } } -inline void relative_to_absolute(const char* rel, char* path) -{ - const char* temp = rel; - if (temp[0] == '.' && temp[1] == '/') { - temp += 2; - } - - char self_path[MAX_PATH]; - ssize_t count = readlink("/proc/self/exe", self_path, MAX_PATH - 1); - if (count == -1) { - return; - } - self_path[count] = '\0'; - - char* last = strrchr(self_path, '/'); - if (last != NULL) { - *(last + 1) = '\0'; - } - - snprintf(path, MAX_PATH, "%s%s", self_path, temp); -} - inline void strncpy_s(char *dest, size_t destsz, const char *src, size_t count) { size_t i; diff --git a/platform/win32/UtilsWin32.h b/platform/win32/UtilsWin32.h index 7dbd801..5eed15f 100644 --- a/platform/win32/UtilsWin32.h +++ b/platform/win32/UtilsWin32.h @@ -12,6 +12,8 @@ #include #include #include +#include + #ifdef _MSC_VER #include #endif @@ -19,20 +21,57 @@ #include "../../stdlib/Types.h" #include "../../utils/Utils.h" #include "../../utils/TestUtils.h" +#include "../../memory/RingMemory.h" #define strtok_r strtok_s +inline void relative_to_absolute(const char* rel, char* path) +{ + char self_path[MAX_PATH]; + if (GetModuleFileNameA(NULL, self_path, MAX_PATH) == 0) { + return; + } + + const char* temp = rel; + if (temp[0] == '.' && temp[1] == '/') { + temp += 2; + } + + char* last = strrchr(self_path, '\\'); + if (last != NULL) { + *(last + 1) = '\0'; + } + + snprintf(path, MAX_PATH, "%s%s", self_path, temp); +} + inline uint64 -file_size(const char* filename) +file_size(const char* path) { // @performance Profile against fseek strategy - HANDLE fp = CreateFileA((LPCSTR) filename, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { return 0; @@ -48,16 +87,47 @@ file_size(const char* filename) return size.QuadPart; } -inline void -file_read(const char* filename, FileBody* file, RingMemory* ring = NULL) +inline +uint64 time_ms() { - HANDLE fp = CreateFileA((LPCSTR) filename, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + LARGE_INTEGER frequency; + LARGE_INTEGER counter; + + if (!QueryPerformanceFrequency(&frequency)) { + return 0; + } + + QueryPerformanceCounter(&counter); + + return (counter.QuadPart * 1000) / frequency.QuadPart; +} + +inline void +file_read(const char* path, FileBody* file, RingMemory* ring = NULL) +{ + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { file->size = 0; @@ -92,15 +162,31 @@ file_read(const char* filename, FileBody* file, RingMemory* ring = NULL) } inline uint64 -file_read_struct(const char* filename, void* file, uint32 size) +file_read_struct(const char* path, void* file, uint32 size) { - HANDLE fp = CreateFileA((LPCSTR) filename, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { return 0; @@ -127,15 +213,31 @@ file_read_struct(const char* filename, void* file, uint32 size) } inline bool -file_write(const char* filename, const FileBody* file) +file_write(const char* path, const FileBody* file) { - HANDLE fp = CreateFileA((LPCSTR) filename, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { return false; @@ -155,18 +257,30 @@ file_write(const char* filename, const FileBody* file) } inline bool -file_write_struct(const char* filename, const void* file, uint32 size) +file_write_struct(const char* path, const void* file, uint32 size) { - HANDLE fp = CreateFileA((LPCSTR) filename, - GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); - if (fp == INVALID_HANDLE_VALUE) { - return false; + fp = CreateFileA((LPCSTR) full_path, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); } DWORD written; @@ -188,15 +302,31 @@ file_copy(const char* src, const char* dst) } inline -HANDLE get_append_handle(const char* filename) +HANDLE get_append_handle(const char* path) { - HANDLE fp = CreateFileA((LPCSTR) filename, - FILE_APPEND_DATA, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + FILE_APPEND_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + FILE_APPEND_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { return NULL; @@ -206,15 +336,31 @@ HANDLE get_append_handle(const char* filename) } inline bool -file_append(const char* filename, const char* file) +file_append(const char* path, const char* file) { - HANDLE fp = CreateFileA((LPCSTR) filename, - FILE_APPEND_DATA, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + FILE_APPEND_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + FILE_APPEND_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { return false; @@ -242,6 +388,7 @@ file_append(HANDLE fp, const char* file) DWORD written; DWORD length = (DWORD) strlen(file); // @question WHY is WriteFile not supporting larger data? ASSERT_SIMPLE(length < MAX_INT32); + if (!WriteFile(fp, file, length, &written, NULL)) { CloseHandle(fp); return false; @@ -252,15 +399,48 @@ file_append(HANDLE fp, const char* file) } inline bool -file_append(const char* filename, const FileBody* file) +file_append(HANDLE fp, const char* file, size_t length) { - HANDLE fp = CreateFileA((LPCSTR) filename, - FILE_APPEND_DATA, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + if (fp == INVALID_HANDLE_VALUE) { + return false; + } + + DWORD written; + if (!WriteFile(fp, file, (uint32) length, &written, NULL)) { + CloseHandle(fp); + return false; + } + + CloseHandle(fp); + return true; +} + +inline bool +file_append(const char* path, const FileBody* file) +{ + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = CreateFileA((LPCSTR) full_path, + FILE_APPEND_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } else { + fp = CreateFileA((LPCSTR) path, + FILE_APPEND_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + } if (fp == INVALID_HANDLE_VALUE) { return false; @@ -279,12 +459,21 @@ file_append(const char* filename, const FileBody* file) } inline -uint64 last_modified(const char* filename) +uint64 last_modified(const char* path) { - FILETIME modified = {}; - WIN32_FIND_DATA find_data; - HANDLE fp = FindFirstFileA(filename, (LPWIN32_FIND_DATAA) &find_data); + + HANDLE fp; + if (*path == '.') { + char full_path[MAX_PATH]; + relative_to_absolute(path, full_path); + + fp = FindFirstFileA(full_path, (LPWIN32_FIND_DATAA) &find_data); + } else { + fp = FindFirstFileA(path, (LPWIN32_FIND_DATAA) &find_data); + } + + FILETIME modified = {}; if(fp != INVALID_HANDLE_VALUE) { modified = find_data.ftLastWriteTime; FindClose(fp); @@ -299,98 +488,45 @@ uint64 last_modified(const char* filename) inline void self_path(char* path) { - //HMODULE dll = GetModuleHandle(NULL); GetModuleFileNameA(NULL, (LPSTR) path, MAX_PATH); } -inline void relative_to_absolute(const char* rel, char* path) -{ - char self_path[MAX_PATH]; - if (GetModuleFileNameA(NULL, self_path, MAX_PATH) == 0) { - return; - } - - const char* temp = rel; - if (temp[0] == '.' && temp[1] == '/') { - temp += 2; - } - - char* last = strrchr(self_path, '\\'); - if (last != NULL) { - *(last + 1) = '\0'; - } - - snprintf(path, MAX_PATH, "%s%s", self_path, temp); -} - -void log_to_file(LogPool* logs, HANDLE fp) +void log_to_file(RingMemory* logs, HANDLE fp) { // we don't log an empty log pool if (logs->pos == 0) { return; } - char *offset = logs->memory; - for (uint32 i = 0; i < logs->pos * MAX_LOG_LENGTH + MAX_LOG_LENGTH; ++i) { - if (*offset == '\0') { - *offset = '\n'; - - // @performance would it make sense to jump to the next log message - // we know that after \0 until the end of this log message everything is 0 - } - - ++offset; - } - - logs->memory[logs->count * MAX_LOG_LENGTH - 1] = '\0'; - file_append(fp, logs->memory); + file_append(fp, (char *) logs->memory, logs->size); + memset(logs->memory, 0, logs->size); // reset log position to start of memory pool logs->pos = 0; + logs->start = 0; } // snprintf(logs->memory + logs->pos * MAX_LOG_LENGTH, MAX_LOG_LENGTH, "My text %s", str1); -// log(log, NULL); -void log(LogPool* logs, HANDLE fp = NULL) +void log(RingMemory* logs, const char* str, HANDLE fp = NULL) { - // Zero memory after \0 until end of THIS log message - // Older log messages that are coming after are retained - // Older log messages can come after this log message due to the ring memory - char *offset = logs->memory + logs->pos * MAX_LOG_LENGTH; - bool ended = false; - for (uint32 i = 0; i < MAX_LOG_LENGTH; ++i) { - if (ended) { - *offset = 0; - ++offset; + size_t length = strlen(str); + ASSERT_SIMPLE(length < MAX_LOG_LENGTH); - continue; - } + char* temp = (char *) ring_get_memory(logs, length + 1); + strcpy(temp, str); + temp[length] = '\0'; - if (*offset == '\0') { - ended = true; - } - - ++offset; - } - - ++logs->pos; - // write log pool to file - if (logs->pos >= logs->count) { - if (fp != NULL) { - log_to_file(logs, fp); - } - - // reset log position to start of memory pool - logs->pos = 0; + if (fp != NULL && logs->size - logs->pos < MAX_LOG_LENGTH) { + log_to_file(logs, fp); } } #if (LOG_LEVEL == 0) // Don't perform any logging at log level 0 - #define LOG(logs, fp) - #define LOG_TO_FILE(logs, fp) + #define LOG(logs, str, fp) ((void)0) + #define LOG_TO_FILE(logs, fp) ((void)0) #else - #define LOG(logs, fp) log(logs, fp); + #define LOG(logs, str, fp) log(logs, str, fp); #define LOG_TO_FILE(logs, fp) log_to_file(logs, fp); #endif diff --git a/platform/win32/UtilsWindows.h b/platform/win32/UtilsWindows.h index 39fb7ff..5d9babf 100644 --- a/platform/win32/UtilsWindows.h +++ b/platform/win32/UtilsWindows.h @@ -10,33 +10,27 @@ #define TOS_UTILS_WINDOWS_H #include +#include "Window.h" #include "../../stdlib/Types.h" - -struct Window { - bool is_fullscreen; - int32 width; - int32 height; - char name[32]; - - int32 x; - int32 y; - - HWND hwnd; -}; +#include "../../utils/TestUtils.h" void window_create(Window* window, void* proc) { + ASSERT_SIMPLE(proc); + WNDPROC wndproc = (WNDPROC) proc; - WNDCLASSEX wc = {}; + WNDCLASSEXA wc = {}; HINSTANCE hinstance = GetModuleHandle(0); - wc.cbSize = sizeof(WNDCLASSEX); + wc.cbSize = sizeof(WNDCLASSEXA); wc.style = CS_OWNDC; wc.lpfnWndProc = wndproc; wc.hInstance = hinstance; - wc.lpszClassName = (LPCWSTR) window->name; + wc.lpszClassName = (LPCSTR) window->name; - RegisterClassEx(&wc); + if (!RegisterClassExA(&wc)) { + return; + } if (window->is_fullscreen) { window->width = GetSystemMetrics(SM_CXSCREEN); @@ -57,7 +51,7 @@ void window_create(Window* window, void* proc) window->y = 0; } - window->hwnd = CreateWindowEx((DWORD) NULL, + window->hwnd = CreateWindowExA((DWORD) NULL, wc.lpszClassName, NULL, WS_OVERLAPPEDWINDOW, window->x, window->y, @@ -66,6 +60,10 @@ void window_create(Window* window, void* proc) NULL, NULL, hinstance, window ); + window->hdc = GetDC(window->hwnd); + + ASSERT_SIMPLE(window->hwnd); + //SetWindowLongA(window->hwnd, GWL_STYLE, 0); } diff --git a/platform/win32/Window.h b/platform/win32/Window.h new file mode 100644 index 0000000..6b88da1 --- /dev/null +++ b/platform/win32/Window.h @@ -0,0 +1,28 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_UTILS_WINDOW_H +#define TOS_UTILS_WINDOW_H + +#include +#include "../../stdlib/Types.h" + +struct Window { + bool is_fullscreen; + int32 width; + int32 height; + char name[32]; + + int32 x; + int32 y; + + HWND hwnd; + HDC hdc; +}; + +#endif \ No newline at end of file diff --git a/platform/win32/audio/DirectSound.h b/platform/win32/audio/DirectSound.h index 5420888..2a0e639 100644 --- a/platform/win32/audio/DirectSound.h +++ b/platform/win32/audio/DirectSound.h @@ -77,9 +77,6 @@ void audio_load(HWND hwnd, AudioSetting* setting, DirectSoundSetting* api_settin return; } - setting->buffer_size = setting->sample_rate * setting->sample_size; - setting->buffer = (int16 *) calloc(setting->sample_rate, setting->sample_size); - // Create secondary buffer DSBUFFERDESC bufferDesc2; ZeroMemory(&bufferDesc2, sizeof(DSBUFFERDESC)); diff --git a/stdlib/HashMap.h b/stdlib/HashMap.h new file mode 100644 index 0000000..de32217 --- /dev/null +++ b/stdlib/HashMap.h @@ -0,0 +1,223 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_STDLIB_HASHMAP_H +#define TOS_STDLIB_HASHMAP_H + +#include "../hash/GeneralHash.h" +#include "../memory/RingMemory.h" +#include "../memory/BufferMemory.h" +#include "../memory/ChunkMemory.h" +#include "Types.h" + +#define MAX_KEY_LENGTH 32 + +struct HashEntryInt32 { + int64 element_id; + char key[MAX_KEY_LENGTH]; + HashEntryInt32* next; + int value; +}; + +struct HashEntryInt64 { + int64 element_id; + char key[MAX_KEY_LENGTH]; + HashEntryInt64* next; + int64 value; +}; + +struct HashEntryFloat { + int64 element_id; + char key[MAX_KEY_LENGTH]; + HashEntryFloat* next; + float value; +}; + +struct HashEntryStr { + int64 element_id; + char key[MAX_KEY_LENGTH]; + HashEntryStr* next; + char value[MAX_KEY_LENGTH]; +}; + +struct HashEntry { + int64 element_id; + char key[MAX_KEY_LENGTH]; + HashEntry* next; + byte* value; +}; + +struct HashMap { + void** table; + ChunkMemory buf; +}; + +// WARNING: element_size = element size + remaining HashEntry data size +void hashmap_create(HashMap* hm, int count, int element_size, RingMemory* ring) +{ + hm->table = (void **) ring_get_memory(ring, count * sizeof(void *)); + + hm->buf.memory = ring_get_memory(ring, count * element_size); + hm->buf.free = (uint64 *) ring_get_memory(ring, CEIL_DIV(count, 64) * sizeof(hm->buf.free)); + hm->buf.count = count; + hm->buf.chunk_size = element_size; + hm->buf.last_pos = -1; + hm->buf.alignment = 1; +} + +void hashmap_create(HashMap* hm, int count, int element_size, BufferMemory* buf) +{ + hm->table = (void **) buffer_get_memory(buf, count * sizeof(void *)); + + hm->buf.memory = buffer_get_memory(buf, count * element_size); + hm->buf.free = (uint64 *) buffer_get_memory(buf, CEIL_DIV(count, 64) * sizeof(hm->buf.free)); + hm->buf.count = count; + hm->buf.chunk_size = element_size; + hm->buf.last_pos = -1; + hm->buf.alignment = 1; +} + +inline +int64 hashmap_get_buffer_size(int count, int element_size) +{ + return sizeof(void *) * count // table + + count * element_size // elements + + sizeof(uint64) * CEIL_DIV(count, 64); // free +} + +void hashmap_create(HashMap* hm, int count, int element_size, byte* buf) +{ + hm->table = (void **) buf; + + hm->buf.memory = buf + sizeof(void *) * count; + hm->buf.free = (uint64 *) (hm->buf.memory + count * element_size); + hm->buf.count = count; + hm->buf.chunk_size = element_size; + hm->buf.last_pos = -1; + hm->buf.alignment = 1; +} + +void hashmap_insert(HashMap* hm, const char* key, int32 value) { + uint64 index = hash_djb2(key) % hm->buf.count; + + int64 element = chunk_reserve(&hm->buf, 1); + HashEntryInt32* entry = (HashEntryInt32 *) 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 = (HashEntryInt32 *) hm->table[index]; + hm->table[index] = entry; +} + +void hashmap_insert(HashMap* hm, const char* key, int64 value) { + uint64 index = hash_djb2(key) % hm->buf.count; + + int64 element = chunk_reserve(&hm->buf, 1); + HashEntryInt64* entry = (HashEntryInt64 *) 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 = (HashEntryInt64 *) 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; + + int64 element = chunk_reserve(&hm->buf, 1); + HashEntryFloat* entry = (HashEntryFloat *) 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 = (HashEntryFloat *) hm->table[index]; + hm->table[index] = entry; +} + +void hashmap_insert(HashMap* hm, const char* key, const char* value) { + uint64 index = hash_djb2(key) % hm->buf.count; + + int64 element = chunk_reserve(&hm->buf, 1); + HashEntryStr* entry = (HashEntryStr *) 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'; + + strncpy(entry->value, value, MAX_KEY_LENGTH); + entry->value[MAX_KEY_LENGTH - 1] = '\0'; + + entry->next = (HashEntryStr *) hm->table[index]; + hm->table[index] = entry; +} + +void hashmap_insert(HashMap* hm, const char* key, byte* value) { + uint64 index = hash_djb2(key) % hm->buf.count; + + int64 element = chunk_reserve(&hm->buf, 1); + HashEntry* entry = (HashEntry *) chunk_get_element(&hm->buf, element, true); + entry->element_id = element; + + entry->value = (byte *) entry + sizeof(HashEntry); + + strncpy(entry->key, key, MAX_KEY_LENGTH); + entry->key[MAX_KEY_LENGTH - 1] = '\0'; + + memcpy(entry->value, value, hm->buf.chunk_size - sizeof(HashEntry)); + + entry->next = (HashEntry *) hm->table[index]; + hm->table[index] = entry; +} + +void* hashmap_get_entry(HashMap* hm, const char* key) { + uint64 index = hash_djb2(key) % hm->buf.count; + HashEntry* entry = (HashEntry *) hm->table[index]; + + while (entry != NULL) { + if (strncmp(entry->key, key, MAX_KEY_LENGTH) == 0) { + return entry; + } + + entry = (HashEntry *) entry->next; + } + + return NULL; +} + +void hashmap_delete_entry(HashMap* hm, const char* key) { + uint64 index = hash_djb2(key); + HashEntry* entry = (HashEntry *) hm->table[index]; + HashEntry* prev = NULL; + + while (entry != NULL) { + if (strncmp(entry->key, key, MAX_KEY_LENGTH) == 0) { + if (prev == NULL) { + hm->table[index] = entry->next; + } else { + prev->next = entry->next; + } + + chunk_free_element(&hm->buf, entry->element_id); + + return; + } + + prev = entry; + entry = entry->next; + } +} + +#endif \ No newline at end of file diff --git a/stdlib/Intrinsics.h b/stdlib/Intrinsics.h index 94b8ccc..ee29ced 100644 --- a/stdlib/Intrinsics.h +++ b/stdlib/Intrinsics.h @@ -19,6 +19,7 @@ #include "Types.h" +/* inline f32 sqrt(f32 a) { return _mm_cvtss_f32(_mm_sqrt_ss(_mm_set_ss(a))); } inline f64 sqrt(f64 a) { @@ -26,6 +27,7 @@ inline f64 sqrt(f64 a) return _mm_cvtsd_f64(_mm_sqrt_sd(temp, temp)); } +*/ inline f32 rsqrt(f32 a) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(a))); } inline f64 rsqrt(f64 a) diff --git a/stdlib/Types.h b/stdlib/Types.h index 76e6466..9c6fc37 100644 --- a/stdlib/Types.h +++ b/stdlib/Types.h @@ -26,6 +26,10 @@ typedef float f32; typedef double f64; typedef unsigned char byte; +typedef char sbyte; + +typedef uintptr_t umm; +typedef intptr_t smm; #define KILOBYTE 1024 #define MEGABYTE 1048576 diff --git a/stdlib/simd/SIMD_I32.h b/stdlib/simd/SIMD_I32.h index 0c3d266..7d483f5 100644 --- a/stdlib/simd/SIMD_I32.h +++ b/stdlib/simd/SIMD_I32.h @@ -13,6 +13,7 @@ #include #include "../Types.h" +#include "../../utils/BitUtils.h" #include "SIMD_F32.h" // @todo a lot of sse functions require high level (e.g. sse4.1) this needs to be changed to be more general @@ -1557,12 +1558,78 @@ void simd_add(const int32* a, const f32* b, int32* result, int size, int steps) } // WARNING: only works with SSE4.2 -// WARNING: incl. \0 both strings must be <= 16 -bool simd_str_compare(const char* str1, const char* str2) { - __m128i s1 = _mm_loadu_si128((const __m128i*) str1); - __m128i s2 = _mm_loadu_si128((const __m128i*) str2); +// WARNING: incl. \0 both strings must be <= 16 length +bool str_compare_avx512(const char* str1, const char* str2) { + __m128i s1 = _mm_loadu_si128((const __m128i *) str1); + __m128i s2 = _mm_loadu_si128((const __m128i *) str2); return _mm_cmpistrc(s1, s2, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_EACH) == 0; } +void +endian_swap(const int* val, int* result, int size, int steps) +{ + int i = 0; + + if (steps == 16) { + const __m512i mask_512 = _mm512_setr_epi8( + 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, + 19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28, + 35, 34, 33, 32, 39, 38, 37, 36, 43, 42, 41, 40, 47, 46, 45, 44, + 51, 50, 49, 48, 55, 54, 53, 60, 59, 58, 57, 56, 64, 63, 62, 61 + ); + + for (i = 0; i <= size - steps; i += steps) { + __m512i vec = _mm512_loadu_si512((const __m512i *) (val + i)); + vec = _mm512_shuffle_epi8(vec, mask_512); + + _mm512_storeu_si512((__m512i *) (result + i), vec); + } + } else if (steps == 8) { + const __m256i mask_256 = _mm256_setr_epi8( + 3, 2, 1, 0, 7, 6, 5, 4, + 11, 10, 9, 8, 15, 14, 13, 12, + 19, 18, 17, 16, 23, 22, 21, 20, + 27, 26, 25, 24, 31, 30, 29, 28 + ); + + for (i = 0; i <= size - steps; i += steps) { + __m256i vec = _mm256_loadu_si256((const __m256i *) (val + i)); + vec = _mm256_shuffle_epi8(vec, mask_256); + + _mm256_storeu_si256((__m256i *) (result + i), vec); + } + } else if (steps == 4) { + const __m128i mask_128 = _mm_setr_epi8( + 3, 2, 1, 0, + 7, 6, 5, 4, + 11, 10, 9, 8, + 15, 14, 13, 12 + ); + + for (i = 0; i <= size - steps; i += steps) { + __m128i vec = _mm_loadu_si128((const __m128i *) (val + i)); + vec = _mm_shuffle_epi8(vec, mask_128); + + _mm_storeu_si128((__m128i *) (result + i), vec); + } + } + + for (; i < size; ++i) { + uint32 v = ((uint32 *) val)[i]; + ((int32 *) result)[i] = ((v << 24) + | ((v & 0xFF00) << 8) + | ((v >> 8) & 0xFF00) + | (v >> 24)); + } +} + +#if _WIN32 || __LITTLE_ENDIAN + #define SWAP_ENDIAN_LITTLE_SIMD(val, result, size, steps) ((void)0) + #define SWAP_ENDIAN_BIG_SIMD(val, result, size, steps) endian_swap((val), (result), (size), (steps)) +#else + #define SWAP_ENDIAN_LITTLE_SIMD(val, result, size, steps) endian_swap((val), (result), (size), (steps)) + #define SWAP_ENDIAN_BIG_SIMD(val, result, size, steps) ((void)0) +#endif + #endif diff --git a/ui/Dropdown.h b/ui/UIDropdown.h similarity index 100% rename from ui/Dropdown.h rename to ui/UIDropdown.h diff --git a/ui/Image.h b/ui/UIImage.h similarity index 100% rename from ui/Image.h rename to ui/UIImage.h diff --git a/ui/Link.h b/ui/UILink.h similarity index 100% rename from ui/Link.h rename to ui/UILink.h diff --git a/ui/Panel.h b/ui/UIPanel.h similarity index 100% rename from ui/Panel.h rename to ui/UIPanel.h diff --git a/ui/Select.h b/ui/UISelect.h similarity index 100% rename from ui/Select.h rename to ui/UISelect.h diff --git a/ui/Table.h b/ui/UITable.h similarity index 100% rename from ui/Table.h rename to ui/UITable.h diff --git a/ui/Text.h b/ui/UIText.h similarity index 100% rename from ui/Text.h rename to ui/UIText.h diff --git a/ui/Textarea.h b/ui/UITextarea.h similarity index 100% rename from ui/Textarea.h rename to ui/UITextarea.h diff --git a/ui/Textfield.h b/ui/UITextfield.h similarity index 100% rename from ui/Textfield.h rename to ui/UITextfield.h diff --git a/utils/BitUtils.h b/utils/BitUtils.h index e621fec..4d6307e 100644 --- a/utils/BitUtils.h +++ b/utils/BitUtils.h @@ -9,6 +9,7 @@ #ifndef TOS_UTILS_BIT_H #define TOS_UTILS_BIT_H +#include #include "../stdlib/Types.h" inline @@ -30,16 +31,44 @@ uint64 bytes_merge( ) { uint64 result = 0; - result |= ((uint32) b0 << 56); - result |= ((uint32) b1 << 48); - result |= ((uint32) b2 << 40); - result |= ((uint32) b3 << 32); - result |= ((uint32) b4 << 24); - result |= ((uint32) b5 << 16); - result |= ((uint32) b6 << 8); - result |= (uint32) b3; + result |= ((uint64) b0 << 56); + result |= ((uint64) b1 << 48); + result |= ((uint64) b2 << 40); + result |= ((uint64) b3 << 32); + result |= ((uint64) b4 << 24); + result |= ((uint64) b5 << 16); + result |= ((uint64) b6 << 8); + result |= (uint64) b7; return result; } +static +inline int find_first_set_bit(int value) { + if (value == 0) { + return 0; + } + + #if __GNUC__ || __clang__ + return __builtin_ffs(value); + #elif _MSC_VER + unsigned long index; // For _BitScanForward, an unsigned long is expected + if (_BitScanForward(&index, value)) { + return (int)index + 1; // Convert to 1-based index + } else { + return 0; // No set bit found + } + #else + int index = 1; // Start at 1 for 1-based index + while (value) { + if (value & 1) { + return index; + } + value >>= 1; // Shift right to check the next bit + index++; + } + return 0; // No set bit found + #endif +} + #endif \ No newline at end of file diff --git a/utils/Compiler.h b/utils/Compiler.h deleted file mode 100644 index 4bac150..0000000 --- a/utils/Compiler.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Jingga - * - * @copyright Jingga - * @license OMS License 2.0 - * @version 1.0.0 - * @link https://jingga.app - */ -#ifndef TOS_UTILS_COMPILER_H -#define TOS_UTILS_COMPILER_H - -#include -#include - -#ifdef _MSC_VER - #include - - inline - void* aligned_alloc(size_t alignment, size_t size) { - return _aligned_malloc(size, alignment); - } - - inline - void aligned_free(void* ptr) { - _aligned_free(ptr); - } -#else - inline - void aligned_free(void* ptr) { - free(ptr); - } -#endif - -#endif diff --git a/utils/FastPipes.h b/utils/FastPipes.h index cbdfaa8..d7057fc 100644 --- a/utils/FastPipes.h +++ b/utils/FastPipes.h @@ -23,14 +23,14 @@ wchar_t pipe_name[32]; wsprintfW(pipe_name, L"\\\\.\\pipe\\fastpipe%x", GetCurrentProcessId()); - HANDLE fast_pip = CreateFileW(pipe_name, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + HANDLE fast_pip = CreateFileW(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); if(fast_pip != INVALID_HANDLE_VALUE) { SetStdHandle(STD_OUTPUT_HANDLE, fast_pip); SetStdHandle(STD_INPUT_HANDLE, fast_pip); - int std_out = _open_osfhandle((intptr_t) fast_pip, O_WRONLY|O_TEXT); - int std_in = _open_osfhandle((intptr_t) fast_pip, O_RDONLY|O_TEXT); + int std_out = _open_osfhandle((intptr_t) fast_pip, O_WRONLY | O_TEXT); + int std_in = _open_osfhandle((intptr_t) fast_pip, O_RDONLY | O_TEXT); _dup2(std_out, _fileno(stdout)); _dup2(std_in, _fileno(stdin)); diff --git a/utils/MathUtils.h b/utils/MathUtils.h index 98706e2..eecc99f 100644 --- a/utils/MathUtils.h +++ b/utils/MathUtils.h @@ -11,11 +11,12 @@ #define TOS_UTILS_MATH_UTILS_H #include "../stdlib/Intrinsics.h" +#include #define OMS_PI 3.14159265358979323846f -#define OMS_PI_OVER_TWO OMS_PI / 2.0f -#define OMS_PI_OVER_FOUR OMS_PI / 4.0f -#define OMS_TWO_PI 2 * OMS_PI +#define OMS_PI_OVER_TWO (OMS_PI / 2.0f) +#define OMS_PI_OVER_FOUR (OMS_PI / 4.0f) +#define OMS_TWO_PI (2 * OMS_PI) #define OMS_MAX(a, b) ((a) > (b) ? (a) : (b)) #define OMS_MIN(a, b) ((a) > (b) ? (b) : (a)) @@ -24,6 +25,9 @@ #define OMS_DEG2RAD(angle) ((angle) * OMS_PI / 180.0f) #define OMS_RAD2DEG(angle) ((angle) * 180.0f / OMS_PI) #define ROUND_TO_NEAREST(a, b) (((a) + ((b) - 1)) & ~((b) - 1)) +#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b)) + +#define SQRT_2 1.4142135623730950488016887242097f // @question Consider to implement table based sine wave + approximation if necessary // [-PI/2, PI/2] @@ -42,7 +46,7 @@ float sinf_approx(float x) inline float cosf_approx(float x) { - return sinf_approx(x + OMS_PI_OVER_TWO); + return sinf_approx(x + OMS_RAD2DEG(OMS_PI_OVER_TWO)); } inline @@ -103,7 +107,7 @@ float asinf_approx(float x) result -= 0.2121144f; result *= x; result += 1.5707288f; - result *= sqrt(1.0f - x); + result *= sqrtf(1.0f - x); result -= 2 * negate * result; return negate * OMS_PI + result; diff --git a/utils/StringUtils.h b/utils/StringUtils.h index 383c6f8..9ecbfec 100644 --- a/utils/StringUtils.h +++ b/utils/StringUtils.h @@ -139,7 +139,7 @@ char* format_number(size_t number, char* buffer, const char thousands = ',') return buffer; } -char* format_number(int number, char* buffer, const char thousands = ',') +char* format_number(int number, char* buffer, const char thousands = ',') { int length = snprintf(buffer, 32, "%i", number); format_number_render(length, buffer, thousands); @@ -147,7 +147,21 @@ char* format_number(int number, char* buffer, const char thousands = ',') return buffer; } -void create_const_name(const unsigned char* name, unsigned char* modified_name) +char toupper_ascii(char c) +{ + return c >= 'a' && c <= 'z' + ? c & 0x5f + : c; +} + +char tolower_ascii(char c) +{ + return c >= 'A' && c <= 'Z' + ? c | 0x20 + : c; +} + +void create_const_name(const unsigned char* name, char* modified_name) { // Print block if (name == NULL) { @@ -156,7 +170,7 @@ void create_const_name(const unsigned char* name, unsigned char* modified_name) size_t i; const size_t length = strlen((const char* ) name); for (i = 0; i < length; ++i) { - modified_name[i] = name[i] == ' ' ? '_' : (unsigned char) toupper(name[i]); + modified_name[i] = name[i] == ' ' ? '_' : toupper_ascii(name[i]); } modified_name[i] = '\0'; @@ -202,4 +216,36 @@ bool str_ends_with(const char* str, const char* suffix) { return strncmp(str + str_len - suffix_len, suffix, suffix_len) == 0; } +// WARNING: result needs to have the correct length +void str_replace(const char* str, const char* search, const char* replace, char* result) { + if (str == NULL || search == NULL || replace == NULL || result == NULL) { + return; + } + + size_t search_len = strlen(search); + size_t replace_len = strlen(replace); + + if (search_len == 0) { + strcpy(result, str); + return; + } + + const char* current = str; + char* result_ptr = result; + + while ((current = strstr(current, search)) != NULL) { + size_t bytes_to_copy = current - str; + memcpy(result_ptr, str, bytes_to_copy); + result_ptr += bytes_to_copy; + + memcpy(result_ptr, replace, replace_len); + result_ptr += replace_len; + + current += search_len; + str = current; + } + + strcpy(result_ptr, str); +} + #endif \ No newline at end of file diff --git a/utils/SystemInfo.h b/utils/SystemInfo.h index 4032f1e..c7ffe5d 100644 --- a/utils/SystemInfo.h +++ b/utils/SystemInfo.h @@ -425,6 +425,37 @@ unsigned int get_gpu_info(GpuInfo* info) { return i; } +struct DisplayInfo { + char name[64]; + int width; + int height; + int hz; +}; + +unsigned int get_display_info(DisplayInfo* info) { + DISPLAY_DEVICE device; + DEVMODE mode; + + device.cb = sizeof(DISPLAY_DEVICE); + + int i = 0; + + while (EnumDisplayDevices(NULL, i, &device, 0)) { + mode.dmSize = sizeof(mode); + + if (EnumDisplaySettings(device.DeviceName, ENUM_CURRENT_SETTINGS, &mode)) { + strcpy(info[i].name, device.DeviceName); + info[i].width = mode.dmPelsWidth; + info[i].height = mode.dmPelsHeight; + info[i].hz = mode.dmDisplayFrequency; + } + + ++i; + } + + return i; +} + struct SystemInfo { OSInfo os; MainboardInfo mainboard; @@ -437,6 +468,9 @@ struct SystemInfo { GpuInfo gpu[2]; int gpu_count; + + DisplayInfo display[6]; + int display_count; }; void render_system_info(char* buf, const SystemInfo* info) { @@ -487,9 +521,17 @@ void render_system_info(char* buf, const SystemInfo* info) { "GPU:\n" "==============\n" "Name: %s\n" "VRAM: %d\n" - "\n" "Name: %s\n" "VRAM: %d\n" "\n" + "Display:\n" + "==============\n" + "Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n" + "Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n" + "Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n" + "Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n" + "Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n" + "Name: %s\n" "Width: %d\n" "Height: %d\n" "Hz: %d\n" + "\n" "RAM:\n" "==============\n" "Memory: %d MB", @@ -507,6 +549,12 @@ void render_system_info(char* buf, const SystemInfo* info) { info->cpu.simd.sse, info->cpu.simd.avx256, info->cpu.simd.avx512 > 0 ? avx512[info->cpu.simd.avx512 - 1] : "0", info->gpu[0].name, info->gpu[0].vram, info->gpu_count < 2 ? "" : info->gpu[1].name, info->gpu_count < 2 ? 0 : info->gpu[1].vram, + info->display[0].name, info->display[0].width, info->display[0].height, info->display[0].hz, + info->display_count < 2 ? "" : info->display[1].name, info->display_count < 2 ? 0 : info->display[1].width, info->display_count < 2 ? 0 : info->display[1].height, info->display_count < 2 ? 0 : info->display[1].hz, + info->display_count < 3 ? "" : info->display[2].name, info->display_count < 3 ? 0 : info->display[2].width, info->display_count < 3 ? 0 : info->display[2].height, info->display_count < 3 ? 0 : info->display[2].hz, + info->display_count < 4 ? "" : info->display[3].name, info->display_count < 4 ? 0 : info->display[3].width, info->display_count < 4 ? 0 : info->display[3].height, info->display_count < 4 ? 0 : info->display[3].hz, + info->display_count < 5 ? "" : info->display[4].name, info->display_count < 5 ? 0 : info->display[4].width, info->display_count < 5 ? 0 : info->display[4].height, info->display_count < 5 ? 0 : info->display[4].hz, + info->display_count < 6 ? "" : info->display[5].name, info->display_count < 6 ? 0 : info->display[5].width, info->display_count < 6 ? 0 : info->display[5].height, info->display_count < 6 ? 0 : info->display[5].hz, info->ram.memory ); } @@ -519,6 +567,7 @@ void get_system_info(SystemInfo* info) get_cpu_info(&info->cpu); get_ram_info(&info->ram); info->gpu_count = get_gpu_info(info->gpu); + info->display_count = get_display_info(info->display); } #endif \ No newline at end of file diff --git a/utils/TestUtils.h b/utils/TestUtils.h index ed49fdd..c5c2215 100644 --- a/utils/TestUtils.h +++ b/utils/TestUtils.h @@ -29,14 +29,6 @@ struct TimingStat { double delta_time; }; -struct LogPool { - char* memory; - uint32 pos; - uint32 count; - - // uint32 size = count * MAX_LOG_LENGTH -}; - // IMPORTANT: This function should only be called when you actually use this data // e.g. log to display or file inline diff --git a/utils/Utils.h b/utils/Utils.h index 81959b8..27a0e90 100644 --- a/utils/Utils.h +++ b/utils/Utils.h @@ -71,17 +71,37 @@ byte get_bits(byte data, int bits_to_read, int start_pos) } inline -uint32 get_bits(const byte* data, int bits_to_read, int start_pos) +uint64 get_bits(const byte* data, int bits_to_read, int start_pos) { + if (bits_to_read <= 0 || bits_to_read > sizeof(uint64)) { + return 0; + } + int byte_index = start_pos / 8; int bit_offset = start_pos % 8; - uint32_t mask = (1 << bits_to_read) - 1; + uint64_t mask = (1ULL << bits_to_read) - 1; + uint64_t result = 0; - uint32_t result = (data[byte_index] >> bit_offset); + int bits_read = 0; - if (bit_offset + bits_to_read > 8) { - result |= (data[byte_index + 1] << (8 - bit_offset)); + while (bits_read < bits_to_read) { + int bits_in_current_byte = 8 - bit_offset; + int bits_to_take = bits_to_read - bits_read; + + if (bits_to_take > bits_in_current_byte) { + bits_to_take = bits_in_current_byte; + } + + uint8_t current_byte = data[byte_index]; + current_byte >>= bit_offset; + current_byte &= (1 << bits_to_take) - 1; + + result |= ((uint64_t)current_byte << bits_read); + + bits_read += bits_to_take; + bit_offset = 0; + byte_index++; } result &= mask;