Browse Source

Review rlglUnproject() system

raysan5 9 years ago
parent
commit
4476a9e241
5 changed files with 37 additions and 66 deletions
  1. 2 2
      examples/core_3d_picking.c
  2. 21 21
      src/core.c
  3. 1 0
      src/raylib.h
  4. 1 1
      src/raymath.h
  5. 12 42
      src/rlgl.c

+ 2 - 2
examples/core_3d_picking.c

@@ -53,8 +53,8 @@ int main()
             
             
             // Check collision between ray and box
             // Check collision between ray and box
             collision = CheckCollisionRayBox(ray,
             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 }});
         }
         }
         //----------------------------------------------------------------------------------
         //----------------------------------------------------------------------------------
 
 

+ 21 - 21
src/core.c

@@ -612,11 +612,11 @@ void Begin3dMode(Camera camera)
 
 
     // Setup perspective projection
     // Setup perspective projection
     float aspect = (float)screenWidth/(float)screenHeight;
     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;
     double right = top*aspect;
 
 
     // NOTE: zNear and zFar values are important when computing depth buffer values
     // 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
     rlMatrixMode(RL_MODELVIEW);         // Switch back to modelview matrix
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
     rlLoadIdentity();                   // Reset current matrix (MODELVIEW)
@@ -867,16 +867,8 @@ int StorageLoadValue(int position)
 }
 }
 
 
 // Returns a ray trace from mouse 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)
 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;
     Ray ray;
     
     
     // Calculate normalized device coordinates
     // Calculate normalized device coordinates
@@ -886,40 +878,48 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
     float z = 1.0f;
     float z = 1.0f;
     
     
     // Store values in a vector
     // 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
     // Calculate view matrix from camera look at
     Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
     Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up);
     
     
     // Do I need to transpose it? It seems that yes...
     // 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.
     // 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
     // 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).
     // to a vector, you will get its 3d world position coordinates (camera.position).
     // If you don't transpose, final position will be wrong.
     // If you don't transpose, final position will be wrong.
     MatrixTranspose(&matView);
     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
     // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it
     Matrix matProjView = MatrixMultiply(matProj, matView);
     Matrix matProjView = MatrixMultiply(matProj, matView);
     MatrixInvert(&matProjView);
     MatrixInvert(&matProjView);
     
     
     // Calculate far and near points
     // 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
     // Multiply points by unproject matrix
     QuaternionTransform(&near, matProjView);
     QuaternionTransform(&near, matProjView);
     QuaternionTransform(&far, matProjView);
     QuaternionTransform(&far, matProjView);
     
     
     // Calculate normalized world points in vectors
     // 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
     // Calculate normalized direction vector
     Vector3 direction = VectorSubtract(farPoint, nearPoint);
     Vector3 direction = VectorSubtract(farPoint, nearPoint);

+ 1 - 0
src/raylib.h

@@ -312,6 +312,7 @@ typedef struct Camera {
     Vector3 position;
     Vector3 position;
     Vector3 target;
     Vector3 target;
     Vector3 up;
     Vector3 up;
+    //float fovy;             // Field-Of-View apperture in Y (degrees)
 } Camera;
 } Camera;
 
 
 // Bounding box type
 // Bounding box type

+ 1 - 1
src/raymath.h

@@ -803,7 +803,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top,
 // Returns perspective projection matrix
 // Returns perspective projection matrix
 RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far)
 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;
     double right = top*aspect;
 
 
     return MatrixFrustum(-right, right, -top, top, near, far);
     return MatrixFrustum(-right, right, -top, top, near, far);

+ 12 - 42
src/rlgl.c

@@ -1611,54 +1611,24 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height)
 }
 }
 
 
 // Get world coordinates from screen coordinates
 // Get world coordinates from screen coordinates
-// NOTE: Using global variables: screenWidth, screenHeight
 Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
 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;
     return result;
 }
 }