Use better generic hashtable implement. for assets

This commit is contained in:
Doyle Thai 2016-08-30 14:19:18 +10:00
parent c93e6ca37c
commit 8b0f2f93e3
4 changed files with 154 additions and 134 deletions

View File

@ -22,6 +22,61 @@
#include "Dengine/OpenGL.h"
#include "Dengine/Platform.h"
/*
*********************************
* Hash Table Operations
*********************************
*/
INTERNAL HashTableEntry *getFreeHashSlot(HashTable *const table,
MemoryArena *arena,
const char *const key)
{
u32 hashIndex = common_getHashIndex(key, table->size);
HashTableEntry *result = &table->entries[hashIndex];
if (result->key)
{
while (result->next)
{
if (common_strcmp(result->key, key) == 0)
{
// TODO(doyle): Error hash item already exists
ASSERT(INVALID_CODE_PATH);
}
result = result->next;
}
result->next = PLATFORM_MEM_ALLOC(arena, 1, HashTableEntry);
result = result->next;
}
/* Check if platform_mem_alloc failed(), otherwise always true if hash table
* entries initialised*/
if (result)
{
// +1 Null terminator
i32 keyLen = common_strlen(key) + 1;
result->key = PLATFORM_MEM_ALLOC(arena, keyLen, char);
common_strncpy(result->key, key, keyLen);
}
return result;
}
INTERNAL HashTableEntry *getEntryFromHash(HashTable *const table,
const char *const key)
{
u32 hashIndex = common_getHashIndex(key, table->size);
HashTableEntry *result = &table->entries[hashIndex];
if (result->key)
{
while (result && common_strcmp(result->key, key) != 0)
result = result->next;
}
return result;
}
/*
*********************************
* XML Operations
@ -308,7 +363,8 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
if (common_strcmp(node->attribute.name, "imagePath") == 0)
{
char *imageName = atlasXmlNode->attribute.value;
atlasEntry = asset_makeTexAtlas(assetManager, arena, imageName);
atlasEntry =
asset_getFreeTexAtlasSlot(assetManager, arena, imageName);
char *dataDir = "data/textures/WorldTraveller/";
char imagePath[512] = {0};
@ -574,29 +630,21 @@ INTERNAL AtlasSubTexture *getFreeAtlasSubTexSlot(TexAtlas *atlas,
return result;
}
INTERNAL Animation *getFreeAnimationSlot(Animation *table, u32 tableSize,
INTERNAL Animation *getFreeAnimationSlot(AssetManager *assetManager,
MemoryArena *arena, char *key)
{
u32 hashIndex = common_getHashIndex(key, tableSize);
Animation *result = &table[hashIndex];
if (result->key)
HashTableEntry *entry = getFreeHashSlot(&assetManager->anims, arena, key);
if (entry)
{
while (result->next)
{
if (common_strcmp(result->key, key) == 0)
{
// TODO(doyle): Error correction whereby if a tex atlas already
// exists
ASSERT(INVALID_CODE_PATH);
}
result = result->next;
}
result->next = PLATFORM_MEM_ALLOC(arena, 1, Animation);
result = result->next;
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Animation);
Animation *result = CAST(Animation *) entry->data;
return result;
}
else
{
return NULL;
}
return result;
}
Rect asset_getSubTexRect(TexAtlas *atlas, char *key)
@ -623,73 +671,71 @@ AudioVorbis *asset_getVorbis(AssetManager *assetManager,
Texture *asset_getTex(AssetManager *const assetManager, const char *const key)
{
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->textures));
Texture *result = &assetManager->textures[hashIndex];
if (result->key)
{
while (result && common_strcmp(result->key, key) != 0)
result = result->next;
}
HashTableEntry *entry = getEntryFromHash(&assetManager->textures, key);
Texture *result = NULL;
if (entry) result = CAST(Texture *)entry->data;
return result;
}
TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager,
MemoryArena *arena, const char *const key)
Texture *asset_getFreeTexSlot(AssetManager *const assetManager,
MemoryArena *const arena, const char *const key)
{
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas));
TexAtlas *result = &assetManager->texAtlas[hashIndex];
if (result->key)
HashTableEntry *const entry =
getFreeHashSlot(&assetManager->textures, arena, key);
if (entry)
{
while (result->next)
{
if (common_strcmp(result->key, key) == 0)
{
// TODO(doyle): Error correction whereby if a tex atlas already
// exists
ASSERT(INVALID_CODE_PATH);
}
result = result->next;
}
result->next = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas);
result = result->next;
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Texture);
Texture *result = CAST(Texture *) entry->data;
return result;
}
else
{
return NULL;
}
}
return result;
TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager,
MemoryArena *arena, const char *const key)
{
HashTableEntry *const entry =
getFreeHashSlot(&assetManager->texAtlas, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas);
TexAtlas *result = CAST(TexAtlas *) entry->data;
return result;
}
else
{
return NULL;
}
}
TexAtlas *asset_getTexAtlas(AssetManager *const assetManager,
const char *const key)
{
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas));
TexAtlas *result = &assetManager->texAtlas[hashIndex];
if (result->key)
{
while (result && common_strcmp(result->key, key) != 0)
result = result->next;
}
else
{
return NULL;
}
HashTableEntry *entry = getEntryFromHash(&assetManager->texAtlas, key);
TexAtlas *result = NULL;
if (entry) result = CAST(TexAtlas *)entry->data;
return result;
}
Animation *asset_getAnim(AssetManager *assetManager, char *key)
Animation *asset_getAnim(AssetManager *const assetManager,
const char *const key)
{
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->anims));
Animation *result = &assetManager->anims[hashIndex];
if (result->key)
{
while (result && common_strcmp(result->key, key) != 0)
result = result->next;
}
else
{
return NULL;
}
HashTableEntry *entry = getEntryFromHash(&assetManager->anims, key);
Animation *result = NULL;
if (entry) result = CAST(Animation *)entry->data;
return result;
}
@ -726,33 +772,6 @@ const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
return 0;
}
// TODO(doyle): Revise passing in the assetmanager
Texture *asset_getAndAllocFreeTexSlot(AssetManager *assetManager,
MemoryArena *arena, const char *const key)
{
i32 texListSize = ARRAY_COUNT(assetManager->textures);
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->textures));
Texture *result = &assetManager->textures[hashIndex];
if (result->key)
{
while (result->next)
{
if (common_strcmp(result->key, key) == 0)
{
// TODO(doyle): Error correction whereby if a tex atlas already
// exists
ASSERT(INVALID_CODE_PATH);
}
result = result->next;
}
result->next = PLATFORM_MEM_ALLOC(arena, 1, Texture);
result = result->next;
}
return result;
}
const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
const char *const path, const char *const key)
{
@ -777,7 +796,7 @@ const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
return -1;
}
Texture *tex = asset_getAndAllocFreeTexSlot(assetManager, arena, key);
Texture *tex = asset_getFreeTexSlot(assetManager, arena, key);
*tex = texture_gen(CAST(GLuint)(imgWidth), CAST(GLuint)(imgHeight),
CAST(GLint)(bytesPerPixel), image);
@ -1015,7 +1034,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
// align the baselines up so we don't need to do baseline adjusting at
// render?
char charToEncode = CAST(char)codepointRange.x;
TexAtlas *fontAtlas = asset_makeTexAtlas(assetManager, arena, "font");
TexAtlas *fontAtlas =
asset_getFreeTexAtlasSlot(assetManager, arena, "font");
for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++)
{
u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE);
@ -1095,9 +1115,9 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
}
}
Texture tex = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4,
CAST(u8 *) fontBitmap);
assetManager->textures[texlist_font] = tex;
Texture *tex = asset_getFreeTexSlot(assetManager, arena, "font");
*tex = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4,
CAST(u8 *) fontBitmap);
#ifdef WT_RENDER_FONT_FILE
/* save out a 4 channel image */
@ -1106,7 +1126,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
#endif
PLATFORM_MEM_FREE(arena, fontBitmap, bitmapSize);
fontAtlas->tex = &assetManager->textures[texlist_font];
fontAtlas->tex = tex;
font->atlas = fontAtlas;
// NOTE(doyle): Formula derived from STB Font
@ -1130,17 +1150,16 @@ void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
char *animName, TexAtlas *atlas, char **subTextureNames,
i32 numSubTextures, f32 frameDuration)
{
Animation *anim = getFreeAnimationSlot(
assetManager->anims, ARRAY_COUNT(assetManager->anims), arena, animName);
Animation *anim = getFreeAnimationSlot(assetManager, arena, animName);
/* Use same animation ptr for name from entry key */
HashTableEntry *entry = getEntryFromHash(&assetManager->anims, animName);
anim->name = entry->key;
anim->atlas = atlas;
anim->frameDuration = frameDuration;
anim->numFrames = numSubTextures;
// NOTE(doyle): +1 for the null terminator
anim->name = PLATFORM_MEM_ALLOC(arena, common_strlen(animName) + 1, char);
common_strncpy(anim->name, animName, common_strlen(animName));
anim->frameList = PLATFORM_MEM_ALLOC(arena, numSubTextures, char*);
for (i32 i = 0; i < numSubTextures; i++)
{

View File

@ -116,12 +116,25 @@ INTERNAL void assetInit(GameState *state)
AssetManager *assetManager = &state->assetManager;
MemoryArena *arena = &state->arena;
/* Create empty 1x1 4bpp black texture */
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
Texture *tex = asset_getAndAllocFreeTexSlot(assetManager, arena, "nullTex");
*tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
i32 texAtlasEntries = 8;
assetManager->texAtlas.size = texAtlasEntries;
assetManager->texAtlas.entries =
PLATFORM_MEM_ALLOC(arena, texAtlasEntries, HashTableEntry);
//assetManager->texAtlas.type = hashtabletype_textureAtlas;
i32 texEntries = 32;
assetManager->textures.size = texEntries;
assetManager->textures.entries =
PLATFORM_MEM_ALLOC(arena, texEntries, HashTableEntry);
i32 animEntries = 1024;
assetManager->anims.size = animEntries;
assetManager->anims.entries =
PLATFORM_MEM_ALLOC(arena, animEntries, HashTableEntry);
/* Create empty 1x1 4bpp black texture */
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex");
*tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
/*
*********************************

View File

@ -9,15 +9,6 @@
typedef struct MemoryArena MemoryArena;
typedef struct PlatformFileRead PlatformFileRead;
enum HashTableType
{
hashtabletype_unknown,
hashtabletype_texture,
hashtabletype_textureAtlas,
hashtabletype_animation,
hashtabletype_count,
};
typedef struct HashTableEntry
{
void *data;
@ -30,15 +21,14 @@ typedef struct HashTable
{
HashTableEntry *entries;
i32 size;
enum HashTableType type;
} HashTable;
typedef struct AssetManager
{
/* Hash Tables */
TexAtlas texAtlas[8];
Texture textures[32];
Animation anims[1024];
HashTable texAtlas;
HashTable textures;
HashTable anims;
/* Primitive Array */
Shader shaders[32];
@ -55,13 +45,12 @@ typedef struct AssetManager
*/
Rect asset_getSubTexRect(TexAtlas *atlas, char *key);
Texture *asset_getTex(AssetManager *const assetManager, const char *const key);
TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager,
MemoryArena *arena, const char *const key);
TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager,
MemoryArena *arena, const char *const key);
TexAtlas *asset_getTexAtlas(AssetManager *const assetManager,
const char *const key);
Texture *asset_getAndAllocFreeTexSlot(AssetManager *assetManager,
MemoryArena *arena,
const char *const key);
Texture *asset_getFreeTexSlot(AssetManager *const assetManager,
MemoryArena *const arena, const char *const key);
const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
const char *const path,
const char *const key);
@ -74,7 +63,8 @@ const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
char *animName, TexAtlas *atlas, char **subTextureNames,
i32 numSubTextures, f32 frameDuration);
Animation *asset_getAnim(AssetManager *assetManager, char *key);
Animation *asset_getAnim(AssetManager *const assetManager,
const char *const key);
/*
*********************************

View File

@ -111,8 +111,6 @@ typedef struct Animation
i32 numFrames;
f32 frameDuration;
struct Animation *next;
} Animation;
// TODO(doyle): We only use the offset and advance metric at the moment, remove?