raylib basic folders structure and some files... ;)

This commit is contained in:
Ray 2013-11-18 23:38:44 +01:00
parent cbbf800bb8
commit 46f10b45ad
59 changed files with 18943 additions and 232 deletions

306
src/audio.c Normal file
View file

@ -0,0 +1,306 @@
/*********************************************************************************************
*
* raylib.audio
*
* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
*
* Uses external lib:
* OpenAL - Audio device management lib
* TODO: stb_vorbis - Ogg audio files loading
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "raylib.h"
#include <AL/al.h> // OpenAL basic header
#include <AL/alc.h> // OpenAL context header (like OpenGL, OpenAL requires a context to work)
#include <stdlib.h> // To use exit() function
#include <stdio.h> // Used for .WAV loading
//#include "stb_vorbis.h" // TODO: OGG loading functions
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Wave file data
typedef struct Wave {
unsigned char *data; // Buffer data pointer
unsigned int sampleRate;
unsigned int dataSize;
short channels;
short format;
} Wave;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static Wave LoadWAV(char *fileName);
static void UnloadWAV(Wave wave);
//static Ogg LoadOGG(char *fileName);
//----------------------------------------------------------------------------------
// Module Functions Definition - Window and OpenGL Context Functions
//----------------------------------------------------------------------------------
// Initialize audio device and context
void InitAudioDevice()
{
// Open and initialize a device with default settings
ALCdevice *device = alcOpenDevice(NULL);
if(!device)
{
fprintf(stderr, "Could not open a device!\n");
exit(1);
}
ALCcontext *context = alcCreateContext(device, NULL);
if(context == NULL || alcMakeContextCurrent(context) == ALC_FALSE)
{
if(context != NULL) alcDestroyContext(context);
alcCloseDevice(device);
fprintf(stderr, "Could not set a context!\n");
exit(1);
}
printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
// Listener definition (just for 2D)
alListener3f(AL_POSITION, 0, 0, 0);
alListener3f(AL_VELOCITY, 0, 0, 0);
alListener3f(AL_ORIENTATION, 0, 0, -1);
}
// Close the audio device for the current context, and destroys the context
void CloseAudioDevice()
{
ALCdevice *device;
ALCcontext *context = alcGetCurrentContext();
if (context == NULL) return;
device = alcGetContextsDevice(context);
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
alcCloseDevice(device);
}
// Load sound to memory
Sound LoadSound(char *fileName)
{
Sound sound;
// NOTE: The entire file is loaded to memory to play it all at once (no-streaming)
// WAV file loading
// NOTE: Buffer space is allocated inside LoadWAV, Wave must be freed
Wave wave = LoadWAV(fileName);
ALenum format;
// The OpenAL format is worked out by looking at the number of channels and the bits per sample
if (wave.channels == 1)
{
if (wave.sampleRate == 8 ) format = AL_FORMAT_MONO8;
else if (wave.sampleRate == 16) format = AL_FORMAT_MONO16;
}
else if (wave.channels == 2)
{
if (wave.sampleRate == 8 ) format = AL_FORMAT_STEREO8;
else if (wave.sampleRate == 16) format = AL_FORMAT_STEREO16;
}
// Create an audio source
ALuint source;
alGenSources(1, &source); // Generate pointer to audio source
alSourcef(source, AL_PITCH, 1);
alSourcef(source, AL_GAIN, 1);
alSource3f(source, AL_POSITION, 0, 0, 0);
alSource3f(source, AL_VELOCITY, 0, 0, 0);
alSourcei(source, AL_LOOPING, AL_FALSE);
// Convert loaded data to OpenAL buffer
//----------------------------------------
ALuint buffer;
alGenBuffers(1, &buffer); // Generate pointer to buffer
// Upload sound data to buffer
alBufferData(buffer, format, wave.data, wave.dataSize, wave.sampleRate);
// Attach sound buffer to source
alSourcei(source, AL_BUFFER, buffer);
// Unallocate WAV data
UnloadWAV(wave);
printf("Sample rate: %i\n", wave.sampleRate);
printf("Channels: %i\n", wave.channels);
printf("Format: %i\n", wave.format);
printf("Audio file loaded...!\n");
sound.source = source;
sound.buffer = buffer;
return sound;
}
// Unload sound
void UnloadSound(Sound sound)
{
alDeleteSources(1, &sound.source);
alDeleteBuffers(1, &sound.buffer);
}
// Play a sound
void PlaySound(Sound sound)
{
alSourcePlay(sound.source); // Play the sound
printf("Playing sound!\n");
// Find the current position of the sound being played
// NOTE: Only work when the entire file is in a single buffer
//int byteOffset;
//alGetSourcei(sound.source, AL_BYTE_OFFSET, &byteOffset);
//float seconds = (float)byteOffset / sampleRate; // Number of seconds since the beginning of the sound
}
// Play a sound with extended options
void PlaySoundEx(Sound sound, float timePosition, bool loop)
{
// TODO: Review
// Change the current position (e.g. skip some part of the sound)
// NOTE: Only work when the entire file is in a single buffer
//alSourcei(sound.source, AL_BYTE_OFFSET, int(position * sampleRate));
alSourcePlay(sound.source); // Play the sound
if (loop) alSourcei(sound.source, AL_LOOPING, AL_TRUE);
else alSourcei(sound.source, AL_LOOPING, AL_FALSE);
}
// Pause a sound
void PauseSound(Sound sound)
{
alSourcePause(sound.source);
}
// Stop reproducing a sound
void StopSound(Sound sound)
{
alSourceStop(sound.source);
}
// Load WAV file into Wave structure
static Wave LoadWAV(char *fileName)
{
Wave wave;
FILE *wavFile;
wavFile = fopen(fileName, "rb");
if (!wavFile)
{
printf("Could not load WAV file.\n");
exit(1);
}
unsigned char id[4]; // Four bytes to hold 'RIFF' and 'WAVE' (and other ids)
unsigned int size = 0; // File size (useless)
short format;
short channels;
short blockAlign;
short bitsPerSample;
unsigned int formatLength;
unsigned int sampleRate;
unsigned int avgBytesSec;
unsigned int dataSize;
fread(id, sizeof(unsigned char), 4, wavFile); // Read the first four bytes
if ((id[0] != 'R') || (id[1] != 'I') || (id[2] != 'F') || (id[3] != 'F'))
{
printf("Invalid RIFF file.\n"); // If not "RIFF" id, exit
exit(1);
}
fread(&size, sizeof(unsigned int), 1, wavFile); // Read file size
fread(id, sizeof(unsigned char), 4, wavFile); // Read the next id
if ((id[0] != 'W') || (id[1] != 'A') || (id[2] != 'V') || (id[3] != 'E'))
{
printf("Invalid WAVE file.\n"); // If not "WAVE" id, exit
exit(1);
}
fread(id, sizeof(unsigned char), 4, wavFile); // Read 4 bytes id "fmt "
fread(&formatLength, sizeof(unsigned int),1,wavFile); // Read format lenght
fread(&format, sizeof(short), 1, wavFile); // Read format tag
fread(&channels, sizeof(short), 1, wavFile); // Read num channels (1 mono, 2 stereo)
fread(&sampleRate, sizeof(unsigned int), 1, wavFile); // Read sample rate (44100, 22050, etc...)
fread(&avgBytesSec, sizeof(short), 1, wavFile); // Read average bytes per second (probably won't need this)
fread(&blockAlign, sizeof(short), 1, wavFile); // Read block alignment (probably won't need this)
fread(&bitsPerSample, sizeof(short), 1, wavFile); // Read bits per sample (8 bit or 16 bit)
fread(id, sizeof(unsigned char), 4, wavFile); // Read 4 bytes id "data"
fread(&dataSize, sizeof(unsigned int), 1, wavFile); // Read data size (in bytes)
wave.sampleRate = sampleRate;
wave.dataSize = dataSize;
wave.channels = channels;
wave.format = format;
wave.data = (unsigned char *)malloc(sizeof(unsigned char) * dataSize); // Allocate the required bytes to store data
fread(wave.data, sizeof(unsigned char), dataSize, wavFile); // Read the whole sound data chunk
return wave;
}
// Unload WAV file data
static void UnloadWAV(Wave wave)
{
free(wave.data);
}
// TODO: Ogg data loading
//static Ogg LoadOGG(char *fileName) { }

582
src/core.c Normal file
View file

@ -0,0 +1,582 @@
/*********************************************************************************************
*
* raylib.core
*
* Basic functions to manage Windows, OpenGL context and Input
*
* Uses external lib:
* GLFW3 - Window, context and Input management (static lib version)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "raylib.h"
#include <GLFW/glfw3.h> // GLFW3 lib: Windows, OpenGL context and Input management
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
#include <stdio.h> // Standard input / output lib
#include <stdlib.h> // Declares malloc() and free() for memory management
#include <math.h> // Math related functions, tan() on SetPerspective
#include "vector3.h" // Basic Vector3 functions
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef Color pixel;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static GLFWwindow* window; // Main window
static bool fullscreen; // Fullscreen mode track
static double currentTime, previousTime; // Used to track timmings
static double updateTime, drawTime; // Time measures for update and draw
static double frameTime; // Time measure for one frame
static double targetTime = 0; // Desired time for one frame, if 0 not applied
static int windowWidth, windowHeight; // Required to switch between windowed/fullscren mode (F11)
static char *windowTitle; // Required to switch between windowed/fullscren mode (F11)
//----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core)
//----------------------------------------------------------------------------------
extern void LoadDefaultFont(); // [Module: text] Loads default font on InitWindow()
extern void UnloadDefaultFont(); // [Module: text] Unloads default font from GPU memory
extern void WriteBitmap(const char *fileName, const pixel *imgDataPixel, int width, int height); // [Module: textures] Writes a bitmap (BMP) file
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static void InitGraphicsDevice(); // Initialize Graphics Device (OpenGL stuff)
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
static void WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up); // Setup camera view (updates MODELVIEW matrix)
static void SetPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); // Setup view projection (updates PROJECTION matrix)
static void TakeScreenshot(); // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
//----------------------------------------------------------------------------------
// Module Functions Definition - Window and OpenGL Context Functions
//----------------------------------------------------------------------------------
// Initialize Window and Graphics Context (OpenGL)
void InitWindow(int width, int height, char* title)
{
glfwSetErrorCallback(ErrorCallback);
if (!glfwInit()) exit(1);
//glfwWindowHint(GLFW_SAMPLES, 4); // If called before windows creation, enables multisampling x4 (MSAA), default is 0
window = glfwCreateWindow(width, height, title, NULL, NULL);
windowWidth = width;
windowHeight = height;
windowTitle = title;
if (!window)
{
glfwTerminate();
exit(1);
}
glfwSetWindowSizeCallback(window, WindowSizeCallback);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, KeyCallback);
glfwSwapInterval(0); // Disables GPU v-sync (if set), so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
// If not set, swap interval uses GPU v-sync configuration
// Framerate can be setup using SetTargetFPS()
InitGraphicsDevice();
previousTime = glfwGetTime();
LoadDefaultFont();
}
// Close Window and Terminate Context
void CloseWindow()
{
UnloadDefaultFont();
glfwDestroyWindow(window);
glfwTerminate();
}
// Detect if KEY_ESCAPE pressed or Close icon pressed
bool WindowShouldClose()
{
return (glfwWindowShouldClose(window));
}
// Fullscreen toggle (by default F11)
void ToggleFullscreen()
{
if (glfwGetKey(window, GLFW_KEY_F11))
{
fullscreen = !fullscreen; // Toggle fullscreen flag
glfwDestroyWindow(window); // Destroy the current window (we will recreate it!)
// NOTE: Window aspect ratio is always windowWidth / windowHeight
if (fullscreen) window = glfwCreateWindow(windowWidth, windowHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); // Fullscreen mode
else window = glfwCreateWindow(windowWidth, windowHeight, windowTitle, NULL, NULL);
if (!window)
{
glfwTerminate();
exit(1);
}
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, KeyCallback);
InitGraphicsDevice();
}
}
// Sets Background Color
void ClearBackground(Color color)
{
// Color values clamp to 0.0f(0) and 1.0f(255)
float r = (float)color.r / 255;
float g = (float)color.g / 255;
float b = (float)color.b / 255;
float a = (float)color.a / 255;
glClearColor(r, g, b, a);
}
// Setup drawing canvas to start drawing
void BeginDrawing()
{
currentTime = glfwGetTime(); // glfwGetTime() returns a 'double' containing the number of elapsed seconds since glfwInit() was called
updateTime = currentTime - previousTime;
previousTime = currentTime;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, Depth Buffer is used for 3D
glLoadIdentity(); // Reset current matrix (MODELVIEW)
glTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL
}
// End canvas drawing and Swap Buffers (Double Buffering)
void EndDrawing()
{
glfwSwapBuffers(window); // Swap back and front buffers
glfwPollEvents(); // Register keyboard/mouse events
currentTime = glfwGetTime();
drawTime = currentTime - previousTime;
previousTime = currentTime;
frameTime = updateTime + drawTime;
double extraTime = 0;
while (frameTime < targetTime)
{
// Implement a delay
currentTime = glfwGetTime();
extraTime = currentTime - previousTime;
previousTime = currentTime;
frameTime += extraTime;
}
}
// Initializes 3D mode for drawing (Camera setup)
void Begin3dMode(Camera camera)
{
//glEnable(GL_LIGHTING); // TODO: Setup proper lighting system (raylib 1.x)
glMatrixMode(GL_PROJECTION); // Switch to projection matrix
glPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
glLoadIdentity(); // Reset current matrix (PROJECTION)
SetPerspective(45.0f, (GLfloat)windowWidth/(GLfloat)windowHeight, 0.1f, 100.0f); // Setup perspective projection
glMatrixMode(GL_MODELVIEW); // Switch back to modelview matrix
glLoadIdentity(); // Reset current matrix (MODELVIEW)
CameraLookAt(camera.position, camera.target, camera.up); // Setup Camera view
}
// Ends 3D mode and returns to default 2D orthographic mode
void End3dMode()
{
glMatrixMode(GL_PROJECTION); // Switch to projection matrix
glPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
glMatrixMode(GL_MODELVIEW); // Get back to modelview matrix
glLoadIdentity(); // Reset current matrix (MODELVIEW)
glTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
//glDisable(GL_LIGHTING); // TODO: Setup proper lighting system (raylib 1.x)
}
// Set target FPS for the game
void SetTargetFPS(int fps)
{
targetTime = 1 / (float)fps;
printf("TargetTime per Frame: %f seconds\n", (float)targetTime);
}
// Returns current FPS
float GetFPS()
{
return (1/(float)frameTime);
}
// Returns time in seconds for one frame
float GetFrameTime()
{
// As we are operating quite a lot with frameTime, it could be no stable
// so we round it before before passing around to be used
// NOTE: There are still problems with high framerates (>500fps)
double roundedFrameTime = round(frameTime*10000) / 10000;
return (float)roundedFrameTime; // Time in seconds to run a frame
}
// Returns a Color struct from hexadecimal value
Color GetColor(int hexValue)
{
Color color;
color.r = (unsigned char)(hexValue >> 24) & 0xFF;
color.g = (unsigned char)(hexValue >> 16) & 0xFF;
color.b = (unsigned char)(hexValue >> 8) & 0xFF;
color.a = (unsigned char)hexValue & 0xFF;
return color;
}
// Returns hexadecimal value for a Color
int GetHexValue(Color color)
{
return ((color.a << 24) + (color.r << 16) + (color.g << 8) + color.b);
}
//----------------------------------------------------------------------------------
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
//----------------------------------------------------------------------------------
// Detect if a key is being pressed (key held down)
bool IsKeyPressed(int key)
{
if (glfwGetKey(window, key) == GLFW_PRESS) return true;
else return false;
}
// Detect if a key is NOT being pressed (key not held down)
bool IsKeyReleased(int key)
{
if (glfwGetKey(window, key) == GLFW_RELEASE) return true;
else return false;
}
// Detect if a mouse button is being pressed
bool IsMouseButtonPressed(int button)
{
if (glfwGetMouseButton(window, button) == GLFW_PRESS) return true;
else return false;
}
// Detect if a mouse button is NOT being pressed
bool IsMouseButtonReleased(int button)
{
if (glfwGetMouseButton(window, button) == GLFW_RELEASE) return true;
else return false;
}
// Returns mouse position X
int GetMouseX()
{
double mouseX;
double mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
return (int)mouseX;
}
// Returns mouse position Y
int GetMouseY()
{
double mouseX;
double mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
return (int)mouseY;
}
// Returns mouse position XY
Vector2 GetMousePosition()
{
double mouseX;
double mouseY;
glfwGetCursorPos(window, &mouseX, &mouseY);
Vector2 position = { (float)mouseX, (float)mouseY };
return position;
}
// Detect if a gamepad is available
bool IsGamepadAvailable(int gamepad)
{
int result = glfwJoystickPresent(gamepad);
if (result == 1) return true;
else return false;
}
// Return axis movement vector for a gamepad
Vector2 GetGamepadMovement(int gamepad)
{
Vector2 vec = { 0, 0 };
const float *axes;
int axisCount;
axes = glfwGetJoystickAxes(gamepad, &axisCount);
if (axisCount >= 2)
{
vec.x = axes[0]; // Left joystick X
vec.y = axes[1]; // Left joystick Y
//vec.x = axes[2]; // Right joystick X
//vec.x = axes[3]; // Right joystick Y
}
return vec;
}
// Detect if a gamepad button is being pressed
bool IsGamepadButtonPressed(int gamepad, int button)
{
const unsigned char* buttons;
int buttonsCount;
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
if (buttons[button] == GLFW_PRESS)
{
return true;
}
else return false;
}
// Detect if a gamepad button is NOT being pressed
bool IsGamepadButtonReleased(int gamepad, int button)
{
const unsigned char* buttons;
int buttonsCount;
buttons = glfwGetJoystickButtons(gamepad, &buttonsCount);
if (buttons[button] == GLFW_RELEASE)
{
return true;
}
else return false;
}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
// GLFW3 Error Callback, runs on GLFW3 error
static void ErrorCallback(int error, const char *description)
{
printf(description);
//fprintf(stderr, description);
}
// GLFW3 Keyboard Callback, runs on key pressed
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, GL_TRUE);
// NOTE: Before closing window, while loop must be left!
}
else if (key == GLFW_KEY_F11 && action == GLFW_PRESS)
{
ToggleFullscreen();
}
else if (key == GLFW_KEY_F12 && action == GLFW_PRESS)
{
TakeScreenshot();
}
}
// GLFW3 WindowSize Callback, runs when window is resized
static void WindowSizeCallback(GLFWwindow* window, int width, int height)
{
InitGraphicsDevice(); // If window is resized, graphics device is re-initialized
// NOTE: Aspect ratio does not change, so, image can be deformed
}
// Initialize Graphics Device (OpenGL stuff)
static void InitGraphicsDevice()
{
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set background color (black)
glClearDepth(1.0f); // Clear depth buffer
glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D)
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
glEnable(GL_BLEND); // Enable color blending (required to work with transparencies)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation (Deprecated in OGL 3.0)
// Other options: GL_FASTEST, GL_DONT_CARE (default)
glMatrixMode(GL_PROJECTION); // Switch to PROJECTION matrix
glLoadIdentity(); // Reset current matrix (PROJECTION)
glOrtho(0, fbWidth, fbHeight, 0, 0, 1); // Config orthographic mode: top-left corner --> (0,0)
glMatrixMode(GL_MODELVIEW); // Switch back to MODELVIEW matrix
glLoadIdentity(); // Reset current matrix (MODELVIEW)
glDisable(GL_LIGHTING); // Lighting Disabled...
// TODO: Create an efficient Lighting System with proper functions (raylib 1.x)
/*
glEnable(GL_COLOR_MATERIAL); // Enable materials, causes some glMaterial atributes to track the current color (glColor)...
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // Material types and where to apply them
// NOTE: ONLY works with lighting; defines how light interacts with material
glLightfv(GL_LIGHT1, GL_AMBIENT, lightAmbient); // Define ambient light color property
glLightfv(GL_LIGHT1, GL_DIFFUSE, lightDiffuse); // Define diffuse light color property
glLightfv(GL_LIGHT1, GL_POSITION, lightPosition); // Define light position
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1); // Enable light one (8 lights available at the same time)
*/
// TODO: Review all shapes/models are drawn CCW and enable backface culling
//glEnable(GL_CULL_FACE); // Enable backface culling (Disabled by default)
//glCullFace(GL_BACK); // Cull the Back face (default)
//glFrontFace(GL_CCW); // Front face are defined counter clockwise (default)
glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
}
// Setup camera view (updates MODELVIEW matrix)
static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up)
{
float rotMatrix[16]; // Matrix to store camera rotation
Vector3 rotX, rotY, rotZ; // Vectors to calculate camera rotations X, Y, Z (Euler)
// Construct rotation matrix from vectors
rotZ = VectorSubtract(position, target);
VectorNormalize(&rotZ);
rotY = up; // Y rotation vector
rotX = VectorCrossProduct(rotY, rotZ); // X rotation vector = Y cross Z
rotY = VectorCrossProduct(rotZ, rotX); // Recompute Y rotation = Z cross X
VectorNormalize(&rotX); // X rotation vector normalization
VectorNormalize(&rotY); // Y rotation vector normalization
rotMatrix[0] = rotX.x;
rotMatrix[1] = rotY.x;
rotMatrix[2] = rotZ.x;
rotMatrix[3] = 0.0f;
rotMatrix[4] = rotX.y;
rotMatrix[5] = rotY.y;
rotMatrix[6] = rotZ.y;
rotMatrix[7] = 0.0f;
rotMatrix[8] = rotX.z;
rotMatrix[9] = rotY.z;
rotMatrix[10] = rotZ.z;
rotMatrix[11] = 0.0f;
rotMatrix[12] = 0.0f;
rotMatrix[13] = 0.0f;
rotMatrix[14] = 0.0f;
rotMatrix[15] = 1.0f;
glMultMatrixf(rotMatrix); // Multiply MODELVIEW matrix by rotation matrix
glTranslatef(-position.x, -position.y, -position.z); // Translate eye to position
}
// Setup view projection (updates PROJECTION matrix)
static void SetPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
double xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
// Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
static void TakeScreenshot()
{
static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution
char buffer[20]; // Buffer to store file name
int fbWidth, fbHeight;
Color *imgDataPixel; // Pixel image data array
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
imgDataPixel = (Color *)malloc(fbWidth * fbHeight * sizeof(Color));
// NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
glReadPixels(0, 0, fbWidth, fbHeight, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixel);
sprintf(buffer, "screenshot%03i.bmp", shotNum);
// NOTE: BMP directly stores data flipped vertically
WriteBitmap(buffer, imgDataPixel, fbWidth, fbHeight); // Writes pixel data array into a bitmap (BMP) file
free(imgDataPixel);
shotNum++;
}

