Road to raylib 1.1 - Testing rlgl

This commit is contained in:
raysan5 2014-03-25 12:40:35 +01:00
parent 1c8dce429e
commit 96f520ff6d
13 changed files with 2537 additions and 1314 deletions

View file

@ -28,15 +28,19 @@
#include "raylib.h" #include "raylib.h"
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
#include <GLFW/glfw3.h> // GLFW3 lib: Windows, OpenGL context and Input management #include <GLFW/glfw3.h> // GLFW3 lib: Windows, OpenGL context and Input management
//#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h) //#include <GL/gl.h> // OpenGL functions (GLFW3 already includes gl.h)
#include <stdio.h> // Standard input / output lib #include <stdio.h> // Standard input / output lib
#include <stdlib.h> // Declares malloc() and free() for memory management, rand() #include <stdlib.h> // Declares malloc() and free() for memory management, rand()
#include <time.h> // Useful to initialize random seed #include <time.h> // Useful to initialize random seed
#include <math.h> // Math related functions, tan() used to set perspective #include <math.h> // Math related functions, tan() used to set perspective
#include "vector3.h" // Basic Vector3 functions //#include "vector3.h" // Basic Vector3 functions, not required any more, replaced by raymath
#include "utils.h" // WritePNG() function #include "utils.h" // WritePNG() function
#include "raymath.h" // Required for data type Matrix and Matrix functions
//#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version! //#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version!
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -47,7 +51,7 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef Color pixel; // ...
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
@ -62,7 +66,7 @@ static double targetTime = 0; // Desired time for one frame, if 0
static int windowWidth, windowHeight; // Required to switch between windowed/fullscren mode (F11) static int windowWidth, windowHeight; // Required to switch between windowed/fullscren mode (F11)
static const char *windowTitle; // Required to switch between windowed/fullscren mode (F11) static const char *windowTitle; // Required to switch between windowed/fullscren mode (F11)
static int exitKey = GLFW_KEY_ESCAPE; static int exitKey = GLFW_KEY_ESCAPE; // Default exit key (ESC)
static bool customCursor = false; // Tracks if custom cursor has been set static bool customCursor = false; // Tracks if custom cursor has been set
static bool cursorOnScreen = false; // Tracks if cursor is inside client area static bool cursorOnScreen = false; // Tracks if cursor is inside client area
@ -77,8 +81,10 @@ static char currentMouseState[3] = { 0 }; // Required to check if mouse btn pr
static char previousGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once static char previousGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
static char currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once static char currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once
static int previousMouseWheelY = 0; static int previousMouseWheelY = 0; // Required to track mouse wheel variation
static int currentMouseWheelY = 0; static int currentMouseWheelY = 0; // Required to track mouse wheel variation
static Color background = { 0, 0, 0, 0 }; // Screen background color
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core) // Other Modules Functions Declaration (required by core)
@ -89,13 +95,11 @@ extern void UnloadDefaultFont(); // [Module: text] Unloads default f
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static void InitGraphicsDevice(); // Initialize Graphics Device (OpenGL stuff)
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel 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 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 WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up); // Setup camera view (updates MODELVIEW matrix)
static void TakeScreenshot(); // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable static void TakeScreenshot(); // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -116,9 +120,17 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
if (!glfwInit()) exit(1); if (!glfwInit()) exit(1);
//glfwDefaultWindowHints() // Set default windows hints //glfwDefaultWindowHints() // Set default windows hints
//glfwWindowHint(GLFW_SAMPLES, 4); // If called before windows creation, enables multisampling x4 (MSAA), default is 0
if (!resizable) glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable if (!resizable) glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable
#ifdef USE_OPENGL_33
//glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE);
#endif
window = glfwCreateWindow(width, height, title, NULL, NULL); window = glfwCreateWindow(width, height, title, NULL, NULL);
windowWidth = width; windowWidth = width;
@ -140,15 +152,29 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
glfwSwapInterval(0); // Disables GPU v-sync (if set), so frames are not limited to screen refresh rate (60Hz -> 60 FPS) glfwSwapInterval(0); // Disables GPU v-sync (if set), so frames are not limited to screen refresh rate (60Hz -> 60 FPS)
// If not set, swap interval uses GPU v-sync configuration // If not set, swap interval uses GPU v-sync configuration
// Framerate can be setup using SetTargetFPS() // Framerate can be setup using SetTargetFPS()
InitGraphicsDevice();
//------------------------------------------------------
#ifdef USE_OPENGL_33
rlglInit(); // Init rlgl
#endif
//------------------------------------------------------
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
//------------------------------------------------------
rlglInitGraphicsDevice(fbWidth, fbHeight);
//------------------------------------------------------
previousTime = glfwGetTime(); previousTime = glfwGetTime();
LoadDefaultFont(); LoadDefaultFont(); // NOTE: External function (defined in module: text)
if (cursorImage != NULL) SetCustomCursor(cursorImage); if (cursorImage != NULL) SetCustomCursor(cursorImage);
srand(time(NULL)); // Initialize random seed srand(time(NULL)); // Initialize random seed
ClearBackground(RAYWHITE); // Default background color for raylib games :P
} }
// Close Window and Terminate Context // Close Window and Terminate Context
@ -156,6 +182,12 @@ void CloseWindow()
{ {
UnloadDefaultFont(); UnloadDefaultFont();
//------------------------------------------------------
#ifdef USE_OPENGL_33
rlglClose(); // De-init rlgl
#endif
//------------------------------------------------------
glfwDestroyWindow(window); glfwDestroyWindow(window);
glfwTerminate(); glfwTerminate();
} }
@ -210,7 +242,10 @@ void ToggleFullscreen()
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, KeyCallback); glfwSetKeyCallback(window, KeyCallback);
InitGraphicsDevice(); int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
rlglInitGraphicsDevice(fbWidth, fbHeight);
LoadDefaultFont(); LoadDefaultFont();
} }
@ -219,13 +254,12 @@ void ToggleFullscreen()
// Sets Background Color // Sets Background Color
void ClearBackground(Color color) void ClearBackground(Color color)
{ {
// Color values clamp to 0.0f(0) and 1.0f(255) if ((color.r != background.r) || (color.g != background.g) || (color.b != background.b) || (color.a != background.a))
float r = (float)color.r / 255; {
float g = (float)color.g / 255; rlClearColor(color.r, color.g, color.b, color.a);
float b = (float)color.b / 255;
float a = (float)color.a / 255;
glClearColor(r, g, b, a); background = color;
}
} }
// Setup drawing canvas to start drawing // Setup drawing canvas to start drawing
@ -235,11 +269,14 @@ void BeginDrawing()
updateTime = currentTime - previousTime; updateTime = currentTime - previousTime;
previousTime = currentTime; previousTime = currentTime;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, Depth Buffer is used for 3D rlClearScreenBuffers();
glLoadIdentity(); // Reset current matrix (MODELVIEW) rlLoadIdentity(); // Reset current matrix (MODELVIEW)
glTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL //#ifdef USE_OPENGL_11
// rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL
// NOTE: Not required with OpenGL 3.3+
//#endif
} }
// End canvas drawing and Swap Buffers (Double Buffering) // End canvas drawing and Swap Buffers (Double Buffering)
@ -247,6 +284,12 @@ void EndDrawing()
{ {
if (customCursor && cursorOnScreen) DrawTexture(cursor, GetMouseX(), GetMouseY(), WHITE); if (customCursor && cursorOnScreen) DrawTexture(cursor, GetMouseX(), GetMouseY(), WHITE);
//------------------------------------------------------
#ifdef USE_OPENGL_33
rlglDraw(); // Draw Buffers
#endif
//------------------------------------------------------
glfwSwapBuffers(window); // Swap back and front buffers glfwSwapBuffers(window); // Swap back and front buffers
glfwPollEvents(); // Register keyboard/mouse events glfwPollEvents(); // Register keyboard/mouse events
@ -271,34 +314,48 @@ void EndDrawing()
// Initializes 3D mode for drawing (Camera setup) // Initializes 3D mode for drawing (Camera setup)
void Begin3dMode(Camera camera) void Begin3dMode(Camera camera)
{ {
glMatrixMode(GL_PROJECTION); // Switch to projection matrix //------------------------------------------------------
#ifdef USE_OPENGL_33
rlglDraw(); // Draw Buffers
#endif
//------------------------------------------------------
glPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
glLoadIdentity(); // Reset current matrix (PROJECTION)
rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
rlLoadIdentity(); // Reset current matrix (PROJECTION)
// Setup perspective projection // Setup perspective projection
float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight; float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight;
double top = 0.1f*tan(45.0f*PI / 360.0); double top = 0.1f*tan(45.0f*PI / 360.0);
double right = top*aspect; double right = top*aspect;
glFrustum(-right, right, -top, top, 0.1f, 100.0f); rlFrustum(-right, right, -top, top, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW); // Switch back to modelview matrix rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
glLoadIdentity(); // Reset current matrix (MODELVIEW) rlLoadIdentity(); // Reset current matrix (MODELVIEW)
CameraLookAt(camera.position, camera.target, camera.up); // Setup Camera view // Setup Camera view
Matrix matLookAt = MatrixLookAt(camera.position, camera.target, camera.up);
rlMultMatrixf(GetMatrixVector(matLookAt)); // Multiply MODELVIEW matrix by view matrix (camera)
} }
// Ends 3D mode and returns to default 2D orthographic mode // Ends 3D mode and returns to default 2D orthographic mode
void End3dMode() void End3dMode()
{ {
glMatrixMode(GL_PROJECTION); // Switch to projection matrix //------------------------------------------------------
glPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack #ifdef USE_OPENGL_33
rlglDraw(); // Draw Buffers
#endif
//------------------------------------------------------
glMatrixMode(GL_MODELVIEW); // Get back to modelview matrix rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
glLoadIdentity(); // Reset current matrix (MODELVIEW) rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack
glTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode) rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
//rlTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode)
} }
// Set target FPS for the game // Set target FPS for the game
@ -649,85 +706,13 @@ static void CursorEnterCallback(GLFWwindow* window, int enter)
// GLFW3 WindowSize Callback, runs when window is resized // GLFW3 WindowSize Callback, runs when window is resized
static void WindowSizeCallback(GLFWwindow* window, int width, int height) static void WindowSizeCallback(GLFWwindow* window, int width, int height)
{
InitGraphicsDevice(); // If window is resized, graphics device is re-initialized
// NOTE: Aspect ratio does not change, so, image can be deformed
}
// Initialize Graphics Device (OpenGL stuff)
static void InitGraphicsDevice()
{ {
int fbWidth, fbHeight; int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height // If window is resized, graphics device is re-initialized
// NOTE: Aspect ratio does not change, so, image can be deformed
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D rlglInitGraphicsDevice(fbWidth, fbHeight);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set background color (black)
glClearDepth(1.0f); // Clear depth buffer
glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D)
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
glEnable(GL_BLEND); // Enable color blending (required to work with transparencies)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation (Deprecated in OGL 3.0)
// Other options: GL_FASTEST, GL_DONT_CARE (default)
glMatrixMode(GL_PROJECTION); // Switch to PROJECTION matrix
glLoadIdentity(); // Reset current matrix (PROJECTION)
glOrtho(0, fbWidth, fbHeight, 0, 0, 1); // Config orthographic mode: top-left corner --> (0,0)
glMatrixMode(GL_MODELVIEW); // Switch back to MODELVIEW matrix
glLoadIdentity(); // Reset current matrix (MODELVIEW)
// TODO: Review all shapes/models are drawn CCW and enable backface culling
//glEnable(GL_CULL_FACE); // Enable backface culling (Disabled by default)
//glCullFace(GL_BACK); // Cull the Back face (default)
//glFrontFace(GL_CCW); // Front face are defined counter clockwise (default)
glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation)
// Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation)
}
// Setup camera view (updates MODELVIEW matrix)
static void CameraLookAt(Vector3 position, Vector3 target, Vector3 up)
{
float rotMatrix[16]; // Matrix to store camera rotation
Vector3 rotX, rotY, rotZ; // Vectors to calculate camera rotations X, Y, Z (Euler)
// Construct rotation matrix from vectors
rotZ = VectorSubtract(position, target);
VectorNormalize(&rotZ);
rotY = up; // Y rotation vector
rotX = VectorCrossProduct(rotY, rotZ); // X rotation vector = Y cross Z
rotY = VectorCrossProduct(rotZ, rotX); // Recompute Y rotation = Z cross X
VectorNormalize(&rotX); // X rotation vector normalization
VectorNormalize(&rotY); // Y rotation vector normalization
rotMatrix[0] = rotX.x;
rotMatrix[1] = rotY.x;
rotMatrix[2] = rotZ.x;
rotMatrix[3] = 0.0f;
rotMatrix[4] = rotX.y;
rotMatrix[5] = rotY.y;
rotMatrix[6] = rotZ.y;
rotMatrix[7] = 0.0f;
rotMatrix[8] = rotX.z;
rotMatrix[9] = rotY.z;
rotMatrix[10] = rotZ.z;
rotMatrix[11] = 0.0f;
rotMatrix[12] = 0.0f;
rotMatrix[13] = 0.0f;
rotMatrix[14] = 0.0f;
rotMatrix[15] = 1.0f;
glMultMatrixf(rotMatrix); // Multiply MODELVIEW matrix by rotation matrix
glTranslatef(-position.x, -position.y, -position.z); // Translate eye to position
} }
// Takes a bitmap (BMP) screenshot and saves it in the same folder as executable // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
@ -736,38 +721,17 @@ static void TakeScreenshot()
static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution
char buffer[20]; // Buffer to store file name char buffer[20]; // Buffer to store file name
int fbWidth, fbHeight; int fbWidth, fbHeight; // Frame buffer width and height
unsigned char *imgData; // Pixel image data array
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
imgData = (unsigned char *)malloc(fbWidth * fbHeight * sizeof(unsigned char) * 4); unsigned char *imgData = rlglReadScreenPixels(fbWidth, fbHeight);
// NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
glReadPixels(0, 0, fbWidth, fbHeight, GL_RGBA, GL_UNSIGNED_BYTE, imgData);
// TODO: Flip image vertically!
unsigned char *imgDataFlip = (unsigned char *)malloc(fbWidth * fbHeight * sizeof(unsigned char) * 4);
for (int y = fbHeight-1; y >= 0; y--)
{
for (int x = 0; x < (fbWidth*4); x++)
{
imgDataFlip[x + (fbHeight - y - 1)*fbWidth*4] = imgData[x + (y*fbWidth*4)];
}
}
free(imgData);
sprintf(buffer, "screenshot%03i.png", shotNum); sprintf(buffer, "screenshot%03i.png", shotNum);
// NOTE: BMP directly stores data flipped vertically WritePNG(buffer, imgData, fbWidth, fbHeight);
//WriteBitmap(buffer, imgDataPixel, fbWidth, fbHeight); // Writes pixel data array into a bitmap (BMP) file
WritePNG(buffer, imgDataFlip, fbWidth, fbHeight);
free(imgDataFlip); free(imgData);
shotNum++; shotNum++;
} }

