Browse Source

Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop

victorfisac 9 years ago
parent
commit
8ae0da1fa1
16 changed files with 1669 additions and 1082 deletions
  1. 13 11
      examples/physics_basic_rigidbody.c
  2. 20 17
      examples/physics_rigidbody_force.c
  3. 44 1
      src/core.c
  4. 43 29
      src/easings.h
  5. 3 3
      src/models.c
  6. 18 14
      src/physac.c
  7. 4 3
      src/physac.h
  8. 6 6
      src/raylib.h
  9. 226 188
      src/raymath.h
  10. 2 0
      src/rlgl.c
  11. 5 4
      src/rlgl.h
  12. 349 213
      src/stb_image.h
  13. 446 132
      src/stb_image_write.h
  14. 35 21
      src/stb_truetype.h
  15. 418 412
      src/stb_vorbis.c
  16. 37 28
      src/stb_vorbis.h

+ 13 - 11
examples/physics_basic_rigidbody.c

@@ -32,28 +32,30 @@ int main()
     int screenHeight = 450;
     int screenHeight = 450;
     
     
     InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody");
     InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody");
-    SetTargetFPS(60);   // Enable v-sync
+
     InitPhysics();      // Initialize internal physics values   (max rigidbodies/colliders available: 1024)
     InitPhysics();      // Initialize internal physics values   (max rigidbodies/colliders available: 1024)
     
     
     // Physics initialization
     // Physics initialization
-    Physics worldPhysics = {true, false, (Vector2){0, -9.81f}};
+    Physics worldPhysics = { true, false, (Vector2){ 0, -9.81f } };
     
     
     // Set internal physics settings
     // Set internal physics settings
     SetPhysics(worldPhysics);
     SetPhysics(worldPhysics);
     
     
     // Object initialization
     // Object initialization
     Transform player = (Transform){(Vector2){(screenWidth - OBJECT_SIZE) / 2, (screenHeight - OBJECT_SIZE) / 2}, 0.0f, (Vector2){OBJECT_SIZE, OBJECT_SIZE}};
     Transform player = (Transform){(Vector2){(screenWidth - OBJECT_SIZE) / 2, (screenHeight - OBJECT_SIZE) / 2}, 0.0f, (Vector2){OBJECT_SIZE, OBJECT_SIZE}};
-    AddCollider(PLAYER_INDEX, (Collider){true, RectangleCollider, (Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, 0});
+    AddCollider(PLAYER_INDEX, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, 0});
     AddRigidbody(PLAYER_INDEX, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 1.0f});
     AddRigidbody(PLAYER_INDEX, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 1.0f});
     
     
     // Floor initialization 
     // Floor initialization 
     // NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody)
     // NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody)
     Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}};
     Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}};
-    AddCollider(PLAYER_INDEX + 1, (Collider){true, RectangleCollider, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0});
+    AddCollider(PLAYER_INDEX + 1, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0});
     
     
     // Object properties initialization
     // Object properties initialization
     float moveSpeed = 6.0f;
     float moveSpeed = 6.0f;
-    float jumpForce = 4.5f;
+    float jumpForce = 5.0f;
+    
+    SetTargetFPS(60);
     //--------------------------------------------------------------------------------------
     //--------------------------------------------------------------------------------------
 
 
     // Main game loop
     // Main game loop
@@ -67,7 +69,7 @@ int main()
         ApplyPhysics(PLAYER_INDEX, &player.position);
         ApplyPhysics(PLAYER_INDEX, &player.position);
         
         
         // Check jump button input
         // Check jump button input
-        if(IsKeyDown(KEY_SPACE) && GetRigidbody(PLAYER_INDEX).isGrounded)
+        if (IsKeyDown(KEY_SPACE) && GetRigidbody(PLAYER_INDEX).isGrounded)
         {
         {
             // Reset object Y velocity to avoid double jumping cases but keep the same X velocity that it already has
             // Reset object Y velocity to avoid double jumping cases but keep the same X velocity that it already has
             SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){GetRigidbody(PLAYER_INDEX).velocity.x, 0});
             SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){GetRigidbody(PLAYER_INDEX).velocity.x, 0});
@@ -77,12 +79,12 @@ int main()
         }
         }
         
         
         // Check movement buttons input
         // Check movement buttons input
-        if(IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D))
+        if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D))
         {
         {
             // Set rigidbody velocity in X based on moveSpeed value and apply the same Y velocity that it already has
             // Set rigidbody velocity in X based on moveSpeed value and apply the same Y velocity that it already has
             SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y});
             SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y});
         }
         }
-        else if(IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A))
+        else if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A))
         {
         {
             // Set rigidbody velocity in X based on moveSpeed negative value and apply the same Y velocity that it already has
             // Set rigidbody velocity in X based on moveSpeed negative value and apply the same Y velocity that it already has
             SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){-moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y});
             SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){-moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y});
@@ -110,12 +112,12 @@ int main()
             DrawText("Use P to switch DEBUG MODE", (screenWidth - MeasureText("Use P to switch DEBUG MODE", 20)) / 2, screenHeight * 0.3f, 20, LIGHTGRAY);
             DrawText("Use P to switch DEBUG MODE", (screenWidth - MeasureText("Use P to switch DEBUG MODE", 20)) / 2, screenHeight * 0.3f, 20, LIGHTGRAY);
             
             
             // Check if debug mode is enabled
             // Check if debug mode is enabled
-            if(worldPhysics.debug)
+            if (worldPhysics.debug)
             {
             {
                 // Draw every internal physics stored collider if it is active
                 // Draw every internal physics stored collider if it is active
-                for(int i = 0; i < 2; i++)
+                for (int i = 0; i < 2; i++)
                 {
                 {
-                    if(GetCollider(i).enabled)
+                    if (GetCollider(i).enabled)
                     {
                     {
                         DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN);
                         DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN);
                     }
                     }

+ 20 - 17
examples/physics_rigidbody_force.c

@@ -11,11 +11,11 @@
 
 
 #include "raylib.h"
 #include "raylib.h"
 
 
-#define MAX_OBJECTS 5
-#define OBJECTS_OFFSET 150
+#define MAX_OBJECTS           5
+#define OBJECTS_OFFSET      150
 
 
-#define FORCE_INTENSITY 250.0f  // Customize by user
-#define FORCE_RADIUS 100        // Customize by user    
+#define FORCE_INTENSITY  250.0f     // Customize by user
+#define FORCE_RADIUS        100     // Customize by user    
 
 
 int main()
 int main()
 {
 {
@@ -25,7 +25,7 @@ int main()
     int screenHeight = 450;
     int screenHeight = 450;
     
     
     InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces");
     InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces");
-    SetTargetFPS(60);   // Enable v-sync
+
     InitPhysics();      // Initialize internal physics values   (max rigidbodies/colliders available: 1024)
     InitPhysics();      // Initialize internal physics values   (max rigidbodies/colliders available: 1024)
     
     
     // Physics initialization
     // Physics initialization
@@ -36,17 +36,20 @@ int main()
     
     
     // Objects initialization
     // Objects initialization
     Transform objects[MAX_OBJECTS];
     Transform objects[MAX_OBJECTS];
-    for(int i = 0; i < MAX_OBJECTS; i++)
+    
+    for (int i = 0; i < MAX_OBJECTS; i++)
     {
     {
         objects[i] = (Transform){(Vector2){75 + OBJECTS_OFFSET * i, (screenHeight - 50) / 2}, 0.0f, (Vector2){50, 50}};
         objects[i] = (Transform){(Vector2){75 + OBJECTS_OFFSET * i, (screenHeight - 50) / 2}, 0.0f, (Vector2){50, 50}};
-        AddCollider(i, (Collider){true, RectangleCollider, (Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, 0});
+        AddCollider(i, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, 0});
         AddRigidbody(i, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 0.5f});
         AddRigidbody(i, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 0.5f});
     }
     }
     
     
     // Floor initialization 
     // Floor initialization 
     // NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody)
     // NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody)
     Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}};
     Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}};
-    AddCollider(MAX_OBJECTS, (Collider){true, RectangleCollider, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0});
+    AddCollider(MAX_OBJECTS, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0});
+
+    SetTargetFPS(60);
     //--------------------------------------------------------------------------------------
     //--------------------------------------------------------------------------------------
 
 
     // Main game loop
     // Main game loop
@@ -57,19 +60,19 @@ int main()
         
         
         // Update object physics 
         // Update object physics 
         // NOTE: all physics detections and reactions are calculated in ApplyPhysics() function (You will live happier :D)
         // NOTE: all physics detections and reactions are calculated in ApplyPhysics() function (You will live happier :D)
-        for(int i = 0; i < MAX_OBJECTS; i++)
+        for (int i = 0; i < MAX_OBJECTS; i++)
         {
         {
             ApplyPhysics(i, &objects[i].position);
             ApplyPhysics(i, &objects[i].position);
         }
         }
         
         
         // Check foce button input
         // Check foce button input
-        if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+        if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
         {
         {
             AddForceAtPosition(GetMousePosition(), FORCE_INTENSITY, FORCE_RADIUS);
             AddForceAtPosition(GetMousePosition(), FORCE_INTENSITY, FORCE_RADIUS);
         }
         }
         
         
         // Check debug mode toggle button input
         // Check debug mode toggle button input
