Convert subtextures to use hash tables

Also clean up and add some block comments to aid code separation mainly in
AssetManager.
This commit is contained in:
Doyle Thai 2016-08-30 18:42:37 +10:00
parent 8b0f2f93e3
commit e9db7b0570
6 changed files with 396 additions and 364 deletions

View File

@ -51,7 +51,7 @@ INTERNAL HashTableEntry *getFreeHashSlot(HashTable *const table,
}
/* Check if platform_mem_alloc failed(), otherwise always true if hash table
* entries initialised*/
* entries initialised, assign key to hash entry */
if (result)
{
// +1 Null terminator
@ -77,6 +77,205 @@ INTERNAL HashTableEntry *getEntryFromHash(HashTable *const table,
return result;
}
/*
*********************************
* Texture Operations
*********************************
*/
INTERNAL Rect *getFreeAtlasSubTexSlot(TexAtlas *const atlas,
MemoryArena *const arena,
const char *const key)
{
HashTableEntry *entry = getFreeHashSlot(&atlas->subTex, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Rect);
Rect *result = CAST(Rect *) entry->data;
return result;
}
else
{
return NULL;
}
}
Rect *asset_getAtlasSubTex(TexAtlas *const atlas, const char *const key)
{
HashTableEntry *entry = getEntryFromHash(&atlas->subTex, key);
Rect *result = NULL;
if (entry) result = CAST(Rect *) entry->data;
return result;
}
Texture *asset_getTex(AssetManager *const assetManager, const char *const key)
{
HashTableEntry *entry = getEntryFromHash(&assetManager->textures, key);
Texture *result = NULL;
if (entry) result = CAST(Texture *)entry->data;
return result;
}
TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager,
MemoryArena *arena, const char *const key,
i32 numSubTex)
{
HashTableEntry *const entry =
getFreeHashSlot(&assetManager->texAtlas, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas);
TexAtlas *result = CAST(TexAtlas *) entry->data;
if (result)
{
result->subTex.size = numSubTex;
result->subTex.entries =
PLATFORM_MEM_ALLOC(arena, numSubTex, HashTableEntry);
if (!result->subTex.entries)
{
PLATFORM_MEM_FREE(arena, result, sizeof(TexAtlas));
result = NULL;
}
}
return result;
}
else
{
return NULL;
}
}
TexAtlas *asset_getTexAtlas(AssetManager *const assetManager,
const char *const key)
{
HashTableEntry *entry = getEntryFromHash(&assetManager->texAtlas, key);
TexAtlas *result = NULL;
if (entry) result = CAST(TexAtlas *)entry->data;
return result;
}
Texture *asset_getFreeTexSlot(AssetManager *const assetManager,
MemoryArena *const arena, const char *const key)
{
HashTableEntry *const entry =
getFreeHashSlot(&assetManager->textures, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Texture);
Texture *result = CAST(Texture *) entry->data;
return result;
}
else
{
return NULL;
}
}
Texture *asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
const char *const path, const char *const key)
{
/* Open the texture image */
i32 imgWidth, imgHeight, bytesPerPixel;
stbi_set_flip_vertically_on_load(TRUE);
u8 *image =
stbi_load(path, &imgWidth, &imgHeight, &bytesPerPixel, 0);
#ifdef DENGINE_DEBUG
if (imgWidth != imgHeight)
{
printf(
"asset_loadTextureImage() warning: Sprite sheet is not square: "
"%dx%dpx\n", imgWidth, imgHeight);
}
#endif
if (!image)
{
printf("stdbi_load() failed: %s\n", stbi_failure_reason());
return NULL;
}
Texture *result = asset_getFreeTexSlot(assetManager, arena, key);
*result = texture_gen(CAST(GLuint)(imgWidth), CAST(GLuint)(imgHeight),
CAST(GLint)(bytesPerPixel), image);
GL_CHECK_ERROR();
stbi_image_free(image);
return result;
}
/*
*********************************
* Animation Asset Managing
*********************************
*/
INTERNAL Animation *getFreeAnimationSlot(AssetManager *assetManager,
MemoryArena *arena, char *key)
{
HashTableEntry *entry = getFreeHashSlot(&assetManager->anims, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Animation);
Animation *result = CAST(Animation *) entry->data;
return result;
}
else
{
return NULL;
}
}
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
char *animName, TexAtlas *atlas, char **subTextureNames,
i32 numSubTextures, f32 frameDuration)
{
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;
anim->frameList = PLATFORM_MEM_ALLOC(arena, numSubTextures, char*);
for (i32 i = 0; i < numSubTextures; i++)
{
anim->frameList[i] = subTextureNames[i];
}
}
Animation *asset_getAnim(AssetManager *const assetManager,
const char *const key)
{
HashTableEntry *entry = getEntryFromHash(&assetManager->anims, key);
Animation *result = NULL;
if (entry) result = CAST(Animation *)entry->data;
return result;
}
/*
*********************************
* XML Operations
@ -356,89 +555,127 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
XmlNode *node = root;
while (node)
{
/*
*********************************
* Branch on node names
*********************************
*/
if (common_strcmp(node->name, "TextureAtlas") == 0)
{
XmlNode *atlasXmlNode = node;
TexAtlas *atlasEntry = NULL;
TexAtlas *atlas = NULL;
if (common_strcmp(node->attribute.name, "imagePath") == 0)
{
/*
**********************************************
* Create a texture atlas with imageName as key
**********************************************
*/
char *imageName = atlasXmlNode->attribute.value;
atlasEntry =
asset_getFreeTexAtlasSlot(assetManager, arena, imageName);
i32 numSubTex = 1024;
atlas = asset_getFreeTexAtlasSlot(assetManager, arena,
imageName, numSubTex);
char *dataDir = "data/textures/WorldTraveller/";
char imagePath[512] = {0};
common_strncat(imagePath, dataDir, common_strlen(dataDir));
common_strncat(imagePath, imageName, common_strlen(imageName));
if (!atlas)
{
DEBUG_LOG(
"parseXmlTreeToGame() failed: Could not get free atlas "
"entry");
return;
}
asset_loadTextureImage(assetManager, arena, imagePath,
imageName);
/*
*************************************************
* Load a texture to hash, with imageName as key
*************************************************
*/
char *dataDir = "data/textures/WorldTraveller/";
i32 dataDirLen = common_strlen(dataDir);
i32 imageNameLen = common_strlen(imageName);
i32 totalPathLen = (dataDirLen + imageNameLen) + 1;
atlasEntry->key = PLATFORM_MEM_ALLOC(
arena, common_strlen(imageName) + 1, char);
common_strncpy(atlasEntry->key, imageName,
common_strlen(imageName));
char *imagePath = PLATFORM_MEM_ALLOC(arena, totalPathLen, char);
common_strncat(imagePath, dataDir, dataDirLen);
common_strncat(imagePath, imageName, imageNameLen);
atlasEntry->tex = asset_getTex(assetManager, imageName);
Texture *tex = asset_loadTextureImage(assetManager, arena,
imagePath, imageName);
if (!tex)
{
DEBUG_LOG("parseXmlTreeToGame() failed: Could not load image");
PLATFORM_MEM_FREE(arena, imagePath,
totalPathLen * sizeof(char));
return;
}
PLATFORM_MEM_FREE(arena, imagePath,
totalPathLen * sizeof(char));
atlas->tex = tex;
/*
*************************************************
* Iterate over XML attributes
*************************************************
*/
XmlNode *atlasChildNode = atlasXmlNode->child;
while (atlasChildNode)
{
if (common_strcmp(atlasChildNode->name, "SubTexture") == 0)
{
XmlAttribute *subTextureAttrib =
&atlasChildNode->attribute;
XmlAttribute *subTexAttrib = &atlasChildNode->attribute;
AtlasSubTexture newSubTexEntry = {0};
while (subTextureAttrib)
char *key = NULL;
Rect subTex = {0};
while (subTexAttrib)
{
// TODO(doyle): Work around for now in xml reading,
// reading the last node closing node not being
// merged to the parent
if (!subTextureAttrib->name) continue;
if (!subTexAttrib->name) continue;
if (common_strcmp(subTextureAttrib->name, "name") ==
0)
if (common_strcmp(subTexAttrib->name, "name") == 0)
{
char *value = subTextureAttrib->value;
newSubTexEntry.key = value;
char *value = subTexAttrib->value;
key = value;
}
else if (common_strcmp(subTextureAttrib->name,
"x") == 0)
else if (common_strcmp(subTexAttrib->name, "x") ==
0)
{
char *value = subTextureAttrib->value;
char *value = subTexAttrib->value;
i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen);
newSubTexEntry.rect.pos.x = CAST(f32) intValue;
subTex.pos.x = CAST(f32) intValue;
}
else if (common_strcmp(subTextureAttrib->name,
"y") == 0)
else if (common_strcmp(subTexAttrib->name, "y") ==
0)
{
char *value = subTextureAttrib->value;
char *value = subTexAttrib->value;
i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen);
newSubTexEntry.rect.pos.y = CAST(f32) intValue;
subTex.pos.y = CAST(f32) intValue;
}
else if (common_strcmp(subTextureAttrib->name,
else if (common_strcmp(subTexAttrib->name,
"width") == 0)
{
char *value = subTextureAttrib->value;
char *value = subTexAttrib->value;
i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen);
newSubTexEntry.rect.size.w = CAST(f32) intValue;
subTex.size.w = CAST(f32) intValue;
}
else if (common_strcmp(subTextureAttrib->name,
else if (common_strcmp(subTexAttrib->name,
"height") == 0)
{
char *value = subTextureAttrib->value;
char *value = subTexAttrib->value;
i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen);
newSubTexEntry.rect.size.h = CAST(f32) intValue;
subTex.size.h = CAST(f32) intValue;
}
else
{
@ -447,53 +684,21 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
"Unsupported xml attribute in SubTexture");
#endif
}
subTextureAttrib = subTextureAttrib->next;
subTexAttrib = subTexAttrib->next;
}
// TODO(doyle): XML specifies 0,0 top left, we
// prefer 0,0 bottom right, so offset by size since 0,0
// is top left and size creates a bounding box below it
newSubTexEntry.rect.pos.y =
1024 - newSubTexEntry.rect.pos.y;
newSubTexEntry.rect.pos.y -= newSubTexEntry.rect.size.h;
subTex.pos.y = 1024 - subTex.pos.y;
subTex.pos.y -= subTex.size.h;
#ifdef DENGINE_DEBUG
ASSERT(newSubTexEntry.key)
ASSERT(key);
#endif
u32 subTexHashIndex = common_murmurHash2(
newSubTexEntry.key,
common_strlen(newSubTexEntry.key), 0xDEADBEEF);
subTexHashIndex =
subTexHashIndex % ARRAY_COUNT(atlasEntry->subTex);
// NOTE(doyle): Hash collision
AtlasSubTexture *subTexEntry =
&atlasEntry->subTex[subTexHashIndex];
if (subTexEntry->key)
{
#ifdef DENGINE_DEBUG
// NOTE(doyle): Two textures have the same access
// name
ASSERT(common_strcmp(subTexEntry->key,
newSubTexEntry.key) != 0);
#endif
while (subTexEntry->next)
subTexEntry = subTexEntry->next;
subTexEntry->next =
PLATFORM_MEM_ALLOC(arena, 1, AtlasSubTexture);
subTexEntry = subTexEntry->next;
}
*subTexEntry = newSubTexEntry;
i32 keyLen = common_strlen(newSubTexEntry.key);
subTexEntry->key =
PLATFORM_MEM_ALLOC(arena, keyLen + 1, char);
common_strncpy(subTexEntry->key, newSubTexEntry.key,
keyLen);
Rect *subTexInHash =
getFreeAtlasSubTexSlot(atlas, arena, key);
*subTexInHash = subTex;
}
else
{
@ -559,6 +764,11 @@ INTERNAL void freeXmlData(MemoryArena *arena, XmlToken *tokens, i32 numTokens,
if (tokens) PLATFORM_MEM_FREE(arena, tokens, numTokens * sizeof(XmlToken));
}
/*
*********************************
* Everything else
*********************************
*/
i32 asset_loadXmlFile(AssetManager *assetManager, MemoryArena *arena,
PlatformFileRead *fileRead)
{
@ -587,73 +797,6 @@ i32 asset_loadXmlFile(AssetManager *assetManager, MemoryArena *arena,
return result;
}
/*
*********************************
* Texture Operations
*********************************
*/
INTERNAL AtlasSubTexture *getAtlasSubTex(TexAtlas *atlas, char *key)
{
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(atlas->subTex));
AtlasSubTexture *result = &atlas->subTex[hashIndex];
if (result->key)
{
while (result && common_strcmp(result->key, key) != 0)
result = result->next;
}
return result;
}
INTERNAL AtlasSubTexture *getFreeAtlasSubTexSlot(TexAtlas *atlas,
MemoryArena *arena, char *key)
{
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(atlas->subTex));
AtlasSubTexture *result = &atlas->subTex[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, AtlasSubTexture);
result = result->next;
}
return result;
}
INTERNAL Animation *getFreeAnimationSlot(AssetManager *assetManager,
MemoryArena *arena, char *key)
{
HashTableEntry *entry = getFreeHashSlot(&assetManager->anims, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Animation);
Animation *result = CAST(Animation *) entry->data;
return result;
}
else
{
return NULL;
}
}
Rect asset_getSubTexRect(TexAtlas *atlas, char *key)
{
AtlasSubTexture *subTex = getAtlasSubTex(atlas, key);
Rect result = subTex->rect;
return result;
}
// TODO(doyle): Switch to hash based lookup
// TODO(doyle): Use pointers, so we can forward declare all assets?
AudioVorbis *asset_getVorbis(AssetManager *assetManager,
@ -669,77 +812,6 @@ AudioVorbis *asset_getVorbis(AssetManager *assetManager,
return NULL;
}
Texture *asset_getTex(AssetManager *const assetManager, const char *const key)
{
HashTableEntry *entry = getEntryFromHash(&assetManager->textures, key);
Texture *result = NULL;
if (entry) result = CAST(Texture *)entry->data;
return result;
}
Texture *asset_getFreeTexSlot(AssetManager *const assetManager,
MemoryArena *const arena, const char *const key)
{
HashTableEntry *const entry =
getFreeHashSlot(&assetManager->textures, arena, key);
if (entry)
{
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Texture);
Texture *result = CAST(Texture *) entry->data;
return result;
}
else
{
return NULL;
}
}
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)
{
HashTableEntry *entry = getEntryFromHash(&assetManager->texAtlas, key);
TexAtlas *result = NULL;
if (entry) result = CAST(TexAtlas *)entry->data;
return result;
}
Animation *asset_getAnim(AssetManager *const assetManager,
const char *const key)
{
HashTableEntry *entry = getEntryFromHash(&assetManager->anims, key);
Animation *result = NULL;
if (entry) result = CAST(Animation *)entry->data;
return result;
}
const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
const char *const path, const enum AudioList type)
{
@ -772,52 +844,8 @@ const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
return 0;
}
const i32 asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
const char *const path, const char *const key)
{
/* Open the texture image */
i32 imgWidth, imgHeight, bytesPerPixel;
stbi_set_flip_vertically_on_load(TRUE);
u8 *image =
stbi_load(path, &imgWidth, &imgHeight, &bytesPerPixel, 0);
#ifdef DENGINE_DEBUG
if (imgWidth != imgHeight)
{
printf(
"asset_loadTextureImage() warning: Sprite sheet is not square: "
"%dx%dpx\n", imgWidth, imgHeight);
}
#endif
if (!image)
{
printf("stdbi_load() failed: %s\n", stbi_failure_reason());
return -1;
}
Texture *tex = asset_getFreeTexSlot(assetManager, arena, key);
*tex = texture_gen(CAST(GLuint)(imgWidth), CAST(GLuint)(imgHeight),
CAST(GLint)(bytesPerPixel), image);
GL_CHECK_ERROR();
stbi_image_free(image);
return 0;
}
Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type)
{
if (type < shaderlist_count)
return &assetManager->shaders[type];
#ifdef DENGINE_DEBUG
ASSERT(INVALID_CODE_PATH);
#endif
return NULL;
}
INTERNAL GLuint createShaderFromPath(MemoryArena *arena, const char *const path, GLuint shadertype)
INTERNAL GLuint createShaderFromPath(MemoryArena *arena, const char *const path,
GLuint shadertype)
{
PlatformFileRead file = {0};
@ -869,6 +897,17 @@ INTERNAL i32 shaderLoadProgram(Shader *const shader, const GLuint vertexShader,
return 0;
}
Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type)
{
if (type < shaderlist_count)
return &assetManager->shaders[type];
#ifdef DENGINE_DEBUG
ASSERT(INVALID_CODE_PATH);
#endif
return NULL;
}
const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena *arena,
const char *const vertexPath,
const char *const fragmentPath,
@ -906,7 +945,11 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
stbtt_InitFont(&fontInfo, fontFileRead.buffer,
stbtt_GetFontOffsetForIndex(fontFileRead.buffer, 0));
/* Initialise Assetmanager Font */
/*
****************************************
* Initialise assetmanager font reference
****************************************
*/
Font *font = &assetManager->font;
font->codepointRange = V2i(32, 127);
v2 codepointRange = font->codepointRange;
@ -930,7 +973,11 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
font->charMetrics = PLATFORM_MEM_ALLOC(arena, numGlyphs, CharMetrics);
/* Use STB_TrueType to generate a series of bitmap characters */
/*
************************************************************
* Use STB_TrueType to generate a series of bitmap characters
************************************************************
*/
i32 glyphIndex = 0;
for (i32 codepoint = CAST(i32) codepointRange.x;
codepoint < CAST(i32) codepointRange.y; codepoint++)
@ -1034,8 +1081,16 @@ 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;
i32 numSubTex = numGlyphs;
TexAtlas *fontAtlas =
asset_getFreeTexAtlasSlot(assetManager, arena, "font");
asset_getFreeTexAtlasSlot(assetManager, arena, "font", numSubTex);
/*
*********************************************************
* Load individual glyph bitmap data into one font bitmap
*********************************************************
*/
for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++)
{
u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE);
@ -1049,25 +1104,15 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
/* Store the location of glyph into atlas */
if (verticalPixelsBlitted == 0)
{
#ifdef DENGINE_DEBUG
ASSERT(activeGlyph.codepoint < ARRAY_COUNT(fontAtlas->subTex));
#endif
v2 origin =
V2(CAST(f32)(glyphIndex * font->maxSize.w), CAST(f32) row);
// NOTE(doyle): Since charToEncode starts from 0 and we record
// all ascii characters, charToEncode represents the character
// 1:1
char charTmp[2] = {0};
charTmp[0] = charToEncode;
AtlasSubTexture *subTex =
getFreeAtlasSubTexSlot(fontAtlas, arena, charTmp);
subTex->key = PLATFORM_MEM_ALLOC(arena, 1, char);
subTex->key[0] = charToEncode;
subTex->rect = CAST(Rect){origin, font->maxSize};
const char key[2] = {charToEncode, 0};
Rect *subTex = getFreeAtlasSubTexSlot(fontAtlas, arena, key);
*subTex = CAST(Rect){origin, font->maxSize};
charToEncode++;
}
@ -1115,6 +1160,11 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
}
}
/*
*******************************************
* Generate and store font bitmap to assets
*******************************************
*/
Texture *tex = asset_getFreeTexSlot(assetManager, arena, "font");
*tex = texture_gen(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4,
CAST(u8 *) fontBitmap);
@ -1146,28 +1196,6 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
return 0;
}
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
char *animName, TexAtlas *atlas, char **subTextureNames,
i32 numSubTextures, f32 frameDuration)
{
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;
anim->frameList = PLATFORM_MEM_ALLOC(arena, numSubTextures, char*);
for (i32 i = 0; i < numSubTextures; i++)
{
AtlasSubTexture *subTex = getAtlasSubTex(atlas, subTextureNames[i]);
anim->frameList[i] = subTex->key;
}
}
v2 asset_stringDimInPixels(const Font *const font, const char *const string)
{

View File

@ -55,9 +55,9 @@ void entity_updateAnim(Entity *entity, f32 dt)
case entitytype_mob:
case entitytype_npc:
char *frameName = anim->frameList[currEntityAnim->currFrame];
Rect texRect =
asset_getSubTexRect(anim->atlas, frameName);
entity->renderSize = texRect.size;
Rect *texRect =
asset_getAtlasSubTex(anim->atlas, frameName);
entity->renderSize = texRect->size;
default:
break;
}

