From 96f520ff6d085536205feb1f943974e354577df4 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 25 Mar 2014 12:40:35 +0100 Subject: [PATCH] Road to raylib 1.1 - Testing rlgl --- src/core.c | 242 ++++---- src/models.c | 681 +++++++++++----------- src/raylib.h | 18 +- src/raymath.c | 548 +++++++++--------- src/raymath.h | 2 + src/rlgl.c | 1364 ++++++++++++++++++++++++++++++++++++++++++++ src/rlgl.h | 117 ++++ src/shapes.c | 305 +++++----- src/simple150.frag | 1 - src/text.c | 154 +++-- src/textures.c | 222 ++++--- src/vector3.c | 140 ----- src/vector3.h | 57 -- 13 files changed, 2537 insertions(+), 1314 deletions(-) create mode 100644 src/rlgl.c create mode 100644 src/rlgl.h delete mode 100644 src/vector3.c delete mode 100644 src/vector3.h diff --git a/src/core.c b/src/core.c index bd373c7c..0d18f57a 100644 --- a/src/core.c +++ b/src/core.c @@ -28,15 +28,19 @@ #include "raylib.h" +#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 + #include // GLFW3 lib: Windows, OpenGL context and Input management //#include // OpenGL functions (GLFW3 already includes gl.h) #include // Standard input / output lib #include // Declares malloc() and free() for memory management, rand() #include // Useful to initialize random seed #include // 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 "raymath.h" // Required for data type Matrix and Matrix functions + //#define GLFW_DLL // Using GLFW DLL on Windows -> No, we use static version! //---------------------------------------------------------------------------------- @@ -47,7 +51,7 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef Color pixel; +// ... //---------------------------------------------------------------------------------- // 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 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 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 currentGamepadState[32] = {0}; // Required to check if gamepad btn pressed/released once -static int previousMouseWheelY = 0; -static int currentMouseWheelY = 0; +static int previousMouseWheelY = 0; // Required to track mouse wheel variation +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) @@ -89,13 +95,11 @@ extern void UnloadDefaultFont(); // [Module: text] Unloads default f //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static void InitGraphicsDevice(); // Initialize Graphics Device (OpenGL stuff) static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel static void CursorEnterCallback(GLFWwindow* window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area static void WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized -static void 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 //---------------------------------------------------------------------------------- @@ -116,9 +120,17 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons if (!glfwInit()) exit(1); //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 - + +#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); windowWidth = width; @@ -140,21 +152,41 @@ 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) // If not set, swap interval uses GPU v-sync configuration // 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(); - LoadDefaultFont(); + LoadDefaultFont(); // NOTE: External function (defined in module: text) 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 void CloseWindow() { UnloadDefaultFont(); + + //------------------------------------------------------ +#ifdef USE_OPENGL_33 + rlglClose(); // De-init rlgl +#endif + //------------------------------------------------------ glfwDestroyWindow(window); glfwTerminate(); @@ -210,7 +242,10 @@ void ToggleFullscreen() glfwMakeContextCurrent(window); glfwSetKeyCallback(window, KeyCallback); - InitGraphicsDevice(); + int fbWidth, fbHeight; + glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window + + rlglInitGraphicsDevice(fbWidth, fbHeight); LoadDefaultFont(); } @@ -219,13 +254,12 @@ void ToggleFullscreen() // Sets Background Color void ClearBackground(Color color) { - // Color values clamp to 0.0f(0) and 1.0f(255) - float r = (float)color.r / 255; - float g = (float)color.g / 255; - float b = (float)color.b / 255; - float a = (float)color.a / 255; - - glClearColor(r, g, b, a); + if ((color.r != background.r) || (color.g != background.g) || (color.b != background.b) || (color.a != background.a)) + { + rlClearColor(color.r, color.g, color.b, color.a); + + background = color; + } } // Setup drawing canvas to start drawing @@ -235,11 +269,14 @@ void BeginDrawing() updateTime = currentTime - previousTime; 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) - - glTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL + rlLoadIdentity(); // Reset current matrix (MODELVIEW) + +//#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) @@ -247,6 +284,12 @@ void EndDrawing() { if (customCursor && cursorOnScreen) DrawTexture(cursor, GetMouseX(), GetMouseY(), WHITE); + //------------------------------------------------------ +#ifdef USE_OPENGL_33 + rlglDraw(); // Draw Buffers +#endif + //------------------------------------------------------ + glfwSwapBuffers(window); // Swap back and front buffers glfwPollEvents(); // Register keyboard/mouse events @@ -271,34 +314,48 @@ void EndDrawing() // Initializes 3D mode for drawing (Camera setup) void Begin3dMode(Camera camera) { - glMatrixMode(GL_PROJECTION); // Switch to projection matrix + //------------------------------------------------------ +#ifdef USE_OPENGL_33 + rlglDraw(); // Draw Buffers +#endif + //------------------------------------------------------ + + rlMatrixMode(RL_PROJECTION); // Switch to projection matrix - glPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection - 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 float aspect = (GLfloat)windowWidth/(GLfloat)windowHeight; double top = 0.1f*tan(45.0f*PI / 360.0); 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 - glLoadIdentity(); // Reset current matrix (MODELVIEW) + rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix + 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 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 + //------------------------------------------------------ + + rlMatrixMode(RL_PROJECTION); // Switch to projection matrix + rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack - glMatrixMode(GL_MODELVIEW); // Get back to modelview matrix - glLoadIdentity(); // Reset current matrix (MODELVIEW) + rlMatrixMode(RL_MODELVIEW); // Get back to modelview matrix + rlLoadIdentity(); // Reset current matrix (MODELVIEW) - glTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode) + //rlTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode) } // Set target FPS for the game @@ -649,125 +706,32 @@ static void CursorEnterCallback(GLFWwindow* window, int enter) // GLFW3 WindowSize Callback, runs when window is resized static void WindowSizeCallback(GLFWwindow* window, int width, int height) -{ - InitGraphicsDevice(); // If window is resized, graphics device is re-initialized - // NOTE: Aspect ratio does not change, so, image can be deformed -} - -// Initialize Graphics Device (OpenGL stuff) -static void InitGraphicsDevice() { int fbWidth, fbHeight; - glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window - glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set background color (black) - glClearDepth(1.0f); // Clear depth buffer - - glEnable(GL_DEPTH_TEST); // Enables depth testing (required for 3D) - glDepthFunc(GL_LEQUAL); // Type of depth testing to apply - - glEnable(GL_BLEND); // Enable color blending (required to work with transparencies) - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Color blending function (how colors are mixed) - - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation (Deprecated in OGL 3.0) - // Other options: GL_FASTEST, GL_DONT_CARE (default) - - glMatrixMode(GL_PROJECTION); // Switch to PROJECTION matrix - glLoadIdentity(); // Reset current matrix (PROJECTION) - glOrtho(0, fbWidth, fbHeight, 0, 0, 1); // Config orthographic mode: top-left corner --> (0,0) - glMatrixMode(GL_MODELVIEW); // Switch back to MODELVIEW matrix - glLoadIdentity(); // Reset current matrix (MODELVIEW) - - // 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 + // If window is resized, graphics device is re-initialized + // NOTE: Aspect ratio does not change, so, image can be deformed + rlglInitGraphicsDevice(fbWidth, fbHeight); } // Takes a bitmap (BMP) screenshot and saves it in the same folder as executable static void TakeScreenshot() { static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution - + char buffer[20]; // Buffer to store file name - int fbWidth, fbHeight; - - unsigned char *imgData; // Pixel image data array + int fbWidth, fbHeight; // Frame buffer width and height 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); - // NOTE: BMP directly stores data flipped vertically - //WriteBitmap(buffer, imgDataPixel, fbWidth, fbHeight); // Writes pixel data array into a bitmap (BMP) file - WritePNG(buffer, imgDataFlip, fbWidth, fbHeight); - - free(imgDataFlip); - + WritePNG(buffer, imgData, fbWidth, fbHeight); + + free(imgData); + shotNum++; } \ No newline at end of file diff --git a/src/models.c b/src/models.c index e21ff894..e1b80617 100644 --- a/src/models.c +++ b/src/models.c @@ -29,7 +29,10 @@ #include // Standard input/output functions, used to read model files data #include // Declares malloc() and free() for memory management #include // 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 @@ -39,14 +42,30 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- - -// Matrix type (OpenGL style 4x4 - right handed) -typedef struct Matrix { - float m0, m4, m8, m12; - float m1, m5, m9, m13; - float m2, m6, m10, m14; - float m3, m7, m11, m15; -} Matrix; +#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; + }; + +/* + struct Model + { + GLUint vaoId; + Matrix transform; + int polyMode; + } +*/ +#endif //---------------------------------------------------------------------------------- // Global Variables Definition @@ -57,8 +76,6 @@ typedef struct Matrix { // Module specific Functions Declaration //---------------------------------------------------------------------------------- static float GetHeightValue(Color pixel); -static void MatrixTranspose(Matrix *mat); -static Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -68,52 +85,66 @@ static Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up); // NOTE: Cube position is the center position void DrawCube(Vector3 position, float width, float height, float lenght, Color color) { - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - //glRotatef(rotation, 0.0f, 1.0f, 0.0f); - //glScalef(1.0f, 1.0f, 1.0f); + // THIS WORKS! +/* + Matrix mat = MatrixTranslate(2.0, 0.0, 0.0); + MatrixTranspose(&mat); + VectorTransform(&position, mat); + + PrintMatrix(mat); +*/ + + float x = position.x; + float y = position.y; + float z = position.z; - glBegin(GL_QUADS); - glColor4ub(color.r, color.g, color.b, color.a); - + 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 - glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer - glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad - glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad - glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, lenght/2); // Top Right Of The Texture and Quad - glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, lenght/2); // Top Left Of The Texture and Quad + rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left 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 + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right 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 - glNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer - glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Bottom Right Of The Texture and Quad - glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad - glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad - glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, -lenght/2); // Bottom Left Of The Texture and Quad + rlNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom 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 + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top 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 - glNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up - glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad - glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, height/2, lenght/2); // Bottom Left Of The Texture and Quad - glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, height/2, lenght/2); // Bottom Right Of The Texture and Quad - glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad + rlNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top 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 + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom 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 - glNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down - glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Top Right Of The Texture and Quad - glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, -height/2, -lenght/2); // Top Left Of The Texture and Quad - glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad - glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad + rlNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Right 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 + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left 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 - glNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right - glTexCoord2f(1.0f, 0.0f); glVertex3f( width/2, -height/2, -lenght/2); // Bottom Right Of The Texture and Quad - glTexCoord2f(1.0f, 1.0f); glVertex3f( width/2, height/2, -lenght/2); // Top Right Of The Texture and Quad - glTexCoord2f(0.0f, 1.0f); glVertex3f( width/2, height/2, lenght/2); // Top Left Of The Texture and Quad - glTexCoord2f(0.0f, 0.0f); glVertex3f( width/2, -height/2, lenght/2); // Bottom Left Of The Texture and Quad + rlNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom 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 + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top 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 - glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left - glTexCoord2f(0.0f, 0.0f); glVertex3f(-width/2, -height/2, -lenght/2); // Bottom Left Of The Texture and Quad - glTexCoord2f(1.0f, 0.0f); glVertex3f(-width/2, -height/2, lenght/2); // Bottom Right Of The Texture and Quad - glTexCoord2f(1.0f, 1.0f); glVertex3f(-width/2, height/2, lenght/2); // Top Right Of The Texture and Quad - glTexCoord2f(0.0f, 1.0f); glVertex3f(-width/2, height/2, -lenght/2); // Top Left Of The Texture and Quad - glEnd(); - glPopMatrix(); + rlNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left 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 + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Right 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 + rlEnd(); + rlPopMatrix(); } // Draw cube (Vector version) @@ -125,9 +156,11 @@ void DrawCubeV(Vector3 position, Vector3 size, Color color) // Draw cube wires void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - DrawCube(position, width, height, lenght, color); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // TODO: Draw cube using RL_LINES! + + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //DrawCube(position, width, height, lenght, color); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // Draw sphere @@ -143,14 +176,16 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color float lat1, z1, zr1; float lng, x, y; - glPushMatrix(); - glTranslatef(centerPos.x, centerPos.y, centerPos.z); - glRotatef(90, 1, 0, 0); - glScalef(radius, radius, radius); + // TODO: Review vertex translate/rotate/scale mechanism + + rlPushMatrix(); + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlRotatef(90, 1, 0, 0); + rlScalef(radius, radius, radius); - glBegin(GL_QUAD_STRIP); + rlBegin(GL_QUAD_STRIP); - glColor4ub(color.r, color.g, color.b, color.a); + rlColor4ub(color.r, color.g, color.b, color.a); 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); y = sin(lng); - glNormal3f(x * zr0, y * zr0, z0); - glVertex3f(x * zr0, y * zr0, z0); + rlNormal3f(x * zr0, y * zr0, z0); + rlVertex3f(x * zr0, y * zr0, z0); - glNormal3f(x * zr1, y * zr1, z1); - glVertex3f(x * zr1, y * zr1, z1); + rlNormal3f(x * zr1, y * zr1, z1); + rlVertex3f(x * zr1, y * zr1, z1); } } - glEnd(); - glPopMatrix(); + rlEnd(); + rlPopMatrix(); } // Draw sphere wires void DrawSphereWires(Vector3 centerPos, float radius, Color color) { - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - DrawSphere(centerPos, radius, color); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + // TODO: Draw sphere using RL_LINES! + + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + //DrawSphere(centerPos, radius, color); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // 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 { - //void drawCone(const Vector3 &d, const Vector3 &a, const float h, const float rd, const int n) //d – axis defined as a normalized vector from base to apex //a – position of apex (top point) //h – height //rd – radius of directrix //n – number of radial "slices" + + // TODO: Review drawing to use RL_TRIANGLES - glPushMatrix(); - //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 + rlBegin(GL_TRIANGLE_FAN); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex3f(a.x, a.y, a.z); - // Draw cone top - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex3f(a.x, a.y, a.z); - for (int i = 0; i <= slices; i++) - { - float rad = angInc * i; - p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom); - p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom); - p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom); - glVertex3f(p.x, p.y, p.z); - } - glEnd(); - - // Draw cone bottom - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex3f(c.x, c.y, c.z); - for (int i = slices; i >= 0; i--) - { - float rad = angInc * i; - p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom); - p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom); - p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom); - glVertex3f(p.x, p.y, p.z); - } - glEnd(); + 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); + rlVertex3f(p.x, p.y, p.z); + } + rlEnd(); + + // Draw cone bottom + rlBegin(GL_TRIANGLE_FAN); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex3f(c.x, c.y, c.z); - glPopMatrix(); + 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 { - 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) - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex3f(c.x, c.y + height, c.z); - for (int i = slices; i >= 0; i--) - { - float rad = angInc * i; - p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop); - p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height; - p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop); - glVertex3f(p.x, p.y, p.z); - } - glEnd(); - - // Draw cylinder sides - glBegin(GL_TRIANGLE_STRIP); - glColor4ub(color.r, color.g, color.b, color.a); - for (int i = slices; i >= 0; i--) - { - float rad = angInc * i; - p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop); - p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height; - p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop); - glVertex3f(p.x, p.y, p.z); - - p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom); - p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom); - p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom); - glVertex3f(p.x, p.y, p.z); - } - glEnd(); - - // Draw cylinder bottom - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex3f(c.x, c.y, c.z); - for (int i = slices; i >= 0; i--) - { - float rad = angInc * i; - p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusBottom); - p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusBottom); - p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom); - glVertex3f(p.x, p.y, p.z); - } - glEnd(); - - glPopMatrix(); + + // TODO: Review drawing to use RL_TRIANGLES + + // Draw cylinder top (pointed cap) + rlBegin(GL_TRIANGLE_FAN); + rlColor4ub(color.r, color.g, color.b, color.a); + 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); + 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); + } + rlEnd(); + + // Draw cylinder sides + rlBegin(GL_TRIANGLE_STRIP); + rlColor4ub(color.r, color.g, color.b, color.a); + for (int i = slices; i >= 0; i--) + { + float rad = angInc * i; + p.x = c.x + (((e0.x * cos(rad)) + (e1.x * sin(rad))) * radiusTop); + p.y = c.y + (((e0.y * cos(rad)) + (e1.y * sin(rad))) * radiusTop) + height; + p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusTop); + 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); + p.z = c.z + (((e0.z * cos(rad)) + (e1.z * sin(rad))) * radiusBottom); + rlVertex3f(p.x, p.y, p.z); + } + rlEnd(); + + // 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 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); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // Draw a plane 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 - glPushMatrix(); - glTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlPushMatrix(); + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... - glRotatef(rotation.x, 1, 0, 0); - glRotatef(rotation.y, 0, 1, 0); - glRotatef(rotation.z, 0, 0, 1); - glScalef(size.x, 1.0f, size.y); + rlRotatef(rotation.x, 1, 0, 0); + rlRotatef(rotation.y, 0, 1, 0); + rlRotatef(rotation.z, 0, 0, 1); + rlScalef(size.x, 1.0f, size.y); - glBegin(GL_QUADS); - glColor4ub(color.r, color.g, color.b, color.a); - glNormal3f(0.0f, 1.0f, 0.0f); - glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, 0.0f, -0.5f); - glTexCoord2f(1.0f, 0.0f); glVertex3f(0.5f, 0.0f, -0.5f); - glTexCoord2f(1.0f, 1.0f); glVertex3f(0.5f, 0.0f, 0.5f); - glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, 0.0f, 0.5f); - glEnd(); - - glPopMatrix(); + rlBegin(GL_QUADS); + rlColor4ub(color.r, color.g, color.b, color.a); + rlNormal3f(0.0f, 1.0f, 0.0f); + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, -0.5f); + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(0.5f, 0.0f, -0.5f); + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(0.5f, 0.0f, 0.5f); + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(-0.5f, 0.0f, 0.5f); + rlEnd(); + rlPopMatrix(); } // Draw a plane with divisions @@ -341,71 +373,75 @@ void DrawPlaneEx(Vector3 centerPos, Vector2 size, Vector3 rotation, int slicesX, float texPieceW = 1 / size.x; float texPieceH = 1 / size.y; + // TODO: Review vertex translate/rotate/scale mechanism + // NOTE: Plane is always created on XZ ground and then rotated - glPushMatrix(); - glTranslatef(-size.x / 2, 0.0f, -size.y / 2); - glTranslatef(centerPos.x, centerPos.y, centerPos.z); + rlPushMatrix(); + rlTranslatef(-size.x / 2, 0.0f, -size.y / 2); + rlTranslatef(centerPos.x, centerPos.y, centerPos.z); // TODO: Review multiples rotations Gimbal-Lock... use matrix or quaternions... - glRotatef(rotation.x, 1, 0, 0); - glRotatef(rotation.y, 0, 1, 0); - glRotatef(rotation.z, 0, 0, 1); + rlRotatef(rotation.x, 1, 0, 0); + rlRotatef(rotation.y, 0, 1, 0); + rlRotatef(rotation.z, 0, 0, 1); - glBegin(GL_QUADS); - glColor4ub(color.r, color.g, color.b, color.a); - glNormal3f(0.0f, 1.0f, 0.0f); + rlBegin(RL_QUADS); + rlColor4ub(color.r, color.g, color.b, color.a); + rlNormal3f(0.0f, 1.0f, 0.0f); for (int z = 0; z < slicesZ; z++) { for (int x = 0; x < slicesX; x++) { // Draw the plane quad by quad (with textcoords) - glTexCoord2f((float)x * texPieceW, (float)z * texPieceH); - glVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght); + rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH); + rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght); - glTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH); - glVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght); + rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH); + rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght); - glTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH); - glVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght); + rlTexCoord2f((float)x * texPieceW + texPieceW, (float)z * texPieceH + texPieceH); + rlVertex3f((float)x * quadWidth + quadWidth, 0.0f, (float)z * quadLenght + quadLenght); - glTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH); - glVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght); + rlTexCoord2f((float)x * texPieceW, (float)z * texPieceH + texPieceH); + rlVertex3f((float)x * quadWidth, 0.0f, (float)z * quadLenght + quadLenght); } } - glEnd(); + rlEnd(); - glPopMatrix(); + rlPopMatrix(); } // Draw a grid centered at (0, 0, 0) void DrawGrid(int slices, float spacing) { int halfSlices = slices / 2; - - //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) - //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) - glPushMatrix(); - glScalef(spacing, 1.0f, spacing); - - glBegin(GL_LINES); - for(int i = -halfSlices; i <= halfSlices; i++) + rlBegin(RL_LINES); + for(int i = -halfSlices; i <= halfSlices; i++) + { + if (i == 0) { - if (i == 0) glColor3f(0.5f, 0.5f, 0.5f); - else glColor3f(0.75f, 0.75f, 0.75f); - - glVertex3f((float)i, 0.0f, (float)-halfSlices); - glVertex3f((float)i, 0.0f, (float)halfSlices); - - glVertex3f((float)-halfSlices, 0.0f, (float)i); - glVertex3f((float)halfSlices, 0.0f, (float)i); + rlColor3f(0.5f, 0.5f, 0.5f); + rlColor3f(0.5f, 0.5f, 0.5f); + rlColor3f(0.5f, 0.5f, 0.5f); + rlColor3f(0.5f, 0.5f, 0.5f); } - glEnd(); - - glPopMatrix(); - - //glDisable(GL_LINE_SMOOTH); + else + { + 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); + } + + rlVertex3f((float)i*spacing, 0.0f, (float)-halfSlices*spacing); + rlVertex3f((float)i*spacing, 0.0f, (float)halfSlices*spacing); + + 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) @@ -418,44 +454,47 @@ void DrawGizmo(Vector3 position, bool orbits) //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); - //glRotatef(rotation, 0, 1, 0); - glScalef(lenght, lenght, lenght); + // GL_LINE_SMOOTH is very poorly supported on desktop GL. + // A lot of drivers ignore it, so most people avoid using... - glBegin(GL_LINES); - glColor3f(1.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(1.0f, 0.0f, 0.0f); + rlPushMatrix(); + rlTranslatef(position.x, position.y, position.z); + //glRotatef(rotation, 0, 1, 0); + rlScalef(lenght, lenght, lenght); + + rlBegin(GL_LINES); + rlColor3f(1.0f, 0.0f, 0.0f); + rlVertex3f(0.0f, 0.0f, 0.0f); + rlVertex3f(1.0f, 0.0f, 0.0f); - glColor3f(0.0f, 1.0f, 0.0f); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 1.0f, 0.0f); + rlColor3f(0.0f, 1.0f, 0.0f); + rlVertex3f(0.0f, 0.0f, 0.0f); + rlVertex3f(0.0f, 1.0f, 0.0f); - glColor3f(0.0f, 0.0f, 1.0f); - glVertex3f(0.0f, 0.0f, 0.0f); - glVertex3f(0.0f, 0.0f, 1.0f); - glEnd(); + rlColor3f(0.0f, 0.0f, 1.0f); + rlVertex3f(0.0f, 0.0f, 0.0f); + rlVertex3f(0.0f, 0.0f, 1.0f); + rlEnd(); if (orbits) { - glBegin(GL_LINE_LOOP); - glColor4f(1.0f, 0.0f, 0.0f, 0.4f); - for (int i=0; i < 360; i++) glVertex3f(sin(DEG2RAD*i) * radius, 0, cos(DEG2RAD*i) * radius); - glEnd(); + rlBegin(GL_LINE_LOOP); + rlColor4f(1.0f, 0.0f, 0.0f, 0.4f); + for (int i=0; i < 360; i++) rlVertex3f(sin(DEG2RAD*i) * radius, 0, cos(DEG2RAD*i) * radius); + rlEnd(); - glBegin(GL_LINE_LOOP); - glColor4f(0.0f, 1.0f, 0.0f, 0.4f); - for (int i=0; i < 360; i++) glVertex3f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius, 0); - glEnd(); + rlBegin(GL_LINE_LOOP); + rlColor4f(0.0f, 1.0f, 0.0f, 0.4f); + for (int i=0; i < 360; i++) rlVertex3f(sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius, 0); + rlEnd(); - glBegin(GL_LINE_LOOP); - glColor4f(0.0f, 0.0f, 1.0f, 0.4f); - for (int i=0; i < 360; i++) glVertex3f(0, sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius); - glEnd(); + rlBegin(GL_LINE_LOOP); + rlColor4f(0.0f, 0.0f, 1.0f, 0.4f); + for (int i=0; i < 360; i++) rlVertex3f(0, sin(DEG2RAD*i) * radius, cos(DEG2RAD*i) * radius); + rlEnd(); } - glPopMatrix(); + rlPopMatrix(); //glDisable(GL_LINE_SMOOTH); } @@ -464,7 +503,7 @@ void DrawGizmo(Vector3 position, bool orbits) // TODO: Add comments explaining this function process Model LoadModel(const char *fileName) { - Model model; + struct Model model; char dataType; char comments[200]; @@ -664,6 +703,12 @@ Model LoadModel(const char *fileName) fclose(objFile); +#ifdef USE_OPENGL_33 + + // TODO: Use loaded data to generate VAO + +#endif + return model; } @@ -749,6 +794,12 @@ Model LoadHeightmap(Image heightmap, float maxHeight) trisCounter += 2; } } + +#ifdef USE_OPENGL_33 + + // TODO: Use loaded data to generate VAO + +#endif 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) //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_TEXTURE_COORD_ARRAY); // Enable texture coords 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 //glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED) - glPushMatrix(); - glTranslatef(position.x, position.y, position.z); + rlPushMatrix(); + rlTranslatef(position.x, position.y, position.z); //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); - glPopMatrix(); + rlPopMatrix(); glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array //rotation += 10; + +// 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 void DrawModelEx(Model model, Texture2D texture, Vector3 position, float scale, Color tint) { - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, texture.glId); + rlEnableTexture(texture.glId); DrawModel(model, position, scale, tint); - glDisable(GL_TEXTURE_2D); + rlDisableTexture(); } // Draw a model wires 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); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } // Draw a billboard @@ -842,20 +914,18 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Vector3 c = VectorAdd(center, p2); Vector3 d = VectorSubtract(center, p1); - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, texture.glId); + rlEnableTexture(texture.glId); - glBegin(GL_QUADS); - 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(); + 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(); - glDisable(GL_TEXTURE_2D); + rlDisableTexture(); } // Draw a billboard (part of a texture defined by a rectangle) @@ -887,92 +957,33 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec Vector3 c = VectorAdd(center, p2); Vector3 d = VectorSubtract(center, p1); - glEnable(GL_TEXTURE_2D); // Enable textures usage + rlEnableTexture(texture.glId); - glBindTexture(GL_TEXTURE_2D, texture.glId); - - glBegin(GL_QUADS); - glColor4ub(tint.r, tint.g, tint.b, tint.a); + rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); // Bottom-left corner for texture and quad - glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); - glVertex3f(a.x, a.y, a.z); + rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); + rlVertex3f(a.x, a.y, a.z); // Bottom-right corner for texture and quad - glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); - glVertex3f(b.x, b.y, b.z); + rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); + rlVertex3f(b.x, b.y, b.z); // Top-right corner for texture and quad - glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); - glVertex3f(c.x, c.y, c.z); + rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlVertex3f(c.x, c.y, c.z); // Top-left corner for texture and quad - glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); - glVertex3f(d.x, d.y, d.z); - glEnd(); + rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlVertex3f(d.x, d.y, d.z); + rlEnd(); - glDisable(GL_TEXTURE_2D); // Disable textures usage + rlDisableTexture(); } // Get current vertex y altitude (proportional to pixel colors in grayscale) static float GetHeightValue(Color pixel) { 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; } \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index fd66819c..4534c5ec 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -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 * * Features: * Library written in plain C code (C99) * 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 -* 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 * * Used external libs: @@ -23,8 +25,9 @@ * 32bit Textures - All loaded images are converted automatically to RGBA textures * SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures * One custom default font is loaded automatically when InitWindow() +* 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, * BSD-like license that allows static linking with closed source software: @@ -213,12 +216,7 @@ typedef struct Camera { } Camera; // Basic 3d Model type -typedef struct Model { - int numVertices; - Vector3 *vertices; - Vector2 *texcoords; - Vector3 *normals; -} Model; +typedef struct Model Model; // Basic Sound source and buffer typedef struct Sound { diff --git a/src/raymath.c b/src/raymath.c index 3546113c..fa4bac90 100644 --- a/src/raymath.c +++ b/src/raymath.c @@ -199,6 +199,28 @@ Vector3 VectorReflect(Vector3 vector, Vector3 normal) 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 //---------------------------------------------------------------------------------- @@ -234,17 +256,17 @@ float MatrixDeterminant(Matrix mat) float result; // Cache the matrix values (speed optimization) - 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 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 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 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; - 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 + - 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 + - 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; + 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 + + 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 + + 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; return result; } @@ -261,21 +283,21 @@ 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; + 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; } @@ -285,50 +307,50 @@ void MatrixInvert(Matrix *mat) { 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 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 a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15; - - float b00 = a00*a11 - a01*a10; - float b01 = a00*a12 - a02*a10; - float b02 = a00*a13 - a03*a10; - float b03 = a01*a12 - a02*a11; - float b04 = a01*a13 - a03*a11; - float b05 = a02*a13 - a03*a12; - float b06 = a20*a31 - a21*a30; - float b07 = a20*a32 - a22*a30; - float b08 = a20*a33 - a23*a30; - float b09 = a21*a32 - a22*a31; - float b10 = a21*a33 - a23*a31; - float b11 = a22*a33 - a23*a32; + 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 a30 = mat->m12, a31 = mat->m13, a32 = mat->m14, a33 = mat->m15; - // 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 b00 = a00*a11 - a01*a10; + float b01 = a00*a12 - a02*a10; + float b02 = a00*a13 - a03*a10; + float b03 = a01*a12 - a02*a11; + float b04 = a01*a13 - a03*a11; + float b05 = a02*a13 - a03*a12; + float b06 = a20*a31 - a21*a30; + float b07 = a20*a32 - a22*a30; + float b08 = a20*a33 - a23*a30; + float b09 = a21*a32 - a22*a31; + float b10 = a21*a33 - a23*a31; + float b11 = a22*a33 - a23*a32; + + // Calculate the invert determinant (inlined to avoid double-caching) + float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); printf("%f\n", invDet); - - temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; - temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; - temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; - temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; - temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; - temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; - temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; - temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; - temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; - temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; - temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; - temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; - temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; - temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; - temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; - temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; + + temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; + temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; + temp.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; + temp.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; + temp.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; + temp.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; + temp.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; + temp.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; + temp.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; + temp.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; + temp.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; + temp.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; + temp.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; + temp.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; + temp.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; + temp.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; PrintMatrix(temp); - - *mat = temp; + + *mat = temp; } // Normalize provided matrix @@ -337,21 +359,21 @@ void MatrixNormalize(Matrix *mat) float det = MatrixDeterminant(*mat); mat->m0 /= det; - mat->m1 /= det; - mat->m2 /= det; - mat->m3 /= det; - mat->m4 /= det; - mat->m5 /= det; - mat->m6 /= det; - mat->m7 /= det; - mat->m8 /= det; - mat->m9 /= det; - mat->m10 /= det; - mat->m11 /= det; - mat->m12 /= det; - mat->m13 /= det; - mat->m14 /= det; - mat->m15 /= det; + mat->m1 /= det; + mat->m2 /= det; + mat->m3 /= det; + mat->m4 /= det; + mat->m5 /= det; + mat->m6 /= det; + mat->m7 /= det; + mat->m8 /= det; + mat->m9 /= det; + mat->m10 /= det; + mat->m11 /= det; + mat->m12 /= det; + mat->m13 /= det; + mat->m14 /= det; + mat->m15 /= det; } // Returns identity matrix @@ -368,21 +390,21 @@ Matrix MatrixAdd(Matrix left, Matrix right) Matrix result = MatrixIdentity(); result.m0 = left.m0 + right.m0; - result.m1 = left.m1 + right.m1; - result.m2 = left.m2 + right.m2; - result.m3 = left.m3 + right.m3; - result.m4 = left.m4 + right.m4; - result.m5 = left.m5 + right.m5; - result.m6 = left.m6 + right.m6; - result.m7 = left.m7 + right.m7; - result.m8 = left.m8 + right.m8; - result.m9 = left.m9 + right.m9; - result.m10 = left.m10 + right.m10; - result.m11 = left.m11 + right.m11; - result.m12 = left.m12 + right.m12; - result.m13 = left.m13 + right.m13; - result.m14 = left.m14 + right.m14; - result.m15 = left.m15 + right.m15; + result.m1 = left.m1 + right.m1; + result.m2 = left.m2 + right.m2; + result.m3 = left.m3 + right.m3; + result.m4 = left.m4 + right.m4; + result.m5 = left.m5 + right.m5; + result.m6 = left.m6 + right.m6; + result.m7 = left.m7 + right.m7; + result.m8 = left.m8 + right.m8; + result.m9 = left.m9 + right.m9; + result.m10 = left.m10 + right.m10; + result.m11 = left.m11 + right.m11; + result.m12 = left.m12 + right.m12; + result.m13 = left.m13 + right.m13; + result.m14 = left.m14 + right.m14; + result.m15 = left.m15 + right.m15; return result; } @@ -393,21 +415,21 @@ Matrix MatrixSubstract(Matrix left, Matrix right) Matrix result = MatrixIdentity(); result.m0 = left.m0 - right.m0; - result.m1 = left.m1 - right.m1; - result.m2 = left.m2 - right.m2; - result.m3 = left.m3 - right.m3; - result.m4 = left.m4 - right.m4; - result.m5 = left.m5 - right.m5; - result.m6 = left.m6 - right.m6; - result.m7 = left.m7 - right.m7; - result.m8 = left.m8 - right.m8; - result.m9 = left.m9 - right.m9; - result.m10 = left.m10 - right.m10; - result.m11 = left.m11 - right.m11; - result.m12 = left.m12 - right.m12; - result.m13 = left.m13 - right.m13; - result.m14 = left.m14 - right.m14; - result.m15 = left.m15 - right.m15; + result.m1 = left.m1 - right.m1; + result.m2 = left.m2 - right.m2; + result.m3 = left.m3 - right.m3; + result.m4 = left.m4 - right.m4; + result.m5 = left.m5 - right.m5; + result.m6 = left.m6 - right.m6; + result.m7 = left.m7 - right.m7; + result.m8 = left.m8 - right.m8; + result.m9 = left.m9 - right.m9; + result.m10 = left.m10 - right.m10; + result.m11 = left.m11 - right.m11; + result.m12 = left.m12 - right.m12; + result.m13 = left.m13 - right.m13; + result.m14 = left.m14 - right.m14; + result.m15 = left.m15 - right.m15; return result; } @@ -476,51 +498,51 @@ Matrix MatrixFromAxisAngle(Vector3 axis, float angle) 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; - x *= length; - y *= length; - z *= length; - } - - float s = sin(angle); - float c = cos(angle); - float t = 1-c; - - // Cache some matrix values (speed optimization) - 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 a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; - - // 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 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; - - // Perform rotation-specific matrix multiplication - result.m0 = a00*b00 + a10*b01 + a20*b02; - result.m1 = a01*b00 + a11*b01 + a21*b02; - result.m2 = a02*b00 + a12*b01 + a22*b02; - result.m3 = a03*b00 + a13*b01 + a23*b02; - result.m4 = a00*b10 + a10*b11 + a20*b12; - result.m5 = a01*b10 + a11*b11 + a21*b12; - result.m6 = a02*b10 + a12*b11 + a22*b12; - result.m7 = a03*b10 + a13*b11 + a23*b12; - result.m8 = a00*b20 + a10*b21 + a20*b22; - result.m9 = a01*b20 + a11*b21 + a21*b22; - result.m10 = a02*b20 + a12*b21 + a22*b22; - result.m11 = a03*b20 + a13*b21 + a23*b22; - result.m12 = mat.m12; - result.m13 = mat.m13; - result.m14 = mat.m14; - result.m15 = mat.m15; + length = 1 / length; + x *= length; + y *= length; + z *= length; + } - return result; + float s = sin(angle); + float c = cos(angle); + float t = 1-c; + + // Cache some matrix values (speed optimization) + 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 a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; + + // 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 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; + + // Perform rotation-specific matrix multiplication + result.m0 = a00*b00 + a10*b01 + a20*b02; + result.m1 = a01*b00 + a11*b01 + a21*b02; + result.m2 = a02*b00 + a12*b01 + a22*b02; + result.m3 = a03*b00 + a13*b01 + a23*b02; + result.m4 = a00*b10 + a10*b11 + a20*b12; + result.m5 = a01*b10 + a11*b11 + a21*b12; + result.m6 = a02*b10 + a12*b11 + a22*b12; + result.m7 = a03*b10 + a13*b11 + a23*b12; + result.m8 = a00*b20 + a10*b21 + a20*b22; + result.m9 = a01*b20 + a11*b21 + a21*b22; + result.m10 = a02*b20 + a12*b21 + a22*b22; + result.m11 = a03*b20 + a13*b21 + a23*b22; + result.m12 = mat.m12; + result.m13 = mat.m13; + result.m14 = mat.m14; + result.m15 = mat.m15; + + return result; }; // Create rotation matrix from axis and angle @@ -645,35 +667,35 @@ Matrix MatrixMultiply(Matrix left, Matrix right) { Matrix result; - // Cache the matrix values (speed optimization) - 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 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 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 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; - - result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30; - result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31; - result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32; - result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33; - result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30; - result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31; - result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32; - result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33; - result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30; - result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31; - result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32; - result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33; - result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30; - result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31; - result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32; - result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33; - - return result; + // Cache the matrix values (speed optimization) + 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 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 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 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; + + result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30; + result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31; + result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32; + result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33; + result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30; + result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31; + result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32; + result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33; + result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30; + result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31; + result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32; + result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33; + result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30; + result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31; + result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32; + result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33; + + return result; } // Returns perspective projection matrix @@ -681,28 +703,28 @@ Matrix MatrixFrustum(double left, double right, double bottom, double top, doubl { Matrix result; - float rl = (right - left); - float tb = (top - bottom); - float fn = (far - near); + float rl = (right - left); + float tb = (top - bottom); + float fn = (far - near); - result.m0 = (near*2) / rl; - result.m1 = 0; - result.m2 = 0; - result.m3 = 0; - result.m4 = 0; - result.m5 = (near*2) / tb; - result.m6 = 0; - result.m7 = 0; - result.m8 = (right + left) / rl; - result.m9 = (top + bottom) / tb; - result.m10 = -(far + near) / fn; - result.m11 = -1; - result.m12 = 0; - result.m13 = 0; - result.m14 = -(far*near*2) / fn; - result.m15 = 0; + result.m0 = (near*2) / rl; + result.m1 = 0; + result.m2 = 0; + result.m3 = 0; + result.m4 = 0; + result.m5 = (near*2) / tb; + result.m6 = 0; + result.m7 = 0; + result.m8 = (right + left) / rl; + result.m9 = (top + bottom) / tb; + result.m10 = -(far + near) / fn; + result.m11 = -1; + result.m12 = 0; + result.m13 = 0; + result.m14 = -(far*near*2) / fn; + result.m15 = 0; - return result; + return result; } // Returns perspective projection matrix @@ -720,25 +742,25 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double Matrix result; float rl = (right - left); - float tb = (top - bottom); - float fn = (far - near); - + float tb = (top - bottom); + float fn = (far - near); + result.m0 = 2 / rl; - result.m1 = 0; - result.m2 = 0; - result.m3 = 0; - result.m4 = 0; - result.m5 = 2 / tb; - result.m6 = 0; - result.m7 = 0; - result.m8 = 0; - result.m9 = 0; - result.m10 = -2 / fn; - result.m11 = 0; - result.m12 = -(left + right) / rl; - result.m13 = -(top + bottom) / tb; - result.m14 = -(far + near) / fn; - result.m15 = 1; + result.m1 = 0; + result.m2 = 0; + result.m3 = 0; + result.m4 = 0; + result.m5 = 2 / tb; + result.m6 = 0; + result.m7 = 0; + result.m8 = 0; + result.m9 = 0; + result.m10 = -2 / fn; + result.m11 = 0; + result.m12 = -(left + right) / rl; + result.m13 = -(top + bottom) / tb; + result.m14 = -(far + near) / fn; + result.m15 = 1; return result; } @@ -747,7 +769,7 @@ Matrix MatrixOrtho(double left, double right, double bottom, double top, double Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) { Matrix result; - + Vector3 z = VectorSubtract(eye, target); VectorNormalize(&z); Vector3 x = VectorCrossProduct(up, z); @@ -793,7 +815,7 @@ void PrintMatrix(Matrix m) // Calculates the length of a quaternion 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 @@ -818,15 +840,15 @@ Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) { Quaternion result; - 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; - - result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby; - result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz; - result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx; - result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz; - - return result; + 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; + + result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby; + result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz; + result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx; + result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz; + + return result; } // Calculates spherical linear interpolation between two quaternions @@ -834,9 +856,9 @@ Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) { Quaternion result; - 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; + 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; else { 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.w = (q1.w*ratioA + q2.w*ratioB); } - } + } - return result; + return result; } // Returns a quaternion from a given rotation matrix @@ -947,42 +969,42 @@ Matrix QuaternionToMatrix(Quaternion q) { 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 y2 = y + y; - float z2 = z + z; + float x2 = x + x; + float y2 = y + y; + float z2 = z + z; - float xx = x*x2; - float xy = x*y2; - float xz = x*z2; + float xx = x*x2; + float xy = x*y2; + float xz = x*z2; - float yy = y*y2; - float yz = y*z2; - float zz = z*z2; + float yy = y*y2; + float yz = y*z2; + float zz = z*z2; - float wx = w*x2; - float wy = w*y2; - float wz = w*z2; + float wx = w*x2; + float wy = w*y2; + float wz = w*z2; - result.m0 = 1 - (yy + zz); - result.m1 = xy - wz; - result.m2 = xz + wy; - result.m3 = 0; - result.m4 = xy + wz; - result.m5 = 1 - (xx + zz); - result.m6 = yz - wx; - result.m7 = 0; - result.m8 = xz - wy; - result.m9 = yz + wx; - result.m10 = 1 - (xx + yy); - result.m11 = 0; - result.m12 = 0; - result.m13 = 0; - result.m14 = 0; - result.m15 = 1; - - return result; + result.m0 = 1 - (yy + zz); + result.m1 = xy - wz; + result.m2 = xz + wy; + result.m3 = 0; + result.m4 = xy + wz; + result.m5 = 1 - (xx + zz); + result.m6 = yz - wx; + result.m7 = 0; + result.m8 = xz - wy; + result.m9 = yz + wx; + result.m10 = 1 - (xx + yy); + result.m11 = 0; + result.m12 = 0; + result.m13 = 0; + result.m14 = 0; + result.m15 = 1; + + return result; } // Returns the axis and the angle for a given quaternion diff --git a/src/raymath.h b/src/raymath.h index 49cceafb..69a6a582 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -91,6 +91,8 @@ void VectorNormalize(Vector3 *v); // Normalize provided ve 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 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 diff --git a/src/rlgl.c b/src/rlgl.c new file mode 100644 index 00000000..63ed9ec4 --- /dev/null +++ b/src/rlgl.c @@ -0,0 +1,1364 @@ +/********************************************************************************************* +* +* 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+ +* +* 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. +* +**********************************************************************************************/ + +#include "rlgl.h" + +#include // Standard input / output lib +#include // Declares malloc() and free() for memory management, rand() + +#include "raymath.h" // Required for data type Matrix and Matrix functions + +#ifdef USE_OPENGL_11 + #include // Extensions loading lib +#endif + +#ifdef USE_OPENGL_33 + #define GLEW_STATIC + #include // Extensions loading lib +#endif + +//#include "glad.h" // Extensions loading lib? --> REVIEW + +#define USE_VBO_DOUBLE_BUFFERS // Enable VBO double buffers usage --> REVIEW! + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MATRIX_STACK_SIZE 16 // TODO: REVIEW: Matrix stack required? +#define MAX_DRAWS_BY_TEXTURE 256 // Draws are organized by texture changes +#define TEMP_VERTEX_BUFFER_SIZE 1024 // Temporal Vertex Buffer (required for post-transformations) + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef struct { + int numQuads; + int texId; +} QuadsByTexture; + +typedef struct { + int vCounter; + int cCounter; + float *vertices; // 3 components per vertex + float *colors; // 4 components per vertex +} VertexPositionColorBuffer; + +typedef struct { + int vCounter; + int tcCounter; + int cCounter; + float *vertices; // 3 components per vertex + float *texcoords; // 2 components per vertex + float *colors; // 4 components per vertex +} VertexPositionColorTextureBuffer; + +typedef struct { + int vCounter; + int tcCounter; + int cCounter; + float *vertices; // 3 components per vertex + float *texcoords; // 2 components per vertex + float *colors; // 4 components per vertex + unsigned int *indices; // 6 indices per quad +} VertexPositionColorTextureIndexBuffer; + +typedef struct { + GLuint texId; + int firstVertex; // Actually, when using glDrawElements, this parameter is useless.. + int vCount; +} DrawCall; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) +static Matrix stack[MATRIX_STACK_SIZE]; +static int stackCounter = 0; + +static Matrix modelview; +static Matrix projection; +static Matrix *currentMatrix; +static int currentMatrixMode; + +static DrawMode currentDrawMode; + +// Vertex arrays for lines, triangles and quads +static VertexPositionColorBuffer lines; +static VertexPositionColorTextureBuffer triangles; +static VertexPositionColorTextureIndexBuffer quads; + +// Vetex-Fragment Shader Program ID +static GLuint shaderProgram; + +// Shader program attibutes binding locations +static GLuint vertexLoc, texcoordLoc, colorLoc; +static GLuint projectionMatrixLoc, modelviewMatrixLoc; +static GLuint textureLoc; + +// Vertex Array Objects (VAO) +static GLuint vaoLines, vaoTriangles, vaoQuads; + +// Vertex Buffer Objects (VBO) +static GLuint linesBuffer[2]; +static GLuint trianglesBuffer[2]; +static GLuint quadsBuffer[4]; + +#ifdef USE_VBO_DOUBLE_BUFFERS +// Double buffering +// TODO: REVIEW -> Not getting any performance improvement... why? +static GLuint vaoQuadsB; +static GLuint quadsBufferB[4]; +static bool useBufferB = false; +#endif + +static DrawCall *draws; +static int drawsCounter; + +// Temp vertex buffer to be used with rlTranslate, rlRotate, rlScale +static Vector3 *tempBuffer; +static int tempBufferCount = 0; +static bool useTempBuffer = false; + +// White texture useful for plain color polys (required by shader) +static GLuint whiteTexture; +#endif + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) +static GLuint LoadDefaultShaders(); +static void InitializeBuffers(); +static void InitializeVAOs(); +static void UpdateBuffers(); + +// Shader files loading (external) - Not used but useful... +static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName); +static char *TextFileRead(char *fn); +#endif + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Matrix operations +//---------------------------------------------------------------------------------- + +#ifdef USE_OPENGL_11 + +// Fallback to OpenGL 1.1 function calls +//--------------------------------------- +void rlMatrixMode(int mode) +{ + switch (mode) + { + case RL_PROJECTION: glMatrixMode(GL_PROJECTION); break; + case RL_MODELVIEW: glMatrixMode(GL_MODELVIEW); break; + case RL_TEXTURE: glMatrixMode(GL_TEXTURE); break; + default: break; + } +} + +void rlFrustum(double left, double right, double bottom, double top, double near, double far) +{ + glFrustum(left, right, bottom, top, near, far); +} + +void rlOrtho(double left, double right, double bottom, double top, double near, double far) +{ + glOrtho(left, right, bottom, top, near, far); +} + +void rlPushMatrix() { glPushMatrix(); } +void rlPopMatrix() { glPopMatrix(); } +void rlLoadIdentity() { glLoadIdentity(); } +void rlTranslatef(float x, float y, float z) { glTranslatef(x, y, z); } +void rlRotatef(float angleDeg, float x, float y, float z) { glRotatef(angleDeg, x, y, z); } +void rlScalef(float x, float y, float z) { glScalef(x, y, z); } +void rlMultMatrixf(float *mat) { glMultMatrixf(mat); } + +#else + +// Choose the current matrix to be transformed +void rlMatrixMode(int mode) +{ + if (mode == RL_PROJECTION) currentMatrix = &projection; + else if (mode == RL_MODELVIEW) currentMatrix = &modelview; + //else if (mode == GL_TEXTURE) TODO: NEVER USED! + + currentMatrixMode = mode; +} + +// Push the current matrix to stack +void rlPushMatrix() +{ + if (stackCounter == MATRIX_STACK_SIZE - 1) + { + printf("ERROR: Stack Buffer Overflow! (MAX 16 MATRIX)"); + + exit(1); + } + + stack[stackCounter] = *currentMatrix; + rlLoadIdentity(); + stackCounter++; + + if (currentMatrixMode == RL_MODELVIEW) useTempBuffer = true; +} + +// Pop lattest inserted matrix from stack +void rlPopMatrix() +{ + if (stackCounter > 0) + { + Matrix mat = stack[stackCounter - 1]; + *currentMatrix = mat; + stackCounter--; + } +} + +// Reset current matrix to identity matrix +void rlLoadIdentity() +{ + *currentMatrix = MatrixIdentity(); +} + +// Multiply the current matrix by a translation matrix +void rlTranslatef(float x, float y, float z) +{ + Matrix mat = MatrixTranslate(x, y, z); + + *currentMatrix = MatrixMultiply(*currentMatrix, mat); +} + +// Multiply the current matrix by a rotation matrix +void rlRotatef(float angleDeg, float x, float y, float z) +{ + // TODO: Rotation matrix --> REVIEW! + Matrix rot = MatrixIdentity(); + + if (x == 1) rot = MatrixRotateX(angleDeg*DEG2RAD); + else if (y == 1) rot = MatrixRotateY(angleDeg*DEG2RAD); + else if (z == 1) rot = MatrixRotateZ(angleDeg*DEG2RAD); + + *currentMatrix = MatrixMultiply(*currentMatrix, rot); +} + +// Multiply the current matrix by a scaling matrix +void rlScalef(float x, float y, float z) +{ + Matrix mat = MatrixScale(x, y, z); + + *currentMatrix = MatrixMultiply(*currentMatrix, mat); +} + +// Multiply the current matrix by another matrix +void rlMultMatrixf(float *m) +{ + // TODO: review Matrix creation from array + Matrix mat = { m[0], m[1], m[2], m[3], + m[4], m[5], m[6], m[7], + m[8], m[9], m[10], m[11], + m[12], m[13], m[14], m[15] }; + + *currentMatrix = MatrixMultiply(*currentMatrix, mat); +} + +// Multiply the current matrix by a perspective matrix generated by parameters +void rlFrustum(double left, double right, double bottom, double top, double near, double far) +{ + Matrix matPerps = MatrixFrustum(left, right, bottom, top, near, far); + MatrixTranspose(&matPerps); + + *currentMatrix = MatrixMultiply(*currentMatrix, matPerps); +} + +// Multiply the current matrix by an orthographic matrix generated by parameters +void rlOrtho(double left, double right, double bottom, double top, double near, double far) +{ + Matrix matOrtho = MatrixOrtho(left, right, bottom, top, near, far); + MatrixTranspose(&matOrtho); + + *currentMatrix = MatrixMultiply(*currentMatrix, matOrtho); +} + +#endif + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Vertex level operations +//---------------------------------------------------------------------------------- +#ifdef USE_OPENGL_11 + +// Fallback to OpenGL 1.1 function calls +//--------------------------------------- +void rlBegin(int mode) +{ + switch (mode) + { + case RL_LINES: glBegin(GL_LINES); break; + case RL_TRIANGLES: glBegin(GL_TRIANGLES); break; + case RL_QUADS: glBegin(GL_QUADS); break; + default: break; + } +} + +void rlEnd() { glEnd(); } +void rlVertex2i(int x, int y) { glVertex2i(x, y); } +void rlVertex2f(float x, float y) { glVertex2f(x, y); } +void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); } +void rlTexCoord2f(float x, float y) { glTexCoord2f(x, y); } +void rlNormal3f(float x, float y, float z) { glNormal3f(x, y, z); } +void rlColor4ub(byte r, byte g, byte b, byte a) { glColor4ub(r, g, b, a); } +void rlColor3f(float x, float y, float z) { glColor3f(x, y, z); } +void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); } + +#else + +// Initialize drawing mode (how to organize vertex) +void rlBegin(int mode) +{ + // Draw mode can only be RL_LINES, RL_TRIANGLES and RL_QUADS + currentDrawMode = mode; +} + +// Finish vertex providing +void rlEnd() +{ + if (useTempBuffer) + { + // IT WORKS!!! --> Refactor... + Matrix mat = *currentMatrix; + MatrixTranspose(&mat); + + // Apply transformation matrix to all temp vertices + for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], mat); + + // Deactivate tempBuffer usage to allow rlVertex3f do its job + useTempBuffer = false; + + // Copy all transformed vertices to right VAO + for (int i = 0; i < tempBufferCount; i++) rlVertex3f(tempBuffer[i].x, tempBuffer[i].y, tempBuffer[i].z); + + // Reset temp buffer + tempBufferCount = 0; + } + + // Make sure vertexCounter is the same for vertices-texcoords-normals-colors + // NOTE: In OpenGL 1.1, one glColor call can be made for all the subsequent glVertex calls. + switch (currentDrawMode) + { + case RL_LINES: + { + if (lines.vCounter != lines.cCounter) + { + int addColors = lines.vCounter - lines.cCounter; + + for (int i = 0; i < addColors; i++) + { + lines.colors[4*lines.cCounter] = lines.colors[4*lines.cCounter - 4]; + lines.colors[4*lines.cCounter + 1] = lines.colors[4*lines.cCounter - 3]; + lines.colors[4*lines.cCounter + 2] = lines.colors[4*lines.cCounter - 2]; + lines.colors[4*lines.cCounter + 3] = lines.colors[4*lines.cCounter - 1]; + + lines.cCounter++; + } + } + } break; + case RL_TRIANGLES: + { + if (triangles.vCounter != triangles.cCounter) + { + int addColors = triangles.vCounter - triangles.cCounter; + + for (int i = 0; i < addColors; i++) + { + triangles.colors[4*triangles.cCounter] = triangles.colors[4*triangles.cCounter - 4]; + triangles.colors[4*triangles.cCounter + 1] = triangles.colors[4*triangles.cCounter - 3]; + triangles.colors[4*triangles.cCounter + 2] = triangles.colors[4*triangles.cCounter - 2]; + triangles.colors[4*triangles.cCounter + 3] = triangles.colors[4*triangles.cCounter - 1]; + + triangles.cCounter++; + } + } + } break; + case RL_QUADS: + { + // Make sure colors count match vertex count + if (quads.vCounter != quads.cCounter) + { + int addColors = quads.vCounter - quads.cCounter; + + for (int i = 0; i < addColors; i++) + { + quads.colors[4*quads.cCounter] = quads.colors[4*quads.cCounter - 4]; + quads.colors[4*quads.cCounter + 1] = quads.colors[4*quads.cCounter - 3]; + quads.colors[4*quads.cCounter + 2] = quads.colors[4*quads.cCounter - 2]; + quads.colors[4*quads.cCounter + 3] = quads.colors[4*quads.cCounter - 1]; + + quads.cCounter++; + } + } + + // Make sure texcoords count match vertex count + if (quads.vCounter != quads.tcCounter) + { + int addTexCoords = quads.vCounter - quads.tcCounter; + + for (int i = 0; i < addTexCoords; i++) + { + quads.texcoords[2*quads.tcCounter] = 0.0f; + quads.texcoords[2*quads.tcCounter + 1] = 0.0f; + + quads.tcCounter++; + } + } + + // TODO: Make sure normals count match vertex count + + } break; + default: break; + } +} + +// Define one vertex (position) +void rlVertex3f(float x, float y, float z) +{ + if (useTempBuffer) + { + tempBuffer[tempBufferCount].x = x; + tempBuffer[tempBufferCount].y = y; + tempBuffer[tempBufferCount].z = z; + tempBufferCount++; + } + else + { + switch (currentDrawMode) + { + case RL_LINES: + { + lines.vertices[3*lines.vCounter] = x; + lines.vertices[3*lines.vCounter + 1] = y; + lines.vertices[3*lines.vCounter + 2] = z; + + lines.vCounter++; + + } break; + case RL_TRIANGLES: + { + triangles.vertices[3*triangles.vCounter] = x; + triangles.vertices[3*triangles.vCounter + 1] = y; + triangles.vertices[3*triangles.vCounter + 2] = z; + + triangles.vCounter++; + + } break; + case RL_QUADS: + { + quads.vertices[3*quads.vCounter] = x; + quads.vertices[3*quads.vCounter + 1] = y; + quads.vertices[3*quads.vCounter + 2] = z; + + quads.vCounter++; + + draws[drawsCounter - 1].vCount++; + + } break; + default: break; + } + } +} + +// Define one vertex (position) +void rlVertex2f(float x, float y) +{ + rlVertex3f(x, y, 0.0); +} + +// Define one vertex (position) +void rlVertex2i(int x, int y) +{ + rlVertex3f((float)x, (float)y, 0.0); +} + +// Define one vertex (texture coordinate) +// NOTE: Texture coordinates are limited to TRIANGLES only +void rlTexCoord2f(float x, float y) +{ + if (currentDrawMode == RL_QUADS) + { + quads.texcoords[2*quads.tcCounter] = x; + quads.texcoords[2*quads.tcCounter + 1] = y; + + quads.tcCounter++; + } +} + +// Define one vertex (normal) +// NOTE: Normals limited to TRIANGLES only ? +void rlNormal3f(float x, float y, float z) +{ + // TODO: Normals usage... +} + +// Define one vertex (color) +void rlColor4f(float x, float y, float z, float w) +{ + switch (currentDrawMode) + { + case RL_LINES: + { + lines.colors[4*lines.cCounter] = x; + lines.colors[4*lines.cCounter + 1] = y; + lines.colors[4*lines.cCounter + 2] = z; + lines.colors[4*lines.cCounter + 3] = w; + + lines.cCounter++; + + } break; + case RL_TRIANGLES: + { + triangles.colors[4*triangles.cCounter] = x; + triangles.colors[4*triangles.cCounter + 1] = y; + triangles.colors[4*triangles.cCounter + 2] = z; + triangles.colors[4*triangles.cCounter + 3] = w; + + triangles.cCounter++; + + } break; + case RL_QUADS: + { + quads.colors[4*quads.cCounter] = x; + quads.colors[4*quads.cCounter + 1] = y; + quads.colors[4*quads.cCounter + 2] = z; + quads.colors[4*quads.cCounter + 3] = w; + + quads.cCounter++; + + } break; + default: break; + } +} + +// Define one vertex (color) +void rlColor4ub(byte r, byte g, byte b, byte a) +{ + rlColor4f((float)r/255, (float)g/255, (float)b/255, (float)a/255); +} + +// Define one vertex (color) +void rlColor3f(float x, float y, float z) +{ + rlColor4f(x, y, z, 1.0); +} + +#endif + +//---------------------------------------------------------------------------------- +// Module Functions Definition - OpenGL equivalent functions (common to 1.1, 3.3+, ES2) +//---------------------------------------------------------------------------------- + +// Enable texture usage +void rlEnableTexture(unsigned int id) +{ +#ifdef USE_OPENGL_11 + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, id); +#endif + +#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) + if (draws[drawsCounter - 1].texId != id) + { + if (draws[drawsCounter - 1].vCount > 0) drawsCounter++; + + draws[drawsCounter - 1].texId = id; + draws[drawsCounter - 1].firstVertex = draws[drawsCounter - 2].vCount; + draws[drawsCounter - 1].vCount = 0; + } +#endif +} + +// Disable texture usage +void rlDisableTexture() +{ +#ifdef USE_OPENGL_11 + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); +#endif +} + +// Unload texture from GPU memory +void rlDeleteTextures(unsigned int id) +{ + glDeleteTextures(1, &id); +} + +// Clear color buffer with color +void rlClearColor(byte r, byte g, byte b, byte a) +{ + // Color values clamp to 0.0f(0) and 1.0f(255) + float cr = (float)r / 255; + float cg = (float)g / 255; + float cb = (float)b / 255; + float ca = (float)a / 255; + + glClearColor(cr, cg, cb, ca); +} + +// Clear used screen buffers (color and depth) +void rlClearScreenBuffers() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers: Color and Depth (Depth is used for 3D) + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Stencil buffer not used... +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - rlgl Functions +//---------------------------------------------------------------------------------- + +#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) + +// Init OpenGL 3.3+ required data +void rlglInit() +{ + // Initialize GLEW + glewExperimental = 1; // Needed for core profile + + GLenum error = glewInit(); + + if (error != GLEW_OK) + { + fprintf(stderr, "Failed to initialize GLEW - Error: %s\n", glewGetErrorString(error)); + exit(1); + } + + if (glewIsSupported("GL_VERSION_3_3")) printf("OpenGL 3.3 initialized\n"); +/* + if (!gladLoadGL()) + { + printf("Something went wrong!\n"); + exit(-1); + } +*/ + // Set default draw mode + currentDrawMode = RL_TRIANGLES; + + // Reset projection and modelview matrices + projection = MatrixIdentity(); + modelview = MatrixIdentity(); + currentMatrix = &modelview; + + // Initialize matrix stack + for (int i = 0; i < MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity(); + + // Init default Shader (GLSL 110) -> Common for GL 3.3+ and ES2 + shaderProgram = LoadDefaultShaders(); + //shaderProgram = LoadShaders("simple150.vert", "simple150.frag"); + + // Get handles to GLSL input vars locations + vertexLoc = glGetAttribLocation(shaderProgram, "vertexPosition"); + texcoordLoc = glGetAttribLocation(shaderProgram, "vertexTexCoord"); + colorLoc = glGetAttribLocation(shaderProgram, "vertexColor"); + + // Get handles to GLSL uniform vars locations (vertex-shader) + modelviewMatrixLoc = glGetUniformLocation(shaderProgram, "modelviewMatrix"); + projectionMatrixLoc = glGetUniformLocation(shaderProgram, "projectionMatrix"); + + // Get handles to GLSL uniform vars locations (fragment-shader) + textureLoc = glGetUniformLocation(shaderProgram, "texture0"); + + printf("Default shaders loaded\n\n"); + + // Print OpenGL and GLSL version + printf("Vendor: %s\n", glGetString(GL_VENDOR)); + printf("Renderer: %s\n", glGetString(GL_RENDERER)); + printf("Version: %s\n", glGetString(GL_VERSION)); + printf("GLSL: %s\n\n", glGetString(0x8B8C)); // GL_SHADING_LANGUAGE_VERSION + + InitializeBuffers(); // Init vertex arrays + InitializeVAOs(); // Init VBO and VAO + + // Init temp vertex buffer, used when transformation required (translate, rotate, scale) + tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); + + for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = VectorZero(); + + // Create default white texture for plain colors (required by shader) + unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) + + whiteTexture = rlglTexture(1, 1, pixels); + + // Init draw calls tracking system + draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE); + + for (int i = 0; i < MAX_DRAWS_BY_TEXTURE; i++) + { + draws[i].texId = 0; + draws[i].firstVertex = 0; + draws[i].vCount = 0; + } + + drawsCounter = 1; + draws[drawsCounter - 1].texId = whiteTexture; +} + +// Vertex Buffer Object deinitialization (memory free) +void rlglClose() +{ + // Unbind everything + glBindVertexArray(0); + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(2); + glDisableVertexAttribArray(3); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glUseProgram(0); + + // Delete VAOs and VBOs + glDeleteBuffers(1, &linesBuffer[0]); + glDeleteBuffers(1, &linesBuffer[1]); + glDeleteBuffers(1, &trianglesBuffer[0]); + glDeleteBuffers(1, &trianglesBuffer[1]); + glDeleteBuffers(1, &quadsBuffer[0]); + glDeleteBuffers(1, &quadsBuffer[1]); + glDeleteBuffers(1, &quadsBuffer[2]); + glDeleteBuffers(1, &quadsBuffer[3]); + + glDeleteVertexArrays(1, &vaoLines); + glDeleteVertexArrays(1, &vaoTriangles); + glDeleteVertexArrays(1, &vaoQuads); + + //glDetachShader(shaderProgram, v); + //glDetachShader(shaderProgram, f); + //glDeleteShader(v); + //glDeleteShader(f); + glDeleteProgram(shaderProgram); + + // Free vertex arrays memory + free(lines.vertices); + free(lines.colors); + + free(triangles.vertices); + free(triangles.colors); + + free(quads.vertices); + free(quads.texcoords); + free(quads.colors); + + // Free GPU texture + glDeleteTextures(1, &whiteTexture); +} + +void rlglDraw() +{ + glUseProgram(shaderProgram); // Use our shader + + glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection)); + glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelview)); + glUniform1i(textureLoc, 0); + + UpdateBuffers(); + + if (lines.vCounter > 0) + { + glBindTexture(GL_TEXTURE_2D, whiteTexture); + + glBindVertexArray(vaoLines); + glDrawArrays(GL_LINES, 0, lines.vCounter); + + glBindTexture(GL_TEXTURE_2D, 0); + } + + if (triangles.vCounter > 0) + { + glBindVertexArray(vaoTriangles); + glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); + } + + if (quads.vCounter > 0) + { + int numQuads = 0; + int numIndicesToProcess = 0; + int indicesOffset = 0; + +#ifdef USE_VBO_DOUBLE_BUFFERS + // Depending on useBufferB, use Buffer A or Buffer B + if (useBufferB) glBindVertexArray(vaoQuadsB); + else +#endif + { + glBindVertexArray(vaoQuads); + } + + //printf("\nRequired Draws: %i\n", drawsCounter); + + for (int i = 0; i < drawsCounter; i++) + { + numQuads = draws[i].vCount/4; + numIndicesToProcess = numQuads*6; // Get number of Quads * 6 index by Quad + + //printf("Quads to render: %i - ", numQuads); + //printf("Vertex Count: %i - ", draws[i].vCount); + //printf("Binding texture: %i\n", draws[i].texId); + + glBindTexture(GL_TEXTURE_2D, draws[i].texId); + + // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); + + indicesOffset += draws[i].vCount/4*6; + + //printf("-------Next vertex offset: %i\n", indicesOffset/6*4); + } + } + + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + glBindVertexArray(0); // Unbind VAO + + // Reset draws counter + drawsCounter = 1; + draws[0].texId = whiteTexture; + draws[0].firstVertex = 0; + draws[0].vCount = 0; + + // Reset vertex counters for next frame + lines.vCounter = 0; + lines.cCounter = 0; + + triangles.vCounter = 0; + triangles.vCounter = 0; + + quads.vCounter = 0; + quads.tcCounter = 0; + quads.cCounter = 0; + + // TODO: Review double buffer performance -> no improvement! (?) +#ifdef USE_VBO_DOUBLE_BUFFERS + useBufferB = !useBufferB; // Change buffers usage! +#endif +} + +#endif + +// Initialize Graphics Device (OpenGL stuff) +void rlglInitGraphicsDevice(int fbWidth, int fbHeight) +{ + //glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height + // NOTE: Not required, viewport will be full window space + + // NOTE: Don't confuse glViewport with the transformation matrix + // NOTE: glViewport just defines the area of the context that you will actually draw to. + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear used buffers, depth buffer is used for 3D + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color (black) + //glClearDepth(1.0f); // Clear depth buffer (default) + + 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) + +#ifdef USE_OPENGL_11 + 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) +#endif + + rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix + rlLoadIdentity(); // Reset current matrix (PROJECTION) + + rlOrtho(0, fbWidth, fbHeight, 0, 0, 1); // Config orthographic mode: top-left corner --> (0,0) + + rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix + rlLoadIdentity(); // 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) + +#ifdef USE_OPENGL_11 + glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) (Deprecated on OpenGL 3.3+) + // Possible options: GL_SMOOTH (Color interpolation) or GL_FLAT (no interpolation) +#endif +} + +// Convert image data to OpenGL texture (returns OpenGL valid Id) +// NOTE: Image is not unloaded, it should be done manually... +unsigned int rlglTexture(int width, int height, unsigned char *pixels) +{ + glBindTexture(GL_TEXTURE_2D,0); // Free any old binding + + GLuint id; + glGenTextures(1, &id); // Generate Pointer to the texture + + //glActiveTexture(GL_TEXTURE0); + 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 + +#ifdef USE_OPENGL_33 + // 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! +#endif + + // NOTE: Not using mipmappings (texture for 2D drawing) + // At this point we have the image converted to texture and uploaded to GPU + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + // At this point we have the image converted to texture and uploaded to GPU + + // Unbind current texture + glBindTexture(GL_TEXTURE_2D, 0); + + printf("New texture created, id: %i (%i x %i)\n", id, width, height); + + return id; +} + +// Read screen pixel data (color buffer) +unsigned char *rlglReadScreenPixels(int width, int height) +{ + unsigned char *screenData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4); + + // NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData); + + // Flip image vertically! + unsigned char *imgData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4); + + for (int y = height-1; y >= 0; y--) + { + for (int x = 0; x < (width*4); x++) + { + imgData[x + (height - y - 1)*width*4] = screenData[x + (y*width*4)]; + } + } + + free(screenData); + + return imgData; // NOTE: image data should be freed +} + +#ifdef USE_OPENGL_33 + +void PrintProjectionMatrix() +{ + PrintMatrix(projection); +} + +void PrintModelviewMatrix() +{ + PrintMatrix(modelview); +} + +#endif + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2) + +// Load Shaders (Vertex and Fragment) +static GLuint LoadDefaultShaders() +{ + // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 + + // Vertex shader directly defined, no external file required + char vShaderStr[] = " #version 110 \n" // Equivalent to version 100 on ES2 + "uniform mat4 projectionMatrix; \n" + "uniform mat4 modelviewMatrix; \n" + "attribute vec3 vertexPosition; \n" + "attribute vec2 vertexTexCoord; \n" + "attribute vec4 vertexColor; \n" + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" + "void main() \n" + "{ \n" + " fragTexCoord = vertexTexCoord; \n" + " fragColor = vertexColor; \n" + " gl_Position = projectionMatrix * modelviewMatrix * vec4(vertexPosition, 1.0); \n" + "} \n"; + + // Fragment shader directly defined, no external file required + char fShaderStr[] = " #version 110 \n" // Equivalent to version 100 on ES2 + "uniform sampler2D texture0; \n" + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D(texture0, fragTexCoord) * fragColor; \n" + "} \n"; + + GLuint program; + GLuint vertexShader; + GLuint fragmentShader; + + vertexShader = glCreateShader(GL_VERTEX_SHADER); + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + const char *pvs = vShaderStr; + const char *pfs = fShaderStr; + + glShaderSource(vertexShader, 1, &pvs, NULL); + glShaderSource(fragmentShader, 1, &pfs, NULL); + + glCompileShader(vertexShader); + glCompileShader(fragmentShader); + + program = glCreateProgram(); + + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + + glLinkProgram(program); + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + return(program); +} + + +// Load Shaders +static GLuint LoadShaders(char *vertexFileName, char *fragmentFileName) +{ + // Shaders loading from external text file + char *vShaderStr = TextFileRead(vertexFileName); + char *fShaderStr = TextFileRead(fragmentFileName); + + GLuint program; + GLuint vertexShader; + GLuint fragmentShader; + + vertexShader = glCreateShader(GL_VERTEX_SHADER); + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + const char *pvs = vShaderStr; + const char *pfs = fShaderStr; + + glShaderSource(vertexShader, 1, &pvs, NULL); + glShaderSource(fragmentShader, 1, &pfs, NULL); + + glCompileShader(vertexShader); + glCompileShader(fragmentShader); + + program = glCreateProgram(); + + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + + glLinkProgram(program); + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + + return(program); +} + +// Read shader text file +static char *TextFileRead(char *fn) +{ + FILE *fp; + char *content = NULL; + + int count=0; + + if (fn != NULL) + { + fp = fopen(fn,"rt"); + + if (fp != NULL) + { + fseek(fp, 0, SEEK_END); + count = ftell(fp); + rewind(fp); + + if (count > 0) + { + content = (char *)malloc(sizeof(char) * (count+1)); + count = fread(content, sizeof(char), count, fp); + content[count] = '\0'; + } + + fclose(fp); + } + } + return content; +} + +// Allocate and initialize float array buffers to store vertex data (lines, triangles, quads) +static void InitializeBuffers() +{ + // Initialize lines arrays (vertex position and color data) + lines.vertices = (float *)malloc(sizeof(float)*3*2*MAX_LINES_BATCH); // 3 float by vertex, 2 vertex by line + lines.colors = (float *)malloc(sizeof(float)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line + + for (int i = 0; i < (3*2*MAX_LINES_BATCH); i++) lines.vertices[i] = 0.0; + for (int i = 0; i < (4*2*MAX_LINES_BATCH); i++) lines.colors[i] = 0.0; + + lines.vCounter = 0; + lines.cCounter = 0; + + // Initialize triangles arrays (vertex position and color data) + triangles.vertices = (float *)malloc(sizeof(float)*3*3*MAX_TRIANGLES_BATCH); // 3 float by vertex, 3 vertex by triangle + triangles.colors = (float *)malloc(sizeof(float)*4*3*MAX_TRIANGLES_BATCH); // 4 float by color, 3 colors by triangle + + for (int i = 0; i < (3*3*MAX_TRIANGLES_BATCH); i++) triangles.vertices[i] = 0.0; + for (int i = 0; i < (4*3*MAX_TRIANGLES_BATCH); i++) triangles.colors[i] = 0.0; + + triangles.vCounter = 0; + triangles.cCounter = 0; + + // Initialize quads arrays (vertex position, texcoord and color data... and indexes) + quads.vertices = (float *)malloc(sizeof(float)*3*4*MAX_QUADS_BATCH); // 3 float by vertex, 4 vertex by quad + quads.texcoords = (float *)malloc(sizeof(float)*2*4*MAX_QUADS_BATCH); // 2 float by texcoord, 4 texcoord by quad + quads.colors = (float *)malloc(sizeof(float)*4*4*MAX_QUADS_BATCH); // 4 float by color, 4 colors by quad + quads.indices = (unsigned int *)malloc(sizeof(int)*6*MAX_QUADS_BATCH); // 6 int by quad (indices) + + for (int i = 0; i < (3*4*MAX_QUADS_BATCH); i++) quads.vertices[i] = 0.0; + for (int i = 0; i < (2*4*MAX_QUADS_BATCH); i++) quads.texcoords[i] = 0.0; + for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0.0; + + int k = 0; + + // Indices can be initialized right now + for (int i = 0; i < (6*MAX_QUADS_BATCH); i+=6) + { + quads.indices[i] = 4*k; + quads.indices[i+1] = 4*k+1; + quads.indices[i+2] = 4*k+2; + quads.indices[i+3] = 4*k; + quads.indices[i+4] = 4*k+2; + quads.indices[i+5] = 4*k+3; + + k++; + } + + quads.vCounter = 0; + quads.tcCounter = 0; + quads.cCounter = 0; +} + +// Initialize Vertex Array Objects (Contain VBO) +static void InitializeVAOs() +{ + // Initialize Lines VAO + glGenVertexArrays(1, &vaoLines); + glBindVertexArray(vaoLines); + + // Create buffers for our vertex data + glGenBuffers(2, linesBuffer); + + // Lines - Vertex positions buffer binding and attributes enable + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(vertexLoc); + glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); + + // Lines - colors buffer + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(colorLoc); + glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); + + //-------------------------------------------------------------- + + // Initialize Triangles VAO + glGenVertexArrays(1, &vaoTriangles); + glBindVertexArray(vaoTriangles); + + // Create buffers for our vertex data + glGenBuffers(2, trianglesBuffer); + + // Enable vertex attributes + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(vertexLoc); + glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(colorLoc); + glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); + + //-------------------------------------------------------------- + + // Initialize Quads VAO (Buffer A) + glGenVertexArrays(1, &vaoQuads); + glBindVertexArray(vaoQuads); + + // Create buffers for our vertex data + glGenBuffers(4, quadsBuffer); + + // Enable vertex attributes + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(vertexLoc); + glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(texcoordLoc); + glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(colorLoc); + glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); + + // Fill index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); + +#ifdef USE_VBO_DOUBLE_BUFFERS + // Initialize Quads VAO (Buffer B) + glGenVertexArrays(1, &vaoQuadsB); + glBindVertexArray(vaoQuadsB); + + // Create buffers for our vertex data + glGenBuffers(4, quadsBufferB); + + // Enable vertex attributes + glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(vertexLoc); + glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(texcoordLoc); + glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[2]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(colorLoc); + glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0); + + // Fill index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBufferB[3]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); + + printf("Using VBO double buffering\n"); +#endif + + printf("Vertex buffers initialized (lines, triangles, quads)\n\n"); + + // Unbind the current VAO + glBindVertexArray(0); +} + +// Update VBOs with vertex array data +static void UpdateBuffers() +{ + // Activate Lines VAO + glBindVertexArray(vaoLines); + + // Lines - vertex positions buffer + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*lines.vCounter, lines.vertices); // target - offset (in bytes) - size (in bytes) - data pointer + + // Lines - colors buffer + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*lines.vCounter, lines.colors); + + //-------------------------------------------------------------- + + // Activate Triangles VAO + glBindVertexArray(vaoTriangles); + + // Triangles - vertex positions buffer + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); + + // Triangles - colors buffer + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); + + //-------------------------------------------------------------- + + // Depending on useBufferB, update Buffer A or Buffer B +#ifdef USE_VBO_DOUBLE_BUFFERS + if (useBufferB) + { + // Activate Quads VAO (Buffer B) + glBindVertexArray(vaoQuadsB); + + // Quads - vertex positions buffer + glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[0]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*quads.vCounter, quads.vertices); + + // Quads - texture coordinates buffer + glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[1]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords); + + // Quads - colors buffer + glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[2]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*quads.vCounter, quads.colors); + } + else +#endif + { + // Activate Quads VAO (Buffer A) + glBindVertexArray(vaoQuads); + + // Quads - vertex positions buffer + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*quads.vCounter, quads.vertices); + + // Quads - texture coordinates buffer + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords); + + // Quads - colors buffer + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); + //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*quads.vCounter, quads.colors); + } + + //-------------------------------------------------------------- + + // Unbind the current VAO + glBindVertexArray(0); +} + +#endif \ No newline at end of file diff --git a/src/rlgl.h b/src/rlgl.h new file mode 100644 index 00000000..b4033050 --- /dev/null +++ b/src/rlgl.h @@ -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 \ No newline at end of file diff --git a/src/shapes.c b/src/shapes.c index 07a73cad..838a9efa 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -25,10 +25,11 @@ #include "raylib.h" -#include // OpenGL functions #include // Required for abs() function #include // Math related functions, sin() and cos() used on DrawCircle* // 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 @@ -57,149 +58,116 @@ // Draw a pixel void DrawPixel(int posX, int posY, Color color) { - glBegin(GL_POINTS); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2i(posX, posY); - glEnd(); - - // 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); -*/ + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2i(posX, posY); + rlVertex2i(posX + 1, posY + 1); + rlEnd(); } // Draw a pixel (Vector version) void DrawPixelV(Vector2 position, Color color) { - glBegin(GL_POINTS); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(position.x, position.y); - glEnd(); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(position.x, position.y); + rlVertex2i(position.x + 1, position.y + 1); + rlEnd(); } // Draw a line void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color) { - glBegin(GL_LINES); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2i(startPosX, startPosY); - glVertex2i(endPosX, endPosY); - glEnd(); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2i(startPosX, startPosY); + rlVertex2i(endPosX, endPosY); + rlEnd(); } // Draw a line (Vector version) void DrawLineV(Vector2 startPos, Vector2 endPos, Color color) { - glBegin(GL_LINES); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(startPos.x, startPos.y); - glVertex2f(endPos.x, endPos.y); - glEnd(); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(startPos.x, startPos.y); + rlVertex2f(endPos.x, endPos.y); + rlEnd(); } // Draw a color-filled circle // 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) { - glEnable(GL_POLYGON_SMOOTH); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); // Deprecated on OGL 3.0 - 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 // NOTE: Gradient goes from center (color1) to border (color2) void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2) { - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color1.r, color1.g, color1.b, color1.a); - glVertex2i(centerX, centerY); - glColor4ub(color2.r, color2.g, color2.b, color2.a); - - for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels + rlBegin(RL_TRIANGLES); + for (int i=0; i <= 360; i += 2) //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) void DrawCircleV(Vector2 center, float radius, Color color) { - glEnable(GL_POLYGON_SMOOTH); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); - - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(center.x, center.y); - - for (int i=0; i <= 360; i++) //i++ --> Step = 1.0 pixels + rlBegin(RL_TRIANGLES); + for (int i=0; i < 360; i += 2) { - 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(); - - glDisable(GL_POLYGON_SMOOTH); + rlEnd(); } // Draw circle outline void DrawCircleLines(int centerX, int centerY, float radius, Color color) { - glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) + //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) - glBegin(GL_LINE_LOOP); - glColor4ub(color.r, color.g, color.b, color.a); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360) for (int i=0; i < 360; i++) { - glVertex2f(centerX + sin(DEG2RAD*i) * radius, centerY + cos(DEG2RAD*i) * radius); + 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 -/* - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - DrawCircle(centerX, centerY, radius, color); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -*/ - glDisable(GL_LINE_SMOOTH); + //glDisable(GL_LINE_SMOOTH); + + // TODO: Draw all lines with line smooth??? --> Do it before drawing lines VAO } // Draw a color-filled rectangle void DrawRectangle(int posX, int posY, int width, int height, Color color) { - glBegin(GL_QUADS); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2i(posX, posY); - glVertex2i(posX + width, posY); - glVertex2i(posX + width, posY + height); - glVertex2i(posX, posY + height); - glEnd(); + rlBegin(RL_QUADS); + rlColor4ub(color.r, color.g, color.b, color.a); + rlTexCoord2f(0.0f, 0.0f); + rlVertex2i(posX, posY); + rlTexCoord2f(0.0f, 1.0f); + rlVertex2i(posX, posY + height); + 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 @@ -212,73 +180,73 @@ void DrawRectangleRec(Rectangle rec, Color color) // NOTE: Gradient goes from bottom (color1) to top (color2) void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2) { - glBegin(GL_QUADS); - glColor4ub(color1.r, color1.g, color1.b, color1.a); - glVertex2i(posX, posY); - glVertex2i(posX + width, posY); - glColor4ub(color2.r, color2.g, color2.b, color2.a); - glVertex2i(posX + width, posY + height); - glVertex2i(posX, posY + height); - glEnd(); + rlBegin(RL_QUADS); + rlColor4ub(color1.r, color1.g, color1.b, color1.a); + rlVertex2i(posX, posY); + rlColor4ub(color1.r, color1.g, color1.b, color1.a); + rlVertex2i(posX, posY + height); + rlColor4ub(color2.r, color2.g, color2.b, color2.a); + rlVertex2i(posX + width, posY + height); + rlColor4ub(color2.r, color2.g, color2.b, color2.a); + rlVertex2i(posX + width, posY); + rlEnd(); } // Draw a color-filled rectangle (Vector version) void DrawRectangleV(Vector2 position, Vector2 size, Color color) { - glBegin(GL_QUADS); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2i(position.x, position.y); - glVertex2i(position.x + size.x, position.y); - glVertex2i(position.x + size.x, position.y + size.y); - glVertex2i(position.x, position.y + size.y); - glEnd(); + rlBegin(RL_QUADS); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2i(position.x, position.y); + rlVertex2i(position.x, position.y + size.y); + rlVertex2i(position.x + size.x, position.y + size.y); + rlVertex2i(position.x + size.x, position.y); + rlEnd(); } // Draw rectangle outline void DrawRectangleLines(int posX, int posY, int width, int height, Color color) { - //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) - //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) - - // NOTE: Lines are rasterized using the "Diamond Exit" rule so, it's nearly impossible to obtain a pixel-perfect engine - // NOTE: Recommended trying to avoid using lines, at least >1.0f pixel lines with anti-aliasing (glLineWidth function) - - glBegin(GL_LINE_LOOP); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2i(posX, posY); - glVertex2i(posX + width - 1, posY); - glVertex2i(posX + width - 1, posY + height - 1); - glVertex2i(posX, posY + height - 1); - glEnd(); - -// NOTE: Alternative method to draw rectangle outline -/* - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - DrawRectangle(posX, posY, width - 1, height - 1, color); - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -*/ - //glDisable(GL_LINE_SMOOTH); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2i(posX, posY); + rlVertex2i(posX + width - 1, posY); + + rlVertex2i(posX + width - 1, posY); + rlVertex2i(posX + width - 1, posY + height - 1); + + rlVertex2i(posX + width - 1, posY + height - 1); + rlVertex2i(posX, posY + height - 1); + + rlVertex2i(posX, posY + height - 1); + rlVertex2i(posX, posY); + rlEnd(); } // Draw a triangle void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) { - glBegin(GL_TRIANGLES); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(v1.x, v1.y); - glVertex2f(v2.x, v2.y); - glVertex2f(v3.x, v3.y); - glEnd(); + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(v1.x, v1.y); + rlVertex2f(v2.x, v2.y); + rlVertex2f(v3.x, v3.y); + rlEnd(); } void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color) { - glBegin(GL_LINE_LOOP); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(v1.x, v1.y); - glVertex2f(v2.x, v2.y); - glVertex2f(v3.x, v3.y); - glEnd(); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex2f(v1.x, v1.y); + rlVertex2f(v2.x, v2.y); + + 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) @@ -286,20 +254,20 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col { if (sides < 3) sides = 3; - glPushMatrix(); - glTranslatef(center.x, center.y, 0); - glRotatef(rotation, 0, 0, 1); - - glBegin(GL_TRIANGLE_FAN); - glColor4ub(color.r, color.g, color.b, color.a); - glVertex2f(0, 0); + rlPushMatrix(); - for (int i=0; i <= sides; i++) - { - glVertex2f(radius*cos(i*2*PI/sides), radius*sin(i*2*PI/sides)); + rlRotatef(rotation, 0, 0, 1); // TODO: compute vertex rotation manually! + + rlBegin(RL_TRIANGLES); + for (int i=0; i < 360; i += 2) + { + 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(); - glPopMatrix(); + rlEnd(); + rlPopMatrix(); } // Draw a closed polygon defined by points @@ -308,19 +276,16 @@ void DrawPolyEx(Vector2 *points, int numPoints, Color color) { if (numPoints >= 3) { - glEnable(GL_POLYGON_SMOOTH); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); - - glBegin(GL_POLYGON); - glColor4ub(color.r, color.g, color.b, color.a); + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); - for (int i = 0; i < numPoints; i++) + for (int i = 0; i < numPoints - 2; 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(); - - glDisable(GL_POLYGON_SMOOTH); + rlEnd(); } } @@ -330,22 +295,22 @@ void DrawPolyExLines(Vector2 *points, int numPoints, Color color) { if (numPoints >= 2) { - //glEnable(GL_LINE_SMOOTH); // Smoothies circle outline (anti-aliasing applied) - //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); // Best quality for line smooth (anti-aliasing best algorithm) - - glBegin(GL_LINE_LOOP); - glColor4ub(color.r, color.g, color.b, color.a); + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); - for (int i = 0; i < numPoints; i++) + for (int i = 0; i < numPoints - 1; 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(); - - //glDisable(GL_LINE_SMOOTH); + rlEnd(); } } +//---------------------------------------------------------------------------------- +// Module Functions Definition - Collision Detection functions +//---------------------------------------------------------------------------------- + // Check if point is inside rectangle bool CheckCollisionPointRec(Vector2 point, Rectangle rec) { diff --git a/src/simple150.frag b/src/simple150.frag index 61b337ed..74a727dd 100644 --- a/src/simple150.frag +++ b/src/simple150.frag @@ -11,5 +11,4 @@ void main() { // Output pixel color pixelColor = texture(texture0, fragTexCoord) * fragColor; - //pixelColor = fragColor; } \ No newline at end of file diff --git a/src/text.c b/src/text.c index 492329c5..b897f1f3 100644 --- a/src/text.c +++ b/src/text.c @@ -28,12 +28,13 @@ #include "raylib.h" -#include // OpenGL functions #include // Declares malloc() and free() for memory management #include // String management functions (just strlen() is used) #include // Used for functions with variable number of parameters (FormatText()) #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 //---------------------------------------------------------------------------------- @@ -63,6 +64,11 @@ struct Character { static SpriteFont defaultFont; // Default font provided by raylib // NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core] +//---------------------------------------------------------------------------------- +// Other Modules Functions Declaration (required by text) +//---------------------------------------------------------------------------------- +//... + //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -78,9 +84,11 @@ static const char *GetExtension(const char *fileName); extern void LoadDefaultFont() { defaultFont.numChars = 96; // We know our default font has 94 chars - defaultFont.texture.width = 128; // We know our default font texture is 128 pixels width - defaultFont.texture.height = 64; // We know our default font texture is 64 pixels height - + + 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) // This way, we reconstruct SpriteFont without creating large global variables // This data is automatically allocated to Stack and automatically deallocated at the end of this function @@ -115,7 +123,31 @@ 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, 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 //------------------------------------------------------------------------------ defaultFont.charSet = (Character *)malloc(defaultFont.numChars * sizeof(Character)); // Allocate space for our character data @@ -145,53 +177,11 @@ extern void LoadDefaultFont() } else currentPosX = testPosX; } - - // Re-construct image from defaultFontData and generate OpenGL texture - //---------------------------------------------------------------------- - Color *imgDataPixel = (Color *)malloc(defaultFont.texture.width * defaultFont.texture.height * sizeof(Color)); - - for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i++) imgDataPixel[i] = BLANK; // Initialize array - - int counter = 0; // Font data elements counter - - // Fill imgData with defaultFontData (convert from bit to pixel!) - for (int i = 0; i < defaultFont.texture.width * defaultFont.texture.height; i += 32) - { - for (int j = 31; j >= 0; j--) - { - if (BIT_CHECK(defaultFontData[counter], j)) imgDataPixel[i+j] = WHITE; - } - - counter++; - - if (counter > 256) counter = 0; // Security check... - } - - // Convert loaded data to OpenGL texture - //---------------------------------------- - GLuint id; - glGenTextures(1, &id); // Generate pointer to the texture - - glBindTexture(GL_TEXTURE_2D, id); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // Set texture to clamp on x-axis - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // Set texture to clamp on y-axis - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, defaultFont.texture.width, defaultFont.texture.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixel); - - // NOTE: Not using mipmappings (texture for 2D drawing) - // At this point we have the image converted to texture and uploaded to GPU - - free(imgDataPixel); // Now we can free loaded data from RAM memory - - defaultFont.texture.glId = id; } extern void UnloadDefaultFont() { - glDeleteTextures(1, &defaultFont.texture.glId); + rlDeleteTextures(defaultFont.texture.glId); free(defaultFont.charSet); } @@ -206,6 +196,8 @@ SpriteFont LoadSpriteFont(const char* fileName) { SpriteFont spriteFont; + Image image; + // Check file extension if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); else @@ -270,24 +262,13 @@ SpriteFont LoadSpriteFont(const char* fileName) free(imgDataPixel); - // Convert loaded data to OpenGL texture - //---------------------------------------- - GLuint id; - glGenTextures(1, &id); // Generate pointer to the texture + image.pixels = imgDataPixelPOT; + image.width = potWidth; + image.height = potHeight; - glBindTexture(GL_TEXTURE_2D, id); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, potWidth, potHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imgDataPixelPOT); - - // NOTE: Not using mipmappings (texture for 2D drawing) - // At this point we have the image converted to texture and uploaded to GPU - - free(imgDataPixelPOT); // Now we can free loaded data from RAM memory - - spriteFont.texture.glId = id; - spriteFont.texture.width = potWidth; - spriteFont.texture.height = potHeight; + spriteFont.texture = CreateTexture(image); // Convert loaded image to OpenGL texture + + UnloadImage(image); } return spriteFont; @@ -296,7 +277,7 @@ SpriteFont LoadSpriteFont(const char* fileName) // Unload SpriteFont from GPU memory void UnloadSpriteFont(SpriteFont spriteFont) { - glDeleteTextures(1, &spriteFont.texture.glId); + rlDeleteTextures(spriteFont.texture.glId); 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; else scaleFactor = (float)fontSize / spriteFont.charSet[0].h; - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, spriteFont.texture.glId); + rlEnableTexture(spriteFont.texture.glId); // Optimized to use one draw call per string - glBegin(GL_QUADS); + rlBegin(RL_QUADS); for(int i = 0; i < length; i++) { c = spriteFont.charSet[(int)text[i] - FONT_FIRST_CHAR]; - glColor4ub(tint.r, tint.g, tint.b, tint.a); - glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer - glTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX, position.y); - glTexCoord2f((float)c.x / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX, position.y + (c.h) * scaleFactor); - glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)(c.y + c.h) / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y + (c.h) * scaleFactor); - glTexCoord2f((float)(c.x + c.w) / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); glVertex2f(positionX + (c.w) * scaleFactor, position.y); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); + rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer + + rlTexCoord2f((float)c.x / spriteFont.texture.width, (float)c.y / spriteFont.texture.height); + rlVertex2f(positionX, 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); } - glEnd(); - - glDisable(GL_TEXTURE_2D); + rlEnd(); + + rlDisableTexture(); } // Formatting of text with variables to 'embed' @@ -417,21 +404,18 @@ void DrawFPS(int posX, int posY) char buffer[20]; if (counter < refreshRate) - { - sprintf(buffer, "%2.0f FPS", fps); - DrawText(buffer, posX, posY, 20, LIME); - + { counter++; } else { fps = GetFPS(); refreshRate = fps; - sprintf(buffer, "%2.0f FPS", fps); - DrawText(buffer, posX, posY, 20, LIME); - counter = 0; } + + sprintf(buffer, "%2.0f FPS", fps); + DrawText(buffer, posX, posY, 20, LIME); } //---------------------------------------------------------------------------------- diff --git a/src/textures.c b/src/textures.c index ca0492c4..f8402b0c 100644 --- a/src/textures.c +++ b/src/textures.c @@ -28,12 +28,13 @@ #include "raylib.h" -#include // OpenGL functions #include // Declares malloc() and free() for memory management #include "stb_image.h" // Used to read image data (multiple formats support) #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 //---------------------------------------------------------------------------------- @@ -49,6 +50,11 @@ typedef unsigned char byte; //---------------------------------------------------------------------------------- // It's lonely here... +//---------------------------------------------------------------------------------- +// Other Modules Functions Declaration (required by text) +//---------------------------------------------------------------------------------- +//... + //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -238,43 +244,6 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId) 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) void UnloadImage(Image image) { @@ -284,7 +253,7 @@ void UnloadImage(Image image) // Unload texture from GPU memory void UnloadTexture(Texture2D texture) { - glDeleteTextures(1, &texture.glId); + rlDeleteTextures(texture.glId); } // Draw a Texture2D @@ -302,101 +271,126 @@ void DrawTextureV(Texture2D texture, Vector2 position, Color tint) // Draw a Texture2D with extended parameters void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint) { - glEnable(GL_TEXTURE_2D); // Enable textures usage + 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 point is upper-left corner - glTranslatef(position.x, position.y, 0); - glScalef(scale, scale, 1.0f); - glRotatef(rotation, 0, 0, 1); + // NOTE: Rotation is applied before translation and scaling, even being called in inverse order... + // NOTE: Rotation point is upper-left corner + //rlTranslatef(position.x, position.y, 0); + //rlScalef(scale, scale, 1.0f); + //rlRotatef(rotation, 0, 0, 1); - glBegin(GL_QUADS); - glColor4ub(tint.r, tint.g, tint.b, tint.a); - glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer - glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); // Bottom-left corner for texture and quad - glTexCoord2f(1.0f, 0.0f); glVertex2f(texture.width, 0.0f); // Bottom-right corner for texture and quad - glTexCoord2f(1.0f, 1.0f); glVertex2f(texture.width, texture.height); // Top-right corner for texture and quad - glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, texture.height); // Top-left corner for texture and quad - glEnd(); - glPopMatrix(); + rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); + rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer + + 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(); - glDisable(GL_TEXTURE_2D); // Disable textures usage + rlDisableTexture(); } // Draw a part of a texture (defined by a rectangle) 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); - - glPushMatrix(); - glTranslatef(position.x, position.y, 0); - //glScalef(1.0f, 1.0f, 1.0f); - //glRotatef(rotation, 0, 0, 1); + rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); + rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer - glBegin(GL_QUADS); - glColor4ub(tint.r, tint.g, tint.b, tint.a); - glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer - - // Bottom-left corner for texture and quad - glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); - glVertex2f(0.0f, 0.0f); - - // Bottom-right corner for texture and quad - glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); - glVertex2f(sourceRec.width, 0.0f); - - // Top-right corner for texture and quad - glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); - glVertex2f(sourceRec.width, sourceRec.height); - - // Top-left corner for texture and quad - glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); - glVertex2f(0.0f, sourceRec.height); - glEnd(); - glPopMatrix(); + // Bottom-left corner for texture and quad + rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); + rlVertex2f(position.x, position.y); + + // Bottom-right corner for texture and quad + rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlVertex2f(position.x, position.y + sourceRec.height); + + // Top-right corner for texture and quad + rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlVertex2f(position.x + sourceRec.width, position.y + sourceRec.height); + + // Top-left corner for texture and quad + rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); + rlVertex2f(position.x + sourceRec.width, position.y); + rlEnd(); - glDisable(GL_TEXTURE_2D); // Disable textures usage + rlDisableTexture(); } // Draw a part of a texture (defined by a rectangle) with 'pro' parameters // TODO: Test this function... 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(); - glTranslatef(-origin.x, -origin.y, 0); - glRotatef(rotation, 0, 0, 1); - glTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0); + //rlTranslatef(-origin.x, -origin.y, 0); + //rlRotatef(rotation, 0, 0, 1); + //rlTranslatef(destRec.x + origin.x, destRec.y + origin.y, 0); - glBegin(GL_QUADS); - glColor4ub(tint.r, tint.g, tint.b, tint.a); - glNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer - - // Bottom-left corner for texture and quad - glTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); - glVertex2f(0.0f, 0.0f); - - // Bottom-right corner for texture and quad - glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); - glVertex2f(destRec.width, 0.0f); - - // Top-right corner for texture and quad - glTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); - glVertex2f(destRec.width, destRec.height); - - // Top-left corner for texture and quad - glTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); - glVertex2f(0.0f, destRec.height); - glEnd(); - glPopMatrix(); + rlBegin(RL_QUADS); + rlColor4ub(tint.r, tint.g, tint.b, tint.a); + rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer + + // Bottom-left corner for texture and quad + rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); + rlVertex2f(0.0f, 0.0f); + + // Bottom-right corner for texture and quad + rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); + rlVertex2f(destRec.width, 0.0f); + + // Top-right corner for texture and quad + rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlVertex2f(destRec.width, destRec.height); + + // Top-left corner for texture and quad + rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlVertex2f(0.0f, destRec.height); + rlEnd(); - 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; } \ No newline at end of file diff --git a/src/vector3.c b/src/vector3.c deleted file mode 100644 index 6b0e1573..00000000 --- a/src/vector3.c +++ /dev/null @@ -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 // 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; -} diff --git a/src/vector3.h b/src/vector3.h deleted file mode 100644 index 6c0ead6d..00000000 --- a/src/vector3.h +++ /dev/null @@ -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 \ No newline at end of file