-        if(IsKeyPressed(KEY_P))
+        if (IsKeyPressed(KEY_P))
         {
         {
             // Update program physics value
             // Update program physics value
             worldPhysics.debug = !worldPhysics.debug;
             worldPhysics.debug = !worldPhysics.debug;
@@ -86,21 +89,21 @@ int main()
             ClearBackground(RAYWHITE);
             ClearBackground(RAYWHITE);
             
             
             // Check if debug mode is enabled
             // Check if debug mode is enabled
-            if(worldPhysics.debug)
+            if (worldPhysics.debug)
             {
             {
                 // Draw every internal physics stored collider if it is active (floor included)
                 // Draw every internal physics stored collider if it is active (floor included)
-                for(int i = 0; i < MAX_OBJECTS + 1; i++)
+                for (int i = 0; i < MAX_OBJECTS + 1; i++)
                 {
                 {
-                    if(GetCollider(i).enabled)
+                    if (GetCollider(i).enabled)
                     {
                     {
                         // Draw collider bounds
                         // Draw collider bounds
                         DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN);
                         DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN);
                         
                         
                         // Check if current collider is not floor
                         // Check if current collider is not floor
-                        if(i < MAX_OBJECTS)
+                        if (i < MAX_OBJECTS)
                         {
                         {
                             // Draw lines between mouse position and objects if they are in force range
                             // Draw lines between mouse position and objects if they are in force range
-                            if(CheckCollisionPointCircle(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, FORCE_RADIUS))
+                            if (CheckCollisionPointCircle(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, FORCE_RADIUS))
                             {
                             {
                                 DrawLineV(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, RED);
                                 DrawLineV(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, RED);
                             }
                             }
@@ -114,7 +117,7 @@ int main()
             else
             else
             {
             {
                 // Draw objects
                 // Draw objects
-                for(int i = 0; i < MAX_OBJECTS; i++)
+                for (int i = 0; i < MAX_OBJECTS; i++)
                 {
                 {
                     DrawRectangleRec((Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, GRAY);
                     DrawRectangleRec((Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, GRAY);
                 }
                 }

+ 44 - 1
src/core.c

@@ -38,9 +38,12 @@
 
 
 #include "raylib.h"         // raylib main header
 #include "raylib.h"         // raylib main header
 #include "rlgl.h"           // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
 #include "rlgl.h"           // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
-#include "raymath.h"        // Required for data type Matrix and Matrix functions
 #include "utils.h"          // TraceLog() function
 #include "utils.h"          // TraceLog() function
                             // NOTE: Includes Android fopen map, InitAssetManager()
                             // NOTE: Includes Android fopen map, InitAssetManager()
+                            
+#define RAYMATH_IMPLEMENTATION  // Use raymath as a header-only library (includes implementation)
+#define RAYMATH_EXTERN_INLINE   // Compile raymath functions as static inline (remember, it's a compiler hint)
+#include "raymath.h"            // Required for Vector3 and Matrix functions
 
 
 #include <stdio.h>          // Standard input / output lib
 #include <stdio.h>          // Standard input / output lib
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand(), atexit()
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand(), atexit()
@@ -643,6 +646,46 @@ float *ColorToFloat(Color color)
     return buffer;
     return buffer;
 }
 }
 
 
+// Converts Vector3 to float array
+float *VectorToFloat(Vector3 vec)
+{
+    static float buffer[3];
+
+    buffer[0] = vec.x;
+    buffer[1] = vec.y;
+    buffer[2] = vec.z;
+
+    return buffer;
+}
+
+// Converts Matrix to float array
+// NOTE: Returned vector is a transposed version of the Matrix struct, 
+// it should be this way because, despite raymath use OpenGL column-major convention,
+// Matrix struct memory alignment and variables naming are not coherent
+float *MatrixToFloat(Matrix mat)
+{
+    static float buffer[16];
+
+    buffer[0] = mat.m0;
+    buffer[1] = mat.m4;
+    buffer[2] = mat.m8;
+    buffer[3] = mat.m12;
+    buffer[4] = mat.m1;
+    buffer[5] = mat.m5;
+    buffer[6] = mat.m9;
+    buffer[7] = mat.m13;
+    buffer[8] = mat.m2;
+    buffer[9] = mat.m6;
+    buffer[10] = mat.m10;
+    buffer[11] = mat.m14;
+    buffer[12] = mat.m3;
+    buffer[13] = mat.m7;
+    buffer[14] = mat.m11;
+    buffer[15] = mat.m15;
+
+    return buffer;
+}
+
 // Returns a Color struct from hexadecimal value
 // Returns a Color struct from hexadecimal value
 Color GetColor(int hexValue)
 Color GetColor(int hexValue)
 {
 {

+ 43 - 29
src/easings.h

@@ -1,6 +1,12 @@
 /*******************************************************************************************
 /*******************************************************************************************
 *
 *
-*   raylib Easings - Useful easing functions for values animation
+*   raylib easings (header only file)
+*   
+*   Useful easing functions for values animation
+*
+*   This header uses:
+*       #define EASINGS_STATIC_INLINE       // Inlines all functions code, so it runs faster.
+*                                           // This requires lots of memory on system.
 *
 *
 *   A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/)
 *   A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/)
 *
 *
@@ -56,6 +62,14 @@
 #ifndef EASINGS_H
 #ifndef EASINGS_H
 #define EASINGS_H
 #define EASINGS_H
 
 
+#define EASINGS_STATIC_INLINE     // NOTE: By default, compile functions as static inline
+
+#if defined(EASINGS_STATIC_INLINE)
+    #define EASEDEF static inline
+#else
+    #define EASEDEF extern
+#endif
+
 #include <math.h>
 #include <math.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -63,47 +77,47 @@ extern "C" {            // Prevents name mangling of functions
 #endif
 #endif
 
 
 // Linear Easing functions
 // Linear Easing functions
-float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); }
-float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); }
-float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); }
-float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); }
+EASEDEF float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); }
+EASEDEF float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); }
+EASEDEF float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); }
+EASEDEF float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); }
 
 
 // Sine Easing functions
 // Sine Easing functions
-float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2)) + c + b); }
-float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2)) + b); }
-float EaseSineInOut(float t, float b, float c, float d) { return (-c/2*(cos(PI*t/d) - 1) + b); }
+EASEDEF float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2)) + c + b); }
+EASEDEF float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2)) + b); }
+EASEDEF float EaseSineInOut(float t, float b, float c, float d) { return (-c/2*(cos(PI*t/d) - 1) + b); }
 
 
 // Circular Easing functions
 // Circular Easing functions
-float EaseCircIn(float t, float b, float c, float d) { return (-c*(sqrt(1 - (t/=d)*t) - 1) + b); }
-float EaseCircOut(float t, float b, float c, float d) { return (c*sqrt(1 - (t=t/d-1)*t) + b); }
-float EaseCircInOut(float t, float b, float c, float d) 
+EASEDEF float EaseCircIn(float t, float b, float c, float d) { return (-c*(sqrt(1 - (t/=d)*t) - 1) + b); }
+EASEDEF float EaseCircOut(float t, float b, float c, float d) { return (c*sqrt(1 - (t=t/d-1)*t) + b); }
+EASEDEF float EaseCircInOut(float t, float b, float c, float d) 
 {
 {
     if ((t/=d/2) < 1) return (-c/2*(sqrt(1 - t*t) - 1) + b);
     if ((t/=d/2) < 1) return (-c/2*(sqrt(1 - t*t) - 1) + b);
     return (c/2*(sqrt(1 - t*(t-=2)) + 1) + b);
     return (c/2*(sqrt(1 - t*(t-=2)) + 1) + b);
 }
 }
 
 
 // Cubic Easing functions
 // Cubic Easing functions
-float EaseCubicIn(float t, float b, float c, float d) { return (c*(t/=d)*t*t + b); }
-float EaseCubicOut(float t, float b, float c, float d) { return (c*((t=t/d-1)*t*t + 1) + b); }
-float EaseCubicInOut(float t, float b, float c, float d) 
+EASEDEF float EaseCubicIn(float t, float b, float c, float d) { return (c*(t/=d)*t*t + b); }
+EASEDEF float EaseCubicOut(float t, float b, float c, float d) { return (c*((t=t/d-1)*t*t + 1) + b); }
+EASEDEF float EaseCubicInOut(float t, float b, float c, float d) 
 { 
 { 
     if ((t/=d/2) < 1) return (c/2*t*t*t + b);
     if ((t/=d/2) < 1) return (c/2*t*t*t + b);
     return (c/2*((t-=2)*t*t + 2) + b);    
     return (c/2*((t-=2)*t*t + 2) + b);    
 }
 }
 
 
 // Quadratic Easing functions
 // Quadratic Easing functions
-float EaseQuadIn(float t, float b, float c, float d) { return (c*(t/=d)*t + b); }
-float EaseQuadOut(float t, float b, float c, float d) { return (-c*(t/=d)*(t-2) + b); }
-float EaseQuadInOut(float t, float b, float c, float d) 
+EASEDEF float EaseQuadIn(float t, float b, float c, float d) { return (c*(t/=d)*t + b); }
+EASEDEF float EaseQuadOut(float t, float b, float c, float d) { return (-c*(t/=d)*(t-2) + b); }
+EASEDEF float EaseQuadInOut(float t, float b, float c, float d) 
 {
 {
     if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b);
     if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b);
     return (-c/2*(((t-2)*(--t)) - 1) + b);
     return (-c/2*(((t-2)*(--t)) - 1) + b);
 }
 }
 
 
 // Exponential Easing functions
 // Exponential Easing functions
-float EaseExpoIn(float t, float b, float c, float d) { return (t == 0) ? b : (c*pow(2, 10*(t/d - 1)) + b); }
-float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2, -10*t/d) + 1) + b);    }
-float EaseExpoInOut(float t, float b, float c, float d) 
+EASEDEF float EaseExpoIn(float t, float b, float c, float d) { return (t == 0) ? b : (c*pow(2, 10*(t/d - 1)) + b); }
+EASEDEF float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2, -10*t/d) + 1) + b);    }
+EASEDEF float EaseExpoInOut(float t, float b, float c, float d) 
 {
 {
     if (t == 0) return b;
     if (t == 0) return b;
     if (t == d) return (b + c);
     if (t == d) return (b + c);
@@ -113,20 +127,20 @@ float EaseExpoInOut(float t, float b, float c, float d)
 }
 }
 
 
 // Back Easing functions
 // Back Easing functions
-float EaseBackIn(float t, float b, float c, float d) 
+EASEDEF float EaseBackIn(float t, float b, float c, float d) 
 {
 {
     float s = 1.70158f;
     float s = 1.70158f;
     float postFix = t/=d;
     float postFix = t/=d;
     return (c*(postFix)*t*((s + 1)*t - s) + b);
     return (c*(postFix)*t*((s + 1)*t - s) + b);
 }
 }
 
 
-float EaseBackOut(float t, float b, float c, float d)
+EASEDEF float EaseBackOut(float t, float b, float c, float d)
 {    
 {    
     float s = 1.70158f;
     float s = 1.70158f;
     return (c*((t=t/d-1)*t*((s + 1)*t + s) + 1) + b);
     return (c*((t=t/d-1)*t*((s + 1)*t + s) + 1) + b);
 }
 }
 
 
-float EaseBackInOut(float t, float b, float c, float d)
+EASEDEF float EaseBackInOut(float t, float b, float c, float d)
 {
 {
     float s = 1.70158f;
     float s = 1.70158f;
     if ((t/=d/2) < 1) return (c/2*(t*t*(((s*=(1.525f)) + 1)*t - s)) + b);
     if ((t/=d/2) < 1) return (c/2*(t*t*(((s*=(1.525f)) + 1)*t - s)) + b);
@@ -136,8 +150,7 @@ float EaseBackInOut(float t, float b, float c, float d)
 }
 }
 
 
 // Bounce Easing functions
 // Bounce Easing functions
-float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d-t, 0, c, d) + b); }
-float EaseBounceOut(float t, float b, float c, float d) 
+EASEDEF float EaseBounceOut(float t, float b, float c, float d) 
 {
 {
     if ((t/=d) < (1/2.75f)) 
     if ((t/=d) < (1/2.75f)) 
     {
     {
@@ -160,14 +173,15 @@ float EaseBounceOut(float t, float b, float c, float d)
     }
     }
 }
 }
 
 
-float EaseBounceInOut(float t, float b, float c, float d) 
+EASEDEF float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d-t, 0, c, d) + b); }
+EASEDEF float EaseBounceInOut(float t, float b, float c, float d) 
 {
 {
     if (t < d/2) return (EaseBounceIn(t*2, 0, c, d)*0.5f + b);
     if (t < d/2) return (EaseBounceIn(t*2, 0, c, d)*0.5f + b);
     else return (EaseBounceOut(t*2-d, 0, c, d)*0.5f + c*0.5f + b);
     else return (EaseBounceOut(t*2-d, 0, c, d)*0.5f + c*0.5f + b);
 }
 }
 
 
 // Elastic Easing functions
 // Elastic Easing functions
-float EaseElasticIn(float t, float b, float c, float d) 
+EASEDEF float EaseElasticIn(float t, float b, float c, float d) 
 {
 {
     if (t == 0) return b;
     if (t == 0) return b;
     if ((t/=d) == 1) return (b + c);
     if ((t/=d) == 1) return (b + c);
@@ -180,7 +194,7 @@ float EaseElasticIn(float t, float b, float c, float d)
     return (-(postFix*sin((t*d-s)*(2*PI)/p )) + b);
     return (-(postFix*sin((t*d-s)*(2*PI)/p )) + b);
 }
 }
 
 
-float EaseElasticOut(float t, float b, float c, float d)
+EASEDEF float EaseElasticOut(float t, float b, float c, float d)
 {
 {
     if (t == 0) return b;
     if (t == 0) return b;
     if ((t/=d) == 1) return (b + c);
     if ((t/=d) == 1) return (b + c);
@@ -192,7 +206,7 @@ float EaseElasticOut(float t, float b, float c, float d)
     return (a*pow(2,-10*t)*sin((t*d-s)*(2*PI)/p) + c + b);    
     return (a*pow(2,-10*t)*sin((t*d-s)*(2*PI)/p) + c + b);    
 }
 }
 
 
-float EaseElasticInOut(float t, float b, float c, float d)
+EASEDEF float EaseElasticInOut(float t, float b, float c, float d)
 {
 {
     if (t == 0) return b;
     if (t == 0) return b;
     if ((t/=d/2) == 2) return (b + c);
     if ((t/=d/2) == 2) return (b + c);

+ 3 - 3
src/models.c

@@ -34,8 +34,8 @@
 #include <string.h>     // Required for strcmp()
 #include <string.h>     // Required for strcmp()
 #include <math.h>       // Used for sin, cos, tan
 #include <math.h>       // Used for sin, cos, tan
 
 
-#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
 #include "rlgl.h"       // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2
+#include "raymath.h"    // Required for data type Matrix and Matrix functions
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Defines and Macros
 // Defines and Macros
@@ -1373,8 +1373,8 @@ bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox)
 BoundingBox CalculateBoundingBox(Mesh mesh)
 BoundingBox CalculateBoundingBox(Mesh mesh)
 {
 {
     // Get min and max vertex to construct bounds (AABB)
     // Get min and max vertex to construct bounds (AABB)
-    Vector3 minVertex = mesh.vertices[0]; 
-    Vector3 maxVertex = mesh.vertices[0];
+    Vector3 minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };
+    Vector3 maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] };
 
 
     for (int i = 1; i < mesh.vertexCount; i++)
     for (int i = 1; i < mesh.vertexCount; i++)
     {
     {

+ 18 - 14
src/physac.c

@@ -55,8 +55,8 @@ static bool collisionChecker = false;
 // Module specific Functions Declarations
 // Module specific Functions Declarations
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 static float Vector2Length(Vector2 vector);
 static float Vector2Length(Vector2 vector);
-static float Vector2LengthPoints(Vector2 a, Vector2 b);
-static Vector2 Vector2Normalize(Vector2 vector);
+static float Vector2Distance(Vector2 a, Vector2 b);
+static void Vector2Normalize(Vector2 *vector);
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Module Functions Definitions
 // Module Functions Definitions
@@ -183,9 +183,9 @@ void ApplyPhysics(int index, Vector2 *position)
             {
             {
                 if (colliders[index].enabled && colliders[j].enabled)
                 if (colliders[index].enabled && colliders[j].enabled)
                 {
                 {
-                    if (colliders[index].type == RectangleCollider)
+                    if (colliders[index].type == COLLIDER_RECTANGLE)
                     {
                     {
-                        if (colliders[j].type == RectangleCollider)
+                        if (colliders[j].type == COLLIDER_RECTANGLE)
                         {
                         {
                             if (CheckCollisionRecs(colliders[index].bounds, colliders[j].bounds))
                             if (CheckCollisionRecs(colliders[index].bounds, colliders[j].bounds))
                             {
                             {
@@ -207,7 +207,7 @@ void ApplyPhysics(int index, Vector2 *position)
                     }
                     }
                     else
                     else
                     {
                     {
-                        if (colliders[j].type == RectangleCollider)
+                        if (colliders[j].type == COLLIDER_RECTANGLE)
                         {
                         {
                             if (CheckCollisionCircleRec((Vector2){colliders[index].bounds.x, colliders[index].bounds.y}, colliders[index].radius, colliders[j].bounds))
                             if (CheckCollisionCircleRec((Vector2){colliders[index].bounds.x, colliders[index].bounds.y}, colliders[index].radius, colliders[j].bounds))
                             {
                             {
@@ -277,7 +277,7 @@ void AddForceAtPosition(Vector2 position, float intensity, float radius)
             Vector2 pos = {colliders[i].bounds.x, colliders[i].bounds.y};
             Vector2 pos = {colliders[i].bounds.x, colliders[i].bounds.y};
             
             
             // Get distance between rigidbody position and target position
             // Get distance between rigidbody position and target position
-            float distance = Vector2LengthPoints(position, pos);
+            float distance = Vector2Distance(position, pos);
             
             
             if(distance <= radius)
             if(distance <= radius)
             {
             {
@@ -285,7 +285,7 @@ void AddForceAtPosition(Vector2 position, float intensity, float radius)
                 Vector2 force = {colliders[i].bounds.x - position.x, colliders[i].bounds.y - position.y};
                 Vector2 force = {colliders[i].bounds.x - position.x, colliders[i].bounds.y - position.y};
                 
                 
                 // Normalize the direction vector
                 // Normalize the direction vector
-                force = Vector2Normalize(force);
+                Vector2Normalize(&force);
                 
                 
                 // Invert y value
                 // Invert y value
                 force.y *= -1;
                 force.y *= -1;
@@ -323,20 +323,24 @@ static float Vector2Length(Vector2 vector)
     return sqrt((vector.x * vector.x) + (vector.y * vector.y));
     return sqrt((vector.x * vector.x) + (vector.y * vector.y));
 }
 }
 
 
-static float Vector2LengthPoints(Vector2 a, Vector2 b)
+static float Vector2Distance(Vector2 a, Vector2 b)
 {
 {
     Vector2 vector = {b.x - a.x, b.y - a.y};
     Vector2 vector = {b.x - a.x, b.y - a.y};
     return sqrt((vector.x * vector.x) + (vector.y * vector.y));
     return sqrt((vector.x * vector.x) + (vector.y * vector.y));
 }
 }
 
 
-static Vector2 Vector2Normalize(Vector2 vector)
+static void Vector2Normalize(Vector2 *vector)
 {
 {
-    float length = Vector2Length(vector);
+    float length = Vector2Length(*vector);
     
     
-    if(length != 0)
+    if (length != 0.0f)
     {
     {
-        return (Vector2){vector.x / length, vector.y / length};
+        vector->x /= length;
+        vector->y /= length;
+    }
+    else 
+    {
+        vector->x = 0.0f;
+        vector->y = 0.0f;
     }
     }
-    
-    return (Vector2){0, 0};
 }
 }

+ 4 - 3
src/physac.h

@@ -32,7 +32,8 @@
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
 // Types and Structures Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
-typedef enum { RectangleCollider, CircleCollider } ColliderType;
+// Collider types
+typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType;
 
 
 // Physics struct
 // Physics struct
 typedef struct Physics {
 typedef struct Physics {
@@ -65,8 +66,8 @@ typedef struct Rigidbody {
 typedef struct Collider {
 typedef struct Collider {
     bool enabled;
     bool enabled;
     ColliderType type;
     ColliderType type;
-    Rectangle bounds;   // Just used for RectangleCollider type
-    int radius;     // Just used for CircleCollider type
+    Rectangle bounds;   // Used for COLLIDER_RECTANGLE and COLLIDER_CAPSULE
+    int radius;         // Used for COLLIDER_CIRCLE and COLLIDER_CAPSULE
 } Collider;
 } Collider;
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 6 - 6
src/raylib.h

@@ -463,12 +463,12 @@ typedef struct {
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
 
 
 // Collider types
 // Collider types
-typedef enum { RectangleCollider, CircleCollider } ColliderType;
+typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType;
 
 
 // Physics struct
 // Physics struct
 typedef struct Physics {
 typedef struct Physics {
     bool enabled;
     bool enabled;
-    bool debug;     // Should be used by programmer for testing purposes
+    bool debug;             // Should be used by programmer for testing purposes
     Vector2 gravity;
     Vector2 gravity;
 } Physics;
 } Physics;
 
 
@@ -496,8 +496,8 @@ typedef struct Rigidbody {
 typedef struct Collider {
 typedef struct Collider {
     bool enabled;
     bool enabled;
     ColliderType type;
     ColliderType type;
-    Rectangle bounds;   // Just used for RectangleCollider type
-    int radius;         // Just used for CircleCollider type
+    Rectangle bounds;   // Used for COLLIDER_RECTANGLE and COLLIDER_CAPSULE
+    int radius;         // Used for COLLIDER_CIRCLE and COLLIDER_CAPSULE
 } Collider;
 } Collider;
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -547,8 +547,8 @@ float GetFrameTime(void);                                   // Returns time in s
 Color GetColor(int hexValue);                               // Returns a Color struct from hexadecimal value
 Color GetColor(int hexValue);                               // Returns a Color struct from hexadecimal value
 int GetHexValue(Color color);                               // Returns hexadecimal value for a Color
 int GetHexValue(Color color);                               // Returns hexadecimal value for a Color
 float *ColorToFloat(Color color);                           // Converts Color to float array and normalizes
 float *ColorToFloat(Color color);                           // Converts Color to float array and normalizes
-float *VectorToFloat(Vector3 vec);                          // Converts Vector3 to float array (defined in raymath module)
-float *MatrixToVector(Matrix mat);                          // Converts Matrix to float array (defined in raymath module)
+float *VectorToFloat(Vector3 vec);                          // Converts Vector3 to float array
+float *MatrixToFloat(Matrix mat);                           // Converts Matrix to float array
 
 
 int GetRandomValue(int min, int max);                       // Returns a random value between min and max (both included)
 int GetRandomValue(int min, int max);                       // Returns a random value between min and max (both included)
 Color Fade(Color color, float alpha);                       // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
 Color Fade(Color color, float alpha);                       // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f

+ 226 - 188
src/raymath.h

@@ -1,9 +1,23 @@
 /**********************************************************************************************
 /**********************************************************************************************
 *
 *
-*   raymath
+*   raymath (header only file)
 *
 *
 *   Some useful functions to work with Vector3, Matrix and Quaternions
 *   Some useful functions to work with Vector3, Matrix and Quaternions
 *
 *
+*   You must:
+*       #define RAYMATH_IMPLEMENTATION
+*   before you include this file in *only one* C or C++ file to create the implementation.
+*
+*   Example:
+*       #define RAYMATH_IMPLEMENTATION
+*       #include "raymath.h"
+*
+*   You can also use:
+*       #define RAYMATH_EXTERN_INLINE       // Inlines all functions code, so it runs faster.
+*                                           // This requires lots of memory on system.
+*       #define RAYMATH_STANDALONE          // Not dependent on raylib.h structs: Vector3, Matrix.
+*
+*
 *   Copyright (c) 2015 Ramon Santamaria (@raysan5)
 *   Copyright (c) 2015 Ramon Santamaria (@raysan5)
 *
 *
 *   This software is provided "as-is", without any express or implied warranty. In no event
 *   This software is provided "as-is", without any express or implied warranty. In no event
@@ -22,37 +36,21 @@
 *     3. This notice may not be removed or altered from any source distribution.
 *     3. This notice may not be removed or altered from any source distribution.
 *
 *
 **********************************************************************************************/
 **********************************************************************************************/
-//============================================================================
-//   YOU MUST                                                                  
-//                                                                             
-//      #define RAYMATH_DEFINE                                                     
-//                                                                             
-//   Like:                                                               
-//                                                                             
-//      #define RAYMATH_DEFINE                                                     
-//      #include "raymath.h"
-//
-//   YOU CAN:
-//      #define RAYMATH_INLINE //inlines all code, so it runs faster. This requires lots of memory on system.
-//   AND
-//      #define RAYMATH_STANDALONE //not dependent on outside libs
-//      
-//   This needs to be done for every library/source file.
-//============================================================================
-
-#ifdef RAYMATH_INLINE
-    #define RMDEF static inline
-#else
-    #define RMDEF static
-#endif
 
 
 #ifndef RAYMATH_H
 #ifndef RAYMATH_H
 #define RAYMATH_H
 #define RAYMATH_H
 
 
-//#define RAYMATH_STANDALONE    // NOTE: To use raymath as standalone lib, just uncomment this line
+//#define RAYMATH_STANDALONE        // NOTE: To use raymath as standalone lib, just uncomment this line
+//#define RAYMATH_EXTERN_INLINE     // NOTE: To compile functions as static inline, uncomment this line
 
 
 #ifndef RAYMATH_STANDALONE
 #ifndef RAYMATH_STANDALONE
-    #include "raylib.h"         // Required for typedef: Vector3
+    #include "raylib.h"             // Required for structs: Vector3, Matrix
+#endif
+
+#if defined(RAYMATH_EXTERN_INLINE)
+    #define RMDEF extern inline
+#else
+    #define RMDEF extern
 #endif
 #endif
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
@@ -63,18 +61,18 @@
 #endif
 #endif
 
 
 #ifndef DEG2RAD
 #ifndef DEG2RAD
-    #define DEG2RAD (PI / 180.0f)
+    #define DEG2RAD (PI/180.0f)
 #endif
 #endif
 
 
 #ifndef RAD2DEG
 #ifndef RAD2DEG
-    #define RAD2DEG (180.0f / PI)
+    #define RAD2DEG (180.0f/PI)
 #endif
 #endif
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 // Types and Structures Definition
 // Types and Structures Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 
 
-#ifdef RAYMATH_STANDALONE
+#if defined(RAYMATH_STANDALONE)
 	// Vector2 type
 	// Vector2 type
     typedef struct Vector2 {
     typedef struct Vector2 {
         float x;
         float x;
@@ -105,7 +103,77 @@ typedef struct Quaternion {
     float w;
     float w;
 } Quaternion;
 } Quaternion;
 
 
-#ifdef RAYMATH_DEFINE
+#ifndef RAYMATH_EXTERN_INLINE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//------------------------------------------------------------------------------------
+// Functions Declaration to work with Vector3
+//------------------------------------------------------------------------------------
+RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2);              // Add two vectors
+RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2);         // Substract two vectors
+RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2);     // Calculate two vectors cross product
+RMDEF Vector3 VectorPerpendicular(Vector3 v);                 // Calculate one vector perpendicular vector
+RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2);         // Calculate two vectors dot product
+RMDEF float VectorLength(const Vector3 v);                    // Calculate vector lenght
+RMDEF void VectorScale(Vector3 *v, float scale);              // Scale provided vector
+RMDEF void VectorNegate(Vector3 *v);                          // Negate provided vector (invert direction)
+RMDEF void VectorNormalize(Vector3 *v);                       // Normalize provided vector
+RMDEF float VectorDistance(Vector3 v1, Vector3 v2);           // Calculate distance between two points
+RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors
+RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal);  // Calculate reflected vector to normal
+RMDEF void VectorTransform(Vector3 *v, Matrix mat);           // Transforms a Vector3 by a given Matrix
+RMDEF Vector3 VectorZero(void);                               // Return a Vector3 init to zero
+
+//------------------------------------------------------------------------------------
+// Functions Declaration to work with Matrix
+//------------------------------------------------------------------------------------
+RMDEF float MatrixDeterminant(Matrix mat);                    // Compute matrix determinant
+RMDEF float MatrixTrace(Matrix mat);                          // Returns the trace of the matrix (sum of the values along the diagonal)
+RMDEF void MatrixTranspose(Matrix *mat);                      // Transposes provided matrix
+RMDEF void MatrixInvert(Matrix *mat);                         // Invert provided matrix
+RMDEF void MatrixNormalize(Matrix *mat);                      // Normalize provided matrix
+RMDEF Matrix MatrixIdentity(void);                            // Returns identity matrix
+RMDEF Matrix MatrixAdd(Matrix left, Matrix right);            // Add two matrices
+RMDEF Matrix MatrixSubstract(Matrix left, Matrix right);      // Substract two matrices (left - right)
+RMDEF Matrix MatrixTranslate(float x, float y, float z);      // Returns translation matrix
+RMDEF Matrix MatrixRotate(float angle, Vector3 axis);         // Returns rotation matrix for an angle around an specified axis (angle in radians)
+RMDEF Matrix MatrixRotateX(float angle);                      // Returns x-rotation matrix (angle in radians)
+RMDEF Matrix MatrixRotateY(float angle);                      // Returns y-rotation matrix (angle in radians)
+RMDEF Matrix MatrixRotateZ(float angle);                      // Returns z-rotation matrix (angle in radians)
+RMDEF Matrix MatrixScale(float x, float y, float z);          // Returns scaling matrix
+RMDEF Matrix MatrixMultiply(Matrix left, Matrix right);       // Returns two matrix multiplication
+RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far);  // Returns perspective projection matrix
+RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far);                        // Returns perspective projection matrix
+RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far);    // Returns orthographic projection matrix
+RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up);  // Returns camera look-at matrix (view matrix)
+RMDEF void PrintMatrix(Matrix m);                             // Print matrix utility
+
+//------------------------------------------------------------------------------------
+// Functions Declaration to work with Quaternions
+//------------------------------------------------------------------------------------
+RMDEF float QuaternionLength(Quaternion quat);                // Compute the length of a quaternion
+RMDEF void QuaternionNormalize(Quaternion *q);                // Normalize provided quaternion
+RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2);    // Calculate two quaternion multiplication
+RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions
+RMDEF Quaternion QuaternionFromMatrix(Matrix matrix);                 // Returns a quaternion for a given rotation matrix
+RMDEF Matrix QuaternionToMatrix(Quaternion q);                        // Returns a matrix for a given quaternion
+RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis);  // Returns rotation quaternion for an angle and axis
+RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis); // Returns the rotation angle and axis for a given quaternion
+RMDEF void QuaternionTransform(Quaternion *q, Matrix mat);            // Transform a quaternion given a transformation matrix
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // notdef RAYMATH_EXTERN_INLINE
+
+//////////////////////////////////////////////////////////////////// end of header file
+
+#if defined(RAYMATH_IMPLEMENTATION) || defined(RAYMATH_EXTERN_INLINE)
+
 #include <stdio.h>      // Used only on PrintMatrix()
 #include <stdio.h>      // Used only on PrintMatrix()
 #include <math.h>       // Standard math libary: sin(), cos(), tan()...
 #include <math.h>       // Standard math libary: sin(), cos(), tan()...
 #include <stdlib.h>     // Used for abs()
 #include <stdlib.h>     // Used for abs()
@@ -114,18 +182,6 @@ typedef struct Quaternion {
 // Module Functions Definition - Vector3 math
 // Module Functions Definition - Vector3 math
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 
 
-// Converts Vector3 to float array
-RMDEF float *VectorToFloat(Vector3 vec)
-{
-    static float buffer[3];
-
-    buffer[0] = vec.x;
-    buffer[1] = vec.y;
-    buffer[2] = vec.z;
-
-    return buffer;
-}
-
 // Add two vectors
 // Add two vectors
 RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2)
 RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2)
 {
 {
@@ -229,9 +285,9 @@ RMDEF void VectorNormalize(Vector3 *v)
 
 
     length = VectorLength(*v);
     length = VectorLength(*v);
 
 
-    if (length == 0) length = 1;
+    if (length == 0) length = 1.0f;
 
 
-    ilength = 1.0/length;
+    ilength = 1.0f/length;
 
 
     v->x *= ilength;
     v->x *= ilength;
     v->y *= ilength;
     v->y *= ilength;
@@ -257,9 +313,9 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount)
 {
 {
     Vector3 result;
     Vector3 result;
 
 
-    result.x = v1.x + amount * (v2.x - v1.x);
-    result.y = v1.y + amount * (v2.y - v1.y);
-    result.z = v1.z + amount * (v2.z - v1.z);
+    result.x = v1.x + amount*(v2.x - v1.x);
+    result.y = v1.y + amount*(v2.y - v1.y);
+    result.z = v1.z + amount*(v2.z - v1.z);
 
 
     return result;
     return result;
 }
 }
@@ -269,15 +325,15 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
 {
 {
     // I is the original vector
     // I is the original vector
     // N is the normal of the incident plane
     // N is the normal of the incident plane
-    // R = I - (2 * N * ( DotProduct[ I,N] ))
+    // R = I - (2*N*( DotProduct[ I,N] ))
 
 
     Vector3 result;
     Vector3 result;
 
 
     float dotProduct = VectorDotProduct(vector, normal);
     float dotProduct = VectorDotProduct(vector, normal);
 
 
-    result.x = vector.x - (2.0 * normal.x) * dotProduct;
-    result.y = vector.y - (2.0 * normal.y) * dotProduct;
-    result.z = vector.z - (2.0 * normal.z) * dotProduct;
+    result.x = vector.x - (2.0f*normal.x)*dotProduct;
+    result.y = vector.y - (2.0f*normal.y)*dotProduct;
+    result.z = vector.z - (2.0f*normal.z)*dotProduct;
 
 
     return result;
     return result;
 }
 }
@@ -308,34 +364,6 @@ RMDEF Vector3 VectorZero(void)
 // Module Functions Definition - Matrix math
 // Module Functions Definition - Matrix math
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 
 
-// Converts Matrix to float array
-// NOTE: Returned vector is a transposed version of the Matrix struct, 
-// it should be this way because, despite raymath use OpenGL column-major convention,
-// Matrix struct memory alignment and variables naming are not coherent
-RMDEF float *MatrixToFloat(Matrix mat)
-{
-    static float buffer[16];
-
-    buffer[0] = mat.m0;
-    buffer[1] = mat.m4;
-    buffer[2] = mat.m8;
-    buffer[3] = mat.m12;
-    buffer[4] = mat.m1;
-    buffer[5] = mat.m5;
-    buffer[6] = mat.m9;
-    buffer[7] = mat.m13;
-    buffer[8] = mat.m2;
-    buffer[9] = mat.m6;
-    buffer[10] = mat.m10;
-    buffer[11] = mat.m14;
-    buffer[12] = mat.m3;
-    buffer[13] = mat.m7;
-    buffer[14] = mat.m11;
-    buffer[15] = mat.m15;
-
-    return buffer;
-}
-
 // Compute matrix determinant
 // Compute matrix determinant
 RMDEF float MatrixDeterminant(Matrix mat)
 RMDEF float MatrixDeterminant(Matrix mat)
 {
 {
@@ -413,7 +441,7 @@ RMDEF void MatrixInvert(Matrix *mat)
     float b11 = a22*a33 - a23*a32;
     float b11 = a22*a33 - a23*a32;
 
 
     // Calculate the invert determinant (inlined to avoid double-caching)
     // Calculate the invert determinant (inlined to avoid double-caching)
-    float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
+    float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
 
 
     temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
     temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet;
     temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
     temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
@@ -461,7 +489,10 @@ RMDEF void MatrixNormalize(Matrix *mat)
 // Returns identity matrix
 // Returns identity matrix
 RMDEF Matrix MatrixIdentity(void)
 RMDEF Matrix MatrixIdentity(void)
 {
 {
-    Matrix result = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
+    Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 
+                      0.0f, 1.0f, 0.0f, 0.0f, 
+                      0.0f, 0.0f, 1.0f, 0.0f,
+                      0.0f, 0.0f, 0.0f, 1.0f };
 
 
     return result;
     return result;
 }
 }
@@ -519,7 +550,10 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right)
 // Returns translation matrix
 // Returns translation matrix
 RMDEF Matrix MatrixTranslate(float x, float y, float z)
 RMDEF Matrix MatrixTranslate(float x, float y, float z)
 {
 {
-    Matrix result = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 };
+    Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 
+                      0.0f, 1.0f, 0.0f, 0.0f, 
+                      0.0f, 0.0f, 1.0f, 0.0f, 
+                      x, y, z, 1.0f };
 
 
     return result;
     return result;
 }
 }