View File

@ -210,12 +210,13 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
pos.x += charMetric.advance;
/* Get texture out */
Rect charTexRect =
asset_getSubTexRect(font->atlas, &CAST(char)codepoint);
Rect *charTexRect =
asset_getAtlasSubTex(font->atlas, &CAST(char)codepoint);
v4 deprecatedTexRect = {0};
deprecatedTexRect.vec2[0] = charTexRect.pos;
deprecatedTexRect.vec2[1] = v2_add(charTexRect.pos, charTexRect.size);
deprecatedTexRect.vec2[0] = charTexRect->pos;
deprecatedTexRect.vec2[1] =
v2_add(charTexRect->pos, charTexRect->size);
flipTexCoord(&deprecatedTexRect, FALSE, TRUE);
@ -251,12 +252,12 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
EntityAnim *entityAnim = &entity->animList[entity->currAnimId];
Animation *anim = entityAnim->anim;
char *frameName = anim->frameList[entityAnim->currFrame];
Rect animRect = asset_getSubTexRect(anim->atlas, frameName);
Rect *animRect = asset_getAtlasSubTex(anim->atlas, frameName);
// TODO(doyle): Switch to rect
v4 animTexRect = {0};
animTexRect.vec2[0] = animRect.pos;
animTexRect.vec2[1] = v2_add(animRect.pos, animRect.size);
animTexRect.vec2[0] = animRect->pos;
animTexRect.vec2[1] = v2_add(animRect->pos, animRect->size);
if (entity->direction == direction_east)
{

View File

@ -1641,17 +1641,18 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
/* Draw hero avatar */
TexAtlas *heroAtlas =
asset_getTexAtlas(assetManager, "ClaudeSprite.png");
Rect heroAvatarRect =
asset_getSubTexRect(heroAtlas, "ClaudeSprite_Avatar_01");
Rect *heroAvatarRect =
asset_getAtlasSubTex(heroAtlas, "ClaudeSprite_Avatar_01");
v2 heroAvatarP =
V2(10.0f, (renderer->size.h * 0.5f) - (0.5f * heroAvatarRect.size.h));
V2(10.0f, (renderer->size.h * 0.5f) - (0.5f * heroAvatarRect->size.h));
// TODO(doyle): Use rect in rendering not V4
v4 heroAvatarTexRect = {0};
heroAvatarTexRect.vec2[0] = heroAvatarRect.pos;
heroAvatarTexRect.vec2[1] = v2_add(heroAvatarRect.pos, heroAvatarRect.size);
heroAvatarTexRect.vec2[0] = heroAvatarRect->pos;
heroAvatarTexRect.vec2[1] = v2_add(heroAvatarRect->pos, heroAvatarRect->size);
RenderTex heroRenderTex = {hero->tex, heroAvatarTexRect};
renderer_staticRect(renderer, heroAvatarP, heroAvatarRect.size, V2(0, 0), 0,
renderer_staticRect(renderer, heroAvatarP, heroAvatarRect->size, V2(0, 0), 0,
heroRenderTex, V4(1, 1, 1, 1));
char heroAvatarStr[20];
@ -1660,7 +1661,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
f32 strLenInPixels =
CAST(f32)(font->maxSize.w * common_strlen(heroAvatarStr));
v2 strPos =
V2(heroAvatarP.x, heroAvatarP.y - (0.5f * heroAvatarRect.size.h));
V2(heroAvatarP.x, heroAvatarP.y - (0.5f * heroAvatarRect->size.h));
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
strPos, V2(0, 0), 0, V4(0, 0, 1, 1));

View File

@ -9,20 +9,6 @@
typedef struct MemoryArena MemoryArena;
typedef struct PlatformFileRead PlatformFileRead;
typedef struct HashTableEntry
{
void *data;
char *key;
void *next;
} HashTableEntry;
typedef struct HashTable
{
HashTableEntry *entries;
i32 size;
} HashTable;
typedef struct AssetManager
{
/* Hash Tables */
@ -37,23 +23,22 @@ typedef struct AssetManager
} AssetManager;
#define MAX_TEXTURE_SIZE 1024
/*
*********************************
* Texture Asset Managing
* Texture Operations
*********************************
*/
Rect asset_getSubTexRect(TexAtlas *atlas, char *key);
Rect *asset_getAtlasSubTex(TexAtlas *const atlas, const char *const key);
Texture *asset_getTex(AssetManager *const assetManager, const char *const key);
TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager,
MemoryArena *arena, const char *const key);
MemoryArena *arena, const char *const key,
i32 numSubTex);
TexAtlas *asset_getTexAtlas(AssetManager *const assetManager,
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);
Texture *asset_loadTextureImage(AssetManager *assetManager, MemoryArena *arena,
const char *const path, const char *const key);
/*
*********************************
@ -73,18 +58,22 @@ Animation *asset_getAnim(AssetManager *const assetManager,
*/
i32 asset_loadXmlFile(AssetManager *assetManager, MemoryArena *arena,
PlatformFileRead *fileRead);
AudioVorbis *asset_getVorbis(AssetManager *assetManager,
const enum AudioList type);
Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type);
const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
const char *const path, const enum AudioList type);
Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type);
const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena *arena,
const char *const vertexPath,
const char *const fragmentPath,
const enum ShaderList type);
const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
const char *filePath);
v2 asset_stringDimInPixels(const Font *const font, const char *const string);
void asset_unitTest(MemoryArena *arena);
#endif

