Merge pull request #2 from raysan5/master

Merge Master
This commit is contained in:
Tyler Jessilynn Bezera 2019-08-29 21:04:06 -07:00 committed by GitHub
commit 8314e7e4dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 887 additions and 373 deletions

View File

@ -471,7 +471,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
del *.o *.exe /s
endif
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable|x-pie-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -fv
endif
ifeq ($(PLATFORM_OS),OSX)
find . -type f -perm +ugo+x -delete

View File

@ -42,7 +42,7 @@ int main(void)
Camera2D camera = { 0 };
camera.target = (Vector2){ player.x + 20, player.y + 20 };
camera.offset = (Vector2){ 0, 0 };
camera.offset = (Vector2){ screenWidth/2, screenHeight/2 };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
@ -54,16 +54,10 @@ int main(void)
{
// Update
//----------------------------------------------------------------------------------
if (IsKeyDown(KEY_RIGHT))
{
player.x += 2; // Player movement
camera.offset.x -= 2; // Camera displacement with player movement
}
else if (IsKeyDown(KEY_LEFT))
{
player.x -= 2; // Player movement
camera.offset.x += 2; // Camera displacement with player movement
}
// Player movement
if (IsKeyDown(KEY_RIGHT)) player.x += 2;
else if (IsKeyDown(KEY_LEFT)) player.x -= 2;
// Camera target follows player
camera.target = (Vector2){ player.x + 20, player.y + 20 };
@ -135,4 +129,4 @@ int main(void)
//--------------------------------------------------------------------------------------
return 0;
}
}

View File

