Big batch of changes, check description:
- Camera system moved to a separate module [camera.c] - WIP: Added customization functions for camera controls - Added custom shaders support on batch drawing - Complete redesign of textures module to support multiple texture formats (compressed and uncompressed)
This commit is contained in:
parent
ba257b09f5
commit
eae98e1c34
86
examples/models_custom_shader.c
Normal file
86
examples/models_custom_shader.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*******************************************************************************************
|
||||
*
|
||||
* raylib [models] example - Load and draw a 3d model (OBJ)
|
||||
*
|
||||
* This example has been created using raylib 1.0 (www.raylib.com)
|
||||
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
|
||||
*
|
||||
* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.com)
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
int screenWidth = 1280;
|
||||
int screenHeight = 720;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [models] example - custom shader");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
Camera camera = {{ 10.0, 8.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }};
|
||||
|
||||
Texture2D texture = LoadTexture("resources/catsham.png"); // Load model texture
|
||||
Shader shader = LoadShader("resources/shaders/custom.vs", "resources/shaders/custom.fs");
|
||||
//Shader poste = LoadShader("resources/shaders/custom.vs", "resources/shaders/pixel.fs");
|
||||
|
||||
Model cat = LoadModel("resources/cat.obj"); // Load OBJ model
|
||||
|
||||
SetModelTexture(&cat, texture); // Bind texture to model
|
||||
//SetModelShader(&cat, poste);
|
||||
|
||||
Vector3 catPosition = { 0.0, 0.0, 0.0 }; // Set model position
|
||||
|
||||
SetPostproShader(shader);
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyDown(KEY_LEFT)) catPosition.x -= 0.2;
|
||||
if (IsKeyDown(KEY_RIGHT)) catPosition.x += 0.2;
|
||||
if (IsKeyDown(KEY_UP)) catPosition.z -= 0.2;
|
||||
if (IsKeyDown(KEY_DOWN)) catPosition.z += 0.2;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
Begin3dMode(camera);
|
||||
|
||||
DrawModel(cat, catPosition, 0.1f, WHITE); // Draw 3d model with texture
|
||||
|
||||
DrawGrid(10.0, 1.0); // Draw a grid
|
||||
|
||||
DrawGizmo(catPosition); // Draw gizmo
|
||||
|
||||
End3dMode();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadModel(cat); // Unload model
|
||||
UnloadShader(shader);
|
||||
//UnloadShader(poste);
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
return 0;
|
||||
}
|
19
examples/resources/shaders/base.vs
Normal file
19
examples/resources/shaders/base.vs
Normal file
@ -0,0 +1,19 @@
|
||||
#version 110
|
||||
|
||||
attribute vec3 vertexPosition;
|
||||
attribute vec2 vertexTexCoord;
|
||||
attribute vec4 vertexColor;
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 modelviewMatrix;
|
||||
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragTexCoord = vertexTexCoord;
|
||||
fragColor = vertexColor;
|
||||
|
||||
gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0);
|
||||
}
|
16
examples/resources/shaders/custom.fs
Normal file
16
examples/resources/shaders/custom.fs
Normal file
@ -0,0 +1,16 @@
|
||||
#version 330
|
||||
|
||||
uniform sampler2D texture0;
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
uniform vec4 tintColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(texture0, fragTexCoord)*tintColor;
|
||||
|
||||
// Convert to grayscale using NTSC conversion weights
|
||||
float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114));
|
||||
|
||||
gl_FragColor = vec4(gray, gray, gray, tintColor.a);
|
||||
}
|
16
examples/resources/shaders/custom.vs
Normal file
16
examples/resources/shaders/custom.vs
Normal file
@ -0,0 +1,16 @@
|
||||
#version 330
|
||||
|
||||
attribute vec3 vertexPosition;
|
||||
attribute vec2 vertexTexCoord;
|
||||
attribute vec3 vertexNormal;
|
||||
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 modelviewMatrix;
|
||||
|
||||
varying vec2 fragTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
fragTexCoord = vertexTexCoord;
|
||||
gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0);
|
||||
}
|
15
examples/resources/shaders/grayscale.fs
Normal file
15
examples/resources/shaders/grayscale.fs
Normal file
@ -0,0 +1,15 @@
|
||||
#version 110
|
||||
|
||||
uniform sampler2D texture0;
|
||||
varying vec2 fragTexCoord;
|
||||
varying vec4 fragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(texture0, fragTexCoord)*fragColor;
|
||||
|
||||
// Convert to grayscale using NTSC conversion weights
|
||||
float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114));
|
||||
|
||||
gl_FragColor = vec4(gray, gray, gray, base.a);
|
||||
}
|
476
src/camera.c
Normal file
476
src/camera.c
Normal file
@ -0,0 +1,476 @@
|
||||
/**********************************************************************************************
|
||||
*
|
||||
* raylib.camera
|
||||
*
|
||||
* Camera Modes Setup and Control Functions
|
||||
*
|
||||
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||
* in the product documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
* as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
**********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include <math.h>
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
// CAMERA_GENERIC
|
||||
#define CAMERA_SCROLL_SENSITIVITY 1.5
|
||||
|
||||
// FREE_CAMERA
|
||||
#define FREE_CAMERA_MOUSE_SENSITIVITY 0.01
|
||||
#define FREE_CAMERA_DISTANCE_MIN_CLAMP 0.3
|
||||
#define FREE_CAMERA_DISTANCE_MAX_CLAMP 12
|
||||
#define FREE_CAMERA_MIN_CLAMP 85
|
||||
#define FREE_CAMERA_MAX_CLAMP -85
|
||||
#define FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY 0.05
|
||||
#define FREE_CAMERA_PANNING_DIVIDER 5.1
|
||||
|
||||
// ORBITAL_CAMERA
|
||||
#define ORBITAL_CAMERA_SPEED 0.01
|
||||
|
||||
// FIRST_PERSON
|
||||
//#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003
|
||||
#define FIRST_PERSON_FOCUS_DISTANCE 25
|
||||
#define FIRST_PERSON_MIN_CLAMP 85
|
||||
#define FIRST_PERSON_MAX_CLAMP -85
|
||||
|
||||
#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0
|
||||
#define FIRST_PERSON_STEP_DIVIDER 30.0
|
||||
#define FIRST_PERSON_WAVING_DIVIDER 200.0
|
||||
|
||||
#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85
|
||||
|
||||
// THIRD_PERSON
|
||||
//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003
|
||||
#define THIRD_PERSON_DISTANCE_CLAMP 1.2
|
||||
#define THIRD_PERSON_MIN_CLAMP 5
|
||||
#define THIRD_PERSON_MAX_CLAMP -85
|
||||
#define THIRD_PERSON_OFFSET (Vector3){ 0.4, 0, 0 }
|
||||
|
||||
// PLAYER (used by camera)
|
||||
#define PLAYER_WIDTH 0.4
|
||||
#define PLAYER_HEIGHT 0.9
|
||||
#define PLAYER_DEPTH 0.4
|
||||
#define PLAYER_MOVEMENT_DIVIDER 20.0
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
static Camera internalCamera = {{2,0,2},{0,0,0},{0,1,0}};
|
||||
static Vector2 cameraAngle = { 0, 0 };
|
||||
static float cameraTargetDistance = 5;
|
||||
static Vector3 resetingPosition = { 0, 0, 0 };
|
||||
static int resetingKey = 'Z';
|
||||
static Vector2 cameraMousePosition = { 0, 0 };
|
||||
static Vector2 cameraMouseVariation = { 0, 0 };
|
||||
static float mouseSensitivity = 0.003;
|
||||
static int cameraMovementController[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' };
|
||||
static int cameraMovementCounter = 0;
|
||||
static bool cameraUseGravity = true;
|
||||
static int pawnControllingKey = MOUSE_MIDDLE_BUTTON;
|
||||
static int fnControllingKey = KEY_LEFT_ALT;
|
||||
static int smoothZoomControllingKey = KEY_LEFT_CONTROL;
|
||||
|
||||
static int cameraMode = CAMERA_CUSTOM;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
//----------------------------------------------------------------------------------
|
||||
static void ProcessCamera(Camera *camera, Vector3 *playerPosition);
|
||||
/*
|
||||
static void SetCameraControls(int front, int left, int back, right, up, down);
|
||||
static void SetMouseSensitivity(int sensitivity);
|
||||
static void SetResetPosition(Vector3 resetPosition);
|
||||
static void SetResetControl(int resetKey);
|
||||
static void SetPawnControl(int pawnControlKey);
|
||||
static void SetFnControl(int fnControlKey);
|
||||
static void SetSmoothZoomControl(int smoothZoomControlKey);
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Select camera mode (multiple camera modes available)
|
||||
void SetCameraMode(int mode)
|
||||
{
|
||||
if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_FREE))
|
||||
{
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
cameraTargetDistance = 5;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
else if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_ORBITAL))
|
||||
{
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
cameraTargetDistance = 5;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_FREE))
|
||||
{
|
||||
cameraTargetDistance = 10;
|
||||
cameraAngle.x = 45 * DEG2RAD;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
internalCamera.target = (Vector3){ 0, 0, 0};
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL))
|
||||
{
|
||||
cameraTargetDistance = 10;
|
||||
cameraAngle.x = 225 * DEG2RAD;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
internalCamera.target = (Vector3){ 3, 0, 3};
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
|
||||
cameraMode = mode;
|
||||
}
|
||||
|
||||
// Update camera with position
|
||||
Camera UpdateCamera(Vector3 *position)
|
||||
{
|
||||
// Calculate camera
|
||||
if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, position);
|
||||
|
||||
return internalCamera;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Process desired camera mode and controls
|
||||
static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI)
|
||||
// Mouse movement detection
|
||||
if (cameraMode != CAMERA_FREE)
|
||||
{
|
||||
HideCursor();
|
||||
|
||||
if (GetMousePosition().x < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetScreenWidth() - GetScreenHeight() / 3, GetMousePosition().y});
|
||||
else if (GetMousePosition().y < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() - GetScreenHeight() / 3});
|
||||
else if (GetMousePosition().x > GetScreenWidth() - GetScreenHeight() / 3) SetMousePosition((Vector2) { GetScreenHeight() / 3, GetMousePosition().y});
|
||||
else if (GetMousePosition().y > GetScreenHeight() - GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() / 3});
|
||||
else
|
||||
{
|
||||
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
|
||||
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowCursor();
|
||||
|
||||
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
|
||||
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
|
||||
}
|
||||
|
||||
cameraMousePosition = GetMousePosition();
|
||||
|
||||
// Support for multiple automatic camera modes
|
||||
switch (cameraMode)
|
||||
{
|
||||
case CAMERA_FREE:
|
||||
{
|
||||
// Camera zoom
|
||||
if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
|
||||
{
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
|
||||
if (cameraTargetDistance > FREE_CAMERA_DISTANCE_MAX_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MAX_CLAMP;
|
||||
}
|
||||
// Camera looking down
|
||||
else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
}
|
||||
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
|
||||
if (camera->target.y < 0) camera->target.y = -0.001;
|
||||
}
|
||||
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (GetMouseWheelMove() > 0))
|
||||
{
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
|
||||
}
|
||||
// Camera looking up
|
||||
else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
}
|
||||
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
|
||||
if (camera->target.y > 0) camera->target.y = 0.001;
|
||||
}
|
||||
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (GetMouseWheelMove() > 0))
|
||||
{
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
|
||||
}
|
||||
|
||||
// Inputs
|
||||
if (IsKeyDown(fnControllingKey))
|
||||
{
|
||||
if (IsKeyDown(smoothZoomControllingKey))
|
||||
{
|
||||
// Camera smooth zoom
|
||||
if (IsMouseButtonDown(pawnControllingKey)) cameraTargetDistance += (cameraMouseVariation.y * FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
|
||||
}
|
||||
// Camera orientation calculation
|
||||
else if (IsMouseButtonDown(pawnControllingKey))
|
||||
{
|
||||
// Camera orientation calculation
|
||||
// Get the mouse sensitivity
|
||||
cameraAngle.x += cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY;
|
||||
cameraAngle.y += cameraMouseVariation.y * -FREE_CAMERA_MOUSE_SENSITIVITY;
|
||||
|
||||
// Angle clamp
|
||||
if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP * DEG2RAD;
|
||||
else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP * DEG2RAD;
|
||||
}
|
||||
}
|
||||
// Paning
|
||||
else if (IsMouseButtonDown(pawnControllingKey))
|
||||
{
|
||||
camera->target.x += ((cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
|
||||
camera->target.y += ((cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
|
||||
camera->target.z += ((cameraMouseVariation.x * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
|
||||
}
|
||||
|
||||
// Focus to center
|
||||
if (IsKeyDown(resetingKey)) camera->target = resetingPosition;
|
||||
|
||||
// Camera position update
|
||||
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
|
||||
|
||||
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
|
||||
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
|
||||
|
||||
} break;
|
||||
case CAMERA_ORBITAL:
|
||||
{
|
||||
cameraAngle.x += ORBITAL_CAMERA_SPEED;
|
||||
|
||||
// Camera zoom
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
// Camera distance clamp
|
||||
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
|
||||
|
||||
// Focus to center
|
||||
if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 };
|
||||
|
||||
// Camera position update
|
||||
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
|
||||
|
||||
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
|
||||
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
|
||||
|
||||
} break;
|
||||
case CAMERA_FIRST_PERSON:
|
||||
case CAMERA_THIRD_PERSON:
|
||||
{
|
||||
bool isMoving = false;
|
||||
|
||||
// Keyboard inputs
|
||||
if (IsKeyDown(cameraMovementController[0]))
|
||||
{
|
||||
playerPosition->x -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
else if (IsKeyDown(cameraMovementController[2]))
|
||||
{
|
||||
playerPosition->x += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
|
||||
if (IsKeyDown(cameraMovementController[1]))
|
||||
{
|
||||
playerPosition->x -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
else if (IsKeyDown(cameraMovementController[3]))
|
||||
{
|
||||
playerPosition->x += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
|
||||
if (IsKeyDown(cameraMovementController[4]))
|
||||
{
|
||||
if (!cameraUseGravity) playerPosition->y += 1 / PLAYER_MOVEMENT_DIVIDER;
|
||||
}
|
||||
else if (IsKeyDown(cameraMovementController[5]))
|
||||
{
|
||||
if (!cameraUseGravity) playerPosition->y -= 1 / PLAYER_MOVEMENT_DIVIDER;
|
||||
}
|
||||
|
||||
if (cameraMode == CAMERA_THIRD_PERSON)
|
||||
{
|
||||
// Camera orientation calculation
|
||||
// Get the mouse sensitivity
|
||||
cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
|
||||
cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
|
||||
|
||||
// Angle clamp
|
||||
if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP * DEG2RAD;
|
||||
else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP * DEG2RAD;
|
||||
|
||||
// Camera zoom
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
|
||||
// Camera distance clamp
|
||||
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
|
||||
|
||||
// Camera is always looking at player
|
||||
camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x * cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x);
|
||||
camera->target.y = playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
|
||||
camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x * sin(cameraAngle.x);
|
||||
|
||||
// Camera position update
|
||||
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
|
||||
|
||||
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
|
||||
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isMoving) cameraMovementCounter++;
|
||||
|
||||
// Camera orientation calculation
|
||||
// Get the mouse sensitivity
|
||||
cameraAngle.x += cameraMouseVariation.x * -mouseSensitivity;
|
||||
cameraAngle.y += cameraMouseVariation.y * -mouseSensitivity;
|
||||
|
||||
// Angle clamp
|
||||
if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP * DEG2RAD;
|
||||
else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP * DEG2RAD;
|
||||
|
||||
// Camera is always looking at player
|
||||
camera->target.x = camera->position.x - sin(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
|
||||
camera->target.y = camera->position.y + sin(cameraAngle.y) * FIRST_PERSON_FOCUS_DISTANCE;
|
||||
camera->target.z = camera->position.z - cos(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
|
||||
|
||||
camera->position.x = playerPosition->x;
|
||||
camera->position.y = (playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMovementCounter / FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER) / FIRST_PERSON_STEP_DIVIDER;
|
||||
camera->position.z = playerPosition->z;
|
||||
|
||||
camera->up.x = sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
|
||||
camera->up.z = -sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetCameraControls(int frontKey, int leftKey, int backKey, int rightKey, int upKey, int downKey)
|
||||
{
|
||||
cameraMovementController[0] = frontKey;
|
||||
cameraMovementController[1] = leftKey;
|
||||
cameraMovementController[2] = backKey;
|
||||
cameraMovementController[3] = rightKey;
|
||||
cameraMovementController[4] = upKey;
|
||||
cameraMovementController[5] = downKey;
|
||||
}
|
||||
|
||||
void SetMouseSensitivity(float sensitivity)
|
||||
{
|
||||
mouseSensitivity = (sensitivity / 10000.0);
|
||||
}
|
||||
|
||||
void SetResetPosition(Vector3 resetPosition)
|
||||
{
|
||||
resetingPosition = resetPosition;
|
||||
}
|
||||
|
||||
void SetResetControl(int resetKey)
|
||||
{
|
||||
resetingKey = resetKey;
|
||||
}
|
||||
|
||||
void SetPawnControl(int pawnControlKey)
|
||||
{
|
||||
pawnControllingKey = pawnControlKey;
|
||||
}
|
||||
|
||||
void SetFnControl(int fnControlKey)
|
||||
{
|
||||
fnControllingKey = fnControlKey;
|
||||
}
|
||||
|
||||
void SetSmoothZoomControl(int smoothZoomControlKey)
|
||||
{
|
||||
smoothZoomControllingKey = smoothZoomControlKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
406
src/core.c
406
src/core.c
@ -45,7 +45,7 @@
|
||||
#include <stdio.h> // Standard input / output lib
|
||||
#include <stdlib.h> // Declares malloc() and free() for memory management, rand(), atexit()
|
||||
#include <stdint.h> // Required for typedef unsigned long long int uint64_t, used by hi-res timer
|
||||
#include <time.h> // Useful to initialize random seed - Android/RPI hi-res timer
|
||||
#include <time.h> // Useful to initialize random seed - Android/RPI hi-res timer (NOTE: Linux only!)
|
||||
#include <math.h> // Math related functions, tan() used to set perspective
|
||||
#include <string.h> // String function definitions, memset()
|
||||
#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
|
||||
@ -99,48 +99,6 @@
|
||||
//----------------------------------------------------------------------------------
|
||||
#define MAX_TOUCH_POINTS 256
|
||||
|
||||
// Camera System configuration
|
||||
//----------------------------------------------------------------------------------
|
||||
// CAMERA_GENERIC
|
||||
#define CAMERA_SCROLL_SENSITIVITY 1.5
|
||||
|
||||
// FREE_CAMERA
|
||||
#define FREE_CAMERA_MOUSE_SENSITIVITY 0.01
|
||||
#define FREE_CAMERA_DISTANCE_MIN_CLAMP 0.3
|
||||
#define FREE_CAMERA_DISTANCE_MAX_CLAMP 12
|
||||
#define FREE_CAMERA_MIN_CLAMP 85
|
||||
#define FREE_CAMERA_MAX_CLAMP -85
|
||||
#define FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY 0.05
|
||||
#define FREE_CAMERA_PANNING_DIVIDER 5.1
|
||||
|
||||
// ORBITAL_CAMERA
|
||||
#define ORBITAL_CAMERA_SPEED 0.01
|
||||
|
||||
// FIRST_PERSON
|
||||
#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003
|
||||
#define FIRST_PERSON_FOCUS_DISTANCE 25
|
||||
#define FIRST_PERSON_MIN_CLAMP 85
|
||||
#define FIRST_PERSON_MAX_CLAMP -85
|
||||
|
||||
#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0
|
||||
#define FIRST_PERSON_STEP_DIVIDER 30.0
|
||||
#define FIRST_PERSON_WAVING_DIVIDER 200.0
|
||||
|
||||
#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85
|
||||
|
||||
// THIRD_PERSON
|
||||
#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003
|
||||
#define THIRD_PERSON_DISTANCE_CLAMP 1.2
|
||||
#define THIRD_PERSON_MIN_CLAMP 5
|
||||
#define THIRD_PERSON_MAX_CLAMP -85
|
||||
#define THIRD_PERSON_OFFSET (Vector3){ 0.4, 0, 0 }
|
||||
|
||||
// PLAYER (used by camera)
|
||||
#define PLAYER_WIDTH 0.4
|
||||
#define PLAYER_HEIGHT 0.9
|
||||
#define PLAYER_DEPTH 0.4
|
||||
#define PLAYER_MOVEMENT_DIVIDER 20.0
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Types and Structures Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -207,7 +165,6 @@ static bool cursorOnScreen = false; // Tracks if cursor is inside client
|
||||
static Texture2D cursor; // Cursor texture
|
||||
|
||||
static Vector2 mousePosition;
|
||||
static bool cursorHidden;
|
||||
|
||||
static char previousKeyState[512] = { 0 }; // Required to check if key pressed/released once
|
||||
static char currentKeyState[512] = { 0 }; // Required to check if key pressed/released once
|
||||
@ -225,6 +182,8 @@ static int exitKey = KEY_ESCAPE; // Default exit key (ESC)
|
||||
static int lastKeyPressed = -1;
|
||||
#endif
|
||||
|
||||
static bool cursorHidden;
|
||||
|
||||
static double currentTime, previousTime; // Used to track timmings
|
||||
static double updateTime, drawTime; // Time measures for update and draw
|
||||
static double frameTime; // Time measure for one frame
|
||||
@ -233,17 +192,6 @@ static double targetTime = 0.0; // Desired time for one frame, if 0
|
||||
static char configFlags = 0;
|
||||
static bool showLogo = false;
|
||||
|
||||
// Camera variables
|
||||
static int cameraMode = CAMERA_CUSTOM;
|
||||
static Camera currentCamera;
|
||||
static Camera internalCamera = {{2,0,2},{0,0,0},{0,1,0}};
|
||||
static Vector2 cameraAngle = { 0, 0 };
|
||||
static float cameraTargetDistance = 5;
|
||||
static Vector2 cameraMousePosition = { 0, 0 };
|
||||
static Vector2 cameraMouseVariation = { 0, 0 };
|
||||
static int cameraMovementCounter = 0;
|
||||
static bool cameraUseGravity = true;
|
||||
|
||||
// Shaders variables
|
||||
static bool enabledPostpro = false;
|
||||
|
||||
@ -306,8 +254,6 @@ static void TakeScreenshot(void);
|
||||
static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands
|
||||
#endif
|
||||
|
||||
static void ProcessCamera(Camera *camera, Vector3 *playerPosition);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Window and OpenGL Context Functions
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -600,10 +546,7 @@ void Begin3dMode(Camera camera)
|
||||
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
|
||||
|
||||
// Setup Camera view
|
||||
if (cameraMode == CAMERA_CUSTOM) currentCamera = camera;
|
||||
else currentCamera = internalCamera;
|
||||
|
||||
Matrix view = MatrixLookAt(currentCamera.position, currentCamera.target, currentCamera.up);
|
||||
Matrix view = MatrixLookAt(camera.position, camera.target, camera.up);
|
||||
rlMultMatrixf(GetMatrixVector(view)); // Multiply MODELVIEW matrix by view matrix (camera)
|
||||
}
|
||||
|
||||
@ -707,7 +650,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||
Ray ray;
|
||||
|
||||
Matrix proj = MatrixIdentity();
|
||||
Matrix view = MatrixLookAt(currentCamera.position, currentCamera.target, currentCamera.up);
|
||||
Matrix view = MatrixLookAt(camera.position, camera.target, camera.up);
|
||||
|
||||
float aspect = (GLfloat)GetScreenWidth()/(GLfloat)GetScreenHeight();
|
||||
double top = 0.1f*tanf(45.0f*PI / 360.0f);
|
||||
@ -725,7 +668,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||
Vector3 nearPoint = { mousePosition.x, realy, 0.0f };
|
||||
Vector3 farPoint = { mousePosition.x, realy, 1.0f };
|
||||
|
||||
nearPoint = internalCamera.position;
|
||||
//nearPoint = internalCamera.position;
|
||||
farPoint = rlglUnproject(farPoint, proj, view);
|
||||
|
||||
Vector3 direction = VectorSubtract(farPoint, nearPoint);
|
||||
@ -734,72 +677,9 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||
ray.position = nearPoint;
|
||||
ray.direction = direction;
|
||||
|
||||
// Test
|
||||
Vector2 screenPos;
|
||||
screenPos.x = (mousePosition.x / (float)GetScreenWidth() * 2.0) - 1.0f;
|
||||
screenPos.y = (mousePosition.y / (float)GetScreenHeight() * 2.0) - 1.0f;
|
||||
|
||||
direction = VectorSubtract(internalCamera.target, internalCamera.position);
|
||||
|
||||
printf("/nScreenPos %f, %f", screenPos.x, screenPos.y);
|
||||
|
||||
Matrix rotate;
|
||||
rotate = MatrixIdentity();
|
||||
rotate = MatrixRotate(0, 45*DEG2RAD*screenPos.y, 0);
|
||||
VectorTransform(&direction, rotate);
|
||||
|
||||
VectorNormalize(&direction);
|
||||
|
||||
ray.position = internalCamera.position;
|
||||
ray.direction = direction;
|
||||
|
||||
return ray;
|
||||
}
|
||||
|
||||
void SetCameraMode(int mode)
|
||||
{
|
||||
if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_FREE))
|
||||
{
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
cameraTargetDistance = 5;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
else if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_ORBITAL))
|
||||
{
|
||||
cameraMode = CAMERA_THIRD_PERSON;
|
||||
cameraTargetDistance = 5;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_FREE))
|
||||
{
|
||||
cameraTargetDistance = 10;
|
||||
cameraAngle.x = 45 * DEG2RAD;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
internalCamera.target = (Vector3){ 0, 0, 0};
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL))
|
||||
{
|
||||
cameraTargetDistance = 10;
|
||||
cameraAngle.x = 225 * DEG2RAD;
|
||||
cameraAngle.y = -40 * DEG2RAD;
|
||||
internalCamera.target = (Vector3){ 3, 0, 3};
|
||||
ProcessCamera(&internalCamera, &internalCamera.position);
|
||||
}
|
||||
|
||||
cameraMode = mode;
|
||||
}
|
||||
|
||||
Camera UpdateCamera(Vector3 *position)
|
||||
{
|
||||
// Calculate camera
|
||||
if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, position);
|
||||
|
||||
return internalCamera;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -915,8 +795,8 @@ int GetMouseWheelMove(void)
|
||||
{
|
||||
return previousMouseWheelY;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Hide mouse cursor
|
||||
void HideCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
@ -936,6 +816,7 @@ void HideCursor()
|
||||
cursorHidden = true;
|
||||
}
|
||||
|
||||
// Show mouse cursor
|
||||
void ShowCursor()
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP)
|
||||
@ -948,10 +829,12 @@ void ShowCursor()
|
||||
cursorHidden = false;
|
||||
}
|
||||
|
||||
// Check if mouse cursor is hidden
|
||||
bool IsCursorHidden()
|
||||
{
|
||||
return cursorHidden;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Enable gamepad usage on Rapsberry Pi
|
||||
// NOTE: emscripten not implemented
|
||||
@ -1105,6 +988,18 @@ void SetPostproShader(Shader shader)
|
||||
}
|
||||
}
|
||||
|
||||
// Set custom shader to be used in batch draw
|
||||
void SetCustomShader(Shader shader)
|
||||
{
|
||||
rlglSetCustomShader(shader);
|
||||
}
|
||||
|
||||
// Set default shader to be used in batch draw
|
||||
void SetDefaultShader(void)
|
||||
{
|
||||
rlglSetDefaultShader();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
@ -2161,260 +2056,3 @@ static void LogoAnimation(void)
|
||||
|
||||
showLogo = false; // Prevent for repeating when reloading window (Android)
|
||||
}
|
||||
|
||||
// Process desired camera mode and controls
|
||||
static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
|
||||
{
|
||||
#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) || defined(PLATFORM_RPI)
|
||||
// Mouse movement detection
|
||||
if (cameraMode != CAMERA_FREE)
|
||||
{
|
||||
HideCursor();
|
||||
if (GetMousePosition().x < GetScreenHeight() / 3) SetMousePosition((Vector2){ screenWidth - GetScreenHeight() / 3, GetMousePosition().y});
|
||||
else if (GetMousePosition().y < GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, screenHeight - GetScreenHeight() / 3});
|
||||
else if (GetMousePosition().x > screenWidth - GetScreenHeight() / 3) SetMousePosition((Vector2) { GetScreenHeight() / 3, GetMousePosition().y});
|
||||
else if (GetMousePosition().y > screenHeight - GetScreenHeight() / 3) SetMousePosition((Vector2){ GetMousePosition().x, GetScreenHeight() / 3});
|
||||
else
|
||||
{
|
||||
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
|
||||
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowCursor();
|
||||
cameraMouseVariation.x = GetMousePosition().x - cameraMousePosition.x;
|
||||
cameraMouseVariation.y = GetMousePosition().y - cameraMousePosition.y;
|
||||
}
|
||||
|
||||
cameraMousePosition = GetMousePosition();
|
||||
|
||||
// Support for multiple automatic camera modes
|
||||
switch (cameraMode)
|
||||
{
|
||||
case CAMERA_FREE:
|
||||
{
|
||||
// Pass to orbiting camera
|
||||
if (IsKeyPressed('O')) cameraMode = CAMERA_ORBITAL;
|
||||
|
||||
// Camera zoom
|
||||
if ((cameraTargetDistance < FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
|
||||
{
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
|
||||
if (cameraTargetDistance > FREE_CAMERA_DISTANCE_MAX_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MAX_CLAMP;
|
||||
}
|
||||
// Camera looking down
|
||||
else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
}
|
||||
else if ((camera->position.y > camera->target.y) && (camera->target.y >= 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
|
||||
if (camera->target.y < 0) camera->target.y = -0.001;
|
||||
}
|
||||
else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (GetMouseWheelMove() > 0))
|
||||
{
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
|
||||
}
|
||||
// Camera looking up
|
||||
else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == FREE_CAMERA_DISTANCE_MAX_CLAMP) && (GetMouseWheelMove() < 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
}
|
||||
else if ((camera->position.y < camera->target.y) && (camera->target.y <= 0))
|
||||
{
|
||||
camera->target.x += GetMouseWheelMove() * (camera->target.x - camera->position.x) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.y += GetMouseWheelMove() * (camera->target.y - camera->position.y) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
camera->target.z += GetMouseWheelMove() * (camera->target.z - camera->position.z) * CAMERA_SCROLL_SENSITIVITY / cameraTargetDistance;
|
||||
|
||||
if (camera->target.y > 0) camera->target.y = 0.001;
|
||||
}
|
||||
else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (GetMouseWheelMove() > 0))
|
||||
{
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
if (cameraTargetDistance < FREE_CAMERA_DISTANCE_MIN_CLAMP) cameraTargetDistance = FREE_CAMERA_DISTANCE_MIN_CLAMP;
|
||||
}
|
||||
|
||||
|
||||
// Inputs
|
||||
if (IsKeyDown(KEY_LEFT_ALT))
|
||||
{
|
||||
if (IsKeyDown(KEY_LEFT_CONTROL))
|
||||
{
|
||||
// Camera smooth zoom
|
||||
if (IsMouseButtonDown(MOUSE_MIDDLE_BUTTON)) cameraTargetDistance += (cameraMouseVariation.y * FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY);
|
||||
}
|
||||
// Camera orientation calculation
|
||||
else if (IsMouseButtonDown(MOUSE_MIDDLE_BUTTON))
|
||||
{
|
||||
// Camera orientation calculation
|
||||
// Get the mouse sensitivity
|
||||
cameraAngle.x += cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY;
|
||||
cameraAngle.y += cameraMouseVariation.y * -FREE_CAMERA_MOUSE_SENSITIVITY;
|
||||
|
||||
// Angle clamp
|
||||
if (cameraAngle.y > FREE_CAMERA_MIN_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MIN_CLAMP * DEG2RAD;
|
||||
else if (cameraAngle.y < FREE_CAMERA_MAX_CLAMP * DEG2RAD) cameraAngle.y = FREE_CAMERA_MAX_CLAMP * DEG2RAD;
|
||||
}
|
||||
}
|
||||
// Paning
|
||||
else if (IsMouseButtonDown(MOUSE_MIDDLE_BUTTON))
|
||||
{
|
||||
camera->target.x += ((cameraMouseVariation.x * -FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
|
||||
camera->target.y += ((cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
|
||||
camera->target.z += ((cameraMouseVariation.x * FREE_CAMERA_MOUSE_SENSITIVITY) * sin(cameraAngle.x) + (cameraMouseVariation.y * FREE_CAMERA_MOUSE_SENSITIVITY) * cos(cameraAngle.x) * sin(cameraAngle.y)) * (cameraTargetDistance / FREE_CAMERA_PANNING_DIVIDER);
|
||||
}
|
||||
|
||||
// Focus to center
|
||||
if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 };
|
||||
|
||||
// Camera position update
|
||||
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
|
||||
|
||||
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
|
||||
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
|
||||
|
||||
} break;
|
||||
case CAMERA_ORBITAL:
|
||||
{
|
||||
// Pass to free camera
|
||||
if (IsKeyPressed('O')) cameraMode = CAMERA_FREE;
|
||||
|
||||
cameraAngle.x += ORBITAL_CAMERA_SPEED;
|
||||
|
||||
// Camera zoom
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
// Camera distance clamp
|
||||
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
|
||||
|
||||
// Focus to center
|
||||
if (IsKeyDown('Z')) camera->target = (Vector3) { 0, 0, 0 };
|
||||
|
||||
// Camera position update
|
||||
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
|
||||
|
||||
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
|
||||
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
|
||||
|
||||
} break;
|
||||
case CAMERA_FIRST_PERSON:
|
||||
case CAMERA_THIRD_PERSON:
|
||||
{
|
||||
bool isMoving = false;
|
||||
|
||||
// Keyboard inputs
|
||||
if (IsKeyDown('W'))
|
||||
{
|
||||
playerPosition->x -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
else if (IsKeyDown('S'))
|
||||
{
|
||||
playerPosition->x += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
|
||||
if (IsKeyDown('A'))
|
||||
{
|
||||
playerPosition->x -= cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z += sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
else if (IsKeyDown('D'))
|
||||
{
|
||||
playerPosition->x += cos(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
playerPosition->z -= sin(cameraAngle.x) / PLAYER_MOVEMENT_DIVIDER;
|
||||
|
||||
isMoving = true;
|
||||
}
|
||||
|
||||
if (IsKeyDown('E'))
|
||||
{
|
||||
if (!cameraUseGravity) playerPosition->y += 1 / PLAYER_MOVEMENT_DIVIDER;
|
||||
}
|
||||
else if (IsKeyDown('Q'))
|
||||
{
|
||||
if (!cameraUseGravity) playerPosition->y -= 1 / PLAYER_MOVEMENT_DIVIDER;
|
||||
}
|
||||
|
||||
if (cameraMode == CAMERA_THIRD_PERSON)
|
||||
{
|
||||
// Camera orientation calculation
|
||||
// Get the mouse sensitivity
|
||||
cameraAngle.x += cameraMouseVariation.x * -THIRD_PERSON_MOUSE_SENSITIVITY;
|
||||
cameraAngle.y += cameraMouseVariation.y * -THIRD_PERSON_MOUSE_SENSITIVITY;
|
||||
|
||||
// Angle clamp
|
||||
if (cameraAngle.y > THIRD_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MIN_CLAMP * DEG2RAD;
|
||||
else if (cameraAngle.y < THIRD_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = THIRD_PERSON_MAX_CLAMP * DEG2RAD;
|
||||
|
||||
// Camera zoom
|
||||
cameraTargetDistance -= (GetMouseWheelMove() * CAMERA_SCROLL_SENSITIVITY);
|
||||
|
||||
// Camera distance clamp
|
||||
if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP;
|
||||
|
||||
// Camera is always looking at player
|
||||
camera->target.x = playerPosition->x + THIRD_PERSON_OFFSET.x * cos(cameraAngle.x) + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x);
|
||||
camera->target.y = playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION + THIRD_PERSON_OFFSET.y;
|
||||
camera->target.z = playerPosition->z + THIRD_PERSON_OFFSET.z * sin(cameraAngle.x) - THIRD_PERSON_OFFSET.x * sin(cameraAngle.x);
|
||||
|
||||
// Camera position update
|
||||
camera->position.x = sin(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.x;
|
||||
|
||||
if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
else camera->position.y = -sin(cameraAngle.y) * cameraTargetDistance * sin(cameraAngle.y) + camera->target.y;
|
||||
|
||||
camera->position.z = cos(cameraAngle.x) * cameraTargetDistance * cos(cameraAngle.y) + camera->target.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isMoving) cameraMovementCounter++;
|
||||
|
||||
// Camera orientation calculation
|
||||
// Get the mouse sensitivity
|
||||
cameraAngle.x += cameraMouseVariation.x * -FIRST_PERSON_MOUSE_SENSITIVITY;
|
||||
cameraAngle.y += cameraMouseVariation.y * -FIRST_PERSON_MOUSE_SENSITIVITY;
|
||||
|
||||
// Angle clamp
|
||||
if (cameraAngle.y > FIRST_PERSON_MIN_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MIN_CLAMP * DEG2RAD;
|
||||
else if (cameraAngle.y < FIRST_PERSON_MAX_CLAMP * DEG2RAD) cameraAngle.y = FIRST_PERSON_MAX_CLAMP * DEG2RAD;
|
||||
|
||||
// Camera is always looking at player
|
||||
camera->target.x = camera->position.x - sin(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
|
||||
camera->target.y = camera->position.y + sin(cameraAngle.y) * FIRST_PERSON_FOCUS_DISTANCE;
|
||||
camera->target.z = camera->position.z - cos(cameraAngle.x) * FIRST_PERSON_FOCUS_DISTANCE;
|
||||
|
||||
camera->position.x = playerPosition->x;
|
||||
camera->position.y = (playerPosition->y + PLAYER_HEIGHT * FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION) - sin(cameraMovementCounter / FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER) / FIRST_PERSON_STEP_DIVIDER;
|
||||
camera->position.z = playerPosition->z;
|
||||
|
||||
camera->up.x = sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
|
||||
camera->up.z = -sin(cameraMovementCounter / (FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER * 2)) / FIRST_PERSON_WAVING_DIVIDER;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
}
|
@ -30,9 +30,14 @@
|
||||
#include <stdlib.h> // malloc(), free()
|
||||
#include <stdio.h> // printf(), fprintf()
|
||||
#include <math.h> // Used for ...
|
||||
#include <time.h> // Used for clock functions
|
||||
#include <stdint.h> // Defines int32_t, int64_t
|
||||
|
||||
#if defined(_WIN32)
|
||||
//#include <Windows.h>
|
||||
#elif defined(__linux)
|
||||
#include <time.h> // Used for clock functions
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
#include <jni.h> // Java native interface
|
||||
#include <android/sensor.h> // Android sensors functions
|
||||
@ -75,15 +80,10 @@ typedef struct {
|
||||
// Global Variables Definition
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// typedef
|
||||
static GestureType gestureType = TYPE_MOTIONLESS;
|
||||
|
||||
// Gestures detection variables
|
||||
static double eventTime = 0;
|
||||
//static int32_t touchId; // Not used...
|
||||
|
||||
// Event
|
||||
static int64_t eventTime = 0;
|
||||
|
||||
// Tap
|
||||
// Our initial press position on tap
|
||||
static Vector2 initialTapPosition = { 0, 0 };
|
||||
@ -127,7 +127,7 @@ static float pinchDelta = 0;
|
||||
// Detected gesture
|
||||
static int currentGesture = GESTURE_NONE;
|
||||
|
||||
static float touchX, touchY;
|
||||
static Vector2 touchPosition;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Module specific Functions Declaration
|
||||
@ -141,7 +141,7 @@ static float OnPinch();
|
||||
static void SetDualInput(GestureEvent event);
|
||||
static float Distance(Vector2 v1, Vector2 v2);
|
||||
static float DotProduct(Vector2 v1, Vector2 v2);
|
||||
static int GetCurrentTime();
|
||||
static double GetCurrentTime();
|
||||
|
||||
#if defined(PLATFORM_WEB)
|
||||
static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
|
||||
@ -158,9 +158,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||
// Returns tap position XY
|
||||
extern Vector2 GetRawPosition(void)
|
||||
{
|
||||
Vector2 position = { touchX, touchY };
|
||||
|
||||
return position;
|
||||
return touchPosition;
|
||||
}
|
||||
|
||||
// Check if a gesture have been detected
|
||||
@ -531,13 +529,27 @@ static float DotProduct(Vector2 v1, Vector2 v2)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int GetCurrentTime()
|
||||
static double GetCurrentTime()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
// NOTE: Requires Windows.h
|
||||
FILETIME tm;
|
||||
GetSystemTimePreciseAsFileTime(&tm);
|
||||
ULONGLONG nowTime = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; // Time provided in 100-nanosecond intervals
|
||||
|
||||
return ((double)nowTime/10000000.0); // Return time in seconds
|
||||
*/
|
||||
#endif
|
||||
|
||||
#if defined(__linux)
|
||||
// NOTE: Only for Linux-based systems
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; // Time provided in nanoseconds
|
||||
|
||||
return nowTime / 1000000; // Return time in miliseconds
|
||||
return ((double)nowTime/1000000.0); // Return time in miliseconds
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_ANDROID)
|
||||
@ -545,23 +557,21 @@ static int GetCurrentTime()
|
||||
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
|
||||
{
|
||||
int type = AInputEvent_getType(event);
|
||||
//int32_t key = 0;
|
||||
|
||||
if (type == AINPUT_EVENT_TYPE_MOTION)
|
||||
{
|
||||
touchX = AMotionEvent_getX(event, 0);
|
||||
touchY = AMotionEvent_getY(event, 0);
|
||||
touchPosition.x = AMotionEvent_getX(event, 0);
|
||||
touchPosition.y = AMotionEvent_getY(event, 0);
|
||||
}
|
||||
else if (type == AINPUT_EVENT_TYPE_KEY)
|
||||
{
|
||||
//key = AKeyEvent_getKeyCode(event);
|
||||
//int32_t key = AKeyEvent_getKeyCode(event);
|
||||
//int32_t AKeyEvent_getMetaState(event);
|
||||
}
|
||||
|
||||
int32_t action = AMotionEvent_getAction(event);
|
||||
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
|
||||
|
||||
|
||||
GestureEvent gestureEvent;
|
||||
|
||||
// Action
|
||||
@ -609,6 +619,8 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent
|
||||
}
|
||||
*/
|
||||
|
||||
touchPosition = gestureEvent.position[0];
|
||||
|
||||
GestureEvent gestureEvent;
|
||||
|
||||
// Action
|
||||
|
116
src/models.c
116
src/models.c
@ -599,6 +599,8 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
|
||||
|
||||
int mapX = heightmap.width;
|
||||
int mapZ = heightmap.height;
|
||||
|
||||
Color *heightmapPixels = GetPixelData(heightmap);
|
||||
|
||||
// NOTE: One vertex per pixel
|
||||
// TODO: Consider resolution when generating model data?
|
||||
@ -628,15 +630,15 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
|
||||
|
||||
// one triangle - 3 vertex
|
||||
vData.vertices[vCounter] = x;
|
||||
vData.vertices[vCounter + 1] = GetHeightValue(heightmap.pixels[x + z*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 1] = GetHeightValue(heightmapPixels[x + z*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 2] = z;
|
||||
|
||||
vData.vertices[vCounter + 3] = x;
|
||||
vData.vertices[vCounter + 4] = GetHeightValue(heightmap.pixels[x + (z+1)*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 4] = GetHeightValue(heightmapPixels[x + (z+1)*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 5] = z+1;
|
||||
|
||||
vData.vertices[vCounter + 6] = x+1;
|
||||
vData.vertices[vCounter + 7] = GetHeightValue(heightmap.pixels[(x+1) + z*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 7] = GetHeightValue(heightmapPixels[(x+1) + z*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 8] = z;
|
||||
|
||||
// another triangle - 3 vertex
|
||||
@ -649,7 +651,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
|
||||
vData.vertices[vCounter + 14] = vData.vertices[vCounter + 5];
|
||||
|
||||
vData.vertices[vCounter + 15] = x+1;
|
||||
vData.vertices[vCounter + 16] = GetHeightValue(heightmap.pixels[(x+1) + (z+1)*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 16] = GetHeightValue(heightmapPixels[(x+1) + (z+1)*mapX])*scaleFactor;
|
||||
vData.vertices[vCounter + 17] = z+1;
|
||||
vCounter += 18; // 6 vertex, 18 floats
|
||||
|
||||
@ -691,6 +693,8 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
|
||||
trisCounter += 2;
|
||||
}
|
||||
}
|
||||
|
||||
free(heightmapPixels);
|
||||
|
||||
// Fill color data
|
||||
// NOTE: Not used any more... just one plain color defined at DrawModel()
|
||||
@ -713,17 +717,19 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
|
||||
}
|
||||
|
||||
// Load a map image as a 3d model (cubes based)
|
||||
Model LoadCubicmap(Image cubesmap)
|
||||
Model LoadCubicmap(Image cubicmap)
|
||||
{
|
||||
VertexData vData;
|
||||
|
||||
Color *cubicmapPixels = GetPixelData(cubicmap);
|
||||
|
||||
// Map cube size will be 1.0
|
||||
float mapCubeSide = 1.0f;
|
||||
int mapWidth = cubesmap.width * (int)mapCubeSide;
|
||||
int mapHeight = cubesmap.height * (int)mapCubeSide;
|
||||
int mapWidth = cubicmap.width * (int)mapCubeSide;
|
||||
int mapHeight = cubicmap.height * (int)mapCubeSide;
|
||||
|
||||
// NOTE: Max possible number of triangles numCubes * (12 triangles by cube)
|
||||
int maxTriangles = cubesmap.width*cubesmap.height*12;
|
||||
int maxTriangles = cubicmap.width*cubicmap.height*12;
|
||||
|
||||
int vCounter = 0; // Used to count vertices
|
||||
int tcCounter = 0; // Used to count texcoords
|
||||
@ -775,9 +781,9 @@ Model LoadCubicmap(Image cubesmap)
|
||||
Vector3 v8 = { x + w/2, 0, z + h/2 };
|
||||
|
||||
// We check pixel color to be WHITE, we will full cubes
|
||||
if ((cubesmap.pixels[z*cubesmap.width + x].r == 255) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + x].g == 255) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + x].b == 255))
|
||||
if ((cubicmapPixels[z*cubicmap.width + x].r == 255) &&
|
||||
(cubicmapPixels[z*cubicmap.width + x].g == 255) &&
|
||||
(cubicmapPixels[z*cubicmap.width + x].b == 255))
|
||||
{
|
||||
// Define triangles (Checking Collateral Cubes!)
|
||||
//----------------------------------------------
|
||||
@ -832,10 +838,10 @@ Model LoadCubicmap(Image cubesmap)
|
||||
mapTexcoords[tcCounter + 5] = (Vector2){ bottomTexUV.x, bottomTexUV.y + bottomTexUV.height };
|
||||
tcCounter += 6;
|
||||
|
||||
if (((z < cubesmap.height - 1) &&
|
||||
(cubesmap.pixels[(z + 1)*cubesmap.width + x].r == 0) &&
|
||||
(cubesmap.pixels[(z + 1)*cubesmap.width + x].g == 0) &&
|
||||
(cubesmap.pixels[(z + 1)*cubesmap.width + x].b == 0)) || (z == cubesmap.height - 1))
|
||||
if (((z < cubicmap.height - 1) &&
|
||||
(cubicmapPixels[(z + 1)*cubicmap.width + x].r == 0) &&
|
||||
(cubicmapPixels[(z + 1)*cubicmap.width + x].g == 0) &&
|
||||
(cubicmapPixels[(z + 1)*cubicmap.width + x].b == 0)) || (z == cubicmap.height - 1))
|
||||
{
|
||||
// Define front triangles (2 tris, 6 vertex) --> v2 v7 v3, v3 v7 v8
|
||||
// NOTE: Collateral occluded faces are not generated
|
||||
@ -865,9 +871,9 @@ Model LoadCubicmap(Image cubesmap)
|
||||
}
|
||||
|
||||
if (((z > 0) &&
|
||||
(cubesmap.pixels[(z - 1)*cubesmap.width + x].r == 0) &&
|
||||
(cubesmap.pixels[(z - 1)*cubesmap.width + x].g == 0) &&
|
||||
(cubesmap.pixels[(z - 1)*cubesmap.width + x].b == 0)) || (z == 0))
|
||||
(cubicmapPixels[(z - 1)*cubicmap.width + x].r == 0) &&
|
||||
(cubicmapPixels[(z - 1)*cubicmap.width + x].g == 0) &&
|
||||
(cubicmapPixels[(z - 1)*cubicmap.width + x].b == 0)) || (z == 0))
|
||||
{
|
||||
// Define back triangles (2 tris, 6 vertex) --> v1 v5 v6, v1 v4 v5
|
||||
// NOTE: Collateral occluded faces are not generated
|
||||
@ -896,10 +902,10 @@ Model LoadCubicmap(Image cubesmap)
|
||||
tcCounter += 6;
|
||||
}
|
||||
|
||||
if (((x < cubesmap.width - 1) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + (x + 1)].r == 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + (x + 1)].g == 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + (x + 1)].b == 0)) || (x == cubesmap.width - 1))
|
||||
if (((x < cubicmap.width - 1) &&
|
||||
(cubicmapPixels[z*cubicmap.width + (x + 1)].r == 0) &&
|
||||
(cubicmapPixels[z*cubicmap.width + (x + 1)].g == 0) &&
|
||||
(cubicmapPixels[z*cubicmap.width + (x + 1)].b == 0)) || (x == cubicmap.width - 1))
|
||||
{
|
||||
// Define right triangles (2 tris, 6 vertex) --> v3 v8 v4, v4 v8 v5
|
||||
// NOTE: Collateral occluded faces are not generated
|
||||
@ -929,9 +935,9 @@ Model LoadCubicmap(Image cubesmap)
|
||||
}
|
||||
|
||||
if (((x > 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + (x - 1)].r == 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + (x - 1)].g == 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + (x - 1)].b == 0)) || (x == 0))
|
||||
(cubicmapPixels[z*cubicmap.width + (x - 1)].r == 0) &&
|
||||
(cubicmapPixels[z*cubicmap.width + (x - 1)].g == 0) &&
|
||||
(cubicmapPixels[z*cubicmap.width + (x - 1)].b == 0)) || (x == 0))
|
||||
{
|
||||
// Define left triangles (2 tris, 6 vertex) --> v1 v7 v2, v1 v6 v7
|
||||
// NOTE: Collateral occluded faces are not generated
|
||||
@ -961,9 +967,9 @@ Model LoadCubicmap(Image cubesmap)
|
||||
}
|
||||
}
|
||||
// We check pixel color to be BLACK, we will only draw floor and roof
|
||||
else if ((cubesmap.pixels[z*cubesmap.width + x].r == 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + x].g == 0) &&
|
||||
(cubesmap.pixels[z*cubesmap.width + x].b == 0))
|
||||
else if ((cubicmapPixels[z*cubicmap.width + x].r == 0) &&
|
||||
(cubicmapPixels[z*cubicmap.width + x].g == 0) &&
|
||||
(cubicmapPixels[z*cubicmap.width + x].b == 0))
|
||||
{
|
||||
// Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)
|
||||
mapVertices[vCounter] = v1;
|
||||
@ -1065,6 +1071,8 @@ Model LoadCubicmap(Image cubesmap)
|
||||
free(mapVertices);
|
||||
free(mapNormals);
|
||||
free(mapTexcoords);
|
||||
|
||||
free(cubicmapPixels);
|
||||
|
||||
// NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
|
||||
|
||||
@ -1335,6 +1343,8 @@ bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSph
|
||||
// NOTE: player position (or camera) is modified inside this function
|
||||
Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius)
|
||||
{
|
||||
Color *cubicmapPixels = GetPixelData(cubicmap);
|
||||
|
||||
// Detect the cell where the player is located
|
||||
Vector3 impactDirection = { 0, 0, 0 };
|
||||
|
||||
@ -1347,8 +1357,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
// Multiple Axis --------------------------------------------------------------------------------------------
|
||||
|
||||
// Axis x-, y-
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
|
||||
(cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
|
||||
(cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
|
||||
@ -1360,8 +1370,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
|
||||
// Axis x-, y+
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
|
||||
(cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) &&
|
||||
(cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
|
||||
@ -1373,8 +1383,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
|
||||
// Axis x+, y-
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
|
||||
(cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
|
||||
(cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
|
||||
@ -1386,8 +1396,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
|
||||
// Axis x+, y+
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
|
||||
(cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) &&
|
||||
(cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
|
||||
@ -1401,7 +1411,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
// Single Axis ---------------------------------------------------------------------------------------------------
|
||||
|
||||
// Axis x-
|
||||
if (cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0)
|
||||
if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0)
|
||||
{
|
||||
if ((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius)
|
||||
{
|
||||
@ -1410,7 +1420,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
}
|
||||
// Axis x+
|
||||
if (cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0)
|
||||
if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0)
|
||||
{
|
||||
if ((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius)
|
||||
{
|
||||
@ -1419,7 +1429,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
}
|
||||
// Axis y-
|
||||
if (cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)
|
||||
if (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)
|
||||
{
|
||||
if ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)
|
||||
{
|
||||
@ -1428,7 +1438,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
}
|
||||
// Axis y+
|
||||
if (cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)
|
||||
if (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)
|
||||
{
|
||||
if ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)
|
||||
{
|
||||
@ -1440,9 +1450,9 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
// Diagonals -------------------------------------------------------------------------------------------------------
|
||||
|
||||
// Axis x-, y-
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX - 1)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX - 1)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
|
||||
@ -1460,9 +1470,9 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
|
||||
// Axis x-, y+
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX - 1)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX - 1)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
|
||||
@ -1480,9 +1490,9 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
|
||||
// Axis x+, y-
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY - 1) * cubicmap.width + (locationCellX + 1)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX + 1)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius))
|
||||
@ -1500,9 +1510,9 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
}
|
||||
|
||||
// Axis x+, y+
|
||||
if ((cubicmap.pixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmap.pixels[(locationCellY + 1) * cubicmap.width + (locationCellX + 1)].r != 0))
|
||||
if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) &&
|
||||
(cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX + 1)].r != 0))
|
||||
{
|
||||
if (((playerPosition->x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) &&
|
||||
((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius))
|
||||
@ -1531,6 +1541,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p
|
||||
playerPosition->y = (1.5 - radius) - 0.01;
|
||||
impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z};
|
||||
}
|
||||
|
||||
free(cubicmapPixels);
|
||||
|
||||
return impactDirection;
|
||||
}
|
||||
|
75
src/raylib.h
75
src/raylib.h
@ -27,7 +27,6 @@
|
||||
*
|
||||
* Some design decisions:
|
||||
* 32bit Colors - All defined color are always RGBA
|
||||
* 32bit Textures - All loaded images are converted automatically to RGBA textures
|
||||
* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures
|
||||
* One custom default font is loaded automatically when InitWindow()
|
||||
* If using OpenGL 3.3+ or ES2, one default shader is loaded automatically (internally defined)
|
||||
@ -78,7 +77,7 @@
|
||||
// Some basic Defines
|
||||
//----------------------------------------------------------------------------------
|
||||
#ifndef PI
|
||||
#define PI 3.14159265358979323846
|
||||
#define PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define DEG2RAD (PI / 180.0f)
|
||||
@ -183,20 +182,6 @@
|
||||
typedef enum { false, true } bool;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GESTURE_NONE = 0,
|
||||
GESTURE_TAP,
|
||||
GESTURE_DOUBLETAP,
|
||||
GESTURE_HOLD,
|
||||
GESTURE_DRAG,
|
||||
GESTURE_SWIPE_RIGHT,
|
||||
GESTURE_SWIPE_LEFT,
|
||||
GESTURE_SWIPE_UP,
|
||||
GESTURE_SWIPE_DOWN,
|
||||
GESTURE_PINCH_IN,
|
||||
GESTURE_PINCH_OUT
|
||||
} Gestures;
|
||||
|
||||
// byte type
|
||||
typedef unsigned char byte;
|
||||
|
||||
@ -240,17 +225,21 @@ typedef struct Rectangle {
|
||||
// Image type, bpp always RGBA (32bit)
|
||||
// NOTE: Data stored in CPU memory (RAM)
|
||||
typedef struct Image {
|
||||
Color *pixels;
|
||||
int width;
|
||||
int height;
|
||||
void *data; // Image raw data
|
||||
int width; // Image base width
|
||||
int height; // Image base height
|
||||
int mipmaps; // Mipmap levels, 1 by default
|
||||
int format; // Data format (TextureFormat)
|
||||
} Image;
|
||||
|
||||
// Texture2D type, bpp always RGBA (32bit)
|
||||
// NOTE: Data stored in GPU memory
|
||||
typedef struct Texture2D {
|
||||
unsigned int id; // OpenGL id
|
||||
int width;
|
||||
int height;
|
||||
unsigned int id; // OpenGL texture id
|
||||
int width; // Texture base width
|
||||
int height; // Texture base height
|
||||
int mipmaps; // Mipmap levels, 1 by default
|
||||
int format; // Data format (TextureFormat)
|
||||
} Texture2D;
|
||||
|
||||
// Character type (one font glyph)
|
||||
@ -337,9 +326,11 @@ typedef struct Wave {
|
||||
short channels;
|
||||
} Wave;
|
||||
|
||||
// Texture formats (support depends on OpenGL version)
|
||||
// Texture formats
|
||||
// NOTE: Support depends on OpenGL version and platform
|
||||
typedef enum {
|
||||
UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha)
|
||||
UNCOMPRESSED_GRAY_ALPHA, // 16 bpp (2 channels)
|
||||
UNCOMPRESSED_R5G6B5, // 16 bpp
|
||||
UNCOMPRESSED_R8G8B8, // 24 bpp
|
||||
UNCOMPRESSED_R5G5B5A1, // 16 bpp (1 bit alpha)
|
||||
@ -354,9 +345,25 @@ typedef enum {
|
||||
COMPRESSED_ETC2_EAC_RGBA, // 8 bpp
|
||||
COMPRESSED_PVRT_RGB, // 4 bpp
|
||||
COMPRESSED_PVRT_RGBA, // 4 bpp
|
||||
/*COMPRESSED_ASTC_RGBA_4x4*/ // 8 bpp
|
||||
COMPRESSED_ASTC_4x4_RGBA, // 8 bpp
|
||||
COMPRESSED_ASTC_8x8_RGBA // 2 bpp
|
||||
} TextureFormat;
|
||||
|
||||
// Gestures type
|
||||
typedef enum {
|
||||
GESTURE_NONE = 0,
|
||||
GESTURE_TAP,
|
||||
GESTURE_DOUBLETAP,
|
||||
GESTURE_HOLD,
|
||||
GESTURE_DRAG,
|
||||
GESTURE_SWIPE_RIGHT,
|
||||
GESTURE_SWIPE_LEFT,
|
||||
GESTURE_SWIPE_UP,
|
||||
GESTURE_SWIPE_DOWN,
|
||||
GESTURE_PINCH_IN,
|
||||
GESTURE_PINCH_OUT
|
||||
} Gestures;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { // Prevents name mangling of functions
|
||||
#endif
|
||||
@ -402,16 +409,27 @@ int GetHexValue(Color color); // Returns hexadecim
|
||||
int GetRandomValue(int min, int max); // Returns a random value between min and max (both included)
|
||||
Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f
|
||||
|
||||
void SetCameraMode(int mode); // Multiple camera modes available
|
||||
Camera UpdateCamera(Vector3 *position); // Update camera with position (when using internal camera)
|
||||
|
||||
void SetConfigFlags(char flags); // Enable some window configurations
|
||||
void ShowLogo(void); // Activates raylib logo at startup (can be done with flags)
|
||||
|
||||
void SetPostproShader(Shader shader); // Set fullscreen postproduction shader
|
||||
void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
|
||||
void SetDefaultShader(void); // Set default shader to be used in batch draw
|
||||
|
||||
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Gives the rayTrace from mouse position
|
||||
|
||||
// Camera modes setup and control functions (module: camera)
|
||||
void SetCameraMode(int mode); // Select camera mode (multiple camera modes available)
|
||||
Camera UpdateCamera(Vector3 *position); // Update camera with position
|
||||
|
||||
void SetCameraControls(int front, int left, int back, int right, int up, int down);
|
||||
void SetMouseSensitivity(float sensitivity);
|
||||
void SetResetPosition(Vector3 resetPosition);
|
||||
void SetResetControl(int resetKey);
|
||||
void SetPawnControl(int pawnControlKey);
|
||||
void SetFnControl(int fnControlKey);
|
||||
void SetSmoothZoomControl(int smoothZoomControlKey);
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Input Handling Functions (Module: core)
|
||||
//------------------------------------------------------------------------------------
|
||||
@ -451,6 +469,7 @@ int GetTouchX(void); // Returns touch positio
|
||||
int GetTouchY(void); // Returns touch position Y
|
||||
Vector2 GetTouchPosition(void); // Returns touch position XY
|
||||
|
||||
// Gestures System (module: gestures)
|
||||
bool IsGestureDetected(void);
|
||||
int GetGestureType(void);
|
||||
float GetDragIntensity(void);
|
||||
@ -504,6 +523,8 @@ Texture2D CreateTexture(Image image, bool genMipmaps);
|
||||
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
|
||||
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
|
||||
void ConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
|
||||
Color *GetPixelData(Image image); // Get pixel data from image as a Color struct array
|
||||
void SetPixelData(Image *image, Color *pixels, int format); // Set image data from Color struct array
|
||||
|
||||
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
|
||||
void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
|
||||
|
158
src/rlgl.c
158
src/rlgl.c
@ -143,6 +143,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
GLuint textureId;
|
||||
int vertexCount;
|
||||
// TODO: DrawState state -> Blending mode, shader
|
||||
} DrawCall;
|
||||
|
||||
// pixel type (same as Color type)
|
||||
@ -175,6 +176,7 @@ static VertexPositionColorTextureIndexBuffer quads;
|
||||
|
||||
// Shader Programs
|
||||
static Shader defaultShader, simpleShader;
|
||||
static Shader currentShader; // By default, defaultShader
|
||||
|
||||
// Vertex Array Objects (VAO)
|
||||
static GLuint vaoLines, vaoTriangles, vaoQuads;
|
||||
@ -330,14 +332,14 @@ void rlRotatef(float angleDeg, float x, float y, float z)
|
||||
Matrix rotation = MatrixIdentity();
|
||||
|
||||
// OPTION 1: It works...
|
||||
//if (x == 1) rot = MatrixRotateX(angleDeg*DEG2RAD);
|
||||
//else if (y == 1) rot = MatrixRotateY(angleDeg*DEG2RAD);
|
||||
//else if (z == 1) rot = MatrixRotateZ(angleDeg*DEG2RAD);
|
||||
if (x == 1) rotation = MatrixRotateX(angleDeg*DEG2RAD);
|
||||
else if (y == 1) rotation = MatrixRotateY(angleDeg*DEG2RAD);
|
||||
else if (z == 1) rotation = MatrixRotateZ(angleDeg*DEG2RAD);
|
||||
|
||||
// OPTION 2: Requires review...
|
||||
Vector3 axis = (Vector3){ x, y, z };
|
||||
VectorNormalize(&axis);
|
||||
rotation = MatrixRotateY(angleDeg*DEG2RAD); //MatrixFromAxisAngle(axis, angleDeg*DEG2RAD);
|
||||
//Vector3 axis = (Vector3){ x, y, z };
|
||||
//VectorNormalize(&axis);
|
||||
//rotation = MatrixRotateY(angleDeg*DEG2RAD); //MatrixFromAxisAngle(axis, angleDeg*DEG2RAD);
|
||||
|
||||
// OPTION 3: TODO: Review, it doesn't work!
|
||||
//Vector3 vec = (Vector3){ x, y, z };
|
||||
@ -921,6 +923,8 @@ void rlglInit(void)
|
||||
defaultShader = LoadDefaultShader();
|
||||
simpleShader = LoadSimpleShader();
|
||||
//customShader = rlglLoadShader("custom.vs", "custom.fs"); // Works ok
|
||||
|
||||
currentShader = defaultShader;
|
||||
|
||||
InitializeBuffers(); // Init vertex arrays
|
||||
InitializeBuffersGPU(); // Init VBO and VAO
|
||||
@ -1094,6 +1098,7 @@ void rlglClose(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Drawing batches: triangles, quads, lines
|
||||
void rlglDraw(void)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
@ -1101,11 +1106,11 @@ void rlglDraw(void)
|
||||
|
||||
if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
|
||||
{
|
||||
glUseProgram(defaultShader.id);
|
||||
glUseProgram(currentShader.id);
|
||||
|
||||
glUniformMatrix4fv(defaultShader.projectionLoc, 1, false, GetMatrixVector(projection));
|
||||
glUniformMatrix4fv(defaultShader.modelviewLoc, 1, false, GetMatrixVector(modelview));
|
||||
glUniform1i(defaultShader.textureLoc, 0);
|
||||
glUniformMatrix4fv(currentShader.projectionLoc, 1, false, GetMatrixVector(projection));
|
||||
glUniformMatrix4fv(currentShader.modelviewLoc, 1, false, GetMatrixVector(modelview));
|
||||
glUniform1i(currentShader.textureLoc, 0);
|
||||
}
|
||||
|
||||
// NOTE: We draw in this order: triangle shapes, textured quads and lines
|
||||
@ -1121,12 +1126,12 @@ void rlglDraw(void)
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]);
|
||||
glVertexAttribPointer(defaultShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]);
|
||||
glVertexAttribPointer(defaultShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
|
||||
@ -1149,16 +1154,16 @@ void rlglDraw(void)
|
||||
{
|
||||
// Enable vertex attributes
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
|
||||
glVertexAttribPointer(defaultShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
|
||||
glVertexAttribPointer(defaultShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.texcoordLoc);
|
||||
glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.texcoordLoc);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
|
||||
glVertexAttribPointer(defaultShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]);
|
||||
}
|
||||
@ -1206,12 +1211,12 @@ void rlglDraw(void)
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]);
|
||||
glVertexAttribPointer(defaultShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]);
|
||||
glVertexAttribPointer(defaultShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(defaultShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
}
|
||||
|
||||
glDrawArrays(GL_LINES, 0, lines.vCounter);
|
||||
@ -1310,7 +1315,7 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
|
||||
// NOTE: Drawing in OpenGL 3.3+, transform is passed to shader
|
||||
glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(projection));
|
||||
glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(modelviewworld));
|
||||
glUniform1i(model.shader.textureLoc, 0);
|
||||
glUniform1i(model.shader.textureLoc, 0); // Texture fits in texture unit 0 (Check glActiveTexture())
|
||||
|
||||
// Apply color tinting to model
|
||||
// NOTE: Just update one uniform on fragment shader
|
||||
@ -1573,16 +1578,18 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
|
||||
|
||||
GLuint id;
|
||||
|
||||
// TODO: Review compressed textures support by OpenGL version
|
||||
/* (rlGetVersion() == OPENGL_11)
|
||||
if ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA) ||
|
||||
(textureFormat == COMPRESSED_ETC1_RGB8) || (textureFormat == COMPRESSED_ETC2_RGB8) || (textureFormat == COMPRESSED_ETC2_EAC_RGBA8))
|
||||
// Check compressed textures support by OpenGL 1.1
|
||||
if (rlGetVersion() == OPENGL_11)
|
||||
{
|
||||
id = 0;
|
||||
TraceLog(WARNING, "GPU compressed textures not supported on OpenGL 1.1");
|
||||
return id;
|
||||
if ((textureFormat == COMPRESSED_ETC1_RGB) || (textureFormat == COMPRESSED_ETC2_RGB) || (textureFormat == COMPRESSED_ETC2_EAC_RGBA) ||
|
||||
(textureFormat == COMPRESSED_PVRT_RGB) || (textureFormat == COMPRESSED_PVRT_RGBA) ||
|
||||
(textureFormat == COMPRESSED_ASTC_4x4_RGBA) || (textureFormat == COMPRESSED_ASTC_8x8_RGBA))
|
||||
{
|
||||
id = 0;
|
||||
TraceLog(WARNING, "Required GPU compressed texture format not supported");
|
||||
return id;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
glGenTextures(1, &id); // Generate Pointer to the texture
|
||||
|
||||
@ -1679,10 +1686,17 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
|
||||
|
||||
// With swizzleMask we define how a one channel texture will be mapped to RGBA
|
||||
// Required GL >= 3.3 or EXT_texture_swizzle/ARB_texture_swizzle
|
||||
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, 1.0f };
|
||||
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
|
||||
TraceLog(INFO, "Grayscale texture loaded and swizzled!");
|
||||
TraceLog(INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id);
|
||||
} break;
|
||||
case UNCOMPRESSED_GRAY_ALPHA:
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width, height, 0, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data);
|
||||
|
||||
GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
} break;
|
||||
case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
|
||||
case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
||||
@ -1711,6 +1725,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
|
||||
switch (textureFormat)
|
||||
{
|
||||
case UNCOMPRESSED_GRAYSCALE: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
||||
case UNCOMPRESSED_GRAY_ALPHA: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
||||
case UNCOMPRESSED_R5G6B5: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break;
|
||||
case UNCOMPRESSED_R8G8B8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break;
|
||||
case UNCOMPRESSED_R5G5B5A1: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break;
|
||||
@ -1724,7 +1739,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
|
||||
case COMPRESSED_ETC2_RGB: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
||||
case COMPRESSED_ETC2_EAC_RGBA: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3
|
||||
//case COMPRESSED_ASTC_RGBA_4x4: LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3
|
||||
default: TraceLog(WARNING, "Texture format not recognized"); break;
|
||||
default: TraceLog(WARNING, "Texture format not supported"); break;
|
||||
}
|
||||
|
||||
if ((mipmapCount == 1) && (genMipmaps))
|
||||
@ -2009,13 +2024,50 @@ void rlglSetModelShader(Model *model, Shader shader)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set custom shader to be used on batch draw
|
||||
void rlglSetCustomShader(Shader shader)
|
||||
{
|
||||
if (currentShader.id != shader.id)
|
||||
{
|
||||
rlglDraw();
|
||||
|
||||
currentShader = shader;
|
||||
/*
|
||||
if (vaoSupported) glBindVertexArray(vaoQuads);
|
||||
|
||||
// Enable vertex attributes: position
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
|
||||
// Enable vertex attributes: texcoords
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
|
||||
glEnableVertexAttribArray(currentShader.texcoordLoc);
|
||||
glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
|
||||
|
||||
// Enable vertex attributes: colors
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
|
||||
if (vaoSupported) glBindVertexArray(0); // Unbind VAO
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// Set default shader to be used on batch draw
|
||||
void rlglSetDefaultShader(void)
|
||||
{
|
||||
rlglSetCustomShader(defaultShader);
|
||||
}
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
void PrintProjectionMatrix()
|
||||
void PrintProjectionMatrix(void)
|
||||
{
|
||||
PrintMatrix(projection);
|
||||
}
|
||||
|
||||
void PrintModelviewMatrix()
|
||||
void PrintModelviewMatrix(void)
|
||||
{
|
||||
PrintMatrix(modelview);
|
||||
}
|
||||
@ -2292,7 +2344,7 @@ static void InitializeBuffers(void)
|
||||
}
|
||||
|
||||
// Initialize Vertex Array Objects (Contain VBO)
|
||||
// NOTE: lines, triangles and quads buffers use defaultShader
|
||||
// NOTE: lines, triangles and quads buffers use currentShader
|
||||
static void InitializeBuffersGPU(void)
|
||||
{
|
||||
if (vaoSupported)
|
||||
@ -2308,14 +2360,14 @@ static void InitializeBuffersGPU(void)
|
||||
// Lines - Vertex positions buffer binding and attributes enable
|
||||
glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.vertexLoc);
|
||||
glVertexAttribPointer(defaultShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
|
||||
// Lines - colors buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.colorLoc);
|
||||
glVertexAttribPointer(defaultShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
|
||||
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Lines VAO initialized successfully", vaoLines);
|
||||
else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Lines VBOs initialized successfully", linesBuffer[0], linesBuffer[1]);
|
||||
@ -2334,13 +2386,13 @@ static void InitializeBuffersGPU(void)
|
||||
// Enable vertex attributes
|
||||
glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.vertexLoc);
|
||||
glVertexAttribPointer(defaultShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.colorLoc);
|
||||
glVertexAttribPointer(defaultShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
|
||||
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Triangles VAO initialized successfully", vaoTriangles);
|
||||
else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Triangles VBOs initialized successfully", trianglesBuffer[0], trianglesBuffer[1]);
|
||||
@ -2359,18 +2411,18 @@ static void InitializeBuffersGPU(void)
|
||||
// Enable vertex attributes
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.vertexLoc);
|
||||
glVertexAttribPointer(defaultShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.vertexLoc);
|
||||
glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.texcoordLoc);
|
||||
glVertexAttribPointer(defaultShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.texcoordLoc);
|
||||
glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(defaultShader.colorLoc);
|
||||
glVertexAttribPointer(defaultShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||
|
||||
// Fill index buffer
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]);
|
||||
|
@ -216,6 +216,8 @@ void rlglInitPostpro(void); // Initialize postprocessing sys
|
||||
void rlglDrawPostpro(void); // Draw with postprocessing shader
|
||||
void rlglSetPostproShader(Shader shader); // Set postprocessing shader
|
||||
void rlglSetModelShader(Model *model, Shader shader); // Set shader for a model
|
||||
void rlglSetCustomShader(Shader shader); // Set custom shader to be used on batch draw
|
||||
void rlglSetDefaultShader(void); // Set default shader to be used on batch draw
|
||||
|
||||
Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids
|
||||
void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires);
|
||||
|
37
src/text.c
37
src/text.c
@ -87,6 +87,8 @@ extern void LoadDefaultFont(void)
|
||||
Image image;
|
||||
image.width = 128; // We know our default font image is 128 pixels width
|
||||
image.height = 128; // We know our default font image is 128 pixels height
|
||||
image.mipmaps = 1;
|
||||
image.format = UNCOMPRESSED_R8G8B8A8;
|
||||
|
||||
// Default font is directly defined here (data generated from a sprite font image)
|
||||
// This way, we reconstruct SpriteFont without creating large global variables
|
||||
@ -149,9 +151,9 @@ extern void LoadDefaultFont(void)
|
||||
|
||||
// Re-construct image from defaultFontData and generate OpenGL texture
|
||||
//----------------------------------------------------------------------
|
||||
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
||||
Color *imagePixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
||||
|
||||
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
|
||||
for (int i = 0; i < image.width*image.height; i++) imagePixels[i] = BLANK; // Initialize array
|
||||
|
||||
int counter = 0; // Font data elements counter
|
||||
|
||||
@ -160,7 +162,7 @@ extern void LoadDefaultFont(void)
|
||||
{
|
||||
for (int j = 31; j >= 0; j--)
|
||||
{
|
||||
if (BIT_CHECK(defaultFontData[counter], j)) image.pixels[i+j] = WHITE;
|
||||
if (BIT_CHECK(defaultFontData[counter], j)) imagePixels[i+j] = WHITE;
|
||||
}
|
||||
|
||||
counter++;
|
||||
@ -171,6 +173,10 @@ extern void LoadDefaultFont(void)
|
||||
//FILE *myimage = fopen("default_font.raw", "wb");
|
||||
//fwrite(image.pixels, 1, 128*128*4, myimage);
|
||||
//fclose(myimage);
|
||||
|
||||
SetPixelData(&image, imagePixels, 0);
|
||||
|
||||
free(imagePixels);
|
||||
|
||||
defaultFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
|
||||
UnloadImage(image);
|
||||
@ -232,14 +238,16 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||
{
|
||||
Image image = LoadImage(fileName);
|
||||
|
||||
// At this point we have a pixel array with all the data...
|
||||
// At this point we have a data array...
|
||||
|
||||
Color *imagePixels = GetPixelData(image);
|
||||
|
||||
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
|
||||
ConvertToPOT(&image, MAGENTA);
|
||||
#endif
|
||||
// Process bitmap Font pixel data to get measures (Character array)
|
||||
// spriteFont.charSet data is filled inside the function and memory is allocated!
|
||||
int numChars = ParseImageData(image.pixels, image.width, image.height, &spriteFont.charSet);
|
||||
int numChars = ParseImageData(imagePixels, image.width, image.height, &spriteFont.charSet);
|
||||
|
||||
TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
|
||||
TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
|
||||
@ -248,6 +256,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||
|
||||
spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
|
||||
|
||||
free(imagePixels);
|
||||
UnloadImage(image);
|
||||
}
|
||||
|
||||
@ -522,6 +531,8 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||
|
||||
image.width = (int)rbmfHeader.imgWidth;
|
||||
image.height = (int)rbmfHeader.imgHeight;
|
||||
image.mipmaps = 1;
|
||||
image.format = UNCOMPRESSED_R8G8B8A8;
|
||||
|
||||
int numPixelBits = rbmfHeader.imgWidth * rbmfHeader.imgHeight / 32;
|
||||
|
||||
@ -535,9 +546,9 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||
|
||||
// Re-construct image from rbmfFileData
|
||||
//-----------------------------------------
|
||||
image.pixels = (Color *)malloc(image.width * image.height * sizeof(Color));
|
||||
Color *imagePixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
||||
|
||||
for (int i = 0; i < image.width * image.height; i++) image.pixels[i] = BLANK; // Initialize array
|
||||
for (int i = 0; i < image.width*image.height; i++) imagePixels[i] = BLANK; // Initialize array
|
||||
|
||||
int counter = 0; // Font data elements counter
|
||||
|
||||
@ -546,11 +557,15 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||
{
|
||||
for (int j = 31; j >= 0; j--)
|
||||
{
|
||||
if (BIT_CHECK(rbmfFileData[counter], j)) image.pixels[i+j] = WHITE;
|
||||
if (BIT_CHECK(rbmfFileData[counter], j)) imagePixels[i+j] = WHITE;
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
SetPixelData(&image, imagePixels, 0);
|
||||
|
||||
free(imagePixels);
|
||||
|
||||
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
||||
|
||||
@ -607,7 +622,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
|
||||
Image image;
|
||||
image.width = 512;
|
||||
image.height = 512;
|
||||
image.pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
||||
//image.pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
|
||||
|
||||
unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25);
|
||||
|
||||
@ -647,7 +662,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
|
||||
free(ttfBuffer);
|
||||
|
||||
// Now we have image data in tempBitmap and chardata filled...
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 512*512; i++)
|
||||
{
|
||||
image.pixels[i].r = tempBitmap[i];
|
||||
@ -655,7 +670,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
|
||||
image.pixels[i].b = tempBitmap[i];
|
||||
image.pixels[i].a = 255;
|
||||
}
|
||||
|
||||
*/
|
||||
free(tempBitmap);
|
||||
|
||||
// REFERENCE EXAMPLE
|
||||
|
891
src/textures.c
891
src/textures.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user