@@ -536,9 +570,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis)
 
 
     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.0f) && (length != 0.0f))
     {
     {
-        length = 1/length;
+        length = 1.0f/length;
         x *= length;
         x *= length;
         y *= length;
         y *= length;
         z *= length;
         z *= length;
@@ -594,15 +628,15 @@ RMDEF Matrix MatrixRotate(float angle, float x, float y, float z)
           m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14;
           m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14;
 
 
     // build rotation matrix
     // build rotation matrix
-    float r0 = x * x * c1 + c;
-    float r1 = x * y * c1 + z * s;
-    float r2 = x * z * c1 - y * s;
-    float r4 = x * y * c1 - z * s;
-    float r5 = y * y * c1 + c;
-    float r6 = y * z * c1 + x * s;
-    float r8 = x * z * c1 + y * s;
-    float r9 = y * z * c1 - x * s;
-    float r10= z * z * c1 + c;
+    float r0 = x*x*c1 + c;
+    float r1 = x*y*c1 + z*s;
+    float r2 = x*z*c1 - y*s;
+    float r4 = x*y*c1 - z*s;
+    float r5 = y*y*c1 + c;
+    float r6 = y*z*c1 + x*s;
+    float r8 = x*z*c1 + y*s;
+    float r9 = y*z*c1 - x*s;
+    float r10= z*z*c1 + c;
 
 
     // multiply rotation matrix
     // multiply rotation matrix
     result.m0 = r0*m0 + r4*m1 + r8*m2;
     result.m0 = r0*m0 + r4*m1 + r8*m2;
@@ -673,7 +707,10 @@ RMDEF Matrix MatrixRotateZ(float angle)
 // Returns scaling matrix
 // Returns scaling matrix
 RMDEF Matrix MatrixScale(float x, float y, float z)
 RMDEF Matrix MatrixScale(float x, float y, float z)
 {
 {
-    Matrix result = { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 };
+    Matrix result = { x, 0.0f, 0.0f, 0.0f, 
+                      0.0f, y, 0.0f, 0.0f, 
+                      0.0f, 0.0f, z, 0.0f, 
+                      0.0f, 0.0f, 0.0f, 1.0f };
 
 
     return result;
     return result;
 }
 }
@@ -713,25 +750,25 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
     float tb = (top - bottom);
     float tb = (top - bottom);
     float fn = (far - near);
     float fn = (far - near);
 
 
-    result.m0 = (near*2.0f) / rl;
-    result.m1 = 0;
-    result.m2 = 0;
-    result.m3 = 0;
+    result.m0 = (near*2.0f)/rl;
+    result.m1 = 0.0f;
+    result.m2 = 0.0f;
+    result.m3 = 0.0f;
 
 
-    result.m4 = 0;
-    result.m5 = (near*2.0f) / tb;
-    result.m6 = 0;
-    result.m7 = 0;
+    result.m4 = 0.0f;
+    result.m5 = (near*2.0f)/tb;
+    result.m6 = 0.0f;
+    result.m7 = 0.0f;
 
 
-    result.m8 = (right + left) / rl;
-    result.m9 = (top + bottom) / tb;
-    result.m10 = -(far + near) / fn;
+    result.m8 = (right + left)/rl;
+    result.m9 = (top + bottom)/tb;
+    result.m10 = -(far + near)/fn;
     result.m11 = -1.0f;
     result.m11 = -1.0f;
 
 
-    result.m12 = 0;
-    result.m13 = 0;
-    result.m14 = -(far*near*2.0f) / fn;
-    result.m15 = 0;
+    result.m12 = 0.0f;
+    result.m13 = 0.0f;
+    result.m14 = -(far*near*2.0f)/fn;
+    result.m15 = 0.0f;
 
 
     return result;
     return result;
 }
 }
