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/raylib.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/raylib.h') 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 -- 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/raylib.h') 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/raylib.h') 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 4476a9e241b952f631afb6c8c3f3c69a481219e3 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 2 Mar 2016 17:13:31 +0100 Subject: Review rlglUnproject() system --- examples/core_3d_picking.c | 4 ++-- src/core.c | 42 ++++++++++++++++++------------------ src/raylib.h | 1 + src/raymath.h | 2 +- src/rlgl.c | 54 +++++++++++----------------------------------- 5 files changed, 37 insertions(+), 66 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c index fdf77030..612f6374 100644 --- a/examples/core_3d_picking.c +++ b/examples/core_3d_picking.c @@ -53,8 +53,8 @@ int main() // Check collision between ray and box collision = CheckCollisionRayBox(ray, - (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 }); + (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 }}); } //---------------------------------------------------------------------------------- diff --git a/src/core.c b/src/core.c index dbcfa6bc..1589439e 100644 --- a/src/core.c +++ b/src/core.c @@ -612,11 +612,11 @@ void Begin3dMode(Camera camera) // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.1*tan(45.0*PI/360.0); + double top = 0.01*tan(45.0*PI/360.0); double right = top*aspect; // NOTE: zNear and zFar values are important when computing depth buffer values - rlFrustum(-right, right, -top, top, 0.1f, 1000.0f); + rlFrustum(-right, right, -top, top, 0.01, 1000.0); rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix rlLoadIdentity(); // Reset current matrix (MODELVIEW) @@ -867,16 +867,8 @@ int StorageLoadValue(int position) } // Returns a ray trace from mouse position -//http://www.songho.ca/opengl/gl_transform.html -//http://www.songho.ca/opengl/gl_matrix.html -//http://www.sjbaker.org/steve/omniv/matrices_can_be_your_friends.html -//https://www.opengl.org/archives/resources/faq/technical/transformations.htm Ray GetMouseRay(Vector2 mousePosition, Camera camera) -{ - // Tutorial used: https://mkonrad.net/2014/08/07/simple-opengl-object-picking-in-3d.html - // Similar to http://antongerdelan.net, the problem is maybe in MatrixPerspective vs MatrixFrustum - // or matrix order (transpose it or not... that's the question) - +{ Ray ray; // Calculate normalized device coordinates @@ -886,40 +878,48 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) float z = 1.0f; // Store values in a vector - Vector3 deviceCoords = {x, y, z}; + Vector3 deviceCoords = { x, y, z }; - // Device debug message - TraceLog(INFO, "device(%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.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(45.0f, (float)((float)GetScreenWidth() / (float)GetScreenHeight()), 0.01f, 1000.0f); + // Calculate projection matrix (from perspective instead of frustum) + Matrix matProj = MatrixPerspective(45.0, ((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 is maybe incorrect... In OpenGL to get world position from + // 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. // For example, if you get view matrix, transpose and inverted and you transform it // 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); + +#else // OPTION 2: Compute unprojection directly here + // 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}; + 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}; + 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); diff --git a/src/raylib.h b/src/raylib.h index b7dc1a8c..4f36e203 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -312,6 +312,7 @@ typedef struct Camera { Vector3 position; Vector3 target; Vector3 up; + //float fovy; // Field-Of-View apperture in Y (degrees) } Camera; // Bounding box type diff --git a/src/raymath.h b/src/raymath.h index 35cee39f..52e92b50 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -803,7 +803,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, // Returns perspective projection matrix RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far) { - double top = near*tanf(fovy*PI/360.0f); + double top = near*tan(fovy*PI/360.0); double right = top*aspect; return MatrixFrustum(-right, right, -top, top, near, far); diff --git a/src/rlgl.c b/src/rlgl.c index 7616c1a4..e1949274 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1611,54 +1611,24 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height) } // Get world coordinates from screen coordinates -// NOTE: Using global variables: screenWidth, screenHeight Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) { - Vector3 result = { 0.0f, 0.0f, 0.0f }; // Object coordinates + Vector3 result = { 0.0f, 0.0f, 0.0f }; - //GLint viewport[4]; - //glGetIntegerv(GL_VIEWPORT, viewport); // Not available on OpenGL ES 2.0 - - // Viewport data - int x = 0; // viewport[0] - int y = 0; // viewport[1] - int width = screenWidth; // viewport[2] - int height = screenHeight; // viewport[3] + // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it + Matrix matProjView = MatrixMultiply(proj, view); + MatrixInvert(&matProjView); - Matrix modelviewprojection = MatrixMultiply(view, proj); - MatrixInvert(&modelviewprojection); -/* - // NOTE: Compute unproject using Vector3 - - // Transformation of normalized coordinates between -1 and 1 - result.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f; - result.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f; - result.z = source.z*2.0f - 1.0f; - - // Object coordinates (multiply vector by matrix) - VectorTransform(&result, modelviewprojection); -*/ - - // NOTE: Compute unproject using Quaternion (Vector4) - Quaternion quat; + // Create quaternion from source point + Quaternion quat = { source.x, source.y, source.z, 1.0f }; - quat.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f; - quat.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f; - quat.z = source.z*2.0f - 1.0f; - quat.w = 1.0f; + // Multiply quat point by unproject matrix + QuaternionTransform(&quat, matProjView); - QuaternionTransform(&quat, modelviewprojection); - - if (quat.w != 0.0f) - { - quat.x /= quat.w; - quat.y /= quat.w; - quat.z /= quat.w; - } - - result.x = quat.x; - result.y = quat.y; - result.z = quat.z; + // Normalized world points in vectors + result.x = quat.x/quat.w; + result.y = quat.y/quat.w; + result.z = quat.z/quat.w; return result; } -- cgit v1.2.3 From fffbf48dec317d55262de62f8bab757a31d0eebd Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 2 Mar 2016 19:22:55 +0100 Subject: Added support for Nearest-Neighbor image scaling Specially useful on default font scaling --- src/raylib.h | 1 + src/textures.c | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 4f36e203..f8f1683e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -691,6 +691,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering) +void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm) void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint); // Create an image from text (custom sprite font) diff --git a/src/textures.c b/src/textures.c index 36819daf..cb3113dc 100644 --- a/src/textures.c +++ b/src/textures.c @@ -919,6 +919,39 @@ void ImageResize(Image *image, int newWidth, int newHeight) free(pixels); } +// Resize and image to new size using Nearest-Neighbor scaling algorithm +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 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 + + free(output); + free(pixels); +} + // Draw an image (source) within an image (destination) void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) { @@ -1046,8 +1079,9 @@ Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, float scaleFactor = (float)fontSize/imSize.y; TraceLog(INFO, "Scalefactor: %f", scaleFactor); - // TODO: Allow nearest-neighbor scaling algorithm - ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*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); -- cgit v1.2.3 From dcbf2a0e0c904870ac3ac59a3623a3954ab0243f Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 3 Mar 2016 13:24:56 +0100 Subject: Replaced tabs by spaces --- games/tetris.c | 466 ++++++++++++++++++++++++++++----------------------------- src/core.c | 12 +- src/raylib.h | 2 +- 3 files changed, 240 insertions(+), 240 deletions(-) (limited to 'src/raylib.h') diff --git a/games/tetris.c b/games/tetris.c index 62400201..84ba9196 100644 --- a/games/tetris.c +++ b/games/tetris.c @@ -179,22 +179,22 @@ void InitGame(void) // Initialize grid matrices for (int i = 0; i < GRID_HORIZONTAL_SIZE; i++) - { - for (int j = 0; j < GRID_VERTICAL_SIZE; j++) - { + { + for (int j = 0; j < GRID_VERTICAL_SIZE; j++) + { if ((j == GRID_VERTICAL_SIZE - 1) || (i == 0) || (i == GRID_HORIZONTAL_SIZE - 1)) grid[i][j] = BLOCK; else grid[i][j] = EMPTY; - } - } + } + } // Initialize incoming piece matrices for (int i = 0; i < 4; i++) - { - for (int j = 0; j< 4; j++) - { - incomingPiece[i][j] = EMPTY; - } - } + { + for (int j = 0; j< 4; j++) + { + incomingPiece[i][j] = EMPTY; + } + } } // Update game (one frame) @@ -423,34 +423,34 @@ static bool Createpiece() piecePositionY = 0; // If the game is starting and you are going to create the first piece, we create an extra one - if (beginPlay) - { + if (beginPlay) + { GetRandompiece(); beginPlay = false; - } - + } + // We assign the incoming piece to the actual piece for (int i = 0; i < 4; i++) - { - for (int j = 0; j< 4; j++) - { - piece[i][j] = incomingPiece[i][j]; - } - } - + { + for (int j = 0; j< 4; j++) + { + piece[i][j] = incomingPiece[i][j]; + } + } + // We assign a random piece to the incoming one - GetRandompiece(); + GetRandompiece(); // Assign the piece to the grid for (int i = piecePositionX; i < piecePositionX + 4; i++) - { - for (int j = 0; j < 4; j++) - { - if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING; - } - } - - return true; + { + for (int j = 0; j < 4; j++) + { + if (piece[i - (int)piecePositionX][j] == MOVING) grid[i][j] = MOVING; + } + } + + return true; } static void GetRandompiece() @@ -459,22 +459,22 @@ static void GetRandompiece() int random = rand() % 7; for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - incomingPiece[i][j] = EMPTY; - } - } + { + for (int j = 0; j < 4; j++) + { + incomingPiece[i][j] = EMPTY; + } + } switch(random) - { - case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube - case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L - case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa - case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta - case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada - case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S - case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa + { + case 0: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //Cube + case 1: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; } break; //L + case 2: { incomingPiece[1][2] = MOVING; incomingPiece[2][0] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; } break; //L inversa + case 3: { incomingPiece[0][1] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //Recta + case 4: { incomingPiece[1][0] = MOVING; incomingPiece[1][1] = MOVING; incomingPiece[1][2] = MOVING; incomingPiece[2][1] = MOVING; } break; //Creu tallada + case 5: { incomingPiece[1][1] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[3][2] = MOVING; } break; //S + case 6: { incomingPiece[1][2] = MOVING; incomingPiece[2][2] = MOVING; incomingPiece[2][1] = MOVING; incomingPiece[3][1] = MOVING; } break; //S inversa } } @@ -482,34 +482,34 @@ static void ResolveFallingMovement(bool *detection, bool *pieceActive) { // If we finished moving this piece, we stop it if (*detection) - { + { for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - grid[i][j] = FULL; - *detection = false; - *pieceActive = false; - } - } - } - } + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j] = FULL; + *detection = false; + *pieceActive = false; + } + } + } + } // We move down the piece - else - { + else + { for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - grid[i][j+1] = MOVING; - grid[i][j] = EMPTY; - } - } - } + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j+1] = MOVING; + grid[i][j] = EMPTY; + } + } + } piecePositionY++; } } @@ -519,78 +519,78 @@ static bool ResolveLateralMovement() bool collision = false; // Move left - if (IsKeyDown(KEY_LEFT)) - { + if (IsKeyDown(KEY_LEFT)) + { // Check if is possible to move to left - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { // Check if we are touching the left wall or we have a full square at the left - if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true; - } - } - } + if ((i-1 == 0) || (grid[i-1][j] == FULL)) collision = true; + } + } + } // If able, move left - if (!collision) - { - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right - { + if (!collision) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) // We check the matrix from left to right + { // Move everything to the left - if (grid[i][j] == MOVING) - { - grid[i-1][j] = MOVING; - grid[i][j] = EMPTY; - } - } - } + if (grid[i][j] == MOVING) + { + grid[i-1][j] = MOVING; + grid[i][j] = EMPTY; + } + } + } piecePositionX--; - } - } + } + } // Move right - else if (IsKeyDown(KEY_RIGHT)) - { + else if (IsKeyDown(KEY_RIGHT)) + { // Check if is possible to move to right - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { // Check if we are touching the right wall or we have a full square at the right - if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL)) + if ((i+1 == GRID_HORIZONTAL_SIZE - 1) || (grid[i+1][j] == FULL)) { collision = true; } - } - } - } + } + } + } // If able move right - if (!collision) - { - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left - { + if (!collision) + { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = GRID_HORIZONTAL_SIZE - 1; i >= 1; i--) // We check the matrix from right to left + { // Move everything to the right - if (grid[i][j] == MOVING) - { - grid[i+1][j] = MOVING; - grid[i][j] = EMPTY; - } - } - } + if (grid[i][j] == MOVING) + { + grid[i+1][j] = MOVING; + grid[i][j] = EMPTY; + } + } + } piecePositionX++; - } - } + } + } return collision; } @@ -599,164 +599,164 @@ static bool ResolveTurnMovement() { // Input for turning the piece if (IsKeyDown(KEY_UP)) - { - int aux; - bool checker = false; + { + int aux; + bool checker = false; // Check all turning possibilities - if ((grid[piecePositionX + 3][piecePositionY] == MOVING) && + if ((grid[piecePositionX + 3][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY] != EMPTY) && (grid[piecePositionX][piecePositionY] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) && + if ((grid[piecePositionX + 3][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY] != EMPTY) && (grid[piecePositionX + 3][piecePositionY] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX][piecePositionY + 3] == MOVING) && + if ((grid[piecePositionX][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY + 3] != EMPTY) && (grid[piecePositionX + 3][piecePositionY + 3] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX][piecePositionY] == MOVING) && + if ((grid[piecePositionX][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY + 3] != EMPTY) && (grid[piecePositionX][piecePositionY + 3] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 1][piecePositionY] == MOVING) && + if ((grid[piecePositionX + 1][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY + 2] != EMPTY) && (grid[piecePositionX][piecePositionY + 2] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) && + if ((grid[piecePositionX + 3][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY] != EMPTY) && (grid[piecePositionX + 1][piecePositionY] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) && + if ((grid[piecePositionX + 2][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY + 1] != EMPTY) && (grid[piecePositionX + 3][piecePositionY + 1] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX][piecePositionY + 2] == MOVING) && + if ((grid[piecePositionX][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY + 3] != EMPTY) && (grid[piecePositionX + 2][piecePositionY + 3] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 2][piecePositionY] == MOVING) && + if ((grid[piecePositionX + 2][piecePositionY] == MOVING) && (grid[piecePositionX][piecePositionY + 1] != EMPTY) && (grid[piecePositionX][piecePositionY + 1] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) && + if ((grid[piecePositionX + 3][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY] != EMPTY) && (grid[piecePositionX + 2][piecePositionY] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) && + if ((grid[piecePositionX + 1][piecePositionY + 3] == MOVING) && (grid[piecePositionX + 3][piecePositionY + 2] != EMPTY) && (grid[piecePositionX + 3][piecePositionY + 2] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX][piecePositionY + 1] == MOVING) && + if ((grid[piecePositionX][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY + 3] != EMPTY) && (grid[piecePositionX + 1][piecePositionY + 3] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) && + if ((grid[piecePositionX + 1][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY + 2] != EMPTY) && (grid[piecePositionX + 1][piecePositionY + 2] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) && + if ((grid[piecePositionX + 2][piecePositionY + 1] == MOVING) && (grid[piecePositionX + 1][piecePositionY + 1] != EMPTY) && (grid[piecePositionX + 1][piecePositionY + 1] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) && + if ((grid[piecePositionX + 2][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY + 1] != EMPTY) && (grid[piecePositionX + 2][piecePositionY + 1] != MOVING)) - { + { checker = true; } - if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) && + if ((grid[piecePositionX + 1][piecePositionY + 2] == MOVING) && (grid[piecePositionX + 2][piecePositionY + 2] != EMPTY) && (grid[piecePositionX + 2][piecePositionY + 2] != MOVING)) - { + { checker = true; } - if (!checker) - { - aux = piece[0][0]; - piece[0][0] = piece[3][0]; - piece[3][0] = piece[3][3]; - piece[3][3] = piece[0][3]; - piece[0][3] = aux; - - aux = piece[1][0]; - piece[1][0] = piece[3][1]; - piece[3][1] = piece[2][3]; - piece[2][3] = piece[0][2]; - piece[0][2] = aux; - - aux = piece[2][0]; - piece[2][0] = piece[3][2]; - piece[3][2] = piece[1][3]; - piece[1][3] = piece[0][1]; - piece[0][1] = aux; - - aux = piece[1][1]; - piece[1][1] = piece[2][1]; - piece[2][1] = piece[2][2]; - piece[2][2] = piece[1][2]; - piece[1][2] = aux; - } - - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if (grid[i][j] == MOVING) - { - grid[i][j] = EMPTY; - } - } - } - - for (int i = piecePositionX; i < piecePositionX + 4; i++) - { - for (int j = piecePositionY; j < piecePositionY + 4; j++) - { - if (piece[i - piecePositionX][j - piecePositionY] == MOVING) - { - grid[i][j] = MOVING; - } - } - } + if (!checker) + { + aux = piece[0][0]; + piece[0][0] = piece[3][0]; + piece[3][0] = piece[3][3]; + piece[3][3] = piece[0][3]; + piece[0][3] = aux; + + aux = piece[1][0]; + piece[1][0] = piece[3][1]; + piece[3][1] = piece[2][3]; + piece[2][3] = piece[0][2]; + piece[0][2] = aux; + + aux = piece[2][0]; + piece[2][0] = piece[3][2]; + piece[3][2] = piece[1][3]; + piece[1][3] = piece[0][1]; + piece[0][1] = aux; + + aux = piece[1][1]; + piece[1][1] = piece[2][1]; + piece[2][1] = piece[2][2]; + piece[2][2] = piece[1][2]; + piece[1][2] = aux; + } + + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if (grid[i][j] == MOVING) + { + grid[i][j] = EMPTY; + } + } + } + + for (int i = piecePositionX; i < piecePositionX + 4; i++) + { + for (int j = piecePositionY; j < piecePositionY + 4; j++) + { + if (piece[i - piecePositionX][j - piecePositionY] == MOVING) + { + grid[i][j] = MOVING; + } + } + } return true; - } + } return false; } @@ -764,44 +764,44 @@ static bool ResolveTurnMovement() static void CheckDetection(bool *detection) { for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { - if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true; - } - } + { + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { + if ((grid[i][j] == MOVING) && ((grid[i][j+1] == FULL) || (grid[i][j+1] == BLOCK))) *detection = true; + } + } } static void CheckCompletition(bool *lineToDelete) { int calculator; - for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) - { - calculator = 0; - for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) - { + for (int j = GRID_VERTICAL_SIZE - 2; j >= 0; j--) + { + calculator = 0; + for (int i = 1; i < GRID_HORIZONTAL_SIZE - 1; i++) + { // Count each square of the line - if (grid[i][j] == FULL) - { - calculator++; - } + if (grid[i][j] == FULL) + { + calculator++; + } // Check if we completed the whole line - if (calculator == GRID_HORIZONTAL_SIZE - 2) - { + if (calculator == GRID_HORIZONTAL_SIZE - 2) + { *lineToDelete = true; calculator = 0; - // points++; + // points++; // Mark the completed line - for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++) - { - grid[z][j] = FADING; - } - } - } - } + for (int z = 1; z < GRID_HORIZONTAL_SIZE - 1; z++) + { + grid[z][j] = FADING; + } + } + } + } } static void DeleteCompleteLines() diff --git a/src/core.c b/src/core.c index 1589439e..259e1f29 100644 --- a/src/core.c +++ b/src/core.c @@ -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/raylib.h b/src/raylib.h index f8f1683e..00afb4f3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -385,7 +385,7 @@ typedef struct Model { 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) -- 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/raylib.h') 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 5ea18b9426823e92f1fc16e686702f2caadf83c9 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 5 Mar 2016 15:40:08 +0100 Subject: Support 2d camera system -IN PROGRESS- --- examples/core_2d_camera.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ src/core.c | 21 ++++++++++++-- src/raylib.h | 11 +++++++- 3 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 examples/core_2d_camera.c (limited to 'src/raylib.h') diff --git a/examples/core_2d_camera.c b/examples/core_2d_camera.c new file mode 100644 index 00000000..71c474f0 --- /dev/null +++ b/examples/core_2d_camera.c @@ -0,0 +1,71 @@ +/******************************************************************************************* +* +* raylib [core] example - 2d camera +* +* This example has been created using raylib 1.5 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2016 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - 2d camera"); + + Camera2D camera; + + camera.position = (Vector2){ 0, 0 }; + camera.origin = (Vector2){ 100, 100 }; + camera.rotation = 0.0f; + camera.zoom = 1.0f; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyDown(KEY_RIGHT)) camera.position.x--; + else if (IsKeyDown(KEY_LEFT)) camera.position.x++; + else if (IsKeyDown(KEY_UP)) camera.position.y++; + else if (IsKeyDown(KEY_DOWN)) camera.position.y--; + + if (IsKeyDown(KEY_R)) camera.rotation--; + else if (IsKeyDown(KEY_F)) camera.rotation++; + + if (IsKeyDown(KEY_W)) camera.zoom += 0.005f; + if (IsKeyDown(KEY_S)) camera.zoom -= 0.005f; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawingEx(camera); + + ClearBackground(RAYWHITE); + + DrawText("2D CAMERA TEST", 20, 20, 20, GRAY); + + DrawRectangle(0, 300, screenWidth, 50, GRAY); + DrawRectangle(400, 250, 40, 40, RED); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/src/core.c b/src/core.c index a8cc593a..870ca3b4 100644 --- a/src/core.c +++ b/src/core.c @@ -560,8 +560,25 @@ void BeginDrawing(void) // NOTE: Not required with OpenGL 3.3+ } -// Setup drawing canvas with extended parameters -void BeginDrawingEx(int blendMode, Shader shader, Matrix transform) +// Setup drawing canvas with 2d camera +void BeginDrawingEx(Camera2D camera) +{ + BeginDrawing(); + + // TODO: Consider origin offset on position, rotation, scaling + + 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.position.x, camera.position.y, 0.0f); + Matrix matOrigin = MatrixTranslate(-camera.origin.x, -camera.origin.y, 0.0f); + + Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation); + + rlMultMatrixf(MatrixToFloat(matTransform)); +} + +// Setup drawing canvas with pro parameters +void BeginDrawingPro(int blendMode, Shader shader, Matrix transform) { BeginDrawing(); diff --git a/src/raylib.h b/src/raylib.h index b6cf98fe..7173a556 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -315,6 +315,14 @@ typedef struct Camera { float fovy; // Field-Of-View apperture in Y (degrees) } Camera; +// Camera2D type, defines a 2d camera +typedef struct Camera2D { + Vector2 position; // Camera position + Vector2 origin; // Camera origin (for rotation and zoom) + float rotation; // Camera rotation in degrees + float zoom; // Camera zoom (scaling), should be 1.0f by default +} Camera2D; + // Bounding box type typedef struct BoundingBox { Vector3 min; @@ -528,7 +536,8 @@ int GetScreenHeight(void); // Get current scree void ClearBackground(Color color); // Sets Background Color void BeginDrawing(void); // Setup drawing canvas to start drawing -void BeginDrawingEx(int blendMode, Shader shader, Matrix transform); // Setup drawing canvas with extended parameters +void BeginDrawingEx(Camera2D camera); // Setup drawing canvas with 2d camera +void BeginDrawingPro(int blendMode, Shader shader, Matrix transform); // Setup drawing canvas with pro parameters void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering) void Begin3dMode(Camera camera); // Initializes 3D mode for drawing (Camera setup) -- 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/raylib.h') 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/raylib.h') 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 d0e7195a16c50b23fd82e7ca7869cc07773ddba2 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 6 Mar 2016 19:28:58 +0100 Subject: Added new functions to draw text on image --- src/raylib.h | 4 +++- src/textures.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index f448487e..527d0cb9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -697,9 +697,11 @@ Image ImageCopy(Image image); void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering) void ImageResizeNN(Image *image,int newWidth,int newHeight); // Resize and image (Nearest-Neighbor scaling algorithm) -void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint); // Create an image from text (custom sprite font) +void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image +void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color); // Draw text (default font) within an image (destination) +void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, int fontSize, int spacing, Color color); // Draw text (custom sprite font) within an image (destination) void ImageFlipVertical(Image *image); // Flip image vertically void ImageFlipHorizontal(Image *image); // Flip image horizontally void ImageColorTint(Image *image, Color color); // Modify image color: tint diff --git a/src/textures.c b/src/textures.c index cb3113dc..e649df57 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1090,6 +1090,25 @@ Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, return imText; } +// Draw text (default font) within an image (destination) +void ImageDrawText(Image *dst, Vector2 position, const char *text, int fontSize, Color color) +{ + ImageDrawTextEx(dst, position, GetDefaultFont(), text, fontSize, 0, color); +} + +// Draw text (custom sprite font) within an image (destination) +void ImageDrawTextEx(Image *dst, Vector2 position, SpriteFont font, const char *text, int 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); +} + // Flip image vertically void ImageFlipVertical(Image *image) { -- cgit v1.2.3