mirror of
https://github.com/nicbarker/clay.git
synced 2025-04-22 06:08:03 +00:00
1566 lines
55 KiB
C
1566 lines
55 KiB
C
/*
|
|
*
|
|
* Copyright (c) 2021-24 ColleagueRiley ColleagueRiley@gmail.com
|
|
*
|
|
* 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.
|
|
*
|
|
*
|
|
*/
|
|
|
|
/*
|
|
define args
|
|
(MAKE SURE RSGL_IMPLEMENTATION is in exactly one header or you use -DRSGL_IMPLEMENTATION)
|
|
#define RSGL_IMPLEMENTATION - makes it so source code is included with header
|
|
|
|
#define RSGL_NO_TEXT - do not include text rendering functions
|
|
#define RSGL_NO_SAVE_IMAGE - do not save/load images (don't use RSGL_drawImage if you use this),
|
|
RSGL_drawImage saves the file name + texture so it can load it
|
|
when you ask for it later. This disables that
|
|
#define RSGL_INIT_FONTS [number of fonts] - set how much room should be pre-allocated for fonts by fontstash
|
|
this avoids performance issues related to RSGL_REALLOC
|
|
RSGL_INIT_FONTS = 4 by default
|
|
#define RSGL_INIT_IMAGES [number of fonts] - set how much room should be pre-allocated for images by RSGL
|
|
this avoids performance issues related to RSGL_REALLOC
|
|
RSGL_INIT_IMAGES = 20 by default
|
|
#define RSGL_NEW_IMAGES [number of fonts] - set how much room should be RSGL_REALLOCated at a time for images by RSGL
|
|
this avoids performance issues related to RSGL_REALLOC
|
|
RSGL_NEW_IMAGES 10 by default
|
|
|
|
#define RSGL_MAX_BATCHES [number of batches] - set max number of batches to be allocated
|
|
#define RSGL_MAX_VERTS [number of verts] - set max number of verts to be allocated (global, not per batch)
|
|
|
|
#define RSGL_RENDER_LEGACY - use legacy rendering (ex. opengl) functions
|
|
|
|
#define RSGL_NO_STB_IMAGE - do not include stb_image.h (& don't define image loading funcs)
|
|
#define RSGL_NO_STB_IMAGE_IMP - declare stb funcs but don't define
|
|
#define RSGL_NO_DEPS_FOLDER - Do not use '/deps' for the deps includes, use "./"
|
|
*/
|
|
#ifndef RSGL_INIT_FONTS
|
|
#define RSGL_INIT_FONTS 4
|
|
#endif
|
|
#ifndef RSGL_NEW_FONTS
|
|
#define RSGL_NEW_FONTS 2
|
|
#endif
|
|
#ifndef RSGL_INIT_IMAGES
|
|
#define RSGL_INIT_IMAGES 20
|
|
#endif
|
|
#ifndef RSGL_NEW_IMAGES
|
|
#define RSGL_NEW_IMAGES 10
|
|
#endif
|
|
#ifndef RSGL_MAX_BATCHES
|
|
#define RSGL_MAX_BATCHES 2028
|
|
#endif
|
|
#ifndef RSGL_MAX_VERTS
|
|
#define RSGL_MAX_VERTS 8192
|
|
#endif
|
|
|
|
#ifndef RSGL_MALLOC
|
|
#include <stdlib.h>
|
|
#define RSGL_MALLOC malloc
|
|
#define RSGL_REALLOC realloc
|
|
#define RSGL_FREE free
|
|
#endif
|
|
|
|
#ifndef RSGL_UNUSED
|
|
#define RSGL_UNUSED(x) (void) (x);
|
|
#endif
|
|
|
|
/*
|
|
RSGL basicDraw types
|
|
*/
|
|
|
|
#ifndef RSGL_QUADS
|
|
#define RSGL_POINTS 0x0000
|
|
#define RSGL_LINES 0x0001
|
|
#define RSGL_LINE_LOOP 0x0002
|
|
#define RSGL_LINE_STRIP 0x0003
|
|
#define RSGL_TRIANGLES 0x0004
|
|
#define RSGL_TRIANGLE_STRIP 0x0005
|
|
#define RSGL_TRIANGLE_FAN 0x0006
|
|
#define RSGL_QUADS 0x0007
|
|
|
|
/* these are to ensure GL_DEPTH_TEST is disabled when they're being rendered */
|
|
#define RSGL_POINTS_2D 0x0010
|
|
#define RSGL_LINES_2D 0x0011
|
|
#define RSGL_LINE_LOOP_2D 0x0012
|
|
#define RSGL_LINE_STRIP_2D 0x0013
|
|
#define RSGL_TRIANGLES_2D 0x0014
|
|
#define RSGL_TRIANGLE_STRIP_2D 0x0015
|
|
#define RSGL_TRIANGLE_FAN_2D 0x0016
|
|
|
|
#define RSGL_TRIANGLES_2D_BLEND 0x0114
|
|
#endif
|
|
|
|
#ifndef RSGL_H
|
|
#define RSGL_H
|
|
#ifndef RSGLDEF
|
|
#ifdef __APPLE__
|
|
#define RSGLDEF extern inline
|
|
#else
|
|
#define RSGLDEF inline
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(u8)
|
|
#define u8 u8
|
|
#if defined(_MSC_VER) || defined(__SYMBIAN32__)
|
|
typedef unsigned char u8;
|
|
typedef signed char i8;
|
|
typedef unsigned short u16;
|
|
typedef signed short i16;
|
|
typedef unsigned int u32;
|
|
typedef signed int i32;
|
|
typedef unsigned long u64;
|
|
typedef signed long i64;
|
|
#else
|
|
#include <stdint.h>
|
|
|
|
typedef uint8_t u8;
|
|
typedef int8_t i8;
|
|
typedef uint16_t u16;
|
|
typedef int16_t i16;
|
|
typedef uint32_t u32;
|
|
typedef int32_t i32;
|
|
typedef uint64_t u64;
|
|
typedef int64_t i64;
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(b8)
|
|
#define b8 b8
|
|
typedef u8 b8;
|
|
typedef u32 b32;
|
|
#endif
|
|
|
|
#ifndef RSGL_texture
|
|
#define RSGL_texture size_t
|
|
#endif
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
|
|
#define RSGL_between(x, lower, upper) (((lower) <= (x)) && ((x) <= (upper)))
|
|
#define RSGL_ENUM(type, name) type name; enum
|
|
|
|
/*
|
|
*******
|
|
RSGL_[shape]
|
|
*******
|
|
*/
|
|
|
|
#ifndef RSGL_rect
|
|
typedef struct RSGL_rect {
|
|
i32 x, y, w, h;
|
|
} RSGL_rect;
|
|
#endif
|
|
#define RSGL_RECT(x, y, w, h) (RSGL_rect){x, y, w, h}
|
|
|
|
typedef struct RSGL_rectF { float x, y, w, h; } RSGL_rectF;
|
|
#define RSGL_RECTF(x, y, w, h) (RSGL_rectF){x, y, w, h}
|
|
|
|
#ifndef RSGL_point
|
|
typedef struct RSGL_point {
|
|
i32 x, y;
|
|
} RSGL_point;
|
|
#endif
|
|
#define RSGL_POINT(x, y) (RSGL_point){x, y}
|
|
|
|
#ifndef RSGL_area
|
|
typedef struct RSGL_area {
|
|
u32 w, h;
|
|
} RSGL_area;
|
|
#endif
|
|
#define RSGL_AREA(w, h) (RSGL_area){w, h}
|
|
|
|
/*
|
|
*******
|
|
RSGL_[shape]
|
|
*******
|
|
*/
|
|
|
|
typedef struct RSGL_pointF { float x, y; } RSGL_pointF;
|
|
#define RSGL_POINTF(x, y) (RSGL_pointF){x, y}
|
|
|
|
typedef struct RSGL_point3D {
|
|
i32 x, y, z;
|
|
} RSGL_point3D;
|
|
|
|
typedef struct RSGL_point3DF { float x, y, z; } RSGL_point3DF;
|
|
|
|
#define RSGL_POINT3D(x, y, z) (RSGL_point3D){x, y, z}
|
|
#define RSGL_POINT3DF(x, y, z) (RSGL_point3DF){x, y, z}
|
|
|
|
typedef struct RSGL_areaF { float w, h;} RSGL_areaF;
|
|
#define RSGL_AREAF(w, h) (RSGL_areaF){w, h}
|
|
|
|
typedef struct RSGL_circle {
|
|
i32 x, y, d;
|
|
} RSGL_circle;
|
|
#define RSGL_CIRCLE(x, y, d) (RSGL_circle){x, y, d}
|
|
|
|
typedef struct RSGL_circleF { float x, y, d; } RSGL_circleF;
|
|
#define RSGL_CIRCLEF(x, y, d) (RSGL_circleF){x, y, d}
|
|
|
|
typedef struct RSGL_triangle {
|
|
RSGL_point p1, p2, p3;
|
|
} RSGL_triangle;
|
|
#define RSGL_TRIANGLE(p1, p2, p3) (RSGL_triangle){p1, p2, p3}
|
|
|
|
typedef struct RSGL_triangleF { RSGL_pointF p1, p2, p3; } RSGL_triangleF;
|
|
#define RSGL_TRIANGLEF(p1, p2, p3) (RSGL_triangleF){p1, p2, p3}
|
|
|
|
#define RSGL_createTriangle(x1, y1, x2, y2, x3, y3) (RSGL_triangle){{x1, y1}, {x2, y2}, {x3, y3}}
|
|
#define RSGL_createTriangleF(x1, y1, x2, y2, x3, y3) (RSGL_triangleF){{x1, y1}, {x2, y2}, {x3, y3}}
|
|
|
|
typedef struct RSGL_cube {
|
|
i32 x, y, z, w, h, l;
|
|
} RSGL_cube;
|
|
#define RSGL_CUBE(x, y, z, w, h, l) (RSGL_cube){x, y, z, w, h, l}
|
|
|
|
typedef struct RSGL_cubeF { float x, y, z, w, h, l; } RSGL_cubeF;
|
|
#define RSGL_CUBEF(x, y, z, w, h, l) (RSGL_cubeF){x, y, z, w, h, l}
|
|
|
|
/*
|
|
the color stucture is in
|
|
ABGR by default for performance reasons
|
|
(converting color to hex for example)
|
|
*/
|
|
typedef struct RSGL_color {
|
|
u8 a, b, g, r;
|
|
} RSGL_color;
|
|
|
|
#define RSGL_RGBA(r, g, b, a) ((RSGL_color){(a), (b), (g), (r)})
|
|
#define RSGL_RGB(r, g, b) ((RSGL_color){255, (b), (g), (r)})
|
|
|
|
#define RSGL_COLOR_TO_HEX(color) ((u32)(color) & 0xFFFFFF00)
|
|
#define RSGL_RGB_TO_HEX(r, g, b, a) (RSGL_COLOR_TO_HEX(RSGL_RGBA(r, g, b, a)))
|
|
#define RSGL_RGBA_TO_HEX(r, g, b) (RSGL_COLOR_TO_HEX(RSGL_RGB(r, g, b, a)))
|
|
|
|
/* toggle the use of legacy OpenGL, on by default unless it fails to load */
|
|
RSGLDEF void RSGL_legacy(i32 legacy);
|
|
|
|
/*
|
|
*********************
|
|
RSGL_GRAPHICS_CONTEXT
|
|
*********************
|
|
*/
|
|
|
|
RSGLDEF void RSGL_init(
|
|
RSGL_area r, /* graphics context size */
|
|
void* loader /* opengl prozc address ex. wglProcAddress */
|
|
);
|
|
RSGLDEF void RSGL_updateSize(RSGL_area r);
|
|
RSGLDEF void RSGL_clear(RSGL_color c);
|
|
RSGLDEF void RSGL_free(void);
|
|
|
|
/*
|
|
*******
|
|
RSGL_draw
|
|
*******
|
|
*/
|
|
|
|
|
|
/*
|
|
RSGL_draw args
|
|
|
|
RSGL has internal args which control how RSGL draws certain things
|
|
by default these args clear after each RSGL_draw<whatever> call
|
|
|
|
but you can run RSGL_setClearArgs to enable or disable this behavior
|
|
you can also run RSGL_clearArgs to clear the args by hand
|
|
*/
|
|
/* RSGL_args */
|
|
typedef struct RSGL_drawArgs {
|
|
float* gradient; /* does not allocate any memory */
|
|
|
|
RSGL_texture texture;
|
|
u32 gradient_len;
|
|
|
|
RSGL_rect currentRect; /* size of current surface */
|
|
RSGL_point3D rotate;
|
|
|
|
bool fill;
|
|
RSGL_point3DF center;
|
|
float lineWidth;
|
|
i32 legacy;
|
|
u32 program;
|
|
} RSGL_drawArgs;
|
|
|
|
RSGLDEF void RSGL_rotate(RSGL_point3D rotate); /* apply rotation to drawing */
|
|
RSGLDEF void RSGL_setTexture(RSGL_texture texture); /* apply texture to drawing */
|
|
RSGLDEF void RSGL_setProgram(u32 program); /* use shader program for drawing */
|
|
RSGLDEF void RSGL_setGradient(
|
|
float* gradient, /* array of gradients */
|
|
size_t len /* length of array */
|
|
); /* apply gradient to drawing, based on color list*/
|
|
RSGLDEF void RSGL_fill(bool fill); /* toggle filling, if fill is false it runs RSGL_draw<whatever>_outline instead */
|
|
RSGLDEF void RSGL_center(RSGL_point3DF center); /* the center of the drawing (or shape), this is used for rotation */
|
|
|
|
/* args clear after a draw function by default, this toggles that */
|
|
RSGLDEF void RSGL_setClearArgs(bool clearArgs); /* toggles if args are cleared by default or not */
|
|
RSGLDEF void RSGL_clearArgs(void); /* clears the args */
|
|
|
|
/* calculate the align a smaller rect with larger rect */
|
|
typedef RSGL_ENUM(u8, RSGL_alignment) {
|
|
RSGL_ALIGN_NONE = (1 << 0),
|
|
/* horizontal */
|
|
RSGL_ALIGN_LEFT = (1 << 1),
|
|
RSGL_ALIGN_CENTER = (1 << 2),
|
|
RSGL_ALIGN_RIGHT = (1 << 3),
|
|
|
|
/* vertical */
|
|
RSGL_ALIGN_UP = (1 << 4),
|
|
RSGL_ALIGN_MIDDLE = (1 << 5),
|
|
RSGL_ALIGN_DOWN = (1 << 6),
|
|
|
|
RSGL_ALIGN_HORIZONTAL = RSGL_ALIGN_LEFT | RSGL_ALIGN_CENTER | RSGL_ALIGN_RIGHT,
|
|
RSGL_ALIGN_VERTICAL = RSGL_ALIGN_UP | RSGL_ALIGN_MIDDLE | RSGL_ALIGN_DOWN,
|
|
/* ex : alignment = (RSGL_ALIGN_LEFT | RSGL_ALIGN_MIDDLE) */
|
|
};
|
|
|
|
/* align smaller rect onto larger rect based on a given alignment */
|
|
RSGLDEF RSGL_rect RSGL_alignRect(RSGL_rect larger, RSGL_rect smaller, u16 alignment);
|
|
RSGLDEF RSGL_rectF RSGL_alignRectF(RSGL_rectF larger, RSGL_rectF smaller, u16 alignment);
|
|
|
|
#ifndef RSGL_GET_WORLD_X
|
|
#define RSGL_GET_WORLD_X(x) (float)(2.0f * (x) / RSGL_args.currentRect.w - 1.0f)
|
|
#define RSGL_GET_WORLD_Y(y) (float)(1.0f + -2.0f * (y) / RSGL_args.currentRect.h)
|
|
#define RSGL_GET_WORLD_Z(z) (float)(z)
|
|
#endif
|
|
|
|
#define RSGL_GET_MATRIX_X(x, y, z) (matrix.m[0] * x + matrix.m[4] * y + matrix.m[8] * z + matrix.m[12])
|
|
#define RSGL_GET_MATRIX_Y(x, y, z) (matrix.m[1] * x + matrix.m[5] * y + matrix.m[9] * z + matrix.m[13])
|
|
#define RSGL_GET_MATRIX_Z(x, y, z) (matrix.m[2] * x + matrix.m[6] * y + matrix.m[10] * z + matrix.m[14])
|
|
|
|
#define RSGL_GET_MATRIX_POINT(x, y, z) RSGL_GET_MATRIX_X(x, y, z), RSGL_GET_MATRIX_Y(x, y, z), RSGL_GET_MATRIX_Z(x, y, z)
|
|
#define RSGL_GET_WORLD_POINT(x, y, z) RSGL_GET_WORLD_X((x)), RSGL_GET_WORLD_Y((y)), RSGL_GET_WORLD_Z((z))
|
|
|
|
#define RSGL_GET_FINAL_POINT(x, y, z) RSGL_GET_MATRIX_POINT(RSGL_GET_WORLD_X((x)), RSGL_GET_WORLD_Y((y)), RSGL_GET_WORLD_Z((z)))
|
|
|
|
typedef struct RSGL_MATRIX {
|
|
float m[16];
|
|
} RSGL_MATRIX;
|
|
|
|
RSGLDEF RSGL_MATRIX RSGL_initDrawMatrix(RSGL_point3DF center);
|
|
|
|
/*
|
|
RSGL_basicDraw is a function used internally by RSGL, but you can use it yourself
|
|
RSGL_basicDraw batches a given set of points based on the data to be rendered
|
|
*/
|
|
RSGLDEF void RSGL_basicDraw(
|
|
u32 TYPE, /* type of shape, RSGL_QUADS, RSGL_TRIANGLES, RSGL_LINES, RSGL_QUADS_2D */
|
|
float* points, /* array of 3D points */
|
|
float* texPoints, /* array of 2D texture points (must be same length as points)*/
|
|
RSGL_color c, /* the color to draw the shape */
|
|
size_t len /* the length of the points array */
|
|
);
|
|
|
|
typedef struct RSGL_BATCH {
|
|
size_t start, len; /* when batch starts and it's length */
|
|
u32 type;
|
|
RSGL_texture tex;
|
|
float lineWidth;
|
|
} RSGL_BATCH; /* batch data type for rendering */
|
|
|
|
typedef struct RSGL_RENDER_INFO {
|
|
RSGL_BATCH* batches;
|
|
|
|
float* verts;
|
|
float* texCoords;
|
|
float* colors;
|
|
|
|
size_t len; /* number of batches*/
|
|
size_t vert_len; /* number of verts */
|
|
} RSGL_RENDER_INFO; /* render data */
|
|
|
|
/*
|
|
All of these functions are to be defined by the external render backend
|
|
*/
|
|
|
|
/* renders the current batches */
|
|
RSGLDEF void RSGL_renderBatch(RSGL_RENDER_INFO* info);
|
|
RSGLDEF void RSGL_renderInit(void* proc, RSGL_RENDER_INFO* info); /* init render backend */
|
|
RSGLDEF void RSGL_renderFree(void); /* free render backend */
|
|
RSGLDEF void RSGL_renderClear(float r, float g, float b, float a);
|
|
RSGLDEF void RSGL_renderViewport(i32 x, i32 y, i32 w, i32 h);
|
|
/* create a texture based on a given bitmap, this must be freed later using RSGL_deleteTexture or opengl*/
|
|
RSGLDEF RSGL_texture RSGL_renderCreateTexture(u8* bitmap, RSGL_area memsize, u8 channels);
|
|
/* updates an existing texture wiht a new bitmap */
|
|
RSGLDEF void RSGL_renderUpdateTexture(RSGL_texture texture, u8* bitmap, RSGL_area memsize, u8 channels);
|
|
/* delete a texture */
|
|
RSGLDEF void RSGL_renderDeleteTexture(RSGL_texture tex);
|
|
|
|
/* custom shader program */
|
|
typedef struct RSGL_programInfo {
|
|
u32 vShader, fShader, program;
|
|
} RSGL_programInfo;
|
|
|
|
RSGLDEF RSGL_programInfo RSGL_renderCreateProgram(const char* VShaderCode, const char* FShaderCode, char* posName, char* texName, char* colorName);
|
|
RSGLDEF void RSGL_renderDeleteProgram(RSGL_programInfo program);
|
|
RSGLDEF void RSGL_renderSetShaderValue(u32 program, char* var, float value[], u8 len);
|
|
|
|
/* these are RFont functions that also must be defined by the renderer
|
|
|
|
32 RFont_create_atlas(u32 atlasWidth, u32 atlasHeight);
|
|
void RFont_bitmap_to_atlas(RSGL_rsoft_texture atlas, u8* bitmap, float x, float y, float w, float h);
|
|
|
|
*/
|
|
|
|
/* RSGL translation */
|
|
RSGLDEF RSGL_MATRIX RSGL_matrixMultiply(float left[16], float right[16]);
|
|
RSGLDEF RSGL_MATRIX RSGL_rotatef(RSGL_MATRIX* matrix, float angle, float x, float y, float z);
|
|
RSGLDEF RSGL_MATRIX RSGL_translatef(RSGL_MATRIX* matrix, float x, float y, float z);
|
|
/* 2D shape drawing */
|
|
/* in the function names, F means float */
|
|
|
|
RSGLDEF void RSGL_drawPoint(RSGL_point p, RSGL_color c);
|
|
RSGLDEF void RSGL_drawPointF(RSGL_pointF p, RSGL_color c);
|
|
RSGLDEF void RSGL_plotLines(RSGL_pointF* lines, size_t points_count, u32 thickness, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawTriangle(RSGL_triangle t, RSGL_color c);
|
|
RSGLDEF void RSGL_drawTriangleF(RSGL_triangleF t, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawTriangleHyp(RSGL_pointF p, size_t angle, float hypotenuse, RSGL_color color);
|
|
|
|
RSGLDEF void RSGL_drawRect(RSGL_rect r, RSGL_color c);
|
|
RSGLDEF void RSGL_drawRectF(RSGL_rectF r, RSGL_color c);
|
|
|
|
|
|
RSGLDEF void RSGL_drawRoundRect(RSGL_rect r, RSGL_point rounding, RSGL_color c);
|
|
RSGLDEF void RSGL_drawRoundRectF(RSGL_rectF r, RSGL_point rounding, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawPolygon(RSGL_rect r, u32 sides, RSGL_color c);
|
|
RSGLDEF void RSGL_drawPolygonF(RSGL_rectF r, u32 sides, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawArc(RSGL_rect o, RSGL_point arc, RSGL_color color);
|
|
RSGLDEF void RSGL_drawArcF(RSGL_rectF o, RSGL_pointF arc, RSGL_color color);
|
|
|
|
RSGLDEF void RSGL_drawCircle(RSGL_circle c, RSGL_color color);
|
|
RSGLDEF void RSGL_drawCircleF(RSGL_circleF c, RSGL_color color);
|
|
|
|
RSGLDEF void RSGL_drawOval(RSGL_rect o, RSGL_color c);
|
|
RSGLDEF void RSGL_drawOvalF(RSGL_rectF o, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawLine(RSGL_point p1, RSGL_point p2, u32 thickness, RSGL_color c);
|
|
RSGLDEF void RSGL_drawLineF(RSGL_pointF p1, RSGL_pointF p2, u32 thickness, RSGL_color c);
|
|
|
|
/* 2D outlines */
|
|
|
|
/* thickness means the thickness of the line */
|
|
|
|
RSGLDEF void RSGL_drawTriangleOutline(RSGL_triangle t, u32 thickness, RSGL_color c);
|
|
RSGLDEF void RSGL_drawTriangleFOutline(RSGL_triangleF t, u32 thickness, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawRectOutline(RSGL_rect r, u32 thickness, RSGL_color c);
|
|
RSGLDEF void RSGL_drawRectFOutline(RSGL_rectF r, u32 thickness, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawRoundRectOutline(RSGL_rect r, RSGL_point rounding, u32 thickness, RSGL_color c);
|
|
RSGLDEF void RSGL_drawRoundRectFOutline(RSGL_rectF r, RSGL_point rounding, u32 thickness, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawPolygonOutline(RSGL_rect r, u32 sides, u32 thickness, RSGL_color c);
|
|
RSGLDEF void RSGL_drawPolygonFOutline(RSGL_rectF r, u32 sides, u32 thickness, RSGL_color c);
|
|
|
|
RSGLDEF void RSGL_drawArcOutline(RSGL_rect o, RSGL_point arc, u32 thickness, RSGL_color color);
|
|
RSGLDEF void RSGL_drawArcFOutline(RSGL_rectF o, RSGL_pointF arc, u32 thickness, RSGL_color color);
|
|
|
|
RSGLDEF void RSGL_drawCircleOutline(RSGL_circle c, u32 thickness, RSGL_color color);
|
|
RSGLDEF void RSGL_drawCircleFOutline(RSGL_circleF c, u32 thickness, RSGL_color color);
|
|
|
|
RSGLDEF void RSGL_drawOvalFOutline(RSGL_rectF o, u32 thickness, RSGL_color c);
|
|
RSGLDEF void RSGL_drawOvalOutline(RSGL_rect o, u32 thickness, RSGL_color c);
|
|
|
|
/* format a string */
|
|
#ifndef RSGL_NO_TEXT
|
|
RSGLDEF const char* RFont_fmt(const char* string, ...);
|
|
#define RSGL_strFmt RFont_fmt
|
|
|
|
/* loads a font into RSGL, returns it's index into the RSGL_fonts array, this is used as an id in later functions */
|
|
RSGLDEF i32 RSGL_loadFont(const char* font);
|
|
/* sets font as the current font in use based on index in RSGL_font, given when it was loaded */
|
|
RSGLDEF void RSGL_setFont(i32 font);
|
|
|
|
/* sets source RFont font as the current font, given when it was loaded */
|
|
struct RFont_font;
|
|
RSGLDEF void RSGL_setRFont(struct RFont_font* font);
|
|
|
|
RSGLDEF void RSGL_drawText_len(const char* text, size_t len, RSGL_circle c, RSGL_color color);
|
|
RSGLDEF void RSGL_drawText(const char* text, RSGL_circle c, RSGL_color color);
|
|
#define RSGL_drawTextF(text, font, c, color) \
|
|
RSGL_setFont(font);\
|
|
RSGL_drawText(text, c, color);
|
|
|
|
/* align text onto larger rect based on a given alignment */
|
|
RSGLDEF RSGL_circle RSGL_alignText(const char* str, RSGL_circle c, RSGL_rectF larger, u8 alignment);
|
|
/* align text based on a length */
|
|
RSGLDEF RSGL_circle RSGL_alignText_len(const char* str, size_t str_len, RSGL_circle c, RSGL_rectF larger, u8 alignment);
|
|
|
|
/*
|
|
returns the width of a text when rendered with the set font with the size of `fontSize
|
|
stops at `textEnd` or when it reaches '\0'
|
|
*/
|
|
RSGLDEF RSGL_area RSGL_textArea(const char* text, u32 fontSize, size_t textEnd);
|
|
RSGLDEF RSGL_area RSGL_textLineArea(const char* text, u32 fontSize, size_t textEnd, size_t line);
|
|
#define RSGL_textAreaF(text, fontSize, textEnd) \
|
|
RSGL_setFont(font);\
|
|
RSGL_textAreaF(text, fontSize, textEnd);
|
|
#endif /* RSGL_NO_TEXT */
|
|
|
|
/*
|
|
this creates a texture based on a given image, draws it on a rectangle and then returns the loaded texture
|
|
|
|
if the rectangle's width and height are 0 it doesn't draw the image
|
|
the texture is loaded into RSGL_image, this means it doesn't need to be freed
|
|
but you can still free it early
|
|
*/
|
|
|
|
typedef struct RSGL_image { RSGL_texture tex; RSGL_area srcSize; char file[255]; } RSGL_image;
|
|
RSGLDEF RSGL_image RSGL_drawImage(const char* image, RSGL_rect r);
|
|
|
|
#define RSGL_loadImage(image) ((RSGL_image) RSGL_drawImage(image, (RSGL_rect){0, 0, 0, 0}))
|
|
|
|
/*
|
|
these two functions can be used before RSGL_renderCreateTexture in order to create
|
|
an swizzle'd texutre or atlas
|
|
*/
|
|
|
|
/*
|
|
*******
|
|
extra
|
|
*******
|
|
*/
|
|
|
|
/* ** collision functions ** */
|
|
RSGLDEF bool RSGL_circleCollidePoint(RSGL_circle c, RSGL_point p);
|
|
RSGLDEF bool RSGL_circleCollideRect(RSGL_circle c, RSGL_rect r);
|
|
RSGLDEF bool RSGL_circleCollide(RSGL_circle cir1, RSGL_circle cir2);
|
|
RSGLDEF bool RSGL_rectCollidePoint(RSGL_rect r, RSGL_point p);
|
|
RSGLDEF bool RSGL_rectCollide(RSGL_rect r, RSGL_rect r2);
|
|
RSGLDEF bool RSGL_pointCollide(RSGL_point p, RSGL_point p2);
|
|
|
|
RSGLDEF bool RSGL_circleCollidePointF(RSGL_circleF c, RSGL_pointF p);
|
|
RSGLDEF bool RSGL_circleCollideRectF(RSGL_circleF c, RSGL_rectF r);
|
|
RSGLDEF bool RSGL_circleCollideF(RSGL_circleF cir1, RSGL_circleF cir2);
|
|
RSGLDEF bool RSGL_rectCollidePointF(RSGL_rectF r, RSGL_pointF p);
|
|
RSGLDEF bool RSGL_rectCollideF(RSGL_rectF r, RSGL_rectF r2);
|
|
RSGLDEF bool RSGL_pointCollideF(RSGL_pointF p, RSGL_pointF p2);
|
|
|
|
#endif /* ndef RSGL_H */
|
|
|
|
/*
|
|
(Notes on how to manage Silicon (macos) included)
|
|
|
|
Example to get you started :
|
|
|
|
linux : gcc main.c -lX11 -lXcursor -lGL
|
|
windows : gcc main.c -lopengl32 -lshell32 -lgdi32
|
|
macos:
|
|
<Silicon> can be replaced to where you have the Silicon headers stored
|
|
<libSilicon.a> can be replaced to wherever you have libSilicon.a
|
|
clang main.c -I<Silicon> <libSilicon.a> -framework Foundation -framework AppKit -framework OpenGL -framework CoreVideo
|
|
|
|
NOTE(EimaMei): If you want the MacOS experience to be fully single header, then I'd be best to install Silicon (after compiling)
|
|
by going to the `Silicon` folder and running `make install`. After this you can easily include Silicon via `#include <Silicon/silicon.h>'
|
|
and link it by doing `-lSilicon`
|
|
|
|
(TODO: make new example)
|
|
|
|
compiling :
|
|
|
|
if you wish to compile the library all you have to do is create a new file with this in it
|
|
|
|
RSGL.c
|
|
#define RSGL_IMPLEMENTATION
|
|
#include "RSGL.h"
|
|
|
|
then you can use gcc (or whatever compile you wish to use) to compile the library into object file
|
|
|
|
ex. gcc -c RSGL.c -fPIC
|
|
|
|
after you compile the library into an object file, you can also turn the object file into an static or shared library
|
|
|
|
(commands ar and gcc can be replaced with whatever equivalent your system uses)
|
|
static : ar rcs RSGL.a RSGL.o
|
|
shared :
|
|
windows:
|
|
gcc -shared RSGL.o -lshell32 -lgdi32 -o RSGL.dll
|
|
linux:
|
|
gcc -shared RSGL.o -lX11 -lXcursor -o RSGL.so
|
|
macos:
|
|
<Silicon/include> can be replaced to where you have the Silicon headers stored
|
|
<libSilicon.a> can be replaced to wherever you have libSilicon.a
|
|
gcc -shared RSGL.o -framework Foundation -framework AppKit -framework CoreVideo
|
|
|
|
ex.
|
|
gcc main.c -framework Foundation -framework AppKit -framework CoreVideo
|
|
*/
|
|
|
|
#ifdef RSGL_IMPLEMENTATION
|
|
|
|
#ifdef RSGL_RENDER_LEGACY
|
|
#define RFONT_RENDER_LEGACY
|
|
#endif
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
|
|
#include <assert.h>
|
|
|
|
#ifndef RSGL_NO_TEXT
|
|
#define RFONT_IMPLEMENTATION
|
|
|
|
#define RFONT_RENDER_LEGACY
|
|
#define RFONT_NO_OPENGL
|
|
|
|
#define RFont_area RSGL_area
|
|
|
|
#define RFont_texture RSGL_texture
|
|
#define RFONT_MALLOC RSGL_MALLOC
|
|
#define RFONT_FREE RSGL_FREE
|
|
|
|
#ifndef RSGL_NO_DEPS_FOLDER
|
|
#include "deps/RFont.h"
|
|
#else
|
|
#include "RFont.h"
|
|
#endif
|
|
#endif /* RSGL_NO_TEXT */
|
|
|
|
#if !defined(RSGL_NO_STB_IMAGE) && !defined(RSGL_NO_STB_IMAGE_IMP)
|
|
|
|
#ifndef RSGL_NO_DEPS_FOLDER
|
|
#include "deps/stb_image.h"
|
|
#else
|
|
#include <stb_image.h>
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#ifdef RSGL_NO_STB_IMAGE_IMP
|
|
u8* stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
|
|
#endif
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#ifndef RSGL_NO_TEXT
|
|
typedef struct RSGL_fontData {
|
|
char* name;
|
|
RFont_font* f;
|
|
} RSGL_fontData;
|
|
|
|
typedef struct RSGL_fontsData {
|
|
RFont_font* f;
|
|
|
|
RSGL_fontData* fonts;
|
|
size_t len;
|
|
size_t cap;
|
|
} RSGL_fontsData;
|
|
|
|
RSGL_fontsData RSGL_font = {NULL, NULL, 0, 0};
|
|
#endif
|
|
|
|
RSGL_drawArgs RSGL_args = {NULL, 0, 0, { }, {0, 0, 0}, 1, RSGL_POINT3DF(-1, -1, -1), 1, 0, 0};
|
|
bool RSGL_argsClear = false;
|
|
|
|
RSGL_image* RSGL_images = NULL;
|
|
size_t RSGL_images_len = 0;
|
|
|
|
RSGLDEF bool RSGL_cstr_equal(const char* str, const char* str2);
|
|
bool RSGL_cstr_equal(const char* str, const char* str2) {
|
|
char* s;
|
|
char* s2 = (char*)str2;
|
|
|
|
for (s = (char*)str; *s && *s2; s++) {
|
|
if (*s != *s2)
|
|
return false;
|
|
|
|
s2++;
|
|
}
|
|
|
|
if (*s == '\0' && *s2 == '\0')
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
RSGL_rect RSGL_alignRect(RSGL_rect larger, RSGL_rect smaller, u16 alignment) {
|
|
RSGL_rectF r = RSGL_alignRectF(
|
|
RSGL_RECTF(larger.x, larger.y, larger.w, larger.y),
|
|
RSGL_RECTF(smaller.x, smaller.y, smaller.w, smaller.h),
|
|
alignment
|
|
);
|
|
|
|
return RSGL_RECT(r.x, r.y, r.w, r.h);
|
|
}
|
|
|
|
RSGL_rectF RSGL_alignRectF(RSGL_rectF larger, RSGL_rectF smaller, u16 alignment) {
|
|
RSGL_rectF aligned = smaller;
|
|
|
|
switch (alignment & RSGL_ALIGN_HORIZONTAL) {
|
|
case RSGL_ALIGN_LEFT:
|
|
aligned.x = larger.x;
|
|
break;
|
|
case RSGL_ALIGN_CENTER:
|
|
aligned.x = larger.x + ((larger.w - smaller.w) / 2.0);
|
|
break;
|
|
case RSGL_ALIGN_RIGHT:
|
|
aligned.x = (larger.x + larger.w) - smaller.w;
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
switch (alignment & RSGL_ALIGN_VERTICAL) {
|
|
case RSGL_ALIGN_UP:
|
|
aligned.y = larger.y;
|
|
break;
|
|
case RSGL_ALIGN_MIDDLE:
|
|
aligned.y = larger.y + ((larger.h - smaller.h) / 2.0);
|
|
break;
|
|
case RSGL_ALIGN_DOWN:
|
|
aligned.y = (larger.y + larger.h) - smaller.h;
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
return aligned;
|
|
}
|
|
|
|
RSGL_MATRIX RSGL_initDrawMatrix(RSGL_point3DF center) {
|
|
RSGL_MATRIX matrix = (RSGL_MATRIX) {
|
|
{
|
|
1.0f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, 1.0f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, 1.0f, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 1.0f
|
|
}
|
|
};
|
|
|
|
if (RSGL_args.rotate.x || RSGL_args.rotate.y || RSGL_args.rotate.z) {
|
|
if (RSGL_args.center.x != -1 && RSGL_args.center.y != -1 && RSGL_args.center.z != -1)
|
|
center = RSGL_args.center;
|
|
|
|
matrix = RSGL_translatef(&matrix, center.x, center.y, center.z);
|
|
matrix = RSGL_rotatef(&matrix, RSGL_args.rotate.z, 0, 0, 1);
|
|
matrix = RSGL_rotatef(&matrix, RSGL_args.rotate.y, 0, 1, 0);
|
|
matrix = RSGL_rotatef(&matrix, RSGL_args.rotate.x, 1, 0, 0);
|
|
matrix = RSGL_translatef(&matrix, -center.x, -center.y, -center.z);
|
|
}
|
|
|
|
return matrix;
|
|
}
|
|
|
|
RSGL_RENDER_INFO RSGL_renderInfo = {NULL, NULL, NULL, NULL, 0, 0};
|
|
|
|
#ifndef RSGL_CUSTOM_RENDER
|
|
#include "RSGL_gl.h"
|
|
#endif
|
|
|
|
void RSGL_basicDraw(u32 type, float* points, float* texPoints, RSGL_color c, size_t len) {
|
|
if (RSGL_renderInfo.len + 1 >= RSGL_MAX_BATCHES || RSGL_renderInfo.vert_len + len >= RSGL_MAX_VERTS) {
|
|
RSGL_renderBatch(&RSGL_renderInfo);
|
|
}
|
|
|
|
RSGL_BATCH* batch = NULL;
|
|
|
|
if (
|
|
RSGL_renderInfo.len == 0 ||
|
|
RSGL_renderInfo.batches[RSGL_renderInfo.len - 1].tex != RSGL_args.texture ||
|
|
RSGL_renderInfo.batches[RSGL_renderInfo.len - 1].lineWidth != RSGL_args.lineWidth ||
|
|
RSGL_renderInfo.batches[RSGL_renderInfo.len - 1].type != type ||
|
|
RSGL_renderInfo.batches[RSGL_renderInfo.len - 1].type == RSGL_TRIANGLE_FAN_2D
|
|
) {
|
|
RSGL_renderInfo.len += 1;
|
|
|
|
batch = &RSGL_renderInfo.batches[RSGL_renderInfo.len - 1];
|
|
batch->start = RSGL_renderInfo.vert_len;
|
|
batch->len = 0;
|
|
batch->type = type;
|
|
batch->tex = RSGL_args.texture;
|
|
batch->lineWidth = RSGL_args.lineWidth;
|
|
} else {
|
|
batch = &RSGL_renderInfo.batches[RSGL_renderInfo.len - 1];
|
|
}
|
|
|
|
if (batch == NULL)
|
|
return;
|
|
|
|
batch->len += len;
|
|
|
|
memcpy(&RSGL_renderInfo.verts[RSGL_renderInfo.vert_len * 3], points, len * sizeof(float) * 3);
|
|
memcpy(&RSGL_renderInfo.texCoords[RSGL_renderInfo.vert_len * 2], texPoints, len * sizeof(float) * 2);
|
|
|
|
float color[4] = {c.r / 255.0f, c.g / 255.0f, c.b / 255.0f, c.a / 255.0f};
|
|
|
|
if (RSGL_args.gradient_len && RSGL_args.gradient && (i64)(len - 1) > 0) {
|
|
memcpy(&RSGL_renderInfo.colors[RSGL_renderInfo.vert_len * 4], color, sizeof(float) * 4);
|
|
memcpy(&RSGL_renderInfo.colors[RSGL_renderInfo.vert_len * 4 + 4], RSGL_args.gradient, (len - 1) * sizeof(float) * 4);
|
|
}
|
|
else {
|
|
size_t i;
|
|
for (i = 0; i < len * 4; i += 4)
|
|
memcpy(&RSGL_renderInfo.colors[(RSGL_renderInfo.vert_len * 4) + i], color, sizeof(float) * 4);
|
|
}
|
|
|
|
RSGL_renderInfo.vert_len += len;
|
|
|
|
if (RSGL_argsClear) {
|
|
RSGL_setTexture(0);
|
|
RSGL_clearArgs();
|
|
}
|
|
}
|
|
|
|
void RSGL_legacy(i32 legacy) {
|
|
if (RSGL_args.legacy != 2)
|
|
RSGL_args.legacy = legacy;
|
|
}
|
|
|
|
/*
|
|
*********************
|
|
RSGL_GRAPHICS_CONTEXT
|
|
*********************
|
|
*/
|
|
|
|
void RSGL_init(RSGL_area r, void* loader) {
|
|
RSGL_renderViewport(0, 0, r.w, r.h);
|
|
|
|
RSGL_args.currentRect = (RSGL_rect){0, 0, r.w, r.h};
|
|
|
|
#ifndef RSGL_NO_TEXT
|
|
RFont_init(r.w, r.h);
|
|
#endif
|
|
|
|
if (RSGL_renderInfo.batches == NULL) {
|
|
RSGL_renderInfo.len = 0;
|
|
RSGL_renderInfo.vert_len = 0;
|
|
RSGL_renderInfo.batches = (RSGL_BATCH*)RSGL_MALLOC(sizeof(RSGL_BATCH) * RSGL_MAX_BATCHES);
|
|
RSGL_renderInfo.verts = (float*)RSGL_MALLOC(sizeof(float) * RSGL_MAX_VERTS * 3);
|
|
RSGL_renderInfo.colors = (float*)RSGL_MALLOC(sizeof(float) * RSGL_MAX_VERTS * 4);
|
|
RSGL_renderInfo.texCoords = (float*)RSGL_MALLOC(sizeof(float) * RSGL_MAX_VERTS * 2);
|
|
|
|
RSGL_renderInit(loader, &RSGL_renderInfo);
|
|
}
|
|
}
|
|
|
|
void RSGL_clear(RSGL_color color) {
|
|
RSGL_renderClear(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f);
|
|
|
|
RSGL_renderBatch(&RSGL_renderInfo);
|
|
}
|
|
|
|
void RSGL_updateSize(RSGL_area r) {
|
|
RSGL_args.currentRect = (RSGL_rect){0, 0, r.w, r.h};
|
|
RFont_update_framebuffer(r.w, r.h);
|
|
RSGL_renderViewport(0, 0, r.w, r.h);
|
|
}
|
|
|
|
void RSGL_free() {
|
|
u32 i;
|
|
#ifndef RSGL_NO_TEXT
|
|
for (i = 0; i < RSGL_font.len; i++)
|
|
RFont_font_free(RSGL_font.fonts[i].f);
|
|
|
|
RSGL_FREE(RSGL_font.fonts);
|
|
#endif
|
|
|
|
RSGL_renderFree();
|
|
|
|
if (RSGL_renderInfo.batches != NULL) {
|
|
RSGL_FREE(RSGL_renderInfo.batches);
|
|
RSGL_FREE(RSGL_renderInfo.verts);
|
|
RSGL_FREE(RSGL_renderInfo.colors);
|
|
RSGL_FREE(RSGL_renderInfo.texCoords);
|
|
RSGL_renderInfo.batches = NULL;
|
|
RSGL_renderInfo.len = 0;
|
|
RSGL_renderInfo.vert_len = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
****
|
|
RSGL_draw
|
|
****
|
|
*/
|
|
|
|
/* RSGL_args */
|
|
void RSGL_rotate(RSGL_point3D rotate){
|
|
RSGL_args.rotate = rotate;
|
|
}
|
|
void RSGL_setTexture(RSGL_texture texture) {
|
|
RSGL_args.texture = texture;
|
|
}
|
|
void RSGL_setProgram(u32 program) {
|
|
if (RSGL_args.program != program) {
|
|
/* render using the current program */
|
|
RSGL_renderBatch(&RSGL_renderInfo);
|
|
RSGL_args.program = program;
|
|
}
|
|
}
|
|
|
|
void RSGL_setGradient(float gradient[], size_t len) {
|
|
RSGL_args.gradient_len = len;
|
|
RSGL_args.gradient = gradient;
|
|
}
|
|
void RSGL_fill(bool fill) {
|
|
RSGL_args.fill = fill;
|
|
}
|
|
void RSGL_center(RSGL_point3DF center) {
|
|
RSGL_args.center = center;
|
|
}
|
|
void RSGL_setClearArgs(bool clearArgs) {
|
|
RSGL_argsClear = clearArgs;
|
|
}
|
|
void RSGL_clearArgs(void) {
|
|
RSGL_args = (RSGL_drawArgs){NULL, 0, 0, { }, {0, 0, 0}, 1, RSGL_POINT3DF(-1, -1, -1), 0, 0, 0};
|
|
}
|
|
|
|
|
|
void RSGL_drawPoint(RSGL_point p, RSGL_color c) {
|
|
RSGL_drawPointF((RSGL_pointF){(float)p.x, (float)p.y}, c);
|
|
}
|
|
|
|
void RSGL_drawTriangle(RSGL_triangle t, RSGL_color c) {
|
|
RSGL_drawTriangleF(RSGL_createTriangleF((float)t.p1.x, (float)t.p1.y, (float)t.p2.x, (float)t.p2.y, (float)t.p3.x, (float)t.p3.y), c);
|
|
}
|
|
|
|
void RSGL_drawRect(RSGL_rect r, RSGL_color c) {
|
|
RSGL_drawRectF((RSGL_rectF){(float)r.x, (float)r.y, (float)r.w, (float)r.h}, c);
|
|
}
|
|
|
|
void RSGL_drawRoundRect(RSGL_rect r, RSGL_point rounding, RSGL_color c) {
|
|
RSGL_drawRoundRectF((RSGL_rectF){(float)r.x, (float)r.y, (float)r.w, (float)r.h}, rounding, c);
|
|
}
|
|
|
|
void RSGL_drawPolygon(RSGL_rect r, u32 sides, RSGL_color c) {
|
|
RSGL_drawPolygonF((RSGL_rectF){(float)r.x, (float)r.y, (float)r.w, (float)r.h}, sides, c);
|
|
}
|
|
|
|
void RSGL_drawArc(RSGL_rect o, RSGL_point arc, RSGL_color color) {
|
|
RSGL_drawArcF((RSGL_rectF){(float)o.x, (float)o.y, (float)o.w, (float)o.h}, (RSGL_pointF){(float)arc.x, (float)arc.y}, color);
|
|
}
|
|
|
|
void RSGL_drawCircle(RSGL_circle c, RSGL_color color) {
|
|
RSGL_drawCircleF((RSGL_circleF){(float)c.x, (float)c.y, (float)c.d}, color);
|
|
}
|
|
|
|
void RSGL_drawOval(RSGL_rect o, RSGL_color c) {
|
|
RSGL_drawOvalF((RSGL_rectF){(float)o.x, (float)o.y, (float)o.w, (float)o.h}, c);
|
|
}
|
|
|
|
void RSGL_drawLine(RSGL_point p1, RSGL_point p2, u32 thickness, RSGL_color c) {
|
|
RSGL_drawLineF((RSGL_pointF){(float)p1.x, (float)p1.y}, (RSGL_pointF){(float)p2.x, (float)p2.y}, thickness, c);
|
|
}
|
|
|
|
void RSGL_drawTriangleOutline(RSGL_triangle t, u32 thickness, RSGL_color c) {
|
|
RSGL_drawTriangleFOutline(RSGL_createTriangleF((float)t.p1.x, (float)t.p1.y, (float)t.p2.x, (float)t.p2.y, (float)t.p3.x, (float)t.p3.y), thickness, c);
|
|
}
|
|
|
|
void RSGL_drawRectOutline(RSGL_rect r, u32 thickness, RSGL_color c) {
|
|
RSGL_drawRectFOutline((RSGL_rectF){(float)r.x, (float)r.y, (float)r.w, (float)r.h}, thickness, c);
|
|
}
|
|
|
|
void RSGL_drawRoundRectOutline(RSGL_rect r, RSGL_point rounding, u32 thickness, RSGL_color c) {
|
|
RSGL_drawRoundRectFOutline((RSGL_rectF){(float)r.x, (float)r.y, (float)r.w, (float)r.h}, rounding, thickness, c);
|
|
}
|
|
|
|
void RSGL_drawPolygonOutline(RSGL_rect r, u32 sides, u32 thickness, RSGL_color c) {
|
|
RSGL_drawPolygonFOutline((RSGL_rectF){(float)r.x, (float)r.y, (float)r.w, (float)r.h}, sides, thickness, c);
|
|
}
|
|
|
|
void RSGL_drawArcOutline(RSGL_rect o, RSGL_point arc, u32 thickness, RSGL_color color) {
|
|
RSGL_drawArcFOutline((RSGL_rectF){(float)o.x, (float)o.y, (float)o.w, (float)o.h}, (RSGL_pointF){(float)arc.x, (float)arc.y}, thickness, color);
|
|
}
|
|
|
|
void RSGL_drawCircleOutline(RSGL_circle c, u32 thickness, RSGL_color color) {
|
|
RSGL_drawCircleFOutline((RSGL_circleF){(float)c.x, (float)c.y, (float)c.d}, thickness, color);
|
|
}
|
|
|
|
void RSGL_drawOvalOutline(RSGL_rect o, u32 thickness, RSGL_color c) {
|
|
RSGL_drawOvalFOutline((RSGL_rectF){(float)o.x, (float)o.y, (float)o.w, (float)o.h}, thickness, c);
|
|
}
|
|
|
|
void RSGL_drawPointF(RSGL_pointF p, RSGL_color c) {
|
|
RSGL_drawRectF((RSGL_rectF){p.x, p.y, 1.0f, 1.0f}, c);
|
|
}
|
|
|
|
void RSGL_plotLines(RSGL_pointF* lines, size_t points_count, u32 thickness, RSGL_color c) {
|
|
size_t i;
|
|
for (i = 0; i < points_count; i += 2) {
|
|
RSGL_drawLineF(lines[i], lines[i + 1], thickness, c);
|
|
}
|
|
}
|
|
|
|
void RSGL_drawTriangleF(RSGL_triangleF t, RSGL_color c) {
|
|
if (RSGL_args.fill == false)
|
|
return RSGL_drawTriangleFOutline(t, 1, c);
|
|
|
|
RSGL_point3DF center = {RSGL_GET_WORLD_POINT(t.p3.x, (t.p3.y + t.p1.y) / 2.0f, 0)};
|
|
RSGL_MATRIX matrix = RSGL_initDrawMatrix(center);
|
|
|
|
float points[] = {RSGL_GET_FINAL_POINT((float)t.p1.x, (float)t.p1.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT((float)t.p2.x, (float)t.p2.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT((float)t.p3.x, (float)t.p3.y, 0.0f)};
|
|
|
|
float texPoints[] = {
|
|
0.0f, 1.0f,
|
|
1.0f, 1.0f,
|
|
((float)(t.p3.x - t.p1.x)/t.p2.x < 1) ? (float)(t.p3.x - t.p1.x) / t.p2.x : 0, 0.0f,
|
|
};
|
|
|
|
RSGL_basicDraw(RSGL_TRIANGLES_2D, (float*)points, (float*)texPoints, c, 3);
|
|
}
|
|
|
|
#ifndef PI
|
|
#define PI 3.14159265358979323846f
|
|
#endif
|
|
#ifndef DEG2RAD
|
|
#define DEG2RAD (PI/180.0f)
|
|
#endif
|
|
#ifndef RAD2DEG
|
|
#define RAD2DEG (180.0f/PI)
|
|
#endif
|
|
|
|
void RSGL_drawTriangleHyp(RSGL_pointF p, size_t angle, float hypotenuse, RSGL_color color) {
|
|
float dir = (hypotenuse > 0);
|
|
hypotenuse = fabsf(hypotenuse);
|
|
|
|
float base = hypotenuse * (cos(angle) * DEG2RAD);
|
|
float opp = hypotenuse * (sin(angle) * DEG2RAD);
|
|
|
|
RSGL_triangleF t = RSGL_TRIANGLEF(
|
|
p,
|
|
RSGL_POINTF(p.x + base, p.y),
|
|
RSGL_POINTF(p.x + (base * dir), p.y - opp)
|
|
);
|
|
|
|
RSGL_drawTriangleF(t, color);
|
|
}
|
|
|
|
void RSGL_drawRectF(RSGL_rectF r, RSGL_color c) {
|
|
if (RSGL_args.fill == false)
|
|
return RSGL_drawRectFOutline(r, 1, c);
|
|
|
|
float texPoints[] = {
|
|
0.0f, 0.0f,
|
|
0.0f, 1.0f,
|
|
1.0f, 0.0f,
|
|
1.0f, 1.0f,
|
|
1.0f, 0.0f,
|
|
0.0f, 1.0f
|
|
};
|
|
|
|
RSGL_point3DF center = (RSGL_point3DF){RSGL_GET_WORLD_POINT(r.x + (r.w / 2.0f), r.y + (r.h / 2.0f), 0.0f)};
|
|
RSGL_MATRIX matrix = RSGL_initDrawMatrix(center);
|
|
|
|
float points[] = {
|
|
RSGL_GET_FINAL_POINT(r.x, r.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(r.x, r.y + r.h, 0.0f),
|
|
RSGL_GET_FINAL_POINT(r.x + r.w, r.y, 0.0f),
|
|
|
|
RSGL_GET_FINAL_POINT(r.x + r.w, r.y + r.h, 0.0f),
|
|
RSGL_GET_FINAL_POINT(r.x + r.w, r.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(r.x, r.y + r.h, 0.0f),
|
|
};
|
|
|
|
RSGL_basicDraw(RSGL_TRIANGLES_2D, (float*)points, (float*)texPoints, c, 6);
|
|
}
|
|
|
|
void RSGL_drawRoundRectF(RSGL_rectF r, RSGL_point rounding, RSGL_color c) {
|
|
if (RSGL_args.fill == false)
|
|
return RSGL_drawRoundRectFOutline(r, rounding, 1, c);
|
|
|
|
RSGL_drawRect((RSGL_rect) {r.x + (rounding.x / 2), r.y, r.w - rounding.x, r.h}, c);
|
|
RSGL_drawRect((RSGL_rect) {r.x, r.y + (rounding.y / 2), r.w, r.h - rounding.y}, c);
|
|
|
|
RSGL_drawArc((RSGL_rect) {r.x, r.y, rounding.x, rounding.y}, (RSGL_point){180, 270}, c);
|
|
RSGL_drawArc((RSGL_rect) {r.x + (r.w - rounding.x), r.y, rounding.x, rounding.y}, (RSGL_point){90, 180}, c);
|
|
RSGL_drawArc((RSGL_rect) {r.x + (r.w - rounding.x), r.y + (r.h - rounding.y), rounding.x, rounding.y}, (RSGL_point){0, 90}, c);
|
|
RSGL_drawArc((RSGL_rect) {r.x, r.y + (r.h - rounding.y), rounding.x, rounding.y}, (RSGL_point){270, 360}, c);
|
|
}
|
|
|
|
void RSGL_drawPolygonFOutlinePro(RSGL_rectF o, u32 sides, RSGL_pointF arc, RSGL_color c);
|
|
|
|
void RSGL_drawPolygonFPro(RSGL_rectF o, u32 sides, RSGL_pointF arc, RSGL_color c) {
|
|
static float verts[360 * 3];
|
|
static float texcoords[360 * 2];
|
|
|
|
if (RSGL_args.fill == false)
|
|
return RSGL_drawPolygonFOutlinePro(o, sides, arc, c);
|
|
|
|
RSGL_point3DF center = (RSGL_point3DF){RSGL_GET_WORLD_POINT(o.x + (o.w / 2.0f), o.y + (o.h / 2.0f), 0)};
|
|
|
|
o = (RSGL_rectF){o.x, o.y, o.w / 2, o.h / 2};
|
|
RSGL_MATRIX matrix = RSGL_initDrawMatrix(center);
|
|
|
|
float displacement = 360.0f / (float)sides;
|
|
float angle = displacement * arc.x;
|
|
|
|
size_t vIndex = 0;
|
|
size_t tIndex = 0;
|
|
|
|
u32 i;
|
|
for (i = 0; i < sides; i++) {
|
|
RSGL_pointF p = {sinf(angle * DEG2RAD), cosf(angle * DEG2RAD)};
|
|
|
|
texcoords[tIndex] = (p.x + 1.0f) * 0.5;
|
|
texcoords[tIndex + 1] = (p.y + 1.0f) * 0.5;
|
|
|
|
memcpy(verts + vIndex, (float[3]){RSGL_GET_FINAL_POINT(o.x + o.w + (p.x * o.w), o.y + o.h + (p.y * o.h), 0.0)}, 3 * sizeof(float));
|
|
|
|
angle += displacement;
|
|
tIndex += 2;
|
|
vIndex += 3;
|
|
}
|
|
|
|
texcoords[tIndex + 1] = 0;
|
|
texcoords[tIndex + 2] = 0;
|
|
|
|
RSGL_basicDraw(RSGL_TRIANGLE_FAN_2D, verts, texcoords, c, vIndex / 3);
|
|
}
|
|
|
|
void RSGL_drawPolygonF(RSGL_rectF o, u32 sides, RSGL_color c) { RSGL_drawPolygonFPro(o, sides, (RSGL_pointF){0, (int)sides}, c); }
|
|
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846 /* pi */
|
|
#endif
|
|
|
|
void RSGL_drawArcF(RSGL_rectF o, RSGL_pointF arc, RSGL_color color) {
|
|
u32 verts = (u32)round((float)((2 * M_PI * ((o.w + o.h) / 2.0f)) / 10));
|
|
verts = (verts > 360 ? 360 : verts);
|
|
|
|
RSGL_drawPolygonFPro(o, verts, arc, color);
|
|
}
|
|
|
|
void RSGL_drawCircleF(RSGL_circleF c, RSGL_color color) {
|
|
float verts = ((2 * M_PI * c.d) / 10);
|
|
verts = (verts > 360 ? 360 : verts);
|
|
|
|
RSGL_drawPolygonFPro((RSGL_rectF){c.x, c.y, c.d, c.d}, verts, (RSGL_pointF){0, verts}, color);
|
|
}
|
|
|
|
void RSGL_drawOvalF(RSGL_rectF o, RSGL_color c) {
|
|
float verts = ((2 * M_PI * ((o.w + o.h) / 2.0f)) / 10);
|
|
verts = (verts > 360 ? 360 : verts);
|
|
|
|
RSGL_drawPolygonFPro(o, verts, (RSGL_pointF){0, verts}, c);
|
|
}
|
|
|
|
/*
|
|
outlines
|
|
*/
|
|
|
|
void RSGL_drawLineF(RSGL_pointF p1, RSGL_pointF p2, u32 thickness, RSGL_color c) {
|
|
RSGL_args.lineWidth = thickness;
|
|
|
|
RSGL_point3DF center = {RSGL_GET_WORLD_POINT((p1.x + p2.x) / 2.0f, (p1.y + p2.y) / 2.0f, 0.0f)};
|
|
RSGL_MATRIX matrix = RSGL_initDrawMatrix(center);
|
|
|
|
float points[] = {RSGL_GET_FINAL_POINT(p1.x, p1.y, 0.0f), RSGL_GET_FINAL_POINT(p2.x, p2.y, 0.0f)};
|
|
float texPoints[] = {0, 0.0f, 0, 0.0f};
|
|
|
|
RSGL_basicDraw(RSGL_LINES_2D, (float*)points, (float*)texPoints, c, 2);
|
|
}
|
|
|
|
void RSGL_drawTriangleFOutline(RSGL_triangleF t, u32 thickness, RSGL_color c) {
|
|
RSGL_args.lineWidth = thickness;
|
|
RSGL_point3DF center = {RSGL_GET_WORLD_POINT(t.p3.x, (t.p3.y + t.p1.y) / 2.0f, 0)};
|
|
RSGL_MATRIX matrix = RSGL_initDrawMatrix(center);
|
|
|
|
float points[] = {RSGL_GET_FINAL_POINT(t.p3.x, t.p3.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(t.p1.x, t.p1.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(t.p1.x, t.p1.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(t.p2.x, t.p2.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(t.p2.x, t.p2.y, 0.0f),
|
|
RSGL_GET_FINAL_POINT(t.p3.x, t.p3.y, 0.0f)};
|
|
|
|
float texCoords[18];
|
|
|
|
RSGL_basicDraw(RSGL_LINES_2D, (float*)points, texCoords, c, 6);
|
|
}
|
|
void RSGL_drawRectFOutline(RSGL_rectF r, u32 thickness, RSGL_color c) {
|
|
RSGL_point3DF oCenter = RSGL_args.center;
|
|
|
|
RSGL_center((RSGL_point3DF){RSGL_GET_WORLD_POINT(r.x + (r.w / 2.0f), r.y + (r.h / 2.0f), 0.0f)});
|
|
RSGL_drawLineF((RSGL_pointF){r.x, r.y}, (RSGL_pointF){r.x + r.w, r.y}, thickness, c);
|
|
|
|
RSGL_center((RSGL_point3DF){RSGL_GET_WORLD_POINT(r.x + (r.w / 2.0f), r.y + (r.h / 2.0f), 0.0f)});
|
|
RSGL_drawLineF((RSGL_pointF){r.x, r.y}, (RSGL_pointF){r.x, r.y + r.h}, thickness, c);
|
|
|
|
RSGL_center((RSGL_point3DF){RSGL_GET_WORLD_POINT(r.x + (r.w / 2.0f), r.y + (r.h / 2.0f), 0.0f)});
|
|
RSGL_drawLineF((RSGL_pointF){r.x, r.y + r.h}, (RSGL_pointF){r.x + r.w, r.y + r.h}, thickness, c);
|
|
|
|
RSGL_center((RSGL_point3DF){RSGL_GET_WORLD_POINT(r.x + (r.w / 2.0f), r.y + (r.h / 2.0f), 0.0f)});
|
|
RSGL_drawLineF((RSGL_pointF){r.x + r.w, r.y}, (RSGL_pointF){r.x + r.w, r.y + r.h}, thickness, c);
|
|
|
|
RSGL_center(oCenter);
|
|
}
|
|
void RSGL_drawRoundRectFOutline(RSGL_rectF r, RSGL_point rounding, u32 thickness, RSGL_color c) {
|
|
RSGL_drawRectF((RSGL_rectF) {r.x + (rounding.x/2), r.y, r.w - rounding.x, (int)(thickness + !thickness)}, c);
|
|
RSGL_drawRectF((RSGL_rectF) {r.x + (rounding.x/2), r.y + r.h, r.w - rounding.x, (int)(thickness + !thickness)}, c);
|
|
RSGL_drawRectF((RSGL_rectF) {r.x, r.y + (rounding.y/2), (int)(thickness + !thickness), r.h - rounding.y}, c);
|
|
RSGL_drawRectF((RSGL_rectF) {r.x + r.w, r.y + (rounding.y/2), (int)(thickness + !thickness), r.h - rounding.y}, c);
|
|
|
|
RSGL_drawArcFOutline((RSGL_rectF) {r.x, r.y, rounding.x, rounding.y}, (RSGL_pointF){180, 270}, thickness, c);
|
|
RSGL_drawArcFOutline((RSGL_rectF) {r.x + (r.w - rounding.x), r.y, rounding.x, rounding.y}, (RSGL_pointF){90, 180}, thickness, c);
|
|
RSGL_drawArcFOutline((RSGL_rectF) {r.x + (r.w - rounding.x), r.y + (r.h - rounding.y) - 1, rounding.x, rounding.y + 2}, (RSGL_pointF){0, 90}, thickness, c);
|
|
RSGL_drawArcFOutline((RSGL_rectF) {r.x + 1, r.y + (r.h - rounding.y) - 1, rounding.x, rounding.y + 2}, (RSGL_pointF){270, 360}, thickness, c);
|
|
}
|
|
|
|
void RSGL_drawPolygonFOutlinePro(RSGL_rectF o, u32 sides, RSGL_pointF arc, RSGL_color c) {
|
|
static float verts[360 * 2 * 3];
|
|
static float texCoords[360 * 2 * 2];
|
|
|
|
RSGL_point3DF center = (RSGL_point3DF) {RSGL_GET_WORLD_POINT(o.x + (o.w / 2.0f), o.y + (o.h / 2.0f), 0.0f)};
|
|
RSGL_MATRIX matrix = RSGL_initDrawMatrix(center);
|
|
|
|
o = (RSGL_rectF){o.x + (o.w / 2), o.y + (o.h / 2), o.w / 2, o.h / 2};
|
|
|
|
float displacement = 360.0f / (float)sides;
|
|
float centralAngle = displacement * arc.x;
|
|
|
|
i32 i;
|
|
u32 j;
|
|
size_t index = 0;
|
|
|
|
for (i = arc.x; i < arc.y; i++) {
|
|
for (j = 0; j < 2; j++) {
|
|
memcpy(verts + index, (float[3]) {
|
|
RSGL_GET_FINAL_POINT(
|
|
o.x + (sinf(DEG2RAD * centralAngle) * o.w),
|
|
o.y + (cosf(DEG2RAD * centralAngle) * o.h),
|
|
(0.0))
|
|
}, sizeof(float) * 3);
|
|
|
|
if (!j) centralAngle += displacement;
|
|
index += 3;
|
|
}
|
|
}
|
|
|
|
RSGL_basicDraw(RSGL_LINES_2D, verts, texCoords, c, index / 3);
|
|
}
|
|
|
|
void RSGL_drawPolygonFOutline(RSGL_rectF o, u32 sides, u32 thickness, RSGL_color c) {
|
|
RSGL_args.lineWidth = thickness;
|
|
RSGL_drawPolygonFOutlinePro(o, sides, (RSGL_pointF){0, (int)sides}, c);
|
|
}
|
|
void RSGL_drawArcFOutline(RSGL_rectF o, RSGL_pointF arc, u32 thickness, RSGL_color color) {
|
|
float verts = ((2 * M_PI * ((o.w + o.h) / 2.0f)) / 10);
|
|
verts = (verts > 360 ? 360 : verts);
|
|
|
|
RSGL_args.lineWidth = thickness;
|
|
RSGL_drawPolygonFOutlinePro(o, verts, arc, color);
|
|
}
|
|
void RSGL_drawCircleFOutline(RSGL_circleF c, u32 thickness, RSGL_color color) {
|
|
float verts = ((2 * M_PI * c.d) / 10);
|
|
verts = (verts > 360 ? 360 : verts);
|
|
|
|
RSGL_args.lineWidth = thickness;
|
|
RSGL_drawPolygonFOutlinePro((RSGL_rectF){c.x, c.y, c.d, c.d}, verts, (RSGL_pointF){0, verts}, color);
|
|
}
|
|
void RSGL_drawOvalFOutline(RSGL_rectF o, u32 thickness, RSGL_color c) {
|
|
float verts = ((2 * M_PI * ((o.w + o.h) / 2.0f)) / 10);
|
|
verts = (verts > 360 ? 360 : verts);
|
|
|
|
RSGL_args.lineWidth = thickness;
|
|
RSGL_drawPolygonFOutlinePro(o, verts, (RSGL_pointF){0, verts}, c);
|
|
}
|
|
|
|
#ifndef RSGL_NO_STB_IMAGE
|
|
RSGL_image RSGL_drawImage(const char* image, RSGL_rect r) {
|
|
RSGL_image img;
|
|
img.tex = 0;
|
|
|
|
#ifndef RSGL_NO_SAVE_IMAGE
|
|
static size_t images_comp = 0;
|
|
|
|
if (images_comp == 0) {
|
|
RSGL_images = (RSGL_image*)RSGL_MALLOC(sizeof(RSGL_image) * RSGL_INIT_IMAGES);
|
|
images_comp = RSGL_INIT_IMAGES;
|
|
}
|
|
|
|
if (RSGL_images_len) {
|
|
size_t i;
|
|
for (i = 0; i < RSGL_images_len; i++) {
|
|
if (RSGL_cstr_equal(image, RSGL_images[i].file)) {
|
|
img.tex = RSGL_images[i].tex;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* RSGL_NO_SAVE_IMAGE */
|
|
|
|
if (img.tex == 0) {
|
|
i32 c;
|
|
u8* bitmap = stbi_load(image, (int*)&img.srcSize.w, (int*)&img.srcSize.h, &c, 0);
|
|
|
|
img.tex = RSGL_renderCreateTexture(bitmap, (RSGL_area){img.srcSize.w, img.srcSize.h}, c);
|
|
|
|
RSGL_FREE(bitmap);
|
|
|
|
#ifndef RSGL_NO_SAVE_IMAGE
|
|
if (RSGL_images_len + 1 > images_comp) {
|
|
RSGL_images = (RSGL_image*)RSGL_REALLOC(RSGL_images, sizeof(RSGL_image) * (RSGL_NEW_IMAGES + images_comp));
|
|
images_comp += RSGL_NEW_IMAGES;
|
|
}
|
|
|
|
strcpy(img.file, image);
|
|
|
|
RSGL_images[RSGL_images_len] = img;
|
|
RSGL_images_len++;
|
|
#endif
|
|
}
|
|
|
|
if (r.w || r.h) {
|
|
RSGL_texture tex = RSGL_args.texture;
|
|
RSGL_setTexture(img.tex);
|
|
|
|
RSGL_drawRect(r, RSGL_RGB(255, 255, 255));
|
|
|
|
RSGL_args.texture = tex;
|
|
}
|
|
|
|
return img;
|
|
}
|
|
#endif
|
|
|
|
#ifndef RSGL_NO_TEXT
|
|
|
|
#ifdef WIN32
|
|
#include <io.h>
|
|
#define F_OK 0
|
|
#define access _access
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
i32 RSGL_loadFont(const char* font) {
|
|
u32 i;
|
|
for (i = 0; i < RSGL_font.len; i++)
|
|
if (RSGL_font.fonts[i].name == font)
|
|
return i;
|
|
|
|
if (access(font, 0)) {
|
|
printf("RSGL_loadFont File %s does not exist.\n", font);
|
|
return -1;
|
|
}
|
|
|
|
if (RSGL_font.len == RSGL_font.cap) {
|
|
RSGL_font.cap += RSGL_NEW_FONTS;
|
|
|
|
RSGL_fontData* nFonts = (RSGL_fontData*)RSGL_MALLOC(sizeof(RSGL_fontData) * RSGL_font.cap);
|
|
memcpy(nFonts, RSGL_font.fonts, sizeof(RSGL_fontData) * RSGL_font.len);
|
|
RSGL_FREE(RSGL_font.fonts);
|
|
|
|
RSGL_font.fonts = nFonts;
|
|
}
|
|
|
|
|
|
RSGL_font.fonts[RSGL_font.len].name = (char*)font;
|
|
RSGL_font.fonts[RSGL_font.len].f = RFont_font_init(font);
|
|
RSGL_font.len++;
|
|
|
|
return RSGL_font.len - 1;
|
|
}
|
|
|
|
void RSGL_setFont(i32 font) {
|
|
if (font == -1) {
|
|
printf("RSGL_setFont : invalid font\n");
|
|
return;
|
|
}
|
|
|
|
RSGL_font.f = RSGL_font.fonts[font].f;
|
|
}
|
|
|
|
void RSGL_setRFont(RFont_font* font) {
|
|
RSGL_font.f = font;
|
|
}
|
|
|
|
void RSGL_drawText_len(const char* text, size_t len, RSGL_circle c, RSGL_color color) {
|
|
if (text == NULL || RSGL_font.f == NULL)
|
|
return;
|
|
|
|
RFont_set_color(color.r / 255.0f, color.b / 255.0f, color.g / 255.0f, color.a / 255.0f);
|
|
RFont_draw_text_len(RSGL_font.f, text, len, c.x, c.y, c.d, 0.0f);
|
|
}
|
|
|
|
void RSGL_drawText(const char* text, RSGL_circle c, RSGL_color color) {
|
|
RSGL_drawText_len(text, 0, c, color);
|
|
}
|
|
|
|
RSGL_circle RSGL_alignText(const char* str, RSGL_circle c, RSGL_rectF larger, u8 alignment) {
|
|
return RSGL_alignText_len(str, 0, c, larger, alignment);
|
|
}
|
|
|
|
RSGL_circle RSGL_alignText_len(const char* str, size_t str_len, RSGL_circle c, RSGL_rectF larger, u8 alignment) {
|
|
RSGL_area area = RSGL_textArea(str, c.d, str_len);
|
|
|
|
RSGL_rectF smaller = RSGL_RECTF(c.x, c.y, area.w, c.d);
|
|
RSGL_rectF r = RSGL_alignRectF(larger, smaller, alignment);
|
|
|
|
return RSGL_CIRCLE(r.x, r.y + (c.d / 4), r.h);
|
|
}
|
|
|
|
RSGL_area RSGL_textArea(const char* text, u32 fontSize, size_t textEnd) {
|
|
if (RSGL_font.f == NULL)
|
|
return RSGL_AREA(0, 0);
|
|
|
|
return RFont_text_area_len(RSGL_font.f, text, textEnd, fontSize, 0, 0.0);
|
|
}
|
|
|
|
RSGL_area RSGL_textLineArea(const char* text, u32 fontSize, size_t textEnd, size_t line) {
|
|
return RFont_text_area_len(RSGL_font.f, text, textEnd, fontSize, line, 0.0);
|
|
}
|
|
|
|
RSGL_color RFontcolor = RSGL_RGBA(0, 0, 0, 0);
|
|
void RFont_render_set_color(float r, float g, float b, float a) {
|
|
RFontcolor = RSGL_RGBA(r * 255, g * 255, b * 255, a * 255);
|
|
}
|
|
|
|
void RFont_render_text(RFont_texture atlas, float* verts, float* tcoords, size_t nverts) {
|
|
RSGL_drawArgs save = RSGL_args;
|
|
RSGL_rotate(RSGL_POINT3D(0, 0, 0));
|
|
RSGL_setTexture(atlas);
|
|
RSGL_basicDraw(RSGL_TRIANGLES_2D_BLEND, verts, tcoords, RFontcolor, nverts);
|
|
RSGL_args = save;
|
|
}
|
|
|
|
void RFont_render_init(void) { }
|
|
|
|
void RFont_render_free(RFont_texture atlas) {
|
|
RSGL_renderDeleteTexture(atlas);
|
|
}
|
|
|
|
void RFont_render_legacy(u8 legacy) { RSGL_UNUSED(legacy); }
|
|
#endif /* RSGL_NO_TEXT */
|
|
|
|
/*
|
|
******
|
|
RSGL_Other
|
|
******
|
|
*/
|
|
|
|
/* collision detection */
|
|
bool RSGL_circleCollidePoint(RSGL_circle c, RSGL_point p) { return RSGL_circleCollideRect(c, (RSGL_rect) {p.x, p.y, 1, 1}); }
|
|
bool RSGL_circleCollidePointF(RSGL_circleF c, RSGL_pointF p) { return RSGL_circleCollideRectF(c, (RSGL_rectF) {p.x, p.y, 1, 1}); }
|
|
|
|
bool RSGL_circleCollideRectF(RSGL_circleF c, RSGL_rectF r) {
|
|
// test cords
|
|
float testX = c.x;
|
|
float testY = c.y;
|
|
|
|
// fill cords based on x/ys of the shapes
|
|
if (c.x < r.x)
|
|
testX = r.x;
|
|
|
|
else if (c.x > r.x+r.w)
|
|
testX = r.x-r.w;
|
|
|
|
if (c.y < r.y)
|
|
testY = r.y;
|
|
|
|
else if (c.y > r.y+r.h)
|
|
testY = r.y+r.h;
|
|
|
|
// check
|
|
return ( sqrt( ( (c.x - testX) * (c.x - testX) ) + ( (c.y - testY) * (c.y - testY) ) ) <= (c.d/2) );
|
|
}
|
|
bool RSGL_circleCollideRect(RSGL_circle c, RSGL_rect r) { return RSGL_circleCollideRectF(RSGL_CIRCLEF(c.x, c.y, c.d), RSGL_RECTF(r.x, r.y, r.w, r.h)); }
|
|
|
|
bool RSGL_circleCollideF(RSGL_circleF cir, RSGL_circleF cir2) {
|
|
float distanceBetweenCircles = (float) sqrt(
|
|
(cir2.x - cir.x) * (cir2.x - cir.x) +
|
|
(cir2.y - cir.y) * (cir2.y - cir.y)
|
|
);
|
|
|
|
return !(distanceBetweenCircles > (cir.d/2) + (cir2.d/2)); // check if there is a collide
|
|
}
|
|
|
|
bool RSGL_circleCollide(RSGL_circle cir, RSGL_circle cir2) { return RSGL_circleCollideF(RSGL_CIRCLEF(cir.x, cir.y, cir.d), RSGL_CIRCLEF(cir2.x, cir2.y, cir2.d)); }
|
|
|
|
bool RSGL_rectCollidePoint(RSGL_rect r, RSGL_point p){ return (p.x >= r.x && p.x <= r.x + r.w && p.y >= r.y && p.y <= r.y + r.h); }
|
|
bool RSGL_rectCollide(RSGL_rect r, RSGL_rect r2){ return (r.x + r.w >= r2.x && r.x <= r2.x + r2.w && r.y + r.h >= r2.y && r.y <= r2.y + r2.h); }
|
|
bool RSGL_pointCollide(RSGL_point p, RSGL_point p2){ return (p.x == p2.x && p.y == p2.y); }
|
|
|
|
bool RSGL_rectCollidePointF(RSGL_rectF r, RSGL_pointF p){ return (p.x >= r.x && p.x <= r.x + r.w && p.y >= r.y && p.y <= r.y + r.h); }
|
|
bool RSGL_rectCollideF(RSGL_rectF r, RSGL_rectF r2){ return (r.x + r.w >= r2.x && r.x <= r2.x + r2.w && r.y + r.h >= r2.y && r.y <= r2.y + r2.h); }
|
|
bool RSGL_pointCollideF(RSGL_pointF p, RSGL_pointF p2){ return (p.x == p2.x && p.y == p2.y); }
|
|
|
|
/* Multiply the current matrix by a translation matrix */
|
|
RSGL_MATRIX RSGL_translatef(RSGL_MATRIX* matrix, float x, float y, float z) {
|
|
RSGL_MATRIX matTranslation = {
|
|
{
|
|
1.0f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, 1.0f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 1.0f,
|
|
x, y, z, 1.0f
|
|
}
|
|
};
|
|
|
|
/* NOTE: We transpose matrix with multiplication order */
|
|
return RSGL_matrixMultiply(matTranslation.m, matrix->m);
|
|
}
|
|
|
|
/* Multiply the current matrix by a rotation matrix */
|
|
RSGL_MATRIX RSGL_rotatef(RSGL_MATRIX* matrix, float angle, float x, float y, float z) {
|
|
/* Axis vector (x, y, z) normalization */
|
|
float lengthSquared = x * x + y * y + z * z;
|
|
if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) {
|
|
float inverseLength = 1.0f / sqrtf(lengthSquared);
|
|
x *= inverseLength;
|
|
y *= inverseLength;
|
|
z *= inverseLength;
|
|
}
|
|
|
|
/* Rotation matrix generation */
|
|
float sinres = sinf(DEG2RAD * angle);
|
|
float cosres = cosf(DEG2RAD * angle);
|
|
float t = 1.0f - cosres;
|
|
|
|
float matRotation[16] =
|
|
{
|
|
x * x * t + cosres, y * x * t + z * sinres, z * x * t - y * sinres, 0.0f,
|
|
x * y * t - z * sinres, y * y * t + cosres, z * y * t + x * sinres, 0.0f,
|
|
x * z * t + y * sinres, y * z * t - x * sinres, z * z * t + cosres, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 1.0f
|
|
};
|
|
|
|
return RSGL_matrixMultiply(matRotation, matrix->m);
|
|
}
|
|
|
|
RSGL_MATRIX RSGL_matrixMultiply(float left[16], float right[16]) {
|
|
return (RSGL_MATRIX) {
|
|
{
|
|
left[0] * right[0] + left[1] * right[4] + left[2] * right[8] + left[3] * right[12],
|
|
left[0] * right[1] + left[1] * right[5] + left[2] * right[9] + left[3] * right[13],
|
|
left[0] * right[2] + left[1] * right[6] + left[2] * right[10] + left[3] * right[14],
|
|
left[0] * right[3] + left[1] * right[7] + left[2] * right[11] + left[3] * right[15],
|
|
left[4] * right[0] + left[5] * right[4] + left[6] * right[8] + left[7] * right[12],
|
|
left[4] * right[1] + left[5] * right[5] + left[6] * right[9] + left[7] * right[13],
|
|
left[4] * right[2] + left[5] * right[6] + left[6] * right[10] + left[7] * right[14],
|
|
left[4] * right[3] + left[5] * right[7] + left[6] * right[11] + left[7] * right[15],
|
|
left[8] * right[0] + left[9] * right[4] + left[10] * right[8] + left[11] * right[12],
|
|
left[8] * right[1] + left[9] * right[5] + left[10] * right[9] + left[11] * right[13],
|
|
left[8] * right[2] + left[9] * right[6] + left[10] * right[10] + left[11] * right[14],
|
|
left[8] * right[3] + left[9] * right[7] + left[10] * right[11] + left[11] * right[15],
|
|
left[12] * right[0] + left[13] * right[4] + left[14] * right[8] + left[15] * right[12],
|
|
left[12] * right[1] + left[13] * right[5] + left[14] * right[9] + left[15] * right[13],
|
|
left[12] * right[2] + left[13] * right[6] + left[14] * right[10] + left[15] * right[14],
|
|
left[12] * right[3] + left[13] * right[7] + left[14] * right[11] + left[15] * right[15]
|
|
}
|
|
};
|
|
}
|
|
#endif /* RSGL_IMPLEMENTATION */
|