implementation progress
parent
534f61cbb0
commit
bd8194afc4
|
@ -47,6 +47,7 @@ add_library(Cram
|
|||
include/cram.h
|
||||
#Source
|
||||
lib/stb_rect_pack.h
|
||||
lib/stb_image.h
|
||||
src/cram.c
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Cram - A texture atlas system in C
|
||||
/* Cram - A texture packing system in C
|
||||
*
|
||||
* Copyright (c) 2022 Evan Hemsley
|
||||
*
|
||||
|
@ -56,6 +56,56 @@ extern "C"
|
|||
|
||||
CRAMAPI uint32_t Cram_LinkedVersion(void);
|
||||
|
||||
/* Type definitions */
|
||||
|
||||
typedef struct Cram_Context Cram_Context;
|
||||
|
||||
typedef struct Cram_ContextCreateInfo
|
||||
{
|
||||
const char *name;
|
||||
uint32_t maxDimension;
|
||||
uint32_t padding;
|
||||
uint8_t trim;
|
||||
} Cram_ContextCreateInfo;
|
||||
|
||||
typedef struct Cram_ImageData
|
||||
{
|
||||
const char *path;
|
||||
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
uint32_t offsetX;
|
||||
uint32_t offsetY;
|
||||
uint32_t trimmedWidth;
|
||||
uint32_t trimmedHeight;
|
||||
} Cram_ImageData;
|
||||
|
||||
typedef struct Cram_AtlasData
|
||||
{
|
||||
const char *name;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
Cram_ImageData *imageDatas;
|
||||
uint32_t imageDataCount;
|
||||
} Cram_AtlasData;
|
||||
|
||||
/* API definition */
|
||||
|
||||
CRAMAPI Cram_Context* Cram_Init(Cram_ContextCreateInfo *createInfo);
|
||||
|
||||
CRAMAPI void Cram_AddFile(Cram_Context *context, const char *path);
|
||||
CRAMAPI void Cram_AddFolder(Cram_Context *context, const char *path);
|
||||
|
||||
CRAMAPI void Cram_Pack(Cram_Context *context);
|
||||
|
||||
CRAMAPI void Cram_GetPixelData(Cram_Context *context, uint8_t **pPixelData, uint32_t *pWidth, uint32_t *pHeight);
|
||||
CRAMAPI void Cram_GetAtlasData(Cram_Context *context, Cram_AtlasData **pAtlasData);
|
||||
|
||||
CRAMAPI void Cram_Destroy(Cram_Context *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
316
src/cram.c
316
src/cram.c
|
@ -0,0 +1,316 @@
|
|||
/* Cram - A texture packing system in C
|
||||
*
|
||||
* Copyright (c) 2022 Evan Hemsley
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied warranty.
|
||||
* In no event will the authors be held liable for any damages arising from
|
||||
* the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software in a
|
||||
* product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* Evan "cosmonaut" Hemsley <evan@moonside.games>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cram.h"
|
||||
|
||||
#ifdef USE_SDL2
|
||||
|
||||
#define Cram_assert SDL_assert
|
||||
#define Cram_qsort SDL_qsort
|
||||
#define Cram_malloc SDL_malloc
|
||||
#define Cram_realloc SDL_realloc
|
||||
#define Cram_free SDL_free
|
||||
#define Cram_memcpy SDL_memcpy
|
||||
#define Cram_strdup SDL_strdup
|
||||
|
||||
#else
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <search.h>
|
||||
#include <string.h>
|
||||
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#define Cram_assert assert
|
||||
#define Cram_qsort qsort
|
||||
#define Cram_malloc malloc
|
||||
#define Cram_realloc realloc
|
||||
#define Cram_free free
|
||||
#define Cram_memcpy memcpy
|
||||
#define Cram_strdup strdup
|
||||
|
||||
#endif /* USE_SDL2 */
|
||||
|
||||
#define STBRP_ASSERT Cram_assert
|
||||
#define STBRP_SORT Cram_sort
|
||||
|
||||
#define STBRP_STATIC
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#include "stb_rect_pack.h"
|
||||
|
||||
#define STBI_ASSERT Cram_assert
|
||||
#define STBI_MALLOC Cram_malloc
|
||||
#define STBI_REALLOC Cram_realloc
|
||||
#define STBI_FREE Cram_free
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
#define INITIAL_DATA_CAPACITY 8
|
||||
|
||||
/* Structures */
|
||||
|
||||
typedef struct Cram_ImageRect
|
||||
{
|
||||
const char *name;
|
||||
uint32_t offsetX;
|
||||
uint32_t offsetY;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint8_t *pixels;
|
||||
} Cram_ImageRect;
|
||||
|
||||
typedef struct Cram_Internal_Context
|
||||
{
|
||||
const char *name;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
|
||||
uint32_t padding;
|
||||
uint8_t trim;
|
||||
|
||||
uint8_t *pixels;
|
||||
|
||||
Cram_ImageRect *imageRects;
|
||||
uint32_t imageRectCount;
|
||||
uint32_t imageRectCapacity;
|
||||
|
||||
Cram_AtlasData *atlasData;
|
||||
} Cram_Internal_Context;
|
||||
|
||||
/* API functions */
|
||||
|
||||
uint32_t Wellspring_LinkedVersion(void)
|
||||
{
|
||||
return WELLSPRING_COMPILED_VERSION;
|
||||
}
|
||||
|
||||
Cram_Context* Cram_Init(Cram_ContextCreateInfo *createInfo)
|
||||
{
|
||||
Cram_Internal_Context *context = Cram_malloc(sizeof(Cram_Internal_Context));
|
||||
|
||||
context->name = Cram_strdup(createInfo->name);
|
||||
|
||||
context->width = createInfo->maxDimension;
|
||||
context->height = createInfo->maxDimension;
|
||||
|
||||
context->padding = createInfo->padding;
|
||||
context->trim = createInfo->trim;
|
||||
|
||||
context->imageRects = Cram_malloc(INITIAL_DATA_CAPACITY * sizeof(Cram_ImageRect));
|
||||
context->imageRectCapacity = INITIAL_DATA_CAPACITY;
|
||||
context->imageRectCount = 0;
|
||||
|
||||
context->atlasData = Cram_malloc(sizeof(Cram_AtlasData));
|
||||
|
||||
context->pixels = NULL;
|
||||
|
||||
return (Cram_Context*) context;
|
||||
}
|
||||
|
||||
static inline uint32_t GetPixelIndex(uint32_t i, uint32_t j, uint32_t width)
|
||||
{
|
||||
return (i + j * width) * 4;
|
||||
}
|
||||
|
||||
void Cram_AddFile(Cram_Context *context, const char *path)
|
||||
{
|
||||
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
|
||||
Cram_ImageRect *imageRect;
|
||||
uint8_t *pixels;
|
||||
int32_t leftTrim, topTrim, rightTrim, bottomTrim;
|
||||
int32_t width, height, numChannels;
|
||||
uint32_t pixelIndex, pixelOffset;
|
||||
uint8_t allClear;
|
||||
int32_t i;
|
||||
|
||||
if (internalContext->imageRectCapacity == internalContext->imageRectCount)
|
||||
{
|
||||
internalContext->imageRectCapacity *= 2;
|
||||
internalContext->imageRects = Cram_realloc(internalContext->imageRects, internalContext->imageRectCapacity * sizeof(Cram_ImageRect));
|
||||
}
|
||||
|
||||
imageRect = &internalContext->imageRects[internalContext->imageRectCount];
|
||||
|
||||
imageRect->name = Cram_Internal_GetTrimmedPath();
|
||||
|
||||
pixels = stbi_load_from_file(
|
||||
path,
|
||||
&width,
|
||||
&height,
|
||||
&numChannels,
|
||||
STBI_rgb_alpha
|
||||
);
|
||||
|
||||
if (internalContext->trim)
|
||||
{
|
||||
/* Check for trim */
|
||||
allClear = 1;
|
||||
topTrim = -1;
|
||||
|
||||
while (allClear)
|
||||
{
|
||||
topTrim += 1;
|
||||
|
||||
for (i = 0; i < width; i += 1)
|
||||
{
|
||||
pixelIndex = GetPixelIndex(i, topTrim, width);
|
||||
|
||||
/* alpha check */
|
||||
if (pixels[pixelIndex + 3] > 0)
|
||||
{
|
||||
allClear = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allClear = 1;
|
||||
leftTrim = -1;
|
||||
|
||||
while (allClear)
|
||||
{
|
||||
leftTrim += 1;
|
||||
|
||||
for (i = topTrim; i < height; i += 1)
|
||||
{
|
||||
pixelIndex = GetPixelIndex(leftTrim, i, width);
|
||||
|
||||
if (pixels[pixelIndex + 3] > 0)
|
||||
{
|
||||
allClear = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allClear = 1;
|
||||
bottomTrim = -1;
|
||||
|
||||
while (allClear)
|
||||
{
|
||||
bottomTrim += 1;
|
||||
|
||||
for (i = width - 1; i >= leftTrim; i -= 1)
|
||||
{
|
||||
pixelIndex = GetPixelIndex(i, bottomTrim, width);
|
||||
|
||||
if (pixels[pixelIndex + 3] > 0)
|
||||
{
|
||||
allClear = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allClear = 1;
|
||||
rightTrim = -1;
|
||||
|
||||
while (allClear)
|
||||
{
|
||||
rightTrim += 1;
|
||||
|
||||
for (i = height - 1; i >= topTrim; i -= 1)
|
||||
{
|
||||
pixelIndex = GetPixelIndex(rightTrim, i, width);
|
||||
|
||||
if (pixels[pixelIndex + 3] > 0)
|
||||
{
|
||||
allClear = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imageRect->offsetX = leftTrim;
|
||||
imageRect->offsetY = topTrim;
|
||||
imageRect->width = width - rightTrim;
|
||||
imageRect->height = height - bottomTrim;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageRect->offsetX = 0;
|
||||
imageRect->offsetY = 0;
|
||||
imageRect->width = width;
|
||||
imageRect->height = height;
|
||||
}
|
||||
/* copy */
|
||||
imageRect->pixels = Cram_malloc(imageRect->width * imageRect->height * 4);
|
||||
|
||||
pixelOffset = GetPixelIndex(imageRect->offsetX, imageRect->offsetY, width);
|
||||
Cram_memcpy(imageRect->pixels, pixels + pixelOffset, (width * height * 4) - pixelOffset);
|
||||
|
||||
stbi_image_free(pixels);
|
||||
|
||||
internalContext->imageRectCount += 1;
|
||||
}
|
||||
|
||||
void Cram_AddFolder(Cram_Context *context, const char *path)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Cram_Pack(Cram_Context *context)
|
||||
{
|
||||
stbrp_context rectPackContext;
|
||||
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
|
||||
uint32_t numNodes = internalContext->width;
|
||||
stbrp_node *nodes = Cram_malloc(sizeof(stbrp_node*) * numNodes);
|
||||
|
||||
stbrp_init_target(&rectPackContext, internalContext->width, internalContext->height, nodes, numNodes);
|
||||
|
||||
/* TODO: pack rects */
|
||||
}
|
||||
|
||||
void Cram_GetPixelData(Cram_Context *context, uint8_t **pPixels, uint32_t *pWidth, uint32_t *pHeight)
|
||||
{
|
||||
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
|
||||
*pPixels = internalContext->pixels;
|
||||
*pWidth = internalContext->width;
|
||||
*pHeight = internalContext->height;
|
||||
}
|
||||
|
||||
void Cram_GetAtlasData(Cram_Context *context, Cram_AtlasData **pAtlasData)
|
||||
{
|
||||
*pAtlasData = ((Cram_Internal_Context*) context)->atlasData;
|
||||
}
|
||||
|
||||
void Cram_Destroy(Cram_Context *context)
|
||||
{
|
||||
Cram_Internal_Context *internalContext = (Cram_Internal_Context*) context;
|
||||
|
||||
if (internalContext->pixels != NULL)
|
||||
{
|
||||
Cram_free(internalContext);
|
||||
}
|
||||
|
||||
Cram_free(internalContext->imageRects);
|
||||
Cram_free(internalContext->atlasData);
|
||||
Cram_free(internalContext);
|
||||
}
|
Loading…
Reference in New Issue