View file

@ -29,7 +29,10 @@
#include <stdio.h> // Standard input/output functions, used to read model files data #include <stdio.h> // Standard input/output functions, used to read model files data
#include <stdlib.h> // Declares malloc() and free() for memory management #include <stdlib.h> // Declares malloc() and free() for memory management
#include <math.h> // Used for sin, cos, tan #include <math.h> // Used for sin, cos, tan
#include "vector3.h" // Basic Vector3 functions
#include "raymath.h" // Required for data type Matrix and Matrix functions
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
@ -39,14 +42,30 @@
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Types and Structures Definition // Types and Structures Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#ifdef USE_OPENGL_11
struct Model {
int numVertices;
Vector3 *vertices;
Vector2 *texcoords;
Vector3 *normals;
};
#else
struct Model {
int numVertices;
Vector3 *vertices;
Vector2 *texcoords;
Vector3 *normals;
};
// Matrix type (OpenGL style 4x4 - right handed) /*
typedef struct Matrix { struct Model
float m0, m4, m8, m12; {
float m1, m5, m9, m13; GLUint vaoId;
float m2, m6, m10, m14; Matrix transform;
float m3, m7, m11, m15; int polyMode;
} Matrix; }
*/
#endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Global Variables Definition // Global Variables Definition
@ -57,8 +76,6 @@ typedef struct Matrix {
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
static float GetHeightValue(Color pixel); static float GetHeightValue(Color pixel);
static void MatrixTranspose(Matrix *mat);
static Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up);
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition // Module Functions Definition
@ -68,52 +85,66 @@ static Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up);
// NOTE: Cube position is the center position // NOTE: Cube position is the center position
void DrawCube(Vector3 position, float width, float height, float lenght, Color color) void DrawCube(Vector3 position, float width, float height, float lenght, Color color)
{ {
glPushMatrix(); // THIS WORKS!
glTranslatef(position.x, position.y, position.z); /*
//glRotatef(rotation, 0.0f, 1.0f, 0.0f); Matrix mat = MatrixTranslate(2.0, 0.0, 0.0);
//glScalef(1.0f, 1.0f, 1.0f); MatrixTranspose(&mat);
VectorTransform(&position, mat);
glBegin(GL_QUADS); PrintMatrix(mat);
glColor4ub(color.r, color.g, color.b, color.a); */
float x = position.x;
float y = position.y;
float z = position.z;
rlPushMatrix();
// NOTE: Be careful! Function order matters (scale, translate, rotate)
//rlScalef(2.0f, 2.0f, 2.0f);
//rlTranslatef(2.0f, 0.0f, 0.0f);
rlRotatef(45, 0, 1, 0);
rlBegin(RL_QUADS);
rlColor4ub(color.r, color.g, color.b, color.a);
// Front Face // Front Face
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, lenght/2); // Top Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, lenght/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left Of The Texture and Quad
// Back Face // Back Face
glNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer rlNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer
glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, -lenght/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Left Of The Texture and Quad
// Top Face // Top Face
glNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up rlNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, height/2, lenght/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, height/2, lenght/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right Of The Texture and Quad
// Bottom Face // Bottom Face
glNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down rlNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down
glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Top Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, -height/2, -lenght/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Right Of The Texture and Quad
// Right face // Right face
glNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right rlNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right
glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, -height/2, -lenght/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, height/2, lenght/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad
// Left Face // Left Face
glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left rlNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, height/2, lenght/2); // Top Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad
glEnd(); rlEnd();
glPopMatrix(); rlPopMatrix();
} }
// Draw cube (Vector version) // Draw cube (Vector version)
@ -125,9 +156,11 @@ void DrawCubeV(Vector3 position, Vector3 size, Color color)
// Draw cube wires // Draw cube wires
void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color) void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // TODO: Draw cube using RL_LINES!
DrawCube(position, width, height, lenght, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//DrawCube(position, width, height, lenght, color);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
// Draw sphere // Draw sphere
@ -143,14 +176,16 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
float lat1, z1, zr1; float lat1, z1, zr1;
float lng, x, y; float lng, x, y;
glPushMatrix(); // TODO: Review vertex translate/rotate/scale mechanism
glTranslatef(centerPos.x, centerPos.y, centerPos.z);
glRotatef(90, 1, 0, 0);
glScalef(radius, radius, radius);
glBegin(GL_QUAD_STRIP); rlPushMatrix();
rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
rlRotatef(90, 1, 0, 0);
rlScalef(radius, radius, radius);
glColor4ub(color.r, color.g, color.b, color.a); rlBegin(GL_QUAD_STRIP);
rlColor4ub(color.r, color.g, color.b, color.a);
for(int i = 0; i <= rings; i++) for(int i = 0; i <= rings; i++)
{ {
@ -168,23 +203,25 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
x = cos(lng); x = cos(lng);
y = sin(lng); y = sin(lng);
glNormal3f(x * zr0, y * zr0, z0); rlNormal3f(x * zr0, y * zr0, z0);
glVertex3f(x * zr0, y * zr0, z0); rlVertex3f(x * zr0, y * zr0, z0);
glNormal3f(x * zr1, y * zr1, z1); rlNormal3f(x * zr1, y * zr1, z1);
glVertex3f(x * zr1, y * zr1, z1); rlVertex3f(x * zr1, y * zr1, z1);
} }
} }
glEnd(); rlEnd();
glPopMatrix(); rlPopMatrix();
} }
// Draw sphere wires // Draw sphere wires
void DrawSphereWires(Vector3 centerPos, float radius, Color color) void DrawSphereWires(Vector3 centerPos, float radius, Color color)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // TODO: Draw sphere using RL_LINES!
DrawSphere(centerPos, radius, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//DrawSphere(centerPos, radius, color);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
// Draw a cylinder/cone // Draw a cylinder/cone
@ -200,136 +237,131 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
if (radiusTop == 0) // Draw pyramid or cone if (radiusTop == 0) // Draw pyramid or cone
{ {
//void drawCone(const Vector3 &d, const Vector3 &a, const float h, const float rd, const int n)
//d axis defined as a normalized vector from base to apex //d axis defined as a normalized vector from base to apex
//a position of apex (top point) //a position of apex (top point)
//h height //h height
//rd radius of directrix //rd radius of directrix
//n number of radial "slices" //n number of radial "slices"
glPushMatrix(); // TODO: Review drawing to use RL_TRIANGLES
//glTranslatef(centerPos.x, centerPos.y, centerPos.z);
//glRotatef(degrees, 0.0f, 1.0f, 0.0f);
//glScalef(1.0f, 1.0f, 1.0f);
// Draw cone top // Draw cone top
glBegin(GL_TRIANGLE_FAN); rlBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(a.x, a.y, a.z); rlVertex3f(a.x, a.y, a.z);
for (int i = 0; i <= slices; i++)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
// Draw cone bottom for (int i = 0; i <= slices; i++)
glBegin(GL_TRIANGLE_FAN); {
glColor4ub(color.r, color.g, color.b, color.a); float rad = angInc * i;
glVertex3f(c.x, c.y, c.z); p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
for (int i = slices; i >= 0; i--) p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
{ p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
float rad = angInc * i; rlVertex3f(p.x, p.y, p.z);
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom); }
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom); rlEnd();
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
glPopMatrix(); // Draw cone bottom
rlBegin(GL_TRIANGLE_FAN);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex3f(c.x, c.y, c.z);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
rlVertex3f(p.x, p.y, p.z);
}
rlEnd();
} }
else // Draw cylinder else // Draw cylinder
{ {
glPushMatrix();
//glTranslatef(centerPos.x, centerPos.y, centerPos.z);
//glRotatef(degrees, 0.0f, 1.0f, 0.0f);
//glScalef(1.0f, 1.0f, 1.0f);
// Draw cylinder top (pointed cap) // TODO: Review drawing to use RL_TRIANGLES
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(c.x, c.y + height, c.z);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height;
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
// Draw cylinder sides // Draw cylinder top (pointed cap)
glBegin(GL_TRIANGLE_STRIP); rlBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
for (int i = slices; i >= 0; i--) rlVertex3f(c.x, c.y + height, c.z);
{ for (int i = slices; i >= 0; i--)
float rad = angInc * i; {
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop); float rad = angInc * i;
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height; p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop); p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height;
glVertex3f(p.x, p.y, p.z); p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop);
rlVertex3f(p.x, p.y, p.z);
}
rlEnd();
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom); // Draw cylinder sides
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom); rlBegin(GL_TRIANGLE_STRIP);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex3f(p.x, p.y, p.z); for (int i = slices; i >= 0; i--)
} {
glEnd(); float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height;
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop);
rlVertex3f(p.x, p.y, p.z);
// Draw cylinder bottom p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
glBegin(GL_TRIANGLE_FAN); p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
glColor4ub(color.r, color.g, color.b, color.a); p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(c.x, c.y, c.z); rlVertex3f(p.x, p.y, p.z);
for (int i = slices; i >= 0; i--) }
{ rlEnd();
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
glVertex3f(p.x, p.y, p.z);
}
glEnd();
glPopMatrix(); // Draw cylinder bottom
rlBegin(GL_TRIANGLE_FAN);
rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex3f(c.x, c.y, c.z);
for (int i = slices; i >= 0; i--)
{
float rad = angInc * i;
p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom);
p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom);
p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom);
rlVertex3f(p.x, p.y, p.z);
}
rlEnd();
} }
} }
// Draw a cylinder/cone wires // Draw a cylinder/cone wires
void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color) void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // TODO: Draw sphere using RL_LINES!
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawCylinder(position, radiusTop, radiusBottom, height, slices, color); DrawCylinder(position, radiusTop, radiusBottom, height, slices, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
// Draw a plane // Draw a plane
void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color) void DrawPlane(Vector3 centerPos, Vector2 size, Vector3 rotation, Color color)
{ {
// TODO: Review vertex translate/rotate/scale mechanism
// NOTE: Plane is always created on XZ ground and then rotated // NOTE: Plane is always created on XZ ground and then rotated
glPushMatrix(); rlPushMatrix();
glTranslatef(centerPos.x, centerPos.y, centerPos.z); rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
// TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions...
glRotatef(rotation.x, 1, 0, 0); rlRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0); rlRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1); rlRotatef(rotation.z, 0, 0, 1);
glScalef(size.x, 1.0f, size.y); rlScalef(size.x, 1.0f, size.y);
glBegin(GL_QUADS); rlBegin(GL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glNormal3f(0.0f, 1.0f, 0.0f); rlNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, 0.0f, -0.5f); rlTexCoord2f(0.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, -0.5f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5f, 0.0f, -0.5f); rlTexCoord2f(1.0f, 0.0f); rlVertex3f(0.5f, 0.0f, -0.5f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5f, 0.0f, 0.5f); rlTexCoord2f(1.0f, 1.0f); rlVertex3f(0.5f, 0.0f, 0.5f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, 0.0f, 0.5f); rlTexCoord2f(0.0f, 1.0f); rlVertex3f(-0.5f, 0.0f, 0.5f);
glEnd(); rlEnd();
rlPopMatrix();
glPopMatrix();
} }
// Draw a plane with divisions // Draw a plane with divisions
@ -341,41 +373,43 @@ void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX,
float texPieceW = 1 / size.x; float texPieceW = 1 / size.x;
float texPieceH = 1 / size.y; float texPieceH = 1 / size.y;
// TODO: Review vertex translate/rotate/scale mechanism
// NOTE: Plane is always created on XZ ground and then rotated // NOTE: Plane is always created on XZ ground and then rotated
glPushMatrix(); rlPushMatrix();
glTranslatef(-size.x / 2, 0.0f, -size.y / 2); rlTranslatef(-size.x / 2, 0.0f, -size.y / 2);
glTranslatef(centerPos.x, centerPos.y, centerPos.z); rlTranslatef(centerPos.x, centerPos.y, centerPos.z);
// TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions...
glRotatef(rotation.x, 1, 0, 0); rlRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0); rlRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1); rlRotatef(rotation.z, 0, 0, 1);
glBegin(GL_QUADS); rlBegin(RL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glNormal3f(0.0f, 1.0f, 0.0f); rlNormal3f(0.0f, 1.0f, 0.0f);
for (int z = 0; z < slicesZ; z++) for (int z = 0; z < slicesZ; z++)
{ {
for (int x = 0; x < slicesX; x++) for (int x = 0; x < slicesX; x++)
{ {
// Draw the plane quad by quad (with textcoords) // Draw the plane quad by quad (with textcoords)
glTexCoord2f((float)x * texPieceW, (float)z * texPieceH); rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH);
glVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght); rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght);
glTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH); rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH);
glVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght); rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght);
glTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH); rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH);
glVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght); rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght);
glTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH); rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH);
glVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght); rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght);
} }
} }
glEnd(); rlEnd();
glPopMatrix(); rlPopMatrix();
} }
// Draw a grid centered at (0, 0, 0) // Draw a grid centered at (0, 0, 0)
@ -383,29 +417,31 @@ void DrawGrid(int slices, float spacing)
{ {
int halfSlices = slices / 2; int halfSlices = slices / 2;
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) rlBegin(RL_LINES);
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) for(int i = -halfSlices; i <= halfSlices; i++)
{
glPushMatrix(); if (i == 0)
glScalef(spacing, 1.0f, spacing);
glBegin(GL_LINES);
for(int i = -halfSlices; i <= halfSlices; i++)
{ {
if (i == 0) glColor3f(0.5f, 0.5f, 0.5f); rlColor3f(0.5f, 0.5f, 0.5f);
else glColor3f(0.75f, 0.75f, 0.75f); rlColor3f(0.5f, 0.5f, 0.5f);
rlColor3f(0.5f, 0.5f, 0.5f);
glVertex3f((float)i, 0.0f, (float)-halfSlices); rlColor3f(0.5f, 0.5f, 0.5f);
glVertex3f((float)i, 0.0f, (float)halfSlices); }
else
glVertex3f((float)-halfSlices, 0.0f, (float)i); {
glVertex3f((float)halfSlices, 0.0f, (float)i); rlColor3f(0.75f, 0.75f, 0.75f);
rlColor3f(0.75f, 0.75f, 0.75f);
rlColor3f(0.75f, 0.75f, 0.75f);
rlColor3f(0.75f, 0.75f, 0.75f);
} }
glEnd();
glPopMatrix(); rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing);
rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing);
//glDisable(GL_LINE_SMOOTH); rlVertex3f((float)-halfSlices*spacing, 0.0f, (float)i*spacing);
rlVertex3f((float)halfSlices*spacing, 0.0f, (float)i*spacing);
}
rlEnd();
} }
// Draw gizmo (with or without orbits) // Draw gizmo (with or without orbits)
@ -418,44 +454,47 @@ void DrawGizmo(Vector3 position, bool orbits)
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
glPushMatrix(); // GL_LINE_SMOOTH is very poorly supported on desktop GL.
glTranslatef(position.x, position.y, position.z); // A lot of drivers ignore it, so most people avoid using...
rlPushMatrix();
rlTranslatef(position.x, position.y, position.z);
//glRotatef(rotation, 0, 1, 0); //glRotatef(rotation, 0, 1, 0);
glScalef(lenght, lenght, lenght); rlScalef(lenght, lenght, lenght);
glBegin(GL_LINES); rlBegin(GL_LINES);
glColor3f(1.0f, 0.0f, 0.0f); rlColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(1.0f, 0.0f, 0.0f); rlVertex3f(1.0f, 0.0f, 0.0f);
glColor3f(0.0f, 1.0f, 0.0f); rlColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f); rlVertex3f(0.0f, 1.0f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f); rlColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 1.0f); rlVertex3f(0.0f, 0.0f, 1.0f);
glEnd(); rlEnd();
if (orbits) if (orbits)
{ {
glBegin(GL_LINE_LOOP); rlBegin(GL_LINE_LOOP);
glColor4f(1.0f, 0.0f, 0.0f, 0.4f); rlColor4f(1.0f, 0.0f, 0.0f, 0.4f);
for (int i=0; i < 360; i++) glVertex3f(sin(DEG2RAD*i) * radius, 0, cos(DEG2RAD*i) * radius); for (int i=0; i < 360; i++) rlVertex3f(sin(DEG2RAD*i) * radius, 0, cos(DEG2RAD*i) * radius);
glEnd(); rlEnd();
glBegin(GL_LINE_LOOP); rlBegin(GL_LINE_LOOP);
glColor4f(0.0f, 1.0f, 0.0f, 0.4f); rlColor4f(0.0f, 1.0f, 0.0f, 0.4f);
for (int i=0; i < 360; i++) glVertex3f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius, 0); for (int i=0; i < 360; i++) rlVertex3f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius, 0);
glEnd(); rlEnd();
glBegin(GL_LINE_LOOP); rlBegin(GL_LINE_LOOP);
glColor4f(0.0f, 0.0f, 1.0f, 0.4f); rlColor4f(0.0f, 0.0f, 1.0f, 0.4f);
for (int i=0; i < 360; i++) glVertex3f(0, sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius); for (int i=0; i < 360; i++) rlVertex3f(0, sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius);
glEnd(); rlEnd();
} }
glPopMatrix(); rlPopMatrix();
//glDisable(GL_LINE_SMOOTH); //glDisable(GL_LINE_SMOOTH);
} }
@ -464,7 +503,7 @@ void DrawGizmo(Vector3 position, bool orbits)
// TODO: Add comments explaining this function process // TODO: Add comments explaining this function process
Model LoadModel(const char *fileName) Model LoadModel(const char *fileName)
{ {
Model model; struct Model model;
char dataType; char dataType;
char comments[200]; char comments[200];
@ -664,6 +703,12 @@ Model LoadModel(const char *fileName)
fclose(objFile); fclose(objFile);
#ifdef USE_OPENGL_33
// TODO: Use loaded data to generate VAO
#endif
return model; return model;
} }
@ -750,6 +795,12 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
} }
} }
#ifdef USE_OPENGL_33
// TODO: Use loaded data to generate VAO
#endif
return model; return model;
} }
@ -767,6 +818,8 @@ void DrawModel(Model model, Vector3 position, float scale, Color color)
// NOTE: For models we use Vertex Arrays (OpenGL 1.1) // NOTE: For models we use Vertex Arrays (OpenGL 1.1)
//static int rotation = 0; //static int rotation = 0;
// NOTE: Add OpenGL 3.3+ VAOs-based drawing! --> Move this stuff to rlgl?
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array
glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array
@ -776,41 +829,60 @@ void DrawModel(Model model, Vector3 position, float scale, Color color)
glNormalPointer(GL_FLOAT, 0, model.normals); // Pointer to normals array glNormalPointer(GL_FLOAT, 0, model.normals); // Pointer to normals array
//glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED) //glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED)
glPushMatrix(); rlPushMatrix();
glTranslatef(position.x, position.y, position.z); rlTranslatef(position.x, position.y, position.z);
//glRotatef(rotation * GetFrameTime(), 0, 1, 0); //glRotatef(rotation * GetFrameTime(), 0, 1, 0);
glScalef(scale, scale, scale); rlScalef(scale, scale, scale);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glDrawArrays(GL_TRIANGLES, 0, model.numVertices); glDrawArrays(GL_TRIANGLES, 0, model.numVertices);
glPopMatrix(); rlPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array
glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array
glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array
//rotation += 10; //rotation += 10;
// Model drawing in OpenGL 3.3+, transform is passed to shader
/*
glUseProgram(shaderProgram); // Use our shader
Matrix modelview = MatrixMultiply(model.transform, view);
glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelview));
glUniform1i(textureLoc, 0);
glBindVertexArray(model.vaoId);
glBindTexture(GL_TEXTURE_2D, model.texId);
glDrawArrays(GL_TRIANGLES, 0, model.numVertices);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
glBindVertexArray(0); // Unbind VAO
*/
} }
// Draw a textured model // Draw a textured model
void DrawModelEx(Model model, Texture2D texture, Vector3 position, float scale, Color tint) void DrawModelEx(Model model, Texture2D texture, Vector3 position, float scale, Color tint)
{ {
glEnable(GL_TEXTURE_2D); rlEnableTexture(texture.glId);
glBindTexture(GL_TEXTURE_2D, texture.glId);
DrawModel(model, position, scale, tint); DrawModel(model, position, scale, tint);
glDisable(GL_TEXTURE_2D); rlDisableTexture();
} }
// Draw a model wires // Draw a model wires
void DrawModelWires(Model model, Vector3 position, float scale, Color color) void DrawModelWires(Model model, Vector3 position, float scale, Color color)
{ {
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // TODO: Draw model using RL_LINES... or look for a way to deal with polygon mode!
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
DrawModel(model, position, scale, color); DrawModel(model, position, scale, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
} }
// Draw a billboard // Draw a billboard
@ -842,20 +914,18 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size,
Vector3 c = VectorAdd(center, p2); Vector3 c = VectorAdd(center, p2);
Vector3 d = VectorSubtract(center, p1); Vector3 d = VectorSubtract(center, p1);
glEnable(GL_TEXTURE_2D); rlEnableTexture(texture.glId);
glBindTexture(GL_TEXTURE_2D, texture.glId); rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
rlNormal3f(0.0f, 1.0f, 0.0f);
rlTexCoord2f(0.0f, 0.0f); rlVertex3f(a.x, a.y, a.z);
rlTexCoord2f(1.0f, 0.0f); rlVertex3f(b.x, b.y, b.z);
rlTexCoord2f(1.0f, 1.0f); rlVertex3f(c.x, c.y, c.z);
rlTexCoord2f(0.0f, 1.0f); rlVertex3f(d.x, d.y, d.z);
rlEnd();
glBegin(GL_QUADS); rlDisableTexture();
glColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(a.x, a.y, a.z);
glTexCoord2f(1.0f, 0.0f); glVertex3f(b.x, b.y, b.z);
glTexCoord2f(1.0f, 1.0f); glVertex3f(c.x, c.y, c.z);
glTexCoord2f(0.0f, 1.0f); glVertex3f(d.x, d.y, d.z);
glEnd();
glDisable(GL_TEXTURE_2D);
} }
// Draw a billboard (part of a texture defined by a rectangle) // Draw a billboard (part of a texture defined by a rectangle)
@ -887,31 +957,29 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec
Vector3 c = VectorAdd(center, p2); Vector3 c = VectorAdd(center, p2);
Vector3 d = VectorSubtract(center, p1); Vector3 d = VectorSubtract(center, p1);
glEnable(GL_TEXTURE_2D); // Enable textures usage rlEnableTexture(texture.glId);
glBindTexture(GL_TEXTURE_2D, texture.glId); rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
glBegin(GL_QUADS);
glColor4ub(tint.r, tint.g, tint.b, tint.a);
// Bottom-left corner for texture and quad // Bottom-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
glVertex3f(a.x, a.y, a.z); rlVertex3f(a.x, a.y, a.z);
// Bottom-right corner for texture and quad // Bottom-right corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
glVertex3f(b.x, b.y, b.z); rlVertex3f(b.x, b.y, b.z);
// Top-right corner for texture and quad // Top-right corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex3f(c.x, c.y, c.z); rlVertex3f(c.x, c.y, c.z);
// Top-left corner for texture and quad // Top-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex3f(d.x, d.y, d.z); rlVertex3f(d.x, d.y, d.z);
glEnd(); rlEnd();
glDisable(GL_TEXTURE_2D); // Disable textures usage rlDisableTexture();
} }
// Get current vertex y altitude (proportional to pixel colors in grayscale) // Get current vertex y altitude (proportional to pixel colors in grayscale)
@ -919,60 +987,3 @@ static float GetHeightValue(Color pixel)
{ {
return (((float)pixel.r + (float)pixel.g + (float)pixel.b)/3); return (((float)pixel.r + (float)pixel.g + (float)pixel.b)/3);
} }
// Returns camera look-at matrix (view matrix)
static Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
{
Matrix result;
Vector3 z = VectorSubtract(eye, target);
VectorNormalize(&z);
Vector3 x = VectorCrossProduct(up, z);
VectorNormalize(&x);
Vector3 y = VectorCrossProduct(z, x);
VectorNormalize(&y);
result.m0 = x.x;
result.m1 = x.y;
result.m2 = x.z;
result.m3 = -((x.x * eye.x) + (x.y * eye.y) + (x.z * eye.z));
result.m4 = y.x;
result.m5 = y.y;
result.m6 = y.z;
result.m7 = -((y.x * eye.x) + (y.y * eye.y) + (y.z * eye.z));
result.m8 = z.x;
result.m9 = z.y;
result.m10 = z.z;
result.m11 = -((z.x * eye.x) + (z.y * eye.y) + (z.z * eye.z));
result.m12 = 0;
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
return result;
}
// Transposes provided matrix
static void MatrixTranspose(Matrix *mat)
{
Matrix temp;
temp.m0 = mat->m0;
temp.m1 = mat->m4;
temp.m2 = mat->m8;
temp.m3 = mat->m12;
temp.m4 = mat->m1;
temp.m5 = mat->m5;
temp.m6 = mat->m9;
temp.m7 = mat->m13;
temp.m8 = mat->m2;
temp.m9 = mat->m6;
temp.m10 = mat->m10;
temp.m11 = mat->m14;
temp.m12 = mat->m3;
temp.m13 = mat->m7;
temp.m14 = mat->m11;
temp.m15 = mat->m15;
*mat = temp;
}