819
src/models.c Normal file
View file

@ -0,0 +1,819 @@
/*********************************************************************************************
*
* raylib.models
*
* Basic functions to draw 3d shapes and load/draw 3d models (.OBJ)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <stdio.h> // Standard input/output functions, used to read model files data
#include <stdlib.h> // Declares malloc() and free() for memory management
#include <math.h> // Used for sin, cos, tan
#include "vector3.h" // Basic Vector3 functions
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// ...
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// It's lonely here...
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
// No private (static) functions in this module
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Draw cube
// NOTE: Cube position is de center position
void DrawCube(Vector3 position, float width, float height, float lenght, Color color)
{
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
//glRotatef(rotation, 0.0f, 1.0f, 0.0f);
//glScalef(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a);
// Front Face
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, lenght/2); // Top Left Of The Texture and Quad
// Back Face
glNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer
glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, -lenght/2); // Bottom Left Of The Texture and Quad
// Top Face
glNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, height/2, lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, height/2, lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad
// Bottom Face
glNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down
glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, -height/2, -lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad
// Right face
glNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right
glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, -height/2, -lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, height/2, lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad
// Left Face
glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, height/2, lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad
glEnd();
glPopMatrix();
}
// Draw cube (Vector version)
void DrawCubeV(Vector3 position, Vector3 size, Color color)
{
DrawCube(position, size.x, size.y, size.z, color);
}
// Draw cube wires
void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawCube(position, width, height, lenght, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Draw sphere
void DrawSphere(Vector3 centerPos, float radius, Color color)
{
DrawSphereEx(centerPos, radius, 16, 16, color);
}
// Draw sphere with extended parameters
void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color)
{
float lat0, z0, zr0;
float lat1, z1, zr1;
float lng, x, y;
glPushMatrix();
glTranslatef(centerPos.x, centerPos.y, centerPos.z);
glRotatef(90, 1, 0, 0);
glScalef(radius, radius, radius);
glBegin(GL_QUAD_STRIP);
glColor4ub(color.r, color.g, color.b, color.a);
for(int i = 0; i <= rings; i++)
{
lat0 = PI * (-0.5 + (float)(i - 1) / rings);
z0 = sin(lat0);
zr0 = cos(lat0);
lat1 = PI * (-0.5 + (float)i / rings);
z1 = sin(lat1);
zr1 = cos(lat1);
for(int j = 0; j <= slices; j++)
{
lng = 2 * PI * (float)(j - 1) / slices;
x = cos(lng);
y = sin(lng);
glNormal3f(x * zr0, y * zr0, z0);
glVertex3f(x * zr0, y * zr0, z0);
glNormal3f(x * zr1, y * zr1, z1);
glVertex3f(x * zr1, y * zr1, z1);
}
}
glEnd();
glPopMatrix();
}
// Draw sphere wires
void DrawSphereWires(Vector3 centerPos, float radius, Color color)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawSphere(centerPos, radius, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Draw a cylinder/cone
void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color) // Could be used for pyramid and cone!
{
static int count = 0;
Vector3 a = { position.x, position.y + height, position.z };
Vector3 d = { 0.0f, 1.0f, 0.0f };
Vector3 p;
Vector3 c = { a.x + (-d.x * height), a.y + (-d.y * height), a.z + (-d.z * height) }; //= a + (-d * h);
Vector3 e0 = VectorPerpendicular(d);
Vector3 e1 = VectorCrossProduct(e0, d);
float angInc = 360.0 / slices * DEG2RAD;
if (radiusTop == 0) // Draw pyramid or cone
{
//void drawCone(const Vector3 &d, const Vector3 &a, const float h, const float rd, const int n)
//d axis defined as a normalized vector from base to apex
//a position of apex (top point)
//h height
//rd radius of directrix
//n number of radial "slices"
glPushMatrix();
//glTranslatef(centerPos.x, centerPos.y, centerPos.z);
glRotatef(DEG2RAD*count, 0.0f, 1.0f, 0.0f);
//glScalef(1.0f, 1.0f, 1.0f);
// Draw cone top
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(a.x, a.y, a.z);
for (int i = 0; i <= slices; i++)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
// Draw cone bottom
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(c.x, c.y, c.z);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
glPopMatrix();
}
else // Draw cylinder
{
glPushMatrix();
//glTranslatef(centerPos.x, centerPos.y, centerPos.z);
glRotatef(DEG2RAD*count, 0.0f, 1.0f, 0.0f);
//glScalef(1.0f, 1.0f, 1.0f);
// Draw cylinder top (pointed cap)
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(c.x, c.y + height, c.z);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height;
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
// Draw cylinder sides
glBegin(GL_TRIANGLE_STRIP);
glColor4ub(color.r, color.g, color.b, color.a);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height;
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop);
glVertex3f(p.x, p.y, p.z);
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
// Draw cylinder bottom
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(c.x, c.y, c.z);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
glPopMatrix();
}
count += 1;
}
// Draw a cylinder/cone wires
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawCylinder(position, radiusTop, radiusBottom, height, slices, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Draw a plane
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color)
{
// NOTE: Plane is always created on XZ ground and then rotated
glPushMatrix();
glTranslatef(centerPos.x, centerPos.y, centerPos.z);
// TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions...
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
glScalef(size.x, 1.0f, size.y);
glBegin(GL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, 0.0f, -0.5f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5f, 0.0f, -0.5f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5f, 0.0f, 0.5f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, 0.0f, 0.5f);
glEnd();
glPopMatrix();
}
// Draw a plane with divisions
void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color)
{
float quadWidth = size.x / slicesX;
float quadLenght = size.y / slicesZ;
float texPieceW = 1 / size.x;
float texPieceH = 1 / size.y;
// NOTE: Plane is always created on XZ ground and then rotated
glPushMatrix();
glTranslatef(-size.x / 2, 0.0f, -size.y / 2);
glTranslatef(centerPos.x, centerPos.y, centerPos.z);
// TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions...
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
glBegin(GL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a);
glNormal3f(0.0f, 1.0f, 0.0f);
for (int z = 0; z < slicesZ; z++)
{
for (int x = 0; x < slicesX; x++)
{
// Draw the plane quad by quad (with textcoords)
glTexCoord2f((float)x * texPieceW, (float)z * texPieceH);
glVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght);
glTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH);
glVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght);
glTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH);
glVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght);
glTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH);
glVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght);
}
}
glEnd();
glPopMatrix();
}
// Draw a grid centered at (0, 0, 0)
void DrawGrid(int slices, float spacing)
{
int halfSlices = slices / 2;
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
glPushMatrix();
glScalef(spacing, 1.0f, spacing);
glBegin(GL_LINES);
for(int i = -halfSlices; i <= halfSlices; i++)
{
if (i == 0) glColor3f(0.5f, 0.5f, 0.5f);
else glColor3f(0.75f, 0.75f, 0.75f);
glVertex3f((float)i, 0.0f, (float)-halfSlices);
glVertex3f((float)i, 0.0f, (float)halfSlices);
glVertex3f((float)-halfSlices, 0.0f, (float)i);
glVertex3f((float)halfSlices, 0.0f, (float)i);
}
glEnd();
glPopMatrix();
//glDisable(GL_LINE_SMOOTH);
}
// Draw gizmo (with or without orbits)
void DrawGizmo(Vector3 position, bool orbits)
{
// NOTE: RGB = XYZ
float lenght = 1.0f;
float radius = 1.0f;
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
//glRotatef(rotation, 0, 1, 0);
glScalef(lenght, lenght, lenght);
glBegin(GL_LINES);
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 1.0f);
glEnd();
if (orbits)
{
glBegin(GL_LINE_LOOP);
glColor4f(1.0f, 0.0f, 0.0f, 0.4f);
for (int i=0; i < 360; i++) glVertex3f(sin(DEG2RAD*i) * radius, 0, cos(DEG2RAD*i) * radius);
glEnd();
glBegin(GL_LINE_LOOP);
glColor4f(0.0f, 1.0f, 0.0f, 0.4f);
for (int i=0; i < 360; i++) glVertex3f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius, 0);
glEnd();
glBegin(GL_LINE_LOOP);
glColor4f(0.0f, 0.0f, 1.0f, 0.4f);
for (int i=0; i < 360; i++) glVertex3f(0, sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius);
glEnd();
}
glPopMatrix();
//glDisable(GL_LINE_SMOOTH);
}
// Load a 3d model (.OBJ)
// TODO: Add comments explaining this function process
Model LoadModel(const char *fileName)
{
Model model;
char dataType;
char comments[200];
int numVertex = 0;
int numNormals = 0;
int numTexCoords = 0;
int numTriangles = 0;
FILE* objfile;
objfile = fopen(fileName, "rt");
while(!feof(objfile))
{
fscanf(objfile, "%c", &dataType);
switch(dataType)
{
case '#': // It's a comment
{
fgets(comments, 200, objfile);
} break;
case 'v':
{
fscanf(objfile, "%c", &dataType);
if (dataType == 't') // Read texCoord
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
while (dataType == 'v')
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
}
if (dataType == '#')
{
fscanf(objfile, "%i", &numTexCoords);
}
else printf("Ouch! Something was wrong...");
fgets(comments, 200, objfile);
}
else if (dataType == 'n') // Read normals
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
while (dataType == 'v')
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
}
if (dataType == '#')
{
fscanf(objfile, "%i", &numNormals);
}
else printf("Ouch! Something was wrong...");
fgets(comments, 200, objfile);
}
else // Read vertex
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
while (dataType == 'v')
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
}
if (dataType == '#')
{
fscanf(objfile, "%i", &numVertex);
}
else printf("Ouch! Something was wrong...");
fgets(comments, 200, objfile);
}
} break;
case 'f':
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
while (dataType == 'f')
{
fgets(comments, 200, objfile);
fscanf(objfile, "%c", &dataType);
}
if (dataType == '#')
{
fscanf(objfile, "%i", &numTriangles);
}
else printf("Ouch! Something was wrong...");
fgets(comments, 200, objfile);
} break;
default: break;
}
}
Vector3 midVertices[numVertex];
Vector3 midNormals[numNormals];
Vector2 midTexCoords[numTexCoords];
model.numVertices = numTriangles*3;
model.vertices = (Vector3 *)malloc(model.numVertices * sizeof(Vector3));
model.normals = (Vector3 *)malloc(model.numVertices * sizeof(Vector3));
model.texcoords = (Vector2 *)malloc(model.numVertices * sizeof(Vector2));
int countVertex = 0;
int countNormals = 0;
int countTexCoords = 0;
int countMaxVertex = 0;
rewind(objfile);
while(!feof(objfile))
{
fscanf(objfile, "%c", &dataType);
switch(dataType)
{
case '#':
{
fgets(comments, 200, objfile);
} break;
case 'v':
{
fscanf(objfile, "%c", &dataType);
if (dataType == 't') // Read texCoord
{
float useless = 0;
fscanf(objfile, "%f %f %f", &midTexCoords[countTexCoords].x, &midTexCoords[countTexCoords].y, &useless);
countTexCoords++;
fscanf(objfile, "%c", &dataType);
}
else if (dataType == 'n') // Read normals
{
fscanf(objfile, "%f %f %f", &midNormals[countNormals].x, &midNormals[countNormals].y, &midNormals[countNormals].z );
countNormals++;
fscanf(objfile, "%c", &dataType);
}
else // Read vertex
{
fscanf(objfile, "%f %f %f", &midVertices[countVertex].x, &midVertices[countVertex].y, &midVertices[countVertex].z );
countVertex++;
fscanf(objfile, "%c", &dataType);
}
} break;
case 'f':
{
int vNum, vtNum, vnNum;
fscanf(objfile, "%c", &dataType);
fscanf(objfile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
model.vertices[countMaxVertex] = midVertices[vNum-1];
model.normals[countMaxVertex] = midNormals[vnNum-1];
model.texcoords[countMaxVertex].x = midTexCoords[vtNum-1].x;
model.texcoords[countMaxVertex].y = -midTexCoords[vtNum-1].y;
countMaxVertex++;
fscanf(objfile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
model.vertices[countMaxVertex] = midVertices[vNum-1];
model.normals[countMaxVertex] = midNormals[vnNum-1];
model.texcoords[countMaxVertex].x = midTexCoords[vtNum-1].x;
model.texcoords[countMaxVertex].y = -midTexCoords[vtNum-1].y;
countMaxVertex++;
fscanf(objfile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
model.vertices[countMaxVertex] = midVertices[vNum-1];
model.normals[countMaxVertex] = midNormals[vnNum-1];
model.texcoords[countMaxVertex].x = midTexCoords[vtNum-1].x;
model.texcoords[countMaxVertex].y = -midTexCoords[vtNum-1].y;
countMaxVertex++;
} break;
default: break;
}
}
fclose(objfile);
return model;
}
// Unload 3d model from memory
void UnloadModel(Model model)
{
free(model.vertices);
free(model.texcoords);
free(model.normals);
}
// Draw a model
void DrawModel(Model model, Vector3 position, float scale, Color color)
{
// NOTE: For models we use Vertex Arrays (OpenGL 1.1)
static float rotation = 0;
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array
glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array
glVertexPointer(3, GL_FLOAT, 0, model.vertices); // Pointer to vertex coords array
glTexCoordPointer(2, GL_FLOAT, 0, model.texcoords); // Pointer to texture coords array
glNormalPointer(GL_FLOAT, 0, model.normals); // Pointer to normals array
//glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED)
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
glRotatef(rotation * GetFrameTime(), 0, 1, 0);
glScalef(scale, scale, scale);
glColor4ub(color.r, color.g, color.b, color.a);
glDrawArrays(GL_TRIANGLES, 0, model.numVertices);
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array
glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array
rotation += 10;
}
// Draw a textured model
void DrawModelEx(Model model, Texture2D texture, Vector3 position, float scale, Color tint)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture.glId);
DrawModel(model, position, scale, tint);
glDisable(GL_TEXTURE_2D);
}
// Draw a model wires
void DrawModelWires(Model model, Vector3 position, float scale, Color color)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawModel(model, position, scale, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Draw a billboard
void DrawBillboard(Camera camera, Texture2D texture, Vector3 basePos, float size, Color tint)
{
// NOTE: Billboard size will represent the width, height maintains aspect ratio
Vector3 centerPos = { basePos.x, basePos.y + size * (float)texture.height/(float)texture.width/2, basePos.z };
Vector2 sizeRatio = { size, size * (float)texture.height/texture.width };
Vector3 rotation = { 90, 0, 0 };
// TODO: Calculate Y rotation to face always camera (use matrix)
// OPTION: Lock Y-axis
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture.glId);
DrawPlane(centerPos, sizeRatio, rotation, tint); // TODO: Review this function...
glDisable(GL_TEXTURE_2D);
}
// Draw a billboard (part of a texture defined by a rectangle)
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 basePos, float size, Color tint)
{
// NOTE: Billboard size will represent the width, height maintains aspect ratio
Vector3 centerPos = { basePos.x, basePos.y + size * (float)texture.height/(float)texture.width/2, basePos.z };
Vector2 sizeRatio = { size, size * (float)texture.height/texture.width };
Vector3 rotation = { 90, 0, 0 };
// TODO: Calculate Y rotation to face always camera (use matrix)
// OPTION: Lock Y-axis
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture.glId);
// TODO: DrawPlane with correct textcoords for source rec.
glDisable(GL_TEXTURE_2D);
}
// Draw a heightmap using a provided image data
void DrawHeightmap(Image heightmap, Vector3 centerPos, Vector3 scale, Color color)
{
// NOTE: Pixel-data is interpreted as grey-scale (even being a color image)
// NOTE: Heightmap resolution will depend on image size (one quad per pixel)
// TODO: Review how this function works... probably we need:
// Model LoadHeightmap(Image image, Vector3 resolution);
// NOTE: We are allocating and de-allocating vertex data every frame! --> framerate drops 80%! CRAZY!
Vector3 *terrainVertex = (Vector3 *)malloc(heightmap.width * heightmap.height * sizeof(Vector3));
for (int z = 0; z < heightmap.height; z++)
{
for (int x = 0; x < heightmap.width; x++)
{
terrainVertex[z*heightmap.height + x].x = (float)(x*scale.x);
terrainVertex[z*heightmap.height + x].y = ((float)heightmap.pixels[z*heightmap.height + x].r +
(float)heightmap.pixels[z*heightmap.height + x].g +
(float)heightmap.pixels[z*heightmap.height + x].b) / 3 * scale.y;
terrainVertex[z*heightmap.height + x].z = (float)(-z*scale.z);
}
}
// TODO: Texture coordinates and normals computing
for (int z = 0; z < heightmap.height-1; z++)
{
glBegin(GL_TRIANGLE_STRIP);
for (int x = 0; x < heightmap.width; x++)
{
glColor3f((float)heightmap.pixels[z*heightmap.height + x].r / 255.0f,
(float)heightmap.pixels[z*heightmap.height + x].g / 255.0f,
(float)heightmap.pixels[z*heightmap.height + x].b / 255.0f);
glVertex3f(terrainVertex[z*heightmap.height + x].x, terrainVertex[z*heightmap.height + x].y, terrainVertex[z*heightmap.height + x].z);
glVertex3f(terrainVertex[(z+1)*heightmap.height + x].x, terrainVertex[(z+1)*heightmap.height + x].y, terrainVertex[(z+1)*heightmap.height + x].z);
}
glEnd();
}
free(terrainVertex);
}
void DrawHeightmapEx(Image heightmap, Texture2D texture, Vector3 centerPos, Vector3 scale, Color tint)
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture.glId);
// NOTE: No texture coordinates or normals defined at this moment...
DrawHeightmap(heightmap, centerPos, scale, tint);
glDisable(GL_TEXTURE_2D);
}

376
src/raylib.h Normal file
View file

@ -0,0 +1,376 @@
/*********************************************************************************************
*
* raylib 1.0.0 (www.raylib.com)
*
* A simple and easy-to-use library to learn C videogames programming
*
* Features:
* Library written in plain C code (C99)
* Uses C# PascalCase/camelCase notation
* Hardware accelerated with OpenGL 1.1
* Powerful fonts module with SpriteFonts support
* Basic 3d support for Shapes and Models
* Audio loading and playing
*
* Used external libs:
* GLFW3 (www.glfw.org) for window/context management and input
* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC)
* OpenAL Soft for audio device/context management
*
* Some design decisions:
* 32bit Colors - All defined color are always RGBA
* 32bit Textures - All loaded images are converted automatically to RGBA textures
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
* One custom default font is loaded automatically when InitWindow()
*
* -- LICENSE (raylib v1.0, November 2013) --
*
* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified,
* BSD-like license that allows static linking with closed source software:
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#ifndef RAYLIB_H
#define RAYLIB_H
//#define NO_AUDIO // Audio is still being tested, deactivated by default
//----------------------------------------------------------------------------------
// Some basic Defines
//----------------------------------------------------------------------------------
#ifndef PI
#define PI 3.14159265358979323846
#endif
#define DEG2RAD (PI / 180.0)
#define RAD2DEG (180.0 / PI)
// Keyboard Function Keys
#define KEY_SPACE 32
#define KEY_ESCAPE 256
#define KEY_ENTER 257
#define KEY_RIGHT 262
#define KEY_LEFT 263
#define KEY_DOWN 264
#define KEY_UP 265
#define KEY_F1 290
#define KEY_F2 291
#define KEY_F3 292
#define KEY_F4 293
#define KEY_F5 294
#define KEY_F6 295
#define KEY_F7 296
#define KEY_F8 297
#define KEY_F9 298
#define KEY_F10 299
#define KEY_LEFT_SHIFT 340
#define KEY_LEFT_CONTROL 341
#define KEY_LEFT_ALT 342
#define KEY_RIGHT_SHIFT 344
#define KEY_RIGHT_CONTROL 345
#define KEY_RIGHT_ALT 346
// Mouse Buttons
#define MOUSE_LEFT_BUTTON 0
#define MOUSE_RIGHT_BUTTON 1
#define MOUSE_MIDDLE_BUTTON 2
// Gamepad Number
#define GAMEPAD_PLAYER1 0
#define GAMEPAD_PLAYER2 1
#define GAMEPAD_PLAYER3 2
#define GAMEPAD_PLAYER4 3
// Gamepad Buttons
// NOTE: Adjusted for a PS3 USB Controller
#define GAMEPAD_BUTTON_A 2
#define GAMEPAD_BUTTON_B 1
#define GAMEPAD_BUTTON_X 3
#define GAMEPAD_BUTTON_Y 4
#define GAMEPAD_BUTTON_R1 7
#define GAMEPAD_BUTTON_R2 5
#define GAMEPAD_BUTTON_L1 6
#define GAMEPAD_BUTTON_L2 8
#define GAMEPAD_BUTTON_SELECT 9
#define GAMEPAD_BUTTON_START 10
// TODO: Review Xbox360 USB Controller Buttons
// Some Basic Colors
// NOTE: Custom raylib color palette for amazing visuals on WHITE background
#define LIGHTGRAY (Color){ 200, 200, 200, 255 } // Light Gray
#define GRAY (Color){ 130, 130, 130, 255 } // Gray
#define DARKGRAY (Color){ 80, 80, 80, 255 } // Dark Gray
#define YELLOW (Color){ 253, 249, 0, 255 } // Yellow
#define GOLD (Color){ 255, 203, 0, 255 } // Gold
#define ORANGE (Color){ 255, 161, 0, 255 } // Orange
#define PINK (Color){ 255, 109, 194, 255 } // Pink
#define RED (Color){ 230, 41, 55, 255 } // Red
#define MAROON (Color){ 190, 33, 55, 255 } // Maroon
#define GREEN (Color){ 0, 228, 48, 255 } // Green
#define LIME (Color){ 0, 158, 47, 255 } // Lime
#define DARKGREEN (Color){ 0, 117, 44, 255 } // Dark Green
#define SKYBLUE (Color){ 102, 191, 255, 255 } // Sky Blue
#define BLUE (Color){ 0, 121, 241, 255 } // Blue
#define DARKBLUE (Color){ 0, 82, 172, 255 } // Dark Blue
#define PURPLE (Color){ 200, 122, 255, 255 } // Purple
#define VIOLET (Color){ 135, 60, 190, 255 } // Violet
#define DARKPURPLE (Color){ 112, 31, 126, 255 } // Dark Purple
#define BEIGE (Color){ 211, 176, 131, 255 } // Beige
#define BROWN (Color){ 127, 106, 79, 255 } // Brown
#define DARKBROWN (Color){ 76, 63, 47, 255 } // Dark Brown
#define WHITE (Color){ 255, 255, 255, 255 } // White
#define BLACK (Color){ 0, 0, 0, 255 } // Black
#define BLANK (Color){ 0, 0, 0, 0 } // Blank (Transparent)
#define MAGENTA (Color){ 255, 0, 255, 255 } // Magenta
#define RAYWHITE (Color){ 245, 245, 245, 255 } // My own White (raylib logo)
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Boolean type
typedef enum { false, true } bool;
// Color type, RGBA (32bit)
typedef struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
} Color;
// Rectangle type
typedef struct Rectangle {
int x;
int y;
int width;
int height;
} Rectangle;
// Image type, bpp always RGBA (32bit)
// NOTE: Data stored in CPU memory (RAM)
typedef struct Image {
Color *pixels;
int width;
int height;
} Image;
// Texture2D type, bpp always RGBA (32bit)
// NOTE: Data stored in GPU memory
typedef struct Texture2D {
unsigned int glId;
int width;
int height;
} Texture2D;
// SpriteFont one Character (Glyph) data, defined in text module
typedef struct Character Character;
// SpriteFont type, includes texture and charSet array data
typedef struct SpriteFont {
Texture2D texture;
int numChars;
Character *charSet;
} SpriteFont;
// Vector2 type
typedef struct Vector2 {
float x;
float y;
} Vector2;
// Vector3 type
typedef struct Vector3 {
float x;
float y;
float z;
} Vector3;
// Camera type, defines a camera position/orientation in 3d space
typedef struct Camera {
Vector3 position;
Vector3 target;
Vector3 up;
} Camera;
// Basic 3d Model type
typedef struct Model {
int numVertices;
Vector3 *vertices;
Vector2 *texcoords;
Vector3 *normals;
} Model;
// Basic Sound source and buffer
typedef struct Sound {
unsigned int source;
unsigned int buffer;
} Sound;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//------------------------------------------------------------------------------------
// Global Variables Definition
//------------------------------------------------------------------------------------
// It's lonely here...
//------------------------------------------------------------------------------------
// Window and Graphics Device Functions (Module: core)
//------------------------------------------------------------------------------------
void InitWindow(int width, int height, char* title); // Initialize Window and Graphics Context (OpenGL)
void CloseWindow(); // Close Window and Terminate Context
bool WindowShouldClose(); // Detect if KEY_ESCAPE pressed or Close icon pressed
void ToggleFullscreen(); // Fullscreen toggle (by default F11)
void ClearBackground(Color color); // Sets Background Color
void BeginDrawing(); // Setup drawing canvas to start drawing
void EndDrawing(); // End canvas drawing and Swap Buffers (Double Buffering)
void Begin3dMode(Camera cam); // Initializes 3D mode for drawing (Camera setup)
void End3dMode(); // Ends 3D mode and returns to default 2D orthographic mode
void SetTargetFPS(int fps); // Set target FPS (maximum)
float GetFPS(); // Returns current FPS
float GetFrameTime(); // Returns time in seconds for one frame
Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
int GetHexValue(Color color); // Returns hexadecimal value for a Color
//------------------------------------------------------------------------------------
// Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------
bool IsKeyPressed(int key); // Detect if a key is being pressed
bool IsKeyReleased(int key); // Detect if a key is NOT being pressed
bool IsMouseButtonPressed(int button); // Detect if a mouse button is being pressed
bool IsMouseButtonReleased(int button); // Detect if a mouse button is NOT being pressed
int GetMouseX(); // Returns mouse position X
int GetMouseY(); // Returns mouse position Y
Vector2 GetMousePosition(); // Returns mouse position XY
bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available
Vector2 GetGamepadMovement(int gamepad); // Return axis movement vector for a gamepad
bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button is being pressed
bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad button is NOT being pressed
//------------------------------------------------------------------------------------
// Basic Shapes Drawing Functions (Module: shapes)
//------------------------------------------------------------------------------------
void DrawPixel(int posX, int posY, Color color); // Draw a pixel
void DrawPixelV(Vector2 position, Color color); // Draw a pixel (Vector version)
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color); // Draw a line
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); // Draw a line (Vector version)
void DrawCircle(int centerX, int centerY, float radius, Color color); // Draw a color-filled circle
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2); // Draw a gradient-filled circle
void DrawCircleV(Vector2 center, float radius, Color color); // Draw a color-filled circle (Vector version)
void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline
void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle
void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle
void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version)
void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw a color-filled triangle
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); // Draw triangle outline
void DrawPoly(Vector2 *points, int numPoints, Color color); // Draw a closed polygon defined by points
void DrawPolyLine(Vector2 *points, int numPoints, Color color); // Draw polygon lines
//------------------------------------------------------------------------------------
// Texture Loading and Drawing Functions (Module: textures)
//------------------------------------------------------------------------------------
Image LoadImage(const char *fileName); // Load an image into CPU memory (RAM)
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory
//Texture2D LoadTextureEx(const char *fileName, bool createPOT, bool mipmaps); // Load an image as texture (and convert to POT with mipmaps) (raylib 1.x)
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, float scale, Color tint); // Draw a part of a texture defined by a rectangle
//------------------------------------------------------------------------------------
// Font Loading and Text Drawing Functions (Module: text)
//------------------------------------------------------------------------------------
SpriteFont LoadSpriteFont(const char *fileName); // Load a SpriteFont image into GPU memory
void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory
void DrawText(const char *text, int posX, int posY, int fontSize, int spacing, Color color); // Draw text (using default font)
void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint); // Draw text using SpriteFont
int MeasureText(const char *text, int fontSize, int spacing); // Measure string width for default font
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing); // Measure string size for SpriteFont
int GetFontBaseSize(SpriteFont spriteFont); // Returns the base size for a SpriteFont (chars height)
void DrawFps(int posX, int posY); // Shows current FPS on top-left corner
const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed'
//------------------------------------------------------------------------------------
// Basic 3d Shapes Drawing Functions (Module: models)
//------------------------------------------------------------------------------------
void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube
void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version)
void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires
void DrawSphere(Vector3 centerPos, float radius, Color color); // Draw sphere
void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color color); // Draw sphere with extended parameters
void DrawSphereWires(Vector3 centerPos, float radius, Color color); // Draw sphere wires
void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color); // Draw a plane
void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, int slicesZ, Color color); // Draw a plane with divisions
void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0))
void DrawGizmo(Vector3 position, bool orbits); // Draw gizmo (with or without orbits)
//DrawTorus(), DrawTeapot() are useless...
//------------------------------------------------------------------------------------
// Model 3d Loading and Drawing Functions (Module: models)
//------------------------------------------------------------------------------------
Model LoadModel(const char *fileName); // Load a 3d model (.OBJ)
void UnloadModel(Model model); // Unload 3d model from memory
void DrawModel(Model model, Vector3 position, float scale, Color color); // Draw a model
void DrawModelEx(Model model, Texture2D texture, Vector3 position, float scale, Color tint); // Draw a textured model
void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires
// NOTE: The following functions work but are incomplete or require some revision
// DrawHeightmap is extremely inefficient and can impact performance up to 60%
void DrawBillboard(Camera camera, Texture2D texture, Vector3 basePos, float size, Color tint); // REVIEW: Draw a billboard (raylib 1.x)
void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 basePos, float size, Color tint); // REVIEW: Draw a billboard (raylib 1.x)
void DrawHeightmap(Image heightmap, Vector3 centerPos, Vector3 scale, Color color); // REVIEW: Draw heightmap using image map (raylib 1.x)
void DrawHeightmapEx(Image heightmap, Texture2D texture, Vector3 centerPos, Vector3 scale, Color tint); // REVIEW: Draw textured heightmap (raylib 1.x)
#ifndef NO_AUDIO
//------------------------------------------------------------------------------------
// Audio Loading and Playing Functions (Module: audio)
//------------------------------------------------------------------------------------
void InitAudioDevice(); // Initialize audio device and context
void CloseAudioDevice(); // Close the audio device and context
Sound LoadSound(char *fileName); // Load sound to memory
void UnloadSound(Sound sound); // Unload sound
void PlaySound(Sound sound); // Play a sound
void PlaySoundEx(Sound sound, float timePosition, bool loop); // Play a sound with extended parameters
void PauseSound(Sound sound); // Pause a sound
void StopSound(Sound sound); // Stop playing a sound
#endif // NO_AUDIO
#ifdef __cplusplus
}
#endif
#endif // RAYLIB_H

326
src/shapes.c Normal file
View file

@ -0,0 +1,326 @@
/*********************************************************************************************
*
* raylib.shapes
*
* Basic functions to draw 2d Shapes
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
// Not here...
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// It's lonely here...
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
// No private (static) functions in this module (.c file)
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Draw a pixel
void DrawPixel(int posX, int posY, Color color)
{
glBegin(GL_POINTS);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(posX, posY);
glEnd();
// NOTE: Alternative method to draw a pixel (point)
/*
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
glPointSize(1.0f);
glPoint((float)posX, (float)posY, 0.0f);
*/
}
// Draw a pixel (Vector version)
void DrawPixelV(Vector2 position, Color color)
{
glBegin(GL_POINTS);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(position.x, position.y);
glEnd();
}
// Draw a line
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
{
glBegin(GL_LINES);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(startPosX, startPosY);
glVertex2i(endPosX, endPosY);
glEnd();
}
// Draw a line (Vector version)
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
{
glBegin(GL_LINES);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(startPos.x, startPos.y);
glVertex2f(endPos.x, endPos.y);
glEnd();
}
// Draw a color-filled circle
void DrawCircle(int centerX, int centerY, float radius, Color color)
{
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(centerX, centerY);
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
{
float degInRad = i*DEG2RAD;
//glVertex2f(cos(degInRad)*radius,sin(degInRad)*radius);
glVertex2f(centerX + sin(degInRad) * radius, centerY + cos(degInRad) * radius);
}
glEnd();
glDisable(GL_POLYGON_SMOOTH);
// NOTE: Alternative method to draw a circle (point)
/*
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
glPointSize(radius);
glPoint((float)centerX, (float)centerY, 0.0f);
*/
}
// Draw a gradient-filled circle
// NOTE: Gradient goes from center (color1) to border (color2)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
{
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color1.r, color1.g, color1.b, color1.a);
glVertex2i(centerX, centerY);
glColor4ub(color2.r, color2.g, color2.b, color2.a);
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
{
glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
}
glEnd();
}
// Draw a color-filled circle (Vector version)
void DrawCircleV(Vector2 center, float radius, Color color)
{
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(center.x, center.y);
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
{
glVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius);
}
glEnd();
glDisable(GL_POLYGON_SMOOTH);
}
// Draw circle outline
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
{
glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
glBegin(GL_LINE_LOOP);
glColor4ub(color.r, color.g, color.b, color.a);
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
for (int i=0; i < 360; i++)
{
glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
}
glEnd();
// NOTE: Alternative method to draw circle outline
/*
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawCircle(centerX, centerY, radius, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
*/
glDisable(GL_LINE_SMOOTH);
}
// Draw a color-filled rectangle
void DrawRectangle(int posX, int posY, int width, int height, Color color)
{
glBegin(GL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(posX, posY);
glVertex2i(posX + width, posY);
glVertex2i(posX + width, posY + height);
glVertex2i(posX, posY + height);
glEnd();
}
// Draw a color-filled rectangle
void DrawRectangleRec(Rectangle rec, Color color)
{
DrawRectangle(rec.x, rec.y, rec.width, rec.height, color);
}
// Draw a gradient-filled rectangle
// NOTE: Gradient goes from bottom (color1) to top (color2)
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
{
glBegin(GL_QUADS);
glColor4ub(color1.r, color1.g, color1.b, color1.a);
glVertex2i(posX, posY);
glVertex2i(posX + width, posY);
glColor4ub(color2.r, color2.g, color2.b, color2.a);
glVertex2i(posX + width, posY + height);
glVertex2i(posX, posY + height);
glEnd();
}
// Draw a color-filled rectangle (Vector version)
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
{
glBegin(GL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(position.x, position.y);
glVertex2i(position.x + size.x, position.y);
glVertex2i(position.x + size.x, position.y + size.y);
glVertex2i(position.x, position.y + size.y);
glEnd();
}
// Draw rectangle outline
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
{
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
// NOTE: Lines are rasterized using the "Diamond Exit" rule so, it's nearly impossible to obtain a pixel-perfect engine
// NOTE: Recommended trying to avoid using lines, at least >1.0f pixel lines with anti-aliasing (glLineWidth function)
glBegin(GL_LINE_LOOP);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(posX, posY);
glVertex2i(posX + width - 1, posY);
glVertex2i(posX + width - 1, posY + height - 1);
glVertex2i(posX, posY + height - 1);
glEnd();
// NOTE: Alternative method to draw rectangle outline
/*
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawRectangle(posX, posY, width - 1, height - 1, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
*/
//glDisable(GL_LINE_SMOOTH);
}
// Draw a triangle
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
{
glBegin(GL_TRIANGLES);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(v1.x, v1.y);
glVertex2f(v2.x, v2.y);
glVertex2f(v3.x, v3.y);
glEnd();
}
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
{
glBegin(GL_LINE_LOOP);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(v1.x, v1.y);
glVertex2f(v2.x, v2.y);
glVertex2f(v3.x, v3.y);
glEnd();
}
// Draw a closed polygon defined by points
// NOTE: Array num elements MUST be passed as parameter to function
void DrawPoly(Vector2 *points, int numPoints, Color color)
{
if (numPoints >= 3)
{
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
glBegin(GL_POLYGON);
glColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < numPoints; i++)
{
glVertex2f(points[i].x, points[i].y);
}
glEnd();
glDisable(GL_POLYGON_SMOOTH);
}
}
// Draw polygon lines
// NOTE: Array num elements MUST be passed as parameter to function
void DrawPolyLine(Vector2 *points, int numPoints, Color color)
{
if (numPoints >= 2)
{
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
glBegin(GL_LINE_LOOP);
glColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < numPoints; i++)
{
glVertex2f(points[i].x, points[i].y);
}
glEnd();
//glDisable(GL_LINE_SMOOTH);
}
}