@@ -739,7 +776,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
 // Returns perspective projection matrix
 // Returns perspective projection matrix
 RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
 RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
 {
 {
-    double top = near*tanf(fovy*PI / 360.0f);
+    double top = near*tanf(fovy*PI/360.0f);
     double right = top*aspect;
     double right = top*aspect;
 
 
     return MatrixFrustum(-right, right, -top, top, near, far);
     return MatrixFrustum(-right, right, -top, top, near, far);
@@ -754,22 +791,22 @@ RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, d
     float tb = (top - bottom);
     float tb = (top - bottom);
     float fn = (far - near);
     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.m0 = 2.0f/rl;
+    result.m1 = 0.0f;
+    result.m2 = 0.0f;
+    result.m3 = 0.0f;
+    result.m4 = 0.0f;
+    result.m5 = 2.0f/tb;
+    result.m6 = 0.0f;
+    result.m7 = 0.0f;
+    result.m8 = 0.0f;
+    result.m9 = 0.0f;
+    result.m10 = -2.0f/fn;
+    result.m11 = 0.0f;
+    result.m12 = -(left + right)/rl;
+    result.m13 = -(top + bottom)/tb;
+    result.m14 = -(far + near)/fn;
+    result.m15 = 1.0f;
 
 
     return result;
     return result;
 }
 }
@@ -789,19 +826,19 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
     result.m0 = x.x;
     result.m0 = x.x;
     result.m1 = x.y;
     result.m1 = x.y;
     result.m2 = x.z;
     result.m2 = x.z;
-    result.m3 = -((x.x * eye.x) + (x.y * eye.y) + (x.z * eye.z));
+    result.m3 = -((x.x*eye.x) + (x.y*eye.y) + (x.z*eye.z));
     result.m4 = y.x;
     result.m4 = y.x;
     result.m5 = y.y;
     result.m5 = y.y;
     result.m6 = y.z;
     result.m6 = y.z;
-    result.m7 = -((y.x * eye.x) + (y.y * eye.y) + (y.z * eye.z));
+    result.m7 = -((y.x*eye.x) + (y.y*eye.y) + (y.z*eye.z));
     result.m8 = z.x;
     result.m8 = z.x;
     result.m9 = z.y;
     result.m9 = z.y;
     result.m10 = z.z;
     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;
+    result.m11 = -((z.x*eye.x) + (z.y*eye.y) + (z.z*eye.z));
+    result.m12 = 0.0f;
+    result.m13 = 0.0f;
+    result.m14 = 0.0f;
+    result.m15 = 1.0f;
 
 
     return result;
     return result;
 }
 }
@@ -834,9 +871,9 @@ RMDEF void QuaternionNormalize(Quaternion *q)
 
 
     length = QuaternionLength(*q);
     length = QuaternionLength(*q);
 
 
-    if (length == 0) length = 1;
+    if (length == 0.0f) length = 1.0f;
 
 
-    ilength = 1.0/length;
+    ilength = 1.0f/length;
 
 
     q->x *= ilength;
     q->x *= ilength;
     q->y *= ilength;
     q->y *= ilength;