View File

@ -10,6 +10,12 @@
/* Forward Declaration */
typedef struct Texture Texture;
/*
*********************************
* XML
*********************************
*/
// TODO(doyle): We only expose this to for debug.h to print out xml trees
typedef struct XmlAttribute
{
b32 init;
@ -36,28 +42,17 @@ typedef struct XmlNode
} XmlNode;
enum TexList
{
texlist_empty,
texlist_hero,
texlist_claude,
texlist_terrain,
texlist_font,
texlist_count,
};
enum ShaderList
{
shaderlist_sprite,
shaderlist_count,
};
enum TerrainRects
{
terrainrects_ground,
terrainrects_count,
};
/*
*********************************
* Audio
*********************************
*/
enum AudioList
{
audiolist_battle,
@ -80,23 +75,36 @@ typedef struct AudioVorbis
i32 size;
} AudioVorbis;
typedef struct AtlasSubTexture
/*
*********************************
* Hash Table
*********************************
*/
typedef struct HashTableEntry
{
// NOTE(doyle): Key used to arrive to hash entry
void *data;
char *key;
Rect rect;
// NOTE(doyle): For hashing collisions
struct AtlasSubTexture *next;
} AtlasSubTexture;
void *next;
} HashTableEntry;
typedef struct HashTable
{
HashTableEntry *entries;
i32 size;
} HashTable;
/*
*********************************
* Texture Assets
*********************************
*/
typedef struct TexAtlas
{
char *key;
Texture *tex;
AtlasSubTexture subTex[512];
struct TexAtlas *next;
HashTable subTex;
i32 numSubTex;
} TexAtlas;
typedef struct Animation
@ -113,6 +121,11 @@ typedef struct Animation
f32 frameDuration;
} Animation;
/*
*********************************
* Font
*********************************
*/
// TODO(doyle): We only use the offset and advance metric at the moment, remove?
typedef struct FontMetrics
{