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

This commit is contained in:
victorfisac 2016-01-20 19:26:52 +01:00
commit 8ae0da1fa1
16 changed files with 1772 additions and 1146 deletions

View File

@ -32,28 +32,30 @@ int main()
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody");
SetTargetFPS(60); // Enable v-sync
InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024)
// Physics initialization
Physics worldPhysics = {true, false, (Vector2){0, -9.81f}};
Physics worldPhysics = { true, false, (Vector2){ 0, -9.81f } };
// Set internal physics settings
SetPhysics(worldPhysics);
// Object initialization
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});
// 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)
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
float moveSpeed = 6.0f;
float jumpForce = 4.5f;
float jumpForce = 5.0f;
SetTargetFPS(60);
//--------------------------------------------------------------------------------------
// Main game loop
@ -67,7 +69,7 @@ int main()
ApplyPhysics(PLAYER_INDEX, &player.position);
// 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
SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){GetRigidbody(PLAYER_INDEX).velocity.x, 0});
@ -77,12 +79,12 @@ int main()
}
// 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
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
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);
// Check if debug mode is enabled
if(worldPhysics.debug)
if (worldPhysics.debug)
{
// 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);
}

View File

@ -11,11 +11,11 @@
#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()
{
@ -25,7 +25,7 @@ int main()
int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces");
SetTargetFPS(60); // Enable v-sync
InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024)
// Physics initialization
@ -36,17 +36,20 @@ int main()
// Objects initialization
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}};
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});
}
// 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)
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
@ -57,19 +60,19 @@ int main()
// Update object physics
// 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);
}
// Check foce button input
if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
AddForceAtPosition(GetMousePosition(), FORCE_INTENSITY, FORCE_RADIUS);
}
// Check debug mode toggle button input
if(IsKeyPressed(KEY_P))
if (IsKeyPressed(KEY_P))
{
// Update program physics value
worldPhysics.debug = !worldPhysics.debug;
@ -86,21 +89,21 @@ int main()
ClearBackground(RAYWHITE);
// Check if debug mode is enabled
if(worldPhysics.debug)
if (worldPhysics.debug)
{
// 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
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
if(i < MAX_OBJECTS)
if (i < MAX_OBJECTS)
{
// 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);
}
@ -114,7 +117,7 @@ int main()
else
{
// 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);
}

View File

@ -38,9 +38,12 @@
#include "raylib.h" // raylib main header
#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
// 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 <stdlib.h> // Declares malloc() and free() for memory management, rand(), atexit()
@ -643,6 +646,46 @@ float *ColorToFloat(Color color)
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
Color GetColor(int hexValue)
{

View File

@ -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/)
*
@ -56,6 +62,14 @@
#ifndef 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>
#ifdef __cplusplus
@ -63,47 +77,47 @@ extern "C" { // Prevents name mangling of functions
#endif
// 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
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
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);
return (c/2*(sqrt(1 - t*(t-=2)) + 1) + b);
}
// 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);
return (c/2*((t-=2)*t*t + 2) + b);
}
// 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);
return (-c/2*(((t-2)*(--t)) - 1) + b);
}
// 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 == d) return (b + c);
@ -113,20 +127,20 @@ float EaseExpoInOut(float t, float b, float c, float d)
}
// 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 postFix = t/=d;
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;
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;
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
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))
{
@ -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);
else return (EaseBounceOut(t*2-d, 0, c, d)*0.5f + c*0.5f + b);
}
// 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/=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);
}
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/=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);
}
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/=d/2) == 2) return (b + c);

View File

@ -34,8 +34,8 @@
#include <string.h> // Required for strcmp()
#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 "raymath.h" // Required for data type Matrix and Matrix functions
//----------------------------------------------------------------------------------
// Defines and Macros
@ -1373,8 +1373,8 @@ bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox)
BoundingBox CalculateBoundingBox(Mesh mesh)
{
// 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++)
{

View File

@ -55,8 +55,8 @@ static bool collisionChecker = false;
// Module specific Functions Declarations
//----------------------------------------------------------------------------------
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
@ -183,9 +183,9 @@ void ApplyPhysics(int index, Vector2 *position)
{
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))
{
@ -207,7 +207,7 @@ void ApplyPhysics(int index, Vector2 *position)
}
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))
{
@ -277,7 +277,7 @@ void AddForceAtPosition(Vector2 position, float intensity, float radius)
Vector2 pos = {colliders[i].bounds.x, colliders[i].bounds.y};
// Get distance between rigidbody position and target position
float distance = Vector2LengthPoints(position, pos);
float distance = Vector2Distance(position, pos);
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};
// Normalize the direction vector
force = Vector2Normalize(force);
Vector2Normalize(&force);
// Invert y value
force.y *= -1;
@ -323,20 +323,24 @@ static float Vector2Length(Vector2 vector)
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};
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};
}