View file

@ -1,15 +1,17 @@
/********************************************************************************************* /*********************************************************************************************
* *
* raylib 1.0.6 (www.raylib.com) * raylib 1.1 (www.raylib.com)
* *
* A simple and easy-to-use library to learn videogames programming * A simple and easy-to-use library to learn videogames programming
* *
* Features: * Features:
* Library written in plain C code (C99) * Library written in plain C code (C99)
* Uses C# PascalCase/camelCase notation * Uses C# PascalCase/camelCase notation
* Hardware accelerated with OpenGL 1.1 * Hardware accelerated with OpenGL (1.1, 3.3+ or ES2)
* Unique OpenGL abstraction layer [rlgl]
* Powerful fonts module with SpriteFonts support * Powerful fonts module with SpriteFonts support
* Basic 3d support for Shapes and Models * Basic 3d support for Shapes, Models, Heightmaps and Billboards
* Powerful math module for Vector and Matrix operations [raymath]
* Audio loading and playing * Audio loading and playing
* *
* Used external libs: * Used external libs:
@ -23,8 +25,9 @@
* 32bit Textures - All loaded images are converted automatically to RGBA textures * 32bit Textures - All loaded images are converted automatically to RGBA textures
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures * SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
* One custom default font is loaded automatically when InitWindow() * One custom default font is loaded automatically when InitWindow()
* If using OpenGL 3.3+, one default shader is loaded automatically (internally defined)
* *
* -- LICENSE (raylib v1.0, November 2013) -- * -- LICENSE (raylib v1.1, March 2014) --
* *
* raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * 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: * BSD-like license that allows static linking with closed source software:
@ -213,12 +216,7 @@ typedef struct Camera {
} Camera; } Camera;
// Basic 3d Model type // Basic 3d Model type
typedef struct Model { typedef struct Model Model;
int numVertices;
Vector3 *vertices;
Vector2 *texcoords;
Vector3 *normals;
} Model;
// Basic Sound source and buffer // Basic Sound source and buffer
typedef struct Sound { typedef struct Sound {

View file

@ -199,6 +199,28 @@ Vector3 VectorReflect(Vector3 vector, Vector3 normal)
return result; return result;
} }
// Transforms a Vector3 with a given Matrix
void VectorTransform(Vector3 *v, Matrix mat)
{
float x = v->x;
float y = v->y;
float z = v->z;
//MatrixTranspose(&mat);
v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12;
v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13;
v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14;
};
// Return a Vector3 init to zero
Vector3 VectorZero()
{
Vector3 zero = { 0.0, 0.0, 0.0 };
return zero;
}
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Functions Definition - Matrix math // Module Functions Definition - Matrix math
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -234,17 +256,17 @@ float MatrixDeterminant(Matrix mat)
float result; float result;
// Cache the matrix values (speed optimization) // Cache the matrix values (speed optimization)
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15;
result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 + result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 +
a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 + a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 +
a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 + a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 +
a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 + a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 +
a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 + a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 +
a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33; a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33;
return result; return result;
} }
@ -261,21 +283,21 @@ void MatrixTranspose(Matrix *mat)
Matrix temp; Matrix temp;
temp.m0 = mat->m0; temp.m0 = mat->m0;
temp.m1 = mat->m4; temp.m1 = mat->m4;
temp.m2 = mat->m8; temp.m2 = mat->m8;
temp.m3 = mat->m12; temp.m3 = mat->m12;
temp.m4 = mat->m1; temp.m4 = mat->m1;
temp.m5 = mat->m5; temp.m5 = mat->m5;
temp.m6 = mat->m9; temp.m6 = mat->m9;
temp.m7 = mat->m13; temp.m7 = mat->m13;
temp.m8 = mat->m2; temp.m8 = mat->m2;
temp.m9 = mat->m6; temp.m9 = mat->m6;
temp.m10 = mat->m10; temp.m10 = mat->m10;
temp.m11 = mat->m14; temp.m11 = mat->m14;
temp.m12 = mat->m3; temp.m12 = mat->m3;
temp.m13 = mat->m7; temp.m13 = mat->m7;
temp.m14 = mat->m11; temp.m14 = mat->m11;
temp.m15 = mat->m15; temp.m15 = mat->m15;
*mat = temp; *mat = temp;
} }
@ -285,50 +307,50 @@ void MatrixInvert(Matrix *mat)
{ {
Matrix temp; Matrix temp;
// Cache the matrix values (speed optimization) // Cache the matrix values (speed optimization)
float a00 = mat->m0, a01 = mat->m1, a02 = mat->m2, a03 = mat->m3; float a00 = mat->m0, a01 = mat->m1, a02 = mat->m2, a03 = mat->m3;
float a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7; float a10 = mat->m4, a11 = mat->m5, a12 = mat->m6, a13 = mat->m7;
float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11; float a20 = mat->m8, a21 = mat->m9, a22 = mat->m10, a23 = mat->m11;
float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15; float a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15;
float b00 = a00*a11 - a01*a10; float b00 = a00*a11 - a01*a10;
float b01 = a00*a12 - a02*a10; float b01 = a00*a12 - a02*a10;
float b02 = a00*a13 - a03*a10; float b02 = a00*a13 - a03*a10;
float b03 = a01*a12 - a02*a11; float b03 = a01*a12 - a02*a11;
float b04 = a01*a13 - a03*a11; float b04 = a01*a13 - a03*a11;
float b05 = a02*a13 - a03*a12; float b05 = a02*a13 - a03*a12;
float b06 = a20*a31 - a21*a30; float b06 = a20*a31 - a21*a30;
float b07 = a20*a32 - a22*a30; float b07 = a20*a32 - a22*a30;
float b08 = a20*a33 - a23*a30; float b08 = a20*a33 - a23*a30;
float b09 = a21*a32 - a22*a31; float b09 = a21*a32 - a22*a31;
float b10 = a21*a33 - a23*a31; float b10 = a21*a33 - a23*a31;
float b11 = a22*a33 - a23*a32; float b11 = a22*a33 - a23*a32;
// Calculate the invert determinant (inlined to avoid double-caching) // Calculate the invert determinant (inlined to avoid double-caching)
float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
printf("%f\n", invDet); printf("%f\n", invDet);
temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet;
temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet;
temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet;
temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet;
temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet;
temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet;
temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet;
temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet;
temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet;
temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet;
temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet;
temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet;
temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet;
temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet;
PrintMatrix(temp); PrintMatrix(temp);
*mat = temp; *mat = temp;
} }
// Normalize provided matrix // Normalize provided matrix
@ -337,21 +359,21 @@ void MatrixNormalize(Matrix *mat)
float det = MatrixDeterminant(*mat); float det = MatrixDeterminant(*mat);
mat->m0 /= det; mat->m0 /= det;
mat->m1 /= det; mat->m1 /= det;
mat->m2 /= det; mat->m2 /= det;
mat->m3 /= det; mat->m3 /= det;
mat->m4 /= det; mat->m4 /= det;
mat->m5 /= det; mat->m5 /= det;
mat->m6 /= det; mat->m6 /= det;
mat->m7 /= det; mat->m7 /= det;
mat->m8 /= det; mat->m8 /= det;
mat->m9 /= det; mat->m9 /= det;
mat->m10 /= det; mat->m10 /= det;
mat->m11 /= det; mat->m11 /= det;
mat->m12 /= det; mat->m12 /= det;
mat->m13 /= det; mat->m13 /= det;
mat->m14 /= det; mat->m14 /= det;
mat->m15 /= det; mat->m15 /= det;
} }
// Returns identity matrix // Returns identity matrix
@ -368,21 +390,21 @@ Matrix MatrixAdd(Matrix left, Matrix right)
Matrix result = MatrixIdentity(); Matrix result = MatrixIdentity();
result.m0 = left.m0 + right.m0; result.m0 = left.m0 + right.m0;
result.m1 = left.m1 + right.m1; result.m1 = left.m1 + right.m1;
result.m2 = left.m2 + right.m2; result.m2 = left.m2 + right.m2;
result.m3 = left.m3 + right.m3; result.m3 = left.m3 + right.m3;
result.m4 = left.m4 + right.m4; result.m4 = left.m4 + right.m4;
result.m5 = left.m5 + right.m5; result.m5 = left.m5 + right.m5;
result.m6 = left.m6 + right.m6; result.m6 = left.m6 + right.m6;
result.m7 = left.m7 + right.m7; result.m7 = left.m7 + right.m7;
result.m8 = left.m8 + right.m8; result.m8 = left.m8 + right.m8;
result.m9 = left.m9 + right.m9; result.m9 = left.m9 + right.m9;
result.m10 = left.m10 + right.m10; result.m10 = left.m10 + right.m10;
result.m11 = left.m11 + right.m11; result.m11 = left.m11 + right.m11;
result.m12 = left.m12 + right.m12; result.m12 = left.m12 + right.m12;
result.m13 = left.m13 + right.m13; result.m13 = left.m13 + right.m13;
result.m14 = left.m14 + right.m14; result.m14 = left.m14 + right.m14;
result.m15 = left.m15 + right.m15; result.m15 = left.m15 + right.m15;
return result; return result;
} }
@ -393,21 +415,21 @@ Matrix MatrixSubstract(Matrix left, Matrix right)
Matrix result = MatrixIdentity(); Matrix result = MatrixIdentity();
result.m0 = left.m0 - right.m0; result.m0 = left.m0 - right.m0;
result.m1 = left.m1 - right.m1; result.m1 = left.m1 - right.m1;
result.m2 = left.m2 - right.m2; result.m2 = left.m2 - right.m2;
result.m3 = left.m3 - right.m3; result.m3 = left.m3 - right.m3;
result.m4 = left.m4 - right.m4; result.m4 = left.m4 - right.m4;
result.m5 = left.m5 - right.m5; result.m5 = left.m5 - right.m5;
result.m6 = left.m6 - right.m6; result.m6 = left.m6 - right.m6;
result.m7 = left.m7 - right.m7; result.m7 = left.m7 - right.m7;
result.m8 = left.m8 - right.m8; result.m8 = left.m8 - right.m8;
result.m9 = left.m9 - right.m9; result.m9 = left.m9 - right.m9;
result.m10 = left.m10 - right.m10; result.m10 = left.m10 - right.m10;
result.m11 = left.m11 - right.m11; result.m11 = left.m11 - right.m11;
result.m12 = left.m12 - right.m12; result.m12 = left.m12 - right.m12;
result.m13 = left.m13 - right.m13; result.m13 = left.m13 - right.m13;
result.m14 = left.m14 - right.m14; result.m14 = left.m14 - right.m14;
result.m15 = left.m15 - right.m15; result.m15 = left.m15 - right.m15;
return result; return result;
} }
@ -476,51 +498,51 @@ Matrix MatrixFromAxisAngle(Vector3 axis, float angle)
Matrix mat = MatrixIdentity(); Matrix mat = MatrixIdentity();
float x = axis.x, y = axis.y, z = axis.z; float x = axis.x, y = axis.y, z = axis.z;
float length = sqrt(x*x + y*y + z*z); float length = sqrt(x*x + y*y + z*z);
if ((length != 1) && (length != 0)) if ((length != 1) && (length != 0))
{ {
length = 1 / length; length = 1 / length;
x *= length; x *= length;
y *= length; y *= length;
z *= length; z *= length;
} }
float s = sin(angle); float s = sin(angle);
float c = cos(angle); float c = cos(angle);
float t = 1-c; float t = 1-c;
// Cache some matrix values (speed optimization) // Cache some matrix values (speed optimization)
float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3;
float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7;
float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11;
// Construct the elements of the rotation matrix // Construct the elements of the rotation matrix
float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s; float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s;
float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s; float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s;
float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c; float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c;
// Perform rotation-specific matrix multiplication // Perform rotation-specific matrix multiplication
result.m0 = a00*b00 + a10*b01 + a20*b02; result.m0 = a00*b00 + a10*b01 + a20*b02;
result.m1 = a01*b00 + a11*b01 + a21*b02; result.m1 = a01*b00 + a11*b01 + a21*b02;
result.m2 = a02*b00 + a12*b01 + a22*b02; result.m2 = a02*b00 + a12*b01 + a22*b02;
result.m3 = a03*b00 + a13*b01 + a23*b02; result.m3 = a03*b00 + a13*b01 + a23*b02;
result.m4 = a00*b10 + a10*b11 + a20*b12; result.m4 = a00*b10 + a10*b11 + a20*b12;
result.m5 = a01*b10 + a11*b11 + a21*b12; result.m5 = a01*b10 + a11*b11 + a21*b12;
result.m6 = a02*b10 + a12*b11 + a22*b12; result.m6 = a02*b10 + a12*b11 + a22*b12;
result.m7 = a03*b10 + a13*b11 + a23*b12; result.m7 = a03*b10 + a13*b11 + a23*b12;
result.m8 = a00*b20 + a10*b21 + a20*b22; result.m8 = a00*b20 + a10*b21 + a20*b22;
result.m9 = a01*b20 + a11*b21 + a21*b22; result.m9 = a01*b20 + a11*b21 + a21*b22;
result.m10 = a02*b20 + a12*b21 + a22*b22; result.m10 = a02*b20 + a12*b21 + a22*b22;
result.m11 = a03*b20 + a13*b21 + a23*b22; result.m11 = a03*b20 + a13*b21 + a23*b22;
result.m12 = mat.m12; result.m12 = mat.m12;
result.m13 = mat.m13; result.m13 = mat.m13;
result.m14 = mat.m14; result.m14 = mat.m14;
result.m15 = mat.m15; result.m15 = mat.m15;
return result; return result;
}; };
// Create rotation matrix from axis and angle // Create rotation matrix from axis and angle
@ -645,35 +667,35 @@ Matrix MatrixMultiply(Matrix left, Matrix right)
{ {
Matrix result; Matrix result;
// Cache the matrix values (speed optimization) // Cache the matrix values (speed optimization)
float a00 = left.m0, a01 = left.m1, a02 = left.m2, a03 = left.m3; float a00 = left.m0, a01 = left.m1, a02 = left.m2, a03 = left.m3;
float a10 = left.m4, a11 = left.m5, a12 = left.m6, a13 = left.m7; float a10 = left.m4, a11 = left.m5, a12 = left.m6, a13 = left.m7;
float a20 = left.m8, a21 = left.m9, a22 = left.m10, a23 = left.m11; float a20 = left.m8, a21 = left.m9, a22 = left.m10, a23 = left.m11;
float a30 = left.m12, a31 = left.m13, a32 = left.m14, a33 = left.m15; float a30 = left.m12, a31 = left.m13, a32 = left.m14, a33 = left.m15;
float b00 = right.m0, b01 = right.m1, b02 = right.m2, b03 = right.m3; float b00 = right.m0, b01 = right.m1, b02 = right.m2, b03 = right.m3;
float b10 = right.m4, b11 = right.m5, b12 = right.m6, b13 = right.m7; float b10 = right.m4, b11 = right.m5, b12 = right.m6, b13 = right.m7;
float b20 = right.m8, b21 = right.m9, b22 = right.m10, b23 = right.m11; float b20 = right.m8, b21 = right.m9, b22 = right.m10, b23 = right.m11;
float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15; float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15;
result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30; result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30;
result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31; result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31;
result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32; result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32;
result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33; result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33;
result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30; result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30;
result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31; result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31;
result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32; result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32;
result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33; result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33;
result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30; result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30;
result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31; result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31;
result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32; result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32;
result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33; result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33;
result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30; result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30;
result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31; result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31;
result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32; result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32;
result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33; result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33;
return result; return result;
} }
// Returns perspective projection matrix // Returns perspective projection matrix
@ -681,28 +703,28 @@ Matrix MatrixFrustum(double left, double right, double bottom, double top, doubl
{ {
Matrix result; Matrix result;
float rl = (right - left); float rl = (right - left);
float tb = (top - bottom); float tb = (top - bottom);
float fn = (far - near); float fn = (far - near);
result.m0 = (near*2) / rl; result.m0 = (near*2) / rl;
result.m1 = 0; result.m1 = 0;
result.m2 = 0; result.m2 = 0;
result.m3 = 0; result.m3 = 0;
result.m4 = 0; result.m4 = 0;
result.m5 = (near*2) / tb; result.m5 = (near*2) / tb;
result.m6 = 0; result.m6 = 0;
result.m7 = 0; result.m7 = 0;
result.m8 = (right + left) / rl; result.m8 = (right + left) / rl;
result.m9 = (top + bottom) / tb; result.m9 = (top + bottom) / tb;
result.m10 = -(far + near) / fn; result.m10 = -(far + near) / fn;
result.m11 = -1; result.m11 = -1;
result.m12 = 0; result.m12 = 0;
result.m13 = 0; result.m13 = 0;
result.m14 = -(far*near*2) / fn; result.m14 = -(far*near*2) / fn;
result.m15 = 0; result.m15 = 0;
return result; return result;
} }
// Returns perspective projection matrix // Returns perspective projection matrix
@ -720,25 +742,25 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double
Matrix result; Matrix result;
float rl = (right - left); float rl = (right - left);
float tb = (top - bottom); float tb = (top - bottom);
float fn = (far - near); float fn = (far - near);
result.m0 = 2 / rl; result.m0 = 2 / rl;
result.m1 = 0; result.m1 = 0;
result.m2 = 0; result.m2 = 0;
result.m3 = 0; result.m3 = 0;
result.m4 = 0; result.m4 = 0;
result.m5 = 2 / tb; result.m5 = 2 / tb;
result.m6 = 0; result.m6 = 0;
result.m7 = 0; result.m7 = 0;
result.m8 = 0; result.m8 = 0;
result.m9 = 0; result.m9 = 0;
result.m10 = -2 / fn; result.m10 = -2 / fn;
result.m11 = 0; result.m11 = 0;
result.m12 = -(left + right) / rl; result.m12 = -(left + right) / rl;
result.m13 = -(top + bottom) / tb; result.m13 = -(top + bottom) / tb;
result.m14 = -(far + near) / fn; result.m14 = -(far + near) / fn;
result.m15 = 1; result.m15 = 1;
return result; return result;
} }
@ -793,7 +815,7 @@ void PrintMatrix(Matrix m)
// Calculates the length of a quaternion // Calculates the length of a quaternion
float QuaternionLength(Quaternion quat) float QuaternionLength(Quaternion quat)
{ {
return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w); return sqrt(quat.x*quat.x + quat.y*quat.y + quat.z*quat.z + quat.w*quat.w);
} }
// Normalize provided quaternion // Normalize provided quaternion
@ -818,15 +840,15 @@ Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2)
{ {
Quaternion result; Quaternion result;
float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w; float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w;
float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w; float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w;
result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby; result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby;
result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz; result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz;
result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx; result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx;
result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz; result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz;
return result; return result;
} }
// Calculates spherical linear interpolation between two quaternions // Calculates spherical linear interpolation between two quaternions
@ -834,9 +856,9 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
{ {
Quaternion result; Quaternion result;
float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w;
if (abs(cosHalfTheta) >= 1.0) result = q1; if (abs(cosHalfTheta) >= 1.0) result = q1;
else else
{ {
float halfTheta = acos(cosHalfTheta); float halfTheta = acos(cosHalfTheta);
@ -859,9 +881,9 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
result.z = (q1.z*ratioA + q2.z*ratioB); result.z = (q1.z*ratioA + q2.z*ratioB);
result.w = (q1.w*ratioA + q2.w*ratioB); result.w = (q1.w*ratioA + q2.w*ratioB);
} }
} }
return result; return result;
} }
// Returns a quaternion from a given rotation matrix // Returns a quaternion from a given rotation matrix
@ -947,42 +969,42 @@ Matrix QuaternionToMatrix(Quaternion q)
{ {
Matrix result; Matrix result;
float x = q.x, y = q.y, z = q.z, w = q.w; float x = q.x, y = q.y, z = q.z, w = q.w;
float x2 = x + x; float x2 = x + x;
float y2 = y + y; float y2 = y + y;
float z2 = z + z; float z2 = z + z;
float xx = x*x2; float xx = x*x2;
float xy = x*y2; float xy = x*y2;
float xz = x*z2; float xz = x*z2;
float yy = y*y2; float yy = y*y2;
float yz = y*z2; float yz = y*z2;
float zz = z*z2; float zz = z*z2;
float wx = w*x2; float wx = w*x2;
float wy = w*y2; float wy = w*y2;
float wz = w*z2; float wz = w*z2;
result.m0 = 1 - (yy + zz); result.m0 = 1 - (yy + zz);
result.m1 = xy - wz; result.m1 = xy - wz;
result.m2 = xz + wy; result.m2 = xz + wy;
result.m3 = 0; result.m3 = 0;
result.m4 = xy + wz; result.m4 = xy + wz;
result.m5 = 1 - (xx + zz); result.m5 = 1 - (xx + zz);
result.m6 = yz - wx; result.m6 = yz - wx;
result.m7 = 0; result.m7 = 0;
result.m8 = xz - wy; result.m8 = xz - wy;
result.m9 = yz + wx; result.m9 = yz + wx;
result.m10 = 1 - (xx + yy); result.m10 = 1 - (xx + yy);
result.m11 = 0; result.m11 = 0;
result.m12 = 0; result.m12 = 0;
result.m13 = 0; result.m13 = 0;
result.m14 = 0; result.m14 = 0;
result.m15 = 1; result.m15 = 1;
return result; return result;
} }
// Returns the axis and the angle for a given quaternion // Returns the axis and the angle for a given quaternion

View file

@ -91,6 +91,8 @@ void VectorNormalize(Vector3 *v); // Normalize provided ve
float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points
Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal
void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 with a given Matrix
Vector3 VectorZero(); // Return a Vector3 init to zero
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Functions Declaration to work with Matrix // Functions Declaration to work with Matrix

1364
src/rlgl.c Normal file

File diff suppressed because it is too large Load diff

117
src/rlgl.h Normal file
View file

@ -0,0 +1,117 @@
/*********************************************************************************************
*
* rlgl - raylib OpenGL abstraction layer
*
* raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version:
* OpenGL 1.1 - Direct map rl* -> gl*
* OpenGL 3.3+ - Vertex data is stored in VAOs, call rlglDraw() to render
* OpenGL ES 2 - Same behaviour as OpenGL 3.3+ (NOT TESTED)
*
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef RLGL_H
#define RLGL_H
// Select desired OpenGL version
//#define USE_OPENGL_11
#define USE_OPENGL_33
//#define USE_OPENGL_ES2
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define MAX_LINES_BATCH 1024
#define MAX_TRIANGLES_BATCH 2048
#define MAX_QUADS_BATCH 8192
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef unsigned char byte;
typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode;
typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//------------------------------------------------------------------------------------
// Functions Declaration - Matrix operations
//------------------------------------------------------------------------------------
void rlMatrixMode(int mode); // Choose the current matrix to be transformed
void rlPushMatrix(); // TODO: REVIEW: Required? - Push the current matrix to stack
void rlPopMatrix(); // TODO: REVIEW: Required? - Pop lattest inserted matrix from stack
void rlLoadIdentity(); // Reset current matrix to identity matrix
void rlTranslatef(float x, float y, float z); // Multiply the current matrix by a translation matrix
void rlRotatef(float angleDeg, float x, float y, float z); // Multiply the current matrix by a rotation matrix
void rlScalef(float x, float y, float z); // Multiply the current matrix by a scaling matrix
void rlMultMatrixf(float *mat); // Multiply the current matrix by another matrix
void rlFrustum(double left, double right, double bottom, double top, double near, double far);
void rlOrtho(double left, double right, double bottom, double top, double near, double far);
//------------------------------------------------------------------------------------
// Functions Declaration - Vertex level operations
//------------------------------------------------------------------------------------
void rlBegin(int mode); // Initialize drawing mode (how to organize vertex)
void rlEnd(); // Finish vertex providing
void rlVertex2i(int x, int y); // Define one vertex (position) - 2 int
void rlVertex2f(float x, float y); // Define one vertex (position) - 2 float
void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float
void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float
void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float
void rlColor4ub(byte r, byte g, byte b, byte a); // Define one vertex (color) - 4 byte
void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float
void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
//------------------------------------------------------------------------------------
// Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2)
// NOTE: This functions are used to completely abstract raylib code from OpenGL layer
//------------------------------------------------------------------------------------
void rlEnableTexture(unsigned int id); // Enable texture usage
void rlDisableTexture(); // Disable texture usage
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture
void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
void rlClearScreenBuffers(); // Clear used screen buffers (color and depth)
//------------------------------------------------------------------------------------
// Functions Declaration - rlgl functionality
//------------------------------------------------------------------------------------
#ifdef USE_OPENGL_33
void rlglInit(); // Initialize rlgl (shaders, VAO, VBO...)
void rlglClose(); // De-init rlgl
void rlglDraw(); // Draw VAOs
#endif
void rlglInitGraphicsDevice(int fbWidth, int fbHeight); // Initialize Graphics Device (OpenGL stuff)
unsigned int rlglTexture(int width, int height, unsigned char *pixels); // Create OpenGL texture
byte *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
#ifdef USE_OPENGL_33
void PrintProjectionMatrix(); // DEBUG: Print projection matrix
void PrintModelviewMatrix(); // DEBUG: Print modelview matrix
#endif
#ifdef __cplusplus
}
#endif
#endif // RLGL_H

View file

@ -25,11 +25,12 @@
#include "raylib.h" #include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <stdlib.h> // Required for abs() function #include <stdlib.h> // Required for abs() function
#include <math.h> // Math related functions, sin() and cos() used on DrawCircle* #include <math.h> // Math related functions, sin() and cos() used on DrawCircle*
// sqrt() and pow() and abs() used on CheckCollision* // sqrt() and pow() and abs() used on CheckCollision*
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -57,149 +58,116 @@
// Draw a pixel // Draw a pixel
void DrawPixel(int posX, int posY, Color color) void DrawPixel(int posX, int posY, Color color)
{ {
glBegin(GL_POINTS); rlBegin(RL_LINES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(posX, posY); rlVertex2i(posX, posY);
glEnd(); rlVertex2i(posX + 1, posY + 1);
rlEnd();
// NOTE1: Alternative method to draw a pixel (GL_LINES)
/*
glBegin(GL_LINES);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(posX, posY);
glVertex2i(posX+1, posY+1);
glEnd();
*/
// NOTE2: Alternative method to draw a pixel (glPoint())
/*
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
glPointSize(1.0f);
glPoint((float)posX, (float)posY, 0.0f);
*/
} }
// Draw a pixel (Vector version) // Draw a pixel (Vector version)
void DrawPixelV(Vector2 position, Color color) void DrawPixelV(Vector2 position, Color color)
{ {
glBegin(GL_POINTS); rlBegin(RL_LINES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(position.x, position.y); rlVertex2f(position.x, position.y);
glEnd(); rlVertex2i(position.x + 1, position.y + 1);
rlEnd();
} }
// Draw a line // Draw a line
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color) void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
{ {
glBegin(GL_LINES); rlBegin(RL_LINES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(startPosX, startPosY); rlVertex2i(startPosX, startPosY);
glVertex2i(endPosX, endPosY); rlVertex2i(endPosX, endPosY);
glEnd(); rlEnd();
} }
// Draw a line (Vector version) // Draw a line (Vector version)
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color) void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
{ {
glBegin(GL_LINES); rlBegin(RL_LINES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(startPos.x, startPos.y); rlVertex2f(startPos.x, startPos.y);
glVertex2f(endPos.x, endPos.y); rlVertex2f(endPos.x, endPos.y);
glEnd(); rlEnd();
} }
// Draw a color-filled circle // Draw a color-filled circle
// TODO: Review, on some GPUs is drawn with a weird transparency (GL_POLYGON_SMOOTH issue?) // TODO: Review, on some GPUs is drawn with a weird transparency (GL_POLYGON_SMOOTH issue?)
void DrawCircle(int centerX, int centerY, float radius, Color color) void DrawCircle(int centerX, int centerY, float radius, Color color)
{ {
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color); DrawPoly((Vector2){centerX, centerY}, 360, radius, 0, color);
glDisable(GL_POLYGON_SMOOTH);
// NOTE: Alternative method to draw a circle (point)
/*
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0
glPointSize(radius);
glPoint((float)centerX, (float)centerY, 0.0f);
*/
} }
// Draw a gradient-filled circle // Draw a gradient-filled circle
// NOTE: Gradient goes from center (color1) to border (color2) // NOTE: Gradient goes from center (color1) to border (color2)
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2) void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
{ {
glBegin(GL_TRIANGLE_FAN); rlBegin(RL_TRIANGLES);
glColor4ub(color1.r, color1.g, color1.b, color1.a); for (int i=0; i <= 360; i += 2) //i++ --> Step = 1.0 pixels
glVertex2i(centerX, centerY);
glColor4ub(color2.r, color2.g, color2.b, color2.a);
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
{ {
glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius); rlColor4ub(color1.r, color1.g, color1.b, color1.a);
rlVertex2i(centerX, centerY);
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
rlVertex2f(centerX + sin(DEG2RAD*(i+1)) * radius, centerY + cos(DEG2RAD*(i+1)) * radius);
} }
glEnd(); rlEnd();
} }
// Draw a color-filled circle (Vector version) // Draw a color-filled circle (Vector version)
void DrawCircleV(Vector2 center, float radius, Color color) void DrawCircleV(Vector2 center, float radius, Color color)
{ {
glEnable(GL_POLYGON_SMOOTH); rlBegin(RL_TRIANGLES);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); for (int i=0; i < 360; i += 2)
glBegin(GL_TRIANGLE_FAN);
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(center.x, center.y);
for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels
{ {
glVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(center.x, center.y);
rlVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius);
rlVertex2f(center.x + sin(DEG2RAD*(i+1)) * radius, center.y + cos(DEG2RAD*(i+1)) * radius);
} }
glEnd(); rlEnd();
glDisable(GL_POLYGON_SMOOTH);
} }
// Draw circle outline // Draw circle outline
void DrawCircleLines(int centerX, int centerY, float radius, Color color) void DrawCircleLines(int centerX, int centerY, float radius, Color color)
{ {
glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied)
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm)
glBegin(GL_LINE_LOOP); rlBegin(RL_LINES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360) // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
for (int i=0; i < 360; i++) for (int i=0; i < 360; i++)
{ {
glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius); rlVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius);
rlVertex2f(centerX + sin(DEG2RAD*(i+1)) * radius, centerY + cos(DEG2RAD*(i+1)) * radius);
} }
glEnd(); rlEnd();
// NOTE: Alternative method to draw circle outline //glDisable(GL_LINE_SMOOTH);
/*
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // TODO: Draw all lines with line smooth??? --> Do it before drawing lines VAO
DrawCircle(centerX, centerY, radius, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
*/
glDisable(GL_LINE_SMOOTH);
} }
// Draw a color-filled rectangle // Draw a color-filled rectangle
void DrawRectangle(int posX, int posY, int width, int height, Color color) void DrawRectangle(int posX, int posY, int width, int height, Color color)
{ {
glBegin(GL_QUADS); rlBegin(RL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(posX, posY); rlTexCoord2f(0.0f, 0.0f);
glVertex2i(posX + width, posY); rlVertex2i(posX, posY);
glVertex2i(posX + width, posY + height); rlTexCoord2f(0.0f, 1.0f);
glVertex2i(posX, posY + height); rlVertex2i(posX, posY + height);
glEnd(); rlTexCoord2f(1.0f, 1.0f);
rlVertex2i(posX + width, posY + height);
rlTexCoord2f(1.0f, 0.0f);
rlVertex2i(posX + width, posY);
rlEnd();
} }
// Draw a color-filled rectangle // Draw a color-filled rectangle
@ -212,73 +180,73 @@ void DrawRectangleRec(Rectangle rec, Color color)
// NOTE: Gradient goes from bottom (color1) to top (color2) // NOTE: Gradient goes from bottom (color1) to top (color2)
void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2) void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2)
{ {
glBegin(GL_QUADS); rlBegin(RL_QUADS);
glColor4ub(color1.r, color1.g, color1.b, color1.a); rlColor4ub(color1.r, color1.g, color1.b, color1.a);
glVertex2i(posX, posY); rlVertex2i(posX, posY);
glVertex2i(posX + width, posY); rlColor4ub(color1.r, color1.g, color1.b, color1.a);
glColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2i(posX, posY + height);
glVertex2i(posX + width, posY + height); rlColor4ub(color2.r, color2.g, color2.b, color2.a);
glVertex2i(posX, posY + height); rlVertex2i(posX + width, posY + height);
glEnd(); rlColor4ub(color2.r, color2.g, color2.b, color2.a);
rlVertex2i(posX + width, posY);
rlEnd();
} }
// Draw a color-filled rectangle (Vector version) // Draw a color-filled rectangle (Vector version)
void DrawRectangleV(Vector2 position, Vector2 size, Color color) void DrawRectangleV(Vector2 position, Vector2 size, Color color)
{ {
glBegin(GL_QUADS); rlBegin(RL_QUADS);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2i(position.x, position.y); rlVertex2i(position.x, position.y);
glVertex2i(position.x + size.x, position.y); rlVertex2i(position.x, position.y + size.y);
glVertex2i(position.x + size.x, position.y + size.y); rlVertex2i(position.x + size.x, position.y + size.y);
glVertex2i(position.x, position.y + size.y); rlVertex2i(position.x + size.x, position.y);
glEnd(); rlEnd();
} }
// Draw rectangle outline // Draw rectangle outline
void DrawRectangleLines(int posX, int posY, int width, int height, Color color) void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
{ {
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) rlBegin(RL_LINES);
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(posX, posY);
rlVertex2i(posX + width - 1, posY);
// NOTE: Lines are rasterized using the "Diamond Exit" rule so, it's nearly impossible to obtain a pixel-perfect engine rlVertex2i(posX + width - 1, posY);
// NOTE: Recommended trying to avoid using lines, at least >1.0f pixel lines with anti-aliasing (glLineWidth function) rlVertex2i(posX + width - 1, posY + height - 1);
glBegin(GL_LINE_LOOP); rlVertex2i(posX + width - 1, posY + height - 1);
glColor4ub(color.r, color.g, color.b, color.a); rlVertex2i(posX, posY + height - 1);
glVertex2i(posX, posY);
glVertex2i(posX + width - 1, posY);
glVertex2i(posX + width - 1, posY + height - 1);
glVertex2i(posX, posY + height - 1);
glEnd();
// NOTE: Alternative method to draw rectangle outline rlVertex2i(posX, posY + height - 1);
/* rlVertex2i(posX, posY);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); rlEnd();
DrawRectangle(posX, posY, width - 1, height - 1, color);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
*/
//glDisable(GL_LINE_SMOOTH);
} }
// Draw a triangle // Draw a triangle
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
{ {
glBegin(GL_TRIANGLES); rlBegin(RL_TRIANGLES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(v1.x, v1.y); rlVertex2f(v1.x, v1.y);
glVertex2f(v2.x, v2.y); rlVertex2f(v2.x, v2.y);
glVertex2f(v3.x, v3.y); rlVertex2f(v3.x, v3.y);
glEnd(); rlEnd();
} }
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
{ {
glBegin(GL_LINE_LOOP); rlBegin(RL_LINES);
glColor4ub(color.r, color.g, color.b, color.a); rlColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(v1.x, v1.y); rlVertex2f(v1.x, v1.y);
glVertex2f(v2.x, v2.y); rlVertex2f(v2.x, v2.y);
glVertex2f(v3.x, v3.y);
glEnd(); rlVertex2f(v2.x, v2.y);
rlVertex2f(v3.x, v3.y);
rlVertex2f(v3.x, v3.y);
rlVertex2f(v1.x, v1.y);
rlEnd();
} }
// Draw a regular polygon of n sides (Vector version) // Draw a regular polygon of n sides (Vector version)
@ -286,20 +254,20 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col
{ {
if (sides < 3) sides = 3; if (sides < 3) sides = 3;
glPushMatrix(); rlPushMatrix();
glTranslatef(center.x, center.y, 0);
glRotatef(rotation, 0, 0, 1);
glBegin(GL_TRIANGLE_FAN); rlRotatef(rotation, 0, 0, 1); // TODO: compute vertex rotation manually!
glColor4ub(color.r, color.g, color.b, color.a);
glVertex2f(0, 0);
for (int i=0; i <= sides; i++) rlBegin(RL_TRIANGLES);
for (int i=0; i < 360; i += 2)
{ {
glVertex2f(radius*cos(i*2*PI/sides), radius*sin(i*2*PI/sides)); rlColor4ub(color.r, color.g, color.b, color.a);
rlVertex2i(center.x, center.y);
rlVertex2f(center.x + sin(DEG2RAD*i) * radius, center.y + cos(DEG2RAD*i) * radius);
rlVertex2f(center.x + sin(DEG2RAD*(i+1)) * radius, center.y + cos(DEG2RAD*(i+1)) * radius);
} }
glEnd(); rlEnd();
glPopMatrix(); rlPopMatrix();
} }
// Draw a closed polygon defined by points // Draw a closed polygon defined by points
@ -308,19 +276,16 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color)
{ {
if (numPoints >= 3) if (numPoints >= 3)
{ {
glEnable(GL_POLYGON_SMOOTH); rlBegin(RL_TRIANGLES);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); rlColor4ub(color.r, color.g, color.b, color.a);
glBegin(GL_POLYGON); for (int i = 0; i < numPoints - 2; i++)
glColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < numPoints; i++)
{ {
glVertex2f(points[i].x, points[i].y); rlVertex2f(points[i].x, points[i].y);
rlVertex2f(points[i+1].x, points[i+1].y);
rlVertex2f(points[i+2].x, points[i+2].y);
} }
glEnd(); rlEnd();
glDisable(GL_POLYGON_SMOOTH);
} }
} }
@ -330,22 +295,22 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color)
{ {
if (numPoints >= 2) if (numPoints >= 2)
{ {
//glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) rlBegin(RL_LINES);
//glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) rlColor4ub(color.r, color.g, color.b, color.a);
glBegin(GL_LINE_LOOP); for (int i = 0; i < numPoints - 1; i++)
glColor4ub(color.r, color.g, color.b, color.a);
for (int i = 0; i < numPoints; i++)
{ {
glVertex2f(points[i].x, points[i].y); rlVertex2f(points[i].x, points[i].y);
rlVertex2f(points[i+1].x, points[i+1].y);
} }
glEnd(); rlEnd();
//glDisable(GL_LINE_SMOOTH);
} }
} }
//----------------------------------------------------------------------------------
// Module Functions Definition - Collision Detection functions
//----------------------------------------------------------------------------------
// Check if point is inside rectangle // Check if point is inside rectangle
bool CheckCollisionPointRec(Vector2 point, Rectangle rec) bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
{ {

View file

@ -11,5 +11,4 @@ void main()
{ {
// Output pixel color // Output pixel color
pixelColor = texture(texture0, fragTexCoord) * fragColor; pixelColor = texture(texture0, fragTexCoord) * fragColor;
//pixelColor = fragColor;
} }

View file

@ -28,12 +28,13 @@
#include "raylib.h" #include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <stdlib.h> // Declares malloc() and free() for memory management #include <stdlib.h> // Declares malloc() and free() for memory management
#include <string.h> // String management functions (just strlen() is used) #include <string.h> // String management functions (just strlen() is used)
#include <stdarg.h> // Used for functions with variable number of parameters (FormatText()) #include <stdarg.h> // Used for functions with variable number of parameters (FormatText())
#include "stb_image.h" // Used to read image data (multiple formats support) #include "stb_image.h" // Used to read image data (multiple formats support)
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -63,6 +64,11 @@ struct Character {
static SpriteFont defaultFont; // Default font provided by raylib static SpriteFont defaultFont; // Default font provided by raylib
// NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core] // NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core]
//----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by text)
//----------------------------------------------------------------------------------
//...
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -78,8 +84,10 @@ static const char *GetExtension(const char *fileName);
extern void LoadDefaultFont() extern void LoadDefaultFont()
{ {
defaultFont.numChars = 96; // We know our default font has 94 chars defaultFont.numChars = 96; // We know our default font has 94 chars
defaultFont.texture.width = 128; // We know our default font texture is 128 pixels width
defaultFont.texture.height = 64; // We know our default font texture is 64 pixels height Image image;
image.width = 128; // We know our default font image is 128 pixels width
image.height = 64; // We know our default font image is 64 pixels height
// Default font is directly defined here (data generated from a sprite font image) // Default font is directly defined here (data generated from a sprite font image)
// This way, we reconstruct SpriteFont without creating large global variables // This way, we reconstruct SpriteFont without creating large global variables
@ -115,6 +123,30 @@ extern void LoadDefaultFont()
7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5, 7, 6, 6, 6, 6, 6, 6, 6, 6, 3, 5, 6, 5, 7, 6, 6, 6, 6, 6, 6, 7, 6, 7, 7, 6, 6, 6, 2, 7, 2, 3, 5,
2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4 }; 2, 5, 5, 5, 5, 5, 4, 5, 5, 1, 2, 5, 2, 5, 5, 5, 5, 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, 3, 1, 3, 4, 4 };
// Re-construct image from defaultFontData and generate OpenGL texture
//----------------------------------------------------------------------
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
int counter = 0; // Font data elements counter
// Fill imgData with defaultFontData (convert from bit to pixel!)
for (int i = 0; i < image.width * image.height; i += 32)
{
for (int j = 31; j >= 0; j--)
{
if (BIT_CHECK(defaultFontData[counter], j)) image.pixels[i+j] = WHITE;
}
counter++;
if (counter > 256) counter = 0; // Security check...
}
defaultFont.texture = CreateTexture(image); // Convert loaded image to OpenGL texture
UnloadImage(image);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -145,53 +177,11 @@ extern void LoadDefaultFont()
} }
else currentPosX = testPosX; else currentPosX = testPosX;
} }
// Re-construct image from defaultFontData and generate OpenGL texture
//----------------------------------------------------------------------
Color *imgDataPixel = (Color *)malloc(defaultFont.texture.width * defaultFont.texture.height * sizeof(Color));
for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i++) imgDataPixel[i] = BLANK; // Initialize array
int counter = 0; // Font data elements counter
// Fill imgData with defaultFontData (convert from bit to pixel!)
for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i += 32)
{
for (int j = 31; j >= 0; j--)
{
if (BIT_CHECK(defaultFontData[counter], j)) imgDataPixel[i+j] = WHITE;
}
counter++;
if (counter > 256) counter = 0; // Security check...
}
// Convert loaded data to OpenGL texture
//----------------------------------------
GLuint id;
glGenTextures(1, &id); // Generate pointer to the texture
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // Set texture to clamp on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // Set texture to clamp on y-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, defaultFont.texture.width, defaultFont.texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixel);
// NOTE: Not using mipmappings (texture for 2D drawing)
// At this point we have the image converted to texture and uploaded to GPU
free(imgDataPixel); // Now we can free loaded data from RAM memory
defaultFont.texture.glId = id;
} }
extern void UnloadDefaultFont() extern void UnloadDefaultFont()
{ {
glDeleteTextures(1, &defaultFont.texture.glId); rlDeleteTextures(defaultFont.texture.glId);
free(defaultFont.charSet); free(defaultFont.charSet);
} }
@ -206,6 +196,8 @@ SpriteFont LoadSpriteFont(const char* fileName)
{ {
SpriteFont spriteFont; SpriteFont spriteFont;
Image image;
// Check file extension // Check file extension
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
else else
@ -270,24 +262,13 @@ SpriteFont LoadSpriteFont(const char* fileName)
free(imgDataPixel); free(imgDataPixel);
// Convert loaded data to OpenGL texture image.pixels = imgDataPixelPOT;
//---------------------------------------- image.width = potWidth;
GLuint id; image.height = potHeight;
glGenTextures(1, &id); // Generate pointer to the texture
glBindTexture(GL_TEXTURE_2D, id); spriteFont.texture = CreateTexture(image); // Convert loaded image to OpenGL texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, potWidth, potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixelPOT);
// NOTE: Not using mipmappings (texture for 2D drawing) UnloadImage(image);
// At this point we have the image converted to texture and uploaded to GPU
free(imgDataPixelPOT); // Now we can free loaded data from RAM memory
spriteFont.texture.glId = id;
spriteFont.texture.width = potWidth;
spriteFont.texture.height = potHeight;
} }
return spriteFont; return spriteFont;
@ -296,7 +277,7 @@ SpriteFont LoadSpriteFont(const char* fileName)
// Unload SpriteFont from GPU memory // Unload SpriteFont from GPU memory
void UnloadSpriteFont(SpriteFont spriteFont) void UnloadSpriteFont(SpriteFont spriteFont)
{ {
glDeleteTextures(1, &spriteFont.texture.glId); rlDeleteTextures(spriteFont.texture.glId);
free(spriteFont.charSet); free(spriteFont.charSet);
} }
@ -330,28 +311,34 @@ void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, int f
if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f; if (fontSize <= spriteFont.charSet[0].h) scaleFactor = 1.0f;
else scaleFactor = (float)fontSize / spriteFont.charSet[0].h; else scaleFactor = (float)fontSize / spriteFont.charSet[0].h;
glEnable(GL_TEXTURE_2D); rlEnableTexture(spriteFont.texture.glId);
glBindTexture(GL_TEXTURE_2D, spriteFont.texture.glId);
// Optimized to use one draw call per string // Optimized to use one draw call per string
glBegin(GL_QUADS); rlBegin(RL_QUADS);
for(int i = 0; i < length; i++) for(int i = 0; i < length; i++)
{ {
c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR]; c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR];
glColor4ub(tint.r, tint.g, tint.b, tint.a); rlColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer
glTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX, position.y);
glTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX, position.y + (c.h) * scaleFactor); rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor); rlVertex2f(positionX, position.y);
glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y);
rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlVertex2f(positionX, position.y + (c.h) * scaleFactor);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height);
rlVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor);
rlTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height);
rlVertex2f(positionX + (c.w) * scaleFactor, position.y);
positionX += ((spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w) * scaleFactor + spacing); positionX += ((spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR].w) * scaleFactor + spacing);
} }
glEnd(); rlEnd();
glDisable(GL_TEXTURE_2D); rlDisableTexture();
} }
// Formatting of text with variables to 'embed' // Formatting of text with variables to 'embed'
@ -418,20 +405,17 @@ void DrawFPS(int posX, int posY)
if (counter < refreshRate) if (counter < refreshRate)
{ {
sprintf(buffer, "%2.0f FPS", fps);
DrawText(buffer, posX, posY, 20, LIME);
counter++; counter++;
} }
else else
{ {
fps = GetFPS(); fps = GetFPS();
refreshRate = fps; refreshRate = fps;
sprintf(buffer, "%2.0f FPS", fps);
DrawText(buffer, posX, posY, 20, LIME);
counter = 0; counter = 0;
} }
sprintf(buffer, "%2.0f FPS", fps);
DrawText(buffer, posX, posY, 20, LIME);
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------

