diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c index fdf770300..612f63748 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 dbcfa6bc1..1589439e4 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 b7dc1a8cd..4f36e203f 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 35cee39f8..52e92b50e 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 7616c1a4b..e19492749 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; }