4341
src/stb_image.c Normal file

File diff suppressed because it is too large Load diff

334
src/stb_image.h Normal file
View file

@ -0,0 +1,334 @@
/* stbi-1.33 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
when you control the images you're loading
no warranty implied; use at your own risk
QUICK NOTES:
Primarily of interest to game developers and other people who can
avoid problematic images and only need the trivial interface
JPEG baseline (no JPEG progressive)
PNG 8-bit-per-channel only
TGA (not sure what subset, if a subset)
BMP non-1bpp, non-RLE
PSD (composited view only, no extra channels)
GIF (*comp always reports as 4-channel)
HDR (radiance rgbE format)
PIC (Softimage PIC)
- decode from memory or through FILE (define STBI_NO_STDIO to remove code)
- decode from arbitrary I/O callbacks
- overridable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
Latest revisions:
1.33 (2011-07-14) minor fixes suggested by Dave Moore
1.32 (2011-07-13) info support for all filetypes (SpartanJ)
1.31 (2011-06-19) a few more leak fixes, bug in PNG handling (SpartanJ)
1.30 (2011-06-11) added ability to load files via io callbacks (Ben Wenger)
1.29 (2010-08-16) various warning fixes from Aurelien Pocheville
1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ)
1.27 (2010-08-01) cast-to-uint8 to fix warnings (Laurent Gomila)
allow trailing 0s at end of image data (Laurent Gomila)
1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ
See end of file for full revision history.
TODO:
stbi_info support for BMP,PSD,HDR,PIC
============================ Contributors =========================
Image formats Optimizations & bugfixes
Sean Barrett (jpeg, png, bmp) Fabian "ryg" Giesen
Nicolas Schulz (hdr, psd)
Jonathan Dummer (tga) Bug fixes & warning fixes
Jean-Marc Lienher (gif) Marc LeBlanc
Tom Seddon (pic) Christpher Lloyd
Thatcher Ulrich (psd) Dave Moore
Won Chun
the Horde3D community
Extensions, features Janez Zemva
Jetro Lauha (stbi_info) Jonathan Blow
James "moose2000" Brown (iPhone PNG) Laurent Gomila
Ben "Disch" Wenger (io callbacks) Aruelien Pocheville
Martin "SpartanJ" Golini Ryamond Barbiero
David Woo
If your name should be here but isn't, let Sean know.
*/
#ifndef STBI_INCLUDE_STB_IMAGE_H
#define STBI_INCLUDE_STB_IMAGE_H
// To get a header file for this, either cut and paste the header,
// or create stb_image.h, #define STBI_HEADER_FILE_ONLY, and
// then include stb_image.c from it.
//// begin header file ////////////////////////////////////////////////////
//
// Limitations:
// - no jpeg progressive support
// - non-HDR formats support 8-bit samples only (jpeg, png)
// - no delayed line count (jpeg) -- IJG doesn't support either
// - no 1-bit BMP
// - GIF always returns *comp=4
//
// Basic usage (see HDR discussion below):
// int x,y,n;
// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
// // ... process data if not NULL ...
// // ... x = width, y = height, n = # 8-bit components per pixel ...
// // ... replace '0' with '1'..'4' to force that many components per pixel
// // ... but 'n' will always be the number that it would have been if you said 0
// stbi_image_free(data)
//
// Standard parameters:
// int *x -- outputs image width in pixels
// int *y -- outputs image height in pixels
// int *comp -- outputs # of image components in image file
// int req_comp -- if non-zero, # of image components requested in result
//
// The return value from an image loader is an 'unsigned char *' which points
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
// with each pixel consisting of N interleaved 8-bit components; the first
// pixel pointed to is top-left-most in the image. There is no padding between
// image scanlines or between pixels, regardless of format. The number of
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
// If req_comp is non-zero, *comp has the number of components that _would_
// have been output otherwise. E.g. if you set req_comp to 4, you will always
// get RGBA output, but you can check *comp to easily see if it's opaque.
//
// An output image with N components has the following components interleaved
// in this order in each pixel:
//
// N=#comp components
// 1 grey
// 2 grey, alpha
// 3 red, green, blue
// 4 red, green, blue, alpha
//
// If image loading fails for any reason, the return value will be NULL,
// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
// can be queried for an extremely brief, end-user unfriendly explanation
// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
// more user-friendly ones.
//
// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized.
//
// ===========================================================================
//
// iPhone PNG support:
//
// By default we convert iphone-formatted PNGs back to RGB; nominally they
// would silently load as BGR, except the existing code should have just
// failed on such iPhone PNGs. But you can disable this conversion by
// by calling stbi_convert_iphone_png_to_rgb(0), in which case
// you will always just get the native iphone "format" through.
//
// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per
// pixel to remove any premultiplied alpha *only* if the image file explicitly
// says there's premultiplied data (currently only happens in iPhone images,
// and only if iPhone convert-to-rgb processing is on).
//
// ===========================================================================
//
// HDR image support (disable by defining STBI_NO_HDR)
//
// stb_image now supports loading HDR images in general, and currently
// the Radiance .HDR file format, although the support is provided
// generically. You can still load any file through the existing interface;
// if you attempt to load an HDR file, it will be automatically remapped to
// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
// both of these constants can be reconfigured through this interface:
//
// stbi_hdr_to_ldr_gamma(2.2f);
// stbi_hdr_to_ldr_scale(1.0f);
//
// (note, do not use _inverse_ constants; stbi_image will invert them
// appropriately).
//
// Additionally, there is a new, parallel interface for loading files as
// (linear) floats to preserve the full dynamic range:
//
// float *data = stbi_loadf(filename, &x, &y, &n, 0);
//
// If you load LDR images through this interface, those images will
// be promoted to floating point values, run through the inverse of
// constants corresponding to the above:
//
// stbi_ldr_to_hdr_scale(1.0f);
// stbi_ldr_to_hdr_gamma(2.2f);
//
// Finally, given a filename (or an open file or memory block--see header
// file for details) containing image data, you can query for the "most
// appropriate" interface to use (that is, whether the image is HDR or
// not), using:
//
// stbi_is_hdr(char *filename);
//
// ===========================================================================
//
// I/O callbacks
//
// I/O callbacks allow you to read from arbitrary sources, like packaged
// files or some other source. Data read from callbacks are processed
// through a small internal buffer (currently 128 bytes) to try to reduce
// overhead.
//
// The three functions you must define are "read" (reads some bytes of data),
// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end).
#define STBI_NO_HDR // RaySan: not required by raylib
#ifndef STBI_NO_STDIO
#if defined(_MSC_VER) && _MSC_VER >= 0x1400
#define _CRT_SECURE_NO_WARNINGS // suppress bogus warnings about fopen()
#endif
#include <stdio.h>
#endif
#define STBI_VERSION 1
enum
{
STBI_default = 0, // only used for req_comp
STBI_grey = 1,
STBI_grey_alpha = 2,
STBI_rgb = 3,
STBI_rgb_alpha = 4
};
typedef unsigned char stbi_uc;
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////
//
// PRIMARY API - works on images of any type
//
//
// load image by filename, open file, or memory buffer
//
extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
#ifndef STBI_NO_STDIO
extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
// for stbi_load_from_file, file pointer is left pointing immediately after image
#endif
typedef struct
{
int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read
void (*skip) (void *user,unsigned n); // skip the next 'n' bytes
int (*eof) (void *user); // returns nonzero if we are at end of file/data
} stbi_io_callbacks;
extern stbi_uc *stbi_load_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
#ifndef STBI_NO_HDR
extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
#ifndef STBI_NO_STDIO
extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
#endif
extern float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
extern void stbi_hdr_to_ldr_gamma(float gamma);
extern void stbi_hdr_to_ldr_scale(float scale);
extern void stbi_ldr_to_hdr_gamma(float gamma);
extern void stbi_ldr_to_hdr_scale(float scale);
#endif // STBI_NO_HDR
// stbi_is_hdr is always defined
extern int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
#ifndef STBI_NO_STDIO
extern int stbi_is_hdr (char const *filename);
extern int stbi_is_hdr_from_file(FILE *f);
#endif // STBI_NO_STDIO
// get a VERY brief reason for failure
// NOT THREADSAFE
extern const char *stbi_failure_reason (void);
// free the loaded image -- this is just free()
extern void stbi_image_free (void *retval_from_stbi_load);
// get image dimensions & components without fully decoding
extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
extern int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp);
#ifndef STBI_NO_STDIO
extern int stbi_info (char const *filename, int *x, int *y, int *comp);
extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
#endif
// for image formats that explicitly notate that they have premultiplied alpha,
// we just return the colors as stored in the file. set this flag to force
// unpremultiplication. results are undefined if the unpremultiply overflow.
extern void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply);
// indicate whether we should process iphone images back to canonical format,
// or just pass them through "as-is"
extern void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert);
// ZLIB client - used by PNG, available for other purposes
extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
// define faster low-level operations (typically SIMD support)
#ifdef STBI_SIMD
typedef void (*stbi_idct_8x8)(stbi_uc *out, int out_stride, short data[64], unsigned short *dequantize);
// compute an integer IDCT on "input"
// input[x] = data[x] * dequantize[x]
// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride'
// CLAMP results to 0..255
typedef void (*stbi_YCbCr_to_RGB_run)(stbi_uc *output, stbi_uc const *y, stbi_uc const *cb, stbi_uc const *cr, int count, int step);
// compute a conversion from YCbCr to RGB
// 'count' pixels
// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B
// y: Y input channel
// cb: Cb input channel; scale/biased to be 0..255
// cr: Cr input channel; scale/biased to be 0..255
extern void stbi_install_idct(stbi_idct_8x8 func);
extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func);
#endif // STBI_SIMD
#ifdef __cplusplus
}
#endif
//
//
//// end header file /////////////////////////////////////////////////////
#endif // STBI_INCLUDE_STB_IMAGE_H

