aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorraysan5 <raysan5@gmail.com>2015-08-27 16:32:06 +0200
committerraysan5 <raysan5@gmail.com>2015-08-27 16:32:06 +0200
commit3a9ed0e8462570e30d92e2aa8c0ff3cf655ef863 (patch)
tree9e2593de39f6daab0dc283837e325937cbf41f1c /src
parent8b3a82688e82922819d24494c08e24570c03bdc4 (diff)
parent997170a317bb8077cb96d3fc757c6cde0c0ea466 (diff)
downloadraylib-3a9ed0e8462570e30d92e2aa8c0ff3cf655ef863.tar.gz
raylib-3a9ed0e8462570e30d92e2aa8c0ff3cf655ef863.zip
Merged master fixed conflict.
Diffstat (limited to 'src')
-rw-r--r--src/audio.c143
-rw-r--r--src/audio.h102
-rw-r--r--src/camera.c315
-rw-r--r--src/camera.h51
-rw-r--r--src/core.c208
-rw-r--r--src/gestures.c225
-rw-r--r--src/gestures.h107
-rw-r--r--src/makefile6
-rw-r--r--src/models.c35
-rw-r--r--src/raylib.h80
-rw-r--r--src/rlgl.c543
-rw-r--r--src/rlgl.h94
-rw-r--r--src/shapes.c2
-rw-r--r--src/text.c6
-rw-r--r--src/textures.c279
-rw-r--r--src/utils.c2
16 files changed, 1365 insertions, 833 deletions
diff --git a/src/audio.c b/src/audio.c
index 9653c091..b8025ad6 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -8,7 +8,7 @@
* OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
* stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -27,7 +27,13 @@
*
**********************************************************************************************/
-#include "raylib.h"
+//#define AUDIO_STANDALONE // NOTE: To use the audio module as standalone lib, just uncomment this line
+
+#if defined(AUDIO_STANDALONE)
+ #include "audio.h"
+#else
+ #include "raylib.h"
+#endif
#include "AL/al.h" // OpenAL basic header
#include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work)
@@ -36,8 +42,12 @@
#include <string.h> // Required for strcmp()
#include <stdio.h> // Used for .WAV loading
-#include "utils.h" // rRES data decompression utility function
+#if defined(AUDIO_STANDALONE)
+ #include <stdarg.h> // Used for functions with variable number of parameters (TraceLog())
+#else
+ #include "utils.h" // rRES data decompression utility function
// NOTE: Includes Android fopen function map
+#endif
//#define STB_VORBIS_HEADER_ONLY
#include "stb_vorbis.h" // OGG loading functions
@@ -75,6 +85,10 @@ typedef struct Music {
} Music;
+#if defined(AUDIO_STANDALONE)
+typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
+#endif
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
@@ -85,13 +99,18 @@ static Music currentMusic; // Current music loaded
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
-static Wave LoadWAV(const char *fileName); // Load WAV file
-static Wave LoadOGG(char *fileName); // Load OGG file
-static void UnloadWave(Wave wave); // Unload wave data
+static Wave LoadWAV(const char *fileName); // Load WAV file
+static Wave LoadOGG(char *fileName); // Load OGG file
+static void UnloadWave(Wave wave); // Unload wave data
-static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data
-static void EmptyMusicStream(void); // Empty music buffers
-extern void UpdateMusicStream(void); // Updates buffers (refill) for music streaming
+static bool BufferMusicStream(ALuint buffer); // Fill music buffers with data
+static void EmptyMusicStream(void); // Empty music buffers
+extern void UpdateMusicStream(void); // Updates buffers (refill) for music streaming
+
+#if defined(AUDIO_STANDALONE)
+const char *GetExtension(const char *fileName); // Get the extension for a filename
+void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message (INFO, ERROR, WARNING)
+#endif
//----------------------------------------------------------------------------------
// Module Functions Definition - Audio Device initialization and Closing
@@ -273,8 +292,13 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
{
// NOTE: rresName could be directly a char array with all the data!!! --> TODO
Sound sound;
- bool found = false;
+#if defined(AUDIO_STANDALONE)
+ TraceLog(WARNING, "Sound loading from rRES resource file not supported on standalone mode");
+#else
+
+ bool found = false;
+
char id[4]; // rRES file identifier
unsigned char version; // rRES file version and subversion
char useless; // rRES header reserved data
@@ -416,7 +440,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId)
}
if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId);
-
+#endif
return sound;
}
@@ -425,6 +449,8 @@ void UnloadSound(Sound sound)
{
alDeleteSources(1, &sound.source);
alDeleteBuffers(1, &sound.buffer);
+
+ TraceLog(INFO, "Unloaded sound data");
}
// Play a sound
@@ -777,6 +803,7 @@ static Wave LoadWAV(const char *fileName)
if (wavFile == NULL)
{
TraceLog(WARNING, "[%s] WAV file could not be opened", fileName);
+ wave.data = NULL;
}
else
{
@@ -846,40 +873,49 @@ static Wave LoadOGG(char *fileName)
Wave wave;
stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL);
- stb_vorbis_info info = stb_vorbis_get_info(oggFile);
- wave.sampleRate = info.sample_rate;
- wave.bitsPerSample = 16;
- wave.channels = info.channels;
+ if (oggFile == NULL)
+ {
+ TraceLog(WARNING, "[%s] OGG file could not be opened", fileName);
+ wave.data = NULL;
+ }
+ else
+ {
+ stb_vorbis_info info = stb_vorbis_get_info(oggFile);
- TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
- TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels);
+ wave.sampleRate = info.sample_rate;
+ wave.bitsPerSample = 16;
+ wave.channels = info.channels;
- int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels);
+ TraceLog(DEBUG, "[%s] Ogg sample rate: %i", fileName, info.sample_rate);
+ TraceLog(DEBUG, "[%s] Ogg channels: %i", fileName, info.channels);
- wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes
+ int totalSamplesLength = (stb_vorbis_stream_length_in_samples(oggFile) * info.channels);
- TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength);
+ wave.dataSize = totalSamplesLength*sizeof(short); // Size must be in bytes
- float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
+ TraceLog(DEBUG, "[%s] Samples length: %i", fileName, totalSamplesLength);
- TraceLog(DEBUG, "[%s] Total seconds: %f", fileName, totalSeconds);
+ float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile);
- if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
+ TraceLog(DEBUG, "[%s] Total seconds: %f", fileName, totalSeconds);
- int totalSamples = totalSeconds*info.sample_rate*info.channels;
+ if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds);
- TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples);
+ int totalSamples = totalSeconds*info.sample_rate*info.channels;
- wave.data = malloc(sizeof(short)*totalSamplesLength);
+ TraceLog(DEBUG, "[%s] Total samples calculated: %i", fileName, totalSamples);
- int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
+ wave.data = malloc(sizeof(short)*totalSamplesLength);
- TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
+ int samplesObtained = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, wave.data, totalSamplesLength);
- TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
+ TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, samplesObtained);
- stb_vorbis_close(oggFile);
+ TraceLog(INFO, "[%s] OGG file loaded successfully (SampleRate: %i, BitRate: %i, Channels: %i)", fileName, wave.sampleRate, wave.bitsPerSample, wave.channels);
+
+ stb_vorbis_close(oggFile);
+ }
return wave;
}
@@ -888,4 +924,49 @@ static Wave LoadOGG(char *fileName)
static void UnloadWave(Wave wave)
{
free(wave.data);
-} \ No newline at end of file
+
+ TraceLog(INFO, "Unloaded wave data");
+}
+
+// Some required functions for audio standalone module version
+#if defined(AUDIO_STANDALONE)
+// Get the extension for a filename
+const char *GetExtension(const char *fileName)
+{
+ const char *dot = strrchr(fileName, '.');
+ if(!dot || dot == fileName) return "";
+ return (dot + 1);
+}
+
+// Outputs a trace log message (INFO, ERROR, WARNING)
+// NOTE: If a file has been init, output log is written there
+void TraceLog(int msgType, const char *text, ...)
+{
+ va_list args;
+ int traceDebugMsgs = 0;
+
+#ifdef DO_NOT_TRACE_DEBUG_MSGS
+ traceDebugMsgs = 0;
+#endif
+
+ switch(msgType)
+ {
+ case INFO: fprintf(stdout, "INFO: "); break;
+ case ERROR: fprintf(stdout, "ERROR: "); break;
+ case WARNING: fprintf(stdout, "WARNING: "); break;
+ case DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break;
+ default: break;
+ }
+
+ if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs)))
+ {
+ va_start(args, text);
+ vfprintf(stdout, text, args);
+ va_end(args);
+
+ fprintf(stdout, "\n");
+ }
+
+ if (msgType == ERROR) exit(1); // If ERROR message, exit program
+}
+#endif \ No newline at end of file
diff --git a/src/audio.h b/src/audio.h
new file mode 100644
index 00000000..ed156532
--- /dev/null
+++ b/src/audio.h
@@ -0,0 +1,102 @@
+/**********************************************************************************************
+*
+* raylib.audio
+*
+* Basic functions to manage Audio: InitAudioDevice, LoadAudioFiles, PlayAudioFiles
+*
+* Uses external lib:
+* OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html)
+* stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/)
+*
+* Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*
+* 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 AUDIO_H
+#define AUDIO_H
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// NOTE: Below types are required for CAMERA_STANDALONE usage
+//----------------------------------------------------------------------------------
+#ifndef __cplusplus
+// Boolean type
+typedef enum { false, true } bool;
+#endif
+
+// Sound source type
+typedef struct Sound {
+ unsigned int source;
+ unsigned int buffer;
+} Sound;
+
+// Wave type, defines audio wave data
+typedef struct Wave {
+ void *data; // Buffer data pointer
+ unsigned int dataSize; // Data size in bytes
+ unsigned int sampleRate;
+ short bitsPerSample;
+ short channels;
+} Wave;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+void InitAudioDevice(void); // Initialize audio device and context
+void CloseAudioDevice(void); // Close the audio device and context (and music stream)
+
+Sound LoadSound(char *fileName); // Load sound to memory
+Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data
+Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource)
+void UnloadSound(Sound sound); // Unload sound
+void PlaySound(Sound sound); // Play a sound
+void PauseSound(Sound sound); // Pause a sound
+void StopSound(Sound sound); // Stop playing a sound
+bool SoundIsPlaying(Sound sound); // Check if a sound is currently playing
+void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
+void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
+
+void PlayMusicStream(char *fileName); // Start music playing (open stream)
+void UpdateMusicStream(void); // Updates buffers for music streaming
+void StopMusicStream(void); // Stop music playing (close stream)
+void PauseMusicStream(void); // Pause music playing
+void ResumeMusicStream(void); // Resume playing paused music
+bool MusicIsPlaying(void); // Check if music is playing
+void SetMusicVolume(float volume); // Set volume for music (1.0 is max level)
+float GetMusicTimeLength(void); // Get current music time length (in seconds)
+float GetMusicTimePlayed(void); // Get current music time played (in seconds)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AUDIO_H \ No newline at end of file
diff --git a/src/camera.c b/src/camera.c
index cde118c9..627451fe 100644
--- a/src/camera.c
+++ b/src/camera.c
@@ -1,8 +1,6 @@
/**********************************************************************************************
*
-* raylib.camera
-*
-* Camera Modes Setup and Control Functions
+* raylib Camera System - Camera Modes Setup and Control Functions
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
@@ -23,7 +21,14 @@
*
**********************************************************************************************/
-#include "camera.h"
+//#define CAMERA_STANDALONE // NOTE: To use the camera module as standalone lib, just uncomment this line
+ // NOTE: ProcessCamera() should be reviewed to adapt inputs to other systems
+
+#if defined(CAMERA_STANDALONE)
+ #include "camera.h"
+#else
+ #include "raylib.h"
+#endif
#include <math.h>
@@ -49,7 +54,7 @@
//#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003
#define FIRST_PERSON_FOCUS_DISTANCE 25
#define FIRST_PERSON_MIN_CLAMP 85
-#define FIRST_PERSON_MAX_CLAMP -85
+#define FIRST_PERSON_MAX_CLAMP -85
#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0
#define FIRST_PERSON_STEP_DIVIDER 30.0
@@ -61,7 +66,7 @@
//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003
#define THIRD_PERSON_DISTANCE_CLAMP 1.2
#define THIRD_PERSON_MIN_CLAMP 5
-#define THIRD_PERSON_MAX_CLAMP -85
+#define THIRD_PERSON_MAX_CLAMP -85
#define THIRD_PERSON_OFFSET (Vector3){ 0.4, 0, 0 }
// PLAYER (used by camera)
@@ -71,22 +76,26 @@
#define PLAYER_MOVEMENT_DIVIDER 20.0
//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Camera move modes (first person and third person cameras)
+typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_DOWN } CameraMove;
+
+//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static Camera internalCamera = {{2,0,2},{0,0,0},{0,1,0}};
static Vector2 cameraAngle = { 0, 0 };
static float cameraTargetDistance = 5;
-static Vector3 resetingPosition = { 0, 0, 0 };
-static int resetingKey = 'Z';
static Vector2 cameraMousePosition = { 0, 0 };
static Vector2 cameraMouseVariation = { 0, 0 };
static float mouseSensitivity = 0.003;
-static int cameraMovementController[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
-static int cameraMovementCounter = 0;
-static bool cameraUseGravity = true;
-static int pawnControllingKey = MOUSE_MIDDLE_BUTTON;
-static int fnControllingKey = KEY_LEFT_ALT;
-static int smoothZoomControllingKey = KEY_LEFT_CONTROL;
+static int cameraMoveControl[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
+static int cameraMoveCounter = 0;
+static int cameraUseGravity = 1;
+static int panControlKey = 2; // raylib: MOUSE_MIDDLE_BUTTON
+static int altControlKey = 342; // raylib: KEY_LEFT_ALT
+static int smoothZoomControlKey = 341; // raylib: KEY_LEFT_CONTROL
static int cameraMode = CAMERA_CUSTOM;
@@ -95,6 +104,20 @@ static int cameraMode = CAMERA_CUSTOM;
//----------------------------------------------------------------------------------
static void ProcessCamera(Camera *camera, Vector3 *playerPosition);
+#if defined(CAMERA_STANDALONE)
+// NOTE: Camera controls depend on some raylib input functions
+// TODO: Set your own input functions (used in ProcessCamera())
+static Vector2 GetMousePosition() { return (Vector2){ 0, 0}; }
+static void SetMousePosition(Vector2 pos) {}
+static int IsMouseButtonDown(int button) { return 0;}
+static int GetMouseWheelMove() { return 0; }
+static int GetScreenWidth() { return 1280; }
+static int GetScreenHeight() { return 720; }
+static void ShowCursor() {}
+static void HideCursor() {}
+static int IsKeyDown(int key) { return 0; }
+#endif
+
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
@@ -123,6 +146,8 @@ void SetCameraMode(int mode)
cameraAngle.y = -40 * DEG2RAD;
internalCamera.target = (Vector3){ 0, 0, 0};
ProcessCamera(&internalCamera, &internalCamera.position);
+
+ ShowCursor();
}
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL))
{
@@ -145,48 +170,37 @@ Camera UpdateCamera(Vector3 *position)
return internalCamera;
}
-
-void SetCameraControls(int frontKey, int leftKey, int backKey, int rightKey, int upKey, int downKey)
+void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, int upKey, int downKey)
{
- cameraMovementController[0] = frontKey;
- cameraMovementController[1] = leftKey;
- cameraMovementController[2] = backKey;
- cameraMovementController[3] = rightKey;
- cameraMovementController[4] = upKey;
- cameraMovementController[5] = downKey;
+ cameraMoveControl[MOVE_FRONT] = frontKey;
+ cameraMoveControl[MOVE_LEFT] = leftKey;
+ cameraMoveControl[MOVE_BACK] = backKey;
+ cameraMoveControl[MOVE_RIGHT] = rightKey;
+ cameraMoveControl[MOVE_UP] = upKey;
+ cameraMoveControl[MOVE_DOWN] = downKey;
}
void SetCameraMouseSensitivity(float sensitivity)
{
mouseSensitivity = (sensitivity / 10000.0);
}
-
-void SetCameraResetPosition(Vector3 resetPosition)
-{
- resetingPosition = resetPosition;
-}
-
-void SetCameraResetControl(int resetKey)
-{
- resetingKey = resetKey;
-}
-void SetCameraPawnControl(int pawnControlKey)
+void SetCameraPanControl(int panKey)
{
- pawnControllingKey = pawnControlKey;
+ panControlKey = panKey;
}
-void SetCameraFnControl(int fnControlKey)
+void SetCameraAltControl(int altKey)
{
- fnControllingKey = fnControlKey;
+ altControlKey = altKey;
}
-void SetCameraSmoothZoomControl(int smoothZoomControlKey)
+void SetCameraSmoothZoomControl(int szKey)
{
- smoothZoomControllingKey = smoothZoomControlKey;
+ smoothZoomControlKey = szKey;
}
-void SetCameraOrbitalTarget(Vector3 target)
+void SetCameraTarget(Vector3 target)
{
internalCamera.target = target;
}
@@ -197,33 +211,43 @@ void SetCameraOrbitalTarget(Vector3 target)
//----------------------------------------------------------------------------------
// Process desired camera mode and controls
+// NOTE: Camera controls depend on some raylib functions:
+// Mouse: GetMousePosition(), SetMousePosition(), IsMouseButtonDown(), GetMouseWheelMove()
+// System: GetScreenWidth(), GetScreenHeight(), ShowCursor(), HideCursor()
+// Keys: IsKeyDown()
static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
{
-#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI)
// Mouse movement detection
+ Vector2 mousePosition = GetMousePosition();
+ int mouseWheelMove = GetMouseWheelMove();
+ int panKey = IsMouseButtonDown(panControlKey); // bool value
+
+ int screenWidth = GetScreenWidth();
+ int screenHeight = GetScreenHeight();
+
if ((cameraMode != CAMERA_FREE) && (cameraMode != CAMERA_ORBITAL))
{
HideCursor();
-
- if (GetMousePosition().x < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetScreenWidth() - GetScreenHeight() / 3, GetMousePosition().y});
- else if (GetMousePosition().y < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() - GetScreenHeight() / 3});
- else if (GetMousePosition().x > GetScreenWidth() - GetScreenHeight() / 3) SetMousePosition((Vector2) { GetScreenHeight() / 3, GetMousePosition().y});
- else if (GetMousePosition().y > GetScreenHeight() - GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() / 3});
+
+ if (mousePosition.x < screenHeight/3) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y});
+ else if (mousePosition.y < screenHeight/3) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3});
+ else if (mousePosition.x > screenWidth - screenHeight/3) SetMousePosition((Vector2) { screenHeight/3, mousePosition.y});
+ else if (mousePosition.y > screenHeight - screenHeight/3) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3});
else
{
- cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
- cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
+ cameraMouseVariation.x = mousePosition.x - cameraMousePosition.x;
+ cameraMouseVariation.y = mousePosition.y - cameraMousePosition.y;
}
}
else
{
ShowCursor();
-
- cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
- cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
+
+ cameraMouseVariation.x = mousePosition.x - cameraMousePosition.x;
+ cameraMouseVariation.y = mousePosition.y - cameraMousePosition.y;
}
- cameraMousePosition = GetMousePosition();
+ cameraMousePosition = mousePosition;
// Support for multiple automatic camera modes
switch (cameraMode)
@@ -231,92 +255,93 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
case CAMERA_FREE:
{
// Camera zoom
- if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
+ if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
- cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
+ cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance > FREE_CAMERA_DISTANCE_MAX_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MAX_CLAMP;
}
// Camera looking down
- else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
+ else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
- camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
}
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
{
- camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
if (camera->target.y < 0) camera->target.y = -0.001;
}
- else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (GetMouseWheelMove() > 0))
+ else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (mouseWheelMove > 0))
{
- cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
+ cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
// Camera looking up
- else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
+ else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0))
{
- camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
}
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
{
- camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
- camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
+ camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
+ camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance;
if (camera->target.y > 0) camera->target.y = 0.001;
}
- else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (GetMouseWheelMove() > 0))
+ else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (mouseWheelMove > 0))
{
- cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
+ cameraTargetDistance -= (mouseWheelMove * CAMERA_SCROLL_SENSITIVITY);
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
}
// Inputs
- if (IsKeyDown(fnControllingKey))
+ if (IsKeyDown(altControlKey))
{
- if (IsKeyDown(smoothZoomControllingKey))
+ if (IsKeyDown(smoothZoomControlKey))
{
// Camera smooth zoom
- if (IsMouseButtonDown(pawnControllingKey)) cameraTargetDistance += (cameraMouseVariation.y * FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
+ if (panKey) cameraTargetDistance += (cameraMouseVariation.y*FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
}
// Camera orientation calculation
- else if (IsMouseButtonDown(pawnControllingKey))
+ else if (panKey)
{
// Camera orientation calculation
// Get the mouse sensitivity
- cameraAngle.x += cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY;
- cameraAngle.y += cameraMouseVariation.y * -FREE_CAMERA_MOUSE_SENSITIVITY;
+ cameraAngle.x += cameraMouseVariation.x*-FREE_CAMERA_MOUSE_SENSITIVITY;
+ cameraAngle.y += cameraMouseVariation.y*-FREE_CAMERA_MOUSE_SENSITIVITY;
// Angle clamp
- if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP * DEG2RAD;
- else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP * DEG2RAD;
+ if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP*DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP*DEG2RAD;
+ else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP*DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP*DEG2RAD;
}
}
// Paning
- else if (IsMouseButtonDown(pawnControllingKey))
+ else if (panKey)
{
- camera->target.x += ((cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
- camera->target.y += ((cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
- camera->target.z += ((cameraMouseVariation.x * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
+ camera->target.x += ((cameraMouseVariation.x*-FREE_CAMERA_MOUSE_SENSITIVITY)*cos(cameraAngle.x) + (cameraMouseVariation.y*FREE_CAMERA_MOUSE_SENSITIVITY)*sin(cameraAngle.x)*sin(cameraAngle.y))*(cameraTargetDistance/FREE_CAMERA_PANNING_DIVIDER);
+ camera->target.y += ((cameraMouseVariation.y*FREE_CAMERA_MOUSE_SENSITIVITY)*cos(cameraAngle.y))*(cameraTargetDistance/FREE_CAMERA_PANNING_DIVIDER);
+ camera->target.z += ((cameraMouseVariation.x*FREE_CAMERA_MOUSE_SENSITIVITY)*sin(cameraAngle.x) + (cameraMouseVariation.y*FREE_CAMERA_MOUSE_SENSITIVITY)*cos(cameraAngle.x)*sin(cameraAngle.y))*(cameraTargetDistance/FREE_CAMERA_PANNING_DIVIDER);
}
// Focus to center
- if (IsKeyDown(resetingKey)) camera->target = resetingPosition;
+ // TODO: Move this function out of the module?
+ if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 };
// Camera position update
- camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
+ camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x;
- if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
- else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
+ if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
+ else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
- camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
+ camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z;
} break;
case CAMERA_ORBITAL:
@@ -324,126 +349,126 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
cameraAngle.x += ORBITAL_CAMERA_SPEED;
// Camera zoom
- cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
+ cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
+
// Camera distance clamp
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
// Focus to center
- if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 };
+ if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 };
// Camera position update
- camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
+ camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x;
- if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
- else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
+ if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
+ else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
- camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
+ camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z;
} break;
case CAMERA_FIRST_PERSON:
case CAMERA_THIRD_PERSON:
{
- bool isMoving = false;
+ int isMoving = 0;
// Keyboard inputs
- if (IsKeyDown(cameraMovementController[0]))
+ if (IsKeyDown(cameraMoveControl[MOVE_FRONT]))
{
- playerPosition->x -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
- playerPosition->z -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
- if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->x -= sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->z -= cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
+
+ if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER;
- isMoving = true;
+ isMoving = 1;
}
- else if (IsKeyDown(cameraMovementController[2]))
+ else if (IsKeyDown(cameraMoveControl[MOVE_BACK]))
{
- playerPosition->x += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
- playerPosition->z += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
- if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->x += sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->z += cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
+
+ if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER;
- isMoving = true;
+ isMoving = 1;
}
- if (IsKeyDown(cameraMovementController[1]))
+ if (IsKeyDown(cameraMoveControl[MOVE_LEFT]))
{
- playerPosition->x -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
- playerPosition->z += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->x -= cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->z += sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
- isMoving = true;
+ isMoving = 1;
}
- else if (IsKeyDown(cameraMovementController[3]))
+ else if (IsKeyDown(cameraMoveControl[MOVE_RIGHT]))
{
- playerPosition->x += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
- playerPosition->z -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->x += cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
+ playerPosition->z -= sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER;
- isMoving = true;
+ isMoving = 1;
}
- if (IsKeyDown(cameraMovementController[4]))
+ if (IsKeyDown(cameraMoveControl[MOVE_UP]))
{
- if (!cameraUseGravity) playerPosition->y += 1 / PLAYER_MOVEMENT_DIVIDER;
+ if (!cameraUseGravity) playerPosition->y += 1/PLAYER_MOVEMENT_DIVIDER;
}
- else if (IsKeyDown(cameraMovementController[5]))
+ else if (IsKeyDown(cameraMoveControl[MOVE_DOWN]))
{
- if (!cameraUseGravity) playerPosition->y -= 1 / PLAYER_MOVEMENT_DIVIDER;
+ if (!cameraUseGravity) playerPosition->y -= 1/PLAYER_MOVEMENT_DIVIDER;
}
if (cameraMode == CAMERA_THIRD_PERSON)
{
// Camera orientation calculation
- // Get the mouse sensitivity
- cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
- cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
+ cameraAngle.x += cameraMouseVariation.x*-mouseSensitivity;
+ cameraAngle.y += cameraMouseVariation.y*-mouseSensitivity;
// Angle clamp
- if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP * DEG2RAD;
- else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP * DEG2RAD;
+ if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP*DEG2RAD;
+ else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP*DEG2RAD;
// Camera zoom
- cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
+ cameraTargetDistance -= (mouseWheelMove*CAMERA_SCROLL_SENSITIVITY);
// Camera distance clamp
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
// Camera is always looking at player
- camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x * cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x);
- camera->target.y = playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
- camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x * sin(cameraAngle.x);
+ camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x*cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z*sin(cameraAngle.x);
+ camera->target.y = playerPosition->y + PLAYER_HEIGHT*FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
+ camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z*sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x*sin(cameraAngle.x);
// Camera position update
- camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
+ camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x;
- if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
- else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
+ if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
+ else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y;
- camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
+ camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z;
}
- else
+ else // CAMERA_FIRST_PERSON
{
- if (isMoving) cameraMovementCounter++;
+ if (isMoving) cameraMoveCounter++;
// Camera orientation calculation
- // Get the mouse sensitivity
- cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
- cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
+ cameraAngle.x += cameraMouseVariation.x*-mouseSensitivity;
+ cameraAngle.y += cameraMouseVariation.y*-mouseSensitivity;
// Angle clamp
- if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP * DEG2RAD;
- else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP * DEG2RAD;
+ if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP*DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP*DEG2RAD;
+ else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP*DEG2RAD;
// Camera is always looking at player
- camera->target.x = camera->position.x - sin(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
- camera->target.y = camera->position.y + sin(cameraAngle.y) * FIRST_PERSON_FOCUS_DISTANCE;
- camera->target.z = camera->position.z - cos(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
+ camera->target.x = camera->position.x - sin(cameraAngle.x)*FIRST_PERSON_FOCUS_DISTANCE;
+ camera->target.y = camera->position.y + sin(cameraAngle.y)*FIRST_PERSON_FOCUS_DISTANCE;
+ camera->target.z = camera->position.z - cos(cameraAngle.x)*FIRST_PERSON_FOCUS_DISTANCE;
camera->position.x = playerPosition->x;
- camera->position.y = (playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMovementCounter / FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER) / FIRST_PERSON_STEP_DIVIDER;
+ camera->position.y = (playerPosition->y + PLAYER_HEIGHT*FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMoveCounter/FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/FIRST_PERSON_STEP_DIVIDER;
camera->position.z = playerPosition->z;
- camera->up.x = sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
- camera->up.z = -sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
+ camera->up.x = sin(cameraMoveCounter/(FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/FIRST_PERSON_WAVING_DIVIDER;
+ camera->up.z = -sin(cameraMoveCounter/(FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/FIRST_PERSON_WAVING_DIVIDER;
}
} break;
default: break;
}
-#endif
-}
+} \ No newline at end of file
diff --git a/src/camera.h b/src/camera.h
index cb5f2bde..63d8f786 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -24,7 +24,12 @@
#ifndef CAMERA_H
#define CAMERA_H
-#include "raylib.h"
+#ifndef PI
+ #define PI 3.14159265358979323846
+#endif
+
+#define DEG2RAD (PI / 180.0f)
+#define RAD2DEG (180.0f / PI)
//----------------------------------------------------------------------------------
// Defines and Macros
@@ -33,10 +38,30 @@
//----------------------------------------------------------------------------------
// Types and Structures Definition
+// NOTE: Below types are required for CAMERA_STANDALONE usage
//----------------------------------------------------------------------------------
// Camera modes
typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
+// 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;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
@@ -50,17 +75,19 @@ extern "C" { // Prevents name mangling of functions
//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
-void SetCameraMode(int mode); // Select camera mode (multiple camera modes available)
-Camera UpdateCamera(Vector3 *position); // Update camera with position
-
-void SetCameraControls(int front, int left, int back, int right, int up, int down);
-void SetCameraMouseSensitivity(float sensitivity);
-void SetCameraResetPosition(Vector3 resetPosition);
-void SetCameraResetControl(int resetKey);
-void SetCameraPawnControl(int pawnControlKey);
-void SetCameraFnControl(int fnControlKey);
-void SetCameraSmoothZoomControl(int smoothZoomControlKey);
-void SetCameraOrbitalTarget(Vector3 target);
+void SetCameraMode(int mode); // Set camera mode (multiple camera modes available)
+Camera UpdateCamera(Vector3 *playerPosition); // Update camera and player position (1st person and 3rd person cameras)
+
+void SetCameraMoveControls(int frontKey, int backKey,
+ int leftKey, int rightKey,
+ int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
+
+void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera)
+void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera)
+void SetCameraSmoothZoomControl(int szKey); // Set camera smooth zoom key to combine with mouse (free camera)
+
+void SetCameraMouseSensitivity(float sensitivity); // Set camera mouse sensitivity (1st person and 3rd person cameras)
+void SetCameraTarget(Vector3 target); // Set internal camera target
#ifdef __cplusplus
}
diff --git a/src/core.c b/src/core.c
index 1cdcd679..e3c4e10b 100644
--- a/src/core.c
+++ b/src/core.c
@@ -17,7 +17,7 @@
*
* On PLATFORM_RPI, graphic device is managed by EGL and input system is coded in raw mode.
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -164,7 +164,7 @@ static bool customCursor = false; // Tracks if custom cursor has been
static bool cursorOnScreen = false; // Tracks if cursor is inside client area
static Texture2D cursor; // Cursor texture
-static Vector2 mousePosition;
+static Vector2 mousePosition; // Mouse position on screen
static char previousKeyState[512] = { 0 }; // Required to check if key pressed/released once
static char currentKeyState[512] = { 0 }; // Required to check if key pressed/released once
@@ -179,9 +179,12 @@ static int previousMouseWheelY = 0; // Required to track mouse wheel var
static int currentMouseWheelY = 0; // Required to track mouse wheel variation
static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
-static int lastKeyPressed = -1;
+static int lastKeyPressed = -1; // Register last key pressed
-static bool cursorHidden;
+static bool cursorHidden; // Track if cursor is hidden
+
+static char **dropFilesPath; // Store dropped files paths as strings
+static int dropFilesCount = 0; // Count stored strings
#endif
static double currentTime, previousTime; // Used to track timmings
@@ -189,8 +192,8 @@ static double updateTime, drawTime; // Time measures for update and draw
static double frameTime; // Time measure for one frame
static double targetTime = 0.0; // Desired time for one frame, if 0 not applied
-static char configFlags = 0;
-static bool showLogo = false;
+static char configFlags = 0; // Configuration flags (bit based)
+static bool showLogo = false; // Track if showing logo at init is enabled
//----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core)
@@ -198,19 +201,6 @@ static bool showLogo = false;
extern void LoadDefaultFont(void); // [Module: text] Loads default font on InitWindow()
extern void UnloadDefaultFont(void); // [Module: text] Unloads default font from GPU memory
-extern void UpdateMusicStream(void); // [Module: audio] Updates buffers for music streaming
-
-extern Vector2 GetRawPosition(void);
-extern void ResetGestures(void);
-
-#if defined(PLATFORM_ANDROID)
-extern void InitAndroidGestures(struct android_app *app);
-#endif
-
-#if defined(PLATFORM_WEB)
-extern void InitWebGestures(void); // [Module: gestures] Initializes emscripten gestures for web
-#endif
-
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
@@ -241,7 +231,11 @@ static void CharCallback(GLFWwindow *window, unsigned int key);
static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel
static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
static void WindowSizeCallback(GLFWwindow *window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
-static void WindowIconifyCallback(GLFWwindow* window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
+static void WindowIconifyCallback(GLFWwindow *window, int iconified); // GLFW3 WindowIconify Callback, runs when window is minimized/restored
+#endif
+
+#if defined(PLATFORM_DESKTOP)
+static void WindowDropCallback(GLFWwindow *window, int count, const char **paths); // GLFW3 Window Drop Callback, runs when drop files into window
#endif
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
@@ -284,10 +278,6 @@ void InitWindow(int width, int height, const char *title)
InitGamepad(); // Gamepad init
#endif
-#if defined(PLATFORM_WEB)
- InitWebGestures(); // Init touch input events for web
-#endif
-
mousePosition.x = screenWidth/2;
mousePosition.y = screenHeight/2;
@@ -341,7 +331,7 @@ void InitWindow(int width, int height, struct android_app *state)
//state->userData = &engine;
app->onAppCmd = AndroidCommandCallback;
- InitAndroidGestures(app);
+ //InitGesturesSystem(app); // NOTE: Must be called by user
InitAssetManager(app->activity->assetManager);
@@ -412,6 +402,16 @@ bool WindowShouldClose(void)
#endif
}
+// Detect if window has been minimized (or lost focus)
+bool IsWindowMinimized(void)
+{
+#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
+ return windowMinimized;
+#else
+ return false;
+#endif
+}
+
// Fullscreen toggle
void ToggleFullscreen(void)
{
@@ -497,14 +497,8 @@ void EndDrawing(void)
SwapBuffers(); // Copy back buffer to front buffer
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
- ResetGestures();
-#endif
-
PollInputEvents(); // Poll user events
- UpdateMusicStream(); // NOTE: Function checks if music is enabled
-
currentTime = GetTime();
drawTime = currentTime - previousTime;
previousTime = currentTime;
@@ -538,6 +532,7 @@ void Begin3dMode(Camera camera)
double top = 0.1f*tan(45.0f*PI / 360.0f);
double right = top*aspect;
+ // NOTE: zNear and zFar values are important when computing depth buffer values
rlFrustum(-right, right, -top, top, 0.1f, 1000.0f);
rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
@@ -565,7 +560,7 @@ void End3dMode(void)
// Set target FPS for the game
void SetTargetFPS(int fps)
{
- targetTime = 1 / (float)fps;
+ targetTime = 1 / (double)fps;
TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000);
}
@@ -573,16 +568,16 @@ void SetTargetFPS(int fps)
// Returns current FPS
float GetFPS(void)
{
- return (1/(float)frameTime);
+ return (float)(1/frameTime);
}
// Returns time in seconds for one frame
float GetFrameTime(void)
{
- // 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
+ // As we are operate quite a lot with frameTime,
+ // it could be no stable, so we round it before passing it around
// NOTE: There are still problems with high framerates (>500fps)
- double roundedFrameTime = round(frameTime*10000) / 10000;
+ double roundedFrameTime = round(frameTime*10000)/10000;
return (float)roundedFrameTime; // Time in seconds to run a frame
}
@@ -643,6 +638,34 @@ void ShowLogo(void)
showLogo = true;
}
+// Check if a file have been dropped into window
+bool IsFileDropped(void)
+{
+ if (dropFilesCount > 0) return true;
+ else return false;
+}
+
+// Retrieve dropped files into window
+char **GetDroppedFiles(int *count)
+{
+ *count = dropFilesCount;
+ return dropFilesPath;
+}
+
+// Clear dropped files paths buffer
+void ClearDroppedFiles(void)
+{
+ if (dropFilesCount > 0)
+ {
+ for (int i = 0; i < dropFilesCount; i++) free(dropFilesPath[i]);
+
+ free(dropFilesPath);
+
+ dropFilesCount = 0;
+ }
+}
+
+// TODO: Gives the ray trace from mouse position
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
{
Ray ray;
@@ -650,24 +673,28 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
Matrix proj = MatrixIdentity();
Matrix view = MatrixLookAt(camera.position, camera.target, camera.up);
+ // Calculate projection matrix for the camera
float aspect = (GLfloat)GetScreenWidth()/(GLfloat)GetScreenHeight();
- double top = 0.1f*tanf(45.0f*PI / 360.0f);
+ double top = 0.1f*tanf(45.0f*PI/360.0f);
double right = top*aspect;
+ // NOTE: zNear and zFar values are important for depth
proj = MatrixFrustum(-right, right, -top, top, 0.01f, 1000.0f);
MatrixTranspose(&proj);
- float realy = (float)GetScreenHeight() - mousePosition.y;
+ // NOTE: Our screen origin is top-left instead of bottom-left: transform required!
+ float invertedMouseY = (float)GetScreenHeight() - mousePosition.y;
+ // NOTE: Do I really need to get z value from depth buffer?
//float z;
- // glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
+ //glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
//http://www.bfilipek.com/2012/06/select-mouse-opengl.html
- Vector3 nearPoint = { mousePosition.x, realy, 0.0f };
- Vector3 farPoint = { mousePosition.x, realy, 1.0f };
+ Vector3 nearPoint = { mousePosition.x, invertedMouseY, 0.0f };
+ Vector3 farPoint = { mousePosition.x, invertedMouseY, 1.0f };
- //nearPoint = internalCamera.position;
- farPoint = rlglUnproject(farPoint, proj, view);
+ nearPoint = rlglUnproject(nearPoint, proj, view);
+ farPoint = rlglUnproject(farPoint, proj, view); // TODO: it seems it doesn't work...
Vector3 direction = VectorSubtract(farPoint, nearPoint);
VectorNormalize(&direction);
@@ -791,7 +818,11 @@ void SetMousePosition(Vector2 position)
// Returns mouse wheel movement Y
int GetMouseWheelMove(void)
{
+#if defined(PLATFORM_WEB)
+ return previousMouseWheelY/100;
+#else
return previousMouseWheelY;
+#endif
}
// Hide mouse cursor
@@ -933,40 +964,6 @@ bool IsGamepadButtonUp(int gamepad, int button)
}
#endif
-#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
-// Returns touch position X
-int GetTouchX(void)
-{
- return (int)GetRawPosition().x;
-}
-
-// Returns touch position Y
-int GetTouchY(void)
-{
- return (int)GetRawPosition().y;
-}
-
-// Returns touch position XY
-Vector2 GetTouchPosition(void)
-{
- Vector2 position = GetRawPosition();
-
- if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
- {
- // TODO: Seems to work ok but... review!
- position.x = position.x*((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
- position.y = position.y*((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
- }
- else
- {
- position.x = position.x*((float)renderWidth / (float)displayWidth) - renderOffsetX/2;
- position.y = position.y*((float)renderHeight / (float)displayHeight) - renderOffsetY/2;
- }
-
- return position;
-}
-#endif
-
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@@ -1010,7 +1007,8 @@ static void InitDisplay(int width, int height)
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
//glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window
- //glfwWindowHint(GLFW_RED_BITS, 8); // Bit depths of color components for default framebuffer
+ //glfwWindowHint(GLFW_RED_BITS, 8); // Color framebuffer red component bits
+ //glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depth buffer bits (24 by default)
//glfwWindowHint(GLFW_REFRESH_RATE, 0); // Refresh rate for fullscreen window
//glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API); // Default OpenGL API to use. Alternative: GLFW_OPENGL_ES_API
//glfwWindowHint(GLFW_AUX_BUFFERS, 0); // Number of auxiliar buffers
@@ -1074,6 +1072,9 @@ static void InitDisplay(int width, int height)
glfwSetCharCallback(window, CharCallback);
glfwSetScrollCallback(window, ScrollCallback);
glfwSetWindowIconifyCallback(window, WindowIconifyCallback);
+#if defined(PLATFORM_DESKTOP)
+ glfwSetDropCallback(window, WindowDropCallback);
+#endif
glfwMakeContextCurrent(window);
@@ -1106,7 +1107,14 @@ static void InitDisplay(int width, int height)
VC_RECT_T srcRect;
#endif
- // TODO: if (configFlags & FLAG_MSAA_4X_HINT) activate (EGL_SAMPLES, 4)
+ EGLint samples = 0;
+ EGLint sampleBuffer = 0;
+ if (configFlags & FLAG_MSAA_4X_HINT)
+ {
+ samples = 4;
+ sampleBuffer = 1;
+ }
+
const EGLint framebufferAttribs[] =
{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Type of context support -> Required on RPI?
@@ -1115,10 +1123,10 @@ static void InitDisplay(int width, int height)
EGL_GREEN_SIZE, 8, // GREEN color bit depth (alternative: 6)
EGL_BLUE_SIZE, 8, // BLUE color bit depth (alternative: 5)
//EGL_ALPHA_SIZE, 8, // ALPHA bit depth
- EGL_DEPTH_SIZE, 8, // Depth buffer size (Required to use Depth testing!)
+ EGL_DEPTH_SIZE, 16, // Depth buffer size (Required to use Depth testing!)
//EGL_STENCIL_SIZE, 8, // Stencil buffer size
- //EGL_SAMPLE_BUFFERS, 1, // Activate MSAA
- //EGL_SAMPLES, 4, // 4x Antialiasing (Free on MALI GPUs)
+ EGL_SAMPLE_BUFFERS, sampleBuffer, // Activate MSAA
+ EGL_SAMPLES, samples, // 4x Antialiasing if activated (Free on MALI GPUs)
EGL_NONE
};
@@ -1317,20 +1325,28 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height)
// GLFW3 WindowIconify Callback, runs when window is minimized/restored
static void WindowIconifyCallback(GLFWwindow* window, int iconified)
{
- if (iconified)
- {
- // The window was iconified
- PauseMusicStream();
+ if (iconified) windowMinimized = true; // The window was iconified
+ else windowMinimized = false; // The window was restored
+}
+#endif
- windowMinimized = true;
- }
- else
+#if defined(PLATFORM_DESKTOP)
+// GLFW3 Window Drop Callback, runs when drop files into window
+// NOTE: Paths are stored in dinamic memory for further retrieval
+// Everytime new files are dropped, old ones are discarded
+static void WindowDropCallback(GLFWwindow *window, int count, const char **paths)
+{
+ ClearDroppedFiles();
+
+ dropFilesPath = (char **)malloc(sizeof(char *)*count);
+
+ for (int i = 0; i < count; i++)
{
- // The window was restored
- ResumeMusicStream();
-
- windowMinimized = false;
+ dropFilesPath[i] = (char *)malloc(sizeof(char)*256); // Max path length set to 256 char
+ strcpy(dropFilesPath[i], paths[i]);
}
+
+ dropFilesCount = count;
}
#endif
@@ -1379,7 +1395,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
case APP_CMD_GAINED_FOCUS:
{
TraceLog(INFO, "APP_CMD_GAINED_FOCUS");
- ResumeMusicStream();
+ //ResumeMusicStream();
} break;
case APP_CMD_PAUSE:
{
@@ -1389,7 +1405,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
{
//DrawFrame();
TraceLog(INFO, "APP_CMD_LOST_FOCUS");
- PauseMusicStream();
+ //PauseMusicStream();
} break;
case APP_CMD_TERM_WINDOW:
{
@@ -1476,7 +1492,7 @@ static double GetTime(void)
clock_gettime(CLOCK_MONOTONIC, &ts);
uint64_t time = ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec;
- return (double)(time - baseTime) * 1e-9;
+ return (double)(time - baseTime)*1e-9;
#endif
}
diff --git a/src/gestures.c b/src/gestures.c
index ad8ac9f6..27e3830a 100644
--- a/src/gestures.c
+++ b/src/gestures.c
@@ -1,8 +1,6 @@
/**********************************************************************************************
*
-* raylib.gestures
-*
-* Gestures Detection and Usage Functions Definitions
+* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5)
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
@@ -23,8 +21,13 @@
*
**********************************************************************************************/
-#include "raylib.h"
-#include "utils.h"
+//#define GESTURES_STANDALONE // NOTE: To use the gestures module as standalone lib, just uncomment this line
+
+#if defined(GESTURES_STANDALONE)
+ #include "gestures.h"
+#else
+ #include "raylib.h" // Required for typedef(s): Vector2, Gestures
+#endif
#include <stdlib.h> // malloc(), free()
#include <stdio.h> // printf(), fprintf()
@@ -53,9 +56,11 @@
//----------------------------------------------------------------------------------
#define FORCE_TO_SWIPE 20
#define TAP_TIMEOUT 300
-
#define MAX_TOUCH_POINTS 4
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
typedef enum {
TYPE_MOTIONLESS,
TYPE_DRAG,
@@ -75,72 +80,56 @@ typedef struct {
Vector2 position[MAX_TOUCH_POINTS];
} GestureEvent;
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
-
static GestureType gestureType = TYPE_MOTIONLESS;
static double eventTime = 0;
-//static int32_t touchId; // Not used...
+//static int32_t touchId; // Not used...
-// Tap
-// Our initial press position on tap
+// Tap gesture variables
static Vector2 initialTapPosition = { 0, 0 };
-// Double tap
-// If we are double tapping or not
+// Double Tap gesture variables
static bool doubleTapping = false;
-// If we recently made a tap
-static bool untap = false;
+static bool untap = false; // Check if recently done a tap
-// Drag
-// Our initial press position on drag
+// Drag gesture variables
static Vector2 initialDragPosition = { 0, 0 };
-// Position that will compare itself with the mouse one
static Vector2 endDragPosition = { 0, 0 };
-// Position of the last event detection
static Vector2 lastDragPosition = { 0, 0 };
-// The total drag vector
static Vector2 dragVector = { 0, 0 };
-// The distance traveled dragging
-static float magnitude = 0;
-// The angle direction of the drag
-static float angle = 0;
-// A magnitude to calculate how fast we did the drag ( pixels per frame )
-static float intensity = 0;
-// Time that have passed while dragging
-static int draggingTimeCounter = 0;
-
-// Pinch
-// First initial pinch position
+
+static float magnitude = 0; // Distance traveled dragging
+static float angle = 0; // Angle direction of the drag
+static float intensity = 0; // How fast we did the drag (pixels per frame)
+static int draggingTimeCounter = 0; // Time that have passed while dragging
+
+// Pinch gesture variables
static Vector2 firstInitialPinchPosition = { 0, 0 };
-// Second initial pinch position
static Vector2 secondInitialPinchPosition = { 0, 0 };
-// First end pinch position
static Vector2 firstEndPinchPosition = { 0, 0 };
-// Second end pinch position
static Vector2 secondEndPinchPosition = { 0, 0 };
-// Delta Displacement
-static float pinchDelta = 0;
+static float pinchDelta = 0; // Pinch delta displacement
-// Detected gesture
+// Detected gestures
+static int previousGesture = GESTURE_NONE;
static int currentGesture = GESTURE_NONE;
-unsigned int enabledGestures = 0; // TODO: Currently not in use...
+
+static unsigned int enabledGestures = 0; // TODO: Currently not in use...
static Vector2 touchPosition;
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
-extern void ResetGestures(void);
-extern Vector2 GetRawPosition(void);
-
static void ProcessMotionEvent(GestureEvent event);
+
+static void InitPinchGesture(Vector2 posA, Vector2 posB);
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
-static float OnPinch();
-static void SetDualInput(GestureEvent event);
-static float Distance(Vector2 v1, Vector2 v2);
-static float DotProduct(Vector2 v1, Vector2 v2);
+static float VectorDistance(Vector2 v1, Vector2 v2);
+static float VectorDotProduct(Vector2 v1, Vector2 v2);
static double GetCurrentTime();
#if defined(PLATFORM_WEB)
@@ -155,15 +144,43 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
// Module Functions Definition
//----------------------------------------------------------------------------------
-// Returns tap position XY
-extern Vector2 GetRawPosition(void)
+// Returns touch position X
+int GetTouchX(void)
{
- return touchPosition;
+ return (int)touchPosition.x;
+}
+
+// Returns touch position Y
+int GetTouchY(void)
+{
+ return (int)touchPosition.y;
+}
+
+// Returns touch position XY
+// TODO: touch position should be scaled depending on display size and render size
+Vector2 GetTouchPosition(void)
+{
+ Vector2 position = touchPosition;
+/*
+ if ((screenWidth > displayWidth) || (screenHeight > displayHeight))
+ {
+ // TODO: Seems to work ok but... review!
+ position.x = position.x*((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2;
+ position.y = position.y*((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2;
+ }
+ else
+ {
+ position.x = position.x*((float)renderWidth / (float)displayWidth) - renderOffsetX/2;
+ position.y = position.y*((float)renderHeight / (float)displayHeight) - renderOffsetY/2;
+ }
+*/
+ return position;
}
// Check if a gesture have been detected
bool IsGestureDetected(void)
{
+/*
if (currentGesture == GESTURE_DRAG) TraceLog(INFO, "DRAG");
else if (currentGesture == GESTURE_TAP) TraceLog(INFO, "TAP");
else if (currentGesture == GESTURE_DOUBLETAP) TraceLog(INFO, "DOUBLE");
@@ -174,6 +191,7 @@ bool IsGestureDetected(void)
else if (currentGesture == GESTURE_SWIPE_DOWN) TraceLog(INFO, "DOWN");
else if (currentGesture == GESTURE_PINCH_IN) TraceLog(INFO, "PINCH IN");
else if (currentGesture == GESTURE_PINCH_OUT) TraceLog(INFO, "PINCH OUT");
+*/
if (currentGesture != GESTURE_NONE) return true;
else return false;
@@ -228,33 +246,24 @@ float GetGesturePinchAngle(void)
return 0;
}
-extern void ResetGestures(void)
-{
- if (currentGesture == GESTURE_TAP) currentGesture = GESTURE_HOLD;
- else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
-}
-
#if defined(PLATFORM_WEB)
-extern void InitWebGestures(void)
+// Init gestures system (web)
+void InitGesturesSystem(void)
{
- /*
- emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
- emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
- emscripten_set_touchmove_callback("#canvas", data, 0, Emscripten_HandleTouch);
- emscripten_set_touchcancel_callback("#canvas", data, 0, Emscripten_HandleTouch);
- */
-
+ // Init gestures system web (emscripten)
+
+ // NOTE: Some code examples
//emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch);
+ //emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback);
}
-#endif
-
-#if defined(PLATFORM_ANDROID)
-extern void InitAndroidGestures(struct android_app *app)
+#elif defined(PLATFORM_ANDROID)
+// Init gestures system (android)
+void InitGesturesSystem(struct android_app *app)
{
app->onInputEvent = AndroidInputCallback;
@@ -262,6 +271,15 @@ extern void InitAndroidGestures(struct android_app *app)
}
#endif
+// Update gestures detected (must be called every frame)
+void UpdateGestures(void)
+{
+ // NOTE: Gestures are processed through system callbacks on touch events
+
+ if ((previousGesture == GESTURE_TAP) && (currentGesture == GESTURE_TAP)) currentGesture = GESTURE_HOLD;
+ else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
+}
+
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@@ -271,13 +289,15 @@ static void ProcessMotionEvent(GestureEvent event)
dragVector = (Vector2){ 0, 0 };
pinchDelta = 0;
+ previousGesture = currentGesture;
+
switch (gestureType)
{
case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events
{
if (event.action == DOWN)
{
- if (event.pointCount > 1) SetDualInput(event);
+ if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
// Set the press position
@@ -317,7 +337,7 @@ static void ProcessMotionEvent(GestureEvent event)
// Begin dragging
else if (event.action == MOVE)
{
- if (event.pointCount > 1) SetDualInput(event);
+ if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
// Set the drag starting position
@@ -354,7 +374,7 @@ static void ProcessMotionEvent(GestureEvent event)
// Update while we are dragging
else if (event.action == MOVE)
{
- if (event.pointCount > 1) SetDualInput(event);
+ if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
lastDragPosition = endDragPosition;
@@ -395,8 +415,17 @@ static void ProcessMotionEvent(GestureEvent event)
// If there is no more than two inputs
if (event.pointCount == 2)
{
- // Detect pinch delta
- pinchDelta = OnPinch();
+ // Calculate distances
+ float initialDistance = VectorDistance(firstInitialPinchPosition, secondInitialPinchPosition);
+ float endDistance = VectorDistance(firstEndPinchPosition, secondEndPinchPosition);
+
+ // Calculate Vectors
+ Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y };
+ Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y };
+
+ // Detect the pinch gesture
+ if (VectorDotProduct(firstTouchVector, secondTouchVector) < -0.5) pinchDelta = initialDistance - endDistance;
+ else pinchDelta = 0;
// Pinch gesture resolution
if (pinchDelta != 0)
@@ -422,36 +451,30 @@ static void ProcessMotionEvent(GestureEvent event)
//--------------------------------------------------------------------
}
-static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude)
+static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude)
{
float angle;
- // Calculate arcsinus of the movement ( Our sinus is (actualPosition.y - initialPosition.y) / magnitude)
- angle = asin((actualPosition.y - initialPosition.y) / magnitude);
+ // Calculate arcsinus of the movement
+ angle = asin((finalPosition.y - initialPosition.y)/magnitude);
angle *= RAD2DEG;
// Calculate angle depending on the sector
- if (actualPosition.x - initialPosition.x >= 0)
+ if ((finalPosition.x - initialPosition.x) >= 0)
{
// Sector 4
- if (actualPosition.y - initialPosition.y >= 0)
+ if ((finalPosition.y - initialPosition.y) >= 0)
{
angle *= -1;
angle += 360;
}
// Sector 1
- else
- {
- angle *= -1;
- }
+ else angle *= -1;
}
else
{
// Sector 3
- if (actualPosition.y - initialPosition.y >= 0)
- {
- angle += 180;
- }
+ if ((finalPosition.y - initialPosition.y) >= 0) angle += 180;
// Sector 2
else
{
@@ -463,31 +486,15 @@ static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, flo
return angle;
}
-static float OnPinch()
-{
- // Calculate distances
- float initialDistance = Distance(firstInitialPinchPosition, secondInitialPinchPosition);
- float endDistance = Distance(firstEndPinchPosition, secondEndPinchPosition);
-
- // Calculate Vectors
- Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y };
- Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y };
-
- // Detect the pinch gesture
- // Calculate Distances
- if (DotProduct(firstTouchVector, secondTouchVector) < -0.5) return initialDistance - endDistance;
- else return 0;
-}
-
-static void SetDualInput(GestureEvent event)
+static void InitPinchGesture(Vector2 posA, Vector2 posB)
{
initialDragPosition = (Vector2){ 0, 0 };
endDragPosition = (Vector2){ 0, 0 };
lastDragPosition = (Vector2){ 0, 0 };
// Initialize positions
- firstInitialPinchPosition = event.position[0];
- secondInitialPinchPosition = event.position[1];
+ firstInitialPinchPosition = posA;
+ secondInitialPinchPosition = posB;
firstEndPinchPosition = firstInitialPinchPosition;
secondEndPinchPosition = secondInitialPinchPosition;
@@ -500,7 +507,7 @@ static void SetDualInput(GestureEvent event)
gestureType = TYPE_DUAL_INPUT;
}
-static float Distance(Vector2 v1, Vector2 v2)
+static float VectorDistance(Vector2 v1, Vector2 v2)
{
float result;
@@ -512,7 +519,7 @@ static float Distance(Vector2 v1, Vector2 v2)
return result;
}
-static float DotProduct(Vector2 v1, Vector2 v2)
+static float VectorDotProduct(Vector2 v1, Vector2 v2)
{
float result;
@@ -569,7 +576,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
//int32_t key = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
- int32_t code = AKeyEvent_getKeyCode((const AInputEvent *)event);
+ //int32_t code = AKeyEvent_getKeyCode((const AInputEvent *)event);
// If we are in active mode, we eat the back button and move into pause mode.
// If we are already in pause mode, we allow the back button to be handled by the OS, which means we'll be shut down.
@@ -652,10 +659,4 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent
return 1;
}
-#endif
-
-
-
-
-
-
+#endif \ No newline at end of file
diff --git a/src/gestures.h b/src/gestures.h
new file mode 100644
index 00000000..896f3028
--- /dev/null
+++ b/src/gestures.h
@@ -0,0 +1,107 @@
+/**********************************************************************************************
+*
+* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5)
+*
+* Copyright (c) 2015 Marc Palau and Ramon Santamaria
+*
+* 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 GESTURES_H
+#define GESTURES_H
+
+#ifndef PI
+ #define PI 3.14159265358979323846
+#endif
+
+#define DEG2RAD (PI / 180.0f)
+#define RAD2DEG (180.0f / PI)
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+// NOTE: Below types are required for GESTURES_STANDALONE usage
+//----------------------------------------------------------------------------------
+#ifndef __cplusplus
+ // Boolean type
+ typedef enum { false, true } bool;
+#endif
+
+// Vector2 type
+typedef struct Vector2 {
+ float x;
+ float y;
+} Vector2;
+
+// Gestures type
+// NOTE: It could be used as flags to enable only some gestures
+typedef enum {
+ GESTURE_NONE = 1,
+ GESTURE_TAP = 2,
+ GESTURE_DOUBLETAP = 4,
+ GESTURE_HOLD = 8,
+ GESTURE_DRAG = 16,
+ GESTURE_SWIPE_RIGHT = 32,
+ GESTURE_SWIPE_LEFT = 64,
+ GESTURE_SWIPE_UP = 128,
+ GESTURE_SWIPE_DOWN = 256,
+ GESTURE_PINCH_IN = 512,
+ GESTURE_PINCH_OUT = 1024
+} Gestures;
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+int GetTouchX(void); // Returns touch position X (relative to screen size)
+int GetTouchY(void); // Returns touch position Y (relative to screen size)
+Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size)
+
+#if defined(PLATFORM_WEB)
+void InitGesturesSystem(void); // Init gestures system (web)
+#elif defined(PLATFORM_ANDROID)
+void InitGesturesSystem(struct android_app *app); // Init gestures system (android)
+#endif
+void UpdateGestures(void); // Update gestures detected (must be called every frame)
+bool IsGestureDetected(void); // Check if a gesture have been detected
+int GetGestureType(void); // Get latest detected gesture
+void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags
+
+float GetGestureDragIntensity(void); // Get gesture drag intensity
+float GetGestureDragAngle(void); // Get gesture drag angle
+Vector2 GetGestureDragVector(void); // Get gesture drag vector
+int GetGestureHoldDuration(void); // Get gesture hold time in frames
+float GetGesturePinchDelta(void); // Get gesture pinch delta
+float GetGesturePinchAngle(void); // Get gesture pinch angle
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GESTURES_H
diff --git a/src/makefile b/src/makefile
index 11bbea9d..67123a9a 100644
--- a/src/makefile
+++ b/src/makefile
@@ -93,7 +93,7 @@ else
endif
# define all object files required
-OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o
+OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is raylib
@@ -139,6 +139,10 @@ models.o: models.c
# compile audio module
audio.o: audio.c
$(CC) -c audio.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
+
+# compile stb_vorbis library
+stb_vorbis.o: stb_vorbis.c
+ $(CC) -c stb_vorbis.c -O1 $(INCLUDES) -D$(PLATFORM)
# compile utils module
utils.o: utils.c
diff --git a/src/models.c b/src/models.c
index c45e18c8..054febcf 100644
--- a/src/models.c
+++ b/src/models.c
@@ -4,7 +4,7 @@
*
* Basic functions to draw 3d shapes and load/draw 3d models (.OBJ)
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -558,22 +558,33 @@ void DrawGizmo(Vector3 position)
Model LoadModel(const char *fileName)
{
VertexData vData;
+
+ Model model;
+
+ // TODO: Initialize default data for model in case loading fails, maybe a cube?
if (strcmp(GetExtension(fileName),"obj") == 0) vData = LoadOBJ(fileName);
else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName);
// NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
-
- // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel()
- Model model = rlglLoadModel(vData); // Upload vertex data to GPU
-
- // Now that vertex data is uploaded to GPU, we can free arrays
- // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2
- if (rlGetVersion() != OPENGL_11)
+
+ if (vData.vertexCount == 0)
{
- free(vData.vertices);
- free(vData.texcoords);
- free(vData.normals);
+ TraceLog(WARNING, "Model could not be loaded");
+ }
+ else
+ {
+ // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel()
+ model = rlglLoadModel(vData); // Upload vertex data to GPU
+
+ // Now that vertex data is uploaded to GPU, we can free arrays
+ // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2
+ if (rlGetVersion() != OPENGL_11)
+ {
+ free(vData.vertices);
+ free(vData.texcoords);
+ free(vData.normals);
+ }
}
return model;
@@ -1105,6 +1116,8 @@ void UnloadModel(Model model)
rlDeleteBuffers(model.mesh.vboId[2]);
rlDeleteVertexArrays(model.mesh.vaoId);
+
+ TraceLog(INFO, "Unloaded model data");
}
// Link a texture to a model
diff --git a/src/raylib.h b/src/raylib.h
index 228d3e58..f5220e2e 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -36,7 +36,7 @@
* 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)
+* Copyright (c) 2013 Ramon Santamaria (@raysan5)
*
* 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.
@@ -176,7 +176,6 @@
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
-
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;
@@ -354,6 +353,9 @@ typedef enum {
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
} TextureFormat;
+// Color blending modes (pre-defined)
+typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
+
// Gestures type
// NOTE: It could be used as flags to enable only some gestures
typedef enum {
@@ -370,6 +372,9 @@ typedef enum {
GESTURE_PINCH_OUT = 1024
} Gestures;
+// Camera system modes
+typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
+
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
@@ -383,13 +388,14 @@ extern "C" { // Prevents name mangling of functions
// Window and Graphics Device Functions (Module: core)
//------------------------------------------------------------------------------------
#if defined(PLATFORM_ANDROID)
-void InitWindow(int width, int height, struct android_app *state); // Init Android activity
+void InitWindow(int width, int height, struct android_app *state); // Init Android Activity and OpenGL Graphics
#elif defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
void InitWindow(int width, int height, const char *title); // Initialize Window and OpenGL Graphics
#endif
void CloseWindow(void); // Close Window and Terminate Context
bool WindowShouldClose(void); // Detect if KEY_ESCAPE pressed or Close icon pressed
+bool IsWindowMinimized(void); // Detect if window has been minimized (or lost focus)
void ToggleFullscreen(void); // Fullscreen toggle (only PLATFORM_DESKTOP)
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI)
void SetCustomCursor(const char *cursorImage); // Set a custom cursor icon/image
@@ -418,6 +424,10 @@ Color Fade(Color color, float alpha); // Color fade-in or
void SetConfigFlags(char flags); // Enable some window configurations
void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
+bool IsFileDropped(void); // Check if a file have been dropped into window
+char **GetDroppedFiles(int *count); // Retrieve dropped files into window
+void ClearDroppedFiles(void); // Clear dropped files paths buffer
+
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Gives the ray trace from mouse position
//------------------------------------------------------------------------------------
@@ -441,6 +451,8 @@ void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D textu
void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment
void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
+void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
+
//------------------------------------------------------------------------------------
// Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------
@@ -461,9 +473,9 @@ Vector2 GetMousePosition(void); // Returns mouse positio
void SetMousePosition(Vector2 position); // Set mouse position XY
int GetMouseWheelMove(void); // Returns mouse wheel movement Y
-void ShowCursor(void); // Shows cursor
-void HideCursor(void); // Hides cursor
-bool IsCursorHidden(void); // Returns true if cursor is not visible
+void ShowCursor(void); // Shows cursor
+void HideCursor(void); // Hides cursor
+bool IsCursorHidden(void); // Returns true if cursor is not visible
#endif
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
@@ -476,22 +488,47 @@ bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad b
#endif
#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB)
-int GetTouchX(void); // Returns touch position X
-int GetTouchY(void); // Returns touch position Y
-Vector2 GetTouchPosition(void); // Returns touch position XY
-
-// Gestures System (module: gestures)
-bool IsGestureDetected(void);
-int GetGestureType(void);
-void SetGesturesEnabled(unsigned int gestureFlags);
-
-float GetGestureDragIntensity(void);
-float GetGestureDragAngle(void);
-Vector2 GetGestureDragVector(void);
-int GetGestureHoldDuration(void); // Hold time in frames
-float GetGesturePinchDelta(void);
-float GetGesturePinchAngle(void);
+//------------------------------------------------------------------------------------
+// Gestures and Touch Handling Functions (Module: gestures)
+//------------------------------------------------------------------------------------
+int GetTouchX(void); // Returns touch position X (relative to screen size)
+int GetTouchY(void); // Returns touch position Y (relative to screen size)
+Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size)
+
+#if defined(PLATFORM_WEB)
+void InitGesturesSystem(void); // Init gestures system (web)
+#elif defined(PLATFORM_ANDROID)
+void InitGesturesSystem(struct android_app *app); // Init gestures system (android)
#endif
+void UpdateGestures(void); // Update gestures detected (must be called every frame)
+bool IsGestureDetected(void); // Check if a gesture have been detected
+int GetGestureType(void); // Get latest detected gesture
+void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags
+
+float GetGestureDragIntensity(void); // Get gesture drag intensity
+float GetGestureDragAngle(void); // Get gesture drag angle
+Vector2 GetGestureDragVector(void); // Get gesture drag vector
+int GetGestureHoldDuration(void); // Get gesture hold time in frames
+float GetGesturePinchDelta(void); // Get gesture pinch delta
+float GetGesturePinchAngle(void); // Get gesture pinch angle
+#endif
+
+//------------------------------------------------------------------------------------
+// Camera System Functions (Module: camera)
+//------------------------------------------------------------------------------------
+void SetCameraMode(int mode); // Set camera mode (multiple camera modes available)
+Camera UpdateCamera(Vector3 *playerPosition); // Update camera and player position (1st person and 3rd person cameras)
+
+void SetCameraMoveControls(int frontKey, int backKey,
+ int leftKey, int rightKey,
+ int upKey, int downKey); // Set camera move controls (1st person and 3rd person cameras)
+
+void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera)
+void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera)
+void SetCameraSmoothZoomControl(int szKey); // Set camera smooth zoom key to combine with mouse (free camera)
+
+void SetCameraMouseSensitivity(float sensitivity); // Set camera mouse sensitivity (1st person and 3rd person cameras)
+void SetCameraTarget(Vector3 target); // Set internal camera target
//------------------------------------------------------------------------------------
// Basic Shapes Drawing Functions (Module: shapes)
@@ -625,6 +662,7 @@ void SetSoundVolume(Sound sound, float volume); // Set volume fo
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
void PlayMusicStream(char *fileName); // Start music playing (open stream)
+void UpdateMusicStream(void); // Updates buffers for music streaming
void StopMusicStream(void); // Stop music playing (close stream)
void PauseMusicStream(void); // Pause music playing
void ResumeMusicStream(void); // Resume playing paused music
diff --git a/src/rlgl.c b/src/rlgl.c
index 12a25736..163fa35a 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -7,7 +7,7 @@
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Same behaviour as OpenGL 3.3+
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -33,20 +33,21 @@
#include <string.h> // Declares strcmp(), strlen(), strtok()
#if defined(GRAPHICS_API_OPENGL_11)
- #ifdef __APPLE__ // OpenGL include for OSX
+ #ifdef __APPLE__ // OpenGL include for OSX
#include <OpenGL/gl.h>
#else
- #include <GL/gl.h> // Basic OpenGL include
+ #include <GL/gl.h> // Basic OpenGL include
#endif
#endif
#if defined(GRAPHICS_API_OPENGL_33)
#define GLEW_STATIC
- #ifdef __APPLE__ // OpenGL include for OSX
+ #ifdef __APPLE__ // OpenGL include for OSX
#include <OpenGL/gl3.h>
#else
- #include <GL/glew.h> // Extensions loading lib
- //#include "glad.h" // TODO: Other extensions loading lib? --> REVIEW
+ #include <GL/glew.h> // GLEW extensions loading lib
+ //#include "glad.h" // glad extensions loading lib: ERRORS: windows.h
+ //#include "gl_core_3_3.h" // glLoadGen extension loading lib: ERRORS: windows.h
#endif
#endif
@@ -56,6 +57,10 @@
#include <GLES2/gl2ext.h>
#endif
+#if defined(RLGL_STANDALONE)
+ #include <stdarg.h> // Used for functions with variable number of parameters (TraceLog())
+#endif
+
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -177,6 +182,10 @@ typedef struct {
unsigned char a;
} pixel;
+#if defined(RLGL_STANDALONE)
+typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
+#endif
+
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
@@ -218,7 +227,6 @@ static bool useTempBuffer = false;
// Flags for supported extensions
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
-static bool npotSupported = false; // NPOT textures full support
// Compressed textures support flags
//static bool texCompDXTSupported = false; // DDS texture compression support
@@ -236,7 +244,8 @@ static bool enabledPostpro = false;
#endif
// Compressed textures support flags
-static bool texCompDXTSupported = false; // DDS texture compression support
+static bool texCompDXTSupported = false; // DDS texture compression support
+static bool npotSupported = false; // NPOT textures full support
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: VAO functionality is exposed through extensions (OES)
@@ -246,6 +255,11 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays;
//static PFNGLISVERTEXARRAYOESPROC glIsVertexArray; // NOTE: Fails in WebGL, omitted
#endif
+// Save screen size data (render size), required for postpro quad
+static int screenWidth, screenHeight;
+
+static int blendMode = 0;
+
// White texture useful for plain color polys (required by shader)
// NOTE: It's required in shapes and models modules!
unsigned int whiteTexture;
@@ -273,6 +287,10 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight);
static char** StringSplit(char *baseString, const char delimiter, int *numExt);
#endif
+#if defined(RLGL_STANDALONE)
+static void TraceLog(int msgType, const char *text, ...);
+#endif
+
//----------------------------------------------------------------------------------
// Module Functions Definition - Matrix operations
//----------------------------------------------------------------------------------
@@ -838,35 +856,69 @@ void rlglInit(void)
//for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]);
// NOTE: We don't need that much data on screen... right now...
+
+#if defined(GRAPHICS_API_OPENGL_11)
+ TraceLog(INFO, "OpenGL 1.1 profile initialized");
+#endif
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Get supported extensions list
GLint numExt;
#if defined(GRAPHICS_API_OPENGL_33)
+
+#define GLEW_EXTENSIONS_LOADER
+#if defined(GLEW_EXTENSIONS_LOADER)
// Initialize extensions using GLEW
glewExperimental = 1; // Needed for core profile
-
GLenum error = glewInit();
if (error != GLEW_OK) TraceLog(ERROR, "Failed to initialize GLEW - Error Code: %s\n", glewGetErrorString(error));
-
+
if (glewIsSupported("GL_VERSION_3_3"))
{
- TraceLog(INFO, "OpenGL 3.3 Core profile");
+ TraceLog(INFO, "OpenGL 3.3 Core profile supported");
vaoSupported = true;
npotSupported = true;
}
+ else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+
+ // With GLEW, we can check if an extension has been loaded in two ways:
+ //if (GLEW_ARB_vertex_array_object) { }
+ //if (glewIsSupported("GL_ARB_vertex_array_object")) { }
// NOTE: GLEW is a big library that loads ALL extensions, we can use some alternative to load only required ones
// Alternatives: glLoadGen, glad, libepoxy
- //if (!gladLoadGL()) TraceLog("ERROR: Failed to initialize glad\n");
+
+#elif defined(GLAD_EXTENSIONS_LOADER)
+ // NOTE: glad is generated and contains only required OpenGL version and core extensions
+ if (!gladLoadGL()) TraceLog(ERROR, "Failed to initialize glad\n");
+ //if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) TraceLog(ERROR, "Failed to initialize glad\n");
- // With GLEW we can check if an extension has been loaded in two ways:
- //if (GLEW_ARB_vertex_array_object) { }
- //if (glewIsSupported("GL_ARB_vertex_array_object")) { }
+ if (GLAD_GL_VERSION_3_3)
+ {
+ TraceLog(INFO, "OpenGL 3.3 Core profile supported");
+
+ vaoSupported = true;
+ npotSupported = true;
+ }
+ else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+
+ // With GLAD, we can check if an extension is supported using the GLAD_GL_xxx booleans
+ //if (GLAD_GL_ARB_vertex_array_object) // Use GL_ARB_vertex_array_object
+#elif defined(GLLOADGEN_EXTENSIONS_LOADER)
+ // NOTE: glLoadGen already generates a header with required OpenGL version and core extensions
+ if (ogl_LoadFunctions() != ogl_LOAD_FAILED)
+ {
+ TraceLog(INFO, "OpenGL 3.3 Core profile supported");
+
+ vaoSupported = true;
+ npotSupported = true;
+ }
+ else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported");
+#endif
// NOTE: We don't need to check again supported extensions but we do (in case GLEW is replaced sometime)
// We get a list of available extensions and we check for some of them (compressed textures)
@@ -995,6 +1047,7 @@ void rlglInit(void)
}
// Init postpro system
+// NOTE: Uses global variables screenWidth and screenHeight
void rlglInitPostpro(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -1003,57 +1056,82 @@ void rlglInitPostpro(void)
glBindTexture(GL_TEXTURE_2D, fboColorTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, GetScreenWidth(), GetScreenHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, screenWidth, screenHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
- // Create the texture that will serve as the depth attachment for the framebuffer.
+ // Create the renderbuffer that will serve as the depth attachment for the framebuffer.
+ glGenRenderbuffers(1, &fboDepthTexture);
+ glBindRenderbuffer(GL_RENDERBUFFER, fboDepthTexture);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, screenWidth, screenHeight);
+
+ // NOTE: We can also use a texture for depth buffer (GL_ARB_depth_texture/GL_OES_depth_texture extensions)
+ // A renderbuffer is simpler than a texture and could offer better performance on embedded devices
+/*
glGenTextures(1, &fboDepthTexture);
glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GetScreenWidth(), GetScreenHeight(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);
+*/
// Create the framebuffer object
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- // Attach color texture and depth texture to FBO
+ // Attach color texture and depth renderbuffer to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboColorTexture, 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, fboDepthTexture, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboDepthTexture);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) TraceLog(WARNING, "Framebuffer object could not be created...");
- else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ TraceLog(WARNING, "Framebuffer object could not be created...");
+
+ switch(status)
+ {
+ case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break;
+#endif
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break;
+ default: break;
+ }
+ }
+ else
+ {
+ TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
- // Create a simple quad model to render fbo texture
- VertexData quadData;
-
- quadData.vertexCount = 6;
-
- float w = GetScreenWidth();
- float h = GetScreenHeight();
-
- float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 };
- float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
- float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
- unsigned char quadColors[6*4] = { 255 };
-
- quadData.vertices = quadPositions;
- quadData.texcoords = quadTexcoords;
- quadData.normals = quadNormals;
- quadData.colors = quadColors;
-
- postproQuad = rlglLoadModel(quadData);
-
- // NOTE: fboColorTexture id must be assigned to postproQuad model shader
+ // Create a simple quad model to render fbo texture
+ VertexData quadData;
+
+ quadData.vertexCount = 6;
+
+ float w = screenWidth;
+ float h = screenHeight;
+
+ float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 };
+ float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 };
+ float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 };
+ unsigned char quadColors[6*4] = { 255 };
+
+ quadData.vertices = quadPositions;
+ quadData.texcoords = quadTexcoords;
+ quadData.normals = quadNormals;
+ quadData.colors = quadColors;
+
+ postproQuad = rlglLoadModel(quadData);
+
+ // NOTE: fboColorTexture id must be assigned to postproQuad model shader
+ }
#endif
}
@@ -1116,7 +1194,20 @@ void rlglClose(void)
{
glDeleteFramebuffers(1, &fbo);
- UnloadModel(postproQuad);
+ // Unload postpro quad model data
+#if defined(GRAPHICS_API_OPENGL_11)
+ free(postproQuad.mesh.vertices);
+ free(postproQuad.mesh.texcoords);
+ free(postproQuad.mesh.normals);
+#endif
+
+ rlDeleteBuffers(postproQuad.mesh.vboId[0]);
+ rlDeleteBuffers(postproQuad.mesh.vboId[1]);
+ rlDeleteBuffers(postproQuad.mesh.vboId[2]);
+
+ rlDeleteVertexArrays(postproQuad.mesh.vaoId);
+
+ TraceLog(INFO, "Unloaded postpro quad data");
}
free(draws);
@@ -1287,7 +1378,7 @@ void rlglDrawPostpro(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, WHITE, false);
+ rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false);
#endif
}
@@ -1352,15 +1443,16 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
// NOTE: Drawing in OpenGL 3.3+, transform is passed to shader
glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(modelviewworld));
-
+
// Apply color tinting to model
// NOTE: Just update one uniform on fragment shader
float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 };
glUniform4fv(model.shader.tintColorLoc, 1, vColor);
-
+
// Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, model.shader.texDiffuseId);
+ glUniform1i(model.shader.mapDiffuseLoc, 0);
if (model.shader.texNormalId != 0)
{
@@ -1390,14 +1482,21 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
glEnableVertexAttribArray(model.shader.texcoordLoc);
// Add normals support
- glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
- glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
- glEnableVertexAttribArray(model.shader.normalLoc);
+ if (model.shader.normalLoc != -1)
+ {
+ glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]);
+ glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.normalLoc);
+ }
}
// Draw call!
glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount);
+ //glDisableVertexAttribArray(model.shader.vertexLoc);
+ //glDisableVertexAttribArray(model.shader.texcoordLoc);
+ //if (model.shader.normalLoc != -1) glDisableVertexAttribArray(model.shader.normalLoc);
+
if (model.shader.texNormalId != 0)
{
glActiveTexture(GL_TEXTURE1);
@@ -1426,17 +1525,23 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
}
// Initialize Graphics Device (OpenGL stuff)
+// NOTE: Stores global variables screenWidth and screenHeight
void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
{
+ // Save screen size data (global vars), required on postpro quad
+ // NOTE: Size represents render size, it could differ from screen size!
+ screenWidth = width;
+ screenHeight = height;
+
// NOTE: Required! viewport must be recalculated if screen resized!
glViewport(offsetX/2, offsetY/2, width - offsetX, height - offsetY); // Set viewport width and height
// NOTE: Don't confuse glViewport with the transformation matrix
// NOTE: glViewport just defines the area of the context that you will actually draw to.
- 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, 1.0f); // Set background color (black)
//glClearDepth(1.0f); // Clear depth buffer (default)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D
glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D)
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
@@ -1468,170 +1573,61 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
#endif
- TraceLog(INFO, "OpenGL Graphics initialized successfully");
+ TraceLog(INFO, "OpenGL graphic device initialized successfully");
}
// Get world coordinates from screen coordinates
// TODO: It doesn't work! It drives me crazy!
+// NOTE: Using global variables: screenWidth, screenHeight
Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
{
+ Vector3 result = { 0, 0, 0 }; // Object coordinates
+
//GLint viewport[4];
- //glGetIntegerv(GL_VIEWPORT, viewport);
+ //glGetIntegerv(GL_VIEWPORT, viewport); // Not available on OpenGL ES 2.0
// Viewport data
-/*
- int x = 0;
- int y = 0;
- int width = GetScreenWidth();
- int height = GetScreenHeight();
- float minDepth = 0.0f;
- float maxDepth = 1.0f;
-*/
-/*
- Matrix modelviewprojection = MatrixMultiply(modelview, projection);
+ int x = 0; // viewport[0]
+ int y = 0; // viewport[1]
+ int width = screenWidth; // viewport[2]
+ int height = screenHeight; // viewport[3]
+
+ Matrix modelviewprojection = MatrixMultiply(view, proj);
MatrixInvert(&modelviewprojection);
-
- Vector3 vector;
-
- vector.x = (((source.x - x) / ((float)width)) * 2.0f) - 1.0f;
- vector.y = -((((source.y - y) / ((float)height)) * 2.0f) - 1.0f);
- vector.z = (source.z - minDepth) / (maxDepth - minDepth);
-
- //float a = (((vector.x * matrix.M14) + (vector.y * matrix.M24)) + (vector.z * matrix.M34)) + matrix.M44;
- //float a = (((vector.x * modelviewprojection.m3) + (vector.y * modelviewprojection.m7)) + (vector.z * modelviewprojection.m11)) + modelviewprojection.m15;
- VectorTransform(&vector, modelviewprojection);
-
- //if (!MathUtil.IsOne(a)) vector = (vector / a);
- //VectorScale(&vector, 1/a);
-
- return vector;
-*/
/*
- Vector3 worldPoint;
-
- // Transformation matrices
- Matrix modelviewprojection = MatrixIdentity();
- Quaternion quat;
-
- // Calculation for inverting a matrix, compute projection x modelview
- modelviewprojection = MatrixMultiply(proj, view);
- MatrixInvert(&modelviewprojection);
+ // NOTE: Compute unproject using Vector3
// Transformation of normalized coordinates between -1 and 1
- quat.x = ((source.x - (float)x)/(float)width*2.0) - 1.0f;
- quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f;
- quat.z = 2.0*source.z - 1.0;
- quat.w = 1.0;
-
- // Objects coordinates
- QuaternionTransform(&quat, modelviewprojection);
-
- //if (quat.w == 0.0) return 0;
-
- worldPoint.x = quat.x/quat.w;
- worldPoint.y = quat.y/quat.w;
- worldPoint.z = quat.z/quat.w;
+ result.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
+ result.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
+ result.z = source.z*2.0f - 1.0f;
- return worldPoint;
- */
-/*
- Quaternion quat;
- Vector3 vec;
-
- quat.x = 2.0f * GetMousePosition().x / (float)width - 1;
- quat.y = -(2.0f * GetMousePosition().y / (float)height - 1);
- quat.z = 0;
- quat.w = 1;
-
- Matrix invView;
- MatrixInvert(&view);
- Matrix invProj;
- MatrixInvert(&proj);
-
- quat.x = invProj.m0 * quat.x + invProj.m4 * quat.y + invProj.m8 * quat.z + invProj.m12 * quat.w;
- quat.y = invProj.m1 * quat.x + invProj.m5 * quat.y + invProj.m9 * quat.z + invProj.m13 * quat.w;
- quat.z = invProj.m2 * quat.x + invProj.m6 * quat.y + invProj.m10 * quat.z + invProj.m14 * quat.w;
- quat.w = invProj.m3 * quat.x + invProj.m7 * quat.y + invProj.m11 * quat.z + invProj.m15 * quat.w;
-
- quat.x = invView.m0 * quat.x + invView.m4 * quat.y + invView.m8 * quat.z + invView.m12 * quat.w;
- quat.y = invView.m1 * quat.x + invView.m5 * quat.y + invView.m9 * quat.z + invView.m13 * quat.w;
- quat.z = invView.m2 * quat.x + invView.m6 * quat.y + invView.m10 * quat.z + invView.m14 * quat.w;
- quat.w = invView.m3 * quat.x + invView.m7 * quat.y + invView.m11 * quat.z + invView.m15 * quat.w;
-
- vec.x /= quat.w;
- vec.y /= quat.w;
- vec.z /= quat.w;
-
- return vec;
- */
-/*
- Vector3 worldPoint;
-
- // Transformation matrices
- Matrix modelviewprojection;
+ // Object coordinates (multiply vector by matrix)
+ VectorTransform(&result, modelviewprojection);
+*/
+
+ // NOTE: Compute unproject using Quaternion (Vector4)
Quaternion quat;
-
- // Calculation for inverting a matrix, compute projection x modelview
- modelviewprojection = MatrixMultiply(view, proj);
-
- // Now compute the inverse of matrix A
- MatrixInvert(&modelviewprojection);
-
- // Transformation of normalized coordinates between -1 and 1
- quat.x = ((source.x - (float)x)/(float)width*2.0) - 1.0f;
- quat.y = ((source.y - (float)y)/(float)height*2.0) - 1.0f;
- quat.z = 2.0*source.z - 1.0;
+
+ quat.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f;
+ quat.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f;
+ quat.z = source.z*2.0f - 1.0f;
quat.w = 1.0;
+
+ QuaternionTransform(&quat, modelviewprojection);
- // Traspose quaternion and multiply
- Quaternion result;
- result.x = modelviewprojection.m0 * quad.x + modelviewprojection.m4 * quad.y + modelviewprojection.m8 * quad.z + modelviewprojection.m12 * quad.w;
- result.y = modelviewprojection.m1 * quad.x + modelviewprojection.m5 * quad.y + modelviewprojection.m9 * quad.z + modelviewprojection.m13 * quad.w;
- result.z = modelviewprojection.m2 * quad.x + modelviewprojection.m6 * quad.y + modelviewprojection.m10 * quad.z + modelviewprojection.m14 * quad.w;
- result.w = modelviewprojection.m3 * quad.x + modelviewprojection.m7 * quad.y + modelviewprojection.m11 * quad.z + modelviewprojection.m15 * quad.w;
-
- // Invert
- result.w = 1.0f / result.w;
-
- //if (quat.w == 0.0) return 0;
-
- worldPoint.x = quat.x * quat.w;
- worldPoint.y = quat.y * quat.w;
- worldPoint.z = quat.z * quat.w;
-
- return worldPoint;
- */
-/*
- // Needed Vectors
- Vector3 normalDeviceCoordinates;
- Quaternion rayClip;
- Quaternion rayEye;
- Vector3 rayWorld;
-
- // Getting normal device coordinates
- float x = (2.0 * mousePosition.x) / GetScreenWidth() - 1.0;
- float y = 1.0 - (2.0 * mousePosition.y) / GetScreenHeight();
- float z = 1.0;
- normalDeviceCoordinates = (Vector3){ x, y, z };
-
- // Getting clip vector
- rayClip = (Quaternion){ normalDeviceCoordinates.x, normalDeviceCoordinates.y, -1, 1 };
-
- Matrix invProjection = projection;
- MatrixInvert(&invProjection);
-
- rayEye = MatrixQuaternionMultiply(invProjection, rayClip);
- rayEye = (Quaternion){ rayEye.x, rayEye.y, -1, 0 };
-
- Matrix invModelview = modelview;
- MatrixInvert(&invModelview);
+ if (quat.w != 0.0)
+ {
+ quat.x /= quat.w;
+ quat.y /= quat.w;
+ quat.z /= quat.w;
+ }
- rayWorld = MatrixVector3Multiply(invModelview, (Vector3){rayEye.x, rayEye.y, rayEye.z} );
- VectorNormalize(&rayWorld);
+ result.x = quat.x;
+ result.y = quat.y;
+ result.z = quat.z;
- return rayWorld;
-*/
- return (Vector3){ 0, 0, 0 };
+ return result;
}
// Convert image data to OpenGL texture (returns OpenGL valid Id)
@@ -1780,9 +1776,9 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
#endif
// Magnification and minification filters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
- 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); // Alternative: GL_LINEAR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Alternative: GL_LINEAR
+
#if defined(GRAPHICS_API_OPENGL_33)
if (mipmapCount > 1)
{
@@ -1883,9 +1879,10 @@ Model rlglLoadModel(VertexData mesh)
model.shader.id = 0; // No shader used
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- model.texture.id = whiteTexture; // Default whiteTexture
- model.texture.width = 1; // Default whiteTexture width
- model.texture.height = 1; // Default whiteTexture height
+ model.texture.id = whiteTexture; // Default whiteTexture
+ model.texture.width = 1; // Default whiteTexture width
+ model.texture.height = 1; // Default whiteTexture height
+ model.shader = simpleShader; // Default model shader
GLuint vaoModel = 0; // Vertex Array Objects (VAO)
GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO)
@@ -1903,22 +1900,20 @@ Model rlglLoadModel(VertexData mesh)
// Enable vertex attributes: position
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW);
- glEnableVertexAttribArray(simpleShader.vertexLoc);
- glVertexAttribPointer(simpleShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.vertexLoc);
// Enable vertex attributes: texcoords
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW);
- glEnableVertexAttribArray(simpleShader.texcoordLoc);
- glVertexAttribPointer(simpleShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.texcoordLoc);
// Enable vertex attributes: normals
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW);
- glEnableVertexAttribArray(simpleShader.normalLoc);
- glVertexAttribPointer(simpleShader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
-
- model.shader = simpleShader; // By default, simple shader will be used
+ glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0);
+ glEnableVertexAttribArray(model.shader.normalLoc);
model.mesh.vboId[0] = vertexBuffer[0]; // Vertex position VBO
model.mesh.vboId[1] = vertexBuffer[1]; // Texcoords VBO
@@ -1975,6 +1970,8 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
int width, height;
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
@@ -1995,15 +1992,13 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; // 32 bpp
default: TraceLog(WARNING, "Texture format not suported"); break;
}
-
- glBindTexture(GL_TEXTURE_2D, textureId);
// NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
// Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting.
// GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.)
// GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
glPixelStorei(GL_PACK_ALIGNMENT, 1);
-
+
glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
glBindTexture(GL_TEXTURE_2D, 0);
@@ -2027,39 +2022,54 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
// Shaders loading from external text file
char *vShaderStr = TextFileRead(vsFileName);
char *fShaderStr = TextFileRead(fsFileName);
-
- shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
-
- if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
- else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shader.id);
-
- // Shader strings must be freed
- free(vShaderStr);
- free(fShaderStr);
- // Set shader textures ids (all 0 by default)
- shader.texDiffuseId = 0;
- shader.texNormalId = 0;
- shader.texSpecularId = 0;
-
- // Get handles to GLSL input attibute locations
- //-------------------------------------------------------------------
- shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition");
- shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord");
- shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal");
- // NOTE: custom shader does not use colorLoc
- shader.colorLoc = -1;
-
- // Get handles to GLSL uniform locations (vertex shader)
- shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix");
- shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
+ if ((vShaderStr != NULL) && (fShaderStr != NULL))
+ {
+ shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
- // Get handles to GLSL uniform locations (fragment shader)
- shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
- shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
- shader.mapNormalLoc = -1; // It can be set later
- shader.mapSpecularLoc = -1; // It can be set later
- //--------------------------------------------------------------------
+ if (shader.id != 0)
+ {
+ TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
+
+ // Set shader textures ids (all 0 by default)
+ shader.texDiffuseId = 0;
+ shader.texNormalId = 0;
+ shader.texSpecularId = 0;
+
+ // Get handles to GLSL input attibute locations
+ //-------------------------------------------------------------------
+ shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition");
+ shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord");
+ shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal");
+ // NOTE: custom shader does not use colorLoc
+ shader.colorLoc = -1;
+
+ // Get handles to GLSL uniform locations (vertex shader)
+ shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix");
+ shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
+
+ // Get handles to GLSL uniform locations (fragment shader)
+ shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
+ shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
+ shader.mapNormalLoc = -1; // It can be set later
+ shader.mapSpecularLoc = -1; // It can be set later
+ //--------------------------------------------------------------------
+ }
+ else
+ {
+ TraceLog(WARNING, "Custom shader could not be loaded");
+ shader = simpleShader;
+ }
+
+ // Shader strings must be freed
+ free(vShaderStr);
+ free(fShaderStr);
+ }
+ else
+ {
+ TraceLog(WARNING, "Custom shader could not be loaded");
+ shader = simpleShader;
+ }
#endif
return shader;
@@ -2169,6 +2179,8 @@ unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr)
void UnloadShader(Shader shader)
{
rlDeleteShader(shader.id);
+
+ TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id);
}
// Set custom shader to be used on batch draw
@@ -2205,6 +2217,7 @@ void SetCustomShader(Shader shader)
}
// Set postprocessing shader
+// NOTE: Uses global variables screenWidth and screenHeight
void SetPostproShader(Shader shader)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -2218,8 +2231,8 @@ void SetPostproShader(Shader shader)
Texture2D texture;
texture.id = fboColorTexture;
- texture.width = GetScreenWidth();
- texture.height = GetScreenHeight();
+ texture.width = screenWidth;
+ texture.height = screenHeight;
SetShaderMapDiffuse(&postproQuad.shader, texture);
@@ -2236,9 +2249,12 @@ void SetDefaultShader(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
SetCustomShader(defaultShader);
- SetPostproShader(defaultShader);
- enabledPostpro = false;
+ if (enabledPostpro)
+ {
+ SetPostproShader(defaultShader);
+ enabledPostpro = false;
+ }
#endif
}
@@ -2267,7 +2283,8 @@ void SetModelShader(Model *model, Shader shader)
if (vaoSupported) glBindVertexArray(0); // Unbind VAO
- //if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
+ // NOTE: If SetModelTexture() is called previously, texture is not assigned to new shader
+ if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id;
#endif
}
@@ -2423,6 +2440,26 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur
*/
}
+// Set blending mode (alpha, additive, multiplied)
+// NOTE: Only 3 blending modes predefined
+void SetBlendMode(int mode)
+{
+ if ((blendMode != mode) && (mode < 3))
+ {
+ rlglDraw();
+
+ switch (mode)
+ {
+ case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break;
+ case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; // Alternative: glBlendFunc(GL_ONE, GL_ONE);
+ case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break;
+ default: break;
+ }
+
+ blendMode = mode;
+ }
+}
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
void PrintProjectionMatrix(void)
{
@@ -3026,7 +3063,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType;
// Output a trace log message
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
-void TraceLog(int msgType, const char *text, ...)
+static void TraceLog(int msgType, const char *text, ...)
{
va_list args;
va_start(args, text);
diff --git a/src/rlgl.h b/src/rlgl.h
index eabf07e4..af312596 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -7,7 +7,7 @@
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -36,6 +36,10 @@
#include "utils.h" // Required for function TraceLog()
#endif
+#if defined(RLGL_STANDALONE)
+ #define RAYMATH_STANDALONE
+#endif
+
#include "raymath.h" // Required for data type Matrix and Matrix functions
// Select desired OpenGL version
@@ -89,9 +93,26 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
#ifdef RLGL_STANDALONE
+ #ifndef __cplusplus
+ // Boolean type
+ typedef enum { false, true } bool;
+ #endif
+
+ // byte type
+ typedef unsigned char byte;
+
+ // Color type, RGBA (32bit)
+ typedef struct Color {
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char a;
+ } Color;
+
// Texture formats (support depends on OpenGL version)
typedef enum {
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
+ UNCOMPRESSED_GRAY_ALPHA,
UNCOMPRESSED_R5G6B5, // 16 bpp
UNCOMPRESSED_R8G8B8, // 24 bpp
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
@@ -106,7 +127,8 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
COMPRESSED_PVRT_RGB, // 4 bpp
COMPRESSED_PVRT_RGBA, // 4 bpp
- /*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp
+ COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
+ COMPRESSED_ASTC_8x8_RGBA // 2 bpp
} TextureFormat;
// VertexData type
@@ -123,21 +145,36 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
// Shader type
typedef struct Shader {
- unsigned int id; // Shader program id
+ unsigned int id; // Shader program id
+ // TODO: This should be Texture2D objects
+ unsigned int texDiffuseId; // Diffuse texture id
+ unsigned int texNormalId; // Normal texture id
+ unsigned int texSpecularId; // Specular texture id
+
// Variable attributes
- unsigned int vertexLoc; // Vertex attribute location point (vertex shader)
- unsigned int texcoordLoc; // Texcoord attribute location point (vertex shader)
- unsigned int normalLoc; // Normal attribute location point (vertex shader)
- unsigned int colorLoc; // Color attibute location point (vertex shader)
+ int vertexLoc; // Vertex attribute location point (vertex shader)
+ int texcoordLoc; // Texcoord attribute location point (vertex shader)
+ int normalLoc; // Normal attribute location point (vertex shader)
+ int colorLoc; // Color attibute location point (vertex shader)
// Uniforms
- unsigned int projectionLoc; // Projection matrix uniform location point (vertex shader)
- unsigned int modelviewLoc; // ModeView matrix uniform location point (vertex shader)
- unsigned int textureLoc; // Texture uniform location point (fragment shader)
- unsigned int tintColorLoc; // Color uniform location point (fragment shader)
+ int projectionLoc; // Projection matrix uniform location point (vertex shader)
+ int modelviewLoc; // ModeView matrix uniform location point (vertex shader)
+ int tintColorLoc; // Color uniform location point (fragment shader)
+
+ int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader)
+ int mapNormalLoc; // Normal map texture uniform location point (fragment shader)
+ int mapSpecularLoc; // Specular map texture uniform location point (fragment shader)
} Shader;
+ // Texture2D type
+ typedef struct Texture2D {
+ unsigned int id; // Texture id
+ int width;
+ int height;
+ } Texture2D;
+
// 3d Model type
typedef struct Model {
VertexData mesh;
@@ -145,13 +182,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
Texture2D texture;
Shader shader;
} Model;
-
- // Texture2D type
- typedef struct Texture2D {
- unsigned int id; // Texture id
- int width;
- int height;
- } Texture2D;
+
+ // Color blending modes (pre-defined)
+ typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
#endif
#ifdef __cplusplus
@@ -231,6 +264,31 @@ void PrintProjectionMatrix(void); // DEBUG: Print projection matrix
void PrintModelviewMatrix(void); // DEBUG: Print modelview matrix
#endif
+#if defined(RLGL_STANDALONE)
+//------------------------------------------------------------------------------------
+// Shaders System Functions (Module: rlgl)
+// NOTE: This functions are useless when using OpenGL 1.1
+//------------------------------------------------------------------------------------
+Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations
+unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load a custom shader and return program id
+void UnloadShader(Shader shader); // Unload a custom shader from memory
+void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
+void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
+void SetDefaultShader(void); // Set default shader to be used in batch draw
+void SetModelShader(Model *model, Shader shader); // Link a shader to a model
+bool IsPosproShaderEnabled(void); // Check if postprocessing shader is enabled
+
+int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
+void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float)
+void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int)
+void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment
+void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment
+void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment
+void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
+
+void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/src/shapes.c b/src/shapes.c
index 6e6c9dd7..071fa63c 100644
--- a/src/shapes.c
+++ b/src/shapes.c
@@ -4,7 +4,7 @@
*
* Basic functions to draw 2d Shapes and check collisions
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
diff --git a/src/text.c b/src/text.c
index feed211e..65d52f26 100644
--- a/src/text.c
+++ b/src/text.c
@@ -4,7 +4,7 @@
*
* Basic functions to load SpriteFonts and draw Text
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -216,6 +216,8 @@ extern void UnloadDefaultFont(void)
{
UnloadTexture(defaultFont.texture);
free(defaultFont.charSet);
+
+ TraceLog(INFO, "Unloaded default font data");
}
// Get the default font, useful to be used with extended parameters
@@ -266,6 +268,8 @@ void UnloadSpriteFont(SpriteFont spriteFont)
{
UnloadTexture(spriteFont.texture);
free(spriteFont.charSet);
+
+ TraceLog(INFO, "Unloaded sprite font data");
}
// Draw text (using default font)
diff --git a/src/textures.c b/src/textures.c
index b7ab1f7e..69456701 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -8,7 +8,7 @@
* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC)
* NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.
@@ -330,7 +330,6 @@ Texture2D LoadTexture(const char *fileName)
else
{
TraceLog(WARNING, "Texture could not be created");
-
texture.id = 0;
}
@@ -390,12 +389,17 @@ Texture2D LoadTextureFromImage(Image image)
void UnloadImage(Image image)
{
free(image.data);
+
+ // NOTE: It becomes anoying every time a texture is loaded
+ //TraceLog(INFO, "Unloaded image data");
}
// Unload texture from GPU memory
void UnloadTexture(Texture2D texture)
{
rlDeleteTextures(texture.id);
+
+ TraceLog(INFO, "[TEX ID %i] Unloaded texture data", texture.id);
}
// Get pixel data from image in the form of Color struct array
@@ -486,20 +490,28 @@ Color *GetImageData(Image image)
}
// Get pixel data from GPU texture and return an Image
+// NOTE: Compressed texture formats not supported
Image GetTextureData(Texture2D texture)
{
Image image;
+ image.data = NULL;
- image.data = rlglReadTexturePixels(texture.id, texture.format);
-
- if (image.data != NULL)
+ if (texture.format < 8)
{
- image.width = texture.width;
- image.height = texture.height;
- image.format = texture.format;
- image.mipmaps = 1;
+ image.data = rlglReadTexturePixels(texture.id, texture.format);
+
+ if (image.data != NULL)
+ {
+ image.width = texture.width;
+ image.height = texture.height;
+ image.format = texture.format;
+ image.mipmaps = 1;
+
+ TraceLog(INFO, "Texture pixel data obtained successfully");
+ }
+ else TraceLog(WARNING, "Texture pixel data could not be obtained");
}
- else TraceLog(WARNING, "Texture pixel data could not be obtained");
+ else TraceLog(WARNING, "Compressed texture data could not be obtained");
return image;
}
@@ -507,136 +519,139 @@ Image GetTextureData(Texture2D texture)
// Convert image data to desired format
void ImageConvertFormat(Image *image, int newFormat)
{
- if ((image->format != newFormat) && (image->format < 8) && (newFormat < 8))
+ if (image->format != newFormat)
{
- Color *pixels = GetImageData(*image);
-
- free(image->data);
-
- image->format = newFormat;
-
- int k = 0;
-
- switch (image->format)
+ if ((image->format < 8) && (newFormat < 8))
{
- case UNCOMPRESSED_GRAYSCALE:
+ Color *pixels = GetImageData(*image);
+
+ free(image->data);
+
+ image->format = newFormat;
+
+ int k = 0;
+
+ switch (image->format)
{
- image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char));
-
- for (int i = 0; i < image->width*image->height; i++)
+ case UNCOMPRESSED_GRAYSCALE:
{
- ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
- k++;
- }
-
- } break;
- case UNCOMPRESSED_GRAY_ALPHA:
- {
- image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
-
- for (int i = 0; i < image->width*image->height*2; i += 2)
+ image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
+ k++;
+ }
+
+ } break;
+ case UNCOMPRESSED_GRAY_ALPHA:
{
- ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
- ((unsigned char *)image->data)[i + 1] = pixels[k].a;
- k++;
- }
+ image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height*2; i += 2)
+ {
+ ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
+ ((unsigned char *)image->data)[i + 1] = pixels[k].a;
+ k++;
+ }
- } break;
- case UNCOMPRESSED_R5G6B5:
- {
- image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
-
- unsigned char r;
- unsigned char g;
- unsigned char b;
-
- for (int i = 0; i < image->width*image->height; i++)
+ } break;
+ case UNCOMPRESSED_R5G6B5:
{
- r = (unsigned char)(round((float)pixels[k].r*31/255));
- g = (unsigned char)(round((float)pixels[k].g*63/255));
- b = (unsigned char)(round((float)pixels[k].b*31/255));
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
- ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ r = (unsigned char)(round((float)pixels[k].r*31/255));
+ g = (unsigned char)(round((float)pixels[k].g*63/255));
+ b = (unsigned char)(round((float)pixels[k].b*31/255));
+
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
- k++;
- }
+ k++;
+ }
- } break;
- case UNCOMPRESSED_R8G8B8:
- {
- image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
-
- for (int i = 0; i < image->width*image->height*3; i += 3)
+ } break;
+ case UNCOMPRESSED_R8G8B8:
{
- ((unsigned char *)image->data)[i] = pixels[k].r;
- ((unsigned char *)image->data)[i + 1] = pixels[k].g;
- ((unsigned char *)image->data)[i + 2] = pixels[k].b;
- k++;
- }
- } break;
- case UNCOMPRESSED_R5G5B5A1:
- {
- image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
-
- unsigned char r;
- unsigned char g;
- unsigned char b;
- unsigned char a = 1;
-
- for (int i = 0; i < image->width*image->height; i++)
+ image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height*3; i += 3)
+ {
+ ((unsigned char *)image->data)[i] = pixels[k].r;
+ ((unsigned char *)image->data)[i + 1] = pixels[k].g;
+ ((unsigned char *)image->data)[i + 2] = pixels[k].b;
+ k++;
+ }
+ } break;
+ case UNCOMPRESSED_R5G5B5A1:
{
- r = (unsigned char)(round((float)pixels[k].r*31/255));
- g = (unsigned char)(round((float)pixels[k].g*31/255));
- b = (unsigned char)(round((float)pixels[k].b*31/255));
- a = (pixels[k].a > 50) ? 1 : 0;
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
+
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char a = 1;
- ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ r = (unsigned char)(round((float)pixels[k].r*31/255));
+ g = (unsigned char)(round((float)pixels[k].g*31/255));
+ b = (unsigned char)(round((float)pixels[k].b*31/255));
+ a = (pixels[k].a > 50) ? 1 : 0;
+
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
- k++;
- }
+ k++;
+ }
- } break;
- case UNCOMPRESSED_R4G4B4A4:
- {
- image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
-
- unsigned char r;
- unsigned char g;
- unsigned char b;
- unsigned char a;
-
- for (int i = 0; i < image->width*image->height; i++)
+ } break;
+ case UNCOMPRESSED_R4G4B4A4:
{
- r = (unsigned char)(round((float)pixels[k].r*15/255));
- g = (unsigned char)(round((float)pixels[k].g*15/255));
- b = (unsigned char)(round((float)pixels[k].b*15/255));
- a = (unsigned char)(round((float)pixels[k].a*15/255));
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
- ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char a;
+
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ r = (unsigned char)(round((float)pixels[k].r*15/255));
+ g = (unsigned char)(round((float)pixels[k].g*15/255));
+ b = (unsigned char)(round((float)pixels[k].b*15/255));
+ a = (unsigned char)(round((float)pixels[k].a*15/255));
+
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
- k++;
- }
-
- } break;
- case UNCOMPRESSED_R8G8B8A8:
- {
- image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
-
- for (int i = 0; i < image->width*image->height*4; i += 4)
+ k++;
+ }
+
+ } break;
+ case UNCOMPRESSED_R8G8B8A8:
{
- ((unsigned char *)image->data)[i] = pixels[k].r;
- ((unsigned char *)image->data)[i + 1] = pixels[k].g;
- ((unsigned char *)image->data)[i + 2] = pixels[k].b;
- ((unsigned char *)image->data)[i + 3] = pixels[k].a;
- k++;
- }
- } break;
- default: break;
+ image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height*4; i += 4)
+ {
+ ((unsigned char *)image->data)[i] = pixels[k].r;
+ ((unsigned char *)image->data)[i + 1] = pixels[k].g;
+ ((unsigned char *)image->data)[i + 2] = pixels[k].b;
+ ((unsigned char *)image->data)[i + 3] = pixels[k].a;
+ k++;
+ }
+ } break;
+ default: break;
+ }
+
+ free(pixels);
}
-
- free(pixels);
+ else TraceLog(WARNING, "Image data format is compressed, can not be converted");
}
- else TraceLog(WARNING, "Image data format is compressed, can not be converted");
}
@@ -644,8 +659,8 @@ void ImageConvertFormat(Image *image, int newFormat)
// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5)
void ImageConvertToPOT(Image *image, Color fillColor)
{
- // TODO: Review for new image struct
- /*
+ Color *pixels = GetImageData(*image); // Get pixels data
+
// Just add the required amount of pixels at the right and bottom sides of image...
int potWidth = GetNextPOT(image->width);
int potHeight = GetNextPOT(image->height);
@@ -653,29 +668,33 @@ void ImageConvertToPOT(Image *image, Color fillColor)
// Check if POT texture generation is required (if texture is not already POT)
if ((potWidth != image->width) || (potHeight != image->height))
{
- Color *imgDataPixelPOT = NULL;
+ Color *pixelsPOT = NULL;
// Generate POT array from NPOT data
- imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
+ pixelsPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
for (int j = 0; j < potHeight; j++)
{
for (int i = 0; i < potWidth; i++)
{
- if ((j < image->height) && (i < image->width)) imgDataPixelPOT[j*potWidth + i] = image->data[j*image->width + i];
- else imgDataPixelPOT[j*potWidth + i] = fillColor;
+ if ((j < image->height) && (i < image->width)) pixelsPOT[j*potWidth + i] = pixels[j*image->width + i];
+ else pixelsPOT[j*potWidth + i] = fillColor;
}
}
TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
- free(image->pixels);
+ free(pixels); // Free pixels data
+ free(image->data); // Free old image data
+
+ int format = image->format; // Store image data format to reconvert later
+
+ *image = LoadImageEx(pixelsPOT, potWidth, potHeight);
+
+ free(pixelsPOT); // Free POT pixels data
- image->pixels = imgDataPixelPOT;
- image->width = potWidth;
- image->height = potHeight;
+ ImageConvertFormat(image, format); // Reconvert image to previous format
}
- */
}
// Copy an image to a new image
diff --git a/src/utils.c b/src/utils.c
index 8e42e533..b8e8bc1a 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -8,7 +8,7 @@
* tinfl - zlib DEFLATE algorithm decompression lib
* stb_image_write - PNG writting functions
*
-* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
+* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
* 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.