@@ -882,8 +919,8 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
         }
         }
         else
         else
         {
         {
-            float ratioA = sin((1 - amount)*halfTheta) / sinHalfTheta;
-            float ratioB = sin(amount*halfTheta) / sinHalfTheta;
+            float ratioA = sin((1 - amount)*halfTheta)/sinHalfTheta;
+            float ratioB = sin(amount*halfTheta)/sinHalfTheta;
 
 
             result.x = (q1.x*ratioA + q2.x*ratioB);
             result.x = (q1.x*ratioA + q2.x*ratioB);
             result.y = (q1.y*ratioA + q2.y*ratioB);
             result.y = (q1.y*ratioA + q2.y*ratioB);
@@ -902,15 +939,15 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix)
 
 
     float trace = MatrixTrace(matrix);
     float trace = MatrixTrace(matrix);
 
 
-    if (trace > 0)
+    if (trace > 0.0f)
     {
     {
-        float s = (float)sqrt(trace + 1) * 2;
-        float invS = 1 / s;
+        float s = (float)sqrt(trace + 1)*2.0f;
+        float invS = 1.0f/s;
 
 
-        result.w = s * 0.25;
-        result.x = (matrix.m6 - matrix.m9) * invS;
-        result.y = (matrix.m8 - matrix.m2) * invS;
-        result.z = (matrix.m1 - matrix.m4) * invS;
+        result.w = s*0.25f;
+        result.x = (matrix.m6 - matrix.m9)*invS;
+        result.y = (matrix.m8 - matrix.m2)*invS;
+        result.z = (matrix.m1 - matrix.m4)*invS;
     }
     }
     else
     else
     {
     {
@@ -918,33 +955,33 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix)
 
 
         if (m00 > m11 && m00 > m22)
         if (m00 > m11 && m00 > m22)
         {
         {
-            float s = (float)sqrt(1 + m00 - m11 - m22) * 2;
-            float invS = 1 / s;
+            float s = (float)sqrt(1.0f + m00 - m11 - m22)*2.0f;
+            float invS = 1.0f/s;
 
 
-            result.w = (matrix.m6 - matrix.m9) * invS;
-            result.x = s * 0.25;
-            result.y = (matrix.m4 + matrix.m1) * invS;
-            result.z = (matrix.m8 + matrix.m2) * invS;
+            result.w = (matrix.m6 - matrix.m9)*invS;
+            result.x = s*0.25f;
+            result.y = (matrix.m4 + matrix.m1)*invS;
+            result.z = (matrix.m8 + matrix.m2)*invS;
         }
         }
         else if (m11 > m22)
         else if (m11 > m22)
         {
         {
-            float s = (float)sqrt(1 + m11 - m00 - m22) * 2;
-            float invS = 1 / s;
+            float s = (float)sqrt(1.0f + m11 - m00 - m22)*2.0f;
+            float invS = 1.0f/s;
 
 
-            result.w = (matrix.m8 - matrix.m2) * invS;
-            result.x = (matrix.m4 + matrix.m1) * invS;
-            result.y = s * 0.25;
-            result.z = (matrix.m9 + matrix.m6) * invS;
+            result.w = (matrix.m8 - matrix.m2)*invS;
+            result.x = (matrix.m4 + matrix.m1)*invS;
+            result.y = s*0.25f;
+            result.z = (matrix.m9 + matrix.m6)*invS;
         }
         }
         else
         else
         {
         {
-            float s = (float)sqrt(1 + m22 - m00 - m11) * 2;
-            float invS = 1 / s;
+            float s = (float)sqrt(1.0f + m22 - m00 - m11)*2.0f;
+            float invS = 1.0f/s;
 
 
-            result.w = (matrix.m1 - matrix.m4) * invS;
-            result.x = (matrix.m8 + matrix.m2) * invS;
-            result.y = (matrix.m9 + matrix.m6) * invS;
-            result.z = s * 0.25;
+            result.w = (matrix.m1 - matrix.m4)*invS;
+            result.x = (matrix.m8 + matrix.m2)*invS;
+            result.y = (matrix.m9 + matrix.m6)*invS;
+            result.z = s*0.25f;
         }
         }
     }
     }
 
 
@@ -974,22 +1011,22 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q)
     float wy = w*y2;
     float wy = w*y2;
     float wz = w*z2;
     float wz = w*z2;
 
 
-    result.m0 = 1 - (yy + zz);
+    result.m0 = 1.0f - (yy + zz);
     result.m1 = xy - wz;
     result.m1 = xy - wz;
     result.m2 = xz + wy;
     result.m2 = xz + wy;
-    result.m3 = 0;
+    result.m3 = 0.0f;
     result.m4 = xy + wz;
     result.m4 = xy + wz;
-    result.m5 = 1 - (xx + zz);
+    result.m5 = 1.0f - (xx + zz);
     result.m6 = yz - wx;
     result.m6 = yz - wx;
-    result.m7 = 0;
+    result.m7 = 0.0f;
     result.m8 = xz - wy;
     result.m8 = xz - wy;
     result.m9 = yz + wx;
     result.m9 = yz + wx;
-    result.m10 = 1 - (xx + yy);
-    result.m11 = 0;
-    result.m12 = 0;
-    result.m13 = 0;
-    result.m14 = 0;
-    result.m15 = 1;
+    result.m10 = 1.0f - (xx + yy);
+    result.m11 = 0.0f;
+    result.m12 = 0.0f;
+    result.m13 = 0.0f;
+    result.m14 = 0.0f;
+    result.m15 = 1.0f;
     
     
     return result;
     return result;
 }
 }