5039
src/stb_vorbis.c Normal file

File diff suppressed because it is too large Load diff

352
src/stb_vorbis.h Normal file
View file

@ -0,0 +1,352 @@
// Ogg Vorbis I audio decoder -- version 0.99996
//
// Written in April 2007 by Sean Barrett, sponsored by RAD Game Tools.
//
// Placed in the public domain April 2007 by the author: no copyright is
// claimed, and you may use it for any purpose you like.
//
// No warranty for any purpose is expressed or implied by the author (nor
// by RAD Game Tools). Report bugs and send enhancements to the author.
//
// Get the latest version and other information at:
// http://nothings.org/stb_vorbis/
// Todo:
//
// - seeking (note you can seek yourself using the pushdata API)
//
// Limitations:
//
// - floor 0 not supported (used in old ogg vorbis files)
// - lossless sample-truncation at beginning ignored
// - cannot concatenate multiple vorbis streams
// - sample positions are 32-bit, limiting seekable 192Khz
// files to around 6 hours (Ogg supports 64-bit)
//
// All of these limitations may be removed in future versions.
//////////////////////////////////////////////////////////////////////////////
//
// HEADER BEGINS HERE
//
#ifndef STB_VORBIS_INCLUDE_STB_VORBIS_H
#define STB_VORBIS_INCLUDE_STB_VORBIS_H
#if defined(STB_VORBIS_NO_CRT) && !defined(STB_VORBIS_NO_STDIO)
#define STB_VORBIS_NO_STDIO 1
#endif
#ifndef STB_VORBIS_NO_STDIO
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/////////// THREAD SAFETY
// Individual stb_vorbis* handles are not thread-safe; you cannot decode from
// them from multiple threads at the same time. However, you can have multiple
// stb_vorbis* handles and decode from them independently in multiple thrads.
/////////// MEMORY ALLOCATION
// normally stb_vorbis uses malloc() to allocate memory at startup,
// and alloca() to allocate temporary memory during a frame on the
// stack. (Memory consumption will depend on the amount of setup
// data in the file and how you set the compile flags for speed
// vs. size. In my test files the maximal-size usage is ~150KB.)
//
// You can modify the wrapper functions in the source (setup_malloc,
// setup_temp_malloc, temp_malloc) to change this behavior, or you
// can use a simpler allocation model: you pass in a buffer from
// which stb_vorbis will allocate _all_ its memory (including the
// temp memory). "open" may fail with a VORBIS_outofmem if you
// do not pass in enough data; there is no way to determine how
// much you do need except to succeed (at which point you can
// query get_info to find the exact amount required. yes I know
// this is lame).
//
// If you pass in a non-NULL buffer of the type below, allocation
// will occur from it as described above. Otherwise just pass NULL
// to use malloc()/alloca()
typedef struct
{
char *alloc_buffer;
int alloc_buffer_length_in_bytes;
} stb_vorbis_alloc;
/////////// FUNCTIONS USEABLE WITH ALL INPUT MODES
typedef struct stb_vorbis stb_vorbis;
typedef struct
{
unsigned int sample_rate;
int channels;
unsigned int setup_memory_required;
unsigned int setup_temp_memory_required;
unsigned int temp_memory_required;
int max_frame_size;
} stb_vorbis_info;
// get general information about the file
extern stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f);
// get the last error detected (clears it, too)
extern int stb_vorbis_get_error(stb_vorbis *f);
// close an ogg vorbis file and free all memory in use
extern void stb_vorbis_close(stb_vorbis *f);
// this function returns the offset (in samples) from the beginning of the
// file that will be returned by the next decode, if it is known, or -1
// otherwise. after a flush_pushdata() call, this may take a while before
// it becomes valid again.
// NOT WORKING YET after a seek with PULLDATA API
extern int stb_vorbis_get_sample_offset(stb_vorbis *f);
// returns the current seek point within the file, or offset from the beginning
// of the memory buffer. In pushdata mode it returns 0.
extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
/////////// PUSHDATA API
#ifndef STB_VORBIS_NO_PUSHDATA_API
// this API allows you to get blocks of data from any source and hand
// them to stb_vorbis. you have to buffer them; stb_vorbis will tell
// you how much it used, and you have to give it the rest next time;
// and stb_vorbis may not have enough data to work with and you will
// need to give it the same data again PLUS more. Note that the Vorbis
// specification does not bound the size of an individual frame.
extern stb_vorbis *stb_vorbis_open_pushdata(
unsigned char *datablock, int datablock_length_in_bytes,
int *datablock_memory_consumed_in_bytes,
int *error,
stb_vorbis_alloc *alloc_buffer);
// create a vorbis decoder by passing in the initial data block containing
// the ogg&vorbis headers (you don't need to do parse them, just provide
// the first N bytes of the file--you're told if it's not enough, see below)
// on success, returns an stb_vorbis *, does not set error, returns the amount of
// data parsed/consumed on this call in *datablock_memory_consumed_in_bytes;
// on failure, returns NULL on error and sets *error, does not change *datablock_memory_consumed
// if returns NULL and *error is VORBIS_need_more_data, then the input block was
// incomplete and you need to pass in a larger block from the start of the file
extern int stb_vorbis_decode_frame_pushdata(
stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes,
int *channels, // place to write number of float * buffers
float ***output, // place to write float ** array of float * buffers
int *samples // place to write number of output samples
);
// decode a frame of audio sample data if possible from the passed-in data block
//
// return value: number of bytes we used from datablock
// possible cases:
// 0 bytes used, 0 samples output (need more data)
// N bytes used, 0 samples output (resynching the stream, keep going)
// N bytes used, M samples output (one frame of data)
// note that after opening a file, you will ALWAYS get one N-bytes,0-sample
// frame, because Vorbis always "discards" the first frame.
//
// Note that on resynch, stb_vorbis will rarely consume all of the buffer,
// instead only datablock_length_in_bytes-3 or less. This is because it wants
// to avoid missing parts of a page header if they cross a datablock boundary,
// without writing state-machiney code to record a partial detection.
//
// The number of channels returned are stored in *channels (which can be
// NULL--it is always the same as the number of channels reported by
// get_info). *output will contain an array of float* buffers, one per
// channel. In other words, (*output)[0][0] contains the first sample from
// the first channel, and (*output)[1][0] contains the first sample from
// the second channel.
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
// inform stb_vorbis that your next datablock will not be contiguous with
// previous ones (e.g. you've seeked in the data); future attempts to decode
// frames will cause stb_vorbis to resynchronize (as noted above), and
// once it sees a valid Ogg page (typically 4-8KB, as large as 64KB), it
// will begin decoding the _next_ frame.
//
// if you want to seek using pushdata, you need to seek in your file, then
// call stb_vorbis_flush_pushdata(), then start calling decoding, then once
// decoding is returning you data, call stb_vorbis_get_sample_offset, and
// if you don't like the result, seek your file again and repeat.
#endif
////////// PULLING INPUT API
#ifndef STB_VORBIS_NO_PULLDATA_API
// This API assumes stb_vorbis is allowed to pull data from a source--
// either a block of memory containing the _entire_ vorbis stream, or a
// FILE * that you or it create, or possibly some other reading mechanism
// if you go modify the source to replace the FILE * case with some kind
// of callback to your code. (But if you don't support seeking, you may
// just want to go ahead and use pushdata.)
#if !defined(STB_VORBIS_NO_STDIO) && !defined(STB_VORBIS_NO_INTEGER_CONVERSION)
extern int stb_vorbis_decode_filename(char *filename, int *channels, short **output);
#endif
extern int stb_vorbis_decode_memory(unsigned char *mem, int len, int *channels, short **output);
// decode an entire file and output the data interleaved into a malloc()ed
// buffer stored in *output. The return value is the number of samples
// decoded, or -1 if the file could not be opened or was not an ogg vorbis file.
// When you're done with it, just free() the pointer returned in *output.
extern stb_vorbis * stb_vorbis_open_memory(unsigned char *data, int len,
int *error, stb_vorbis_alloc *alloc_buffer);
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
// this must be the entire stream!). on failure, returns NULL and sets *error
#ifndef STB_VORBIS_NO_STDIO
extern stb_vorbis * stb_vorbis_open_filename(char *filename,
int *error, stb_vorbis_alloc *alloc_buffer);
// create an ogg vorbis decoder from a filename via fopen(). on failure,
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
int *error, stb_vorbis_alloc *alloc_buffer);
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
// note that stb_vorbis must "own" this stream; if you seek it in between
// calls to stb_vorbis, it will become confused. Morever, if you attempt to
// perform stb_vorbis_seek_*() operations on this file, it will assume it
// owns the _entire_ rest of the file after the start point. Use the next
// function, stb_vorbis_open_file_section(), to limit it.
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len);
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
// this stream; if you seek it in between calls to stb_vorbis, it will become
// confused.
#endif
extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
// NOT WORKING YET
// these functions seek in the Vorbis file to (approximately) 'sample_number'.
// after calling seek_frame(), the next call to get_frame_*() will include
// the specified sample. after calling stb_vorbis_seek(), the next call to
// stb_vorbis_get_samples_* will start with the specified sample. If you
// do not need to seek to EXACTLY the target sample when using get_samples_*,
// you can also use seek_frame().
extern void stb_vorbis_seek_start(stb_vorbis *f);
// this function is equivalent to stb_vorbis_seek(f,0), but it
// actually works
extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
// these functions return the total length of the vorbis stream
extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output);
// decode the next frame and return the number of samples. the number of
// channels returned are stored in *channels (which can be NULL--it is always
// the same as the number of channels reported by get_info). *output will
// contain an array of float* buffers, one per channel. These outputs will
// be overwritten on the next call to stb_vorbis_get_frame_*.
//
// You generally should not intermix calls to stb_vorbis_get_frame_*()
// and stb_vorbis_get_samples_*(), since the latter calls the former.
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples);
#endif
// decode the next frame and return the number of samples per channel. the
// data is coerced to the number of channels you request according to the
// channel coercion rules (see below). You must pass in the size of your
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
// The maximum buffer size needed can be gotten from get_info(); however,
// the Vorbis I specification implies an absolute maximum of 4096 samples
// per channel. Note that for interleaved data, you pass in the number of
// shorts (the size of your array), but the return value is the number of
// samples per channel, not the total number of samples.
// Channel coercion rules:
// Let M be the number of channels requested, and N the number of channels present,
// and Cn be the nth channel; let stereo L be the sum of all L and center channels,
// and stereo R be the sum of all R and center channels (channel assignment from the
// vorbis spec).
// M N output
// 1 k sum(Ck) for all k
// 2 * stereo L, stereo R
// k l k > l, the first l channels, then 0s
// k l k <= l, the first k channels
// Note that this is not _good_ surround etc. mixing at all! It's just so
// you get something useful.
extern int stb_vorbis_get_samples_float_interleaved(stb_vorbis *f, int channels, float *buffer, int num_floats);
extern int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, int num_samples);
// gets num_samples samples, not necessarily on a frame boundary--this requires
// buffering so you have to supply the buffers. DOES NOT APPLY THE COERCION RULES.
// Returns the number of samples stored per channel; it may be less than requested
// at the end of the file. If there are no more samples in the file, returns 0.
#ifndef STB_VORBIS_NO_INTEGER_CONVERSION
extern int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short *buffer, int num_shorts);
extern int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, int num_samples);
#endif
// gets num_samples samples, not necessarily on a frame boundary--this requires
// buffering so you have to supply the buffers. Applies the coercion rules above
// to produce 'channels' channels. Returns the number of samples stored per channel;
// it may be less than requested at the end of the file. If there are no more
// samples in the file, returns 0.
#endif
//////// ERROR CODES
enum STBVorbisError
{
VORBIS__no_error,
VORBIS_need_more_data=1, // not a real error
VORBIS_invalid_api_mixing, // can't mix API modes
VORBIS_outofmem, // not enough memory
VORBIS_feature_not_supported, // uses floor 0
VORBIS_too_many_channels, // STB_VORBIS_MAX_CHANNELS is too small
VORBIS_file_open_failure, // fopen() failed
VORBIS_seek_without_length, // can't seek in unknown-length file
VORBIS_unexpected_eof=10, // file is truncated?
VORBIS_seek_invalid, // seek past EOF
// decoding errors (corrupt/invalid stream) -- you probably
// don't care about the exact details of these
// vorbis errors:
VORBIS_invalid_setup=20,
VORBIS_invalid_stream,
// ogg errors:
VORBIS_missing_capture_pattern=30,
VORBIS_invalid_stream_structure_version,
VORBIS_continued_packet_flag_invalid,
VORBIS_incorrect_stream_serial_number,
VORBIS_invalid_first_page,
VORBIS_bad_packet_type,
VORBIS_cant_find_last_page,
VORBIS_seek_failed,
};
#ifdef __cplusplus
}
#endif
#endif // STB_VORBIS_INCLUDE_STB_VORBIS_H

