commit
c015529088
@ -7,7 +7,7 @@ Use your best judgement, and feel free to propose changes to this document in a
|
||||
|
||||
### raylib philosophy
|
||||
|
||||
- raylib is a tool to LEARN videogames programming, every single function in raylib should be a tutorial on itself.
|
||||
- raylib is a tool to enjoy videogames programming, every single function in raylib should be a tutorial on itself.
|
||||
- raylib is SIMPLE and EASY-TO-USE, I tried to keep it compact with a small set of functions, if a function is too complex or is not clearly useful, better not to include it.
|
||||
- raylib is open source and free; educators and institutions can use this tool to TEACH videogames programming completely by free.
|
||||
- raylib is collaborative; contribution of tutorials / code-examples / bugs-solving / code-comments are highly appreciated.
|
||||
|
@ -18,7 +18,7 @@ with a small [donation](http://www.raylib.com/helpme.html) or contributing with
|
||||
raylib philosophy
|
||||
------------------
|
||||
|
||||
* raylib is a tool to LEARN videogames programming, every single function in raylib should be a tutorial on itself.
|
||||
* raylib is a tool to enjoy videogames programming, every single function in raylib should be a tutorial on itself.
|
||||
* raylib is SIMPLE and EASY-TO-USE, I tried to keep it compact with a small set of functions, if a function is too complex or has not a clear usefulness, better not to include it.
|
||||
* raylib is open source and free; educators and institutions can use this tool to TEACH videogames programming completely by free.
|
||||
* raylib is collaborative; contribution of tutorials / code-examples / bugs-solving / code-comments are highly appreciated.
|
||||
|
@ -1,12 +1,12 @@
|
||||
<img align="left" src="https://github.com/raysan5/raylib/blob/master/logo/raylib_256x256.png" width=256>
|
||||
|
||||
**raylib is a simple and easy-to-use library to learn videogames programming.**
|
||||
**raylib is a simple and easy-to-use library to enjoy videogames programming.**
|
||||
|
||||
raylib is highly inspired by Borland BGI graphics lib and by XNA framework.
|
||||
|
||||
raylib could be useful for prototyping, tools development, graphic applications, embedded systems and education.
|
||||
|
||||
NOTE for ADVENTURERS: raylib is a programming library to learn videogames programming;
|
||||
NOTE for ADVENTURERS: raylib is a programming library to enjoy videogames programming;
|
||||
no fancy interface, no visual helpers, no auto-debugging... just coding in the most
|
||||
pure spartan-programmers way. Are you ready to learn? Jump to [code examples!](http://www.raylib.com/examples.html)
|
||||
|
||||
|
@ -29,19 +29,18 @@ int main()
|
||||
fontDefault.baseSize = 16;
|
||||
fontDefault.charsCount = 95;
|
||||
// Parameters > font size: 16, no chars array provided (0), chars count: 95 (autogenerate chars array)
|
||||
fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 95, false);
|
||||
fontDefault.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 95, FONT_DEFAULT);
|
||||
// Parameters > chars count: 95, font size: 16, chars padding in image: 4 px, pack method: 0 (default)
|
||||
Image atlas = GenImageFontAtlas(fontDefault.chars, 95, 16, 4, 0);
|
||||
fontDefault.texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
|
||||
// SDF font generation from TTF font
|
||||
// NOTE: SDF chars data is generated with LoadFontData(), it's just a bool option
|
||||
Font fontSDF = { 0 };
|
||||
fontSDF.baseSize = 16;
|
||||
fontSDF.charsCount = 95;
|
||||
// Parameters > font size: 16, no chars array provided (0), chars count: 0 (defaults to 95)
|
||||
fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 0, true);
|
||||
fontSDF.chars = LoadFontData("resources/AnonymousPro-Bold.ttf", 16, 0, 0, FONT_SDF);
|
||||
// Parameters > chars count: 95, font size: 16, chars padding in image: 0 px, pack method: 1 (Skyline algorythm)
|
||||
atlas = GenImageFontAtlas(fontSDF.chars, 95, 16, 0, 1);
|
||||
fontSDF.texture = LoadTextureFromImage(atlas);
|
||||
|
@ -26,7 +26,7 @@ int main()
|
||||
Image parrots = LoadImage("resources/parrots.png"); // Load image in CPU memory (RAM)
|
||||
|
||||
// Draw over image using custom font
|
||||
ImageDrawTextEx(&parrots, (Vector2){ 20.0f, 20.0f }, font, "[Parrots font drawing]", (float)font.baseSize, 0.0f, WHITE);
|
||||
ImageDrawTextEx(&parrots, (Vector2){ 20.0f, 20.0f }, font, "[Parrots font drawing]", (float)font.baseSize, 0.0f, RED);
|
||||
|
||||
Texture2D texture = LoadTextureFromImage(parrots); // Image converted to texture, uploaded to GPU memory (VRAM)
|
||||
UnloadImage(parrots); // Once image has been converted to texture and uploaded to VRAM, it can be unloaded from RAM
|
||||
|
@ -37,7 +37,7 @@ static int framesCounter;
|
||||
static int finishScreen;
|
||||
|
||||
const char msgLogoA[64] = "A simple and easy-to-use library";
|
||||
const char msgLogoB[64] = "to learn videogames programming";
|
||||
const char msgLogoB[64] = "to enjoy videogames programming";
|
||||
|
||||
int logoPositionX;
|
||||
int logoPositionY;
|
||||
|
@ -37,7 +37,7 @@ static int framesCounter;
|
||||
static int finishScreen;
|
||||
|
||||
const char msgLogoA[64] = "A simple and easy-to-use library";
|
||||
const char msgLogoB[64] = "to learn videogames programming";
|
||||
const char msgLogoB[64] = "to enjoy videogames programming";
|
||||
|
||||
int logoPositionX;
|
||||
int logoPositionY;
|
||||
|
@ -4,7 +4,7 @@ libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: raylib
|
||||
Description: Simple and easy-to-use library to learn videogames programming
|
||||
Description: Simple and easy-to-use library to enjoy videogames programming
|
||||
URL: http://github.com/raysan5/raylib
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lraylib @PKG_CONFIG_LIBS_EXTRA@
|
||||
|
@ -259,7 +259,7 @@ message(STATUS " GRAPHICS=" ${GRAPHICS})
|
||||
|
||||
# Packaging
|
||||
SET(CPACK_PACKAGE_NAME "raylib")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Simple and easy-to-use library to learn videogames programming")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Simple and easy-to-use library to enjoy videogames programming")
|
||||
SET(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}")
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}")
|
||||
|
@ -45,6 +45,7 @@ option(SUPPORT_FONT_TEXTURE "Draw rectangle shapes using font texture white char
|
||||
option(SUPPORT_QUADS_DRAW_MODE "Use QUADS instead of TRIANGLES for drawing when possible. Some lines-based shapes could still use lines" ON)
|
||||
|
||||
# textures.c
|
||||
option(SUPPORT_IMAGE_EXPORT "Support image exporting to file" ON)
|
||||
option(SUPPORT_IMAGE_GENERATION "Support procedural image generation functionality (gradient, spot, perlin-noise, cellular)" ON)
|
||||
option(SUPPORT_FILEFORMAT_PNG "Support loading PNG as textures" ON)
|
||||
option(SUPPORT_FILEFORMAT_DDS "Support loading DDS as textures" ON)
|
||||
@ -72,8 +73,6 @@ option(SUPPORT_FILEFORMAT_MOD "Support loading MOD for sound" ON)
|
||||
option(SUPPORT_FILEFORMAT_FLAC "Support loading FLAC for sound" ${OFF})
|
||||
|
||||
# utils.c
|
||||
option(SUPPORT_SAVE_PNG "Support saving image data in PNG file format" ON)
|
||||
option(SUPPORT_SAVE_BMP "Support saving image data in BMP file format" ${OFF})
|
||||
option(SUPPORT_TRACELOG "Show TraceLog() output messages. NOTE: By default LOG_DEBUG traces not shown" ON)
|
||||
|
||||
option(SUPPORT_FILEFORMAT_FNT "Support loading fonts in FNT format" ON)
|
||||
|
126
src/audio.c
126
src/audio.c
@ -221,6 +221,9 @@ static Wave LoadOGG(const char *fileName); // Load OGG file
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
static Wave LoadFLAC(const char *fileName); // Load FLAC file
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
static Wave LoadMP3(const char *fileName); // Load MP3 file
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
bool IsFileExtension(const char *fileName, const char *ext); // Check file extension
|
||||
@ -857,6 +860,9 @@ Wave LoadWave(const char *fileName)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
else if (IsFileExtension(fileName, ".flac")) wave = LoadFLAC(fileName);
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
else if (IsFileExtension(fileName, ".mp3")) wave = LoadMP3(fileName);
|
||||
#endif
|
||||
else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName);
|
||||
|
||||
@ -1049,6 +1055,89 @@ void UpdateSound(Sound sound, const void *data, int samplesCount)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Export wave data to file
|
||||
void ExportWave(Wave wave, const char *fileName)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (IsFileExtension(fileName, ".wav"))
|
||||
{
|
||||
// Basic WAV headers structs
|
||||
typedef struct {
|
||||
char chunkID[4];
|
||||
int chunkSize;
|
||||
char format[4];
|
||||
} RiffHeader;
|
||||
|
||||
typedef struct {
|
||||
char subChunkID[4];
|
||||
int subChunkSize;
|
||||
short audioFormat;
|
||||
short numChannels;
|
||||
int sampleRate;
|
||||
int byteRate;
|
||||
short blockAlign;
|
||||
short bitsPerSample;
|
||||
} WaveFormat;
|
||||
|
||||
typedef struct {
|
||||
char subChunkID[4];
|
||||
int subChunkSize;
|
||||
} WaveData;
|
||||
|
||||
RiffHeader riffHeader;
|
||||
WaveFormat waveFormat;
|
||||
WaveData waveData;
|
||||
|
||||
// Fill structs with data
|
||||
riffHeader.chunkID[0] = 'R';
|
||||
riffHeader.chunkID[1] = 'I';
|
||||
riffHeader.chunkID[2] = 'F';
|
||||
riffHeader.chunkID[3] = 'F';
|
||||
riffHeader.chunkSize = 44 - 4 + wave.sampleCount*wave.sampleSize/8;
|
||||
riffHeader.format[0] = 'W';
|
||||
riffHeader.format[1] = 'A';
|
||||
riffHeader.format[2] = 'V';
|
||||
riffHeader.format[3] = 'E';
|
||||
|
||||
waveFormat.subChunkID[0] = 'f';
|
||||
waveFormat.subChunkID[1] = 'm';
|
||||
waveFormat.subChunkID[2] = 't';
|
||||
waveFormat.subChunkID[3] = ' ';
|
||||
waveFormat.subChunkSize = 16;
|
||||
waveFormat.audioFormat = 1;
|
||||
waveFormat.numChannels = wave.channels;
|
||||
waveFormat.sampleRate = wave.sampleRate;
|
||||
waveFormat.byteRate = wave.sampleRate*wave.sampleSize/8;
|
||||
waveFormat.blockAlign = wave.sampleSize/8;
|
||||
waveFormat.bitsPerSample = wave.sampleSize;
|
||||
|
||||
waveData.subChunkID[0] = 'd';
|
||||
waveData.subChunkID[1] = 'a';
|
||||
waveData.subChunkID[2] = 't';
|
||||
waveData.subChunkID[3] = 'a';
|
||||
waveData.subChunkSize = wave.sampleCount*wave.channels*wave.sampleSize/8;
|
||||
|
||||
FILE *wavFile = fopen(fileName, "wb");
|
||||
|
||||
if (wavFile == NULL) return;
|
||||
|
||||
fwrite(&riffHeader, 1, sizeof(RiffHeader), wavFile);
|
||||
fwrite(&waveFormat, 1, sizeof(WaveFormat), wavFile);
|
||||
fwrite(&waveData, 1, sizeof(WaveData), wavFile);
|
||||
|
||||
fwrite(wave.data, 1, wave.sampleCount*wave.channels*wave.sampleSize/8, wavFile);
|
||||
|
||||
fclose(wavFile);
|
||||
|
||||
success = true;
|
||||
}
|
||||
else if (IsFileExtension(fileName, ".raw")) { } // TODO: Support additional file formats to export wave sample data
|
||||
|
||||
if (success) TraceLog(LOG_INFO, "Wave exported successfully: %s", fileName);
|
||||
else TraceLog(LOG_WARNING, "Wave could not be exported.");
|
||||
}
|
||||
|
||||
// Play a sound
|
||||
void PlaySound(Sound sound)
|
||||
{
|
||||
@ -1565,6 +1654,9 @@ void StopMusicStream(Music music)
|
||||
#if defined(SUPPORT_FILEFORMAT_FLAC)
|
||||
case MUSIC_AUDIO_FLAC: /* TODO: Restart FLAC context */ break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
case MUSIC_AUDIO_MP3: /* TODO: Restart MP3 context */ break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
case MUSIC_MODULE_XM: /* TODO: Restart XM context */ break;
|
||||
#endif
|
||||
@ -1705,6 +1797,13 @@ void UpdateMusicStream(Music music)
|
||||
|
||||
} break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
case MUSIC_AUDIO_MP3:
|
||||
{
|
||||
// NOTE: Returns the number of samples to process
|
||||
unsigned int numSamplesMp3 = (unsigned int)drmp3_read_f32(&music->ctxMp3, samplesCount*music->stream.channels, (float *)pcm);
|
||||
} break;
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
case MUSIC_MODULE_XM: jar_xm_generate_samples_16bit(music->ctxXm, pcm, samplesCount); break;
|
||||
#endif
|
||||
@ -2294,6 +2393,33 @@ static Wave LoadFLAC(const char *fileName)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_MP3)
|
||||
// Load MP3 file into Wave structure
|
||||
// NOTE: Using dr_mp3 library
|
||||
static Wave LoadMP3(const char *fileName)
|
||||
{
|
||||
Wave wave;
|
||||
|
||||
// Decode an entire MP3 file in one go
|
||||
uint64_t totalSampleCount;
|
||||
drmp3_config *config;
|
||||
wave.data = drmp3_open_and_decode_file_f32(fileName, config, &totalSampleCount);
|
||||
|
||||
wave.channels = config->outputChannels;
|
||||
wave.sampleRate = config->outputSampleRate;
|
||||
wave.sampleCount = (int)totalSampleCount/wave.channels;
|
||||
wave.sampleSize = 16;
|
||||
|
||||
// NOTE: Only support up to 2 channels (mono, stereo)
|
||||
if (wave.channels > 2) TraceLog(LOG_WARNING, "[%s] MP3 channels number (%i) not supported", fileName, wave.channels);
|
||||
|
||||
if (wave.data == NULL) TraceLog(LOG_WARNING, "[%s] MP3 data could not be loaded", fileName);
|
||||
else TraceLog(LOG_INFO, "[%s] MP3 file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo");
|
||||
|
||||
return wave;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Some required functions for audio standalone module version
|
||||
#if defined(AUDIO_STANDALONE)
|
||||
// Check file extension
|
||||
|
@ -86,6 +86,8 @@
|
||||
//#define SUPPORT_FILEFORMAT_PKM 1
|
||||
//#define SUPPORT_FILEFORMAT_PVR 1
|
||||
|
||||
// Support image export functionality (.png, .bmp, .tga, .jpg)
|
||||
#define SUPPORT_IMAGE_EXPORT 1
|
||||
// Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
|
||||
// If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()
|
||||
#define SUPPORT_IMAGE_MANIPULATION 1
|
||||
@ -133,10 +135,6 @@
|
||||
// Show TraceLog() output messages
|
||||
// NOTE: By default LOG_DEBUG traces not shown
|
||||
#define SUPPORT_TRACELOG 1
|
||||
// Support saving image data fileformats
|
||||
// NOTE: Requires stb_image_write library
|
||||
#define SUPPORT_SAVE_PNG 1
|
||||
//#define SUPPORT_SAVE_BMP 1
|
||||
|
||||
|
||||
#endif //defined(RAYLIB_CMAKE)
|
||||
|
@ -41,6 +41,9 @@
|
||||
#cmakedefine SUPPORT_FILEFORMAT_PKM 1
|
||||
#cmakedefine SUPPORT_FILEFORMAT_PVR 1
|
||||
|
||||
// Support image export functionality (.png, .bmp, .tga, .jpg)
|
||||
#define SUPPORT_IMAGE_EXPORT 1
|
||||
|
||||
/* Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop... If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT() */
|
||||
#cmakedefine SUPPORT_IMAGE_MANIPULATION 1
|
||||
|
||||
|
@ -886,7 +886,7 @@ void EndDrawing(void)
|
||||
// Wait for some milliseconds...
|
||||
if (frameTime < targetTime)
|
||||
{
|
||||
Wait( (float)(targetTime - frameTime)*1000.0f);
|
||||
Wait((float)(targetTime - frameTime)*1000.0f);
|
||||
|
||||
currentTime = GetTime();
|
||||
double extraTime = currentTime - previousTime;
|
||||
@ -1297,7 +1297,9 @@ void TakeScreenshot(const char *fileName)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||
unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight);
|
||||
SavePNG(fileName, imgData, renderWidth, renderHeight, 4); // Save image as PNG
|
||||
|
||||
Image image = { imgData, renderWidth, renderHeight, 1, UNCOMPRESSED_R8G8B8A8 };
|
||||
ExportImage(image, fileName);
|
||||
free(imgData);
|
||||
|
||||
TraceLog(LOG_INFO, "Screenshot taken: %s", fileName);
|
||||
|
2023
src/external/cgltf.h
vendored
Normal file
2023
src/external/cgltf.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1851
src/external/mini_al.h
vendored
1851
src/external/mini_al.h
vendored
File diff suppressed because it is too large
Load Diff
174
src/models.c
174
src/models.c
@ -5,10 +5,10 @@
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define SUPPORT_FILEFORMAT_OBJ
|
||||
* Selected desired fileformats to be supported for loading.
|
||||
*
|
||||
* #define SUPPORT_FILEFORMAT_MTL
|
||||
* Selected desired fileformats to be supported for loading.
|
||||
* #define SUPPORT_FILEFORMAT_IQM
|
||||
* #define SUPPORT_FILEFORMAT_GLTF
|
||||
* Selected desired fileformats to be supported for model data loading.
|
||||
*
|
||||
* #define SUPPORT_MESH_GENERATION
|
||||
* Support procedural mesh generation functions, uses external par_shapes.h library
|
||||
@ -48,8 +48,20 @@
|
||||
|
||||
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
||||
|
||||
#define PAR_SHAPES_IMPLEMENTATION
|
||||
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
||||
#if defined(SUPPORT_FILEFORMAT_IQM)
|
||||
#define RIQM_IMPLEMENTATION
|
||||
#include "external/riqm.h" // IQM file format loading
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||
#define CGLTF_IMPLEMENTATION
|
||||
#include "external/cgltf.h" // glTF file format loading
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_MESH_GENERATION)
|
||||
#define PAR_SHAPES_IMPLEMENTATION
|
||||
#include "external/par_shapes.h" // Shapes 3d parametric generation
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
@ -75,6 +87,12 @@ static Mesh LoadOBJ(const char *fileName); // Load OBJ mesh data
|
||||
#if defined(SUPPORT_FILEFORMAT_MTL)
|
||||
static Material LoadMTL(const char *fileName); // Load MTL material data
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||
static Mesh LoadIQM(const char *fileName); // Load IQM mesh data
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||
static Mesh LoadGLTF(const char *fileName); // Load GLTF mesh data
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
@ -646,45 +664,54 @@ void UnloadMesh(Mesh *mesh)
|
||||
rlUnloadMesh(mesh);
|
||||
}
|
||||
|
||||
// Export mesh as an OBJ file
|
||||
void ExportMesh(const char *fileName, Mesh mesh)
|
||||
// Export mesh data to file
|
||||
void ExportMesh(Mesh mesh, const char *fileName)
|
||||
{
|
||||
FILE *objFile = fopen(fileName, "wt");
|
||||
bool success = false;
|
||||
|
||||
fprintf(objFile, "# raylib Mesh OBJ exporter v1.0\n\n");
|
||||
fprintf(objFile, "# Mesh exported as triangle faces and not optimized.\n");
|
||||
fprintf(objFile, "# Vertex Count: %i\n", mesh.vertexCount);
|
||||
fprintf(objFile, "# Triangle Count: %i\n\n", mesh.triangleCount);
|
||||
fprintf(objFile, "# LICENSE: zlib/libpng\n");
|
||||
fprintf(objFile, "# Copyright (c) 2018 Ramon Santamaria (@raysan5)\n\n");
|
||||
|
||||
fprintf(objFile, "g mesh\n");
|
||||
|
||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
||||
if (IsFileExtension(fileName, ".obj"))
|
||||
{
|
||||
fprintf(objFile, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);
|
||||
FILE *objFile = fopen(fileName, "wt");
|
||||
|
||||
fprintf(objFile, "# raylib Mesh OBJ exporter v1.0\n\n");
|
||||
fprintf(objFile, "# Mesh exported as triangle faces and not optimized.\n");
|
||||
fprintf(objFile, "# Vertex Count: %i\n", mesh.vertexCount);
|
||||
fprintf(objFile, "# Triangle Count: %i\n\n", mesh.triangleCount);
|
||||
fprintf(objFile, "# LICENSE: zlib/libpng\n");
|
||||
fprintf(objFile, "# Copyright (c) 2018 Ramon Santamaria (@raysan5)\n\n");
|
||||
|
||||
fprintf(objFile, "g mesh\n");
|
||||
|
||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
||||
{
|
||||
fprintf(objFile, "v %.2f %.2f %.2f\n", mesh.vertices[v], mesh.vertices[v + 1], mesh.vertices[v + 2]);
|
||||
}
|
||||
|
||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)
|
||||
{
|
||||
fprintf(objFile, "vt %.2f %.2f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);
|
||||
}
|
||||
|
||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
||||
{
|
||||
fprintf(objFile, "vn %.2f %.2f %.2f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh.triangleCount; i += 3)
|
||||
{
|
||||
fprintf(objFile, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2);
|
||||
}
|
||||
|
||||
fprintf(objFile, "\n");
|
||||
|
||||
fclose(objFile);
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 2)
|
||||
{
|
||||
fprintf(objFile, "vt %.2f %.2f\n", mesh.texcoords[v], mesh.texcoords[v + 1]);
|
||||
}
|
||||
|
||||
for (int i = 0, v = 0; i < mesh.vertexCount; i++, v += 3)
|
||||
{
|
||||
fprintf(objFile, "vn %.2f %.2f %.2f\n", mesh.normals[v], mesh.normals[v + 1], mesh.normals[v + 2]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < mesh.triangleCount; i += 3)
|
||||
{
|
||||
fprintf(objFile, "f %i/%i/%i %i/%i/%i %i/%i/%i\n", i, i, i, i + 1, i + 1, i + 1, i + 2, i + 2, i + 2);
|
||||
}
|
||||
|
||||
fprintf(objFile, "\n");
|
||||
|
||||
fclose(objFile);
|
||||
else if (IsFileExtension(fileName, ".raw")) { } // TODO: Support additional file formats to export mesh vertex data
|
||||
|
||||
TraceLog(LOG_INFO, "Mesh saved: %s", fileName);
|
||||
if (success) TraceLog(LOG_INFO, "Mesh exported successfully: %s", fileName);
|
||||
else TraceLog(LOG_WARNING, "Mesh could not be exported.");
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_MESH_GENERATION)
|
||||
@ -699,7 +726,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
|
||||
resZ++;
|
||||
|
||||
// Vertices definition
|
||||
int vertexCount = resX*resZ*6; // 6 vertex by quad
|
||||
int vertexCount = resX*resZ; // vertices get reused for the faces
|
||||
|
||||
Vector3 *vertices = (Vector3 *)malloc(vertexCount*sizeof(Vector3));
|
||||
for (int z = 0; z < resZ; z++)
|
||||
@ -718,7 +745,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
|
||||
Vector3 *normals = (Vector3 *)malloc(vertexCount*sizeof(Vector3));
|
||||
for (int n = 0; n < vertexCount; n++) normals[n] = (Vector3){ 0.0f, 1.0f, 0.0f }; // Vector3.up;
|
||||
|
||||
// TexCoords definition
|
||||
// TexCoords definition
|
||||
Vector2 *texcoords = (Vector2 *)malloc(vertexCount*sizeof(Vector2));
|
||||
for (int v = 0; v < resZ; v++)
|
||||
{
|
||||
@ -741,7 +768,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
|
||||
triangles[t++] = i + 1;
|
||||
triangles[t++] = i;
|
||||
|
||||
triangles[t++] = i + resX;
|
||||
triangles[t++] = i + resX;
|
||||
triangles[t++] = i + resX + 1;
|
||||
triangles[t++] = i + 1;
|
||||
}
|
||||
@ -2206,9 +2233,8 @@ void MeshBinormals(Mesh *mesh)
|
||||
Vector3 tangent = { mesh->tangents[i*4 + 0], mesh->tangents[i*4 + 1], mesh->tangents[i*4 + 2] };
|
||||
float tangentW = mesh->tangents[i*4 + 3];
|
||||
|
||||
|
||||
// TODO: Register computed binormal in mesh->binormal ?
|
||||
// Vector3 binormal = Vector3Multiply( Vector3CrossProduct( normal, tangent ), tangentW );
|
||||
// Vector3 binormal = Vector3Multiply(Vector3CrossProduct(normal, tangent), tangentW);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2222,7 +2248,7 @@ static Mesh LoadOBJ(const char *fileName)
|
||||
{
|
||||
Mesh mesh = { 0 };
|
||||
|
||||
char dataType;
|
||||
char dataType = 0;
|
||||
char comments[200];
|
||||
|
||||
int vertexCount = 0;
|
||||
@ -2245,7 +2271,7 @@ static Mesh LoadOBJ(const char *fileName)
|
||||
// NOTE: faces MUST be defined as TRIANGLES (3 vertex per face)
|
||||
while (!feof(objFile))
|
||||
{
|
||||
dataType = '\0';
|
||||
dataType = 0;
|
||||
fscanf(objFile, "%c", &dataType);
|
||||
|
||||
switch (dataType)
|
||||
@ -2631,3 +2657,59 @@ static Material LoadMTL(const char *fileName)
|
||||
return material;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||
// Load IQM mesh data
|
||||
static Mesh LoadIQM(const char *fileName)
|
||||
{
|
||||
Mesh mesh = { 0 };
|
||||
|
||||
// TODO: Load IQM file
|
||||
|
||||
return mesh;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_GLTF)
|
||||
// Load GLTF mesh data
|
||||
static Mesh LoadGLTF(const char *fileName)
|
||||
{
|
||||
Mesh mesh = { 0 };
|
||||
|
||||
// GLTF file loading
|
||||
FILE *gltfFile = fopen(fileName, "rb");
|
||||
|
||||
if (gltfFile == NULL)
|
||||
{
|
||||
TraceLog(LOG_WARNING, "[%s] GLTF file could not be opened", fileName);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
fseek(gltfFile, 0, SEEK_END);
|
||||
int size = ftell(gltfFile);
|
||||
fseek(gltfFile, 0, SEEK_SET);
|
||||
|
||||
void *buffer = malloc(size);
|
||||
fread(buffer, size, 1, gltfFile);
|
||||
|
||||
fclose(gltfFile);
|
||||
|
||||
// GLTF data loading
|
||||
cgltf_options options = {0};
|
||||
cgltf_data data;
|
||||
cgltf_result result = cgltf_parse(&options, buffer, size, &data);
|
||||
|
||||
if (result == cgltf_result_success)
|
||||
{
|
||||
printf("Type: %u\n", data.file_type);
|
||||
printf("Version: %d\n", data.version);
|
||||
printf("Meshes: %lu\n", data.meshes_count);
|
||||
}
|
||||
else TraceLog(LOG_WARNING, "[%s] GLTF data could not be loaded", fileName);
|
||||
|
||||
free(buffer);
|
||||
cgltf_free(&data);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
#endif
|
||||
|
17
src/raylib.h
17
src/raylib.h
@ -1,6 +1,6 @@
|
||||
/**********************************************************************************************
|
||||
*
|
||||
* raylib - A simple and easy-to-use library to learn videogames programming (www.raylib.com)
|
||||
* raylib - A simple and easy-to-use library to enjoy videogames programming (www.raylib.com)
|
||||
*
|
||||
* FEATURES:
|
||||
* - NO external dependencies, all required libraries included with raylib
|
||||
@ -442,6 +442,7 @@ typedef struct RenderTexture2D {
|
||||
// RenderTexture type, same as RenderTexture2D
|
||||
typedef RenderTexture2D RenderTexture;
|
||||
|
||||
// N-Patch layout info
|
||||
typedef struct NPatchInfo {
|
||||
Rectangle sourceRec; // Region in the texture
|
||||
int left; // left border offset
|
||||
@ -720,6 +721,13 @@ typedef enum {
|
||||
WRAP_MIRROR
|
||||
} TextureWrapMode;
|
||||
|
||||
// Font type, defines generation method
|
||||
typedef enum {
|
||||
FONT_DEFAULT = 0, // Default font generation, anti-aliased
|
||||
FONT_BITMAP, // Bitmap font generation, no anti-aliasing
|
||||
FONT_SDF // SDF font generation, requires external shader
|
||||
} FontType;
|
||||
|
||||
// Color blending modes (pre-defined)
|
||||
typedef enum {
|
||||
BLEND_ALPHA = 0,
|
||||
@ -980,7 +988,7 @@ RLAPI Image LoadImage(const char *fileName);
|
||||
RLAPI Image LoadImageEx(Color *pixels, int width, int height); // Load image from Color array data (RGBA - 32bit)
|
||||
RLAPI Image LoadImagePro(void *data, int width, int height, int format); // Load image from raw data with parameters
|
||||
RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image from RAW file data
|
||||
RLAPI void ExportImage(const char *fileName, Image image); // Export image as a PNG file
|
||||
RLAPI void ExportImage(Image image, const char *fileName); // Export image data to file
|
||||
RLAPI Texture2D LoadTexture(const char *fileName); // Load texture from file into GPU memory (VRAM)
|
||||
RLAPI Texture2D LoadTextureFromImage(Image image); // Load texture from image data
|
||||
RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load texture for rendering (framebuffer)
|
||||
@ -1055,7 +1063,7 @@ RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle
|
||||
RLAPI Font GetFontDefault(void); // Get the default Font
|
||||
RLAPI Font LoadFont(const char *fileName); // Load font from file into GPU memory (VRAM)
|
||||
RLAPI Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load font from file with extended parameters
|
||||
RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf); // Load font data for further use
|
||||
RLAPI CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, int type); // Load font data for further use
|
||||
RLAPI Image GenImageFontAtlas(CharInfo *chars, int fontSize, int charsCount, int padding, int packMethod); // Generate image font atlas using chars info
|
||||
RLAPI void UnloadFont(Font font); // Unload Font from GPU memory (VRAM)
|
||||
|
||||
@ -1105,7 +1113,7 @@ RLAPI void UnloadModel(Model model);
|
||||
// Mesh loading/unloading functions
|
||||
RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file
|
||||
RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM)
|
||||
RLAPI void ExportMesh(const char *fileName, Mesh mesh); // Export mesh as an OBJ file
|
||||
RLAPI void ExportMesh(Mesh mesh, const char *fileName); // Export mesh data to file
|
||||
|
||||
// Mesh manipulation functions
|
||||
RLAPI BoundingBox MeshBoundingBox(Mesh mesh); // Compute mesh bounding box limits
|
||||
@ -1213,6 +1221,7 @@ RLAPI Sound LoadSoundFromWave(Wave wave); // Load so
|
||||
RLAPI void UpdateSound(Sound sound, const void *data, int samplesCount);// Update sound buffer with new data
|
||||
RLAPI void UnloadWave(Wave wave); // Unload wave data
|
||||
RLAPI void UnloadSound(Sound sound); // Unload sound
|
||||
RLAPI void ExportWave(Wave wave, const char *fileName); // Export wave data to file
|
||||
|
||||
// Wave/Sound management functions
|
||||
RLAPI void PlaySound(Sound sound); // Play a sound
|
||||
|
@ -229,6 +229,13 @@ RMDEF Vector2 Vector2Scale(Vector2 v, float scale)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Multiply vector by vector
|
||||
RMDEF Vector2 Vector2MultiplyV(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
Vector2 result = { v1.x*v2.x, v1.y*v2.y };
|
||||
return result;
|
||||
}
|
||||
|
||||
// Negate vector
|
||||
RMDEF Vector2 Vector2Negate(Vector2 v)
|
||||
{
|
||||
@ -243,6 +250,13 @@ RMDEF Vector2 Vector2Divide(Vector2 v, float div)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Divide vector by vector
|
||||
RMDEF Vector2 Vector2DivideV(Vector2 v1, Vector2 v2)
|
||||
{
|
||||
Vector2 result = { v1.x/v2.x, v1.y/v2.y };
|
||||
return result;
|
||||
}
|
||||
|
||||
// Normalize provided vector
|
||||
RMDEF Vector2 Vector2Normalize(Vector2 v)
|
||||
{
|
||||
@ -378,6 +392,20 @@ RMDEF Vector3 Vector3Negate(Vector3 v)
|
||||
return result;
|
||||
}
|
||||
|
||||
// Divide vector by a float value
|
||||
RMDEF Vector3 Vector3Divide(Vector3 v, float div)
|
||||
{
|
||||
Vector3 result = { v.x / div, v.y / div, v.z / div };
|
||||
return result;
|
||||
}
|
||||
|
||||
// Divide vector by vector
|
||||
RMDEF Vector3 Vector3DivideV(Vector3 v1, Vector3 v2)
|
||||
{
|
||||
Vector3 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z };
|
||||
return result;
|
||||
}
|
||||
|
||||
// Normalize provided vector
|
||||
RMDEF Vector3 Vector3Normalize(Vector3 v)
|
||||
{
|
||||
|
46
src/text.c
46
src/text.c
@ -86,9 +86,6 @@ static Font LoadImageFont(Image image, Color key, int firstChar); // Load a Imag
|
||||
#if defined(SUPPORT_FILEFORMAT_FNT)
|
||||
static Font LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||
#endif
|
||||
#if defined(SUPPORT_FILEFORMAT_TTF)
|
||||
//static Font LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_DEFAULT_FONT)
|
||||
extern void LoadDefaultFont(void);
|
||||
@ -221,7 +218,7 @@ extern void LoadDefaultFont(void)
|
||||
defaultFont.chars[i].value = 32 + i; // First char is 32
|
||||
|
||||
defaultFont.chars[i].rec.x = (float)currentPosX;
|
||||
defaultFont.chars[i].rec.y = (float)charsDivisor + currentLine*(charsHeight + charsDivisor);
|
||||
defaultFont.chars[i].rec.y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
|
||||
defaultFont.chars[i].rec.width = (float)charsWidth[i];
|
||||
defaultFont.chars[i].rec.height = (float)charsHeight;
|
||||
|
||||
@ -234,7 +231,7 @@ extern void LoadDefaultFont(void)
|
||||
testPosX = currentPosX;
|
||||
|
||||
defaultFont.chars[i].rec.x = (float)charsDivisor;
|
||||
defaultFont.chars[i].rec.y = (float)charsDivisor + currentLine*(charsHeight + charsDivisor);
|
||||
defaultFont.chars[i].rec.y = (float)(charsDivisor + currentLine*(charsHeight + charsDivisor));
|
||||
}
|
||||
else currentPosX = testPosX;
|
||||
|
||||
@ -244,7 +241,7 @@ extern void LoadDefaultFont(void)
|
||||
defaultFont.chars[i].advanceX = 0;
|
||||
}
|
||||
|
||||
defaultFont.baseSize = (int) defaultFont.chars[0].rec.height;
|
||||
defaultFont.baseSize = (int)defaultFont.chars[0].rec.height;
|
||||
|
||||
TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id);
|
||||
}
|
||||
@ -283,7 +280,7 @@ Font LoadFont(const char *fileName)
|
||||
{
|
||||
font.baseSize = DEFAULT_TTF_FONTSIZE;
|
||||
font.charsCount = DEFAULT_TTF_NUMCHARS;
|
||||
font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, false);
|
||||
font.chars = LoadFontData(fileName, font.baseSize, NULL, font.charsCount, FONT_DEFAULT);
|
||||
Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 4, 0);
|
||||
font.texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
@ -319,8 +316,8 @@ Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontCha
|
||||
|
||||
font.baseSize = fontSize;
|
||||
font.charsCount = (charsCount > 0) ? charsCount : 95;
|
||||
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, false);
|
||||
Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 0, 0);
|
||||
font.chars = LoadFontData(fileName, font.baseSize, fontChars, font.charsCount, FONT_DEFAULT);
|
||||
Image atlas = GenImageFontAtlas(font.chars, font.charsCount, font.baseSize, 2, 0);
|
||||
font.texture = LoadTextureFromImage(atlas);
|
||||
UnloadImage(atlas);
|
||||
|
||||
@ -329,7 +326,7 @@ Font LoadFontEx(const char *fileName, int fontSize, int charsCount, int *fontCha
|
||||
|
||||
// Load font data for further use
|
||||
// NOTE: Requires TTF font and can generate SDF data
|
||||
CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, bool sdf)
|
||||
CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int charsCount, int type)
|
||||
{
|
||||
// NOTE: Using some SDF generation default values,
|
||||
// trades off precision with ability to handle *smaller* sizes
|
||||
@ -337,6 +334,8 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
|
||||
#define SDF_ON_EDGE_VALUE 128
|
||||
#define SDF_PIXEL_DIST_SCALE 64.0f
|
||||
|
||||
#define BITMAP_ALPHA_THRESHOLD 80
|
||||
|
||||
// In case no chars count provided, default to 95
|
||||
charsCount = (charsCount > 0) ? charsCount : 95;
|
||||
|
||||
@ -367,8 +366,6 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
|
||||
// NOTE: ascent is equivalent to font baseline
|
||||
int ascent, descent, lineGap;
|
||||
stbtt_GetFontVMetrics(&fontInfo, &ascent, &descent, &lineGap);
|
||||
ascent *= (int) scaleFactor;
|
||||
descent *= (int) scaleFactor;
|
||||
|
||||
// Fill fontChars in case not provided externally
|
||||
// NOTE: By default we fill charsCount consecutevely, starting at 32 (Space)
|
||||
@ -392,22 +389,33 @@ CharInfo *LoadFontData(const char *fileName, int fontSize, int *fontChars, int c
|
||||
// stbtt_GetCodepointBitmapBox() -- how big the bitmap must be
|
||||
// stbtt_MakeCodepointBitmap() -- renders into bitmap you provide
|
||||
|
||||
if (!sdf) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
if (type != FONT_SDF) chars[i].data = stbtt_GetCodepointBitmap(&fontInfo, scaleFactor, scaleFactor, ch, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
else if (ch != 32) chars[i].data = stbtt_GetCodepointSDF(&fontInfo, scaleFactor, ch, SDF_CHAR_PADDING, SDF_ON_EDGE_VALUE, SDF_PIXEL_DIST_SCALE, &chw, &chh, &chars[i].offsetX, &chars[i].offsetY);
|
||||
|
||||
if (type == FONT_BITMAP)
|
||||
{
|
||||
// Aliased bitmap (black & white) font generation, avoiding anti-aliasing
|
||||
// NOTE: For optimum results, bitmap font should be generated at base pixel size
|
||||
for (int p = 0; p < chw*chh; p++)
|
||||
{
|
||||
if (chars[i].data[p] < BITMAP_ALPHA_THRESHOLD) chars[i].data[p] = 0;
|
||||
else chars[i].data[p] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
chars[i].rec.width = (float)chw;
|
||||
chars[i].rec.height = (float)chh;
|
||||
chars[i].offsetY += ascent;
|
||||
chars[i].offsetY += (int)((float)ascent*scaleFactor);
|
||||
|
||||
// Get bounding box for character (may be offset to account for chars that dip above or below the line)
|
||||
int chX1, chY1, chX2, chY2;
|
||||
stbtt_GetCodepointBitmapBox(&fontInfo, ch, scaleFactor, scaleFactor, &chX1, &chY1, &chX2, &chY2);
|
||||
|
||||
TraceLog(LOG_DEBUG, "Character box measures: %i, %i, %i, %i", chX1, chY1, chX2 - chX1, chY2 - chY1);
|
||||
TraceLog(LOG_DEBUG, "Character offsetY: %i", ascent + chY1);
|
||||
TraceLog(LOG_DEBUG, "Character offsetY: %i", (int)((float)ascent*scaleFactor) + chY1);
|
||||
|
||||
stbtt_GetCodepointHMetrics(&fontInfo, ch, &chars[i].advanceX, NULL);
|
||||
chars[i].advanceX *= (int) scaleFactor;
|
||||
chars[i].advanceX *= scaleFactor;
|
||||
}
|
||||
|
||||
free(fontBuffer);
|
||||
@ -660,11 +668,11 @@ const char *SubText(const char *text, int position, int length)
|
||||
|
||||
for (int c = 0 ; c < length ; c++)
|
||||
{
|
||||
*(buffer+c) = *(text+position);
|
||||
*(buffer + c) = *(text + position);
|
||||
text++;
|
||||
}
|
||||
|
||||
*(buffer+length) = '\0';
|
||||
*(buffer + length) = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@ -887,7 +895,7 @@ static Font LoadImageFont(Image image, Color key, int firstChar)
|
||||
spriteFont.chars[i].advanceX = 0;
|
||||
}
|
||||
|
||||
spriteFont.baseSize = (int) spriteFont.chars[0].rec.height;
|
||||
spriteFont.baseSize = (int)spriteFont.chars[0].rec.height;
|
||||
|
||||
TraceLog(LOG_INFO, "Image file loaded correctly as Font");
|
||||
|
||||
|
@ -19,6 +19,9 @@
|
||||
* Selecte desired fileformats to be supported for image data loading. Some of those formats are
|
||||
* supported by default, to remove support, just comment unrequired #define in this module
|
||||
*
|
||||
* #define SUPPORT_IMAGE_EXPORT
|
||||
* Support image export in multiple file formats
|
||||
*
|
||||
* #define SUPPORT_IMAGE_MANIPULATION
|
||||
* Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop...
|
||||
* If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT()
|
||||
@ -103,6 +106,11 @@
|
||||
// NOTE: Used to read image data (multiple formats support)
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_IMAGE_EXPORT)
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "external/stb_image_write.h" // Required for: stbi_write_*()
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_IMAGE_MANIPULATION)
|
||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8()
|
||||
@ -706,15 +714,32 @@ void UpdateTexture(Texture2D texture, const void *pixels)
|
||||
rlUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels);
|
||||
}
|
||||
|
||||
// Export image as a PNG file
|
||||
void ExportImage(const char *fileName, Image image)
|
||||
// Export image data to file
|
||||
// NOTE: File format depends on fileName extension
|
||||
void ExportImage(Image image, const char *fileName)
|
||||
{
|
||||
int success = 0;
|
||||
|
||||
// NOTE: Getting Color array as RGBA unsigned char values
|
||||
unsigned char *imgData = (unsigned char *)GetImageData(image);
|
||||
|
||||
// NOTE: SavePNG() not supported by some platforms: PLATFORM_WEB, PLATFORM_ANDROID
|
||||
SavePNG(fileName, imgData, image.width, image.height, 4);
|
||||
|
||||
if (IsFileExtension(fileName, ".png")) success = stbi_write_png(fileName, image.width, image.height, 4, imgData, image.width*4);
|
||||
else if (IsFileExtension(fileName, ".bmp")) success = stbi_write_bmp(fileName, image.width, image.height, 4, imgData);
|
||||
else if (IsFileExtension(fileName, ".tga")) success = stbi_write_tga(fileName, image.width, image.height, 4, imgData);
|
||||
else if (IsFileExtension(fileName, ".jpg")) success = stbi_write_jpg(fileName, image.width, image.height, 4, imgData, 80); // Between 1 and 100
|
||||
else if (IsFileExtension(fileName, ".raw"))
|
||||
{
|
||||
// Export raw pixel data
|
||||
// NOTE: It's up to the user to track image parameters
|
||||
FILE *rawFile = fopen(fileName, "wb");
|
||||
fwrite(image.data, GetPixelDataSize(image.width, image.height, image.format), 1, rawFile);
|
||||
fclose(rawFile);
|
||||
}
|
||||
else if (IsFileExtension(fileName, ".h")) { } // TODO: Export pixel data as an array of bytes
|
||||
|
||||
if (success != 0) TraceLog(LOG_INFO, "Image exported successfully: %s", fileName);
|
||||
else TraceLog(LOG_WARNING, "Image could not be exported.");
|
||||
|
||||
free(imgData);
|
||||
}
|
||||
|
||||
@ -1555,7 +1580,9 @@ Image ImageTextEx(Font font, const char *text, float fontSize, float spacing, Co
|
||||
// Define ImageFont struct? or include Image spritefont in Font struct?
|
||||
Image imFont = GetTextureData(font.texture);
|
||||
|
||||
ImageColorTint(&imFont, tint); // Apply color tint to font
|
||||
ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Make sure image format could be properly colored!
|
||||
|
||||
ImageColorTint(&imFont, tint); // Apply color tint to font
|
||||
|
||||
// Create image to store text
|
||||
Image imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK);
|
||||
@ -2827,7 +2854,11 @@ static Image LoadKTX(const char *fileName)
|
||||
// GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
|
||||
|
||||
// KTX file Header (64 bytes)
|
||||
// https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
|
||||
// v1.1 - https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/
|
||||
// v2.0 - http://github.khronos.org/KTX-Specification/
|
||||
|
||||
// TODO: Support KTX 2.2 specs!
|
||||
|
||||
typedef struct {
|
||||
char id[12]; // Identifier: "«KTX 11»\r\n\x1A\n"
|
||||
unsigned int endianness; // Little endian: 0x01 0x02 0x03 0x04
|
||||
|
35
src/utils.c
35
src/utils.c
@ -4,21 +4,10 @@
|
||||
*
|
||||
* CONFIGURATION:
|
||||
*
|
||||
* #define SUPPORT_SAVE_PNG (defined by default)
|
||||
* Support saving image data as PNG fileformat
|
||||
* NOTE: Requires stb_image_write library
|
||||
*
|
||||
* #define SUPPORT_SAVE_BMP
|
||||
* Support saving image data as BMP fileformat
|
||||
* NOTE: Requires stb_image_write library
|
||||
*
|
||||
* #define SUPPORT_TRACELOG
|
||||
* Show TraceLog() output messages
|
||||
* NOTE: By default LOG_DEBUG traces not shown
|
||||
*
|
||||
* DEPENDENCIES:
|
||||
* stb_image_write - BMP/PNG writting functions
|
||||
*
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
@ -62,12 +51,6 @@ FILE *funopen(const void *cookie, int (*readfn)(void *, char *, int),
|
||||
int (*writefn)(void *, const char *, int),
|
||||
fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *));
|
||||
|
||||
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "external/stb_image_write.h" // Required for: stbi_write_bmp(), stbi_write_png()
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -160,24 +143,6 @@ void TraceLog(int msgType, const char *text, ...)
|
||||
#endif // SUPPORT_TRACELOG
|
||||
}
|
||||
|
||||
// Creates a BMP image file from an array of pixel data
|
||||
void SaveBMP(const char *fileName, unsigned char *imgData, int width, int height, int compSize)
|
||||
{
|
||||
#if defined(SUPPORT_SAVE_BMP) && (defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI))
|
||||
stbi_write_bmp(fileName, width, height, compSize, imgData);
|
||||
TraceLog(LOG_INFO, "BMP Image saved: %s", fileName);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Creates a PNG image file from an array of pixel data
|
||||
void SavePNG(const char *fileName, unsigned char *imgData, int width, int height, int compSize)
|
||||
{
|
||||
#if defined(SUPPORT_SAVE_PNG) && (defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI))
|
||||
stbi_write_png(fileName, width, height, compSize, imgData, width*compSize);
|
||||
TraceLog(LOG_INFO, "PNG Image saved: %s", fileName);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Keep track of memory allocated
|
||||
// NOTE: mallocType defines the type of data allocated
|
||||
/*
|
||||
|
11
src/utils.h
11
src/utils.h
@ -32,10 +32,6 @@
|
||||
#include <android/asset_manager.h> // Required for: AAssetManager
|
||||
#endif
|
||||
|
||||
#ifndef SUPPORT_SAVE_PNG
|
||||
#define SUPPORT_SAVE_PNG 1
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Some basic Defines
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -58,13 +54,6 @@ extern "C" { // Prevents name mangling of functions
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
#if defined(SUPPORT_SAVE_BMP)
|
||||
void SaveBMP(const char *fileName, unsigned char *imgData, int width, int height, int compSize);
|
||||
#endif
|
||||
#if defined(SUPPORT_SAVE_PNG)
|
||||
void SavePNG(const char *fileName, unsigned char *imgData, int width, int height, int compSize);
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app
|
||||
FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen()
|
||||
|
Loading…
Reference in New Issue
Block a user