View file

@ -28,12 +28,13 @@
#include "raylib.h" #include "raylib.h"
#include <GL/gl.h> // OpenGL functions
#include <stdlib.h> // Declares malloc() and free() for memory management #include <stdlib.h> // Declares malloc() and free() for memory management
#include "stb_image.h" // Used to read image data (multiple formats support) #include "stb_image.h" // Used to read image data (multiple formats support)
#include "utils.h" // rRES data decompression utility function #include "utils.h" // rRES data decompression utility function
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -49,6 +50,11 @@ typedef unsigned char byte;
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// It's lonely here... // It's lonely here...
//----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by text)
//----------------------------------------------------------------------------------
//...
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module specific Functions Declaration // Module specific Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@ -238,43 +244,6 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId)
return texture; return texture;
} }
// Create a Texture2D from Image data
// NOTE: Image is not unloaded, it should be done manually...
Texture2D CreateTexture(Image image)
{
Texture2D texture;
// Convert image data to OpenGL texture
//----------------------------------------
GLuint id;
glGenTextures(1, &id); // Generate Pointer to the Texture
glBindTexture(GL_TEXTURE_2D, id);
// NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used!
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repead on x-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repead on y-axis
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_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
// Trilinear filtering
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate use of mipmaps (must be available)
//glGenerateMipmap(GL_TEXTURE_2D); // OpenGL 3.3!
// Upload texture to GPU
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels);
// NOTE: Not using mipmappings (texture for 2D drawing)
// At this point we have the image converted to texture and uploaded to GPU
texture.glId = id;
texture.width = image.width;
texture.height = image.height;
return texture;
}
// Unload image from CPU memory (RAM) // Unload image from CPU memory (RAM)
void UnloadImage(Image image) void UnloadImage(Image image)
{ {
@ -284,7 +253,7 @@ void UnloadImage(Image image)
// Unload texture from GPU memory // Unload texture from GPU memory
void UnloadTexture(Texture2D texture) void UnloadTexture(Texture2D texture)
{ {
glDeleteTextures(1, &texture.glId); rlDeleteTextures(texture.glId);
} }
// Draw a Texture2D // Draw a Texture2D
@ -302,101 +271,126 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint)
// Draw a Texture2D with extended parameters // Draw a Texture2D with extended parameters
void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint) void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint)
{ {
glEnable(GL_TEXTURE_2D); // Enable textures usage rlEnableTexture(texture.glId);
glBindTexture(GL_TEXTURE_2D, texture.glId); // TODO: Apply rotation to vertex! --> rotate from origin CW (0, 0)
// TODO: Compute vertex scaling!
glPushMatrix(); // NOTE: Rotation is applied before translation and scaling, even being called in inverse order...
// NOTE: Rotation is applied before translation and scaling, even being called in inverse order... // NOTE: Rotation point is upper-left corner
// NOTE: Rotation point is upper-left corner //rlTranslatef(position.x, position.y, 0);
glTranslatef(position.x, position.y, 0); //rlScalef(scale, scale, 1.0f);
glScalef(scale, scale, 1.0f); //rlRotatef(rotation, 0, 0, 1);
glRotatef(rotation, 0, 0, 1);
glBegin(GL_QUADS); rlBegin(RL_QUADS);
glColor4ub(tint.r, tint.g, tint.b, tint.a); rlColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // Bottom-left corner for texture and quad
glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-right corner for texture and quad
glTexCoord2f(1.0f, 1.0f); glVertex2f(texture.width, texture.height); // Top-right corner for texture and quad
glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, texture.height); // Top-left corner for texture and quad
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // Disable textures usage rlTexCoord2f(0.0f, 0.0f);
rlVertex2f(position.x, position.y); // Bottom-left corner for texture and quad
rlTexCoord2f(0.0f, 1.0f);
rlVertex2f(position.x, position.y + texture.height); // Bottom-right corner for texture and quad
rlTexCoord2f(1.0f, 1.0f);
rlVertex2f(position.x + texture.width, position.y + texture.height); // Top-right corner for texture and quad
rlTexCoord2f(1.0f, 0.0f);
rlVertex2f(position.x + texture.width, position.y); // Top-left corner for texture and quad
rlEnd();
rlDisableTexture();
} }
// Draw a part of a texture (defined by a rectangle) // Draw a part of a texture (defined by a rectangle)
void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint) void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint)
{ {
glEnable(GL_TEXTURE_2D); // Enable textures usage rlEnableTexture(texture.glId);
glBindTexture(GL_TEXTURE_2D, texture.glId); rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
glPushMatrix(); // Bottom-left corner for texture and quad
glTranslatef(position.x, position.y, 0); rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
//glScalef(1.0f, 1.0f, 1.0f); rlVertex2f(position.x, position.y);
//glRotatef(rotation, 0, 0, 1);
glBegin(GL_QUADS); // Bottom-right corner for texture and quad
glColor4ub(tint.r, tint.g, tint.b, tint.a); rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer rlVertex2f(position.x, position.y + sourceRec.height);
// Bottom-left corner for texture and quad // Top-right corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(0.0f, 0.0f); rlVertex2f(position.x + sourceRec.width, position.y + sourceRec.height);
// Bottom-right corner for texture and quad // Top-left corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
glVertex2f(sourceRec.width, 0.0f); rlVertex2f(position.x + sourceRec.width, position.y);
rlEnd();
// Top-right corner for texture and quad rlDisableTexture();
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(sourceRec.width, sourceRec.height);
// Top-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(0.0f, sourceRec.height);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // Disable textures usage
} }
// Draw a part of a texture (defined by a rectangle) with 'pro' parameters // Draw a part of a texture (defined by a rectangle) with 'pro' parameters
// TODO: Test this function... // TODO: Test this function...
void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint) void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint)
{ {
glEnable(GL_TEXTURE_2D); // Enable textures usage rlEnableTexture(texture.glId);
glBindTexture(GL_TEXTURE_2D, texture.glId); // TODO: Apply translation, rotation and scaling of vertex manually!
glPushMatrix(); //rlTranslatef(-origin.x, -origin.y, 0);
glTranslatef(-origin.x, -origin.y, 0); //rlRotatef(rotation, 0, 0, 1);
glRotatef(rotation, 0, 0, 1); //rlTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
glTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0);
glBegin(GL_QUADS); rlBegin(RL_QUADS);
glColor4ub(tint.r, tint.g, tint.b, tint.a); rlColor4ub(tint.r, tint.g, tint.b, tint.a);
glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
// Bottom-left corner for texture and quad // Bottom-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height);
glVertex2f(0.0f, 0.0f); rlVertex2f(0.0f, 0.0f);
// Bottom-right corner for texture and quad // Bottom-right corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height);
glVertex2f(destRec.width, 0.0f); rlVertex2f(destRec.width, 0.0f);
// Top-right corner for texture and quad // Top-right corner for texture and quad
glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(destRec.width, destRec.height); rlVertex2f(destRec.width, destRec.height);
// Top-left corner for texture and quad // Top-left corner for texture and quad
glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height);
glVertex2f(0.0f, destRec.height); rlVertex2f(0.0f, destRec.height);
glEnd(); rlEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // Disable textures usage rlDisableTexture();
}
Texture2D CreateTexture(Image image)
{
Texture2D texture;
unsigned char *img = malloc(image.width * image.height * 4);
int j = 0;
for (int i = 0; i < image.width * image.height * 4; i += 4)
{
img[i] = image.pixels[j].r;
img[i+1] = image.pixels[j].g;
img[i+2] = image.pixels[j].b;
img[i+3] = image.pixels[j].a;
j++;
}
texture.glId = rlglTexture(image.width, image.height, img);
texture.width = image.width;
texture.height = image.height;
free(img);
return texture;
} }

