From 8ca6f8c6ec0630c27ce5df646ca12859b74ad980 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 1 Mar 2016 15:37:01 +0100 Subject: Do not free model mesh --- src/models.c | 48 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 8a36c279..fc1bb483 100644 --- a/src/models.c +++ b/src/models.c @@ -575,7 +575,7 @@ Model LoadModel(const char *fileName) // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() model = rlglLoadModel(mesh); // Upload vertex data to GPU - // Now that vertex data is uploaded to GPU, we can free arrays + // Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM // NOTE 1: We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes... // NOTE 2: ...but we could keep CPU vertex data in case we need to update the mesh @@ -718,15 +718,8 @@ Model LoadHeightmap(Image heightmap, Vector3 size) Model model = rlglLoadModel(mesh); - // Now that vertex data is uploaded to GPU, we can free arrays - // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2 - if (rlGetVersion() != OPENGL_11) - { - free(mesh.vertices); - free(mesh.texcoords); - free(mesh.normals); - free(mesh.colors); - } + // Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM... + // ...but we keep CPU RAM vertex data in case we need to update the mesh return model; } @@ -1093,15 +1086,8 @@ Model LoadCubicmap(Image cubicmap) Model model = rlglLoadModel(mesh); - // Now that vertex data is uploaded to GPU, we can free arrays - // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2 - if (rlGetVersion() != OPENGL_11) - { - free(mesh.vertices); - free(mesh.texcoords); - free(mesh.normals); - free(mesh.colors); - } + // Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM... + // ...but we keep CPU RAM vertex data in case we need to update the mesh return model; } @@ -1109,16 +1095,20 @@ Model LoadCubicmap(Image cubicmap) // Unload 3d model from memory void UnloadModel(Model model) { - if (rlGetVersion() == OPENGL_11) - { - free(model.mesh.vertices); - free(model.mesh.texcoords); - free(model.mesh.normals); - } - - rlDeleteBuffers(model.mesh.vboId[0]); - rlDeleteBuffers(model.mesh.vboId[1]); - rlDeleteBuffers(model.mesh.vboId[2]); + // Unload mesh data + free(model.mesh.vertices); + free(model.mesh.texcoords); + free(model.mesh.normals); + if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); + if (model.mesh.tangents != NULL) free(model.mesh.tangents); + if (model.mesh.colors != NULL) free(model.mesh.colors); + + rlDeleteBuffers(model.mesh.vboId[0]); // vertex + rlDeleteBuffers(model.mesh.vboId[1]); // texcoords + rlDeleteBuffers(model.mesh.vboId[2]); // normals + rlDeleteBuffers(model.mesh.vboId[3]); // texcoords2 + rlDeleteBuffers(model.mesh.vboId[4]); // tangents + rlDeleteBuffers(model.mesh.vboId[5]); // colors rlDeleteVertexArrays(model.mesh.vaoId); -- cgit v1.2.3 From 1674465bdc17f522013c5552bd154f04254d8e74 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 1 Mar 2016 19:00:12 +0100 Subject: Adjust buffers usage - Removed DrawQuad() function - DrawBillboard() uses DrawBillboardRec() - DrawPlane() uses RL_TRIANGLES - DrawRectangleV() uses RL_TRIANGLES, that way, [shapes] module uses only TRIANGLES buffers. --- src/models.c | 86 ++++++++++++------------------------------------------------ src/raylib.h | 1 - src/shapes.c | 45 +++++++------------------------ 3 files changed, 26 insertions(+), 106 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index fc1bb483..4eb2e104 100644 --- a/src/models.c +++ b/src/models.c @@ -446,41 +446,24 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl // Draw a plane void DrawPlane(Vector3 centerPos, Vector2 size, Color color) { - // NOTE: QUADS usage require defining a texture on OpenGL 3.3+ - if (rlGetVersion() != OPENGL_11) rlEnableTexture(whiteTexture); // Default white texture - // NOTE: Plane is always created on XZ ground rlPushMatrix(); rlTranslatef(centerPos.x, centerPos.y, centerPos.z); rlScalef(size.x, 1.0f, size.y); - rlBegin(RL_QUADS); + rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); rlNormal3f(0.0f, 1.0f, 0.0f); - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, -0.5f); - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(-0.5f, 0.0f, 0.5f); - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(0.5f, 0.0f, 0.5f); - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(0.5f, 0.0f, -0.5f); - rlEnd(); - rlPopMatrix(); - if (rlGetVersion() != OPENGL_11) rlDisableTexture(); -} + rlVertex3f(0.5f, 0.0f, -0.5f); + rlVertex3f(-0.5f, 0.0f, -0.5f); + rlVertex3f(-0.5f, 0.0f, 0.5f); -// Draw a quad -void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color) -{ - // TODO: Calculate normals from vertex position - - rlBegin(RL_QUADS); - rlColor4ub(color.r, color.g, color.b, color.a); - //rlNormal3f(0.0f, 0.0f, 0.0f); - - rlVertex3f(v1.x, v1.y, v1.z); - rlVertex3f(v2.x, v2.y, v2.z); - rlVertex3f(v3.x, v3.y, v3.z); - rlVertex3f(v4.x, v4.y, v4.z); - rlEnd(); + rlVertex3f(-0.5f, 0.0f, 0.5f); + rlVertex3f(0.5f, 0.0f, 0.5f); + rlVertex3f(0.5f, 0.0f, -0.5f); + rlEnd(); + rlPopMatrix(); } // Draw a ray line @@ -1167,60 +1150,25 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float // Draw a billboard void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint) { - // NOTE: Billboard size will maintain texture aspect ratio, size will be billboard width - Vector2 sizeRatio = { size, size * (float)texture.height/texture.width }; - - Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up); - MatrixTranspose(&viewMatrix); - - Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 }; - //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; + Rectangle sourceRec = { 0, 0, texture.width, texture.height }; - // NOTE: Billboard locked to axis-Y - Vector3 up = { 0.0f, 1.0f, 0.0f }; -/* - a-------b - | | - | * | - | | - d-------c -*/ - VectorScale(&right, sizeRatio.x/2); - VectorScale(&up, sizeRatio.y/2); - - Vector3 p1 = VectorAdd(right, up); - Vector3 p2 = VectorSubtract(right, up); - - Vector3 a = VectorSubtract(center, p2); - Vector3 b = VectorAdd(center, p1); - Vector3 c = VectorAdd(center, p2); - Vector3 d = VectorSubtract(center, p1); - - rlEnableTexture(texture.id); - - rlBegin(RL_QUADS); - rlColor4ub(tint.r, tint.g, tint.b, tint.a); - - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(a.x, a.y, a.z); - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(d.x, d.y, d.z); - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(c.x, c.y, c.z); - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(b.x, b.y, b.z); - rlEnd(); - - rlDisableTexture(); + DrawBillboardRec(camera, texture, sourceRec, center, size, tint); } // Draw a billboard (part of a texture defined by a rectangle) void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint) { // NOTE: Billboard size will maintain sourceRec aspect ratio, size will represent billboard width - Vector2 sizeRatio = { size, size * (float)sourceRec.height/sourceRec.width }; + Vector2 sizeRatio = { size, size*(float)sourceRec.height/sourceRec.width }; Matrix viewMatrix = MatrixLookAt(camera.position, camera.target, camera.up); MatrixTranspose(&viewMatrix); Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 }; - Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; + //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; + + // NOTE: Billboard locked on axis-Y + Vector3 up = { 0.0f, 1.0f, 0.0f }; /* a-------b | | @@ -1702,7 +1650,7 @@ static Mesh LoadOBJ(const char *fileName) // 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 + // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face) while(!feof(objFile)) { fscanf(objFile, "%c", &dataType); diff --git a/src/raylib.h b/src/raylib.h index c598ec30..36ca216d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -740,7 +740,6 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ -void DrawQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color); // Draw a quad void DrawRay(Ray ray, Color color); // Draw a ray line void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) void DrawGizmo(Vector3 position); // Draw simple gizmo diff --git a/src/shapes.c b/src/shapes.c index 65e3621b..51730a05 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -180,44 +180,17 @@ void DrawRectangleGradient(int posX, int posY, int width, int height, Color colo // Draw a color-filled rectangle (Vector version) void DrawRectangleV(Vector2 position, Vector2 size, Color color) { - if (rlGetVersion() == OPENGL_11) - { - rlBegin(RL_TRIANGLES); - rlColor4ub(color.r, color.g, color.b, color.a); - - rlVertex2i(position.x, position.y); - rlVertex2i(position.x, position.y + size.y); - rlVertex2i(position.x + size.x, position.y + size.y); - - rlVertex2i(position.x, position.y); - rlVertex2i(position.x + size.x, position.y + size.y); - rlVertex2i(position.x + size.x, position.y); - rlEnd(); - } - else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) - { - // NOTE: This shape uses QUADS to avoid drawing order issues (view rlglDraw) - rlEnableTexture(whiteTexture); // Default white texture - - rlBegin(RL_QUADS); - rlColor4ub(color.r, color.g, color.b, color.a); - rlNormal3f(0.0f, 0.0f, 1.0f); - - rlTexCoord2f(0.0f, 0.0f); - rlVertex2f(position.x, position.y); - - rlTexCoord2f(0.0f, 1.0f); - rlVertex2f(position.x, position.y + size.y); - - rlTexCoord2f(1.0f, 1.0f); - rlVertex2f(position.x + size.x, position.y + size.y); + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); - rlTexCoord2f(1.0f, 0.0f); - rlVertex2f(position.x + size.x, position.y); - rlEnd(); + rlVertex2i(position.x, position.y); + rlVertex2i(position.x, position.y + size.y); + rlVertex2i(position.x + size.x, position.y + size.y); - rlDisableTexture(); - } + rlVertex2i(position.x, position.y); + rlVertex2i(position.x + size.x, position.y + size.y); + rlVertex2i(position.x + size.x, position.y); + rlEnd(); } // Draw rectangle outline -- cgit v1.2.3 From 6106ab8a2eda76454b0cd3ff46a079896a90eee8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 1 Mar 2016 20:26:01 +0100 Subject: Added color to DrawBoundigBox() --- src/models.c | 4 ++-- src/raylib.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 4eb2e104..a3649a07 100644 --- a/src/models.c +++ b/src/models.c @@ -1213,7 +1213,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec } // Draw a bounding box with wires -void DrawBoundingBox(BoundingBox box) +void DrawBoundingBox(BoundingBox box, Color color) { Vector3 size; @@ -1223,7 +1223,7 @@ void DrawBoundingBox(BoundingBox box) Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f }; - DrawCubeWires(center, size.x, size.y, size.z, GREEN); + DrawCubeWires(center, size.x, size.y, size.z, color); } // Detect collision between two spheres diff --git a/src/raylib.h b/src/raylib.h index 36ca216d..73f92fc2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -760,7 +760,7 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint); void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set) void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters -void DrawBoundingBox(BoundingBox box); // Draw bounding box (wires) +void DrawBoundingBox(BoundingBox box, Color color) // Draw bounding box (wires) void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec -- cgit v1.2.3 From 4011c13d4b0b7a684def27bac29f084085bf87a5 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 1 Mar 2016 20:54:02 +0100 Subject: Updated BoundingBox collision detections --- examples/models_box_collisions.c | 40 +++++++++++++++++---------------- src/models.c | 48 +++++++++++++++++----------------------- src/raylib.h | 10 ++++----- 3 files changed, 46 insertions(+), 52 deletions(-) (limited to 'src/models.c') diff --git a/examples/models_box_collisions.c b/examples/models_box_collisions.c index 3751041f..ffd0a2af 100644 --- a/examples/models_box_collisions.c +++ b/examples/models_box_collisions.c @@ -53,27 +53,29 @@ int main() collision = false; // Check collisions player vs enemy-box - if (CheckCollisionBoxes((Vector3){ playerPosition.x - playerSize.x/2, - playerPosition.y - playerSize.y/2, - playerPosition.z - playerSize.z/2 }, - (Vector3){ playerPosition.x + playerSize.x/2, - playerPosition.y + playerSize.y/2, - playerPosition.z + playerSize.z/2 }, - (Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, - enemyBoxPos.y - enemyBoxSize.y/2, - enemyBoxPos.z - enemyBoxSize.z/2 }, - (Vector3){ enemyBoxPos.x + enemyBoxSize.x/2, - enemyBoxPos.y + enemyBoxSize.y/2, - enemyBoxPos.z + enemyBoxSize.z/2 })) collision = true; + if (CheckCollisionBoxes( + (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, + playerPosition.y - playerSize.y/2, + playerPosition.z - playerSize.z/2 }, + (Vector3){ playerPosition.x + playerSize.x/2, + playerPosition.y + playerSize.y/2, + playerPosition.z + playerSize.z/2 }}, + (BoundingBox){(Vector3){ enemyBoxPos.x - enemyBoxSize.x/2, + enemyBoxPos.y - enemyBoxSize.y/2, + enemyBoxPos.z - enemyBoxSize.z/2 }, + (Vector3){ enemyBoxPos.x + enemyBoxSize.x/2, + enemyBoxPos.y + enemyBoxSize.y/2, + enemyBoxPos.z + enemyBoxSize.z/2 }})) collision = true; // Check collisions player vs enemy-sphere - if (CheckCollisionBoxSphere((Vector3){ playerPosition.x - playerSize.x/2, - playerPosition.y - playerSize.y/2, - playerPosition.z - playerSize.z/2 }, - (Vector3){ playerPosition.x + playerSize.x/2, - playerPosition.y + playerSize.y/2, - playerPosition.z + playerSize.z/2 }, - enemySpherePos, enemySphereSize)) collision = true; + if (CheckCollisionBoxSphere( + (BoundingBox){(Vector3){ playerPosition.x - playerSize.x/2, + playerPosition.y - playerSize.y/2, + playerPosition.z - playerSize.z/2 }, + (Vector3){ playerPosition.x + playerSize.x/2, + playerPosition.y + playerSize.y/2, + playerPosition.z + playerSize.z/2 }}, + enemySpherePos, enemySphereSize)) collision = true; if (collision) playerColor = RED; else playerColor = GREEN; diff --git a/src/models.c b/src/models.c index a3649a07..fc95f58d 100644 --- a/src/models.c +++ b/src/models.c @@ -1244,14 +1244,14 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa // Detect collision between two boxes // NOTE: Boxes are defined by two points minimum and maximum -bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2) +bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2) { bool collision = true; - if ((maxBBox1.x >= minBBox2.x) && (minBBox1.x <= maxBBox2.x)) + if ((box1.max.x >= box2.min.x) && (box1.min.x <= box2.max.x)) { - if ((maxBBox1.y < minBBox2.y) || (minBBox1.y > maxBBox2.y)) collision = false; - if ((maxBBox1.z < minBBox2.z) || (minBBox1.z > maxBBox2.z)) collision = false; + if ((box1.max.y < box2.min.y) || (box1.min.y > box2.max.y)) collision = false; + if ((box1.max.z < box2.min.z) || (box1.min.z > box2.max.z)) collision = false; } else collision = false; @@ -1259,30 +1259,22 @@ bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, V } // Detect collision between box and sphere -bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere) +bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere) { bool collision = false; - if ((centerSphere.x - minBBox.x > radiusSphere) && (centerSphere.y - minBBox.y > radiusSphere) && (centerSphere.z - minBBox.z > radiusSphere) && - (maxBBox.x - centerSphere.x > radiusSphere) && (maxBBox.y - centerSphere.y > radiusSphere) && (maxBBox.z - centerSphere.z > radiusSphere)) - { - collision = true; - } - else - { - float dmin = 0; + float dmin = 0; - if (centerSphere.x - minBBox.x <= radiusSphere) dmin += (centerSphere.x - minBBox.x)*(centerSphere.x - minBBox.x); - else if (maxBBox.x - centerSphere.x <= radiusSphere) dmin += (centerSphere.x - maxBBox.x)*(centerSphere.x - maxBBox.x); + if (centerSphere.x < box.min.x) dmin += pow(centerSphere.x - box.min.x, 2); + else if (centerSphere.x > box.max.x) dmin += pow(centerSphere.x - box.max.x, 2); - if (centerSphere.y - minBBox.y <= radiusSphere) dmin += (centerSphere.y - minBBox.y)*(centerSphere.y - minBBox.y); - else if (maxBBox.y - centerSphere.y <= radiusSphere) dmin += (centerSphere.y - maxBBox.y)*(centerSphere.y - maxBBox.y); + if (centerSphere.y < box.min.y) dmin += pow(centerSphere.y - box.min.y, 2); + else if (centerSphere.y > box.max.y) dmin += pow(centerSphere.y - box.max.y, 2); - if (centerSphere.z - minBBox.z <= radiusSphere) dmin += (centerSphere.z - minBBox.z)*(centerSphere.z - minBBox.z); - else if (maxBBox.z - centerSphere.z <= radiusSphere) dmin += (centerSphere.z - maxBBox.z)*(centerSphere.z - maxBBox.z); + if (centerSphere.z < box.min.z) dmin += pow(centerSphere.z - box.min.z, 2); + else if (centerSphere.z > box.max.z) dmin += pow(centerSphere.z - box.max.z, 2); - if (dmin <= radiusSphere*radiusSphere) collision = true; - } + if (dmin <= (radiusSphere*radiusSphere)) collision = true; return collision; } @@ -1333,17 +1325,17 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi } // Detect collision between ray and bounding box -bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox) +bool CheckCollisionRayBox(Ray ray, BoundingBox box) { bool collision = false; float t[8]; - t[0] = (minBBox.x - ray.position.x)/ray.direction.x; - t[1] = (maxBBox.x - ray.position.x)/ray.direction.x; - t[2] = (minBBox.y - ray.position.y)/ray.direction.y; - t[3] = (maxBBox.y - ray.position.y)/ray.direction.y; - t[4] = (minBBox.z - ray.position.z)/ray.direction.z; - t[5] = (maxBBox.z - ray.position.z)/ray.direction.z; + t[0] = (box.min.x - ray.position.x)/ray.direction.x; + t[1] = (box.max.x - ray.position.x)/ray.direction.x; + t[2] = (box.min.y - ray.position.y)/ray.direction.y; + t[3] = (box.max.y - ray.position.y)/ray.direction.y; + t[4] = (box.min.z - ray.position.z)/ray.direction.z; + t[5] = (box.max.z - ray.position.z)/ray.direction.z; t[6] = fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); t[7] = fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); diff --git a/src/raylib.h b/src/raylib.h index 73f92fc2..b7dc1a8c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -760,18 +760,18 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint); void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set) void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters -void DrawBoundingBox(BoundingBox box, Color color) // Draw bounding box (wires) +void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec -BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits +BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres -bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2); // Detect collision between two boxes -bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere +bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Detect collision between two bounding boxes +bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius); // Detect collision between ray and sphere bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint); // Detect collision between ray and sphere with extended parameters and collision point detection -bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox); // Detect collision between ray and box +bool CheckCollisionRayBox(Ray ray, BoundingBox box); // Detect collision between ray and box Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Detect collision of player radius with cubicmap // NOTE: Return the normal vector of the impacted surface //------------------------------------------------------------------------------------ -- cgit v1.2.3 From d8bd8634ab7d5179cb1481206176af1f8e592e75 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 5 Mar 2016 13:05:45 +0100 Subject: 3d Camera: Added support for field-of-view Y --- examples/core_3d_camera_first_person.c | 3 ++- examples/core_3d_camera_free.c | 2 ++ examples/core_3d_mode.c | 1 + examples/core_3d_picking.c | 2 ++ examples/core_world_screen.c | 3 ++- examples/models_billboard.c | 3 ++- examples/models_box_collisions.c | 2 +- examples/models_cubicmap.c | 3 ++- examples/models_geometric_shapes.c | 2 +- examples/models_heightmap.c | 2 +- examples/models_obj_loading.c | 2 +- examples/shaders_basic_lighting.c | 2 +- examples/shaders_custom_uniform.c | 2 +- examples/shaders_model_shader.c | 2 +- examples/shaders_postprocessing.c | 2 +- src/camera.c | 8 +++++++- src/camera.h | 1 + src/core.c | 20 ++++++++++---------- src/models.c | 28 +++++++++------------------- src/raylib.h | 9 +++++---- 20 files changed, 53 insertions(+), 46 deletions(-) (limited to 'src/models.c') diff --git a/examples/core_3d_camera_first_person.c b/examples/core_3d_camera_first_person.c index 2b8dc7fc..16d388df 100644 --- a/examples/core_3d_camera_first_person.c +++ b/examples/core_3d_camera_first_person.c @@ -23,7 +23,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person"); // Define the camera to look into our 3d world (position, target, up vector) - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 60.0f }; // Generates some random columns float heights[MAX_COLUMNS]; @@ -40,6 +40,7 @@ int main() Vector3 playerPosition = { 4.0f, 2.0f, 4.0f }; // Define player position SetCameraMode(CAMERA_FIRST_PERSON); // Set a first person camera mode + SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/core_3d_camera_free.c b/examples/core_3d_camera_free.c index 4b45373d..234c46b3 100644 --- a/examples/core_3d_camera_free.c +++ b/examples/core_3d_camera_free.c @@ -25,12 +25,14 @@ int main() camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position SetCameraTarget(camera.target); // Set internal camera target to match our camera target + SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/core_3d_mode.c b/examples/core_3d_mode.c index 7be5dd45..5f761655 100644 --- a/examples/core_3d_mode.c +++ b/examples/core_3d_mode.c @@ -25,6 +25,7 @@ int main() camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c index 612f6374..33eaed8a 100644 --- a/examples/core_3d_picking.c +++ b/examples/core_3d_picking.c @@ -25,6 +25,7 @@ int main() camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; // Camera position camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; @@ -35,6 +36,7 @@ int main() SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position + SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/core_world_screen.c b/examples/core_world_screen.c index b70b40dd..d89a296b 100644 --- a/examples/core_world_screen.c +++ b/examples/core_world_screen.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; @@ -30,6 +30,7 @@ int main() SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position SetCameraTarget(camera.target); // Set internal camera target to match our camera target + SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/models_billboard.c b/examples/models_billboard.c index bac42d35..654b3618 100644 --- a/examples/models_billboard.c +++ b/examples/models_billboard.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards"); // Define the camera to look into our 3d world - Camera camera = {{ 5.0f, 4.0f, 5.0f }, { 0.0f, 2.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 5.0f, 4.0f, 5.0f }, { 0.0f, 2.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard @@ -29,6 +29,7 @@ int main() SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position SetCameraTarget(camera.target); // Set internal camera target to match our camera target + SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/models_box_collisions.c b/examples/models_box_collisions.c index ffd0a2af..69cec418 100644 --- a/examples/models_box_collisions.c +++ b/examples/models_box_collisions.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Vector3 playerPosition = { 0.0f, 1.0f, 2.0f }; Vector3 playerSize = { 1.0f, 2.0f, 1.0f }; diff --git a/examples/models_cubicmap.c b/examples/models_cubicmap.c index e2a902ef..1ca27dfd 100644 --- a/examples/models_cubicmap.c +++ b/examples/models_cubicmap.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing"); // Define the camera to look into our 3d world - Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) @@ -37,6 +37,7 @@ int main() SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraPosition(camera.position); // Set internal camera position to match our custom camera position + SetCameraFovy(camera.fovy); // Set internal camera field-of-view Y SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/models_geometric_shapes.c b/examples/models_geometric_shapes.c index 9ea5b423..a13a1f3b 100644 --- a/examples/models_geometric_shapes.c +++ b/examples/models_geometric_shapes.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c index f1da3301..c8e5ff35 100644 --- a/examples/models_heightmap.c +++ b/examples/models_heightmap.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing"); // Define our custom camera to look into our 3d world - Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 18.0f, 16.0f, 18.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) diff --git a/examples/models_obj_loading.c b/examples/models_obj_loading.c index 41f4569a..e8dd0adc 100644 --- a/examples/models_obj_loading.c +++ b/examples/models_obj_loading.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture diff --git a/examples/shaders_basic_lighting.c b/examples/shaders_basic_lighting.c index 84bd1af4..18aea8e1 100644 --- a/examples/shaders_basic_lighting.c +++ b/examples/shaders_basic_lighting.c @@ -36,7 +36,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting"); // Camera initialization - Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; // Model initialization Vector3 position = { 0.0f, 0.0f, 0.0f }; diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c index 0377cfff..ecfbaa71 100644 --- a/examples/shaders_custom_uniform.c +++ b/examples/shaders_custom_uniform.c @@ -30,7 +30,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - custom uniform variable"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture diff --git a/examples/shaders_model_shader.c b/examples/shaders_model_shader.c index 5d8c3711..a10ec235 100644 --- a/examples/shaders_model_shader.c +++ b/examples/shaders_model_shader.c @@ -30,7 +30,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index 0f851658..44829648 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -30,7 +30,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing shader"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture diff --git a/src/camera.c b/src/camera.c index 517e4a2b..8e5c527e 100644 --- a/src/camera.c +++ b/src/camera.c @@ -84,7 +84,7 @@ typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_D //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static Camera internalCamera = {{ 2.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; +static Camera internalCamera = {{ 2.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; static Vector2 cameraAngle = { 0.0f, 0.0f }; static float cameraTargetDistance = 5.0f; static Vector2 cameraMousePosition = { 0.0f, 0.0f }; @@ -212,6 +212,12 @@ void SetCameraTarget(Vector3 target) cameraTargetDistance = sqrt(dx*dx + dy*dy + dz*dz); } +// Set internal camera fovy +void SetCameraFovy(float fovy) +{ + internalCamera.fovy = fovy; +} + // Set camera pan key to combine with mouse movement (free camera) void SetCameraPanControl(int panKey) { diff --git a/src/camera.h b/src/camera.h index 9ad09c6f..8d8029af 100644 --- a/src/camera.h +++ b/src/camera.h @@ -81,6 +81,7 @@ void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and void SetCameraPosition(Vector3 position); // Set internal camera position void SetCameraTarget(Vector3 target); // Set internal camera target +void SetCameraFovy(float fovy); // Set internal camera field-of-view-y void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera) void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera) diff --git a/src/core.c b/src/core.c index 259e1f29..a8cc593a 100644 --- a/src/core.c +++ b/src/core.c @@ -609,10 +609,10 @@ void Begin3dMode(Camera camera) rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection rlLoadIdentity(); // Reset current matrix (PROJECTION) - + // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.01*tan(45.0*PI/360.0); + double top = 0.01*tan(camera.fovy*PI/360.0); double right = top*aspect; // NOTE: zNear and zFar values are important when computing depth buffer values @@ -883,7 +883,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) TraceLog(DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); // Calculate projection matrix (from perspective instead of frustum) - Matrix matProj = MatrixPerspective(45.0, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); + Matrix matProj = MatrixPerspective(camera.fovy, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); // Calculate view matrix from camera look at Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); @@ -936,7 +936,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) Vector2 WorldToScreen(Vector3 position, Camera camera) { // Calculate projection matrix (from perspective instead of frustum - Matrix matProj = MatrixPerspective(45.0f, (float)((float)GetScreenWidth() / (float)GetScreenHeight()), 0.01f, 1000.0f); + Matrix matProj = MatrixPerspective(camera.fovy, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); // Calculate view matrix from camera look at (and transpose it) Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); @@ -1752,8 +1752,8 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Normalize gestureEvent.position[0] for screenWidth and screenHeight gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); - - // Gesture data is sent to gestures system for processing + + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); #endif } @@ -1890,7 +1890,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // TODO: GPU assets reload in case of lost focus (lost context) // NOTE: This problem has been solved just unbinding and rebinding context from display - /* + /* if (assetsReloadRequired) { for (int i = 0; i < assetsCount; i++) @@ -2471,9 +2471,9 @@ static void *GamepadThread(void *arg) const int joystickAxisY = 1; // Read gamepad event - struct js_event gamepadEvent; + struct js_event gamepadEvent; - while (1) + while (1) { if (read(gamepadStream, &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event)) { @@ -2507,7 +2507,7 @@ static void *GamepadThread(void *arg) */ } } - } + } return NULL; } diff --git a/src/models.c b/src/models.c index fc95f58d..a0b0e656 100644 --- a/src/models.c +++ b/src/models.c @@ -558,19 +558,9 @@ Model LoadModel(const char *fileName) // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() model = rlglLoadModel(mesh); // Upload vertex data to GPU - // Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM - // NOTE 1: We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes... - // NOTE 2: ...but we could keep CPU vertex data in case we need to update the mesh - - /* - if (rlGetVersion() != OPENGL_11) - { - free(mesh.vertices); - free(mesh.texcoords); - free(mesh.normals); - free(mesh.colors); - } - */ + // NOTE: Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM + // We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes... + // ...but we could keep CPU vertex data in case we need to update the mesh } return model; @@ -1082,16 +1072,16 @@ void UnloadModel(Model model) free(model.mesh.vertices); free(model.mesh.texcoords); free(model.mesh.normals); - if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); - if (model.mesh.tangents != NULL) free(model.mesh.tangents); - if (model.mesh.colors != NULL) free(model.mesh.colors); + free(model.mesh.colors); + //if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); // Not used + //if (model.mesh.tangents != NULL) free(model.mesh.tangents); // Not used rlDeleteBuffers(model.mesh.vboId[0]); // vertex rlDeleteBuffers(model.mesh.vboId[1]); // texcoords rlDeleteBuffers(model.mesh.vboId[2]); // normals - rlDeleteBuffers(model.mesh.vboId[3]); // texcoords2 - rlDeleteBuffers(model.mesh.vboId[4]); // tangents - rlDeleteBuffers(model.mesh.vboId[5]); // colors + //rlDeleteBuffers(model.mesh.vboId[3]); // texcoords2 (NOT USED) + //rlDeleteBuffers(model.mesh.vboId[4]); // tangents (NOT USED) + //rlDeleteBuffers(model.mesh.vboId[5]); // colors (NOT USED) rlDeleteVertexArrays(model.mesh.vaoId); diff --git a/src/raylib.h b/src/raylib.h index 00afb4f3..b6cf98fe 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -309,10 +309,10 @@ typedef struct SpriteFont { // Camera type, defines a camera position/orientation in 3d space typedef struct Camera { - Vector3 position; - Vector3 target; - Vector3 up; - //float fovy; // Field-Of-View apperture in Y (degrees) + Vector3 position; // Camera position + Vector3 target; // Camera target it looks-at + Vector3 up; // Camera up vector (rotation over its axis) + float fovy; // Field-Of-View apperture in Y (degrees) } Camera; // Bounding box type @@ -630,6 +630,7 @@ void UpdateCameraPlayer(Camera *camera, Vector3 *position); // Update camera and void SetCameraPosition(Vector3 position); // Set internal camera position void SetCameraTarget(Vector3 target); // Set internal camera target +void SetCameraFovy(float fovy); // Set internal camera field-of-view-y void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera) void SetCameraAltControl(int altKey); // Set camera alt key to combine with mouse movement (free camera) -- cgit v1.2.3 From 0d911127d759e3f507b598c1666da1635c863e51 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 5 Mar 2016 16:17:54 +0100 Subject: Split mesh generation from model loading --- src/models.c | 138 ++++++++++++++++++++++++++++++----------------------------- src/raylib.h | 2 +- 2 files changed, 71 insertions(+), 69 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index a0b0e656..ee5e57c7 100644 --- a/src/models.c +++ b/src/models.c @@ -56,6 +56,8 @@ extern unsigned int whiteTexture; // Module specific Functions Declaration //---------------------------------------------------------------------------------- static Mesh LoadOBJ(const char *fileName); +static Mesh GenMeshHeightmap(Image image, Vector3 size); +static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -582,6 +584,63 @@ Model LoadModelEx(Mesh data) // Load a heightmap image as a 3d model // NOTE: model map size is defined in generic units Model LoadHeightmap(Image heightmap, Vector3 size) +{ + Mesh mesh = GenMeshHeightmap(heightmap, size); + Model model = rlglLoadModel(mesh); + + return model; +} + +// Load a map image as a 3d model (cubes based) +Model LoadCubicmap(Image cubicmap) +{ + Mesh mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f }); + Model model = rlglLoadModel(mesh); + + return model; +} + +// Unload 3d model from memory +void UnloadModel(Model model) +{ + // Unload mesh data + free(model.mesh.vertices); + free(model.mesh.texcoords); + free(model.mesh.normals); + free(model.mesh.colors); + //if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); // Not used + //if (model.mesh.tangents != NULL) free(model.mesh.tangents); // Not used + + rlDeleteBuffers(model.mesh.vboId[0]); // vertex + rlDeleteBuffers(model.mesh.vboId[1]); // texcoords + rlDeleteBuffers(model.mesh.vboId[2]); // normals + //rlDeleteBuffers(model.mesh.vboId[3]); // texcoords2 (NOT USED) + //rlDeleteBuffers(model.mesh.vboId[4]); // tangents (NOT USED) + //rlDeleteBuffers(model.mesh.vboId[5]); // colors (NOT USED) + + rlDeleteVertexArrays(model.mesh.vaoId); + + if (model.mesh.vaoId > 0) TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vaoId); + else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]); +} + +// Link a texture to a model +void SetModelTexture(Model *model, Texture2D texture) +{ + if (texture.id <= 0) + { + // Use default white texture (use mesh color) + model->texture.id = whiteTexture; // OpenGL 1.1 + model->shader.texDiffuseId = whiteTexture; // OpenGL 3.3 / ES 2.0 + } + else + { + model->texture = texture; + model->shader.texDiffuseId = texture.id; + } +} + +static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) @@ -687,27 +746,17 @@ Model LoadHeightmap(Image heightmap, Vector3 size) // NOTE: Not used any more... just one plain color defined at DrawModel() for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; - // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - - Model model = rlglLoadModel(mesh); - - // Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM... - // ...but we keep CPU RAM vertex data in case we need to update the mesh - - return model; + return mesh; } -// Load a map image as a 3d model (cubes based) -Model LoadCubicmap(Image cubicmap) +static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { Mesh mesh; Color *cubicmapPixels = GetImageData(cubicmap); - // Map cube size will be 1.0 - float mapCubeSide = 1.0f; - int mapWidth = cubicmap.width*(int)mapCubeSide; - int mapHeight = cubicmap.height*(int)mapCubeSide; + int mapWidth = cubicmap.width*(int)cubeSize.x; + int mapHeight = cubicmap.height*(int)cubeSize.z; // NOTE: Max possible number of triangles numCubes * (12 triangles by cube) int maxTriangles = cubicmap.width*cubicmap.height*12; @@ -716,9 +765,9 @@ Model LoadCubicmap(Image cubicmap) int tcCounter = 0; // Used to count texcoords int nCounter = 0; // Used to count normals - float w = mapCubeSide; - float h = mapCubeSide; - float h2 = mapCubeSide*1.5f; // TODO: Review walls height... + float w = cubeSize.x; + float h = cubeSize.z; + float h2 = cubeSize.y; Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles*3*sizeof(Vector3)); Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles*3*sizeof(Vector2)); @@ -747,9 +796,9 @@ Model LoadCubicmap(Image cubicmap) RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f }; RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f }; - for (int z = 0; z < mapHeight; z += mapCubeSide) + for (int z = 0; z < mapHeight; z += cubeSize.z) { - for (int x = 0; x < mapWidth; x += mapCubeSide) + for (int x = 0; x < mapWidth; x += cubeSize.x) { // Define the 8 vertex of the cube, we will combine them accordingly later... Vector3 v1 = { x - w/2, h2, z - h/2 }; @@ -1053,56 +1102,9 @@ Model LoadCubicmap(Image cubicmap) free(mapNormals); free(mapTexcoords); - free(cubicmapPixels); - - // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - - Model model = rlglLoadModel(mesh); - - // Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM... - // ...but we keep CPU RAM vertex data in case we need to update the mesh - - return model; -} - -// Unload 3d model from memory -void UnloadModel(Model model) -{ - // Unload mesh data - free(model.mesh.vertices); - free(model.mesh.texcoords); - free(model.mesh.normals); - free(model.mesh.colors); - //if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); // Not used - //if (model.mesh.tangents != NULL) free(model.mesh.tangents); // Not used + free(cubicmapPixels); // Free image pixel data - rlDeleteBuffers(model.mesh.vboId[0]); // vertex - rlDeleteBuffers(model.mesh.vboId[1]); // texcoords - rlDeleteBuffers(model.mesh.vboId[2]); // normals - //rlDeleteBuffers(model.mesh.vboId[3]); // texcoords2 (NOT USED) - //rlDeleteBuffers(model.mesh.vboId[4]); // tangents (NOT USED) - //rlDeleteBuffers(model.mesh.vboId[5]); // colors (NOT USED) - - rlDeleteVertexArrays(model.mesh.vaoId); - - if (model.mesh.vaoId > 0) TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]); -} - -// Link a texture to a model -void SetModelTexture(Model *model, Texture2D texture) -{ - if (texture.id <= 0) - { - // Use default white texture (use mesh color) - model->texture.id = whiteTexture; // OpenGL 1.1 - model->shader.texDiffuseId = whiteTexture; // OpenGL 3.3 / ES 2.0 - } - else - { - model->texture = texture; - model->shader.texDiffuseId = texture.id; - } + return mesh; } // Draw a model (with texture if set) diff --git a/src/raylib.h b/src/raylib.h index 7173a556..9545f96d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -761,7 +761,7 @@ void DrawGizmo(Vector3 position); // Model 3d Loading and Drawing Functions (Module: models) //------------------------------------------------------------------------------------ Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) -Model LoadModelEx(Mesh data); // Load a 3d model (from vertex data) +Model LoadModelEx(Mesh data); // Load a 3d model (from mesh data) //Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) -- cgit v1.2.3 From c9d22c7a14a84b24a94f876c9e438c621b4bf420 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 6 Mar 2016 02:05:16 +0100 Subject: Redesign to use Material type -IN PROGRESS- Requires Shader access functions review --- src/models.c | 18 +---- src/raylib.h | 40 ++++------ src/rlgl.c | 240 +++++++++++++---------------------------------------------- src/rlgl.h | 24 ++++-- 4 files changed, 89 insertions(+), 233 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index ee5e57c7..a1590424 100644 --- a/src/models.c +++ b/src/models.c @@ -551,10 +551,7 @@ Model LoadModel(const char *fileName) // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - if (mesh.vertexCount == 0) - { - TraceLog(WARNING, "Model could not be loaded"); - } + if (mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); else { // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() @@ -627,17 +624,8 @@ void UnloadModel(Model model) // Link a texture to a model void SetModelTexture(Model *model, Texture2D texture) { - if (texture.id <= 0) - { - // Use default white texture (use mesh color) - model->texture.id = whiteTexture; // OpenGL 1.1 - model->shader.texDiffuseId = whiteTexture; // OpenGL 3.3 / ES 2.0 - } - else - { - model->texture = texture; - model->shader.texDiffuseId = texture.id; - } + if (texture.id <= 0) model->material.texDiffuse.id = whiteTexture; // Use default white texture + else model->material.texDiffuse = texture; } static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) diff --git a/src/raylib.h b/src/raylib.h index 83e41ac7..f448487e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -347,12 +347,7 @@ typedef struct Mesh { // Shader type (generic shader) typedef struct Shader { - unsigned int id; // Shader program id - - // TODO: This should be Texture2D objects - unsigned int texDiffuseId; // Diffuse texture id - unsigned int texNormalId; // Normal texture id - unsigned int texSpecularId; // Specular texture id + unsigned int id; // Shader program id // Variable attributes int vertexLoc; // Vertex attribute location point (vertex shader) @@ -370,20 +365,19 @@ typedef struct Shader { } Shader; // Material type -// TODO: Redesign material-shaders-textures system typedef struct Material { - //Shader shader; + Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) - //Texture2D texDiffuse; // Diffuse texture - //Texture2D texNormal; // Normal texture - //Texture2D texSpecular; // Specular texture + Texture2D texDiffuse; // Diffuse texture + Texture2D texNormal; // Normal texture + Texture2D texSpecular; // Specular texture - Color colDiffuse; - Color colAmbient; - Color colSpecular; + Color colDiffuse; // Diffuse color + Color colAmbient; // Ambient color + Color colSpecular; // Specular color - float glossiness; - float normalDepth; + float glossiness; // Glossiness level + float normalDepth; // Normal map depth } Material; // 3d Model type @@ -391,9 +385,7 @@ typedef struct Material { typedef struct Model { Mesh mesh; Matrix transform; - Texture2D texture; // Only for OpenGL 1.1, on newer versions this should be in the shader - Shader shader; - //Material material; + Material material; } Model; // Ray type (useful for raycast) @@ -774,7 +766,7 @@ void SetModelTexture(Model *model, Texture2D texture); void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set) -void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters +void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture @@ -806,10 +798,10 @@ int GetShaderLocation(Shader shader, const char *uniformName); void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) -void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment -void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment -void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment -void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment +//void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment +//void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment +//void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment +//void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) diff --git a/src/rlgl.c b/src/rlgl.c index e1949274..d9761732 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1421,7 +1421,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, model.texture.id); + glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array @@ -1452,7 +1452,7 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(model.shader.id); + glUseProgram(model.material.shader.id); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -1476,28 +1476,30 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates // Send combined model-view-projection matrix to shader - glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + glUniformMatrix4fv(model.material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); // Apply color tinting to model // NOTE: Just update one uniform on fragment shader float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 }; - glUniform4fv(model.shader.tintColorLoc, 1, vColor); + glUniform4fv(model.material.shader.tintColorLoc, 1, vColor); // Set shader textures (diffuse, normal, specular) glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, model.shader.texDiffuseId); - glUniform1i(model.shader.mapDiffuseLoc, 0); - - if (model.shader.texNormalId != 0) + glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id); + glUniform1i(model.material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 + + if (model.material.texNormal.id != 0) { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, model.shader.texNormalId); + glBindTexture(GL_TEXTURE_2D, model.material.texNormal.id); + glUniform1i(model.material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 } - if (model.shader.texSpecularId != 0) + if (model.material.texSpecular.id != 0) { glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, model.shader.texSpecularId); + glBindTexture(GL_TEXTURE_2D, model.material.texSpecular.id); + glUniform1i(model.material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 } if (vaoSupported) @@ -1508,19 +1510,19 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro { // Bind model VBOs data glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[0]); - glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.shader.vertexLoc); + glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(model.material.shader.vertexLoc); glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[1]); - glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.shader.texcoordLoc); + glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(model.material.shader.texcoordLoc); // Add normals support - if (model.shader.normalLoc != -1) + if (model.material.shader.normalLoc != -1) { glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]); - glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.shader.normalLoc); + glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(model.material.shader.normalLoc); } } @@ -1531,13 +1533,13 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro //glDisableVertexAttribArray(model.shader.texcoordLoc); //if (model.shader.normalLoc != -1) glDisableVertexAttribArray(model.shader.normalLoc); - if (model.shader.texNormalId != 0) + if (model.material.texNormal.id != 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); } - if (model.shader.texSpecularId != 0) + if (model.material.texSpecular.id != 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); @@ -1907,22 +1909,29 @@ Model rlglLoadModel(Mesh mesh) Model model; model.mesh = mesh; - model.transform = MatrixIdentity(); model.mesh.vaoId = 0; // Vertex Array Object - model.mesh.vboId[0] = 0; // Vertex position VBO - model.mesh.vboId[1] = 0; // Texcoords VBO - model.mesh.vboId[2] = 0; // Normals VBO + model.mesh.vboId[0] = 0; // Vertex positions VBO + model.mesh.vboId[1] = 0; // Vertex texcoords VBO + model.mesh.vboId[2] = 0; // Vertex normals VBO + + model.transform = MatrixIdentity(); #if defined(GRAPHICS_API_OPENGL_11) - model.texture.id = 0; // No texture required - model.shader.id = 0; // No shader used + model.material.texDiffuse.id = 0; // No texture required + model.material.shader.id = 0; // No shader used #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - model.texture.id = whiteTexture; // Default whiteTexture - model.texture.width = 1; // Default whiteTexture width - model.texture.height = 1; // Default whiteTexture height - model.texture.format = UNCOMPRESSED_R8G8B8A8; // Default whiteTexture format - model.shader = simpleShader; // Default model shader + model.material.shader = simpleShader; // Default model shader + + model.material.texDiffuse.id = whiteTexture; // Default whiteTexture + model.material.texDiffuse.width = 1; // Default whiteTexture width + model.material.texDiffuse.height = 1; // Default whiteTexture height + model.material.texDiffuse.format = UNCOMPRESSED_R8G8B8A8; // Default whiteTexture format + + model.material.texNormal.id = 0; // By default, no normal texture + model.material.texSpecular.id = 0; // By default, no specular texture + + // TODO: Fill default material properties (color, glossiness...) GLuint vaoModel = 0; // Vertex Array Objects (VAO) GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO) @@ -1940,20 +1949,20 @@ Model rlglLoadModel(Mesh mesh) // Enable vertex attributes: position glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW); - glVertexAttribPointer(model.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.shader.vertexLoc); + glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(model.material.shader.vertexLoc); // Enable vertex attributes: texcoords glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW); - glVertexAttribPointer(model.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.shader.texcoordLoc); + glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(model.material.shader.texcoordLoc); // Enable vertex attributes: normals glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW); - glVertexAttribPointer(model.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.shader.normalLoc); + glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(model.material.shader.normalLoc); model.mesh.vboId[0] = vertexBuffer[0]; // Vertex position VBO model.mesh.vboId[1] = vertexBuffer[1]; // Texcoords VBO @@ -2153,11 +2162,6 @@ Shader LoadShader(char *vsFileName, char *fsFileName) if (shader.id != 0) { TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id); - - // Set shader textures ids (all 0 by default) - shader.texDiffuseId = 0; - shader.texNormalId = 0; - shader.texSpecularId = 0; // Get handles to GLSL input attibute locations //------------------------------------------------------------------- @@ -2314,28 +2318,7 @@ void SetCustomShader(Shader shader) if (currentShader.id != shader.id) { rlglDraw(); - currentShader = shader; -/* - if (vaoSupported) glBindVertexArray(vaoQuads); - - // Enable vertex attributes: position - glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - - // Enable vertex attributes: texcoords - glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); - glEnableVertexAttribArray(currentShader.texcoordLoc); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - - // Enable vertex attributes: colors - glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - - if (vaoSupported) glBindVertexArray(0); // Unbind VAO -*/ } #endif } @@ -2358,7 +2341,7 @@ void SetPostproShader(Shader shader) texture.width = screenWidth; texture.height = screenHeight; - SetShaderMapDiffuse(&postproQuad.shader, texture); + postproQuad.material.texDiffuse = texture; //TraceLog(DEBUG, "Postproquad texture id: %i", postproQuad.texture.id); //TraceLog(DEBUG, "Postproquad shader diffuse map id: %i", postproQuad.shader.texDiffuseId); @@ -2386,7 +2369,7 @@ void SetDefaultShader(void) void SetModelShader(Model *model, Shader shader) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - model->shader = shader; + model->material.shader = shader; if (vaoSupported) glBindVertexArray(model->mesh.vaoId); @@ -2406,9 +2389,7 @@ void SetModelShader(Model *model, Shader shader) glVertexAttribPointer(shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); if (vaoSupported) glBindVertexArray(0); // Unbind VAO - - // NOTE: If SetModelTexture() is called previously, texture is not assigned to new shader - if (model->texture.id > 0) model->shader.texDiffuseId = model->texture.id; + #elif (GRAPHICS_API_OPENGL_11) TraceLog(WARNING, "Shaders not supported on OpenGL 1.1"); #endif @@ -2480,104 +2461,6 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) #endif } -// Default diffuse shader map texture assignment -void SetShaderMapDiffuse(Shader *shader, Texture2D texture) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - shader->texDiffuseId = texture.id; - - glUseProgram(shader->id); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, shader->texDiffuseId); - - glUniform1i(shader->mapDiffuseLoc, 0); // Texture fits in active texture unit 0 - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - glUseProgram(0); -#endif -} - -// Normal map texture shader assignment -void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - shader->mapNormalLoc = glGetUniformLocation(shader->id, uniformName); - - if (shader->mapNormalLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName); - else - { - shader->texNormalId = texture.id; - - glUseProgram(shader->id); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, shader->texNormalId); - - glUniform1i(shader->mapNormalLoc, 1); // Texture fits in active texture unit 1 - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - glUseProgram(0); - } -#endif -} - -// Specular map texture shader assignment -void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - shader->mapSpecularLoc = glGetUniformLocation(shader->id, uniformName); - - if (shader->mapSpecularLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName); - else - { - shader->texSpecularId = texture.id; - - glUseProgram(shader->id); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, shader->texSpecularId); - - glUniform1i(shader->mapSpecularLoc, 2); // Texture fits in active texture unit 2 - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - glUseProgram(0); - } -#endif -} - -// Generic shader maps assignment -// TODO: Trying to find a generic shader to allow any kind of map -// NOTE: mapLocation should be retrieved by user with GetShaderLocation() -// ISSUE: mapTextureId: Shader should contain a reference to map texture and corresponding textureUnit, -// so it can be automatically checked and used in rlglDrawModel() -void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit) -{ -/* -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (mapLocation == -1) TraceLog(WARNING, "[SHDR ID %i] Map location could not be found", shader->id); - else - { - shader->mapTextureId = texture.id; - - glUseProgram(shader->id); - - glActiveTexture(GL_TEXTURE0 + textureUnit); - glBindTexture(GL_TEXTURE_2D, shader->mapTextureId); - - glUniform1i(mapLocation, textureUnit); // Texture fits in active textureUnit - - glBindTexture(GL_TEXTURE_2D, 0); - glActiveTexture(GL_TEXTURE0); - glUseProgram(0); - } -#endif -*/ -} - // Set blending mode (alpha, additive, multiplied) // NOTE: Only 3 blending modes predefined void SetBlendMode(int mode) @@ -2652,15 +2535,11 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in } // Load Shader (Vertex and Fragment) -// NOTE: This shader program is used only for batch buffers (lines, triangles, quads) +// NOTE: This shader program is used for batch buffers (lines, triangles, quads) static Shader LoadDefaultShader(void) { Shader shader; - // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 - // NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+ - // Just defined #version 330 despite shader is #version 110 - // Vertex shader directly defined, no external file required #if defined(GRAPHICS_API_OPENGL_33) char vShaderStr[] = "#version 330 \n" @@ -2668,7 +2547,7 @@ static Shader LoadDefaultShader(void) "in vec2 vertexTexCoord; \n" "in vec4 vertexColor; \n" "out vec2 fragTexCoord; \n" - "out vec4 fragTintColor; \n" + "out vec4 fragTintColor; \n" #elif defined(GRAPHICS_API_OPENGL_ES2) char vShaderStr[] = "#version 100 \n" "attribute vec3 vertexPosition; \n" @@ -2677,7 +2556,7 @@ static Shader LoadDefaultShader(void) "varying vec2 fragTexCoord; \n" "varying vec4 fragTintColor; \n" #endif - "uniform mat4 mvpMatrix; \n" + "uniform mat4 mvpMatrix; \n" "void main() \n" "{ \n" " fragTexCoord = vertexTexCoord; \n" @@ -2689,7 +2568,7 @@ static Shader LoadDefaultShader(void) #if defined(GRAPHICS_API_OPENGL_33) char fShaderStr[] = "#version 330 \n" "in vec2 fragTexCoord; \n" - "in vec4 fragTintColor; \n" + "in vec4 fragTintColor; \n" #elif defined(GRAPHICS_API_OPENGL_ES2) char fShaderStr[] = "#version 100 \n" "precision mediump float; \n" // precision required for OpenGL ES2 (WebGL) @@ -2724,10 +2603,6 @@ static Shader LoadDefaultShader(void) shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); shader.mapNormalLoc = -1; // It can be set later shader.mapSpecularLoc = -1; // It can be set later - - shader.texDiffuseId = whiteTexture; // Default white texture - shader.texNormalId = 0; - shader.texSpecularId = 0; //-------------------------------------------------------------------- return shader; @@ -2739,10 +2614,6 @@ static Shader LoadSimpleShader(void) { Shader shader; - // NOTE: Shaders are written using GLSL 110 (desktop), that is equivalent to GLSL 100 on ES2 - // NOTE: Detected an error on ATI cards if defined #version 110 while OpenGL 3.3+ - // Just defined #version 330 despite shader is #version 110 - // Vertex shader directly defined, no external file required #if defined(GRAPHICS_API_OPENGL_33) char vShaderStr[] = "#version 330 \n" @@ -2802,10 +2673,6 @@ static Shader LoadSimpleShader(void) shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); shader.mapNormalLoc = -1; // It can be set later shader.mapSpecularLoc = -1; // It can be set later - - shader.texDiffuseId = whiteTexture; // Default white texture - shader.texNormalId = 0; - shader.texSpecularId = 0; //-------------------------------------------------------------------- return shader; @@ -2878,7 +2745,6 @@ static void InitializeBuffers(void) quads.indices = (unsigned short *)malloc(sizeof(short)*6*MAX_QUADS_BATCH); // 6 int by quad (indices) #endif - for (int i = 0; i < (3*4*MAX_QUADS_BATCH); i++) quads.vertices[i] = 0.0f; for (int i = 0; i < (2*4*MAX_QUADS_BATCH); i++) quads.texcoords[i] = 0.0f; for (int i = 0; i < (4*4*MAX_QUADS_BATCH); i++) quads.colors[i] = 0; diff --git a/src/rlgl.h b/src/rlgl.h index 9e0aaaaa..69640feb 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -154,11 +154,6 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; typedef struct Shader { unsigned int id; // Shader program id - // TODO: This should be Texture2D objects - unsigned int texDiffuseId; // Diffuse texture id - unsigned int texNormalId; // Normal texture id - unsigned int texSpecularId; // Specular texture id - // Variable attributes int vertexLoc; // Vertex attribute location point (vertex shader) int texcoordLoc; // Texcoord attribute location point (vertex shader) @@ -184,12 +179,27 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; int format; // Data format (TextureFormat) } Texture2D; + // Material type + typedef struct Material { + Shader shader; + + Texture2D texDiffuse; // Diffuse texture + Texture2D texNormal; // Normal texture + Texture2D texSpecular; // Specular texture + + Color colDiffuse; + Color colAmbient; + Color colSpecular; + + float glossiness; + float normalDepth; + } Material; + // 3d Model type typedef struct Model { Mesh mesh; Matrix transform; - Texture2D texture; - Shader shader; + Material material; } Model; // Color blending modes (pre-defined) -- cgit v1.2.3 From 956a6e6f7713a19e746497efb9e909ba88be9c3d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 27 Mar 2016 18:33:30 +0200 Subject: Corrected bug and comments on model unloading --- src/models.c | 5 ++--- src/rlgl.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index a1590424..52c68f9b 100644 --- a/src/models.c +++ b/src/models.c @@ -608,6 +608,8 @@ void UnloadModel(Model model) //if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); // Not used //if (model.mesh.tangents != NULL) free(model.mesh.tangents); // Not used + TraceLog(INFO, "Unloaded model data from RAM (CPU)"); + rlDeleteBuffers(model.mesh.vboId[0]); // vertex rlDeleteBuffers(model.mesh.vboId[1]); // texcoords rlDeleteBuffers(model.mesh.vboId[2]); // normals @@ -616,9 +618,6 @@ void UnloadModel(Model model) //rlDeleteBuffers(model.mesh.vboId[5]); // colors (NOT USED) rlDeleteVertexArrays(model.mesh.vaoId); - - if (model.mesh.vaoId > 0) TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Unloaded model data from VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]); } // Link a texture to a model diff --git a/src/rlgl.c b/src/rlgl.c index fc14a0af..39a34095 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -823,7 +823,11 @@ void rlDeleteShader(unsigned int id) void rlDeleteVertexArrays(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (vaoSupported) glDeleteVertexArrays(1, &id); + if (vaoSupported) + { + glDeleteVertexArrays(1, &id); + TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); + } #endif } @@ -832,6 +836,8 @@ void rlDeleteBuffers(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glDeleteBuffers(1, &id); + + if (!vaoSupported) TraceLog(INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); #endif } @@ -1139,7 +1145,7 @@ FBO rlglLoadFBO(int width, int height) GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) + if (status != GL_FRAMEBUFFER_COMPLETE) { TraceLog(WARNING, "Framebuffer object could not be created..."); @@ -1238,12 +1244,6 @@ void rlglClose(void) rlglUnloadFBO(postproFbo); // Unload postpro quad model data -#if defined(GRAPHICS_API_OPENGL_11) - free(postproQuad.mesh.vertices); - free(postproQuad.mesh.texcoords); - free(postproQuad.mesh.normals); -#endif - rlDeleteBuffers(postproQuad.mesh.vboId[0]); rlDeleteBuffers(postproQuad.mesh.vboId[1]); rlDeleteBuffers(postproQuad.mesh.vboId[2]); @@ -1907,7 +1907,7 @@ void rlglGenerateMipmaps(Texture2D texture) TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture.id); // NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data - free(data): + free(data); #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically -- cgit v1.2.3 From 136408d8b8b096f23953aba3d81b3fbeccdc2680 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 27 Mar 2016 19:42:57 +0200 Subject: Corrected bug on bounding box if mesh is not loaded properly it breaks the game! --- src/models.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 52c68f9b..a515dd86 100644 --- a/src/models.c +++ b/src/models.c @@ -1328,13 +1328,19 @@ bool CheckCollisionRayBox(Ray ray, BoundingBox box) BoundingBox CalculateBoundingBox(Mesh mesh) { // Get min and max vertex to construct bounds (AABB) - Vector3 minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; - Vector3 maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; + Vector3 minVertex = { 0 }; + Vector3 maxVertex = { 0 }; - for (int i = 1; i < mesh.vertexCount; i++) + if (mesh.vertices != NULL) { - minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); - maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; + maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; + + for (int i = 1; i < mesh.vertexCount; i++) + { + minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + } } // Create the bounding box -- cgit v1.2.3 From a66c8531d69569b0c5173c71a8ed28565c1b5214 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 3 Apr 2016 18:31:42 +0200 Subject: Some code simplifications --- src/models.c | 1 + src/rlgl.c | 84 +++++++++++++++++++----------------------------------------- 2 files changed, 27 insertions(+), 58 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index a515dd86..0bb2b8d6 100644 --- a/src/models.c +++ b/src/models.c @@ -627,6 +627,7 @@ void SetModelTexture(Model *model, Texture2D texture) else model->material.texDiffuse = texture; } +// Generate a mesh from heightmap static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) diff --git a/src/rlgl.c b/src/rlgl.c index 809077e3..cf9fe17b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -256,6 +256,7 @@ unsigned int whiteTexture; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) static Shader LoadDefaultShader(void); static Shader LoadSimpleShader(void); +static void GetShaderDefaultLocations(Shader *shader); static void InitializeBuffers(void); static void InitializeBuffersGPU(void); static void UpdateBuffers(void); @@ -1369,22 +1370,25 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro } else { - // Bind model VBOs data + // Bind model VBO data: vertex position glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[0]); glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(model.material.shader.vertexLoc); + // Bind model VBO data: vertex texcoords glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[1]); glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(model.material.shader.texcoordLoc); - // Add normals support + // Bind model VBO data: vertex normals (if available) if (model.material.shader.normalLoc != -1) { glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]); glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(model.material.shader.normalLoc); } + + // TODO: Bind model VBO data: colors, tangents, texcoords2 (if available) } // Draw call! @@ -2094,9 +2098,7 @@ void *rlglReadTexturePixels(Texture2D texture) // Load a custom shader and bind default locations Shader LoadShader(char *vsFileName, char *fsFileName) { - Shader shader; - - shader.id = 0; // Default value in case of loading failure + Shader shader = { 0 }; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Shaders loading from external text file @@ -2107,28 +2109,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) { shader.id = LoadShaderProgram(vShaderStr, fShaderStr); - if (shader.id != 0) - { - TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id); - - // Get handles to GLSL input attibute locations - //------------------------------------------------------------------- - shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition"); - shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord"); - shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal"); - // NOTE: custom shader does not use colorLoc - shader.colorLoc = -1; - - // Get handles to GLSL uniform locations (vertex shader) - shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); - - // Get handles to GLSL uniform locations (fragment shader) - shader.tintColorLoc = glGetUniformLocation(shader.id, "fragTintColor"); - shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); - shader.mapNormalLoc = -1; // It can be set later - shader.mapSpecularLoc = -1; // It can be set later - //-------------------------------------------------------------------- - } + if (shader.id != 0) GetShaderDefaultLocations(&shader); else { TraceLog(WARNING, "Custom shader could not be loaded"); @@ -2497,23 +2478,7 @@ static Shader LoadDefaultShader(void) if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); - // Get handles to GLSL input attibute locations - //------------------------------------------------------------------- - shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition"); - shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord"); - shader.colorLoc = glGetAttribLocation(shader.id, "vertexColor"); - // NOTE: default shader does not use normalLoc - shader.normalLoc = -1; - - // Get handles to GLSL uniform locations (vertex shader) - shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); - - // Get handles to GLSL uniform locations (fragment shader) - shader.tintColorLoc = -1; - shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); - shader.mapNormalLoc = -1; // It can be set later - shader.mapSpecularLoc = -1; // It can be set later - //-------------------------------------------------------------------- + GetShaderDefaultLocations(&shader); return shader; } @@ -2573,25 +2538,28 @@ static Shader LoadSimpleShader(void) if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Simple shader loaded successfully", shader.id); else TraceLog(WARNING, "[SHDR ID %i] Simple shader could not be loaded", shader.id); + GetShaderDefaultLocations(&shader); + + return shader; +} + +// Get location handlers to for shader attributes and uniforms +static void GetShaderDefaultLocations(Shader *shader) +{ // Get handles to GLSL input attibute locations - //------------------------------------------------------------------- - shader.vertexLoc = glGetAttribLocation(shader.id, "vertexPosition"); - shader.texcoordLoc = glGetAttribLocation(shader.id, "vertexTexCoord"); - shader.normalLoc = glGetAttribLocation(shader.id, "vertexNormal"); - // NOTE: simple shader does not use colorLoc - shader.colorLoc = -1; + shader->vertexLoc = glGetAttribLocation(shader->id, "vertexPosition"); + shader->texcoordLoc = glGetAttribLocation(shader->id, "vertexTexCoord"); + shader->normalLoc = glGetAttribLocation(shader->id, "vertexNormal"); + shader->colorLoc = glGetAttribLocation(shader->id, "vertexColor"); // -1 if not found // Get handles to GLSL uniform locations (vertex shader) - shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); // Get handles to GLSL uniform locations (fragment shader) - shader.tintColorLoc = glGetUniformLocation(shader.id, "fragTintColor"); - shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); - shader.mapNormalLoc = -1; // It can be set later - shader.mapSpecularLoc = -1; // It can be set later - //-------------------------------------------------------------------- - - return shader; + shader->tintColorLoc = glGetUniformLocation(shader->id, "fragTintColor"); + shader->mapDiffuseLoc = glGetUniformLocation(shader->id, "texture0"); + shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1"); // -1 if not found + shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2"); // -1 if not found } // Read text file -- cgit v1.2.3 From 7ab008878afa202b4f2e579567be7a7d87242661 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 7 May 2016 18:07:15 +0200 Subject: Library redesign to accomodate materials system --- src/models.c | 164 ++++++++-- src/raylib.h | 31 +- src/rlgl.c | 989 +++++++++++++++++++++++++++++------------------------------ src/rlgl.h | 15 +- 4 files changed, 641 insertions(+), 558 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 0bb2b8d6..9b139120 100644 --- a/src/models.c +++ b/src/models.c @@ -55,7 +55,9 @@ extern unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static Mesh LoadOBJ(const char *fileName); +static Mesh LoadOBJ(const char *fileName); // Load OBJ mesh data +static Material LoadMTL(const char *fileName); // Load MTL material data + static Mesh GenMeshHeightmap(Image image, Vector3 size); static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); @@ -542,24 +544,19 @@ void DrawGizmo(Vector3 position) Model LoadModel(const char *fileName) { Model model = { 0 }; - Mesh mesh = { 0 }; - // NOTE: Initialize default data for model in case loading fails, maybe a cube? + // TODO: Initialize default data for model in case loading fails, maybe a cube? - if (strcmp(GetExtension(fileName),"obj") == 0) mesh = LoadOBJ(fileName); + if (strcmp(GetExtension(fileName),"obj") == 0) model.mesh = LoadOBJ(fileName); else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName); - // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - - if (mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); + if (model.mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); else { - // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() - model = rlglLoadModel(mesh); // Upload vertex data to GPU - - // NOTE: Now that vertex data is uploaded to GPU VRAM, we can free arrays from CPU RAM - // We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes... - // ...but we could keep CPU vertex data in case we need to update the mesh + rlglLoadMesh(&model.mesh); // Upload vertex data to GPU + + model.transform = MatrixIdentity(); + model.material = LoadDefaultMaterial(); } return model; @@ -568,12 +565,12 @@ Model LoadModel(const char *fileName) // Load a 3d model (from vertex data) Model LoadModelEx(Mesh data) { - Model model; + Model model = { 0 }; - // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() - model = rlglLoadModel(data); // Upload vertex data to GPU + rlglLoadMesh(&data); // Upload vertex data to GPU - // NOTE: Vertex data is managed externally, must be deallocated manually + model.transform = MatrixIdentity(); + model.material = LoadDefaultMaterial(); return model; } @@ -582,8 +579,14 @@ Model LoadModelEx(Mesh data) // NOTE: model map size is defined in generic units Model LoadHeightmap(Image heightmap, Vector3 size) { - Mesh mesh = GenMeshHeightmap(heightmap, size); - Model model = rlglLoadModel(mesh); + Model model = { 0 }; + + model.mesh = GenMeshHeightmap(heightmap, size); + + rlglLoadMesh(&model.mesh); + + model.transform = MatrixIdentity(); + model.material = LoadDefaultMaterial(); return model; } @@ -591,8 +594,14 @@ Model LoadHeightmap(Image heightmap, Vector3 size) // Load a map image as a 3d model (cubes based) Model LoadCubicmap(Image cubicmap) { - Mesh mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f }); - Model model = rlglLoadModel(mesh); + Model model = { 0 }; + + model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f }); + + rlglLoadMesh(&model.mesh); + + model.transform = MatrixIdentity(); + model.material = LoadDefaultMaterial(); return model; } @@ -613,13 +622,44 @@ void UnloadModel(Model model) rlDeleteBuffers(model.mesh.vboId[0]); // vertex rlDeleteBuffers(model.mesh.vboId[1]); // texcoords rlDeleteBuffers(model.mesh.vboId[2]); // normals - //rlDeleteBuffers(model.mesh.vboId[3]); // texcoords2 (NOT USED) + //rlDeleteBuffers(model.mesh.vboId[3]); // colors (NOT USED) //rlDeleteBuffers(model.mesh.vboId[4]); // tangents (NOT USED) - //rlDeleteBuffers(model.mesh.vboId[5]); // colors (NOT USED) + //rlDeleteBuffers(model.mesh.vboId[5]); // texcoords2 (NOT USED) rlDeleteVertexArrays(model.mesh.vaoId); } +// Load material data (from file) +Material LoadMaterial(const char *fileName) +{ + Material material = { 0 }; + + if (strcmp(GetExtension(fileName),"mtl") == 0) material = LoadMTL(fileName); + else TraceLog(WARNING, "[%s] Material extension not recognized, it can't be loaded", fileName); + + return material; +} + +// Load default material (uses default models shader) +Material LoadDefaultMaterial(void) +{ + Material material = { 0 }; + + material.shader = GetDefaultShader(); + material.texDiffuse = GetDefaultTexture(); // White texture (1x1 pixel) + //material.texNormal; // NOTE: By default, not set + //material.texSpecular; // NOTE: By default, not set + + material.colDiffuse = WHITE; // Diffuse color + material.colAmbient = WHITE; // Ambient color + material.colSpecular = WHITE; // Specular color + + material.glossiness = 100.0f; // Glossiness level + material.normalDepth = 1.0f; // Normal map depth + + return material; +} + // Link a texture to a model void SetModelTexture(Model *model, Texture2D texture) { @@ -1100,31 +1140,59 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint) { Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - + DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint); } // Draw a model with extended parameters void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { - // NOTE: Rotation must be provided in degrees, it's converted to radians inside rlglDrawModel() - rlglDrawModel(model, position, rotationAxis, rotationAngle, scale, tint, false); + // Calculate transformation matrix from function parameters + // Get transform matrix (rotation -> scale -> translation) + Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); + Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); + Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + + // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) + //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates + + model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); + model.material.colDiffuse = tint; + + rlglDrawEx(model.mesh, model.material, model.transform, false); } // Draw a model wires (with texture if set) -void DrawModelWires(Model model, Vector3 position, float scale, Color color) +void DrawModelWires(Model model, Vector3 position, float scale, Color tint) { Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - rlglDrawModel(model, position, rotationAxis, 0.0f, vScale, color, true); + // Calculate transformation matrix from function parameters + // Get transform matrix (rotation -> scale -> translation) + Matrix matRotation = MatrixRotate(rotationAxis, 0.0f); + Matrix matScale = MatrixScale(vScale.x, vScale.y, vScale.z); + Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + + model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); + model.material.colDiffuse = tint; + + rlglDrawEx(model.mesh, model.material, model.transform, true); } // Draw a model wires (with texture if set) with extended parameters void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { - // NOTE: Rotation must be provided in degrees, it's converted to radians inside rlglDrawModel() - rlglDrawModel(model, position, rotationAxis, rotationAngle, scale, tint, true); + // Calculate transformation matrix from function parameters + // Get transform matrix (rotation -> scale -> translation) + Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); + Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); + Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + + model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); + model.material.colDiffuse = tint; + + rlglDrawEx(model.mesh, model.material, model.transform, true); } // Draw a billboard @@ -1856,3 +1924,39 @@ static Mesh LoadOBJ(const char *fileName) return mesh; } + +// Load MTL material data +static Material LoadMTL(const char *fileName) +{ + Material material = { 0 }; + + // TODO: Load mtl file + + char dataType; + char comments[200]; + + FILE *mtlFile; + + mtlFile = fopen(fileName, "rt"); + + if (mtlFile == NULL) + { + TraceLog(WARNING, "[%s] MTL file could not be opened", fileName); + return material; + } + + // 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 (3 vertex per face) + while(!feof(mtlFile)) + { + fscanf(mtlFile, "%c", &dataType); + } + + fclose(mtlFile); + + // NOTE: At this point we have all material data + TraceLog(INFO, "[%s] Material loaded successfully", fileName); + + return material; +} diff --git a/src/raylib.h b/src/raylib.h index 8af7d2fb..c88a60f4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -387,10 +387,10 @@ typedef struct Shader { unsigned int id; // Shader program id // Variable attributes locations - int vertexLoc; // Vertex attribute location point (vertex shader) - int texcoordLoc; // Texcoord attribute location point (vertex shader) - int normalLoc; // Normal attribute location point (vertex shader) - int colorLoc; // Color attibute location point (vertex shader) + int vertexLoc; // Vertex attribute location point (default-location = 0) + int texcoordLoc; // Texcoord attribute location point (default-location = 1) + int normalLoc; // Normal attribute location point (default-location = 2) + int colorLoc; // Color attibute location point (default-location = 3) // Uniform locations int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) @@ -801,17 +801,20 @@ void DrawGizmo(Vector3 position); //------------------------------------------------------------------------------------ // Model 3d Loading and Drawing Functions (Module: models) //------------------------------------------------------------------------------------ -Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) -Model LoadModelEx(Mesh data); // Load a 3d model (from mesh data) -//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) -Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model -Model LoadCubicmap(Image cubicmap); // 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 +Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) +Model LoadModelEx(Mesh data); // Load a 3d model (from mesh data) +//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) +Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model +Model LoadCubicmap(Image cubicmap); // 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 + +Material LoadMaterial(const char *fileName); // Load material data (from file) +Material LoadDefaultMaterial(void); // Load default material (uses default models shader) void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters -void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set) +void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) @@ -832,11 +835,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // NOTE: This functions are useless when using OpenGL 1.1 //------------------------------------------------------------------------------------ Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations -unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shaders strings and return program id void UnloadShader(Shader shader); // Unload a custom shader from memory void SetDefaultShader(void); // Set default shader to be used in batch draw void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw -void SetModelShader(Model *model, Shader shader); // Link a shader to a model +Shader GetDefaultShader(void); // Get default shader +Texture2D GetDefaultTexture(void); // Get default texture int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) diff --git a/src/rlgl.c b/src/rlgl.c index 9112e47e..02649e30 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -255,14 +255,16 @@ unsigned int whiteTexture; //---------------------------------------------------------------------------------- #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat); +static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shader strings and return program id -static Shader LoadDefaultShader(void); -static void LoadDefaultShaderLocations(Shader *shader); -static void UnloadDefaultShader(void); +static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring) +static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) +static void UnloadDefaultShader(void); // Unload default shader -static void LoadDefaultBuffers(void); -static void UpdateDefaultBuffers(void); -static void UnloadDefaultBuffers(void); +static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) +static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data +static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data +static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU static char *ReadTextFile(const char *fileName); #endif @@ -1061,167 +1063,12 @@ void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UpdateDefaultBuffers(); - - if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) - { - glUseProgram(currentShader.id); - - Matrix matMVP = MatrixMultiply(modelview, projection); // Create modelview-projection matrix - - glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - glUniform1i(currentShader.mapDiffuseLoc, 0); - glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f); - } - - // NOTE: We draw in this order: lines, triangles, quads - - if (lines.vCounter > 0) - { - glBindTexture(GL_TEXTURE_2D, whiteTexture); - - if (vaoSupported) - { - glBindVertexArray(vaoLines); - } - else - { - glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - if (currentShader.colorLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); - } - } - - glDrawArrays(GL_LINES, 0, lines.vCounter); - - if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - } - - if (triangles.vCounter > 0) - { - glBindTexture(GL_TEXTURE_2D, whiteTexture); - - if (vaoSupported) - { - glBindVertexArray(vaoTriangles); - } - else - { - glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - if (currentShader.colorLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); - } - } - - glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); - - if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - } - - if (quads.vCounter > 0) - { - int quadsCount = 0; - int numIndicesToProcess = 0; - int indicesOffset = 0; - - if (vaoSupported) - { - glBindVertexArray(vaoQuads); - } - else - { - // Enable vertex attributes - glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.texcoordLoc); - - if (currentShader.colorLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); - } - - //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); - - for (int i = 0; i < drawsCounter; i++) - { - quadsCount = draws[i].vertexCount/4; - numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad - - //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); - - glBindTexture(GL_TEXTURE_2D, draws[i].textureId); - - // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process -#if defined(GRAPHICS_API_OPENGL_33) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); -#elif defined(GRAPHICS_API_OPENGL_ES2) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * indicesOffset)); -#endif - //GLenum err; - //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! - - indicesOffset += draws[i].vertexCount/4*6; - } - - if (!vaoSupported) - { - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - } - - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures - } - - if (vaoSupported) glBindVertexArray(0); // Unbind VAO - - glUseProgram(0); // Unbind shader program - - // Reset draws counter - drawsCounter = 1; - draws[0].textureId = whiteTexture; - draws[0].vertexCount = 0; - - // Reset vertex counters for next frame - lines.vCounter = 0; - lines.cCounter = 0; - - triangles.vCounter = 0; - triangles.cCounter = 0; - - quads.vCounter = 0; - quads.tcCounter = 0; - quads.cCounter = 0; - - // Reset depth for next draw - currentDepth = -1.0f; + DrawDefaultBuffers(); #endif } -// Draw a 3d model -// NOTE: Model transform can come within model struct -void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color color, bool wires) +// Draw a 3d mesh with material and transform +void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) { #if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glPolygonMode() not available on OpenGL ES @@ -1230,27 +1077,21 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id); + glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array - 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.mesh.colors); // Pointer to colors array (NOT USED) + glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array + glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array + glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array + //glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array (NOT USED) - rlPushMatrix(); - rlTranslatef(position.x, position.y, position.z); - rlScalef(scale.x, scale.y, scale.z); - rlRotatef(rotationAngle, rotationAxis.x, rotationAxis.y, rotationAxis.z); - - rlColor4ub(color.r, color.g, color.b, color.a); - - glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount); - rlPopMatrix(); + rlMultMatrixf(MatrixToFloat(transform)); + + glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array @@ -1261,97 +1102,83 @@ void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float ro #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(model.material.shader.id); + glUseProgram(material.shader.id); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() Matrix matView = modelview; // View matrix (camera) Matrix matProjection = projection; // Projection matrix (perspective) - - // Calculate transformation matrix from function parameters - // Get transform matrix (rotation -> scale -> translation) - Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); - Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); - Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); - Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - - // Combine model internal transformation matrix (model.transform) with matrix generated by function parameters (matTransform) - Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates - + // Calculate model-view matrix combining matModel and matView - Matrix matModelView = MatrixMultiply(matModel, matView); // Transform to camera-space coordinates + Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates // Calculate model-view-projection matrix (MVP) Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates // Send combined model-view-projection matrix to shader - glUniformMatrix4fv(model.material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - // Apply color tinting to model + // Apply color tinting (material.colDiffuse) // NOTE: Just update one uniform on fragment shader - float vColor[4] = { (float)color.r/255, (float)color.g/255, (float)color.b/255, (float)color.a/255 }; - glUniform4fv(model.material.shader.tintColorLoc, 1, vColor); + float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; + glUniform4fv(material.shader.tintColorLoc, 1, vColor); // Set shader textures (diffuse, normal, specular) glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, model.material.texDiffuse.id); - glUniform1i(model.material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 + glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); + glUniform1i(material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 - if ((model.material.texNormal.id != 0) && (model.material.shader.mapNormalLoc != -1)) + if ((material.texNormal.id != 0) && (material.shader.mapNormalLoc != -1)) { glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, model.material.texNormal.id); - glUniform1i(model.material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 + glBindTexture(GL_TEXTURE_2D, material.texNormal.id); + glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 } - if ((model.material.texSpecular.id != 0) && (model.material.shader.mapSpecularLoc != -1)) + if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1)) { glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, model.material.texSpecular.id); - glUniform1i(model.material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 + glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); + glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 } if (vaoSupported) { - glBindVertexArray(model.mesh.vaoId); + glBindVertexArray(mesh.vaoId); } else { - // Bind model VBO data: vertex position - glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[0]); - glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.material.shader.vertexLoc); + // Bind mesh VBO data: vertex position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); + glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.vertexLoc); - // Bind model VBO data: vertex texcoords - glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[1]); - glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.material.shader.texcoordLoc); + // Bind mesh VBO data: vertex texcoords (shader-location = 1) + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); + glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.texcoordLoc); - // Bind model VBO data: vertex normals (if available) - if (model.material.shader.normalLoc != -1) + // Bind mesh VBO data: vertex normals (shader-location = 2, if available) + if (material.shader.normalLoc != -1) { - glBindBuffer(GL_ARRAY_BUFFER, model.mesh.vboId[2]); - glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.material.shader.normalLoc); + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); + glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.normalLoc); } - // TODO: Bind model VBO data: colors, tangents, texcoords2 (if available) + // TODO: Bind mesh VBO data: colors, tangents, texcoords2 (if available) } // Draw call! - glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount); - - //glDisableVertexAttribArray(model.shader.vertexLoc); - //glDisableVertexAttribArray(model.shader.texcoordLoc); - //if (model.shader.normalLoc != -1) glDisableVertexAttribArray(model.shader.normalLoc); + glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); - if (model.material.texNormal.id != 0) + if (material.texNormal.id != 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); } - if (model.material.texSpecular.id != 0) + if (material.texSpecular.id != 0) { glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, 0); @@ -1808,95 +1635,75 @@ void rlglGenerateMipmaps(Texture2D texture) glBindTexture(GL_TEXTURE_2D, 0); } -// Load vertex data into a VAO (if supported) and VBO -Model rlglLoadModel(Mesh mesh) +// Upload vertex data into a VAO (if supported) and VBO +void rlglLoadMesh(Mesh *mesh) { - Model model; - - model.mesh = mesh; - model.mesh.vaoId = 0; // Vertex Array Object - model.mesh.vboId[0] = 0; // Vertex positions VBO - model.mesh.vboId[1] = 0; // Vertex texcoords VBO - model.mesh.vboId[2] = 0; // Vertex normals VBO + mesh->vaoId = 0; // Vertex Array Object + mesh->vboId[0] = 0; // Vertex positions VBO + mesh->vboId[1] = 0; // Vertex texcoords VBO + mesh->vboId[2] = 0; // Vertex normals VBO + mesh->vboId[3] = 0; // Vertex color VBO + mesh->vboId[4] = 0; // Vertex tangent VBO + mesh->vboId[5] = 0; // Vertex texcoord2 VBO // TODO: Consider attributes: color, texcoords2, tangents (if available) - model.transform = MatrixIdentity(); - -#if defined(GRAPHICS_API_OPENGL_11) - model.material.texDiffuse.id = 0; // No texture required - model.material.shader.id = 0; // No shader used - -#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - model.material.shader = defaultShader; // Default model shader - - model.material.texDiffuse.id = whiteTexture; // Default whiteTexture - model.material.texDiffuse.width = 1; // Default whiteTexture width - model.material.texDiffuse.height = 1; // Default whiteTexture height - model.material.texDiffuse.format = UNCOMPRESSED_R8G8B8A8; // Default whiteTexture format - - model.material.texNormal.id = 0; // By default, no normal texture - model.material.texSpecular.id = 0; // By default, no specular texture - - // TODO: Fill default material properties (color, glossiness...) - - GLuint vaoModel = 0; // Vertex Array Objects (VAO) - GLuint vertexBuffer[3]; // Vertex Buffer Objects (VBO) +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + GLuint vaoId = 0; // Vertex Array Objects (VAO) + GLuint vboId[3]; // Vertex Buffer Objects (VBOs) if (vaoSupported) { // Initialize Quads VAO (Buffer A) - glGenVertexArrays(1, &vaoModel); - glBindVertexArray(vaoModel); + glGenVertexArrays(1, &vaoId); + glBindVertexArray(vaoId); } // Create buffers for our vertex data (positions, texcoords, normals) - glGenBuffers(3, vertexBuffer); - - // NOTE: Default shader is assigned to model, so vbo buffers are properly linked to vertex attribs - // If model shader is changed, vbo buffers must be re-assigned to new location points (previously loaded) - - // Enable vertex attributes: position - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.vertices, GL_STATIC_DRAW); - glVertexAttribPointer(model.material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.material.shader.vertexLoc); - - // Enable vertex attributes: texcoords - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh.vertexCount, mesh.texcoords, GL_STATIC_DRAW); - glVertexAttribPointer(model.material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.material.shader.texcoordLoc); - - // Enable vertex attributes: normals - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh.vertexCount, mesh.normals, GL_STATIC_DRAW); - glVertexAttribPointer(model.material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(model.material.shader.normalLoc); - - glVertexAttrib4f(model.material.shader.colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); // Color vertex attribute set to default: WHITE - glDisableVertexAttribArray(model.material.shader.colorLoc); + glGenBuffers(3, vboId); + + // NOTE: Attributes must be uploaded considering default locations points + + // Enable vertex attributes: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, vboId[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->vertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(0); + + // Enable vertex attributes: texcoords (shader-location = 1) + glBindBuffer(GL_ARRAY_BUFFER, vboId[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords, GL_STATIC_DRAW); + glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(1); + + // Enable vertex attributes: normals (shader-location = 2) + glBindBuffer(GL_ARRAY_BUFFER, vboId[2]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, GL_STATIC_DRAW); + glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(2); + + // Default color vertex attribute (shader-location = 3) + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); // Color vertex attribute set to default: WHITE + glDisableVertexAttribArray(3); - model.mesh.vboId[0] = vertexBuffer[0]; // Vertex position VBO - model.mesh.vboId[1] = vertexBuffer[1]; // Texcoords VBO - model.mesh.vboId[2] = vertexBuffer[2]; // Normals VBO + mesh->vboId[0] = vboId[0]; // Vertex position VBO + mesh->vboId[1] = vboId[1]; // Texcoords VBO + mesh->vboId[2] = vboId[2]; // Normals VBO if (vaoSupported) { - if (vaoModel > 0) + if (vaoId > 0) { - model.mesh.vaoId = vaoModel; - TraceLog(INFO, "[VAO ID %i] Model uploaded successfully to VRAM (GPU)", vaoModel); + mesh->vaoId = vaoId; + TraceLog(INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); } - else TraceLog(WARNING, "Model could not be uploaded to VRAM (GPU)"); + else TraceLog(WARNING, "Mesh could not be uploaded to VRAM (GPU)"); } else { - TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Model uploaded successfully to VRAM (GPU)", model.mesh.vboId[0], model.mesh.vboId[1], model.mesh.vboId[2]); + TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vboId[0], mesh->vboId[1], mesh->vboId[2]); } #endif - - return model; } // Read screen pixel data (color buffer) @@ -2090,36 +1897,202 @@ Shader LoadShader(char *vsFileName, char *fsFileName) return shader; } -// Load custom shader strings and return program id -unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr) +// Unload a custom shader from memory +void UnloadShader(Shader shader) +{ + if (shader.id != 0) + { + rlDeleteShader(shader.id); + TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); + } +} + +// Set custom shader to be used on batch draw +void SetCustomShader(Shader shader) { - unsigned int program = 0; - #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - GLuint vertexShader; - GLuint fragmentShader; + if (currentShader.id != shader.id) + { + rlglDraw(); + currentShader = shader; + } +#endif +} - vertexShader = glCreateShader(GL_VERTEX_SHADER); - fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); +// Set default shader to be used in batch draw +void SetDefaultShader(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + SetCustomShader(defaultShader); +#endif +} - const char *pvs = vShaderStr; - const char *pfs = fShaderStr; +// Get default shader +Shader GetDefaultShader(void) +{ + return defaultShader; +} - glShaderSource(vertexShader, 1, &pvs, NULL); - glShaderSource(fragmentShader, 1, &pfs, NULL); +// Get shader uniform location +int GetShaderLocation(Shader shader, const char *uniformName) +{ + int location = -1; +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + location = glGetUniformLocation(shader.id, uniformName); + + if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); +#endif + return location; +} - GLint success = 0; +// Set shader uniform value (float) +void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); - glCompileShader(vertexShader); + if (size == 1) glUniform1fv(uniformLoc, 1, value); // Shader uniform type: float + else if (size == 2) glUniform2fv(uniformLoc, 1, value); // Shader uniform type: vec2 + else if (size == 3) glUniform3fv(uniformLoc, 1, value); // Shader uniform type: vec3 + else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4 + else TraceLog(WARNING, "Shader value float array size not supported"); + + glUseProgram(0); +#endif +} - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); +// Set shader uniform value (int) +void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); - if (success != GL_TRUE) - { - TraceLog(WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); + if (size == 1) glUniform1iv(uniformLoc, 1, value); // Shader uniform type: int + else if (size == 2) glUniform2iv(uniformLoc, 1, value); // Shader uniform type: ivec2 + else if (size == 3) glUniform3iv(uniformLoc, 1, value); // Shader uniform type: ivec3 + else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 + else TraceLog(WARNING, "Shader value int array size not supported"); + + glUseProgram(0); +#endif +} - int maxLength = 0; - int length; +// Set shader uniform value (matrix 4x4) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); + + glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + + glUseProgram(0); +#endif +} + +// Set blending mode (alpha, additive, multiplied) +// NOTE: Only 3 blending modes predefined +void SetBlendMode(int mode) +{ + if ((blendMode != mode) && (mode < 3)) + { + rlglDraw(); + + switch (mode) + { + case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; + case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; // Alternative: glBlendFunc(GL_ONE, GL_ONE); + case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; + default: break; + } + + blendMode = mode; + } +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +// Convert image data to OpenGL texture (returns OpenGL valid Id) +// NOTE: Expected compressed image data and POT image +static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat) +{ + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + int blockSize = 0; // Bytes every block + int offset = 0; + + if ((compressedFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) || + (compressedFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || +#if defined(GRAPHICS_API_OPENGL_ES2) + (compressedFormat == GL_ETC1_RGB8_OES) || +#endif + (compressedFormat == GL_COMPRESSED_RGB8_ETC2)) blockSize = 8; + else blockSize = 16; + + // Load the mipmap levels + for (int level = 0; level < mipmapCount && (width || height); level++) + { + unsigned int size = 0; + + size = ((width + 3)/4)*((height + 3)/4)*blockSize; + + glCompressedTexImage2D(GL_TEXTURE_2D, level, compressedFormat, width, height, 0, size, data + offset); + + offset += size; + width /= 2; + height /= 2; + + // Security check for NPOT textures + if (width < 1) width = 1; + if (height < 1) height = 1; + } +} + +Texture2D GetDefaultTexture(void) +{ + Texture2D texture; + + texture.id = whiteTexture; + texture.width = 1; + texture.height = 1; + texture.mipmaps = 1; + texture.format = UNCOMPRESSED_R8G8B8A8; + + return texture; +} + +// Load custom shader strings and return program id +static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr) +{ + unsigned int program = 0; + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + GLuint vertexShader; + GLuint fragmentShader; + + vertexShader = glCreateShader(GL_VERTEX_SHADER); + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + + const char *pvs = vShaderStr; + const char *pfs = fShaderStr; + + glShaderSource(vertexShader, 1, &pvs, NULL); + glShaderSource(fragmentShader, 1, &pfs, NULL); + + GLint success = 0; + + glCompileShader(vertexShader); + + glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); + + if (success != GL_TRUE) + { + TraceLog(WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); + + int maxLength = 0; + int length; glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength); @@ -2156,7 +2129,17 @@ unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr) glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); - + + // NOTE: Default attribute shader locations must be binded before linking + glBindAttribLocation(program, 0, "vertexPosition"); + glBindAttribLocation(program, 1, "vertexTexCoord"); + glBindAttribLocation(program, 2, "vertexNormal"); + glBindAttribLocation(program, 3, "vertexColor"); + glBindAttribLocation(program, 4, "vertexTangent"); + glBindAttribLocation(program, 5, "vertexTexCoord2"); + + // NOTE: If some attrib name is no found on the shader, it locations becomes -1 + glLinkProgram(program); // NOTE: All uniform variables are intitialised to 0 when a program links @@ -2190,184 +2173,8 @@ unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr) return program; } -// Unload a custom shader from memory -void UnloadShader(Shader shader) -{ - if (shader.id != 0) - { - rlDeleteShader(shader.id); - TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); - } -} - -// Set custom shader to be used on batch draw -void SetCustomShader(Shader shader) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (currentShader.id != shader.id) - { - rlglDraw(); - currentShader = shader; - } -#endif -} - -// Set default shader to be used in batch draw -void SetDefaultShader(void) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - SetCustomShader(defaultShader); -#endif -} - -// Link shader to model -void SetModelShader(Model *model, Shader shader) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - model->material.shader = shader; - - if (vaoSupported) glBindVertexArray(model->mesh.vaoId); - - // Enable vertex attributes: position - glBindBuffer(GL_ARRAY_BUFFER, model->mesh.vboId[0]); - glEnableVertexAttribArray(shader.vertexLoc); - glVertexAttribPointer(shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - - // Enable vertex attributes: texcoords - glBindBuffer(GL_ARRAY_BUFFER, model->mesh.vboId[1]); - glEnableVertexAttribArray(shader.texcoordLoc); - glVertexAttribPointer(shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - - // Enable vertex attributes: normals - glBindBuffer(GL_ARRAY_BUFFER, model->mesh.vboId[2]); - glEnableVertexAttribArray(shader.normalLoc); - glVertexAttribPointer(shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - - if (vaoSupported) glBindVertexArray(0); // Unbind VAO - -#elif (GRAPHICS_API_OPENGL_11) - TraceLog(WARNING, "Shaders not supported on OpenGL 1.1"); -#endif -} - -// Get shader uniform location -int GetShaderLocation(Shader shader, const char *uniformName) -{ - int location = -1; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - location = glGetUniformLocation(shader.id, uniformName); - - if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); -#endif - return location; -} - -// Set shader uniform value (float) -void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(shader.id); - - if (size == 1) glUniform1fv(uniformLoc, 1, value); // Shader uniform type: float - else if (size == 2) glUniform2fv(uniformLoc, 1, value); // Shader uniform type: vec2 - else if (size == 3) glUniform3fv(uniformLoc, 1, value); // Shader uniform type: vec3 - else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4 - else TraceLog(WARNING, "Shader value float array size not supported"); - - glUseProgram(0); -#endif -} - -// Set shader uniform value (int) -void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(shader.id); - - if (size == 1) glUniform1iv(uniformLoc, 1, value); // Shader uniform type: int - else if (size == 2) glUniform2iv(uniformLoc, 1, value); // Shader uniform type: ivec2 - else if (size == 3) glUniform3iv(uniformLoc, 1, value); // Shader uniform type: ivec3 - else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 - else TraceLog(WARNING, "Shader value int array size not supported"); - - glUseProgram(0); -#endif -} - -// Set shader uniform value (matrix 4x4) -void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(shader.id); - - glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); - - glUseProgram(0); -#endif -} - -// Set blending mode (alpha, additive, multiplied) -// NOTE: Only 3 blending modes predefined -void SetBlendMode(int mode) -{ - if ((blendMode != mode) && (mode < 3)) - { - rlglDraw(); - - switch (mode) - { - case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; - case BLEND_ADDITIVE: glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; // Alternative: glBlendFunc(GL_ONE, GL_ONE); - case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; - default: break; - } - - blendMode = mode; - } -} - -//---------------------------------------------------------------------------------- -// Module specific Functions Definition -//---------------------------------------------------------------------------------- - -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) -// Convert image data to OpenGL texture (returns OpenGL valid Id) -// NOTE: Expected compressed image data and POT image -static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat) -{ - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - int blockSize = 0; // Bytes every block - int offset = 0; - - if ((compressedFormat == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) || - (compressedFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || -#if defined(GRAPHICS_API_OPENGL_ES2) - (compressedFormat == GL_ETC1_RGB8_OES) || -#endif - (compressedFormat == GL_COMPRESSED_RGB8_ETC2)) blockSize = 8; - else blockSize = 16; - - // Load the mipmap levels - for (int level = 0; level < mipmapCount && (width || height); level++) - { - unsigned int size = 0; - - size = ((width + 3)/4)*((height + 3)/4)*blockSize; - - glCompressedTexImage2D(GL_TEXTURE_2D, level, compressedFormat, width, height, 0, size, data + offset); - offset += size; - width /= 2; - height /= 2; - - // Security check for NPOT textures - if (width < 1) width = 1; - if (height < 1) height = 1; - } -} - -// Load default shader (Vertex and Fragment) +// Load default shader (just vertex positioning and texture coloring) // NOTE: This shader program is used for batch buffers (lines, triangles, quads) static Shader LoadDefaultShader(void) { @@ -2436,6 +2243,12 @@ static Shader LoadDefaultShader(void) // NOTE: If any location is not found, loc point becomes -1 static void LoadDefaultShaderLocations(Shader *shader) { + // NOTE: Default shader attrib locations have been fixed before linking: + // vertex position location = 0 + // vertex texcoord location = 1 + // vertex normal location = 2 + // vertex color location = 3 + // Get handles to GLSL input attibute locations shader->vertexLoc = glGetAttribLocation(shader->id, "vertexPosition"); shader->texcoordLoc = glGetAttribLocation(shader->id, "vertexTexCoord"); @@ -2470,7 +2283,7 @@ static void LoadDefaultBuffers(void) // [CPU] Allocate and initialize float array buffers to store vertex data (lines, triangles, quads) //-------------------------------------------------------------------------------------------- - // Initialize lines arrays (vertex position and color data) + // Lines - Initialize 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 = (unsigned char *)malloc(sizeof(unsigned char)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line @@ -2480,7 +2293,7 @@ static void LoadDefaultBuffers(void) lines.vCounter = 0; lines.cCounter = 0; - // Initialize triangles arrays (vertex position and color data) + // Triangles - Initialize 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 = (unsigned char *)malloc(sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH); // 4 float by color, 3 colors by triangle @@ -2490,7 +2303,7 @@ static void LoadDefaultBuffers(void) triangles.vCounter = 0; triangles.cCounter = 0; - // Initialize quads arrays (vertex position, texcoord and color data... and indexes) + // Quads - Initialize arrays (vertex position, texcoord, 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 = (unsigned char *)malloc(sizeof(unsigned char)*4*4*MAX_QUADS_BATCH); // 4 float by color, 4 colors by quad @@ -2523,7 +2336,7 @@ static void LoadDefaultBuffers(void) quads.tcCounter = 0; quads.cCounter = 0; - TraceLog(INFO, "Default buffers initialized successfully in CPU (lines, triangles, quads)"); + TraceLog(INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)"); //-------------------------------------------------------------------------------------------- // [GPU] Upload vertex data and initialize VAOs/VBOs (lines, triangles, quads) @@ -2541,20 +2354,21 @@ static void LoadDefaultBuffers(void) // Create buffers for our vertex data glGenBuffers(2, linesBuffer); - // Lines - Vertex positions buffer binding and attributes enable + // Lines - Vertex buffers binding and attributes enable + // Vertex position buffer (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.vertexLoc); glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - // Lines - colors buffer + // Vertex color buffer (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.colorLoc); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers (lines) VAO initialized successfully", vaoLines); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers (lines) VBOs initialized successfully", linesBuffer[0], linesBuffer[1]); + if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", vaoLines); + else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", linesBuffer[0], linesBuffer[1]); // Upload and link triangles vertex buffers if (vaoSupported) @@ -2567,19 +2381,21 @@ static void LoadDefaultBuffers(void) // Create buffers for our vertex data glGenBuffers(2, trianglesBuffer); - // Enable vertex attributes + // Triangles - Vertex buffers binding and attributes enable + // Vertex position buffer (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.vertexLoc); glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + // Vertex color buffer (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.colorLoc); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers (triangles) VAO initialized successfully", vaoTriangles); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers (triangles) VBOs initialized successfully", trianglesBuffer[0], trianglesBuffer[1]); + if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", vaoTriangles); + else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully(triangles)", trianglesBuffer[0], trianglesBuffer[1]); // Upload and link quads vertex buffers if (vaoSupported) @@ -2592,17 +2408,20 @@ static void LoadDefaultBuffers(void) // Create buffers for our vertex data glGenBuffers(4, quadsBuffer); - // Enable vertex attributes + // Quads - Vertex buffers binding and attributes enable + // Vertex position buffer (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.vertexLoc); glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + // Vertex texcoord buffer (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.texcoordLoc); glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + // Vertex color buffer (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); glEnableVertexAttribArray(currentShader.colorLoc); @@ -2616,15 +2435,15 @@ static void LoadDefaultBuffers(void) glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); #endif - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers (quads) VAO initialized successfully", vaoQuads); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers (quads) VBOs initialized successfully", quadsBuffer[0], quadsBuffer[1], quadsBuffer[2], quadsBuffer[3]); + if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (quads)", vaoQuads); + else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (quads)", quadsBuffer[0], quadsBuffer[1], quadsBuffer[2], quadsBuffer[3]); // Unbind the current VAO if (vaoSupported) glBindVertexArray(0); //-------------------------------------------------------------------------------------------- } -// Update default buffers (VAOs/VBOs) with vertex array data +// Update default internal buffers (VAOs/VBOs) with vertex array data // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0) // TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required) static void UpdateDefaultBuffers(void) @@ -2695,7 +2514,165 @@ static void UpdateDefaultBuffers(void) if (vaoSupported) glBindVertexArray(0); } -// Unload default buffers vertex data from CPU and GPU +// Draw default internal buffers vertex data +// NOTE: We draw in this order: lines, triangles, quads +static void DrawDefaultBuffers(void) +{ + // Set current shader and upload current MVP matrix + if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) + { + glUseProgram(currentShader.id); + + // Create modelview-projection matrix + Matrix matMVP = MatrixMultiply(modelview, projection); + + glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + glUniform1i(currentShader.mapDiffuseLoc, 0); + glUniform4f(currentShader.tintColorLoc, 1.0f, 1.0f, 1.0f, 1.0f); + } + + // Draw lines buffers + if (lines.vCounter > 0) + { + glBindTexture(GL_TEXTURE_2D, whiteTexture); + + if (vaoSupported) + { + glBindVertexArray(vaoLines); + } + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + } + + glDrawArrays(GL_LINES, 0, lines.vCounter); + + if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + } + + // Draw triangles buffers + if (triangles.vCounter > 0) + { + glBindTexture(GL_TEXTURE_2D, whiteTexture); + + if (vaoSupported) + { + glBindVertexArray(vaoTriangles); + } + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, trianglesBuffer[1]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + } + + glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); + + if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + } + + // Draw quads buffers + if (quads.vCounter > 0) + { + int quadsCount = 0; + int numIndicesToProcess = 0; + int indicesOffset = 0; + + if (vaoSupported) + { + glBindVertexArray(vaoQuads); + } + else + { + // Bind vertex attrib: position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + // Bind vertex attrib: texcoord (shader-location = 1) + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]); + glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.texcoordLoc); + + // Bind vertex attrib: color (shader-location = 3) + glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); + } + + //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); + + for (int i = 0; i < drawsCounter; i++) + { + quadsCount = draws[i].vertexCount/4; + numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad + + //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); + + glBindTexture(GL_TEXTURE_2D, draws[i].textureId); + + // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process +#if defined(GRAPHICS_API_OPENGL_33) + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); +#elif defined(GRAPHICS_API_OPENGL_ES2) + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * indicesOffset)); +#endif + //GLenum err; + //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! + + indicesOffset += draws[i].vertexCount/4*6; + } + + if (!vaoSupported) + { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + } + + if (vaoSupported) glBindVertexArray(0); // Unbind VAO + + glUseProgram(0); // Unbind shader program + + // Reset draws counter + drawsCounter = 1; + draws[0].textureId = whiteTexture; + draws[0].vertexCount = 0; + + // Reset vertex counters for next frame + lines.vCounter = 0; + lines.cCounter = 0; + triangles.vCounter = 0; + triangles.cCounter = 0; + quads.vCounter = 0; + quads.tcCounter = 0; + quads.cCounter = 0; + + // Reset depth for next draw + currentDepth = -1.0f; +} + +// Unload default internal buffers vertex data from CPU and GPU static void UnloadDefaultBuffers(void) { // Unbind everything diff --git a/src/rlgl.h b/src/rlgl.h index cd8e6d1d..afc2ab96 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -280,29 +280,28 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data void rlglGenerateMipmaps(Texture2D texture); // Generate mipmap data for selected texture - -// NOTE: There is a set of shader related functions that are available to end user, -// to avoid creating function wrappers through core module, they have been directly declared in raylib.h - -Model rlglLoadModel(Mesh mesh); // Upload vertex data into GPU and provided VAO/VBO ids -void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color color, bool wires); +void rlglLoadMesh(Mesh *mesh); // Upload vertex data into GPU and provided VAO/VBO ids +void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires); Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) void *rlglReadTexturePixels(Texture2D texture); // Read texture pixel data +// NOTE: There is a set of shader related functions that are available to end user, +// to avoid creating function wrappers through core module, they have been directly declared in raylib.h + #if defined(RLGL_STANDALONE) //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 //------------------------------------------------------------------------------------ Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations -unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shader strings and return program id void UnloadShader(Shader shader); // Unload a custom shader from memory void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw void SetDefaultShader(void); // Set default shader to be used in batch draw -void SetModelShader(Model *model, Shader shader); // Link a shader to a model +Shader GetDefaultShader(void); // Get default shader +Texture2D GetDefaultTexture(void); // Get default texture int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) -- cgit v1.2.3 From 0bcb873cbb3758d67b1d263fafb6be818ddbf067 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 8 May 2016 15:24:02 +0200 Subject: Improved mesh support Depending on mesh data, it can be loaded and default vertex attribute location points are set, including colors, tangents and texcoords2 --- src/models.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++------------- src/raylib.h | 6 +-- src/rlgl.c | 90 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 171 insertions(+), 45 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 9b139120..4aff7216 100644 --- a/src/models.c +++ b/src/models.c @@ -575,6 +575,89 @@ Model LoadModelEx(Mesh data) return model; } +// Load a 3d model from rRES file (raylib Resource) +Model LoadModelFromRES(const char *rresName, int resId) +{ + Model model = { 0 }; + bool found = false; + + char id[4]; // rRES file identifier + unsigned char version; // rRES file version and subversion + char useless; // rRES header reserved data + short numRes; + + ResInfoHeader infoHeader; + + FILE *rresFile = fopen(rresName, "rb"); + + if (rresFile == NULL) + { + TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); + } + else + { + // Read rres file (basic file check - id) + fread(&id[0], sizeof(char), 1, rresFile); + fread(&id[1], sizeof(char), 1, rresFile); + fread(&id[2], sizeof(char), 1, rresFile); + fread(&id[3], sizeof(char), 1, rresFile); + fread(&version, sizeof(char), 1, rresFile); + fread(&useless, sizeof(char), 1, rresFile); + + if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S')) + { + TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName); + } + else + { + // Read number of resources embedded + fread(&numRes, sizeof(short), 1, rresFile); + + for (int i = 0; i < numRes; i++) + { + fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile); + + if (infoHeader.id == resId) + { + found = true; + + // Check data is of valid MODEL type + if (infoHeader.type == 8) + { + // TODO: Load model data + } + else + { + TraceLog(WARNING, "[%s] Required resource do not seem to be a valid MODEL resource", rresName); + } + } + else + { + // Depending on type, skip the right amount of parameters + switch (infoHeader.type) + { + case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters + case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters + case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review) + case 3: break; // TEXT: No parameters + case 4: break; // RAW: No parameters + default: break; + } + + // Jump DATA to read next infoHeader + fseek(rresFile, infoHeader.size, SEEK_CUR); + } + } + } + + fclose(rresFile); + } + + if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId); + + return model; +} + // Load a heightmap image as a 3d model // NOTE: model map size is defined in generic units Model LoadHeightmap(Image heightmap, Vector3 size) @@ -613,18 +696,18 @@ void UnloadModel(Model model) free(model.mesh.vertices); free(model.mesh.texcoords); free(model.mesh.normals); - free(model.mesh.colors); - //if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); // Not used - //if (model.mesh.tangents != NULL) free(model.mesh.tangents); // Not used + if (model.mesh.colors != NULL) free(model.mesh.colors); + if (model.mesh.tangents != NULL) free(model.mesh.tangents); + if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); TraceLog(INFO, "Unloaded model data from RAM (CPU)"); rlDeleteBuffers(model.mesh.vboId[0]); // vertex rlDeleteBuffers(model.mesh.vboId[1]); // texcoords rlDeleteBuffers(model.mesh.vboId[2]); // normals - //rlDeleteBuffers(model.mesh.vboId[3]); // colors (NOT USED) - //rlDeleteBuffers(model.mesh.vboId[4]); // tangents (NOT USED) - //rlDeleteBuffers(model.mesh.vboId[5]); // texcoords2 (NOT USED) + rlDeleteBuffers(model.mesh.vboId[3]); // colors + rlDeleteBuffers(model.mesh.vboId[4]); // tangents + rlDeleteBuffers(model.mesh.vboId[5]); // texcoords2 rlDeleteVertexArrays(model.mesh.vaoId); } @@ -672,7 +755,7 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) - Mesh mesh; + Mesh mesh = { 0 }; int mapX = heightmap.width; int mapZ = heightmap.height; @@ -687,7 +770,7 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); - mesh.colors = (unsigned char *)malloc(mesh.vertexCount*4*sizeof(unsigned char)); // Not used... + mesh.colors = NULL; int vCounter = 0; // Used to count vertices float by float int tcCounter = 0; // Used to count texcoords float by float @@ -770,16 +853,12 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) free(pixels); - // Fill color data - // NOTE: Not used any more... just one plain color defined at DrawModel() - for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; - return mesh; } static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { - Mesh mesh; + Mesh mesh = { 0 }; Color *cubicmapPixels = GetImageData(cubicmap); @@ -1088,11 +1167,7 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); - mesh.colors = (unsigned char *)malloc(mesh.vertexCount*4*sizeof(unsigned char)); // Not used... - - // Fill color data - // NOTE: Not used any more... just one plain color defined at DrawModel() - for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; + mesh.colors = NULL; int fCounter = 0; @@ -1810,7 +1885,7 @@ static Mesh LoadOBJ(const char *fileName) mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); - mesh.colors = (unsigned char *)malloc(mesh.vertexCount*4*sizeof(unsigned char)); + mesh.colors = NULL; int vCounter = 0; // Used to count vertices float by float int tcCounter = 0; // Used to count texcoords float by float @@ -1909,10 +1984,6 @@ static Mesh LoadOBJ(const char *fileName) // Security check, just in case no normals or no texcoords defined in OBJ if (numTexCoords == 0) for (int i = 0; i < (2*mesh.vertexCount); i++) mesh.texcoords[i] = 0.0f; - - // NOTE: We set all vertex colors to white - // NOTE: Not used any more... just one plain color defined at DrawModel() - for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; // Now we can free temp mid* arrays free(midVertices); @@ -1945,9 +2016,6 @@ static Material LoadMTL(const char *fileName) return material; } - // 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 (3 vertex per face) while(!feof(mtlFile)) { fscanf(mtlFile, "%c", &dataType); diff --git a/src/raylib.h b/src/raylib.h index c88a60f4..60384444 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -386,7 +386,7 @@ typedef struct Mesh { typedef struct Shader { unsigned int id; // Shader program id - // Variable attributes locations + // Vertex attributes locations (default locations) int vertexLoc; // Vertex attribute location point (default-location = 0) int texcoordLoc; // Texcoord attribute location point (default-location = 1) int normalLoc; // Normal attribute location point (default-location = 2) @@ -803,14 +803,14 @@ void DrawGizmo(Vector3 position); //------------------------------------------------------------------------------------ Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) Model LoadModelEx(Mesh data); // Load a 3d model (from mesh data) -//Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) +Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d model from rRES file (raylib Resource) Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // 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 Material LoadMaterial(const char *fileName); // Load material data (from file) -Material LoadDefaultMaterial(void); // Load default material (uses default models shader) +Material LoadDefaultMaterial(void); // Load default material (uses default models shader) void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters diff --git a/src/rlgl.c b/src/rlgl.c index 462ccdec..6ffcb8a5 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -811,9 +811,11 @@ void rlDeleteVertexArrays(unsigned int id) void rlDeleteBuffers(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDeleteBuffers(1, &id); - - if (!vaoSupported) TraceLog(INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); + if (id != 0) + { + glDeleteBuffers(1, &id); + if (!vaoSupported) TraceLog(INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); + } #endif } @@ -1638,6 +1640,7 @@ void rlglGenerateMipmaps(Texture2D texture) } // Upload vertex data into a VAO (if supported) and VBO +// TODO: Consider attributes: color, texcoords2, tangents (if available) void rlglLoadMesh(Mesh *mesh) { mesh->vaoId = 0; // Vertex Array Object @@ -1648,11 +1651,10 @@ void rlglLoadMesh(Mesh *mesh) mesh->vboId[4] = 0; // Vertex tangent VBO mesh->vboId[5] = 0; // Vertex texcoord2 VBO - // TODO: Consider attributes: color, texcoords2, tangents (if available) - + #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) GLuint vaoId = 0; // Vertex Array Objects (VAO) - GLuint vboId[3]; // Vertex Buffer Objects (VBOs) + GLuint vboId[6]; // Vertex Buffer Objects (VBOs) if (vaoSupported) { @@ -1661,36 +1663,92 @@ void rlglLoadMesh(Mesh *mesh) glBindVertexArray(vaoId); } - // Create buffers for our vertex data (positions, texcoords, normals) - glGenBuffers(3, vboId); - // NOTE: Attributes must be uploaded considering default locations points // Enable vertex attributes: position (shader-location = 0) + glGenBuffers(1, &vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(0); // Enable vertex attributes: texcoords (shader-location = 1) + glGenBuffers(1, &vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords, GL_STATIC_DRAW); glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(1); // Enable vertex attributes: normals (shader-location = 2) - glBindBuffer(GL_ARRAY_BUFFER, vboId[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, GL_STATIC_DRAW); - glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(2); + if (mesh->normals != NULL) + { + glGenBuffers(1, &vboId[2]); + glBindBuffer(GL_ARRAY_BUFFER, vboId[2]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, GL_STATIC_DRAW); + glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(2); + } + else + { + // Default color vertex attribute set to WHITE + glVertexAttrib3f(2, 1.0f, 1.0f, 1.0f); + glDisableVertexAttribArray(2); + } // Default color vertex attribute (shader-location = 3) - glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); // Color vertex attribute set to default: WHITE - glDisableVertexAttribArray(3); + if (mesh->colors != NULL) + { + glGenBuffers(1, &vboId[3]); + glBindBuffer(GL_ARRAY_BUFFER, vboId[3]); + glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh->vertexCount, mesh->colors, GL_STATIC_DRAW); + glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(3); + } + else + { + // Default color vertex attribute set to WHITE + glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); + glDisableVertexAttribArray(3); + } + + // Default tangent vertex attribute (shader-location = 4) + if (mesh->tangents != NULL) + { + glGenBuffers(1, &vboId[4]); + glBindBuffer(GL_ARRAY_BUFFER, vboId[4]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->tangents, GL_STATIC_DRAW); + glVertexAttribPointer(4, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(4); + } + else + { + // Default tangents vertex attribute + glVertexAttrib3f(4, 0.0f, 0.0f, 0.0f); + glDisableVertexAttribArray(4); + } + + // Default texcoord2 vertex attribute (shader-location = 5) + if (mesh->texcoords2 != NULL) + { + glGenBuffers(1, &vboId[5]); + glBindBuffer(GL_ARRAY_BUFFER, vboId[5]); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords2, GL_STATIC_DRAW); + glVertexAttribPointer(5, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(5); + } + else + { + // Default tangents vertex attribute + glVertexAttrib2f(5, 0.0f, 0.0f); + glDisableVertexAttribArray(5); + } mesh->vboId[0] = vboId[0]; // Vertex position VBO mesh->vboId[1] = vboId[1]; // Texcoords VBO mesh->vboId[2] = vboId[2]; // Normals VBO + mesh->vboId[3] = vboId[3]; // Colors VBO + mesh->vboId[4] = vboId[4]; // Tangents VBO + mesh->vboId[5] = vboId[5]; // Texcoords2 VBO if (vaoSupported) { @@ -1703,7 +1761,7 @@ void rlglLoadMesh(Mesh *mesh) } else { - TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vboId[0], mesh->vboId[1], mesh->vboId[2]); + TraceLog(INFO, "[VBOs] Mesh uploaded successfully to VRAM (GPU)"); } #endif } -- cgit v1.2.3 From f7d4951165e8bece5ae58cd4c92b08e4f29cbef7 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 8 May 2016 23:50:35 +0200 Subject: Improved vertex attribs support for models --- src/models.c | 2 +- src/raylib.h | 14 ++++++++------ src/rlgl.c | 45 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 16 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 4aff7216..ee04b449 100644 --- a/src/models.c +++ b/src/models.c @@ -695,7 +695,7 @@ void UnloadModel(Model model) // Unload mesh data free(model.mesh.vertices); free(model.mesh.texcoords); - free(model.mesh.normals); + if (model.mesh.normals != NULL) free(model.mesh.normals); if (model.mesh.colors != NULL) free(model.mesh.colors); if (model.mesh.tangents != NULL) free(model.mesh.tangents); if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); diff --git a/src/raylib.h b/src/raylib.h index 60384444..1258bffc 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -369,12 +369,12 @@ typedef struct BoundingBox { // Vertex data definning a mesh typedef struct Mesh { int vertexCount; // num vertices - float *vertices; // vertex position (XYZ - 3 components per vertex) - float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) - float *texcoords2; // vertex second texture coordinates (useful for lightmaps) - float *normals; // vertex normals (XYZ - 3 components per vertex) - float *tangents; // vertex tangents (XYZ - 3 components per vertex) - unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) + float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) + float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) + float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) + unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) BoundingBox bounds; // mesh limits defined by min and max points @@ -391,6 +391,8 @@ typedef struct Shader { int texcoordLoc; // Texcoord attribute location point (default-location = 1) int normalLoc; // Normal attribute location point (default-location = 2) int colorLoc; // Color attibute location point (default-location = 3) + int tangentLoc; // Tangent attribute location point (default-location = 4) + int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) // Uniform locations int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) diff --git a/src/rlgl.c b/src/rlgl.c index 6ffcb8a5..2e4601df 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1084,12 +1084,13 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array - glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array + if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array + if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array - glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array - //glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array (NOT USED) + if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array + if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array rlPushMatrix(); rlMultMatrixf(MatrixToFloat(transform)); @@ -1099,7 +1100,8 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array - glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array + if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array + if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); @@ -1170,7 +1172,29 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glEnableVertexAttribArray(material.shader.normalLoc); } - // TODO: Bind mesh VBO data: colors, tangents, texcoords2 (if available) + // Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available) + if (material.shader.colorLoc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); + glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(material.shader.colorLoc); + } + + // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) + if (material.shader.tangentLoc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); + glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.tangentLoc); + } + + // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) + if (material.shader.texcoord2Loc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); + glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.texcoord2Loc); + } } // Draw call! @@ -1640,16 +1664,15 @@ void rlglGenerateMipmaps(Texture2D texture) } // Upload vertex data into a VAO (if supported) and VBO -// TODO: Consider attributes: color, texcoords2, tangents (if available) void rlglLoadMesh(Mesh *mesh) { mesh->vaoId = 0; // Vertex Array Object mesh->vboId[0] = 0; // Vertex positions VBO mesh->vboId[1] = 0; // Vertex texcoords VBO mesh->vboId[2] = 0; // Vertex normals VBO - mesh->vboId[3] = 0; // Vertex color VBO - mesh->vboId[4] = 0; // Vertex tangent VBO - mesh->vboId[5] = 0; // Vertex texcoord2 VBO + mesh->vboId[3] = 0; // Vertex colors VBO + mesh->vboId[4] = 0; // Vertex tangents VBO + mesh->vboId[5] = 0; // Vertex texcoords2 VBO #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2314,12 +2337,16 @@ static void LoadDefaultShaderLocations(Shader *shader) // vertex texcoord location = 1 // vertex normal location = 2 // vertex color location = 3 + // vertex tangent location = 4 + // vertex texcoord2 location = 5 // Get handles to GLSL input attibute locations shader->vertexLoc = glGetAttribLocation(shader->id, "vertexPosition"); shader->texcoordLoc = glGetAttribLocation(shader->id, "vertexTexCoord"); shader->normalLoc = glGetAttribLocation(shader->id, "vertexNormal"); shader->colorLoc = glGetAttribLocation(shader->id, "vertexColor"); + shader->tangentLoc = glGetAttribLocation(shader->id, "vertexTangent"); + shader->texcoord2Loc = glGetAttribLocation(shader->id, "vertexTexCoord2"); // Get handles to GLSL uniform locations (vertex shader) shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); -- cgit v1.2.3 From dc4d5dabcdf8f35f32acb9c5b48a24b1141c460f Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 9 May 2016 01:18:46 +0200 Subject: Added MTL loading info --- src/models.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index ee04b449..7b6deb5c 100644 --- a/src/models.c +++ b/src/models.c @@ -2001,7 +2001,26 @@ static Material LoadMTL(const char *fileName) { Material material = { 0 }; - // TODO: Load mtl file + // TODO: Load mtl file (multiple variations of .mtl format) + /* + newmtl string Material newmtl (material name). Begins a new material description. + Ka float float float Ambient color Ka (red) (green) (blue) + Kd float float float Diffuse color Kd (red) (green) (blue) + Ks float float float Specular color Ks (red) (green) (blue) + Ke float float float Emmisive color + d float Tr float Dissolve factor. Transparency Tr (alpha). d is inverse of Tr + Ns int Shininess Ns (specular power). Ranges from 0 to 1000. Specular exponent. + Ni int Refraction index. + illum int Illumination model illum (1 / 2); 1 if specular disabled, 2 if specular enabled (lambertian model) + map_Kd string Texture map_Kd (filename) + map_Kd string Diffuse color texture map. + map_Ks string Specular color texture map. + map_Ka string Ambient color texture map. + map_Bump string Bump texture map. Alternative: bump string / map_bump string + map_d string Opacity texture map. + disp string Displacement map + refl Reflection type and map + */ char dataType; char comments[200]; -- cgit v1.2.3 From 3d0208223ad5b79cb4c3d6cd367d39f9d4e51662 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 9 May 2016 12:40:59 +0200 Subject: First implementation of MTL loading Not tested yet --- src/models.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 132 insertions(+), 24 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 7b6deb5c..dff6b224 100644 --- a/src/models.c +++ b/src/models.c @@ -1997,33 +1997,16 @@ static Mesh LoadOBJ(const char *fileName) } // Load MTL material data +// NOTE: Texture map parameters are not supported static Material LoadMTL(const char *fileName) { - Material material = { 0 }; + #define MAX_BUFFER_SIZE 128 - // TODO: Load mtl file (multiple variations of .mtl format) - /* - newmtl string Material newmtl (material name). Begins a new material description. - Ka float float float Ambient color Ka (red) (green) (blue) - Kd float float float Diffuse color Kd (red) (green) (blue) - Ks float float float Specular color Ks (red) (green) (blue) - Ke float float float Emmisive color - d float Tr float Dissolve factor. Transparency Tr (alpha). d is inverse of Tr - Ns int Shininess Ns (specular power). Ranges from 0 to 1000. Specular exponent. - Ni int Refraction index. - illum int Illumination model illum (1 / 2); 1 if specular disabled, 2 if specular enabled (lambertian model) - map_Kd string Texture map_Kd (filename) - map_Kd string Diffuse color texture map. - map_Ks string Specular color texture map. - map_Ka string Ambient color texture map. - map_Bump string Bump texture map. Alternative: bump string / map_bump string - map_d string Opacity texture map. - disp string Displacement map - refl Reflection type and map - */ + Material material = { 0 }; // LoadDefaultMaterial(); - char dataType; - char comments[200]; + char buffer[MAX_BUFFER_SIZE]; + Vector3 color = { 1.0f, 1.0f, 1.0f }; + char *mapFileName; FILE *mtlFile; @@ -2037,7 +2020,132 @@ static Material LoadMTL(const char *fileName) while(!feof(mtlFile)) { - fscanf(mtlFile, "%c", &dataType); + fgets(buffer, MAX_BUFFER_SIZE, mtlFile); + + switch (buffer[0]) + { + case 'n': // newmtl string Material name. Begins a new material description. + { + // TODO: Support multiple materials in a single .mtl + sscanf(buffer, "newmtl %s", mapFileName); + + TraceLog(INFO, "[%s] Loading material...", mapFileName); + } + case 'i': // illum int Illumination model + { + // illum = 1 if specular disabled + // illum = 2 if specular enabled (lambertian model) + // ... + } + case 'K': // Ka, Kd, Ks, Ke + { + switch (buffer[1]) + { + case 'a': // Ka float float float Ambient color (RGB) + { + sscanf(buffer, "Ka %f %f %f", &color.x, &color.y, &color.z); + material.colAmbient.r = (unsigned char)(color.x*255); + material.colAmbient.g = (unsigned char)(color.y*255); + material.colAmbient.b = (unsigned char)(color.z*255); + } break; + case 'd': // Kd float float float Diffuse color (RGB) + { + sscanf(buffer, "Kd %f %f %f", &color.x, &color.y, &color.z); + material.colDiffuse.r = (unsigned char)(color.x*255); + material.colDiffuse.g = (unsigned char)(color.y*255); + material.colDiffuse.b = (unsigned char)(color.z*255); + } break; + case 's': // Ks float float float Specular color (RGB) + { + sscanf(buffer, "Ks %f %f %f", &color.x, &color.y, &color.z); + material.colSpecular.r = (unsigned char)(color.x*255); + material.colSpecular.g = (unsigned char)(color.y*255); + material.colSpecular.b = (unsigned char)(color.z*255); + } break; + case 'e': // Ke float float float Emmisive color (RGB) + { + // TODO: Support Ke ? + } break; + default: break; + } + } break; + case 'N': // Ns, Ni + { + if (buffer[1] == 's') // Ns int Shininess (specular exponent). Ranges from 0 to 1000. + { + sscanf(buffer, "Ns %i", &material.glossiness); + } + else if (buffer[1] == 'i') // Ni int Refraction index. + { + // Not supported... + } + } break; + case 'm': // map_Kd, map_Ks, map_Ka, map_Bump, map_d + { + switch (buffer[4]) + { + case 'K': // Color texture maps + { + if (buffer[5] == 'd') // map_Kd string Diffuse color texture map. + { + sscanf(buffer, "map_Kd %s", mapFileName); + if (mapFileName != NULL) material.texDiffuse = LoadTexture(mapFileName); + } + else if (buffer[5] == 's') // map_Ks string Specular color texture map. + { + sscanf(buffer, "map_Ks %s", mapFileName); + if (mapFileName != NULL) material.texSpecular = LoadTexture(mapFileName); + } + else if (buffer[5] == 'a') // map_Ka string Ambient color texture map. + { + // Not supported... + } + } break; + case 'B': // map_Bump string Bump texture map. + { + sscanf(buffer, "map_Bump %s", mapFileName); + if (mapFileName != NULL) material.texNormal = LoadTexture(mapFileName); + } break; + case 'b': // map_bump string Bump texture map. + { + sscanf(buffer, "map_bump %s", mapFileName); + if (mapFileName != NULL) material.texNormal = LoadTexture(mapFileName); + } break; + case 'd': // map_d string Opacity texture map. + { + // Not supported... + } break; + default: break; + } + } break; + case 'd': // d, disp + { + if (buffer[1] == ' ') // d float Dissolve factor. d is inverse of Tr + { + float alpha = 1.0f; + sscanf(buffer, "d %f", &alpha); + material.colDiffuse.a = (unsigned char)(alpha*255); + } + else if (buffer[1] == 'i') // disp string Displacement map + { + // Not supported... + } + } break; + case 'b': // bump string Bump texture map + { + sscanf(buffer, "bump %s", mapFileName); + if (mapFileName != NULL) material.texNormal = LoadTexture(mapFileName); + } break; + case 'T': // Tr float Transparency Tr (alpha). Tr is inverse of d + { + float ialpha = 0.0f; + sscanf(buffer, "Tr %f", &ialpha); + material.colDiffuse.a = (unsigned char)((1.0f - ialpha)*255); + + } break; + case 'r': // refl string Reflection texture map + default: break; + } } fclose(mtlFile); -- cgit v1.2.3 From ac44db26a2a2bed901c7e75d96e215fa09bd3705 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 9 May 2016 13:16:44 +0200 Subject: Added reference --- src/models.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index dff6b224..7d24e383 100644 --- a/src/models.c +++ b/src/models.c @@ -1996,7 +1996,7 @@ static Mesh LoadOBJ(const char *fileName) return mesh; } -// Load MTL material data +// Load MTL material data (specs: http://paulbourke.net/dataformats/mtl/) // NOTE: Texture map parameters are not supported static Material LoadMTL(const char *fileName) { -- cgit v1.2.3 From 1ddf594d15f31f1502eeb18f0f0c8039799fff01 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 May 2016 18:24:28 +0200 Subject: Added support for indexed mesh data --- src/models.c | 21 +++++++++++++++++---- src/raylib.h | 7 +++++-- src/rlgl.c | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 50 insertions(+), 17 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 7d24e383..41150179 100644 --- a/src/models.c +++ b/src/models.c @@ -553,7 +553,7 @@ Model LoadModel(const char *fileName) if (model.mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); else { - rlglLoadMesh(&model.mesh); // Upload vertex data to GPU + rlglLoadMesh(&model.mesh); // Upload vertex data to GPU model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -567,7 +567,9 @@ Model LoadModelEx(Mesh data) { Model model = { 0 }; - rlglLoadMesh(&data); // Upload vertex data to GPU + model.mesh = data; + + rlglLoadMesh(&model.mesh); // Upload vertex data to GPU model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -693,12 +695,13 @@ Model LoadCubicmap(Image cubicmap) void UnloadModel(Model model) { // Unload mesh data - free(model.mesh.vertices); - free(model.mesh.texcoords); + if (model.mesh.vertices != NULL) free(model.mesh.vertices); + if (model.mesh.texcoords != NULL) free(model.mesh.texcoords); if (model.mesh.normals != NULL) free(model.mesh.normals); if (model.mesh.colors != NULL) free(model.mesh.colors); if (model.mesh.tangents != NULL) free(model.mesh.tangents); if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); + if (model.mesh.indices != NULL) free(model.mesh.indices); TraceLog(INFO, "Unloaded model data from RAM (CPU)"); @@ -708,8 +711,11 @@ void UnloadModel(Model model) rlDeleteBuffers(model.mesh.vboId[3]); // colors rlDeleteBuffers(model.mesh.vboId[4]); // tangents rlDeleteBuffers(model.mesh.vboId[5]); // texcoords2 + rlDeleteBuffers(model.mesh.vboId[6]); // indices rlDeleteVertexArrays(model.mesh.vaoId); + + UnloadMaterial(model.material); } // Load material data (from file) @@ -743,6 +749,13 @@ Material LoadDefaultMaterial(void) return material; } +void UnloadMaterial(Material material) +{ + rlDeleteTextures(material.texDiffuse.id); + rlDeleteTextures(material.texNormal.id); + rlDeleteTextures(material.texSpecular.id); +} + // Link a texture to a model void SetModelTexture(Model *model, Texture2D texture) { diff --git a/src/raylib.h b/src/raylib.h index 1258bffc..05463325 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -368,18 +368,20 @@ typedef struct BoundingBox { // Vertex data definning a mesh typedef struct Mesh { - int vertexCount; // num vertices + int vertexCount; // number of vertices stored in arrays float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices; // vertex indices (in case vertex data comes indexed) + int trianglesCount; // number of triangles to draw BoundingBox bounds; // mesh limits defined by min and max points unsigned int vaoId; // OpenGL Vertex Array Object id - unsigned int vboId[6]; // OpenGL Vertex Buffer Objects id (6 types of vertex data) + unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; // Shader type (generic shader) @@ -813,6 +815,7 @@ void SetModelTexture(Model *model, Texture2D texture); // Link a textur Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadDefaultMaterial(void); // Load default material (uses default models shader) +void UnloadMaterial(Material material); // Unload material textures from VRAM void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters diff --git a/src/rlgl.c b/src/rlgl.c index 33f12deb..8364c4f1 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -783,16 +783,16 @@ void rlDisableDepthTest(void) // Unload texture from GPU memory void rlDeleteTextures(unsigned int id) { - glDeleteTextures(1, &id); + if (id != 0) glDeleteTextures(1, &id); } // Unload render texture from GPU memory void rlDeleteRenderTextures(RenderTexture2D target) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDeleteFramebuffers(1, &target.id); - glDeleteTextures(1, &target.texture.id); - glDeleteTextures(1, &target.depth.id); + if (target.id != 0) glDeleteFramebuffers(1, &target.id); + if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); + if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); #endif } @@ -800,7 +800,7 @@ void rlDeleteRenderTextures(RenderTexture2D target) void rlDeleteShader(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glDeleteProgram(id); + if (id != 0) glDeleteProgram(id); #endif } @@ -810,7 +810,7 @@ void rlDeleteVertexArrays(unsigned int id) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (vaoSupported) { - glDeleteVertexArrays(1, &id); + if (id != 0) glDeleteVertexArrays(1, &id); TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); } #endif @@ -1204,10 +1204,13 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(material.shader.texcoord2Loc); } + + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadsBuffer[3]); } // Draw call! - glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.trianglesCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw + else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); if (material.texNormal.id != 0) { @@ -1225,7 +1228,11 @@ void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures if (vaoSupported) glBindVertexArray(0); // Unbind VAO - else glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + else + { + glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } glUseProgram(0); // Unbind shader program #endif @@ -1682,11 +1689,12 @@ void rlglLoadMesh(Mesh *mesh) mesh->vboId[3] = 0; // Vertex colors VBO mesh->vboId[4] = 0; // Vertex tangents VBO mesh->vboId[5] = 0; // Vertex texcoords2 VBO + mesh->vboId[6] = 0; // Vertex indices VBO #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) GLuint vaoId = 0; // Vertex Array Objects (VAO) - GLuint vboId[6]; // Vertex Buffer Objects (VBOs) + GLuint vboId[7]; // Vertex Buffer Objects (VBOs) if (vaoSupported) { @@ -1775,12 +1783,21 @@ void rlglLoadMesh(Mesh *mesh) glDisableVertexAttribArray(5); } + if (mesh->indices != NULL) + { + glGenBuffers(1, &vboId[6]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[6]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*mesh->trianglesCount*3, mesh->indices, GL_STATIC_DRAW); + } + + mesh->vboId[0] = vboId[0]; // Vertex position VBO mesh->vboId[1] = vboId[1]; // Texcoords VBO mesh->vboId[2] = vboId[2]; // Normals VBO mesh->vboId[3] = vboId[3]; // Colors VBO mesh->vboId[4] = vboId[4]; // Tangents VBO mesh->vboId[5] = vboId[5]; // Texcoords2 VBO + mesh->vboId[6] = vboId[6]; // Indices VBO if (vaoSupported) { @@ -2733,9 +2750,9 @@ static void DrawDefaultBuffers(void) // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process #if defined(GRAPHICS_API_OPENGL_33) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid*) (sizeof(GLuint) * indicesOffset)); + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_INT, (GLvoid *)(sizeof(GLuint)*indicesOffset)); #elif defined(GRAPHICS_API_OPENGL_ES2) - glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid*) (sizeof(GLushort) * indicesOffset)); + glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset)); #endif //GLenum err; //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! -- cgit v1.2.3 From aee5d9a39026d7cff2536806c1f10e25ccc57dcc Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 10 May 2016 19:24:05 +0200 Subject: Code tweak --- src/models.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 41150179..066b919e 100644 --- a/src/models.c +++ b/src/models.c @@ -2019,7 +2019,7 @@ static Material LoadMTL(const char *fileName) char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; - char *mapFileName; + char *mapFileName = NULL; FILE *mtlFile; -- cgit v1.2.3 From 037edbaa1322a2174d91c7aeacc9170f5b6913cb Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 18 May 2016 13:22:14 +0200 Subject: Reorganize data for consistency --- src/models.c | 54 ++------ src/rlgl.c | 431 ++++++++++++++++++++++++++++++++++++----------------------- src/rlgl.h | 9 +- 3 files changed, 283 insertions(+), 211 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 066b919e..bb2d56c2 100644 --- a/src/models.c +++ b/src/models.c @@ -691,31 +691,14 @@ Model LoadCubicmap(Image cubicmap) return model; } -// Unload 3d model from memory +// Unload 3d model from memory (mesh and material) void UnloadModel(Model model) { - // Unload mesh data - if (model.mesh.vertices != NULL) free(model.mesh.vertices); - if (model.mesh.texcoords != NULL) free(model.mesh.texcoords); - if (model.mesh.normals != NULL) free(model.mesh.normals); - if (model.mesh.colors != NULL) free(model.mesh.colors); - if (model.mesh.tangents != NULL) free(model.mesh.tangents); - if (model.mesh.texcoords2 != NULL) free(model.mesh.texcoords2); - if (model.mesh.indices != NULL) free(model.mesh.indices); - - TraceLog(INFO, "Unloaded model data from RAM (CPU)"); - - rlDeleteBuffers(model.mesh.vboId[0]); // vertex - rlDeleteBuffers(model.mesh.vboId[1]); // texcoords - rlDeleteBuffers(model.mesh.vboId[2]); // normals - rlDeleteBuffers(model.mesh.vboId[3]); // colors - rlDeleteBuffers(model.mesh.vboId[4]); // tangents - rlDeleteBuffers(model.mesh.vboId[5]); // texcoords2 - rlDeleteBuffers(model.mesh.vboId[6]); // indices - - rlDeleteVertexArrays(model.mesh.vaoId); - + rlglUnloadMesh(&model.mesh); + UnloadMaterial(model.material); + + TraceLog(INFO, "Unloaded model data from RAM and VRAM"); } // Load material data (from file) @@ -1247,40 +1230,27 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); model.material.colDiffuse = tint; - rlglDrawEx(model.mesh, model.material, model.transform, false); + rlglDrawMesh(model.mesh, model.material, model.transform); } // Draw a model wires (with texture if set) void DrawModelWires(Model model, Vector3 position, float scale, Color tint) { - Vector3 vScale = { scale, scale, scale }; - Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - - // Calculate transformation matrix from function parameters - // Get transform matrix (rotation -> scale -> translation) - Matrix matRotation = MatrixRotate(rotationAxis, 0.0f); - Matrix matScale = MatrixScale(vScale.x, vScale.y, vScale.z); - Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + rlEnableWireMode(); - model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - model.material.colDiffuse = tint; + DrawModel(model, position, scale, tint); - rlglDrawEx(model.mesh, model.material, model.transform, true); + rlDisableWireMode(); } // Draw a model wires (with texture if set) with extended parameters void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { - // Calculate transformation matrix from function parameters - // Get transform matrix (rotation -> scale -> translation) - Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); - Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); - Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + rlEnableWireMode(); - model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - model.material.colDiffuse = tint; + DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint); - rlglDrawEx(model.mesh, model.material, model.transform, true); + rlDisableWireMode(); } // Draw a billboard diff --git a/src/rlgl.c b/src/rlgl.c index 0c0da221..8e725521 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -740,6 +740,24 @@ void rlDisableDepthTest(void) glDisable(GL_DEPTH_TEST); } +// Enable wire mode +void rlEnableWireMode(void) +{ +#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif +} + +// Disable wire mode +void rlDisableWireMode(void) +{ +#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) + // NOTE: glPolygonMode() not available on OpenGL ES + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif +} + // Unload texture from GPU memory void rlDeleteTextures(unsigned int id) { @@ -1033,175 +1051,15 @@ void rlglClose(void) void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - UpdateDefaultBuffers(); - DrawDefaultBuffers(); -#endif -} - -// Draw a 3d mesh with material and transform -void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires) -{ -#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - // NOTE: glPolygonMode() not available on OpenGL ES - if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -#endif - -#if defined(GRAPHICS_API_OPENGL_11) - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); - - // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model - glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array - glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array - if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array - if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array - - glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array - glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array - if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array - if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array - - rlPushMatrix(); - rlMultMatrixf(MatrixToFloat(transform)); - rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); - - if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); - else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); - rlPopMatrix(); - - glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array - glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array - if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array - if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array - - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); -#endif - -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(material.shader.id); - - // At this point the modelview matrix just contains the view matrix (camera) - // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() - Matrix matView = modelview; // View matrix (camera) - Matrix matProjection = projection; // Projection matrix (perspective) - - // Calculate model-view matrix combining matModel and matView - Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates - - // Calculate model-view-projection matrix (MVP) - Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates - - // Send combined model-view-projection matrix to shader - glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - - // Apply color tinting (material.colDiffuse) - // NOTE: Just update one uniform on fragment shader - float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; - glUniform4fv(material.shader.tintColorLoc, 1, vColor); - - // Set shader textures (diffuse, normal, specular) - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); - glUniform1i(material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 - - if ((material.texNormal.id != 0) && (material.shader.mapNormalLoc != -1)) - { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, material.texNormal.id); - glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 - } - - if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1)) - { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); - glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 - } - - if (vaoSupported) - { - glBindVertexArray(mesh.vaoId); - } - else - { - // Bind mesh VBO data: vertex position (shader-location = 0) - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); - glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.vertexLoc); - - // Bind mesh VBO data: vertex texcoords (shader-location = 1) - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); - glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.texcoordLoc); - - // Bind mesh VBO data: vertex normals (shader-location = 2, if available) - if (material.shader.normalLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); - glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.normalLoc); - } - - // Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available) - if (material.shader.colorLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); - glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(material.shader.colorLoc); - } - - // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) - if (material.shader.tangentLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); - glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.tangentLoc); - } - - // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) - if (material.shader.texcoord2Loc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); - glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.texcoord2Loc); - } - - if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); - } - - // Draw call! - if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw - else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); - - if (material.texNormal.id != 0) - { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - } - - if (material.texSpecular.id != 0) - { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, 0); - } - - glActiveTexture(GL_TEXTURE0); // Set shader active texture to default 0 - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures - - if (vaoSupported) glBindVertexArray(0); // Unbind VAO - else +/* + for (int i = 0; i < modelsCount; i++) { - glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs - if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); } - - glUseProgram(0); // Unbind shader program -#endif - -#if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - // NOTE: glPolygonMode() not available on OpenGL ES - if (wires) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +*/ + // NOTE: Default buffers always drawn at the end + UpdateDefaultBuffers(); + DrawDefaultBuffers(); #endif } @@ -1776,6 +1634,245 @@ void rlglLoadMesh(Mesh *mesh) #endif } +// Update vertex data on GPU (upload new data to one buffer) +void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) +{ + // Activate mesh VAO + if (vaoSupported) glBindVertexArray(mesh.vaoId); + + switch (buffer) + { + case 0: // Update vertices (vertex position) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); + if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.vertices, GL_DYNAMIC_DRAW); + else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.vertices); + + } break; + case 1: // Update texcoords (vertex texture coordinates) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); + if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords, GL_DYNAMIC_DRAW); + else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords); + + } break; + case 2: // Update normals (vertex normals) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); + if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.normals, GL_DYNAMIC_DRAW); + else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.normals); + + } break; + case 3: // Update colors (vertex colors) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); + if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*numVertex, mesh.colors, GL_DYNAMIC_DRAW); + else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*numVertex, mesh.colors); + + } break; + case 4: // Update tangents (vertex tangents) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); + if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.tangents, GL_DYNAMIC_DRAW); + else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.tangents); + } break; + case 5: // Update texcoords2 (vertex second texture coordinates) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); + if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords2, GL_DYNAMIC_DRAW); + else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords2); + } break; + default: break; + } + + // Unbind the current VAO + if (vaoSupported) glBindVertexArray(0); + + // Another option would be using buffer mapping... + //mesh.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); + // Now we can modify vertices + //glUnmapBuffer(GL_ARRAY_BUFFER); +} + +// Draw a 3d mesh with material and transform +void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) +{ +#if defined(GRAPHICS_API_OPENGL_11) + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); + + // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model + glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array + glEnableClientState(GL_TEXTURE_COORD_ARRAY); // Enable texture coords array + if (mesh.normals != NULL) glEnableClientState(GL_NORMAL_ARRAY); // Enable normals array + if (mesh.colors != NULL) glEnableClientState(GL_COLOR_ARRAY); // Enable colors array + + glVertexPointer(3, GL_FLOAT, 0, mesh.vertices); // Pointer to vertex coords array + glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array + if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array + if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array + + rlPushMatrix(); + rlMultMatrixf(MatrixToFloat(transform)); + rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); + + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); + else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + rlPopMatrix(); + + glDisableClientState(GL_VERTEX_ARRAY); // Disable vertex array + glDisableClientState(GL_TEXTURE_COORD_ARRAY); // Disable texture coords array + if (mesh.normals != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable normals array + if (mesh.colors != NULL) glDisableClientState(GL_NORMAL_ARRAY); // Disable colors array + + glDisable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, 0); +#endif + +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(material.shader.id); + + // At this point the modelview matrix just contains the view matrix (camera) + // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() + Matrix matView = modelview; // View matrix (camera) + Matrix matProjection = projection; // Projection matrix (perspective) + + // Calculate model-view matrix combining matModel and matView + Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates + + // Calculate model-view-projection matrix (MVP) + Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates + + // Send combined model-view-projection matrix to shader + glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + + // Apply color tinting (material.colDiffuse) + // NOTE: Just update one uniform on fragment shader + float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; + glUniform4fv(material.shader.tintColorLoc, 1, vColor); + + // Set shader textures (diffuse, normal, specular) + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); + glUniform1i(material.shader.mapDiffuseLoc, 0); // Texture fits in active texture unit 0 + + if ((material.texNormal.id != 0) && (material.shader.mapNormalLoc != -1)) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, material.texNormal.id); + glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 + } + + if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1)) + { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); + glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 + } + + if (vaoSupported) + { + glBindVertexArray(mesh.vaoId); + } + else + { + // Bind mesh VBO data: vertex position (shader-location = 0) + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); + glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.vertexLoc); + + // Bind mesh VBO data: vertex texcoords (shader-location = 1) + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); + glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.texcoordLoc); + + // Bind mesh VBO data: vertex normals (shader-location = 2, if available) + if (material.shader.normalLoc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); + glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.normalLoc); + } + + // Bind mesh VBO data: vertex colors (shader-location = 3, if available) , tangents, texcoords2 (if available) + if (material.shader.colorLoc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); + glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(material.shader.colorLoc); + } + + // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) + if (material.shader.tangentLoc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); + glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.tangentLoc); + } + + // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) + if (material.shader.texcoord2Loc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); + glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.texcoord2Loc); + } + + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); + } + + // Draw call! + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw + else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); + + if (material.texNormal.id != 0) + { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, 0); + } + + if (material.texSpecular.id != 0) + { + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, 0); + } + + glActiveTexture(GL_TEXTURE0); // Set shader active texture to default 0 + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + + if (vaoSupported) glBindVertexArray(0); // Unbind VAO + else + { + glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + glUseProgram(0); // Unbind shader program +#endif +} + +// Unload mesh data from CPU and GPU +void rlglUnloadMesh(Mesh *mesh) +{ + if (mesh->vertices != NULL) free(mesh->vertices); + if (mesh->texcoords != NULL) free(mesh->texcoords); + if (mesh->normals != NULL) free(mesh->normals); + if (mesh->colors != NULL) free(mesh->colors); + if (mesh->tangents != NULL) free(mesh->tangents); + if (mesh->texcoords2 != NULL) free(mesh->texcoords2); + if (mesh->indices != NULL) free(mesh->indices); + + rlDeleteBuffers(mesh->vboId[0]); // vertex + rlDeleteBuffers(mesh->vboId[1]); // texcoords + rlDeleteBuffers(mesh->vboId[2]); // normals + rlDeleteBuffers(mesh->vboId[3]); // colors + rlDeleteBuffers(mesh->vboId[4]); // tangents + rlDeleteBuffers(mesh->vboId[5]); // texcoords2 + rlDeleteBuffers(mesh->vboId[6]); // indices + + rlDeleteVertexArrays(mesh->vaoId); +} + // Read screen pixel data (color buffer) unsigned char *rlglReadScreenPixels(int width, int height) { diff --git a/src/rlgl.h b/src/rlgl.h index 7b88bc9e..a33e3a0a 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -256,6 +256,8 @@ void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo) void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer void rlEnableDepthTest(void); // Enable depth test void rlDisableDepthTest(void); // Disable depth test +void rlEnableWireMode(void); // Enable wire mode +void rlDisableWireMode(void); // Disable wire mode void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU @@ -277,8 +279,11 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data void rlglGenerateMipmaps(Texture2D texture); // Generate mipmap data for selected texture -void rlglLoadMesh(Mesh *mesh); // Upload vertex data into GPU and provided VAO/VBO ids -void rlglDrawEx(Mesh mesh, Material material, Matrix transform, bool wires); + +void rlglLoadMesh(Mesh *mesh); // Upload vertex data into GPU and provided VAO/VBO ids +void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer) +void rlglDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform +void rlglUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates -- cgit v1.2.3 From 7d1d9ff143cd7c6c55d3fd891b43e143431ea15f Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 20 May 2016 09:36:02 +0200 Subject: Support DYNAMIC_DRAW mesh loading --- src/models.c | 10 +++++----- src/raylib.h | 2 +- src/rlgl.c | 17 ++++++++++------- src/rlgl.h | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index bb2d56c2..6d72d1e3 100644 --- a/src/models.c +++ b/src/models.c @@ -553,7 +553,7 @@ Model LoadModel(const char *fileName) if (model.mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); else { - rlglLoadMesh(&model.mesh); // Upload vertex data to GPU + rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -563,13 +563,13 @@ Model LoadModel(const char *fileName) } // Load a 3d model (from vertex data) -Model LoadModelEx(Mesh data) +Model LoadModelEx(Mesh data, bool dynamic) { Model model = { 0 }; model.mesh = data; - rlglLoadMesh(&model.mesh); // Upload vertex data to GPU + rlglLoadMesh(&model.mesh, dynamic); // Upload vertex data to GPU model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -668,7 +668,7 @@ Model LoadHeightmap(Image heightmap, Vector3 size) model.mesh = GenMeshHeightmap(heightmap, size); - rlglLoadMesh(&model.mesh); + rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -683,7 +683,7 @@ Model LoadCubicmap(Image cubicmap) model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f }); - rlglLoadMesh(&model.mesh); + rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); diff --git a/src/raylib.h b/src/raylib.h index 986dc7bf..8a46ec35 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -803,7 +803,7 @@ void DrawGizmo(Vector3 position); // Model 3d Loading and Drawing Functions (Module: models) //------------------------------------------------------------------------------------ Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) -Model LoadModelEx(Mesh data); // Load a 3d model (from mesh data) +Model LoadModelEx(Mesh data, bool dynamic); // Load a 3d model (from mesh data) Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d model from rRES file (raylib Resource) Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) diff --git a/src/rlgl.c b/src/rlgl.c index 888a9313..cc2b8942 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1500,7 +1500,7 @@ void rlglGenerateMipmaps(Texture2D texture) } // Upload vertex data into a VAO (if supported) and VBO -void rlglLoadMesh(Mesh *mesh) +void rlglLoadMesh(Mesh *mesh, bool dynamic) { mesh->vaoId = 0; // Vertex Array Object mesh->vboId[0] = 0; // Vertex positions VBO @@ -1510,6 +1510,9 @@ void rlglLoadMesh(Mesh *mesh) mesh->vboId[4] = 0; // Vertex tangents VBO mesh->vboId[5] = 0; // Vertex texcoords2 VBO mesh->vboId[6] = 0; // Vertex indices VBO + + int drawHint = GL_STATIC_DRAW; + if (dynamic) drawHint = GL_DYNAMIC_DRAW; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) GLuint vaoId = 0; // Vertex Array Objects (VAO) @@ -1527,14 +1530,14 @@ void rlglLoadMesh(Mesh *mesh) // Enable vertex attributes: position (shader-location = 0) glGenBuffers(1, &vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, vboId[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->vertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->vertices, drawHint); glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(0); // Enable vertex attributes: texcoords (shader-location = 1) glGenBuffers(1, &vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, vboId[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords, drawHint); glVertexAttribPointer(1, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(1); @@ -1543,7 +1546,7 @@ void rlglLoadMesh(Mesh *mesh) { glGenBuffers(1, &vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, vboId[2]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->normals, drawHint); glVertexAttribPointer(2, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(2); } @@ -1559,7 +1562,7 @@ void rlglLoadMesh(Mesh *mesh) { glGenBuffers(1, &vboId[3]); glBindBuffer(GL_ARRAY_BUFFER, vboId[3]); - glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh->vertexCount, mesh->colors, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*mesh->vertexCount, mesh->colors, drawHint); glVertexAttribPointer(3, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); glEnableVertexAttribArray(3); } @@ -1575,7 +1578,7 @@ void rlglLoadMesh(Mesh *mesh) { glGenBuffers(1, &vboId[4]); glBindBuffer(GL_ARRAY_BUFFER, vboId[4]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->tangents, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*mesh->vertexCount, mesh->tangents, drawHint); glVertexAttribPointer(4, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(4); } @@ -1591,7 +1594,7 @@ void rlglLoadMesh(Mesh *mesh) { glGenBuffers(1, &vboId[5]); glBindBuffer(GL_ARRAY_BUFFER, vboId[5]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords2, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*mesh->vertexCount, mesh->texcoords2, drawHint); glVertexAttribPointer(5, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(5); } diff --git a/src/rlgl.h b/src/rlgl.h index a33e3a0a..a557ffa2 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -280,7 +280,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a textur void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data void rlglGenerateMipmaps(Texture2D texture); // Generate mipmap data for selected texture -void rlglLoadMesh(Mesh *mesh); // Upload vertex data into GPU and provided VAO/VBO ids +void rlglLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer) void rlglDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform void rlglUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU -- cgit v1.2.3 From dcf5f45f687f2a534286aecd5e6471a0440b0c21 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 20 May 2016 12:28:07 +0200 Subject: Add lighting system -IN PROGRESS- Improved materials --- src/models.c | 12 +++++ src/raylib.h | 30 ++++++++++- src/rlgl.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/rlgl.h | 25 +++++++++ 4 files changed, 228 insertions(+), 6 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 6d72d1e3..44e30390 100644 --- a/src/models.c +++ b/src/models.c @@ -732,6 +732,18 @@ Material LoadDefaultMaterial(void) return material; } +// Load standard material (uses standard models shader) +// NOTE: Standard shader supports multiple maps and lights +Material LoadStandardMaterial(void) +{ + Material material = LoadDefaultMaterial(); + + //material.shader = GetStandardShader(); + + return material; +} + +// Unload material from memory void UnloadMaterial(Material material) { rlDeleteTextures(material.texDiffuse.id); diff --git a/src/raylib.h b/src/raylib.h index fc1914bb..d98a0797 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -422,13 +422,38 @@ typedef struct Material { float normalDepth; // Normal map depth } Material; -// 3d Model type +// Model type typedef struct Model { Mesh mesh; // Vertex data buffers (RAM and VRAM) Matrix transform; // Local transform matrix Material material; // Shader and textures data } Model; +// Light type +// TODO: Review contained data to support different light types and features +typedef struct LightData { + int id; + int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; + + Vector3 position; + Vector3 direction; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction) + float attenuation; // Lost of light intensity with distance (use radius?) + + Color diffuse; // Use Vector3 diffuse (including intensities)? + float intensity; + + Color specular; + //float specFactor; // Specular intensity ? + + //Color ambient; // Required? + + float coneAngle; // SpotLight +} LightData, *Light; + +// Light types +typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; + // Ray type (useful for raycast) typedef struct Ray { Vector3 position; @@ -849,6 +874,9 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) +Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool +void DestroyLight(Light light); // Destroy a light and take it out of the list + //---------------------------------------------------------------------------------- // Physics System Functions (Module: physac) //---------------------------------------------------------------------------------- diff --git a/src/rlgl.c b/src/rlgl.c index cc2b8942..e971d747 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -71,6 +71,8 @@ #define MAX_DRAWS_BY_TEXTURE 256 // Draws are organized by texture changes #define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations) // NOTE: Every vertex are 3 floats (12 bytes) + +#define MAX_LIGHTS 8 // Max lights supported by standard shader #ifndef GL_SHADING_LANGUAGE_VERSION #define GL_SHADING_LANGUAGE_VERSION 0x8B8C @@ -199,6 +201,10 @@ static bool texCompETC1Supported = false; // ETC1 texture compression support static bool texCompETC2Supported = false; // ETC2/EAC texture compression support static bool texCompPVRTSupported = false; // PVR texture compression support static bool texCompASTCSupported = false; // ASTC texture compression support + +// Lighting data +static Light lights[MAX_LIGHTS]; // Lights pool +static int lightsCount; // Counts current enabled physic objects #endif // Compressed textures support flags @@ -227,6 +233,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shader strings and return program id static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring) +static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting) static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) static void UnloadDefaultShader(void); // Unload default shader @@ -235,6 +242,8 @@ static void UpdateDefaultBuffers(void); // Update default internal buffers ( static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +static void SetShaderLights(Shader shader); // Sets shader uniform values for lights array + static char *ReadTextFile(const char *fileName); #endif @@ -1749,11 +1758,19 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Send combined model-view-projection matrix to shader glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - // Apply color tinting (material.colDiffuse) - // NOTE: Just update one uniform on fragment shader - float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; - glUniform4fv(material.shader.tintColorLoc, 1, vColor); - + // Setup shader uniforms for material related data + // TODO: Check if using standard shader to get location points + + // Upload to shader material.colDiffuse + float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; + glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse); + + // TODO: Upload to shader material.colAmbient + // glUniform4f(???, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); + + // TODO: Upload to shader material.colSpecular + // glUniform4f(???, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); + // Set shader textures (diffuse, normal, specular) glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); @@ -1764,6 +1781,9 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, material.texNormal.id); glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1 + + // TODO: Upload to shader normalDepth + //glUniform1f(???, material.normalDepth); } if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1)) @@ -1771,7 +1791,13 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 + + // TODO: Upload to shader glossiness + //glUniform1f(???, material.glossiness); } + + // Setup shader uniforms for lights + SetShaderLights(material.shader); if (vaoSupported) { @@ -2198,6 +2224,55 @@ void SetBlendMode(int mode) } } +// Create a new light, initialize it and add to pool +// TODO: Review creation parameters (only generic ones) +Light CreateLight(int type, Vector3 position, Color diffuse) +{ + // Allocate dynamic memory + Light light = (Light)malloc(sizeof(LightData)); + + // Initialize light values with generic values + light->id = lightsCount; + light->type = type; + light->enabled = true; + + light->position = position; + light->direction = (Vector3){ 0.0f, 0.0f, 0.0f }; + light->intensity = 1.0f; + light->diffuse = diffuse; + light->specular = WHITE; + + // Add new light to the array + lights[lightsCount] = light; + + // Increase enabled lights count + lightsCount++; + + return light; +} + +// Destroy a light and take it out of the list +void DestroyLight(Light light) +{ + // Free dynamic memory allocation + free(lights[light->id]); + + // Remove *obj from the pointers array + for (int i = light->id; i < lightsCount; i++) + { + // Resort all the following pointers of the array + if ((i + 1) < lightsCount) + { + lights[i] = lights[i + 1]; + lights[i]->id = lights[i + 1]->id; + } + else free(lights[i]); + } + + // Decrease enabled physic objects count + lightsCount--; +} + //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- @@ -2415,6 +2490,32 @@ static Shader LoadDefaultShader(void) return shader; } +// Load standard shader +// NOTE: This shader supports: +// - Up to 3 different maps: diffuse, normal, specular +// - Material properties: colDiffuse, colAmbient, colSpecular, glossiness, normalDepth +// - Up to 8 lights: Point, Directional or Spot +static Shader LoadStandardShader(void) +{ + Shader shader; + + char *vShaderStr; + char *fShaderStr; + + // TODO: Implement standard uber-shader, supporting all features (GLSL 100 / GLSL 330) + + // NOTE: Shader could be quite extensive so it could be implemented in external files (standard.vs/standard.fs) + + shader.id = LoadShaderProgram(vShaderStr, fShaderStr); + + if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id); + else TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded", shader.id); + + if (shader.id != 0) LoadDefaultShaderLocations(&shader); // TODO: Review locations fetching + + return shader; +} + // Get location handlers to for shader attributes and uniforms // NOTE: If any location is not found, loc point becomes -1 static void LoadDefaultShaderLocations(Shader *shader) @@ -2900,6 +3001,62 @@ static void UnloadDefaultBuffers(void) free(quads.indices); } +// Sets shader uniform values for lights array +// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f +// TODO: Review memcpy() and parameters pass +static void SetShaderLights(Shader shader) +{ + /* + // NOTE: Standard Shader must include the following data: + + // Shader Light struct + struct Light { + vec3 position; + vec3 direction; + + vec3 diffuse; + float intensity; + } + + const int maxLights = 8; + uniform int lightsCount; // Number of lights + uniform Light lights[maxLights]; + */ + + int locPoint; + char locName[32] = "lights[x].position\0"; + + glUseProgram(shader.id); + + locPoint = glGetUniformLocation(shader.id, "lightsCount"); + glUniform1i(locPoint, lightsCount); + + for (int i = 0; i < lightsCount; i++) + { + locName[7] = '0' + i; + + memcpy(&locName[10], "position\0", strlen("position\0")); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + memcpy(&locName[10], "direction\0", strlen("direction\0")); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform3f(locPoint, lights[i]->direction.x, lights[i]->direction.y, lights[i]->direction.z); + + memcpy(&locName[10], "diffuse\0", strlen("diffuse\0")); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255 ); + + memcpy(&locName[10], "intensity\0", strlen("intensity\0")); + locPoint = glGetUniformLocation(shader.id, locName); + glUniform1f(locPoint, lights[i]->intensity); + + // TODO: Pass to the shader any other required data from LightData struct + } + + glUseProgram(0); +} + // Read text data from file // NOTE: text chars array should be freed manually static char *ReadTextFile(const char *fileName) diff --git a/src/rlgl.h b/src/rlgl.h index a557ffa2..39941b33 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -209,6 +209,28 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; float glossiness; float normalDepth; } Material; + + // Light type + // TODO: Review contained data to support different light types and features + typedef struct LightData { + int id; + int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; + + Vector3 position; + Vector3 direction; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction) + float attenuation; // Lost of light intensity with distance (use radius?) + + Color diffuse; // Use Vector3 diffuse (including intensities)? + float intensity; + + Color specular; + //float specFactor; // Specular intensity ? + + //Color ambient; // Required? + + float coneAngle; // SpotLight + } LightData, *Light; // Color blending modes (pre-defined) typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; @@ -311,6 +333,9 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // S void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) + +Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool +void DestroyLight(Light light); // Destroy a light and take it out of the list #endif #ifdef __cplusplus -- cgit v1.2.3 From 90c62c4cc0bc79ea51ae114467757a8d80c38fa6 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Fri, 20 May 2016 14:07:50 +0200 Subject: Fix small warning Material glossiness is a float type value... --- src/models.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 44e30390..0e59242b 100644 --- a/src/models.c +++ b/src/models.c @@ -2068,7 +2068,7 @@ static Material LoadMTL(const char *fileName) { if (buffer[1] == 's') // Ns int Shininess (specular exponent). Ranges from 0 to 1000. { - sscanf(buffer, "Ns %i", &material.glossiness); + sscanf(buffer, "Ns %f", &material.glossiness); } else if (buffer[1] == 'i') // Ni int Refraction index. { -- cgit v1.2.3 From 3fa6fdacf2be438cfc81d3ae5ef2b58801aecce6 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Fri, 20 May 2016 14:24:53 +0200 Subject: Improved MTL loading shininess value --- src/models.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 0e59242b..414f6716 100644 --- a/src/models.c +++ b/src/models.c @@ -2068,7 +2068,11 @@ static Material LoadMTL(const char *fileName) { if (buffer[1] == 's') // Ns int Shininess (specular exponent). Ranges from 0 to 1000. { - sscanf(buffer, "Ns %f", &material.glossiness); + int shininess = 0; + sscanf(buffer, "Ns %i", &shininess); + + // Normalize shininess value to material glossiness attribute + material.glossiness = (float)shininess/1000; } else if (buffer[1] == 'i') // Ni int Refraction index. { -- cgit v1.2.3 From 30c8058fca39e4d6566b2fc06ae2498c48c00717 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Fri, 20 May 2016 17:18:07 +0200 Subject: Add standard lighting (1/3) - Ambient and lambert lighting added. - Ambient and diffuse colors linked to standard shader. - Single light linked to standard shader. - LoadStandardMaterial() and depending functions added. --- src/models.c | 6 +-- src/raylib.h | 9 ++-- src/rlgl.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 131 insertions(+), 33 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 414f6716..2629dffd 100644 --- a/src/models.c +++ b/src/models.c @@ -732,13 +732,13 @@ Material LoadDefaultMaterial(void) return material; } -// Load standard material (uses standard models shader) +// Load standard material (uses material attributes and lighting shader) // NOTE: Standard shader supports multiple maps and lights Material LoadStandardMaterial(void) { Material material = LoadDefaultMaterial(); - //material.shader = GetStandardShader(); + material.shader = GetStandardShader(); return material; } @@ -1240,7 +1240,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - model.material.colDiffuse = tint; + // model.material.colDiffuse = tint; rlglDrawMesh(model.mesh, model.material, model.transform); } diff --git a/src/raylib.h b/src/raylib.h index d98a0797..48534fd6 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -398,7 +398,7 @@ typedef struct Shader { // Uniform locations int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int tintColorLoc; // Color uniform location point (fragment shader) + int tintColorLoc; // Diffuse color uniform location point (fragment shader) // Texture map locations int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) @@ -444,11 +444,8 @@ typedef struct LightData { float intensity; Color specular; - //float specFactor; // Specular intensity ? - - //Color ambient; // Required? - float coneAngle; // SpotLight + float coneAngle; // SpotLight } LightData, *Light; // Light types @@ -836,6 +833,7 @@ void SetModelTexture(Model *model, Texture2D texture); // Link a textur Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadDefaultMaterial(void); // Load default material (uses default models shader) +Material LoadStandardMaterial(void); // Load standard material (uses material attributes and lighting shader) void UnloadMaterial(Material material); // Unload material textures from VRAM void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -865,6 +863,7 @@ void UnloadShader(Shader shader); // Unload a void SetDefaultShader(void); // Set default shader to be used in batch draw void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw Shader GetDefaultShader(void); // Get default shader +Shader GetStandardShader(void); // Get default shader Texture2D GetDefaultTexture(void); // Get default texture int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location diff --git a/src/rlgl.c b/src/rlgl.c index c5048aff..e2195e4d 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -191,6 +191,7 @@ static bool useTempBuffer = false; // Shader Programs static Shader defaultShader; +static Shader standardShader; static Shader currentShader; // By default, defaultShader // Flags for supported extensions @@ -236,6 +237,7 @@ static Shader LoadDefaultShader(void); // Load default shader (just vertex static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting) static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) static void UnloadDefaultShader(void); // Unload default shader +static void UnloadStandardShader(void); // Unload standard shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data @@ -1018,6 +1020,7 @@ void rlglInit(void) // Init default Shader (customized for GL 3.3 and ES2) defaultShader = LoadDefaultShader(); + standardShader = LoadStandardShader(); currentShader = defaultShader; LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads) @@ -1046,6 +1049,7 @@ void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UnloadDefaultShader(); + UnloadStandardShader(); UnloadDefaultBuffers(); // Delete default white texture @@ -1757,19 +1761,30 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Send combined model-view-projection matrix to shader glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - - // Setup shader uniforms for material related data - // TODO: Check if using standard shader to get location points // Upload to shader material.colDiffuse float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 }; glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse); + + // Check if using standard shader to get location points + // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations) + if(material.shader.id == standardShader.id) + { + // Send model transformations matrix to shader + glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transform)); + + // Setup shader uniforms for lights + SetShaderLights(material.shader); + + // Upload to shader material.colAmbient + glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); + + // Upload to shader material.colSpecular + glUniform4f(glGetUniformLocation(material.shader.id, "colSpecular"), (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); - // TODO: Upload to shader material.colAmbient - // glUniform4f(???, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); - - // TODO: Upload to shader material.colSpecular - // glUniform4f(???, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); + // TODO: Upload to shader glossiness + //glUniform1f(???, material.glossiness); + } // Set shader textures (diffuse, normal, specular) glActiveTexture(GL_TEXTURE0); @@ -1791,13 +1806,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2 - - // TODO: Upload to shader glossiness - //glUniform1f(???, material.glossiness); } - - // Setup shader uniforms for lights - //SetShaderLights(material.shader); if (vaoSupported) { @@ -2148,6 +2157,17 @@ Shader GetDefaultShader(void) #endif } +// Get default shader +Shader GetStandardShader(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + return standardShader; +#else + Shader shader = { 0 }; + return shader; +#endif +} + // Get shader uniform location int GetShaderLocation(Shader shader, const char *uniformName) { @@ -2499,13 +2519,75 @@ static Shader LoadStandardShader(void) { Shader shader; - char *vShaderStr; - char *fShaderStr; - - // TODO: Implement standard uber-shader, supporting all features (GLSL 100 / GLSL 330) - - // NOTE: Shader could be quite extensive so it could be implemented in external files (standard.vs/standard.fs) - + // Vertex shader directly defined, no external file required +#if defined(GRAPHICS_API_OPENGL_33) + char vShaderStr[] = "#version 330 \n" + "in vec3 vertexPosition; \n" + "in vec3 vertexNormal; \n" + "in vec2 vertexTexCoord; \n" + "in vec4 vertexColor; \n" + "out vec2 fragTexCoord; \n" + "out vec4 fragColor; \n" + "out vec3 fragNormal; \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) + char vShaderStr[] = "#version 100 \n" + "attribute vec3 vertexPosition; \n" + "attribute vec3 vertexNormal; \n" + "attribute vec2 vertexTexCoord; \n" + "attribute vec4 vertexColor; \n" + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" + "varying vec3 fragNormal; \n" +#endif + "uniform mat4 mvpMatrix; \n" + "uniform mat4 modelMatrix; \n" + "void main() \n" + "{ \n" + " fragTexCoord = vertexTexCoord; \n" + " fragColor = vertexColor; \n" + " mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); \n" + " fragNormal = normalize(normalMatrix*vertexNormal); \n" + " gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" + "} \n"; + + // TODO: add specular calculation, multi-lights structs and light type calculations (directional, point, spot) + // Fragment shader directly defined, no external file required +#if defined(GRAPHICS_API_OPENGL_33) + char fShaderStr[] = "#version 330 \n" + "in vec2 fragTexCoord; \n" + "in vec4 fragColor; \n" + "in vec3 fragNormal; \n" + "out vec4 finalColor; \n" +#elif defined(GRAPHICS_API_OPENGL_ES2) + char fShaderStr[] = "#version 100 \n" + "precision mediump float; \n" // precision required for OpenGL ES2 (WebGL) + "varying vec2 fragTexCoord; \n" + "varying vec4 fragColor; \n" + "varying vec3 fragNormal; \n" +#endif + "uniform sampler2D texture0; \n" + "uniform vec4 fragTintColor; \n" + "uniform vec4 colAmbient; \n" + "uniform vec4 colSpecular; \n" + "uniform vec3 lightDir; \n" + "vec3 LambertLighting(in vec3 n, in vec3 l) \n" + "{ \n" + " return clamp(dot(n, l), 0, 1)*fragTintColor.rgb; \n" + "} \n" + + "void main() \n" + "{ \n" + " vec3 n = normalize(fragNormal); \n" + " vec3 l = normalize(lightDir); \n" +#if defined(GRAPHICS_API_OPENGL_33) + " vec4 texelColor = texture(texture0, fragTexCoord); \n" + " finalColor = vec4(texelColor.rgb*(colAmbient.rgb + LambertLighting(n, l)) - colSpecular.rgb + colSpecular.rgb, texelColor.a*fragTintColor.a); \n" // Stupid specular color operation to avoid shader location errors +#elif defined(GRAPHICS_API_OPENGL_ES2) + " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0 + " gl_FragColor = texelColor*fragTintColor*fragColor; \n" +#endif + "} \n"; + shader.id = LoadShaderProgram(vShaderStr, fShaderStr); if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id); @@ -2554,10 +2636,23 @@ static void UnloadDefaultShader(void) //glDetachShader(defaultShader, vertexShader); //glDetachShader(defaultShader, fragmentShader); //glDeleteShader(vertexShader); // Already deleted on shader compilation - //glDeleteShader(fragmentShader); // Already deleted on sahder compilation + //glDeleteShader(fragmentShader); // Already deleted on shader compilation glDeleteProgram(defaultShader.id); } +// Unload standard shader +static void UnloadStandardShader(void) +{ + glUseProgram(0); + + //glDetachShader(defaultShader, vertexShader); + //glDetachShader(defaultShader, fragmentShader); + //glDeleteShader(vertexShader); // Already deleted on shader compilation + //glDeleteShader(fragmentShader); // Already deleted on shader compilation + glDeleteProgram(standardShader.id); +} + + // Load default internal buffers (lines, triangles, quads) static void LoadDefaultBuffers(void) { @@ -3006,6 +3101,9 @@ static void UnloadDefaultBuffers(void) // TODO: Review memcpy() and parameters pass static void SetShaderLights(Shader shader) { + // Note: currently working with one light (index 0) + // TODO: add multi-lights feature (http://www.learnopengl.com/#!Lighting/Multiple-lights) + /* // NOTE: Standard Shader must include the following data: @@ -3023,7 +3121,7 @@ static void SetShaderLights(Shader shader) uniform Light lights[maxLights]; */ - int locPoint; + /*int locPoint; char locName[32] = "lights[x].position\0"; glUseProgram(shader.id); @@ -3052,9 +3150,10 @@ static void SetShaderLights(Shader shader) glUniform1f(locPoint, lights[i]->intensity); // TODO: Pass to the shader any other required data from LightData struct - } + }*/ - glUseProgram(0); + int locPoint = GetShaderLocation(shader, "lightDir"); + glUniform3f(locPoint, lights[0]->position.x, lights[0]->position.y, lights[0]->position.z); } // Read text data from file -- cgit v1.2.3 From 30941c0dd1f7904b5a0b50c05ec17265f8d69baa Mon Sep 17 00:00:00 2001 From: victorfisac Date: Sat, 21 May 2016 18:10:06 +0200 Subject: Add Draw3DLine function and fixed MLT glossiness import value In standard shader, material glossiness is a value from 0 to 1000 like in MLT files. So, it doesn't need to be normalized. --- src/models.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 2629dffd..aef79626 100644 --- a/src/models.c +++ b/src/models.c @@ -65,6 +65,16 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Module Functions Definition //---------------------------------------------------------------------------------- +// Draw a line in 3D world space +void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color) +{ + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + rlVertex3f(startPos.x, startPos.y, startPos.z); + rlVertex3f(endPos.x, endPos.y, endPos.z); + rlEnd(); +} + // Draw cube // NOTE: Cube position is the center position void DrawCube(Vector3 position, float width, float height, float length, Color color) @@ -2071,8 +2081,7 @@ static Material LoadMTL(const char *fileName) int shininess = 0; sscanf(buffer, "Ns %i", &shininess); - // Normalize shininess value to material glossiness attribute - material.glossiness = (float)shininess/1000; + material.glossiness = (float)shininess; } else if (buffer[1] == 'i') // Ni int Refraction index. { -- cgit v1.2.3 From dcd6942ed1ab703625f5c7072cbcfd823c681db7 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Sat, 21 May 2016 18:22:15 +0200 Subject: Fix small bug and spacing --- examples/resources/shaders/standard.fs | 14 +++++------ src/models.c | 46 +++++++++++++++++----------------- src/rlgl.c | 10 ++++---- 3 files changed, 35 insertions(+), 35 deletions(-) (limited to 'src/models.c') diff --git a/examples/resources/shaders/standard.fs b/examples/resources/shaders/standard.fs index 30c841d2..3c3bef4b 100644 --- a/examples/resources/shaders/standard.fs +++ b/examples/resources/shaders/standard.fs @@ -43,7 +43,7 @@ vec3 CalcPointLight(Light l, vec3 n, vec3 v) // Specular shading float spec = 0.0; - if(diff > 0.0) + if (diff > 0.0) { vec3 h = normalize(-l.direction + v); spec = pow(dot(n, h), 3 + glossiness); @@ -61,7 +61,7 @@ vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v) // Specular shading float spec = 0.0; - if(diff > 0.0) + if (diff > 0.0) { vec3 h = normalize(lightDir + v); spec = pow(dot(n, h), 3 + glossiness); @@ -84,7 +84,7 @@ vec3 CalcSpotLight(Light l, vec3 n, vec3 v) float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0); attenuation = dot(lightToSurface, -lightDir); float lightToSurfaceAngle = degrees(acos(attenuation)); - if(lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; + if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0; float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle; // Combine diffuse and attenuation @@ -92,7 +92,7 @@ vec3 CalcSpotLight(Light l, vec3 n, vec3 v) // Specular shading float spec = 0.0; - if(diffAttenuation > 0.0) + if (diffAttenuation > 0.0) { vec3 h = normalize(lightDir + v); spec = pow(dot(n, h), 3 + glossiness); @@ -115,13 +115,13 @@ void main() vec4 texelColor = texture(texture0, fragTexCoord); vec3 lighting = colAmbient.rgb; - for(int i = 0; i < lightsCount; i++) + for (int i = 0; i < lightsCount; i++) { // Check if light is enabled - if(lights[i].enabled == 1) + if (lights[i].enabled == 1) { // Calculate lighting based on light type - switch(lights[i].type) + switch (lights[i].type) { case 0: lighting += CalcPointLight(lights[i], n, v); break; case 1: lighting += CalcDirectionalLight(lights[i], n, v); break; diff --git a/src/models.c b/src/models.c index aef79626..07dee720 100644 --- a/src/models.c +++ b/src/models.c @@ -302,9 +302,9 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color rlBegin(RL_TRIANGLES); rlColor4ub(color.r, color.g, color.b, color.a); - for(int i = 0; i < (rings + 2); i++) + for (int i = 0; i < (rings + 2); i++) { - for(int j = 0; j < slices; j++) + for (int j = 0; j < slices; j++) { rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*i)), @@ -341,9 +341,9 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - for(int i = 0; i < (rings + 2); i++) + for (int i = 0; i < (rings + 2); i++) { - for(int j = 0; j < slices; j++) + for (int j = 0; j < slices; j++) { rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*i)), @@ -386,7 +386,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h if (radiusTop > 0) { // Draw Body ------------------------------------------------------------------------------------- - for(int i = 0; i < 360; i += 360/sides) + for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right @@ -398,7 +398,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h } // Draw Cap -------------------------------------------------------------------------------------- - for(int i = 0; i < 360; i += 360/sides) + for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, height, 0); rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); @@ -408,7 +408,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h else { // Draw Cone ------------------------------------------------------------------------------------- - for(int i = 0; i < 360; i += 360/sides) + for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, height, 0); rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); @@ -417,7 +417,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h } // Draw Base ----------------------------------------------------------------------------------------- - for(int i = 0; i < 360; i += 360/sides) + for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, 0, 0); rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); @@ -431,7 +431,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h // NOTE: It could be also used for pyramid and cone void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color) { - if(sides < 3) sides = 3; + if (sides < 3) sides = 3; rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); @@ -439,7 +439,7 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); - for(int i = 0; i < 360; i += 360/sides) + for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); @@ -500,7 +500,7 @@ void DrawGrid(int slices, float spacing) int halfSlices = slices / 2; rlBegin(RL_LINES); - for(int i = -halfSlices; i <= halfSlices; i++) + for (int i = -halfSlices; i <= halfSlices; i++) { if (i == 0) { @@ -798,9 +798,9 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ }; - for(int z = 0; z < mapZ-1; z++) + for (int z = 0; z < mapZ-1; z++) { - for(int x = 0; x < mapX-1; x++) + for (int x = 0; x < mapX-1; x++) { // Fill vertices array with data //---------------------------------------------------------- @@ -1417,7 +1417,7 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius float vector = VectorDotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); - if(d >= 0.0f) collision = true; + if (d >= 0.0f) collision = true; return collision; } @@ -1432,14 +1432,14 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi float vector = VectorDotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); - if(d >= 0.0f) collision = true; + if (d >= 0.0f) collision = true; // Calculate collision point Vector3 offset = ray.direction; float collisionDistance = 0; // Check if ray origin is inside the sphere to calculate the correct collision point - if(distance < sphereRadius) collisionDistance = vector + sqrt(d); + if (distance < sphereRadius) collisionDistance = vector + sqrt(d); else collisionDistance = vector - sqrt(d); VectorScale(&offset, collisionDistance); @@ -1777,11 +1777,11 @@ static Mesh LoadOBJ(const char *fileName) // 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 (3 vertex per face) - while(!feof(objFile)) + while (!feof(objFile)) { fscanf(objFile, "%c", &dataType); - switch(dataType) + switch (dataType) { case '#': // Comments case 'o': // Object name (One OBJ file can contain multible named meshes) @@ -1842,11 +1842,11 @@ static Mesh LoadOBJ(const char *fileName) // 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 different meshes can have different vertex data available (position, texcoords, normals) - while(!feof(objFile)) + while (!feof(objFile)) { fscanf(objFile, "%c", &dataType); - switch(dataType) + switch (dataType) { case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break; case 'v': @@ -1903,11 +1903,11 @@ static Mesh LoadOBJ(const char *fileName) 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)) + while (!feof(objFile)) { fscanf(objFile, "%c", &dataType); - switch(dataType) + switch (dataType) { case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break; case 'f': @@ -2023,7 +2023,7 @@ static Material LoadMTL(const char *fileName) return material; } - while(!feof(mtlFile)) + while (!feof(mtlFile)) { fgets(buffer, MAX_BUFFER_SIZE, mtlFile); diff --git a/src/rlgl.c b/src/rlgl.c index 55677f3e..85c0cae2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1397,7 +1397,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) { TraceLog(WARNING, "Framebuffer object could not be created..."); - switch(status) + switch (status) { case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break; @@ -1768,7 +1768,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Check if using standard shader to get location points // NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations) - if(material.shader.id == standardShader.id) + if (material.shader.id == standardShader.id) { // Send model transformations matrix to shader glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transform)); @@ -2285,7 +2285,7 @@ void DrawLights(void) Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } + } break; case LIGHT_SPOT: { Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); @@ -3081,7 +3081,7 @@ static void SetShaderLights(Shader shader) locPoint = glGetUniformLocation(shader.id, locName); glUniform1f(locPoint, lights[i]->intensity); - switch(lights[i]->type) + switch (lights[i]->type) { case LIGHT_POINT: { @@ -3295,7 +3295,7 @@ static void TraceLog(int msgType, const char *text, ...) va_list args; va_start(args, text); - switch(msgType) + switch (msgType) { case INFO: fprintf(stdout, "INFO: "); break; case ERROR: fprintf(stdout, "ERROR: "); break; -- cgit v1.2.3 From 2e26ce235d00fdc633559f9404ddd8ec70c96df7 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 30 May 2016 19:18:11 +0200 Subject: Add Draw3DCircle function and update raylib and rlgl header Draw3DCircle is useful to draw point lights radius. --- src/models.c | 19 +++++++++++++++++++ src/raylib.h | 3 ++- src/rlgl.h | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 07dee720..6ffb561e 100644 --- a/src/models.c +++ b/src/models.c @@ -75,6 +75,25 @@ void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color) rlEnd(); } +// Draw a circle in 3D world space +void Draw3DCircle(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color) +{ + rlPushMatrix(); + rlTranslatef(center.x, center.y, center.z); + rlRotatef(rotationAngle, rotation.x, rotation.y, rotation.z); + + rlBegin(RL_LINES); + for (int i = 0; i < 360; i += 10) + { + rlColor4ub(color.r, color.g, color.b, color.a); + + rlVertex3f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius, 0.0f); + rlVertex3f(sin(DEG2RAD*(i + 10)) * radius, cos(DEG2RAD*(i + 10)) * radius, 0.0f); + } + rlEnd(); + rlPopMatrix(); +} + // Draw cube // NOTE: Cube position is the center position void DrawCube(Vector3 position, float width, float height, float length, Color color) diff --git a/src/raylib.h b/src/raylib.h index d0231be2..0af7ef31 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -437,7 +437,7 @@ typedef struct LightData { Vector3 position; Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float attenuation; // Lost of light intensity with distance (world distance) + float radius; // Lost of light intensity with distance (world distance) Color diffuse; // Light color float intensity; // Light intensity level @@ -803,6 +803,7 @@ const char *SubText(const char *text, int position, int length); // Basic 3d Shapes Drawing Functions (Module: models) //------------------------------------------------------------------------------------ void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space +void Draw3DCircle(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color); // Draw a circle in 3D world space void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires diff --git a/src/rlgl.h b/src/rlgl.h index a3ba6cd5..d4a2dabe 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -218,7 +218,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; Vector3 position; Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float attenuation; // Lost of light intensity with distance (world distance) + float radius; // Lost of light intensity with distance (world distance) Color diffuse; // Use Vector3 diffuse float intensity; -- cgit v1.2.3 From f2d61d4043850e89b2d2cb7bacffe628aef0b981 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 30 May 2016 19:43:35 +0200 Subject: Remove normal depth Scaling normal depth (y axis) makes disappear the specular of fragments... So I think it can be removed, it is not a very useful/important attribute. --- src/models.c | 1 - src/raylib.h | 1 - src/rlgl.c | 5 +---- src/rlgl.h | 1 - 4 files changed, 1 insertion(+), 7 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 6ffb561e..90b752fd 100644 --- a/src/models.c +++ b/src/models.c @@ -756,7 +756,6 @@ Material LoadDefaultMaterial(void) material.colSpecular = WHITE; // Specular color material.glossiness = 100.0f; // Glossiness level - material.normalDepth = 1.0f; // Normal map depth return material; } diff --git a/src/raylib.h b/src/raylib.h index 0af7ef31..73a36a16 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -419,7 +419,6 @@ typedef struct Material { Color colSpecular; // Specular color float glossiness; // Glossiness level (Ranges from 0 to 1000) - float normalDepth; // Normal map depth } Material; // Model type diff --git a/src/rlgl.c b/src/rlgl.c index d781b755..b4569207 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1816,9 +1816,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, material.texNormal.id); glUniform1i(material.shader.mapTexture1Loc, 1); // Normal texture fits in active texture unit 1 - - // TODO: Upload to shader normalDepth - //glUniform1f(???, material.normalDepth); } if ((material.texSpecular.id != 0) && (material.shader.mapTexture2Loc != -1)) @@ -2565,7 +2562,7 @@ static Shader LoadDefaultShader(void) // Load standard shader // NOTE: This shader supports: // - Up to 3 different maps: diffuse, normal, specular -// - Material properties: colAmbient, colDiffuse, colSpecular, glossiness, normalDepth +// - Material properties: colAmbient, colDiffuse, colSpecular, glossiness // - Up to 8 lights: Point, Directional or Spot static Shader LoadStandardShader(void) { diff --git a/src/rlgl.h b/src/rlgl.h index d4a2dabe..dc16e807 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -207,7 +207,6 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; Color colSpecular; // Specular color float glossiness; // Glossiness level (Ranges from 0 to 1000) - float normalDepth; // Normal map depth } Material; // Light type -- cgit v1.2.3 From b0a0c5d4312d05d460cdd12f6af12321b0a55e66 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 30 May 2016 19:55:13 +0200 Subject: Added tint color attribute to material data type It tints all fragments, ignores lighting. Useful for some features like feedback (damage color, ...). --- src/models.c | 3 ++- src/raylib.h | 1 + src/rlgl.c | 3 +++ src/rlgl.h | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 90b752fd..092a43fc 100644 --- a/src/models.c +++ b/src/models.c @@ -751,6 +751,7 @@ Material LoadDefaultMaterial(void) //material.texNormal; // NOTE: By default, not set //material.texSpecular; // NOTE: By default, not set + material.colTint = WHITE; // Tint color material.colDiffuse = WHITE; // Diffuse color material.colAmbient = WHITE; // Ambient color material.colSpecular = WHITE; // Specular color @@ -1268,7 +1269,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - // model.material.colDiffuse = tint; + model.material.colTint = tint; rlglDrawMesh(model.mesh, model.material, model.transform); } diff --git a/src/raylib.h b/src/raylib.h index 73a36a16..dfec956d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -414,6 +414,7 @@ typedef struct Material { Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) + Color colTint; // Tint color Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color diff --git a/src/rlgl.c b/src/rlgl.c index b4569207..0f68953e 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1793,6 +1793,9 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Setup shader uniforms for lights SetShaderLights(material.shader); + // Upload to shader material.colSpecular + glUniform4f(glGetUniformLocation(material.shader.id, "colTint"), (float)material.colTint.r/255, (float)material.colTint.g/255, (float)material.colTint.b/255, (float)material.colTint.a/255); + // Upload to shader material.colAmbient glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); diff --git a/src/rlgl.h b/src/rlgl.h index dc16e807..23ad29fb 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -202,6 +202,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; Texture2D texNormal; // Normal texture Texture2D texSpecular; // Specular texture + Color colTint; // Tint color Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color -- cgit v1.2.3 From caa7bc366b949310fbb9c7eafbb9fa7050e1514a Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 31 May 2016 00:51:55 +0200 Subject: Reviewed DrawLight() function and some tweaks --- examples/shaders_standard_lighting.c | 12 ++++++------ src/models.c | 29 +++++++++++++++++++++++++++ src/raylib.h | 18 ++++++++--------- src/rlgl.c | 38 +++++++----------------------------- 4 files changed, 51 insertions(+), 46 deletions(-) (limited to 'src/models.c') diff --git a/examples/shaders_standard_lighting.c b/examples/shaders_standard_lighting.c index 6b5cd9f5..10416f7f 100644 --- a/examples/shaders_standard_lighting.c +++ b/examples/shaders_standard_lighting.c @@ -33,12 +33,12 @@ int main() Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position - Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model + Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Material material = LoadStandardMaterial(); - material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture - material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture + material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture + material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture material.colDiffuse = (Color){255, 255, 255, 255}; material.colAmbient = (Color){0, 0, 10, 255}; @@ -46,8 +46,6 @@ int main() material.glossiness = 50.0f; dwarf.material = material; // Apply material to model - - Model dwarf2 = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Light spotLight = CreateLight(LIGHT_SPOT, (Vector3){3.0f, 5.0f, 2.0f}, (Color){255, 255, 255, 255}); spotLight->target = (Vector3){0.0f, 0.0f, 0.0f}; @@ -91,7 +89,9 @@ int main() DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawLights(); // Draw all created lights in 3D world + DrawLight(spotLight); // Draw spot light + DrawLight(dirLight); // Draw directional light + DrawLight(pointLight); // Draw point light DrawGrid(10, 1.0f); // Draw a grid diff --git a/src/models.c b/src/models.c index 092a43fc..8c5ed914 100644 --- a/src/models.c +++ b/src/models.c @@ -569,6 +569,35 @@ void DrawGizmo(Vector3 position) rlPopMatrix(); } + +// Draw light in 3D world +void DrawLight(Light light) +{ + switch (light->type) + { + case LIGHT_POINT: + { + DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); + Draw3DCircle(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); + Draw3DCircle(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); + Draw3DCircle(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : BLACK)); + } break; + case LIGHT_DIRECTIONAL: + { + Draw3DLine(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); + DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); + } break; + case LIGHT_SPOT: + { + Draw3DLine(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); + DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : BLACK)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); + } break; + default: break; + } +} + // Load a 3d model (from file) Model LoadModel(const char *fileName) { diff --git a/src/raylib.h b/src/raylib.h index dfec956d..cba73e52 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -431,18 +431,18 @@ typedef struct Model { // Light type typedef struct LightData { - int id; - int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - bool enabled; + unsigned int id; // Light id + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; // Light enabled - Vector3 position; - Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Lost of light intensity with distance (world distance) + Vector3 position; // Light position + Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) - Color diffuse; // Light color + Color diffuse; // Light diffuse color float intensity; // Light intensity level - float coneAngle; // Spot light max angle + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; // Light types @@ -817,6 +817,7 @@ void DrawPlane(Vector3 centerPos, Vector2 size, Color color); void DrawRay(Ray ray, Color color); // Draw a ray line void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) void DrawGizmo(Vector3 position); // Draw simple gizmo +void DrawLight(Light light); // Draw light in 3D world //DrawTorus(), DrawTeapot() are useless... //------------------------------------------------------------------------------------ @@ -873,7 +874,6 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool -void DrawLights(void); // Draw all created lights in 3D world void DestroyLight(Light light); // Destroy a light and take it out of the list //---------------------------------------------------------------------------------- diff --git a/src/rlgl.c b/src/rlgl.c index 0f68953e..97a92a4d 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1069,6 +1069,13 @@ void rlglClose(void) // Delete default white texture glDeleteTextures(1, &whiteTexture); TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); + + // Unload lights + if (lightsCount > 0) + { + for (int i = 0; i < lightsCount; i++) free(lights[i]); + lightsCount = 0; + } free(draws); #endif @@ -2292,37 +2299,6 @@ Light CreateLight(int type, Vector3 position, Color diffuse) return light; } -// Draw all created lights in 3D world -void DrawLights(void) -{ - for (int i = 0; i < lightsCount; i++) - { - switch (lights[i]->type) - { - case LIGHT_POINT: - { - DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - Draw3DCircle(lights[i]->position, lights[i]->radius, 0.0f, (Vector3){ 0, 0, 0 }, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - Draw3DCircle(lights[i]->position, lights[i]->radius, 90.0f, (Vector3){ 1, 0, 0 }, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - Draw3DCircle(lights[i]->position, lights[i]->radius, 90.0f, (Vector3){ 0, 1, 0 }, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } break; - case LIGHT_DIRECTIONAL: - { - Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } break; - case LIGHT_SPOT: - { - Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawCylinderWires(lights[i]->position, 0.0f, 0.3f*lights[i]->coneAngle/50, 0.6f, 5, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); - } break; - default: break; - } - } -} - // Destroy a light and take it out of the list void DestroyLight(Light light) { -- cgit v1.2.3 From 302ec438dd8a5483e4fcf81d4bd80ac7d09e6a61 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 31 May 2016 18:15:53 +0200 Subject: Removed colTint, tint color is colDiffuse Tint color could be applied to colDiffuse... but what's the best way? Replace it? Multiply by? A point to think about... --- examples/resources/shaders/glsl330/grayscale.fs | 4 ++-- examples/resources/shaders/standard.fs | 7 +++---- examples/shaders_standard_lighting.c | 4 ++-- src/models.c | 5 ++--- src/raylib.h | 1 - src/rlgl.c | 3 --- src/rlgl.h | 21 ++++++++++----------- 7 files changed, 19 insertions(+), 26 deletions(-) (limited to 'src/models.c') diff --git a/examples/resources/shaders/glsl330/grayscale.fs b/examples/resources/shaders/glsl330/grayscale.fs index d4a8824f..5b3e11be 100644 --- a/examples/resources/shaders/glsl330/grayscale.fs +++ b/examples/resources/shaders/glsl330/grayscale.fs @@ -6,7 +6,7 @@ in vec4 fragColor; // Input uniform values uniform sampler2D texture0; -uniform vec4 fragTintColor; +uniform vec4 colDiffuse; // Output fragment color out vec4 finalColor; @@ -16,7 +16,7 @@ out vec4 finalColor; void main() { // Texel color fetching from texture sampler - vec4 texelColor = texture(texture0, fragTexCoord)*fragTintColor*fragColor; + vec4 texelColor = texture(texture0, fragTexCoord)*colDiffuse*fragColor; // Convert texel color to grayscale using NTSC conversion weights float gray = dot(texelColor.rgb, vec3(0.299, 0.587, 0.114)); diff --git a/examples/resources/shaders/standard.fs b/examples/resources/shaders/standard.fs index bb9e6865..e5916031 100644 --- a/examples/resources/shaders/standard.fs +++ b/examples/resources/shaders/standard.fs @@ -11,7 +11,6 @@ uniform sampler2D texture0; uniform sampler2D texture1; uniform sampler2D texture2; -uniform vec4 colTint; uniform vec4 colAmbient; uniform vec4 colDiffuse; uniform vec4 colSpecular; @@ -55,7 +54,7 @@ vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) spec = pow(dot(n, h), 3 + glossiness)*s; } - return (diff*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb); + return (diff*l.diffuse.rgb + spec*colSpecular.rgb); } vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s) @@ -74,7 +73,7 @@ vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s) } // Combine results - return (diff*l.intensity*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb); + return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb); } vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s) @@ -150,5 +149,5 @@ void main() } // Calculate final fragment color - finalColor = vec4(texelColor.rgb*lighting*colTint.rgb, texelColor.a*colTint.a); + finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); } diff --git a/examples/shaders_standard_lighting.c b/examples/shaders_standard_lighting.c index 10416f7f..ccbe74ca 100644 --- a/examples/shaders_standard_lighting.c +++ b/examples/shaders_standard_lighting.c @@ -40,9 +40,9 @@ int main() material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture - material.colDiffuse = (Color){255, 255, 255, 255}; + material.colDiffuse = WHITE; material.colAmbient = (Color){0, 0, 10, 255}; - material.colSpecular = (Color){255, 255, 255, 255}; + material.colSpecular = WHITE; material.glossiness = 50.0f; dwarf.material = material; // Apply material to model diff --git a/src/models.c b/src/models.c index 8c5ed914..962a6470 100644 --- a/src/models.c +++ b/src/models.c @@ -779,8 +779,7 @@ Material LoadDefaultMaterial(void) material.texDiffuse = GetDefaultTexture(); // White texture (1x1 pixel) //material.texNormal; // NOTE: By default, not set //material.texSpecular; // NOTE: By default, not set - - material.colTint = WHITE; // Tint color + material.colDiffuse = WHITE; // Diffuse color material.colAmbient = WHITE; // Ambient color material.colSpecular = WHITE; // Specular color @@ -1298,7 +1297,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); - model.material.colTint = tint; + model.material.colDiffuse = tint; // TODO: Multiply tint color by diffuse color? rlglDrawMesh(model.mesh, model.material, model.transform); } diff --git a/src/raylib.h b/src/raylib.h index 5bef3698..271c0e42 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -414,7 +414,6 @@ typedef struct Material { Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) - Color colTint; // Tint color Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color diff --git a/src/rlgl.c b/src/rlgl.c index 5c4c9c01..6a2adeb2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1800,9 +1800,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Setup shader uniforms for lights SetShaderLights(material.shader); - // Upload to shader material.colSpecular - glUniform4f(glGetUniformLocation(material.shader.id, "colTint"), (float)material.colTint.r/255, (float)material.colTint.g/255, (float)material.colTint.b/255, (float)material.colTint.a/255); - // Upload to shader material.colAmbient glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); diff --git a/src/rlgl.h b/src/rlgl.h index ccf2b36a..336f6019 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -201,8 +201,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; Texture2D texDiffuse; // Diffuse texture Texture2D texNormal; // Normal texture Texture2D texSpecular; // Specular texture - - Color colTint; // Tint color + Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color @@ -212,18 +211,18 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; // Light type typedef struct LightData { - int id; - int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - bool enabled; + unsigned int id; // Light id + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + bool enabled; // Light enabled - Vector3 position; - Vector3 target; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Lost of light intensity with distance (world distance) + Vector3 position; // Light position + Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) - Color diffuse; // Use Vector3 diffuse - float intensity; + Color diffuse; // Light diffuse color + float intensity; // Light intensity level - float coneAngle; // Spot light max angle + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; // Color blending modes (pre-defined) -- cgit v1.2.3 From 17878550b1e2dde44fcd1e668c92ca2d96680a28 Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 2 Jun 2016 01:26:44 +0200 Subject: Review heades usage This is a first step toward a bigger project. Some modules could be ported to header-only to be used as standalone. --- src/audio.c | 16 ++++++++-------- src/models.c | 18 +++++++++--------- src/rlgl.c | 30 +++++++++++++++--------------- src/rlgl.h | 6 +++--- src/text.c | 12 ++++++------ src/textures.c | 10 ++++++---- src/utils.c | 10 +++++----- src/utils.h | 4 ++-- 8 files changed, 54 insertions(+), 52 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 0c61c0fa..a884303c 100644 --- a/src/audio.c +++ b/src/audio.c @@ -37,24 +37,24 @@ #include "AL/al.h" // OpenAL basic header #include "AL/alc.h" // OpenAL context header (like OpenGL, OpenAL requires a context to work) -#include "AL/alext.h" // extensions for other format types +#include "AL/alext.h" // OpenAL extensions for other format types -#include // Declares malloc() and free() for memory management -#include // Required for strcmp() -#include // Used for .WAV loading +#include // Required for: malloc(), free() +#include // Required for: strcmp(), strncmp() +#include // Required for: FILE, fopen(), fclose(), fread() #if defined(AUDIO_STANDALONE) - #include // Used for functions with variable number of parameters (TraceLog()) + #include // Required for: va_list, va_start(), vfprintf(), va_end() #else - #include "utils.h" // rRES data decompression utility function - // NOTE: Includes Android fopen function map + #include "utils.h" // Required for: DecompressData() + // NOTE: Includes Android fopen() function map #endif //#define STB_VORBIS_HEADER_ONLY #include "stb_vorbis.h" // OGG loading functions #define JAR_XM_IMPLEMENTATION -#include "jar_xm.h" // For playing .xm files +#include "jar_xm.h" // XM loading functions //---------------------------------------------------------------------------------- // Defines and Macros diff --git a/src/models.c b/src/models.c index 962a6470..15565c98 100644 --- a/src/models.c +++ b/src/models.c @@ -26,16 +26,16 @@ #include "raylib.h" #if defined(PLATFORM_ANDROID) - #include "utils.h" // Android fopen function map + #include "utils.h" // Android fopen function map #endif -#include // Standard input/output functions, used to read model files data -#include // Declares malloc() and free() for memory management -#include // Required for strcmp() -#include // Used for sin, cos, tan +#include // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets() +#include // Required for: malloc(), free() +#include // Required for: strcmp() +#include // Required for: sin(), cos() -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 -#include "raymath.h" // Required for data type Matrix and Matrix functions +#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 +#include "raymath.h" // Matrix data type and Matrix functions //---------------------------------------------------------------------------------- // Defines and Macros @@ -605,7 +605,7 @@ Model LoadModel(const char *fileName) // TODO: Initialize default data for model in case loading fails, maybe a cube? - if (strcmp(GetExtension(fileName),"obj") == 0) model.mesh = LoadOBJ(fileName); + if (strcmp(GetExtension(fileName), "obj") == 0) model.mesh = LoadOBJ(fileName); else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName); if (model.mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); @@ -764,7 +764,7 @@ Material LoadMaterial(const char *fileName) { Material material = { 0 }; - if (strcmp(GetExtension(fileName),"mtl") == 0) material = LoadMTL(fileName); + if (strcmp(GetExtension(fileName), "mtl") == 0) material = LoadMTL(fileName); else TraceLog(WARNING, "[%s] Material extension not recognized, it can't be loaded", fileName); return material; diff --git a/src/rlgl.c b/src/rlgl.c index aa536e2a..cca48ba2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -28,41 +28,41 @@ #include "rlgl.h" -#include // Standard input / output lib -#include // Declares malloc() and free() for memory management, rand() -#include // Declares strcmp(), strlen(), strtok() +#include // Standard input / output lib +#include // Required for: malloc(), free(), rand() +#include // Required for: strcmp(), strlen(), strtok() #ifndef RLGL_STANDALONE - #include "raymath.h" // Required for Vector3 and Matrix functions + #include "raymath.h" // Required for Vector3 and Matrix functions #endif #if defined(GRAPHICS_API_OPENGL_11) - #ifdef __APPLE__ // OpenGL include for OSX - #include + #ifdef __APPLE__ + #include // OpenGL 1.1 library for OSX #else - #include // Basic OpenGL include + #include // OpenGL 1.1 library #endif #endif #if defined(GRAPHICS_API_OPENGL_33) - #ifdef __APPLE__ // OpenGL include for OSX - #include + #ifdef __APPLE__ + #include // OpenGL 3 library for OSX #else //#define GLEW_STATIC //#include // GLEW header, includes OpenGL headers - #include "glad.h" // glad header, includes OpenGL headers + #include "glad.h" // GLAD library, includes OpenGL headers #endif #endif #if defined(GRAPHICS_API_OPENGL_ES2) - #include - #include - #include + #include // EGL library + #include // OpenGL ES 2.0 library + #include // OpenGL ES 2.0 extensions library #endif #if defined(RLGL_STANDALONE) - #include // Used for functions with variable number of parameters (TraceLog()) -#endif + #include // Required for: va_list, va_start(), vfprintf(), va_end() +#endif // NOTE: Used on TraceLog() //---------------------------------------------------------------------------------- // Defines and Macros diff --git a/src/rlgl.h b/src/rlgl.h index e8e754b4..00482d2e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -32,15 +32,15 @@ //#define RLGL_STANDALONE // NOTE: To use rlgl as standalone lib, just uncomment this line #ifndef RLGL_STANDALONE - #include "raylib.h" // Required for typedef(s): Model, Shader, Texture2D - #include "utils.h" // Required for function TraceLog() + #include "raylib.h" // Required for: Model, Shader, Texture2D + #include "utils.h" // Required for: TraceLog() #endif #ifdef RLGL_STANDALONE #define RAYMATH_STANDALONE #endif -#include "raymath.h" // Required for types: Vector3, Matrix +#include "raymath.h" // Required for: Vector3, Matrix // Select desired OpenGL version // NOTE: Those preprocessor defines are only used on rlgl module, diff --git a/src/text.c b/src/text.c index 7bb06f44..cef0ebcb 100644 --- a/src/text.c +++ b/src/text.c @@ -25,16 +25,16 @@ #include "raylib.h" -#include // Declares malloc() and free() for memory management -#include // String management functions (just strlen() is used) -#include // Used for functions with variable number of parameters (FormatText()) -#include // Standard input / output lib +#include // Required for: malloc(), free() +#include // Required for: strlen() +#include // Required for: va_list, va_start(), vfprintf(), va_end() +#include // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets() -#include "utils.h" // Required for function GetExtension() +#include "utils.h" // Required for: GetExtension() // Following libs are used on LoadTTF() #define STB_TRUETYPE_IMPLEMENTATION -#include "stb_truetype.h" +#include "stb_truetype.h" // Required for: stbtt_BakeFontBitmap() // Rectangle packing functions (not used at the moment) //#define STB_RECT_PACK_IMPLEMENTATION diff --git a/src/textures.c b/src/textures.c index 8c59f3f2..432d3426 100644 --- a/src/textures.c +++ b/src/textures.c @@ -29,8 +29,8 @@ #include "raylib.h" -#include // Declares malloc() and free() for memory management -#include // Required for strcmp(), strrchr(), strncmp() +#include // Required for: malloc(), free() +#include // Required for: strcmp(), strrchr(), strncmp() #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 // Required: rlglLoadTexture() rlDeleteTextures(), @@ -40,10 +40,12 @@ // NOTE: Includes Android fopen function map #define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" // Used to read image data (multiple formats support) +#include "stb_image.h" // Required for: stbi_load() + // NOTE: Used to read image data (multiple formats support) #define STB_IMAGE_RESIZE_IMPLEMENTATION -#include "stb_image_resize.h" // Used on image scaling function: ImageResize() +#include "stb_image_resize.h" // Required for: stbir_resize_uint8() + // NOTE: Used for image scaling on ImageResize() //---------------------------------------------------------------------------------- // Defines and Macros diff --git a/src/utils.c b/src/utils.c index f0ccf3e2..97561ee6 100644 --- a/src/utils.c +++ b/src/utils.c @@ -35,14 +35,14 @@ #include #endif -#include // malloc(), free() -#include // printf(), fprintf() -#include // Used for functions with variable number of parameters (TraceLog()) -//#include // String management functions: strlen(), strrchr(), strcmp() +#include // Required for: malloc(), free() +#include // Required for: fopen(), fclose(), fputc(), fwrite(), printf(), fprintf(), funopen() +#include // Required for: va_list, va_start(), vfprintf(), va_end() +//#include // Required for: strlen(), strrchr(), strcmp() #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) #define STB_IMAGE_WRITE_IMPLEMENTATION - #include "stb_image_write.h" // Create PNG file + #include "stb_image_write.h" // Required for: stbi_write_png() #endif #include "tinfl.c" diff --git a/src/utils.h b/src/utils.h index 77909ba6..899cf583 100644 --- a/src/utils.h +++ b/src/utils.h @@ -27,8 +27,8 @@ #define UTILS_H #if defined(PLATFORM_ANDROID) - #include // Defines FILE struct - #include // defines AAssetManager struct + #include // Required for: FILE + #include // Required for: AAssetManager #endif //---------------------------------------------------------------------------------- -- cgit v1.2.3 From 3e8427799c27b1e0bca22759ae434e23b06547ae Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 11 Jun 2016 10:56:20 +0200 Subject: Corrected bug on cubemap generation --- src/models.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 15565c98..8d9219e3 100644 --- a/src/models.c +++ b/src/models.c @@ -739,7 +739,7 @@ Model LoadCubicmap(Image cubicmap) { Model model = { 0 }; - model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0, 1.0, 1.5f }); + model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0f, 1.5f, 1.0f }); rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) -- cgit v1.2.3 From 68a02e567d5fea42d1593e7932a0e052cf244d52 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 11 Jun 2016 12:41:03 +0200 Subject: Avoid external variable whiteTexture To get it, use GetDefaultTexture() --- src/models.c | 4 ++-- src/rlgl.c | 3 +-- src/shapes.c | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 8d9219e3..8deabcb0 100644 --- a/src/models.c +++ b/src/models.c @@ -50,7 +50,7 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -extern unsigned int whiteTexture; +// ... //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -811,7 +811,7 @@ void UnloadMaterial(Material material) // Link a texture to a model void SetModelTexture(Model *model, Texture2D texture) { - if (texture.id <= 0) model->material.texDiffuse.id = whiteTexture; // Use default white texture + if (texture.id <= 0) model->material.texDiffuse = GetDefaultTexture(); // Use default white texture else model->material.texDiffuse = texture; } diff --git a/src/rlgl.c b/src/rlgl.c index 9a88a818..d4502595 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -228,8 +228,7 @@ static PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArrays; static int blendMode = 0; // White texture useful for plain color polys (required by shader) -// NOTE: It's required in shapes and models modules! -unsigned int whiteTexture; +static unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration diff --git a/src/shapes.c b/src/shapes.c index 7129ac17..3ccfd660 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -44,7 +44,7 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -extern unsigned int whiteTexture; +// ... //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -137,7 +137,7 @@ void DrawCircleV(Vector2 center, float radius, Color color) } else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(whiteTexture); // Default white texture + rlEnableTexture(GetDefaultTexture().id); // Default white texture rlBegin(RL_QUADS); for (int i = 0; i < 360; i += 20) @@ -220,7 +220,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color) } else if ((rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(whiteTexture); // Default white texture + rlEnableTexture(GetDefaultTexture().id); // Default white texture rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); -- cgit v1.2.3 From 5f7ac64c44543383b10ec6a56e5ec1db5706276e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 24 Jun 2016 19:49:36 +0200 Subject: Removed function SetModelTexture() It's more educational to go through new material system, so, I decide to remove this function to avoid students confusion... --- CHANGELOG | 7 ++++--- examples/models_cubicmap.c | 2 +- examples/models_heightmap.c | 2 +- examples/models_obj_loading.c | 2 +- examples/shaders_custom_uniform.c | 2 +- examples/shaders_postprocessing.c | 2 +- games/raylib_demo/raylib_demo.c | 4 ++-- src/models.c | 7 ------- src/raylib.h | 1 - 9 files changed, 11 insertions(+), 18 deletions(-) (limited to 'src/models.c') diff --git a/CHANGELOG b/CHANGELOG index 5024dc6e..300c9089 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,20 +1,20 @@ changelog --------- -Current Release: raylib 1.5.0 (23 June 2016) +Current Release: raylib 1.5.0 (xx June 2016) NOTE: Only versions marked as 'Release' are available in installer, updates are only available as source. NOTE: Current Release includes all previous updates. ----------------------------------------------- -Release: raylib 1.5.0 (23 June 2016) +Release: raylib 1.5.0 (xx June 2016) ----------------------------------------------- NOTE: Probably this new version is the biggest boost of the library ever, lots of parts of the library have been redesigned, lots of bugs have been solved and some **AMAZING** new features have been added. HUGE changes: -[core] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering. +[rlgl] OCULUS RIFT CV1: Added support for VR witha bunch of Oculus-specific functions to init/close device and Oculus rendering. [rlgl] MATERIALS SYSTEM: Added support for Materials (.mtl) and multiple material properties: diffuse, specular, normal. [rlgl] LIGHTING SYSTEM: Added support for up to 8 lights of 3 different types: Omni, Directional and Spot [physac] REDESIGNED: Improved performance and simplified usage, physic objects are managed internally @@ -65,6 +65,7 @@ other changes: [models] Updated BoundingBox collision detections [models] Added color parameter to DrawBoundigBox() [models] Removed function: DrawQuad() +[models] Removed function: SetModelTexture() [models] Redesigned DrawPlane() to use RL_TRIANGLES [models] Redesigned DrawRectangleV() to use RL_TRIANGLES [models] Redesign to accomodate new materials system: LoadMaterial() diff --git a/examples/models_cubicmap.c b/examples/models_cubicmap.c index 1ca27dfd..89bc75cf 100644 --- a/examples/models_cubicmap.c +++ b/examples/models_cubicmap.c @@ -29,7 +29,7 @@ int main() // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - SetModelTexture(&map, texture); // Bind texture to map model + map.material.texDiffuse = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c index c8e5ff35..90e5f5bb 100644 --- a/examples/models_heightmap.c +++ b/examples/models_heightmap.c @@ -26,7 +26,7 @@ int main() Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) Model map = LoadHeightmap(image, (Vector3){ 16, 8, 16 }); // Load heightmap model with defined size - SetModelTexture(&map, texture); // Bind texture to model + map.material.texDiffuse = texture; // Set map diffuse texture Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!) UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM diff --git a/examples/models_obj_loading.c b/examples/models_obj_loading.c index e8dd0adc..a6969f70 100644 --- a/examples/models_obj_loading.c +++ b/examples/models_obj_loading.c @@ -25,7 +25,7 @@ int main() Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture - SetModelTexture(&dwarf, texture); // Bind texture to model + dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position SetTargetFPS(60); // Set our game to run at 60 frames-per-second diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c index 516d5087..c4f87259 100644 --- a/examples/shaders_custom_uniform.c +++ b/examples/shaders_custom_uniform.c @@ -34,7 +34,7 @@ int main() Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map) - SetModelTexture(&dwarf, texture); // Bind texture to model + dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index 5e8b5a80..43d21e08 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -34,7 +34,7 @@ int main() Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture (diffuse map) - SetModelTexture(&dwarf, texture); // Bind texture to model + dwarf.material.texDiffuse = texture; // Set dwarf model diffuse texture Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position diff --git a/games/raylib_demo/raylib_demo.c b/games/raylib_demo/raylib_demo.c index 7f6f291a..22213b46 100644 --- a/games/raylib_demo/raylib_demo.c +++ b/games/raylib_demo/raylib_demo.c @@ -202,8 +202,8 @@ int main() camera = (Camera){{ 0.0, 12.0, 15.0 }, { 0.0, 3.0, 0.0 }, { 0.0, 1.0, 0.0 }}; catTexture = LoadTexture("resources/catsham.png"); // Load model texture - cat = LoadModel("resources/cat.obj"); // Load OBJ model - SetModelTexture(&cat, catTexture); + cat = LoadModel("resources/cat.obj"); // Load OBJ model + cat.material.texDiffuse = texture; // Set cat model diffuse texture fxWav = LoadSound("resources/audio/weird.wav"); // Load WAV audio file fxOgg = LoadSound("resources/audio/tanatana.ogg"); // Load OGG audio file diff --git a/src/models.c b/src/models.c index 8deabcb0..a4bcde8f 100644 --- a/src/models.c +++ b/src/models.c @@ -808,13 +808,6 @@ void UnloadMaterial(Material material) rlDeleteTextures(material.texSpecular.id); } -// Link a texture to a model -void SetModelTexture(Model *model, Texture2D texture) -{ - if (texture.id <= 0) model->material.texDiffuse = GetDefaultTexture(); // Use default white texture - else model->material.texDiffuse = texture; -} - // Generate a mesh from heightmap static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { diff --git a/src/raylib.h b/src/raylib.h index ed787892..641f4c09 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -795,7 +795,6 @@ Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d mod Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // 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 Material LoadMaterial(const char *fileName); // Load material data (from file) Material LoadDefaultMaterial(void); // Load default material (uses default models shader) -- cgit v1.2.3 From 2f9abe6e1388a84d662eb12e62bbcccc7eccd9d0 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 4 Jul 2016 01:30:07 +0200 Subject: Review ResolveCollisionCubicmap() This function needs to be redesigned or removed... --- src/models.c | 71 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index a4bcde8f..b194a0db 100644 --- a/src/models.c +++ b/src/models.c @@ -40,7 +40,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define CUBIC_MAP_HALF_BLOCK_SIZE 0.5 +// ... //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -1542,8 +1542,11 @@ BoundingBox CalculateBoundingBox(Mesh mesh) // Detect and resolve cubicmap collisions // NOTE: player position (or camera) is modified inside this function +// TODO: This functions needs to be completely reviewed! Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius) { + #define CUBIC_MAP_HALF_BLOCK_SIZE 0.5 + Color *cubicmapPixels = GetImageData(cubicmap); // Detect the cell where the player is located @@ -1555,15 +1558,15 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p locationCellX = floor(playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE); locationCellY = floor(playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE); - if (locationCellX >= 0 && locationCellY >= 0 && locationCellX < cubicmap.width && locationCellY < cubicmap.height) + if ((locationCellX >= 0) && (locationCellY >= 0) && (locationCellX < cubicmap.width) && (locationCellY < cubicmap.height)) { // Multiple Axis -------------------------------------------------------------------------------------------- // Axis x-, y- - if (locationCellX > 0 && locationCellY > 0) + if ((locationCellX > 0) && (locationCellY > 0)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) && - (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) && + (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) @@ -1576,10 +1579,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p } // Axis x-, y+ - if (locationCellX > 0 && locationCellY < cubicmap.height - 1) + if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) && - (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) && + (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) @@ -1592,10 +1595,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p } // Axis x+, y- - if (locationCellX < cubicmap.width - 1 && locationCellY > 0) + if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) && - (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) && + (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) @@ -1608,10 +1611,10 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p } // Axis x+, y+ - if (locationCellX < cubicmap.width - 1 && locationCellY < cubicmap.height - 1) + if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) && - (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) && + (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) @@ -1628,7 +1631,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Axis x- if (locationCellX > 0) { - if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r != 0) + if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) { if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) { @@ -1640,7 +1643,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Axis x+ if (locationCellX < cubicmap.width - 1) { - if (cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r != 0) + if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) { if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) { @@ -1652,7 +1655,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Axis y- if (locationCellY > 0) { - if (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r != 0) + if (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0) { if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius) { @@ -1664,7 +1667,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Axis y+ if (locationCellY < cubicmap.height - 1) { - if (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r != 0) + if (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0) { if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius) { @@ -1677,11 +1680,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Diagonals ------------------------------------------------------------------------------------------------------- // Axis x-, y- - if (locationCellX > 0 && locationCellY > 0) + if ((locationCellX > 0) && (locationCellY > 0)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) && - (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX - 1)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) && + (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) && + (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX - 1)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) @@ -1700,11 +1703,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p } // Axis x-, y+ - if (locationCellX > 0 && locationCellY < cubicmap.height - 1) + if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX - 1)].r == 0) && - (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX - 1)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) && + (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) && + (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX - 1)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) @@ -1723,11 +1726,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p } // Axis x+, y- - if (locationCellX < cubicmap.width - 1 && locationCellY > 0) + if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) && - (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY - 1) * cubicmap.width + (locationCellX + 1)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) && + (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) && + (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX + 1)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) @@ -1746,11 +1749,11 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p } // Axis x+, y+ - if (locationCellX < cubicmap.width - 1 && locationCellY < cubicmap.height - 1) + if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1)) { - if ((cubicmapPixels[locationCellY * cubicmap.width + (locationCellX + 1)].r == 0) && - (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY + 1) * cubicmap.width + (locationCellX + 1)].r != 0)) + if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) && + (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) && + (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX + 1)].r != 0)) { if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) -- cgit v1.2.3 From eb9072a2f133cdad9fb4fed4c8b80aca04770d55 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 10 Aug 2016 12:20:46 +0200 Subject: Renamed functions for consistency --- src/models.c | 14 +++++++------- src/raylib.h | 4 ++-- src/rlua.h | 56 ++++++++++++++++++++++++++++++-------------------------- 3 files changed, 39 insertions(+), 35 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index b194a0db..7f248aa2 100644 --- a/src/models.c +++ b/src/models.c @@ -66,7 +66,7 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); //---------------------------------------------------------------------------------- // Draw a line in 3D world space -void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color) +void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color) { rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); @@ -76,7 +76,7 @@ void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color) } // Draw a circle in 3D world space -void Draw3DCircle(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color) +void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color) { rlPushMatrix(); rlTranslatef(center.x, center.y, center.z); @@ -578,19 +578,19 @@ void DrawLight(Light light) case LIGHT_POINT: { DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); - Draw3DCircle(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); - Draw3DCircle(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); - Draw3DCircle(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : BLACK)); + DrawCircle3D(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); + DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); + DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : BLACK)); } break; case LIGHT_DIRECTIONAL: { - Draw3DLine(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); } break; case LIGHT_SPOT: { - Draw3DLine(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : BLACK)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); } break; diff --git a/src/raylib.h b/src/raylib.h index 41c32476..1673578d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -800,6 +800,8 @@ const char *SubText(const char *text, int position, int length); //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) //------------------------------------------------------------------------------------ +void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space +void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color); // Draw a circle in 3D world space void DrawCube(Vector3 position, float width, float height, float lenght, Color color); // Draw cube void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color); // Draw cube wires @@ -814,8 +816,6 @@ void DrawRay(Ray ray, Color color); void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) void DrawGizmo(Vector3 position); // Draw simple gizmo void DrawLight(Light light); // Draw light in 3D world -void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space -void Draw3DCircle(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color); // Draw a circle in 3D world space //DrawTorus(), DrawTeapot() are useless... //------------------------------------------------------------------------------------ diff --git a/src/rlua.h b/src/rlua.h index 849c1c64..b100b06d 100644 --- a/src/rlua.h +++ b/src/rlua.h @@ -2239,6 +2239,29 @@ int lua_DrawFPS(lua_State* L) // NOTE: FormatText() can be replaced by Lua function: string.format() // NOTE: SubText() can be replaced by Lua function: string.sub() +//------------------------------------------------------------------------------------ +// raylib [models] module functions - Basic 3d Shapes Drawing Functions +//------------------------------------------------------------------------------------ +int lua_DrawLine3D(lua_State* L) +{ + Vector3 arg1 = LuaGetArgument_Vector3(L, 1); + Vector3 arg2 = LuaGetArgument_Vector3(L, 2); + Color arg3 = LuaGetArgument_Color(L, 3); + DrawLine3D(arg1, arg2, arg3); + return 0; +} + +int lua_DrawCircle3D(lua_State* L) +{ + Vector3 arg1 = LuaGetArgument_Vector3(L, 1); + float arg2 = LuaGetArgument_float(L, 2); + float arg3 = LuaGetArgument_float(L, 3); + Vector3 arg4 = LuaGetArgument_Vector3(L, 4); + Color arg5 = LuaGetArgument_Color(L, 5); + DrawCircle3D(arg1, arg2, arg3, arg4, arg5); + return 0; +} + int lua_DrawCube(lua_State* L) { Vector3 arg1 = LuaGetArgument_Vector3(L, 1); @@ -2376,26 +2399,6 @@ int lua_DrawLight(lua_State* L) return 0; } -int lua_Draw3DLine(lua_State* L) -{ - Vector3 arg1 = LuaGetArgument_Vector3(L, 1); - Vector3 arg2 = LuaGetArgument_Vector3(L, 2); - Color arg3 = LuaGetArgument_Color(L, 3); - Draw3DLine(arg1, arg2, arg3); - return 0; -} - -int lua_Draw3DCircle(lua_State* L) -{ - Vector3 arg1 = LuaGetArgument_Vector3(L, 1); - float arg2 = LuaGetArgument_float(L, 2); - float arg3 = LuaGetArgument_float(L, 3); - Vector3 arg4 = LuaGetArgument_Vector3(L, 4); - Color arg5 = LuaGetArgument_Color(L, 5); - Draw3DCircle(arg1, arg2, arg3, arg4, arg5); - return 0; -} - //------------------------------------------------------------------------------------ // raylib [models] module functions //------------------------------------------------------------------------------------ @@ -3725,6 +3728,8 @@ static luaL_Reg raylib_functions[] = { REG(MeasureTextEx) REG(DrawFPS) + REG(DrawLine3D) + REG(DrawCircle3D) REG(DrawCube) REG(DrawCubeV) REG(DrawCubeWires) @@ -3738,8 +3743,7 @@ static luaL_Reg raylib_functions[] = { REG(DrawRay) REG(DrawGrid) REG(DrawGizmo) - - REG(DrawLight) + REG(DrawLight) REG(LoadModel) REG(LoadModelEx) @@ -3747,10 +3751,10 @@ static luaL_Reg raylib_functions[] = { REG(LoadHeightmap) REG(LoadCubicmap) REG(UnloadModel) - REG(LoadMaterial) - REG(LoadDefaultMaterial) - REG(LoadStandardMaterial) - REG(UnloadMaterial) + REG(LoadMaterial) + REG(LoadDefaultMaterial) + REG(LoadStandardMaterial) + REG(UnloadMaterial) //REG(GenMesh*) // Not ready yet... REG(DrawModel) -- cgit v1.2.3 From 6e20037f7d72931f52a0bd03abbb45e2e7abf2e8 Mon Sep 17 00:00:00 2001 From: Teodor Stoenescu Date: Fri, 12 Aug 2016 21:42:17 +0300 Subject: Small fix for GenMeshCubicmap() This fix allows GenMeshCubicmap() to create cubic maps having cells of arbitrary sizes. --- src/models.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 7f248aa2..42798483 100644 --- a/src/models.c +++ b/src/models.c @@ -920,8 +920,8 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) Color *cubicmapPixels = GetImageData(cubicmap); - int mapWidth = cubicmap.width*(int)cubeSize.x; - int mapHeight = cubicmap.height*(int)cubeSize.z; + int mapWidth = cubicmap.width; + int mapHeight = cubicmap.height; // NOTE: Max possible number of triangles numCubes * (12 triangles by cube) int maxTriangles = cubicmap.width*cubicmap.height*12; @@ -961,19 +961,19 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f }; RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f }; - for (int z = 0; z < mapHeight; z += cubeSize.z) + for (int z = 0; z < mapHeight; ++z) { - for (int x = 0; x < mapWidth; x += cubeSize.x) + for (int x = 0; x < mapWidth; ++x) { // 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 }; + Vector3 v1 = { w * (x - .5f), h2, h * (z - .5f) }; + Vector3 v2 = { w * (x - .5f), h2, h * (z + .5f) }; + Vector3 v3 = { w * (x + .5f), h2, h * (z + .5f) }; + Vector3 v4 = { w * (x + .5f), h2, h * (z - .5f) }; + Vector3 v5 = { w * (x + .5f), 0, h * (z - .5f) }; + Vector3 v6 = { w * (x - .5f), 0, h * (z - .5f) }; + Vector3 v7 = { w * (x - .5f), 0, h * (z + .5f) }; + Vector3 v8 = { w * (x + .5f), 0, h * (z + .5f) }; // We check pixel color to be WHITE, we will full cubes if ((cubicmapPixels[z*cubicmap.width + x].r == 255) && -- cgit v1.2.3 From 852813bdf19445a80fa8de9daef052f9f1b72c74 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 15 Aug 2016 16:34:21 +0200 Subject: Reviewed formatting --- src/models.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 42798483..24238ed2 100644 --- a/src/models.c +++ b/src/models.c @@ -966,14 +966,14 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) for (int x = 0; x < mapWidth; ++x) { // Define the 8 vertex of the cube, we will combine them accordingly later... - Vector3 v1 = { w * (x - .5f), h2, h * (z - .5f) }; - Vector3 v2 = { w * (x - .5f), h2, h * (z + .5f) }; - Vector3 v3 = { w * (x + .5f), h2, h * (z + .5f) }; - Vector3 v4 = { w * (x + .5f), h2, h * (z - .5f) }; - Vector3 v5 = { w * (x + .5f), 0, h * (z - .5f) }; - Vector3 v6 = { w * (x - .5f), 0, h * (z - .5f) }; - Vector3 v7 = { w * (x - .5f), 0, h * (z + .5f) }; - Vector3 v8 = { w * (x + .5f), 0, h * (z + .5f) }; + Vector3 v1 = { w*(x - 0.5f), h2, h*(z - 0.5f) }; + Vector3 v2 = { w*(x - 0.5f), h2, h*(z + 0.5f) }; + Vector3 v3 = { w*(x + 0.5f), h2, h*(z + 0.5f) }; + Vector3 v4 = { w*(x + 0.5f), h2, h*(z - 0.5f) }; + Vector3 v5 = { w*(x + 0.5f), 0, h*(z - 0.5f) }; + Vector3 v6 = { w*(x - 0.5f), 0, h*(z - 0.5f) }; + Vector3 v7 = { w*(x - 0.5f), 0, h*(z + 0.5f) }; + Vector3 v8 = { w*(x + 0.5f), 0, h*(z + 0.5f) }; // We check pixel color to be WHITE, we will full cubes if ((cubicmapPixels[z*cubicmap.width + x].r == 255) && -- cgit v1.2.3 From 959a228815edcecdde692fcd47a7b540844c5712 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 16 Aug 2016 11:09:55 +0200 Subject: Removed useless spacing --- src/audio.c | 74 +++++------ src/core.c | 342 ++++++++++++++++++++++++------------------------- src/models.c | 134 +++++++++---------- src/raylib.h | 4 +- src/rlgl.h | 26 ++-- src/rlua.h | 72 +++++------ src/text.c | 146 ++++++++++----------- src/textures.c | 398 ++++++++++++++++++++++++++++----------------------------- 8 files changed, 598 insertions(+), 598 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 683ee66b..1772196f 100644 --- a/src/audio.c +++ b/src/audio.c @@ -183,7 +183,7 @@ void CloseAudioDevice(void) alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); - + TraceLog(INFO, "Audio device closed successfully"); } @@ -217,7 +217,7 @@ Sound LoadSound(char *fileName) else TraceLog(WARNING, "[%s] Sound extension not recognized, it can't be loaded", fileName); Sound sound = LoadSoundFromWave(wave); - + // Sound is loaded, we can unload wave UnloadWave(wave); @@ -233,7 +233,7 @@ Sound LoadSoundFromWave(Wave wave) if (wave.data != NULL) { ALenum format = 0; - + // The OpenAL format is worked out by looking at the number of channels and the sample size (bits per sample) if (wave.channels == 1) { @@ -256,7 +256,7 @@ Sound LoadSoundFromWave(Wave wave) } } else TraceLog(WARNING, "Wave number of channels not supported: %i", wave.channels); - + // Create an audio source ALuint source; alGenSources(1, &source); // Generate pointer to audio source @@ -271,7 +271,7 @@ Sound LoadSoundFromWave(Wave wave) //---------------------------------------- ALuint buffer; alGenBuffers(1, &buffer); // Generate pointer to buffer - + unsigned int dataSize = wave.sampleCount*wave.sampleSize/8; // Size in bytes // Upload sound data to buffer @@ -367,7 +367,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) free(data); sound = LoadSoundFromWave(wave); - + // Sound is loaded, we can unload wave data UnloadWave(wave); } @@ -506,13 +506,13 @@ Music LoadMusicStream(char *fileName) TraceLog(DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); TraceLog(DEBUG, "[%s] OGG channels: %i", fileName, info.channels); TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); - + } } else if (strcmp(GetExtension(fileName), "xm") == 0) { int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName); - + if (!result) // XM context created successfully { jar_xm_set_max_loop_count(music->ctxXm, 0); // Set infinite number of loops @@ -523,7 +523,7 @@ Music LoadMusicStream(char *fileName) music->samplesLeft = music->totalSamples; music->ctxType = MUSIC_MODULE_XM; music->loop = true; - + TraceLog(DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples); TraceLog(DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); } @@ -555,11 +555,11 @@ Music LoadMusicStream(char *fileName) void UnloadMusicStream(Music music) { CloseAudioStream(music->stream); - + if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg); else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm); else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod); - + free(music); } @@ -597,58 +597,58 @@ void UpdateMusicStream(Music music) // Determine if music stream is ready to be written alGetSourcei(music->stream.source, AL_BUFFERS_PROCESSED, &processed); - + int numBuffersToProcess = processed; - + if (processed > 0) { bool active = true; short pcm[AUDIO_BUFFER_SIZE]; float pcmf[AUDIO_BUFFER_SIZE]; - - int numSamples = 0; // Total size of data steamed in L+R samples for xm floats, + + int numSamples = 0; // Total size of data steamed in L+R samples for xm floats, // individual L or R for ogg shorts for (int i = 0; i < numBuffersToProcess; i++) { switch (music->ctxType) { - case MUSIC_AUDIO_OGG: + case MUSIC_AUDIO_OGG: { if (music->samplesLeft >= AUDIO_BUFFER_SIZE) numSamples = AUDIO_BUFFER_SIZE; else numSamples = music->samplesLeft; - + // NOTE: Returns the number of samples to process (should be the same as numSamples -> it is) int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, pcm, numSamples); // TODO: Review stereo channels Ogg, not enough samples served! UpdateAudioStream(music->stream, pcm, numSamplesOgg*music->stream.channels); music->samplesLeft -= (numSamplesOgg*music->stream.channels); - + } break; - case MUSIC_MODULE_XM: + case MUSIC_MODULE_XM: { if (music->samplesLeft >= AUDIO_BUFFER_SIZE/2) numSamples = AUDIO_BUFFER_SIZE/2; else numSamples = music->samplesLeft; - + // NOTE: Output buffer is 2*numsamples elements (left and right value for each sample) jar_xm_generate_samples(music->ctxXm, pcmf, numSamples); UpdateAudioStream(music->stream, pcmf, numSamples*2); // Using 32bit PCM data music->samplesLeft -= numSamples; - + //TraceLog(INFO, "Samples left: %i", music->samplesLeft); - + } break; - case MUSIC_MODULE_MOD: + case MUSIC_MODULE_MOD: { if (music->samplesLeft >= AUDIO_BUFFER_SIZE/2) numSamples = AUDIO_BUFFER_SIZE/2; else numSamples = music->samplesLeft; - + // NOTE: Output buffer size is nbsample*channels (default: 48000Hz, 16bit, Stereo) - jar_mod_fillbuffer(&music->ctxMod, pcm, numSamples, 0); + jar_mod_fillbuffer(&music->ctxMod, pcm, numSamples, 0); UpdateAudioStream(music->stream, pcm, numSamples*2); music->samplesLeft -= numSamples; - + } break; default: break; } @@ -659,15 +659,15 @@ void UpdateMusicStream(Music music) break; } } - + // Reset audio stream for looping if (!active && music->loop) { // Restart music context (if required) - //if (music->ctxType == MUSIC_MODULE_XM) + //if (music->ctxType == MUSIC_MODULE_XM) if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_seek_start(&music->ctxMod); else if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_seek_start(music->ctxOgg); - + // Reset samples left to total samples music->samplesLeft = music->totalSamples; } @@ -713,7 +713,7 @@ void SetMusicPitch(Music music, float pitch) float GetMusicTimeLength(Music music) { float totalSeconds = (float)music->totalSamples/music->stream.sampleRate; - + return totalSeconds; } @@ -732,7 +732,7 @@ float GetMusicTimePlayed(Music music) AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, unsigned int channels) { AudioStream stream = { 0 }; - + stream.sampleRate = sampleRate; stream.sampleSize = sampleSize; stream.channels = channels; @@ -791,7 +791,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un } alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers); - + TraceLog(INFO, "[AUD ID %i] Audio stream loaded successfully", stream.source); return stream; @@ -806,9 +806,9 @@ void CloseAudioStream(AudioStream stream) // Flush out all queued buffers int queued = 0; alGetSourcei(stream.source, AL_BUFFERS_QUEUED, &queued); - + ALuint buffer = 0; - + while (queued > 0) { alSourceUnqueueBuffers(stream.source, 1, &buffer); @@ -818,7 +818,7 @@ void CloseAudioStream(AudioStream stream) // Delete source and buffers alDeleteSources(1, &stream.source); alDeleteBuffers(MAX_STREAM_BUFFERS, stream.buffers); - + TraceLog(INFO, "[AUD ID %i] Unloaded audio stream data", stream.source); } @@ -828,14 +828,14 @@ void UpdateAudioStream(AudioStream stream, void *data, int numSamples) { ALuint buffer = 0; alSourceUnqueueBuffers(stream.source, 1, &buffer); - + // Check if any buffer was available for unqueue if (alGetError() != AL_INVALID_VALUE) { if (stream.sampleSize == 8) alBufferData(buffer, stream.format, (unsigned char *)data, numSamples*sizeof(unsigned char), stream.sampleRate); else if (stream.sampleSize == 16) alBufferData(buffer, stream.format, (short *)data, numSamples*sizeof(short), stream.sampleRate); else if (stream.sampleSize == 32) alBufferData(buffer, stream.format, (float *)data, numSamples*sizeof(float), stream.sampleRate); - + alSourceQueueBuffers(stream.source, 1, &buffer); } } diff --git a/src/core.c b/src/core.c index 2b5329e3..a76fe0be 100644 --- a/src/core.c +++ b/src/core.c @@ -120,9 +120,9 @@ //#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN" //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" - + #define MOUSE_SENSITIVITY 0.8f - + #define MAX_GAMEPADS 2 // Max number of gamepads supported #define MAX_GAMEPAD_BUTTONS 11 // Max bumber of buttons supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) @@ -333,7 +333,7 @@ void InitWindow(int width, int height, const char *title) emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback); emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback); emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback); - + // TODO: Add gamepad support (not provided by GLFW3 on emscripten) //emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenInputCallback); //emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenInputCallback); @@ -394,7 +394,7 @@ void InitWindow(int width, int height, struct android_app *state) //state->userData = &engine; app->onAppCmd = AndroidCommandCallback; app->onInputEvent = AndroidInputCallback; - + InitAssetManager(app->activity->assetManager); TraceLog(INFO, "Android app initialized successfully"); @@ -447,7 +447,7 @@ void CloseWindow(void) eglTerminate(display); display = EGL_NO_DISPLAY; - } + } #endif #if defined(PLATFORM_RPI) @@ -527,7 +527,7 @@ void BeginDrawing(void) currentTime = GetTime(); // Number of elapsed seconds since InitTimer() was called updateTime = currentTime - previousTime; previousTime = currentTime; - + rlClearScreenBuffers(); // Clear current framebuffers rlLoadIdentity(); // Reset current matrix (MODELVIEW) rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here @@ -543,7 +543,7 @@ void EndDrawing(void) SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events - + // Frame time control system currentTime = GetTime(); drawTime = currentTime - previousTime; @@ -575,9 +575,9 @@ void Begin2dMode(Camera2D camera) Matrix matRotation = MatrixRotate((Vector3){ 0.0f, 0.0f, 1.0f }, camera.rotation*DEG2RAD); Matrix matScale = MatrixScale(camera.zoom, camera.zoom, 1.0f); Matrix matTranslation = MatrixTranslate(camera.offset.x + camera.target.x, camera.offset.y + camera.target.y, 0.0f); - + Matrix matTransform = MatrixMultiply(MatrixMultiply(matOrigin, MatrixMultiply(matScale, matRotation)), matTranslation); - + rlMultMatrixf(MatrixToFloat(matTransform)); } @@ -593,14 +593,14 @@ void End2dMode(void) void Begin3dMode(Camera camera) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) - + if (IsVrDeviceReady()) BeginVrDrawing(); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection rlLoadIdentity(); // Reset current matrix (PROJECTION) - + // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; double top = 0.01*tan(camera.fovy*PI/360.0); @@ -615,15 +615,15 @@ void Begin3dMode(Camera camera) // Setup Camera view Matrix cameraView = MatrixLookAt(camera.position, camera.target, camera.up); rlMultMatrixf(MatrixToFloat(cameraView)); // Multiply MODELVIEW matrix by view matrix (camera) - + rlEnableDepthTest(); // Enable DEPTH_TEST for 3D } // Ends 3D mode and returns to default 2D orthographic mode void End3dMode(void) -{ +{ rlglDraw(); // Process internal buffers (update + draw) - + if (IsVrDeviceReady()) EndVrDrawing(); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix @@ -633,7 +633,7 @@ void End3dMode(void) rlLoadIdentity(); // Reset current matrix (MODELVIEW) //rlTranslatef(0.375, 0.375, 0); // HACK to ensure pixel-perfect drawing on OpenGL (after exiting 3D mode) - + rlDisableDepthTest(); // Disable DEPTH_TEST for 2D } @@ -645,16 +645,16 @@ void BeginTextureMode(RenderTexture2D target) rlEnableRenderTexture(target.id); // Enable render target rlClearScreenBuffers(); // Clear render texture buffers - + // Set viewport to framebuffer size - rlViewport(0, 0, target.texture.width, target.texture.height); - + rlViewport(0, 0, target.texture.width, target.texture.height); + rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix rlLoadIdentity(); // Reset current matrix (PROJECTION) // Set orthographic projection to current framebuffer size // NOTE: Configured top-left corner as (0, 0) - rlOrtho(0, target.texture.width, target.texture.height, 0, 0.0f, 1.0f); + rlOrtho(0, target.texture.width, target.texture.height, 0, 0.0f, 1.0f); rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -672,10 +672,10 @@ void EndTextureMode(void) // Set viewport to default framebuffer size (screen size) // TODO: consider possible viewport offsets rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - + rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix rlLoadIdentity(); // Reset current matrix (PROJECTION) - + // Set orthographic projection to current framebuffer size // NOTE: Configured top-left corner as (0, 0) rlOrtho(0, GetScreenWidth(), GetScreenHeight(), 0, 0.0f, 1.0f); @@ -701,7 +701,7 @@ float GetFPS(void) // Returns time in seconds for one frame float GetFrameTime(void) { - // As we are operate quite a lot with frameTime, + // As we are operate quite a lot with frameTime, // it could be no stable, so we round it before passing it around // NOTE: There are still problems with high framerates (>500fps) double roundedFrameTime = round(frameTime*10000)/10000.0; @@ -735,7 +735,7 @@ float *VectorToFloat(Vector3 vec) } // Converts Matrix to float array -// NOTE: Returned vector is a transposed version of the Matrix struct, +// NOTE: Returned vector is a transposed version of the Matrix struct, // it should be this way because, despite raymath use OpenGL column-major convention, // Matrix struct memory alignment and variables naming are not coherent float *MatrixToFloat(Matrix mat) @@ -799,7 +799,7 @@ Color Fade(Color color, float alpha) { if (alpha < 0.0f) alpha = 0.0f; else if (alpha > 1.0f) alpha = 1.0f; - + float colorAlpha = (float)color.a*alpha; return (Color){color.r, color.g, color.b, (unsigned char)colorAlpha}; @@ -841,9 +841,9 @@ void ClearDroppedFiles(void) if (dropFilesCount > 0) { for (int i = 0; i < dropFilesCount; i++) free(dropFilesPath[i]); - + free(dropFilesPath); - + dropFilesCount = 0; } } @@ -854,7 +854,7 @@ void ClearDroppedFiles(void) void StorageSaveValue(int position, int value) { FILE *storageFile = NULL; - + char path[128]; #if defined(PLATFORM_ANDROID) strcpy(path, internalDataPath); @@ -865,7 +865,7 @@ void StorageSaveValue(int position, int value) #endif // Try open existing file to append data - storageFile = fopen(path, "rb+"); + storageFile = fopen(path, "rb+"); // If file doesn't exist, create a new storage data file if (!storageFile) storageFile = fopen(path, "wb"); @@ -877,14 +877,14 @@ void StorageSaveValue(int position, int value) fseek(storageFile, 0, SEEK_END); int fileSize = ftell(storageFile); // Size in bytes fseek(storageFile, 0, SEEK_SET); - + if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); else { fseek(storageFile, (position*4), SEEK_SET); fwrite(&value, 1, 4, storageFile); } - + fclose(storageFile); } } @@ -894,7 +894,7 @@ void StorageSaveValue(int position, int value) int StorageLoadValue(int position) { int value = 0; - + char path[128]; #if defined(PLATFORM_ANDROID) strcpy(path, internalDataPath); @@ -903,9 +903,9 @@ int StorageLoadValue(int position) #else strcpy(path, STORAGE_FILENAME); #endif - + // Try open existing file to append data - FILE *storageFile = fopen(path, "rb"); + FILE *storageFile = fopen(path, "rb"); if (!storageFile) TraceLog(WARNING, "Storage data file could not be found"); else @@ -914,42 +914,42 @@ int StorageLoadValue(int position) fseek(storageFile, 0, SEEK_END); int fileSize = ftell(storageFile); // Size in bytes rewind(storageFile); - + if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); else { fseek(storageFile, (position*4), SEEK_SET); fread(&value, 1, 4, storageFile); } - + fclose(storageFile); } - + return value; } // Returns a ray trace from mouse position Ray GetMouseRay(Vector2 mousePosition, Camera camera) -{ +{ Ray ray; - + // Calculate normalized device coordinates // NOTE: y value is negative float x = (2.0f*mousePosition.x)/(float)GetScreenWidth() - 1.0f; float y = 1.0f - (2.0f*mousePosition.y)/(float)GetScreenHeight(); float z = 1.0f; - + // Store values in a vector Vector3 deviceCoords = { x, y, z }; - + TraceLog(DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); - + // Calculate projection matrix (from perspective instead of frustum) Matrix matProj = MatrixPerspective(camera.fovy, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); - + // Calculate view matrix from camera look at Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - + // Do I need to transpose it? It seems that yes... // NOTE: matrix order may be incorrect... In OpenGL to get world position from // camera view it just needs to get inverted, but here we need to transpose it too. @@ -957,10 +957,10 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) // to a vector, you will get its 3d world position coordinates (camera.position). // If you don't transpose, final position will be wrong. MatrixTranspose(&matView); - + //#define USE_RLGL_UNPROJECT #if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlglUnproject() - + Vector3 nearPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); Vector3 farPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); @@ -969,56 +969,56 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it Matrix matProjView = MatrixMultiply(matProj, matView); MatrixInvert(&matProjView); - + // Calculate far and near points Quaternion near = { deviceCoords.x, deviceCoords.y, 0.0f, 1.0f }; Quaternion far = { deviceCoords.x, deviceCoords.y, 1.0f, 1.0f }; - + // Multiply points by unproject matrix QuaternionTransform(&near, matProjView); QuaternionTransform(&far, matProjView); - + // Calculate normalized world points in vectors Vector3 nearPoint = { near.x/near.w, near.y/near.w, near.z/near.w}; Vector3 farPoint = { far.x/far.w, far.y/far.w, far.z/far.w}; #endif - + // Calculate normalized direction vector Vector3 direction = VectorSubtract(farPoint, nearPoint); VectorNormalize(&direction); - + // Apply calculated vectors to ray ray.position = camera.position; ray.direction = direction; - + return ray; } // Returns the screen space position from a 3d world space position Vector2 GetWorldToScreen(Vector3 position, Camera camera) -{ +{ // Calculate projection matrix (from perspective instead of frustum Matrix matProj = MatrixPerspective(camera.fovy, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); - + // Calculate view matrix from camera look at (and transpose it) Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); MatrixTranspose(&matView); - + // Convert world position vector to quaternion Quaternion worldPos = { position.x, position.y, position.z, 1.0f }; - + // Transform world position to view QuaternionTransform(&worldPos, matView); - + // Transform result to projection (clip space position) QuaternionTransform(&worldPos, matProj); - + // Calculate normalized device coordinates (inverted y) Vector3 ndcPos = { worldPos.x / worldPos.w, -worldPos.y / worldPos.w, worldPos.z / worldPos.z }; - + // Calculate 2d screen position vector Vector2 screenPosition = { (ndcPos.x + 1.0f)/2.0f*(float)GetScreenWidth(), (ndcPos.y + 1.0f)/2.0f*(float)GetScreenHeight() }; - + return screenPosition; } @@ -1144,7 +1144,7 @@ bool IsCursorHidden() bool IsGamepadAvailable(int gamepad) { bool result = false; - + #if defined(PLATFORM_RPI) if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true; #else @@ -1158,7 +1158,7 @@ bool IsGamepadAvailable(int gamepad) float GetGamepadAxisMovement(int gamepad, int axis) { float value = 0; - + #if defined(PLATFORM_RPI) if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) { @@ -1167,9 +1167,9 @@ float GetGamepadAxisMovement(int gamepad, int axis) #else const float *axes; int axisCount = 0; - + axes = glfwGetJoystickAxes(gamepad, &axisCount); - + if (axis < axisCount) value = axes[axis]; #endif @@ -1197,7 +1197,7 @@ bool IsGamepadButtonPressed(int gamepad, int button) bool IsGamepadButtonDown(int gamepad, int button) { bool result = false; - + #if defined(PLATFORM_RPI) // Get gamepad buttons information if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (gamepadButtons[gamepad][button] == 1)) result = true; @@ -1205,13 +1205,13 @@ bool IsGamepadButtonDown(int gamepad, int button) #else const unsigned char *buttons; int buttonsCount; - + buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true; else result = false; #endif - + return result; } @@ -1260,7 +1260,7 @@ bool IsGamepadButtonUp(int gamepad, int button) bool IsMouseButtonPressed(int button) { bool pressed = false; - + #if defined(PLATFORM_ANDROID) if (IsGestureDetected(GESTURE_TAP)) pressed = true; #else @@ -1274,13 +1274,13 @@ bool IsMouseButtonPressed(int button) bool IsMouseButtonDown(int button) { bool down = false; - + #if defined(PLATFORM_ANDROID) if (IsGestureDetected(GESTURE_HOLD)) down = true; #else if (GetMouseButtonStatus(button) == 1) down = true; #endif - + return down; } @@ -1288,7 +1288,7 @@ bool IsMouseButtonDown(int button) bool IsMouseButtonReleased(int button) { bool released = false; - + #if !defined(PLATFORM_ANDROID) if ((currentMouseState[button] != previousMouseState[button]) && (currentMouseState[button] == 0)) released = true; #endif @@ -1300,7 +1300,7 @@ bool IsMouseButtonReleased(int button) bool IsMouseButtonUp(int button) { bool up = false; - + #if !defined(PLATFORM_ANDROID) if (GetMouseButtonStatus(button) == 0) up = true; #endif @@ -1385,7 +1385,7 @@ int GetTouchY(void) Vector2 GetTouchPosition(int index) { Vector2 position = { -1.0f, -1.0f }; - + #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) if (index < MAX_TOUCH_POINTS) position = touchPosition[index]; else TraceLog(WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); @@ -1493,7 +1493,7 @@ static void InitGraphicsDevice(int width, int height) // NOTE: When asking for an OpenGL context version, most drivers provide highest supported version // with forward compatibility to older OpenGL versions. // For example, if using OpenGL 1.1, driver can provide a 3.3 context fordward compatible. - + if (configFlags & FLAG_MSAA_4X_HINT) { glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0 @@ -1513,7 +1513,7 @@ static void InitGraphicsDevice(int width, int height) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Profiles Hint: Only 3.3 and above! // Other values: GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_COMPAT_PROFILE #ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // OSX Requires #else glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); // Fordward Compatibility Hint: Only 3.3 and above! #endif @@ -1523,9 +1523,9 @@ static void InitGraphicsDevice(int width, int height) if (fullscreen) { // Obtain recommended displayWidth/displayHeight from a valid videomode for the monitor - int count; + int count; const GLFWvidmode *modes = glfwGetVideoModes(glfwGetPrimaryMonitor(), &count); - + // Get closest videomode to desired screenWidth/screenHeight for (int i = 0; i < count; i++) { @@ -1539,7 +1539,7 @@ static void InitGraphicsDevice(int width, int height) } } } - + TraceLog(WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight); // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, @@ -1548,12 +1548,12 @@ static void InitGraphicsDevice(int width, int height) // by the sides to fit all monitor space... // At this point we need to manage render size vs screen size - // NOTE: This function uses and modifies global module variables: + // NOTE: This function uses and modifies global module variables: // screenWidth/screenHeight - renderWidth/renderHeight - downscaleView SetupFramebufferSize(displayWidth, displayHeight); window = glfwCreateWindow(displayWidth, displayHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); - + // NOTE: Full-screen change, not working properly... //glfwSetWindowMonitor(window, glfwGetPrimaryMonitor(), 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE); } @@ -1561,15 +1561,15 @@ static void InitGraphicsDevice(int width, int height) { // No-fullscreen window creation window = glfwCreateWindow(screenWidth, screenHeight, windowTitle, NULL, NULL); - + #if defined(PLATFORM_DESKTOP) // Center window on screen int windowPosX = displayWidth/2 - screenWidth/2; int windowPosY = displayHeight/2 - screenHeight/2; - + if (windowPosX < 0) windowPosX = 0; if (windowPosY < 0) windowPosY = 0; - + glfwSetWindowPos(window, windowPosX, windowPosY); #endif renderWidth = screenWidth; @@ -1612,7 +1612,7 @@ static void InitGraphicsDevice(int width, int height) // NOTE: GLFW loader function is passed as parameter rlglLoadExtensions(glfwGetProcAddress); #endif - + // Enables GPU v-sync, so frames are not limited to screen refresh rate (60Hz -> 60 FPS) // If not set, swap interval uses GPU v-sync configuration // Framerate can be setup using SetTargetFPS() @@ -1620,7 +1620,7 @@ static void InitGraphicsDevice(int width, int height) { glfwSwapInterval(1); TraceLog(INFO, "Trying to enable VSYNC"); - } + } #endif // defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -1643,13 +1643,13 @@ static void InitGraphicsDevice(int width, int height) EGLint samples = 0; EGLint sampleBuffer = 0; - if (configFlags & FLAG_MSAA_4X_HINT) + if (configFlags & FLAG_MSAA_4X_HINT) { samples = 4; sampleBuffer = 1; TraceLog(INFO, "Trying to enable MSAA x4"); } - + const EGLint framebufferAttribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // Type of context support -> Required on RPI? @@ -1773,10 +1773,10 @@ static void InitGraphicsDevice(int width, int height) // Initialize OpenGL context (states and resources) // NOTE: screenWidth and screenHeight not used, just stored as globals rlglInit(screenWidth, screenHeight); - + #ifdef __APPLE__ // Get framebuffer size of current window - // NOTE: Required to handle HighDPI display correctly on OSX because framebuffer + // NOTE: Required to handle HighDPI display correctly on OSX because framebuffer // is automatically reasized to adapt to new DPI. // When OS does that, it can be detected using GLFW3 callback: glfwSetFramebufferSizeCallback() int fbWidth, fbHeight; @@ -1792,7 +1792,7 @@ static void InitGraphicsDevice(int width, int height) // NOTE: Default to orthographic projection mode with top-left corner at (0,0) rlMatrixMode(RL_PROJECTION); // Switch to PROJECTION matrix rlLoadIdentity(); // Reset current matrix (PROJECTION) - rlOrtho(0, renderWidth - renderOffsetX, renderHeight - renderOffsetY, 0, 0.0f, 1.0f); + rlOrtho(0, renderWidth - renderOffsetX, renderHeight - renderOffsetY, 0, 0.0f, 1.0f); rlMatrixMode(RL_MODELVIEW); // Switch back to MODELVIEW matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -1806,7 +1806,7 @@ static void InitGraphicsDevice(int width, int height) // Compute framebuffer size relative to screen size and display size // NOTE: Global variables renderWidth/renderHeight and renderOffsetX/renderOffsetY can be modified static void SetupFramebufferSize(int displayWidth, int displayHeight) -{ +{ // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var) if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { @@ -1945,7 +1945,7 @@ static void PollInputEvents(void) // NOTE: Gestures update must be called every frame to reset gestures correctly // because ProcessGestureEvent() is just called on an event, not every frame UpdateGestures(); - + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // Mouse input polling double mouseX; @@ -2025,7 +2025,7 @@ static void TakeScreenshot(void) unsigned char *imgData = rlglReadScreenPixels(renderWidth, renderHeight); sprintf(buffer, "screenshot%03i.png", shotNum); - + // Save image as PNG WritePNG(buffer, imgData, renderWidth, renderHeight, 4); @@ -2062,7 +2062,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i #if defined(PLATFORM_DESKTOP) else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) TakeScreenshot(); #endif - else + else { currentKeyState[key] = action; if (action == GLFW_PRESS) lastKeyPressed = key; @@ -2073,27 +2073,27 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { currentMouseState[button] = action; - + #define ENABLE_MOUSE_GESTURES #if defined(ENABLE_MOUSE_GESTURES) // Process mouse events as touches to be able to use mouse-gestures GestureEvent gestureEvent; - + // Register touch actions if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; - + // NOTE: TOUCH_MOVE event is registered in MouseCursorPosCallback() - + // Assign a pointer ID gestureEvent.pointerId[0] = 0; - + // Register touch points count gestureEvent.pointCount = 1; - + // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); - + // Normalize gestureEvent.position[0] for screenWidth and screenHeight gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); @@ -2112,20 +2112,20 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) GestureEvent gestureEvent; gestureEvent.touchAction = TOUCH_MOVE; - + // Assign a pointer ID gestureEvent.pointerId[0] = 0; // Register touch points count gestureEvent.pointCount = 1; - + // Register touch points position, only one point registered gestureEvent.position[0] = (Vector2){ (float)x, (float)y }; - + touchPosition[0] = gestureEvent.position[0]; - + // Normalize gestureEvent.position[0] for screenWidth and screenHeight - gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing @@ -2166,7 +2166,7 @@ static void WindowSizeCallback(GLFWwindow *window, int width, int height) screenHeight = height; renderWidth = width; renderHeight = height; - + // NOTE: Postprocessing texture is not scaled to new size } @@ -2185,9 +2185,9 @@ static void WindowIconifyCallback(GLFWwindow* window, int iconified) static void WindowDropCallback(GLFWwindow *window, int count, const char **paths) { ClearDroppedFiles(); - + dropFilesPath = (char **)malloc(sizeof(char *)*count); - + for (int i = 0; i < count; i++) { dropFilesPath[i] = (char *)malloc(sizeof(char)*256); // Max path length set to 256 char @@ -2249,7 +2249,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) for (int i = 0; i < assetsCount; i++) { // TODO: Unload old asset if required - + // Load texture again to pointed texture (*textureAsset + i) = LoadTexture(assetPath[i]); } @@ -2292,7 +2292,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // NOTE 2: In some cases (too many context loaded), OS could unload context automatically... :( eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(display, surface); - + contextRebindRequired = true; TraceLog(INFO, "APP_CMD_TERM_WINDOW"); @@ -2329,7 +2329,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) { //http://developer.android.com/ndk/reference/index.html - + int type = AInputEvent_getType(event); if (type == AINPUT_EVENT_TYPE_MOTION) @@ -2337,7 +2337,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) // Get first touch position touchPosition[0].x = AMotionEvent_getX(event, 0); touchPosition[0].y = AMotionEvent_getY(event, 0); - + // Get second touch position touchPosition[1].x = AMotionEvent_getX(event, 1); touchPosition[1].y = AMotionEvent_getY(event, 1); @@ -2346,7 +2346,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) { int32_t keycode = AKeyEvent_getKeyCode(event); //int32_t AKeyEvent_getMetaState(event); - + // Save current button and its state currentButtonState[keycode] = AKeyEvent_getAction(event); // Down = 0, Up = 1 @@ -2358,7 +2358,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) // NOTE: AndroidManifest.xml must have // Before that change, activity was calling CMD_TERM_WINDOW and CMD_DESTROY when locking mobile, so that was not a normal behaviour return 0; - } + } else if ((keycode == AKEYCODE_BACK) || (keycode == AKEYCODE_MENU)) { // Eat BACK_BUTTON and AKEYCODE_MENU, just do nothing... and don't let to be handled by OS! @@ -2370,36 +2370,36 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) return 0; } } - + int32_t action = AMotionEvent_getAction(event); unsigned int flags = action & AMOTION_EVENT_ACTION_MASK; - + GestureEvent gestureEvent; - + // Register touch actions if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.touchAction = TOUCH_DOWN; else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.touchAction = TOUCH_UP; else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.touchAction = TOUCH_MOVE; - + // Register touch points count gestureEvent.pointCount = AMotionEvent_getPointerCount(event); - + // Register touch points id gestureEvent.pointerId[0] = AMotionEvent_getPointerId(event, 0); gestureEvent.pointerId[1] = AMotionEvent_getPointerId(event, 1); - + // Register touch points position // NOTE: Only two points registered gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) }; gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) }; - + // Normalize gestureEvent.position[x] for screenWidth and screenHeight - gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); - - gestureEvent.position[1].x /= (float)GetScreenWidth(); + + gestureEvent.position[1].x /= (float)GetScreenWidth(); gestureEvent.position[1].y /= (float)GetScreenHeight(); - + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -2410,13 +2410,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) #if defined(PLATFORM_WEB) static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData) { - //isFullscreen: int e->isFullscreen - //fullscreenEnabled: int e->fullscreenEnabled + //isFullscreen: int e->isFullscreen + //fullscreenEnabled: int e->fullscreenEnabled //fs element nodeName: (char *) e->nodeName //fs element id: (char *) e->id //Current element size: (int) e->elementWidth, (int) e->elementHeight //Screen size:(int) e->screenWidth, (int) e->screenHeight - + if (e->isFullscreen) { TraceLog(INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); @@ -2425,7 +2425,7 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte { TraceLog(INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); } - + // TODO: Depending on scaling factor (screen vs element), calculate factor to scale mouse/touch input return 0; @@ -2445,33 +2445,33 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent x = touchEvent->touches[i].canvasX; y = touchEvent->touches[i].canvasY; } - + printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches, event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : ""); for(int i = 0; i < event->numTouches; ++i) { const EmscriptenTouchPoint *t = &event->touches[i]; - + printf(" %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n", t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY); } */ - + GestureEvent gestureEvent; // Register touch actions if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_DOWN; else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_UP; else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_MOVE; - + // Register touch points count gestureEvent.pointCount = touchEvent->numTouches; - + // Register touch points id gestureEvent.pointerId[0] = touchEvent->touches[0].identifier; gestureEvent.pointerId[1] = touchEvent->touches[1].identifier; - + // Register touch points position // NOTE: Only two points registered // TODO: Touch data should be scaled accordingly! @@ -2482,12 +2482,12 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent touchPosition[0] = gestureEvent.position[0]; touchPosition[1] = gestureEvent.position[1]; - + // Normalize gestureEvent.position[x] for screenWidth and screenHeight - gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].x /= (float)GetScreenWidth(); gestureEvent.position[0].y /= (float)GetScreenHeight(); - - gestureEvent.position[1].x /= (float)GetScreenWidth(); + + gestureEvent.position[1].x /= (float)GetScreenWidth(); gestureEvent.position[1].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing @@ -2533,7 +2533,7 @@ static void InitKeyboard(void) else { // We reconfigure keyboard mode to get: - // - scancodes (K_RAW) + // - scancodes (K_RAW) // - keycodes (K_MEDIUMRAW) // - ASCII chars (K_XLATE) // - UNICODE chars (K_UNICODE) @@ -2549,7 +2549,7 @@ static void InitKeyboard(void) static void ProcessKeyboard(void) { #define MAX_KEYBUFFER_SIZE 32 // Max size in bytes to read - + // Keyboard input polling (fill keys[256] array with status) int bufferByteCount = 0; // Bytes available on the buffer char keysBuffer[MAX_KEYBUFFER_SIZE]; // Max keys to be read at a time @@ -2564,7 +2564,7 @@ static void ProcessKeyboard(void) for (int i = 0; i < bufferByteCount; i++) { TraceLog(DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); - + //printf("Key(s) bytes: "); //for (int i = 0; i < bufferByteCount; i++) printf("0x%02x ", keysBuffer[i]); //printf("\n"); @@ -2598,7 +2598,7 @@ static void ProcessKeyboard(void) case 0x34: currentKeyState[301] = 1; break; // raylib KEY_F12 default: break; } - + if (keysBuffer[i + 2] == 0x5b) i += 4; else if ((keysBuffer[i + 2] == 0x31) || (keysBuffer[i + 2] == 0x32)) i += 5; } @@ -2615,7 +2615,7 @@ static void ProcessKeyboard(void) i += 3; // Jump to next key } - + // NOTE: Some keys are not directly keymapped (CTRL, ALT, SHIFT) } } @@ -2625,7 +2625,7 @@ static void ProcessKeyboard(void) else { TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); - + // Translate lowercase a-z letters to A-Z if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122)) { @@ -2634,10 +2634,10 @@ static void ProcessKeyboard(void) else currentKeyState[(int)keysBuffer[i]] = 1; } } - + // Check exit key (same functionality as GLFW3 KeyCallback()) if (currentKeyState[exitKey] == 1) windowShouldClose = true; - + // Check screen capture key if (currentKeyState[301] == 1) TakeScreenshot(); // raylib key: KEY_F12 (GLFW_KEY_F12) } @@ -2647,7 +2647,7 @@ static void RestoreKeyboard(void) { // Reset to default keyboard settings tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings); - + // Reconfigure keyboard to default mode ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode); } @@ -2677,14 +2677,14 @@ static void InitMouse(void) static void *MouseThread(void *arg) { const unsigned char XSIGN = 1<<4, YSIGN = 1<<5; - - typedef struct { + + typedef struct { char buttons; - char dx, dy; + char dx, dy; } MouseEvent; - + MouseEvent mouse; - + int mouseRelX = 0; int mouseRelY = 0; @@ -2693,7 +2693,7 @@ static void *MouseThread(void *arg) if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent)) { if ((mouse.buttons & 0x08) == 0) break; // This bit should always be set - + // Check Left button pressed if ((mouse.buttons & 0x01) > 0) currentMouseState[0] = 1; else currentMouseState[0] = 0; @@ -2701,27 +2701,27 @@ static void *MouseThread(void *arg) // Check Right button pressed if ((mouse.buttons & 0x02) > 0) currentMouseState[1] = 1; else currentMouseState[1] = 0; - + // Check Middle button pressed if ((mouse.buttons & 0x04) > 0) currentMouseState[2] = 1; else currentMouseState[2] = 0; - + mouseRelX = (int)mouse.dx; mouseRelY = (int)mouse.dy; - + if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX); if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY); - + // NOTE: Mouse movement is normalized to not be screen resolution dependant // We suppose 2*255 (max relative movement) is equivalent to screenWidth (max pixels width) // Result after normalization is multiplied by MOUSE_SENSITIVITY factor mousePosition.x += (float)mouseRelX*((float)screenWidth/(2*255))*MOUSE_SENSITIVITY; mousePosition.y -= (float)mouseRelY*((float)screenHeight/(2*255))*MOUSE_SENSITIVITY; - + if (mousePosition.x < 0) mousePosition.x = 0; if (mousePosition.y < 0) mousePosition.y = 0; - + if (mousePosition.x > screenWidth) mousePosition.x = screenWidth; if (mousePosition.y > screenHeight) mousePosition.y = screenHeight; } @@ -2735,12 +2735,12 @@ static void *MouseThread(void *arg) static void InitGamepad(void) { char gamepadDev[128] = ""; - + for (int i = 0; i < MAX_GAMEPADS; i++) { sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i); - - if ((gamepadStream[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0) + + if ((gamepadStream[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0) { // NOTE: Only show message for first gamepad if (i == 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); @@ -2758,7 +2758,7 @@ static void InitGamepad(void) else TraceLog(INFO, "Gamepad device initialized successfully"); } } - } + } } // Process Gamepad (/dev/input/js0) @@ -2777,7 +2777,7 @@ static void *GamepadThread(void *arg) // Read gamepad event struct js_event gamepadEvent; - + while (!windowShouldClose) { for (int i = 0; i < MAX_GAMEPADS; i++) @@ -2785,22 +2785,22 @@ static void *GamepadThread(void *arg) if (read(gamepadStream[i], &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event)) { gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events - + // Process gamepad events by type - if (gamepadEvent.type == JS_EVENT_BUTTON) + if (gamepadEvent.type == JS_EVENT_BUTTON) { TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); - - if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) + + if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) { // 1 - button pressed, 0 - button released gamepadButtons[i][gamepadEvent.number] = (int)gamepadEvent.value; } } - else if (gamepadEvent.type == JS_EVENT_AXIS) + else if (gamepadEvent.type == JS_EVENT_AXIS) { TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); - + if (gamepadEvent.number < MAX_GAMEPAD_AXIS) { // NOTE: Scaling of gamepadEvent.value to get values between -1..1 diff --git a/src/models.c b/src/models.c index 24238ed2..e9044e96 100644 --- a/src/models.c +++ b/src/models.c @@ -81,12 +81,12 @@ void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rot rlPushMatrix(); rlTranslatef(center.x, center.y, center.z); rlRotatef(rotationAngle, rotation.x, rotation.y, rotation.z); - + rlBegin(RL_LINES); for (int i = 0; i < 360; i += 10) { rlColor4ub(color.r, color.g, color.b, color.a); - + rlVertex3f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius, 0.0f); rlVertex3f(sin(DEG2RAD*(i + 10)) * radius, cos(DEG2RAD*(i + 10)) * radius, 0.0f); } @@ -583,13 +583,13 @@ void DrawLight(Light light) DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : BLACK)); } break; case LIGHT_DIRECTIONAL: - { + { DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); } break; case LIGHT_SPOT: - { + { DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : BLACK)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); @@ -602,7 +602,7 @@ void DrawLight(Light light) Model LoadModel(const char *fileName) { Model model = { 0 }; - + // TODO: Initialize default data for model in case loading fails, maybe a cube? if (strcmp(GetExtension(fileName), "obj") == 0) model.mesh = LoadOBJ(fileName); @@ -612,7 +612,7 @@ Model LoadModel(const char *fileName) else { rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - + model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); } @@ -626,12 +626,12 @@ Model LoadModelEx(Mesh data, bool dynamic) Model model = { 0 }; model.mesh = data; - + rlglLoadMesh(&model.mesh, dynamic); // Upload vertex data to GPU - + model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); - + return model; } @@ -723,11 +723,11 @@ Model LoadModelFromRES(const char *rresName, int resId) Model LoadHeightmap(Image heightmap, Vector3 size) { Model model = { 0 }; - + model.mesh = GenMeshHeightmap(heightmap, size); - + rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - + model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -738,11 +738,11 @@ Model LoadHeightmap(Image heightmap, Vector3 size) Model LoadCubicmap(Image cubicmap) { Model model = { 0 }; - + model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0f, 1.5f, 1.0f }); - + rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - + model.transform = MatrixIdentity(); model.material = LoadDefaultMaterial(); @@ -755,7 +755,7 @@ void UnloadModel(Model model) rlglUnloadMesh(&model.mesh); UnloadMaterial(model.material); - + TraceLog(INFO, "Unloaded model data from RAM and VRAM"); } @@ -763,10 +763,10 @@ void UnloadModel(Model model) Material LoadMaterial(const char *fileName) { Material material = { 0 }; - + if (strcmp(GetExtension(fileName), "mtl") == 0) material = LoadMTL(fileName); else TraceLog(WARNING, "[%s] Material extension not recognized, it can't be loaded", fileName); - + return material; } @@ -774,7 +774,7 @@ Material LoadMaterial(const char *fileName) Material LoadDefaultMaterial(void) { Material material = { 0 }; - + material.shader = GetDefaultShader(); material.texDiffuse = GetDefaultTexture(); // White texture (1x1 pixel) //material.texNormal; // NOTE: By default, not set @@ -783,9 +783,9 @@ Material LoadDefaultMaterial(void) material.colDiffuse = WHITE; // Diffuse color material.colAmbient = WHITE; // Ambient color material.colSpecular = WHITE; // Specular color - + material.glossiness = 100.0f; // Glossiness level - + return material; } @@ -794,7 +794,7 @@ Material LoadDefaultMaterial(void) Material LoadStandardMaterial(void) { Material material = LoadDefaultMaterial(); - + material.shader = GetStandardShader(); return material; @@ -812,12 +812,12 @@ void UnloadMaterial(Material material) static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) - + Mesh mesh = { 0 }; int mapX = heightmap.width; int mapZ = heightmap.height; - + Color *pixels = GetImageData(heightmap); // NOTE: One vertex per pixel @@ -908,7 +908,7 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) trisCounter += 2; } } - + free(pixels); return mesh; @@ -919,7 +919,7 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) Mesh mesh = { 0 }; Color *cubicmapPixels = GetImageData(cubicmap); - + int mapWidth = cubicmap.width; int mapHeight = cubicmap.height; @@ -1262,9 +1262,9 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) free(mapVertices); free(mapNormals); free(mapTexcoords); - + free(cubicmapPixels); // Free image pixel data - + return mesh; } @@ -1273,7 +1273,7 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint) { Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - + DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint); } @@ -1285,13 +1285,13 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); - + // Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform) //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates - + model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); model.material.colDiffuse = tint; // TODO: Multiply tint color by diffuse color? - + rlglDrawMesh(model.mesh, model.material, model.transform); } @@ -1299,9 +1299,9 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota void DrawModelWires(Model model, Vector3 position, float scale, Color tint) { rlEnableWireMode(); - + DrawModel(model, position, scale, tint); - + rlDisableWireMode(); } @@ -1309,9 +1309,9 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color tint) void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint) { rlEnableWireMode(); - + DrawModelEx(model, position, rotationAxis, rotationAngle, scale, tint); - + rlDisableWireMode(); } @@ -1319,7 +1319,7 @@ void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint) { Rectangle sourceRec = { 0, 0, texture.width, texture.height }; - + DrawBillboardRec(camera, texture, sourceRec, center, size, tint); } @@ -1334,7 +1334,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec Vector3 right = { viewMatrix.m0, viewMatrix.m4, viewMatrix.m8 }; //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; - + // NOTE: Billboard locked on axis-Y Vector3 up = { 0.0f, 1.0f, 0.0f }; /* @@ -1384,13 +1384,13 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec void DrawBoundingBox(BoundingBox box, Color color) { Vector3 size; - + size.x = fabsf(box.max.x - box.min.x); size.y = fabsf(box.max.y - box.min.y); size.z = fabsf(box.max.z - box.min.z); - + Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f }; - + DrawCubeWires(center, size.x, size.y, size.z, color); } @@ -1451,14 +1451,14 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radius bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius) { bool collision = false; - + Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); float distance = VectorLength(raySpherePos); float vector = VectorDotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); - + if (d >= 0.0f) collision = true; - + return collision; } @@ -1466,29 +1466,29 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint) { bool collision = false; - + Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); float distance = VectorLength(raySpherePos); float vector = VectorDotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); - + if (d >= 0.0f) collision = true; - + // Calculate collision point Vector3 offset = ray.direction; float collisionDistance = 0; - + // Check if ray origin is inside the sphere to calculate the correct collision point if (distance < sphereRadius) collisionDistance = vector + sqrt(d); else collisionDistance = vector - sqrt(d); - + VectorScale(&offset, collisionDistance); Vector3 cPoint = VectorAdd(ray.position, offset); - + collisionPoint->x = cPoint.x; collisionPoint->y = cPoint.y; collisionPoint->z = cPoint.z; - + return collision; } @@ -1496,7 +1496,7 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi bool CheckCollisionRayBox(Ray ray, BoundingBox box) { bool collision = false; - + float t[8]; t[0] = (box.min.x - ray.position.x)/ray.direction.x; t[1] = (box.max.x - ray.position.x)/ray.direction.x; @@ -1506,9 +1506,9 @@ bool CheckCollisionRayBox(Ray ray, BoundingBox box) t[5] = (box.max.z - ray.position.z)/ray.direction.z; t[6] = fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); t[7] = fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); - + collision = !(t[7] < 0 || t[6] > t[7]); - + return collision; } @@ -1524,19 +1524,19 @@ BoundingBox CalculateBoundingBox(Mesh mesh) { minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; - + for (int i = 1; i < mesh.vertexCount; i++) { minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); } } - + // Create the bounding box BoundingBox box; box.min = minVertex; box.max = maxVertex; - + return box; } @@ -1546,9 +1546,9 @@ BoundingBox CalculateBoundingBox(Mesh mesh) Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius) { #define CUBIC_MAP_HALF_BLOCK_SIZE 0.5 - + Color *cubicmapPixels = GetImageData(cubicmap); - + // Detect the cell where the player is located Vector3 impactDirection = { 0.0f, 0.0f, 0.0f }; @@ -1784,7 +1784,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p playerPosition->y = (1.5f - radius) - 0.01f; impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z}; } - + free(cubicmapPixels); return impactDirection; @@ -2049,9 +2049,9 @@ static Mesh LoadOBJ(const char *fileName) static Material LoadMTL(const char *fileName) { #define MAX_BUFFER_SIZE 128 - + Material material = { 0 }; // LoadDefaultMaterial(); - + char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; char *mapFileName = NULL; @@ -2069,14 +2069,14 @@ static Material LoadMTL(const char *fileName) while (!feof(mtlFile)) { fgets(buffer, MAX_BUFFER_SIZE, mtlFile); - + switch (buffer[0]) { case 'n': // newmtl string Material name. Begins a new material description. { // TODO: Support multiple materials in a single .mtl sscanf(buffer, "newmtl %s", mapFileName); - + TraceLog(INFO, "[%s] Loading material...", mapFileName); } case 'i': // illum int Illumination model @@ -2123,7 +2123,7 @@ static Material LoadMTL(const char *fileName) { int shininess = 0; sscanf(buffer, "Ns %i", &shininess); - + material.glossiness = (float)shininess; } else if (buffer[1] == 'i') // Ni int Refraction index. @@ -2192,7 +2192,7 @@ static Material LoadMTL(const char *fileName) float ialpha = 0.0f; sscanf(buffer, "Tr %f", &ialpha); material.colDiffuse.a = (unsigned char)((1.0f - ialpha)*255); - + } break; case 'r': // refl string Reflection texture map default: break; @@ -2203,6 +2203,6 @@ static Material LoadMTL(const char *fileName) // NOTE: At this point we have all material data TraceLog(INFO, "[%s] Material loaded successfully", fileName); - + return material; } diff --git a/src/raylib.h b/src/raylib.h index 22494aec..7b7348c8 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -930,8 +930,8 @@ RLAPI void SetMusicPitch(Music music, float pitch); // Set pit RLAPI float GetMusicTimeLength(Music music); // Get music time length (in seconds) RLAPI float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) -RLAPI AudioStream InitAudioStream(unsigned int sampleRate, - unsigned int sampleSize, +RLAPI AudioStream InitAudioStream(unsigned int sampleRate, + unsigned int sampleSize, unsigned int channels); // Init audio stream (to stream audio pcm data) RLAPI void UpdateAudioStream(AudioStream stream, void *data, int numSamples); // Update audio stream buffers with data RLAPI void CloseAudioStream(AudioStream stream); // Close audio stream and free memory diff --git a/src/rlgl.h b/src/rlgl.h index bcb7c24f..3fc54219 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -107,7 +107,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; // byte type typedef unsigned char byte; - + // Color type, RGBA (32bit) typedef struct Color { unsigned char r; @@ -117,7 +117,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; } Color; // Texture formats (support depends on OpenGL version) - typedef enum { + typedef enum { UNCOMPRESSED_GRAYSCALE = 1, // 8 bit per pixel (no alpha) UNCOMPRESSED_GRAY_ALPHA, UNCOMPRESSED_R5G6B5, // 16 bpp @@ -157,7 +157,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; // Shader type (generic shader) typedef struct Shader { unsigned int id; // Shader program id - + // Vertex attributes locations (default locations) int vertexLoc; // Vertex attribute location point (default-location = 0) int texcoordLoc; // Texcoord attribute location point (default-location = 1) @@ -169,7 +169,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; // Uniform locations int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) - + // Texture map locations (generic for any kind of map) int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) @@ -185,14 +185,14 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; int mipmaps; // Mipmap levels, 1 by default int format; // Data format (TextureFormat) } Texture2D; - + // RenderTexture2D type, for texture rendering typedef struct RenderTexture2D { unsigned int id; // Render texture (fbo) id Texture2D texture; // Color buffer attachment texture Texture2D depth; // Depth buffer attachment texture } RenderTexture2D; - + // Material type typedef struct Material { Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) @@ -204,10 +204,10 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; Color colDiffuse; // Diffuse color Color colAmbient; // Ambient color Color colSpecular; // Specular color - + float glossiness; // Glossiness level (Ranges from 0 to 1000) } Material; - + // Camera type, defines a camera position/orientation in 3d space typedef struct Camera { Vector3 position; // Camera position @@ -225,22 +225,22 @@ typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; Vector3 position; // Light position Vector3 target; // Light target: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) float radius; // Light attenuation radius light intensity reduced with distance (world distance) - + Color diffuse; // Light diffuse color float intensity; // Light intensity level - + float coneAngle; // Light cone max angle: LIGHT_SPOT } LightData, *Light; - + // Light types typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; // Color blending modes (pre-defined) typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; - + // TraceLog message types typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; - + // VR Head Mounted Display devices typedef enum { HMD_DEFAULT_DEVICE = 0, diff --git a/src/rlua.h b/src/rlua.h index b100b06d..1c8c7b38 100644 --- a/src/rlua.h +++ b/src/rlua.h @@ -6,7 +6,7 @@ * The following types: * Color, Vector2, Vector3, Rectangle, Ray, Camera, Camera2D * are treated as objects with named fields, same as in C. -* +* * Lua defines utility functions for creating those objects. * Usage: * local cl = Color(255,255,255,255) @@ -27,7 +27,7 @@ * NOTE 02: * Some raylib functions take a pointer to an array, and the size of that array. * The equivalent Lua functions take only an array table of the specified type UNLESS -* it's a pointer to a large char array (e.g. for images), then it takes (and potentially returns) +* it's a pointer to a large char array (e.g. for images), then it takes (and potentially returns) * a Lua string (without the size argument, as Lua strings are sized by default). * * NOTE 03: @@ -362,7 +362,7 @@ static void LuaBuildOpaqueMetatables(void) lua_pushcfunction(L, &LuaIndexTexture2D); lua_setfield(L, -2, "__index"); lua_pop(L, 1); - + luaL_newmetatable(L, "RenderTexture2D"); lua_pushcfunction(L, &LuaIndexRenderTexture2D); lua_setfield(L, -2, "__index"); @@ -3112,7 +3112,7 @@ int lua_TraceLog(lua_State* L) lua_getfield(L, 1, "format"); /// fmt, args..., [string], format() lua_rotate(L, 1, 2); /// [string], format(), fmt, args... lua_call(L, num_args, 1); /// [string], formatted_string - + TraceLog(arg1, "%s", luaL_checkstring(L,-1)); return 0; } @@ -3525,7 +3525,7 @@ int lua_QuaternionTransform(lua_State* L) // raylib Functions (and data types) list static luaL_Reg raylib_functions[] = { - + // Register non-opaque data types REG(Color) REG(Vector2) @@ -3547,7 +3547,7 @@ static luaL_Reg raylib_functions[] = { REG(ToggleFullscreen) REG(GetScreenWidth) REG(GetScreenHeight) - + REG(ShowCursor) REG(HideCursor) REG(IsCursorHidden) @@ -3563,11 +3563,11 @@ static luaL_Reg raylib_functions[] = { REG(End3dMode) REG(BeginTextureMode) REG(EndTextureMode) - + REG(GetMouseRay) REG(GetWorldToScreen) REG(GetCameraMatrix) - + #if defined(PLATFORM_WEB) REG(SetDrawingLoop) #else @@ -3575,7 +3575,7 @@ static luaL_Reg raylib_functions[] = { #endif REG(GetFPS) REG(GetFrameTime) - + REG(GetColor) REG(GetHexValue) REG(ColorToFloat) @@ -3585,13 +3585,13 @@ static luaL_Reg raylib_functions[] = { REG(Fade) REG(SetConfigFlags) REG(ShowLogo) - + REG(IsFileDropped) REG(GetDroppedFiles) REG(ClearDroppedFiles) REG(StorageSaveValue) REG(StorageLoadValue) - + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) REG(IsKeyPressed) REG(IsKeyDown) @@ -3599,7 +3599,7 @@ static luaL_Reg raylib_functions[] = { REG(IsKeyUp) REG(GetKeyPressed) REG(SetExitKey) - + REG(IsGamepadAvailable) REG(GetGamepadAxisMovement) REG(IsGamepadButtonPressed) @@ -3643,13 +3643,13 @@ static luaL_Reg raylib_functions[] = { REG(SetCameraPosition) REG(SetCameraTarget) REG(SetCameraFovy) - + REG(SetCameraPanControl) REG(SetCameraAltControl) REG(SetCameraSmoothZoomControl) REG(SetCameraMoveControls) REG(SetCameraMouseSensitivity) - + REG(DrawPixel) REG(DrawPixelV) REG(DrawLine) @@ -3668,7 +3668,7 @@ static luaL_Reg raylib_functions[] = { REG(DrawPoly) REG(DrawPolyEx) REG(DrawPolyExLines) - + REG(CheckCollisionRecs) REG(CheckCollisionCircles) REG(CheckCollisionCircleRec) @@ -3676,7 +3676,7 @@ static luaL_Reg raylib_functions[] = { REG(CheckCollisionPointRec) REG(CheckCollisionPointCircle) REG(CheckCollisionPointTriangle) - + REG(LoadImage) REG(LoadImageEx) REG(LoadImageRaw) @@ -3712,13 +3712,13 @@ static luaL_Reg raylib_functions[] = { REG(ImageColorBrightness) REG(GenTextureMipmaps) REG(UpdateTexture) - + REG(DrawTexture) REG(DrawTextureV) REG(DrawTextureEx) REG(DrawTextureRec) REG(DrawTexturePro) - + REG(GetDefaultFont) REG(LoadSpriteFont) REG(UnloadSpriteFont) @@ -3727,7 +3727,7 @@ static luaL_Reg raylib_functions[] = { REG(MeasureText) REG(MeasureTextEx) REG(DrawFPS) - + REG(DrawLine3D) REG(DrawCircle3D) REG(DrawCube) @@ -3744,7 +3744,7 @@ static luaL_Reg raylib_functions[] = { REG(DrawGrid) REG(DrawGizmo) REG(DrawLight) - + REG(LoadModel) REG(LoadModelEx) REG(LoadModelFromRES) @@ -3756,7 +3756,7 @@ static luaL_Reg raylib_functions[] = { REG(LoadStandardMaterial) REG(UnloadMaterial) //REG(GenMesh*) // Not ready yet... - + REG(DrawModel) REG(DrawModelEx) REG(DrawModelWires) @@ -3771,7 +3771,7 @@ static luaL_Reg raylib_functions[] = { REG(CheckCollisionRaySphereEx) REG(CheckCollisionRayBox) REG(ResolveCollisionCubicmap) - + REG(LoadShader) REG(UnloadShader) REG(GetDefaultShader) @@ -3789,13 +3789,13 @@ static luaL_Reg raylib_functions[] = { REG(EndBlendMode) REG(CreateLight) REG(DestroyLight) - + REG(InitVrDevice) REG(CloseVrDevice) REG(IsVrDeviceReady) REG(UpdateVrTracking) REG(ToggleVrMode) - + REG(InitAudioDevice) REG(CloseAudioDevice) REG(IsAudioDeviceReady) @@ -3810,7 +3810,7 @@ static luaL_Reg raylib_functions[] = { REG(IsSoundPlaying) REG(SetSoundVolume) REG(SetSoundPitch) - + REG(LoadMusicStream) REG(UnloadMusicStream) REG(UpdateMusicStream) @@ -3823,7 +3823,7 @@ static luaL_Reg raylib_functions[] = { REG(SetMusicPitch) REG(GetMusicTimeLength) REG(GetMusicTimePlayed) - + REG(InitAudioStream) REG(UpdateAudioStream) REG(CloseAudioStream) @@ -3906,7 +3906,7 @@ RLUADEF void InitLuaDevice(void) { mainLuaState = luaL_newstate(); L = mainLuaState; - + LuaStartEnum(); LuaSetEnum("FULLSCREEN_MODE", 1); LuaSetEnum("SHOW_LOGO", 2); @@ -4001,7 +4001,7 @@ RLUADEF void InitLuaDevice(void) LuaSetEnum("PS3_BUTTON_L2", 8); LuaSetEnum("PS3_BUTTON_SELECT", 9); LuaSetEnum("PS3_BUTTON_START", 10); - + LuaSetEnum("XBOX_BUTTON_A", 0); LuaSetEnum("XBOX_BUTTON_B", 1); LuaSetEnum("XBOX_BUTTON_X", 2); @@ -4086,9 +4086,9 @@ RLUADEF void InitLuaDevice(void) LuaSetEnum("ADDITIVE", BLEND_ADDITIVE); LuaSetEnum("MULTIPLIED", BLEND_MULTIPLIED); LuaEndEnum("BlendMode"); - + LuaStartEnum(); - LuaSetEnum("POINT", LIGHT_POINT); + LuaSetEnum("POINT", LIGHT_POINT); LuaSetEnum("DIRECTIONAL", LIGHT_DIRECTIONAL); LuaSetEnum("SPOT", LIGHT_SPOT); LuaEndEnum("LightType"); @@ -4114,7 +4114,7 @@ RLUADEF void InitLuaDevice(void) LuaSetEnum("FIRST_PERSON", CAMERA_FIRST_PERSON); LuaSetEnum("THIRD_PERSON", CAMERA_THIRD_PERSON); LuaEndEnum("CameraMode"); - + LuaStartEnum(); LuaSetEnum("DEFAULT_DEVICE", HMD_DEFAULT_DEVICE); LuaSetEnum("OCULUS_RIFT_DK2", HMD_OCULUS_RIFT_DK2); @@ -4138,9 +4138,9 @@ RLUADEF void InitLuaDevice(void) lua_pushboolean(L, true); #if defined(PLATFORM_DESKTOP) lua_setglobal(L, "PLATFORM_DESKTOP"); -#elif defined(PLATFORM_ANDROID) +#elif defined(PLATFORM_ANDROID) lua_setglobal(L, "PLATFORM_ANDROID"); -#elif defined(PLATFORM_RPI) +#elif defined(PLATFORM_RPI) lua_setglobal(L, "PLATFORM_RPI"); #elif defined(PLATFORM_WEB) lua_setglobal(L, "PLATFORM_WEB"); @@ -4148,7 +4148,7 @@ RLUADEF void InitLuaDevice(void) luaL_openlibs(L); LuaBuildOpaqueMetatables(); - + LuaRegisterRayLib(0); } @@ -4173,7 +4173,7 @@ RLUADEF void ExecuteLuaCode(const char *code) } int result = luaL_dostring(L, code); - + switch (result) { case LUA_OK: break; @@ -4193,7 +4193,7 @@ RLUADEF void ExecuteLuaFile(const char *filename) } int result = luaL_dofile(L, filename); - + switch (result) { case LUA_OK: break; diff --git a/src/text.c b/src/text.c index 2f347b5d..8dc55455 100644 --- a/src/text.c +++ b/src/text.c @@ -151,7 +151,7 @@ extern void LoadDefaultFont(void) //---------------------------------------------------------------------- int imWidth = 128; int imHeight = 128; - + Color *imagePixels = (Color *)malloc(imWidth*imHeight*sizeof(Color)); for (int i = 0; i < imWidth*imHeight; i++) imagePixels[i] = BLANK; // Initialize array @@ -174,7 +174,7 @@ extern void LoadDefaultFont(void) //FILE *myimage = fopen("default_font.raw", "wb"); //fwrite(image.pixels, 1, 128*128*4, myimage); //fclose(myimage); - + Image image = LoadImageEx(imagePixels, imWidth, imHeight); ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA); @@ -185,13 +185,13 @@ extern void LoadDefaultFont(void) // Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars //------------------------------------------------------------------------------ - defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int)); + defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int)); defaultFont.charRecs = (Rectangle *)malloc(defaultFont.numChars*sizeof(Rectangle)); // Allocate space for our character rectangle data // This memory should be freed at end! --> Done on CloseWindow() - + defaultFont.charOffsets = (Vector2 *)malloc(defaultFont.numChars*sizeof(Vector2)); defaultFont.charAdvanceX = (int *)malloc(defaultFont.numChars*sizeof(int)); - + int currentLine = 0; int currentPosX = charsDivisor; int testPosX = charsDivisor; @@ -199,7 +199,7 @@ extern void LoadDefaultFont(void) for (int i = 0; i < defaultFont.numChars; i++) { defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32 - + defaultFont.charRecs[i].x = currentPosX; defaultFont.charRecs[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor); defaultFont.charRecs[i].width = charsWidth[i]; @@ -217,12 +217,12 @@ extern void LoadDefaultFont(void) defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor); } else currentPosX = testPosX; - + // NOTE: On default font character offsets and xAdvance are not required defaultFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; defaultFont.charAdvanceX[i] = 0; } - + defaultFont.size = defaultFont.charRecs[0].height; TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); @@ -262,7 +262,7 @@ SpriteFont LoadSpriteFont(const char *fileName) if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, FONT_FIRST_CHAR); UnloadImage(image); } - + if (spriteFont.texture.id == 0) { TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); @@ -316,15 +316,15 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float scaleFactor = fontSize/spriteFont.size; - // NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly + // NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly // written in C code files (codified by default as UTF-8) - + for(int i = 0; i < length; i++) { // TODO: Right now we are supposing characters that follow a continous order and start at FONT_FIRST_CHAR, // this sytem can be improved to support any characters order and init value... // An intermediate table could be created to link char values with predefined char position index in chars rectangle array - + if ((unsigned char)text[i] == 0xc2) // UTF-8 encoding identification HACK! { // Support UTF-8 encoded values from [0xc2 0x80] -> [0xc2 0xbf](¿) @@ -353,8 +353,8 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float if (rec.x > 0) { - DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor, - position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor, + DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor, + position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor, rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint); if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] == 0) textOffsetX += (rec.width*scaleFactor + spacing); @@ -381,15 +381,15 @@ const char *SubText(const char *text, int position, int length) { static char buffer[MAX_SUBTEXT_LENGTH]; int textLength = strlen(text); - + if (position >= textLength) { position = textLength - 1; length = 0; } - + if (length >= textLength) length = textLength; - + for (int c = 0 ; c < length ; c++) { *(buffer+c) = *(text+position); @@ -421,17 +421,17 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int int len = strlen(text); int tempLen = 0; // Used to count longer text line num chars int lenCounter = 0; - + int textWidth = 0; int tempTextWidth = 0; // Used to count longer text line width - + int textHeight = spriteFont.size; float scaleFactor; for (int i = 0; i < len; i++) { lenCounter++; - + if (text[i] != '\n') { if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] != 0) textWidth += spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]; @@ -444,10 +444,10 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int textWidth = 0; textHeight += (spriteFont.size + spriteFont.size/2); // NOTE: Fixed line spacing of 1.5 lines } - + if (tempLen < lenCounter) tempLen = lenCounter; } - + if (tempTextWidth < textWidth) tempTextWidth = textWidth; if (fontSize <= spriteFont.size) scaleFactor = 1.0f; @@ -496,21 +496,21 @@ void DrawFPS(int posX, int posY) static SpriteFont LoadImageFont(Image image, Color key, int firstChar) { #define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a)) - + int charSpacing = 0; int lineSpacing = 0; int x = 0; int y = 0; - + // Default number of characters expected supported #define MAX_FONTCHARS 128 - // We allocate a temporal arrays for chars data measures, + // We allocate a temporal arrays for chars data measures, // once we get the actual number of chars, we copy data to a sized arrays int tempCharValues[MAX_FONTCHARS]; Rectangle tempCharRecs[MAX_FONTCHARS]; - + Color *pixels = GetImageData(image); // Parse image data to get charSpacing and lineSpacing @@ -545,7 +545,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) !COLOR_EQUAL((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead]), key)) { tempCharValues[index] = firstChar + index; - + tempCharRecs[index].x = xPosToRead; tempCharRecs[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing); tempCharRecs[index].height = charHeight; @@ -564,14 +564,14 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) lineToRead++; xPosToRead = charSpacing; } - + free(pixels); - + TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); - + // Create spritefont with all data parsed from image SpriteFont spriteFont = { 0 }; - + spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture spriteFont.numChars = index; @@ -586,12 +586,12 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) { spriteFont.charValues[i] = tempCharValues[i]; spriteFont.charRecs[i] = tempCharRecs[i]; - + // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; spriteFont.charAdvanceX[i] = 0; } - + spriteFont.size = spriteFont.charRecs[0].height; return spriteFont; @@ -631,7 +631,7 @@ static SpriteFont LoadRBMF(const char *fileName) if (rbmfFile == NULL) { TraceLog(WARNING, "[%s] rBMF font file could not be opened, using default font", fileName); - + spriteFont = GetDefaultFont(); } else @@ -670,10 +670,10 @@ static SpriteFont LoadRBMF(const char *fileName) counter++; } - + Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight); ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA); - + free(imagePixels); TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName); @@ -685,7 +685,7 @@ static SpriteFont LoadRBMF(const char *fileName) //TraceLog(INFO, "[%s] Starting chars set reconstruction", fileName); // Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars - spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int)); + spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int)); spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle)); spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2)); spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int)); @@ -697,12 +697,12 @@ static SpriteFont LoadRBMF(const char *fileName) for (int i = 0; i < spriteFont.numChars; i++) { spriteFont.charValues[i] = (int)rbmfHeader.firstChar + i; - + spriteFont.charRecs[i].x = currentPosX; spriteFont.charRecs[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor); spriteFont.charRecs[i].width = (int)rbmfCharWidthData[i]; spriteFont.charRecs[i].height = (int)rbmfHeader.charHeight; - + // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; spriteFont.charAdvanceX[i] = 0; @@ -720,7 +720,7 @@ static SpriteFont LoadRBMF(const char *fileName) } else currentPosX = testPosX; } - + spriteFont.size = spriteFont.charRecs[0].height; TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName); @@ -738,20 +738,20 @@ static SpriteFont LoadRBMF(const char *fileName) static SpriteFont LoadBMFont(const char *fileName) { #define MAX_BUFFER_SIZE 256 - + SpriteFont font = { 0 }; font.texture.id = 0; - + char buffer[MAX_BUFFER_SIZE]; char *searchPoint = NULL; - + int fontSize = 0; int texWidth, texHeight; char texFileName[128]; int numChars = 0; int base; // Useless data - + FILE *fntFile; fntFile = fopen(fileName, "rt"); @@ -766,42 +766,42 @@ static SpriteFont LoadBMFont(const char *fileName) fgets(buffer, MAX_BUFFER_SIZE, fntFile); //searchPoint = strstr(buffer, "size"); //sscanf(searchPoint, "size=%i", &fontSize); - + fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "lineHeight"); sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight); - + TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize); TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight); - + fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "file"); sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName); - + TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName); - + fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "count"); sscanf(searchPoint, "count=%i", &numChars); - + TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, numChars); - + // Compose correct path using route of .fnt file (fileName) and texFileName char *texPath = NULL; char *lastSlash = NULL; lastSlash = strrchr(fileName, '/'); - + // NOTE: We need some extra space to avoid memory corruption on next allocations! texPath = malloc(strlen(fileName) - strlen(lastSlash) + strlen(texFileName) + 4); - + // NOTE: strcat() and strncat() required a '\0' terminated string to work! *texPath = '\0'; strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1); strncat(texPath, texFileName, strlen(texFileName)); TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); - + font.texture = LoadTexture(texPath); font.size = fontSize; font.numChars = numChars; @@ -809,35 +809,35 @@ static SpriteFont LoadBMFont(const char *fileName) font.charRecs = (Rectangle *)malloc(numChars*sizeof(Rectangle)); font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2)); font.charAdvanceX = (int *)malloc(numChars*sizeof(int)); - + free(texPath); - + int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; - + bool unorderedChars = false; int firstChar = 0; - + for (int i = 0; i < numChars; i++) { fgets(buffer, MAX_BUFFER_SIZE, fntFile); - sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", + sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX); - + if (i == 0) firstChar = charId; else if (i != (charId - firstChar)) unorderedChars = true; - + // Save data properly in sprite font font.charValues[i] = charId; font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight }; font.charOffsets[i] = (Vector2){ (float)charOffsetX, (float)charOffsetY }; font.charAdvanceX[i] = charAdvanceX; } - + fclose(fntFile); - + if (firstChar != FONT_FIRST_CHAR) TraceLog(WARNING, "BMFont not supported: expected SPACE(32) as first character, falling back to default font"); else if (unorderedChars) TraceLog(WARNING, "BMFont not supported: unordered chars data, falling back to default font"); - + // NOTE: Font data could be not ordered by charId: 32,33,34,35... raylib does not support unordered BMFonts if ((firstChar != FONT_FIRST_CHAR) || (unorderedChars) || (font.texture.id == 0)) { @@ -862,9 +862,9 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int stbtt_bakedchar *charData = (stbtt_bakedchar *)malloc(sizeof(stbtt_bakedchar)*numChars); SpriteFont font = { 0 }; - + FILE *ttfFile = fopen(fileName, "rb"); - + if (ttfFile == NULL) { TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); @@ -877,11 +877,11 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int stbtt_BakeFontBitmap(ttfBuffer,0, fontSize, dataBitmap, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, firstChar, numChars, charData); free(ttfBuffer); - + // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA unsigned char *dataGrayAlpha = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)*2); // Two channels int k = 0; - + for (int i = 0; i < FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT; i++) { dataGrayAlpha[k] = 255; @@ -889,9 +889,9 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int k += 2; } - + free(dataBitmap); - + // Sprite font generation from TTF extracted data Image image; image.width = FONT_TEXTURE_WIDTH; @@ -909,7 +909,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int font.charRecs = (Rectangle *)malloc(font.numChars*sizeof(Rectangle)); font.charOffsets = (Vector2 *)malloc(font.numChars*sizeof(Vector2)); font.charAdvanceX = (int *)malloc(font.numChars*sizeof(int)); - + for (int i = 0; i < font.numChars; i++) { font.charValues[i] = i + firstChar; @@ -918,11 +918,11 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int firstChar, int font.charRecs[i].y = (int)charData[i].y0; font.charRecs[i].width = (int)charData[i].x1 - (int)charData[i].x0; font.charRecs[i].height = (int)charData[i].y1 - (int)charData[i].y0; - + font.charOffsets[i] = (Vector2){ charData[i].xoff, charData[i].yoff }; font.charAdvanceX[i] = (int)charData[i].xadvance; } - + free(charData); return font; diff --git a/src/textures.c b/src/textures.c index c6b7e0bb..8f4fa301 100644 --- a/src/textures.c +++ b/src/textures.c @@ -33,7 +33,7 @@ #include // Required for: strcmp(), strrchr(), strncmp() #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 - // Required: rlglLoadTexture() rlDeleteTextures(), + // Required: rlglLoadTexture() rlDeleteTextures(), // rlglGenerateMipmaps(), some funcs for DrawTexturePro() #include "utils.h" // rRES data decompression utility function @@ -44,7 +44,7 @@ // NOTE: Used to read image data (multiple formats support) #define STB_IMAGE_RESIZE_IMPLEMENTATION -#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() +#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() // NOTE: Used for image scaling on ImageResize() //---------------------------------------------------------------------------------- @@ -103,14 +103,14 @@ Image LoadImage(const char *fileName) int imgWidth = 0; int imgHeight = 0; int imgBpp = 0; - + // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...) image.data = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 0); image.width = imgWidth; image.height = imgHeight; image.mipmaps = 1; - + if (imgBpp == 1) image.format = UNCOMPRESSED_GRAYSCALE; else if (imgBpp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA; else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8; @@ -121,12 +121,12 @@ Image LoadImage(const char *fileName) else if (strcmp(GetExtension(fileName),"ktx") == 0) image = LoadKTX(fileName); else if (strcmp(GetExtension(fileName),"pvr") == 0) image = LoadPVR(fileName); else if (strcmp(GetExtension(fileName),"astc") == 0) image = LoadASTC(fileName); - + if (image.data != NULL) - { + { TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); } - else TraceLog(WARNING, "[%s] Image could not be loaded, file not recognized", fileName); + else TraceLog(WARNING, "[%s] Image could not be loaded, file not recognized", fileName); return image; } @@ -141,11 +141,11 @@ Image LoadImageEx(Color *pixels, int width, int height) image.height = height; image.mipmaps = 1; image.format = UNCOMPRESSED_R8G8B8A8; - + int k = 0; image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char)); - + for (int i = 0; i < image.width*image.height*4; i += 4) { ((unsigned char *)image.data)[i] = pixels[k].r; @@ -180,7 +180,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET); unsigned int size = width*height; - + switch (format) { case UNCOMPRESSED_GRAYSCALE: image.data = (unsigned char *)malloc(size); break; // 8 bit per pixel (no alpha) @@ -192,16 +192,16 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int case UNCOMPRESSED_R8G8B8A8: image.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp default: TraceLog(WARNING, "Image format not suported"); break; } - + fread(image.data, size, 1, rawFile); - + // TODO: Check if data have been read - + image.width = width; image.height = height; image.mipmaps = 0; image.format = format; - + fclose(rawFile); } @@ -326,9 +326,9 @@ Texture2D LoadTexture(const char *fileName) Texture2D texture; Image image = LoadImage(fileName); - + if (image.data != NULL) - { + { texture = LoadTextureFromImage(image); UnloadImage(image); } @@ -350,9 +350,9 @@ Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat) texture.height = height; texture.mipmaps = 1; texture.format = textureFormat; - + texture.id = rlglLoadTexture(data, width, height, textureFormat, 1); - + return texture; } @@ -380,7 +380,7 @@ Texture2D LoadTextureFromImage(Image image) texture.height = 0; texture.mipmaps = 0; texture.format = 0; - + texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); texture.width = image.width; @@ -395,7 +395,7 @@ Texture2D LoadTextureFromImage(Image image) RenderTexture2D LoadRenderTexture(int width, int height) { RenderTexture2D target = rlglLoadRenderTexture(width, height); - + return target; } @@ -403,7 +403,7 @@ RenderTexture2D LoadRenderTexture(int width, int height) void UnloadImage(Image image) { free(image.data); - + // NOTE: It becomes anoying every time a texture is loaded //TraceLog(INFO, "Unloaded image data"); } @@ -414,7 +414,7 @@ void UnloadTexture(Texture2D texture) if (texture.id != 0) { rlDeleteTextures(texture.id); - + TraceLog(INFO, "[TEX ID %i] Unloaded texture data from VRAM (GPU)", texture.id); } } @@ -429,7 +429,7 @@ void UnloadRenderTexture(RenderTexture2D target) Color *GetImageData(Image image) { Color *pixels = (Color *)malloc(image.width*image.height*sizeof(Color)); - + int k = 0; for (int i = 0; i < image.width*image.height; i++) @@ -442,7 +442,7 @@ Color *GetImageData(Image image) pixels[i].g = ((unsigned char *)image.data)[k]; pixels[i].b = ((unsigned char *)image.data)[k]; pixels[i].a = 255; - + k++; } break; case UNCOMPRESSED_GRAY_ALPHA: @@ -451,7 +451,7 @@ Color *GetImageData(Image image) pixels[i].g = ((unsigned char *)image.data)[k]; pixels[i].b = ((unsigned char *)image.data)[k]; pixels[i].a = ((unsigned char *)image.data)[k + 1]; - + k += 2; } break; case UNCOMPRESSED_R5G5B5A1: @@ -462,7 +462,7 @@ Color *GetImageData(Image image) pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111000000) >> 6)*(255/31)); pixels[i].b = (unsigned char)((float)((pixel & 0b0000000000111110) >> 1)*(255/31)); pixels[i].a = (unsigned char)((pixel & 0b0000000000000001)*255); - + k++; } break; case UNCOMPRESSED_R5G6B5: @@ -473,18 +473,18 @@ Color *GetImageData(Image image) pixels[i].g = (unsigned char)((float)((pixel & 0b0000011111100000) >> 5)*(255/63)); pixels[i].b = (unsigned char)((float)(pixel & 0b0000000000011111)*(255/31)); pixels[i].a = 255; - + k++; } break; case UNCOMPRESSED_R4G4B4A4: { unsigned short pixel = ((unsigned short *)image.data)[k]; - + pixels[i].r = (unsigned char)((float)((pixel & 0b1111000000000000) >> 12)*(255/15)); pixels[i].g = (unsigned char)((float)((pixel & 0b0000111100000000) >> 8)*(255/15)); pixels[i].b = (unsigned char)((float)((pixel & 0b0000000011110000) >> 4)*(255/15)); pixels[i].a = (unsigned char)((float)(pixel & 0b0000000000001111)*(255/15)); - + k++; } break; case UNCOMPRESSED_R8G8B8A8: @@ -493,7 +493,7 @@ Color *GetImageData(Image image) pixels[i].g = ((unsigned char *)image.data)[k + 1]; pixels[i].b = ((unsigned char *)image.data)[k + 2]; pixels[i].a = ((unsigned char *)image.data)[k + 3]; - + k += 4; } break; case UNCOMPRESSED_R8G8B8: @@ -502,11 +502,11 @@ Color *GetImageData(Image image) pixels[i].g = (unsigned char)((unsigned char *)image.data)[k + 1]; pixels[i].b = (unsigned char)((unsigned char *)image.data)[k + 2]; pixels[i].a = 255; - + k += 3; } break; default: TraceLog(WARNING, "Format not supported for pixel data retrieval"); break; - } + } } return pixels; @@ -522,7 +522,7 @@ Image GetTextureData(Texture2D texture) if (texture.format < 8) { image.data = rlglReadTexturePixels(texture); - + if (image.data != NULL) { image.width = texture.width; @@ -551,29 +551,29 @@ void ImageFormat(Image *image, int newFormat) if ((image->format < 8) && (newFormat < 8)) { Color *pixels = GetImageData(*image); - + free(image->data); - + image->format = newFormat; int k = 0; - + switch (image->format) { case UNCOMPRESSED_GRAYSCALE: { image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char)); - + for (int i = 0; i < image->width*image->height; i++) { ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[i].r*0.299f + (float)pixels[i].g*0.587f + (float)pixels[i].b*0.114f); } - + } break; case UNCOMPRESSED_GRAY_ALPHA: { image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char)); - + for (int i = 0; i < image->width*image->height*2; i += 2) { ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); @@ -585,17 +585,17 @@ void ImageFormat(Image *image, int newFormat) case UNCOMPRESSED_R5G6B5: { image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - + unsigned char r = 0; unsigned char g = 0; unsigned char b = 0; - + for (int i = 0; i < image->width*image->height; i++) { r = (unsigned char)(round((float)pixels[k].r*31/255)); g = (unsigned char)(round((float)pixels[k].g*63/255)); b = (unsigned char)(round((float)pixels[k].b*31/255)); - + ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b; } @@ -603,7 +603,7 @@ void ImageFormat(Image *image, int newFormat) case UNCOMPRESSED_R8G8B8: { image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char)); - + for (int i = 0; i < image->width*image->height*3; i += 3) { ((unsigned char *)image->data)[i] = pixels[k].r; @@ -615,49 +615,49 @@ void ImageFormat(Image *image, int newFormat) case UNCOMPRESSED_R5G5B5A1: { #define ALPHA_THRESHOLD 50 - + image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - + unsigned char r = 0; unsigned char g = 0; unsigned char b = 0; unsigned char a = 0; - + for (int i = 0; i < image->width*image->height; i++) { r = (unsigned char)(round((float)pixels[i].r*31/255)); g = (unsigned char)(round((float)pixels[i].g*31/255)); b = (unsigned char)(round((float)pixels[i].b*31/255)); a = (pixels[i].a > ALPHA_THRESHOLD) ? 1 : 0; - + ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a; } - + } break; case UNCOMPRESSED_R4G4B4A4: { image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - + unsigned char r = 0; unsigned char g = 0; unsigned char b = 0; unsigned char a = 0; - + for (int i = 0; i < image->width*image->height; i++) { r = (unsigned char)(round((float)pixels[i].r*15/255)); g = (unsigned char)(round((float)pixels[i].g*15/255)); b = (unsigned char)(round((float)pixels[i].b*15/255)); a = (unsigned char)(round((float)pixels[i].a*15/255)); - + ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a; } - + } break; case UNCOMPRESSED_R8G8B8A8: { image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char)); - + for (int i = 0; i < image->width*image->height*4; i += 4) { ((unsigned char *)image->data)[i] = pixels[k].r; @@ -669,7 +669,7 @@ void ImageFormat(Image *image, int newFormat) } break; default: break; } - + free(pixels); } else TraceLog(WARNING, "Image data format is compressed, can not be converted"); @@ -677,7 +677,7 @@ void ImageFormat(Image *image, int newFormat) } // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) -// NOTE: In case selected bpp do not represent an known 16bit format, +// NOTE: In case selected bpp do not represent an known 16bit format, // dithered data is stored in the LSB part of the unsigned short void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) { @@ -694,14 +694,14 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) else { Color *pixels = GetImageData(*image); - + free(image->data); // free old image data - + if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8)) { TraceLog(WARNING, "Image format is already 16bpp or lower, dithering could have no effect"); } - + // Define new image format, check if desired bpp match internal known format if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = UNCOMPRESSED_R5G6B5; else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = UNCOMPRESSED_R5G5B5A1; @@ -714,13 +714,13 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) // NOTE: We will store the dithered data as unsigned short (16bpp) image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - + Color oldpixel = WHITE; Color newpixel = WHITE; - + int error_r, error_g, error_b; unsigned short pixel_r, pixel_g, pixel_b, pixel_a; // Used for 16bit pixel composition - + #define MIN(a,b) (((a)<(b))?(a):(b)) for (int y = 0; y < image->height; y++) @@ -728,7 +728,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) for (int x = 0; x < image->width; x++) { oldpixel = pixels[y*image->width + x]; - + // NOTE: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat()) newpixel.r = oldpixel.r>>(8 - rBpp); // R bits newpixel.g = oldpixel.g>>(8 - gBpp); // G bits @@ -740,7 +740,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) error_r = (int)oldpixel.r - (int)(newpixel.r<<(8 - rBpp)); error_g = (int)oldpixel.g - (int)(newpixel.g<<(8 - gBpp)); error_b = (int)oldpixel.b - (int)(newpixel.b<<(8 - bBpp)); - + pixels[y*image->width + x] = newpixel; // NOTE: Some cases are out of the array and should be ignored @@ -750,21 +750,21 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)error_g*7.0f/16), 0xff); pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)error_b*7.0f/16), 0xff); } - + if ((x > 0) && (y < (image->height - 1))) { pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)error_r*3.0f/16), 0xff); pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)error_g*3.0f/16), 0xff); pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)error_b*3.0f/16), 0xff); } - + if (y < (image->height - 1)) { pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)error_r*5.0f/16), 0xff); pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)error_g*5.0f/16), 0xff); pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)error_b*5.0f/16), 0xff); } - + if ((x < (image->width - 1)) && (y < (image->height - 1))) { pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)error_r*1.0f/16), 0xff); @@ -776,7 +776,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) pixel_g = (unsigned short)newpixel.g; pixel_b = (unsigned short)newpixel.b; pixel_a = (unsigned short)newpixel.a; - + ((unsigned short *)image->data)[y*image->width + x] = (pixel_r<<(gBpp + bBpp + aBpp)) | (pixel_g<<(bBpp + aBpp)) | (pixel_b<width); int potHeight = GetNextPOT(image->height); @@ -816,13 +816,13 @@ void ImageToPOT(Image *image, Color fillColor) free(pixels); // Free pixels data free(image->data); // Free old image data - + int format = image->format; // Store image data format to reconvert later - + // TODO: Image width and height changes... do we want to store new values or keep the old ones? // NOTE: Issues when using image.width and image.height for sprite animations... *image = LoadImageEx(pixelsPOT, potWidth, potHeight); - + free(pixelsPOT); // Free POT pixels data ImageFormat(image, format); // Reconvert image to previous format @@ -833,9 +833,9 @@ void ImageToPOT(Image *image, Color fillColor) Image ImageCopy(Image image) { Image newImage; - + int size = image.width*image.height; - + switch (image.format) { case UNCOMPRESSED_GRAYSCALE: newImage.data = (unsigned char *)malloc(size); break; // 8 bit per pixel (no alpha) @@ -847,24 +847,24 @@ Image ImageCopy(Image image) case UNCOMPRESSED_R8G8B8A8: newImage.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp default: TraceLog(WARNING, "Image format not suported for copy"); break; } - + if (newImage.data != NULL) { // NOTE: Size must be provided in bytes memcpy(newImage.data, image.data, size); - + newImage.width = image.width; newImage.height = image.height; newImage.mipmaps = image.mipmaps; newImage.format = image.format; } - + return newImage; } // Crop an image to area defined by a rectangle // NOTE: Security checks are performed in case rectangle goes out of bounds -void ImageCrop(Image *image, Rectangle crop) +void ImageCrop(Image *image, Rectangle crop) { // Security checks to make sure cropping rectangle is inside margins if ((crop.x + crop.width) > image->width) @@ -872,13 +872,13 @@ void ImageCrop(Image *image, Rectangle crop) crop.width = image->width - crop.x; TraceLog(WARNING, "Crop rectangle width out of bounds, rescaled crop width: %i", crop.width); } - + if ((crop.y + crop.height) > image->height) { crop.height = image->height - crop.y; TraceLog(WARNING, "Crop rectangle height out of bounds, rescaled crop height: %i", crop.height); } - + if ((crop.x < image->width) && (crop.y < image->height)) { // Start the cropping process @@ -903,7 +903,7 @@ void ImageCrop(Image *image, Rectangle crop) free(cropPixels); - // Reformat 32bit RGBA image to original format + // Reformat 32bit RGBA image to original format ImageFormat(image, format); } else @@ -916,7 +916,7 @@ void ImageCrop(Image *image, Rectangle crop) // NOTE: Uses stb default scaling filters (both bicubic): // STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM // STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL (high-quality Catmull-Rom) -void ImageResize(Image *image, int newWidth, int newHeight) +void ImageResize(Image *image, int newWidth, int newHeight) { // Get data as Color pixels array to work with it Color *pixels = GetImageData(*image); @@ -930,81 +930,81 @@ void ImageResize(Image *image, int newWidth, int newHeight) UnloadImage(*image); *image = LoadImageEx(output, newWidth, newHeight); - ImageFormat(image, format); // Reformat 32bit RGBA image to original format - + ImageFormat(image, format); // Reformat 32bit RGBA image to original format + free(output); free(pixels); } // Resize and image to new size using Nearest-Neighbor scaling algorithm -void ImageResizeNN(Image *image,int newWidth,int newHeight) +void ImageResizeNN(Image *image,int newWidth,int newHeight) { Color *pixels = GetImageData(*image); Color *output = (Color *)malloc(newWidth*newHeight*sizeof(Color)); - + // EDIT: added +1 to account for an early rounding problem int x_ratio = (int)((image->width<<16)/newWidth) + 1; int y_ratio = (int)((image->height<<16)/newHeight) + 1; - + int x2, y2; - for (int i = 0; i < newHeight; i++) + for (int i = 0; i < newHeight; i++) { - for (int j = 0; j < newWidth; j++) + for (int j = 0; j < newWidth; j++) { x2 = ((j*x_ratio) >> 16); y2 = ((i*y_ratio) >> 16); - + output[(i*newWidth) + j] = pixels[(y2*image->width) + x2] ; - } - } + } + } int format = image->format; UnloadImage(*image); *image = LoadImageEx(output, newWidth, newHeight); - ImageFormat(image, format); // Reformat 32bit RGBA image to original format - + ImageFormat(image, format); // Reformat 32bit RGBA image to original format + free(output); free(pixels); } // Draw an image (source) within an image (destination) -void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) +void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) { // Security checks to avoid size and rectangle issues (out of bounds) // Check that srcRec is inside src image if (srcRec.x < 0) srcRec.x = 0; if (srcRec.y < 0) srcRec.y = 0; - + if ((srcRec.x + srcRec.width) > src.width) { srcRec.width = src.width - srcRec.x; TraceLog(WARNING, "Source rectangle width out of bounds, rescaled width: %i", srcRec.width); } - + if ((srcRec.y + srcRec.height) > src.height) { srcRec.height = src.height - srcRec.y; TraceLog(WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); } - + // Check that dstRec is inside dst image if (dstRec.x < 0) dstRec.x = 0; if (dstRec.y < 0) dstRec.y = 0; - + if ((dstRec.x + dstRec.width) > dst->width) { dstRec.width = dst->width - dstRec.x; TraceLog(WARNING, "Destination rectangle width out of bounds, rescaled width: %i", dstRec.width); } - + if ((dstRec.y + dstRec.height) > dst->height) { dstRec.height = dst->height - dstRec.y; TraceLog(WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); } - + // Get dstination image data as Color pixels array to work with it Color *dstPixels = GetImageData(*dst); @@ -1012,14 +1012,14 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) ImageCrop(&srcCopy, srcRec); // Crop source image to desired source rectangle // Scale source image in case destination rec size is different than source rec size - if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) + if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) { ImageResize(&srcCopy, dstRec.width, dstRec.height); } // Get source image data as Color array Color *srcPixels = GetImageData(srcCopy); - + UnloadImage(srcCopy); // Blit pixels, copy source image into destination @@ -1030,7 +1030,7 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) dstPixels[j*dst->width + i] = srcPixels[(j - dstRec.y)*dstRec.width + (i - dstRec.x)]; } } - + UnloadImage(*dst); // NOTE: Only dst->data is unloaded *dst = LoadImageEx(dstPixels, dst->width, dst->height); @@ -1046,9 +1046,9 @@ Image ImageText(const char *text, int fontSize, Color color) int defaultFontSize = 10; // Default Font chars height in pixel if (fontSize < defaultFontSize) fontSize = defaultFontSize; int spacing = fontSize / defaultFontSize; - + Image imText = ImageTextEx(GetDefaultFont(), text, fontSize, spacing, color); - + return imText; } @@ -1062,19 +1062,19 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing // NOTE: GetTextureData() not available in OpenGL ES Image imFont = GetTextureData(font.texture); - + ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Required for color tint ImageColorTint(&imFont, tint); // Apply color tint to font Color *fontPixels = GetImageData(imFont); - + // Create image to store text Color *pixels = (Color *)malloc(sizeof(Color)*(int)imSize.x*(int)imSize.y); - + for (int i = 0; i < length; i++) { Rectangle letterRec = font.charRecs[(int)text[i] - 32]; - + for (int y = letterRec.y; y < (letterRec.y + letterRec.height); y++) { for (int x = posX; x < (posX + letterRec.width); x++) @@ -1082,28 +1082,28 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing pixels[(y - letterRec.y)*(int)imSize.x + x] = fontPixels[y*font.texture.width + (x - posX + letterRec.x)]; } } - + posX += letterRec.width + spacing; } - + UnloadImage(imFont); - + Image imText = LoadImageEx(pixels, (int)imSize.x, (int)imSize.y); - + // Scale image depending on text size if (fontSize > imSize.y) { float scaleFactor = fontSize/imSize.y; TraceLog(INFO, "Scalefactor: %f", scaleFactor); - + // Using nearest-neighbor scaling algorithm for default font if (font.texture.id == GetDefaultFont().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); else ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); } - + free(pixels); free(fontPixels); - + return imText; } @@ -1117,12 +1117,12 @@ void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, float fontSize, int spacing, Color color) { Image imText = ImageTextEx(font, text, fontSize, spacing, color); - + Rectangle srcRec = { 0, 0, imText.width, imText.height }; Rectangle dstRec = { (int)position.x, (int)position.y, imText.width, imText.height }; - + ImageDraw(dst, imText, srcRec, dstRec); - + UnloadImage(imText); } @@ -1131,7 +1131,7 @@ void ImageFlipVertical(Image *image) { Color *srcPixels = GetImageData(*image); Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height); - + for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) @@ -1139,14 +1139,14 @@ void ImageFlipVertical(Image *image) dstPixels[y*image->width + x] = srcPixels[(image->height - 1 - y)*image->width + x]; } } - + Image processed = LoadImageEx(dstPixels, image->width, image->height); ImageFormat(&processed, image->format); UnloadImage(*image); - + free(srcPixels); free(dstPixels); - + image->data = processed.data; } @@ -1155,7 +1155,7 @@ void ImageFlipHorizontal(Image *image) { Color *srcPixels = GetImageData(*image); Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height); - + for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) @@ -1163,14 +1163,14 @@ void ImageFlipHorizontal(Image *image) dstPixels[y*image->width + x] = srcPixels[y*image->width + (image->width - 1 - x)]; } } - + Image processed = LoadImageEx(dstPixels, image->width, image->height); ImageFormat(&processed, image->format); UnloadImage(*image); - + free(srcPixels); free(dstPixels); - + image->data = processed.data; } @@ -1178,12 +1178,12 @@ void ImageFlipHorizontal(Image *image) void ImageColorTint(Image *image, Color color) { Color *pixels = GetImageData(*image); - + float cR = (float)color.r/255; float cG = (float)color.g/255; float cB = (float)color.b/255; float cA = (float)color.a/255; - + for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) @@ -1204,7 +1204,7 @@ void ImageColorTint(Image *image, Color color) ImageFormat(&processed, image->format); UnloadImage(*image); free(pixels); - + image->data = processed.data; } @@ -1212,7 +1212,7 @@ void ImageColorTint(Image *image, Color color) void ImageColorInvert(Image *image) { Color *pixels = GetImageData(*image); - + for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) @@ -1222,12 +1222,12 @@ void ImageColorInvert(Image *image) pixels[y*image->width + x].b = 255 - pixels[y*image->width + x].b; } } - + Image processed = LoadImageEx(pixels, image->width, image->height); ImageFormat(&processed, image->format); UnloadImage(*image); free(pixels); - + image->data = processed.data; } @@ -1243,12 +1243,12 @@ void ImageColorContrast(Image *image, float contrast) { if (contrast < -100) contrast = -100; if (contrast > 100) contrast = 100; - + contrast = (100.0 + contrast)/100.0; contrast *= contrast; - + Color *pixels = GetImageData(*image); - + for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) @@ -1287,7 +1287,7 @@ void ImageColorContrast(Image *image, float contrast) ImageFormat(&processed, image->format); UnloadImage(*image); free(pixels); - + image->data = processed.data; } @@ -1297,9 +1297,9 @@ void ImageColorBrightness(Image *image, int brightness) { if (brightness < -255) brightness = -255; if (brightness > 255) brightness = 255; - + Color *pixels = GetImageData(*image); - + for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) @@ -1316,7 +1316,7 @@ void ImageColorBrightness(Image *image, int brightness) if (cB < 0) cB = 1; if (cB > 255) cB = 255; - + pixels[y*image->width + x].r = (unsigned char)cR; pixels[y*image->width + x].g = (unsigned char)cG; pixels[y*image->width + x].b = (unsigned char)cB; @@ -1327,7 +1327,7 @@ void ImageColorBrightness(Image *image, int brightness) ImageFormat(&processed, image->format); UnloadImage(*image); free(pixels); - + image->data = processed.data; } @@ -1396,7 +1396,7 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V { if (sourceRec.width < 0) sourceRec.x -= sourceRec.width; if (sourceRec.height < 0) sourceRec.y -= sourceRec.height; - + rlEnableTexture(texture.id); rlPushMatrix(); @@ -1439,13 +1439,13 @@ static Image LoadDDS(const char *fileName) { // Required extension: // GL_EXT_texture_compression_s3tc - + // Supported tokens (defined by extensions) // GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 - + #define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII #define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII #define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII @@ -1508,7 +1508,7 @@ static Image LoadDDS(const char *fileName) else { ddsHeader header; - + // Get the image header fread(&header, sizeof(ddsHeader), 1, ddsFile); @@ -1537,9 +1537,9 @@ static Image LoadDDS(const char *fileName) { image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short)); fread(image.data, image.width*image.height*sizeof(unsigned short), 1, ddsFile); - + unsigned char alpha = 0; - + // NOTE: Data comes as A1R5G5B5, it must be reordered to R5G5B5A1 for (int i = 0; i < image.width*image.height; i++) { @@ -1554,9 +1554,9 @@ static Image LoadDDS(const char *fileName) { image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short)); fread(image.data, image.width*image.height*sizeof(unsigned short), 1, ddsFile); - + unsigned char alpha = 0; - + // NOTE: Data comes as A4R4G4B4, it must be reordered R4G4B4A4 for (int i = 0; i < image.width*image.height; i++) { @@ -1564,7 +1564,7 @@ static Image LoadDDS(const char *fileName) ((unsigned short *)image.data)[i] = ((unsigned short *)image.data)[i] << 4; ((unsigned short *)image.data)[i] += alpha; } - + image.format = UNCOMPRESSED_R4G4B4A4; } } @@ -1574,14 +1574,14 @@ static Image LoadDDS(const char *fileName) // NOTE: not sure if this case exists... image.data = (unsigned char *)malloc(image.width*image.height*3*sizeof(unsigned char)); fread(image.data, image.width*image.height*3, 1, ddsFile); - + image.format = UNCOMPRESSED_R8G8B8; } else if (header.ddspf.flags == 0x41 && header.ddspf.rgbBitCount == 32) // DDS_RGBA, no compressed { image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char)); fread(image.data, image.width*image.height*4, 1, ddsFile); - + unsigned char blue = 0; // NOTE: Data comes as A8R8G8B8, it must be reordered R8G8B8A8 (view next comment) @@ -1593,7 +1593,7 @@ static Image LoadDDS(const char *fileName) ((unsigned char *)image.data)[i] = ((unsigned char *)image.data)[i + 2]; ((unsigned char *)image.data)[i + 2] = blue; } - + image.format = UNCOMPRESSED_R8G8B8A8; } else if (((header.ddspf.flags == 0x04) || (header.ddspf.flags == 0x05)) && (header.ddspf.fourCC > 0)) // Compressed @@ -1603,7 +1603,7 @@ static Image LoadDDS(const char *fileName) // Calculate data size, including all mipmaps if (header.mipmapCount > 1) bufsize = header.pitchOrLinearSize*2; else bufsize = header.pitchOrLinearSize; - + TraceLog(DEBUG, "Pitch or linear size: %i", header.pitchOrLinearSize); image.data = (unsigned char*)malloc(bufsize*sizeof(unsigned char)); @@ -1625,7 +1625,7 @@ static Image LoadDDS(const char *fileName) } } } - + fclose(ddsFile); // Close file pointer } @@ -1640,9 +1640,9 @@ static Image LoadPKM(const char *fileName) // Required extensions: // GL_OES_compressed_ETC1_RGB8_texture (ETC1) (OpenGL ES 2.0) // GL_ARB_ES3_compatibility (ETC2/EAC) (OpenGL ES 3.0) - + // Supported tokens (defined by extensions) - // GL_ETC1_RGB8_OES 0x8D64 + // GL_ETC1_RGB8_OES 0x8D64 // GL_COMPRESSED_RGB8_ETC2 0x9274 // GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 @@ -1656,7 +1656,7 @@ static Image LoadPKM(const char *fileName) unsigned short origWidth; // Original width (big-endian) unsigned short origHeight; // Original height (big-endian) } pkmHeader; - + // Formats list // version 10: format: 0=ETC1_RGB, [1=ETC1_RGBA, 2=ETC1_RGB_MIP, 3=ETC1_RGBA_MIP] (not used) // version 20: format: 0=ETC1_RGB, 1=ETC2_RGB, 2=ETC2_RGBA_OLD, 3=ETC2_RGBA, 4=ETC2_RGBA1, 5=ETC2_R, 6=ETC2_RG, 7=ETC2_SIGNED_R, 8=ETC2_SIGNED_R @@ -1665,7 +1665,7 @@ static Image LoadPKM(const char *fileName) // NOTE: ETC is always 4bit per pixel (64 bit for each 4x4 block of pixels) Image image; - + image.data = NULL; image.width = 0; image.height = 0; @@ -1695,18 +1695,18 @@ static Image LoadPKM(const char *fileName) header.format = ((header.format & 0x00FF) << 8) | ((header.format & 0xFF00) >> 8); header.width = ((header.width & 0x00FF) << 8) | ((header.width & 0xFF00) >> 8); header.height = ((header.height & 0x00FF) << 8) | ((header.height & 0xFF00) >> 8); - + TraceLog(DEBUG, "PKM (ETC) image width: %i", header.width); TraceLog(DEBUG, "PKM (ETC) image height: %i", header.height); TraceLog(DEBUG, "PKM (ETC) image format: %i", header.format); - + image.width = header.width; image.height = header.height; image.mipmaps = 1; - + int bpp = 4; if (header.format == 3) bpp = 8; - + int size = image.width*image.height*bpp/8; // Total data size in bytes image.data = (unsigned char*)malloc(size * sizeof(unsigned char)); @@ -1717,7 +1717,7 @@ static Image LoadPKM(const char *fileName) else if (header.format == 1) image.format = COMPRESSED_ETC2_RGB; else if (header.format == 3) image.format = COMPRESSED_ETC2_EAC_RGBA; } - + fclose(pkmFile); // Close file pointer } @@ -1730,12 +1730,12 @@ static Image LoadKTX(const char *fileName) // Required extensions: // GL_OES_compressed_ETC1_RGB8_texture (ETC1) // GL_ARB_ES3_compatibility (ETC2/EAC) - + // Supported tokens (defined by extensions) // GL_ETC1_RGB8_OES 0x8D64 // GL_COMPRESSED_RGB8_ETC2 0x9274 // GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 - + // KTX file Header (64 bytes) // https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ typedef struct { @@ -1754,16 +1754,16 @@ static Image LoadKTX(const char *fileName) unsigned int mipmapLevels; // Non-mipmapped textures = 1 unsigned int keyValueDataSize; // Used to encode any arbitrary data... } ktxHeader; - + // NOTE: Before start of every mipmap data block, we have: unsigned int dataSize - + Image image; image.width = 0; image.height = 0; image.mipmaps = 0; image.format = 0; - + FILE *ktxFile = fopen(fileName, "rb"); if (ktxFile == NULL) @@ -1783,22 +1783,22 @@ static Image LoadKTX(const char *fileName) TraceLog(WARNING, "[%s] KTX file does not seem to be a valid file", fileName); } else - { + { image.width = header.width; image.height = header.height; image.mipmaps = header.mipmapLevels; - + TraceLog(DEBUG, "KTX (ETC) image width: %i", header.width); TraceLog(DEBUG, "KTX (ETC) image height: %i", header.height); TraceLog(DEBUG, "KTX (ETC) image format: 0x%x", header.glInternalFormat); - + unsigned char unused; - + if (header.keyValueDataSize > 0) { for (int i = 0; i < header.keyValueDataSize; i++) fread(&unused, 1, 1, ktxFile); } - + int dataSize; fread(&dataSize, sizeof(unsigned int), 1, ktxFile); @@ -1810,10 +1810,10 @@ static Image LoadKTX(const char *fileName) else if (header.glInternalFormat == 0x9274) image.format = COMPRESSED_ETC2_RGB; else if (header.glInternalFormat == 0x9278) image.format = COMPRESSED_ETC2_EAC_RGBA; } - + fclose(ktxFile); // Close file pointer } - + return image; } @@ -1823,11 +1823,11 @@ static Image LoadPVR(const char *fileName) { // Required extension: // GL_IMG_texture_compression_pvrtc - + // Supported tokens (defined by extensions) // GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 // GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 - + #if 0 // Not used... // PVR file v2 Header (52 bytes) typedef struct { @@ -1864,7 +1864,7 @@ static Image LoadPVR(const char *fileName) unsigned int numMipmaps; unsigned int metaDataSize; } pvrHeaderV3; - + #if 0 // Not used... // Metadata (usually 15 bytes) typedef struct { @@ -1872,7 +1872,7 @@ static Image LoadPVR(const char *fileName) unsigned int key; unsigned int dataSize; // Not used? unsigned char *data; // Not used? - } pvrMetadata; + } pvrMetadata; #endif Image image; @@ -1895,15 +1895,15 @@ static Image LoadPVR(const char *fileName) unsigned char pvrVersion = 0; fread(&pvrVersion, sizeof(unsigned char), 1, pvrFile); fseek(pvrFile, 0, SEEK_SET); - + // Load different PVR data formats if (pvrVersion == 0x50) { pvrHeaderV3 header; - + // Get PVR image header fread(&header, sizeof(pvrHeaderV3), 1, pvrFile); - + if ((header.id[0] != 'P') || (header.id[1] != 'V') || (header.id[2] != 'R') || (header.id[3] != 3)) { TraceLog(WARNING, "[%s] PVR file does not seem to be a valid image", fileName); @@ -1913,7 +1913,7 @@ static Image LoadPVR(const char *fileName) image.width = header.width; image.height = header.height; image.mipmaps = header.numMipmaps; - + // Check data format if (((header.channels[0] == 'l') && (header.channels[1] == 0)) && (header.channelDepth[0] == 8)) image.format = UNCOMPRESSED_GRAYSCALE; else if (((header.channels[0] == 'l') && (header.channels[1] == 'a')) && ((header.channelDepth[0] == 8) && (header.channelDepth[1] == 8))) image.format = UNCOMPRESSED_GRAY_ALPHA; @@ -1933,14 +1933,14 @@ static Image LoadPVR(const char *fileName) } else if (header.channels[0] == 2) image.format = COMPRESSED_PVRT_RGB; else if (header.channels[0] == 3) image.format = COMPRESSED_PVRT_RGBA; - + // Skip meta data header unsigned char unused = 0; for (int i = 0; i < header.metaDataSize; i++) fread(&unused, sizeof(unsigned char), 1, pvrFile); - + // Calculate data size (depends on format) int bpp = 0; - + switch (image.format) { case UNCOMPRESSED_GRAYSCALE: bpp = 8; break; @@ -1954,7 +1954,7 @@ static Image LoadPVR(const char *fileName) case COMPRESSED_PVRT_RGBA: bpp = 4; break; default: break; } - + int dataSize = image.width*image.height*bpp/8; // Total data size in bytes image.data = (unsigned char*)malloc(dataSize*sizeof(unsigned char)); @@ -1976,11 +1976,11 @@ static Image LoadASTC(const char *fileName) // Required extensions: // GL_KHR_texture_compression_astc_hdr // GL_KHR_texture_compression_astc_ldr - + // Supported tokens (defined by extensions) // GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93b0 // GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93b7 - + // ASTC file Header (16 bytes) typedef struct { unsigned char id[4]; // Signature: 0x13 0xAB 0xA1 0x5C @@ -1999,7 +1999,7 @@ static Image LoadASTC(const char *fileName) image.height = 0; image.mipmaps = 0; image.format = 0; - + FILE *astcFile = fopen(fileName, "rb"); if (astcFile == NULL) @@ -2012,7 +2012,7 @@ static Image LoadASTC(const char *fileName) // Get ASTC image header fread(&header, sizeof(astcHeader), 1, astcFile); - + if ((header.id[3] != 0x5c) || (header.id[2] != 0xa1) || (header.id[1] != 0xab) || (header.id[0] != 0x13)) { TraceLog(WARNING, "[%s] ASTC file does not seem to be a valid image", fileName); @@ -2022,31 +2022,31 @@ static Image LoadASTC(const char *fileName) // NOTE: Assuming Little Endian (could it be wrong?) image.width = 0x00000000 | ((int)header.width[2] << 16) | ((int)header.width[1] << 8) | ((int)header.width[0]); image.height = 0x00000000 | ((int)header.height[2] << 16) | ((int)header.height[1] << 8) | ((int)header.height[0]); - + // NOTE: ASTC format only contains one mipmap level image.mipmaps = 1; - + TraceLog(DEBUG, "ASTC image width: %i", image.width); TraceLog(DEBUG, "ASTC image height: %i", image.height); TraceLog(DEBUG, "ASTC image blocks: %ix%i", header.blockX, header.blockY); - + // NOTE: Each block is always stored in 128bit so we can calculate the bpp int bpp = 128/(header.blockX*header.blockY); // NOTE: Currently we only support 2 blocks configurations: 4x4 and 8x8 - if ((bpp == 8) || (bpp == 2)) + if ((bpp == 8) || (bpp == 2)) { int dataSize = image.width*image.height*bpp/8; // Data size in bytes - + image.data = (unsigned char *)malloc(dataSize*sizeof(unsigned char)); fread(image.data, dataSize, 1, astcFile); - + if (bpp == 8) image.format = COMPRESSED_ASTC_4x4_RGBA; else if (bpp == 2) image.format = COMPRESSED_ASTC_4x4_RGBA; } else TraceLog(WARNING, "[%s] ASTC block size configuration not supported", fileName); } - + fclose(astcFile); } -- cgit v1.2.3 From d0cf19e03559eb5cd60035d54d4ca7b5991344b8 Mon Sep 17 00:00:00 2001 From: Teodor Stoenescu Date: Wed, 31 Aug 2016 09:24:39 +0300 Subject: Greater LoadOBJ() flexibility LoadOBJ can now load objects with having no texture coordinates or objects having texture coordinates specified as tuples. --- src/models.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 42798483..92b9850e 100644 --- a/src/models.c +++ b/src/models.c @@ -1898,9 +1898,7 @@ static Mesh LoadOBJ(const char *fileName) if (dataType == 't') // Read texCoord { - float useless = 0; - - fscanf(objFile, "%f %f %f", &midTexCoords[countTexCoords].x, &midTexCoords[countTexCoords].y, &useless); + fscanf(objFile, "%f %f%*[^\n]s\n", &midTexCoords[countTexCoords].x, &midTexCoords[countTexCoords].y); countTexCoords++; fscanf(objFile, "%c", &dataType); @@ -1959,6 +1957,7 @@ static Mesh LoadOBJ(const char *fileName) 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 if (numTexCoords == 0) fscanf(objFile, "%i//%i %i//%i %i//%i", &vNum[0], &vnNum[0], &vNum[1], &vnNum[1], &vNum[2], &vnNum[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]); mesh.vertices[vCounter] = midVertices[vNum[0]-1].x; -- cgit v1.2.3 From a9ab516dae83d95a8701160bb7dcc72917e2d2ab Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 31 Aug 2016 10:27:29 +0200 Subject: Formatting tweaks --- src/audio.c | 4 ++-- src/core.c | 2 +- src/models.c | 12 ++++++------ src/text.c | 18 +++++++++--------- src/textures.c | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 3bace5f7..ea14d77d 100644 --- a/src/audio.c +++ b/src/audio.c @@ -1068,7 +1068,7 @@ static void UnloadWave(Wave wave) const char *GetExtension(const char *fileName) { const char *dot = strrchr(fileName, '.'); - if(!dot || dot == fileName) return ""; + if (!dot || dot == fileName) return ""; return (dot + 1); } @@ -1083,7 +1083,7 @@ void TraceLog(int msgType, const char *text, ...) traceDebugMsgs = 0; #endif - switch(msgType) + switch (msgType) { case INFO: fprintf(stdout, "INFO: "); break; case ERROR: fprintf(stdout, "ERROR: "); break; diff --git a/src/core.c b/src/core.c index 81c2942a..b9ffe87b 100644 --- a/src/core.c +++ b/src/core.c @@ -2451,7 +2451,7 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches, event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : ""); - for(int i = 0; i < event->numTouches; ++i) + for (int i = 0; i < event->numTouches; ++i) { const EmscriptenTouchPoint *t = &event->touches[i]; diff --git a/src/models.c b/src/models.c index 55de3d4f..25eb1fe0 100644 --- a/src/models.c +++ b/src/models.c @@ -270,25 +270,25 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Of The Texture and Quad // Back Face - rlNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer + rlNormal3f(0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Left Of The Texture and Quad // Top Face - rlNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up + rlNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad // Bottom Face - rlNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down + rlNormal3f(0.0f,-1.0f, 0.0f); // Normal Pointing Down rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Right Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Left Of The Texture and Quad rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad // Right face - rlNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right + rlNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right Of The Texture and Quad rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left Of The Texture and Quad @@ -1905,14 +1905,14 @@ static Mesh LoadOBJ(const char *fileName) } else if (dataType == 'n') // Read normals { - fscanf(objFile, "%f %f %f", &midNormals[countNormals].x, &midNormals[countNormals].y, &midNormals[countNormals].z ); + fscanf(objFile, "%f %f %f", &midNormals[countNormals].x, &midNormals[countNormals].y, &midNormals[countNormals].z); countNormals++; fscanf(objFile, "%c", &dataType); } else // Read vertex { - fscanf(objFile, "%f %f %f", &midVertices[countVertex].x, &midVertices[countVertex].y, &midVertices[countVertex].z ); + fscanf(objFile, "%f %f %f", &midVertices[countVertex].x, &midVertices[countVertex].y, &midVertices[countVertex].z); countVertex++; fscanf(objFile, "%c", &dataType); diff --git a/src/text.c b/src/text.c index 3d28fc3c..d00f01d7 100644 --- a/src/text.c +++ b/src/text.c @@ -319,7 +319,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float // NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly // written in C code files (codified by default as UTF-8) - for(int i = 0; i < length; i++) + for (int i = 0; i < length; i++) { // TODO: Right now we are supposing characters that follow a continous order and start at FONT_FIRST_CHAR, // this sytem can be improved to support any characters order and init value... @@ -514,9 +514,9 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) Color *pixels = GetImageData(image); // Parse image data to get charSpacing and lineSpacing - for(y = 0; y < image.height; y++) + for (y = 0; y < image.height; y++) { - for(x = 0; x < image.width; x++) + for (x = 0; x < image.width; x++) { if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break; } @@ -529,7 +529,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) int charHeight = 0; int j = 0; - while(!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++; + while (!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++; charHeight = j; @@ -539,9 +539,9 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) int xPosToRead = charSpacing; // Parse image data to get rectangle sizes - while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height) + while ((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height) { - while((xPosToRead < image.width) && + while ((xPosToRead < image.width) && !COLOR_EQUAL((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead]), key)) { tempCharValues[index] = firstChar + index; @@ -552,7 +552,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) int charWidth = 0; - while(!COLOR_EQUAL(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth], key)) charWidth++; + while (!COLOR_EQUAL(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth], key)) charWidth++; tempCharRecs[index].width = charWidth; @@ -648,11 +648,11 @@ static SpriteFont LoadRBMF(const char *fileName) rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int)); - for(int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); + for (int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char)); - for(int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); + for (int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); // Re-construct image from rbmfFileData //----------------------------------------- diff --git a/src/textures.c b/src/textures.c index 8f4fa301..4d9fc6b0 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1612,7 +1612,7 @@ static Image LoadDDS(const char *fileName) image.mipmaps = header.mipmapCount; - switch(header.ddspf.fourCC) + switch (header.ddspf.fourCC) { case FOURCC_DXT1: { -- cgit v1.2.3 From 7f0880a73580c14312e18966d8aae568b7a3f7cb Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 12 Sep 2016 19:36:41 +0200 Subject: Review spacing formatting raylib uses spaces between '+' and '-' signs but not between '*' and '/' signs, it's a chosen convention --- src/audio.c | 2 +- src/core.c | 2 +- src/models.c | 144 ++++++++++++++++++++++++++++++--------------------------- src/rlgl.c | 8 ++-- src/shapes.c | 10 ++-- src/text.c | 20 ++++---- src/textures.c | 4 +- 7 files changed, 99 insertions(+), 91 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index fa18f7c8..06bf55d4 100644 --- a/src/audio.c +++ b/src/audio.c @@ -482,7 +482,7 @@ void PlaySound(Sound sound) //int sampleRate; //alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate); // AL_CHANNELS, AL_BITS (bps) - //float seconds = (float)byteOffset / sampleRate; // Number of seconds since the beginning of the sound + //float seconds = (float)byteOffset/sampleRate; // Number of seconds since the beginning of the sound //or //float result; //alGetSourcef(sound.source, AL_SEC_OFFSET, &result); // AL_SAMPLE_OFFSET diff --git a/src/core.c b/src/core.c index b9ffe87b..d5b07e7a 100644 --- a/src/core.c +++ b/src/core.c @@ -1016,7 +1016,7 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera) QuaternionTransform(&worldPos, matProj); // Calculate normalized device coordinates (inverted y) - Vector3 ndcPos = { worldPos.x / worldPos.w, -worldPos.y / worldPos.w, worldPos.z / worldPos.z }; + Vector3 ndcPos = { worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.z }; // Calculate 2d screen position vector Vector2 screenPosition = { (ndcPos.x + 1.0f)/2.0f*(float)GetScreenWidth(), (ndcPos.y + 1.0f)/2.0f*(float)GetScreenHeight() }; diff --git a/src/models.c b/src/models.c index 25eb1fe0..8195c5f6 100644 --- a/src/models.c +++ b/src/models.c @@ -88,7 +88,7 @@ void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rot rlColor4ub(color.r, color.g, color.b, color.a); rlVertex3f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius, 0.0f); - rlVertex3f(sin(DEG2RAD*(i + 10)) * radius, cos(DEG2RAD*(i + 10)) * radius, 0.0f); + rlVertex3f(sin(DEG2RAD*(i + 10))*radius, cos(DEG2RAD*(i + 10))*radius, 0.0f); } rlEnd(); rlPopMatrix(); @@ -325,25 +325,25 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color { for (int j = 0; j < slices; j++) { - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*(j*360/slices))); + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i))) * sin(DEG2RAD*((j+1)*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*sin(DEG2RAD*((j+1)*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i))) * cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*cos(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); } } rlEnd(); @@ -364,26 +364,26 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col { for (int j = 0; j < slices; j++) { - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*((j+1)*360/slices)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*(j*360/slices))); + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * sin(DEG2RAD*(j*360/slices)), + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1))) * cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)), + cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); + rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i)) * cos(DEG2RAD*(j*360/slices))); + cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); } } rlEnd(); @@ -407,21 +407,21 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h // Draw Body ------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides) { - rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); //Top Right + rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right - rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); //Top Left - rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); //Top Right + rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); //Top Left + rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right } // Draw Cap -------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, height, 0); - rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); + rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); } } else @@ -430,8 +430,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, height, 0); - rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); + rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); } } @@ -439,8 +439,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, 0, 0); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); - rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); } rlEnd(); rlPopMatrix(); @@ -460,17 +460,17 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl for (int i = 0; i < 360; i += 360/sides) { - rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); + rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); - rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusTop, height, cos(DEG2RAD*(i+360/sides)) * radiusTop); - rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); + rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); - rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop); - rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); + rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); + rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); } rlEnd(); rlPopMatrix(); @@ -516,7 +516,7 @@ void DrawRay(Ray ray, Color color) // Draw a grid centered at (0, 0, 0) void DrawGrid(int slices, float spacing) { - int halfSlices = slices / 2; + int halfSlices = slices/2; rlBegin(RL_LINES); for (int i = -halfSlices; i <= halfSlices; i++) @@ -577,22 +577,30 @@ void DrawLight(Light light) { case LIGHT_POINT: { - DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); - DrawCircle3D(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); - DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : BLACK)); - DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : BLACK)); + DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); + + DrawCircle3D(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : GRAY)); } break; case LIGHT_DIRECTIONAL: { - DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); - DrawSphereWires(light->position, 0.3f*light->intensity, 4, 8, (light->enabled ? light->diffuse : BLACK)); - DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); + + DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); } break; case LIGHT_SPOT: { - DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : BLACK)); - DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : BLACK)); - DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : BLACK)); + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); + + Vector3 dir = VectorSubtract(light->target, light->position); + VectorNormalize(&dir); + + DrawCircle3D(light->position, 0.5f, 0.0f, dir, (light->enabled ? light->diffuse : GRAY)); + + //DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); } break; default: break; } @@ -1361,19 +1369,19 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec rlColor4ub(tint.r, tint.g, tint.b, tint.a); // Bottom-left corner for texture and quad - rlTexCoord2f((float)sourceRec.x / texture.width, (float)sourceRec.y / texture.height); + rlTexCoord2f((float)sourceRec.x/texture.width, (float)sourceRec.y/texture.height); rlVertex3f(a.x, a.y, a.z); // Top-left corner for texture and quad - rlTexCoord2f((float)sourceRec.x / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlTexCoord2f((float)sourceRec.x/texture.width, (float)(sourceRec.y + sourceRec.height)/texture.height); rlVertex3f(d.x, d.y, d.z); // Top-right corner for texture and quad - rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)(sourceRec.y + sourceRec.height) / texture.height); + rlTexCoord2f((float)(sourceRec.x + sourceRec.width)/texture.width, (float)(sourceRec.y + sourceRec.height)/texture.height); rlVertex3f(c.x, c.y, c.z); // Bottom-right corner for texture and quad - rlTexCoord2f((float)(sourceRec.x + sourceRec.width) / texture.width, (float)sourceRec.y / texture.height); + rlTexCoord2f((float)(sourceRec.x + sourceRec.width)/texture.width, (float)sourceRec.y/texture.height); rlVertex3f(b.x, b.y, b.z); rlEnd(); @@ -1693,8 +1701,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p else playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius / 3)) + if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius/3) && + ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius/3)) { impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } @@ -1716,8 +1724,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p else playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius / 3)) + if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius/3) && + ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius/3)) { impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } @@ -1739,8 +1747,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p else playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius / 3)) + if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius/3) && + ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius/3)) { impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } @@ -1762,8 +1770,8 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p else playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius / 3)) + if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius/3) && + ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius/3)) { impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } diff --git a/src/rlgl.c b/src/rlgl.c index 518f2a66..244de52c 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -708,7 +708,7 @@ void rlVertex3f(float x, float y, float z) case RL_LINES: { // Verify that MAX_LINES_BATCH limit not reached - if (lines.vCounter / 2 < MAX_LINES_BATCH) + if (lines.vCounter/2 < MAX_LINES_BATCH) { lines.vertices[3*lines.vCounter] = x; lines.vertices[3*lines.vCounter + 1] = y; @@ -722,7 +722,7 @@ void rlVertex3f(float x, float y, float z) case RL_TRIANGLES: { // Verify that MAX_TRIANGLES_BATCH limit not reached - if (triangles.vCounter / 3 < MAX_TRIANGLES_BATCH) + if (triangles.vCounter/3 < MAX_TRIANGLES_BATCH) { triangles.vertices[3*triangles.vCounter] = x; triangles.vertices[3*triangles.vCounter + 1] = y; @@ -736,7 +736,7 @@ void rlVertex3f(float x, float y, float z) case RL_QUADS: { // Verify that MAX_QUADS_BATCH limit not reached - if (quads.vCounter / 4 < MAX_QUADS_BATCH) + if (quads.vCounter/4 < MAX_QUADS_BATCH) { quads.vertices[3*quads.vCounter] = x; quads.vertices[3*quads.vCounter + 1] = y; @@ -3542,7 +3542,7 @@ static void DrawDefaultBuffers(int eyesCount) for (int i = 0; i < drawsCounter; i++) { quadsCount = draws[i].vertexCount/4; - numIndicesToProcess = quadsCount*6; // Get number of Quads * 6 index by Quad + numIndicesToProcess = quadsCount*6; // Get number of Quads*6 index by Quad //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); diff --git a/src/shapes.c b/src/shapes.c index d9b172f1..6200a823 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -113,7 +113,7 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co rlColor4ub(color2.r, color2.g, color2.b, color2.a); rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); rlColor4ub(color2.r, color2.g, color2.b, color2.a); - rlVertex2f(centerX + sin(DEG2RAD*(i + 10)) * radius, centerY + cos(DEG2RAD*(i + 10))*radius); + rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius); } rlEnd(); } @@ -131,7 +131,7 @@ void DrawCircleV(Vector2 center, float radius, Color color) rlVertex2i(center.x, center.y); rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); - rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius); + rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius); } rlEnd(); } @@ -146,8 +146,8 @@ void DrawCircleV(Vector2 center, float radius, Color color) rlVertex2i(center.x, center.y); rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); - rlVertex2f(center.x + sin(DEG2RAD*(i + 10)) * radius, center.y + cos(DEG2RAD*(i + 10)) * radius); - rlVertex2f(center.x + sin(DEG2RAD*(i + 20)) * radius, center.y + cos(DEG2RAD*(i + 20)) * radius); + rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius); + rlVertex2f(center.x + sin(DEG2RAD*(i + 20))*radius, center.y + cos(DEG2RAD*(i + 20))*radius); } rlEnd(); @@ -165,7 +165,7 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color) for (int i = 0; i < 360; i += 10) { rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); - rlVertex2f(centerX + sin(DEG2RAD*(i + 10)) * radius, centerY + cos(DEG2RAD*(i + 10))*radius); + rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius); } rlEnd(); } diff --git a/src/text.c b/src/text.c index d00f01d7..c538ea56 100644 --- a/src/text.c +++ b/src/text.c @@ -201,7 +201,7 @@ extern void LoadDefaultFont(void) defaultFont.charValues[i] = FONT_FIRST_CHAR + i; // First char is 32 defaultFont.charRecs[i].x = currentPosX; - defaultFont.charRecs[i].y = charsDivisor + currentLine * (charsHeight + charsDivisor); + defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor); defaultFont.charRecs[i].width = charsWidth[i]; defaultFont.charRecs[i].height = charsHeight; @@ -297,7 +297,7 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color) int defaultFontSize = 10; // Default Font chars height in pixel if (fontSize < defaultFontSize) fontSize = defaultFontSize; - int spacing = fontSize / defaultFontSize; + int spacing = fontSize/defaultFontSize; DrawTextEx(defaultFont, text, position, (float)fontSize, spacing, color); } @@ -408,7 +408,7 @@ int MeasureText(const char *text, int fontSize) int defaultFontSize = 10; // Default Font chars height in pixel if (fontSize < defaultFontSize) fontSize = defaultFontSize; - int spacing = fontSize / defaultFontSize; + int spacing = fontSize/defaultFontSize; vec = MeasureTextEx(defaultFont, text, fontSize, spacing); @@ -539,7 +539,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) int xPosToRead = charSpacing; // Parse image data to get rectangle sizes - while ((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height) + while ((lineSpacing + lineToRead*(charHeight + lineSpacing)) < image.height) { while ((xPosToRead < image.width) && !COLOR_EQUAL((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead]), key)) @@ -547,7 +547,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) tempCharValues[index] = firstChar + index; tempCharRecs[index].x = xPosToRead; - tempCharRecs[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing); + tempCharRecs[index].y = lineSpacing + lineToRead*(charHeight + lineSpacing); tempCharRecs[index].height = charHeight; int charWidth = 0; @@ -646,11 +646,11 @@ static SpriteFont LoadRBMF(const char *fileName) int numPixelBits = rbmfHeader.imgWidth*rbmfHeader.imgHeight/32; - rbmfFileData = (unsigned int *)malloc(numPixelBits * sizeof(unsigned int)); + rbmfFileData = (unsigned int *)malloc(numPixelBits*sizeof(unsigned int)); for (int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); - rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars * sizeof(unsigned char)); + rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars*sizeof(unsigned char)); for (int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); @@ -701,7 +701,7 @@ static SpriteFont LoadRBMF(const char *fileName) spriteFont.charValues[i] = (int)rbmfHeader.firstChar + i; spriteFont.charRecs[i].x = currentPosX; - spriteFont.charRecs[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor); + spriteFont.charRecs[i].y = charsDivisor + currentLine*((int)rbmfHeader.charHeight + charsDivisor); spriteFont.charRecs[i].width = (int)rbmfCharWidthData[i]; spriteFont.charRecs[i].height = (int)rbmfHeader.charHeight; @@ -714,11 +714,11 @@ static SpriteFont LoadRBMF(const char *fileName) if (testPosX > spriteFont.texture.width) { currentLine++; - currentPosX = 2 * charsDivisor + (int)rbmfCharWidthData[i]; + currentPosX = 2*charsDivisor + (int)rbmfCharWidthData[i]; testPosX = currentPosX; spriteFont.charRecs[i].x = charsDivisor; - spriteFont.charRecs[i].y = charsDivisor + currentLine * (rbmfHeader.charHeight + charsDivisor); + spriteFont.charRecs[i].y = charsDivisor + currentLine*(rbmfHeader.charHeight + charsDivisor); } else currentPosX = testPosX; } diff --git a/src/textures.c b/src/textures.c index 15293371..d4dd2ac2 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1765,7 +1765,7 @@ static Image LoadPKM(const char *fileName) int size = image.width*image.height*bpp/8; // Total data size in bytes - image.data = (unsigned char*)malloc(size * sizeof(unsigned char)); + image.data = (unsigned char*)malloc(size*sizeof(unsigned char)); fread(image.data, 1, size, pkmFile); @@ -1858,7 +1858,7 @@ static Image LoadKTX(const char *fileName) int dataSize; fread(&dataSize, sizeof(unsigned int), 1, ktxFile); - image.data = (unsigned char*)malloc(dataSize * sizeof(unsigned char)); + image.data = (unsigned char*)malloc(dataSize*sizeof(unsigned char)); fread(image.data, 1, dataSize, ktxFile); -- cgit v1.2.3 From b082807b0b90bce07e15098d6d0a17574d100277 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 3 Oct 2016 13:29:01 +0200 Subject: Removed function: ResolveCollisionCubicmap() Function was inefficient and should be rewritten from scratch, it probably neither belongs to this module but an example... --- src/models.c | 250 ----------------------------------------------------------- src/raylib.h | 7 +- 2 files changed, 2 insertions(+), 255 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 8195c5f6..822da6e9 100644 --- a/src/models.c +++ b/src/models.c @@ -1548,256 +1548,6 @@ BoundingBox CalculateBoundingBox(Mesh mesh) return box; } -// Detect and resolve cubicmap collisions -// NOTE: player position (or camera) is modified inside this function -// TODO: This functions needs to be completely reviewed! -Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius) -{ - #define CUBIC_MAP_HALF_BLOCK_SIZE 0.5 - - Color *cubicmapPixels = GetImageData(cubicmap); - - // Detect the cell where the player is located - Vector3 impactDirection = { 0.0f, 0.0f, 0.0f }; - - int locationCellX = 0; - int locationCellY = 0; - - locationCellX = floor(playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE); - locationCellY = floor(playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE); - - if ((locationCellX >= 0) && (locationCellY >= 0) && (locationCellX < cubicmap.width) && (locationCellY < cubicmap.height)) - { - // Multiple Axis -------------------------------------------------------------------------------------------- - - // Axis x-, y- - if ((locationCellX > 0) && (locationCellY > 0)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) && - (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) - { - playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - - // Axis x-, y+ - if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) && - (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) - { - playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - - // Axis x+, y- - if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) && - (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) - { - playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - - // Axis x+, y+ - if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) && - (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) - { - playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - - // Single Axis --------------------------------------------------------------------------------------------------- - - // Axis x- - if (locationCellX > 0) - { - if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r != 0) - { - if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) - { - playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 1.0f, 0.0f, 0.0f }; - } - } - } - // Axis x+ - if (locationCellX < cubicmap.width - 1) - { - if (cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r != 0) - { - if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) - { - playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 1.0f, 0.0f, 0.0f }; - } - } - } - // Axis y- - if (locationCellY > 0) - { - if (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r != 0) - { - if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius) - { - playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 0.0f, 0.0f, 1.0f }; - } - } - } - // Axis y+ - if (locationCellY < cubicmap.height - 1) - { - if (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r != 0) - { - if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius) - { - playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3){ 0.0f, 0.0f, 1.0f }; - } - } - } - - // Diagonals ------------------------------------------------------------------------------------------------------- - - // Axis x-, y- - if ((locationCellX > 0) && (locationCellY > 0)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) && - (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX - 1)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) > ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY)) playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - else playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - - // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius/3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius/3)) - { - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - } - - // Axis x-, y+ - if ((locationCellX > 0) && (locationCellY < cubicmap.height - 1)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX - 1)].r == 0) && - (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX - 1)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) > (1 - ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY))) playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - else playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - - // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius/3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius/3)) - { - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - } - - // Axis x+, y- - if ((locationCellX < cubicmap.width - 1) && (locationCellY > 0)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) && - (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY - 1)*cubicmap.width + (locationCellX + 1)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) < (1 - ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY))) playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - else playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - - // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius/3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius/3)) - { - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - } - - // Axis x+, y+ - if ((locationCellX < cubicmap.width - 1) && (locationCellY < cubicmap.height - 1)) - { - if ((cubicmapPixels[locationCellY*cubicmap.width + (locationCellX + 1)].r == 0) && - (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX)].r == 0) && - (cubicmapPixels[(locationCellY + 1)*cubicmap.width + (locationCellX + 1)].r != 0)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius)) - { - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX) < ((playerPosition->z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY)) playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - else playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - - // Return ricochet - if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius/3) && - ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius/3)) - { - impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; - } - } - } - } - } - - // Floor collision - if (playerPosition->y <= radius) - { - playerPosition->y = radius + 0.01f; - impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z}; - } - // Roof collision - else if (playerPosition->y >= (1.5f - radius)) - { - playerPosition->y = (1.5f - radius) - 0.01f; - impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z}; - } - - free(cubicmapPixels); - - return impactDirection; -} - //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index 35319d6a..d022e8f5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -839,9 +839,7 @@ RLAPI Model LoadHeightmap(Image heightmap, Vector3 size); // Load a RLAPI Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) RLAPI void UnloadModel(Model model); // Unload 3d model from memory -RLAPI Mesh GenMeshCube(float width, float height, float depth); // Generate mesh: cube - -RLAPI Material LoadMaterial(const char *fileName); // Load material data (from file) +RLAPI Material LoadMaterial(const char *fileName); // Load material data (.MTL) RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader) RLAPI Material LoadStandardMaterial(void); // Load standard material (uses material attributes and lighting shader) RLAPI void UnloadMaterial(Material material); // Unload material textures from VRAM @@ -862,8 +860,7 @@ RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float RLAPI bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius); // Detect collision between ray and sphere RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint); // Detect collision between ray and sphere with extended parameters and collision point detection RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box); // Detect collision between ray and box -RLAPI Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Detect collision of player radius with cubicmap - // NOTE: Return the normal vector of the impacted surface + //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 -- cgit v1.2.3 From 8f60996b6482246cb8f66d0ba8f6aa1604e6dd01 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 17 Oct 2016 00:03:38 +0200 Subject: Corrected some warnings --- src/audio.c | 6 +-- src/models.c | 122 ++++++++++++++++++++++++++++----------------------------- src/raylib.h | 2 +- src/rlgl.c | 10 ++--- src/shapes.c | 22 +++++------ src/textures.c | 12 +++--- 6 files changed, 87 insertions(+), 87 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 9d2eeb47..3684e10a 100644 --- a/src/audio.c +++ b/src/audio.c @@ -706,7 +706,7 @@ Music LoadMusicStream(const char *fileName) else { music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels); - music->totalSamples = music->ctxFlac->totalSampleCount; + music->totalSamples = (unsigned int)music->ctxFlac->totalSampleCount; music->samplesLeft = music->totalSamples; music->ctxType = MUSIC_AUDIO_FLAC; music->loop = true; // We loop by default @@ -853,7 +853,7 @@ void UpdateMusicStream(Music music) int pcmi[AUDIO_BUFFER_SIZE]; // NOTE: Returns the number of samples to process (should be the same as numSamples) - int numSamplesFlac = drflac_read_s32(music->ctxFlac, numSamples, pcmi); + unsigned int numSamplesFlac = (unsigned int)drflac_read_s32(music->ctxFlac, numSamples, pcmi); UpdateAudioStream(music->stream, pcmi, numSamplesFlac*music->stream.channels); music->samplesLeft -= (numSamples*music->stream.channels); @@ -1237,7 +1237,7 @@ static Wave LoadOGG(const char *fileName) if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); - int totalSamples = totalSeconds*info.sample_rate*info.channels; + int totalSamples = (int)(totalSeconds*info.sample_rate*info.channels); wave.sampleCount = totalSamples; wave.data = (short *)malloc(totalSamplesLength*sizeof(short)); diff --git a/src/models.c b/src/models.c index 822da6e9..55ac7893 100644 --- a/src/models.c +++ b/src/models.c @@ -87,8 +87,8 @@ void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rot { rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex3f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius, 0.0f); - rlVertex3f(sin(DEG2RAD*(i + 10))*radius, cos(DEG2RAD*(i + 10))*radius, 0.0f); + rlVertex3f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius, 0.0f); + rlVertex3f(sinf(DEG2RAD*(i + 10))*radius, cosf(DEG2RAD*(i + 10))*radius, 0.0f); } rlEnd(); rlPopMatrix(); @@ -325,25 +325,25 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color { for (int j = 0; j < slices; j++) { - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); - - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i)))*cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*i)), + cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices))); + + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*i)), + cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i)))*cosf(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); } } rlEnd(); @@ -364,26 +364,26 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col { for (int j = 0; j < slices; j++) { - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); - - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*((j+1)*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*((j+1)*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); - - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*(i+1))), - cos(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cos(DEG2RAD*(j*360/slices))); - rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i))*sin(DEG2RAD*(j*360/slices)), - sin(DEG2RAD*(270+(180/(rings + 1))*i)), - cos(DEG2RAD*(270+(180/(rings + 1))*i))*cos(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*i)), + cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); + + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*((j+1)*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*((j+1)*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices))); + + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*(i+1))), + cosf(DEG2RAD*(270+(180/(rings + 1))*(i+1)))*cosf(DEG2RAD*(j*360/slices))); + rlVertex3f(cosf(DEG2RAD*(270+(180/(rings + 1))*i))*sinf(DEG2RAD*(j*360/slices)), + sinf(DEG2RAD*(270+(180/(rings + 1))*i)), + cosf(DEG2RAD*(270+(180/(rings + 1))*i))*cosf(DEG2RAD*(j*360/slices))); } } rlEnd(); @@ -407,21 +407,21 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h // Draw Body ------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides) { - rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right + rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); //Bottom Right + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right - rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); //Top Left - rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); //Bottom Left - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); //Top Right + rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); //Top Left + rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); //Bottom Left + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); //Top Right } // Draw Cap -------------------------------------------------------------------------------------- for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, height, 0); - rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); } } else @@ -430,8 +430,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, height, 0); - rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); } } @@ -439,8 +439,8 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h for (int i = 0; i < 360; i += 360/sides) { rlVertex3f(0, 0, 0); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); - rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); } rlEnd(); rlPopMatrix(); @@ -460,17 +460,17 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl for (int i = 0; i < 360; i += 360/sides) { - rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusBottom, 0, cos(DEG2RAD*(i+360/sides))*radiusBottom); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusBottom, 0, cosf(DEG2RAD*(i+360/sides))*radiusBottom); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); - rlVertex3f(sin(DEG2RAD*(i+360/sides))*radiusTop, height, cos(DEG2RAD*(i+360/sides))*radiusTop); - rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); + rlVertex3f(sinf(DEG2RAD*(i+360/sides))*radiusTop, height, cosf(DEG2RAD*(i+360/sides))*radiusTop); + rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); - rlVertex3f(sin(DEG2RAD*i)*radiusTop, height, cos(DEG2RAD*i)*radiusTop); - rlVertex3f(sin(DEG2RAD*i)*radiusBottom, 0, cos(DEG2RAD*i)*radiusBottom); + rlVertex3f(sinf(DEG2RAD*i)*radiusTop, height, cosf(DEG2RAD*i)*radiusTop); + rlVertex3f(sinf(DEG2RAD*i)*radiusBottom, 0, cosf(DEG2RAD*i)*radiusBottom); } rlEnd(); rlPopMatrix(); diff --git a/src/raylib.h b/src/raylib.h index 5834d1c9..1433268b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -93,7 +93,7 @@ // Some basic Defines //---------------------------------------------------------------------------------- #ifndef PI - #define PI 3.14159265358979323846 + #define PI 3.14159265358979323846f #endif #define DEG2RAD (PI/180.0f) diff --git a/src/rlgl.c b/src/rlgl.c index e8607925..a754678c 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2653,7 +2653,7 @@ void InitVrDevice(int vrDevice) hmd.hResolution = 2160; // HMD horizontal resolution in pixels hmd.vResolution = 1200; // HMD vertical resolution in pixels hmd.hScreenSize = 0.133793f; // HMD horizontal size in meters - hmd.vScreenSize = 0.0669; // HMD vertical size in meters + hmd.vScreenSize = 0.0669f; // HMD vertical size in meters hmd.vScreenCenter = 0.04678f; // HMD screen center in meters hmd.eyeToScreenDistance = 0.041f; // HMD distance between eye and display in meters hmd.lensSeparationDistance = 0.07f; // HMD lens separation distance in meters @@ -3786,8 +3786,8 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Compute lens parameters float lensShift = (hmd.hScreenSize*0.25f - hmd.lensSeparationDistance*0.5f)/hmd.hScreenSize; - float leftLensCenter[2] = { 0.25 + lensShift, 0.5f }; - float rightLensCenter[2] = { 0.75 - lensShift, 0.5f }; + float leftLensCenter[2] = { 0.25f + lensShift, 0.5f }; + float rightLensCenter[2] = { 0.75f - lensShift, 0.5f }; float leftScreenCenter[2] = { 0.25f, 0.5f }; float rightScreenCenter[2] = { 0.75f, 0.5f }; @@ -3804,8 +3804,8 @@ static void SetStereoConfig(VrDeviceInfo hmd) float normScreenWidth = 0.5f; float normScreenHeight = 1.0f; - float scaleIn[2] = { 2/normScreenWidth, 2/normScreenHeight/aspect }; - float scale[2] = { normScreenWidth*0.5/distortionScale, normScreenHeight*0.5*aspect/distortionScale }; + float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect }; + float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale }; TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); diff --git a/src/shapes.c b/src/shapes.c index 9fcbeff7..62076b2c 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -71,7 +71,7 @@ void DrawPixelV(Vector2 position, Color color) rlBegin(RL_LINES); rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2f(position.x, position.y); - rlVertex2i(position.x + 1, position.y + 1); + rlVertex2f(position.x + 1.0f, position.y + 1.0f); rlEnd(); } @@ -98,7 +98,7 @@ void DrawLineV(Vector2 startPos, Vector2 endPos, Color color) // Draw a color-filled circle void DrawCircle(int centerX, int centerY, float radius, Color color) { - DrawCircleV((Vector2){ centerX, centerY }, radius, color); + DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color); } // Draw a gradient-filled circle @@ -111,9 +111,9 @@ void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Co rlColor4ub(color1.r, color1.g, color1.b, color1.a); rlVertex2i(centerX, centerY); rlColor4ub(color2.r, color2.g, color2.b, color2.a); - rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); + rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius); rlColor4ub(color2.r, color2.g, color2.b, color2.a); - rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius); + rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius); } rlEnd(); } @@ -130,8 +130,8 @@ void DrawCircleV(Vector2 center, float radius, Color color) rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2f(center.x, center.y); - rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); - rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius); + rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius); + rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius); } rlEnd(); } @@ -145,9 +145,9 @@ void DrawCircleV(Vector2 center, float radius, Color color) rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2f(center.x, center.y); - rlVertex2f(center.x + sin(DEG2RAD*i)*radius, center.y + cos(DEG2RAD*i)*radius); - rlVertex2f(center.x + sin(DEG2RAD*(i + 10))*radius, center.y + cos(DEG2RAD*(i + 10))*radius); - rlVertex2f(center.x + sin(DEG2RAD*(i + 20))*radius, center.y + cos(DEG2RAD*(i + 20))*radius); + rlVertex2f(center.x + sinf(DEG2RAD*i)*radius, center.y + cosf(DEG2RAD*i)*radius); + rlVertex2f(center.x + sinf(DEG2RAD*(i + 10))*radius, center.y + cosf(DEG2RAD*(i + 10))*radius); + rlVertex2f(center.x + sinf(DEG2RAD*(i + 20))*radius, center.y + cosf(DEG2RAD*(i + 20))*radius); } rlEnd(); @@ -164,8 +164,8 @@ void DrawCircleLines(int centerX, int centerY, float radius, Color color) // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360) for (int i = 0; i < 360; i += 10) { - rlVertex2f(centerX + sin(DEG2RAD*i)*radius, centerY + cos(DEG2RAD*i)*radius); - rlVertex2f(centerX + sin(DEG2RAD*(i + 10))*radius, centerY + cos(DEG2RAD*(i + 10))*radius); + rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius); + rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius); } rlEnd(); } diff --git a/src/textures.c b/src/textures.c index fd5bdd80..323c0a8a 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1118,7 +1118,7 @@ Image ImageText(const char *text, int fontSize, Color color) if (fontSize < defaultFontSize) fontSize = defaultFontSize; int spacing = fontSize/defaultFontSize; - Image imText = ImageTextEx(GetDefaultFont(), text, fontSize, spacing, color); + Image imText = ImageTextEx(GetDefaultFont(), text, (float)fontSize, spacing, color); return imText; } @@ -1183,7 +1183,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color) { // NOTE: For default font, sapcing is set to desired font size / default font size (10) - ImageDrawTextEx(dst, position, GetDefaultFont(), text, fontSize, fontSize/10, color); + ImageDrawTextEx(dst, position, GetDefaultFont(), text, (float)fontSize, fontSize/10, color); } // Draw text (custom sprite font) within an image (destination) @@ -1317,7 +1317,7 @@ void ImageColorContrast(Image *image, float contrast) if (contrast < -100) contrast = -100; if (contrast > 100) contrast = 100; - contrast = (100.0 + contrast)/100.0; + contrast = (100.0f + contrast)/100.0f; contrast *= contrast; Color *pixels = GetImageData(*image); @@ -1326,7 +1326,7 @@ void ImageColorContrast(Image *image, float contrast) { for (int x = 0; x < image->width; x++) { - float pR = (float)pixels[y*image->width + x].r/255.0; + float pR = (float)pixels[y*image->width + x].r/255.0f; pR -= 0.5; pR *= contrast; pR += 0.5; @@ -1334,7 +1334,7 @@ void ImageColorContrast(Image *image, float contrast) if (pR < 0) pR = 0; if (pR > 255) pR = 255; - float pG = (float)pixels[y*image->width + x].g/255.0; + float pG = (float)pixels[y*image->width + x].g/255.0f; pG -= 0.5; pG *= contrast; pG += 0.5; @@ -1342,7 +1342,7 @@ void ImageColorContrast(Image *image, float contrast) if (pG < 0) pG = 0; if (pG > 255) pG = 255; - float pB = (float)pixels[y*image->width + x].b/255.0; + float pB = (float)pixels[y*image->width + x].b/255.0f; pB -= 0.5; pB *= contrast; pB += 0.5; -- cgit v1.2.3 From 673dcf94364d37f3d52285ac27c88707ae567872 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 31 Oct 2016 20:39:03 +0100 Subject: Comments tweaks --- src/core.c | 2 +- src/models.c | 2 +- src/rlgl.c | 2 +- src/shapes.c | 15 +++++++-------- src/textures.c | 4 ++-- src/utils.c | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) (limited to 'src/models.c') diff --git a/src/core.c b/src/core.c index 9bb7b8cf..8850eefa 100644 --- a/src/core.c +++ b/src/core.c @@ -22,7 +22,7 @@ * * RL_LOAD_DEFAULT_FONT - Use external module functions to load default raylib font (module: text) * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. diff --git a/src/models.c b/src/models.c index 55ac7893..c0f04387 100644 --- a/src/models.c +++ b/src/models.c @@ -4,7 +4,7 @@ * * Basic functions to draw 3d shapes and load/draw 3d models (.OBJ) * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. diff --git a/src/rlgl.c b/src/rlgl.c index 492ca3a6..e2804e9c 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -35,7 +35,7 @@ #include // Required for: atan2() #ifndef RLGL_STANDALONE - #include "raymath.h" // Required for Vector3 and Matrix functions + #include "raymath.h" // Required for: Vector3 and Matrix functions #endif #if defined(GRAPHICS_API_OPENGL_11) diff --git a/src/shapes.c b/src/shapes.c index 62076b2c..79cf567a 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -4,7 +4,7 @@ * * Basic functions to draw 2d Shapes and check collisions * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -25,9 +25,8 @@ #include "raylib.h" -#include // Required for abs() function -#include // Math related functions, sin() and cos() used on DrawCircle* - // sqrt() and pow() and abs() used on CheckCollision* +#include // Required for: abs() +#include // Required for: sinf(), cosf(), sqrtf() #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 @@ -331,8 +330,8 @@ void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color col rlColor4ub(color.r, color.g, color.b, color.a); rlVertex2f(0, 0); - rlVertex2f(sin(DEG2RAD*i)*radius, cos(DEG2RAD*i)*radius); - rlVertex2f(sin(DEG2RAD*(i + 360/sides))*radius, cos(DEG2RAD*(i + 360/sides))*radius); + rlVertex2f(sinf(DEG2RAD*i)*radius, cosf(DEG2RAD*i)*radius); + rlVertex2f(sinf(DEG2RAD*(i + 360/sides))*radius, cosf(DEG2RAD*(i + 360/sides))*radius); } rlEnd(); rlPopMatrix(); @@ -434,7 +433,7 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa float dx = center2.x - center1.x; // X distance between centers float dy = center2.y - center1.y; // Y distance between centers - float distance = sqrt(dx*dx + dy*dy); // Distance between centers + float distance = sqrtf(dx*dx + dy*dy); // Distance between centers if (distance <= (radius1 + radius2)) collision = true; @@ -457,7 +456,7 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) if (dx <= (rec.width/2)) { return true; } if (dy <= (rec.height/2)) { return true; } - float cornerDistanceSq = pow(dx - rec.width/2, 2) + pow(dy - rec.height/2, 2); + float cornerDistanceSq = (dx - rec.width/2)*(dx - rec.width/2) + (dy - rec.height/2)*(dy - rec.height/2); return (cornerDistanceSq <= (radius*radius)); } diff --git a/src/textures.c b/src/textures.c index 729756a5..5354a74f 100644 --- a/src/textures.c +++ b/src/textures.c @@ -8,7 +8,7 @@ * stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) * NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -1241,7 +1241,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing // NOTE: GetTextureData() not available in OpenGL ES Image imFont = GetTextureData(font.texture); - ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Required for color tint + ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Convert to 32 bit for color tint ImageColorTint(&imFont, tint); // Apply color tint to font Color *fontPixels = GetImageData(imFont); diff --git a/src/utils.c b/src/utils.c index 36b06f0f..b96e2c70 100644 --- a/src/utils.c +++ b/src/utils.c @@ -8,7 +8,7 @@ * tinfl - zlib DEFLATE algorithm decompression lib * stb_image_write - PNG writting functions * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. -- cgit v1.2.3 From f16f39e8aaf0ee95a31600e549c0221d1ce46fdd Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 2 Nov 2016 00:50:08 +0100 Subject: code tweaks to avoid some warnings --- src/models.c | 18 +++++++++--------- src/rlgl.c | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index c0f04387..ad084f05 100644 --- a/src/models.c +++ b/src/models.c @@ -1411,7 +1411,7 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa float dy = centerA.y - centerB.y; // Y distance between centers float dz = centerA.z - centerB.z; // Y distance between centers - float distance = sqrt(dx*dx + dy*dy + dz*dz); // Distance between centers + float distance = sqrtf(dx*dx + dy*dy + dz*dz); // Distance between centers if (distance <= (radiusA + radiusB)) collision = true; @@ -1441,14 +1441,14 @@ bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radius float dmin = 0; - if (centerSphere.x < box.min.x) dmin += pow(centerSphere.x - box.min.x, 2); - else if (centerSphere.x > box.max.x) dmin += pow(centerSphere.x - box.max.x, 2); + if (centerSphere.x < box.min.x) dmin += powf(centerSphere.x - box.min.x, 2); + else if (centerSphere.x > box.max.x) dmin += powf(centerSphere.x - box.max.x, 2); - if (centerSphere.y < box.min.y) dmin += pow(centerSphere.y - box.min.y, 2); - else if (centerSphere.y > box.max.y) dmin += pow(centerSphere.y - box.max.y, 2); + if (centerSphere.y < box.min.y) dmin += powf(centerSphere.y - box.min.y, 2); + else if (centerSphere.y > box.max.y) dmin += powf(centerSphere.y - box.max.y, 2); - if (centerSphere.z < box.min.z) dmin += pow(centerSphere.z - box.min.z, 2); - else if (centerSphere.z > box.max.z) dmin += pow(centerSphere.z - box.max.z, 2); + if (centerSphere.z < box.min.z) dmin += powf(centerSphere.z - box.min.z, 2); + else if (centerSphere.z > box.max.z) dmin += powf(centerSphere.z - box.max.z, 2); if (dmin <= (radiusSphere*radiusSphere)) collision = true; @@ -1487,8 +1487,8 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi float collisionDistance = 0; // Check if ray origin is inside the sphere to calculate the correct collision point - if (distance < sphereRadius) collisionDistance = vector + sqrt(d); - else collisionDistance = vector - sqrt(d); + if (distance < sphereRadius) collisionDistance = vector + sqrtf(d); + else collisionDistance = vector - sqrtf(d); VectorScale(&offset, collisionDistance); Vector3 cPoint = VectorAdd(ray.position, offset); diff --git a/src/rlgl.c b/src/rlgl.c index e2804e9c..d3bba07b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -3882,7 +3882,7 @@ static void SetStereoConfig(VrDeviceInfo hmd) // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG // ...but with lens distortion it is increased (see Oculus SDK Documentation) //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? - float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; + float fovy = 2.0f*(float)atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] -- cgit v1.2.3 From 42452378925e3b1d407a33084cd8cf0495632ee8 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 13 Nov 2016 23:47:28 +0100 Subject: Corrected SIGSEV bug --- src/models.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index ad084f05..b7e36b8a 100644 --- a/src/models.c +++ b/src/models.c @@ -1811,7 +1811,7 @@ static Material LoadMTL(const char *fileName) char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; - char *mapFileName = NULL; + char mapFileName[128]; FILE *mtlFile; -- cgit v1.2.3 From 6d1b712a9678a7e1d57d994ab51afafbe06ec5fb Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 16 Nov 2016 18:46:13 +0100 Subject: Reviewed modules comments --- src/audio.c | 19 ++++++++++++------- src/audio.h | 16 +++++++++------- src/core.c | 25 +++++++++++++------------ src/external/stb_image.h | 4 ++-- src/models.c | 9 +++++++-- src/raylib.h | 34 ++++++++++++++++++---------------- src/rlgl.c | 29 ++++++++++++++++++++++++----- src/rlgl.h | 26 +++++++++++++++++++++----- src/shapes.c | 10 ++++++++-- src/text.c | 8 +++++++- src/textures.c | 10 +++++++--- src/utils.c | 14 ++++++++++---- src/utils.h | 6 ++---- 13 files changed, 140 insertions(+), 70 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 3684e10a..3ddbf0ce 100644 --- a/src/audio.c +++ b/src/audio.c @@ -2,18 +2,22 @@ * * raylib.audio * -* Basic functions to manage Audio: +* This module provides basic functionality to work with audio: * Manage audio device (init/close) -* Load and Unload audio files +* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD) * Play/Stop/Pause/Resume loaded audio * Manage mixing channels * Manage raw audio context * -* Uses external lib: -* OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) -* stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) -* jar_xm - XM module file loading -* jar_mod - MOD audio file loading +* External libs: +* OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html) +* stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading +* dr_flac - FLAC audio file loading +* +* Module Configuration Flags: +* AUDIO_STANDALONE - Use this module as standalone library (independently of raylib) * * Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: * XM audio module support (jar_xm) @@ -21,6 +25,7 @@ * Mixing channels support * Raw audio context support * +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event diff --git a/src/audio.h b/src/audio.h index 923492ca..5de8f613 100644 --- a/src/audio.h +++ b/src/audio.h @@ -2,18 +2,19 @@ * * raylib.audio * -* Basic functions to manage Audio: +* This module provides basic functionality to work with audio: * Manage audio device (init/close) -* Load and Unload audio files +* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD) * Play/Stop/Pause/Resume loaded audio * Manage mixing channels * Manage raw audio context * -* Uses external lib: -* OpenAL Soft - Audio device management lib (http://kcat.strangesoft.net/openal.html) -* stb_vorbis - Ogg audio files loading (http://www.nothings.org/stb_vorbis/) -* jar_xm - XM module file loading -* jar_mod - MOD audio file loading +* External libs: +* OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html) +* stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/) +* jar_xm - XM module file loading +* jar_mod - MOD audio file loading +* dr_flac - FLAC audio file loading * * Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: * XM audio module support (jar_xm) @@ -21,6 +22,7 @@ * Mixing channels support * Raw audio context support * +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event diff --git a/src/core.c b/src/core.c index 8e15eb96..991dd4a0 100644 --- a/src/core.c +++ b/src/core.c @@ -4,24 +4,25 @@ * * Basic functions to manage windows, OpenGL context and input on multiple platforms * -* The following platforms are supported: -* PLATFORM_DESKTOP - Windows, Linux, Mac (OSX) -* PLATFORM_ANDROID - Only OpenGL ES 2.0 devices -* PLATFORM_RPI - Rapsberry Pi (tested on Raspbian) -* PLATFORM_WEB - Emscripten, HTML5 -* Oculus Rift CV1 (with desktop mirror) - View [rlgl] module to enable it +* The following platforms are supported: Windows, Linux, Mac (OSX), Android, Raspberry Pi, HTML5, Oculus Rift CV1 * -* On PLATFORM_DESKTOP, the external lib GLFW3 (www.glfw.com) is used to manage graphic -* device, OpenGL context and input on multiple operating systems (Windows, Linux, OSX). -* -* On PLATFORM_ANDROID, graphic device is managed by EGL and input system by Android activity. -* -* On PLATFORM_RPI, graphic device is managed by EGL and input system is coded in raw mode. +* External libs: +* GLFW3 - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX) +* raymath - 3D math functionality (Vector3, Matrix, Quaternion) +* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person) +* gestures - Gestures system for touch-ready devices (or simulated from mouse inputs) * * Module Configuration Flags: +* PLATFORM_DESKTOP - Windows, Linux, Mac (OSX) +* PLATFORM_ANDROID - Android (only OpenGL ES 2.0 devices), graphic device is managed by EGL and input system by Android activity. +* PLATFORM_RPI - Rapsberry Pi (tested on Raspbian), graphic device is managed by EGL and input system is coded in raw mode. +* PLATFORM_WEB - HTML5 (using emscripten compiler) * * RL_LOAD_DEFAULT_FONT - Use external module functions to load default raylib font (module: text) * +* NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for render mirror - View [rlgl] module to enable it +* +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event diff --git a/src/external/stb_image.h b/src/external/stb_image.h index ce87646d..5572a880 100644 --- a/src/external/stb_image.h +++ b/src/external/stb_image.h @@ -390,7 +390,7 @@ publish, and distribute this file as you see fit. #define STBI_NO_HDR // RaySan: not required by raylib -#define STBI_NO_SIMD // RaySan: issues when compiling with GCC 4.7.2 +//#define STBI_NO_SIMD // RaySan: issues when compiling with GCC 4.7.2 #ifndef STBI_NO_STDIO #include @@ -398,7 +398,7 @@ publish, and distribute this file as you see fit. // NOTE: Added to work with raylib on Android #if defined(PLATFORM_ANDROID) - #include "utils.h" // Android fopen function map + #include "utils.h" // RaySan: Android fopen function map #endif #define STBI_VERSION 1 diff --git a/src/models.c b/src/models.c index b7e36b8a..4275f89e 100644 --- a/src/models.c +++ b/src/models.c @@ -4,6 +4,12 @@ * * Basic functions to draw 3d shapes and load/draw 3d models (.OBJ) * +* External libs: +* rlgl - raylib OpenGL abstraction layer +* +* Module Configuration Flags: +* ... +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event @@ -34,8 +40,7 @@ #include // Required for: strcmp() #include // Required for: sin(), cos() -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 -#include "raymath.h" // Matrix data type and Matrix functions +#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 //---------------------------------------------------------------------------------- // Defines and Macros diff --git a/src/raylib.h b/src/raylib.h index 2e3112cf..ef393f63 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -6,37 +6,39 @@ * * Features: * Library written in plain C code (C99) -* Uses C# PascalCase/camelCase notation +* Uses PascalCase/camelCase notation * Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0) * Unique OpenGL abstraction layer (usable as standalone module): [rlgl] * Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF) * Multiple textures support, including compressed formats and mipmaps generation * Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps * Materials (diffuse, normal, specular) and Lighting (point, directional, spot) support -* Powerful math module for Vector, Matrix and Quaternion operations [raymath] -* Audio loading and playing with streaming support and mixing channels (WAV, OGG, XM, MOD) +* Powerful math module for Vector, Matrix and Quaternion operations: [raymath] +* Audio loading and playing with streaming support and mixing channels [audio] * VR stereo rendering support with configurable HMD device parameters * Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1 * Custom color palette for fancy visuals on raywhite background * Minimal external dependencies (GLFW3, OpenGL, OpenAL) +* Complete binding for LUA [rlua] * -* Used external libs: -* GLFW3 (www.glfw.org) for window/context management and input -* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) -* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC) -* stb_image_write (Sean Barret) for image writting (PNG) -* stb_vorbis (Sean Barret) for ogg audio loading -* stb_truetype (Sean Barret) for ttf fonts loading -* jar_xm (Joshua Reisenauer) for XM audio module loading -* jar_mod (Joshua Reisenauer) for MOD audio module loading -* OpenAL Soft for audio device/context management -* tinfl for data decompression (DEFLATE algorithm) +* External libs: +* GLFW3 (www.glfw.org) for window/context management and input [core] +* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) [rlgl] +* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA) [textures] +* stb_image_write (Sean Barret) for image writting (PNG) [utils] +* stb_truetype (Sean Barret) for ttf fonts loading [text] +* stb_vorbis (Sean Barret) for ogg audio loading [audio] +* jar_xm (Joshua Reisenauer) for XM audio module loading [audio] +* jar_mod (Joshua Reisenauer) for MOD audio module loading [audio] +* dr_flac (David Reid) for FLAC audio file loading [audio] +* OpenAL Soft for audio device/context management [audio] +* tinfl for data decompression (DEFLATE algorithm) [utils] * * Some design decisions: * 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) -* One custom default font is loaded automatically when InitWindow() +* One custom default font could be loaded automatically when InitWindow() [core] * If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads -* If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined) +* If using OpenGL 3.3 or ES2, two default shaders could be loaded automatically (internally defined) * * -- LICENSE -- * diff --git a/src/rlgl.c b/src/rlgl.c index d3bba07b..28dc5171 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2,11 +2,30 @@ * * rlgl - raylib OpenGL abstraction layer * -* raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version: -* OpenGL 1.1 - Direct map rl* -> gl* -* OpenGL 2.1 - Vertex data is stored in VBOs, call rlglDraw() to render -* OpenGL 3.3 - Vertex data is stored in VAOs, call rlglDraw() to render -* OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render +* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to +* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). +* +* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal +* VBO buffers (and VAOs if available). It requires calling 3 functions: +* rlglInit() - Initialize internal buffers and auxiliar resources +* rlglDraw() - Process internal buffers and send required draw calls +* rlglClose() - De-initialize internal buffers data and other auxiliar resources +* +* External libs: +* raymath - 3D math functionality (Vector3, Matrix, Quaternion) +* GLAD - OpenGL extensions loading (OpenGL 3.3 Core only) +* +* Module Configuration Flags: +* GRAPHICS_API_OPENGL_11 - Use OpenGL 1.1 backend +* GRAPHICS_API_OPENGL_21 - Use OpenGL 2.1 backend +* GRAPHICS_API_OPENGL_33 - Use OpenGL 3.3 Core profile backend +* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend +* +* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency) +* RLGL_NO_STANDARD_SHADER - Avoid standard shader (shader_standard.h) inclusion +* RLGL_NO_DISTORTION_SHADER - Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion +* RLGL_OCULUS_SUPPORT - Enable Oculus Rift CV1 functionality +* * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * diff --git a/src/rlgl.h b/src/rlgl.h index 78ea6727..e4d40714 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -2,11 +2,27 @@ * * rlgl - raylib OpenGL abstraction layer * -* raylib now uses OpenGL 1.1 style functions (rlVertex) that are mapped to selected OpenGL version: -* OpenGL 1.1 - Direct map rl* -> gl* -* OpenGL 2.1 - Vertex data is stored in VBOs, call rlglDraw() to render -* OpenGL 3.3 - Vertex data is stored in VAOs, call rlglDraw() to render -* OpenGL ES 2 - Vertex data is stored in VBOs or VAOs (when available), call rlglDraw() to render +* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to +* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). +* +* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal +* VBO buffers (and VAOs if available). It requires calling 3 functions: +* rlglInit() - Initialize internal buffers and auxiliar resources +* rlglDraw() - Process internal buffers and send required draw calls +* rlglClose() - De-initialize internal buffers data and other auxiliar resources +* +* External libs: +* raymath - 3D math functionality (Vector3, Matrix, Quaternion) +* GLAD - OpenGL extensions loading (OpenGL 3.3 Core only) +* +* Module Configuration Flags: +* GRAPHICS_API_OPENGL_11 - Use OpenGL 1.1 backend +* GRAPHICS_API_OPENGL_21 - Use OpenGL 2.1 backend +* GRAPHICS_API_OPENGL_33 - Use OpenGL 3.3 Core profile backend +* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend +* +* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency) +* * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * diff --git a/src/shapes.c b/src/shapes.c index 79cf567a..70aad59a 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -4,6 +4,12 @@ * * Basic functions to draw 2d Shapes and check collisions * +* External libs: +* rlgl - raylib OpenGL abstraction layer +* +* Module Configuration Flags: +* ... +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event @@ -25,11 +31,11 @@ #include "raylib.h" +#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2 + #include // Required for: abs() #include // Required for: sinf(), cosf(), sqrtf() -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- diff --git a/src/text.c b/src/text.c index 72d273d4..d752f1cb 100644 --- a/src/text.c +++ b/src/text.c @@ -4,6 +4,12 @@ * * Basic functions to load SpriteFonts and draw Text * +* External libs: +* stb_truetype - Load TTF file and rasterize characters data +* +* Module Configuration Flags: +* ... +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event @@ -33,7 +39,7 @@ #include "utils.h" // Required for: GetExtension(), GetNextPOT() // Following libs are used on LoadTTF() -//#define STBTT_STATIC +#define STBTT_STATIC // Define stb_truetype functions static to this module #define STB_TRUETYPE_IMPLEMENTATION #include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap() diff --git a/src/textures.c b/src/textures.c index 5354a74f..af59d035 100644 --- a/src/textures.c +++ b/src/textures.c @@ -4,9 +4,13 @@ * * Basic functions to load and draw Textures (2d) * -* Uses external lib: -* stb_image - Multiple formats image loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) -* NOTE: stb_image has been slightly modified, original library: https://github.com/nothings/stb +* External libs: +* stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) +* NOTE: stb_image has been slightly modified to support Android platform. +* stb_image_resize - Multiple image resize algorythms +* +* Module Configuration Flags: +* ... * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * diff --git a/src/utils.c b/src/utils.c index b96e2c70..640c5720 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,12 +2,16 @@ * * raylib.utils * -* Utils Functions Definitions +* Some utility functions * -* Uses external libs: -* tinfl - zlib DEFLATE algorithm decompression lib +* External libs: +* tinfl - zlib DEFLATE algorithm decompression * stb_image_write - PNG writting functions * +* Module Configuration Flags: +* DO_NOT_TRACE_DEBUG_MSGS - Avoid showing DEBUG TraceLog() messages +* +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event @@ -46,7 +50,9 @@ #endif #include "external/tinfl.c" // Required for: tinfl_decompress_mem_to_mem() - // NOTE: Deflate algorythm data decompression + // NOTE: DEFLATE algorythm data decompression + +#define DO_NOT_TRACE_DEBUG_MSGS // Avoid DEBUG messages tracing //---------------------------------------------------------------------------------- // Global Variables Definition diff --git a/src/utils.h b/src/utils.h index 899cf583..045b0692 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,9 +2,9 @@ * * raylib.utils * -* Some utility functions: rRES files data decompression +* Some utility functions * -* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -34,8 +34,6 @@ //---------------------------------------------------------------------------------- // Some basic Defines //---------------------------------------------------------------------------------- -#define DO_NOT_TRACE_DEBUG_MSGS // Use this define to avoid DEBUG tracing - #if defined(PLATFORM_ANDROID) #define fopen(name, mode) android_fopen(name, mode) #endif -- cgit v1.2.3 From bee283b12b348b054bde2eae1a449c363ac26fd7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 17 Nov 2016 12:55:30 +0100 Subject: Some tweaks around --- src/Makefile | 5 +++++ src/core.c | 4 ++-- src/models.c | 12 ++++++------ src/raylib.h | 16 ++++++++-------- src/rlgl.c | 4 ++-- src/rlgl.h | 3 ++- 6 files changed, 25 insertions(+), 19 deletions(-) (limited to 'src/models.c') diff --git a/src/Makefile b/src/Makefile index feadc424..2433428f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,6 +41,11 @@ SHARED ?= NO # define NO to use OpenAL Soft as static library (or shared by default) SHARED_OPENAL ?= NO +# on PLATFORM_WEB force OpenAL Soft shared library +ifeq ($(PLATFORM),PLATFORM_WEB) + SHARED_OPENAL ?= YES +endif + # determine if the file has root access (only for installing raylib) # "whoami" prints the name of the user that calls him (so, if it is the root # user, "whoami" prints "root"). diff --git a/src/core.c b/src/core.c index 991dd4a0..4807b7f6 100644 --- a/src/core.c +++ b/src/core.c @@ -668,7 +668,7 @@ void Begin3dMode(Camera camera) { rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2) - if (IsVrDeviceReady()) BeginVrDrawing(); + if (IsVrDeviceReady() || IsVrSimulator()) BeginVrDrawing(); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix @@ -698,7 +698,7 @@ void End3dMode(void) { rlglDraw(); // Process internal buffers (update + draw) - if (IsVrDeviceReady()) EndVrDrawing(); + if (IsVrDeviceReady() || IsVrSimulator()) EndVrDrawing(); rlMatrixMode(RL_PROJECTION); // Switch to projection matrix rlPopMatrix(); // Restore previous matrix (PROJECTION) from matrix stack diff --git a/src/models.c b/src/models.c index 4275f89e..be0e6ea4 100644 --- a/src/models.c +++ b/src/models.c @@ -81,11 +81,11 @@ void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color) } // Draw a circle in 3D world space -void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color) +void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color) { rlPushMatrix(); rlTranslatef(center.x, center.y, center.z); - rlRotatef(rotationAngle, rotation.x, rotation.y, rotation.z); + rlRotatef(rotationAngle, rotationAxis.x, rotationAxis.y, rotationAxis.z); rlBegin(RL_LINES); for (int i = 0; i < 360; i += 10) @@ -584,9 +584,9 @@ void DrawLight(Light light) { DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); - DrawCircle3D(light->position, light->radius, 0.0f, (Vector3){ 0, 0, 0 }, (light->enabled ? light->diffuse : GRAY)); - DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 1, 0, 0 }, (light->enabled ? light->diffuse : GRAY)); - DrawCircle3D(light->position, light->radius, 90.0f, (Vector3){ 0, 1, 0 }, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 0, 0, 0 }, 0.0f, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 1, 0, 0 }, 90.0f, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 0, 1, 0 },90.0f, (light->enabled ? light->diffuse : GRAY)); } break; case LIGHT_DIRECTIONAL: { @@ -602,7 +602,7 @@ void DrawLight(Light light) Vector3 dir = VectorSubtract(light->target, light->position); VectorNormalize(&dir); - DrawCircle3D(light->position, 0.5f, 0.0f, dir, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY)); //DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY)); DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); diff --git a/src/raylib.h b/src/raylib.h index ef393f63..6d67051e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -724,7 +724,7 @@ RLAPI float GetGesturePinchAngle(void); // Get gesture pin //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) //------------------------------------------------------------------------------------ -RLAPI void SetCameraMode(Camera, int mode); // Set camera mode (multiple camera modes available) +RLAPI void SetCameraMode(Camera camera, int mode); // Set camera mode (multiple camera modes available) RLAPI void UpdateCamera(Camera *camera); // Update camera position for selected mode RLAPI void SetCameraPanControl(int panKey); // Set camera pan key to combine with mouse movement (free camera) @@ -835,7 +835,7 @@ RLAPI const char *SubText(const char *text, int position, int length); // Basic 3d Shapes Drawing Functions (Module: models) //------------------------------------------------------------------------------------ RLAPI void DrawLine3D(Vector3 startPos, Vector3 endPos, Color color); // Draw a line in 3D world space -RLAPI void DrawCircle3D(Vector3 center, float radius, float rotationAngle, Vector3 rotation, Color color); // Draw a circle in 3D world space +RLAPI void DrawCircle3D(Vector3 center, float radius, Vector3 rotationAxis, float rotationAngle, Color color); // Draw a circle in 3D world space RLAPI void DrawCube(Vector3 position, float width, float height, float length, Color color); // Draw cube RLAPI void DrawCubeV(Vector3 position, Vector3 size, Color color); // Draw cube (Vector version) RLAPI void DrawCubeWires(Vector3 position, float width, float height, float length, Color color); // Draw cube wires @@ -850,7 +850,7 @@ RLAPI void DrawRay(Ray ray, Color color); RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) RLAPI void DrawGizmo(Vector3 position); // Draw simple gizmo RLAPI void DrawLight(Light light); // Draw light in 3D world -//DrawTorus(), DrawTeapot() are useless... +//DrawTorus(), DrawTeapot() could be useful? //------------------------------------------------------------------------------------ // Model 3d Loading and Drawing Functions (Module: models) @@ -917,7 +917,7 @@ RLAPI void DestroyLight(Light light); // Des //------------------------------------------------------------------------------------ RLAPI void InitVrDevice(int vdDevice); // Init VR device RLAPI void CloseVrDevice(void); // Close VR device -RLAPI bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready +RLAPI bool IsVrDeviceReady(void); // Detect if VR device is ready RLAPI bool IsVrSimulator(void); // Detect if VR simulator is running RLAPI void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera RLAPI void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) @@ -926,7 +926,7 @@ RLAPI void ToggleVrMode(void); // Enable/Disable VR experienc // Audio Loading and Playing Functions (Module: audio) //------------------------------------------------------------------------------------ RLAPI void InitAudioDevice(void); // Initialize audio device and context -RLAPI void CloseAudioDevice(void); // Close the audio device and context (and music stream) +RLAPI void CloseAudioDevice(void); // Close the audio device and context RLAPI bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully RLAPI Wave LoadWave(const char *fileName); // Load wave data from file into RAM @@ -950,9 +950,9 @@ RLAPI void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a RLAPI float *GetWaveData(Wave wave); // Get samples data from wave as a floats array RLAPI Music LoadMusicStream(const char *fileName); // Load music stream from file RLAPI void UnloadMusicStream(Music music); // Unload music stream -RLAPI void PlayMusicStream(Music music); // Start music playing (open stream) +RLAPI void PlayMusicStream(Music music); // Start music playing RLAPI void UpdateMusicStream(Music music); // Updates buffers for music streaming -RLAPI void StopMusicStream(Music music); // Stop music playing (close stream) +RLAPI void StopMusicStream(Music music); // Stop music playing RLAPI void PauseMusicStream(Music music); // Pause music playing RLAPI void ResumeMusicStream(Music music); // Resume playing paused music RLAPI bool IsMusicPlaying(Music music); // Check if music is playing @@ -963,7 +963,7 @@ RLAPI float GetMusicTimePlayed(Music music); // Get cur RLAPI AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, - unsigned int channels); // Init audio stream (to stream audio pcm data) + unsigned int channels); // Init audio stream (to stream raw audio pcm data) RLAPI void UpdateAudioStream(AudioStream stream, void *data, int numSamples); // Update audio stream buffers with data RLAPI void CloseAudioStream(AudioStream stream); // Close audio stream and free memory RLAPI bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill diff --git a/src/rlgl.c b/src/rlgl.c index 28dc5171..b567f8fd 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2786,13 +2786,13 @@ void CloseVrDevice(void) // Detect if VR device is available bool IsVrDeviceReady(void) { - return (vrDeviceReady || vrSimulator) && vrEnabled; + return (vrDeviceReady && vrEnabled); } // Detect if VR simulator is running bool IsVrSimulator(void) { - return vrSimulator; + return (vrSimulator && vrEnabled); } // Enable/Disable VR experience (device or simulator) diff --git a/src/rlgl.h b/src/rlgl.h index e4d40714..7d328a52 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -423,7 +423,8 @@ float *MatrixToFloat(Matrix mat); void InitVrDevice(int vrDevice); // Init VR device void CloseVrDevice(void); // Close VR device -bool IsVrDeviceReady(void); // Detect if VR device (or simulator) is ready +bool IsVrDeviceReady(void); // Detect if VR device is ready +bool IsVrSimulator(void); // Detect if VR simulator is running void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) -- cgit v1.2.3 From f7b706263a820034a93ab88e7582b7001819d8d0 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 18 Nov 2016 13:39:57 +0100 Subject: Some code tweaks Correcting details that pop-up when testing the different platforms --- src/Makefile | 7 ++++++- src/audio.c | 12 ++++-------- src/audio.h | 39 +++++++++++++++++++++++---------------- src/core.c | 9 +++++++-- src/models.c | 21 +++++++++++---------- 5 files changed, 51 insertions(+), 37 deletions(-) (limited to 'src/models.c') diff --git a/src/Makefile b/src/Makefile index 2433428f..2e263189 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,7 +39,7 @@ PLATFORM ?= PLATFORM_DESKTOP SHARED ?= NO # define NO to use OpenAL Soft as static library (or shared by default) -SHARED_OPENAL ?= NO +SHARED_OPENAL ?= YES # on PLATFORM_WEB force OpenAL Soft shared library ifeq ($(PLATFORM),PLATFORM_WEB) @@ -188,6 +188,11 @@ else # compile raylib static library for desktop platforms. ar rcs $(OUTPUT_PATH)/libraylib.a $(OBJS) @echo "libraylib.a generated (static library)!" + ifeq ($(SHARED_OPENAL),NO) + @echo "expected OpenAL Soft static library linking" + else + @echo "expected OpenAL Soft shared library linking" + endif endif endif diff --git a/src/audio.c b/src/audio.c index 3ddbf0ce..49aca4b0 100644 --- a/src/audio.c +++ b/src/audio.c @@ -49,8 +49,11 @@ #if defined(AUDIO_STANDALONE) #include "audio.h" + #include // Required for: va_list, va_start(), vfprintf(), va_end() #else #include "raylib.h" + #include "utils.h" // Required for: DecompressData() + // NOTE: Includes Android fopen() function map #endif #include "AL/al.h" // OpenAL basic header @@ -68,13 +71,6 @@ #define AL_FORMAT_STEREO_FLOAT32 0x10011 #endif -#if defined(AUDIO_STANDALONE) - #include // Required for: va_list, va_start(), vfprintf(), va_end() -#else - #include "utils.h" // Required for: DecompressData() - // NOTE: Includes Android fopen() function map -#endif - //#define STB_VORBIS_HEADER_ONLY #include "external/stb_vorbis.h" // OGG loading functions @@ -122,7 +118,7 @@ typedef struct MusicData { bool loop; // Repeat music after finish (loop) unsigned int totalSamples; // Total number of samples unsigned int samplesLeft; // Number of samples left to end -} MusicData, *Music; +} MusicData; #if defined(AUDIO_STANDALONE) typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; diff --git a/src/audio.h b/src/audio.h index 5de8f613..2b3c5933 100644 --- a/src/audio.h +++ b/src/audio.h @@ -62,12 +62,6 @@ #endif #endif -// Sound source type -typedef struct Sound { - unsigned int source; // Sound audio source id - unsigned int buffer; // Sound audio buffer id -} Sound; - // Wave type, defines audio wave data typedef struct Wave { unsigned int sampleCount; // Number of samples @@ -77,9 +71,16 @@ typedef struct Wave { void *data; // Buffer data pointer } Wave; +// Sound source type +typedef struct Sound { + unsigned int source; // OpenAL audio source id + unsigned int buffer; // OpenAL audio buffer id + int format; // OpenAL audio format specifier +} Sound; + // Music type (file streaming from memory) // NOTE: Anything longer than ~10 seconds should be streamed -typedef struct Music *Music; +typedef struct MusicData *Music; // Audio stream type // NOTE: Useful to create custom audio streams not bound to a specific file @@ -106,13 +107,16 @@ extern "C" { // Prevents name mangling of functions // Module Functions Declaration //---------------------------------------------------------------------------------- void InitAudioDevice(void); // Initialize audio device and context -void CloseAudioDevice(void); // Close the audio device and context (and music stream) +void CloseAudioDevice(void); // Close the audio device and context bool IsAudioDeviceReady(void); // Check if audio device has been initialized successfully -Sound LoadSound(char *fileName); // Load sound to memory +Wave LoadWave(const char *fileName); // Load wave data from file into RAM +Wave LoadWaveEx(float *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from float array data (32bit) +Sound LoadSound(const char *fileName); // Load sound to memory Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource) void UpdateSound(Sound sound, void *data, int numSamples); // Update sound buffer with new data +void UnloadWave(Wave wave); // Unload wave data void UnloadSound(Sound sound); // Unload sound void PlaySound(Sound sound); // Play a sound void PauseSound(Sound sound); // Pause a sound @@ -121,12 +125,15 @@ void StopSound(Sound sound); // Stop playing bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level) void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level) - -Music LoadMusicStream(char *fileName); // Load music stream from file +void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels); // Convert wave data to desired format +Wave WaveCopy(Wave wave); // Copy a wave to a new wave +void WaveCrop(Wave *wave, int initSample, int finalSample); // Crop a wave to defined samples range +float *GetWaveData(Wave wave); // Get samples data from wave as a floats array +Music LoadMusicStream(const char *fileName); // Load music stream from file void UnloadMusicStream(Music music); // Unload music stream -void PlayMusicStream(Music music); // Start music playing (open stream) +void PlayMusicStream(Music music); // Start music playing void UpdateMusicStream(Music music); // Updates buffers for music streaming -void StopMusicStream(Music music); // Stop music playing (close stream) +void StopMusicStream(Music music); // Stop music playing void PauseMusicStream(Music music); // Pause music playing void ResumeMusicStream(Music music); // Resume playing paused music bool IsMusicPlaying(Music music); // Check if music is playing @@ -135,9 +142,9 @@ void SetMusicPitch(Music music, float pitch); // Set pitch for float GetMusicTimeLength(Music music); // Get music time length (in seconds) float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) -AudioStream InitAudioStream(unsigned int sampleRate, - unsigned int sampleSize, - unsigned int channels); // Init audio stream (to stream audio pcm data) +AudioStream InitAudioStream(unsigned int sampleRate, + unsigned int sampleSize, + unsigned int channels); // Init audio stream (to stream raw audio pcm data) void UpdateAudioStream(AudioStream stream, void *data, int numSamples); // Update audio stream buffers with data void CloseAudioStream(AudioStream stream); // Close audio stream and free memory bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill diff --git a/src/core.c b/src/core.c index 7749eab7..241772ec 100644 --- a/src/core.c +++ b/src/core.c @@ -1175,9 +1175,10 @@ bool IsGamepadAvailable(int gamepad) bool IsGamepadName(int gamepad, const char *name) { bool result = false; - const char *gamepadName = NULL; #if !defined(PLATFORM_ANDROID) + const char *gamepadName = NULL; + if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad); if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0); #endif @@ -1977,7 +1978,11 @@ static void PollInputEvents(void) previousMouseWheelY = currentMouseWheelY; currentMouseWheelY = 0; - +#endif + +// NOTE: GLFW3 joystick functionality not available in web +// TODO: Support joysticks using emscripten API +#if defined(PLATFORM_DESKTOP) // Check if gamepads are ready // NOTE: We do it here in case of disconection for (int i = 0; i < MAX_GAMEPADS; i++) diff --git a/src/models.c b/src/models.c index be0e6ea4..48f8b813 100644 --- a/src/models.c +++ b/src/models.c @@ -1817,6 +1817,7 @@ static Material LoadMTL(const char *fileName) char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; char mapFileName[128]; + int result = 0; FILE *mtlFile; @@ -1901,13 +1902,13 @@ static Material LoadMTL(const char *fileName) { if (buffer[5] == 'd') // map_Kd string Diffuse color texture map. { - sscanf(buffer, "map_Kd %s", mapFileName); - if (mapFileName != NULL) material.texDiffuse = LoadTexture(mapFileName); + result = sscanf(buffer, "map_Kd %s", mapFileName); + if (result != EOF) material.texDiffuse = LoadTexture(mapFileName); } else if (buffer[5] == 's') // map_Ks string Specular color texture map. { - sscanf(buffer, "map_Ks %s", mapFileName); - if (mapFileName != NULL) material.texSpecular = LoadTexture(mapFileName); + result = sscanf(buffer, "map_Ks %s", mapFileName); + if (result != EOF) material.texSpecular = LoadTexture(mapFileName); } else if (buffer[5] == 'a') // map_Ka string Ambient color texture map. { @@ -1916,13 +1917,13 @@ static Material LoadMTL(const char *fileName) } break; case 'B': // map_Bump string Bump texture map. { - sscanf(buffer, "map_Bump %s", mapFileName); - if (mapFileName != NULL) material.texNormal = LoadTexture(mapFileName); + result = sscanf(buffer, "map_Bump %s", mapFileName); + if (result != EOF) material.texNormal = LoadTexture(mapFileName); } break; case 'b': // map_bump string Bump texture map. { - sscanf(buffer, "map_bump %s", mapFileName); - if (mapFileName != NULL) material.texNormal = LoadTexture(mapFileName); + result = sscanf(buffer, "map_bump %s", mapFileName); + if (result != EOF) material.texNormal = LoadTexture(mapFileName); } break; case 'd': // map_d string Opacity texture map. { @@ -1946,8 +1947,8 @@ static Material LoadMTL(const char *fileName) } break; case 'b': // bump string Bump texture map { - sscanf(buffer, "bump %s", mapFileName); - if (mapFileName != NULL) material.texNormal = LoadTexture(mapFileName); + result = sscanf(buffer, "bump %s", mapFileName); + if (result != EOF) material.texNormal = LoadTexture(mapFileName); } break; case 'T': // Tr float Transparency Tr (alpha). Tr is inverse of d { -- cgit v1.2.3 From 377dcb025fb6957f73263e1913dfc5f29ba21a58 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 5 Dec 2016 01:14:18 +0100 Subject: Corrected some warnings --- src/audio.c | 16 ++++++++------ src/camera.h | 70 ++++++++++++++++++++++++++++++---------------------------- src/core.c | 4 ++-- src/gestures.h | 12 +++++----- src/models.c | 6 +++-- src/raymath.h | 16 +++++++------- src/rlgl.c | 10 ++++++--- src/shapes.c | 15 +++++++------ src/text.c | 33 +++++++++++++-------------- src/textures.c | 25 +++++++++++---------- 10 files changed, 108 insertions(+), 99 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 49aca4b0..eef07154 100644 --- a/src/audio.c +++ b/src/audio.c @@ -411,6 +411,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) else { // Depending on type, skip the right amount of parameters + /* TODO: Review switch (infoHeader.type) { case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters @@ -420,6 +421,7 @@ Sound LoadSoundFromRES(const char *rresName, int resId) case 4: break; // RAW: No parameters default: break; } + */ // Jump DATA to read next infoHeader fseek(rresFile, infoHeader.size, SEEK_CUR); @@ -604,7 +606,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) // Copy a wave to a new wave Wave WaveCopy(Wave wave) { - Wave newWave; + Wave newWave = { 0 }; if (wave.sampleSize == 8) newWave.data = (unsigned char *)malloc(wave.sampleCount*wave.channels*sizeof(unsigned char)); else if (wave.sampleSize == 16) newWave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short)); @@ -822,8 +824,8 @@ void UpdateMusicStream(Music music) if (processed > 0) { bool active = true; - short pcm[AUDIO_BUFFER_SIZE]; - float pcmf[AUDIO_BUFFER_SIZE]; + short pcm[AUDIO_BUFFER_SIZE]; // TODO: Dynamic allocation (uses more than 16KB of stack) + float pcmf[AUDIO_BUFFER_SIZE]; // TODO: Dynamic allocation (uses more than 16KB of stack) int numBuffersToProcess = processed; int numSamples = 0; // Total size of data steamed in L+R samples for xm floats, @@ -952,7 +954,7 @@ float GetMusicTimePlayed(Music music) float secondsPlayed = 0.0f; unsigned int samplesPlayed = music->totalSamples - music->samplesLeft; - secondsPlayed = (float)samplesPlayed/(music->stream.sampleRate*music->stream.channels); + secondsPlayed = (float)(samplesPlayed/(music->stream.sampleRate*music->stream.channels)); return secondsPlayed; } @@ -1004,17 +1006,17 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un { if (stream.sampleSize == 8) { - unsigned char pcm[AUDIO_BUFFER_SIZE] = { 0 }; + unsigned char pcm[AUDIO_BUFFER_SIZE] = { 0 }; // TODO: Dynamic allocation (uses more than 16KB of stack) alBufferData(stream.buffers[i], stream.format, pcm, AUDIO_BUFFER_SIZE*sizeof(unsigned char), stream.sampleRate); } else if (stream.sampleSize == 16) { - short pcm[AUDIO_BUFFER_SIZE] = { 0 }; + short pcm[AUDIO_BUFFER_SIZE] = { 0 }; // TODO: Dynamic allocation (uses more than 16KB of stack) alBufferData(stream.buffers[i], stream.format, pcm, AUDIO_BUFFER_SIZE*sizeof(short), stream.sampleRate); } else if (stream.sampleSize == 32) { - float pcm[AUDIO_BUFFER_SIZE] = { 0.0f }; + float pcm[AUDIO_BUFFER_SIZE] = { 0.0f }; // TODO: Dynamic allocation (uses more than 16KB of stack) alBufferData(stream.buffers[i], stream.format, pcm, AUDIO_BUFFER_SIZE*sizeof(float), stream.sampleRate); } } diff --git a/src/camera.h b/src/camera.h index 33220390..cf542288 100644 --- a/src/camera.h +++ b/src/camera.h @@ -223,15 +223,15 @@ void SetCameraMode(Camera camera, int mode) float dy = v2.y - v1.y; float dz = v2.z - v1.z; - cameraTargetDistance = sqrt(dx*dx + dy*dy + dz*dz); + cameraTargetDistance = sqrtf(dx*dx + dy*dy + dz*dz); Vector2 distance = { 0.0f, 0.0f }; - distance.x = sqrt(dx*dx + dz*dz); - distance.y = sqrt(dx*dx + dy*dy); + distance.x = sqrtf(dx*dx + dz*dz); + distance.y = sqrtf(dx*dx + dy*dy); // Camera angle calculation - cameraAngle.x = asin(fabs(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW) - cameraAngle.y = -asin(fabs(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW) + cameraAngle.x = asinf(fabsf(dx)/distance.x); // Camera angle in plane XZ (0 aligned with Z, move positive CCW) + cameraAngle.y = -asinf(fabsf(dy)/distance.y); // Camera angle in plane XY (0 aligned with X, move positive CW) // NOTE: Just testing what cameraAngle means //cameraAngle.x = 0.0f*DEG2RAD; // Camera angle in plane XZ (0 aligned with Z, move positive CCW) @@ -285,10 +285,10 @@ void UpdateCamera(Camera *camera) { HideCursor(); - if (mousePosition.x < screenHeight/3) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y }); - else if (mousePosition.y < screenHeight/3) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3 }); - else if (mousePosition.x > (screenWidth - screenHeight/3)) SetMousePosition((Vector2){ screenHeight/3, mousePosition.y }); - else if (mousePosition.y > (screenHeight - screenHeight/3)) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3 }); + if (mousePosition.x < (float)screenHeight/3.0f) SetMousePosition((Vector2){ screenWidth - screenHeight/3, mousePosition.y }); + else if (mousePosition.y < (float)screenHeight/3.0f) SetMousePosition((Vector2){ mousePosition.x, screenHeight - screenHeight/3 }); + else if (mousePosition.x > (screenWidth - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ screenHeight/3, mousePosition.y }); + else if (mousePosition.y > (screenHeight - (float)screenHeight/3.0f)) SetMousePosition((Vector2){ mousePosition.x, screenHeight/3 }); else { mousePositionDelta.x = mousePosition.x - previousMousePosition.x; @@ -321,6 +321,7 @@ void UpdateCamera(Camera *camera) if (cameraTargetDistance > CAMERA_FREE_DISTANCE_MAX_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MAX_CLAMP; } // Camera looking down + // TODO: Review, weird comparisson of cameraTargetDistance == 120.0f? else if ((camera->position.y > camera->target.y) && (cameraTargetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0)) { camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance; @@ -341,6 +342,7 @@ void UpdateCamera(Camera *camera) if (cameraTargetDistance < CAMERA_FREE_DISTANCE_MIN_CLAMP) cameraTargetDistance = CAMERA_FREE_DISTANCE_MIN_CLAMP; } // Camera looking up + // TODO: Review, weird comparisson of cameraTargetDistance == 120.0f? else if ((camera->position.y < camera->target.y) && (cameraTargetDistance == CAMERA_FREE_DISTANCE_MAX_CLAMP) && (mouseWheelMove < 0)) { camera->target.x += mouseWheelMove*(camera->target.x - camera->position.x)*CAMERA_MOUSE_SCROLL_SENSITIVITY/cameraTargetDistance; @@ -385,9 +387,9 @@ void UpdateCamera(Camera *camera) else { // Camera panning - camera->target.x += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*cos(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*sin(cameraAngle.x)*sin(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER); - camera->target.y += ((mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cos(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER); - camera->target.z += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*sin(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cos(cameraAngle.x)*sin(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER); + camera->target.x += ((mousePositionDelta.x*-CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(cameraAngle.x)*sinf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER); + camera->target.y += ((mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER); + camera->target.z += ((mousePositionDelta.x*CAMERA_FREE_MOUSE_SENSITIVITY)*sinf(cameraAngle.x) + (mousePositionDelta.y*CAMERA_FREE_MOUSE_SENSITIVITY)*cosf(cameraAngle.x)*sinf(cameraAngle.y))*(cameraTargetDistance/CAMERA_FREE_PANNING_DIVIDER); } } @@ -404,19 +406,19 @@ void UpdateCamera(Camera *camera) case CAMERA_FIRST_PERSON: case CAMERA_THIRD_PERSON: { - camera->position.x += (sin(cameraAngle.x)*direction[MOVE_BACK] - - sin(cameraAngle.x)*direction[MOVE_FRONT] - - cos(cameraAngle.x)*direction[MOVE_LEFT] + - cos(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY; + camera->position.x += (sinf(cameraAngle.x)*direction[MOVE_BACK] - + sinf(cameraAngle.x)*direction[MOVE_FRONT] - + cosf(cameraAngle.x)*direction[MOVE_LEFT] + + cosf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY; - camera->position.y += (sin(cameraAngle.y)*direction[MOVE_FRONT] - - sin(cameraAngle.y)*direction[MOVE_BACK] + + camera->position.y += (sinf(cameraAngle.y)*direction[MOVE_FRONT] - + sinf(cameraAngle.y)*direction[MOVE_BACK] + 1.0f*direction[MOVE_UP] - 1.0f*direction[MOVE_DOWN])/PLAYER_MOVEMENT_SENSITIVITY; - camera->position.z += (cos(cameraAngle.x)*direction[MOVE_BACK] - - cos(cameraAngle.x)*direction[MOVE_FRONT] + - sin(cameraAngle.x)*direction[MOVE_LEFT] - - sin(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY; + camera->position.z += (cosf(cameraAngle.x)*direction[MOVE_BACK] - + cosf(cameraAngle.x)*direction[MOVE_FRONT] + + sinf(cameraAngle.x)*direction[MOVE_LEFT] - + sinf(cameraAngle.x)*direction[MOVE_RIGHT])/PLAYER_MOVEMENT_SENSITIVITY; bool isMoving = false; // Required for swinging @@ -439,9 +441,9 @@ void UpdateCamera(Camera *camera) if (cameraTargetDistance < CAMERA_THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = CAMERA_THIRD_PERSON_DISTANCE_CLAMP; // Camera is always looking at player - camera->target.x = camera->position.x + CAMERA_THIRD_PERSON_OFFSET.x*cos(cameraAngle.x) + CAMERA_THIRD_PERSON_OFFSET.z*sin(cameraAngle.x); + camera->target.x = camera->position.x + CAMERA_THIRD_PERSON_OFFSET.x*cosf(cameraAngle.x) + CAMERA_THIRD_PERSON_OFFSET.z*sinf(cameraAngle.x); camera->target.y = camera->position.y + CAMERA_THIRD_PERSON_OFFSET.y; - camera->target.z = camera->position.z + CAMERA_THIRD_PERSON_OFFSET.z*sin(cameraAngle.x) - CAMERA_THIRD_PERSON_OFFSET.x*sin(cameraAngle.x); + camera->target.z = camera->position.z + CAMERA_THIRD_PERSON_OFFSET.z*sinf(cameraAngle.x) - CAMERA_THIRD_PERSON_OFFSET.x*sinf(cameraAngle.x); } else // CAMERA_FIRST_PERSON { @@ -450,18 +452,18 @@ void UpdateCamera(Camera *camera) else if (cameraAngle.y < CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD) cameraAngle.y = CAMERA_FIRST_PERSON_MAX_CLAMP*DEG2RAD; // Camera is always looking at player - camera->target.x = camera->position.x - sin(cameraAngle.x)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE; - camera->target.y = camera->position.y + sin(cameraAngle.y)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE; - camera->target.z = camera->position.z - cos(cameraAngle.x)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE; + camera->target.x = camera->position.x - sinf(cameraAngle.x)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE; + camera->target.y = camera->position.y + sinf(cameraAngle.y)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE; + camera->target.z = camera->position.z - cosf(cameraAngle.x)*CAMERA_FIRST_PERSON_FOCUS_DISTANCE; if (isMoving) swingCounter++; // Camera position update // NOTE: On CAMERA_FIRST_PERSON player Y-movement is limited to player 'eyes position' - camera->position.y = playerEyesPosition - sin(swingCounter/CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/CAMERA_FIRST_PERSON_STEP_DIVIDER; + camera->position.y = playerEyesPosition - sinf(swingCounter/CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER)/CAMERA_FIRST_PERSON_STEP_DIVIDER; - camera->up.x = sin(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER; - camera->up.z = -sin(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER; + camera->up.x = sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER; + camera->up.z = -sinf(swingCounter/(CAMERA_FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER*2))/CAMERA_FIRST_PERSON_WAVING_DIVIDER; } } break; default: break; @@ -473,10 +475,10 @@ void UpdateCamera(Camera *camera) (cameraMode == CAMERA_THIRD_PERSON)) { // TODO: It seems camera->position is not correctly updated or some rounding issue makes the camera move straight to camera->target... - camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x; - if (cameraAngle.y <= 0.0f) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; - else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; - camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z; + camera->position.x = sinf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.x; + if (cameraAngle.y <= 0.0f) camera->position.y = sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y; + else camera->position.y = -sinf(cameraAngle.y)*cameraTargetDistance*sinf(cameraAngle.y) + camera->target.y; + camera->position.z = cosf(cameraAngle.x)*cameraTargetDistance*cosf(cameraAngle.y) + camera->target.z; } } diff --git a/src/core.c b/src/core.c index 241772ec..7fa20979 100644 --- a/src/core.c +++ b/src/core.c @@ -779,7 +779,7 @@ float GetFrameTime(void) // As we are operate quite a lot with frameTime, // it could be no stable, so we round it before passing it around // NOTE: There are still problems with high framerates (>500fps) - double roundedFrameTime = round(frameTime*10000)/10000.0; + double roundedFrameTime = round(frameTime*10000)/10000.0; return (float)roundedFrameTime; // Time in seconds to run a frame } @@ -1089,7 +1089,7 @@ Vector2 GetWorldToScreen(Vector3 position, Camera camera) QuaternionTransform(&worldPos, matProj); // Calculate normalized device coordinates (inverted y) - Vector3 ndcPos = { worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.z }; + Vector3 ndcPos = { worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.w }; // Calculate 2d screen position vector Vector2 screenPosition = { (ndcPos.x + 1.0f)/2.0f*(float)GetScreenWidth(), (ndcPos.y + 1.0f)/2.0f*(float)GetScreenHeight() }; diff --git a/src/gestures.h b/src/gestures.h index 481ef317..19b09269 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -179,7 +179,7 @@ static int tapCounter = 0; // TAP counter (one tap implies // Hold gesture variables static bool resetHold = false; // HOLD reset to get first touch point again -static float timeHold = 0.0f; // HOLD duration in milliseconds +static double timeHold = 0.0f; // HOLD duration in milliseconds // Drag gesture variables static Vector2 dragVector = { 0.0f , 0.0f }; // DRAG vector (between initial and current position) @@ -423,11 +423,11 @@ float GetGestureHoldDuration(void) { // NOTE: time is calculated on current gesture HOLD - float time = 0.0f; + double time = 0.0; - if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; + if (currentGesture == GESTURE_HOLD) time = GetCurrentTime() - timeHold; - return time; + return (float)time; } // Get drag vector (between initial touch point to current) @@ -474,7 +474,7 @@ static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition) { float angle; - angle = atan2(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x)*(180.0f/PI); + angle = atan2f(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x)*(180.0f/PI); if (angle < 0) angle += 360.0f; @@ -489,7 +489,7 @@ static float Vector2Distance(Vector2 v1, Vector2 v2) float dx = v2.x - v1.x; float dy = v2.y - v1.y; - result = sqrt(dx*dx + dy*dy); + result = (float)sqrt(dx*dx + dy*dy); return result; } diff --git a/src/models.c b/src/models.c index 48f8b813..97c84abc 100644 --- a/src/models.c +++ b/src/models.c @@ -707,6 +707,7 @@ Model LoadModelFromRES(const char *rresName, int resId) else { // Depending on type, skip the right amount of parameters + /* Review switch (infoHeader.type) { case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters @@ -716,6 +717,7 @@ Model LoadModelFromRES(const char *rresName, int resId) case 4: break; // RAW: No parameters default: break; } + */ // Jump DATA to read next infoHeader fseek(rresFile, infoHeader.size, SEEK_CUR); @@ -1517,8 +1519,8 @@ bool CheckCollisionRayBox(Ray ray, BoundingBox box) t[3] = (box.max.y - ray.position.y)/ray.direction.y; t[4] = (box.min.z - ray.position.z)/ray.direction.z; t[5] = (box.max.z - ray.position.z)/ray.direction.z; - t[6] = fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); - t[7] = fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); + t[6] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); + t[7] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); collision = !(t[7] < 0 || t[6] > t[7]); diff --git a/src/raymath.h b/src/raymath.h index 10eabb6b..3cd1394e 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -222,16 +222,16 @@ RMDEF Vector3 VectorPerpendicular(Vector3 v) { Vector3 result; - float min = fabs(v.x); + float min = fabsf(v.x); Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; - if (fabs(v.y) < min) + if (fabsf(v.y) < min) { - min = fabs(v.y); + min = fabsf(v.y); cardinalAxis = (Vector3){0.0f, 1.0f, 0.0f}; } - if(fabs(v.z) < min) + if(fabsf(v.z) < min) { cardinalAxis = (Vector3){0.0f, 0.0f, 1.0f}; } @@ -256,7 +256,7 @@ RMDEF float VectorLength(const Vector3 v) { float length; - length = sqrt(v.x*v.x + v.y*v.y + v.z*v.z); + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); return length; } @@ -284,7 +284,7 @@ RMDEF void VectorNormalize(Vector3 *v) length = VectorLength(*v); - if (length == 0) length = 1.0f; + if (length == 0.0f) length = 1.0f; ilength = 1.0f/length; @@ -302,7 +302,7 @@ RMDEF float VectorDistance(Vector3 v1, Vector3 v2) float dy = v2.y - v1.y; float dz = v2.z - v1.z; - result = sqrt(dx*dx + dy*dy + dz*dz); + result = sqrtf(dx*dx + dy*dy + dz*dz); return result; } @@ -590,7 +590,7 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle) float x = axis.x, y = axis.y, z = axis.z; - float length = sqrt(x*x + y*y + z*z); + float length = sqrtf(x*x + y*y + z*z); if ((length != 1.0f) && (length != 0.0f)) { diff --git a/src/rlgl.c b/src/rlgl.c index 47e2a57d..83cc7050 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -902,6 +902,10 @@ void rlDisableTexture(void) #if defined(GRAPHICS_API_OPENGL_11) glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); +#else + // NOTE: If quads batch limit is reached, + // we force a draw call and next batch starts + if (quads.vCounter/4 >= MAX_QUADS_BATCH) rlglDraw(); #endif } @@ -922,11 +926,11 @@ void rlTextureParameters(unsigned int id, int param, int value) case RL_TEXTURE_MIN_FILTER: glTexParameteri(GL_TEXTURE_2D, param, value); break; case RL_TEXTURE_ANISOTROPIC_FILTER: { - if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value); + if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); else if (maxAnisotropicLevel > 0.0f) { TraceLog(WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, value); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); } else TraceLog(WARNING, "Anisotropic filtering not supported"); } break; @@ -1776,7 +1780,7 @@ void rlglGenerateMipmaps(Texture2D *texture) #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) - texture->mipmaps = 1 + floor(log2(MAX(texture->width, texture->height))); + texture->mipmaps = 1 + (int)floor(log2(MAX(texture->width, texture->height))); #endif } else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture->id); diff --git a/src/shapes.c b/src/shapes.c index 70aad59a..3d3333c1 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -453,16 +453,17 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) int recCenterX = rec.x + rec.width/2; int recCenterY = rec.y + rec.height/2; - float dx = fabs(center.x - recCenterX); - float dy = fabs(center.y - recCenterY); + float dx = fabsf(center.x - recCenterX); + float dy = fabsf(center.y - recCenterY); - if (dx > (rec.width/2 + radius)) { return false; } - if (dy > (rec.height/2 + radius)) { return false; } + if (dx > ((float)rec.width/2.0f + radius)) { return false; } + if (dy > ((float)rec.height/2.0f + radius)) { return false; } - if (dx <= (rec.width/2)) { return true; } - if (dy <= (rec.height/2)) { return true; } + if (dx <= ((float)rec.width/2.0f)) { return true; } + if (dy <= ((float)rec.height/2.0f)) { return true; } - float cornerDistanceSq = (dx - rec.width/2)*(dx - rec.width/2) + (dy - rec.height/2)*(dy - rec.height/2); + float cornerDistanceSq = (dx - (float)rec.width/2.0f)*(dx - (float)rec.width/2.0f) + + (dy - (float)rec.height/2.0f)*(dy - (float)rec.height/2.0f); return (cornerDistanceSq <= (radius*radius)); } diff --git a/src/text.c b/src/text.c index c394889e..27b0a9ce 100644 --- a/src/text.c +++ b/src/text.c @@ -367,7 +367,7 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float if ((unsigned char)text[i] == '\n') { // NOTE: Fixed line spacing of 1.5 lines - textOffsetY += ((spriteFont.size + spriteFont.size/2)*scaleFactor); + textOffsetY += (int)((spriteFont.size + spriteFont.size/2)*scaleFactor); textOffsetX = 0; } else @@ -394,8 +394,8 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float spriteFont.charRecs[index].width*scaleFactor, spriteFont.charRecs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint); - if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (spriteFont.charRecs[index].width*scaleFactor + spacing); - else textOffsetX += (spriteFont.charAdvanceX[index]*scaleFactor + spacing); + if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (int)(spriteFont.charRecs[index].width*scaleFactor + spacing); + else textOffsetX += (int)(spriteFont.charAdvanceX[index]*scaleFactor + spacing); } } } @@ -460,14 +460,14 @@ int MeasureText(const char *text, int fontSize) Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, int spacing) { int len = strlen(text); - int tempLen = 0; // Used to count longer text line num chars + int tempLen = 0; // Used to count longer text line num chars int lenCounter = 0; - int textWidth = 0; - int tempTextWidth = 0; // Used to count longer text line width + float textWidth = 0; + float tempTextWidth = 0; // Used to count longer text line width - int textHeight = spriteFont.size; - float scaleFactor = fontSize/spriteFont.size; + float textHeight = (float)spriteFont.size; + float scaleFactor = fontSize/(float)spriteFont.size; for (int i = 0; i < len; i++) { @@ -485,7 +485,7 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i if (tempTextWidth < textWidth) tempTextWidth = textWidth; lenCounter = 0; textWidth = 0; - textHeight += (spriteFont.size + spriteFont.size/2); // NOTE: Fixed line spacing of 1.5 lines + textHeight += ((float)spriteFont.size*1.5f); // NOTE: Fixed line spacing of 1.5 lines } if (tempLen < lenCounter) tempLen = lenCounter; @@ -494,8 +494,8 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i if (tempTextWidth < textWidth) tempTextWidth = textWidth; Vector2 vec; - vec.x = (float)tempTextWidth*scaleFactor + (tempLen - 1)*spacing; // Adds chars spacing to measure - vec.y = (float)textHeight*scaleFactor; + vec.x = tempTextWidth*scaleFactor + (float)((tempLen - 1)*spacing); // Adds chars spacing to measure + vec.y = textHeight*scaleFactor; return vec; } @@ -504,10 +504,8 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i // NOTE: Uses default font void DrawFPS(int posX, int posY) { - char buffer[20]; - // NOTE: We are rendering fps every second for better viewing on high framerates - // TODO: Not working properly on ANDROID and RPI + // TODO: Not working properly on ANDROID and RPI (for high framerates) static float fps = 0.0f; static int counter = 0; @@ -520,12 +518,11 @@ void DrawFPS(int posX, int posY) else { fps = GetFPS(); - refreshRate = fps; + refreshRate = (int)fps; counter = 0; } - - sprintf(buffer, "%2.0f FPS", fps); - DrawText(buffer, posX, posY, 20, LIME); + + DrawText(FormatText("%2.0f FPS", fps), posX, posY, 20, LIME); } //---------------------------------------------------------------------------------- diff --git a/src/textures.c b/src/textures.c index 126adad3..631468f9 100644 --- a/src/textures.c +++ b/src/textures.c @@ -317,6 +317,7 @@ Image LoadImageFromRES(const char *rresName, int resId) else { // Depending on type, skip the right amount of parameters + /* TODO: Review switch (infoHeader.type) { case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters @@ -326,7 +327,7 @@ Image LoadImageFromRES(const char *rresName, int resId) case 4: break; // RAW: No parameters default: break; } - + */ // Jump DATA to read next infoHeader fseek(rresFile, infoHeader.size, SEEK_CUR); } @@ -1100,18 +1101,18 @@ void ImageResizeNN(Image *image,int newWidth,int newHeight) Color *output = (Color *)malloc(newWidth*newHeight*sizeof(Color)); // EDIT: added +1 to account for an early rounding problem - int x_ratio = (int)((image->width<<16)/newWidth) + 1; - int y_ratio = (int)((image->height<<16)/newHeight) + 1; + int xRatio = (int)((image->width << 16)/newWidth) + 1; + int yRatio = (int)((image->height << 16)/newHeight) + 1; int x2, y2; - for (int i = 0; i < newHeight; i++) + for (int y = 0; y < newHeight; y++) { - for (int j = 0; j < newWidth; j++) + for (int x = 0; x < newWidth; x++) { - x2 = ((j*x_ratio) >> 16); - y2 = ((i*y_ratio) >> 16); + x2 = ((x*xRatio) >> 16); + y2 = ((y*yRatio) >> 16); - output[(i*newWidth) + j] = pixels[(y2*image->width) + x2] ; + output[(y*newWidth) + x] = pixels[(y2*image->width) + x2] ; } } @@ -1584,7 +1585,7 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V rlEnableTexture(texture.id); rlPushMatrix(); - rlTranslatef(destRec.x, destRec.y, 0); + rlTranslatef((float)destRec.x, (float)destRec.y, 0); rlRotatef(rotation, 0, 0, 1); rlTranslatef(-origin.x, -origin.y, 0); @@ -1598,15 +1599,15 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V // Bottom-right corner for texture and quad rlTexCoord2f((float)sourceRec.x/texture.width, (float)(sourceRec.y + sourceRec.height)/texture.height); - rlVertex2f(0.0f, destRec.height); + rlVertex2f(0.0f, (float)destRec.height); // Top-right corner for texture and quad rlTexCoord2f((float)(sourceRec.x + sourceRec.width)/texture.width, (float)(sourceRec.y + sourceRec.height)/texture.height); - rlVertex2f(destRec.width, destRec.height); + rlVertex2f((float)destRec.width, (float)destRec.height); // Top-left corner for texture and quad rlTexCoord2f((float)(sourceRec.x + sourceRec.width)/texture.width, (float)sourceRec.y/texture.height); - rlVertex2f(destRec.width, 0.0f); + rlVertex2f((float)destRec.width, 0.0f); rlEnd(); rlPopMatrix(); -- cgit v1.2.3 From 814507906f56f346d35ca95e7d9888213d3e5974 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 17 Dec 2016 19:05:40 +0100 Subject: Improving rRES custom format support -IN PROGRESS- Start removing old rRES functions. --- src/audio.c | 116 +------------------------------------------------ src/core.c | 7 +-- src/models.c | 85 ------------------------------------ src/raylib.h | 4 -- src/textures.c | 134 ++------------------------------------------------------- src/utils.c | 42 ------------------ 6 files changed, 9 insertions(+), 379 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index eef07154..4435b760 100644 --- a/src/audio.c +++ b/src/audio.c @@ -52,8 +52,7 @@ #include // Required for: va_list, va_start(), vfprintf(), va_end() #else #include "raylib.h" - #include "utils.h" // Required for: DecompressData() - // NOTE: Includes Android fopen() function map + #include "utils.h" // Required for: fopen() Android mapping, TraceLog() #endif #include "AL/al.h" // OpenAL basic header @@ -324,119 +323,6 @@ Sound LoadSoundFromWave(Wave wave) return sound; } -// Load sound to memory from rRES file (raylib Resource) -// TODO: Maybe rresName could be directly a char array with all the data? -Sound LoadSoundFromRES(const char *rresName, int resId) -{ - Sound sound = { 0 }; - -#if defined(AUDIO_STANDALONE) - TraceLog(WARNING, "Sound loading from rRES resource file not supported on standalone mode"); -#else - - bool found = false; - - char id[4]; // rRES file identifier - unsigned char version; // rRES file version and subversion - char useless; // rRES header reserved data - short numRes; - - ResInfoHeader infoHeader; - - FILE *rresFile = fopen(rresName, "rb"); - - if (rresFile == NULL) TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); - else - { - // Read rres file (basic file check - id) - fread(&id[0], sizeof(char), 1, rresFile); - fread(&id[1], sizeof(char), 1, rresFile); - fread(&id[2], sizeof(char), 1, rresFile); - fread(&id[3], sizeof(char), 1, rresFile); - fread(&version, sizeof(char), 1, rresFile); - fread(&useless, sizeof(char), 1, rresFile); - - if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S')) - { - TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName); - } - else - { - // Read number of resources embedded - fread(&numRes, sizeof(short), 1, rresFile); - - for (int i = 0; i < numRes; i++) - { - fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile); - - if (infoHeader.id == resId) - { - found = true; - - // Check data is of valid SOUND type - if (infoHeader.type == 1) // SOUND data type - { - // TODO: Check data compression type - // NOTE: We suppose compression type 2 (DEFLATE - default) - - // Reading SOUND parameters - Wave wave; - short sampleRate, bps; - char channels, reserved; - - fread(&sampleRate, sizeof(short), 1, rresFile); // Sample rate (frequency) - fread(&bps, sizeof(short), 1, rresFile); // Bits per sample - fread(&channels, 1, 1, rresFile); // Channels (1 - mono, 2 - stereo) - fread(&reserved, 1, 1, rresFile); // - - wave.sampleRate = sampleRate; - wave.sampleSize = bps; - wave.channels = (short)channels; - - unsigned char *data = malloc(infoHeader.size); - - fread(data, infoHeader.size, 1, rresFile); - - wave.data = DecompressData(data, infoHeader.size, infoHeader.srcSize); - - free(data); - - sound = LoadSoundFromWave(wave); - - // Sound is loaded, we can unload wave data - UnloadWave(wave); - } - else TraceLog(WARNING, "[%s] Required resource do not seem to be a valid SOUND resource", rresName); - } - else - { - // Depending on type, skip the right amount of parameters - /* TODO: Review - switch (infoHeader.type) - { - case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters - case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters - case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review) - case 3: break; // TEXT: No parameters - case 4: break; // RAW: No parameters - default: break; - } - */ - - // Jump DATA to read next infoHeader - fseek(rresFile, infoHeader.size, SEEK_CUR); - } - } - } - - fclose(rresFile); - } - - if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId); -#endif - return sound; -} - // Unload Wave data void UnloadWave(Wave wave) { diff --git a/src/core.c b/src/core.c index 455417d2..1e03b757 100644 --- a/src/core.c +++ b/src/core.c @@ -42,13 +42,14 @@ * **********************************************************************************************/ -#include "raylib.h" // raylib main header +#include "raylib.h" + #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 -#include "utils.h" // Includes Android fopen map, InitAssetManager(), TraceLog() +#include "utils.h" // Required for: fopen() Android mapping, TraceLog() #define RAYMATH_IMPLEMENTATION // Use raymath as a header-only library (includes implementation) #define RAYMATH_EXTERN_INLINE // Compile raymath functions as static inline (remember, it's a compiler hint) -#include "raymath.h" // Required for Vector3 and Matrix functions +#include "raymath.h" // Required for: Vector3 and Matrix functions #define GESTURES_IMPLEMENTATION #include "gestures.h" // Gestures detection functionality diff --git a/src/models.c b/src/models.c index 97c84abc..7edf8750 100644 --- a/src/models.c +++ b/src/models.c @@ -648,91 +648,6 @@ Model LoadModelEx(Mesh data, bool dynamic) return model; } -// Load a 3d model from rRES file (raylib Resource) -Model LoadModelFromRES(const char *rresName, int resId) -{ - Model model = { 0 }; - bool found = false; - - char id[4]; // rRES file identifier - unsigned char version; // rRES file version and subversion - char useless; // rRES header reserved data - short numRes; - - ResInfoHeader infoHeader; - - FILE *rresFile = fopen(rresName, "rb"); - - if (rresFile == NULL) - { - TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); - } - else - { - // Read rres file (basic file check - id) - fread(&id[0], sizeof(char), 1, rresFile); - fread(&id[1], sizeof(char), 1, rresFile); - fread(&id[2], sizeof(char), 1, rresFile); - fread(&id[3], sizeof(char), 1, rresFile); - fread(&version, sizeof(char), 1, rresFile); - fread(&useless, sizeof(char), 1, rresFile); - - if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S')) - { - TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName); - } - else - { - // Read number of resources embedded - fread(&numRes, sizeof(short), 1, rresFile); - - for (int i = 0; i < numRes; i++) - { - fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile); - - if (infoHeader.id == resId) - { - found = true; - - // Check data is of valid MODEL type - if (infoHeader.type == 8) - { - // TODO: Load model data - } - else - { - TraceLog(WARNING, "[%s] Required resource do not seem to be a valid MODEL resource", rresName); - } - } - else - { - // Depending on type, skip the right amount of parameters - /* Review - switch (infoHeader.type) - { - case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters - case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters - case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review) - case 3: break; // TEXT: No parameters - case 4: break; // RAW: No parameters - default: break; - } - */ - - // Jump DATA to read next infoHeader - fseek(rresFile, infoHeader.size, SEEK_CUR); - } - } - } - - fclose(rresFile); - } - - if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId); - - return model; -} - // Load a heightmap image as a 3d model // NOTE: model map size is defined in generic units Model LoadHeightmap(Image heightmap, Vector3 size) diff --git a/src/raylib.h b/src/raylib.h index 8f69438f..e7d2b74a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -770,10 +770,8 @@ RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Ve RLAPI Image LoadImage(const char *fileName); // Load an image into CPU memory (RAM) RLAPI Image LoadImageEx(Color *pixels, int width, int height); // Load image data from Color array data (RGBA - 32bit) RLAPI Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image data from RAW file -RLAPI Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource) RLAPI Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory RLAPI Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat); // Load a texture from raw data into GPU memory -RLAPI Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource) RLAPI Texture2D LoadTextureFromImage(Image image); // Load a texture from image data RLAPI RenderTexture2D LoadRenderTexture(int width, int height); // Load a texture to be used for rendering RLAPI void UnloadImage(Image image); // Unload image from CPU memory (RAM) @@ -857,7 +855,6 @@ RLAPI void DrawLight(Light light); //------------------------------------------------------------------------------------ RLAPI Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) RLAPI Model LoadModelEx(Mesh data, bool dynamic); // Load a 3d model (from mesh data) -RLAPI Model LoadModelFromRES(const char *rresName, int resId); // Load a 3d model from rRES file (raylib Resource) RLAPI Model LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model RLAPI Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) RLAPI void UnloadModel(Model model); // Unload 3d model from memory @@ -933,7 +930,6 @@ RLAPI Wave LoadWave(const char *fileName); // Load wa RLAPI Wave LoadWaveEx(float *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from float array data (32bit) RLAPI Sound LoadSound(const char *fileName); // Load sound to memory RLAPI Sound LoadSoundFromWave(Wave wave); // Load sound to memory from wave data -RLAPI Sound LoadSoundFromRES(const char *rresName, int resId); // Load sound to memory from rRES file (raylib Resource) RLAPI void UpdateSound(Sound sound, void *data, int numSamples); // Update sound buffer with new data RLAPI void UnloadWave(Wave wave); // Unload wave data RLAPI void UnloadSound(Sound sound); // Unload sound diff --git a/src/textures.c b/src/textures.c index 631468f9..92b22317 100644 --- a/src/textures.c +++ b/src/textures.c @@ -37,11 +37,10 @@ #include // Required for: strcmp(), strrchr(), strncmp() #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 - // Required: rlglLoadTexture() rlDeleteTextures(), - // rlglGenerateMipmaps(), some funcs for DrawTexturePro() + // Required for: rlglLoadTexture() rlDeleteTextures(), + // rlglGenerateMipmaps(), some funcs for DrawTexturePro() -#include "utils.h" // rRES data decompression utility function - // NOTE: Includes Android fopen function map +#include "utils.h" // Required for: fopen() Android mapping, TraceLog() // Support only desired texture formats, by default: JPEG, PNG, BMP, TGA //#define STBI_NO_JPEG // Image format .jpg and .jpeg @@ -216,7 +215,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int fread(image.data, size, 1, rawFile); - // TODO: Check if data have been read + // TODO: Check if data has been read image.width = width; image.height = height; @@ -229,119 +228,6 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int return image; } -// Load an image from rRES file (raylib Resource) -// TODO: Review function to support multiple color modes -Image LoadImageFromRES(const char *rresName, int resId) -{ - Image image = { 0 }; - bool found = false; - - char id[4]; // rRES file identifier - unsigned char version; // rRES file version and subversion - char useless; // rRES header reserved data - short numRes; - - ResInfoHeader infoHeader; - - FILE *rresFile = fopen(rresName, "rb"); - - if (rresFile == NULL) - { - TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", rresName); - } - else - { - // Read rres file (basic file check - id) - fread(&id[0], sizeof(char), 1, rresFile); - fread(&id[1], sizeof(char), 1, rresFile); - fread(&id[2], sizeof(char), 1, rresFile); - fread(&id[3], sizeof(char), 1, rresFile); - fread(&version, sizeof(char), 1, rresFile); - fread(&useless, sizeof(char), 1, rresFile); - - if ((id[0] != 'r') && (id[1] != 'R') && (id[2] != 'E') &&(id[3] != 'S')) - { - TraceLog(WARNING, "[%s] This is not a valid raylib resource file", rresName); - } - else - { - // Read number of resources embedded - fread(&numRes, sizeof(short), 1, rresFile); - - for (int i = 0; i < numRes; i++) - { - fread(&infoHeader, sizeof(ResInfoHeader), 1, rresFile); - - if (infoHeader.id == resId) - { - found = true; - - // Check data is of valid IMAGE type - if (infoHeader.type == 0) // IMAGE data type - { - // TODO: Check data compression type - // NOTE: We suppose compression type 2 (DEFLATE - default) - - short imgWidth, imgHeight; - char colorFormat, mipmaps; - - fread(&imgWidth, sizeof(short), 1, rresFile); // Image width - fread(&imgHeight, sizeof(short), 1, rresFile); // Image height - fread(&colorFormat, 1, 1, rresFile); // Image data color format (default: RGBA 32 bit) - fread(&mipmaps, 1, 1, rresFile); // Mipmap images included (default: 0) - - image.width = (int)imgWidth; - image.height = (int)imgHeight; - - unsigned char *compData = malloc(infoHeader.size); - - fread(compData, infoHeader.size, 1, rresFile); - - unsigned char *imgData = DecompressData(compData, infoHeader.size, infoHeader.srcSize); - - // TODO: Review color mode - //image.data = (unsigned char *)malloc(sizeof(unsigned char)*imgWidth*imgHeight*4); - image.data = imgData; - - //free(imgData); - - free(compData); - - TraceLog(INFO, "[%s] Image loaded successfully from resource, size: %ix%i", rresName, image.width, image.height); - } - else - { - TraceLog(WARNING, "[%s] Required resource do not seem to be a valid IMAGE resource", rresName); - } - } - else - { - // Depending on type, skip the right amount of parameters - /* TODO: Review - switch (infoHeader.type) - { - case 0: fseek(rresFile, 6, SEEK_CUR); break; // IMAGE: Jump 6 bytes of parameters - case 1: fseek(rresFile, 6, SEEK_CUR); break; // SOUND: Jump 6 bytes of parameters - case 2: fseek(rresFile, 5, SEEK_CUR); break; // MODEL: Jump 5 bytes of parameters (TODO: Review) - case 3: break; // TEXT: No parameters - case 4: break; // RAW: No parameters - default: break; - } - */ - // Jump DATA to read next infoHeader - fseek(rresFile, infoHeader.size, SEEK_CUR); - } - } - } - - fclose(rresFile); - } - - if (!found) TraceLog(WARNING, "[%s] Required resource id [%i] could not be found in the raylib resource file", rresName, resId); - - return image; -} - // Load an image as texture into GPU memory Texture2D LoadTexture(const char *fileName) { @@ -378,18 +264,6 @@ Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat) return texture; } -// Load an image as texture from rRES file (raylib Resource) -Texture2D LoadTextureFromRES(const char *rresName, int resId) -{ - Texture2D texture; - - Image image = LoadImageFromRES(rresName, resId); - texture = LoadTextureFromImage(image); - UnloadImage(image); - - return texture; -} - // Load a texture from image data // NOTE: image is not unloaded, it must be done manually Texture2D LoadTextureFromImage(Image image) diff --git a/src/utils.c b/src/utils.c index 640c5720..8fedcaad 100644 --- a/src/utils.c +++ b/src/utils.c @@ -49,9 +49,6 @@ #include "external/stb_image_write.h" // Required for: stbi_write_png() #endif -#include "external/tinfl.c" // Required for: tinfl_decompress_mem_to_mem() - // NOTE: DEFLATE algorythm data decompression - #define DO_NOT_TRACE_DEBUG_MSGS // Avoid DEBUG messages tracing //---------------------------------------------------------------------------------- @@ -75,45 +72,6 @@ static int android_close(void *cookie); // Module Functions Definition - Utilities //---------------------------------------------------------------------------------- -// Data decompression function -// NOTE: Allocated data MUST be freed! -unsigned char *DecompressData(const unsigned char *data, unsigned long compSize, int uncompSize) -{ - int tempUncompSize; - unsigned char *pUncomp; - - // Allocate buffer to hold decompressed data - pUncomp = (mz_uint8 *)malloc((size_t)uncompSize); - - // Check correct memory allocation - if (pUncomp == NULL) - { - TraceLog(WARNING, "Out of memory while decompressing data"); - } - else - { - // Decompress data - tempUncompSize = tinfl_decompress_mem_to_mem(pUncomp, (size_t)uncompSize, data, compSize, 1); - - if (tempUncompSize == -1) - { - TraceLog(WARNING, "Data decompression failed"); - free(pUncomp); - } - - if (uncompSize != (int)tempUncompSize) - { - TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted"); - TraceLog(WARNING, " -- Expected uncompressed size: %i", uncompSize); - TraceLog(WARNING, " -- Returned uncompressed size: %i", tempUncompSize); - } - - TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize); - } - - return pUncomp; -} - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) // Creates a bitmap (BMP) file from an array of pixel data // NOTE: This function is not explicitly available to raylib users -- cgit v1.2.3 From d8bf84f118cd311dbbc81e7183f8cd3e8d2d7e27 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 25 Dec 2016 01:59:23 +0100 Subject: Added mesh loading functions --- src/models.c | 74 +++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 21 deletions(-) (limited to 'src/models.c') diff --git a/src/models.c b/src/models.c index 7edf8750..a2043913 100644 --- a/src/models.c +++ b/src/models.c @@ -611,30 +611,57 @@ void DrawLight(Light light) } } -// Load a 3d model (from file) -Model LoadModel(const char *fileName) +// Load mesh from file +Mesh LoadMesh(const char *fileName) { - Model model = { 0 }; + Mesh mesh = { 0 }; - // TODO: Initialize default data for model in case loading fails, maybe a cube? + if (strcmp(GetExtension(fileName), "obj") == 0) mesh = LoadOBJ(fileName); + else TraceLog(WARNING, "[%s] Mesh extension not recognized, it can't be loaded", fileName); - if (strcmp(GetExtension(fileName), "obj") == 0) model.mesh = LoadOBJ(fileName); - else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName); + if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); + else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) + + // TODO: Initialize default mesh data in case loading fails, maybe a cube? - if (model.mesh.vertexCount == 0) TraceLog(WARNING, "Model could not be loaded"); - else - { - rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) + return mesh; +} - model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); - } +// Load mesh from vertex data +// NOTE: All vertex data arrays must be same size: numVertex +Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData) +{ + Mesh mesh = { 0 }; + + mesh.vertexCount = numVertex; + mesh.triangleCount = numVertex/3; + mesh.vertices = vData; + mesh.texcoords = vtData; + mesh.texcoords2 = NULL; + mesh.normals = vnData; + mesh.tangents = NULL; + mesh.colors = (unsigned char *)cData; + mesh.indices = NULL; + + rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) + + return mesh; +} + +// Load model from file +Model LoadModel(const char *fileName) +{ + Model model = { 0 }; + + model.mesh = LoadMesh(fileName); + model.transform = MatrixIdentity(); + model.material = LoadDefaultMaterial(); return model; } -// Load a 3d model (from vertex data) -Model LoadModelEx(Mesh data, bool dynamic) +// Load model from mesh data +Model LoadModelFromMesh(Mesh data, bool dynamic) { Model model = { 0 }; @@ -648,7 +675,7 @@ Model LoadModelEx(Mesh data, bool dynamic) return model; } -// Load a heightmap image as a 3d model +// Load heightmap model from image data // NOTE: model map size is defined in generic units Model LoadHeightmap(Image heightmap, Vector3 size) { @@ -664,7 +691,7 @@ Model LoadHeightmap(Image heightmap, Vector3 size) return model; } -// Load a map image as a 3d model (cubes based) +// Load cubes-based map model from image data Model LoadCubicmap(Image cubicmap) { Model model = { 0 }; @@ -678,15 +705,20 @@ Model LoadCubicmap(Image cubicmap) return model; } + +// Unload mesh from memory (RAM and/or VRAM) +void UnloadMesh(Mesh *mesh) +{ + rlglUnloadMesh(mesh); +} -// Unload 3d model from memory (mesh and material) +// Unload model from memory (RAM and/or VRAM) void UnloadModel(Model model) { - rlglUnloadMesh(&model.mesh); - + UnloadMesh(&model.mesh); UnloadMaterial(model.material); - TraceLog(INFO, "Unloaded model data from RAM and VRAM"); + TraceLog(INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); } // Load material data (from file) -- cgit v1.2.3 From d5d391faaf69027b8fecb26f30754c3bff83c311 Mon Sep 17 00:00:00 2001 From: Joel Davis Date: Mon, 2 Jan 2017 21:56:25 -0800 Subject: Added RaycastMesh function and example test case --- examples/core_3d_raypick.c | 159 +++++++--- examples/resources/model/lowpoly-tower.obj | 456 +++++++++++++++++++++++++++++ examples/resources/model/lowpoly-tower.png | Bin 0 -> 24939 bytes src/models.c | 38 +++ src/raylib.h | 3 + src/raymath.h | 26 ++ src/shapes.c | 73 ++++- 7 files changed, 708 insertions(+), 47 deletions(-) create mode 100644 examples/resources/model/lowpoly-tower.obj create mode 100644 examples/resources/model/lowpoly-tower.png (limited to 'src/models.c') diff --git a/examples/core_3d_raypick.c b/examples/core_3d_raypick.c index c1c32771..cf56b277 100644 --- a/examples/core_3d_raypick.c +++ b/examples/core_3d_raypick.c @@ -1,15 +1,21 @@ /******************************************************************************************* * -* raylib [core] example - Ray-Picking in 3d mode, also ground plane +* raylib [core] example - Ray-Picking in 3d mode, ground plane, triangle, mesh * * This example has been created using raylib 1.3 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * * Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Example contributed by Joel Davis (@joeld42) * ********************************************************************************************/ #include "raylib.h" +#include "raymath.h" + +#include +#include + int main() { @@ -22,24 +28,36 @@ int main() // Define the camera to look into our 3d world Camera camera; - camera.position = (Vector3){ 10.0f, 10.0f, 10.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target) + camera.position = (Vector3){ 10.0f, 8.0f, 10.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 2.3f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target) camera.fovy = 45.0f; // Camera field-of-view Y Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; - Vector3 groundCursorPos = { 0 }; Ray ray; // Picking line ray - bool collision = false; - + Model tower = LoadModel("resources/model/lowpoly-tower.obj"); // Load OBJ model + Texture2D texture = LoadTexture("resources/model/lowpoly-tower.png"); // Load model texture + tower.material.texDiffuse = texture; // Set model diffuse texture + Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position + BoundingBox towerBBox = CalculateBoundingBox( tower.mesh ); + bool hitMeshBBox; + bool hitTriangle; + + // Test triangle + Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 }; + Vector3 tb = (Vector3){ -4.0, 2.5, 1.0 }; + Vector3 tc = (Vector3){ -8.0, 6.5, 0.0 }; + + Vector3 bary = {0}; + SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- // Main game loop while (!WindowShouldClose()) // Detect window close button or ESC key { @@ -47,22 +65,52 @@ int main() //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - // if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - // { - // // NOTE: This function is NOT WORKING properly! - // ray = GetMouseRay(GetMousePosition(), camera); - - // // Check collision between ray and box - // collision = CheckCollisionRayBox(ray, - // (BoundingBox){(Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, - // (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }}); - // } + // Display information about closest hit + RayHitInfo nearestHit; + char *hitObjectName = "None"; + nearestHit.distance = FLT_MAX; + nearestHit.hit = false; + Color cursorColor = WHITE; + + // Get ray and test against ground, triangle, and mesh ray = GetMouseRay(GetMousePosition(), camera); - RayHitInfo hitinfo = RaycastGroundPlane( ray, 0.0 ); + + RayHitInfo groundHitInfo = RaycastGroundPlane( ray, 0.0 ); + if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) { + nearestHit = groundHitInfo; + cursorColor = GREEN; + hitObjectName = "Ground"; + } + + RayHitInfo triHitInfo = RaycastTriangle( ray, ta, tb, tc ); + if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) { + nearestHit = triHitInfo; + cursorColor = PURPLE; + hitObjectName = "Triangle"; + + bary = Barycentric( nearestHit.hitPosition, ta, tb, tc ); + hitTriangle = true; + } else { + hitTriangle = false; + } + + RayHitInfo meshHitInfo; + + // check the bounding box first, before trying the full ray/mesh test + if (CheckCollisionRayBox( ray, towerBBox )) { + hitMeshBBox = true; + meshHitInfo = RaycastMesh( ray, &tower.mesh ); + if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) { + nearestHit = meshHitInfo; + cursorColor = ORANGE; + hitObjectName = "Mesh"; + } + } else { + hitMeshBBox = false; + } //---------------------------------------------------------------------------------- - // Draw //---------------------------------------------------------------------------------- BeginDrawing(); @@ -71,37 +119,66 @@ int main() Begin3dMode(camera); - if (collision) - { - DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, RED); - DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, MAROON); - - DrawCubeWires(cubePosition, cubeSize.x + 0.2f, cubeSize.y + 0.2f, cubeSize.z + 0.2f, GREEN); - } - else - { - DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY); - DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY); + // Draw the tower + DrawModel( tower, towerPos, 1.0, WHITE ); + + // Draw the test triangle + DrawLine3D( ta, tb, PURPLE ); + DrawLine3D( tb, tc, PURPLE ); + DrawLine3D( tc, ta, PURPLE ); + + // Draw the mesh bbox if we hit it + if (hitMeshBBox) { + DrawBoundingBox( towerBBox, LIME ); } - if (hitinfo.hit) { + // If we hit something, draw the cursor at the hit point + if (nearestHit.hit) { + DrawCube( nearestHit.hitPosition, 0.5, 0.5, 0.5, cursorColor ); + DrawCubeWires( nearestHit.hitPosition, 0.5, 0.5, 0.5, YELLOW ); - groundCursorPos = hitinfo.hitPosition; - groundCursorPos.y += 0.25; // Offset so the cube rests on the ground - printf("Hit: groundpos %3.2f %3.2f %3.2f\n", - groundCursorPos.x, groundCursorPos.y, groundCursorPos.z ); - DrawCubeWires( groundCursorPos, 0.5, 0.5, 0.5, RED ); + Vector3 normalEnd; + normalEnd.x = nearestHit.hitPosition.x + nearestHit.hitNormal.x; + normalEnd.y = nearestHit.hitPosition.y + nearestHit.hitNormal.y; + normalEnd.z = nearestHit.hitPosition.z + nearestHit.hitNormal.z; + DrawLine3D( nearestHit.hitPosition, normalEnd, YELLOW ); } - + DrawRay(ray, MAROON); DrawGrid(10, 1.0f); End3dMode(); - //DrawText("Try selecting the box with mouse!", 240, 10, 20, DARKGRAY); - - //if(collision) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, screenHeight * 0.1f, 30, GREEN); + // Show some debug text + char line[1024]; + sprintf( line, "Hit Object: %s\n", hitObjectName ); + DrawText( line, 10, 30, 15, BLACK ); + + if (nearestHit.hit) { + int ypos = 45; + sprintf( line, "Distance: %3.2f", nearestHit.distance ); + DrawText( line, 10, ypos, 15, BLACK ); + ypos += 15; + + sprintf( line, "Hit Pos: %3.2f %3.2f %3.2f", + nearestHit.hitPosition.x, nearestHit.hitPosition.y, nearestHit.hitPosition.z ); + DrawText( line, 10, ypos, 15, BLACK ); + ypos += 15; + + sprintf( line, "Hit Norm: %3.2f %3.2f %3.2f", + nearestHit.hitNormal.x, nearestHit.hitNormal.y, nearestHit.hitNormal.z ); + DrawText( line, 10, ypos, 15, BLACK ); + ypos += 15; + + if (hitTriangle) { + sprintf( line, "Barycentric: %3.2f %3.2f %3.2f", + bary.x, bary.y, bary.z ); + DrawText( line, 10, ypos, 15, BLACK ); + } + } + + DrawText( "Use Mouse to Move Camera", 10, 420, 15, LIGHTGRAY ); DrawFPS(10, 10); diff --git a/examples/resources/model/lowpoly-tower.obj b/examples/resources/model/lowpoly-tower.obj new file mode 100644 index 00000000..ea03a9fc --- /dev/null +++ b/examples/resources/model/lowpoly-tower.obj @@ -0,0 +1,456 @@ +# Blender v2.78 (sub 0) OBJ File: 'lowpoly-tower.blend' +# www.blender.org +o Grid +v -4.000000 0.000000 4.000000 +v -2.327363 0.000000 4.654725 +v 0.000000 0.000000 4.654725 +v 2.327363 0.000000 4.654725 +v 4.000000 0.000000 4.000000 +v -4.654725 0.955085 2.327363 +v -2.000000 0.815050 2.000000 +v 0.000000 0.476341 2.423448 +v 2.000000 0.476341 2.000000 +v 4.654725 0.000000 2.327363 +v -4.654725 1.649076 0.000000 +v -2.423448 1.092402 0.000000 +v 2.423448 0.198579 0.000000 +v 4.654725 0.000000 0.000000 +v -4.654725 1.649076 -2.327363 +v -2.000000 1.092402 -2.000000 +v 0.000000 0.476341 -2.423448 +v 2.000000 -0.012791 -2.000000 +v 4.654725 0.000000 -2.612731 +v -4.000000 0.955085 -4.000000 +v -2.327363 0.955085 -4.654725 +v 0.000000 0.955085 -4.654725 +v 2.327363 0.000000 -4.654725 +v 4.000000 0.000000 -4.000000 +v 2.423448 0.682825 0.000000 +v 2.000000 0.565423 -2.000000 +v -4.654725 -0.020560 2.327363 +v -4.654725 0.000000 0.000000 +v -4.654725 0.000000 -2.327363 +v -4.000000 0.000000 -4.000000 +v -2.327363 0.000000 -4.654725 +v 0.000000 -0.020560 -4.654725 +v 0.000000 0.709880 -1.230535 +v -0.000000 7.395413 0.000000 +v 0.962071 0.709880 -0.767226 +v -0.533909 0.709880 1.108674 +v -1.199683 0.709880 0.273820 +v -0.962071 0.709880 -0.767226 +v 1.506076 0.859071 1.325337 +v 1.199683 0.709880 0.273820 +v 0.533909 0.709880 1.108674 +v 0.000000 1.875340 -1.177842 +v -0.000000 2.293973 -0.649884 +v -0.000000 4.365648 -0.627970 +v 0.000000 6.167194 -0.942957 +v 0.000000 6.232434 -1.708677 +v 1.335898 6.232434 -1.065343 +v 0.737233 6.167195 -0.587924 +v 0.490966 4.365648 -0.391533 +v 0.508100 2.293973 -0.405196 +v 0.920874 1.875340 -0.734372 +v -0.741367 6.232434 1.539465 +v -0.409133 6.167195 0.849574 +v -0.272466 4.365648 0.565781 +v -0.281974 2.293973 0.585526 +v -0.511047 1.875340 1.061199 +v -1.665837 6.232434 0.380217 +v -0.919314 6.167195 0.209828 +v -0.612225 4.365648 0.139736 +v -0.633590 2.293973 0.144613 +v -1.148311 1.875340 0.262095 +v -1.335898 6.232434 -1.065343 +v -0.737233 6.167195 -0.587924 +v -0.490967 4.365648 -0.391533 +v -0.508100 2.293973 -0.405196 +v -0.920874 1.875340 -0.734372 +v 1.665837 6.232434 0.380216 +v 0.919315 6.167195 0.209828 +v 0.612225 4.365648 0.139736 +v 0.633590 2.293973 0.144613 +v 1.148311 1.875340 0.262095 +v 0.741367 6.232434 1.539465 +v 0.409133 6.167195 0.849575 +v 0.272466 4.365648 0.565781 +v 0.281974 2.293973 0.585526 +v 0.511046 1.875340 1.061199 +v 0.000000 5.012550 -0.969733 +v 0.758168 5.012550 -0.604618 +v -0.420751 5.012550 0.873699 +v -0.945419 5.012550 0.215786 +v -0.758168 5.012550 -0.604618 +v 0.945419 5.012550 0.215786 +v 0.420751 5.012550 0.873699 +vt 0.0523 0.5444 +vt 0.1817 0.4284 +vt 0.1641 0.5859 +vt 0.0177 0.4451 +vt 0.1526 0.3090 +vt 0.0189 0.1737 +vt 0.0188 0.3088 +vt 0.0561 0.0762 +vt 0.1757 0.1924 +vt 0.3024 0.4534 +vt 0.3071 0.5902 +vt 0.3413 0.2459 +vt 0.2906 0.1614 +vt 0.4116 0.1801 +vt 0.2834 0.3774 +vt 0.1526 0.0362 +vt 0.2917 0.1622 +vt 0.4446 0.5865 +vt 0.4443 0.2989 +vt 0.3711 0.3021 +vt 0.4396 0.0275 +vt 0.4094 0.1829 +vt 0.4219 0.4255 +vt 0.5474 0.5381 +vt 0.5811 0.4376 +vt 0.5715 0.1505 +vt 0.5811 0.2997 +vt 0.5272 0.0533 +vt 0.2208 0.2194 +vt 0.3456 0.3610 +vt 0.2878 0.0321 +vt 0.2321 0.3392 +vt 0.4432 0.0177 +vt 0.7347 0.7934 +vt 0.7382 0.7595 +vt 0.8982 0.7768 +vt 0.6169 0.7595 +vt 0.6139 0.7879 +vt 0.4951 0.7634 +vt 0.1551 0.6832 +vt 0.2925 0.6268 +vt 0.2925 0.6832 +vt 0.7795 0.6832 +vt 0.6421 0.6268 +vt 0.7795 0.6255 +vt 0.5046 0.7241 +vt 0.6421 0.7241 +vt 0.3986 0.6268 +vt 0.3986 0.6832 +vt 0.5046 0.6268 +vt 0.0177 0.6268 +vt 0.1551 0.6255 +vt 0.8856 0.6268 +vt 0.1899 0.9579 +vt 0.1194 0.8696 +vt 0.2324 0.8696 +vt 0.1899 0.7813 +vt 0.0943 0.7595 +vt 0.0177 0.8206 +vt 0.0177 0.9186 +vt 0.0943 0.9797 +vt 0.2793 0.2349 +vt 0.2304 0.2758 +vt 0.6597 0.0177 +vt 0.6954 0.0993 +vt 0.6367 0.0768 +vt 0.7558 0.0777 +vt 0.7238 0.0440 +vt 0.8840 0.1330 +vt 0.7385 0.1141 +vt 0.9157 0.0886 +vt 0.9781 0.1232 +vt 0.9224 0.1276 +vt 0.2677 0.8141 +vt 0.3463 0.8037 +vt 0.3086 0.8339 +vt 0.6387 0.3550 +vt 0.7130 0.3801 +vt 0.6596 0.4053 +vt 0.7245 0.3245 +vt 0.6919 0.3383 +vt 0.8655 0.3566 +vt 0.7351 0.3577 +vt 0.9770 0.3365 +vt 0.9078 0.3751 +vt 0.9174 0.3282 +vt 0.2677 0.9018 +vt 0.3086 0.8821 +vt 0.6803 0.2948 +vt 0.6251 0.3035 +vt 0.7194 0.2854 +vt 0.8764 0.2832 +vt 0.9221 0.2861 +vt 0.3363 0.9565 +vt 0.3464 0.9122 +vt 0.6751 0.2482 +vt 0.6178 0.2499 +vt 0.7179 0.2431 +vt 0.9823 0.2484 +vt 0.9247 0.2452 +vt 0.3935 0.9014 +vt 0.6755 0.1996 +vt 0.6164 0.1941 +vt 0.7201 0.1992 +vt 0.8793 0.2446 +vt 0.9823 0.2060 +vt 0.9257 0.2051 +vt 0.4598 0.8580 +vt 0.4144 0.8579 +vt 0.6819 0.1498 +vt 0.6222 0.1361 +vt 0.7266 0.1555 +vt 0.8831 0.1684 +vt 0.9252 0.1659 +vt 0.4218 0.7790 +vt 0.3934 0.8145 +vt 0.3363 0.7595 +vt 0.8815 0.2060 +vt 0.8720 0.3208 +vt 0.8825 0.1012 +vt 0.9735 0.0816 +vt 0.9718 0.3817 +vt 0.9807 0.2918 +vt 0.4218 0.9370 +vt 0.9810 0.1644 +vn 0.1035 0.8806 0.4623 +vn 0.0964 0.9481 0.3030 +vn 0.0000 0.9780 0.2088 +vn 0.0659 0.9835 0.1683 +vn 0.2325 0.9320 0.2779 +vn 0.0553 0.9960 -0.0702 +vn 0.2827 0.9564 0.0728 +vn 0.1873 0.9776 -0.0961 +vn 0.2421 0.9703 0.0000 +vn 0.0921 0.9772 -0.1913 +vn -0.0277 0.9947 -0.0993 +vn 0.2308 0.9274 -0.2944 +vn 0.2771 0.9572 -0.0837 +vn 0.3724 0.9074 0.1947 +vn 0.0777 0.9770 -0.1985 +vn -0.1094 0.9539 0.2794 +vn 0.0364 0.9844 0.1721 +vn 0.1683 0.9835 0.0659 +vn 0.0674 0.9901 0.1230 +vn 0.4338 0.8823 0.1829 +vn 0.2845 0.9565 0.0649 +vn 0.0886 0.9961 0.0000 +vn 0.2000 0.9789 0.0424 +vn 0.1417 0.9830 0.1171 +vn 0.3021 0.9524 0.0412 +vn -0.0193 0.9986 -0.0493 +vn 0.0000 0.9777 0.2098 +vn 0.0005 0.9781 -0.2083 +vn 0.1879 0.9782 -0.0887 +vn 0.2249 0.0000 0.9744 +vn 0.9783 0.0000 -0.2071 +vn 0.9783 0.0000 0.2071 +vn 0.0000 0.0000 -1.0000 +vn -1.0000 0.0000 0.0000 +vn -0.3645 0.0000 -0.9312 +vn -0.9312 0.0000 -0.3645 +vn -0.9312 0.0000 0.3645 +vn 0.2615 0.7979 -0.5431 +vn 0.5877 0.7979 -0.1341 +vn 0.4713 0.7979 0.3758 +vn -0.0000 0.7979 0.6028 +vn -0.4713 0.7979 0.3758 +vn -0.5877 0.7979 -0.1341 +vn -0.2615 0.7979 -0.5431 +vn -0.1285 0.9864 -0.1025 +vn 0.0929 0.8937 0.4389 +vn -0.4335 0.0407 -0.9002 +vn -0.2867 0.7507 -0.5952 +vn -0.4339 0.0095 -0.9009 +vn -0.4338 0.0209 -0.9008 +vn -0.0408 -0.9956 -0.0848 +vn -0.9741 0.0407 -0.2223 +vn -0.6441 0.7507 -0.1470 +vn -0.9749 0.0095 -0.2225 +vn -0.9747 0.0209 -0.2225 +vn -0.0918 -0.9956 -0.0209 +vn -0.7812 0.0407 0.6230 +vn -0.5165 0.7507 0.4119 +vn -0.7818 0.0095 0.6235 +vn -0.7817 0.0209 0.6234 +vn -0.0736 -0.9956 0.0587 +vn -0.0000 0.0407 0.9992 +vn 0.0000 0.7507 0.6607 +vn 0.0000 0.0095 1.0000 +vn -0.0000 0.0209 0.9998 +vn -0.0000 -0.9956 0.0941 +vn 0.7812 0.0407 0.6230 +vn 0.5165 0.7507 0.4119 +vn 0.7818 0.0095 0.6235 +vn 0.7817 0.0209 0.6234 +vn 0.0736 -0.9956 0.0587 +vn 0.9741 0.0407 -0.2223 +vn 0.6441 0.7507 -0.1470 +vn 0.9749 0.0095 -0.2225 +vn 0.9747 0.0209 -0.2225 +vn 0.0918 -0.9956 -0.0209 +vn 0.4335 0.0407 -0.9002 +vn 0.2867 0.7507 -0.5952 +vn 0.4339 0.0095 -0.9009 +vn 0.4338 0.0209 -0.9008 +vn 0.0408 -0.9956 -0.0848 +vn 0.3918 -0.4298 -0.8135 +vn 0.8803 -0.4298 -0.2009 +vn 0.7059 -0.4298 0.5630 +vn -0.0000 -0.4298 0.9029 +vn -0.7059 -0.4298 0.5630 +vn -0.8803 -0.4298 -0.2009 +vn -0.3918 -0.4298 -0.8135 +vn 0.0210 0.9998 -0.0048 +vn 0.0482 0.9981 -0.0385 +vn -0.0166 0.9914 -0.1301 +vn -0.0090 0.9904 -0.1379 +vn 0.2820 0.9576 0.0597 +vn -0.0000 0.9846 0.1749 +vn -0.0921 0.9772 -0.1913 +vn -0.1734 0.9794 0.1036 +s off +f 1/1/1 7/2/1 6/3/1 +f 2/4/2 8/5/2 7/2/2 +f 4/6/3 8/5/3 3/7/3 +f 5/8/4 9/9/4 4/6/4 +f 6/3/5 12/10/5 11/11/5 +f 35/12/6 25/13/6 26/14/6 +f 7/2/7 37/15/7 12/10/7 +f 10/16/8 13/17/8 9/9/8 +f 12/10/9 15/18/9 11/11/9 +f 35/12/10 17/19/10 33/20/10 +f 13/17/11 19/21/11 18/22/11 +f 16/23/12 20/24/12 15/18/12 +f 17/19/13 21/25/13 16/23/13 +f 17/19/14 23/26/14 22/27/14 +f 26/14/15 24/28/15 23/26/15 +f 1/1/16 2/4/16 7/2/16 +f 2/4/3 3/7/3 8/5/3 +f 4/6/17 9/9/17 8/5/17 +f 5/8/18 10/16/18 9/9/18 +f 6/3/19 7/2/19 12/10/19 +f 25/13/20 39/29/20 9/9/20 +f 38/30/21 12/10/21 37/15/21 +f 10/16/22 14/31/22 13/17/22 +f 12/10/23 16/23/23 15/18/23 +f 8/5/24 36/32/24 7/2/24 +f 38/30/25 17/19/25 16/23/25 +f 13/17/22 14/31/22 19/21/22 +f 16/23/26 21/25/26 20/24/26 +f 17/19/27 22/27/27 21/25/27 +f 17/19/28 26/14/28 23/26/28 +f 26/14/29 19/33/29 24/28/29 +f 26/34/30 18/35/30 19/36/30 +f 26/34/31 13/37/31 18/35/31 +f 25/38/32 9/39/32 13/37/32 +f 22/40/33 31/41/33 21/42/33 +f 6/43/34 28/44/34 27/45/34 +f 15/46/34 28/44/34 11/47/34 +f 21/42/35 30/48/35 20/49/35 +f 20/49/36 29/50/36 15/46/36 +f 22/40/33 23/51/33 32/52/33 +f 6/43/37 27/45/37 1/53/37 +f 46/54/38 34/55/38 47/56/38 +f 47/56/39 34/55/39 67/57/39 +f 67/57/40 34/55/40 72/58/40 +f 72/58/41 34/55/41 52/59/41 +f 52/59/42 34/55/42 57/60/42 +f 57/60/43 34/55/43 62/61/43 +f 62/61/44 34/55/44 46/54/44 +f 40/62/45 41/63/45 39/29/45 +f 39/29/46 8/5/46 9/9/46 +f 38/64/47 42/65/47 33/66/47 +f 65/67/48 42/65/48 66/68/48 +f 65/67/49 44/69/49 43/70/49 +f 81/71/50 45/72/50 77/73/50 +f 62/74/51 45/75/51 63/76/51 +f 37/77/52 66/78/52 38/79/52 +f 60/80/53 66/78/53 61/81/53 +f 60/80/54 64/82/54 65/83/54 +f 58/84/55 81/85/55 80/86/55 +f 57/87/56 63/76/56 58/88/56 +f 56/89/57 37/77/57 36/90/57 +f 55/91/58 61/81/58 56/89/58 +f 54/92/59 60/80/59 55/91/59 +f 79/93/60 58/84/60 80/86/60 +f 52/94/61 58/88/61 53/95/61 +f 76/96/62 36/90/62 41/97/62 +f 75/98/63 56/89/63 76/96/63 +f 75/98/64 54/92/64 55/91/64 +f 73/99/65 79/93/65 83/100/65 +f 73/101/66 52/94/66 53/95/66 +f 71/102/67 41/97/67 40/103/67 +f 70/104/68 76/96/68 71/102/68 +f 70/104/69 74/105/69 75/98/69 +f 68/106/70 83/100/70 82/107/70 +f 67/108/71 73/101/71 68/109/71 +f 51/110/72 40/103/72 35/111/72 +f 50/112/73 71/102/73 51/110/73 +f 49/113/74 70/104/74 50/112/74 +f 78/114/75 68/106/75 82/107/75 +f 47/115/76 68/109/76 48/116/76 +f 42/65/77 35/111/77 33/66/77 +f 43/70/78 51/110/78 42/65/78 +f 44/69/79 50/112/79 43/70/79 +f 45/72/80 78/114/80 77/73/80 +f 46/117/81 48/116/81 45/75/81 +f 44/69/82 78/114/82 49/113/82 +f 49/113/83 82/107/83 69/118/83 +f 82/107/84 74/105/84 69/118/84 +f 83/100/85 54/92/85 74/105/85 +f 79/93/86 59/119/86 54/92/86 +f 80/86/87 64/82/87 59/119/87 +f 64/120/88 77/73/88 44/69/88 +f 35/12/89 40/62/89 25/13/89 +f 7/2/90 36/32/90 37/15/90 +f 35/12/91 26/14/91 17/19/91 +f 25/13/92 40/62/92 39/29/92 +f 38/30/93 16/23/93 12/10/93 +f 8/5/94 41/63/94 36/32/94 +f 38/30/95 33/20/95 17/19/95 +f 26/34/31 25/38/31 13/37/31 +f 22/40/33 32/52/33 31/41/33 +f 6/43/34 11/47/34 28/44/34 +f 15/46/34 29/50/34 28/44/34 +f 21/42/35 31/41/35 30/48/35 +f 20/49/36 30/48/36 29/50/36 +f 39/29/96 41/63/96 8/5/96 +f 38/64/47 66/68/47 42/65/47 +f 65/67/48 43/70/48 42/65/48 +f 65/67/49 64/120/49 44/69/49 +f 81/71/50 63/121/50 45/72/50 +f 62/74/51 46/117/51 45/75/51 +f 37/77/52 61/81/52 66/78/52 +f 60/80/53 65/83/53 66/78/53 +f 60/80/54 59/119/54 64/82/54 +f 58/84/55 63/122/55 81/85/55 +f 57/87/56 62/74/56 63/76/56 +f 56/89/57 61/81/57 37/77/57 +f 55/91/58 60/80/58 61/81/58 +f 54/92/59 59/119/59 60/80/59 +f 79/93/60 53/123/60 58/84/60 +f 52/94/61 57/87/61 58/88/61 +f 76/96/62 56/89/62 36/90/62 +f 75/98/63 55/91/63 56/89/63 +f 75/98/64 74/105/64 54/92/64 +f 73/99/65 53/123/65 79/93/65 +f 73/101/66 72/124/66 52/94/66 +f 71/102/67 76/96/67 41/97/67 +f 70/104/68 75/98/68 76/96/68 +f 70/104/69 69/118/69 74/105/69 +f 68/106/70 73/99/70 83/100/70 +f 67/108/71 72/124/71 73/101/71 +f 51/110/72 71/102/72 40/103/72 +f 50/112/73 70/104/73 71/102/73 +f 49/113/74 69/118/74 70/104/74 +f 78/114/75 48/125/75 68/106/75 +f 47/115/76 67/108/76 68/109/76 +f 42/65/77 51/110/77 35/111/77 +f 43/70/78 50/112/78 51/110/78 +f 44/69/79 49/113/79 50/112/79 +f 45/72/80 48/125/80 78/114/80 +f 46/117/81 47/115/81 48/116/81 +f 44/69/82 77/73/82 78/114/82 +f 49/113/83 78/114/83 82/107/83 +f 82/107/84 83/100/84 74/105/84 +f 83/100/85 79/93/85 54/92/85 +f 79/93/86 80/86/86 59/119/86 +f 80/86/87 81/85/87 64/82/87 +f 64/120/88 81/71/88 77/73/88 diff --git a/examples/resources/model/lowpoly-tower.png b/examples/resources/model/lowpoly-tower.png new file mode 100644 index 00000000..7c9239e2 Binary files /dev/null and b/examples/resources/model/lowpoly-tower.png differ diff --git a/src/models.c b/src/models.c index a2043913..41e527dc 100644 --- a/src/models.c +++ b/src/models.c @@ -1918,3 +1918,41 @@ static Material LoadMTL(const char *fileName) return material; } + +RayHitInfo RaycastMesh( Ray ray, Mesh *mesh ) +{ + RayHitInfo result = {0}; + + // If mesh doesn't have vertex data on CPU, can't test it. + if (!mesh->vertices) { + return result; + } + + // mesh->triangleCount may not be set, vertexCount is more reliable + int triangleCount = mesh->vertexCount / 3; + + // Test against all triangles in mesh + for (int i=0; i < triangleCount; i++) { + Vector3 a, b, c; + Vector3 *vertdata = (Vector3*)mesh->vertices; + if (mesh->indices) { + a = vertdata[ mesh->indices[i*3+0] ]; + b = vertdata[ mesh->indices[i*3+1] ]; + c = vertdata[ mesh->indices[i*3+2] ]; + } else { + a = vertdata[i*3+0]; + b = vertdata[i*3+1]; + c = vertdata[i*3+2]; + } + + RayHitInfo triHitInfo = RaycastTriangle( ray, a, b, c ); + if (triHitInfo.hit) { + // Save the closest hit triangle + if ((!result.hit)||(result.distance > triHitInfo.distance)) { + result = triHitInfo; + } + } + } + + return result; +} diff --git a/src/raylib.h b/src/raylib.h index f291ce85..7252ba4e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -497,6 +497,7 @@ typedef struct Ray { // Information returned from a raycast typedef struct RayHitInfo { bool hit; // Did the ray hit something? + float distance; // Distance to nearest hit Vector3 hitPosition; // Position of nearest hit Vector3 hitNormal; // Surface normal of hit } RayHitInfo; @@ -924,6 +925,8 @@ RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box); // Ray Casts //------------------------------------------------------------------------------------ RLAPI RayHitInfo RaycastGroundPlane( Ray ray, float groundHeight ); +RLAPI RayHitInfo RaycastTriangle( Ray ray, Vector3 a, Vector3 b, Vector3 c ); +RLAPI RayHitInfo RaycastMesh( Ray ray, Mesh *mesh ); //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) diff --git a/src/raymath.h b/src/raymath.h index 3cd1394e..5871e350 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -130,6 +130,7 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Ve RMDEF Vector3 VectorZero(void); // Return a Vector3 init to zero RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components +RMDEF Vector3 Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycentric coords for p in triangle abc //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -382,6 +383,31 @@ RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) return result; } +// Compute barycentric coordinates (u, v, w) for +// point p with respect to triangle (a, b, c) +// Assumes P is on the plane of the triangle +RMDEF Vector3 Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c) +{ + + //Vector v0 = b - a, v1 = c - a, v2 = p - a; + Vector3 v0 = VectorSubtract( b, a ); + Vector3 v1 = VectorSubtract( c, a ); + Vector3 v2 = VectorSubtract( p, a ); + float d00 = VectorDotProduct(v0, v0); + float d01 = VectorDotProduct(v0, v1); + float d11 = VectorDotProduct(v1, v1); + float d20 = VectorDotProduct(v2, v0); + float d21 = VectorDotProduct(v2, v1); + float denom = d00 * d11 - d01 * d01; + + Vector3 result; + result.y = (d11 * d20 - d01 * d21) / denom; + result.z = (d00 * d21 - d01 * d20) / denom; + result.x = 1.0f - (result.z + result.y); + + return result; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- diff --git a/src/shapes.c b/src/shapes.c index 4b2de4f2..74480c83 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -544,13 +544,74 @@ RayHitInfo RaycastGroundPlane( Ray ray, float groundHeight ) { float t = (ray.position.y - groundHeight) / -ray.direction.y; if (t >= 0.0) { - Vector3 camDir = ray.direction; - VectorScale( &camDir, t ); - result.hit = true; - result.hitNormal = (Vector3){ 0.0, 1.0, 0.0}; - result.hitPosition = VectorAdd( ray.position, camDir ); + Vector3 rayDir = ray.direction; + VectorScale( &rayDir, t ); + result.hit = true; + result.distance = t; + result.hitNormal = (Vector3){ 0.0, 1.0, 0.0}; + result.hitPosition = VectorAdd( ray.position, rayDir ); } } + return result; +} +// Adapted from: +// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm +RayHitInfo RaycastTriangle( Ray ray, Vector3 a, Vector3 b, Vector3 c ) +{ + Vector3 e1, e2; //Edge1, Edge2 + Vector3 p, q, tv; + float det, inv_det, u, v; + float t; + RayHitInfo result = {0}; + + //Find vectors for two edges sharing V1 + e1 = VectorSubtract( b, a); + e2 = VectorSubtract( c, a); + + //Begin calculating determinant - also used to calculate u parameter + p = VectorCrossProduct( ray.direction, e2); + + //if determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle + det = VectorDotProduct(e1, p); + + //NOT CULLING + if(det > -EPSILON && det < EPSILON) return result; + inv_det = 1.f / det; + + //calculate distance from V1 to ray origin + tv = VectorSubtract( ray.position, a ); + + //Calculate u parameter and test bound + u = VectorDotProduct(tv, p) * inv_det; + + //The intersection lies outside of the triangle + if(u < 0.f || u > 1.f) return result; + + //Prepare to test v parameter + q = VectorCrossProduct( tv, e1 ); + + //Calculate V parameter and test bound + v = VectorDotProduct( ray.direction, q) * inv_det; + + //The intersection lies outside of the triangle + if(v < 0.f || (u + v) > 1.f) return result; + + t = VectorDotProduct(e2, q) * inv_det; + + + if(t > EPSILON) { + // ray hit, get hit point and normal + result.hit = true; + result.distance = t; + result.hit = true; + result.hitNormal = VectorCrossProduct( e1, e2 ); + VectorNormalize( &result.hitNormal ); + Vector3 rayDir = ray.direction; + VectorScale( &rayDir, t ); + result.hitPosition = VectorAdd( ray.position, rayDir ); + } + return result; -} \ No newline at end of file +} + -- cgit v1.2.3 From 658c2806690ace34a0dae6b6ed12d0ea52d2d6e4 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 5 Jan 2017 19:33:05 +0100 Subject: Lattest PR review Function names, code formatting... --- examples/Makefile | 11 ++- examples/core_3d_raypick.c | 195 ----------------------------------------- examples/models_ray_picking.c | 197 ++++++++++++++++++++++++++++++++++++++++++ src/models.c | 167 +++++++++++++++++++++++++++-------- src/raylib.h | 21 ++--- src/raymath.h | 25 +++--- src/shapes.c | 81 ----------------- 7 files changed, 351 insertions(+), 346 deletions(-) delete mode 100644 examples/core_3d_raypick.c create mode 100644 examples/models_ray_picking.c (limited to 'src/models.c') diff --git a/examples/Makefile b/examples/Makefile index 676529c7..80437590 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -203,7 +203,6 @@ EXAMPLES = \ core_gestures_detection \ core_3d_mode \ core_3d_picking \ - core_3d_raypick \ core_3d_camera_free \ core_3d_camera_first_person \ core_2d_camera \ @@ -237,6 +236,7 @@ EXAMPLES = \ models_obj_loading \ models_heightmap \ models_cubicmap \ + models_ray_picking \ shaders_model_shader \ shaders_shapes_textures \ shaders_custom_uniform \ @@ -321,11 +321,6 @@ core_3d_mode: core_3d_mode.c core_3d_picking: core_3d_picking.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) -# compile [core] example - 3d ray picking -core_3d_raypick: core_3d_raypick.c - $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) - - # compile [core] example - 3d camera free core_3d_camera_free: core_3d_camera_free.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) @@ -462,6 +457,10 @@ models_heightmap: models_heightmap.c models_cubicmap: models_cubicmap.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) +# compile [models] example - model ray picking +models_ray_picking: models_ray_picking.c + $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + # compile [shaders] example - model shader shaders_model_shader: shaders_model_shader.c $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) diff --git a/examples/core_3d_raypick.c b/examples/core_3d_raypick.c deleted file mode 100644 index cf56b277..00000000 --- a/examples/core_3d_raypick.c +++ /dev/null @@ -1,195 +0,0 @@ -/******************************************************************************************* -* -* raylib [core] example - Ray-Picking in 3d mode, ground plane, triangle, mesh -* -* This example has been created using raylib 1.3 (www.raylib.com) -* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) -* -* Copyright (c) 2015 Ramon Santamaria (@raysan5) -* Example contributed by Joel Davis (@joeld42) -* -********************************************************************************************/ - -#include "raylib.h" -#include "raymath.h" - -#include -#include - - -int main() -{ - // Initialization - //-------------------------------------------------------------------------------------- - int screenWidth = 800; - int screenHeight = 450; - - InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d ray picking"); - - // Define the camera to look into our 3d world - Camera camera; - camera.position = (Vector3){ 10.0f, 8.0f, 10.0f }; // Camera position - camera.target = (Vector3){ 0.0f, 2.3f, 0.0f }; // Camera looking at point - camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target) - camera.fovy = 45.0f; // Camera field-of-view Y - - Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; - Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; - - Ray ray; // Picking line ray - - Model tower = LoadModel("resources/model/lowpoly-tower.obj"); // Load OBJ model - Texture2D texture = LoadTexture("resources/model/lowpoly-tower.png"); // Load model texture - tower.material.texDiffuse = texture; // Set model diffuse texture - Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position - BoundingBox towerBBox = CalculateBoundingBox( tower.mesh ); - bool hitMeshBBox; - bool hitTriangle; - - // Test triangle - Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 }; - Vector3 tb = (Vector3){ -4.0, 2.5, 1.0 }; - Vector3 tc = (Vector3){ -8.0, 6.5, 0.0 }; - - Vector3 bary = {0}; - - SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - - //-------------------------------------------------------------------------------------- - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - UpdateCamera(&camera); // Update camera - - - // Display information about closest hit - RayHitInfo nearestHit; - char *hitObjectName = "None"; - nearestHit.distance = FLT_MAX; - nearestHit.hit = false; - Color cursorColor = WHITE; - - // Get ray and test against ground, triangle, and mesh - ray = GetMouseRay(GetMousePosition(), camera); - - RayHitInfo groundHitInfo = RaycastGroundPlane( ray, 0.0 ); - if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) { - nearestHit = groundHitInfo; - cursorColor = GREEN; - hitObjectName = "Ground"; - } - - RayHitInfo triHitInfo = RaycastTriangle( ray, ta, tb, tc ); - if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) { - nearestHit = triHitInfo; - cursorColor = PURPLE; - hitObjectName = "Triangle"; - - bary = Barycentric( nearestHit.hitPosition, ta, tb, tc ); - hitTriangle = true; - } else { - hitTriangle = false; - } - - RayHitInfo meshHitInfo; - - // check the bounding box first, before trying the full ray/mesh test - if (CheckCollisionRayBox( ray, towerBBox )) { - hitMeshBBox = true; - meshHitInfo = RaycastMesh( ray, &tower.mesh ); - if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) { - nearestHit = meshHitInfo; - cursorColor = ORANGE; - hitObjectName = "Mesh"; - } - } else { - hitMeshBBox = false; - } - - //---------------------------------------------------------------------------------- - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - Begin3dMode(camera); - - // Draw the tower - DrawModel( tower, towerPos, 1.0, WHITE ); - - // Draw the test triangle - DrawLine3D( ta, tb, PURPLE ); - DrawLine3D( tb, tc, PURPLE ); - DrawLine3D( tc, ta, PURPLE ); - - // Draw the mesh bbox if we hit it - if (hitMeshBBox) { - DrawBoundingBox( towerBBox, LIME ); - } - - // If we hit something, draw the cursor at the hit point - if (nearestHit.hit) { - DrawCube( nearestHit.hitPosition, 0.5, 0.5, 0.5, cursorColor ); - DrawCubeWires( nearestHit.hitPosition, 0.5, 0.5, 0.5, YELLOW ); - - Vector3 normalEnd; - normalEnd.x = nearestHit.hitPosition.x + nearestHit.hitNormal.x; - normalEnd.y = nearestHit.hitPosition.y + nearestHit.hitNormal.y; - normalEnd.z = nearestHit.hitPosition.z + nearestHit.hitNormal.z; - DrawLine3D( nearestHit.hitPosition, normalEnd, YELLOW ); - } - - DrawRay(ray, MAROON); - - DrawGrid(10, 1.0f); - - End3dMode(); - - // Show some debug text - char line[1024]; - sprintf( line, "Hit Object: %s\n", hitObjectName ); - DrawText( line, 10, 30, 15, BLACK ); - - if (nearestHit.hit) { - int ypos = 45; - sprintf( line, "Distance: %3.2f", nearestHit.distance ); - DrawText( line, 10, ypos, 15, BLACK ); - ypos += 15; - - sprintf( line, "Hit Pos: %3.2f %3.2f %3.2f", - nearestHit.hitPosition.x, nearestHit.hitPosition.y, nearestHit.hitPosition.z ); - DrawText( line, 10, ypos, 15, BLACK ); - ypos += 15; - - sprintf( line, "Hit Norm: %3.2f %3.2f %3.2f", - nearestHit.hitNormal.x, nearestHit.hitNormal.y, nearestHit.hitNormal.z ); - DrawText( line, 10, ypos, 15, BLACK ); - ypos += 15; - - if (hitTriangle) { - sprintf( line, "Barycentric: %3.2f %3.2f %3.2f", - bary.x, bary.y, bary.z ); - DrawText( line, 10, ypos, 15, BLACK ); - } - } - - DrawText( "Use Mouse to Move Camera", 10, 420, 15, LIGHTGRAY ); - - DrawFPS(10, 10); - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -} \ No newline at end of file diff --git a/examples/models_ray_picking.c b/examples/models_ray_picking.c new file mode 100644 index 00000000..c578a185 --- /dev/null +++ b/examples/models_ray_picking.c @@ -0,0 +1,197 @@ +/******************************************************************************************* +* +* raylib [models] example - Ray picking in 3d mode, ground plane, triangle, mesh +* +* This example has been created using raylib 1.7 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* Example contributed by Joel Davis (@joeld42) +* +********************************************************************************************/ + +#include "raylib.h" +#include "../src/raymath.h" + +#include +#include + + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - 3d ray picking"); + + // Define the camera to look into our 3d world + Camera camera; + camera.position = (Vector3){ 10.0f, 8.0f, 10.0f }; // Camera position + camera.target = (Vector3){ 0.0f, 2.3f, 0.0f }; // Camera looking at point + camera.up = (Vector3){ 0.0f, 1.6f, 0.0f }; // Camera up vector (rotation towards target) + camera.fovy = 45.0f; // Camera field-of-view Y + + Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; + Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; + + Ray ray; // Picking line ray + + Model tower = LoadModel("resources/model/lowpoly-tower.obj"); // Load OBJ model + Texture2D texture = LoadTexture("resources/model/lowpoly-tower.png"); // Load model texture + tower.material.texDiffuse = texture; // Set model diffuse texture + + Vector3 towerPos = { 0.0f, 0.0f, 0.0f }; // Set model position + BoundingBox towerBBox = CalculateBoundingBox( tower.mesh ); + bool hitMeshBBox = false; + bool hitTriangle = false; + + // Test triangle + Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 }; + Vector3 tb = (Vector3){ -4.0, 2.5, 1.0 }; + Vector3 tc = (Vector3){ -8.0, 6.5, 0.0 }; + + Vector3 bary = { 0.0f, 0.0f, 0.0f }; + + SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + + // Display information about closest hit + RayHitInfo nearestHit; + char *hitObjectName = "None"; + nearestHit.distance = FLT_MAX; + nearestHit.hit = false; + Color cursorColor = WHITE; + + // Get ray and test against ground, triangle, and mesh + ray = GetMouseRay(GetMousePosition(), camera); + + // Check ray collision aginst ground plane + RayHitInfo groundHitInfo = GetCollisionRayGround(ray, 0.0f); + + if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) + { + nearestHit = groundHitInfo; + cursorColor = GREEN; + hitObjectName = "Ground"; + } + + // Check ray collision against test triangle + RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, ta, tb, tc); + + if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) + { + nearestHit = triHitInfo; + cursorColor = PURPLE; + hitObjectName = "Triangle"; + + bary = Barycenter(nearestHit.hitPosition, ta, tb, tc); + hitTriangle = true; + } + else hitTriangle = false; + + RayHitInfo meshHitInfo; + + // Check ray collision against bounding box first, before trying the full ray-mesh test + if (CheckCollisionRayBox(ray, towerBBox)) + { + hitMeshBBox = true; + + // Check ray collision against mesh + meshHitInfo = GetCollisionRayMesh(ray, &tower.mesh); + + if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) + { + nearestHit = meshHitInfo; + cursorColor = ORANGE; + hitObjectName = "Mesh"; + } + + } hitMeshBBox = false; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + // Draw the tower + DrawModel(tower, towerPos, 1.0, WHITE); + + // Draw the test triangle + DrawLine3D(ta, tb, PURPLE); + DrawLine3D(tb, tc, PURPLE); + DrawLine3D(tc, ta, PURPLE); + + // Draw the mesh bbox if we hit it + if (hitMeshBBox) DrawBoundingBox(towerBBox, LIME); + + // If we hit something, draw the cursor at the hit point + if (nearestHit.hit) + { + DrawCube(nearestHit.hitPosition, 0.5, 0.5, 0.5, cursorColor); + DrawCubeWires(nearestHit.hitPosition, 0.5, 0.5, 0.5, YELLOW); + + Vector3 normalEnd; + normalEnd.x = nearestHit.hitPosition.x + nearestHit.hitNormal.x; + normalEnd.y = nearestHit.hitPosition.y + nearestHit.hitNormal.y; + normalEnd.z = nearestHit.hitPosition.z + nearestHit.hitNormal.z; + + DrawLine3D(nearestHit.hitPosition, normalEnd, YELLOW); + } + + DrawRay(ray, MAROON); + + DrawGrid(100, 1.0f); + + End3dMode(); + + // Draw some debug GUI text + DrawText(FormatText("Hit Object: %s", hitObjectName), 10, 50, 10, BLACK); + + if (nearestHit.hit) + { + int ypos = 70; + + DrawText(FormatText("Distance: %3.2f", nearestHit.distance), 10, ypos, 10, BLACK); + + DrawText(FormatText("Hit Pos: %3.2f %3.2f %3.2f", + nearestHit.hitPosition.x, + nearestHit.hitPosition.y, + nearestHit.hitPosition.z), 10, ypos + 15, 10, BLACK); + + DrawText(FormatText("Hit Norm: %3.2f %3.2f %3.2f", + nearestHit.hitNormal.x, + nearestHit.hitNormal.y, + nearestHit.hitNormal.z), 10, ypos + 30, 10, BLACK); + + if (hitTriangle) DrawText(FormatText("Barycenter: %3.2f %3.2f %3.2f", bary.x, bary.y, bary.z), 10, ypos + 45, 10, BLACK); + } + + DrawText("Use Mouse to Move Camera", 10, 430, 10, GRAY); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/src/models.c b/src/models.c index 41e527dc..0673874b 100644 --- a/src/models.c +++ b/src/models.c @@ -1474,6 +1474,135 @@ bool CheckCollisionRayBox(Ray ray, BoundingBox box) return collision; } +// Get collision info between ray and mesh +RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh) +{ + RayHitInfo result = { 0 }; + + // If mesh doesn't have vertex data on CPU, can't test it. + if (!mesh->vertices) return result; + + // mesh->triangleCount may not be set, vertexCount is more reliable + int triangleCount = mesh->vertexCount/3; + + // Test against all triangles in mesh + for (int i = 0; i < triangleCount; i++) + { + Vector3 a, b, c; + Vector3 *vertdata = (Vector3 *)mesh->vertices; + + if (mesh->indices) + { + a = vertdata[mesh->indices[i*3 + 0]]; + b = vertdata[mesh->indices[i*3 + 1]]; + c = vertdata[mesh->indices[i*3 + 2]]; + } + else + { + a = vertdata[i*3 + 0]; + b = vertdata[i*3 + 1]; + c = vertdata[i*3 + 2]; + } + + RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, a, b, c); + + if (triHitInfo.hit) + { + // Save the closest hit triangle + if ((!result.hit) || (result.distance > triHitInfo.distance)) result = triHitInfo; + } + } + + return result; +} + +// Get collision info between ray and triangle +// NOTE: Based on https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm +RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) +{ + #define EPSILON 0.000001 // A small number + + Vector3 edge1, edge2; + Vector3 p, q, tv; + float det, invDet, u, v, t; + RayHitInfo result = {0}; + + // Find vectors for two edges sharing V1 + edge1 = VectorSubtract(p2, p1); + edge2 = VectorSubtract(p3, p1); + + // Begin calculating determinant - also used to calculate u parameter + p = VectorCrossProduct(ray.direction, edge2); + + // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle + det = VectorDotProduct(edge1, p); + + // Avoid culling! + if ((det > -EPSILON) && (det < EPSILON)) return result; + + invDet = 1.0f/det; + + // Calculate distance from V1 to ray origin + tv = VectorSubtract(ray.position, p1); + + // Calculate u parameter and test bound + u = VectorDotProduct(tv, p)*invDet; + + // The intersection lies outside of the triangle + if ((u < 0.0f) || (u > 1.0f)) return result; + + // Prepare to test v parameter + q = VectorCrossProduct(tv, edge1); + + // Calculate V parameter and test bound + v = VectorDotProduct(ray.direction, q)*invDet; + + // The intersection lies outside of the triangle + if ((v < 0.0f) || ((u + v) > 1.0f)) return result; + + t = VectorDotProduct(edge2, q)*invDet; + + if (t > EPSILON) + { + // Ray hit, get hit point and normal + result.hit = true; + result.distance = t; + result.hit = true; + result.hitNormal = VectorCrossProduct(edge1, edge2); + VectorNormalize(&result.hitNormal); + Vector3 rayDir = ray.direction; + VectorScale(&rayDir, t); + result.hitPosition = VectorAdd(ray.position, rayDir); + } + + return result; +} + +// Get collision info between ray and ground plane (Y-normal plane) +RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) +{ + #define EPSILON 0.000001 // A small number + + RayHitInfo result = { 0 }; + + if (fabsf(ray.direction.y) > EPSILON) + { + float t = (ray.position.y - groundHeight)/-ray.direction.y; + + if (t >= 0.0) + { + Vector3 rayDir = ray.direction; + VectorScale(&rayDir, t); + result.hit = true; + result.distance = t; + result.hitNormal = (Vector3){ 0.0, 1.0, 0.0 }; + result.hitPosition = VectorAdd(ray.position, rayDir); + } + } + + return result; +} + // Calculate mesh bounding box limits // NOTE: minVertex and maxVertex should be transformed by model transform matrix (position, scale, rotate) BoundingBox CalculateBoundingBox(Mesh mesh) @@ -1918,41 +2047,3 @@ static Material LoadMTL(const char *fileName) return material; } - -RayHitInfo RaycastMesh( Ray ray, Mesh *mesh ) -{ - RayHitInfo result = {0}; - - // If mesh doesn't have vertex data on CPU, can't test it. - if (!mesh->vertices) { - return result; - } - - // mesh->triangleCount may not be set, vertexCount is more reliable - int triangleCount = mesh->vertexCount / 3; - - // Test against all triangles in mesh - for (int i=0; i < triangleCount; i++) { - Vector3 a, b, c; - Vector3 *vertdata = (Vector3*)mesh->vertices; - if (mesh->indices) { - a = vertdata[ mesh->indices[i*3+0] ]; - b = vertdata[ mesh->indices[i*3+1] ]; - c = vertdata[ mesh->indices[i*3+2] ]; - } else { - a = vertdata[i*3+0]; - b = vertdata[i*3+1]; - c = vertdata[i*3+2]; - } - - RayHitInfo triHitInfo = RaycastTriangle( ray, a, b, c ); - if (triHitInfo.hit) { - // Save the closest hit triangle - if ((!result.hit)||(result.distance > triHitInfo.distance)) { - result = triHitInfo; - } - } - } - - return result; -} diff --git a/src/raylib.h b/src/raylib.h index 7252ba4e..fa4f44e6 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -97,9 +97,6 @@ #define DEG2RAD (PI/180.0f) #define RAD2DEG (180.0f/PI) -// A small number -#define EPSILON 0.000001 - // raylib Config Flags #define FLAG_FULLSCREEN_MODE 1 #define FLAG_RESIZABLE_WINDOW 2 @@ -496,10 +493,10 @@ typedef struct Ray { // Information returned from a raycast typedef struct RayHitInfo { - bool hit; // Did the ray hit something? - float distance; // Distance to nearest hit - Vector3 hitPosition; // Position of nearest hit - Vector3 hitNormal; // Surface normal of hit + bool hit; // Did the ray hit something? + float distance; // Distance to nearest hit + Vector3 hitPosition; // Position of nearest hit + Vector3 hitNormal; // Surface normal of hit } RayHitInfo; // Wave type, defines audio wave data @@ -920,13 +917,9 @@ RLAPI bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphere RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint); // Detect collision between ray and sphere, returns collision point RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box); // Detect collision between ray and box - -//------------------------------------------------------------------------------------ -// Ray Casts -//------------------------------------------------------------------------------------ -RLAPI RayHitInfo RaycastGroundPlane( Ray ray, float groundHeight ); -RLAPI RayHitInfo RaycastTriangle( Ray ray, Vector3 a, Vector3 b, Vector3 c ); -RLAPI RayHitInfo RaycastMesh( Ray ray, Mesh *mesh ); +RLAPI RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh); // Get collision info between ray and mesh +RLAPI RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3); // Get collision info between ray and triangle +RLAPI RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight); // Get collision info between ray and ground plane (Y-normal plane) //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) diff --git a/src/raymath.h b/src/raymath.h index 5871e350..c073b72d 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -130,7 +130,7 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Ve RMDEF Vector3 VectorZero(void); // Return a Vector3 init to zero RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components -RMDEF Vector3 Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycentric coords for p in triangle abc +RMDEF Vector3 Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -383,26 +383,27 @@ RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) return result; } -// Compute barycentric coordinates (u, v, w) for -// point p with respect to triangle (a, b, c) -// Assumes P is on the plane of the triangle -RMDEF Vector3 Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c) +// Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c) +// NOTE: Assumes P is on the plane of the triangle +RMDEF Vector3 Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) { - //Vector v0 = b - a, v1 = c - a, v2 = p - a; - Vector3 v0 = VectorSubtract( b, a ); - Vector3 v1 = VectorSubtract( c, a ); - Vector3 v2 = VectorSubtract( p, a ); + + Vector3 v0 = VectorSubtract(b, a); + Vector3 v1 = VectorSubtract(c, a); + Vector3 v2 = VectorSubtract(p, a); float d00 = VectorDotProduct(v0, v0); float d01 = VectorDotProduct(v0, v1); float d11 = VectorDotProduct(v1, v1); float d20 = VectorDotProduct(v2, v0); float d21 = VectorDotProduct(v2, v1); - float denom = d00 * d11 - d01 * d01; + + float denom = d00*d11 - d01*d01; Vector3 result; - result.y = (d11 * d20 - d01 * d21) / denom; - result.z = (d00 * d21 - d01 * d20) / denom; + + result.y = (d11*d20 - d01*d21)/denom; + result.z = (d00*d21 - d01*d20)/denom; result.x = 1.0f - (result.z + result.y); return result; diff --git a/src/shapes.c b/src/shapes.c index 74480c83..8c6c4be0 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -534,84 +534,3 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2) return retRec; } - - -RayHitInfo RaycastGroundPlane( Ray ray, float groundHeight ) -{ - RayHitInfo result = {0}; - - if (fabs(ray.direction.y) > EPSILON) - { - float t = (ray.position.y - groundHeight) / -ray.direction.y; - if (t >= 0.0) { - Vector3 rayDir = ray.direction; - VectorScale( &rayDir, t ); - result.hit = true; - result.distance = t; - result.hitNormal = (Vector3){ 0.0, 1.0, 0.0}; - result.hitPosition = VectorAdd( ray.position, rayDir ); - } - } - return result; -} -// Adapted from: -// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm -RayHitInfo RaycastTriangle( Ray ray, Vector3 a, Vector3 b, Vector3 c ) -{ - Vector3 e1, e2; //Edge1, Edge2 - Vector3 p, q, tv; - float det, inv_det, u, v; - float t; - RayHitInfo result = {0}; - - //Find vectors for two edges sharing V1 - e1 = VectorSubtract( b, a); - e2 = VectorSubtract( c, a); - - //Begin calculating determinant - also used to calculate u parameter - p = VectorCrossProduct( ray.direction, e2); - - //if determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle - det = VectorDotProduct(e1, p); - - //NOT CULLING - if(det > -EPSILON && det < EPSILON) return result; - inv_det = 1.f / det; - - //calculate distance from V1 to ray origin - tv = VectorSubtract( ray.position, a ); - - //Calculate u parameter and test bound - u = VectorDotProduct(tv, p) * inv_det; - - //The intersection lies outside of the triangle - if(u < 0.f || u > 1.f) return result; - - //Prepare to test v parameter - q = VectorCrossProduct( tv, e1 ); - - //Calculate V parameter and test bound - v = VectorDotProduct( ray.direction, q) * inv_det; - - //The intersection lies outside of the triangle - if(v < 0.f || (u + v) > 1.f) return result; - - t = VectorDotProduct(e2, q) * inv_det; - - - if(t > EPSILON) { - // ray hit, get hit point and normal - result.hit = true; - result.distance = t; - - result.hit = true; - result.hitNormal = VectorCrossProduct( e1, e2 ); - VectorNormalize( &result.hitNormal ); - Vector3 rayDir = ray.direction; - VectorScale( &rayDir, t ); - result.hitPosition = VectorAdd( ray.position, rayDir ); - } - - return result; -} - -- cgit v1.2.3 From 37a64df7b9944d1d24872f07a7e713884b33432e Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 27 Jan 2017 23:03:08 +0100 Subject: Move lighting system out of raylib Lighting is implemented as a raylib example now --- examples/shaders_standard_lighting.c | 366 ++++++++++++++++++++++++++++++++++- src/models.c | 48 ----- src/raylib.h | 26 --- src/rlgl.c | 275 +------------------------- src/shader_standard.h | 173 ----------------- 5 files changed, 366 insertions(+), 522 deletions(-) delete mode 100644 src/shader_standard.h (limited to 'src/models.c') diff --git a/examples/shaders_standard_lighting.c b/examples/shaders_standard_lighting.c index 728bdae0..16cd7ff6 100644 --- a/examples/shaders_standard_lighting.c +++ b/examples/shaders_standard_lighting.c @@ -9,15 +9,79 @@ * on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders * raylib comes with shaders ready for both versions, check raylib/shaders install folder * -* This example has been created using raylib 1.3 (www.raylib.com) +* This example has been created using raylib 1.7 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2016-2017 Ramon Santamaria (@raysan5) * ********************************************************************************************/ #include "raylib.h" +#include // Required for: NULL +#include // Required for: strcpy() +#include // Required for: vector math + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 8 // Max lights supported by standard shader + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- + +// Light type +typedef struct LightData { + unsigned int id; // Light unique id + bool enabled; // Light enabled + int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT + + Vector3 position; // Light position + Vector3 target; // Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) + float radius; // Light attenuation radius light intensity reduced with distance (world distance) + + Color diffuse; // Light diffuse color + float intensity; // Light intensity level + + float coneAngle; // Light cone max angle: LIGHT_SPOT +} LightData, *Light; + +// Light types +typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static Light lights[MAX_LIGHTS]; // Lights pool +static int lightsCount = 0; // Enabled lights counter +static int lightsLocs[MAX_LIGHTS][8]; // Lights location points in shader: 8 possible points per light: + // enabled, type, position, target, radius, diffuse, intensity, coneAngle + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +static Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool +static void DestroyLight(Light light); // Destroy a light and take it out of the list +static void DrawLight(Light light); // Draw light in 3D world + +static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS) +static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights + +// Vector3 math functions +static float VectorLength(const Vector3 v); // Calculate vector lenght +static void VectorNormalize(Vector3 *v); // Normalize provided vector +static Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors + + +//https://www.gamedev.net/topic/655969-speed-gluniform-vs-uniform-buffer-objects/ +//https://www.reddit.com/r/opengl/comments/4ri20g/is_gluniform_more_expensive_than_glprogramuniform/ +//http://cg.alexandra.dk/?p=3778 - AZDO +//https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/BestPracticesforShaders/BestPracticesforShaders.html + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ int main() { // Initialization @@ -39,6 +103,9 @@ int main() material.shader = LoadShader("resources/shaders/glsl330/standard.vs", "resources/shaders/glsl330/standard.fs"); + // Try to get lights location points (if available) + GetShaderLightsLocations(material.shader); + material.texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model diffuse texture material.texNormal = LoadTexture("resources/model/dwarf_normal.png"); // Load model normal texture material.texSpecular = LoadTexture("resources/model/dwarf_specular.png"); // Load model specular texture @@ -64,6 +131,12 @@ int main() pointLight->intensity = 2.0f; pointLight->diffuse = (Color){100, 100, 255, 255}; pointLight->radius = 3.0f; + + // Set shader lights values for enabled lights + // NOTE: If values are not changed in real time, they can be set at initialization!!! + SetShaderLightsValues(material.shader); + + //SetShaderActive(0); // Setup orbital camera SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode @@ -115,8 +188,295 @@ int main() DestroyLight(dirLight); DestroyLight(spotLight); + // Unload lights + if (lightsCount > 0) + { + for (int i = 0; i < lightsCount; i++) free(lights[i]); + lightsCount = 0; + } + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; -} \ No newline at end of file +} + +//-------------------------------------------------------------------------------------------- +// Module Functions Definitions +//-------------------------------------------------------------------------------------------- + +// Create a new light, initialize it and add to pool +Light CreateLight(int type, Vector3 position, Color diffuse) +{ + Light light = NULL; + + if (lightsCount < MAX_LIGHTS) + { + // Allocate dynamic memory + light = (Light)malloc(sizeof(LightData)); + + // Initialize light values with generic values + light->id = lightsCount; + light->type = type; + light->enabled = true; + + light->position = position; + light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; + light->intensity = 1.0f; + light->diffuse = diffuse; + + // Add new light to the array + lights[lightsCount] = light; + + // Increase enabled lights count + lightsCount++; + } + else + { + // NOTE: Returning latest created light to avoid crashes + light = lights[lightsCount]; + } + + return light; +} + +// Destroy a light and take it out of the list +void DestroyLight(Light light) +{ + if (light != NULL) + { + int lightId = light->id; + + // Free dynamic memory allocation + free(lights[lightId]); + + // Remove *obj from the pointers array + for (int i = lightId; i < lightsCount; i++) + { + // Resort all the following pointers of the array + if ((i + 1) < lightsCount) + { + lights[i] = lights[i + 1]; + lights[i]->id = lights[i + 1]->id; + } + } + + // Decrease enabled physic objects count + lightsCount--; + } +} + +// Draw light in 3D world +void DrawLight(Light light) +{ + switch (light->type) + { + case LIGHT_POINT: + { + DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); + + DrawCircle3D(light->position, light->radius, (Vector3){ 0, 0, 0 }, 0.0f, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 1, 0, 0 }, 90.0f, (light->enabled ? light->diffuse : GRAY)); + DrawCircle3D(light->position, light->radius, (Vector3){ 0, 1, 0 },90.0f, (light->enabled ? light->diffuse : GRAY)); + } break; + case LIGHT_DIRECTIONAL: + { + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); + + DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); + } break; + case LIGHT_SPOT: + { + DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); + + Vector3 dir = VectorSubtract(light->target, light->position); + VectorNormalize(&dir); + + DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY)); + + //DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY)); + DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); + } break; + default: break; + } +} + +// Get shader locations for lights (up to MAX_LIGHTS) +static void GetShaderLightsLocations(Shader shader) +{ + char locName[32] = "lights[x].\0"; + char locNameUpdated[64]; + + for (int i = 0; i < MAX_LIGHTS; i++) + { + locName[7] = '0' + i; + + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "enabled\0"); + lightsLocs[i][0] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "type\0"); + lightsLocs[i][1] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "position\0"); + lightsLocs[i][2] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "direction\0"); + lightsLocs[i][3] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "radius\0"); + lightsLocs[i][4] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "diffuse\0"); + lightsLocs[i][5] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "intensity\0"); + lightsLocs[i][6] = GetShaderLocation(shader, locNameUpdated); + + locNameUpdated[0] = '\0'; + strcpy(locNameUpdated, locName); + strcat(locNameUpdated, "coneAngle\0"); + lightsLocs[i][7] = GetShaderLocation(shader, locNameUpdated); + } +} + +// Set shader uniform values for lights +// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0 +// TODO: Replace glUniform1i(), glUniform1f(), glUniform3f(), glUniform4f(): +//SetShaderValue(Shader shader, int uniformLoc, float *value, int size) +//SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) +static void SetShaderLightsValues(Shader shader) +{ + int tempInt[8] = { 0 }; + float tempFloat[8] = { 0.0f }; + + for (int i = 0; i < MAX_LIGHTS; i++) + { + if (i < lightsCount) + { + tempInt[0] = lights[i]->enabled; + SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], lights[i]->enabled); + + tempInt[0] = lights[i]->type; + SetShaderValuei(shader, lightsLocs[i][1], tempInt, 1); //glUniform1i(lightsLocs[i][1], lights[i]->type); + + tempFloat[0] = (float)lights[i]->diffuse.r/255.0f; + tempFloat[1] = (float)lights[i]->diffuse.g/255.0f; + tempFloat[2] = (float)lights[i]->diffuse.b/255.0f; + tempFloat[3] = (float)lights[i]->diffuse.a/255.0f; + SetShaderValue(shader, lightsLocs[i][5], tempFloat, 4); + //glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); + + tempFloat[0] = lights[i]->intensity; + SetShaderValue(shader, lightsLocs[i][6], tempFloat, 1); + + switch (lights[i]->type) + { + case LIGHT_POINT: + { + tempFloat[0] = lights[i]->position.x; + tempFloat[1] = lights[i]->position.y; + tempFloat[2] = lights[i]->position.z; + SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3); + + tempFloat[0] = lights[i]->radius; + SetShaderValue(shader, lightsLocs[i][4], tempFloat, 1); + + //glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + //glUniform1f(lightsLocs[i][4], lights[i]->radius); + } break; + case LIGHT_DIRECTIONAL: + { + Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); + VectorNormalize(&direction); + + tempFloat[0] = direction.x; + tempFloat[1] = direction.y; + tempFloat[2] = direction.z; + SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3); + + //glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); + } break; + case LIGHT_SPOT: + { + tempFloat[0] = lights[i]->position.x; + tempFloat[1] = lights[i]->position.y; + tempFloat[2] = lights[i]->position.z; + SetShaderValue(shader, lightsLocs[i][2], tempFloat, 3); + + //glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); + + Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); + VectorNormalize(&direction); + + tempFloat[0] = direction.x; + tempFloat[1] = direction.y; + tempFloat[2] = direction.z; + SetShaderValue(shader, lightsLocs[i][3], tempFloat, 3); + //glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); + + tempFloat[0] = lights[i]->coneAngle; + SetShaderValue(shader, lightsLocs[i][7], tempFloat, 1); + //glUniform1f(lightsLocs[i][7], lights[i]->coneAngle); + } break; + default: break; + } + } + else + { + tempInt[0] = 0; + SetShaderValuei(shader, lightsLocs[i][0], tempInt, 1); //glUniform1i(lightsLocs[i][0], 0); // Light disabled + } + } +} + +// Calculate vector lenght +float VectorLength(const Vector3 v) +{ + float length; + + length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); + + return length; +} + +// Normalize provided vector +void VectorNormalize(Vector3 *v) +{ + float length, ilength; + + length = VectorLength(*v); + + if (length == 0.0f) length = 1.0f; + + ilength = 1.0f/length; + + v->x *= ilength; + v->y *= ilength; + v->z *= ilength; +} + +// Substract two vectors +Vector3 VectorSubtract(Vector3 v1, Vector3 v2) +{ + Vector3 result; + + result.x = v1.x - v2.x; + result.y = v1.y - v2.y; + result.z = v1.z - v2.z; + + return result; +} diff --git a/src/models.c b/src/models.c index 0673874b..23c2e6fd 100644 --- a/src/models.c +++ b/src/models.c @@ -574,43 +574,6 @@ void DrawGizmo(Vector3 position) rlPopMatrix(); } - -// Draw light in 3D world -void DrawLight(Light light) -{ - switch (light->type) - { - case LIGHT_POINT: - { - DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); - - DrawCircle3D(light->position, light->radius, (Vector3){ 0, 0, 0 }, 0.0f, (light->enabled ? light->diffuse : GRAY)); - DrawCircle3D(light->position, light->radius, (Vector3){ 1, 0, 0 }, 90.0f, (light->enabled ? light->diffuse : GRAY)); - DrawCircle3D(light->position, light->radius, (Vector3){ 0, 1, 0 },90.0f, (light->enabled ? light->diffuse : GRAY)); - } break; - case LIGHT_DIRECTIONAL: - { - DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); - - DrawSphereWires(light->position, 0.3f*light->intensity, 8, 8, (light->enabled ? light->diffuse : GRAY)); - DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); - } break; - case LIGHT_SPOT: - { - DrawLine3D(light->position, light->target, (light->enabled ? light->diffuse : GRAY)); - - Vector3 dir = VectorSubtract(light->target, light->position); - VectorNormalize(&dir); - - DrawCircle3D(light->position, 0.5f, dir, 0.0f, (light->enabled ? light->diffuse : GRAY)); - - //DrawCylinderWires(light->position, 0.0f, 0.3f*light->coneAngle/50, 0.6f, 5, (light->enabled ? light->diffuse : GRAY)); - DrawCubeWires(light->target, 0.3f, 0.3f, 0.3f, (light->enabled ? light->diffuse : GRAY)); - } break; - default: break; - } -} - // Load mesh from file Mesh LoadMesh(const char *fileName) { @@ -751,17 +714,6 @@ Material LoadDefaultMaterial(void) return material; } -// Load standard material (uses material attributes and lighting shader) -// NOTE: Standard shader supports multiple maps and lights -Material LoadStandardMaterial(void) -{ - Material material = LoadDefaultMaterial(); - - material.shader = GetStandardShader(); - - return material; -} - // Unload material from memory void UnloadMaterial(Material material) { diff --git a/src/raylib.h b/src/raylib.h index a47d3c59..f8f17eec 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -12,7 +12,6 @@ * Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF) * Multiple textures support, including compressed formats and mipmaps generation * Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps -* Materials (diffuse, normal, specular) and Lighting (point, directional, spot) support * Powerful math module for Vector, Matrix and Quaternion operations: [raymath] * Audio loading and playing with streaming support and mixing channels [audio] * VR stereo rendering support with configurable HMD device parameters @@ -466,25 +465,6 @@ typedef struct Model { Material material; // Shader and textures data } Model; -// Light type -typedef struct LightData { - unsigned int id; // Light unique id - bool enabled; // Light enabled - int type; // Light type: LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT - - Vector3 position; // Light position - Vector3 target; // Light direction: LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target) - float radius; // Light attenuation radius light intensity reduced with distance (world distance) - - Color diffuse; // Light diffuse color - float intensity; // Light intensity level - - float coneAngle; // Light cone max angle: LIGHT_SPOT -} LightData, *Light; - -// Light types -typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType; - // Ray type (useful for raycast) typedef struct Ray { Vector3 position; // Ray position (origin) @@ -876,7 +856,6 @@ RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) RLAPI void DrawGizmo(Vector3 position); // Draw simple gizmo -RLAPI void DrawLight(Light light); // Draw light in 3D world //DrawTorus(), DrawTeapot() could be useful? //------------------------------------------------------------------------------------ @@ -894,7 +873,6 @@ RLAPI void UnloadModel(Model model); RLAPI Material LoadMaterial(const char *fileName); // Load material from file RLAPI Material LoadMaterialEx(Shader shader, Texture2D diffuse, Color color); // Load material from basic shading data RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader) -RLAPI Material LoadStandardMaterial(void); // Load standard material (uses material attributes and lighting shader) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -930,7 +908,6 @@ RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Loa RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) RLAPI Shader GetDefaultShader(void); // Get default shader -RLAPI Shader GetStandardShader(void); // Get standard shader RLAPI Texture2D GetDefaultTexture(void); // Get default texture RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location @@ -946,9 +923,6 @@ RLAPI void EndShaderMode(void); // End RLAPI void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) RLAPI void EndBlendMode(void); // End blending mode (reset to default: alpha blending) -RLAPI Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool -RLAPI void DestroyLight(Light light); // Destroy a light and take it out of the list - //------------------------------------------------------------------------------------ // VR experience Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 diff --git a/src/rlgl.c b/src/rlgl.c index bcbca227..8ec867eb 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -22,7 +22,6 @@ * GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend * * RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency) -* RLGL_NO_STANDARD_SHADER - Avoid standard shader (shader_standard.h) inclusion * RLGL_NO_DISTORTION_SHADER - Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion * RLGL_OCULUS_SUPPORT - Enable Oculus Rift CV1 functionality * @@ -92,10 +91,6 @@ #include // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()] #endif -#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_STANDARD_SHADER) - #include "shader_standard.h" // Standard shader to be embedded -#endif - #if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER) #include "shader_distortion.h" // Distortion shader to be embedded #endif @@ -118,8 +113,6 @@ #define MAX_DRAWS_BY_TEXTURE 256 // Draws are organized by texture changes #define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations) // NOTE: Every vertex are 3 floats (12 bytes) - -#define MAX_LIGHTS 8 // Max lights supported by standard shader #ifndef GL_SHADING_LANGUAGE_VERSION #define GL_SHADING_LANGUAGE_VERSION 0x8B8C @@ -305,10 +298,7 @@ static bool useTempBuffer = false; // Shader Programs static Shader defaultShader; // Basic shader, support vertex color and diffuse texture -static Shader standardShader; // Shader with support for lighting and materials - // NOTE: Lazy initialization when GetStandardShader() static Shader currentShader; // Shader to be used on rendering (by default, defaultShader) -static bool standardShaderLoaded = false; // Flag to track if standard shader has been loaded // Extension supported flag: VAO static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension) @@ -368,12 +358,6 @@ static unsigned int whiteTexture; static int screenWidth; // Default framebuffer width static int screenHeight; // Default framebuffer height -// Lighting data -static Light lights[MAX_LIGHTS]; // Lights pool -static int lightsCount = 0; // Enabled lights counter -static int lightsLocs[MAX_LIGHTS][8]; // Lights location points in shader: 8 possible points per light: - // enabled, type, position, target, radius, diffuse, intensity, coneAngle - //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- @@ -382,10 +366,8 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring) -static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting) static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) static void UnloadDefaultShader(void); // Unload default shader -static void UnloadStandardShader(void); // Unload standard shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data @@ -397,9 +379,6 @@ static void SetStereoConfig(VrDeviceInfo info); // Set internal projection and modelview matrix depending on eyes tracking data static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); - -static void GetShaderLightsLocations(Shader shader); // Get shader locations for lights (up to MAX_LIGHTS) -static void SetShaderLightsValues(Shader shader); // Set shader uniform values for lights #endif #if defined(RLGL_OCULUS_SUPPORT) @@ -1328,19 +1307,11 @@ void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UnloadDefaultShader(); - UnloadStandardShader(); UnloadDefaultBuffers(); // Delete default white texture glDeleteTextures(1, &whiteTexture); TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); - - // Unload lights - if (lightsCount > 0) - { - for (int i = 0; i < lightsCount; i++) free(lights[i]); - lightsCount = 0; - } free(draws); #endif @@ -2003,8 +1974,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array - // TODO: Support OpenGL 1.1 lighting system - rlPushMatrix(); rlMultMatrixf(MatrixToFloat(transform)); rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); @@ -2070,10 +2039,6 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Check if glossiness is located in shader and upload value int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness"); if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness); - - // Set shader lights values for enabled lights - // NOTE: Lights array location points are obtained on shader loading (if available) - if (lightsCount > 0) SetShaderLightsValues(material.shader); } // Set shader textures (diffuse, normal, specular) @@ -2528,25 +2493,6 @@ Shader GetDefaultShader(void) #endif } -// Get default shader -// NOTE: Inits global variable standardShader -Shader GetStandardShader(void) -{ - Shader shader = { 0 }; - -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (standardShaderLoaded) shader = standardShader; - else - { - // Lazy initialization of standard shader - standardShader = LoadStandardShader(); - shader = standardShader; - } -#endif - - return shader; -} - // Get shader uniform location int GetShaderLocation(Shader shader, const char *uniformName) { @@ -2571,7 +2517,7 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4 else TraceLog(WARNING, "Shader value float array size not supported"); - glUseProgram(0); + //glUseProgram(0); // Avoid reseting current shader program, in case other uniforms are set #endif } @@ -2587,7 +2533,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 else TraceLog(WARNING, "Shader value int array size not supported"); - glUseProgram(0); + //glUseProgram(0); #endif } @@ -2599,7 +2545,7 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); - glUseProgram(0); + //glUseProgram(0); #endif } @@ -2645,73 +2591,6 @@ void EndBlendMode(void) BeginBlendMode(BLEND_ALPHA); } -// Create a new light, initialize it and add to pool -Light CreateLight(int type, Vector3 position, Color diffuse) -{ - Light light = NULL; - - if (lightsCount < MAX_LIGHTS) - { - // Allocate dynamic memory - light = (Light)malloc(sizeof(LightData)); - - // Initialize light values with generic values - light->id = lightsCount; - light->type = type; - light->enabled = true; - - light->position = position; - light->target = (Vector3){ 0.0f, 0.0f, 0.0f }; - light->intensity = 1.0f; - light->diffuse = diffuse; - - // Add new light to the array - lights[lightsCount] = light; - - // Increase enabled lights count - lightsCount++; - } - else - { - TraceLog(WARNING, "Too many lights, only supported up to %i lights", MAX_LIGHTS); - - // NOTE: Returning latest created light to avoid crashes - light = lights[lightsCount]; - } - -#if defined(GRAPHICS_API_OPENGL_11) - TraceLog(WARNING, "Lighting currently not supported on OpenGL 1.1"); -#endif - - return light; -} - -// Destroy a light and take it out of the list -void DestroyLight(Light light) -{ - if (light != NULL) - { - int lightId = light->id; - - // Free dynamic memory allocation - free(lights[lightId]); - - // Remove *obj from the pointers array - for (int i = lightId; i < lightsCount; i++) - { - // Resort all the following pointers of the array - if ((i + 1) < lightsCount) - { - lights[i] = lights[i + 1]; - lights[i]->id = lights[i + 1]->id; - } - } - - // Decrease enabled physic objects count - lightsCount--; - } -} - // Init VR device (or simulator) // NOTE: If device is not available, it fallbacks to default device (simulator) // NOTE: It modifies the global variable: VrDeviceInfo hmd @@ -3209,39 +3088,6 @@ static Shader LoadDefaultShader(void) return shader; } -// Load standard shader -// NOTE: This shader supports: -// - Up to 3 different maps: diffuse, normal, specular -// - Material properties: colAmbient, colDiffuse, colSpecular, glossiness -// - Up to 8 lights: Point, Directional or Spot -static Shader LoadStandardShader(void) -{ - Shader shader; - -#if !defined(RLGL_NO_STANDARD_SHADER) - // Load standard shader (embeded in standard_shader.h) - shader.id = LoadShaderProgram(vStandardShaderStr, fStandardShaderStr); - - if (shader.id != 0) - { - LoadDefaultShaderLocations(&shader); - TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id); - - standardShaderLoaded = true; - } - else - { - TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded, using default shader", shader.id); - shader = GetDefaultShader(); - } -#else - shader = GetDefaultShader(); - TraceLog(WARNING, "[SHDR ID %i] Standard shader not available, using default shader", shader.id); -#endif - - return shader; -} - // Get location handlers to for shader attributes and uniforms // NOTE: If any location is not found, loc point becomes -1 static void LoadDefaultShaderLocations(Shader *shader) @@ -3275,9 +3121,6 @@ static void LoadDefaultShaderLocations(Shader *shader) shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2"); // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) - - // Try to get lights location points (if available) - GetShaderLightsLocations(*shader); } // Unload default shader @@ -3292,20 +3135,6 @@ static void UnloadDefaultShader(void) glDeleteProgram(defaultShader.id); } -// Unload standard shader -static void UnloadStandardShader(void) -{ - glUseProgram(0); -#if !defined(RLGL_NO_STANDARD_SHADER) - //glDetachShader(defaultShader, vertexShader); - //glDetachShader(defaultShader, fragmentShader); - //glDeleteShader(vertexShader); // Already deleted on shader compilation - //glDeleteShader(fragmentShader); // Already deleted on shader compilation - glDeleteProgram(standardShader.id); -#endif -} - - // Load default internal buffers (lines, triangles, quads) static void LoadDefaultBuffers(void) { @@ -3763,104 +3592,6 @@ static void UnloadDefaultBuffers(void) free(quads.indices); } -// Get shader locations for lights (up to MAX_LIGHTS) -static void GetShaderLightsLocations(Shader shader) -{ - char locName[32] = "lights[x].\0"; - char locNameUpdated[64]; - - for (int i = 0; i < MAX_LIGHTS; i++) - { - locName[7] = '0' + i; - - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "enabled\0"); - lightsLocs[i][0] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "type\0"); - lightsLocs[i][1] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "position\0"); - lightsLocs[i][2] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "direction\0"); - lightsLocs[i][3] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "radius\0"); - lightsLocs[i][4] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "diffuse\0"); - lightsLocs[i][5] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "intensity\0"); - lightsLocs[i][6] = glGetUniformLocation(shader.id, locNameUpdated); - - locNameUpdated[0] = '\0'; - strcpy(locNameUpdated, locName); - strcat(locNameUpdated, "coneAngle\0"); - lightsLocs[i][7] = glGetUniformLocation(shader.id, locNameUpdated); - } -} - -// Set shader uniform values for lights -// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0 -static void SetShaderLightsValues(Shader shader) -{ - for (int i = 0; i < MAX_LIGHTS; i++) - { - if (i < lightsCount) - { - glUniform1i(lightsLocs[i][0], lights[i]->enabled); - - glUniform1i(lightsLocs[i][1], lights[i]->type); - glUniform4f(lightsLocs[i][5], (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255); - glUniform1f(lightsLocs[i][6], lights[i]->intensity); - - switch (lights[i]->type) - { - case LIGHT_POINT: - { - glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); - glUniform1f(lightsLocs[i][4], lights[i]->radius); - } break; - case LIGHT_DIRECTIONAL: - { - Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); - VectorNormalize(&direction); - glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); - } break; - case LIGHT_SPOT: - { - glUniform3f(lightsLocs[i][2], lights[i]->position.x, lights[i]->position.y, lights[i]->position.z); - - Vector3 direction = VectorSubtract(lights[i]->target, lights[i]->position); - VectorNormalize(&direction); - glUniform3f(lightsLocs[i][3], direction.x, direction.y, direction.z); - - glUniform1f(lightsLocs[i][7], lights[i]->coneAngle); - } break; - default: break; - } - } - else - { - glUniform1i(lightsLocs[i][0], 0); // Light disabled - } - } -} - // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetStereoConfig(VrDeviceInfo hmd) { diff --git a/src/shader_standard.h b/src/shader_standard.h deleted file mode 100644 index 995c62ea..00000000 --- a/src/shader_standard.h +++ /dev/null @@ -1,173 +0,0 @@ - -// Vertex shader definition to embed, no external file required -static const char vStandardShaderStr[] = -#if defined(GRAPHICS_API_OPENGL_21) -"#version 120 \n" -#elif defined(GRAPHICS_API_OPENGL_ES2) -"#version 100 \n" -#endif -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -"attribute vec3 vertexPosition; \n" -"attribute vec3 vertexNormal; \n" -"attribute vec2 vertexTexCoord; \n" -"attribute vec4 vertexColor; \n" -"varying vec3 fragPosition; \n" -"varying vec3 fragNormal; \n" -"varying vec2 fragTexCoord; \n" -"varying vec4 fragColor; \n" -#elif defined(GRAPHICS_API_OPENGL_33) -"#version 330 \n" -"in vec3 vertexPosition; \n" -"in vec3 vertexNormal; \n" -"in vec2 vertexTexCoord; \n" -"in vec4 vertexColor; \n" -"out vec3 fragPosition; \n" -"out vec3 fragNormal; \n" -"out vec2 fragTexCoord; \n" -"out vec4 fragColor; \n" -#endif -"uniform mat4 mvpMatrix; \n" -"void main() \n" -"{ \n" -" fragPosition = vertexPosition; \n" -" fragNormal = vertexNormal; \n" -" fragTexCoord = vertexTexCoord; \n" -" fragColor = vertexColor; \n" -" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" -"} \n"; - -// Fragment shader definition to embed, no external file required -static const char fStandardShaderStr[] = -#if defined(GRAPHICS_API_OPENGL_21) -"#version 120 \n" -#elif defined(GRAPHICS_API_OPENGL_ES2) -"#version 100 \n" -"precision mediump float; \n" // precision required for OpenGL ES2 (WebGL) -#endif -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -"varying vec3 fragPosition; \n" -"varying vec3 fragNormal; \n" -"varying vec2 fragTexCoord; \n" -"varying vec4 fragColor; \n" -#elif defined(GRAPHICS_API_OPENGL_33) -"#version 330 \n" -"in vec3 fragPosition; \n" -"in vec3 fragNormal; \n" -"in vec2 fragTexCoord; \n" -"in vec4 fragColor; \n" -"out vec4 finalColor; \n" -#endif -"uniform sampler2D texture0; \n" -"uniform sampler2D texture1; \n" -"uniform sampler2D texture2; \n" -"uniform vec4 colAmbient; \n" -"uniform vec4 colDiffuse; \n" -"uniform vec4 colSpecular; \n" -"uniform float glossiness; \n" -"uniform int useNormal; \n" -"uniform int useSpecular; \n" -"uniform mat4 modelMatrix; \n" -"uniform vec3 viewDir; \n" -"struct Light { \n" -" int enabled; \n" -" int type; \n" -" vec3 position; \n" -" vec3 direction; \n" -" vec4 diffuse; \n" -" float intensity; \n" -" float radius; \n" -" float coneAngle; }; \n" -"const int maxLights = 8; \n" -"uniform Light lights[maxLights]; \n" -"\n" -"vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) \n" -"{\n" -" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));\n" -" vec3 surfaceToLight = l.position - surfacePos;\n" -" float brightness = clamp(float(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n))), 0.0, 1.0);\n" -" float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*brightness*l.intensity;\n" -" float spec = 0.0;\n" -" if (diff > 0.0)\n" -" {\n" -" vec3 h = normalize(-l.direction + v);\n" -" spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n" -" }\n" -" return (diff*l.diffuse.rgb + spec*colSpecular.rgb);\n" -"}\n" -"\n" -"vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s)\n" -"{\n" -" vec3 lightDir = normalize(-l.direction);\n" -" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" -" float spec = 0.0;\n" -" if (diff > 0.0)\n" -" {\n" -" vec3 h = normalize(lightDir + v);\n" -" spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n" -" }\n" -" return (diff*l.intensity*l.diffuse.rgb + spec*colSpecular.rgb);\n" -"}\n" -"\n" -"vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s)\n" -"{\n" -" vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1.0));\n" -" vec3 lightToSurface = normalize(surfacePos - l.position);\n" -" vec3 lightDir = normalize(-l.direction);\n" -" float diff = clamp(float(dot(n, lightDir)), 0.0, 1.0)*l.intensity;\n" -" float attenuation = clamp(float(dot(n, lightToSurface)), 0.0, 1.0);\n" -" attenuation = dot(lightToSurface, -lightDir);\n" -" float lightToSurfaceAngle = degrees(acos(attenuation));\n" -" if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;\n" -" float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;\n" -" float diffAttenuation = diff*attenuation;\n" -" float spec = 0.0;\n" -" if (diffAttenuation > 0.0)\n" -" {\n" -" vec3 h = normalize(lightDir + v);\n" -" spec = pow(abs(dot(n, h)), 3.0 + glossiness)*s;\n" -" }\n" -" return (falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb));\n" -"}\n" -"\n" -"void main()\n" -"{\n" -" mat3 normalMatrix = mat3(modelMatrix);\n" -" vec3 normal = normalize(normalMatrix*fragNormal);\n" -" vec3 n = normalize(normal);\n" -" vec3 v = normalize(viewDir);\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" vec4 texelColor = texture2D(texture0, fragTexCoord);\n" -#elif defined(GRAPHICS_API_OPENGL_33) -" vec4 texelColor = texture(texture0, fragTexCoord);\n" -#endif -" vec3 lighting = colAmbient.rgb;\n" -" if (useNormal == 1)\n" -" {\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" n *= texture2D(texture1, fragTexCoord).rgb;\n" -#elif defined(GRAPHICS_API_OPENGL_33) -" n *= texture(texture1, fragTexCoord).rgb;\n" -#endif -" n = normalize(n);\n" -" }\n" -" float spec = 1.0;\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" if (useSpecular == 1) spec = texture2D(texture2, fragTexCoord).r;\n" -#elif defined(GRAPHICS_API_OPENGL_33) -" if (useSpecular == 1) spec = texture(texture2, fragTexCoord).r;\n" -#endif -" for (int i = 0; i < maxLights; i++)\n" -" {\n" -" if (lights[i].enabled == 1)\n" -" {\n" -" if(lights[i].type == 0) lighting += CalcPointLight(lights[i], n, v, spec);\n" -" else if(lights[i].type == 1) lighting += CalcDirectionalLight(lights[i], n, v, spec);\n" -" else if(lights[i].type == 2) lighting += CalcSpotLight(lights[i], n, v, spec);\n" -" }\n" -" }\n" -#if defined(GRAPHICS_API_OPENGL_ES2) || defined(GRAPHICS_API_OPENGL_21) -" gl_FragColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" -#elif defined(GRAPHICS_API_OPENGL_33) -" finalColor = vec4(texelColor.rgb*lighting*colDiffuse.rgb, texelColor.a*colDiffuse.a); \n" -#endif -"}\n"; -- cgit v1.2.3 From c85dfd4bc65099924b3ffa4402c24b73b40d35f6 Mon Sep 17 00:00:00 2001 From: Ray Date: Sat, 28 Jan 2017 23:02:30 +0100 Subject: Remove unecessary spaces... --- src/audio.c | 98 ++++++------ src/core.c | 100 ++++++------ src/models.c | 66 ++++---- src/raylib.h | 26 +-- src/rlgl.c | 488 ++++++++++++++++++++++++++++----------------------------- src/text.c | 60 +++---- src/textures.c | 52 +++--- 7 files changed, 445 insertions(+), 445 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 74a54b04..22da74be 100644 --- a/src/audio.c +++ b/src/audio.c @@ -231,9 +231,9 @@ Wave LoadWave(const char *fileName) else if (strcmp(GetExtension(fileName),"rres") == 0) { RRESData rres = LoadResource(fileName); - + // NOTE: Parameters for RRES_WAVE type are: sampleCount, sampleRate, sampleSize, channels - + if (rres.type == RRES_WAVE) wave = LoadWaveEx(rres.data, rres.param1, rres.param2, rres.param3, rres.param4); else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName); @@ -248,18 +248,18 @@ Wave LoadWave(const char *fileName) Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels) { Wave wave; - + wave.data = data; wave.sampleCount = sampleCount; wave.sampleRate = sampleRate; wave.sampleSize = sampleSize; wave.channels = channels; - + // NOTE: Copy wave data to work with, user is responsible of input data to free Wave cwave = WaveCopy(wave); - + WaveFormat(&cwave, sampleRate, sampleSize, channels); - + return cwave; } @@ -268,9 +268,9 @@ Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int Sound LoadSound(const char *fileName) { Wave wave = LoadWave(fileName); - + Sound sound = LoadSoundFromWave(wave); - + UnloadWave(wave); // Sound is loaded, we can unload wave return sound; @@ -354,7 +354,7 @@ void UnloadWave(Wave wave) void UnloadSound(Sound sound) { alSourceStop(sound.source); - + alDeleteSources(1, &sound.source); alDeleteBuffers(1, &sound.buffer); @@ -369,13 +369,13 @@ void UpdateSound(Sound sound, const void *data, int numSamples) alGetBufferi(sound.buffer, AL_FREQUENCY, &sampleRate); alGetBufferi(sound.buffer, AL_BITS, &sampleSize); // It could also be retrieved from sound.format alGetBufferi(sound.buffer, AL_CHANNELS, &channels); // It could also be retrieved from sound.format - + TraceLog(DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); TraceLog(DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); TraceLog(DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); unsigned int dataSize = numSamples*channels*sampleSize/8; // Size of data in bytes - + alSourceStop(sound.source); // Stop sound alSourcei(sound.source, AL_BUFFER, 0); // Unbind buffer from sound to update //alDeleteBuffers(1, &sound.buffer); // Delete current buffer data @@ -463,18 +463,18 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) if (wave->sampleRate != sampleRate) { // TODO: Resample wave data (upsampling or downsampling) - // NOTE 1: To downsample, you have to drop samples or average them. + // NOTE 1: To downsample, you have to drop samples or average them. // NOTE 2: To upsample, you have to interpolate new samples. - + wave->sampleRate = sampleRate; } - + // Format sample size // NOTE: Only supported 8 bit <--> 16 bit <--> 32 bit if (wave->sampleSize != sampleSize) { void *data = malloc(wave->sampleCount*wave->channels*sampleSize/8); - + for (int i = 0; i < wave->sampleCount; i++) { for (int j = 0; j < wave->channels; j++) @@ -484,30 +484,30 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) if (wave->sampleSize == 16) ((unsigned char *)data)[wave->channels*i + j] = (unsigned char)(((float)(((short *)wave->data)[wave->channels*i + j])/32767.0f)*256); else if (wave->sampleSize == 32) ((unsigned char *)data)[wave->channels*i + j] = (unsigned char)(((float *)wave->data)[wave->channels*i + j]*127.0f + 127); } - else if (sampleSize == 16) + else if (sampleSize == 16) { if (wave->sampleSize == 8) ((short *)data)[wave->channels*i + j] = (short)(((float)(((unsigned char *)wave->data)[wave->channels*i + j] - 127)/256.0f)*32767); else if (wave->sampleSize == 32) ((short *)data)[wave->channels*i + j] = (short)((((float *)wave->data)[wave->channels*i + j])*32767); } - else if (sampleSize == 32) + else if (sampleSize == 32) { if (wave->sampleSize == 8) ((float *)data)[wave->channels*i + j] = (float)(((unsigned char *)wave->data)[wave->channels*i + j] - 127)/256.0f; else if (wave->sampleSize == 16) ((float *)data)[wave->channels*i + j] = (float)(((short *)wave->data)[wave->channels*i + j])/32767.0f; } } } - + wave->sampleSize = sampleSize; free(wave->data); wave->data = data; } - + // Format channels (interlaced mode) // NOTE: Only supported mono <--> stereo if (wave->channels != channels) { void *data = malloc(wave->sampleCount*channels*wave->sampleSize/8); - + if ((wave->channels == 1) && (channels == 2)) // mono ---> stereo (duplicate mono information) { for (int i = 0; i < wave->sampleCount; i++) @@ -529,7 +529,7 @@ void WaveFormat(Wave *wave, int sampleRate, int sampleSize, int channels) else if (wave->sampleSize == 32) ((float *)data)[i] = (((float *)wave->data)[j] + ((float *)wave->data)[j + 1])/2.0f; } } - + // TODO: Add/remove additional interlaced channels wave->channels = channels; @@ -563,15 +563,15 @@ Wave WaveCopy(Wave wave) // NOTE: Security check in case of out-of-range void WaveCrop(Wave *wave, int initSample, int finalSample) { - if ((initSample >= 0) && (initSample < finalSample) && + if ((initSample >= 0) && (initSample < finalSample) && (finalSample > 0) && (finalSample < wave->sampleCount)) { int sampleCount = finalSample - initSample; - + void *data = malloc(sampleCount*wave->channels*wave->sampleSize/8); - + memcpy(data, wave->data + (initSample*wave->channels*wave->sampleSize/8), sampleCount*wave->channels*wave->sampleSize/8); - + free(wave->data); wave->data = data; } @@ -583,7 +583,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) float *GetWaveData(Wave wave) { float *samples = (float *)malloc(wave.sampleCount*wave.channels*sizeof(float)); - + for (int i = 0; i < wave.sampleCount; i++) { for (int j = 0; j < wave.channels; j++) @@ -593,7 +593,7 @@ float *GetWaveData(Wave wave) else if (wave.sampleSize == 32) samples[wave.channels*i + j] = ((float *)wave.data)[wave.channels*i + j]; } } - + return samples; } @@ -632,7 +632,7 @@ Music LoadMusicStream(const char *fileName) else if (strcmp(GetExtension(fileName), "flac") == 0) { music->ctxFlac = drflac_open_file(fileName); - + if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName); else { @@ -641,7 +641,7 @@ Music LoadMusicStream(const char *fileName) music->samplesLeft = music->totalSamples; music->ctxType = MUSIC_AUDIO_FLAC; music->loop = true; // We loop by default - + TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); @@ -728,7 +728,7 @@ void ResumeMusicStream(Music music) void StopMusicStream(Music music) { alSourceStop(music->stream.source); - + switch (music->ctxType) { case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break; @@ -736,7 +736,7 @@ void StopMusicStream(Music music) case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break; default: break; } - + music->samplesLeft = music->totalSamples; } @@ -745,14 +745,14 @@ void UpdateMusicStream(Music music) { ALenum state; ALint processed = 0; - + alGetSourcei(music->stream.source, AL_SOURCE_STATE, &state); // Get music stream state alGetSourcei(music->stream.source, AL_BUFFERS_PROCESSED, &processed); // Get processed buffers if (processed > 0) { bool active = true; - + // NOTE: Using dynamic allocation because it could require more than 16KB void *pcm = calloc(AUDIO_BUFFER_SIZE*music->stream.channels*music->stream.sampleSize/8, 1); @@ -764,7 +764,7 @@ void UpdateMusicStream(Music music) { if (music->samplesLeft >= AUDIO_BUFFER_SIZE) numSamples = AUDIO_BUFFER_SIZE; else numSamples = music->samplesLeft; - + // TODO: Really don't like ctxType thingy... switch (music->ctxType) { @@ -784,7 +784,7 @@ void UpdateMusicStream(Music music) case MUSIC_MODULE_MOD: jar_mod_fillbuffer(&music->ctxMod, pcm, numSamples, 0); break; default: break; } - + UpdateAudioStream(music->stream, pcm, numSamples); music->samplesLeft -= numSamples; @@ -794,12 +794,12 @@ void UpdateMusicStream(Music music) break; } } - + // This error is registered when UpdateAudioStream() fails if (alGetError() == AL_INVALID_VALUE) TraceLog(WARNING, "OpenAL: Error buffering data..."); // Reset audio stream for looping - if (!active) + if (!active) { StopMusicStream(music); // Stop music (and reset) if (music->loop) PlayMusicStream(music); // Play again @@ -810,7 +810,7 @@ void UpdateMusicStream(Music music) // just make sure to play again on window restore if (state != AL_PLAYING) PlayMusicStream(music); } - + free(pcm); } } @@ -866,7 +866,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un stream.sampleRate = sampleRate; stream.sampleSize = sampleSize; - + // Only mono and stereo channels are supported, more channels require AL_EXT_MCFORMATS extension if ((channels > 0) && (channels < 3)) stream.channels = channels; else @@ -910,12 +910,12 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un // Initialize buffer with zeros by default // NOTE: Using dynamic allocation because it requires more than 16KB void *pcm = calloc(AUDIO_BUFFER_SIZE*stream.sampleSize/8*stream.channels, 1); - + for (int i = 0; i < MAX_STREAM_BUFFERS; i++) { alBufferData(stream.buffers[i], stream.format, pcm, AUDIO_BUFFER_SIZE*stream.sampleSize/8*stream.channels, stream.sampleRate); } - + free(pcm); alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers); @@ -1095,7 +1095,7 @@ static Wave LoadWAV(const char *fileName) wave.sampleRate = wavFormat.sampleRate; wave.sampleSize = wavFormat.bitsPerSample; wave.channels = wavFormat.numChannels; - + // NOTE: Only support 8 bit, 16 bit and 32 bit sample sizes if ((wave.sampleSize != 8) && (wave.sampleSize != 16) && (wave.sampleSize != 32)) { @@ -1104,16 +1104,16 @@ static Wave LoadWAV(const char *fileName) } // NOTE: Only support up to 2 channels (mono, stereo) - if (wave.channels > 2) + if (wave.channels > 2) { WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2); TraceLog(WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); } - + // NOTE: subChunkSize comes in bytes, we need to translate it to number of samples wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels; - TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); } } } @@ -1145,7 +1145,7 @@ static Wave LoadOGG(const char *fileName) wave.sampleSize = 16; // 16 bit per sample (short) wave.channels = info.channels; wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); - + float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); @@ -1173,16 +1173,16 @@ static Wave LoadFLAC(const char *fileName) // Decode an entire FLAC file in one go uint64_t totalSampleCount; wave.data = drflac_open_and_decode_file_s16(fileName, &wave.channels, &wave.sampleRate, &totalSampleCount); - + wave.sampleCount = (int)totalSampleCount/wave.channels; wave.sampleSize = 16; - + // NOTE: Only support up to 2 channels (mono, stereo) if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName); else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); - + return wave; } diff --git a/src/core.c b/src/core.c index 8b97314d..ea363fce 100644 --- a/src/core.c +++ b/src/core.c @@ -9,7 +9,7 @@ * External libs: * GLFW3 - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX) * raymath - 3D math functionality (Vector3, Matrix, Quaternion) -* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person) +* camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person) * gestures - Gestures system for touch-ready devices (or simulated from mouse inputs) * * Module Configuration Flags: @@ -103,7 +103,7 @@ #include // Linux: KDSKBMODE, K_MEDIUMRAM constants definition #include // Linux: Keycodes constants definition (KEY_A, ...) #include // Linux: Joystick support library - + #include "bcm_host.h" // Raspberry Pi VideoCore IV access functions #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions @@ -488,9 +488,9 @@ void CloseWindow(void) // Wait for mouse and gamepad threads to finish before closing // NOTE: Those threads should already have finished at this point // because they are controlled by windowShouldClose variable - + windowShouldClose = true; // Added to force threads to exit when the close window is called - + pthread_join(mouseThreadId, NULL); pthread_join(touchThreadId, NULL); pthread_join(gamepadThreadId, NULL); @@ -649,14 +649,14 @@ void EndDrawing(void) frameTime = updateTime + drawTime; // Wait for some milliseconds... - if (frameTime < targetTime) + if (frameTime < targetTime) { Wait((int)((targetTime - frameTime)*1000)); - + currentTime = GetTime(); double extraTime = currentTime - previousTime; previousTime = currentTime; - + frameTime = updateTime + drawTime + extraTime; } } @@ -1147,7 +1147,7 @@ bool IsKeyDown(int key) bool IsKeyReleased(int key) { bool released = false; - + if ((currentKeyState[key] != previousKeyState[key]) && (currentKeyState[key] == 0)) released = true; else released = false; @@ -1182,7 +1182,7 @@ void SetExitKey(int key) bool IsGamepadAvailable(int gamepad) { bool result = false; - + #if !defined(PLATFORM_ANDROID) if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad]) result = true; #endif @@ -1196,7 +1196,7 @@ bool IsGamepadName(int gamepad, const char *name) bool result = false; #if !defined(PLATFORM_ANDROID) - const char *gamepadName = NULL; + const char *gamepadName = NULL; if (gamepadReady[gamepad]) gamepadName = GetGamepadName(gamepad); if ((name != NULL) && (gamepadName != NULL)) result = (strcmp(name, gamepadName) == 0); @@ -1235,7 +1235,7 @@ int GetGamepadAxisCount(int gamepad) float GetGamepadAxisMovement(int gamepad, int axis) { float value = 0; - + #if !defined(PLATFORM_ANDROID) if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (axis < MAX_GAMEPAD_AXIS)) value = gamepadAxisState[gamepad][axis]; #endif @@ -1249,8 +1249,8 @@ bool IsGamepadButtonPressed(int gamepad, int button) bool pressed = false; #if !defined(PLATFORM_ANDROID) - if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && - (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) && + if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && + (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) && (currentGamepadState[gamepad][button] == 1)) pressed = true; #endif @@ -1274,10 +1274,10 @@ bool IsGamepadButtonDown(int gamepad, int button) bool IsGamepadButtonReleased(int gamepad, int button) { bool released = false; - + #if !defined(PLATFORM_ANDROID) - if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && - (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) && + if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && + (currentGamepadState[gamepad][button] != previousGamepadState[gamepad][button]) && (currentGamepadState[gamepad][button] == 0)) released = true; #endif @@ -1290,7 +1290,7 @@ bool IsGamepadButtonUp(int gamepad, int button) bool result = false; #if !defined(PLATFORM_ANDROID) - if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && + if ((gamepad < MAX_GAMEPADS) && gamepadReady[gamepad] && (button < MAX_GAMEPAD_BUTTONS) && (currentGamepadState[gamepad][button] == 0)) result = true; #endif @@ -1503,7 +1503,7 @@ static void InitGraphicsDevice(int width, int height) glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // Resizable window } else glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); // Avoid window being resizable - + //glfwWindowHint(GLFW_DECORATED, GL_TRUE); // Border and buttons on Window //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits //glfwWindowHint(GLFW_DEPTH_BITS, 16); // Depthbuffer bits (24 by default) @@ -1941,7 +1941,7 @@ static double GetTime(void) // Wait for some milliseconds (stop program execution) static void Wait(int ms) { -#if defined _WIN32 +#if defined _WIN32 Sleep(ms); #elif defined __linux || defined(PLATFORM_WEB) struct timespec req = { 0 }; @@ -1949,7 +1949,7 @@ static void Wait(int ms) ms -= (sec*1000); req.tv_sec=sec; req.tv_nsec=ms*1000000L; - + // NOTE: Use nanosleep() on Unix platforms... usleep() it's deprecated. while (nanosleep(&req,&req) == -1) continue; //#elif defined __APPLE__ @@ -1999,10 +1999,10 @@ static void PollInputEvents(void) // NOTE: Gestures update must be called every frame to reset gestures correctly // because ProcessGestureEvent() is just called on an event, not every frame UpdateGestures(); - + // Reset last key pressed registered lastKeyPressed = -1; - + #if !defined(PLATFORM_RPI) // Reset last gamepad button/axis registered state lastGamepadButtonPressed = -1; @@ -2018,7 +2018,7 @@ static void PollInputEvents(void) mousePosition.x = (float)mouseX; mousePosition.y = (float)mouseY; - + // Keyboard input polling (automatically managed by GLFW3 through callback) // Register previous keys states @@ -2039,7 +2039,7 @@ static void PollInputEvents(void) if (glfwJoystickPresent(i)) gamepadReady[i] = true; else gamepadReady[i] = false; } - + // Register gamepads buttons events for (int i = 0; i < MAX_GAMEPADS; i++) { @@ -2047,14 +2047,14 @@ static void PollInputEvents(void) { // Register previous gamepad states for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k]; - + // Get current gamepad state // NOTE: There is no callback available, so we get it manually const unsigned char *buttons; int buttonsCount; buttons = glfwGetJoystickButtons(i, &buttonsCount); - + for (int k = 0; (buttons != NULL) && (k < buttonsCount) && (buttonsCount < MAX_GAMEPAD_BUTTONS); k++) { if (buttons[k] == GLFW_PRESS) @@ -2064,18 +2064,18 @@ static void PollInputEvents(void) } else currentGamepadState[i][k] = 0; } - + // Get current axis state const float *axes; int axisCount = 0; axes = glfwGetJoystickAxes(i, &axisCount); - + for (int k = 0; (axes != NULL) && (k < axisCount) && (k < MAX_GAMEPAD_AXIS); k++) { gamepadAxisState[i][k] = axes[k]; } - + gamepadAxisCount = axisCount; } } @@ -2088,16 +2088,16 @@ static void PollInputEvents(void) #if defined(PLATFORM_WEB) // Get number of gamepads connected int numGamepads = emscripten_get_num_gamepads(); - + for (int i = 0; (i < numGamepads) && (i < MAX_GAMEPADS); i++) { // Register previous gamepad button states for (int k = 0; k < MAX_GAMEPAD_BUTTONS; k++) previousGamepadState[i][k] = currentGamepadState[i][k]; - + EmscriptenGamepadEvent gamepadState; - + int result = emscripten_get_gamepad_status(i, &gamepadState); - + if (result == EMSCRIPTEN_RESULT_SUCCESS) { // Register buttons data for every connected gamepad @@ -2109,16 +2109,16 @@ static void PollInputEvents(void) lastGamepadButtonPressed = j; } else currentGamepadState[i][j] = 0; - + //printf("Gamepad %d, button %d: Digital: %d, Analog: %g\n", gamepadState.index, j, gamepadState.digitalButton[j], gamepadState.analogButton[j]); } - + // Register axis data for every connected gamepad for (int j = 0; (j < gamepadState.numAxes) && (j < MAX_GAMEPAD_AXIS); j++) { gamepadAxisState[i][j] = gamepadState.axis[j]; } - + gamepadAxisCount = gamepadState.numAxes; } } @@ -2665,16 +2665,16 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE { /* printf("%s: timeStamp: %g, connected: %d, index: %ld, numAxes: %d, numButtons: %d, id: \"%s\", mapping: \"%s\"\n", - eventType != 0 ? emscripten_event_type_to_string(eventType) : "Gamepad state", + eventType != 0 ? emscripten_event_type_to_string(eventType) : "Gamepad state", gamepadEvent->timestamp, gamepadEvent->connected, gamepadEvent->index, gamepadEvent->numAxes, gamepadEvent->numButtons, gamepadEvent->id, gamepadEvent->mapping); - + for(int i = 0; i < gamepadEvent->numAxes; ++i) printf("Axis %d: %g\n", i, gamepadEvent->axis[i]); for(int i = 0; i < gamepadEvent->numButtons; ++i) printf("Button %d: Digital: %d, Analog: %g\n", i, gamepadEvent->digitalButton[i], gamepadEvent->analogButton[i]); */ - + if ((gamepadEvent->connected) && (gamepadEvent->index < MAX_GAMEPADS)) gamepadReady[gamepadEvent->index] = true; else gamepadReady[gamepadEvent->index] = false; - + // TODO: Test gamepadEvent->index return 0; @@ -2935,7 +2935,7 @@ static void InitTouch(void) } // Touch reading thread. -// This reads from a Virtual Input Event /dev/input/event4 which is +// This reads from a Virtual Input Event /dev/input/event4 which is // created by the ts_uinput daemon. This takes, filters and scales // raw input from the Touchscreen (which appears in /dev/input/event3) // based on the Calibration data referenced by tslib. @@ -2949,7 +2949,7 @@ static void *TouchThread(void *arg) if (read(touchStream, &ev, sizeof(ev)) == (int)sizeof(ev)) { // if pressure > 0 then simulate left mouse button click - if (ev.type == EV_ABS && ev.code == 24 && ev.value == 0 && currentMouseState[0] == 1) + if (ev.type == EV_ABS && ev.code == 24 && ev.value == 0 && currentMouseState[0] == 1) { currentMouseState[0] = 0; gestureEvent.touchAction = TOUCH_UP; @@ -2963,10 +2963,10 @@ static void *TouchThread(void *arg) gestureEvent.position[1].x /= (float)GetScreenWidth(); gestureEvent.position[1].y /= (float)GetScreenHeight(); ProcessGestureEvent(gestureEvent); - } - if (ev.type == EV_ABS && ev.code == 24 && ev.value > 0 && currentMouseState[0] == 0) + } + if (ev.type == EV_ABS && ev.code == 24 && ev.value > 0 && currentMouseState[0] == 0) { - currentMouseState[0] = 1; + currentMouseState[0] = 1; gestureEvent.touchAction = TOUCH_DOWN; gestureEvent.pointCount = 1; gestureEvent.pointerId[0] = 0; @@ -2978,9 +2978,9 @@ static void *TouchThread(void *arg) gestureEvent.position[1].x /= (float)GetScreenWidth(); gestureEvent.position[1].y /= (float)GetScreenHeight(); ProcessGestureEvent(gestureEvent); - } + } // x & y values supplied by event4 have been scaled & de-jittered using tslib calibration data - if (ev.type == EV_ABS && ev.code == 0) + if (ev.type == EV_ABS && ev.code == 0) { mousePosition.x = ev.value; if (mousePosition.x < 0) mousePosition.x = 0; @@ -2997,7 +2997,7 @@ static void *TouchThread(void *arg) gestureEvent.position[1].y /= (float)GetScreenHeight(); ProcessGestureEvent(gestureEvent); } - if (ev.type == EV_ABS && ev.code == 1) + if (ev.type == EV_ABS && ev.code == 1) { mousePosition.y = ev.value; if (mousePosition.y < 0) mousePosition.y = 0; @@ -3014,7 +3014,7 @@ static void *TouchThread(void *arg) gestureEvent.position[1].y /= (float)GetScreenHeight(); ProcessGestureEvent(gestureEvent); } - + } } return NULL; @@ -3084,7 +3084,7 @@ static void *GamepadThread(void *arg) { // 1 - button pressed, 0 - button released currentGamepadState[i][gamepadEvent.number] = (int)gamepadEvent.value; - + if ((int)gamepadEvent.value == 1) lastGamepadButtonPressed = gamepadEvent.number; else lastGamepadButtonPressed = -1; } diff --git a/src/models.c b/src/models.c index 23c2e6fd..43821691 100644 --- a/src/models.c +++ b/src/models.c @@ -584,7 +584,7 @@ Mesh LoadMesh(const char *fileName) if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - + // TODO: Initialize default mesh data in case loading fails, maybe a cube? return mesh; @@ -607,7 +607,7 @@ Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color mesh.indices = NULL; rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - + return mesh; } @@ -668,7 +668,7 @@ Model LoadCubicmap(Image cubicmap) return model; } - + // Unload mesh from memory (RAM and/or VRAM) void UnloadMesh(Mesh *mesh) { @@ -1438,34 +1438,34 @@ RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh) int triangleCount = mesh->vertexCount/3; // Test against all triangles in mesh - for (int i = 0; i < triangleCount; i++) + for (int i = 0; i < triangleCount; i++) { Vector3 a, b, c; Vector3 *vertdata = (Vector3 *)mesh->vertices; - - if (mesh->indices) + + if (mesh->indices) { a = vertdata[mesh->indices[i*3 + 0]]; b = vertdata[mesh->indices[i*3 + 1]]; - c = vertdata[mesh->indices[i*3 + 2]]; - } - else - { + c = vertdata[mesh->indices[i*3 + 2]]; + } + else + { a = vertdata[i*3 + 0]; b = vertdata[i*3 + 1]; c = vertdata[i*3 + 2]; } RayHitInfo triHitInfo = GetCollisionRayTriangle(ray, a, b, c); - - if (triHitInfo.hit) + + if (triHitInfo.hit) { // Save the closest hit triangle if ((!result.hit) || (result.distance > triHitInfo.distance)) result = triHitInfo; } } - return result; + return result; } // Get collision info between ray and triangle @@ -1478,44 +1478,44 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) Vector3 p, q, tv; float det, invDet, u, v, t; RayHitInfo result = {0}; - + // Find vectors for two edges sharing V1 edge1 = VectorSubtract(p2, p1); edge2 = VectorSubtract(p3, p1); - + // Begin calculating determinant - also used to calculate u parameter p = VectorCrossProduct(ray.direction, edge2); - + // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle det = VectorDotProduct(edge1, p); - + // Avoid culling! if ((det > -EPSILON) && (det < EPSILON)) return result; - + invDet = 1.0f/det; - + // Calculate distance from V1 to ray origin tv = VectorSubtract(ray.position, p1); - + // Calculate u parameter and test bound u = VectorDotProduct(tv, p)*invDet; - + // The intersection lies outside of the triangle if ((u < 0.0f) || (u > 1.0f)) return result; - + // Prepare to test v parameter q = VectorCrossProduct(tv, edge1); - + // Calculate V parameter and test bound v = VectorDotProduct(ray.direction, q)*invDet; - + // The intersection lies outside of the triangle if ((v < 0.0f) || ((u + v) > 1.0f)) return result; - + t = VectorDotProduct(edge2, q)*invDet; - - if (t > EPSILON) - { + + if (t > EPSILON) + { // Ray hit, get hit point and normal result.hit = true; result.distance = t; @@ -1523,10 +1523,10 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) result.hitNormal = VectorCrossProduct(edge1, edge2); VectorNormalize(&result.hitNormal); Vector3 rayDir = ray.direction; - VectorScale(&rayDir, t); + VectorScale(&rayDir, t); result.hitPosition = VectorAdd(ray.position, rayDir); } - + return result; } @@ -1540,8 +1540,8 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) if (fabsf(ray.direction.y) > EPSILON) { float t = (ray.position.y - groundHeight)/-ray.direction.y; - - if (t >= 0.0) + + if (t >= 0.0) { Vector3 rayDir = ray.direction; VectorScale(&rayDir, t); @@ -1551,7 +1551,7 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) result.hitPosition = VectorAdd(ray.position, rayDir); } } - + return result; } diff --git a/src/raylib.h b/src/raylib.h index 97130253..c1c9ebae 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -593,21 +593,21 @@ typedef enum { // rRES data returned when reading a resource, it contains all required data for user (24 byte) typedef struct { unsigned int type; // Resource type (4 byte) - + unsigned int param1; // Resouce parameter 1 (4 byte) unsigned int param2; // Resouce parameter 2 (4 byte) unsigned int param3; // Resouce parameter 3 (4 byte) unsigned int param4; // Resouce parameter 4 (4 byte) - + void *data; // Resource data pointer (4 byte) } RRESData; -typedef enum { - RRES_RAW = 0, - RRES_IMAGE, - RRES_WAVE, - RRES_VERTEX, - RRES_TEXT +typedef enum { + RRES_RAW = 0, + RRES_IMAGE, + RRES_WAVE, + RRES_VERTEX, + RRES_TEXT } RRESDataType; #ifdef __cplusplus @@ -800,7 +800,7 @@ RLAPI Image ImageText(const char *text, int fontSize, Color color); RLAPI Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing, Color tint); // Create an image from text (custom sprite font) RLAPI void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image RLAPI void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color); // Draw text (default font) within an image (destination) -RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, +RLAPI void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, float fontSize, int spacing, Color color); // Draw text (custom sprite font) within an image (destination) RLAPI void ImageFlipVertical(Image *image); // Flip image vertically RLAPI void ImageFlipHorizontal(Image *image); // Flip image horizontally @@ -876,15 +876,15 @@ RLAPI Material LoadDefaultMaterial(void); RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) -RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, +RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) -RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, +RLAPI void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture -RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, +RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec RLAPI BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits @@ -892,7 +892,7 @@ RLAPI bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB RLAPI bool CheckCollisionBoxes(BoundingBox box1, BoundingBox box2); // Detect collision between two bounding boxes RLAPI bool CheckCollisionBoxSphere(BoundingBox box, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere RLAPI bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius); // Detect collision between ray and sphere -RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, +RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint); // Detect collision between ray and sphere, returns collision point RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box); // Detect collision between ray and box RLAPI RayHitInfo GetCollisionRayMesh(Ray ray, Mesh *mesh); // Get collision info between ray and mesh diff --git a/src/rlgl.c b/src/rlgl.c index 8ec867eb..6c4e5927 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2,10 +2,10 @@ * * rlgl - raylib OpenGL abstraction layer * -* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to -* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). +* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to +* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). * -* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal +* When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal * VBO buffers (and VAOs if available). It requires calling 3 functions: * rlglInit() - Initialize internal buffers and auxiliar resources * rlglDraw() - Process internal buffers and send required draw calls @@ -57,7 +57,7 @@ #endif #if defined(GRAPHICS_API_OPENGL_11) - #ifdef __APPLE__ + #ifdef __APPLE__ #include // OpenGL 1.1 library for OSX #else #include // OpenGL 1.1 library @@ -69,7 +69,7 @@ #endif #if defined(GRAPHICS_API_OPENGL_33) - #ifdef __APPLE__ + #ifdef __APPLE__ #include // OpenGL 3 library for OSX #else #define GLAD_IMPLEMENTATION @@ -168,7 +168,7 @@ #if defined(GRAPHICS_API_OPENGL_ES2) #define glClearDepth glClearDepthf - #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER + #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #endif @@ -695,7 +695,7 @@ void rlEnd(void) } break; default: break; } - + // NOTE: Depth increment is dependant on rlOrtho(): z-near and z-far values, // as well as depth buffer bit-depth (16bit or 24bit or 32bit) // Correct increment formula would be: depthInc = (zfar - znear)/pow(2, bits) @@ -880,7 +880,7 @@ void rlDisableTexture(void) glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); #else - // NOTE: If quads batch limit is reached, + // NOTE: If quads batch limit is reached, // we force a draw call and next batch starts if (quads.vCounter/4 >= MAX_QUADS_BATCH) rlglDraw(); #endif @@ -982,7 +982,7 @@ void rlDeleteRenderTextures(RenderTexture2D target) if (target.id != 0) glDeleteFramebuffers(1, &target.id); if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); - + TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); #endif } @@ -999,7 +999,7 @@ void rlDeleteShader(unsigned int id) void rlDeleteVertexArrays(unsigned int id) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (vaoSupported) + if (vaoSupported) { if (id != 0) glDeleteVertexArrays(1, &id); TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); @@ -1061,7 +1061,7 @@ void rlglInit(int width, int height) { // Check OpenGL information and capabilities //------------------------------------------------------------------------------ - + // Print current OpenGL and GLSL version TraceLog(INFO, "GPU: Vendor: %s", glGetString(GL_VENDOR)); TraceLog(INFO, "GPU: Renderer: %s", glGetString(GL_RENDERER)); @@ -1072,14 +1072,14 @@ void rlglInit(int width, int height) //int maxTexSize; //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); //TraceLog(INFO, "GL_MAX_TEXTURE_SIZE: %i", maxTexSize); - + //GL_MAX_TEXTURE_IMAGE_UNITS //GL_MAX_VIEWPORT_DIMS //int numAuxBuffers; //glGetIntegerv(GL_AUX_BUFFERS, &numAuxBuffers); //TraceLog(INFO, "GL_AUX_BUFFERS: %i", numAuxBuffers); - + //GLint numComp = 0; //GLint format[32] = { 0 }; //glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numComp); @@ -1087,7 +1087,7 @@ void rlglInit(int width, int height) //for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]); // NOTE: We don't need that much data on screen... right now... - + #if defined(GRAPHICS_API_OPENGL_11) //TraceLog(INFO, "OpenGL 1.1 (or driver default) profile initialized"); #endif @@ -1095,7 +1095,7 @@ void rlglInit(int width, int height) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Get supported extensions list GLint numExt = 0; - + #if defined(GRAPHICS_API_OPENGL_33) // NOTE: On OpenGL 3.3 VAO and NPOT are supported by default @@ -1105,18 +1105,18 @@ void rlglInit(int width, int height) // We get a list of available extensions and we check for some of them (compressed textures) // NOTE: We don't need to check again supported extensions but we do (GLAD already dealt with that) glGetIntegerv(GL_NUM_EXTENSIONS, &numExt); - + #ifdef _MSC_VER const char **extList = malloc(sizeof(const char *)*numExt); #else const char *extList[numExt]; #endif - + for (int i = 0; i < numExt; i++) extList[i] = (char *)glGetStringi(GL_EXTENSIONS, i); - + #elif defined(GRAPHICS_API_OPENGL_ES2) char *extensions = (char *)glGetString(GL_EXTENSIONS); // One big const string - + // NOTE: We have to duplicate string because glGetString() returns a const value // If not duplicated, it fails in some systems (Raspberry Pi) // Equivalent to function: char *strdup(const char *str) @@ -1125,12 +1125,12 @@ void rlglInit(int width, int height) void *newstr = malloc(len); if (newstr == NULL) extensionsDup = NULL; extensionsDup = (char *)memcpy(newstr, extensions, len); - + // NOTE: String could be splitted using strtok() function (string.h) // NOTE: strtok() modifies the received string, it can not be const - + char *extList[512]; // Allocate 512 strings pointers (2 KB) - + extList[numExt] = strtok(extensionsDup, " "); while (extList[numExt] != NULL) @@ -1138,9 +1138,9 @@ void rlglInit(int width, int height) numExt++; extList[numExt] = strtok(NULL, " "); } - + free(extensionsDup); // Duplicated string must be deallocated - + numExt -= 1; #endif @@ -1158,25 +1158,25 @@ void rlglInit(int width, int height) if (strcmp(extList[i], (const char *)"GL_OES_vertex_array_object") == 0) { vaoSupported = true; - - // The extension is supported by our hardware and driver, try to get related functions pointers + + // The extension is supported by our hardware and driver, try to get related functions pointers // NOTE: emscripten does not support VAOs natively, it uses emulation and it reduces overall performance... glGenVertexArrays = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES"); glBindVertexArray = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); //glIsVertexArray = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES"); // NOTE: Fails in WebGL, omitted } - + // Check NPOT textures support // NOTE: Only check on OpenGL ES, OpenGL 3.3 has NPOT textures full support as core feature if (strcmp(extList[i], (const char *)"GL_OES_texture_npot") == 0) npotSupported = true; #endif - + // DDS texture compression support if ((strcmp(extList[i], (const char *)"GL_EXT_texture_compression_s3tc") == 0) || (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_s3tc") == 0) || - (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) texCompDXTSupported = true; - + (strcmp(extList[i], (const char *)"GL_WEBKIT_WEBGL_compressed_texture_s3tc") == 0)) texCompDXTSupported = true; + // ETC1 texture compression support if ((strcmp(extList[i], (const char *)"GL_OES_compressed_ETC1_RGB8_texture") == 0) || (strcmp(extList[i], (const char *)"GL_WEBGL_compressed_texture_etc1") == 0)) texCompETC1Supported = true; @@ -1189,26 +1189,26 @@ void rlglInit(int width, int height) // ASTC texture compression support if (strcmp(extList[i], (const char *)"GL_KHR_texture_compression_astc_hdr") == 0) texCompASTCSupported = true; - + // Anisotropic texture filter support if (strcmp(extList[i], (const char *)"GL_EXT_texture_filter_anisotropic") == 0) { texAnisotropicFilterSupported = true; - glGetFloatv(0x84FF, &maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT + glGetFloatv(0x84FF, &maxAnisotropicLevel); // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT } - + // Clamp mirror wrap mode supported if (strcmp(extList[i], (const char *)"GL_EXT_texture_mirror_clamp") == 0) texClampMirrorSupported = true; } - + #ifdef _MSC_VER free(extList); #endif - + #if defined(GRAPHICS_API_OPENGL_ES2) if (vaoSupported) TraceLog(INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully"); else TraceLog(WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); - + if (npotSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif @@ -1218,13 +1218,13 @@ void rlglInit(int width, int height) if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported"); if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported"); if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported"); - + if (texAnisotropicFilterSupported) TraceLog(INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel); if (texClampMirrorSupported) TraceLog(INFO, "[EXTENSION] Clamp mirror wrap texture mode supported"); // Initialize buffers, default shaders and default textures //---------------------------------------------------------- - + // Init default white texture unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) @@ -1238,7 +1238,7 @@ void rlglInit(int width, int height) currentShader = defaultShader; // Init default vertex arrays buffers (lines, triangles, quads) - LoadDefaultBuffers(); + LoadDefaultBuffers(); // Init temp vertex buffer, used when transformation required (translate, rotate, scale) tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); @@ -1257,7 +1257,7 @@ void rlglInit(int width, int height) drawsCounter = 1; draws[drawsCounter - 1].textureId = whiteTexture; currentDrawMode = RL_TRIANGLES; // Set default draw mode - + // Init internal matrix stack (emulating OpenGL 1.1) for (int i = 0; i < MATRIX_STACK_SIZE; i++) stack[i] = MatrixIdentity(); @@ -1286,7 +1286,7 @@ void rlglInit(int width, int height) #if defined(GRAPHICS_API_OPENGL_11) // Init state: Color hints (deprecated in OpenGL 3.0+) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Improve quality of color and texture coordinate interpolation glShadeModel(GL_SMOOTH); // Smooth shading between vertex (vertex colors interpolation) #endif @@ -1294,7 +1294,7 @@ void rlglInit(int width, int height) glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set clear color (black) glClearDepth(1.0f); // Set clear depth value (default) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers (depth buffer required for 3D) - + // Store screen size into global variables screenWidth = width; screenHeight = height; @@ -1308,7 +1308,7 @@ void rlglClose(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UnloadDefaultShader(); UnloadDefaultBuffers(); - + // Delete default white texture glDeleteTextures(1, &whiteTexture); TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); @@ -1326,7 +1326,7 @@ void rlglDraw(void) // NOTE: Default buffers upload and draw UpdateDefaultBuffers(); - + if (vrEnabled && vrRendering) DrawDefaultBuffers(2); else DrawDefaultBuffers(1); #endif @@ -1342,7 +1342,7 @@ void rlglLoadExtensions(void *loader) if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); #endif - + #if defined(GRAPHICS_API_OPENGL_21) #ifndef __APPLE__ if (GLAD_GL_VERSION_2_1) TraceLog(INFO, "OpenGL 2.1 profile supported"); @@ -1363,17 +1363,17 @@ void rlglLoadExtensions(void *loader) Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) { Vector3 result = { 0.0f, 0.0f, 0.0f }; - + // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it Matrix matProjView = MatrixMultiply(proj, view); MatrixInvert(&matProjView); - + // Create quaternion from source point Quaternion quat = { source.x, source.y, source.z, 1.0f }; - + // Multiply quat point by unproject matrix QuaternionTransform(&quat, matProjView); - + // Normalized world points in vectors result.x = quat.x/quat.w; result.y = quat.y/quat.w; @@ -1388,41 +1388,41 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding GLuint id = 0; - + // Check texture format support by OpenGL 1.1 (compressed textures not supported) -#if defined(GRAPHICS_API_OPENGL_11) +#if defined(GRAPHICS_API_OPENGL_11) if (textureFormat >= 8) { TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); return id; } #endif - + if ((!texCompDXTSupported) && ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT1_RGBA) || (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA))) { TraceLog(WARNING, "DXT compressed texture format not supported"); return id; } -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if ((!texCompETC1Supported) && (textureFormat == COMPRESSED_ETC1_RGB)) { TraceLog(WARNING, "ETC1 compressed texture format not supported"); return id; } - + if ((!texCompETC2Supported) && ((textureFormat == COMPRESSED_ETC2_RGB) || (textureFormat == COMPRESSED_ETC2_EAC_RGBA))) { TraceLog(WARNING, "ETC2 compressed texture format not supported"); return id; } - + if ((!texCompPVRTSupported) && ((textureFormat == COMPRESSED_PVRT_RGB) || (textureFormat == COMPRESSED_PVRT_RGBA))) { TraceLog(WARNING, "PVRT compressed texture format not supported"); return id; } - + if ((!texCompASTCSupported) && ((textureFormat == COMPRESSED_ASTC_4x4_RGBA) || (textureFormat == COMPRESSED_ASTC_8x8_RGBA))) { TraceLog(WARNING, "ASTC compressed texture format not supported"); @@ -1450,24 +1450,24 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma // GL_RGBA4 GL_RGBA GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_4_4_4_4 // GL_RGBA8 GL_RGBA GL_UNSIGNED_BYTE // GL_RGB8 GL_RGB GL_UNSIGNED_BYTE - + switch (textureFormat) { case UNCOMPRESSED_GRAYSCALE: { glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); - + // With swizzleMask we define how a one channel texture will be mapped to RGBA // Required GL >= 3.3 or EXT_texture_swizzle/ARB_texture_swizzle GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - + TraceLog(INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id); } break; case UNCOMPRESSED_GRAY_ALPHA: { glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, width, height, 0, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); - + GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); } break; @@ -1541,7 +1541,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma // Magnification and minification filters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Alternative: GL_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Alternative: GL_LINEAR - + #if defined(GRAPHICS_API_OPENGL_33) if (mipmapCount > 1) { @@ -1551,7 +1551,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma #endif // At this point we have the texture loaded in GPU and texture parameters configured - + // NOTE: If mipmaps were not in data, they are not generated automatically // Unbind current texture @@ -1567,15 +1567,15 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma RenderTexture2D rlglLoadRenderTexture(int width, int height) { RenderTexture2D target; - + target.id = 0; - + target.texture.id = 0; target.texture.width = width; target.texture.height = height; target.texture.format = UNCOMPRESSED_R8G8B8A8; target.texture.mipmaps = 1; - + target.depth.id = 0; target.depth.width = width; target.depth.height = height; @@ -1592,13 +1592,13 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); - + #if defined(GRAPHICS_API_OPENGL_33) #define USE_DEPTH_TEXTURE #else #define USE_DEPTH_RENDERBUFFER #endif - + #if defined(USE_DEPTH_RENDERBUFFER) // Create the renderbuffer that will serve as the depth attachment for the framebuffer. glGenRenderbuffers(1, &target.depth.id); @@ -1634,7 +1634,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) if (status != GL_FRAMEBUFFER_COMPLETE) { TraceLog(WARNING, "Framebuffer object could not be created..."); - + switch (status) { case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break; @@ -1645,17 +1645,17 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break; default: break; } - + glDeleteTextures(1, &target.texture.id); glDeleteTextures(1, &target.depth.id); glDeleteFramebuffers(1, &target.id); } else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", target.id); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif - return target; + return target; } // Update already loaded texture in GPU with new data @@ -1695,11 +1695,11 @@ void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void rlglGenerateMipmaps(Texture2D *texture) { glBindTexture(GL_TEXTURE_2D, texture->id); - + // Check if texture is power-of-two (POT) bool texIsPOT = false; - - if (((texture->width > 0) && ((texture->width & (texture->width - 1)) == 0)) && + + if (((texture->width > 0) && ((texture->width & (texture->width - 1)) == 0)) && ((texture->height > 0) && ((texture->height & (texture->height - 1)) == 0))) texIsPOT = true; if ((texIsPOT) || (npotSupported)) @@ -1707,7 +1707,7 @@ void rlglGenerateMipmaps(Texture2D *texture) #if defined(GRAPHICS_API_OPENGL_11) // Compute required mipmaps void *data = rlglReadTexturePixels(*texture); - + // NOTE: data size is reallocated to fit mipmaps data // NOTE: CPU mipmap generation only supports RGBA 32bit data int mipmapCount = GenerateMipmaps(data, texture->width, texture->height); @@ -1729,12 +1729,12 @@ void rlglGenerateMipmaps(Texture2D *texture) mipWidth /= 2; mipHeight /= 2; } - + TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture->id); - + // NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data free(data); - + texture->mipmaps = mipmapCount + 1; #endif @@ -1745,10 +1745,10 @@ void rlglGenerateMipmaps(Texture2D *texture) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps - + #define MIN(a,b) (((a)<(b))?(a):(b)) #define MAX(a,b) (((a)>(b))?(a):(b)) - + texture->mipmaps = 1 + (int)floor(log(MAX(texture->width, texture->height))/log(2)); #endif } @@ -1768,7 +1768,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) mesh->vboId[4] = 0; // Vertex tangents VBO mesh->vboId[5] = 0; // Vertex texcoords2 VBO mesh->vboId[6] = 0; // Vertex indices VBO - + #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) int drawHint = GL_STATIC_DRAW; if (dynamic) drawHint = GL_DYNAMIC_DRAW; @@ -1783,8 +1783,8 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) glBindVertexArray(vaoId); } - // NOTE: Attributes must be uploaded considering default locations points - + // NOTE: Attributes must be uploaded considering default locations points + // Enable vertex attributes: position (shader-location = 0) glGenBuffers(1, &vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, vboId[0]); @@ -1814,7 +1814,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) glVertexAttrib3f(2, 1.0f, 1.0f, 1.0f); glDisableVertexAttribArray(2); } - + // Default color vertex attribute (shader-location = 3) if (mesh->colors != NULL) { @@ -1830,7 +1830,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) glVertexAttrib4f(3, 1.0f, 1.0f, 1.0f, 1.0f); glDisableVertexAttribArray(3); } - + // Default tangent vertex attribute (shader-location = 4) if (mesh->tangents != NULL) { @@ -1846,7 +1846,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) glVertexAttrib3f(4, 0.0f, 0.0f, 0.0f); glDisableVertexAttribArray(4); } - + // Default texcoord2 vertex attribute (shader-location = 5) if (mesh->texcoords2 != NULL) { @@ -1862,7 +1862,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) glVertexAttrib2f(5, 0.0f, 0.0f); glDisableVertexAttribArray(5); } - + if (mesh->indices != NULL) { glGenBuffers(1, &vboId[6]); @@ -1900,7 +1900,7 @@ void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Activate mesh VAO if (vaoSupported) glBindVertexArray(mesh.vaoId); - + switch (buffer) { case 0: // Update vertices (vertex position) @@ -1908,28 +1908,28 @@ void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.vertices, GL_DYNAMIC_DRAW); else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.vertices); - + } break; case 1: // Update texcoords (vertex texture coordinates) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*numVertex, mesh.texcoords, GL_DYNAMIC_DRAW); else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*2*numVertex, mesh.texcoords); - + } break; case 2: // Update normals (vertex normals) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*numVertex, mesh.normals, GL_DYNAMIC_DRAW); else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float)*3*numVertex, mesh.normals); - + } break; case 3: // Update colors (vertex colors) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); if (numVertex >= mesh.vertexCount) glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*numVertex, mesh.colors, GL_DYNAMIC_DRAW); else glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*numVertex, mesh.colors); - + } break; case 4: // Update tangents (vertex tangents) { @@ -1945,7 +1945,7 @@ void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) } break; default: break; } - + // Unbind the current VAO if (vaoSupported) glBindVertexArray(0); @@ -1973,11 +1973,11 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords); // Pointer to texture coords array if (mesh.normals != NULL) glNormalPointer(GL_FLOAT, 0, mesh.normals); // Pointer to normals array if (mesh.colors != NULL) glColorPointer(4, GL_UNSIGNED_BYTE, 0, mesh.colors); // Pointer to colors array - + rlPushMatrix(); rlMultMatrixf(MatrixToFloat(transform)); rlColor4ub(material.colDiffuse.r, material.colDiffuse.g, material.colDiffuse.b, material.colDiffuse.a); - + if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, mesh.indices); else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); rlPopMatrix(); @@ -1996,13 +1996,13 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) if (vrEnabled) eyesCount = 2; glUseProgram(material.shader.id); - + // Upload to shader material.colDiffuse glUniform4f(material.shader.colDiffuseLoc, (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255); - + // Upload to shader material.colAmbient (if available) if (material.shader.colAmbientLoc != -1) glUniform4f(material.shader.colAmbientLoc, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); - + // Upload to shader material.colSpecular (if available) if (material.shader.colSpecularLoc != -1) glUniform4f(material.shader.colSpecularLoc, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); @@ -2010,7 +2010,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() Matrix matView = modelview; // View matrix (camera) Matrix matProjection = projection; // Projection matrix (perspective) - + // Calculate model-view matrix combining matModel and matView Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates @@ -2026,7 +2026,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) Matrix transInvTransform = transform; MatrixTranspose(&transInvTransform); MatrixInvert(&transInvTransform); - + // Send model transformations matrix to shader glUniformMatrix4fv(modelMatrixLoc, 1, false, MatrixToFloat(transInvTransform)); } @@ -2039,7 +2039,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Check if glossiness is located in shader and upload value int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness"); if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness); - } + } // Set shader textures (diffuse, normal, specular) glActiveTexture(GL_TEXTURE0); @@ -2050,22 +2050,22 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) { // Upload to shader specular map flag glUniform1i(glGetUniformLocation(material.shader.id, "useNormal"), 1); - + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, material.texNormal.id); glUniform1i(material.shader.mapTexture1Loc, 1); // Normal texture fits in active texture unit 1 } - + if ((material.texSpecular.id != 0) && (material.shader.mapTexture2Loc != -1)) { // Upload to shader specular map flag glUniform1i(glGetUniformLocation(material.shader.id, "useSpecular"), 1); - + glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); glUniform1i(material.shader.mapTexture2Loc, 2); // Specular texture fits in active texture unit 2 } - + if (vaoSupported) { glBindVertexArray(mesh.vaoId); @@ -2089,7 +2089,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(material.shader.normalLoc); } - + // Bind mesh VBO data: vertex colors (shader-location = 3, if available) if (material.shader.colorLoc != -1) { @@ -2107,7 +2107,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glDisableVertexAttribArray(material.shader.colorLoc); } } - + // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) if (material.shader.tangentLoc != -1) { @@ -2115,7 +2115,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(material.shader.tangentLoc); } - + // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) if (material.shader.texcoord2Loc != -1) { @@ -2123,7 +2123,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); glEnableVertexAttribArray(material.shader.texcoord2Loc); } - + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } @@ -2142,13 +2142,13 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); } - + if (material.texNormal.id != 0) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); } - + if (material.texSpecular.id != 0) { glActiveTexture(GL_TEXTURE2); @@ -2166,7 +2166,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) } glUseProgram(0); // Unbind shader program - + // Restore projection/modelview matrices projection = matProjection; modelview = matView; @@ -2212,7 +2212,7 @@ unsigned char *rlglReadScreenPixels(int width, int height) { // Flip line imgData[((height - 1) - y)*width*4 + x] = screenData[(y*width*4) + x]; - + // Set alpha component value to 255 (no trasparent image retrieval) // NOTE: Alpha value has already been applied to RGB in framebuffer, we don't need it! if (((x + 1)%4) == 0) imgData[((height - 1) - y)*width*4 + x] = 255; @@ -2230,10 +2230,10 @@ unsigned char *rlglReadScreenPixels(int width, int height) void *rlglReadTexturePixels(Texture2D texture) { void *pixels = NULL; - + #if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) glBindTexture(GL_TEXTURE_2D, texture.id); - + // NOTE: Using texture.id, we can retrieve some texture info (but not on OpenGL ES 2.0) /* int width, height, format; @@ -2242,11 +2242,11 @@ void *rlglReadTexturePixels(Texture2D texture) glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); // Other texture info: GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE */ - + int glFormat = 0, glType = 0; unsigned int size = texture.width*texture.height; - + // NOTE: GL_LUMINANCE and GL_LUMINANCE_ALPHA are removed since OpenGL 3.1 // Must be replaced by GL_RED and GL_RG on Core OpenGL 3.3 @@ -2255,8 +2255,8 @@ void *rlglReadTexturePixels(Texture2D texture) #if defined(GRAPHICS_API_OPENGL_11) case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE; break; // 8 bit per pixel (no alpha) case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_LUMINANCE_ALPHA; glType = GL_UNSIGNED_BYTE; break; // 16 bpp (2 channels) -#elif defined(GRAPHICS_API_OPENGL_33) - case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_RED; glType = GL_UNSIGNED_BYTE; break; +#elif defined(GRAPHICS_API_OPENGL_33) + case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_RED; glType = GL_UNSIGNED_BYTE; break; case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_RG; glType = GL_UNSIGNED_BYTE; break; #endif case UNCOMPRESSED_R5G6B5: pixels = (unsigned short *)malloc(size); glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; break; // 16 bpp @@ -2266,15 +2266,15 @@ void *rlglReadTexturePixels(Texture2D texture) case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break; // 32 bpp default: TraceLog(WARNING, "Texture data retrieval, format not suported"); break; } - + // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding. - // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. - // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) + // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. + // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.) glPixelStorei(GL_PACK_ALIGNMENT, 1); glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels); - + glBindTexture(GL_TEXTURE_2D, 0); #endif @@ -2285,7 +2285,7 @@ void *rlglReadTexturePixels(Texture2D texture) // NOTE: Two possible Options: // 1 - Bind texture to color fbo attachment and glReadPixels() // 2 - Create an fbo, activate it, render quad with texture, glReadPixels() - + #define GET_TEXTURE_FBO_OPTION_1 // It works #if defined(GET_TEXTURE_FBO_OPTION_1) @@ -2295,48 +2295,48 @@ void *rlglReadTexturePixels(Texture2D texture) // Attach our texture to FBO -> Texture must be RGB // NOTE: Previoust attached texture is automatically detached glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0); - + pixels = (unsigned char *)malloc(texture.width*texture.height*4*sizeof(unsigned char)); - + // NOTE: Despite FBO color texture is RGB, we read data as RGBA... reading as RGB doesn't work... o__O glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - + // Re-attach internal FBO color texture before deleting it glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo.texture.id, 0); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); - + #elif defined(GET_TEXTURE_FBO_OPTION_2) // Render texture to fbo glBindFramebuffer(GL_FRAMEBUFFER, fbo.id); - + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepthf(1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, width, height); //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); - rlOrtho(0.0, width, height, 0.0, 0.0, 1.0); + rlOrtho(0.0, width, height, 0.0, 0.0, 1.0); //glMatrixMode(GL_MODELVIEW); //glLoadIdentity(); //glDisable(GL_TEXTURE_2D); //glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); - + Model quad; //quad.mesh = GenMeshQuad(width, height); quad.transform = MatrixIdentity(); quad.shader = defaultShader; - + DrawModel(quad, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, WHITE); - + pixels = (unsigned char *)malloc(texture.width*texture.height*3*sizeof(unsigned char)); - + glReadPixels(0, 0, texture.width, texture.height, GL_RGB, GL_UNSIGNED_BYTE, pixels); // Bind framebuffer 0, which means render to back buffer glBindFramebuffer(GL_FRAMEBUFFER, 0); - + UnloadModel(quad); #endif // GET_TEXTURE_FBO_OPTION @@ -2361,7 +2361,7 @@ void rlglRecordDraw(void) draws[drawsCounter].projection = projection; draws[drawsCounter].modelview = modelview; draws[drawsCounter].vertexCount = currentState.vertexCount; - + drawsCounter++; #endif } @@ -2376,13 +2376,13 @@ void rlglRecordDraw(void) Texture2D GetDefaultTexture(void) { Texture2D texture; - + texture.id = whiteTexture; texture.width = 1; texture.height = 1; texture.mipmaps = 1; texture.format = UNCOMPRESSED_R8G8B8A8; - + return texture; } @@ -2429,24 +2429,24 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Shaders loading from external text file char *vShaderStr = LoadText(vsFileName); char *fShaderStr = LoadText(fsFileName); - + if ((vShaderStr != NULL) && (fShaderStr != NULL)) { shader.id = LoadShaderProgram(vShaderStr, fShaderStr); // After shader loading, we try to load default location names if (shader.id != 0) LoadDefaultShaderLocations(&shader); - + // Shader strings must be freed free(vShaderStr); free(fShaderStr); } - + if (shader.id == 0) { TraceLog(WARNING, "Custom shader could not be loaded"); shader = defaultShader; - } + } #endif return shader; @@ -2497,9 +2497,9 @@ Shader GetDefaultShader(void) int GetShaderLocation(Shader shader, const char *uniformName) { int location = -1; -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shader.id, uniformName); - + if (location == -1) TraceLog(DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); #endif return location; @@ -2516,7 +2516,7 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) else if (size == 3) glUniform3fv(uniformLoc, 1, value); // Shader uniform type: vec3 else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4 else TraceLog(WARNING, "Shader value float array size not supported"); - + //glUseProgram(0); // Avoid reseting current shader program, in case other uniforms are set #endif } @@ -2532,7 +2532,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) else if (size == 3) glUniform3iv(uniformLoc, 1, value); // Shader uniform type: ivec3 else if (size == 4) glUniform4iv(uniformLoc, 1, value); // Shader uniform type: ivec4 else TraceLog(WARNING, "Shader value int array size not supported"); - + //glUseProgram(0); #endif } @@ -2544,7 +2544,7 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) glUseProgram(shader.id); glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); - + //glUseProgram(0); #endif } @@ -2572,7 +2572,7 @@ void BeginBlendMode(int mode) if ((blendMode != mode) && (mode < 3)) { rlglDraw(); - + switch (mode) { case BLEND_ALPHA: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; @@ -2580,7 +2580,7 @@ void BeginBlendMode(int mode) case BLEND_MULTIPLIED: glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; default: break; } - + blendMode = mode; } } @@ -2646,9 +2646,9 @@ void InitVrDevice(int vrDevice) { // Oculus Rift CV1 parameters // NOTE: CV1 represents a complete HMD redesign compared to previous versions, - // new Fresnel-hybrid-asymmetric lenses have been added and, consequently, - // previous parameters (DK2) and distortion shader (DK2) doesn't work any more. - // I just defined a set of parameters for simulator that approximate to CV1 stereo rendering + // new Fresnel-hybrid-asymmetric lenses have been added and, consequently, + // previous parameters (DK2) and distortion shader (DK2) doesn't work any more. + // I just defined a set of parameters for simulator that approximate to CV1 stereo rendering // but result is not the same obtained with Oculus PC SDK. hmd.hResolution = 2160; // HMD horizontal resolution in pixels hmd.vResolution = 1200; // HMD vertical resolution in pixels @@ -2667,17 +2667,17 @@ void InitVrDevice(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 } - + // Initialize framebuffer and textures for stereo rendering // NOTE: screen size should match HMD aspect ratio vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); - + // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); SetStereoConfig(hmd); - + vrSimulator = true; vrEnabled = true; } @@ -2722,9 +2722,9 @@ void ToggleVrMode(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if (vrDeviceReady || vrSimulator) vrEnabled = !vrEnabled; else vrEnabled = false; - + if (!vrEnabled) - { + { // Reset viewport and default projection-modelview matrices rlViewport(0, 0, screenWidth, screenHeight); projection = MatrixOrtho(0, screenWidth, screenHeight, 0, 0.0f, 1.0f); @@ -2759,15 +2759,15 @@ void BeginVrDrawing(void) rlEnableRenderTexture(vrConfig.stereoFbo.id); } - // NOTE: If your application is configured to treat the texture as a linear format (e.g. GL_RGBA) + // NOTE: If your application is configured to treat the texture as a linear format (e.g. GL_RGBA) // and performs linear-to-gamma conversion in GLSL or does not care about gamma-correction, then: // - Require OculusBuffer format to be OVR_FORMAT_R8G8B8A8_UNORM_SRGB // - Do NOT enable GL_FRAMEBUFFER_SRGB //glEnable(GL_FRAMEBUFFER_SRGB); - + //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye) rlClearScreenBuffers(); // Clear current framebuffer(s) - + vrRendering = true; #endif } @@ -2786,12 +2786,12 @@ void EndVrDrawing(void) { // Unbind current framebuffer rlDisableRenderTexture(); - + rlClearScreenBuffers(); // Clear current framebuffer // Set viewport to default framebuffer size (screen size) rlViewport(0, 0, screenWidth, screenHeight); - + // Let rlgl reconfigure internal matrices rlMatrixMode(RL_PROJECTION); // Enable internal projection matrix rlLoadIdentity(); // Reset internal projection matrix @@ -2799,7 +2799,7 @@ void EndVrDrawing(void) rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix rlLoadIdentity(); // Reset internal modelview matrix - // Draw RenderTexture (stereoFbo) using distortion shader + // Draw RenderTexture (stereoFbo) using distortion shader currentShader = vrConfig.distortionShader; rlEnableTexture(vrConfig.stereoFbo.texture.id); @@ -2836,7 +2836,7 @@ void EndVrDrawing(void) } rlDisableDepthTest(); - + vrRendering = false; #endif } @@ -2867,7 +2867,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in for (int level = 0; level < mipmapCount && (width || height); level++) { unsigned int size = 0; - + size = ((width + 3)/4)*((height + 3)/4)*blockSize; glCompressedTexImage2D(GL_TEXTURE_2D, level, compressedFormat, width, height, 0, size, data + offset); @@ -2923,7 +2923,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade glGetShaderInfoLog(vertexShader, maxLength, &length, log); TraceLog(INFO, "%s", log); - + #ifdef _MSC_VER free(log); #endif @@ -2962,7 +2962,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); - + // NOTE: Default attribute shader locations must be binded before linking glBindAttribLocation(program, 0, DEFAULT_ATTRIB_POSITION_NAME); glBindAttribLocation(program, 1, DEFAULT_ATTRIB_TEXCOORD_NAME); @@ -2970,11 +2970,11 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade glBindAttribLocation(program, 3, DEFAULT_ATTRIB_COLOR_NAME); glBindAttribLocation(program, 4, DEFAULT_ATTRIB_TANGENT_NAME); glBindAttribLocation(program, 5, DEFAULT_ATTRIB_TEXCOORD2_NAME); - + // NOTE: If some attrib name is no found on the shader, it locations becomes -1 - + glLinkProgram(program); - + // NOTE: All uniform variables are intitialised to 0 when a program links glGetProgramiv(program, GL_LINK_STATUS, &success); @@ -2996,7 +2996,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade glGetProgramInfoLog(program, maxLength, &length, log); TraceLog(INFO, "%s", log); - + #ifdef _MSC_VER free(log); #endif @@ -3099,7 +3099,7 @@ static void LoadDefaultShaderLocations(Shader *shader) // vertex color location = 3 // vertex tangent location = 4 // vertex texcoord2 location = 5 - + // Get handles to GLSL input attibute locations shader->vertexLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); shader->texcoordLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME); @@ -3115,15 +3115,15 @@ static void LoadDefaultShaderLocations(Shader *shader) shader->colDiffuseLoc = glGetUniformLocation(shader->id, "colDiffuse"); shader->colAmbientLoc = glGetUniformLocation(shader->id, "colAmbient"); shader->colSpecularLoc = glGetUniformLocation(shader->id, "colSpecular"); - + shader->mapTexture0Loc = glGetUniformLocation(shader->id, "texture0"); shader->mapTexture1Loc = glGetUniformLocation(shader->id, "texture1"); shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2"); - + // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) } -// Unload default shader +// Unload default shader static void UnloadDefaultShader(void) { glUseProgram(0); @@ -3140,7 +3140,7 @@ static void LoadDefaultBuffers(void) { // [CPU] Allocate and initialize float array buffers to store vertex data (lines, triangles, quads) //-------------------------------------------------------------------------------------------- - + // Lines - Initialize 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 = (unsigned char *)malloc(sizeof(unsigned char)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line @@ -3202,11 +3202,11 @@ static void LoadDefaultBuffers(void) TraceLog(INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)"); //-------------------------------------------------------------------------------------------- - + // [GPU] Upload vertex data and initialize VAOs/VBOs (lines, triangles, quads) // NOTE: Default buffers are linked to use currentShader (defaultShader) //-------------------------------------------------------------------------------------------- - + // Upload and link lines vertex buffers if (vaoSupported) { @@ -3215,7 +3215,7 @@ static void LoadDefaultBuffers(void) glBindVertexArray(lines.vaoId); } - // Lines - Vertex buffers binding and attributes enable + // Lines - Vertex buffers binding and attributes enable // Vertex position buffer (shader-location = 0) glGenBuffers(2, &lines.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); @@ -3241,7 +3241,7 @@ static void LoadDefaultBuffers(void) glBindVertexArray(triangles.vaoId); } - // Triangles - Vertex buffers binding and attributes enable + // Triangles - Vertex buffers binding and attributes enable // Vertex position buffer (shader-location = 0) glGenBuffers(1, &triangles.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); @@ -3267,7 +3267,7 @@ static void LoadDefaultBuffers(void) glBindVertexArray(quads.vaoId); } - // Quads - Vertex buffers binding and attributes enable + // Quads - Vertex buffers binding and attributes enable // Vertex position buffer (shader-location = 0) glGenBuffers(1, &quads.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); @@ -3383,7 +3383,7 @@ static void DrawDefaultBuffers(int eyesCount) { Matrix matProjection = projection; Matrix matModelView = modelview; - + for (int eye = 0; eye < eyesCount; eye++) { if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView); @@ -3392,17 +3392,17 @@ static void DrawDefaultBuffers(int eyesCount) if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) { glUseProgram(currentShader.id); - + // Create modelview-projection matrix Matrix matMVP = MatrixMultiply(modelview, projection); glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); glUniform4f(currentShader.colDiffuseLoc, 1.0f, 1.0f, 1.0f, 1.0f); glUniform1i(currentShader.mapTexture0Loc, 0); - + // NOTE: Additional map textures not considered for default buffers drawing } - + // Draw lines buffers if (lines.vCounter > 0) { @@ -3486,7 +3486,7 @@ static void DrawDefaultBuffers(int eyesCount) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); glEnableVertexAttribArray(currentShader.colorLoc); - + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } @@ -3526,7 +3526,7 @@ static void DrawDefaultBuffers(int eyesCount) glUseProgram(0); // Unbind shader program } - + // Reset draws counter drawsCounter = 1; draws[0].textureId = whiteTexture; @@ -3540,10 +3540,10 @@ static void DrawDefaultBuffers(int eyesCount) quads.vCounter = 0; quads.tcCounter = 0; quads.cCounter = 0; - + // Reset depth for next draw currentDepth = -1.0f; - + // Restore projection/modelview matrices projection = matProjection; modelview = matModelView; @@ -3604,34 +3604,34 @@ static void SetStereoConfig(VrDeviceInfo hmd) float rightLensCenter[2] = { 0.75f - lensShift, 0.5f }; float leftScreenCenter[2] = { 0.25f, 0.5f }; float rightScreenCenter[2] = { 0.75f, 0.5f }; - + // Compute distortion scale parameters // NOTE: To get lens max radius, lensShift must be normalized to [-1..1] float lensRadius = fabsf(-1.0f - 4.0f*lensShift); float lensRadiusSq = lensRadius*lensRadius; - float distortionScale = hmd.distortionK[0] + - hmd.distortionK[1]*lensRadiusSq + - hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + + float distortionScale = hmd.distortionK[0] + + hmd.distortionK[1]*lensRadiusSq + + hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; - + TraceLog(DEBUG, "VR: Distortion Scale: %f", distortionScale); - + float normScreenWidth = 0.5f; float normScreenHeight = 1.0f; float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect }; float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale }; - + TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); - + // Update distortion shader with lens and distortion-scale parameters SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftScreenCenter"), leftScreenCenter, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightScreenCenter"), rightScreenCenter, 2); - + SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scale"), scale, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4); @@ -3641,24 +3641,24 @@ static void SetStereoConfig(VrDeviceInfo hmd) // ...but with lens distortion it is increased (see Oculus SDK Documentation) //float fovy = 2.0f*atan2(hmd.vScreenSize*0.5f*distortionScale, hmd.eyeToScreenDistance)*RAD2DEG; // Really need distortionScale? float fovy = 2.0f*(float)atan2(hmd.vScreenSize*0.5f, hmd.eyeToScreenDistance)*RAD2DEG; - + // Compute camera projection matrices float projOffset = 4.0f*lensShift; // Scaled to projection space coordinates [-1..1] Matrix proj = MatrixPerspective(fovy, aspect, 0.01, 1000.0); vrConfig.eyesProjection[0] = MatrixMultiply(proj, MatrixTranslate(projOffset, 0.0f, 0.0f)); vrConfig.eyesProjection[1] = MatrixMultiply(proj, MatrixTranslate(-projOffset, 0.0f, 0.0f)); - + // NOTE: Projection matrices must be transposed due to raymath convention MatrixTranspose(&vrConfig.eyesProjection[0]); MatrixTranspose(&vrConfig.eyesProjection[1]); - + // Compute camera transformation matrices - // NOTE: Camera movement might seem more natural if we model the head. - // Our axis of rotation is the base of our head, so we might want to add + // NOTE: Camera movement might seem more natural if we model the head. + // Our axis of rotation is the base of our head, so we might want to add // some y (base of head to eye level) and -z (center of head to eye protrusion) to the camera positions. vrConfig.eyesViewOffset[0] = MatrixTranslate(-hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); vrConfig.eyesViewOffset[1] = MatrixTranslate(hmd.interpupillaryDistance*0.5f, 0.075f, 0.045f); - + // Compute eyes Viewports //vrConfig.eyesViewport[0] = (Rectangle){ 0, 0, hmd.hResolution/2, hmd.vResolution }; //vrConfig.eyesViewport[1] = (Rectangle){ hmd.hResolution/2, 0, hmd.hResolution/2, hmd.vResolution }; @@ -3675,17 +3675,17 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) #if defined(RLGL_OCULUS_SUPPORT) if (vrDeviceReady) { - rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, + rlViewport(layer.eyeLayer.Viewport[eye].Pos.x, layer.eyeLayer.Viewport[eye].Pos.y, layer.eyeLayer.Viewport[eye].Size.w, layer.eyeLayer.Viewport[eye].Size.h); - Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, - layer.eyeLayer.RenderPose[eye].Orientation.y, - layer.eyeLayer.RenderPose[eye].Orientation.z, + Quaternion eyeRenderPose = (Quaternion){ layer.eyeLayer.RenderPose[eye].Orientation.x, + layer.eyeLayer.RenderPose[eye].Orientation.y, + layer.eyeLayer.RenderPose[eye].Orientation.z, layer.eyeLayer.RenderPose[eye].Orientation.w }; QuaternionInvert(&eyeRenderPose); Matrix eyeOrientation = QuaternionToMatrix(eyeRenderPose); - Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, - -layer.eyeLayer.RenderPose[eye].Position.y, + Matrix eyeTranslation = MatrixTranslate(-layer.eyeLayer.RenderPose[eye].Position.x, + -layer.eyeLayer.RenderPose[eye].Position.y, -layer.eyeLayer.RenderPose[eye].Position.z); Matrix eyeView = MatrixMultiply(eyeTranslation, eyeOrientation); // Matrix containing eye-head movement @@ -3701,7 +3701,7 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) // Apply view offset to modelview matrix eyeModelView = MatrixMultiply(matModelView, vrConfig.eyesViewOffset[eye]); - + eyeProjection = vrConfig.eyesProjection[eye]; } @@ -3845,7 +3845,7 @@ OCULUSAPI bool InitOculusDevice(void) bool oculusReady = false; ovrResult result = ovr_Initialize(NULL); - + if (OVR_FAILURE(result)) TraceLog(WARNING, "OVR: Could not initialize Oculus device"); else { @@ -3865,24 +3865,24 @@ OCULUSAPI bool InitOculusDevice(void) TraceLog(INFO, "OVR: Product Type: %i", hmdDesc.Type); //TraceLog(INFO, "OVR: Serial Number: %s", hmdDesc.SerialNumber); TraceLog(INFO, "OVR: Resolution: %ix%i", hmdDesc.Resolution.w, hmdDesc.Resolution.h); - + // NOTE: Oculus mirror is set to defined screenWidth and screenHeight... // ...ideally, it should be (hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2) - + // Initialize Oculus Buffers - layer = InitOculusLayer(session); + layer = InitOculusLayer(session); buffer = LoadOculusBuffer(session, layer.width, layer.height); mirror = LoadOculusMirror(session, hmdDesc.Resolution.w/2, hmdDesc.Resolution.h/2); // NOTE: hardcoded... layer.eyeLayer.ColorTexture[0] = buffer.textureChain; //SetOculusLayerTexture(eyeLayer, buffer.textureChain); - + // Recenter OVR tracking origin ovr_RecenterTrackingOrigin(session); - + oculusReady = true; vrEnabled = true; } } - + return oculusReady; } @@ -3903,18 +3903,18 @@ OCULUSAPI void UpdateOculusTracking(Camera *camera) ovrPosef eyePoses[2]; ovr_GetEyePoses(session, frameIndex, ovrTrue, layer.viewScaleDesc.HmdToEyeOffset, eyePoses, &layer.eyeLayer.SensorSampleTime); - + layer.eyeLayer.RenderPose[0] = eyePoses[0]; layer.eyeLayer.RenderPose[1] = eyePoses[1]; - + // TODO: Update external camera with eyePoses data (position, orientation) // NOTE: We can simplify to simple camera if we consider IPD and HMD device configuration again later // it will be useful for the user to draw, lets say, billboards oriented to camera - + // Get session status information ovrSessionStatus sessionStatus; ovr_GetSessionStatus(session, &sessionStatus); - + if (sessionStatus.ShouldQuit) TraceLog(WARNING, "OVR: Session should quit..."); if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session); //if (sessionStatus.HmdPresent) // HMD is present. @@ -3928,7 +3928,7 @@ OCULUSAPI void BeginOculusDrawing(void) { GLuint currentTexId; int currentIndex; - + ovr_GetTextureSwapChainCurrentIndex(session, buffer.textureChain, ¤tIndex); ovr_GetTextureSwapChainBufferGL(session, buffer.textureChain, currentIndex, ¤tTexId); @@ -3943,9 +3943,9 @@ OCULUSAPI void EndOculusDrawing(void) // Unbind current framebuffer (Oculus buffer) glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - + ovr_CommitTextureSwapChain(session, buffer.textureChain); - + ovrLayerHeader *layers = &layer.eyeLayer.Header; ovr_SubmitFrame(session, frameIndex, &layer.viewScaleDesc, &layers, 1); @@ -3959,7 +3959,7 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) OculusBuffer buffer; buffer.width = width; buffer.height = height; - + // Create OVR texture chain ovrTextureSwapChainDesc desc = {}; desc.Type = ovrTexture_2D; @@ -3972,12 +3972,12 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) desc.StaticImage = ovrFalse; ovrResult result = ovr_CreateTextureSwapChainGL(session, &desc, &buffer.textureChain); - + if (!OVR_SUCCESS(result)) TraceLog(WARNING, "OVR: Failed to create swap textures buffer"); int textureCount = 0; ovr_GetTextureSwapChainLength(session, buffer.textureChain, &textureCount); - + if (!OVR_SUCCESS(result) || !textureCount) TraceLog(WARNING, "OVR: Unable to count swap chain textures"); for (int i = 0; i < textureCount; ++i) @@ -3990,9 +3990,9 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - + glBindTexture(GL_TEXTURE_2D, 0); - + /* // Setup framebuffer object (using depth texture) glGenFramebuffers(1, &buffer.fboId); @@ -4004,7 +4004,7 @@ static OculusBuffer LoadOculusBuffer(ovrSession session, int width, int height) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, buffer.width, buffer.height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); */ - + // Setup framebuffer object (using depth renderbuffer) glGenFramebuffers(1, &buffer.fboId); glGenRenderbuffers(1, &buffer.depthId); @@ -4037,13 +4037,13 @@ static OculusMirror LoadOculusMirror(ovrSession session, int width, int height) OculusMirror mirror; mirror.width = width; mirror.height = height; - + ovrMirrorTextureDesc mirrorDesc; memset(&mirrorDesc, 0, sizeof(mirrorDesc)); mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB; mirrorDesc.Width = mirror.width; mirrorDesc.Height = mirror.height; - + if (!OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirror.texture))) TraceLog(WARNING, "Could not create mirror texture"); glGenFramebuffers(1, &mirror.fboId); @@ -4062,9 +4062,9 @@ static void UnloadOculusMirror(ovrSession session, OculusMirror mirror) static void BlitOculusMirror(ovrSession session, OculusMirror mirror) { GLuint mirrorTextureId; - + ovr_GetMirrorTextureBufferGL(session, mirror.texture, &mirrorTextureId); - + glBindFramebuffer(GL_READ_FRAMEBUFFER, mirror.fboId); glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTextureId, 0); #if defined(GRAPHICS_API_OPENGL_33) @@ -4078,7 +4078,7 @@ static void BlitOculusMirror(ovrSession session, OculusMirror mirror) static OculusLayer InitOculusLayer(ovrSession session) { OculusLayer layer = { 0 }; - + layer.viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; memset(&layer.eyeLayer, 0, sizeof(ovrLayerEyeFov)); @@ -4086,7 +4086,7 @@ static OculusLayer InitOculusLayer(ovrSession session) layer.eyeLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; ovrEyeRenderDesc eyeRenderDescs[2]; - + for (int eye = 0; eye < 2; eye++) { eyeRenderDescs[eye] = ovr_GetRenderDesc(session, eye, hmdDesc.DefaultEyeFov[eye]); @@ -4095,7 +4095,7 @@ static OculusLayer InitOculusLayer(ovrSession session) layer.viewScaleDesc.HmdToEyeOffset[eye] = eyeRenderDescs[eye].HmdToEyeOffset; layer.eyeLayer.Fov[eye] = eyeRenderDescs[eye].Fov; - + ovrSizei eyeSize = ovr_GetFovTextureSize(session, eye, layer.eyeLayer.Fov[eye], 1.0f); layer.eyeLayer.Viewport[eye].Size = eyeSize; layer.eyeLayer.Viewport[eye].Pos.x = layer.width; @@ -4104,7 +4104,7 @@ static OculusLayer InitOculusLayer(ovrSession session) layer.height = eyeSize.h; //std::max(renderTargetSize.y, (uint32_t)eyeSize.h); layer.width += eyeSize.w; } - + return layer; } @@ -4112,7 +4112,7 @@ static OculusLayer InitOculusLayer(ovrSession session) static Matrix FromOvrMatrix(ovrMatrix4f ovrmat) { Matrix rmat; - + rmat.m0 = ovrmat.M[0][0]; rmat.m1 = ovrmat.M[1][0]; rmat.m2 = ovrmat.M[2][0]; @@ -4129,9 +4129,9 @@ static Matrix FromOvrMatrix(ovrMatrix4f ovrmat) rmat.m13 = ovrmat.M[1][3]; rmat.m14 = ovrmat.M[2][3]; rmat.m15 = ovrmat.M[3][3]; - + MatrixTranspose(&rmat); - + return rmat; } #endif @@ -4162,7 +4162,7 @@ void TraceLog(int msgType, const char *text, ...) } // Converts Matrix to float array -// NOTE: Returned vector is a transposed version of the Matrix struct, +// NOTE: Returned vector is a transposed version of the Matrix struct, // it should be this way because, despite raymath use OpenGL column-major convention, // Matrix struct memory alignment and variables naming are not coherent float *MatrixToFloat(Matrix mat) diff --git a/src/text.c b/src/text.c index 4e163668..e3d22fbd 100644 --- a/src/text.c +++ b/src/text.c @@ -286,17 +286,17 @@ SpriteFont LoadSpriteFont(const char *fileName) SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int numChars, int *fontChars) { SpriteFont spriteFont = { 0 }; - - if (strcmp(GetExtension(fileName),"ttf") == 0) + + if (strcmp(GetExtension(fileName),"ttf") == 0) { if ((fontChars == NULL) || (numChars == 0)) { int totalChars = 95; // Default charset [32..126] - + int *defaultFontChars = (int *)malloc(totalChars*sizeof(int)); - + for (int i = 0; i < totalChars; i++) defaultFontChars[i] = i + 32; // Default first character: SPACE[32] - + spriteFont = LoadTTF(fileName, fontSize, totalChars, defaultFontChars); } else spriteFont = LoadTTF(fileName, fontSize, numChars, fontChars); @@ -353,10 +353,10 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float int textOffsetX = 0; // Offset between characters int textOffsetY = 0; // Required for line break! float scaleFactor; - + unsigned char letter; // Current character int index; // Index position in sprite font - + scaleFactor = fontSize/spriteFont.size; // NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly @@ -388,10 +388,10 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float } else index = GetCharIndex(spriteFont, (int)text[i]); - DrawTexturePro(spriteFont.texture, spriteFont.charRecs[index], + DrawTexturePro(spriteFont.texture, spriteFont.charRecs[index], (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[index].x*scaleFactor, position.y + textOffsetY + spriteFont.charOffsets[index].y*scaleFactor, - spriteFont.charRecs[index].width*scaleFactor, + spriteFont.charRecs[index].width*scaleFactor, spriteFont.charRecs[index].height*scaleFactor }, (Vector2){ 0, 0 }, 0.0f, tint); if (spriteFont.charAdvanceX[index] == 0) textOffsetX += (int)(spriteFont.charRecs[index].width*scaleFactor + spacing); @@ -476,7 +476,7 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, float fontSize, i if (text[i] != '\n') { int index = GetCharIndex(spriteFont, (int)text[i]); - + if (spriteFont.charAdvanceX[index] != 0) textWidth += spriteFont.charAdvanceX[index]; else textWidth += (spriteFont.charRecs[index].width + spriteFont.charOffsets[index].x); } @@ -517,7 +517,7 @@ static int GetCharIndex(SpriteFont font, int letter) #define UNORDERED_CHARSET #if defined(UNORDERED_CHARSET) int index = 0; - + for (int i = 0; i < font.numChars; i++) { if (font.charValues[i] == letter) @@ -526,7 +526,7 @@ static int GetCharIndex(SpriteFont font, int letter) break; } } - + return index; #else return (letter - 32); @@ -607,14 +607,14 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) } TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); - - // NOTE: We need to remove key color borders from image to avoid weird + + // NOTE: We need to remove key color borders from image to avoid weird // artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR for (int i = 0; i < image.height*image.width; i++) if (COLOR_EQUAL(pixels[i], key)) pixels[i] = BLANK; // Create a new image with the processed color data (key color replaced by BLANK) Image fontClear = LoadImageEx(pixels, image.width, image.height); - + free(pixels); // Free pixels array memory // Create spritefont with all data parsed from image @@ -622,7 +622,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) spriteFont.texture = LoadTextureFromImage(fontClear); // Convert processed image to OpenGL texture spriteFont.numChars = index; - + UnloadImage(fontClear); // Unload processed image once converted to texture // We got tempCharValues and tempCharsRecs populated with chars data @@ -643,7 +643,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) } spriteFont.size = spriteFont.charRecs[0].height; - + TraceLog(INFO, "Image file loaded correctly as SpriteFont"); return spriteFont; @@ -853,13 +853,13 @@ static SpriteFont LoadBMFont(const char *fileName) strncat(texPath, texFileName, strlen(texFileName)); TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); - + Image imFont = LoadImage(texPath); - - if (imFont.format == UNCOMPRESSED_GRAYSCALE) + + if (imFont.format == UNCOMPRESSED_GRAYSCALE) { Image imCopy = ImageCopy(imFont); - + for (int i = 0; i < imCopy.width*imCopy.height; i++) ((unsigned char *)imCopy.data)[i] = 0xff; // WHITE pixel ImageAlphaMask(&imCopy, imFont); @@ -867,7 +867,7 @@ static SpriteFont LoadBMFont(const char *fileName) UnloadImage(imCopy); } else font.texture = LoadTextureFromImage(imFont); - + font.size = fontSize; font.numChars = numChars; font.charValues = (int *)malloc(numChars*sizeof(int)); @@ -876,7 +876,7 @@ static SpriteFont LoadBMFont(const char *fileName) font.charAdvanceX = (int *)malloc(numChars*sizeof(int)); UnloadImage(imFont); - + free(texPath); int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; @@ -913,11 +913,11 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int // NOTE: Font texture size is predicted (being as much conservative as possible) // Predictive method consist of supposing same number of chars by line-column (sqrtf) // and a maximum character width of 3/4 of fontSize... it worked ok with all my tests... - + // Calculate next power-of-two value float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)numChars)); int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT - + TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25); @@ -935,7 +935,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int } fread(ttfBuffer, 1, 1 << 25, ttfFile); - + if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... @@ -945,7 +945,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int //if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font"); - + free(ttfBuffer); // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA @@ -966,11 +966,11 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int numChars, int image.mipmaps = 1; image.format = UNCOMPRESSED_GRAY_ALPHA; image.data = dataGrayAlpha; - + font.texture = LoadTextureFromImage(image); - + //SavePNG("generated_ttf_image.png", (unsigned char *)image.data, image.width, image.height, 2); - + UnloadImage(image); // Unloads dataGrayAlpha font.size = fontSize; diff --git a/src/textures.c b/src/textures.c index 3fa250c2..9d865aa1 100644 --- a/src/textures.c +++ b/src/textures.c @@ -144,9 +144,9 @@ Image LoadImage(const char *fileName) else if (strcmp(GetExtension(fileName),"rres") == 0) { RRESData rres = LoadResource(fileName); - + // NOTE: Parameters for RRES_IMAGE type are: width, height, format, mipmaps - + if (rres.type == RRES_IMAGE) image = LoadImagePro(rres.data, rres.param1, rres.param2, rres.param3); else TraceLog(WARNING, "[%s] Resource file does not contain image data", fileName); @@ -197,9 +197,9 @@ Image LoadImagePro(void *data, int width, int height, int format) srcImage.height = height; srcImage.mipmaps = 1; srcImage.format = format; - + Image dstImage = ImageCopy(srcImage); - + return dstImage; } @@ -244,7 +244,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int if (bytes < size) { TraceLog(WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); - + if (image.data != NULL) free(image.data); } else @@ -615,12 +615,12 @@ void ImageAlphaMask(Image *image, Image alphaMask) // Force mask to be Grayscale Image mask = ImageCopy(alphaMask); if (mask.format != UNCOMPRESSED_GRAYSCALE) ImageFormat(&mask, UNCOMPRESSED_GRAYSCALE); - + // In case image is only grayscale, we just add alpha channel if (image->format == UNCOMPRESSED_GRAYSCALE) { ImageFormat(image, UNCOMPRESSED_GRAY_ALPHA); - + // Apply alpha mask to alpha channel for (int i = 0, k = 1; (i < mask.width*mask.height) || (i < image->width*image->height); i++, k += 2) { @@ -955,7 +955,7 @@ void ImageResizeNN(Image *image,int newWidth,int newHeight) void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) { bool cropRequired = false; - + // Security checks to avoid size and rectangle issues (out of bounds) // Check that srcRec is inside src image if (srcRec.x < 0) srcRec.x = 0; @@ -973,15 +973,15 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) TraceLog(WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); cropRequired = true; } - + Image srcCopy = ImageCopy(src); // Make a copy of source image to work with it ImageCrop(&srcCopy, srcRec); // Crop source image to desired source rectangle - + // Check that dstRec is inside dst image // TODO: Allow negative position within destination with cropping if (dstRec.x < 0) dstRec.x = 0; if (dstRec.y < 0) dstRec.y = 0; - + // Scale source image in case destination rec size is different than source rec size if ((dstRec.width != srcRec.width) || (dstRec.height != srcRec.height)) { @@ -1001,20 +1001,20 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) TraceLog(WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); cropRequired = true; } - + if (cropRequired) { // Crop destination rectangle if out of bounds Rectangle crop = { 0, 0, dstRec.width, dstRec.height }; ImageCrop(&srcCopy, crop); } - + // Get image data as Color pixels array to work with it Color *dstPixels = GetImageData(*dst); Color *srcPixels = GetImageData(srcCopy); UnloadImage(srcCopy); // Source copy not required any more... - + Color srcCol, dstCol; // Blit pixels, copy source image into destination @@ -1026,13 +1026,13 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) // Alpha blending implementation dstCol = dstPixels[j*dst->width + i]; srcCol = srcPixels[(j - dstRec.y)*dstRec.width + (i - dstRec.x)]; - + dstCol.r = ((srcCol.a*(srcCol.r - dstCol.r)) >> 8) + dstCol.r; dstCol.g = ((srcCol.a*(srcCol.g - dstCol.g)) >> 8) + dstCol.g; dstCol.b = ((srcCol.a*(srcCol.b - dstCol.b)) >> 8) + dstCol.b; - + dstPixels[j*dst->width + i] = dstCol; - + // TODO: Support other blending options } } @@ -1369,7 +1369,7 @@ void SetTextureFilter(Texture2D texture, int filterMode) { // RL_FILTER_MIP_NEAREST - tex filter: POINT, mipmaps filter: POINT (sharp switching between mipmaps) rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_NEAREST); - + // RL_FILTER_NEAREST - tex filter: POINT (no filter), no mipmaps rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_NEAREST); } @@ -1387,7 +1387,7 @@ void SetTextureFilter(Texture2D texture, int filterMode) // RL_FILTER_LINEAR_MIP_NEAREST - tex filter: BILINEAR, mipmaps filter: POINT (sharp switching between mipmaps) // Alternative: RL_FILTER_NEAREST_MIP_LINEAR - tex filter: POINT, mipmaps filter: BILINEAR (smooth transition between mipmaps) rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR_MIP_NEAREST); - + // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); } @@ -1404,14 +1404,14 @@ void SetTextureFilter(Texture2D texture, int filterMode) { // RL_FILTER_MIP_LINEAR - tex filter: BILINEAR, mipmaps filter: BILINEAR (smooth transition between mipmaps) rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_MIP_LINEAR); - + // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); } else { TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); - + // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR); rlTextureParameters(texture.id, RL_TEXTURE_MAG_FILTER, RL_FILTER_LINEAR); @@ -2007,19 +2007,19 @@ static Image LoadPVR(const char *fileName) image.mipmaps = pvrHeader.numMipmaps; // Check data format - if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 0)) && (pvrHeader.channelDepth[0] == 8)) + if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 0)) && (pvrHeader.channelDepth[0] == 8)) image.format = UNCOMPRESSED_GRAYSCALE; - else if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 'a')) && ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8))) + else if (((pvrHeader.channels[0] == 'l') && (pvrHeader.channels[1] == 'a')) && ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8))) image.format = UNCOMPRESSED_GRAY_ALPHA; else if ((pvrHeader.channels[0] == 'r') && (pvrHeader.channels[1] == 'g') && (pvrHeader.channels[2] == 'b')) { if (pvrHeader.channels[3] == 'a') { - if ((pvrHeader.channelDepth[0] == 5) && (pvrHeader.channelDepth[1] == 5) && (pvrHeader.channelDepth[2] == 5) && (pvrHeader.channelDepth[3] == 1)) + if ((pvrHeader.channelDepth[0] == 5) && (pvrHeader.channelDepth[1] == 5) && (pvrHeader.channelDepth[2] == 5) && (pvrHeader.channelDepth[3] == 1)) image.format = UNCOMPRESSED_R5G5B5A1; - else if ((pvrHeader.channelDepth[0] == 4) && (pvrHeader.channelDepth[1] == 4) && (pvrHeader.channelDepth[2] == 4) && (pvrHeader.channelDepth[3] == 4)) + else if ((pvrHeader.channelDepth[0] == 4) && (pvrHeader.channelDepth[1] == 4) && (pvrHeader.channelDepth[2] == 4) && (pvrHeader.channelDepth[3] == 4)) image.format = UNCOMPRESSED_R4G4B4A4; - else if ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8) && (pvrHeader.channelDepth[2] == 8) && (pvrHeader.channelDepth[3] == 8)) + else if ((pvrHeader.channelDepth[0] == 8) && (pvrHeader.channelDepth[1] == 8) && (pvrHeader.channelDepth[2] == 8) && (pvrHeader.channelDepth[3] == 8)) image.format = UNCOMPRESSED_R8G8B8A8; } else if (pvrHeader.channels[3] == 0) -- cgit v1.2.3 From 05cff44d0a9af5bcb41ddd0baa6b7693f6ac116b Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 16 Feb 2017 00:50:02 +0100 Subject: Improved modules description -IN PROGRESS- Working in modules configuration flags... --- src/audio.c | 56 +++++++++++++++++++++++++++++++++++++------------------- src/audio.h | 4 +++- src/camera.h | 14 +++++++++++--- src/core.c | 55 +++++++++++++++++++++++++++++++++++++------------------ src/gestures.h | 17 +++++++++++++---- src/models.c | 13 +++++++------ src/physac.h | 15 +++++++++------ src/raylib.h | 44 +++++++++++++++++++++++++++----------------- src/raymath.h | 25 +++++++++++++------------ src/rlgl.c | 46 ++++++++++++++++++++++++++++++++++++---------- src/rres.h | 18 +++++++++++------- src/shapes.c | 11 ++++------- src/text.c | 36 +++++++++++++++++++++--------------- src/textures.c | 35 +++++++++++++++++++++++++++-------- src/utils.c | 19 +++++++++++++------ 15 files changed, 269 insertions(+), 139 deletions(-) (limited to 'src/models.c') diff --git a/src/audio.c b/src/audio.c index 58699035..690a41eb 100644 --- a/src/audio.c +++ b/src/audio.c @@ -3,32 +3,50 @@ * raylib.audio * * This module provides basic functionality to work with audio: -* Manage audio device (init/close) -* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD) -* Play/Stop/Pause/Resume loaded audio -* Manage mixing channels -* Manage raw audio context +* Manage audio device (init/close) +* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD) +* Play/Stop/Pause/Resume loaded audio +* Manage mixing channels +* Manage raw audio context * -* External libs: +* NOTES: +* +* Only up to two channels supported: MONO and STEREO (for additional channels, use AL_EXT_MCFORMATS) +* Only the following sample sizes supported: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32) +* +* CONFIGURATION: +* +* #define AUDIO_STANDALONE +* If defined, the module can be used as standalone library (independently of raylib). +* Required types and functions are defined in the same module. +* +* #define SUPPORT_FILEFORMAT_WAV / SUPPORT_LOAD_WAV / ENABLE_LOAD_WAV +* #define SUPPORT_FILEFORMAT_OGG +* #define SUPPORT_FILEFORMAT_XM +* #define SUPPORT_FILEFORMAT_MOD +* #define SUPPORT_FILEFORMAT_FLAC +* Selected desired fileformats to be supported for loading. Some of those formats are +* supported by default, to remove support, just comment unrequired #define in this module +* +* #define SUPPORT_RAW_AUDIO_BUFFERS +* +* DEPENDENCIES: * OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html) * stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/) * jar_xm - XM module file loading * jar_mod - MOD audio file loading * dr_flac - FLAC audio file loading * -* Module Configuration Flags: -* AUDIO_STANDALONE - Use this module as standalone library (independently of raylib) -* -* Some design decisions: -* Support only up to two channels: MONO and STEREO (for additional channels, AL_EXT_MCFORMATS) -* Support only the following sample sizes: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32) +* CONTRIBUTORS: * * Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: -* XM audio module support (jar_xm) -* MOD audio module support (jar_mod) -* Mixing channels support -* Raw audio context support +* XM audio module support (jar_xm) +* MOD audio module support (jar_mod) +* Mixing channels support +* Raw audio context support +* * +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * @@ -246,11 +264,11 @@ Wave LoadWave(const char *fileName) else if (strcmp(GetExtension(fileName), "flac") == 0) wave = LoadFLAC(fileName); else if (strcmp(GetExtension(fileName),"rres") == 0) { - RRESData rres = LoadResource(fileName); + RRES rres = LoadResource(fileName, 0); - // NOTE: Parameters for RRES_WAVE type are: sampleCount, sampleRate, sampleSize, channels + // NOTE: Parameters for RRES_TYPE_WAVE are: sampleCount, sampleRate, sampleSize, channels - if (rres.type == RRES_WAVE) wave = LoadWaveEx(rres.data, rres.param1, rres.param2, rres.param3, rres.param4); + if (rres[0].type == RRES_TYPE_WAVE) wave = LoadWaveEx(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3, rres[0].param4); else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName); UnloadResource(rres); diff --git a/src/audio.h b/src/audio.h index 99b58e15..01ed9f72 100644 --- a/src/audio.h +++ b/src/audio.h @@ -9,7 +9,7 @@ * Manage mixing channels * Manage raw audio context * -* External libs: +* DEPENDENCIES: * OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html) * stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/) * jar_xm - XM module file loading @@ -23,6 +23,8 @@ * Raw audio context support * * +* LICENSE: zlib/libpng +* * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event diff --git a/src/camera.h b/src/camera.h index cf542288..87ba1942 100644 --- a/src/camera.h +++ b/src/camera.h @@ -2,6 +2,10 @@ * * raylib Camera System - Camera Modes Setup and Control Functions * +* NOTE: Memory footprint of this library is aproximately 52 bytes (global variables) +* +* CONFIGURATION: +* * #define CAMERA_IMPLEMENTATION * Generates the implementation of the library into the included file. * If not defined, the library is in header only mode and can be included in other headers @@ -11,10 +15,14 @@ * If defined, the library can be used as standalone as a camera system but some * functions must be redefined to manage inputs accordingly. * -* NOTE: Memory footprint of this library is aproximately 52 bytes (global variables) +* CONTRIBUTORS: +* Marc Palau: Initial implementation (2014) +* Ramon Santamaria: Supervision, review, update and maintenance +* +* +* LICENSE: zlib/libpng * -* Initial design by Marc Palau (2014) -* Reviewed by Ramon Santamaria (2015-2016) +* Copyright (c) 2015-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. diff --git a/src/core.c b/src/core.c index 28f73345..9d40edcc 100644 --- a/src/core.c +++ b/src/core.c @@ -1,27 +1,46 @@ /********************************************************************************************** * -* raylib.core -* -* Basic functions to manage windows, OpenGL context and input on multiple platforms +* raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms * * The following platforms are supported: Windows, Linux, Mac (OSX), Android, Raspberry Pi, HTML5, Oculus Rift CV1 * -* External libs: +* CONFIGURATION: +* +* #define PLATFORM_DESKTOP +* Windowing and input system configured for desktop platforms: Windows, Linux, OSX (managed by GLFW3 library) +* NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for mirror rendering - View [rlgl] module to enable it +* +* #define PLATFORM_ANDROID +* Windowing and input system configured for Android device, app activity managed internally in this module. +* NOTE: OpenGL ES 2.0 is required and graphic device is managed by EGL +* +* #define PLATFORM_RPI +* Windowing and input system configured for Raspberry Pi (tested on Raspbian), graphic device is managed by EGL +* and inputs are processed is raw mode, reading from /dev/input/ +* +* #define PLATFORM_WEB +* Windowing and input system configured for HTML5 (run on browser), code converted from C to asm.js +* using emscripten compiler. OpenGL ES 2.0 required for direct translation to WebGL equivalent code. +* +* #define LOAD_DEFAULT_FONT (defined by default) +* Default font is loaded on window initialization to be available for the user to render simple text. +* NOTE: If enabled, uses external module functions to load default raylib font (module: text) +* +* #define INCLUDE_CAMERA_SYSTEM / SUPPORT_CAMERA_SYSTEM +* +* #define INCLUDE_GESTURES_SYSTEM / SUPPORT_GESTURES_SYSTEM +* +* #define SUPPORT_MOUSE_GESTURES +* Mouse gestures are directly mapped like touches and processed by gestures system. +* +* DEPENDENCIES: * GLFW3 - Manage graphic device, OpenGL context and inputs on PLATFORM_DESKTOP (Windows, Linux, OSX) * raymath - 3D math functionality (Vector3, Matrix, Quaternion) * camera - Multiple 3D camera modes (free, orbital, 1st person, 3rd person) * gestures - Gestures system for touch-ready devices (or simulated from mouse inputs) * -* Module Configuration Flags: -* PLATFORM_DESKTOP - Windows, Linux, Mac (OSX) -* PLATFORM_ANDROID - Android (only OpenGL ES 2.0 devices), graphic device is managed by EGL and input system by Android activity. -* PLATFORM_RPI - Rapsberry Pi (tested on Raspbian), graphic device is managed by EGL and input system is coded in raw mode. -* PLATFORM_WEB - HTML5 (using emscripten compiler) -* -* RL_LOAD_DEFAULT_FONT - Use external module functions to load default raylib font (module: text) -* -* NOTE: Oculus Rift CV1 requires PLATFORM_DESKTOP for render mirror - View [rlgl] module to enable it * +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * @@ -140,7 +159,7 @@ #define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) -#define RL_LOAD_DEFAULT_FONT // Load default font on window initialization (module: text) +#define LOAD_DEFAULT_FONT // Load default font on window initialization (module: text) //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -256,7 +275,7 @@ static bool showLogo = false; // Track if showing logo at init is //---------------------------------------------------------------------------------- // Other Modules Functions Declaration (required by core) //---------------------------------------------------------------------------------- -#if defined(RL_LOAD_DEFAULT_FONT) +#if defined(LOAD_DEFAULT_FONT) extern void LoadDefaultFont(void); // [Module: text] Loads default font on InitWindow() extern void UnloadDefaultFont(void); // [Module: text] Unloads default font from GPU memory #endif @@ -338,7 +357,7 @@ void InitWindow(int width, int height, const char *title) // Init graphics device (display device and OpenGL context) InitGraphicsDevice(width, height); -#if defined(RL_LOAD_DEFAULT_FONT) +#if defined(LOAD_DEFAULT_FONT) // Load default font // NOTE: External function (defined in module: text) LoadDefaultFont(); @@ -450,7 +469,7 @@ void InitWindow(int width, int height, void *state) // Close Window and Terminate Context void CloseWindow(void) { -#if defined(RL_LOAD_DEFAULT_FONT) +#if defined(LOAD_DEFAULT_FONT) UnloadDefaultFont(); #endif @@ -2410,7 +2429,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Init graphics device (display device and OpenGL context) InitGraphicsDevice(screenWidth, screenHeight); - #if defined(RL_LOAD_DEFAULT_FONT) + #if defined(LOAD_DEFAULT_FONT) // Load default font // NOTE: External function (defined in module: text) LoadDefaultFont(); diff --git a/src/gestures.h b/src/gestures.h index f4dcb133..99f49d2a 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -2,6 +2,10 @@ * * raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse) * +* NOTE: Memory footprint of this library is aproximately 128 bytes (global variables) +* +* CONFIGURATION: +* * #define GESTURES_IMPLEMENTATION * Generates the implementation of the library into the included file. * If not defined, the library is in header only mode and can be included in other headers @@ -11,11 +15,16 @@ * If defined, the library can be used as standalone to process gesture events with * no external dependencies. * -* NOTE: Memory footprint of this library is aproximately 128 bytes +* CONTRIBUTORS: +* Marc Palau: Initial implementation (2014) +* Albert Martos: Complete redesign and testing (2015) +* Ian Eito: Complete redesign and testing (2015) +* Ramon Santamaria: Supervision, review, update and maintenance +* +* +* LICENSE: zlib/libpng * -* Initial design by Marc Palau (2014) -* Redesigned by Albert Martos and Ian Eito (2015) -* Reviewed by Ramon Santamaria (2015-2016) +* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. diff --git a/src/models.c b/src/models.c index 43821691..bef19e10 100644 --- a/src/models.c +++ b/src/models.c @@ -1,14 +1,15 @@ /********************************************************************************************** * -* raylib.models +* raylib.models - Basic functions to draw 3d shapes and 3d models * -* Basic functions to draw 3d shapes and load/draw 3d models (.OBJ) +* CONFIGURATION: * -* External libs: -* rlgl - raylib OpenGL abstraction layer +* #define SUPPORT_FILEFORMAT_OBJ / SUPPORT_LOAD_OBJ * -* Module Configuration Flags: -* ... +* #define SUPPORT_FILEFORMAT_MTL +* +* +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * diff --git a/src/physac.h b/src/physac.h index d958c701..cb0e3f3c 100644 --- a/src/physac.h +++ b/src/physac.h @@ -1,11 +1,13 @@ /********************************************************************************************** * -* Physac - 2D Physics library for videogames +* Physac v1.0 - 2D Physics library for videogames * -* Description: Physac is a small 2D physics engine written in pure C. The engine uses a fixed time-step thread loop -* to simluate physics. A physics step contains the following phases: get collision information, apply dynamics, -* collision solving and position correction. It uses a very simple struct for physic bodies with a position vector -* to be used in any 3D rendering API. +* DESCRIPTION: +* +* Physac is a small 2D physics engine written in pure C. The engine uses a fixed time-step thread loop +* to simluate physics. A physics step contains the following phases: get collision information, +* apply dynamics, collision solving and position correction. It uses a very simple struct for physic +* bodies with a position vector to be used in any 3D rendering API. * * CONFIGURATION: * @@ -37,7 +39,8 @@ * Otherwise it will include stdlib.h and use the C standard library malloc()/free() function. * * VERY THANKS TO: -* - Ramón Santamaria (@raysan5) +* Ramón Santamaria (@raysan5) +* * * LICENSE: zlib/libpng * diff --git a/src/raylib.h b/src/raylib.h index 800ab2be..3ff0d28f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,10 +1,10 @@ /********************************************************************************************** * -* raylib 1.7.0 (www.raylib.com) +* raylib v1.7.0 (www.raylib.com) * * A simple and easy-to-use library to learn videogames programming * -* Features: +* FEATURES: * Library written in plain C code (C99) * Uses PascalCase/camelCase notation * Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0) @@ -20,7 +20,13 @@ * Minimal external dependencies (GLFW3, OpenGL, OpenAL) * Complete binding for Lua [rlua] * -* External libs: +* NOTES: +* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) +* One custom default font could be loaded automatically when InitWindow() [core] +* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads +* If using OpenGL 3.3 or ES2, two default shaders could be loaded automatically (internally defined) +* +* DEPENDENCIES: * GLFW3 (www.glfw.org) for window/context management and input [core] * GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) [rlgl] * stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA) [textures] @@ -33,13 +39,8 @@ * OpenAL Soft for audio device/context management [audio] * tinfl for data decompression (DEFLATE algorithm) [utils] * -* Some design decisions: -* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) -* One custom default font could be loaded automatically when InitWindow() [core] -* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads -* If using OpenGL 3.3 or ES2, two default shaders could be loaded automatically (internally defined) * -* -- LICENSE -- +* LICENSE: zlib/libpng * * raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: @@ -592,8 +593,9 @@ typedef enum { HMD_FOVE_VR, } VrDevice; -// rRES data returned when reading a resource, it contains all required data for user (24 byte) -typedef struct { +// rRES data returned when reading a resource, +// it contains all required data for user (24 byte) +typedef struct RRESData { unsigned int type; // Resource type (4 byte) unsigned int param1; // Resouce parameter 1 (4 byte) @@ -604,14 +606,21 @@ typedef struct { void *data; // Resource data pointer (4 byte) } RRESData; -typedef enum { - RRES_RAW = 0, - RRES_IMAGE, - RRES_WAVE, - RRES_VERTEX, - RRES_TEXT +// RRESData type +typedef enum { + RRES_TYPE_RAW = 0, + RRES_TYPE_IMAGE, + RRES_TYPE_WAVE, + RRES_TYPE_VERTEX, + RRES_TYPE_TEXT, + RRES_TYPE_FONT_IMAGE, + RRES_TYPE_FONT_CHARDATA, // CharInfo data array + RRES_TYPE_DIRECTORY } RRESDataType; +// RRES type (pointer to RRESData array) +typedef struct RRESData *RRES; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -758,6 +767,7 @@ RLAPI void DrawCircleV(Vector2 center, float radius, Color color); RLAPI void DrawCircleLines(int centerX, int centerY, float radius, Color color); // Draw circle outline RLAPI void DrawRectangle(int posX, int posY, int width, int height, Color color); // Draw a color-filled rectangle RLAPI void DrawRectangleRec(Rectangle rec, Color color); // Draw a color-filled rectangle +RLAPI void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color); // Draw a color-filled rectangle with pro parameters RLAPI void DrawRectangleGradient(int posX, int posY, int width, int height, Color color1, Color color2); // Draw a gradient-filled rectangle RLAPI void DrawRectangleV(Vector2 position, Vector2 size, Color color); // Draw a color-filled rectangle (Vector version) RLAPI void DrawRectangleLines(int posX, int posY, int width, int height, Color color); // Draw rectangle outline diff --git a/src/raymath.h b/src/raymath.h index c073b72d..a2263f19 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,22 +1,23 @@ /********************************************************************************************** * -* raymath (header only file) +* raymath v1.0 - Some useful functions to work with Vector3, Matrix and Quaternions * -* Some useful functions to work with Vector3, Matrix and Quaternions +* CONFIGURATION: * -* You must: -* #define RAYMATH_IMPLEMENTATION -* before you include this file in *only one* C or C++ file to create the implementation. +* #define RAYMATH_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. * -* Example: -* #define RAYMATH_IMPLEMENTATION -* #include "raymath.h" +* #define RAYMATH_EXTERN_INLINE +* Inlines all functions code, so it runs faster. This requires lots of memory on system. +* +* #define RAYMATH_STANDALONE +* Avoid raylib.h header inclusion in this file. +* Vector3 and Matrix data types are defined internally in raymath module. * -* You can also use: -* #define RAYMATH_EXTERN_INLINE // Inlines all functions code, so it runs faster. -* // This requires lots of memory on system. -* #define RAYMATH_STANDALONE // Not dependent on raylib.h structs: Vector3, Matrix. * +* LICENSE: zlib/libpng * * Copyright (c) 2015 Ramon Santamaria (@raysan5) * diff --git a/src/rlgl.c b/src/rlgl.c index ce17adc3..ffc9d741 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2,6 +2,8 @@ * * rlgl - raylib OpenGL abstraction layer * +* DESCRIPTION: +* * rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to * selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). * @@ -11,20 +13,44 @@ * rlglDraw() - Process internal buffers and send required draw calls * rlglClose() - De-initialize internal buffers data and other auxiliar resources * -* External libs: +* CONFIGURATION: +* +* #define GRAPHICS_API_OPENGL_11 +* Use OpenGL 1.1 backend +* +* #define GRAPHICS_API_OPENGL_21 +* Use OpenGL 2.1 backend +* +* #define GRAPHICS_API_OPENGL_33 +* Use OpenGL 3.3 Core profile backend +* +* #define GRAPHICS_API_OPENGL_ES2 +* Use OpenGL ES 2.0 backend +* +* #define RLGL_STANDALONE +* Use rlgl as standalone library (no raylib dependency) +* +* #define RLGL_NO_DISTORTION_SHADER +* Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion +* +* #define SUPPORT_SHADER_DEFAULT / ENABLE_SHADER_DEFAULT +* +* #define SUPPORT_SHADER_DISTORTION +* +* +* #define SUPPORT_OCULUS_RIFT_CV1 / RLGL_OCULUS_SUPPORT +* Enable Oculus Rift CV1 functionality +* +* #define SUPPORT_STEREO_RENDERING +* +* #define RLGL_NO_DEFAULT_SHADER +* +* DEPENDENCIES: * raymath - 3D math functionality (Vector3, Matrix, Quaternion) * GLAD - OpenGL extensions loading (OpenGL 3.3 Core only) * -* Module Configuration Flags: -* GRAPHICS_API_OPENGL_11 - Use OpenGL 1.1 backend -* GRAPHICS_API_OPENGL_21 - Use OpenGL 2.1 backend -* GRAPHICS_API_OPENGL_33 - Use OpenGL 3.3 Core profile backend -* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend -* -* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency) -* RLGL_NO_DISTORTION_SHADER - Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion -* RLGL_OCULUS_SUPPORT - Enable Oculus Rift CV1 functionality * +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * diff --git a/src/rres.h b/src/rres.h index bed28723..362da10d 100644 --- a/src/rres.h +++ b/src/rres.h @@ -4,14 +4,18 @@ * * Basic functions to load/save rRES resource files * -* External libs: -* tinfl - DEFLATE decompression functions +* CONFIGURATION: +* +* #define RREM_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. * -* Module Configuration Flags: +* DEPENDENCIES: +* tinfl - DEFLATE decompression functions * -* #define RREM_IMPLEMENTATION -* Generates the implementation of the library into the included file. * +* LICENSE: zlib/libpng * * Copyright (c) 2016-2017 Ramon Santamaria (@raysan5) * @@ -81,7 +85,7 @@ RRES_TYPE_VERTEX, RRES_TYPE_TEXT, RRES_TYPE_FONT_IMAGE, - RRES_TYPE_FONT_DATA, // Character { int value, recX, recY, recWidth, recHeight, offsetX, offsetY, xAdvance } + RRES_TYPE_FONT_CHARDATA, // Character { int value, recX, recY, recWidth, recHeight, offsetX, offsetY, xAdvance } RRES_TYPE_DIRECTORY } RRESDataType; @@ -243,7 +247,7 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i // NOTE: Returns uncompressed data with parameters, search resource by id RRESDEF RRES LoadResource(const char *fileName, int rresId) { - RRES rres; + RRES rres = { 0 }; RRESFileHeader fileHeader; RRESInfoHeader infoHeader; diff --git a/src/shapes.c b/src/shapes.c index 83b80182..a42b0551 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -1,17 +1,14 @@ /********************************************************************************************** * -* raylib.shapes -* -* Basic functions to draw 2d Shapes and check collisions -* -* DEPENDENCIES: -* rlgl - raylib OpenGL abstraction layer +* raylib.shapes - Basic functions to draw 2d Shapes and check collisions * * CONFIGURATION: * * #define SUPPORT_QUADS_ONLY +* Draw shapes using only QUADS, vertex are accumulated in QUADS arrays (like textures) * - #define SUPPORT_TRIANGLES_ONLY +* #define SUPPORT_TRIANGLES_ONLY +* Draw shapes using only TRIANGLES, vertex are accumulated in TRIANGLES arrays * * * LICENSE: zlib/libpng diff --git a/src/text.c b/src/text.c index 4deae25c..6f18b391 100644 --- a/src/text.c +++ b/src/text.c @@ -1,14 +1,22 @@ /********************************************************************************************** * -* raylib.text +* raylib.text - Basic functions to load SpriteFonts and draw Text * -* Basic functions to load SpriteFonts and draw Text +* CONFIGURATION: * -* External libs: +* #define SUPPORT_FILEFORMAT_FNT +* #define SUPPORT_FILEFORMAT_TTF / INCLUDE_STB_TRUETYPE +* #define SUPPORT_FILEFORMAT_IMAGE_FONT +* Selected desired fileformats to be supported for loading. Some of those formats are +* supported by default, to remove support, just comment unrequired #define in this module +* +* #define INCLUDE_DEFAULT_FONT / SUPPORT_DEFAULT_FONT +* +* DEPENDENCIES: * stb_truetype - Load TTF file and rasterize characters data * -* Module Configuration Flags: -* ... +* +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * @@ -262,30 +270,28 @@ SpriteFont LoadSpriteFont(const char *fileName) else if (strcmp(GetExtension(fileName),"rres") == 0) { // TODO: Read multiple resource blocks from file (RRES_FONT_IMAGE, RRES_FONT_CHARDATA) - RRESData rres = LoadResource(fileName); + RRES rres = LoadResource(fileName, 0); // Load sprite font texture - /* - if (rres.type == RRES_FONT_IMAGE) + if (rres[0].type == RRES_TYPE_FONT_IMAGE) { // NOTE: Parameters for RRES_FONT_IMAGE type are: width, height, format, mipmaps - Image image = LoadImagePro(rres.data, rres.param1, rres.param2, rres.param3); + Image image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3); spriteFont.texture = LoadTextureFromImage(image); UnloadImage(image); } // Load sprite characters data - if (rres.type == RRES_FONT_CHARDATA) + if (rres[1].type == RRES_TYPE_FONT_CHARDATA) { // NOTE: Parameters for RRES_FONT_CHARDATA type are: fontSize, charsCount - spriteFont.baseSize = rres.param1; - spriteFont.charsCount = rres.param2; - spriteFont.chars = rres.data; + spriteFont.baseSize = rres[1].param1; + spriteFont.charsCount = rres[1].param2; + spriteFont.chars = rres[1].data; } - */ // TODO: Do not free rres.data memory (chars info data!) - UnloadResource(rres); + //UnloadResource(rres[0]); } else { diff --git a/src/textures.c b/src/textures.c index 5b2e4775..7db3bf56 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1,16 +1,35 @@ /********************************************************************************************** * -* raylib.textures +* raylib.textures - Basic functions to load and draw Textures (2d) * -* Basic functions to load and draw Textures (2d) +* CONFIGURATION: * -* External libs: +* #define SUPPORT_STB_IMAGE / INCLUDE_STB_IMAGE +* +* #define SUPPORT_FILEFORMAT_BMP / SUPPORT_LOAD_BMP +* #define SUPPORT_FILEFORMAT_PNG / SUPPORT_LOAD_PNG +* #define SUPPORT_FILEFORMAT_TGA +* #define SUPPORT_FILEFORMAT_JPG / ENABLE_LOAD_JPG +* #define SUPPORT_FILEFORMAT_GIF +* #define SUPPORT_FILEFORMAT_HDR +* #define SUPPORT_FILEFORMAT_DDS / ENABLE_LOAD_DDS +* #define SUPPORT_FILEFORMAT_PKM +* #define SUPPORT_FILEFORMAT_KTX +* #define SUPPORT_FILEFORMAT_PVR +* #define SUPPORT_FILEFORMAT_ASTC +* Selected desired fileformats to be supported for loading. Some of those formats are +* supported by default, to remove support, just comment unrequired #define in this module +* +* #define SUPPORT_IMAGE_RESIZE / INCLUDE_STB_IMAGE_RESIZE +* #define SUPPORT_IMAGE_MANIPULATION +* +* DEPENDENCIES: * stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) * NOTE: stb_image has been slightly modified to support Android platform. * stb_image_resize - Multiple image resize algorythms * -* Module Configuration Flags: -* ... +* +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * @@ -143,11 +162,11 @@ Image LoadImage(const char *fileName) else if (strcmp(GetExtension(fileName),"astc") == 0) image = LoadASTC(fileName); else if (strcmp(GetExtension(fileName),"rres") == 0) { - RRESData rres = LoadResource(fileName); + RRES rres = LoadResource(fileName, 0); - // NOTE: Parameters for RRES_IMAGE type are: width, height, format, mipmaps + // NOTE: Parameters for RRES_TYPE_IMAGE are: width, height, format, mipmaps - if (rres.type == RRES_IMAGE) image = LoadImagePro(rres.data, rres.param1, rres.param2, rres.param3); + if (rres[0].type == RRES_TYPE_IMAGE) image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3); else TraceLog(WARNING, "[%s] Resource file does not contain image data", fileName); UnloadResource(rres); diff --git a/src/utils.c b/src/utils.c index e5e05955..9a2a723a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,16 +1,23 @@ /********************************************************************************************** * -* raylib.utils +* raylib.utils - Some common utility functions * -* Some utility functions +* CONFIGURATION: * -* External libs: -* tinfl - zlib DEFLATE algorithm decompression +* #define SUPPORT_SAVE_PNG +* Enable saving PNG fileformat +* NOTE: Requires stb_image_write library +* +* #define SUPPORT_SAVE_BMP +* +* #define DO_NOT_TRACE_DEBUG_MSGS +* Avoid showing DEBUG TraceLog() messages +* +* DEPENDENCIES: * stb_image_write - PNG writting functions * -* Module Configuration Flags: -* DO_NOT_TRACE_DEBUG_MSGS - Avoid showing DEBUG TraceLog() messages * +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * -- cgit v1.2.3