@ -0,0 +1,284 @@
/*******************************************************************************************
*
* raylib [core] example - 2d camera extended
*
* This example has been created using raylib 1.5 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2016 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define G 400
#define PLAYER_JUMP_SPD 350.f
#define PLAYER_HOR_SPD 200.f
typedef struct Player {
Vector2 pos;
float vel;
int canJump;
} Player;
typedef struct EnvItem {
Rectangle rect;
int blocking;
Color color;
} EnvItem;
void updateCameraCenter(
float delta,
Camera2D *camera,
Player *player,
EnvItem *envItems,
int envItemsLength,
int width, int height
) {
camera->offset = (Vector2){ width/2, height/2 };
camera->target = player->pos;
}
void updateCameraCenterInsideMap(
float delta,
Camera2D *camera,
Player *player,
EnvItem *envItems,
int envItemsLength,
int width, int height
) {
camera->target = player->pos;
camera->offset = (Vector2){ width/2, height/2 };
float minX = 1000, minY = 1000, maxX = -1000, maxY = -1000;
for (int i = 0; i < envItemsLength; i++) {
EnvItem *ei = envItems + i;
minX = fminf(ei->rect.x, minX);
maxX = fmaxf(ei->rect.x + ei->rect.width, maxX);
minY = fminf(ei->rect.y, minY);
maxY = fmaxf(ei->rect.y + ei->rect.height, maxY);
}
Vector2 max = GetWorldToScreen2D((Vector2){ maxX, maxY }, *camera);
Vector2 min = GetWorldToScreen2D((Vector2){ minX, minY }, *camera);
if (max.x < width) {
camera->offset.x = width - (max.x - width/2);
}
if (max.y < height) {
camera->offset.y = height - (max.y - height/2);
}
if (min.x > 0) {
camera->offset.x = width/2 - min.x;
}
if (min.y > 0) {
camera->offset.y = height/2- min.y;
}
}
void updateCameraCenterSmoothFollow(
float delta,
Camera2D *camera,
Player *player,
EnvItem *envItems,
int envItemsLength,
int width, int height
) {
static float minSpeed = 30;
static float minEffectLength = 10;
static float fractionSpeed = 0.8f;
camera->offset = (Vector2){ width/2, height/2 };
Vector2 diff = Vector2Subtract(player->pos, camera->target);
float length = Vector2Length(diff);
if (length > minEffectLength) {
float speed = fmaxf(fractionSpeed * length, minSpeed);
camera->target = Vector2Add(camera->target, Vector2Scale(diff, speed*delta/length));
}
}
void updateCameraEvenOutOnLanding(
float delta,
Camera2D *camera,
Player *player,
EnvItem *envItems,
int envItemsLength,
int width, int height
) {
static float evenOutSpeed = 700;
static int eveningOut = false;
static float evenOutTarget;
camera->offset = (Vector2){ width/2, height/2 };
camera->target.x = player->pos.x;
if (eveningOut) {
if (evenOutTarget > camera->target.y) {
camera->target.y += evenOutSpeed * delta;
if (camera->target.y > evenOutTarget) {
camera->target.y = evenOutTarget;
eveningOut = 0;
}
} else {
camera->target.y -= evenOutSpeed * delta;
if (camera->target.y < evenOutTarget) {
camera->target.y = evenOutTarget;
eveningOut = 0;
}
}
} else {
if (player->canJump &&
player->vel == 0 &&
player->pos.y != camera->target.y
) {
eveningOut = 1;
evenOutTarget = player->pos.y;
}
}
}
void updateCameraPlayerBoundsPush(
float delta,
Camera2D *camera,
Player *player,
EnvItem *envItems,
int envItemsLength,
int width, int height
) {
static Vector2 bbox = { 0.2f, 0.2f };
Vector2 bboxWorldMin = GetScreenToWorld2D((Vector2){ (1 - bbox.x) * 0.5 * width, (1 - bbox.y) * 0.5 * height }, *camera);
Vector2 bboxWorldMax = GetScreenToWorld2D((Vector2){ (1 + bbox.x) * 0.5 * width, (1 + bbox.y) * 0.5 * height }, *camera);
camera->offset = (Vector2){ (1 - bbox.x) * 0.5 * width, (1 - bbox.y) * 0.5 * height };
if (player->pos.x < bboxWorldMin.x) {
camera->target.x = player->pos.x;
}
if (player->pos.y < bboxWorldMin.y) {
camera->target.y = player->pos.y;
}
if (player->pos.x > bboxWorldMax.x) {
camera->target.x = bboxWorldMin.x + (player->pos.x - bboxWorldMax.x);
}
if (player->pos.y > bboxWorldMax.y) {
camera->target.y = bboxWorldMin.y + (player->pos.y - bboxWorldMax.y);
}
}
void updatePlayer(float delta, Player *player, EnvItem *envItems, int envItemsLength) {
if (IsKeyDown(KEY_LEFT)) player->pos.x -= PLAYER_HOR_SPD*delta;
if (IsKeyDown(KEY_RIGHT)) player->pos.x += PLAYER_HOR_SPD*delta;
if (IsKeyDown(KEY_SPACE) && player->canJump) {
player->vel = -PLAYER_JUMP_SPD;
player->canJump = 0;
}
int hitObstacle = 0;
for (int i = 0; i < envItemsLength; i++) {
EnvItem *ei = envItems + i;
Vector2 *p = &(player->pos);
if (ei->blocking &&
ei->rect.x <= p->x &&
ei->rect.x + ei->rect.width >= p->x &&
ei->rect.y >= p->y &&
ei->rect.y < p->y + player->vel * delta)
{
hitObstacle = 1;
player->vel = 0.0f;
p->y = ei->rect.y;
}
}
if (!hitObstacle) {
player->pos.y += player->vel * delta;
player->vel += G * delta;
player->canJump = 0;
} else {
player->canJump = 1;
}
}
void renderWorld(Player *player, EnvItem *envItems, int envItemsLength) {
for (int i = 0; i < envItemsLength; i++) {
DrawRectangleRec(envItems[i].rect, envItems[i].color);
}
Rectangle playerRect = { player->pos.x - 20, player->pos.y - 40, 40, 40 };
DrawRectangleRec(playerRect, RED);
}
int main(void)
{
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera");
SetTargetFPS(60);
Player player;
player.pos = (Vector2){ 400, 280 };
player.vel = 0;
player.canJump = 0;
EnvItem envItems[] = {
{{ 0, 0, 1000, 400 }, 0, LIGHTGRAY },
{{ 0, 400, 1000, 200 }, 1, GRAY },
{{ 300, 200, 400, 10 }, 1, GRAY },
{{ 250, 300, 100, 10 }, 1, GRAY },
{{ 650, 300, 100, 10 }, 1, GRAY }
};
int envItemsLength = sizeof(envItems) / sizeof (envItems[0]);
Camera2D camera = { 0 };
camera.target = player.pos;
camera.offset = (Vector2){ screenWidth/2, screenHeight/2 };
camera.rotation = 0.0f;
camera.zoom = 1.0f;
int cameraOption = 0;
void (*cameraUpdaters[])(float, Camera2D*, Player*, EnvItem*, int, int, int) = {
updateCameraCenter,
updateCameraCenterInsideMap,
updateCameraCenterSmoothFollow,
updateCameraEvenOutOnLanding,
updateCameraPlayerBoundsPush
};
int cameraUpdatersLength = sizeof(cameraUpdaters) / sizeof(cameraUpdaters[0]);
char* cameraDescriptions[] = {
"Follow player center",
"Follow player center, but clamp to map edges",
"Follow player center; smoothed",
"Follow player center horizontally; updateplayer center vertically after landing",
"Player push camera on getting too close to screen edge"
};
while (!WindowShouldClose()) {
float delta = GetFrameTime();
updatePlayer(delta, &player, envItems, envItemsLength);
camera.zoom += ((float)GetMouseWheelMove()*0.05f);
if (camera.zoom > 3.0f) camera.zoom = 3.0f;
else if (camera.zoom < 0.25f) camera.zoom = 0.25f;
if (IsKeyPressed(KEY_R))
{
camera.zoom = 1.0f;
}
if (IsKeyPressed(KEY_C)) {
cameraOption = (cameraOption + 1) % cameraUpdatersLength;
}
cameraUpdaters[cameraOption](delta, &camera, &player, envItems, envItemsLength, screenWidth, screenHeight);
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode2D(camera);
renderWorld(&player, envItems, envItemsLength);
EndMode2D();
DrawText("Controls:", 20, 20, 10, BLACK);
DrawText("- Right/Left to move", 40, 40, 10, DARKGRAY);
DrawText("- Space to jump", 40, 60, 10, DARKGRAY);
DrawText("- Mouse Wheel to Zoom in-out, R to reset zoom", 40, 80, 10, DARKGRAY);
DrawText("- C to change camera mode", 40, 100, 10, DARKGRAY);
DrawText("Current camera mode:", 20, 120, 10, BLACK);
DrawText(cameraDescriptions[cameraOption], 40, 140, 10, DARKGRAY);
EndDrawing();
}
CloseWindow(); // Close window and OpenGL context
return 0;
}

View File

@ -11,14 +11,14 @@ uniform sampler2D texture0;
uniform vec4 colDiffuse;
// NOTE: Add here your custom variables
uniform vec2 leftLensCenter = vec2(0.288, 0.5);
uniform vec2 rightLensCenter = vec2(0.712, 0.5);
uniform vec2 leftScreenCenter = vec2(0.25, 0.5);
uniform vec2 rightScreenCenter = vec2(0.75, 0.5);
uniform vec2 scale = vec2(0.25, 0.45);
uniform vec2 scaleIn = vec2(4, 2.2222);
uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0);
uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
uniform vec2 leftLensCenter;
uniform vec2 rightLensCenter;
uniform vec2 leftScreenCenter;
uniform vec2 rightScreenCenter;
uniform vec2 scale;
uniform vec2 scaleIn;
uniform vec4 hmdWarpParam;
uniform vec4 chromaAbParam;
void main()
{

View File

@ -98,6 +98,8 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
// Unload model animations data
for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]);
RL_FREE(anims);

View File

@ -100,7 +100,8 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(model); // Unload skybox model
UnloadMaterial(model.materials[0]); // Unload material: shader and textures
UnloadModel(model); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -115,11 +115,12 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
// Unload models data (GPU VRAM)
for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]);
CloseWindow(); // Close window and OpenGL context
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;

View File

@ -116,6 +116,7 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(model); // Unload model
ClearDroppedFiles(); // Clear internal buffers

View File

@ -89,7 +89,10 @@ int main(void)
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(skybox); // Unload skybox model (and textures)
UnloadShader(skybox.materials[0].shader);
UnloadTexture(skybox.materials[0].maps[MAP_CUBEMAP].texture);
UnloadModel(skybox); // Unload skybox model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------

View File

@ -169,6 +169,7 @@ int main(void)
//--------------------------------------------------------------------------------------
// Unload all loaded data
UnloadTexture(model.materials[0].maps[MAP_DIFFUSE].texture);
UnloadModel(model);
UnloadRenderTexture(framebuffer);

View File

@ -0,0 +1,99 @@
#version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
in vec3 fragPosition;
in vec3 fragNormal;
// Input uniform values
uniform sampler2D texture0;
uniform vec4 colDiffuse;
// Output fragment color
out vec4 finalColor;
// NOTE: Add here your custom variables
#define MAX_LIGHTS 4
#define LIGHT_DIRECTIONAL 0
#define LIGHT_POINT 1
struct MaterialProperty {
vec3 color;
int useSampler;
sampler2D sampler;
};
struct Light {
int enabled;
int type;
vec3 position;
vec3 target;
vec4 color;
};
// Input lighting values
uniform Light lights[MAX_LIGHTS];
uniform vec4 ambient;
uniform vec3 viewPos;
uniform float fogDensity;
void main()
{
// Texel color fetching from texture sampler
vec4 texelColor = texture(texture0, fragTexCoord);
vec3 lightDot = vec3(0.0);
vec3 normal = normalize(fragNormal);
vec3 viewD = normalize(viewPos - fragPosition);
vec3 specular = vec3(0.0);
// NOTE: Implement here your fragment shader code
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (lights[i].enabled == 1)
{
vec3 light = vec3(0.0);
if (lights[i].type == LIGHT_DIRECTIONAL) {
light = -normalize(lights[i].target - lights[i].position);
}
if (lights[i].type == LIGHT_POINT) {
light = normalize(lights[i].position - fragPosition);
}
float NdotL = max(dot(normal, light), 0.0);
lightDot += lights[i].color.rgb * NdotL;
float specCo = 0.0;
if(NdotL > 0.0)
specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16);//16 =shine
specular += specCo;
}
}
finalColor = (texelColor * ((colDiffuse+vec4(specular,1)) * vec4(lightDot, 1.0)));
finalColor += texelColor * (ambient/10.0);
// Gamma correction
finalColor = pow(finalColor, vec4(1.0/2.2));
// Fog calculation
float dist = length(viewPos - fragPosition);
// these could be parameters...
const vec4 fogColor = vec4(0.5, 0.5, 0.5, 1.0);
//const float fogDensity = 0.16;
// Exponential fog
float fogFactor = 1.0/exp((dist*fogDensity)*(dist*fogDensity));
// Linear fog (less nice)
//const float fogStart = 2.0;
//const float fogEnd = 10.0;
//float fogFactor = (fogEnd - dist)/(fogEnd - fogStart);
fogFactor = clamp(fogFactor, 0.0, 1.0);
finalColor = mix(fogColor, finalColor, fogFactor);
}

View File

@ -0,0 +1,32 @@
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform mat4 matModel;
// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec4 fragColor;
out vec3 fragPosition;
out vec3 fragNormal;
// NOTE: Add here your custom variables
void main()
{
// Send vertex attributes to fragment shader
fragTexCoord = vertexTexCoord;
fragColor = vertexColor;
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0f));
mat3 normalMatrix = transpose(inverse(mat3(matModel)));
fragNormal = normalize(normalMatrix*vertexNormal);
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}

View File

@ -0,0 +1,153 @@
/*******************************************************************************************
*
* raylib [shaders] example - fog
*
* NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
* OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
*
* NOTE: Shaders used in this example are #version 330 (OpenGL 3.3).
*
* This example has been created using raylib 2.5 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Example contributed by Chris Camacho (@codifies) and reviewed by Ramon Santamaria (@raysan5)
*
* Chris Camacho (@codifies - http://bedroomcoders.co.uk/) notes:
*
* This is based on the PBR lighting example, but greatly simplified to aid learning...
* actually there is very little of the PBR example left!
* When I first looked at the bewildering complexity of the PBR example I feared
* I would never understand how I could do simple lighting with raylib however its
* a testement to the authors of raylib (including rlights.h) that the example
* came together fairly quickly.
*
* Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
#include "raymath.h"
#define RLIGHTS_IMPLEMENTATION
#include "rlights.h"
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available)
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - fog");
// Define the camera to look into our 3d world
Camera camera = {
(Vector3){ 2.0f, 2.0f, 6.0f }, // position
(Vector3){ 0.0f, 0.5f, 0.0f }, // target
(Vector3){ 0.0f, 1.0f, 0.0f }, // up
45.0f, CAMERA_PERSPECTIVE }; // fov, type
// Load models and texture
Model modelA = LoadModelFromMesh(GenMeshTorus(0.4f, 1.0f, 16, 32));
Model modelB = LoadModelFromMesh(GenMeshCube(1.0f, 1.0f, 1.0f));
Model modelC = LoadModelFromMesh(GenMeshSphere(0.5f, 32, 32));
Texture texture = LoadTexture("resources/texel_checker.png");
// Assign texture to default model material
modelA.materials[0].maps[MAP_DIFFUSE].texture = texture;
modelB.materials[0].maps[MAP_DIFFUSE].texture = texture;
modelC.materials[0].maps[MAP_DIFFUSE].texture = texture;
// Load shader and set up some uniforms
Shader shader = LoadShader("resources/shaders/glsl330/fog.vs", "resources/shaders/glsl330/fog.fs");
shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(shader, "matModel");
shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(shader, "viewPos");
// Ambient light level
int ambientLoc = GetShaderLocation(shader, "ambient");
SetShaderValue(shader, ambientLoc, (float[4]){ 0.2f, 0.2f, 0.2f, 1.0f }, UNIFORM_VEC4);
float fogDensity = 0.15f;
int fogDensityLoc = GetShaderLocation(shader, "fogDensity");
SetShaderValue(shader, fogDensityLoc, &fogDensity, UNIFORM_FLOAT);
// NOTE: All models share the same shader
modelA.materials[0].shader = shader;
modelB.materials[0].shader = shader;
modelC.materials[0].shader = shader;
// Using just 1 point lights
CreateLight(LIGHT_POINT, (Vector3){ 0, 2, 6 }, Vector3Zero(), WHITE, shader);
SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
// Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
UpdateCamera(&camera); // Update camera
if (IsKeyDown(KEY_UP))
{
fogDensity += 0.001;
if (fogDensity > 1.0) fogDensity = 1.0;
}
if (IsKeyDown(KEY_DOWN))
{
fogDensity -= 0.001;
if (fogDensity < 0.0) fogDensity = 0.0;
}
SetShaderValue(shader, fogDensityLoc, &fogDensity, UNIFORM_FLOAT);
// Rotate the torus
modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateX(-0.025));
modelA.transform = MatrixMultiply(modelA.transform, MatrixRotateZ(0.012));
// Update the light shader with the camera view position
SetShaderValue(shader, shader.locs[LOC_VECTOR_VIEW], &camera.position.x, UNIFORM_VEC3);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(GRAY);
BeginMode3D(camera);
// Draw the three models
DrawModel(modelA, Vector3Zero(), 1.0f, WHITE);
DrawModel(modelB, (Vector3){ -2.6, 0, 0 }, 1.0f, WHITE);
DrawModel(modelC, (Vector3){ 2.6, 0, 0 }, 1.0f, WHITE);
for (int i = -20; i < 20; i += 2) DrawModel(modelA,(Vector3){ i, 0, 2 }, 1.0f, WHITE);
EndMode3D();
DrawText(TextFormat("Use KEY_UP/KEY_DOWN to change fog density [%.2f]", fogDensity), 10, 10, 20, RAYWHITE);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadModel(modelA); // Unload the model A
UnloadModel(modelB); // Unload the model B
UnloadModel(modelC); // Unload the model C
UnloadTexture(texture); // Unload the texture
UnloadShader(shader); // Unload shader
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -13,7 +13,7 @@
#include <stdlib.h> // Required for: malloc(), free()
#define MAX_BUNNIES 100000 // 100K bunnies limit
#define MAX_BUNNIES 50000 // 50K bunnies limit
// This is the maximum amount of elements (quads) per batch
// NOTE: This value is defined in [rlgl] module and can be changed there

View File

@ -4,14 +4,17 @@ This folder contains raylib templates for some common IDEs.
IDE | Platform | Template type | State
----| ---------| ------------- | -----
[4coder](http://4coder.net/) | Windows | example compiling | DONE
[Builder](https://wiki.gnome.org/Apps/Builder) | Linux | example compiling | DONE
[CMake](https://cmake.org/) | n/a | example compiling and raylib source downloading/building if necessary | DONE
[CodeBlocks](http://www.codeblocks.org/) | Linux, Windows | example compiling | DONE
[Geany](https://www.geany.org/) | Linux, Windows | - | INCOMPLETE
[Geany](https://www.geany.org/) | Linux, Windows | - | DONE
[KDevelop](https://www.kdevelop.org/) | Linux, Windows, macOS | - | INCOMPLETE
[Notepad++](https://notepad-plus-plus.org/) | Windows | source/example compiling | DONE
[Sublime Text](https://www.sublimetext.com/) | Windows, Linux, macOS | source and example | DONE
[VS2015](https://www.visualstudio.com) | Windows | source/example compiling | DONE
[VS2017](https://www.visualstudio.com) | Windows | source/example compiling | DONE
[VSCode](https://code.visualstudio.com/) | Windows, macOS | example compiling | DONE
scripts | Windows, Linux, macOS | source and example | DONE
*New IDEs config files are welcome!*

View File

@ -44,6 +44,8 @@
#define SUPPORT_MOUSE_GESTURES 1
// Reconfigure standard input to receive key inputs, works with SSH connection.
#define SUPPORT_SSH_KEYBOARD_RPI 1
// Draw a mouse reference on screen (square cursor box)
#define SUPPORT_MOUSE_CURSOR_RPI 1
// Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
//#define SUPPORT_BUSY_WAIT_LOOP 1
// Wait for events passively (sleeping while no events) instead of polling them actively every frame

View File

@ -55,6 +55,9 @@
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other running processes or
* blocking the device is not restored properly. Use with care.
*
* #define SUPPORT_MOUSE_CURSOR_RPI (Raspberry Pi only)
* Draw a mouse reference on screen (square cursor box)
*
* #define SUPPORT_BUSY_WAIT_LOOP
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
*
@ -105,7 +108,7 @@
#if !defined(EXTERNAL_CONFIG_FLAGS)
#include "config.h" // Defines module configuration flags
#else
#define RAYLIB_VERSION "2.5"
#define RAYLIB_VERSION "2.6-dev"
#endif
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_C_SOURCE < 199309L
@ -423,7 +426,6 @@ static double targetTime = 0.0; // Desired time for one frame, if 0
// Config internal variables
//-----------------------------------------------------------------------------------
static unsigned int configFlags = 0; // Configuration flags (bit based)
static bool showLogo = false; // Track if showing logo at init is enabled
static char **dropFilesPath; // Store dropped files paths as strings
static int dropFilesCount = 0; // Count dropped files strings
@ -466,8 +468,6 @@ static int GetGamepadButton(int button); // Get gamepad button ge
static int GetGamepadAxis(int axis); // Get gamepad axis generic to all platforms
static void PollInputEvents(void); // Register user events
static void LogoAnimation(void); // Plays raylib logo appearing animation
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
@ -697,13 +697,6 @@ void InitWindow(int width, int height, const char *title)
mousePosition.x = (float)screenWidth/2.0f;
mousePosition.y = (float)screenHeight/2.0f;
// raylib logo appearing animation (if enabled)
if (showLogo)
{
SetTargetFPS(60);
LogoAnimation();
}
#endif // PLATFORM_ANDROID
}
@ -1187,6 +1180,12 @@ void BeginDrawing(void)
// End canvas drawing and swap buffers (double buffering)
void EndDrawing(void)
{
#if defined(PLATFORM_RPI) && defined(SUPPORT_MOUSE_CURSOR_RPI)
// On RPI native mode we have no system mouse cursor, so,
// we draw a small rectangle for user reference
DrawRectangle(mousePosition.x, mousePosition.y, 3, 3, MAROON);
#endif
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
#if defined(SUPPORT_GIF_RECORDING)
@ -1249,17 +1248,12 @@ void BeginMode2D(Camera2D camera)
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
rlMultMatrixf(MatrixToFloat(screenScaling)); // Apply screen scaling if required
// Camera rotation and scaling is always relative to target
Matrix matOrigin = MatrixTranslate(-camera.target.x, -camera.target.y, 0.0f);
Matrix matRotation = MatrixRotate((Vector3){ 0.0f, 0.0f, 1.0f }, camera.rotation*DEG2RAD);
Matrix matScale = MatrixScale(camera.zoom, camera.zoom, 1.0f);
Matrix matTranslation = MatrixTranslate(camera.offset.x + camera.target.x, camera.offset.y + camera.target.y, 0.0f);
Matrix matTransform = MatrixMultiply(MatrixMultiply(matOrigin, MatrixMultiply(matScale, matRotation)), matTranslation);
rlMultMatrixf(MatrixToFloat(matTransform)); // Apply transformation to modelview
// Apply screen scaling if required
rlMultMatrixf(MatrixToFloat(screenScaling));
// Apply 2d camera transformation to modelview
rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera)));
}
// Ends 2D mode with custom camera
@ -1370,6 +1364,23 @@ void EndTextureMode(void)
currentHeight = GetScreenHeight();
}
// Begin scissor mode (define screen area for following drawing)
// NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
void BeginScissorMode(int x, int y, int width, int height)
{
rlglDraw(); // Force drawing elements
rlEnableScissorTest();
rlScissor(x, GetScreenHeight() - (y + height), width, height);
}
// End scissor mode
void EndScissorMode(void)
{
rlglDraw(); // Force drawing elements
rlDisableScissorTest();
}
// Returns a ray trace from mouse position
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
{
@ -1425,6 +1436,40 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
return ray;
}
// Get transform matrix for camera
Matrix GetCameraMatrix(Camera camera)
{
return MatrixLookAt(camera.position, camera.target, camera.up);
}
// Returns camera 2d transform matrix
Matrix GetCameraMatrix2D(Camera2D camera)
{
Matrix matTransform = { 0 };
// The camera in world-space is set by
// 1. Move it to target
// 2. Rotate by -rotation and scale by (1/zoom)
// When setting higher scale, it's more intuitive for the world to become bigger (= camera become smaller),
// not for the camera getting bigger, hence the invert. Same deal with rotation.
// 3. Move it by (-offset);
// Offset defines target transform relative to screen, but since we're effectively "moving" screen (camera)
// we need to do it into opposite direction (inverse transform)
// Having camera transform in world-space, inverse of it gives the modelview transform.
// Since (A*B*C)' = C'*B'*A', the modelview is
// 1. Move to offset
// 2. Rotate and Scale
// 3. Move by -target
Matrix matOrigin = MatrixTranslate(-camera.target.x, -camera.target.y, 0.0f);
Matrix matRotation = MatrixRotate((Vector3){ 0.0f, 0.0f, 1.0f }, camera.rotation*DEG2RAD);
Matrix matScale = MatrixScale(camera.zoom, camera.zoom, 1.0f);
Matrix matTranslation = MatrixTranslate(camera.offset.x, camera.offset.y, 0.0f);
matTransform = MatrixMultiply(MatrixMultiply(matOrigin, MatrixMultiply(matScale, matRotation)), matTranslation);
return matTransform;
}
// Returns the screen space position from a 3d world space position
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
{
@ -1467,10 +1512,22 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera)
return screenPosition;
}
// Get transform matrix for camera
Matrix GetCameraMatrix(Camera camera)
// Returns the screen space position for a 2d camera world space position
Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera)
{
return MatrixLookAt(camera.position, camera.target, camera.up);
Matrix matCamera = GetCameraMatrix2D(camera);
Vector3 transform = Vector3Transform((Vector3){ position.x, position.y, 0 }, matCamera);
return (Vector2){ transform.x, transform.y };
}
// Returns the world space position for a 2d camera screen space position
Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera)
{
Matrix invMatCamera = MatrixInvert(GetCameraMatrix2D(camera));
Vector3 transform = Vector3Transform((Vector3){ position.x, position.y, 0 }, invMatCamera);
return (Vector2){ transform.x, transform.y };
}
// Set target FPS (maximum)
@ -1664,7 +1721,6 @@ void SetConfigFlags(unsigned int flags)
{
configFlags = flags;
if (configFlags & FLAG_SHOW_LOGO) showLogo = true;
if (configFlags & FLAG_FULLSCREEN_MODE) fullscreen = true;
if (configFlags & FLAG_WINDOW_ALWAYS_RUN) alwaysRun = true;
}
@ -1789,10 +1845,10 @@ const char *GetFileName(const char *filePath)
return fileName + 1;
}
// Get filename string without extension (memory should be freed)
// Get filename string without extension (uses static string)
const char *GetFileNameWithoutExt(const char *filePath)
{
#define MAX_FILENAMEWITHOUTEXT_LENGTH 64
#define MAX_FILENAMEWITHOUTEXT_LENGTH 128
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH];
memset(fileName, 0, MAX_FILENAMEWITHOUTEXT_LENGTH);
@ -2494,9 +2550,6 @@ static bool InitGraphicsDevice(int width, int height)
if (screenHeight <= 0) screenHeight = displayHeight;
#endif // PLATFORM_DESKTOP
currentWidth = screenWidth;
currentHeight = screenHeight;
#if defined(PLATFORM_WEB)
displayWidth = screenWidth;
displayHeight = screenHeight;
@ -3027,6 +3080,9 @@ static bool InitGraphicsDevice(int width, int height)
// Setup default viewport
SetupViewport(fbWidth, fbHeight);
currentWidth = screenWidth;
currentHeight = screenHeight;
ClearBackground(RAYWHITE); // Default background color for raylib games :P
#if defined(PLATFORM_ANDROID)
@ -3935,13 +3991,6 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd)
}
}
*/
// raylib logo appearing animation (if enabled)
if (showLogo)
{
SetTargetFPS(60); // Not required on Android
LogoAnimation();
}
}
}
} break;
@ -4272,8 +4321,8 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping);
for(int i = 0; i < gamepadEvent->numAxes; ++i) TraceLog(LOG_DEBUG, "Axis %d: %g", i, gamepadEvent->axis[i]);
for(int i = 0; i < gamepadEvent->numButtons; ++i) TraceLog(LOG_DEBUG, "Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
for (int i = 0; i < gamepadEvent->numAxes; ++i) TraceLog(LOG_DEBUG, "Axis %d: %g", i, gamepadEvent->axis[i]);
for (int i = 0; i < gamepadEvent->numButtons; ++i) TraceLog(LOG_DEBUG, "Button %d: Digital: %d, Analog: %g", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]);
*/
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) gamepadReady[gamepadEvent->index] = true;
@ -4989,117 +5038,3 @@ static void *GamepadThread(void *arg)
return NULL;
}
#endif // PLATFORM_RPI
// Plays raylib logo appearing animation
static void LogoAnimation(void)
{
#if !defined(PLATFORM_WEB) && !defined(PLATFORM_UWP)
int logoPositionX = screenWidth/2 - 128;
int logoPositionY = screenHeight/2 - 128;
int framesCounter = 0;
int lettersCount = 0;
int topSideRecWidth = 16;
int leftSideRecHeight = 16;
int bottomSideRecWidth = 16;
int rightSideRecHeight = 16;
int state = 0; // Tracking animation states (State Machine)
float alpha = 1.0f; // Useful for fading
while (!WindowShouldClose() && (state != 4)) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (state == 0) // State 0: Small box blinking
{
framesCounter++;
if (framesCounter == 84)
{
state = 1;
framesCounter = 0; // Reset counter... will be used later...
}
}
else if (state == 1) // State 1: Top and left bars growing
{
topSideRecWidth += 4;
leftSideRecHeight += 4;
if (topSideRecWidth == 256) state = 2;
}
else if (state == 2) // State 2: Bottom and right bars growing
{
bottomSideRecWidth += 4;
rightSideRecHeight += 4;
if (bottomSideRecWidth == 256) state = 3;
}
else if (state == 3) // State 3: Letters appearing (one by one)
{
framesCounter++;
if (framesCounter/12) // Every 12 frames, one more letter!
{
lettersCount++;
framesCounter = 0;
}
if (lettersCount >= 10) // When all letters have appeared, just fade out everything
{
alpha -= 0.02f;
if (alpha <= 0.0f)
{
alpha = 0.0f;
state = 4;
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
if (state == 0)
{
if ((framesCounter/12)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
}
else if (state == 1)
{
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
}
else if (state == 2)
{
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
}
else if (state == 3)
{
DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
DrawText(TextSubtext("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha));
}
EndDrawing();
//----------------------------------------------------------------------------------
}
#endif
showLogo = false; // Prevent for repeating when reloading window (Android)
}

View File

@ -1,6 +1,6 @@
/*
Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file.
miniaudio (formerly mini_al) - v0.9.6 - 2019-xx-xx
miniaudio (formerly mini_al) - v0.9.6 - 2019-08-04
David Reid - davidreidsoftware@gmail.com
@ -33361,7 +33361,7 @@ Device
/*
REVISION HISTORY
================
v0.9.6 - 2019-xx-xx
v0.9.6 - 2019-08-04
- Add support for loading decoders using a wchar_t string for file paths.
- Don't trigger an assert when ma_device_start() is called on a device that is already started. This will now log a warning
and return MA_INVALID_OPERATION. The same applies for ma_device_stop().

View File

@ -686,14 +686,14 @@ Model LoadModelFromMesh(Mesh mesh)
model.transform = MatrixIdentity();
model.meshCount = 1;
model.meshes = (Mesh *)RL_MALLOC(model.meshCount*sizeof(Mesh));
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
model.meshes[0] = mesh;
model.materialCount = 1;
model.materials = (Material *)RL_MALLOC(model.materialCount*sizeof(Material));
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
model.materials[0] = LoadMaterialDefault();
model.meshMaterial = (int *)RL_MALLOC(model.meshCount*sizeof(int));
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
model.meshMaterial[0] = 0; // First material index
return model;
@ -829,7 +829,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
Material LoadMaterialDefault(void)
{
Material material = { 0 };
material.maps = (MaterialMap *)RL_CALLOC(MAX_MATERIAL_MAPS*sizeof(MaterialMap), 1);
material.maps = (MaterialMap *)RL_CALLOC(MAX_MATERIAL_MAPS, sizeof(MaterialMap));
material.shader = GetShaderDefault();
material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel)
@ -919,7 +919,7 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
TraceLog(LOG_ERROR, "[%s] Unable to open file", filename);
}
// header
// Read IQM header
fread(&iqm, sizeof(IQMHeader), 1, iqmFile);
if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC)))
@ -934,34 +934,30 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
fclose(iqmFile);
}
// bones
IQMPose *poses;
poses = RL_MALLOC(sizeof(IQMPose)*iqm.num_poses);
// Get bones data
IQMPose *poses = RL_MALLOC(iqm.num_poses*sizeof(IQMPose));
fseek(iqmFile, iqm.ofs_poses, SEEK_SET);
fread(poses, sizeof(IQMPose)*iqm.num_poses, 1, iqmFile);
fread(poses, iqm.num_poses*sizeof(IQMPose), 1, iqmFile);
// animations
// Get animations data
*animCount = iqm.num_anims;
IQMAnim *anim = RL_MALLOC(iqm.num_anims*sizeof(IQMAnim));
fseek(iqmFile, iqm.ofs_anims, SEEK_SET);
fread(anim, iqm.num_anims*sizeof(IQMAnim), 1, iqmFile);
ModelAnimation *animations = RL_MALLOC(iqm.num_anims*sizeof(ModelAnimation));
// frameposes
unsigned short *framedata = RL_MALLOC(sizeof(unsigned short)*iqm.num_frames*iqm.num_framechannels);
unsigned short *framedata = RL_MALLOC(iqm.num_frames*iqm.num_framechannels*sizeof(unsigned short));
fseek(iqmFile, iqm.ofs_frames, SEEK_SET);
fread(framedata, sizeof(unsigned short)*iqm.num_frames*iqm.num_framechannels, 1, iqmFile);
fread(framedata, iqm.num_frames*iqm.num_framechannels*sizeof(unsigned short), 1, iqmFile);
for(int a=0;a<iqm.num_anims;a++)
for (int a = 0; a < iqm.num_anims; a++)
{
animations[a].frameCount = anim[a].num_frames;
animations[a].boneCount = iqm.num_poses;
animations[a].bones = RL_MALLOC(sizeof(BoneInfo)*iqm.num_poses);
animations[a].framePoses = RL_MALLOC(sizeof(Transform*)*anim[a].num_frames);
// unused for now
//animations[a].framerate = anim.framerate;
animations[a].bones = RL_MALLOC(iqm.num_poses*sizeof(BoneInfo));
animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
//animations[a].framerate = anim.framerate; // TODO: Use framerate?
for (int j = 0; j < iqm.num_poses; j++)
{
@ -969,7 +965,7 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
animations[a].bones[j].parent = poses[j].parent;
}
for (int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(sizeof(Transform)*iqm.num_poses);
for (int j = 0; j < anim[a].num_frames; j++) animations[a].framePoses[j] = RL_MALLOC(iqm.num_poses*sizeof(Transform));
int dcounter = anim[a].first_frame*iqm.num_framechannels;
@ -1083,7 +1079,6 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
fclose(iqmFile);
return animations;
}
@ -1091,61 +1086,64 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
// NOTE: Updated data is uploaded to GPU
void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
{
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
for (int m = 0; m < model.meshCount; m++)
if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
{
Vector3 animVertex = { 0 };
Vector3 animNormal = { 0 };
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
Vector3 inTranslation = { 0 };
Quaternion inRotation = { 0 };
Vector3 inScale = { 0 };
Vector3 outTranslation = { 0 };
Quaternion outRotation = { 0 };
Vector3 outScale = { 0 };
int vCounter = 0;
int boneCounter = 0;
int boneId = 0;
for (int i = 0; i < model.meshes[m].vertexCount; i++)
for (int m = 0; m < model.meshCount; m++)
{
boneId = model.meshes[m].boneIds[boneCounter];
inTranslation = model.bindPose[boneId].translation;
inRotation = model.bindPose[boneId].rotation;
inScale = model.bindPose[boneId].scale;
outTranslation = anim.framePoses[frame][boneId].translation;
outRotation = anim.framePoses[frame][boneId].rotation;
outScale = anim.framePoses[frame][boneId].scale;
Vector3 animVertex = { 0 };
Vector3 animNormal = { 0 };
// Vertices processing
// NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)
animVertex = (Vector3){ model.meshes[m].vertices[vCounter], model.meshes[m].vertices[vCounter + 1], model.meshes[m].vertices[vCounter + 2] };
animVertex = Vector3MultiplyV(animVertex, outScale);
animVertex = Vector3Subtract(animVertex, inTranslation);
animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
animVertex = Vector3Add(animVertex, outTranslation);
model.meshes[m].animVertices[vCounter] = animVertex.x;
model.meshes[m].animVertices[vCounter + 1] = animVertex.y;
model.meshes[m].animVertices[vCounter + 2] = animVertex.z;
Vector3 inTranslation = { 0 };
Quaternion inRotation = { 0 };
Vector3 inScale = { 0 };
// Normals processing
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
animNormal = (Vector3){ model.meshes[m].normals[vCounter], model.meshes[m].normals[vCounter + 1], model.meshes[m].normals[vCounter + 2] };
animNormal = Vector3RotateByQuaternion(animNormal, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
model.meshes[m].animNormals[vCounter] = animNormal.x;
model.meshes[m].animNormals[vCounter + 1] = animNormal.y;
model.meshes[m].animNormals[vCounter + 2] = animNormal.z;
vCounter += 3;
Vector3 outTranslation = { 0 };
Quaternion outRotation = { 0 };
Vector3 outScale = { 0 };
boneCounter += 4;
int vCounter = 0;
int boneCounter = 0;
int boneId = 0;
for (int i = 0; i < model.meshes[m].vertexCount; i++)
{
boneId = model.meshes[m].boneIds[boneCounter];
inTranslation = model.bindPose[boneId].translation;
inRotation = model.bindPose[boneId].rotation;
inScale = model.bindPose[boneId].scale;
outTranslation = anim.framePoses[frame][boneId].translation;
outRotation = anim.framePoses[frame][boneId].rotation;
outScale = anim.framePoses[frame][boneId].scale;
// Vertices processing
// NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)
animVertex = (Vector3){ model.meshes[m].vertices[vCounter], model.meshes[m].vertices[vCounter + 1], model.meshes[m].vertices[vCounter + 2] };
animVertex = Vector3MultiplyV(animVertex, outScale);
animVertex = Vector3Subtract(animVertex, inTranslation);
animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
animVertex = Vector3Add(animVertex, outTranslation);
model.meshes[m].animVertices[vCounter] = animVertex.x;
model.meshes[m].animVertices[vCounter + 1] = animVertex.y;
model.meshes[m].animVertices[vCounter + 2] = animVertex.z;
// Normals processing
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
animNormal = (Vector3){ model.meshes[m].normals[vCounter], model.meshes[m].normals[vCounter + 1], model.meshes[m].normals[vCounter + 2] };
animNormal = Vector3RotateByQuaternion(animNormal, QuaternionMultiply(outRotation, QuaternionInvert(inRotation)));
model.meshes[m].animNormals[vCounter] = animNormal.x;
model.meshes[m].animNormals[vCounter + 1] = animNormal.y;
model.meshes[m].animNormals[vCounter + 2] = animNormal.z;
vCounter += 3;
boneCounter += 4;
}
// Upload new vertex data to GPU for model drawing
rlUpdateBuffer(model.meshes[m].vboId[0], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float)); // Update vertex position
rlUpdateBuffer(model.meshes[m].vboId[2], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float)); // Update vertex normals
}
// Upload new vertex data to GPU for model drawing
rlUpdateBuffer(model.meshes[m].vboId[0], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float)); // Update vertex position
rlUpdateBuffer(model.meshes[m].vboId[2], model.meshes[m].animVertices, model.meshes[m].vertexCount*3*sizeof(float)); // Update vertex normals
}
}
@ -1181,7 +1179,7 @@ bool IsModelAnimationValid(Model model, ModelAnimation anim)
Mesh GenMeshPoly(int sides, float radius)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
int vertexCount = sides*3;
// Vertices definition
@ -1244,7 +1242,7 @@ Mesh GenMeshPoly(int sides, float radius)
Mesh GenMeshPlane(float width, float length, int resX, int resZ)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
#define CUSTOM_MESH_GEN_PLANE
#if defined(CUSTOM_MESH_GEN_PLANE)
@ -1347,7 +1345,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
mesh.vertices = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));
mesh.texcoords = (float *)RL_MALLOC(plane->ntriangles*3*2*sizeof(float));
mesh.normals = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int));
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
mesh.vertexCount = plane->ntriangles*3;
mesh.triangleCount = plane->ntriangles;
@ -1379,7 +1377,7 @@ Mesh GenMeshPlane(float width, float length, int resX, int resZ)
Mesh GenMeshCube(float width, float height, float length)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
#define CUSTOM_MESH_GEN_CUBE
#if defined(CUSTOM_MESH_GEN_CUBE)
@ -1545,7 +1543,7 @@ par_shapes_mesh* par_shapes_create_icosahedron(); // 20 sides polyhedron
RLAPI Mesh GenMeshSphere(float radius, int rings, int slices)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
par_shapes_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings);
par_shapes_scale(sphere, radius, radius, radius);
@ -1584,7 +1582,7 @@ RLAPI Mesh GenMeshSphere(float radius, int rings, int slices)
RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
par_shapes_mesh *sphere = par_shapes_create_hemisphere(slices, rings);
par_shapes_scale(sphere, radius, radius, radius);
@ -1623,7 +1621,7 @@ RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices)
Mesh GenMeshCylinder(float radius, float height, int slices)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
// Instance a cylinder that sits on the Z=0 plane using the given tessellation
// levels across the UV domain. Think of "slices" like a number of pizza
@ -1682,7 +1680,7 @@ Mesh GenMeshCylinder(float radius, float height, int slices)
Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
if (radius > 1.0f) radius = 1.0f;
else if (radius < 0.1f) radius = 0.1f;
@ -1725,7 +1723,7 @@ Mesh GenMeshTorus(float radius, float size, int radSeg, int sides)
Mesh GenMeshKnot(float radius, float size, int radSeg, int sides)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
if (radius > 3.0f) radius = 3.0f;
else if (radius < 0.5f) radius = 0.5f;
@ -1769,6 +1767,7 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
#define GRAY_VALUE(c) ((c.r+c.g+c.b)/3)
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
int mapX = heightmap.width;
int mapZ = heightmap.height;
@ -1877,7 +1876,7 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
{
Mesh mesh = { 0 };
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
Color *cubicmapPixels = GetImageData(cubicmap);
@ -2791,11 +2790,15 @@ static Model LoadOBJ(const char *fileName)
// TODO: Support multiple meshes... in the meantime, only one mesh is returned
//model.meshCount = meshCount;
model.meshCount = 1;
model.meshes = (Mesh *)RL_MALLOC(model.meshCount*sizeof(Mesh));
model.meshes = (Mesh *)RL_CALLOC(model.meshCount, sizeof(Mesh));
// Init model materials array
model.materialCount = materialCount;
model.materials = (Material *)RL_MALLOC(model.materialCount*sizeof(Material));
if (materialCount > 0)
{
model.materialCount = materialCount;
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
}
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
/*
@ -2815,10 +2818,10 @@ static Model LoadOBJ(const char *fileName)
memset(&mesh, 0, sizeof(Mesh));
mesh.vertexCount = attrib.num_faces*3;
mesh.triangleCount = attrib.num_faces;
mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));
mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
mesh.vertices = (float *)RL_CALLOC(mesh.vertexCount*3, sizeof(float));
mesh.texcoords = (float *)RL_CALLOC(mesh.vertexCount*2, sizeof(float));
mesh.normals = (float *)RL_CALLOC(mesh.vertexCount*3, sizeof(float));
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
int vCount = 0;
int vtCount = 0;
@ -3065,36 +3068,36 @@ static Model LoadIQM(const char *fileName)
model.meshCount = iqm.num_meshes;
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
char name[MESH_NAME_LENGTH];
char name[MESH_NAME_LENGTH] = { 0 };
for (int i = 0; i < model.meshCount; i++)
{
fseek(iqmFile,iqm.ofs_text+imesh[i].name,SEEK_SET);
fseek(iqmFile, iqm.ofs_text + imesh[i].name, SEEK_SET);
fread(name, sizeof(char)*MESH_NAME_LENGTH, 1, iqmFile); // Mesh name not used...
model.meshes[i].vertexCount = imesh[i].num_vertexes;
model.meshes[i].vertices = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*3); // Default vertex positions
model.meshes[i].normals = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*3); // Default vertex normals
model.meshes[i].texcoords = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*2); // Default vertex texcoords
model.meshes[i].vertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions
model.meshes[i].normals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals
model.meshes[i].texcoords = RL_CALLOC(model.meshes[i].vertexCount*2, sizeof(float)); // Default vertex texcoords
model.meshes[i].boneIds = RL_MALLOC(sizeof(int)*model.meshes[i].vertexCount*4); // Up-to 4 bones supported!
model.meshes[i].boneWeights = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*4); // Up-to 4 bones supported!
model.meshes[i].boneIds = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!
model.meshes[i].boneWeights = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // Up-to 4 bones supported!
model.meshes[i].triangleCount = imesh[i].num_triangles;
model.meshes[i].indices = RL_MALLOC(sizeof(unsigned short)*model.meshes[i].triangleCount*3);
model.meshes[i].indices = RL_CALLOC(model.meshes[i].triangleCount*3, sizeof(unsigned short));
// Animated verted data, what we actually process for rendering
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
model.meshes[i].animVertices = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*3);
model.meshes[i].animNormals = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*3);
model.meshes[i].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].animNormals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
}
// Triangles data processing
tri = RL_MALLOC(sizeof(IQMTriangle)*iqm.num_triangles);
tri = RL_MALLOC(iqm.num_triangles*sizeof(IQMTriangle));
fseek(iqmFile, iqm.ofs_triangles, SEEK_SET);
fread(tri, sizeof(IQMTriangle)*iqm.num_triangles, 1, iqmFile);
fread(tri, iqm.num_triangles*sizeof(IQMTriangle), 1, iqmFile);
for (int m = 0; m < model.meshCount; m++)
{
@ -3111,9 +3114,9 @@ static Model LoadIQM(const char *fileName)
}
// Vertex arrays data processing
va = RL_MALLOC(sizeof(IQMVertexArray)*iqm.num_vertexarrays);
va = RL_MALLOC(iqm.num_vertexarrays*sizeof(IQMVertexArray));
fseek(iqmFile, iqm.ofs_vertexarrays, SEEK_SET);
fread(va, sizeof(IQMVertexArray)*iqm.num_vertexarrays, 1, iqmFile);
fread(va, iqm.num_vertexarrays*sizeof(IQMVertexArray), 1, iqmFile);
for (int i = 0; i < iqm.num_vertexarrays; i++)
{
@ -3121,9 +3124,9 @@ static Model LoadIQM(const char *fileName)
{
case IQM_POSITION:
{
vertex = RL_MALLOC(sizeof(float)*iqm.num_vertexes*3);
vertex = RL_MALLOC(iqm.num_vertexes*3*sizeof(float));
fseek(iqmFile, va[i].offset, SEEK_SET);
fread(vertex, sizeof(float)*iqm.num_vertexes*3, 1, iqmFile);
fread(vertex, iqm.num_vertexes*3*sizeof(float), 1, iqmFile);
for (int m = 0; m < iqm.num_meshes; m++)
{
@ -3138,9 +3141,9 @@ static Model LoadIQM(const char *fileName)
} break;
case IQM_NORMAL:
{
normal = RL_MALLOC(sizeof(float)*iqm.num_vertexes*3);
normal = RL_MALLOC(iqm.num_vertexes*3*sizeof(float));
fseek(iqmFile, va[i].offset, SEEK_SET);
fread(normal, sizeof(float)*iqm.num_vertexes*3, 1, iqmFile);
fread(normal, iqm.num_vertexes*3*sizeof(float), 1, iqmFile);
for (int m = 0; m < iqm.num_meshes; m++)
{
@ -3155,9 +3158,9 @@ static Model LoadIQM(const char *fileName)
} break;
case IQM_TEXCOORD:
{
text = RL_MALLOC(sizeof(float)*iqm.num_vertexes*2);
text = RL_MALLOC(iqm.num_vertexes*2*sizeof(float));
fseek(iqmFile, va[i].offset, SEEK_SET);
fread(text, sizeof(float)*iqm.num_vertexes*2, 1, iqmFile);
fread(text, iqm.num_vertexes*2*sizeof(float), 1, iqmFile);
for (int m = 0; m < iqm.num_meshes; m++)
{
@ -3171,9 +3174,9 @@ static Model LoadIQM(const char *fileName)
} break;
case IQM_BLENDINDEXES:
{
blendi = RL_MALLOC(sizeof(char)*iqm.num_vertexes*4);
blendi = RL_MALLOC(iqm.num_vertexes*4*sizeof(char));
fseek(iqmFile, va[i].offset, SEEK_SET);
fread(blendi, sizeof(char)*iqm.num_vertexes*4, 1, iqmFile);
fread(blendi, iqm.num_vertexes*4*sizeof(char), 1, iqmFile);
for (int m = 0; m < iqm.num_meshes; m++)
{
@ -3187,9 +3190,9 @@ static Model LoadIQM(const char *fileName)
} break;
case IQM_BLENDWEIGHTS:
{
blendw = RL_MALLOC(sizeof(unsigned char)*iqm.num_vertexes*4);
fseek(iqmFile,va[i].offset,SEEK_SET);
fread(blendw,sizeof(unsigned char)*iqm.num_vertexes*4,1,iqmFile);
blendw = RL_MALLOC(iqm.num_vertexes*4*sizeof(unsigned char));
fseek(iqmFile, va[i].offset, SEEK_SET);
fread(blendw, iqm.num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
for (int m = 0; m < iqm.num_meshes; m++)
{
@ -3205,20 +3208,20 @@ static Model LoadIQM(const char *fileName)
}
// Bones (joints) data processing
ijoint = RL_MALLOC(sizeof(IQMJoint)*iqm.num_joints);
ijoint = RL_MALLOC(iqm.num_joints*sizeof(IQMJoint));
fseek(iqmFile, iqm.ofs_joints, SEEK_SET);
fread(ijoint, sizeof(IQMJoint)*iqm.num_joints, 1, iqmFile);
fread(ijoint, iqm.num_joints*sizeof(IQMJoint), 1, iqmFile);
model.boneCount = iqm.num_joints;
model.bones = RL_MALLOC(sizeof(BoneInfo)*iqm.num_joints);
model.bindPose = RL_MALLOC(sizeof(Transform)*iqm.num_joints);
model.bones = RL_MALLOC(iqm.num_joints*sizeof(BoneInfo));
model.bindPose = RL_MALLOC(iqm.num_joints*sizeof(Transform));
for (int i = 0; i < iqm.num_joints; i++)
{
// Bones
model.bones[i].parent = ijoint[i].parent;
fseek(iqmFile, iqm.ofs_text + ijoint[i].name, SEEK_SET);
fread(model.bones[i].name,sizeof(char)*BONE_NAME_LENGTH, 1, iqmFile);
fread(model.bones[i].name, BONE_NAME_LENGTH*sizeof(char), 1, iqmFile);
// Bind pose (base pose)
model.bindPose[i].translation.x = ijoint[i].translate[0];
@ -3410,7 +3413,7 @@ static Model LoadGLTF(const char *fileName)
model.materials = RL_MALLOC(model.materialCount*sizeof(Material));
model.meshMaterial = RL_MALLOC(model.meshCount*sizeof(int));
for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO*sizeof(unsigned int), 1);
for (int i = 0; i < model.meshCount; i++) model.meshes[i].vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
for (int i = 0; i < model.materialCount - 1; i++)
{
@ -3418,7 +3421,7 @@ static Model LoadGLTF(const char *fileName)
Texture2D texture = { 0 };
const char *texPath = GetDirectoryPath(fileName);
if (data->materials[i].pbr_metallic_roughness.base_color_factor)
if (data->materials[i].has_pbr_metallic_roughness)
{
tint.r = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[0]*255.99f);
tint.g = (unsigned char)(data->materials[i].pbr_metallic_roughness.base_color_factor[1]*255.99f);
@ -3427,13 +3430,13 @@ static Model LoadGLTF(const char *fileName)
}
else
{
tint.r = 1.f;
tint.g = 1.f;
tint.b = 1.f;
tint.a = 1.f;
tint.r = 1.0f;
tint.g = 1.0f;
tint.b = 1.0f;
tint.a = 1.0f;
}
if (data->materials[i].pbr_metallic_roughness.base_color_texture.texture)
if (data->materials[i].has_pbr_metallic_roughness)
{
cgltf_image *img = data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image;

View File

@ -591,7 +591,7 @@ void SetMasterVolume(float volume)
// Create a new audio buffer. Initially filled with silence
AudioBuffer *InitAudioBuffer(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_uint32 bufferSizeInFrames, int usage)
{
AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(sizeof(*audioBuffer), 1);
AudioBuffer *audioBuffer = (AudioBuffer *)RL_CALLOC(1, sizeof(AudioBuffer));
audioBuffer->buffer = RL_CALLOC((bufferSizeInFrames*channels*ma_get_bytes_per_sample(format)), 1);
if (audioBuffer == NULL)

View File

@ -182,7 +182,7 @@ float GetMusicTimePlayed(Music music); // Get current m
AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels); // Init audio stream (to stream raw audio pcm data)
void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data
void CloseAudioStream(AudioStream stream); // Close audio stream and free memory
bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
bool IsAudioStreamProcessed(AudioStream stream); // Check if any audio stream buffers requires refill
void PlayAudioStream(AudioStream stream); // Play audio stream
void PauseAudioStream(AudioStream stream); // Pause audio stream
void ResumeAudioStream(AudioStream stream); // Resume audio stream

View File

@ -460,7 +460,7 @@ typedef struct VrDeviceInfo {
// System config flags
// NOTE: Used for bit masks
typedef enum {
FLAG_SHOW_LOGO = 1, // Set to show raylib logo at startup
FLAG_RESERVED = 1, // Reserved
FLAG_FULLSCREEN_MODE = 2, // Set to run program in fullscreen
FLAG_WINDOW_RESIZABLE = 4, // Set to allow resizable window
FLAG_WINDOW_UNDECORATED = 8, // Set to disable window decoration (frame and buttons)
@ -904,11 +904,16 @@ RLAPI void BeginMode3D(Camera3D camera); // Initializes
RLAPI void EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode
RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
RLAPI void EndTextureMode(void); // Ends drawing to render texture
RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
RLAPI void EndScissorMode(void); // End scissor mode
// Screen-space-related functions
RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position
RLAPI Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
RLAPI Matrix GetCameraMatrix2D(Camera2D camera); // Returns camera 2d transform matrix
RLAPI Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position for a 3d world space position
RLAPI Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); // Returns the screen space position for a 2d camera world space position
RLAPI Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); // Returns the world space position for a 2d camera screen space position
// Timing-related functions
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
@ -939,7 +944,7 @@ RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file
RLAPI bool DirectoryExists(const char *dirPath); // Check if a directory path exists
RLAPI const char *GetExtension(const char *fileName); // Get pointer to extension for a filename string
RLAPI const char *GetFileName(const char *filePath); // Get pointer to filename for a path string
RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (memory should be freed)
RLAPI const char *GetFileNameWithoutExt(const char *filePath); // Get filename string without extension (uses static string)
RLAPI const char *GetDirectoryPath(const char *filePath); // Get full path for a given fileName with path (uses static string)
RLAPI const char *GetPrevDirectoryPath(const char *dirPath); // Get previous directory path for a given path (uses static string)
RLAPI const char *GetWorkingDirectory(void); // Get current working directory (uses static string)
@ -1324,8 +1329,6 @@ RLAPI void BeginShaderMode(Shader shader); // Beg
RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader)
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending)
RLAPI void BeginScissorMode(int x, int y, int width, int height); // Begin scissor mode (define screen area for following drawing)
RLAPI void EndScissorMode(void); // End scissor mode
// VR control functions
RLAPI void InitVrSimulator(void); // Init VR simulator for selected device parameters

View File

@ -457,6 +457,9 @@ RLAPI void rlEnableDepthTest(void); // Enable depth te
RLAPI void rlDisableDepthTest(void); // Disable depth test
RLAPI void rlEnableBackfaceCulling(void); // Enable backface culling
RLAPI void rlDisableBackfaceCulling(void); // Disable backface culling
RLAPI void rlEnableScissorTest(void); // Enable scissor test
RLAPI void rlDisableScissorTest(void); // Disable scissor test
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
RLAPI void rlEnableWireMode(void); // Enable wire mode
RLAPI void rlDisableWireMode(void); // Disable wire mode
RLAPI void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
@ -1344,28 +1347,25 @@ void rlDisableRenderTexture(void)
}
// Enable depth test
void rlEnableDepthTest(void)
{
glEnable(GL_DEPTH_TEST);
}
void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); }
// Disable depth test
void rlDisableDepthTest(void)
{
glDisable(GL_DEPTH_TEST);
}
void rlDisableDepthTest(void) { glDisable(GL_DEPTH_TEST); }
// Enable backface culling
void rlEnableBackfaceCulling(void)
{
glEnable(GL_CULL_FACE);
}
void rlEnableBackfaceCulling(void) { glEnable(GL_CULL_FACE); }
// Disable backface culling
void rlDisableBackfaceCulling(void)
{
glDisable(GL_CULL_FACE);
}
void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); }
// Enable scissor test
RLAPI void rlEnableScissorTest(void) { glEnable(GL_SCISSOR_TEST); }
// Disable scissor test
RLAPI void rlDisableScissorTest(void) { glDisable(GL_SCISSOR_TEST); }
// Scissor test
RLAPI void rlScissor(int x, int y, int width, int height) { glScissor(x, y, width, height); }
// Enable wire mode
void rlEnableWireMode(void)
@ -1529,24 +1529,33 @@ void rlglInit(int width, int height)
const char **extList = RL_MALLOC(sizeof(const char *)*numExt);
// Get extensions strings
for (int i = 0; i < numExt; i++) extList[i] = (char *)glGetStringi(GL_EXTENSIONS, i);
for (int i = 0; i < numExt; i++) extList[i] = (const char *)glGetStringi(GL_EXTENSIONS, i);
#elif defined(GRAPHICS_API_OPENGL_ES2)
// Allocate 512 strings pointers (2 KB)
const char **extList = RL_MALLOC(sizeof(const char *)*512);
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
// NOTE: We have to duplicate string because glGetString() returns a const string
int len = strlen(extensions) + 1;
char *extensionsDup = (char *)RL_CALLOC(len, sizeof(char));
strcpy(extensionsDup, extensions);
// Get extensions strings
char *extensions = (char *)glGetString(GL_EXTENSIONS); // One big static const string returned
int len = strlen(extensions);
extList[numExt] = extensionsDup;
for (int i = 0; i < len; i++)
{
if (i == ' ')
if (extensionsDup[i] == ' ')
{
extList[numExt] = &extensions[i + 1];
extensionsDup[i] = '\0';
numExt++;
extList[numExt] = &extensionsDup[i + 1];
}
}
// NOTE: Duplicated string (extensionsDup) must be deallocated
#endif
TraceLog(LOG_INFO, "Number of supported extensions: %i", numExt);
@ -1622,6 +1631,8 @@ void rlglInit(int width, int height)
RL_FREE(extList);
#if defined(GRAPHICS_API_OPENGL_ES2)
RL_FREE(extensionsDup); // Duplicated string must be deallocated
if (vaoSupported) TraceLog(LOG_INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully");
else TraceLog(LOG_WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported");
@ -1687,7 +1698,6 @@ void rlglInit(int width, int height)
// Initialize OpenGL default states
//----------------------------------------------------------
// Init state: Depth test
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
glDisable(GL_DEPTH_TEST); // Disable depth testing for 2D (only used for 3D)
@ -2957,7 +2967,7 @@ char *LoadText(const char *fileName)
Shader LoadShader(const char *vsFileName, const char *fsFileName)
{
Shader shader = { 0 };
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS*sizeof(int), 1);
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS, sizeof(int));
char *vShaderStr = NULL;
char *fShaderStr = NULL;
@ -2978,7 +2988,7 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
Shader LoadShaderCode(char *vsCode, char *fsCode)
{
Shader shader = { 0 };
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS*sizeof(int), 1);
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS, sizeof(int));
// NOTE: All locations must be reseted to -1 (no location)
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
@ -3014,7 +3024,7 @@ Shader LoadShaderCode(char *vsCode, char *fsCode)
glGetProgramiv(shader.id, GL_ACTIVE_UNIFORMS, &uniformCount);
for(int i = 0; i < uniformCount; i++)
for (int i = 0; i < uniformCount; i++)
{
int namelen = -1;
int num = -1;
@ -3513,24 +3523,6 @@ void EndBlendMode(void)
BeginBlendMode(BLEND_ALPHA);
}
// Begin scissor mode (define screen area for following drawing)
// NOTE: Scissor rec refers to bottom-left corner, we change it to upper-left
void BeginScissorMode(int x, int y, int width, int height)
{
rlglDraw(); // Force drawing elements
glEnable(GL_SCISSOR_TEST);
glScissor(x, framebufferHeight - (y + height), width, height);
}
// End scissor mode
void EndScissorMode(void)
{
rlglDraw(); // Force drawing elements
glDisable(GL_SCISSOR_TEST);
}
#if defined(SUPPORT_VR_SIMULATOR)
// Init VR simulator for selected device parameters
// NOTE: It modifies the global variable: stereoFbo
@ -3869,7 +3861,7 @@ static unsigned int LoadShaderProgram(unsigned int vShaderId, unsigned int fShad
static Shader LoadShaderDefault(void)
{
Shader shader = { 0 };
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS*sizeof(int), 1);
shader.locs = (int *)RL_CALLOC(MAX_SHADER_LOCATIONS, sizeof(int));
// NOTE: All locations must be reseted to -1 (no location)
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;

View File

@ -1392,8 +1392,8 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
{
bool collision = false;
if ((rec1.x <= (rec2.x + rec2.width) && (rec1.x + rec1.width) >= rec2.x) &&
(rec1.y <= (rec2.y + rec2.height) && (rec1.y + rec1.height) >= rec2.y)) collision = true;
if ((rec1.x < (rec2.x + rec2.width) && (rec1.x + rec1.width) > rec2.x) &&
(rec1.y < (rec2.y + rec2.height) && (rec1.y + rec1.height) > rec2.y)) collision = true;
return collision;
}

View File

@ -586,7 +586,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
*charRecs = NULL;
// In case no chars count provided we suppose default of 95
charsCount = (charsCount > 0) ? charsCount : 95;
charsCount = (charsCount > 0)? charsCount : 95;
// NOTE: Rectangles memory is loaded here!
Rectangle *recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
@ -597,7 +597,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
// so image size would result bigger than default font type
float requiredArea = 0;
for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
float guessSize = sqrtf(requiredArea)*1.25f;
float guessSize = sqrtf(requiredArea)*1.3f;
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
atlas.width = imageSize; // Atlas bitmap width
@ -1372,20 +1372,25 @@ const char **TextSplit(const char *text, char delimiter, int *count)
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
result[0] = buffer;
int counter = 1;
// Count how many substrings we have on text and point to every one
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
int counter = 0;
if (text != NULL)
{
buffer[i] = text[i];
if (buffer[i] == '\0') break;
else if (buffer[i] == delimiter)
counter = 1;
// Count how many substrings we have on text and point to every one
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
{
buffer[i] = '\0'; // Set an end of string at this point
result[counter] = buffer + i + 1;
counter++;
buffer[i] = text[i];
if (buffer[i] == '\0') break;
else if (buffer[i] == delimiter)
{
buffer[i] = '\0'; // Set an end of string at this point
result[counter] = buffer + i + 1;
counter++;
if (counter == MAX_SUBSTRINGS_COUNT) break;
if (counter == MAX_SUBSTRINGS_COUNT) break;
}
}
}