View File

@ -32,7 +32,8 @@
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef enum { RectangleCollider, CircleCollider } ColliderType;
// Collider types
typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType;
// Physics struct
typedef struct Physics {
@ -65,8 +66,8 @@ typedef struct Rigidbody {
typedef struct Collider {
bool enabled;
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;
#ifdef __cplusplus

View File

@ -463,12 +463,12 @@ typedef struct {
typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
// Collider types
typedef enum { RectangleCollider, CircleCollider } ColliderType;
typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType;
// Physics struct
typedef struct Physics {
bool enabled;
bool debug; // Should be used by programmer for testing purposes
bool debug; // Should be used by programmer for testing purposes
Vector2 gravity;
} Physics;
@ -496,8 +496,8 @@ typedef struct Rigidbody {
typedef struct Collider {
bool enabled;
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;
#ifdef __cplusplus
@ -547,8 +547,8 @@ float GetFrameTime(void); // Returns time in s
Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value
int GetHexValue(Color color); // Returns hexadecimal value for a Color
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)
Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f

View File

@ -1,9 +1,23 @@
/**********************************************************************************************
*
* raymath
* raymath (header only file)
*
* 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)
*
* 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.
*
**********************************************************************************************/
//============================================================================
// 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
#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
#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
//----------------------------------------------------------------------------------
@ -63,18 +61,18 @@
#endif
#ifndef DEG2RAD
#define DEG2RAD (PI / 180.0f)
#define DEG2RAD (PI/180.0f)
#endif
#ifndef RAD2DEG
#define RAD2DEG (180.0f / PI)
#define RAD2DEG (180.0f/PI)
#endif
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
#ifdef RAYMATH_STANDALONE
#if defined(RAYMATH_STANDALONE)
// Vector2 type
typedef struct Vector2 {
float x;
@ -105,7 +103,77 @@ typedef struct Quaternion {
float w;
} 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 <math.h> // Standard math libary: sin(), cos(), tan()...
#include <stdlib.h> // Used for abs()
@ -114,18 +182,6 @@ typedef struct Quaternion {
// 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
RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2)
{
@ -229,9 +285,9 @@ RMDEF void VectorNormalize(Vector3 *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->y *= ilength;
@ -257,9 +313,9 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount)
{
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;
}
@ -269,15 +325,15 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal)
{
// I is the original vector
// N is the normal of the incident plane
// R = I - (2 * N * ( DotProduct[ I,N] ))
// R = I - (2*N*( DotProduct[ I,N] ))
Vector3 result;
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;
}
@ -308,34 +364,6 @@ RMDEF Vector3 VectorZero(void)
// 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
RMDEF float MatrixDeterminant(Matrix mat)
{
@ -413,7 +441,7 @@ RMDEF void MatrixInvert(Matrix *mat)
float b11 = a22*a33 - a23*a32;
// Calculate the invert determinant (inlined to avoid double-caching)
float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06);
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.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet;
@ -461,7 +489,10 @@ RMDEF void MatrixNormalize(Matrix *mat)
// Returns identity matrix
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;
}
@ -519,7 +550,10 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right)
// Returns translation matrix
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;
}
@ -536,9 +570,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis)
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;
y *= 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;
// 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
result.m0 = r0*m0 + r4*m1 + r8*m2;
@ -673,7 +707,10 @@ RMDEF Matrix MatrixRotateZ(float angle)
// Returns scaling matrix
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;
}
@ -713,25 +750,25 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
float tb = (top - bottom);
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.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;
}
@ -739,7 +776,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
// Returns perspective projection matrix
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;
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 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;
}
@ -789,19 +826,19 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up)
result.m0 = x.x;
result.m1 = x.y;
result.m2 = x.z;
result.m3 = -((x.x * eye.x) + (x.y * eye.y) + (x.z * eye.z));
result.m3 = -((x.x*eye.x) + (x.y*eye.y) + (x.z*eye.z));
result.m4 = y.x;
result.m5 = y.y;
result.m6 = y.z;
result.m7 = -((y.x * eye.x) + (y.y * eye.y) + (y.z * eye.z));
result.m7 = -((y.x*eye.x) + (y.y*eye.y) + (y.z*eye.z));
result.m8 = z.x;
result.m9 = z.y;
result.m10 = z.z;
result.m11 = -((z.x * eye.x) + (z.y * eye.y) + (z.z * eye.z));
result.m12 = 0;
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
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;
}
@ -834,9 +871,9 @@ RMDEF void QuaternionNormalize(Quaternion *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->y *= ilength;
@ -882,8 +919,8 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount)
}
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.y = (q1.y*ratioA + q2.y*ratioB);
@ -902,15 +939,15 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix 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
{
@ -918,33 +955,33 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix)
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)
{
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
{
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 wz = w*z2;
result.m0 = 1 - (yy + zz);
result.m0 = 1.0f - (yy + zz);
result.m1 = xy - wz;
result.m2 = xz + wy;
result.m3 = 0;
result.m3 = 0.0f;
result.m4 = xy + wz;
result.m5 = 1 - (xx + zz);
result.m5 = 1.0f - (xx + zz);
result.m6 = yz - wx;
result.m7 = 0;
result.m7 = 0.0f;
result.m8 = xz - wy;
result.m9 = yz + wx;
result.m10 = 1 - (xx + yy);
result.m11 = 0;
result.m12 = 0;
result.m13 = 0;
result.m14 = 0;
result.m15 = 1;
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;
}
@ -998,17 +1035,17 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q)
// NOTE: angle must be provided in radians
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);
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);
QuaternionNormalize(&result);
@ -1021,23 +1058,23 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis
{
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)
{
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
{
// This occurs when the angle is zero.
// Not a problem: just set an arbitrary normalized axis.
resAxis.x = 1.0;
resAxis.x = 1.0f;
}
*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;
}
#endif // RAYMATH_DEFINE
#endif // RAYMATH_H
#endif // RAYMATH_IMPLEMENTATION
#endif // RAYMATH_H