View file

@ -1,140 +0,0 @@
/*********************************************************************************************
*
* raylib.vector3
*
* Vector3 Functions Definition
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#include "vector3.h"
#include <math.h> // Used for fabs(), sqrt()
// Add two vectors
Vector3 VectorAdd(Vector3 v1, Vector3 v2)
{
Vector3 out;
out.x = v1.x + v2.x;
out.y = v1.y + v2.y;
out.z = v1.z + v2.z;
return out;
}
// Substract two vectors
Vector3 VectorSubtract(Vector3 v1, Vector3 v2)
{
Vector3 out;
out.x = v1.x - v2.x;
out.y = v1.y - v2.y;
out.z = v1.z - v2.z;
return out;
}
// Calculate two vectors cross product
Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2)
{
Vector3 cross;
cross.x = v1.y*v2.z - v1.z*v2.y;
cross.y = v1.z*v2.x - v1.x*v2.z;
cross.z = v1.x*v2.y - v1.y*v2.x;
return cross;
}
// Calculate one vector perpendicular vector
Vector3 VectorPerpendicular(Vector3 v)
{
Vector3 out;
float min = fabs(v.x);
Vector3 cardinalAxis = {1.0, 0.0, 0.0};
if (fabs(v.y) < min)
{
min = fabs(v.y);
cardinalAxis = (Vector3){0.0, 1.0, 0.0};
}
if(fabs(v.z) < min)
{
cardinalAxis = (Vector3){0.0, 0.0, 1.0};
}
out = VectorCrossProduct(v, cardinalAxis);
return out;
}
// Calculate two vectors dot product
float VectorDotProduct(Vector3 v1, Vector3 v2)
{
float dot;
dot = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z;
return dot;
}
// Calculate vector lenght
float VectorLength(const Vector3 v)
{
float length;
length = sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
return length;
}
// Scale provided vector
void VectorScale(Vector3 *v, float scale)
{
v->x *= scale;
v->y *= scale;
v->z *= scale;
}
// Invert provided vector (direction)
void VectorInverse(Vector3 *v)
{
v->x = -v->x;
v->y = -v->y;
v->z = -v->z;
}
// Normalize provided vector
void VectorNormalize(Vector3 *v)
{
float length, ilength;
length = VectorLength(*v);
if (length == 0) length = 1;
ilength = 1.0/length;
v->x *= ilength;
v->y *= ilength;
v->z *= ilength;
}

View file

@ -1,57 +0,0 @@
/*********************************************************************************************
*
* raylib.vector3
*
* Some useful functions to work with Vector3
*
* Copyright (c) 2013 Ramon Santamaria (Ray San - raysan@raysanweb.com)
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
* as being the original software.
*
* 3. This notice may not be removed or altered from any source distribution.
*
**********************************************************************************************/
#ifndef VECTOR3_H
#define VECTOR3_H
#include "raylib.h" // Defines Vector3 structure
#ifdef __cplusplus
extern "C" { // Prevents name mangling of functions
#endif
//------------------------------------------------------------------------------------
// Global Variables Definition
//------------------------------------------------------------------------------------
// It's lonely here...
//------------------------------------------------------------------------------------
// Functions Declaration to work with Vector3
//------------------------------------------------------------------------------------
Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors
Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors
Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product
Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector
float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product
float VectorLength(const Vector3 v); // Calculate vector lenght
void VectorScale(Vector3 *v, float scale); // Scale provided vector
void VectorInverse(Vector3 *v); // Invert provided vector (direction)
void VectorNormalize(Vector3 *v); // Normalize provided vector
#ifdef __cplusplus
}
#endif
#endif // VECTOR3_H