515
src/text.c Normal file
View file

@ -0,0 +1,515 @@
/*********************************************************************************************
*
* raylib.text
*
* Basic functions to load SpriteFonts and draw Text
*
* Uses external lib:
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <stdlib.h> // Declares malloc() and free() for memory management
#include <string.h> // String management functions (just strlen() is used)
#include <stdarg.h> // Used for functions with variable number of parameters (FormatText())
#include "stb_image.h" // Used to read image data (multiple formats support)
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define FIRST_CHAR 32
#define MAX_FONTCHARS 128
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef unsigned char byte;
// SpriteFont one Character (Glyph) data
struct Character {
int value; //char value = ' '; (int)value = 32;
int x;
int y;
int w;
int h;
};
//----------------------------------------------------------------------------------
// Global variables
//----------------------------------------------------------------------------------
static SpriteFont defaultFont; // Default font provided by raylib
// NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core]
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static bool PixelIsMagenta(Color p); // Check if a pixel is magenta
static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet); // Parse image pixel data to obtain character set measures
static int GetNextPOT(int num); // Calculate next power-of-two value for a given value
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
extern void LoadDefaultFont()
{
defaultFont.numChars = 96; // We know our default font has 94 chars
defaultFont.texture.width = 128; // We know our default font texture is 128 pixels width
defaultFont.texture.height = 64; // We know our default font texture is 64 pixels height
// Default font is directly defined here (data generated from a sprite font image)
// This way, we reconstruct SpriteFont without creating large global variables
// This data is automatically allocated to Stack and automatically deallocated at the end of this function
int defaultFontData[256] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00200020, 0x0001b000, 0x00000000, 0x00000000, 0x8ef92520, 0x00020a00, 0x7dbe8000, 0x1f7df45f,
0x4a2bf2a0, 0x0852091e, 0x41224000, 0x10041450, 0x2e292020, 0x08220812, 0x41222000, 0x10041450, 0x10f92020, 0x3efa084c, 0x7d22103c, 0x107df7de,
0xe8a12020, 0x08220832, 0x05220800, 0x10450410, 0xa4a3f000, 0x08520832, 0x05220400, 0x10450410, 0xe2f92020, 0x0002085e, 0x7d3e0281, 0x107df41f,
0x00200000, 0x8001b000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xc0000fbe, 0xfbf7e00f, 0x5fbf7e7d, 0x0050bee8, 0x440808a2, 0x0a142fe8, 0x50810285, 0x0050a048,
0x49e428a2, 0x0a142828, 0x40810284, 0x0048a048, 0x10020fbe, 0x09f7ebaf, 0xd89f3e84, 0x0047a04f, 0x09e48822, 0x0a142aa1, 0x50810284, 0x0048a048,
0x04082822, 0x0a142fa0, 0x50810285, 0x0050a248, 0x00008fbe, 0xfbf42021, 0x5f817e7d, 0x07d09ce8, 0x00008000, 0x00000fe0, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000c0180,
0xdfbf4282, 0x0bfbf7ef, 0x42850505, 0x004804bf, 0x50a142c6, 0x08401428, 0x42852505, 0x00a808a0, 0x50a146aa, 0x08401428, 0x42852505, 0x00081090,
0x5fa14a92, 0x0843f7e8, 0x7e792505, 0x00082088, 0x40a15282, 0x08420128, 0x40852489, 0x00084084, 0x40a16282, 0x0842022a, 0x40852451, 0x00088082,
0xc0bf4282, 0xf843f42f, 0x7e85fc21, 0x3e0900bf, 0x00000000, 0x00000004, 0x00000000, 0x000c0180, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x04000402, 0x41482000, 0x00000000, 0x00000800,
0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820,
0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0,
0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x00000000,
0x24fa28a2, 0x00000901, 0x00000000, 0x00000000, 0x2242252a, 0x00000952, 0x00000000, 0x00000000, 0x2422222a, 0x00000929, 0x00000000, 0x00000000,
0x2412252a, 0x00000901, 0x00000000, 0x00000000, 0x24fbe8be, 0x00000901, 0x00000000, 0x00000000, 0xac020000, 0x00000f01, 0x00000000, 0x00000000,
0x0003e000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000 };
int charsHeight = 10;
int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically
int charsWidth[96] = { 3, 1, 4, 6, 5, 7, 6, 2, 3, 3, 5, 5, 2, 4, 1, 7, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 3, 4, 3, 6,
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4 };
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
//------------------------------------------------------------------------------
defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data
// This memory should be freed at end! --> Done on CloseWindow()
int currentLine = 0;
int currentPosX = charsDivisor;
int testPosX = charsDivisor;
for (int i = 0; i < defaultFont.numChars; i++)
{
defaultFont.charSet[i].value = FIRST_CHAR + i;
defaultFont.charSet[i].x = currentPosX;
defaultFont.charSet[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
defaultFont.charSet[i].w = charsWidth[i];
defaultFont.charSet[i].h = charsHeight;
testPosX += (defaultFont.charSet[i].w + charsDivisor);
if (testPosX >= defaultFont.texture.width)
{
currentLine++;
currentPosX = 2 * charsDivisor + charsWidth[i];
testPosX = currentPosX;
defaultFont.charSet[i].x = charsDivisor;
defaultFont.charSet[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor);
}
else currentPosX = testPosX;
}
// Re-construct image from defaultFontData and generate OpenGL texture
//----------------------------------------------------------------------
Color *imgDataPixel = (Color *)malloc(defaultFont.texture.width * defaultFont.texture.height * sizeof(Color));
for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i++) imgDataPixel[i] = BLANK; // Initialize array
int counter = 0; // Font data elements counter
// Fill imgData with defaultFontData (convert from bit to pixel!)
for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i += 32)
{
for (int j = 31; j >= 0; j--)
{
if (BIT_CHECK(defaultFontData[counter], j)) imgDataPixel[i+j] = WHITE;
}
counter++;
if (counter > 256) counter = 0; // Security check...
}
// Convert loaded data to OpenGL texture
//----------------------------------------
GLuint id;
glGenTextures(1, &id); // Generate pointer to the texture
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // Set texture to clamp on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // Set texture to clamp on y-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, defaultFont.texture.width, defaultFont.texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixel);
// NOTE: Not using mipmappings (texture for 2D drawing)
// At this point we have the image converted to texture and uploaded to GPU
free(imgDataPixel); // Now we can free loaded data from RAM memory
defaultFont.texture.glId = id;
}
extern void UnloadDefaultFont()
{
glDeleteTextures(1, &defaultFont.texture.glId);
free(defaultFont.charSet);
}
// Load a SpriteFont image into GPU memory
SpriteFont LoadSpriteFont(const char* fileName)
{
SpriteFont spriteFont;
// Use stb_image to load image data!
int imgWidth;
int imgHeight;
int imgBpp;
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA)
// Convert array to pixel array for working convenience
Color *imgDataPixel = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
Color *imgDataPixelPOT = NULL;
int pix = 0;
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
{
imgDataPixel[pix].r = imgData[i];
imgDataPixel[pix].g = imgData[i+1];
imgDataPixel[pix].b = imgData[i+2];
imgDataPixel[pix].a = imgData[i+3];
pix++;
}
stbi_image_free(imgData);
// At this point we have a pixel array with all the data...
// Process bitmap Font pixel data to get measures (Character array)
// spriteFont.charSet data is filled inside the function and memory is allocated!
int numChars = ParseImageData(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet);
spriteFont.numChars = numChars;
// Convert image font to POT image before conversion to texture
// Just add the required amount of pixels at the right and bottom sides of image...
int potWidth = GetNextPOT(imgWidth);
int potHeight = GetNextPOT(imgHeight);
// Check if POT texture generation is required (if texture is not already POT)
if ((potWidth != imgWidth) || (potHeight != imgWidth))
{
// Generate POT array from NPOT data
imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
for (int j = 0; j < potHeight; j++)
{
for (int i = 0; i < potWidth; i++)
{
if ((j < imgHeight) && (i < imgWidth)) imgDataPixelPOT[j*potWidth + i] = imgDataPixel[j*imgWidth + i];
else imgDataPixelPOT[j*potWidth + i] = MAGENTA;
}
}
}
free(imgDataPixel);
// Convert loaded data to OpenGL texture
//----------------------------------------
GLuint id;
glGenTextures(1, &id); // Generate pointer to the texture
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, potWidth, potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixelPOT);
// NOTE: Not using mipmappings (texture for 2D drawing)
// At this point we have the image converted to texture and uploaded to GPU
free(imgDataPixelPOT); // Now we can free loaded data from RAM memory
spriteFont.texture.glId = id;
spriteFont.texture.width = potWidth;
spriteFont.texture.height = potHeight;
return spriteFont;
}
// Unload SpriteFont from GPU memory
void UnloadSpriteFont(SpriteFont spriteFont)
{
glDeleteTextures(1, &spriteFont.texture.glId);
free(spriteFont.charSet);
}
// Draw text (using default font)
// NOTE: fontSize work like in any drawing program but if fontSize is lower than font-base-size, then font-base-size is used
void DrawText(const char* text, int posX, int posY, int fontSize, int spacing, Color color)
{
Vector2 position = { (float)posX, (float)posY };
DrawTextEx(defaultFont, text, position, fontSize, spacing, color);
}
// Formatting of text with variables to 'embed'
const char *FormatText(const char *text, ...)
{
int length = strlen(text);
char *buffer = malloc(length + 20); // We add 20 extra characters, should be enough... :P
va_list args;
va_start(args, text);
vsprintf(buffer, text, args); // NOTE: We use vsprintf() defined in <stdarg.h>
va_end(args);
//strcat(buffer, "\0"); // We add a end-of-string mark at the end (not needed)
return buffer;
}
// Draw text using SpriteFont
// NOTE: If font size is lower than base size, base size is used
void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int fontSize, int spacing, Color tint)
{
int length = strlen(text);
int positionX = (int)position.x;
float scaleFactor;
Character c;
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
glDisable(GL_LIGHTING); // When drawing text, disable LIGHTING
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, spriteFont.texture.glId);
glPushMatrix();
// Optimized to use one draw call per string
glBegin(GL_QUADS);
for(int i = 0; i < length; i++)
{
c = spriteFont.charSet[(int)text[i] - FIRST_CHAR];
glColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
glTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX, position.y);
glTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX, position.y + (c.h) * scaleFactor);
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor);
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y);
positionX += (spriteFont.charSet[(int)text[i] - FIRST_CHAR].w + spacing) * scaleFactor;
}
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
// Measure string width for default font
int MeasureText(const char *text, int fontSize, int spacing)
{
Vector2 vec;
vec = MeasureTextEx(defaultFont, text, fontSize, spacing);
return (int)vec.x;
}
// Measure string size for SpriteFont
Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int spacing)
{
int len = strlen(text);
int textWidth = 0;
float scaleFactor;
for (int i = 0; i < len; i++)
{
textWidth += spriteFont.charSet[(int)text[i] - FIRST_CHAR].w;
}
textWidth += (int)((len - 1) * spacing); // Adds chars spacing to measure
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
Vector2 vec;
vec.x = (float)textWidth * scaleFactor;
vec.y = (float)spriteFont.charSet[0].h * scaleFactor;
return vec;
}
// Returns the base size for a SpriteFont (chars height)
int GetFontBaseSize(SpriteFont spriteFont)
{
return spriteFont.charSet[0].h;
}
// Shows current FPS on top-left corner
// NOTE: Uses default font
void DrawFps(int posX, int posY)
{
// NOTE: We are rendering fps every second for better viewing on high framerates
static float fps;
static int counter = 0;
static int refreshRate = 0;
char buffer[20];
if (counter < refreshRate)
{
sprintf(buffer, "%2.0f FPS", fps);
DrawText(buffer, posX, posY, 20, 1, LIME);
counter++;
}
else
{
fps = GetFPS();
refreshRate = fps;
sprintf(buffer, "%2.0f FPS", fps);
DrawText(buffer, posX, posY, 20, 1, LIME);
counter = 0;
}
}
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
// Check if a pixel is magenta
static bool PixelIsMagenta(Color p)
{
return ((p.r == 255) && (p.g == 0) && (p.b == 255) && (p.a == 255));
}
// Parse image pixel data to obtain character set measures
static int ParseImageData(Color *imgDataPixel, int imgWidth, int imgHeight, Character **charSet)
{
int charSpacing = 0;
int lineSpacing = 0;
int x = 0;
int y = 0;
Character tempCharSet[MAX_FONTCHARS]; // We allocate a temporal array for charData, once we get the actual charNumber we copy data to a sized array.
for(y = 0; y < imgHeight; y++)
{
for(x = 0; x < imgWidth; x++)
{
if (!PixelIsMagenta(imgDataPixel[y*imgWidth + x])) break;
}
if (!PixelIsMagenta(imgDataPixel[y*imgWidth + x])) break;
}
charSpacing = x;
lineSpacing = y;
int charHeight = 0;
int j = 0;
while(!PixelIsMagenta(imgDataPixel[(lineSpacing + j)*imgWidth + charSpacing])) j++;
charHeight = j;
// Check array values to get characters: value, x, y, w, h
int index = 0;
int lineToRead = 0;
int xPosToRead = charSpacing;
while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < imgHeight)
{
while((xPosToRead < imgWidth) &&
!PixelIsMagenta((imgDataPixel[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*imgWidth + xPosToRead])))
{
tempCharSet[index].value = FIRST_CHAR + index;
tempCharSet[index].x = xPosToRead;
tempCharSet[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
tempCharSet[index].h = charHeight;
int charWidth = 0;
while(!PixelIsMagenta(imgDataPixel[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*imgWidth + xPosToRead + charWidth])) charWidth++;
tempCharSet[index].w = charWidth;
index++;
xPosToRead += (charWidth + charSpacing);
}
lineToRead++;
xPosToRead = charSpacing;
}
// We got tempCharSet populated with char data and the number of chars (index)
// Now we move temp data to real charSet (passed as parameter to the function)
(*charSet) = (Character *)malloc(index * sizeof(Character)); // BE CAREFUL! This memory should be freed!
for (int i = 0; i < index; i++) (*charSet)[i] = tempCharSet[i];
return index;
}
// Calculate next power-of-two value for a given num
static int GetNextPOT(int num)
{
if (num != 0)
{
num--;
num |= (num >> 1); // Or first 2 bits
num |= (num >> 2); // Or next 2 bits
num |= (num >> 4); // Or next 4 bits
num |= (num >> 8); // Or next 8 bits
num |= (num >> 16); // Or next 16 bits
num++;
}
return num;
}

275
src/textures.c Normal file
View file

@ -0,0 +1,275 @@
/*********************************************************************************************
*
* raylib.textures
*
* Basic functions to load and draw Textures (2d)
*
* Uses external lib:
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <stdlib.h> // Declares malloc() and free() for memory management
#include "stb_image.h" // Used to read image data (multiple formats support)
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
// Nop...
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef unsigned char byte;
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
// It's lonely here...
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
// No private (static) functions in this module (.c file)
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
// Load an image into CPU memory (RAM)
Image LoadImage(const char *fileName)
{
Image image;
int imgWidth;
int imgHeight;
int imgBpp;
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA)
// Convert array to pixel array for working convenience
image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
int pix = 0;
for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
{
image.pixels[pix].r = imgData[i];
image.pixels[pix].g = imgData[i+1];
image.pixels[pix].b = imgData[i+2];
image.pixels[pix].a = imgData[i+3];
pix++;
}
stbi_image_free(imgData);
image.width = imgWidth;
image.height = imgHeight;
// ALTERNATIVE: We can load pixel data directly into Color struct pixels array,
// to do that struct data alignment should be the right one (4 byte); it is.
//image.pixels = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
return image;
}
// Unload image from CPU memory (RAM)
void UnloadImage(Image image)
{
free(image.pixels);
}
// Load an image as texture into GPU memory
Texture2D LoadTexture(const char *fileName)
{
Texture2D texture;
int imgWidth;
int imgHeight;
int imgBpp;
// NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...)
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4); // Force loading to 4 components (RGBA)
// Convert loaded data to OpenGL texture
//----------------------------------------
GLuint id;
glGenTextures(1, &id); // Generate Pointer to the Texture
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repead on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repead on y-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, imgWidth, imgHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
// NOTE: Not using mipmappings (texture for 2D drawing)
// At this point we have the image converted to texture and uploaded to GPU
stbi_image_free(imgData); // Now we can free loaded data from RAM memory
texture.glId = id;
texture.width = imgWidth;
texture.height = imgHeight;
return texture;
}
// Load an image as texture (and convert to POT with mipmaps)
Texture2D LoadTextureEx(const char *fileName, bool createPOT, bool mipmaps)
{
Texture2D texture;
// TODO: Load and image and convert to Power-Of-Two
// NOTE: Conversion could be done just adding extra space to image or by scaling image
// NOTE: If scaling image, be careful with scaling algorithm (aproximation, bilinear, bicubic...)
// TODO: Generate all required mipmap levels from image and convert to testure (not that easy)
// NOTE: If using OpenGL 1.1, the only option is doing mipmap generation on CPU side (i.e. gluBuild2DMipmaps)
// NOTE: raylib tries to minimize external dependencies so, we are not using GLU
// NOTE: Re-implement some function similar to gluBuild2DMipmaps (not that easy...)
return texture;
}
// Unload texture from GPU memory
void UnloadTexture(Texture2D texture)
{
glDeleteTextures(1, &texture.glId);
}
// Draw a Texture2D
void DrawTexture(Texture2D texture, int posX, int posY, Color tint)
{
DrawTextureEx(texture, (Vector2){ (float)posX, (float)posY}, 0, 1.0f, tint);
}
// Draw a Texture2D with extended parameters
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
{
glEnable(GL_TEXTURE_2D); // Enable textures usage
glBindTexture(GL_TEXTURE_2D, texture.glId);
glPushMatrix();
// NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
// NOTE: Rotation point is upper-left corner
glTranslatef(position.x, position.y, 0);
glScalef(scale, scale, 1.0f);
glRotatef(rotation, 0, 0, 1);
glBegin(GL_QUADS);
glColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // Bottom-left corner for texture and quad
glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-right corner for texture and quad
glTexCoord2f(1.0f, 1.0f); glVertex2f(texture.width, texture.height); // Top-right corner for texture and quad
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, texture.height); // Top-left corner for texture and quad
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // Disable textures usage
}
// Draw a part of a texture (defined by a rectangle)
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, float scale, Color tint)
{
glEnable(GL_TEXTURE_2D); // Enable textures usage
glBindTexture(GL_TEXTURE_2D, texture.glId);
glPushMatrix();
glTranslatef(position.x, position.y, 0);
glScalef(scale, scale, 1.0f);
//glRotatef(rotation, 0, 0, 1);
glBegin(GL_QUADS);
glColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
// Bottom-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
glVertex2f(0.0f, 0.0f);
// Bottom-right corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
glVertex2f(sourceRec.width, 0.0f);
// Top-right corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(sourceRec.width, sourceRec.height);
// Top-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(0.0f, sourceRec.height);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // Disable textures usage
}
// Creates a bitmap (BMP) file from an array of pixel data
// NOTE: This function is only used by module [core], not explicitly available to raylib users
extern void WriteBitmap(const char *fileName, const Color *imgDataPixel, int width, int height)
{
int filesize = 54 + 3*width*height;
unsigned char bmpFileHeader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0}; // Standard BMP file header
unsigned char bmpInfoHeader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0}; // Standard BMP info header
bmpFileHeader[2] = (unsigned char)(filesize);
bmpFileHeader[3] = (unsigned char)(filesize>>8);
bmpFileHeader[4] = (unsigned char)(filesize>>16);
bmpFileHeader[5] = (unsigned char)(filesize>>24);
bmpInfoHeader[4] = (unsigned char)(width);
bmpInfoHeader[5] = (unsigned char)(width>>8);
bmpInfoHeader[6] = (unsigned char)(width>>16);
bmpInfoHeader[7] = (unsigned char)(width>>24);
bmpInfoHeader[8] = (unsigned char)(height);
bmpInfoHeader[9] = (unsigned char)(height>>8);
bmpInfoHeader[10] = (unsigned char)(height>>16);
bmpInfoHeader[11] = (unsigned char)(height>>24);
FILE *bmpFile = fopen(fileName, "wb"); // Define a pointer to bitmap file and open it in write-binary mode
// NOTE: fwrite parameters are: data pointer, size in bytes of each element to be written, number of elements, file-to-write pointer
fwrite(bmpFileHeader, sizeof(unsigned char), 14, bmpFile); // Write BMP file header data
fwrite(bmpInfoHeader, sizeof(unsigned char), 40, bmpFile); // Write BMP info header data
// Write pixel data to file
for (int y = 0; y < height ; y++)
{
for (int x = 0; x < width; x++)
{
fputc(imgDataPixel[x + y*width].b, bmpFile);
fputc(imgDataPixel[x + y*width].g, bmpFile);
fputc(imgDataPixel[x + y*width].r, bmpFile);
}
}
fclose(bmpFile); // Close bitmap file
}

140
src/vector3.c Normal file
View file

@ -0,0 +1,140 @@
/*********************************************************************************************
*
* raylib.vector3
*
* Vector3 Functions Definition
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#include "vector3.h"
#include <math.h>
// Add two vectors
Vector3 VectorAdd(Vector3 v1, Vector3 v2)
{
Vector3 out;
out.x = v1.x + v2.x;
out.y = v1.y + v2.y;
out.z = v1.z + v2.z;
return out;
}
// Substract two vectors
Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
{
Vector3 out;
out.x = v1.x - v2.x;
out.y = v1.y - v2.y;
out.z = v1.z - v2.z;
return out;
}
// Calculate two vectors cross product
Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
{
Vector3 cross;
cross.x = v1.y*v2.z - v1.z*v2.y;
cross.y = v1.z*v2.x - v1.x*v2.z;
cross.z = v1.x*v2.y - v1.y*v2.x;
return cross;
}
// Calculate one vector perpendicular vector
Vector3 VectorPerpendicular(Vector3 v)
{
Vector3 out;
float min = fabs(v.x);
Vector3 cardinalAxis = {1.0, 0.0, 0.0};
if (fabs(v.y) < min)
{
min = fabs(v.y);
cardinalAxis = (Vector3){0.0, 1.0, 0.0};
}
if(fabs(v.z) < min)
{
cardinalAxis = (Vector3){0.0, 0.0, 1.0};
}
out = VectorCrossProduct(v, cardinalAxis);
return out;
}
// Calculate two vectors dot product
float VectorDotProduct(Vector3 v1, Vector3 v2)
{
float dot;
dot = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
return dot;
}
// Calculate vector lenght
float VectorLength(const Vector3 v)
{
float length;
length = sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
return length;
}
// Scale provided vector
void VectorScale(Vector3 *v, float scale)
{
v->x *= scale;
v->y *= scale;
v->z *= scale;
}
// Invert provided vector (direction)
void VectorInverse(Vector3 *v)
{
v->x = -v->x;
v->y = -v->y;
v->z = -v->z;
}
// Normalize provided vector
void VectorNormalize(Vector3 *v)
{
float length, ilength;
length = VectorLength(*v);
if (length == 0) length = 1;
ilength = 1.0/length;
v->x *= ilength;
v->y *= ilength;
v->z *= ilength;
}

57
src/vector3.h Normal file
View file

@ -0,0 +1,57 @@
/*********************************************************************************************
*
* raylib.vector3
*
* Some useful functions to work with Vector3
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.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.
*
**********************************************************************************************/
#ifndef VECTOR3_H
#define VECTOR3_H
#include "raylib.h" // Defines Vector3 structure
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//------------------------------------------------------------------------------------
// Global Variables Definition
//------------------------------------------------------------------------------------
// It's lonely here...
//------------------------------------------------------------------------------------
// Functions Declaration to work with Vector3
//------------------------------------------------------------------------------------
Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors
Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors
Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product
Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector
float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product
float VectorLength(const Vector3 v); // Calculate vector lenght
void VectorScale(Vector3 *v, float scale); // Scale provided vector
void VectorInverse(Vector3 *v); // Invert provided vector (direction)
void VectorNormalize(Vector3 *v); // Normalize provided vector
#ifdef __cplusplus
}
#endif
#endif // VECTOR3_H