@@ -998,17 +1035,17 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q)
 // NOTE: angle must be provided in radians
 // NOTE: angle must be provided in radians
 RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis)
 RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis)
 {
 {
-    Quaternion result = { 0, 0, 0, 1 };
+    Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f };
 
 
-    if (VectorLength(axis) != 0.0)
+    if (VectorLength(axis) != 0.0f)
 
 
-    angle *= 0.5;
+    angle *= 0.5f;
 
 
     VectorNormalize(&axis);
     VectorNormalize(&axis);
 
 
-    result.x = axis.x * (float)sin(angle);
-    result.y = axis.y * (float)sin(angle);
-    result.z = axis.z * (float)sin(angle);
+    result.x = axis.x*(float)sin(angle);
+    result.y = axis.y*(float)sin(angle);
+    result.z = axis.z*(float)sin(angle);
     result.w = (float)cos(angle);
     result.w = (float)cos(angle);
 
 
     QuaternionNormalize(&result);
     QuaternionNormalize(&result);
@@ -1021,23 +1058,23 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis
 {
 {
     if (fabs(q.w) > 1.0f) QuaternionNormalize(&q);
     if (fabs(q.w) > 1.0f) QuaternionNormalize(&q);
 
 
-    Vector3 resAxis = { 0, 0, 0 };
-    float resAngle = 0;
+    Vector3 resAxis = { 0.0f, 0.0f, 0.0f };
+    float resAngle = 0.0f;
 
 
-    resAngle = 2.0f * (float)acos(q.w);
-    float den = (float)sqrt(1.0 - q.w * q.w);
+    resAngle = 2.0f*(float)acos(q.w);
+    float den = (float)sqrt(1.0f - q.w*q.w);
 
 
     if (den > 0.0001f)
     if (den > 0.0001f)
     {
     {
-        resAxis.x = q.x / den;
-        resAxis.y = q.y / den;
-        resAxis.z = q.z / den;
+        resAxis.x = q.x/den;
+        resAxis.y = q.y/den;
+        resAxis.z = q.z/den;
     }
     }
     else
     else
     {
     {
         // This occurs when the angle is zero.
         // This occurs when the angle is zero.
         // Not a problem: just set an arbitrary normalized axis.
         // Not a problem: just set an arbitrary normalized axis.
-        resAxis.x = 1.0;
+        resAxis.x = 1.0f;
     }
     }
 
 
     *outAxis = resAxis;
     *outAxis = resAxis;
@@ -1058,5 +1095,6 @@ RMDEF void QuaternionTransform(Quaternion *q, Matrix mat)
     q->w = mat.m3*x + mat.m7*y + mat.m11*z + mat.m15*w;
     q->w = mat.m3*x + mat.m7*y + mat.m11*z + mat.m15*w;
 }
 }
 
 
-#endif // RAYMATH_DEFINE
-#endif // RAYMATH_H
+#endif  // RAYMATH_IMPLEMENTATION
+
+#endif  // RAYMATH_H

+ 2 - 0
src/rlgl.c

@@ -32,6 +32,8 @@
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand()
 #include <stdlib.h>         // Declares malloc() and free() for memory management, rand()
 #include <string.h>         // Declares strcmp(), strlen(), strtok()
 #include <string.h>         // Declares strcmp(), strlen(), strtok()
 
 
+#include "raymath.h"        // Required for Vector3 and Matrix functions
+
 #if defined(GRAPHICS_API_OPENGL_11)
 #if defined(GRAPHICS_API_OPENGL_11)
     #ifdef __APPLE__                // OpenGL include for OSX
     #ifdef __APPLE__                // OpenGL include for OSX
         #include <OpenGL/gl.h>
         #include <OpenGL/gl.h>

+ 5 - 4
src/rlgl.h

@@ -37,11 +37,12 @@
 #endif
 #endif
 
 
 #if defined(RLGL_STANDALONE)
 #if defined(RLGL_STANDALONE)
-    #define RAYMATH_STANDALONE
+    #define RAYMATH_IMPLEMENTATION  // Use raymath as a header-only library (includes implementation)
+    #define RAYMATH_EXTERN_INLINE   // Compile raymath functions as static inline (remember, it's a compiler hint)
+    #define RAYMATH_STANDALONE      // Not dependent on raylib.h structs: Vector3, Matrix
+    #include "raymath.h"            // Required for Vector3 and Matrix functions
 #endif
 #endif
 
 
-#include "raymath.h"            // Required for data type Matrix and Matrix functions
-
 // Select desired OpenGL version
 // Select desired OpenGL version
 // NOTE: Those preprocessor defines are only used on rlgl module,
 // NOTE: Those preprocessor defines are only used on rlgl module,
 // if OpenGL version is required by any other module, it uses rlGetVersion()
 // if OpenGL version is required by any other module, it uses rlGetVersion()
@@ -92,7 +93,7 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
 
 
 typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
 typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
 
 
-#ifdef RLGL_STANDALONE
+#if defined(RLGL_STANDALONE)
     #ifndef __cplusplus
     #ifndef __cplusplus
     // Boolean type
     // Boolean type
     typedef enum { false, true } bool;
     typedef enum { false, true } bool;

File diff suppressed because it is too large
+ 349 - 213
src/stb_image.h


+ 446 - 132
src/stb_image_write.h

@@ -1,7 +1,6 @@
-/* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h
-   writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
-                            no warranty implied; use at your own risk
-
+/* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h
+   writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
+                                     no warranty implied; use at your own risk
 
 
    Before #including,
    Before #including,
 
 
@@ -18,7 +17,7 @@ ABOUT:
 
 
    The PNG output is not optimal; it is 20-50% larger than the file
    The PNG output is not optimal; it is 20-50% larger than the file
    written by a decent optimizing implementation. This library is designed
    written by a decent optimizing implementation. This library is designed
-   for source code compactness and simplicitly, not optimal image file size
+   for source code compactness and simplicity, not optimal image file size
    or run-time performance.
    or run-time performance.
 
 
 BUILDING:
 BUILDING:
@@ -35,7 +34,22 @@ USAGE:
      int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
      int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
      int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
      int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
      int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
      int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
-     int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
+     int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+
+   There are also four equivalent functions that use an arbitrary write function. You are
+   expected to open/close your file-equivalent before and after calling these:
+
+     int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
+     int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
+     int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
+     int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
+
+   where the callback is:
+      void stbi_write_func(void *context, void *data, int size);
+
+   You can define STBI_WRITE_NO_STDIO to disable the file variant of these
+   functions, so the library will not use stdio.h at all. However, this will
+   also disable HDR writing, because it requires stdio for formatted output.
 
 
    Each function returns 0 on failure and non-0 on success.
    Each function returns 0 on failure and non-0 on success.
 
 
@@ -63,6 +77,9 @@ USAGE:
    data, alpha (if provided) is discarded, and for monochrome data it is
    data, alpha (if provided) is discarded, and for monochrome data it is
    replicated across all three channels.
    replicated across all three channels.
 
 
+   TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
+   data, set the global variable 'stbi_write_tga_with_rle' to 0.
+
 CREDITS:
 CREDITS:
 
 
    PNG/BMP/TGA
    PNG/BMP/TGA
@@ -73,8 +90,25 @@ CREDITS:
       Jean-Sebastien Guay
       Jean-Sebastien Guay
    misc enhancements:
    misc enhancements:
       Tim Kelsey
       Tim Kelsey
+   TGA RLE
+      Alan Hickman
+   initial file IO callback implementation
+      Emmanuel Julien
    bugfixes:
    bugfixes:
       github:Chribba
       github:Chribba
+      Guillaume Chereau
+      github:jry2
+      github:romigrou
+      Sergio Gonzalez
+      Jonas Karlsson
+      Filip Wasil
+      
+LICENSE
+
+This software is in the public domain. Where that dedication is not
+recognized, you are granted a perpetual, irrevocable license to copy,
+distribute, and modify this file as you see fit.
+
 */
 */
 
 
 #ifndef INCLUDE_STB_IMAGE_WRITE_H
 #ifndef INCLUDE_STB_IMAGE_WRITE_H
@@ -84,10 +118,26 @@ CREDITS:
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-extern int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
-extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
-extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
-extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+#ifdef STB_IMAGE_WRITE_STATIC
+#define STBIWDEF static
+#else
+#define STBIWDEF extern
+extern int stbi_write_tga_with_rle;
+#endif
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
+STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
+STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
+STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+#endif
+
+typedef void stbi_write_func(void *context, void *data, int size);
+
+STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
+STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
+STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
+STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
@@ -97,25 +147,43 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl
 
 
 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
 
 
+#ifdef _WIN32
+   #ifndef _CRT_SECURE_NO_WARNINGS
+   #define _CRT_SECURE_NO_WARNINGS
+   #endif
+   #ifndef _CRT_NONSTDC_NO_DEPRECATE
+   #define _CRT_NONSTDC_NO_DEPRECATE
+   #endif
+#endif
+
+#ifndef STBI_WRITE_NO_STDIO
+#include <stdio.h>
+#endif // STBI_WRITE_NO_STDIO
+
 #include <stdarg.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <string.h>
 #include <string.h>
 #include <math.h>
 #include <math.h>
 
 
-#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
+#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
 // ok
 // ok
-#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
+#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
 // ok
 // ok
 #else
 #else
-#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
+#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
 #endif
 #endif
 
 
 #ifndef STBIW_MALLOC
 #ifndef STBIW_MALLOC
-#define STBIW_MALLOC(sz)    malloc(sz)
-#define STBIW_REALLOC(p,sz) realloc(p,sz)
-#define STBIW_FREE(p)       free(p)
+#define STBIW_MALLOC(sz)        malloc(sz)
+#define STBIW_REALLOC(p,newsz)  realloc(p,newsz)
+#define STBIW_FREE(p)           free(p)
 #endif
 #endif
+
+#ifndef STBIW_REALLOC_SIZED
+#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
+#endif
+
+
 #ifndef STBIW_MEMMOVE
 #ifndef STBIW_MEMMOVE
 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
 #endif
 #endif
@@ -126,22 +194,73 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl
 #define STBIW_ASSERT(x) assert(x)
 #define STBIW_ASSERT(x) assert(x)
 #endif
 #endif
 
 
+#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
+
+typedef struct
+{
+   stbi_write_func *func;
+   void *context;
+} stbi__write_context;
+
+// initialize a callback-based context
+static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
+{
+   s->func    = c;
+   s->context = context;
+}
+
+#ifndef STBI_WRITE_NO_STDIO
+
+static void stbi__stdio_write(void *context, void *data, int size)
+{
+   fwrite(data,1,size,(FILE*) context);
+}
+
+static int stbi__start_write_file(stbi__write_context *s, const char *filename)
+{
+   FILE *f = fopen(filename, "wb");
+   stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
+   return f != NULL;
+}
+
+static void stbi__end_write_file(stbi__write_context *s)
+{
+   fclose((FILE *)s->context);
+}
+
+#endif // !STBI_WRITE_NO_STDIO
+
 typedef unsigned int stbiw_uint32;
 typedef unsigned int stbiw_uint32;
 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
 
 
-static void writefv(FILE *f, const char *fmt, va_list v)
+#ifdef STB_IMAGE_WRITE_STATIC
+static int stbi_write_tga_with_rle = 1;
+#else
+int stbi_write_tga_with_rle = 1;
+#endif
+
+static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
 {
 {
    while (*fmt) {
    while (*fmt) {
       switch (*fmt++) {
       switch (*fmt++) {
          case ' ': break;
          case ' ': break;
-         case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
-         case '2': { int x = va_arg(v,int); unsigned char b[2];
-                     b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
-                     fwrite(b,2,1,f); break; }
-         case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
-                     b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
-                     b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
-                     fwrite(b,4,1,f); break; }
+         case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
+                     s->func(s->context,&x,1);
+                     break; }
+         case '2': { int x = va_arg(v,int);
+                     unsigned char b[2];
+                     b[0] = STBIW_UCHAR(x);
+                     b[1] = STBIW_UCHAR(x>>8);
+                     s->func(s->context,b,2);
+                     break; }
+         case '4': { stbiw_uint32 x = va_arg(v,int);
+                     unsigned char b[4];
+                     b[0]=STBIW_UCHAR(x);
+                     b[1]=STBIW_UCHAR(x>>8);
+                     b[2]=STBIW_UCHAR(x>>16);
+                     b[3]=STBIW_UCHAR(x>>24);
+                     s->func(s->context,b,4);
+                     break; }
          default:
          default:
             STBIW_ASSERT(0);
             STBIW_ASSERT(0);
             return;
             return;
@@ -149,18 +268,60 @@ static void writefv(FILE *f, const char *fmt, va_list v)
    }
    }
 }
 }
 
 
-static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
+static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
+{
+   va_list v;
+   va_start(v, fmt);
+   stbiw__writefv(s, fmt, v);
+   va_end(v);
+}
+
+static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
 {
 {
    unsigned char arr[3];
    unsigned char arr[3];
    arr[0] = a, arr[1] = b, arr[2] = c;
    arr[0] = a, arr[1] = b, arr[2] = c;
-   fwrite(arr, 3, 1, f);
+   s->func(s->context, arr, 3);
 }
 }
 
 
-static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
+static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
 {
 {
    unsigned char bg[3] = { 255, 0, 255}, px[3];
    unsigned char bg[3] = { 255, 0, 255}, px[3];
+   int k;
+
+   if (write_alpha < 0)
+      s->func(s->context, &d[comp - 1], 1);
+
+   switch (comp) {
+      case 1:
+         s->func(s->context,d,1);
+         break;
+      case 2:
+         if (expand_mono)
+            stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
+         else
+            s->func(s->context, d, 1);  // monochrome TGA
+         break;
+      case 4:
+         if (!write_alpha) {
+            // composite against pink background
+            for (k = 0; k < 3; ++k)
+               px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
+            stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
+            break;
+         }
+         /* FALLTHROUGH */
+      case 3:
+         stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
+         break;
+   }
+   if (write_alpha > 0)
+      s->func(s->context, &d[comp - 1], 1);
+}
+
+static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
+{
    stbiw_uint32 zero = 0;
    stbiw_uint32 zero = 0;
-   int i,j,k, j_end;
+   int i,j, j_end;
 
 
    if (y <= 0)
    if (y <= 0)
       return;
       return;
@@ -173,73 +334,148 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp,
    for (; j != j_end; j += vdir) {
    for (; j != j_end; j += vdir) {
       for (i=0; i < x; ++i) {
       for (i=0; i < x; ++i) {
          unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
          unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
-         if (write_alpha < 0)
-            fwrite(&d[comp-1], 1, 1, f);
-         switch (comp) {
-            case 1: fwrite(d, 1, 1, f);
-                    break;
-            case 2: if (expand_mono)
-                       write3(f, d[0],d[0],d[0]); // monochrome bmp
-                    else
-                       fwrite(d, 1, 1, f);  // monochrome TGA
-                    break;
-            case 4:
-               if (!write_alpha) {
-                  // composite against pink background
-                  for (k=0; k < 3; ++k)
-                     px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
-                  write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
-                  break;
-               }
-               /* FALLTHROUGH */
-            case 3:
-               write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
-               break;
-         }
-         if (write_alpha > 0)
-            fwrite(&d[comp-1], 1, 1, f);
+         stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
       }
       }
-      fwrite(&zero,scanline_pad,1,f);
+      s->func(s->context, &zero, scanline_pad);
    }
    }
 }
 }
 
 
-static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
+static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
 {
 {
-   FILE *f;
-   if (y < 0 || x < 0) return 0;
-   f = fopen(filename, "wb");
-   if (f) {
+   if (y < 0 || x < 0) {
+      return 0;
+   } else {
       va_list v;
       va_list v;
       va_start(v, fmt);
       va_start(v, fmt);
-      writefv(f, fmt, v);
+      stbiw__writefv(s, fmt, v);
       va_end(v);
       va_end(v);
-      write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
-      fclose(f);
+      stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
+      return 1;
    }
    }
-   return f != NULL;
 }
 }
 
 
-int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
+static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
 {
 {
    int pad = (-x*3) & 3;
    int pad = (-x*3) & 3;
-   return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
+   return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
            "11 4 22 4" "4 44 22 444444",
            "11 4 22 4" "4 44 22 444444",
            'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
            'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
             40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
             40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
 }
 }
 
 
-int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
+STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
+{
+   stbi__write_context s;
+   stbi__start_write_callbacks(&s, func, context);
+   return stbi_write_bmp_core(&s, x, y, comp, data);
+}
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
+{
+   stbi__write_context s;
+   if (stbi__start_write_file(&s,filename)) {
+      int r = stbi_write_bmp_core(&s, x, y, comp, data);
+      stbi__end_write_file(&s);
+      return r;
+   } else
+      return 0;
+}
+#endif //!STBI_WRITE_NO_STDIO
+
+static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
 {
 {
    int has_alpha = (comp == 2 || comp == 4);
    int has_alpha = (comp == 2 || comp == 4);
    int colorbytes = has_alpha ? comp-1 : comp;
    int colorbytes = has_alpha ? comp-1 : comp;
    int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
    int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
-   return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
-                  "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
+
+   if (y < 0 || x < 0)
+      return 0;
+
+   if (!stbi_write_tga_with_rle) {
+      return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
+         "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
+   } else {
+      int i,j,k;
+
+      stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
+
+      for (j = y - 1; j >= 0; --j) {
+          unsigned char *row = (unsigned char *) data + j * x * comp;
+         int len;
+
+         for (i = 0; i < x; i += len) {
+            unsigned char *begin = row + i * comp;
+            int diff = 1;
+            len = 1;
+
+            if (i < x - 1) {
+               ++len;
+               diff = memcmp(begin, row + (i + 1) * comp, comp);
+               if (diff) {
+                  const unsigned char *prev = begin;
+                  for (k = i + 2; k < x && len < 128; ++k) {
+                     if (memcmp(prev, row + k * comp, comp)) {
+                        prev += comp;
+                        ++len;
+                     } else {
+                        --len;
+                        break;
+                     }
+                  }
+               } else {
+                  for (k = i + 2; k < x && len < 128; ++k) {
+                     if (!memcmp(begin, row + k * comp, comp)) {
+                        ++len;
+                     } else {
+                        break;
+                     }
+                  }
+               }
+            }
+
+            if (diff) {
+               unsigned char header = STBIW_UCHAR(len - 1);
+               s->func(s->context, &header, 1);
+               for (k = 0; k < len; ++k) {
+                  stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
+               }
+            } else {
+               unsigned char header = STBIW_UCHAR(len - 129);
+               s->func(s->context, &header, 1);
+               stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
+            }
+         }
+      }
+   }
+   return 1;
+}
+
+int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
+{
+   stbi__write_context s;
+   stbi__start_write_callbacks(&s, func, context);
+   return stbi_write_tga_core(&s, x, y, comp, (void *) data);
 }
 }
 
 
+#ifndef STBI_WRITE_NO_STDIO
+int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
+{
+   stbi__write_context s;
+   if (stbi__start_write_file(&s,filename)) {
+      int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
+      stbi__end_write_file(&s);
+      return r;
+   } else
+      return 0;
+}
+#endif
+
 // *************************************************************************************************
 // *************************************************************************************************
 // Radiance RGBE HDR writer
 // Radiance RGBE HDR writer
 // by Baldur Karlsson
 // by Baldur Karlsson
+#ifndef STBI_WRITE_NO_STDIO
+
 #define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
 #define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
 
 
 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
@@ -247,7 +483,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
    int exponent;
    int exponent;
    float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
    float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
 
 
-   if (maxcomp < 1e-32) {
+   if (maxcomp < 1e-32f) {
       rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
       rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
    } else {
    } else {
       float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
       float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
@@ -259,23 +495,23 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
    }
    }
 }
 }
 
 
-void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
+void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
 {
 {
-   unsigned char lengthbyte = (unsigned char) (length+128);
+   unsigned char lengthbyte = STBIW_UCHAR(length+128);
    STBIW_ASSERT(length+128 <= 255);
    STBIW_ASSERT(length+128 <= 255);
-   fwrite(&lengthbyte, 1, 1, f);
-   fwrite(&databyte, 1, 1, f);
+   s->func(s->context, &lengthbyte, 1);
+   s->func(s->context, &databyte, 1);
 }
 }
 
 
-void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
+void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
 {
 {
-   unsigned char lengthbyte = (unsigned char )(length & 0xff);
+   unsigned char lengthbyte = STBIW_UCHAR(length);
    STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
    STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
-   fwrite(&lengthbyte, 1, 1, f);
-   fwrite(data, length, 1, f);
+   s->func(s->context, &lengthbyte, 1);
+   s->func(s->context, data, length);
 }
 }
 
 
