Rudimentary font rasterisation at runtime with STB
This commit is contained in:
parent
76d6dfcf2f
commit
e03d3fd14a
@ -2,6 +2,10 @@
|
|||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include <STB/stb_image.h>
|
#include <STB/stb_image.h>
|
||||||
|
|
||||||
|
#define SBTT_STATIC
|
||||||
|
#define STB_TRUETYPE_IMPLEMENTATION
|
||||||
|
#include <STB/stb_truetype.h>
|
||||||
|
|
||||||
#include "Dengine/Platform.h"
|
#include "Dengine/Platform.h"
|
||||||
#include "Dengine/AssetManager.h"
|
#include "Dengine/AssetManager.h"
|
||||||
|
|
||||||
@ -56,7 +60,7 @@ Shader *asset_getShader(const enum ShaderList type)
|
|||||||
|
|
||||||
INTERNAL GLuint createShaderFromPath(const char *const path, GLuint shadertype)
|
INTERNAL GLuint createShaderFromPath(const char *const path, GLuint shadertype)
|
||||||
{
|
{
|
||||||
PlatformFileReadResult file = {0};
|
PlatformFileRead file = {0};
|
||||||
|
|
||||||
i32 status = platform_readFileToBuffer(path, &file);
|
i32 status = platform_readFileToBuffer(path, &file);
|
||||||
if (status)
|
if (status)
|
||||||
@ -77,7 +81,7 @@ INTERNAL GLuint createShaderFromPath(const char *const path, GLuint shadertype)
|
|||||||
printf("glCompileShader() failed: %s\n", infoLog);
|
printf("glCompileShader() failed: %s\n", infoLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_closeFileReadResult(&file);
|
platform_closeFileRead(&file);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -98,3 +102,178 @@ const i32 asset_loadShaderFiles(const char *const vertexPath,
|
|||||||
assetManager.shaders[type] = shader;
|
assetManager.shaders[type] = shader;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const i32 asset_loadTTFont(const char *filePath)
|
||||||
|
{
|
||||||
|
PlatformFileRead fontFileRead = {0};
|
||||||
|
platform_readFileToBuffer(filePath, &fontFileRead);
|
||||||
|
|
||||||
|
stbtt_fontinfo fontInfo = {0};
|
||||||
|
stbtt_InitFont(&fontInfo, fontFileRead.buffer,
|
||||||
|
stbtt_GetFontOffsetForIndex(fontFileRead.buffer, 0));
|
||||||
|
|
||||||
|
const v2i codepointRange = V2i(32, 127);
|
||||||
|
const i32 numGlyphs = codepointRange.y - codepointRange.x;
|
||||||
|
|
||||||
|
i32 glyphIndex = 0;
|
||||||
|
GlyphBitmap *glyphBitmaps =
|
||||||
|
CAST(GlyphBitmap *) calloc(numGlyphs, sizeof(GlyphBitmap));
|
||||||
|
v2i largestGlyphDimension = V2i(0, 0);
|
||||||
|
|
||||||
|
f32 targetFontHeight = 64.0f;
|
||||||
|
f32 scaleY = stbtt_ScaleForPixelHeight(&fontInfo, targetFontHeight);
|
||||||
|
|
||||||
|
/* Use STB_TrueType to generate a series of bitmap characters */
|
||||||
|
for (i32 codepoint = codepointRange.x; codepoint < codepointRange.y;
|
||||||
|
codepoint++)
|
||||||
|
{
|
||||||
|
// NOTE(doyle): ScaleX if not specified, is then calculated based on the
|
||||||
|
// ScaleY component
|
||||||
|
i32 width, height, xOffset, yOffset;
|
||||||
|
u8 *monoBitmap =
|
||||||
|
stbtt_GetCodepointBitmap(&fontInfo, 0, scaleY, codepoint, &width,
|
||||||
|
&height, &xOffset, &yOffset);
|
||||||
|
|
||||||
|
u8 *source = monoBitmap;
|
||||||
|
u32 *colorBitmap = calloc(width * height, sizeof(u32));
|
||||||
|
u32 *dest = colorBitmap;
|
||||||
|
|
||||||
|
// NOTE(doyle): STB generates 1 byte per pixel bitmaps, we use 4bpp, so
|
||||||
|
// duplicate the alpha byte (essentially) for all RGBA components
|
||||||
|
for (i32 y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
for (i32 x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
u8 monoByte = *source++;
|
||||||
|
*dest++ = (monoByte << 24) | (monoByte << 16) |
|
||||||
|
(monoByte << 8) | (monoByte << 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stbtt_FreeBitmap(monoBitmap, NULL);
|
||||||
|
glyphBitmaps[glyphIndex].dimensions = V2i(width, height);
|
||||||
|
glyphBitmaps[glyphIndex++].pixels = colorBitmap;
|
||||||
|
|
||||||
|
if (height > largestGlyphDimension.h)
|
||||||
|
largestGlyphDimension.h = height;
|
||||||
|
if (width > largestGlyphDimension.w)
|
||||||
|
largestGlyphDimension.w = width;
|
||||||
|
|
||||||
|
#ifdef WT_DEBUG
|
||||||
|
if ((largestGlyphDimension.h - CAST(i32)targetFontHeight) >= 50)
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"asset_loadTTFont() warning: The loaded font file has a glyph "
|
||||||
|
"considerably larger than our target .. font packing is "
|
||||||
|
"unoptimal\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE(doyle): Use rasterised TTF bitmap-characters combine them all into
|
||||||
|
* one bitmap as an atlas. We determine how many glyphs we can fit per row
|
||||||
|
* by determining the largest glyph size we have. Rounding it to the nearest
|
||||||
|
* multiple of 2 and dividing by our target texture size.
|
||||||
|
*
|
||||||
|
* For the amount of glyphs we fit per row, we iterate through them and
|
||||||
|
* write each row of the glyph adjacent to the next until we finish writing
|
||||||
|
* all pixels for the glyphs, then move onto the next set of glyphs.
|
||||||
|
*/
|
||||||
|
if ((largestGlyphDimension.w & 1) == 1)
|
||||||
|
largestGlyphDimension.w += 1;
|
||||||
|
|
||||||
|
if ((largestGlyphDimension.h & 1) == 1)
|
||||||
|
largestGlyphDimension.h += 1;
|
||||||
|
|
||||||
|
i32 glyphsPerRow = MAX_TEXTURE_SIZE / largestGlyphDimension.w;
|
||||||
|
|
||||||
|
#ifdef WT_DEBUG
|
||||||
|
i32 glyphsPerCol = MAX_TEXTURE_SIZE / largestGlyphDimension.h;
|
||||||
|
if ((glyphsPerRow * glyphsPerCol) <= numGlyphs)
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"asset_loadTTFont() warning: The target font height creates a "
|
||||||
|
"glyph sheet that exceeds the available space!");
|
||||||
|
ASSERT(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
u32 *fontBitmap = (u32 *)calloc(
|
||||||
|
squared(TARGET_TEXTURE_SIZE) * TARGET_BYTES_PER_PIXEL, sizeof(u32));
|
||||||
|
i32 pitch = MAX_TEXTURE_SIZE * TARGET_BYTES_PER_PIXEL;
|
||||||
|
|
||||||
|
// Check value to determine when a row of glyphs is completely printed
|
||||||
|
i32 verticalPixelsBlitted = 0;
|
||||||
|
|
||||||
|
i32 startingGlyphIndex = 0;
|
||||||
|
i32 glyphsRemaining = numGlyphs;
|
||||||
|
i32 glyphsOnCurrRow = glyphsPerRow;
|
||||||
|
|
||||||
|
for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++)
|
||||||
|
{
|
||||||
|
u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE);
|
||||||
|
for (i32 glyphIndex = 0; glyphIndex < glyphsOnCurrRow;
|
||||||
|
glyphIndex++)
|
||||||
|
{
|
||||||
|
i32 activeGlyphIndex = startingGlyphIndex + glyphIndex;
|
||||||
|
|
||||||
|
GlyphBitmap activeGlyph = glyphBitmaps[activeGlyphIndex];
|
||||||
|
i32 numPixelsToPad = largestGlyphDimension.w;
|
||||||
|
|
||||||
|
/* Copy over exactly one row of pixels */
|
||||||
|
if (verticalPixelsBlitted < activeGlyph.dimensions.h)
|
||||||
|
{
|
||||||
|
const i32 srcPitch =
|
||||||
|
activeGlyph.dimensions.w * verticalPixelsBlitted;
|
||||||
|
const u32 *src = activeGlyph.pixels + srcPitch;
|
||||||
|
|
||||||
|
const i32 numPixelsToCopy = activeGlyph.dimensions.w;
|
||||||
|
|
||||||
|
for (i32 count = 0; count < numPixelsToCopy; count++)
|
||||||
|
*destRow++ = *src++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE(doyle): If the glyph is smaller than largest glyph
|
||||||
|
* available size, don't advance src pointer any further
|
||||||
|
* (NULL/mixes up rows), instead just advance the final bitmap
|
||||||
|
* pointer by the remaining distance
|
||||||
|
*/
|
||||||
|
numPixelsToPad =
|
||||||
|
largestGlyphDimension.w - activeGlyph.dimensions.w;
|
||||||
|
}
|
||||||
|
destRow += numPixelsToPad;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A row of glyphs has been fully formed on the atlas */
|
||||||
|
if (verticalPixelsBlitted++ >= largestGlyphDimension.h)
|
||||||
|
{
|
||||||
|
verticalPixelsBlitted = 0;
|
||||||
|
startingGlyphIndex += glyphsPerRow;
|
||||||
|
|
||||||
|
glyphsRemaining -= glyphsPerRow;
|
||||||
|
|
||||||
|
if (glyphsRemaining <= 0)
|
||||||
|
break;
|
||||||
|
else if (glyphsRemaining <= glyphsPerRow)
|
||||||
|
{
|
||||||
|
// NOTE(doyle): This allows us to modify the glyph iterator to
|
||||||
|
// prevent over-running of the available glyphs
|
||||||
|
glyphsOnCurrRow = glyphsRemaining;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture tex =
|
||||||
|
genTexture(MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4, (u8 *)fontBitmap);
|
||||||
|
assetManager.textures[texlist_font] = tex;
|
||||||
|
|
||||||
|
for (i32 i = 0; i < numGlyphs; i++)
|
||||||
|
free(glyphBitmaps[i].pixels);
|
||||||
|
|
||||||
|
free(glyphBitmaps);
|
||||||
|
platform_closeFileRead(&fontFileRead);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "Dengine/Platform.h"
|
#include "Dengine/Platform.h"
|
||||||
|
|
||||||
i32 platform_readFileToBuffer(const char *const filePath,
|
i32 platform_readFileToBuffer(const char *const filePath,
|
||||||
PlatformFileReadResult *file)
|
PlatformFileRead *file)
|
||||||
{
|
{
|
||||||
HANDLE fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ,
|
HANDLE fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ,
|
||||||
NULL, OPEN_ALWAYS, 0, NULL);
|
NULL, OPEN_ALWAYS, 0, NULL);
|
||||||
|
@ -2,23 +2,23 @@
|
|||||||
|
|
||||||
enum BytesPerPixel
|
enum BytesPerPixel
|
||||||
{
|
{
|
||||||
Greyscale = 1,
|
bytesPerPixel_Greyscale = 1,
|
||||||
GreyscaleAlpha = 2,
|
bytesPerPixel_GreyscaleAlpha = 2,
|
||||||
RGB = 3,
|
bytesPerPixel_RGB = 3,
|
||||||
RGBA = 4,
|
bytesPerPixel_RGBA = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL GLint getGLFormat(i32 bytesPerPixel, b32 srgb)
|
INTERNAL GLint getGLFormat(i32 bytesPerPixel, b32 srgb)
|
||||||
{
|
{
|
||||||
switch (bytesPerPixel)
|
switch (bytesPerPixel)
|
||||||
{
|
{
|
||||||
case Greyscale:
|
case bytesPerPixel_Greyscale:
|
||||||
return GL_LUMINANCE;
|
return GL_LUMINANCE;
|
||||||
case GreyscaleAlpha:
|
case bytesPerPixel_GreyscaleAlpha:
|
||||||
return GL_LUMINANCE_ALPHA;
|
return GL_LUMINANCE_ALPHA;
|
||||||
case RGB:
|
case bytesPerPixel_RGB:
|
||||||
return (srgb ? GL_SRGB : GL_RGB);
|
return (srgb ? GL_SRGB : GL_RGB);
|
||||||
case RGBA:
|
case bytesPerPixel_RGBA:
|
||||||
return (srgb ? GL_SRGB_ALPHA : GL_RGBA);
|
return (srgb ? GL_SRGB_ALPHA : GL_RGBA);
|
||||||
default:
|
default:
|
||||||
// TODO(doyle): Invalid
|
// TODO(doyle): Invalid
|
||||||
@ -45,13 +45,14 @@ Texture genTexture(const GLuint width, const GLuint height,
|
|||||||
glGenTextures(1, &tex.id);
|
glGenTextures(1, &tex.id);
|
||||||
glCheckError();
|
glCheckError();
|
||||||
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex.id);
|
glBindTexture(GL_TEXTURE_2D, tex.id);
|
||||||
glCheckError();
|
glCheckError();
|
||||||
|
|
||||||
/* Load image into texture */
|
/* Load image into texture */
|
||||||
// TODO(doyle) Figure out the gl format
|
// TODO(doyle) Figure out the gl format
|
||||||
tex.imageFormat = getGLFormat(bytesPerPixel, FALSE);
|
tex.imageFormat = getGLFormat(bytesPerPixel, FALSE);
|
||||||
|
ASSERT(tex.imageFormat == GL_RGBA);
|
||||||
|
|
||||||
glCheckError();
|
glCheckError();
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, tex.internalFormat, tex.width, tex.height, 0,
|
glTexImage2D(GL_TEXTURE_2D, 0, tex.internalFormat, tex.width, tex.height, 0,
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
//choose to load assets outside of WorldTraveller!
|
//choose to load assets outside of WorldTraveller!
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void updateBufferObject(Renderer *const renderer, RenderQuad *const quads,
|
INTERNAL void updateBufferObject(Renderer *const renderer,
|
||||||
const i32 numQuads)
|
RenderQuad *const quads, const i32 numQuads)
|
||||||
{
|
{
|
||||||
// TODO(doyle): We assume that vbo and vao are assigned
|
// TODO(doyle): We assume that vbo and vao are assigned
|
||||||
const i32 numVertexesInQuad = 4;
|
const i32 numVertexesInQuad = 4;
|
||||||
@ -34,6 +34,8 @@ void worldTraveller_gameInit(GameState *state)
|
|||||||
|
|
||||||
asset_loadShaderFiles("data/shaders/sprite.vert.glsl",
|
asset_loadShaderFiles("data/shaders/sprite.vert.glsl",
|
||||||
"data/shaders/sprite.frag.glsl", shaderlist_sprite);
|
"data/shaders/sprite.frag.glsl", shaderlist_sprite);
|
||||||
|
|
||||||
|
asset_loadTTFont("C:/Windows/Fonts/Arial.ttf");
|
||||||
glCheckError();
|
glCheckError();
|
||||||
|
|
||||||
state->state = state_active;
|
state->state = state_active;
|
||||||
@ -334,6 +336,14 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
|||||||
renderer_object(&state->renderer, V2(0.0f, 0.0f), screenSize, 0.0f,
|
renderer_object(&state->renderer, V2(0.0f, 0.0f), screenSize, 0.0f,
|
||||||
V3(0, 0, 0), worldTex);
|
V3(0, 0, 0), worldTex);
|
||||||
|
|
||||||
|
Texture *font = asset_getTexture(texlist_font);
|
||||||
|
v4 fontTexRect = V4(0.0f, 1.0f, 1.0f, 0.0);
|
||||||
|
RenderQuad fontQuad = renderer_createDefaultQuad(fontTexRect);
|
||||||
|
updateBufferObject(&state->renderer, &fontQuad, 1);
|
||||||
|
renderer_object(&state->renderer, V2(128.0f, 128.0f),
|
||||||
|
V2(CAST(f32)font->width, CAST(f32)font->height), 0.0f,
|
||||||
|
V3(0, 0, 0), font);
|
||||||
|
|
||||||
// NOTE(doyle): Factor to normalise sprite sheet rect coords to -1, 1
|
// NOTE(doyle): Factor to normalise sprite sheet rect coords to -1, 1
|
||||||
Entity *const hero = &state->entityList[state->heroIndex];
|
Entity *const hero = &state->entityList[state->heroIndex];
|
||||||
texNdcFactor = 1.0f / CAST(f32) hero->tex->width;
|
texNdcFactor = 1.0f / CAST(f32) hero->tex->width;
|
||||||
|
@ -35,7 +35,7 @@ int main()
|
|||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
|
||||||
|
|
||||||
v2 windowSize = V2(1280.0f, 720.0f);
|
v2 windowSize = V2(1600.0f, 900.0f);
|
||||||
|
|
||||||
GLFWwindow *window = glfwCreateWindow(
|
GLFWwindow *window = glfwCreateWindow(
|
||||||
CAST(i32) windowSize.x, CAST(i32) windowSize.y, "Dengine", NULL, NULL);
|
CAST(i32) windowSize.x, CAST(i32) windowSize.y, "Dengine", NULL, NULL);
|
||||||
|
@ -4,10 +4,13 @@
|
|||||||
#include "Dengine/Shader.h"
|
#include "Dengine/Shader.h"
|
||||||
#include "Dengine/Texture.h"
|
#include "Dengine/Texture.h"
|
||||||
|
|
||||||
|
#define MAX_TEXTURE_SIZE 1024
|
||||||
|
|
||||||
enum TexList
|
enum TexList
|
||||||
{
|
{
|
||||||
texlist_hero,
|
texlist_hero,
|
||||||
texlist_terrain,
|
texlist_terrain,
|
||||||
|
texlist_font,
|
||||||
texlist_count,
|
texlist_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -30,12 +33,19 @@ typedef struct TexAtlas
|
|||||||
|
|
||||||
} TexAtlas;
|
} TexAtlas;
|
||||||
|
|
||||||
|
typedef struct GlyphBitmap
|
||||||
|
{
|
||||||
|
v2i dimensions;
|
||||||
|
u32 *pixels;
|
||||||
|
} GlyphBitmap;
|
||||||
|
|
||||||
// TODO(doyle): Switch to hash based lookup
|
// TODO(doyle): Switch to hash based lookup
|
||||||
typedef struct AssetManager
|
typedef struct AssetManager
|
||||||
{
|
{
|
||||||
Texture textures[256];
|
Texture textures[256];
|
||||||
TexAtlas texAtlas[256];
|
TexAtlas texAtlas[256];
|
||||||
Shader shaders[256];
|
Shader shaders[256];
|
||||||
|
Texture font;
|
||||||
} AssetManager;
|
} AssetManager;
|
||||||
|
|
||||||
extern AssetManager assetManager;
|
extern AssetManager assetManager;
|
||||||
@ -52,4 +62,5 @@ const i32 asset_loadShaderFiles(const char *const vertexPath,
|
|||||||
const char *const fragmentPath,
|
const char *const fragmentPath,
|
||||||
const enum ShaderList type);
|
const enum ShaderList type);
|
||||||
|
|
||||||
|
const i32 asset_loadTTFont(const char *filePath);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define WT_DEBUG
|
||||||
|
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint32_t u32;
|
typedef uint32_t u32;
|
||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
|
@ -9,6 +9,13 @@
|
|||||||
#define absolute(x) ((x) > 0 ? (x) : -(x))
|
#define absolute(x) ((x) > 0 ? (x) : -(x))
|
||||||
|
|
||||||
/* VECTORS */
|
/* VECTORS */
|
||||||
|
typedef union v2i
|
||||||
|
{
|
||||||
|
struct { i32 x, y; };
|
||||||
|
struct { i32 w, h; };
|
||||||
|
i32 e[2];
|
||||||
|
} v2i;
|
||||||
|
|
||||||
typedef union v2
|
typedef union v2
|
||||||
{
|
{
|
||||||
struct { f32 x, y; };
|
struct { f32 x, y; };
|
||||||
@ -30,6 +37,11 @@ typedef union v4
|
|||||||
f32 e[4];
|
f32 e[4];
|
||||||
} v4;
|
} v4;
|
||||||
|
|
||||||
|
INTERNAL inline v2i V2i(const i32 x, const i32 y)
|
||||||
|
{
|
||||||
|
v2i result = {x, y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
INTERNAL inline v2 V2(const f32 x, const f32 y)
|
INTERNAL inline v2 V2(const f32 x, const f32 y)
|
||||||
{
|
{
|
||||||
v2 result = {x, y};
|
v2 result = {x, y};
|
||||||
@ -63,7 +75,7 @@ INTERNAL inline v4 V4(const f32 x, const f32 y, const f32 z, const f32 w)
|
|||||||
This is repeated for v3 and v4 for the basic math operations
|
This is repeated for v3 and v4 for the basic math operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEFINE_VECTOR_MATH(num) \
|
#define DEFINE_VECTOR_FLOAT_MATH(num) \
|
||||||
INTERNAL inline v##num v##num##_add(const v##num a, const v##num b) \
|
INTERNAL inline v##num v##num##_add(const v##num a, const v##num b) \
|
||||||
{ \
|
{ \
|
||||||
v##num result; \
|
v##num result; \
|
||||||
@ -109,9 +121,19 @@ INTERNAL inline b32 v##num##_equals(const v##num a, const v##num b) \
|
|||||||
return result; \
|
return result; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
DEFINE_VECTOR_MATH(2);
|
DEFINE_VECTOR_FLOAT_MATH(2);
|
||||||
DEFINE_VECTOR_MATH(3);
|
DEFINE_VECTOR_FLOAT_MATH(3);
|
||||||
DEFINE_VECTOR_MATH(4);
|
DEFINE_VECTOR_FLOAT_MATH(4);
|
||||||
|
|
||||||
|
#define DEFINE_VECTOR_INT_MATH(num) \
|
||||||
|
INTERNAL inline v##num##i v##num##i_add(const v##num##i a, const v##num##i b) \
|
||||||
|
{ \
|
||||||
|
v##num##i result; \
|
||||||
|
for (i32 i = 0; i < ##num; i++) { result.e[i] = a.e[i] + b.e[i]; } \
|
||||||
|
return result; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
DEFINE_VECTOR_INT_MATH(2);
|
||||||
|
|
||||||
INTERNAL inline v3 v3_cross(const v3 a, const v3 b)
|
INTERNAL inline v3 v3_cross(const v3 a, const v3 b)
|
||||||
{
|
{
|
||||||
|
@ -10,12 +10,12 @@ typedef struct
|
|||||||
{
|
{
|
||||||
void *buffer;
|
void *buffer;
|
||||||
i32 size;
|
i32 size;
|
||||||
} PlatformFileReadResult;
|
} PlatformFileRead;
|
||||||
|
|
||||||
i32 platform_readFileToBuffer(const char *const filePath,
|
i32 platform_readFileToBuffer(const char *const filePath,
|
||||||
PlatformFileReadResult *file);
|
PlatformFileRead *file);
|
||||||
|
|
||||||
inline void platform_closeFileReadResult(PlatformFileReadResult *file)
|
inline void platform_closeFileRead(PlatformFileRead *file)
|
||||||
{
|
{
|
||||||
if (file->buffer)
|
if (file->buffer)
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
#include "Dengine/Common.h"
|
#include "Dengine/Common.h"
|
||||||
#include "Dengine/OpenGL.h"
|
#include "Dengine/OpenGL.h"
|
||||||
|
|
||||||
|
#define TARGET_TEXTURE_SIZE 1024
|
||||||
|
#define TARGET_BYTES_PER_PIXEL 4
|
||||||
|
|
||||||
typedef struct Texture
|
typedef struct Texture
|
||||||
{
|
{
|
||||||
// Holds the ID of the texture object, used for all texture operations to
|
// Holds the ID of the texture object, used for all texture operations to
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef WORLDTRAVELLER_GAME_H
|
#ifndef WORLDTRAVELLER_GAME_H
|
||||||
#define WORLDTRAVELLER_GAME_H
|
#define WORLDTRAVELLER_GAME_H
|
||||||
|
|
||||||
#include <Dengine/Common.h>
|
#include "Dengine/Common.h"
|
||||||
#include <Dengine/Entity.h>
|
#include "Dengine/Entity.h"
|
||||||
#include <Dengine/Renderer.h>
|
#include "Dengine/Renderer.h"
|
||||||
|
|
||||||
#define NUM_KEYS 1024
|
#define NUM_KEYS 1024
|
||||||
#define METERS_TO_PIXEL 100
|
#define METERS_TO_PIXEL 100
|
||||||
|
Loading…
Reference in New Issue
Block a user