commit
8314e7e4dc
|
|
@ -471,7 +471,7 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP)
|
||||||
del *.o *.exe /s
|
del *.o *.exe /s
|
||||||
endif
|
endif
|
||||||
ifeq ($(PLATFORM_OS),LINUX)
|
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
|
endif
|
||||||
ifeq ($(PLATFORM_OS),OSX)
|
ifeq ($(PLATFORM_OS),OSX)
|
||||||
find . -type f -perm +ugo+x -delete
|
find . -type f -perm +ugo+x -delete
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ int main(void)
|
||||||
|
|
||||||
Camera2D camera = { 0 };
|
Camera2D camera = { 0 };
|
||||||
camera.target = (Vector2){ player.x + 20, player.y + 20 };
|
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.rotation = 0.0f;
|
||||||
camera.zoom = 1.0f;
|
camera.zoom = 1.0f;
|
||||||
|
|
||||||
|
|
@ -54,16 +54,10 @@ int main(void)
|
||||||
{
|
{
|
||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
if (IsKeyDown(KEY_RIGHT))
|
|
||||||
{
|
// Player movement
|
||||||
player.x += 2; // Player movement
|
if (IsKeyDown(KEY_RIGHT)) player.x += 2;
|
||||||
camera.offset.x -= 2; // Camera displacement with player movement
|
else if (IsKeyDown(KEY_LEFT)) player.x -= 2;
|
||||||
}
|
|
||||||
else if (IsKeyDown(KEY_LEFT))
|
|
||||||
{
|
|
||||||
player.x -= 2; // Player movement
|
|
||||||
camera.offset.x += 2; // Camera displacement with player movement
|
|
||||||
}
|
|
||||||
|
|
||||||
// Camera target follows player
|
// Camera target follows player
|
||||||
camera.target = (Vector2){ player.x + 20, player.y + 20 };
|
camera.target = (Vector2){ player.x + 20, player.y + 20 };
|
||||||
|
|
|
||||||
284
examples/core/core_2d_camera_ext.c
Normal file
284
examples/core/core_2d_camera_ext.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -11,14 +11,14 @@ uniform sampler2D texture0;
|
||||||
uniform vec4 colDiffuse;
|
uniform vec4 colDiffuse;
|
||||||
|
|
||||||
// NOTE: Add here your custom variables
|
// NOTE: Add here your custom variables
|
||||||
uniform vec2 leftLensCenter = vec2(0.288, 0.5);
|
uniform vec2 leftLensCenter;
|
||||||
uniform vec2 rightLensCenter = vec2(0.712, 0.5);
|
uniform vec2 rightLensCenter;
|
||||||
uniform vec2 leftScreenCenter = vec2(0.25, 0.5);
|
uniform vec2 leftScreenCenter;
|
||||||
uniform vec2 rightScreenCenter = vec2(0.75, 0.5);
|
uniform vec2 rightScreenCenter;
|
||||||
uniform vec2 scale = vec2(0.25, 0.45);
|
uniform vec2 scale;
|
||||||
uniform vec2 scaleIn = vec2(4, 2.2222);
|
uniform vec2 scaleIn;
|
||||||
uniform vec4 hmdWarpParam = vec4(1, 0.22, 0.24, 0);
|
uniform vec4 hmdWarpParam;
|
||||||
uniform vec4 chromaAbParam = vec4(0.996, -0.004, 1.014, 0.0);
|
uniform vec4 chromaAbParam;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,8 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadTexture(texture); // Unload texture
|
||||||
|
|
||||||
// Unload model animations data
|
// Unload model animations data
|
||||||
for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]);
|
for (int i = 0; i < animsCount; i++) UnloadModelAnimation(anims[i]);
|
||||||
RL_FREE(anims);
|
RL_FREE(anims);
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,8 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// 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
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -115,11 +115,12 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadTexture(texture); // Unload texture
|
||||||
|
|
||||||
// Unload models data (GPU VRAM)
|
// Unload models data (GPU VRAM)
|
||||||
for (int i = 0; i < NUM_MODELS; i++) UnloadModel(models[i]);
|
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;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
UnloadTexture(texture); // Unload texture
|
||||||
UnloadModel(model); // Unload model
|
UnloadModel(model); // Unload model
|
||||||
|
|
||||||
ClearDroppedFiles(); // Clear internal buffers
|
ClearDroppedFiles(); // Clear internal buffers
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,10 @@ int main(void)
|
||||||
|
|
||||||
// De-Initialization
|
// 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
|
CloseWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ int main(void)
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Unload all loaded data
|
// Unload all loaded data
|
||||||
|
UnloadTexture(model.materials[0].maps[MAP_DIFFUSE].texture);
|
||||||
UnloadModel(model);
|
UnloadModel(model);
|
||||||
|
|
||||||
UnloadRenderTexture(framebuffer);
|
UnloadRenderTexture(framebuffer);
|
||||||
|
|
|
||||||
99
examples/shaders/resources/shaders/glsl330/fog.fs
Normal file
99
examples/shaders/resources/shaders/glsl330/fog.fs
Normal 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);
|
||||||
|
}
|
||||||
32
examples/shaders/resources/shaders/glsl330/fog.vs
Normal file
32
examples/shaders/resources/shaders/glsl330/fog.vs
Normal 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);
|
||||||
|
}
|
||||||
153
examples/shaders/shaders_fog.c
Normal file
153
examples/shaders/shaders_fog.c
Normal 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;
|
||||||
|
}
|
||||||
BIN
examples/shaders/shaders_fog.png
Normal file
BIN
examples/shaders/shaders_fog.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 80 KiB |
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
#include <stdlib.h> // Required for: malloc(), free()
|
#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
|
// This is the maximum amount of elements (quads) per batch
|
||||||
// NOTE: This value is defined in [rlgl] module and can be changed there
|
// NOTE: This value is defined in [rlgl] module and can be changed there
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,17 @@ This folder contains raylib templates for some common IDEs.
|
||||||
|
|
||||||
IDE | Platform | Template type | State
|
IDE | Platform | Template type | State
|
||||||
----| ---------| ------------- | -----
|
----| ---------| ------------- | -----
|
||||||
|
[4coder](http://4coder.net/) | Windows | example compiling | DONE
|
||||||
[Builder](https://wiki.gnome.org/Apps/Builder) | Linux | 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
|
[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
|
[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
|
[KDevelop](https://www.kdevelop.org/) | Linux, Windows, macOS | - | INCOMPLETE
|
||||||
[Notepad++](https://notepad-plus-plus.org/) | Windows | source/example compiling | DONE
|
[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
|
[VS2015](https://www.visualstudio.com) | Windows | source/example compiling | DONE
|
||||||
[VS2017](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
|
[VSCode](https://code.visualstudio.com/) | Windows, macOS | example compiling | DONE
|
||||||
|
scripts | Windows, Linux, macOS | source and example | DONE
|
||||||
|
|
||||||
*New IDEs config files are welcome!*
|
*New IDEs config files are welcome!*
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@
|
||||||
#define SUPPORT_MOUSE_GESTURES 1
|
#define SUPPORT_MOUSE_GESTURES 1
|
||||||
// Reconfigure standard input to receive key inputs, works with SSH connection.
|
// Reconfigure standard input to receive key inputs, works with SSH connection.
|
||||||
#define SUPPORT_SSH_KEYBOARD_RPI 1
|
#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
|
// Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
||||||
//#define SUPPORT_BUSY_WAIT_LOOP 1
|
//#define SUPPORT_BUSY_WAIT_LOOP 1
|
||||||
// Wait for events passively (sleeping while no events) instead of polling them actively every frame
|
// Wait for events passively (sleeping while no events) instead of polling them actively every frame
|
||||||
|
|
|
||||||
239
src/core.c
239
src/core.c
|
|
@ -55,6 +55,9 @@
|
||||||
* WARNING: Reconfiguring standard input could lead to undesired effects, like breaking other running processes or
|
* 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.
|
* 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
|
* #define SUPPORT_BUSY_WAIT_LOOP
|
||||||
* Use busy wait loop for timing sync, if not defined, a high-resolution timer is setup and used
|
* 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)
|
#if !defined(EXTERNAL_CONFIG_FLAGS)
|
||||||
#include "config.h" // Defines module configuration flags
|
#include "config.h" // Defines module configuration flags
|
||||||
#else
|
#else
|
||||||
#define RAYLIB_VERSION "2.5"
|
#define RAYLIB_VERSION "2.6-dev"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__linux__) || defined(PLATFORM_WEB)) && _POSIX_C_SOURCE < 199309L
|
#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
|
// Config internal variables
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
static unsigned int configFlags = 0; // Configuration flags (bit based)
|
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 char **dropFilesPath; // Store dropped files paths as strings
|
||||||
static int dropFilesCount = 0; // Count dropped files 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 int GetGamepadAxis(int axis); // Get gamepad axis generic to all platforms
|
||||||
static void PollInputEvents(void); // Register user events
|
static void PollInputEvents(void); // Register user events
|
||||||
|
|
||||||
static void LogoAnimation(void); // Plays raylib logo appearing animation
|
|
||||||
|
|
||||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB)
|
||||||
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error
|
||||||
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed
|
||||||
|
|
@ -697,13 +697,6 @@ void InitWindow(int width, int height, const char *title)
|
||||||
|
|
||||||
mousePosition.x = (float)screenWidth/2.0f;
|
mousePosition.x = (float)screenWidth/2.0f;
|
||||||
mousePosition.y = (float)screenHeight/2.0f;
|
mousePosition.y = (float)screenHeight/2.0f;
|
||||||
|
|
||||||
// raylib logo appearing animation (if enabled)
|
|
||||||
if (showLogo)
|
|
||||||
{
|
|
||||||
SetTargetFPS(60);
|
|
||||||
LogoAnimation();
|
|
||||||
}
|
|
||||||
#endif // PLATFORM_ANDROID
|
#endif // PLATFORM_ANDROID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1187,6 +1180,12 @@ void BeginDrawing(void)
|
||||||
// End canvas drawing and swap buffers (double buffering)
|
// End canvas drawing and swap buffers (double buffering)
|
||||||
void EndDrawing(void)
|
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)
|
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
|
||||||
|
|
||||||
#if defined(SUPPORT_GIF_RECORDING)
|
#if defined(SUPPORT_GIF_RECORDING)
|
||||||
|
|
@ -1249,17 +1248,12 @@ void BeginMode2D(Camera2D camera)
|
||||||
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
|
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
|
||||||
|
|
||||||
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||||
rlMultMatrixf(MatrixToFloat(screenScaling)); // Apply screen scaling if required
|
|
||||||
|
|
||||||
// Camera rotation and scaling is always relative to target
|
// Apply screen scaling if required
|
||||||
Matrix matOrigin = MatrixTranslate(-camera.target.x, -camera.target.y, 0.0f);
|
rlMultMatrixf(MatrixToFloat(screenScaling));
|
||||||
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);
|
// Apply 2d camera transformation to modelview
|
||||||
|
rlMultMatrixf(MatrixToFloat(GetCameraMatrix2D(camera)));
|
||||||
rlMultMatrixf(MatrixToFloat(matTransform)); // Apply transformation to modelview
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ends 2D mode with custom camera
|
// Ends 2D mode with custom camera
|
||||||
|
|
@ -1370,6 +1364,23 @@ void EndTextureMode(void)
|
||||||
currentHeight = GetScreenHeight();
|
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
|
// Returns a ray trace from mouse position
|
||||||
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||||
{
|
{
|
||||||
|
|
@ -1425,6 +1436,40 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||||
return ray;
|
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
|
// Returns the screen space position from a 3d world space position
|
||||||
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
||||||
{
|
{
|
||||||
|
|
@ -1467,10 +1512,22 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
||||||
return screenPosition;
|
return screenPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get transform matrix for camera
|
// Returns the screen space position for a 2d camera world space position
|
||||||
Matrix GetCameraMatrix(Camera camera)
|
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)
|
// Set target FPS (maximum)
|
||||||
|
|
@ -1664,7 +1721,6 @@ void SetConfigFlags(unsigned int flags)
|
||||||
{
|
{
|
||||||
configFlags = flags;
|
configFlags = flags;
|
||||||
|
|
||||||
if (configFlags & FLAG_SHOW_LOGO) showLogo = true;
|
|
||||||
if (configFlags & FLAG_FULLSCREEN_MODE) fullscreen = true;
|
if (configFlags & FLAG_FULLSCREEN_MODE) fullscreen = true;
|
||||||
if (configFlags & FLAG_WINDOW_ALWAYS_RUN) alwaysRun = true;
|
if (configFlags & FLAG_WINDOW_ALWAYS_RUN) alwaysRun = true;
|
||||||
}
|
}
|
||||||
|
|
@ -1789,10 +1845,10 @@ const char *GetFileName(const char *filePath)
|
||||||
return fileName + 1;
|
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)
|
const char *GetFileNameWithoutExt(const char *filePath)
|
||||||
{
|
{
|
||||||
#define MAX_FILENAMEWITHOUTEXT_LENGTH 64
|
#define MAX_FILENAMEWITHOUTEXT_LENGTH 128
|
||||||
|
|
||||||
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH];
|
static char fileName[MAX_FILENAMEWITHOUTEXT_LENGTH];
|
||||||
memset(fileName, 0, 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;
|
if (screenHeight <= 0) screenHeight = displayHeight;
|
||||||
#endif // PLATFORM_DESKTOP
|
#endif // PLATFORM_DESKTOP
|
||||||
|
|
||||||
currentWidth = screenWidth;
|
|
||||||
currentHeight = screenHeight;
|
|
||||||
|
|
||||||
#if defined(PLATFORM_WEB)
|
#if defined(PLATFORM_WEB)
|
||||||
displayWidth = screenWidth;
|
displayWidth = screenWidth;
|
||||||
displayHeight = screenHeight;
|
displayHeight = screenHeight;
|
||||||
|
|
@ -3027,6 +3080,9 @@ static bool InitGraphicsDevice(int width, int height)
|
||||||
// Setup default viewport
|
// Setup default viewport
|
||||||
SetupViewport(fbWidth, fbHeight);
|
SetupViewport(fbWidth, fbHeight);
|
||||||
|
|
||||||
|
currentWidth = screenWidth;
|
||||||
|
currentHeight = screenHeight;
|
||||||
|
|
||||||
ClearBackground(RAYWHITE); // Default background color for raylib games :P
|
ClearBackground(RAYWHITE); // Default background color for raylib games :P
|
||||||
|
|
||||||
#if defined(PLATFORM_ANDROID)
|
#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;
|
} break;
|
||||||
|
|
@ -4272,8 +4321,8 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
|
||||||
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
|
eventType != 0? emscripten_event_type_to_string(eventType) : "Gamepad state",
|
||||||
gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping);
|
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->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->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;
|
if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) gamepadReady[gamepadEvent->index] = true;
|
||||||
|
|
@ -4989,117 +5038,3 @@ static void *GamepadThread(void *arg)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif // PLATFORM_RPI
|
#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)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
4
src/external/miniaudio.h
vendored
4
src/external/miniaudio.h
vendored
|
|
@ -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.
|
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
|
David Reid - davidreidsoftware@gmail.com
|
||||||
|
|
||||||
|
|
@ -33361,7 +33361,7 @@ Device
|
||||||
/*
|
/*
|
||||||
REVISION HISTORY
|
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.
|
- 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
|
- 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().
|
and return MA_INVALID_OPERATION. The same applies for ma_device_stop().
|
||||||
|
|
|
||||||
251
src/models.c
251
src/models.c
|
|
@ -686,14 +686,14 @@ Model LoadModelFromMesh(Mesh mesh)
|
||||||
model.transform = MatrixIdentity();
|
model.transform = MatrixIdentity();
|
||||||
|
|
||||||
model.meshCount = 1;
|
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.meshes[0] = mesh;
|
||||||
|
|
||||||
model.materialCount = 1;
|
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.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
|
model.meshMaterial[0] = 0; // First material index
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
|
|
@ -829,7 +829,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount)
|
||||||
Material LoadMaterialDefault(void)
|
Material LoadMaterialDefault(void)
|
||||||
{
|
{
|
||||||
Material material = { 0 };
|
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.shader = GetShaderDefault();
|
||||||
material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel)
|
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);
|
TraceLog(LOG_ERROR, "[%s] Unable to open file", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// header
|
// Read IQM header
|
||||||
fread(&iqm, sizeof(IQMHeader), 1, iqmFile);
|
fread(&iqm, sizeof(IQMHeader), 1, iqmFile);
|
||||||
|
|
||||||
if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC)))
|
if (strncmp(iqm.magic, IQM_MAGIC, sizeof(IQM_MAGIC)))
|
||||||
|
|
@ -934,34 +934,30 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
|
||||||
fclose(iqmFile);
|
fclose(iqmFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bones
|
// Get bones data
|
||||||
IQMPose *poses;
|
IQMPose *poses = RL_MALLOC(iqm.num_poses*sizeof(IQMPose));
|
||||||
poses = RL_MALLOC(sizeof(IQMPose)*iqm.num_poses);
|
|
||||||
fseek(iqmFile, iqm.ofs_poses, SEEK_SET);
|
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;
|
*animCount = iqm.num_anims;
|
||||||
IQMAnim *anim = RL_MALLOC(iqm.num_anims*sizeof(IQMAnim));
|
IQMAnim *anim = RL_MALLOC(iqm.num_anims*sizeof(IQMAnim));
|
||||||
fseek(iqmFile, iqm.ofs_anims, SEEK_SET);
|
fseek(iqmFile, iqm.ofs_anims, SEEK_SET);
|
||||||
fread(anim, iqm.num_anims*sizeof(IQMAnim), 1, iqmFile);
|
fread(anim, iqm.num_anims*sizeof(IQMAnim), 1, iqmFile);
|
||||||
ModelAnimation *animations = RL_MALLOC(iqm.num_anims*sizeof(ModelAnimation));
|
ModelAnimation *animations = RL_MALLOC(iqm.num_anims*sizeof(ModelAnimation));
|
||||||
|
|
||||||
|
|
||||||
// frameposes
|
// 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);
|
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].frameCount = anim[a].num_frames;
|
||||||
animations[a].boneCount = iqm.num_poses;
|
animations[a].boneCount = iqm.num_poses;
|
||||||
animations[a].bones = RL_MALLOC(sizeof(BoneInfo)*iqm.num_poses);
|
animations[a].bones = RL_MALLOC(iqm.num_poses*sizeof(BoneInfo));
|
||||||
animations[a].framePoses = RL_MALLOC(sizeof(Transform*)*anim[a].num_frames);
|
animations[a].framePoses = RL_MALLOC(anim[a].num_frames*sizeof(Transform *));
|
||||||
// unused for now
|
//animations[a].framerate = anim.framerate; // TODO: Use framerate?
|
||||||
//animations[a].framerate = anim.framerate;
|
|
||||||
|
|
||||||
for (int j = 0; j < iqm.num_poses; j++)
|
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;
|
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;
|
int dcounter = anim[a].first_frame*iqm.num_framechannels;
|
||||||
|
|
||||||
|
|
@ -1083,7 +1079,6 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
|
||||||
|
|
||||||
fclose(iqmFile);
|
fclose(iqmFile);
|
||||||
|
|
||||||
|
|
||||||
return animations;
|
return animations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1091,61 +1086,64 @@ ModelAnimation *LoadModelAnimations(const char *filename, int *animCount)
|
||||||
// NOTE: Updated data is uploaded to GPU
|
// NOTE: Updated data is uploaded to GPU
|
||||||
void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
void UpdateModelAnimation(Model model, ModelAnimation anim, int frame)
|
||||||
{
|
{
|
||||||
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
|
if ((anim.frameCount > 0) && (anim.bones != NULL) && (anim.framePoses != NULL))
|
||||||
|
|
||||||
for (int m = 0; m < model.meshCount; m++)
|
|
||||||
{
|
{
|
||||||
Vector3 animVertex = { 0 };
|
if (frame >= anim.frameCount) frame = frame%anim.frameCount;
|
||||||
Vector3 animNormal = { 0 };
|
|
||||||
|
|
||||||
Vector3 inTranslation = { 0 };
|
for (int m = 0; m < model.meshCount; m++)
|
||||||
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++)
|
|
||||||
{
|
{
|
||||||
boneId = model.meshes[m].boneIds[boneCounter];
|
Vector3 animVertex = { 0 };
|
||||||
inTranslation = model.bindPose[boneId].translation;
|
Vector3 animNormal = { 0 };
|
||||||
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
|
Vector3 inTranslation = { 0 };
|
||||||
// NOTE: We use meshes.vertices (default vertex position) to calculate meshes.animVertices (animated vertex position)
|
Quaternion inRotation = { 0 };
|
||||||
animVertex = (Vector3){ model.meshes[m].vertices[vCounter], model.meshes[m].vertices[vCounter + 1], model.meshes[m].vertices[vCounter + 2] };
|
Vector3 inScale = { 0 };
|
||||||
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
|
Vector3 outTranslation = { 0 };
|
||||||
// NOTE: We use meshes.baseNormals (default normal) to calculate meshes.normals (animated normals)
|
Quaternion outRotation = { 0 };
|
||||||
animNormal = (Vector3){ model.meshes[m].normals[vCounter], model.meshes[m].normals[vCounter + 1], model.meshes[m].normals[vCounter + 2] };
|
Vector3 outScale = { 0 };
|
||||||
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;
|
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 GenMeshPoly(int sides, float radius)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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;
|
int vertexCount = sides*3;
|
||||||
|
|
||||||
// Vertices definition
|
// Vertices definition
|
||||||
|
|
@ -1244,7 +1242,7 @@ Mesh GenMeshPoly(int sides, float radius)
|
||||||
Mesh GenMeshPlane(float width, float length, int resX, int resZ)
|
Mesh GenMeshPlane(float width, float length, int resX, int resZ)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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
|
#define CUSTOM_MESH_GEN_PLANE
|
||||||
#if defined(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.vertices = (float *)RL_MALLOC(plane->ntriangles*3*3*sizeof(float));
|
||||||
mesh.texcoords = (float *)RL_MALLOC(plane->ntriangles*3*2*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.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.vertexCount = plane->ntriangles*3;
|
||||||
mesh.triangleCount = plane->ntriangles;
|
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 GenMeshCube(float width, float height, float length)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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
|
#define CUSTOM_MESH_GEN_CUBE
|
||||||
#if defined(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)
|
RLAPI Mesh GenMeshSphere(float radius, int rings, int slices)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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_mesh *sphere = par_shapes_create_parametric_sphere(slices, rings);
|
||||||
par_shapes_scale(sphere, radius, radius, radius);
|
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)
|
RLAPI Mesh GenMeshHemiSphere(float radius, int rings, int slices)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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_mesh *sphere = par_shapes_create_hemisphere(slices, rings);
|
||||||
par_shapes_scale(sphere, radius, radius, radius);
|
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 GenMeshCylinder(float radius, float height, int slices)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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
|
// 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
|
// 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 GenMeshTorus(float radius, float size, int radSeg, int sides)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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;
|
if (radius > 1.0f) radius = 1.0f;
|
||||||
else if (radius < 0.1f) radius = 0.1f;
|
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 GenMeshKnot(float radius, float size, int radSeg, int sides)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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;
|
if (radius > 3.0f) radius = 3.0f;
|
||||||
else if (radius < 0.5f) radius = 0.5f;
|
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)
|
#define GRAY_VALUE(c) ((c.r+c.g+c.b)/3)
|
||||||
|
|
||||||
Mesh mesh = { 0 };
|
Mesh mesh = { 0 };
|
||||||
|
mesh.vboId = (unsigned int *)RL_CALLOC(MAX_MESH_VBO, sizeof(unsigned int));
|
||||||
|
|
||||||
int mapX = heightmap.width;
|
int mapX = heightmap.width;
|
||||||
int mapZ = heightmap.height;
|
int mapZ = heightmap.height;
|
||||||
|
|
@ -1877,7 +1876,7 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
|
||||||
Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
|
Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize)
|
||||||
{
|
{
|
||||||
Mesh mesh = { 0 };
|
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);
|
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
|
// TODO: Support multiple meshes... in the meantime, only one mesh is returned
|
||||||
//model.meshCount = meshCount;
|
//model.meshCount = meshCount;
|
||||||
model.meshCount = 1;
|
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
|
// Init model materials array
|
||||||
model.materialCount = materialCount;
|
if (materialCount > 0)
|
||||||
model.materials = (Material *)RL_MALLOC(model.materialCount*sizeof(Material));
|
{
|
||||||
|
model.materialCount = materialCount;
|
||||||
|
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||||
|
}
|
||||||
|
|
||||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -2815,10 +2818,10 @@ static Model LoadOBJ(const char *fileName)
|
||||||
memset(&mesh, 0, sizeof(Mesh));
|
memset(&mesh, 0, sizeof(Mesh));
|
||||||
mesh.vertexCount = attrib.num_faces*3;
|
mesh.vertexCount = attrib.num_faces*3;
|
||||||
mesh.triangleCount = attrib.num_faces;
|
mesh.triangleCount = attrib.num_faces;
|
||||||
mesh.vertices = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
|
mesh.vertices = (float *)RL_CALLOC(mesh.vertexCount*3, sizeof(float));
|
||||||
mesh.texcoords = (float *)RL_MALLOC(mesh.vertexCount*2*sizeof(float));
|
mesh.texcoords = (float *)RL_CALLOC(mesh.vertexCount*2, sizeof(float));
|
||||||
mesh.normals = (float *)RL_MALLOC(mesh.vertexCount*3*sizeof(float));
|
mesh.normals = (float *)RL_CALLOC(mesh.vertexCount*3, sizeof(float));
|
||||||
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 vCount = 0;
|
int vCount = 0;
|
||||||
int vtCount = 0;
|
int vtCount = 0;
|
||||||
|
|
@ -3065,36 +3068,36 @@ static Model LoadIQM(const char *fileName)
|
||||||
model.meshCount = iqm.num_meshes;
|
model.meshCount = iqm.num_meshes;
|
||||||
model.meshes = RL_CALLOC(model.meshCount, sizeof(Mesh));
|
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++)
|
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...
|
fread(name, sizeof(char)*MESH_NAME_LENGTH, 1, iqmFile); // Mesh name not used...
|
||||||
model.meshes[i].vertexCount = imesh[i].num_vertexes;
|
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].vertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex positions
|
||||||
model.meshes[i].normals = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*3); // Default vertex normals
|
model.meshes[i].normals = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float)); // Default vertex normals
|
||||||
model.meshes[i].texcoords = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*2); // Default vertex texcoords
|
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].boneIds = RL_CALLOC(model.meshes[i].vertexCount*4, sizeof(float)); // 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].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].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
|
// Animated verted data, what we actually process for rendering
|
||||||
// NOTE: Animated vertex should be re-uploaded to GPU (if not using GPU skinning)
|
// 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].animVertices = RL_CALLOC(model.meshes[i].vertexCount*3, sizeof(float));
|
||||||
model.meshes[i].animNormals = RL_MALLOC(sizeof(float)*model.meshes[i].vertexCount*3);
|
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
|
// 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);
|
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++)
|
for (int m = 0; m < model.meshCount; m++)
|
||||||
{
|
{
|
||||||
|
|
@ -3111,9 +3114,9 @@ static Model LoadIQM(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vertex arrays data processing
|
// 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);
|
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++)
|
for (int i = 0; i < iqm.num_vertexarrays; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -3121,9 +3124,9 @@ static Model LoadIQM(const char *fileName)
|
||||||
{
|
{
|
||||||
case IQM_POSITION:
|
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);
|
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++)
|
for (int m = 0; m < iqm.num_meshes; m++)
|
||||||
{
|
{
|
||||||
|
|
@ -3138,9 +3141,9 @@ static Model LoadIQM(const char *fileName)
|
||||||
} break;
|
} break;
|
||||||
case IQM_NORMAL:
|
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);
|
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++)
|
for (int m = 0; m < iqm.num_meshes; m++)
|
||||||
{
|
{
|
||||||
|
|
@ -3155,9 +3158,9 @@ static Model LoadIQM(const char *fileName)
|
||||||
} break;
|
} break;
|
||||||
case IQM_TEXCOORD:
|
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);
|
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++)
|
for (int m = 0; m < iqm.num_meshes; m++)
|
||||||
{
|
{
|
||||||
|
|
@ -3171,9 +3174,9 @@ static Model LoadIQM(const char *fileName)
|
||||||
} break;
|
} break;
|
||||||
case IQM_BLENDINDEXES:
|
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);
|
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++)
|
for (int m = 0; m < iqm.num_meshes; m++)
|
||||||
{
|
{
|
||||||
|
|
@ -3187,9 +3190,9 @@ static Model LoadIQM(const char *fileName)
|
||||||
} break;
|
} break;
|
||||||
case IQM_BLENDWEIGHTS:
|
case IQM_BLENDWEIGHTS:
|
||||||
{
|
{
|
||||||
blendw = RL_MALLOC(sizeof(unsigned char)*iqm.num_vertexes*4);
|
blendw = RL_MALLOC(iqm.num_vertexes*4*sizeof(unsigned char));
|
||||||
fseek(iqmFile,va[i].offset,SEEK_SET);
|
fseek(iqmFile, va[i].offset, SEEK_SET);
|
||||||
fread(blendw,sizeof(unsigned char)*iqm.num_vertexes*4,1,iqmFile);
|
fread(blendw, iqm.num_vertexes*4*sizeof(unsigned char), 1, iqmFile);
|
||||||
|
|
||||||
for (int m = 0; m < iqm.num_meshes; m++)
|
for (int m = 0; m < iqm.num_meshes; m++)
|
||||||
{
|
{
|
||||||
|
|
@ -3205,20 +3208,20 @@ static Model LoadIQM(const char *fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bones (joints) data processing
|
// 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);
|
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.boneCount = iqm.num_joints;
|
||||||
model.bones = RL_MALLOC(sizeof(BoneInfo)*iqm.num_joints);
|
model.bones = RL_MALLOC(iqm.num_joints*sizeof(BoneInfo));
|
||||||
model.bindPose = RL_MALLOC(sizeof(Transform)*iqm.num_joints);
|
model.bindPose = RL_MALLOC(iqm.num_joints*sizeof(Transform));
|
||||||
|
|
||||||
for (int i = 0; i < iqm.num_joints; i++)
|
for (int i = 0; i < iqm.num_joints; i++)
|
||||||
{
|
{
|
||||||
// Bones
|
// Bones
|
||||||
model.bones[i].parent = ijoint[i].parent;
|
model.bones[i].parent = ijoint[i].parent;
|
||||||
fseek(iqmFile, iqm.ofs_text + ijoint[i].name, SEEK_SET);
|
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)
|
// Bind pose (base pose)
|
||||||
model.bindPose[i].translation.x = ijoint[i].translate[0];
|
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.materials = RL_MALLOC(model.materialCount*sizeof(Material));
|
||||||
model.meshMaterial = RL_MALLOC(model.meshCount*sizeof(int));
|
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++)
|
for (int i = 0; i < model.materialCount - 1; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -3418,7 +3421,7 @@ static Model LoadGLTF(const char *fileName)
|
||||||
Texture2D texture = { 0 };
|
Texture2D texture = { 0 };
|
||||||
const char *texPath = GetDirectoryPath(fileName);
|
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.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);
|
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
|
else
|
||||||
{
|
{
|
||||||
tint.r = 1.f;
|
tint.r = 1.0f;
|
||||||
tint.g = 1.f;
|
tint.g = 1.0f;
|
||||||
tint.b = 1.f;
|
tint.b = 1.0f;
|
||||||
tint.a = 1.f;
|
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;
|
cgltf_image *img = data->materials[i].pbr_metallic_roughness.base_color_texture.texture->image;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,7 @@ void SetMasterVolume(float volume)
|
||||||
// Create a new audio buffer. Initially filled with silence
|
// 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 *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);
|
audioBuffer->buffer = RL_CALLOC((bufferSizeInFrames*channels*ma_get_bytes_per_sample(format)), 1);
|
||||||
|
|
||||||
if (audioBuffer == NULL)
|
if (audioBuffer == NULL)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
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 UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data
|
||||||
void CloseAudioStream(AudioStream stream); // Close audio stream and free memory
|
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 PlayAudioStream(AudioStream stream); // Play audio stream
|
||||||
void PauseAudioStream(AudioStream stream); // Pause audio stream
|
void PauseAudioStream(AudioStream stream); // Pause audio stream
|
||||||
void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
void ResumeAudioStream(AudioStream stream); // Resume audio stream
|
||||||
|
|
|
||||||
13
src/raylib.h
13
src/raylib.h
|
|
@ -460,7 +460,7 @@ typedef struct VrDeviceInfo {
|
||||||
// System config flags
|
// System config flags
|
||||||
// NOTE: Used for bit masks
|
// NOTE: Used for bit masks
|
||||||
typedef enum {
|
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_FULLSCREEN_MODE = 2, // Set to run program in fullscreen
|
||||||
FLAG_WINDOW_RESIZABLE = 4, // Set to allow resizable window
|
FLAG_WINDOW_RESIZABLE = 4, // Set to allow resizable window
|
||||||
FLAG_WINDOW_UNDECORATED = 8, // Set to disable window decoration (frame and buttons)
|
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 EndMode3D(void); // Ends 3D mode and returns to default 2D orthographic mode
|
||||||
RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
|
RLAPI void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
|
||||||
RLAPI void EndTextureMode(void); // Ends drawing to render texture
|
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
|
// Screen-space-related functions
|
||||||
RLAPI Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
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 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
|
// Timing-related functions
|
||||||
RLAPI void SetTargetFPS(int fps); // Set target FPS (maximum)
|
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 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 *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 *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 *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 *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)
|
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 EndShaderMode(void); // End custom shader drawing (use default shader)
|
||||||
RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied)
|
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 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
|
// VR control functions
|
||||||
RLAPI void InitVrSimulator(void); // Init VR simulator for selected device parameters
|
RLAPI void InitVrSimulator(void); // Init VR simulator for selected device parameters
|
||||||
|
|
|
||||||
82
src/rlgl.h
82
src/rlgl.h
|
|
@ -457,6 +457,9 @@ RLAPI void rlEnableDepthTest(void); // Enable depth te
|
||||||
RLAPI void rlDisableDepthTest(void); // Disable depth test
|
RLAPI void rlDisableDepthTest(void); // Disable depth test
|
||||||
RLAPI void rlEnableBackfaceCulling(void); // Enable backface culling
|
RLAPI void rlEnableBackfaceCulling(void); // Enable backface culling
|
||||||
RLAPI void rlDisableBackfaceCulling(void); // Disable 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 rlEnableWireMode(void); // Enable wire mode
|
||||||
RLAPI void rlDisableWireMode(void); // Disable wire mode
|
RLAPI void rlDisableWireMode(void); // Disable wire mode
|
||||||
RLAPI void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
|
RLAPI void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
|
||||||
|
|
@ -1344,28 +1347,25 @@ void rlDisableRenderTexture(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable depth test
|
// Enable depth test
|
||||||
void rlEnableDepthTest(void)
|
void rlEnableDepthTest(void) { glEnable(GL_DEPTH_TEST); }
|
||||||
{
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable depth test
|
// Disable depth test
|
||||||
void rlDisableDepthTest(void)
|
void rlDisableDepthTest(void) { glDisable(GL_DEPTH_TEST); }
|
||||||
{
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable backface culling
|
// Enable backface culling
|
||||||
void rlEnableBackfaceCulling(void)
|
void rlEnableBackfaceCulling(void) { glEnable(GL_CULL_FACE); }
|
||||||
{
|
|
||||||
glEnable(GL_CULL_FACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable backface culling
|
// Disable backface culling
|
||||||
void rlDisableBackfaceCulling(void)
|
void rlDisableBackfaceCulling(void) { glDisable(GL_CULL_FACE); }
|
||||||
{
|
|
||||||
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
|
// Enable wire mode
|
||||||
void rlEnableWireMode(void)
|
void rlEnableWireMode(void)
|
||||||
|
|
@ -1529,24 +1529,33 @@ void rlglInit(int width, int height)
|
||||||
const char **extList = RL_MALLOC(sizeof(const char *)*numExt);
|
const char **extList = RL_MALLOC(sizeof(const char *)*numExt);
|
||||||
|
|
||||||
// Get extensions strings
|
// 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)
|
#elif defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// Allocate 512 strings pointers (2 KB)
|
// Allocate 512 strings pointers (2 KB)
|
||||||
const char **extList = RL_MALLOC(sizeof(const char *)*512);
|
const char **extList = RL_MALLOC(sizeof(const char *)*512);
|
||||||
|
|
||||||
// Get extensions strings
|
const char *extensions = (const char *)glGetString(GL_EXTENSIONS); // One big const string
|
||||||
char *extensions = (char *)glGetString(GL_EXTENSIONS); // One big static const string returned
|
|
||||||
int len = strlen(extensions);
|
// 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);
|
||||||
|
|
||||||
|
extList[numExt] = extensionsDup;
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
if (i == ' ')
|
if (extensionsDup[i] == ' ')
|
||||||
{
|
{
|
||||||
extList[numExt] = &extensions[i + 1];
|
extensionsDup[i] = '\0';
|
||||||
|
|
||||||
numExt++;
|
numExt++;
|
||||||
|
extList[numExt] = &extensionsDup[i + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Duplicated string (extensionsDup) must be deallocated
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TraceLog(LOG_INFO, "Number of supported extensions: %i", numExt);
|
TraceLog(LOG_INFO, "Number of supported extensions: %i", numExt);
|
||||||
|
|
@ -1622,6 +1631,8 @@ void rlglInit(int width, int height)
|
||||||
RL_FREE(extList);
|
RL_FREE(extList);
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#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");
|
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");
|
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
|
// Initialize OpenGL default states
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
// Init state: Depth test
|
// Init state: Depth test
|
||||||
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
|
glDepthFunc(GL_LEQUAL); // Type of depth testing to apply
|
||||||
glDisable(GL_DEPTH_TEST); // Disable depth testing for 2D (only used for 3D)
|
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 LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
{
|
{
|
||||||
Shader shader = { 0 };
|
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 *vShaderStr = NULL;
|
||||||
char *fShaderStr = NULL;
|
char *fShaderStr = NULL;
|
||||||
|
|
@ -2978,7 +2988,7 @@ Shader LoadShader(const char *vsFileName, const char *fsFileName)
|
||||||
Shader LoadShaderCode(char *vsCode, char *fsCode)
|
Shader LoadShaderCode(char *vsCode, char *fsCode)
|
||||||
{
|
{
|
||||||
Shader shader = { 0 };
|
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)
|
// NOTE: All locations must be reseted to -1 (no location)
|
||||||
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
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);
|
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 namelen = -1;
|
||||||
int num = -1;
|
int num = -1;
|
||||||
|
|
@ -3513,24 +3523,6 @@ void EndBlendMode(void)
|
||||||
BeginBlendMode(BLEND_ALPHA);
|
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)
|
#if defined(SUPPORT_VR_SIMULATOR)
|
||||||
// Init VR simulator for selected device parameters
|
// Init VR simulator for selected device parameters
|
||||||
// NOTE: It modifies the global variable: stereoFbo
|
// 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)
|
static Shader LoadShaderDefault(void)
|
||||||
{
|
{
|
||||||
Shader shader = { 0 };
|
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)
|
// NOTE: All locations must be reseted to -1 (no location)
|
||||||
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
for (int i = 0; i < MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||||
|
|
|
||||||
|
|
@ -1392,8 +1392,8 @@ bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
|
||||||
{
|
{
|
||||||
bool collision = false;
|
bool collision = false;
|
||||||
|
|
||||||
if ((rec1.x <= (rec2.x + rec2.width) && (rec1.x + rec1.width) >= rec2.x) &&
|
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;
|
(rec1.y < (rec2.y + rec2.height) && (rec1.y + rec1.height) > rec2.y)) collision = true;
|
||||||
|
|
||||||
return collision;
|
return collision;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/text.c
31
src/text.c
|
|
@ -586,7 +586,7 @@ Image GenImageFontAtlas(const CharInfo *chars, Rectangle **charRecs, int charsCo
|
||||||
*charRecs = NULL;
|
*charRecs = NULL;
|
||||||
|
|
||||||
// In case no chars count provided we suppose default of 95
|
// 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!
|
// NOTE: Rectangles memory is loaded here!
|
||||||
Rectangle *recs = (Rectangle *)RL_MALLOC(charsCount*sizeof(Rectangle));
|
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
|
// so image size would result bigger than default font type
|
||||||
float requiredArea = 0;
|
float requiredArea = 0;
|
||||||
for (int i = 0; i < charsCount; i++) requiredArea += ((chars[i].image.width + 2*padding)*(chars[i].image.height + 2*padding));
|
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
|
int imageSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT
|
||||||
|
|
||||||
atlas.width = imageSize; // Atlas bitmap width
|
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);
|
memset(buffer, 0, MAX_TEXT_BUFFER_LENGTH);
|
||||||
|
|
||||||
result[0] = buffer;
|
result[0] = buffer;
|
||||||
int counter = 1;
|
int counter = 0;
|
||||||
|
|
||||||
// Count how many substrings we have on text and point to every one
|
if (text != NULL)
|
||||||
for (int i = 0; i < MAX_TEXT_BUFFER_LENGTH; i++)
|
|
||||||
{
|
{
|
||||||
buffer[i] = text[i];
|
counter = 1;
|
||||||
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;
|
// 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] = 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user