-void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
+void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
 {
 {
    unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
    unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
    unsigned char rgbe[4];
    unsigned char rgbe[4];
@@ -288,31 +524,31 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
    /* skip RLE for images too small or large */
    /* skip RLE for images too small or large */
    if (width < 8 || width >= 32768) {
    if (width < 8 || width >= 32768) {
       for (x=0; x < width; x++) {
       for (x=0; x < width; x++) {
-         switch (comp) {
+         switch (ncomp) {
             case 4: /* fallthrough */
             case 4: /* fallthrough */
-            case 3: linear[2] = scanline[x*comp + 2];
-                    linear[1] = scanline[x*comp + 1];
-                    linear[0] = scanline[x*comp + 0];
+            case 3: linear[2] = scanline[x*ncomp + 2];
+                    linear[1] = scanline[x*ncomp + 1];
+                    linear[0] = scanline[x*ncomp + 0];
                     break;
                     break;
-            case 2: /* fallthrough */
-            case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
+            default:
+                    linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
                     break;
                     break;
          }
          }
          stbiw__linear_to_rgbe(rgbe, linear);
          stbiw__linear_to_rgbe(rgbe, linear);
-         fwrite(rgbe, 4, 1, f);
+         s->func(s->context, rgbe, 4);
       }
       }
    } else {
    } else {
       int c,r;
       int c,r;
       /* encode into scratch buffer */
       /* encode into scratch buffer */
       for (x=0; x < width; x++) {
       for (x=0; x < width; x++) {
-         switch(comp) {
+         switch(ncomp) {
             case 4: /* fallthrough */
             case 4: /* fallthrough */
-            case 3: linear[2] = scanline[x*comp + 2];
-                    linear[1] = scanline[x*comp + 1];
-                    linear[0] = scanline[x*comp + 0];
+            case 3: linear[2] = scanline[x*ncomp + 2];
+                    linear[1] = scanline[x*ncomp + 1];
+                    linear[0] = scanline[x*ncomp + 0];
                     break;
                     break;
-            case 2: /* fallthrough */
-            case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
+            default:
+                    linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
                     break;
                     break;
          }
          }
          stbiw__linear_to_rgbe(rgbe, linear);
          stbiw__linear_to_rgbe(rgbe, linear);
@@ -322,7 +558,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
          scratch[x + width*3] = rgbe[3];
          scratch[x + width*3] = rgbe[3];
       }
       }
 
 
-      fwrite(scanlineheader, 4, 1, f);
+      s->func(s->context, scanlineheader, 4);
 
 
       /* RLE each component separately */
       /* RLE each component separately */
       for (c=0; c < 4; c++) {
       for (c=0; c < 4; c++) {
@@ -343,7 +579,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
             while (x < r) {
             while (x < r) {
                int len = r-x;
                int len = r-x;
                if (len > 128) len = 128;
                if (len > 128) len = 128;
-               stbiw__write_dump_data(f, len, &comp[x]);
+               stbiw__write_dump_data(s, len, &comp[x]);
                x += len;
                x += len;
             }
             }
             // if there's a run, output it
             // if there's a run, output it
@@ -355,7 +591,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
                while (x < r) {
                while (x < r) {
                   int len = r-x;
                   int len = r-x;
                   if (len > 127) len = 127;
                   if (len > 127) len = 127;
-                  stbiw__write_run_data(f, len, comp[x]);
+                  stbiw__write_run_data(s, len, comp[x]);
                   x += len;
                   x += len;
                }
                }
             }
             }
@@ -364,27 +600,52 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
    }
    }
 }
 }
 
 