View File

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

View File

@ -37,11 +37,12 @@
#endif
#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
#include "raymath.h" // Required for data type Matrix and Matrix functions
// Select desired OpenGL version
// NOTE: Those preprocessor defines are only used on rlgl module,
// 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;
#ifdef RLGL_STANDALONE
#if defined(RLGL_STANDALONE)
#ifndef __cplusplus
// Boolean type
typedef enum { false, true } bool;

File diff suppressed because it is too large Load Diff

View File

@ -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,
@ -18,7 +17,7 @@ ABOUT:
The PNG output is not optimal; it is 20-50% larger than the file
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.
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_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_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.
@ -63,6 +77,9 @@ USAGE:
data, alpha (if provided) is discarded, and for monochrome data it is
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:
PNG/BMP/TGA
@ -73,8 +90,25 @@ CREDITS:
Jean-Sebastien Guay
misc enhancements:
Tim Kelsey
TGA RLE
Alan Hickman
initial file IO callback implementation
Emmanuel Julien
bugfixes:
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
@ -84,10 +118,26 @@ CREDITS:
extern "C" {
#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
}
@ -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 _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 <stdlib.h>
#include <stdio.h>
#include <string.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
#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
#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
#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
#ifndef STBIW_REALLOC_SIZED
#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
#endif
#ifndef STBIW_MEMMOVE
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
#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)
#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 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) {
switch (*fmt++) {
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:
STBIW_ASSERT(0);
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];
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];
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;
int i,j,k, j_end;
int i,j, j_end;
if (y <= 0)
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 (i=0; i < x; ++i) {
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_start(v, fmt);
writefv(f, fmt, v);
stbiw__writefv(s, fmt, 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;
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",
'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
}
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 colorbytes = has_alpha ? comp-1 : comp;
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
// by Baldur Karlsson
#ifndef STBI_WRITE_NO_STDIO
#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
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;
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;
} else {
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);
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
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 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 */
if (width < 8 || width >= 32768) {
for (x=0; x < width; x++) {
switch (comp) {
switch (ncomp) {
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;
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;
}
stbiw__linear_to_rgbe(rgbe, linear);
fwrite(rgbe, 4, 1, f);
s->func(s->context, rgbe, 4);
}
} else {
int c,r;
/* encode into scratch buffer */
for (x=0; x < width; x++) {
switch(comp) {
switch(ncomp) {
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;
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;
}
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];
}
fwrite(scanlineheader, 4, 1, f);
s->func(s->context, scanlineheader, 4);
/* RLE each component separately */
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) {
int len = r-x;
if (len > 128) len = 128;
stbiw__write_dump_data(f, len, &comp[x]);
stbiw__write_dump_data(s, len, &comp[x]);
x += len;
}
// 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) {
int len = r-x;
if (len > 127) len = 127;
stbiw__write_run_data(f, len, comp[x]);
stbiw__write_run_data(s, len, comp[x]);
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);
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++)
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);
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()
#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)
{
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);
if (p) {
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)
{
while (*bitcount >= 8) {
stbiw__sbpush(data, (unsigned char) *bitbuffer);
stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
*bitbuffer >>= 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
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) {
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
s1 %= 65521, s2 %= 65521;
j += blocklen;
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);
// 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);
}
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;
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)
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
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__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)
{
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)
@ -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, y);
*o++ = 8;
*o++ = (unsigned char) ctype[n];
*o++ = STBIW_UCHAR(ctype[n]);
*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;
}
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;
int 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");
if (!f) { STBIW_FREE(png); return 0; }
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);
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
/* 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)
added STBIW_MALLOC, STBIW_ASSERT etc
0.97 (2015-01-18)

View File

@ -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
//
// This library processes TrueType files:
@ -42,12 +42,15 @@
// Sergey Popov
// Giumo X. Clanjor
// Higor Euripedes
// Thomas Fields
// Derek Vinyard
//
// Misc other:
// Ryan Gordon
//
// 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.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
// 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)
{
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)) {
// e.g. space character
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);
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(z != NULL);
if (!z) return z;
// 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);
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(z != NULL);
//STBTT_assert(e->y0 <= start_point);
if (!z) return z;
z->fdx = dxdy;
@ -1817,21 +1822,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
while (e->y0 <= scan_y) {
if (e->y1 > scan_y) {
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;
@ -2101,10 +2108,12 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
while (e->y0 <= scan_y_bottom) {
if (e->y0 != e->y1) {
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;
}
@ -2513,6 +2522,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo
float scale;
int x,y,bottom_y, i;
stbtt_fontinfo f;
f.userdata = NULL;
if (!stbtt_InitFont(&f, data, offset))
return -1;
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];
int safe_w = w - kernel_width;
int j;
STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
for (j=0; j < h; ++j) {
int i;
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];
int safe_h = h - kernel_width;
int j;
STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
for (j=0; j < w; ++j) {
int i;
unsigned int total;
@ -2975,6 +2987,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
if (rects == NULL)
return 0;
info.userdata = spc->user_allocator_context;
stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
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
//
// 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.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
// allow PackFontRanges to pack and render in separate phases;

File diff suppressed because it is too large Load Diff

View File

@ -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/
//
// 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
// by RAD Game Tools). Report bugs and send enhancements to the author.
//
// Limitations:
//
// - seeking not supported except manually via PUSHDATA api
// - floor 0 not supported (used in old ogg vorbis files pre-2004)
// - lossless sample-truncation at beginning ignored
// - cannot concatenate multiple vorbis streams
// - sample positions are 32-bit, limiting seekable 192Khz
// files to around 6 hours (Ogg supports 64-bit)
//
// Feature contributors:
// Dougall Johnson (sample-exact seeking)
//
// Bugfix/warning contributors:
// Terje Mathisen Niklas Frykholm Andy Hill
// Casey Muratori John Bolton Gargaj
// Laurent Gomila Marc LeBlanc Ronny Chevalier
// Bernhard Wodo Evan Balster "alxprd"@github
// Bernhard Wodo Evan Balster "alxprd"@github
// 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:
// 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.04 - 2014/08/27 - fix missing const-correct case in API
// 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.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
// (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.
@ -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.
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 *error,
stb_vorbis_alloc *alloc_buffer);
const stb_vorbis_alloc *alloc_buffer);
// create a vorbis decoder by passing in the initial data block containing
// the ogg&vorbis headers (you don't need to do parse them, just provide
// the first N bytes of the file--you're told if it's not enough, see below)
@ -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
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
float ***output, // place to write float ** array of float * buffers
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.
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
// this must be the entire stream!). on failure, returns NULL and sets *error
#ifndef STB_VORBIS_NO_STDIO
extern stb_vorbis * stb_vorbis_open_filename(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,
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
int *error, stb_vorbis_alloc *alloc_buffer);
int *error, const stb_vorbis_alloc *alloc_buffer);
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
// note that stb_vorbis must "own" this stream; if you seek it in between
@ -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.
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
// 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"
@ -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(stb_vorbis *f, unsigned int sample_number);
// NOT WORKING YET
// these functions seek in the Vorbis file to (approximately) 'sample_number'.
// after calling seek_frame(), the next call to get_frame_*() will include
// the specified sample. after calling stb_vorbis_seek(), the next call to
@ -275,8 +283,7 @@ extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
// you can also use seek_frame().
extern void stb_vorbis_seek_start(stb_vorbis *f);
// this function is equivalent to stb_vorbis_seek(f,0), but it
// actually works
// this function is equivalent to stb_vorbis_seek(f,0)
extern unsigned int stb_vorbis_stream_length_in_samples(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 (stb_vorbis *f, int num_c, short **buffer, int num_samples);
#endif
// decode the next frame and return the number of samples per channel. the
// data is coerced to the number of channels you request according to the
// 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
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
// The maximum buffer size needed can be gotten from get_info(); however,
// the Vorbis I specification implies an absolute maximum of 4096 samples
// per channel. Note that for interleaved data, you pass in the number of
// shorts (the size of your array), but the return value is the number of
// samples per channel, not the total number of samples.
// per channel.
// Channel coercion rules:
// 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_bad_packet_type,
VORBIS_cant_find_last_page,
VORBIS_seek_failed,
VORBIS_seek_failed
};