Update to version 1.1.1

Check CHANGELOG for a detailed list of changes
This commit is contained in:
raysan5 2014-07-23 00:06:24 +02:00
parent 5e2e9aa23e
commit 0b03431c95
17 changed files with 851 additions and 331 deletions

View File

@ -1,11 +1,28 @@
changelog
---------
Current Release: raylib 1.1.0 (April 2014)
Current Release: raylib 1.1.1 (22 July 2014)
NOTE: Only versions marked as 'Release' are available on release folder, updates are only available as source.
NOTE: Current Release includes all previous updates.
-----------------------------------------------
Release: raylib 1.1.1 (22 July 2014)
-----------------------------------------------
[core] ShowLogo() - To enable raylib logo animation at startup
[core] Corrected bug with window resizing
[rlgl] Redefined colors arrays to use byte instead of float
[rlgl] Removed double buffer system (no performance improvement)
[rlgl] rlglDraw() - Reorganized buffers drawing order
[rlgl] Corrected bug on screen resizing
[models] DrawSphereWires() - Corrected some issues
[models] LoadOBJ() - Redesigned to support multiple meshes
[models] LoadCubesMap() - Loading a map as cubes (by pixel color)
[textures] Added security check if file doesn't exist
[text] Corrected bug on SpriteFont loading
[examples] Corrected some 3d examples
[test] Added cubesmap loading test
-----------------------------------------------
Release: raylib 1.1.0 (19 April 2014)
-----------------------------------------------

View File

@ -34,4 +34,4 @@ contact
* Facebook: [http://www.facebook.com/raylibgames](http://www.facebook.com/raylibgames)
[raysan5]: mailto:raysan5@gmail.com "Ramon Santamaria - Ray San"
[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San"

View File

@ -88,6 +88,8 @@ I believe those are the best tools to train spartan-programmers.
Someone could argue about debugging. raylib is a library intended for learning and I think C it's a clear enough language
to allow writing small-mid size programs with a printf-based debugging. All raylib examples have also been written this way.
Since raylib v1.1, you can download a windows Installer package for easy installation and configuration. Check [raylib Webpage](http://www.raylib.com/)
building
--------
@ -143,4 +145,4 @@ The following people have contributed in some way to make raylib project a reali
- Victor Dual
- Marc Palau
[raysan5]: mailto:raysan5@gmail.com "Ramon Santamaria - Ray San"
[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San"

View File

@ -19,4 +19,4 @@ raylib v1.x
Any feature missing? Do you have a request? [Let me know!][raysan5]
[raysan5]: mailto:raysan5@gmail.com "Ramon Santamaria - Ray San"
[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San"

View File

@ -47,7 +47,7 @@ int main()
DrawCubeWires((Vector3){-4, 0, -2}, 3, 6, 2, MAROON);
DrawSphere((Vector3){-1, 0, -2}, 1, GREEN);
DrawSphereWires((Vector3){1, 0, 2}, 2, LIME);
DrawSphereWires((Vector3){1, 0, 2}, 2, 16, 16, LIME);
DrawCylinder((Vector3){4, 0, -2}, 1, 2, 3, 4, SKYBLUE);
DrawCylinderWires((Vector3){4, 0, -2}, 1, 2, 3, 4, DARKBLUE);

View File

@ -221,16 +221,16 @@ typedef struct Camera {
} Camera;
// Vertex data definning a mesh
typedef struct {
typedef struct VertexData {
int vertexCount;
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

Binary file not shown.

View File

@ -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();
//----------------------------------------------------------------------------------
}
}

View File

@ -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;
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.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.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;
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;
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;
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;
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);

View File

@ -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

View File

@ -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);
// 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, 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);
}
// 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);

View File

@ -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 {

View File

@ -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;

View File

@ -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)
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

83
tests/test_cubesmap.c Normal file
View File

@ -0,0 +1,83 @@
/*******************************************************************************************
*
* raylib test - Testing Heightmap Loading and Drawing
*
* This test 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 = 800;
int screenHeight = 450;
Vector3 position = { 0.5, 0.0, 0.5 };
// Define the camera to look into our 3d world
Camera camera = {{ 7.0, 6.0, 7.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }};
InitWindow(screenWidth, screenHeight, "raylib test - Heightmap loading and drawing");
Image img = LoadImage("resources/cubesmap.png");
Model map = LoadCubesmap(img);
Texture2D texture = CreateTexture(img, false);
UnloadImage(img);
SetModelTexture(&map, texture);
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_UP)) camera.position.y += 0.2f;
else if (IsKeyDown(KEY_DOWN)) camera.position.y -= 0.2f;
if (IsKeyDown(KEY_RIGHT)) camera.position.z += 0.2f;
else if (IsKeyDown(KEY_LEFT)) camera.position.z -= 0.2f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
Begin3dMode(camera);
//DrawCube(position, 1.0f, 1.0f, 1.0f, RED);
DrawModel(map, position, 1.0f, MAROON);
DrawGrid(10.0, 1.0); // Draw a grid
DrawGizmo(position);
End3dMode();
DrawFPS(10, 10);
EndDrawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(texture); // Unload texture
UnloadModel(map); // Unload model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -30,7 +30,7 @@ int main()
Texture2D texture = CreateTexture(img, false);
UnloadImage(img);
SetModelTexture(&map, texture);
SetModelTexture(&map, texture);
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
@ -51,11 +51,11 @@ int main()
Begin3dMode(camera);
DrawModel(map, position, 0.5f, MAROON);
DrawModel(map, position, 0.5f, MAROON);
DrawGrid(10.0, 1.0); // Draw a grid
DrawGizmo(position, false);
DrawGizmo(position);
End3dMode();
@ -67,7 +67,7 @@ int main()
// De-Initialization
//--------------------------------------------------------------------------------------
UnloadTexture(tex); // Unload texture
UnloadTexture(texture); // Unload texture
UnloadModel(map); // Unload model
CloseWindow(); // Close window and OpenGL context