-int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
+static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
 {
 {
-   int i;
-   FILE *f;
-   if (y <= 0 || x <= 0 || data == NULL) return 0;
-   f = fopen(filename, "wb");
-   if (f) {
-      /* Each component is stored separately. Allocate scratch space for full output scanline. */
+   if (y <= 0 || x <= 0 || data == NULL)
+      return 0;
+   else {
+      // Each component is stored separately. Allocate scratch space for full output scanline.
       unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
       unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
-      fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"      );
-      fprintf(f, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n"                 , y, x);
+      int i, len;
+      char buffer[128];
+      char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
+      s->func(s->context, header, sizeof(header)-1);
+
+      len = sprintf(buffer, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
+      s->func(s->context, buffer, len);
+
       for(i=0; i < y; i++)
       for(i=0; i < y; i++)
-         stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
+         stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
       STBIW_FREE(scratch);
       STBIW_FREE(scratch);
-      fclose(f);
+      return 1;
    }
    }
-   return f != NULL;
 }
 }
 
 
-/////////////////////////////////////////////////////////
-// PNG
+int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
+{
+   stbi__write_context s;
+   stbi__start_write_callbacks(&s, func, context);
+   return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
+}
+
+int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
+{
+   stbi__write_context s;
+   if (stbi__start_write_file(&s,filename)) {
+      int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
+      stbi__end_write_file(&s);
+      return r;
+   } else
+      return 0;
+}
+#endif // STBI_WRITE_NO_STDIO
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// PNG writer
+//
 
 
 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
 #define stbiw__sbraw(a) ((int *) (a) - 2)
 #define stbiw__sbraw(a) ((int *) (a) - 2)
@@ -402,7 +663,7 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da
 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
 {
 {
    int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
    int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
-   void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
+   void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
    STBIW_ASSERT(p);
    STBIW_ASSERT(p);
    if (p) {
    if (p) {
       if (!*arr) ((int *) p)[1] = 0;
       if (!*arr) ((int *) p)[1] = 0;
@@ -415,7 +676,7 @@ static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
 {
 {
    while (*bitcount >= 8) {
    while (*bitcount >= 8) {
-      stbiw__sbpush(data, (unsigned char) *bitbuffer);
+      stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
       *bitbuffer >>= 8;
       *bitbuffer >>= 8;
       *bitcount -= 8;
       *bitcount -= 8;
    }
    }
@@ -550,18 +811,19 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
 
 
    {
    {
       // compute adler32 on input
       // compute adler32 on input
-      unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
-      int j=0;
+      unsigned int s1=1, s2=0;
+      int blocklen = (int) (data_len % 5552);
+      j=0;
       while (j < data_len) {
       while (j < data_len) {
          for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
          for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
          s1 %= 65521, s2 %= 65521;
          s1 %= 65521, s2 %= 65521;
          j += blocklen;
          j += blocklen;
          blocklen = 5552;
          blocklen = 5552;
       }
       }
-      stbiw__sbpush(out, (unsigned char) (s2 >> 8));
-      stbiw__sbpush(out, (unsigned char) s2);
-      stbiw__sbpush(out, (unsigned char) (s1 >> 8));
-      stbiw__sbpush(out, (unsigned char) s1);
+      stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
+      stbiw__sbpush(out, STBIW_UCHAR(s2));
+      stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
+      stbiw__sbpush(out, STBIW_UCHAR(s1));
    }
    }
    *out_len = stbiw__sbn(out);
    *out_len = stbiw__sbn(out);
    // make returned pointer freeable
    // make returned pointer freeable
@@ -569,21 +831,52 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
    return (unsigned char *) stbiw__sbraw(out);
    return (unsigned char *) stbiw__sbraw(out);
 }
 }
 
 
-unsigned int stbiw__crc32(unsigned char *buffer, int len)
+static unsigned int stbiw__crc32(unsigned char *buffer, int len)
 {
 {
-   static unsigned int crc_table[256];
+   static unsigned int crc_table[256] =
+   {
+      0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+      0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+      0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+      0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+      0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+      0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+      0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+      0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+      0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+      0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+      0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+      0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+      0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+      0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+      0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+      0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+      0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+      0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+      0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+      0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+      0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+      0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+      0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+      0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+      0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+      0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+      0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+      0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+      0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+      0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+      0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+      0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+   };
+
    unsigned int crc = ~0u;
    unsigned int crc = ~0u;
-   int i,j;
-   if (crc_table[1] == 0)
-      for(i=0; i < 256; i++)
-         for (crc_table[i]=i, j=0; j < 8; ++j)
-            crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
+   int i;
    for (i=0; i < len; ++i)
    for (i=0; i < len; ++i)
       crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
       crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
    return ~crc;
    return ~crc;
 }
 }
 
 
-#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
+#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
 
 
@@ -596,9 +889,9 @@ static void stbiw__wpcrc(unsigned char **data, int len)
 static unsigned char stbiw__paeth(int a, int b, int c)
 static unsigned char stbiw__paeth(int a, int b, int c)
 {
 {
    int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
    int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
-   if (pa <= pb && pa <= pc) return (unsigned char) a;
-   if (pb <= pc) return (unsigned char) b;
-   return (unsigned char) c;
+   if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
+   if (pb <= pc) return STBIW_UCHAR(b);
+   return STBIW_UCHAR(c);
 }
 }
 
 
 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
@@ -671,7 +964,7 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
    stbiw__wp32(o, x);
    stbiw__wp32(o, x);
    stbiw__wp32(o, y);
    stbiw__wp32(o, y);
    *o++ = 8;
    *o++ = 8;
-   *o++ = (unsigned char) ctype[n];
+   *o++ = STBIW_UCHAR(ctype[n]);
    *o++ = 0;
    *o++ = 0;
    *o++ = 0;
    *o++ = 0;
    *o++ = 0;
    *o++ = 0;
@@ -693,12 +986,13 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
    return out;
    return out;
 }
 }
 
 
-int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
 {
 {
    FILE *f;
    FILE *f;
    int len;
    int len;
    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
-   if (!png) return 0;
+   if (png == NULL) return 0;
    f = fopen(filename, "wb");
    f = fopen(filename, "wb");
    if (!f) { STBIW_FREE(png); return 0; }
    if (!f) { STBIW_FREE(png); return 0; }
    fwrite(png, 1, len, f);
    fwrite(png, 1, len, f);
@@ -706,9 +1000,29 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat
    STBIW_FREE(png);
    STBIW_FREE(png);
    return 1;
    return 1;
 }
 }
+#endif
+
+STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
+{
+   int len;
+   unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
+   if (png == NULL) return 0;
+   func(context, png, len);
+   STBIW_FREE(png);
+   return 1;
+}
+
 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
 
 
 /* Revision history
 /* Revision history
+      1.01 (2016-01-16)
+             STBIW_REALLOC_SIZED: support allocators with no realloc support
+             avoid race-condition in crc initialization
+             minor compile issues
+      1.00 (2015-09-14)
+             installable file IO function
+      0.99 (2015-09-13)
+             warning fixes; TGA rle support
       0.98 (2015-04-08)
       0.98 (2015-04-08)
              added STBIW_MALLOC, STBIW_ASSERT etc
              added STBIW_MALLOC, STBIW_ASSERT etc
       0.97 (2015-01-18)
       0.97 (2015-01-18)

+ 35 - 21
src/stb_truetype.h

@@ -1,4 +1,4 @@
-// stb_truetype.h - v1.08 - public domain
+// stb_truetype.h - v1.09 - public domain
 // authored from 2009-2015 by Sean Barrett / RAD Game Tools
 // authored from 2009-2015 by Sean Barrett / RAD Game Tools
 //
 //
 //   This library processes TrueType files:
 //   This library processes TrueType files:
@@ -42,12 +42,15 @@
 //       Sergey Popov
 //       Sergey Popov
 //       Giumo X. Clanjor
 //       Giumo X. Clanjor
 //       Higor Euripedes
 //       Higor Euripedes
+//       Thomas Fields
+//       Derek Vinyard
 //
 //
 //   Misc other:
 //   Misc other:
 //       Ryan Gordon
 //       Ryan Gordon
 //
 //
 // VERSION HISTORY
 // VERSION HISTORY
 //
 //
+//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
 //   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
 //   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
 //   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
 //   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
 //                     variant PackFontRanges to pack and render in separate phases;
 //                     variant PackFontRanges to pack and render in separate phases;
@@ -1556,7 +1559,7 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
 
 
 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
 {
 {
-   int x0,y0,x1,y1;
+   int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
    if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
    if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
       // e.g. space character
       // e.g. space character
       if (ix0) *ix0 = 0;
       if (ix0) *ix0 = 0;
@@ -1672,6 +1675,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
 {
 {
    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
+   STBTT_assert(z != NULL);
    if (!z) return z;
    if (!z) return z;
    
    
    // round dx down to avoid overshooting
    // round dx down to avoid overshooting
@@ -1693,6 +1697,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
 {
 {
    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
    stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
    float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
+   STBTT_assert(z != NULL);
    //STBTT_assert(e->y0 <= start_point);
    //STBTT_assert(e->y0 <= start_point);
    if (!z) return z;
    if (!z) return z;
    z->fdx = dxdy;
    z->fdx = dxdy;
@@ -1817,21 +1822,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
          while (e->y0 <= scan_y) {
          while (e->y0 <= scan_y) {
             if (e->y1 > scan_y) {
             if (e->y1 > scan_y) {
                stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
                stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
-               // find insertion point
-               if (active == NULL)
-                  active = z;
-               else if (z->x < active->x) {
-                  // insert at front
-                  z->next = active;
-                  active = z;
-               } else {
-                  // find thing to insert AFTER
-                  stbtt__active_edge *p = active;
-                  while (p->next && p->next->x < z->x)
-                     p = p->next;
-                  // at this point, p->next->x is NOT < z->x
-                  z->next = p->next;
-                  p->next = z;
+               if (z != NULL) {
+                  // find insertion point
+                  if (active == NULL)
+                     active = z;
+                  else if (z->x < active->x) {
+                     // insert at front
+                     z->next = active;
+                     active = z;
+                  } else {
+                     // find thing to insert AFTER
+                     stbtt__active_edge *p = active;
+                     while (p->next && p->next->x < z->x)
+                        p = p->next;
+                     // at this point, p->next->x is NOT < z->x
+                     z->next = p->next;
+                     p->next = z;
+                  }
                }
                }
             }
             }
             ++e;
             ++e;
@@ -2101,10 +2108,12 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
       while (e->y0 <= scan_y_bottom) {
       while (e->y0 <= scan_y_bottom) {
          if (e->y0 != e->y1) {
          if (e->y0 != e->y1) {
             stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
             stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
-            STBTT_assert(z->ey >= scan_y_top);
-            // insert at front
-            z->next = active;
-            active = z;
+            if (z != NULL) {
+               STBTT_assert(z->ey >= scan_y_top);
+               // insert at front
+               z->next = active;
+               active = z;
+            }
          }
          }
          ++e;
          ++e;
       }
       }
@@ -2513,6 +2522,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset,  // fo
    float scale;
    float scale;
    int x,y,bottom_y, i;
    int x,y,bottom_y, i;
    stbtt_fontinfo f;
    stbtt_fontinfo f;
+   f.userdata = NULL;
    if (!stbtt_InitFont(&f, data, offset))
    if (!stbtt_InitFont(&f, data, offset))
       return -1;
       return -1;
    STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
    STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
@@ -2706,6 +2716,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i
    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
    int safe_w = w - kernel_width;
    int safe_w = w - kernel_width;
    int j;
    int j;
+   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
    for (j=0; j < h; ++j) {
    for (j=0; j < h; ++j) {
       int i;
       int i;
       unsigned int total;
       unsigned int total;
@@ -2767,6 +2778,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i
    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
    unsigned char buffer[STBTT_MAX_OVERSAMPLE];
    int safe_h = h - kernel_width;
    int safe_h = h - kernel_width;
    int j;
    int j;
+   STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
    for (j=0; j < w; ++j) {
    for (j=0; j < w; ++j) {
       int i;
       int i;
       unsigned int total;
       unsigned int total;
@@ -2975,6 +2987,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
    if (rects == NULL)
    if (rects == NULL)
       return 0;
       return 0;
 
 
+   info.userdata = spc->user_allocator_context;
    stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
    stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
 
 
    n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
    n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
@@ -3192,6 +3205,7 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const
 
 
 // FULL VERSION HISTORY
 // FULL VERSION HISTORY
 //
 //
+//   1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
 //   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
 //   1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
 //   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
 //   1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
 //                     allow PackFontRanges to pack and render in separate phases;
 //                     allow PackFontRanges to pack and render in separate phases;

File diff suppressed because it is too large
+ 418 - 412
src/stb_vorbis.c


+ 37 - 28
src/stb_vorbis.h

@@ -1,35 +1,45 @@
-// Ogg Vorbis audio decoder - v1.05 - public domain
+// Ogg Vorbis audio decoder - v1.07 - public domain
 // http://nothings.org/stb_vorbis/
 // http://nothings.org/stb_vorbis/
 //
 //
-// Written by Sean Barrett in 2007, last updated in 2014
-// Sponsored by RAD Game Tools.
+// Original version written by Sean Barrett in 2007.
 //
 //
-// Placed in the public domain April 2007 by the author: no copyright
-// is claimed, and you may use it for any purpose you like.
+// Originally sponsored by RAD Game Tools. Seeking sponsored
+// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
+// Aras Pranckevicius, and Sean Barrett.
+//
+// LICENSE
+//
+//   This software is in the public domain. Where that dedication is not
+//   recognized, you are granted a perpetual, irrevocable license to copy,
+//   distribute, and modify this file as you see fit.
 //
 //
 // No warranty for any purpose is expressed or implied by the author (nor
 // No warranty for any purpose is expressed or implied by the author (nor
 // by RAD Game Tools). Report bugs and send enhancements to the author.
 // by RAD Game Tools). Report bugs and send enhancements to the author.
 //
 //
 // Limitations:
 // Limitations:
 //
 //
-//   - seeking not supported except manually via PUSHDATA api
 //   - floor 0 not supported (used in old ogg vorbis files pre-2004)
 //   - floor 0 not supported (used in old ogg vorbis files pre-2004)
 //   - lossless sample-truncation at beginning ignored
 //   - lossless sample-truncation at beginning ignored
 //   - cannot concatenate multiple vorbis streams
 //   - cannot concatenate multiple vorbis streams
 //   - sample positions are 32-bit, limiting seekable 192Khz
 //   - sample positions are 32-bit, limiting seekable 192Khz
 //       files to around 6 hours (Ogg supports 64-bit)
 //       files to around 6 hours (Ogg supports 64-bit)
 //
 //
+// Feature contributors:
+//    Dougall Johnson (sample-exact seeking)
+//
 // Bugfix/warning contributors:
 // Bugfix/warning contributors:
 //    Terje Mathisen     Niklas Frykholm     Andy Hill
 //    Terje Mathisen     Niklas Frykholm     Andy Hill
 //    Casey Muratori     John Bolton         Gargaj
 //    Casey Muratori     John Bolton         Gargaj
 //    Laurent Gomila     Marc LeBlanc        Ronny Chevalier
 //    Laurent Gomila     Marc LeBlanc        Ronny Chevalier
-//    Bernhard Wodo      Evan Balster			"alxprd"@github
+//    Bernhard Wodo      Evan Balster        "alxprd"@github
 //    Tom Beaumont       Ingo Leitgeb        Nicolas Guillemot
 //    Tom Beaumont       Ingo Leitgeb        Nicolas Guillemot
-// (If you reported a bug but do not appear in this list, it is because
-// someone else reported the bug before you. There were too many of you to
-// list them all because I was lax about updating for a long time, sorry.)
+//    Phillip Bennefall  Rohit
 //
 //
 // Partial history:
 // Partial history:
+//    1.07    - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
+//    1.06    - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
+//                           some crash fixes when out of memory or with corrupt files
+//                           fix some inappropriately signed shifts
 //    1.05    - 2015/04/19 - don't define __forceinline if it's redundant
 //    1.05    - 2015/04/19 - don't define __forceinline if it's redundant
 //    1.04    - 2014/08/27 - fix missing const-correct case in API
 //    1.04    - 2014/08/27 - fix missing const-correct case in API
 //    1.03    - 2014/08/07 - warning fixes
 //    1.03    - 2014/08/07 - warning fixes
@@ -37,8 +47,6 @@
 //    1.01    - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
 //    1.01    - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
 //    1.0     - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
 //    1.0     - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
 //                           (API change) report sample rate for decode-full-file funcs
 //                           (API change) report sample rate for decode-full-file funcs
-//    0.99996 -            - bracket #include <malloc.h> for macintosh compilation
-//    0.99995 -            - avoid alias-optimization issue in float-to-int conversion
 //
 //
 // See end of file for full version history.
 // See end of file for full version history.
 
 
@@ -157,10 +165,10 @@ extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f);
 // specification does not bound the size of an individual frame.
 // specification does not bound the size of an individual frame.
 
 
 extern stb_vorbis *stb_vorbis_open_pushdata(
 extern stb_vorbis *stb_vorbis_open_pushdata(
-         unsigned char *datablock, int datablock_length_in_bytes,
+         const unsigned char * datablock, int datablock_length_in_bytes,
          int *datablock_memory_consumed_in_bytes,
          int *datablock_memory_consumed_in_bytes,
          int *error,
          int *error,
-         stb_vorbis_alloc *alloc_buffer);
+         const stb_vorbis_alloc *alloc_buffer);
 // create a vorbis decoder by passing in the initial data block containing
 // create a vorbis decoder by passing in the initial data block containing
 //    the ogg&vorbis headers (you don't need to do parse them, just provide
 //    the ogg&vorbis headers (you don't need to do parse them, just provide
 //    the first N bytes of the file--you're told if it's not enough, see below)
 //    the first N bytes of the file--you're told if it's not enough, see below)
@@ -171,7 +179,8 @@ extern stb_vorbis *stb_vorbis_open_pushdata(
 //       incomplete and you need to pass in a larger block from the start of the file
 //       incomplete and you need to pass in a larger block from the start of the file
 
 
 extern int stb_vorbis_decode_frame_pushdata(
 extern int stb_vorbis_decode_frame_pushdata(
-         stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes,
+         stb_vorbis *f,
+         const unsigned char *datablock, int datablock_length_in_bytes,
          int *channels,             // place to write number of float * buffers
          int *channels,             // place to write number of float * buffers
          float ***output,           // place to write float ** array of float * buffers
          float ***output,           // place to write float ** array of float * buffers
          int *samples               // place to write number of output samples
          int *samples               // place to write number of output samples
@@ -235,18 +244,18 @@ extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *chan
 // When you're done with it, just free() the pointer returned in *output.
 // When you're done with it, just free() the pointer returned in *output.
 
 
 extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
 extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len,
-                                  int *error, stb_vorbis_alloc *alloc_buffer);
+                                  int *error, const stb_vorbis_alloc *alloc_buffer);
 // create an ogg vorbis decoder from an ogg vorbis stream in memory (note
 // create an ogg vorbis decoder from an ogg vorbis stream in memory (note
 // this must be the entire stream!). on failure, returns NULL and sets *error
 // this must be the entire stream!). on failure, returns NULL and sets *error
 
 
 #ifndef STB_VORBIS_NO_STDIO
 #ifndef STB_VORBIS_NO_STDIO
 extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
 extern stb_vorbis * stb_vorbis_open_filename(const char *filename,
-                                  int *error, stb_vorbis_alloc *alloc_buffer);
+                                  int *error, const stb_vorbis_alloc *alloc_buffer);
 // create an ogg vorbis decoder from a filename via fopen(). on failure,
 // create an ogg vorbis decoder from a filename via fopen(). on failure,
 // returns NULL and sets *error (possibly to VORBIS_file_open_failure).
 // returns NULL and sets *error (possibly to VORBIS_file_open_failure).
 
 
 extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
 extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
-                                  int *error, stb_vorbis_alloc *alloc_buffer);
+                                  int *error, const stb_vorbis_alloc *alloc_buffer);
 // create an ogg vorbis decoder from an open FILE *, looking for a stream at
 // create an ogg vorbis decoder from an open FILE *, looking for a stream at
 // the _current_ seek point (ftell). on failure, returns NULL and sets *error.
 // the _current_ seek point (ftell). on failure, returns NULL and sets *error.
 // note that stb_vorbis must "own" this stream; if you seek it in between
 // note that stb_vorbis must "own" this stream; if you seek it in between
@@ -256,7 +265,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
 // function, stb_vorbis_open_file_section(), to limit it.
 // function, stb_vorbis_open_file_section(), to limit it.
 
 
 extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
 extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close,
-                int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len);
+                int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len);
 // create an ogg vorbis decoder from an open FILE *, looking for a stream at
 // create an ogg vorbis decoder from an open FILE *, looking for a stream at
 // the _current_ seek point (ftell); the stream will be of length 'len' bytes.
 // the _current_ seek point (ftell); the stream will be of length 'len' bytes.
 // on failure, returns NULL and sets *error. note that stb_vorbis must "own"
 // on failure, returns NULL and sets *error. note that stb_vorbis must "own"
@@ -266,7 +275,6 @@ extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_cl
 
 
 extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
 extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
 extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
 extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
-// NOT WORKING YET
 // these functions seek in the Vorbis file to (approximately) 'sample_number'.
 // these functions seek in the Vorbis file to (approximately) 'sample_number'.
 // after calling seek_frame(), the next call to get_frame_*() will include
 // after calling seek_frame(), the next call to get_frame_*() will include
 // the specified sample. after calling stb_vorbis_seek(), the next call to
 // the specified sample. after calling stb_vorbis_seek(), the next call to
@@ -275,8 +283,7 @@ extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
 // you can also use seek_frame().
 // you can also use seek_frame().
 
 
 extern void stb_vorbis_seek_start(stb_vorbis *f);
 extern void stb_vorbis_seek_start(stb_vorbis *f);
-// this function is equivalent to stb_vorbis_seek(f,0), but it
-// actually works
+// this function is equivalent to stb_vorbis_seek(f,0)
 
 
 extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
 extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
 extern float        stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
 extern float        stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
@@ -296,15 +303,17 @@ extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***out
 extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
 extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts);
 extern int stb_vorbis_get_frame_short            (stb_vorbis *f, int num_c, short **buffer, int num_samples);
 extern int stb_vorbis_get_frame_short            (stb_vorbis *f, int num_c, short **buffer, int num_samples);
 #endif
 #endif
-// decode the next frame and return the number of samples per channel. the
-// data is coerced to the number of channels you request according to the
+// decode the next frame and return the number of *samples* per channel.
+// Note that for interleaved data, you pass in the number of shorts (the
+// size of your array), but the return value is the number of samples per
+// channel, not the total number of samples.
+//
+// The data is coerced to the number of channels you request according to the
 // channel coercion rules (see below). You must pass in the size of your
 // channel coercion rules (see below). You must pass in the size of your
 // buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
 // buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
 // The maximum buffer size needed can be gotten from get_info(); however,
 // The maximum buffer size needed can be gotten from get_info(); however,
 // the Vorbis I specification implies an absolute maximum of 4096 samples
 // the Vorbis I specification implies an absolute maximum of 4096 samples
-// per channel. Note that for interleaved data, you pass in the number of
-// shorts (the size of your array), but the return value is the number of
-// samples per channel, not the total number of samples.
+// per channel.
 
 
 // Channel coercion rules:
 // Channel coercion rules:
 //    Let M be the number of channels requested, and N the number of channels present,
 //    Let M be the number of channels requested, and N the number of channels present,
@@ -371,7 +380,7 @@ enum STBVorbisError
    VORBIS_invalid_first_page,
    VORBIS_invalid_first_page,
    VORBIS_bad_packet_type,
    VORBIS_bad_packet_type,
    VORBIS_cant_find_last_page,
    VORBIS_cant_find_last_page,
-   VORBIS_seek_failed,
+   VORBIS_seek_failed
 };
 };
 
 
 
 

Some files were not shown because too many files changed in this diff