aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorraysan5 <raysan5@gmail.com>2014-07-23 00:06:24 +0200
committerraysan5 <raysan5@gmail.com>2014-07-23 00:06:24 +0200
commit0b03431c95c3c348aa686c1a3df68a51bd7761a6 (patch)
treec34f72424d76454a63f0db18f4834623c525b72a /src
parent5e2e9aa23e1fcbc78395443a4b0f83404b5557f8 (diff)
downloadraylib-0b03431c95c3c348aa686c1a3df68a51bd7761a6.tar.gz
raylib-0b03431c95c3c348aa686c1a3df68a51bd7761a6.zip
Update to version 1.1.1
Check CHANGELOG for a detailed list of changes
Diffstat (limited to 'src')
-rw-r--r--src/core.c147
-rw-r--r--src/models.c589
-rw-r--r--src/raylib.h7
-rw-r--r--src/rlgl.c262
-rw-r--r--src/rlgl.h2
-rw-r--r--src/text.c4
-rw-r--r--src/textures.c40
7 files changed, 733 insertions, 318 deletions
diff --git a/src/core.c b/src/core.c
index c61a77bf..4e323db9 100644
--- a/src/core.c
+++ b/src/core.c
@@ -86,6 +86,8 @@ static int currentMouseWheelY = 0; // Required to track mouse wheel var
static Color background = { 0, 0, 0, 0 }; // Screen background color
+static bool showLogo = false;
+
//----------------------------------------------------------------------------------
// Other Modules Functions Declaration (required by core)
//----------------------------------------------------------------------------------
@@ -103,6 +105,7 @@ static void ScrollCallback(GLFWwindow* window, double xoffset, double yoffset);
static void CursorEnterCallback(GLFWwindow* window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area
static void WindowSizeCallback(GLFWwindow* window, int width, int height); // GLFW3 WindowSize Callback, runs when window is resized
static void TakeScreenshot(); // Takes a screenshot and saves it in the same folder as executable
+static void LogoAnimation(); // Plays raylib logo appearing animation
//----------------------------------------------------------------------------------
// Module Functions Definition - Window and OpenGL Context Functions
@@ -177,6 +180,13 @@ void InitWindowEx(int width, int height, const char* title, bool resizable, cons
srand(time(NULL)); // Initialize random seed
ClearBackground(RAYWHITE); // Default background color for raylib games :P
+
+ // raylib logo appearing animation
+ if (showLogo)
+ {
+ SetTargetFPS(60);
+ LogoAnimation();
+ }
}
// Close Window and Terminate Context
@@ -436,6 +446,12 @@ Color Fade(Color color, float alpha)
return (Color){color.r, color.g, color.b, color.a*alpha};
}
+// Activates raylib logo at startup
+void ShowLogo()
+{
+ showLogo = true;
+}
+
//----------------------------------------------------------------------------------
// Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions
//----------------------------------------------------------------------------------
@@ -681,7 +697,7 @@ bool IsGamepadButtonUp(int gamepad, int button)
// GLFW3 Error Callback, runs on GLFW3 error
static void ErrorCallback(int error, const char *description)
{
- TraceLog(WARNING, "GLFW3 Error: %s", description);
+ TraceLog(WARNING, "[GLFW3 Error] Code: %i Decription: %s", error, description);
}
// GLFW3 Srolling Callback, runs on mouse wheel
@@ -721,9 +737,15 @@ static void WindowSizeCallback(GLFWwindow* window, int width, int height)
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight); // Get framebuffer size of current window
- // If window is resized, graphics device is re-initialized
- // NOTE: Aspect ratio does not change, so, image can be deformed
+ // If window is resized, graphics device is re-initialized (but only ortho mode)
rlglInitGraphicsDevice(fbWidth, fbHeight);
+
+ // Window size must be updated to be used on 3D mode to get new aspect ratio (Begin3dMode())
+ windowWidth = fbWidth;
+ windowHeight = fbHeight;
+
+ // Background must be also re-cleared
+ rlClearColor(background.r, background.g, background.b, background.a);
}
// Takes a bitmap (BMP) screenshot and saves it in the same folder as executable
@@ -747,4 +769,123 @@ static void TakeScreenshot()
shotNum++;
TraceLog(INFO, "[%s] Screenshot taken!", buffer);
+}
+
+static void LogoAnimation()
+{
+ int logoPositionX = windowWidth/2 - 128;
+ int logoPositionY = windowHeight/2 - 128;
+
+ int framesCounter = 0;
+ int lettersCount = 0;
+
+ int topSideRecWidth = 16;
+ int leftSideRecHeight = 16;
+
+ int bottomSideRecWidth = 16;
+ int rightSideRecHeight = 16;
+
+ char raylib[8] = " "; // raylib text array, max 8 letters
+ int state = 0; // Tracking animation states (State Machine)
+ float alpha = 1.0; // Useful for fading
+
+ while (!WindowShouldClose() && (state != 4)) // Detect window close button or ESC key
+ {
+ // Update
+ //----------------------------------------------------------------------------------
+ if (state == 0) // State 0: Small box blinking
+ {
+ framesCounter++;
+
+ if (framesCounter == 84)
+ {
+ state = 1;
+ framesCounter = 0; // Reset counter... will be used later...
+ }
+ }
+ else if (state == 1) // State 1: Top and left bars growing
+ {
+ topSideRecWidth += 4;
+ leftSideRecHeight += 4;
+
+ if (topSideRecWidth == 256) state = 2;
+ }
+ else if (state == 2) // State 2: Bottom and right bars growing
+ {
+ bottomSideRecWidth += 4;
+ rightSideRecHeight += 4;
+
+ if (bottomSideRecWidth == 256) state = 3;
+ }
+ else if (state == 3) // State 3: Letters appearing (one by one)
+ {
+ framesCounter++;
+
+ if (framesCounter/12) // Every 12 frames, one more letter!
+ {
+ lettersCount++;
+ framesCounter = 0;
+ }
+
+ switch (lettersCount)
+ {
+ case 1: raylib[0] = 'r'; break;
+ case 2: raylib[1] = 'a'; break;
+ case 3: raylib[2] = 'y'; break;
+ case 4: raylib[3] = 'l'; break;
+ case 5: raylib[4] = 'i'; break;
+ case 6: raylib[5] = 'b'; break;
+ default: break;
+ }
+
+ if (lettersCount >= 10) // When all letters have appeared, just fade out everything
+ {
+ alpha -= 0.02;
+
+ if (alpha <= 0)
+ {
+ alpha = 0;
+ state = 4;
+ }
+ }
+ }
+ //----------------------------------------------------------------------------------
+
+ // Draw
+ //----------------------------------------------------------------------------------
+ BeginDrawing();
+
+ if (state == 0)
+ {
+ if ((framesCounter/12)%2) DrawRectangle(logoPositionX, logoPositionY, 16, 16, BLACK);
+ }
+ else if (state == 1)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+ }
+ else if (state == 2)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY, 16, leftSideRecHeight, BLACK);
+
+ DrawRectangle(logoPositionX + 240, logoPositionY, 16, rightSideRecHeight, BLACK);
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, BLACK);
+ }
+ else if (state == 3)
+ {
+ DrawRectangle(logoPositionX, logoPositionY, topSideRecWidth, 16, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 16, 16, leftSideRecHeight - 32, Fade(BLACK, alpha));
+
+ DrawRectangle(logoPositionX + 240, logoPositionY + 16, 16, rightSideRecHeight - 32, Fade(BLACK, alpha));
+ DrawRectangle(logoPositionX, logoPositionY + 240, bottomSideRecWidth, 16, Fade(BLACK, alpha));
+
+ DrawRectangle(windowWidth/2 - 112, windowHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha));
+
+ DrawText(raylib, 356, 273, 50, Fade(BLACK, alpha));
+ }
+
+ EndDrawing();
+ //----------------------------------------------------------------------------------
+ }
} \ No newline at end of file
diff --git a/src/models.c b/src/models.c
index 0c7201cd..d66d2cce 100644
--- a/src/models.c
+++ b/src/models.c
@@ -681,6 +681,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
+ vData.colors = (unsigned char *)malloc(vData.vertexCount * 4 * sizeof(unsigned char));
int vCounter = 0; // Used to count vertices float by float
int tcCounter = 0; // Used to count texcoords float by float
@@ -765,6 +766,9 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
// NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
+ // Fill color data
+ for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255;
+
Model model;
model.mesh = vData; // Model mesh is vertex data
@@ -783,6 +787,329 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
return model;
}
+// Load a map image as a 3d model (cubes based)
+Model LoadCubesmap(Image cubesmap)
+{
+ VertexData vData;
+
+ // Map cube size will be 1.0
+ float mapCubeSide = 1.0f;
+ int mapWidth = cubesmap.width * (int)mapCubeSide;
+ int mapHeight = cubesmap.height * (int)mapCubeSide;
+
+ // NOTE: Max possible number of triangles numCubes * (12 triangles by cube)
+ int maxTriangles = cubesmap.width*cubesmap.height*12;
+
+ int vCounter = 0; // Used to count vertices
+ int tcCounter = 0; // Used to count texcoords
+ int nCounter = 0; // Used to count normals
+
+ float w = mapCubeSide;
+ float h = mapCubeSide;
+ float h2 = mapCubeSide;
+
+ Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3));
+ Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles * 3 * sizeof(Vector2));
+ Vector3 *mapNormals = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3));
+
+ for (int z = 0; z < mapHeight; z += mapCubeSide)
+ {
+ for (int x = 0; x < mapWidth; x += mapCubeSide)
+ {
+ // Define the 8 vertex of the cube, we will combine them accordingly later...
+ Vector3 v1 = { x - w/2, h2, z - h/2 };
+ Vector3 v2 = { x - w/2, h2, z + h/2 };
+ Vector3 v3 = { x + w/2, h2, z + h/2 };
+ Vector3 v4 = { x + w/2, h2, z - h/2 };
+ Vector3 v5 = { x + w/2, 0, z - h/2 };
+ Vector3 v6 = { x - w/2, 0, z - h/2 };
+ Vector3 v7 = { x - w/2, 0, z + h/2 };
+ Vector3 v8 = { x + w/2, 0, z + h/2 };
+
+ // Define the 6 normals of the cube, we will combine them accordingly later...
+ Vector3 n1 = { 1.0f, 0.0f, 0.0f };
+ Vector3 n2 = { -1.0f, 0.0f, 0.0f };
+ Vector3 n3 = { 0.0f, 1.0f, 0.0f };
+ Vector3 n4 = { 0.0f, -1.0f, 0.0f };
+ Vector3 n5 = { 0.0f, 0.0f, 1.0f };
+ Vector3 n6 = { 0.0f, 0.0f, -1.0f };
+
+ // Define the 4 texture coordinates of the cube, we will combine them accordingly later...
+ // TODO: Use texture rectangles to define different textures for top-bottom-front-back-right-left (6)
+ Vector2 vt2 = { 0.0f, 0.0f };
+ Vector2 vt1 = { 0.0f, 1.0f };
+ Vector2 vt4 = { 1.0f, 0.0f };
+ Vector2 vt3 = { 1.0f, 1.0f };
+
+ // 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))
+ {
+ // Define triangles (Checking Collateral Cubes!)
+ //----------------------------------------------
+
+ // Define top triangles (2 tris, 6 vertex --> v1-v2-v3, v1-v3-v4)
+ mapVertices[vCounter] = v1;
+ mapVertices[vCounter + 1] = v2;
+ mapVertices[vCounter + 2] = v3;
+ mapVertices[vCounter + 3] = v1;
+ mapVertices[vCounter + 4] = v3;
+ mapVertices[vCounter + 5] = v4;
+ vCounter += 6;
+
+ mapNormals[nCounter] = n3;
+ mapNormals[nCounter + 1] = n3;
+ mapNormals[nCounter + 2] = n3;
+ mapNormals[nCounter + 3] = n3;
+ mapNormals[nCounter + 4] = n3;
+ mapNormals[nCounter + 5] = n3;
+ nCounter += 6;
+
+ mapTexcoords[tcCounter] = vt2;
+ mapTexcoords[tcCounter + 1] = vt1;
+ mapTexcoords[tcCounter + 2] = vt3;
+ mapTexcoords[tcCounter + 3] = vt2;
+ mapTexcoords[tcCounter + 4] = vt3;
+ mapTexcoords[tcCounter + 5] = vt4;
+ tcCounter += 6;
+
+ // Define bottom triangles (2 tris, 6 vertex --> v6-v8-v7, v6-v5-v8)
+ mapVertices[vCounter] = v6;
+ mapVertices[vCounter + 1] = v8;
+ mapVertices[vCounter + 2] = v7;
+ mapVertices[vCounter + 3] = v6;
+ mapVertices[vCounter + 4] = v5;
+ mapVertices[vCounter + 5] = v8;
+ vCounter += 6;
+
+ mapNormals[nCounter] = n4;
+ mapNormals[nCounter + 1] = n4;
+ mapNormals[nCounter + 2] = n4;
+ mapNormals[nCounter + 3] = n4;
+ mapNormals[nCounter + 4] = n4;
+ mapNormals[nCounter + 5] = n4;
+ nCounter += 6;
+
+ mapTexcoords[tcCounter] = vt4;
+ mapTexcoords[tcCounter + 1] = vt1;
+ mapTexcoords[tcCounter + 2] = vt3;
+ mapTexcoords[tcCounter + 3] = vt4;
+ mapTexcoords[tcCounter + 4] = vt2;
+ mapTexcoords[tcCounter + 5] = vt1;
+ 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))
+ {
+ // Define front triangles (2 tris, 6 vertex) --> v2 v7 v3, v3 v7 v8
+ // NOTE: Collateral occluded faces are not generated
+ mapVertices[vCounter] = v2;
+ mapVertices[vCounter + 1] = v7;
+ mapVertices[vCounter + 2] = v3;
+ mapVertices[vCounter + 3] = v3;
+ mapVertices[vCounter + 4] = v7;
+ mapVertices[vCounter + 5] = v8;
+ vCounter += 6;
+
+ mapNormals[nCounter] = n6;
+ mapNormals[nCounter + 1] = n6;
+ mapNormals[nCounter + 2] = n6;
+ mapNormals[nCounter + 3] = n6;
+ mapNormals[nCounter + 4] = n6;
+ mapNormals[nCounter + 5] = n6;
+ nCounter += 6;
+
+ mapTexcoords[tcCounter] = vt2;
+ mapTexcoords[tcCounter + 1] = vt1;
+ mapTexcoords[tcCounter + 2] = vt4;
+ mapTexcoords[tcCounter + 3] = vt4;
+ mapTexcoords[tcCounter + 4] = vt1;
+ mapTexcoords[tcCounter + 5] = vt3;
+ tcCounter += 6;
+ }
+
+ 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))
+ {
+ // Define back triangles (2 tris, 6 vertex) --> v1 v5 v6, v1 v4 v5
+ // NOTE: Collateral occluded faces are not generated
+ mapVertices[vCounter] = v1;
+ mapVertices[vCounter + 1] = v5;
+ mapVertices[vCounter + 2] = v6;
+ mapVertices[vCounter + 3] = v1;
+ mapVertices[vCounter + 4] = v4;
+ mapVertices[vCounter + 5] = v5;
+ vCounter += 6;
+
+ mapNormals[nCounter] = n5;
+ mapNormals[nCounter + 1] = n5;
+ mapNormals[nCounter + 2] = n5;
+ mapNormals[nCounter + 3] = n5;
+ mapNormals[nCounter + 4] = n5;
+ mapNormals[nCounter + 5] = n5;
+ nCounter += 6;
+
+ mapTexcoords[tcCounter] = vt4;
+ mapTexcoords[tcCounter + 1] = vt1;
+ mapTexcoords[tcCounter + 2] = vt3;
+ mapTexcoords[tcCounter + 3] = vt4;
+ mapTexcoords[tcCounter + 4] = vt2;
+ mapTexcoords[tcCounter + 5] = vt1;
+ 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))
+ {
+ // Define right triangles (2 tris, 6 vertex) --> v3 v8 v4, v4 v8 v5
+ // NOTE: Collateral occluded faces are not generated
+ mapVertices[vCounter] = v3;
+ mapVertices[vCounter + 1] = v8;
+ mapVertices[vCounter + 2] = v4;
+ mapVertices[vCounter + 3] = v4;
+ mapVertices[vCounter + 4] = v8;
+ mapVertices[vCounter + 5] = v5;
+ vCounter += 6;
+
+ mapNormals[nCounter] = n1;
+ mapNormals[nCounter + 1] = n1;
+ mapNormals[nCounter + 2] = n1;
+ mapNormals[nCounter + 3] = n1;
+ mapNormals[nCounter + 4] = n1;
+ mapNormals[nCounter + 5] = n1;
+ nCounter += 6;
+
+ mapTexcoords[tcCounter] = vt2;
+ mapTexcoords[tcCounter + 1] = vt1;
+ mapTexcoords[tcCounter + 2] = vt4;
+ mapTexcoords[tcCounter + 3] = vt4;
+ mapTexcoords[tcCounter + 4] = vt1;
+ mapTexcoords[tcCounter + 5] = vt3;
+ tcCounter += 6;
+ }
+
+ 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))
+ {
+ // Define left triangles (2 tris, 6 vertex) --> v1 v7 v2, v1 v6 v7
+ // NOTE: Collateral occluded faces are not generated
+ mapVertices[vCounter] = v1;
+ mapVertices[vCounter + 1] = v7;
+ mapVertices[vCounter + 2] = v2;
+ mapVertices[vCounter + 3] = v1;
+ mapVertices[vCounter + 4] = v6;
+ mapVertices[vCounter + 5] = v7;
+ vCounter += 6;
+
+ mapNormals[nCounter] = n2;
+ mapNormals[nCounter + 1] = n2;
+ mapNormals[nCounter + 2] = n2;
+ mapNormals[nCounter + 3] = n2;
+ mapNormals[nCounter + 4] = n2;
+ mapNormals[nCounter + 5] = n2;
+ nCounter += 6;
+
+ mapTexcoords[tcCounter] = vt2;
+ mapTexcoords[tcCounter + 1] = vt3;
+ mapTexcoords[tcCounter + 2] = vt4;
+ mapTexcoords[tcCounter + 3] = vt2;
+ mapTexcoords[tcCounter + 4] = vt1;
+ mapTexcoords[tcCounter + 5] = vt3;
+ tcCounter += 6;
+ }
+ }
+ // 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))
+ {
+ // Define top triangles (2 tris, 6 vertex --> v1-v3-v2, v1-v4-v3)
+ // TODO: ...
+
+ // Define bottom triangles (2 tris, 6 vertex --> v6-v7-v8, v6-v8-v5)
+ // TODO: ...
+ }
+ }
+ }
+
+ // Move data from mapVertices temp arays to vertices float array
+ vData.vertexCount = vCounter;
+
+ printf("Vertex count: %i\n", vCounter);
+
+ vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
+ vData.colors = (unsigned char *)malloc(vData.vertexCount * 4 * sizeof(unsigned char));
+
+ // Fill color data
+ for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255;
+
+ int fCounter = 0;
+
+ // Move vertices data
+ for (int i = 0; i < vCounter; i++)
+ {
+ vData.vertices[fCounter] = mapVertices[i].x;
+ vData.vertices[fCounter + 1] = mapVertices[i].y;
+ vData.vertices[fCounter + 2] = mapVertices[i].z;
+ fCounter += 3;
+ }
+
+ fCounter = 0;
+
+ // Move normals data
+ for (int i = 0; i < nCounter; i++)
+ {
+ vData.normals[fCounter] = mapNormals[i].x;
+ vData.normals[fCounter + 1] = mapNormals[i].y;
+ vData.normals[fCounter + 2] = mapNormals[i].z;
+ fCounter += 3;
+ }
+
+ fCounter = 0;
+
+ // Move texcoords data
+ for (int i = 0; i < tcCounter; i++)
+ {
+ vData.texcoords[fCounter] = mapTexcoords[i].x;
+ vData.texcoords[fCounter + 1] = mapTexcoords[i].y;
+ fCounter += 2;
+ }
+
+ free(mapVertices);
+ free(mapNormals);
+ free(mapTexcoords);
+
+ // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct
+
+ Model model;
+
+ model.mesh = vData; // Model mesh is vertex data
+ model.textureId = 0;
+
+#if defined(USE_OPENGL_33) || defined(USE_OPENGL_ES2)
+ model.vaoId = rlglLoadModel(vData); // Use loaded data to generate VAO
+ model.textureId = 1; // Default whiteTexture
+
+ // Now that vertex data is uploaded to GPU, we can free arrays
+ //free(vData.vertices);
+ //free(vData.texcoords);
+ //free(vData.normals);
+#endif
+
+ return model;
+}
+
// Unload 3d model from memory
void UnloadModel(Model model)
{
@@ -945,141 +1272,81 @@ static VertexData LoadOBJ(const char *fileName)
objFile = fopen(fileName, "rt");
- // First pass over all file to get numVertex, numNormals, numTexCoords, numTriangles
+ // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles
// NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition)
+ // NOTE: faces MUST be defined as TRIANGLES, not QUADS
while(!feof(objFile))
{
fscanf(objFile, "%c", &dataType);
switch(dataType)
{
- case '#': // It's a comment
+ case '#': // Comments
+ case 'o': // Object name (One OBJ file can contain multible named meshes)
+ case 'g': // Group name
+ case 's': // Smoothing level
+ case 'm': // mtllib [external .mtl file name]
+ case 'u': // usemtl [material name]
{
- fgets(comments, 200, objFile);
- } break;
- case 'o': // New object
- {
- // TODO: Read multiple objects, we need to know numMeshes + verticesPerMesh
-
- // NOTE: One OBJ file can contain multible meshes defined, one after every 'o'
-
- } break;
+ fgets(comments, 200, objFile);
+ } break;
case 'v':
{
fscanf(objFile, "%c", &dataType);
if (dataType == 't') // Read texCoord
{
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'v')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numTexCoords);
- }
-
+ numTexCoords++;
fgets(comments, 200, objFile);
}
else if (dataType == 'n') // Read normals
{
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'v')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numNormals);
- }
-
+ numNormals++;
fgets(comments, 200, objFile);
}
else // Read vertex
{
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'v')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numVertex);
- }
-
+ numVertex++;
fgets(comments, 200, objFile);
}
} break;
case 'f':
{
+ numTriangles++;
fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
-
- while (dataType == 'f')
- {
- fgets(comments, 200, objFile);
- fscanf(objFile, "%c", &dataType);
- }
-
- if (dataType == '#')
- {
- fscanf(objFile, "%i", &numTriangles);
- }
-
- fgets(comments, 200, objFile);
-
} break;
default: break;
}
}
+ TraceLog(DEBUG, "[%s] Model num vertices: %i", fileName, numVertex);
+ TraceLog(DEBUG, "[%s] Model num texcoords: %i", fileName, numTexCoords);
+ TraceLog(DEBUG, "[%s] Model num normals: %i", fileName, numNormals);
+ TraceLog(DEBUG, "[%s] Model num triangles: %i", fileName, numTriangles);
+
// Once we know the number of vertices to store, we create required arrays
Vector3 *midVertices = (Vector3 *)malloc(numVertex*sizeof(Vector3));
- Vector3 *midNormals = (Vector3 *)malloc(numNormals*sizeof(Vector3));
- Vector2 *midTexCoords = (Vector2 *)malloc(numTexCoords*sizeof(Vector2));
-
- vData.vertexCount = numTriangles*3;
-
- // Additional arrays to store vertex data as floats
- vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
- vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
- vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
- vData.colors = (float *)malloc(vData.vertexCount * 4 * sizeof(float));
-
+ Vector3 *midNormals;
+ if (numNormals > 0) midNormals = (Vector3 *)malloc(numNormals*sizeof(Vector3));
+ Vector2 *midTexCoords;
+ if (numTexCoords > 0) midTexCoords = (Vector2 *)malloc(numTexCoords*sizeof(Vector2));
+
int countVertex = 0;
int countNormals = 0;
int countTexCoords = 0;
-
- int vCounter = 0; // Used to count vertices float by float
- int tcCounter = 0; // Used to count texcoords float by float
- int nCounter = 0; // Used to count normals float by float
-
+
rewind(objFile); // Return to the beginning of the file, to read again
- // Reading again file to get vertex data
+ // Second reading pass: Get vertex data to fill intermediate arrays
+ // NOTE: This second pass is required in case of multiple meshes defined in same OBJ
+ // TODO: Consider that diferent meshes can have different vertex data available (position, texcoords, normals)
while(!feof(objFile))
{
fscanf(objFile, "%c", &dataType);
switch(dataType)
{
- case '#':
- {
- fgets(comments, 200, objFile);
- } break;
+ case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break;
case 'v':
{
fscanf(objFile, "%c", &dataType);
@@ -1108,60 +1375,107 @@ static VertexData LoadOBJ(const char *fileName)
fscanf(objFile, "%c", &dataType);
}
} break;
+ default: break;
+ }
+ }
+
+ // At this point all vertex data (v, vt, vn) has been gathered on midVertices, midTexCoords, midNormals
+ // Now we can organize that data into our VertexData struct
+
+ vData.vertexCount = numTriangles*3;
+
+ // Additional arrays to store vertex data as floats
+ vData.vertices = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.texcoords = (float *)malloc(vData.vertexCount * 2 * sizeof(float));
+ vData.normals = (float *)malloc(vData.vertexCount * 3 * sizeof(float));
+ vData.colors = (unsigned char *)malloc(vData.vertexCount * 4 * sizeof(unsigned char));
+
+ int vCounter = 0; // Used to count vertices float by float
+ int tcCounter = 0; // Used to count texcoords float by float
+ int nCounter = 0; // Used to count normals float by float
+
+ int vNum[3], vtNum[3], vnNum[3];
+
+ rewind(objFile); // Return to the beginning of the file, to read again
+
+ if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName);
+
+ // Third reading pass: Get faces (triangles) data and fill VertexArray
+ while(!feof(objFile))
+ {
+ fscanf(objFile, "%c", &dataType);
+
+ switch(dataType)
+ {
+ case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break;
case 'f':
{
- // At this point all vertex data (v, vt, vn) have been gathered on midVertices, midTexCoords, midNormals
- // Now we can organize that data into our VertexData struct
-
- int vNum, vtNum, vnNum;
- fscanf(objFile, "%c", &dataType);
- fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
+ // NOTE: It could be that OBJ does not have normals or texcoords defined!
- vData.vertices[vCounter] = midVertices[vNum-1].x;
- vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
- vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
- vCounter += 3;
+ if ((numNormals == 0) && (numTexCoords == 0)) fscanf(objFile, "%i %i %i", &vNum[0], &vNum[1], &vNum[2]);
+ else if (numNormals == 0) fscanf(objFile, "%i/%i %i/%i %i/%i", &vNum[0], &vtNum[0], &vNum[1], &vtNum[1], &vNum[2], &vtNum[2]);
+ else fscanf(objFile, "%i/%i/%i %i/%i/%i %i/%i/%i", &vNum[0], &vtNum[0], &vnNum[0], &vNum[1], &vtNum[1], &vnNum[1], &vNum[2], &vtNum[2], &vnNum[2]);
- vData.normals[nCounter] = midNormals[vnNum-1].x;
- vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
- vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
- nCounter += 3;
-
- vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
- vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
- tcCounter += 2;
-
- fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
-
- vData.vertices[vCounter] = midVertices[vNum-1].x;
- vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
- vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
+ vData.vertices[vCounter] = midVertices[vNum[0]-1].x;
+ vData.vertices[vCounter + 1] = midVertices[vNum[0]-1].y;
+ vData.vertices[vCounter + 2] = midVertices[vNum[0]-1].z;
vCounter += 3;
-
- vData.normals[nCounter] = midNormals[vnNum-1].x;
- vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
- vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
- nCounter += 3;
-
- vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
- vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
- tcCounter += 2;
-
- fscanf(objFile, "%i/%i/%i", &vNum, &vtNum, &vnNum);
-
- vData.vertices[vCounter] = midVertices[vNum-1].x;
- vData.vertices[vCounter + 1] = midVertices[vNum-1].y;
- vData.vertices[vCounter + 2] = midVertices[vNum-1].z;
+ vData.vertices[vCounter] = midVertices[vNum[1]-1].x;
+ vData.vertices[vCounter + 1] = midVertices[vNum[1]-1].y;
+ vData.vertices[vCounter + 2] = midVertices[vNum[1]-1].z;
+ vCounter += 3;
+ vData.vertices[vCounter] = midVertices[vNum[2]-1].x;
+ vData.vertices[vCounter + 1] = midVertices[vNum[2]-1].y;
+ vData.vertices[vCounter + 2] = midVertices[vNum[2]-1].z;
vCounter += 3;
- vData.normals[nCounter] = midNormals[vnNum-1].x;
- vData.normals[nCounter + 1] = midNormals[vnNum-1].y;
- vData.normals[nCounter + 2] = midNormals[vnNum-1].z;
- nCounter += 3;
+ if (numNormals > 0)
+ {
+ vData.normals[nCounter] = midNormals[vnNum[0]-1].x;
+ vData.normals[nCounter + 1] = midNormals[vnNum[0]-1].y;
+ vData.normals[nCounter + 2] = midNormals[vnNum[0]-1].z;
+ nCounter += 3;
+ vData.normals[nCounter] = midNormals[vnNum[1]-1].x;
+ vData.normals[nCounter + 1] = midNormals[vnNum[1]-1].y;
+ vData.normals[nCounter + 2] = midNormals[vnNum[1]-1].z;
+ nCounter += 3;
+ vData.normals[nCounter] = midNormals[vnNum[2]-1].x;
+ vData.normals[nCounter + 1] = midNormals[vnNum[2]-1].y;
+ vData.normals[nCounter + 2] = midNormals[vnNum[2]-1].z;
+ nCounter += 3;
+ }
+ else
+ {
+ // If normals not defined, they are calculated from the 3 vertices [N = (V2 - V1) x (V3 - V1)]
+ Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vNum[1]-1], midVertices[vNum[0]-1]), VectorSubtract(midVertices[vNum[2]-1], midVertices[vNum[0]-1]));
+ VectorNormalize(&norm);
+
+ vData.normals[nCounter] = norm.x;
+ vData.normals[nCounter + 1] = norm.y;
+ vData.normals[nCounter + 2] = norm.z;
+ nCounter += 3;
+ vData.normals[nCounter] = norm.x;
+ vData.normals[nCounter + 1] = norm.y;
+ vData.normals[nCounter + 2] = norm.z;
+ nCounter += 3;
+ vData.normals[nCounter] = norm.x;
+ vData.normals[nCounter + 1] = norm.y;
+ vData.normals[nCounter + 2] = norm.z;
+ nCounter += 3;
+ }
- vData.texcoords[tcCounter] = midTexCoords[vtNum-1].x;
- vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum-1].y;
- tcCounter += 2;
+ if (numTexCoords > 0)
+ {
+ vData.texcoords[tcCounter] = midTexCoords[vtNum[0]-1].x;
+ vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum[0]-1].y;
+ tcCounter += 2;
+ vData.texcoords[tcCounter] = midTexCoords[vtNum[1]-1].x;
+ vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum[1]-1].y;
+ tcCounter += 2;
+ vData.texcoords[tcCounter] = midTexCoords[vtNum[2]-1].x;
+ vData.texcoords[tcCounter + 1] = -midTexCoords[vtNum[2]-1].y;
+ tcCounter += 2;
+ }
} break;
default: break;
}
@@ -1169,8 +1483,11 @@ static VertexData LoadOBJ(const char *fileName)
fclose(objFile);
+ // Security check, just in case no normals or no texcoords defined in OBJ
+ if (numTexCoords == 0) for (int i = 0; i < (2*vData.vertexCount); i++) vData.texcoords[i] = 0.0f;
+
// NOTE: We set all vertex colors to white
- for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 1.0f;
+ for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255;
// Now we can free temp mid* arrays
free(midVertices);
diff --git a/src/raylib.h b/src/raylib.h
index 0ff357c2..da5427c0 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -226,11 +226,11 @@ typedef struct VertexData {
float *vertices; // 3 components per vertex
float *texcoords; // 2 components per vertex
float *normals; // 3 components per vertex
- float *colors; // 4 components per vertex
+ unsigned char *colors; // 4 components per vertex
} VertexData;
// 3d Model type
-// NOTE: If using OpenGL 1.1 loaded in CPU (mesh); if OpenGL 3.3+ loaded in GPU (vaoId)
+// NOTE: If using OpenGL 1.1, loaded in CPU (mesh); if OpenGL 3.3+ loaded in GPU (vaoId)
typedef struct Model {
VertexData mesh;
unsigned int vaoId;
@@ -282,6 +282,8 @@ 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.0 to 1.0
+void ShowLogo(); // Activates raylib logo at startup
+
//------------------------------------------------------------------------------------
// Input Handling Functions (Module: core)
//------------------------------------------------------------------------------------
@@ -395,6 +397,7 @@ void DrawGizmoEx(Vector3 position, Vector3 rotation, float scale);
Model LoadModel(const char *fileName); // Load a 3d model (.OBJ)
//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource)
Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model
+Model LoadCubesmap(Image cubesmap); // Load a map image as a 3d model (cubes based)
void UnloadModel(Model model); // Unload 3d model from memory
void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model
diff --git a/src/rlgl.c b/src/rlgl.c
index 313a2f1c..c181c7d6 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -58,8 +58,6 @@
//#include "glad.h" // Other extensions loading lib? --> REVIEW
-#define USE_VBO_DOUBLE_BUFFERS // Enable VBO double buffers usage --> REVIEW!
-
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
@@ -77,7 +75,7 @@ typedef struct {
int vCounter;
int cCounter;
float *vertices; // 3 components per vertex
- float *colors; // 4 components per vertex
+ unsigned char *colors; // 4 components per vertex
} VertexPositionColorBuffer;
// Vertex buffer (position + texcoords + color arrays)
@@ -88,7 +86,7 @@ typedef struct {
int cCounter;
float *vertices; // 3 components per vertex
float *texcoords; // 2 components per vertex
- float *colors; // 4 components per vertex
+ unsigned char *colors; // 4 components per vertex
} VertexPositionColorTextureBuffer;
// Vertex buffer (position + texcoords + normals arrays)
@@ -110,7 +108,7 @@ typedef struct {
int cCounter;
float *vertices; // 3 components per vertex
float *texcoords; // 2 components per vertex
- float *colors; // 4 components per vertex
+ unsigned char *colors; // 4 components per vertex
unsigned int *indices; // 6 indices per quad
} VertexPositionColorTextureIndexBuffer;
@@ -165,13 +163,6 @@ static GLuint linesBuffer[2];
static GLuint trianglesBuffer[2];
static GLuint quadsBuffer[4];
-#ifdef USE_VBO_DOUBLE_BUFFERS
-// Double buffering
-static GLuint vaoQuadsB;
-static GLuint quadsBufferB[4];
-static bool useBufferB = false;
-#endif
-
static DrawCall *draws;
static int drawsCounter;
@@ -566,7 +557,7 @@ void rlNormal3f(float x, float y, float z)
}
// Define one vertex (color)
-void rlColor4f(float x, float y, float z, float w)
+void rlColor4ub(byte x, byte y, byte z, byte w)
{
switch (currentDrawMode)
{
@@ -605,15 +596,15 @@ void rlColor4f(float x, float y, float z, float w)
}
// Define one vertex (color)
-void rlColor4ub(byte r, byte g, byte b, byte a)
+void rlColor4f(float r, float g, float b, float a)
{
- rlColor4f((float)r/255, (float)g/255, (float)b/255, (float)a/255);
+ rlColor4ub((byte)(r*255), (byte)(g*255), (byte)(b*255), (byte)(a*255));
}
// Define one vertex (color)
void rlColor3f(float x, float y, float z)
{
- rlColor4f(x, y, z, 1.0);
+ rlColor4ub((byte)(x*255), (byte)(y*255), (byte)(z*255), 255);
}
#endif
@@ -826,48 +817,23 @@ void rlglClose()
void rlglDraw()
{
+ UpdateBuffers();
+
glUseProgram(shaderProgram); // Use our shader
glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelview));
glUniform1i(textureLoc, 0);
-
- UpdateBuffers();
-
- if (lines.vCounter > 0)
- {
- glBindTexture(GL_TEXTURE_2D, whiteTexture);
-
- glBindVertexArray(vaoLines);
- glDrawArrays(GL_LINES, 0, lines.vCounter);
-
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-
- if (triangles.vCounter > 0)
- {
- glBindTexture(GL_TEXTURE_2D, whiteTexture);
-
- glBindVertexArray(vaoTriangles);
- glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
-
- glBindTexture(GL_TEXTURE_2D, 0);
- }
+ // NOTE: We draw in this order: textured quads, triangles shapes, lines
+
if (quads.vCounter > 0)
{
int quadsCount = 0;
int numIndicesToProcess = 0;
int indicesOffset = 0;
-#ifdef USE_VBO_DOUBLE_BUFFERS
- // Depending on useBufferB, use Buffer A or Buffer B
- if (useBufferB) glBindVertexArray(vaoQuadsB);
- else
-#endif
- {
- glBindVertexArray(vaoQuads);
- }
+ glBindVertexArray(vaoQuads);
//TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter);
@@ -885,9 +851,30 @@ void rlglDraw()
indicesOffset += draws[i].vertexCount/4*6;
}
+
+ glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
+ }
+
+ if (triangles.vCounter > 0)
+ {
+ glBindTexture(GL_TEXTURE_2D, whiteTexture);
+
+ glBindVertexArray(vaoTriangles);
+ glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ if (lines.vCounter > 0)
+ {
+ glBindTexture(GL_TEXTURE_2D, whiteTexture);
+
+ glBindVertexArray(vaoLines);
+ glDrawArrays(GL_LINES, 0, lines.vCounter);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
}
- glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures
glBindVertexArray(0); // Unbind VAO
// Reset draws counter
@@ -905,11 +892,6 @@ void rlglDraw()
quads.vCounter = 0;
quads.tcCounter = 0;
quads.cCounter = 0;
-
- // TODO: Review double buffer performance -> no improvement! (?)
-#ifdef USE_VBO_DOUBLE_BUFFERS
- useBufferB = !useBufferB; // Change buffers usage!
-#endif
}
#endif // End for OpenGL 3.3+ and ES2 only functions
@@ -931,7 +913,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal
glVertexPointer(3, GL_FLOAT, 0, model.mesh.vertices); // Pointer to vertex coords array
glTexCoordPointer(2, GL_FLOAT, 0, model.mesh.texcoords); // Pointer to texture coords array
glNormalPointer(GL_FLOAT, 0, model.mesh.normals); // Pointer to normals array
- //glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.colors); // Pointer to colors array (NOT USED)
+ //glColorPointer(4, GL_UNSIGNED_BYTE, 0, model.mesh.colors); // Pointer to colors array (NOT USED)
//TraceLog(DEBUG, "Drawing model.mesh, VertexCount: %i", model.mesh.vertexCount);
@@ -966,15 +948,36 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal
glUniformMatrix4fv(projectionMatrixLoc, 1, false, GetMatrixVector(projection));
glUniformMatrix4fv(modelviewMatrixLoc, 1, false, GetMatrixVector(modelviewworld));
glUniform1i(textureLoc, 0);
+
+ // Apply color tinting to model: 2 OPTIONS
+/*
+ // OPTION 1
+ // Update colors array (model.mesh.colors) with color
+ int j = 0;
+ for (int i = 0; i < model.mesh.vertexCount; i++)
+ {
+ model.mesh.colors[j] = color.r;
+ model.mesh.colors[j+1] = color.g;
+ model.mesh.colors[j+2] = color.b;
+ model.mesh.colors[j+3] = color.a;
+ j += 4;
+ }
+
+ // Update colors buffer in CPU (using Shader)
+ glBindVertexArray(model.vaoId);
+ GLuint colorVboId;
+ glGetVertexAttribIuiv(2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &colorVboId); // NOTE: Color VBO is buffer index 2
+ glBindBuffer(GL_ARRAY_BUFFER, colorVboId);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*model.mesh.vertexCount, model.mesh.colors);
+
+ // OPTION 2: Just update one uniform on fragment shader
+ // NOTE: It requires shader modification to add uniform (fragment shader) and create location point
+ //glUniform4f(fragmentUniformColorLoc, (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255);
+*/
//TraceLog(DEBUG, "ShaderProgram: %i, VAO ID: %i, VertexCount: %i", shaderProgram, model.vaoId, model.mesh.vertexCount);
glBindVertexArray(model.vaoId);
-
- // TODO: Update vertex color
- glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*model.mesh.vertexCount, model.mesh.colors);
-
glBindTexture(GL_TEXTURE_2D, model.textureId);
glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount);
@@ -989,8 +992,8 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotation, Vector3 scal
// Initialize Graphics Device (OpenGL stuff)
void rlglInitGraphicsDevice(int fbWidth, int fbHeight)
{
- //glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height
- // NOTE: Not required, viewport will be full window space
+ glViewport(0, 0, fbWidth, fbHeight); // Set viewport width and height
+ // NOTE: Required! viewport must be recalculated if screen resized!
// NOTE: Don't confuse glViewport with the transformation matrix
// NOTE: glViewport just defines the area of the context that you will actually draw to.
@@ -1052,7 +1055,7 @@ unsigned int rlglLoadTexture(unsigned char *data, int width, int height, bool ge
// Check if width and height are power-of-two (POT)
if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
- if (!texIsPOT)
+ if (genMipmaps && !texIsPOT)
{
TraceLog(WARNING, "[ID %i] Texture is not power-of-two, mipmaps can not be generated", id);
@@ -1194,26 +1197,29 @@ unsigned int rlglLoadModel(VertexData mesh)
// Create buffers for our vertex data (positions, texcoords, normals)
glGenBuffers(3, vertexBuffer);
- // Enable vertex attributes
+ // Enable vertex attributes: position
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(vertexLoc);
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0);
+ // Enable vertex attributes: texcoords
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW);
glEnableVertexAttribArray(texcoordLoc);
glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
+ // Enable vertex attributes: normals
//glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW);
//glEnableVertexAttribArray(normalLoc);
//glVertexAttribPointer(normalLoc, 3, GL_FLOAT, 0, 0, 0);
+ // Enable vertex attributes: colors
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*mesh.vertexCount, mesh.colors, GL_STATIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh.vertexCount, mesh.colors, GL_STATIC_DRAW);
glEnableVertexAttribArray(colorLoc);
- glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
if (vaoModel > 0) TraceLog(INFO, "[ID %i] Model uploaded successfully to VRAM (GPU)", vaoModel);
else TraceLog(WARNING, "Model could not be uploaded to VRAM (GPU)");
@@ -1408,34 +1414,34 @@ static char *TextFileRead(char *fn)
static void InitializeBuffers()
{
// Initialize lines arrays (vertex position and color data)
- lines.vertices = (float *)malloc(sizeof(float)*3*2*MAX_LINES_BATCH); // 3 float by vertex, 2 vertex by line
- lines.colors = (float *)malloc(sizeof(float)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line
+ lines.vertices = (float *)malloc(sizeof(float)*3*2*MAX_LINES_BATCH); // 3 float by vertex, 2 vertex by line
+ lines.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line
for (int i = 0; i < (3*2*MAX_LINES_BATCH); i++) lines.vertices[i] = 0.0;
- for (int i = 0; i < (4*2*MAX_LINES_BATCH); i++) lines.colors[i] = 0.0;
+ for (int i = 0; i < (4*2*MAX_LINES_BATCH); i++) lines.colors[i] = 0;
lines.vCounter = 0;
lines.cCounter = 0;
// Initialize triangles arrays (vertex position and color data)
- triangles.vertices = (float *)malloc(sizeof(float)*3*3*MAX_TRIANGLES_BATCH); // 3 float by vertex, 3 vertex by triangle
- triangles.colors = (float *)malloc(sizeof(float)*4*3*MAX_TRIANGLES_BATCH); // 4 float by color, 3 colors by triangle
+ triangles.vertices = (float *)malloc(sizeof(float)*3*3*MAX_TRIANGLES_BATCH); // 3 float by vertex, 3 vertex by triangle
+ triangles.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH); // 4 float by color, 3 colors by triangle
for (int i = 0; i < (3*3*MAX_TRIANGLES_BATCH); i++) triangles.vertices[i] = 0.0;
- for (int i = 0; i < (4*3*MAX_TRIANGLES_BATCH); i++) triangles.colors[i] = 0.0;
+ for (int i = 0; i < (4*3*MAX_TRIANGLES_BATCH); i++) triangles.colors[i] = 0;
triangles.vCounter = 0;
triangles.cCounter = 0;
// Initialize quads arrays (vertex position, texcoord and color data... and indexes)
- quads.vertices = (float *)malloc(sizeof(float)*3*4*MAX_QUADS_BATCH); // 3 float by vertex, 4 vertex by quad
- quads.texcoords = (float *)malloc(sizeof(float)*2*4*MAX_QUADS_BATCH); // 2 float by texcoord, 4 texcoord by quad
- quads.colors = (float *)malloc(sizeof(float)*4*4*MAX_QUADS_BATCH); // 4 float by color, 4 colors by quad
- quads.indices = (unsigned int *)malloc(sizeof(int)*6*MAX_QUADS_BATCH); // 6 int by quad (indices)
+ quads.vertices = (float *)malloc(sizeof(float)*3*4*MAX_QUADS_BATCH); // 3 float by vertex, 4 vertex by quad
+ quads.texcoords = (float *)malloc(sizeof(float)*2*4*MAX_QUADS_BATCH); // 2 float by texcoord, 4 texcoord by quad
+ quads.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*4*MAX_QUADS_BATCH); // 4 float by color, 4 colors by quad
+ quads.indices = (unsigned int *)malloc(sizeof(int)*6*MAX_QUADS_BATCH); // 6 int by quad (indices)
for (int i = 0; i < (3*4*MAX_QUADS_BATCH); i++) quads.vertices[i] = 0.0;
for (int i = 0; i < (2*4*MAX_QUADS_BATCH); i++) quads.texcoords[i] = 0.0;
- for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0.0;
+ for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0;
int k = 0;
@@ -1475,9 +1481,9 @@ static void InitializeVAOs()
// Lines - colors buffer
glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(colorLoc);
- glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
TraceLog(INFO, "[ID %i] Lines VAO initialized successfully", vaoLines);
//--------------------------------------------------------------
@@ -1496,9 +1502,9 @@ static void InitializeVAOs()
glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(colorLoc);
- glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
TraceLog(INFO, "[ID %i] Triangles VAO initialized successfully", vaoTriangles);
//--------------------------------------------------------------
@@ -1522,46 +1528,15 @@ static void InitializeVAOs()
glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(colorLoc);
- glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);
+ glVertexAttribPointer(colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
// Fill index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
TraceLog(INFO, "[ID %i] Quads VAO initialized successfully", vaoQuads);
-
-#ifdef USE_VBO_DOUBLE_BUFFERS
- // Initialize Quads VAO (Buffer B)
- glGenVertexArrays(1, &vaoQuadsB);
- glBindVertexArray(vaoQuadsB);
-
- // Create buffers for our vertex data
- glGenBuffers(4, quadsBufferB);
-
- // Enable vertex attributes
- glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[0]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(vertexLoc);
- glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-
- glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[1]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(texcoordLoc);
- glVertexAttribPointer(texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-
- glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[2]);
- glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
- glEnableVertexAttribArray(colorLoc);
- glVertexAttribPointer(colorLoc, 4, GL_FLOAT, 0, 0, 0);
-
- // Fill index buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBufferB[3]);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
-
- TraceLog(INFO, "[ID %i] Second Quads VAO successfully initilized (double buffering)", vaoQuadsB);
-#endif
// Unbind the current VAO
glBindVertexArray(0);
@@ -1581,7 +1556,7 @@ static void UpdateBuffers()
// Lines - colors buffer
glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*lines.vCounter, lines.colors);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*lines.cCounter, lines.colors);
//--------------------------------------------------------------
@@ -1596,54 +1571,27 @@ static void UpdateBuffers()
// Triangles - colors buffer
glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]);
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*triangles.cCounter, triangles.colors);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*triangles.cCounter, triangles.colors);
//--------------------------------------------------------------
- // Depending on useBufferB, update Buffer A or Buffer B
-#ifdef USE_VBO_DOUBLE_BUFFERS
- if (useBufferB)
- {
- // Activate Quads VAO (Buffer B)
- glBindVertexArray(vaoQuadsB);
-
- // Quads - vertex positions buffer
- glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[0]);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*quads.vCounter, quads.vertices);
-
- // Quads - texture coordinates buffer
- glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[1]);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords);
-
- // Quads - colors buffer
- glBindBuffer(GL_ARRAY_BUFFER, quadsBufferB[2]);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*quads.vCounter, quads.colors);
- }
- else
-#endif
- {
- // Activate Quads VAO (Buffer A)
- glBindVertexArray(vaoQuads);
-
- // Quads - vertex positions buffer
- glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*quads.vCounter, quads.vertices);
-
- // Quads - texture coordinates buffer
- glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords);
-
- // Quads - colors buffer
- glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
- //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*4*quads.vCounter, quads.colors);
- }
+ // Activate Quads VAO
+ glBindVertexArray(vaoQuads);
+
+ // Quads - vertex positions buffer
+ glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*quads.vCounter, quads.vertices);
+
+ // Quads - texture coordinates buffer
+ glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*quads.vCounter, quads.texcoords);
+ // Quads - colors buffer
+ glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
+ //glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*quads.vCounter, quads.colors);
// Another option would be using buffer mapping...
//triangles.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
diff --git a/src/rlgl.h b/src/rlgl.h
index 61e6f8f3..6ec54331 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -65,7 +65,7 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode;
float *vertices; // 3 components per vertex
float *texcoords; // 2 components per vertex
float *normals; // 3 components per vertex
- float *colors;
+ unsigned char *colors;
} VertexData;
typedef struct Model {
diff --git a/src/text.c b/src/text.c
index 87205f67..c8b9f81d 100644
--- a/src/text.c
+++ b/src/text.c
@@ -230,12 +230,14 @@ SpriteFont LoadSpriteFont(const char* fileName)
// At this point we have a pixel array with all the data...
+ TraceLog(INFO, "[%s] SpriteFont image loaded: %i x %i", fileName, imgWidth, imgHeight);
+
// 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(imgDataPixel, imgWidth, imgHeight, &spriteFont.charSet);
TraceLog(INFO, "[%s] SpriteFont data parsed correctly", fileName);
- TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", numChars);
+ TraceLog(INFO, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
spriteFont.numChars = numChars;
diff --git a/src/textures.c b/src/textures.c
index a21dd4bf..4bd6378d 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -100,26 +100,30 @@ Image LoadImage(const char *fileName)
// Force loading to 4 components (RGBA)
byte *imgData = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 4);
- // Convert array to pixel array for working convenience
- image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
-
- int pix = 0;
-
- for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
+ if (imgData != NULL)
{
- image.pixels[pix].r = imgData[i];
- image.pixels[pix].g = imgData[i+1];
- image.pixels[pix].b = imgData[i+2];
- image.pixels[pix].a = imgData[i+3];
- pix++;
+ // Convert array to pixel array for working convenience
+ image.pixels = (Color *)malloc(imgWidth * imgHeight * sizeof(Color));
+
+ int pix = 0;
+
+ for (int i = 0; i < (imgWidth * imgHeight * 4); i += 4)
+ {
+ image.pixels[pix].r = imgData[i];
+ image.pixels[pix].g = imgData[i+1];
+ image.pixels[pix].b = imgData[i+2];
+ image.pixels[pix].a = imgData[i+3];
+ pix++;
+ }
+
+ stbi_image_free(imgData);
+
+ image.width = imgWidth;
+ image.height = imgHeight;
+
+ TraceLog(INFO, "[%s] Image loaded successfully", fileName);
}
-
- stbi_image_free(imgData);
-
- image.width = imgWidth;
- image.height = imgHeight;
-
- TraceLog(INFO, "[%s] Image loaded successfully", fileName);
+ else TraceLog(WARNING, "[%s] Image could not be loaded", fileName);
}
else if (strcmp(GetExtension(fileName),"dds") == 0)
{