Browse Source

Merge pull request #212 from joeld42/jbd_picking

Raycast Picking Utilities
Ray 8 năm trước cách đây
mục cha
commit
0369bb4c8c

+ 6 - 0
examples/Makefile

@@ -203,6 +203,7 @@ EXAMPLES = \
     core_gestures_detection \
     core_3d_mode \
     core_3d_picking \
+    core_3d_raypick \
     core_3d_camera_free \
     core_3d_camera_first_person \
     core_2d_camera \
@@ -320,6 +321,11 @@ core_3d_mode: core_3d_mode.c
 core_3d_picking: core_3d_picking.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
 
+# compile [core] example - 3d ray picking
+core_3d_raypick: core_3d_raypick.c
+	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)
+
+
 # compile [core] example - 3d camera free
 core_3d_camera_free: core_3d_camera_free.c
 	$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS)

+ 195 - 0
examples/core_3d_raypick.c

@@ -0,0 +1,195 @@
+/*******************************************************************************************
+*
+*   raylib [core] example - Ray-Picking in 3d mode, ground plane, triangle, mesh
+*
+*   This example has been created using raylib 1.3 (www.raylib.com)
+*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+*   Copyright (c) 2015 Ramon Santamaria (@raysan5)
+*   Example contributed by Joel Davis (@joeld42)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "raymath.h"
+
+#include <stdio.h>
+#include <float.h>
+
+
+int main()
+{
+    // Initialization
+    //--------------------------------------------------------------------------------------
+    int screenWidth = 800;
+    int screenHeight = 450;
+
+    InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d ray picking");
+
+    // Define the camera to look into our 3d world
+    Camera camera;
+    camera.position = (Vector3){ 10.0f, 8.0f, 10.0f }; // Camera position
+    camera.target = (Vector3){ 0.0f, 2.3f, 0.0f };      // Camera looking at point
+    camera.up = (Vector3){ 0.0f, 1.6f, 0.0f };          // Camera up vector (rotation towards target)
+    camera.fovy = 45.0f;                                // Camera field-of-view Y
+
+    Vector3 cubePosition = { 0.0f, 1.0f, 0.0f };
+    Vector3 cubeSize = { 2.0f, 2.0f, 2.0f };
+    
+    Ray ray;        // Picking line ray
+    
+    Model tower = LoadModel("resources/model/lowpoly-tower.obj");           // Load OBJ model
+    Texture2D texture = LoadTexture("resources/model/lowpoly-tower.png");   // Load model texture
+    tower.material.texDiffuse = texture;                                    // Set model diffuse texture
+    Vector3 towerPos = { 0.0f, 0.0f, 0.0f };                                // Set model position
+    BoundingBox towerBBox = CalculateBoundingBox( tower.mesh );    
+    bool hitMeshBBox;
+    bool hitTriangle;
+
+    // Test triangle
+    Vector3 ta = (Vector3){ -25.0, 0.5, 0.0 };    
+    Vector3 tb = (Vector3){ -4.0, 2.5, 1.0 };
+    Vector3 tc = (Vector3){ -8.0, 6.5, 0.0 };
+
+    Vector3 bary = {0};
+
+    SetCameraMode(camera, CAMERA_FREE); // Set a free camera mode
+
+    SetTargetFPS(60);                   // Set our game to run at 60 frames-per-second
+
+    //--------------------------------------------------------------------------------------
+    // Main game loop
+    while (!WindowShouldClose())        // Detect window close button or ESC key
+    {
+        // Update
+        //----------------------------------------------------------------------------------
+        UpdateCamera(&camera);          // Update camera
+        
+
+        // Display information about closest hit
+        RayHitInfo nearestHit;
+        char *hitObjectName = "None";
+        nearestHit.distance = FLT_MAX;
+        nearestHit.hit = false;
+        Color cursorColor = WHITE;
+
+        // Get ray and test against ground, triangle, and mesh
+        ray = GetMouseRay(GetMousePosition(), camera);
+        
+        RayHitInfo groundHitInfo = RaycastGroundPlane( ray, 0.0 );
+        if ((groundHitInfo.hit) && (groundHitInfo.distance < nearestHit.distance)) {
+            nearestHit = groundHitInfo;
+            cursorColor = GREEN;
+            hitObjectName = "Ground";
+        }
+
+        RayHitInfo triHitInfo = RaycastTriangle( ray, ta, tb, tc );
+        if ((triHitInfo.hit) && (triHitInfo.distance < nearestHit.distance)) {
+            nearestHit = triHitInfo;
+            cursorColor = PURPLE;
+            hitObjectName = "Triangle";
+
+            bary = Barycentric( nearestHit.hitPosition, ta, tb, tc );
+            hitTriangle = true;
+        } else {
+            hitTriangle = false;
+        }
+
+        RayHitInfo meshHitInfo;
+
+        // check the bounding box first, before trying the full ray/mesh test
+        if (CheckCollisionRayBox( ray, towerBBox )) {
+            hitMeshBBox = true;
+            meshHitInfo = RaycastMesh( ray, &tower.mesh );    
+            if ((meshHitInfo.hit) && (meshHitInfo.distance < nearestHit.distance)) {
+                nearestHit = meshHitInfo;
+                cursorColor = ORANGE;
+                hitObjectName = "Mesh";
+            }
+        } else {
+            hitMeshBBox = false;
+        }    
+
+        //----------------------------------------------------------------------------------
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+
+            Begin3dMode(camera);
+
+                // Draw the tower
+                DrawModel( tower, towerPos, 1.0, WHITE );
+                
+                // Draw the test triangle
+                DrawLine3D( ta, tb, PURPLE );
+                DrawLine3D( tb, tc, PURPLE );
+                DrawLine3D( tc, ta, PURPLE );
+
+                // Draw the mesh bbox if we hit it
+                if (hitMeshBBox) {
+                    DrawBoundingBox( towerBBox, LIME );
+                }
+
+                // If we hit something, draw the cursor at the hit point
+                if (nearestHit.hit) {
+                    DrawCube( nearestHit.hitPosition, 0.5, 0.5, 0.5, cursorColor );
+                    DrawCubeWires( nearestHit.hitPosition, 0.5, 0.5, 0.5, YELLOW );
+
+                    Vector3 normalEnd;
+                    normalEnd.x = nearestHit.hitPosition.x + nearestHit.hitNormal.x;
+                    normalEnd.y = nearestHit.hitPosition.y + nearestHit.hitNormal.y;
+                    normalEnd.z = nearestHit.hitPosition.z + nearestHit.hitNormal.z;
+                    DrawLine3D( nearestHit.hitPosition, normalEnd, YELLOW );
+                }
+
+                DrawRay(ray, MAROON);
+                
+                DrawGrid(10, 1.0f);
+
+            End3dMode();
+            
+            // Show some debug text
+            char line[1024];
+            sprintf( line, "Hit Object: %s\n", hitObjectName );
+            DrawText( line, 10, 30, 15, BLACK );
+
+            if (nearestHit.hit) {
+                int ypos = 45;
+                sprintf( line, "Distance: %3.2f", nearestHit.distance );
+                DrawText( line, 10, ypos, 15, BLACK );
+                ypos += 15;
+
+                sprintf( line, "Hit Pos: %3.2f %3.2f %3.2f", 
+                    nearestHit.hitPosition.x, nearestHit.hitPosition.y, nearestHit.hitPosition.z );
+                DrawText( line, 10, ypos, 15, BLACK );
+                ypos += 15;
+
+                sprintf( line, "Hit Norm: %3.2f %3.2f %3.2f", 
+                    nearestHit.hitNormal.x, nearestHit.hitNormal.y, nearestHit.hitNormal.z );
+                DrawText( line, 10, ypos, 15, BLACK );
+                ypos += 15;
+
+                if (hitTriangle) {
+                    sprintf( line, "Barycentric: %3.2f %3.2f %3.2f", 
+                        bary.x, bary.y, bary.z );
+                    DrawText( line, 10, ypos, 15, BLACK );
+                }
+            }
+
+            DrawText( "Use Mouse to Move Camera", 10, 420, 15, LIGHTGRAY );
+
+            DrawFPS(10, 10);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    CloseWindow();        // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

+ 456 - 0
examples/resources/model/lowpoly-tower.obj

@@ -0,0 +1,456 @@
+# Blender v2.78 (sub 0) OBJ File: 'lowpoly-tower.blend'
+# www.blender.org
+o Grid
+v -4.000000 0.000000 4.000000
+v -2.327363 0.000000 4.654725
+v 0.000000 0.000000 4.654725
+v 2.327363 0.000000 4.654725
+v 4.000000 0.000000 4.000000
+v -4.654725 0.955085 2.327363
+v -2.000000 0.815050 2.000000
+v 0.000000 0.476341 2.423448
+v 2.000000 0.476341 2.000000
+v 4.654725 0.000000 2.327363
+v -4.654725 1.649076 0.000000
+v -2.423448 1.092402 0.000000
+v 2.423448 0.198579 0.000000
+v 4.654725 0.000000 0.000000
+v -4.654725 1.649076 -2.327363
+v -2.000000 1.092402 -2.000000
+v 0.000000 0.476341 -2.423448
+v 2.000000 -0.012791 -2.000000
+v 4.654725 0.000000 -2.612731
+v -4.000000 0.955085 -4.000000
+v -2.327363 0.955085 -4.654725
+v 0.000000 0.955085 -4.654725
+v 2.327363 0.000000 -4.654725
+v 4.000000 0.000000 -4.000000
+v 2.423448 0.682825 0.000000
+v 2.000000 0.565423 -2.000000
+v -4.654725 -0.020560 2.327363
+v -4.654725 0.000000 0.000000
+v -4.654725 0.000000 -2.327363
+v -4.000000 0.000000 -4.000000
+v -2.327363 0.000000 -4.654725
+v 0.000000 -0.020560 -4.654725
+v 0.000000 0.709880 -1.230535
+v -0.000000 7.395413 0.000000
+v 0.962071 0.709880 -0.767226
+v -0.533909 0.709880 1.108674
+v -1.199683 0.709880 0.273820
+v -0.962071 0.709880 -0.767226
+v 1.506076 0.859071 1.325337
+v 1.199683 0.709880 0.273820
+v 0.533909 0.709880 1.108674
+v 0.000000 1.875340 -1.177842
+v -0.000000 2.293973 -0.649884
+v -0.000000 4.365648 -0.627970
+v 0.000000 6.167194 -0.942957
+v 0.000000 6.232434 -1.708677
+v 1.335898 6.232434 -1.065343
+v 0.737233 6.167195 -0.587924
+v 0.490966 4.365648 -0.391533
+v 0.508100 2.293973 -0.405196
+v 0.920874 1.875340 -0.734372
+v -0.741367 6.232434 1.539465
+v -0.409133 6.167195 0.849574
+v -0.272466 4.365648 0.565781
+v -0.281974 2.293973 0.585526
+v -0.511047 1.875340 1.061199
+v -1.665837 6.232434 0.380217
+v -0.919314 6.167195 0.209828
+v -0.612225 4.365648 0.139736
+v -0.633590 2.293973 0.144613
+v -1.148311 1.875340 0.262095
+v -1.335898 6.232434 -1.065343
+v -0.737233 6.167195 -0.587924
+v -0.490967 4.365648 -0.391533
+v -0.508100 2.293973 -0.405196
+v -0.920874 1.875340 -0.734372
+v 1.665837 6.232434 0.380216
+v 0.919315 6.167195 0.209828
+v 0.612225 4.365648 0.139736
+v 0.633590 2.293973 0.144613
+v 1.148311 1.875340 0.262095
+v 0.741367 6.232434 1.539465
+v 0.409133 6.167195 0.849575
+v 0.272466 4.365648 0.565781
+v 0.281974 2.293973 0.585526
+v 0.511046 1.875340 1.061199
+v 0.000000 5.012550 -0.969733
+v 0.758168 5.012550 -0.604618
+v -0.420751 5.012550 0.873699
+v -0.945419 5.012550 0.215786
+v -0.758168 5.012550 -0.604618
+v 0.945419 5.012550 0.215786
+v 0.420751 5.012550 0.873699
+vt 0.0523 0.5444
+vt 0.1817 0.4284
+vt 0.1641 0.5859
+vt 0.0177 0.4451
+vt 0.1526 0.3090
+vt 0.0189 0.1737
+vt 0.0188 0.3088
+vt 0.0561 0.0762
+vt 0.1757 0.1924
+vt 0.3024 0.4534
+vt 0.3071 0.5902
+vt 0.3413 0.2459
+vt 0.2906 0.1614
+vt 0.4116 0.1801
+vt 0.2834 0.3774
+vt 0.1526 0.0362
+vt 0.2917 0.1622
+vt 0.4446 0.5865
+vt 0.4443 0.2989
+vt 0.3711 0.3021
+vt 0.4396 0.0275
+vt 0.4094 0.1829
+vt 0.4219 0.4255
+vt 0.5474 0.5381
+vt 0.5811 0.4376
+vt 0.5715 0.1505
+vt 0.5811 0.2997
+vt 0.5272 0.0533
+vt 0.2208 0.2194
+vt 0.3456 0.3610
+vt 0.2878 0.0321
+vt 0.2321 0.3392
+vt 0.4432 0.0177
+vt 0.7347 0.7934
+vt 0.7382 0.7595
+vt 0.8982 0.7768
+vt 0.6169 0.7595
+vt 0.6139 0.7879
+vt 0.4951 0.7634
+vt 0.1551 0.6832
+vt 0.2925 0.6268
+vt 0.2925 0.6832
+vt 0.7795 0.6832
+vt 0.6421 0.6268
+vt 0.7795 0.6255
+vt 0.5046 0.7241
+vt 0.6421 0.7241
+vt 0.3986 0.6268
+vt 0.3986 0.6832
+vt 0.5046 0.6268
+vt 0.0177 0.6268
+vt 0.1551 0.6255
+vt 0.8856 0.6268
+vt 0.1899 0.9579
+vt 0.1194 0.8696
+vt 0.2324 0.8696
+vt 0.1899 0.7813
+vt 0.0943 0.7595
+vt 0.0177 0.8206
+vt 0.0177 0.9186
+vt 0.0943 0.9797
+vt 0.2793 0.2349
+vt 0.2304 0.2758
+vt 0.6597 0.0177
+vt 0.6954 0.0993
+vt 0.6367 0.0768
+vt 0.7558 0.0777
+vt 0.7238 0.0440
+vt 0.8840 0.1330
+vt 0.7385 0.1141
+vt 0.9157 0.0886
+vt 0.9781 0.1232
+vt 0.9224 0.1276
+vt 0.2677 0.8141
+vt 0.3463 0.8037
+vt 0.3086 0.8339
+vt 0.6387 0.3550
+vt 0.7130 0.3801
+vt 0.6596 0.4053
+vt 0.7245 0.3245
+vt 0.6919 0.3383
+vt 0.8655 0.3566
+vt 0.7351 0.3577
+vt 0.9770 0.3365
+vt 0.9078 0.3751
+vt 0.9174 0.3282
+vt 0.2677 0.9018
+vt 0.3086 0.8821
+vt 0.6803 0.2948
+vt 0.6251 0.3035
+vt 0.7194 0.2854
+vt 0.8764 0.2832
+vt 0.9221 0.2861
+vt 0.3363 0.9565
+vt 0.3464 0.9122
+vt 0.6751 0.2482
+vt 0.6178 0.2499
+vt 0.7179 0.2431
+vt 0.9823 0.2484
+vt 0.9247 0.2452
+vt 0.3935 0.9014
+vt 0.6755 0.1996
+vt 0.6164 0.1941
+vt 0.7201 0.1992
+vt 0.8793 0.2446
+vt 0.9823 0.2060
+vt 0.9257 0.2051
+vt 0.4598 0.8580
+vt 0.4144 0.8579
+vt 0.6819 0.1498
+vt 0.6222 0.1361
+vt 0.7266 0.1555
+vt 0.8831 0.1684
+vt 0.9252 0.1659
+vt 0.4218 0.7790
+vt 0.3934 0.8145
+vt 0.3363 0.7595
+vt 0.8815 0.2060
+vt 0.8720 0.3208
+vt 0.8825 0.1012
+vt 0.9735 0.0816
+vt 0.9718 0.3817
+vt 0.9807 0.2918
+vt 0.4218 0.9370
+vt 0.9810 0.1644
+vn 0.1035 0.8806 0.4623
+vn 0.0964 0.9481 0.3030
+vn 0.0000 0.9780 0.2088
+vn 0.0659 0.9835 0.1683
+vn 0.2325 0.9320 0.2779
+vn 0.0553 0.9960 -0.0702
+vn 0.2827 0.9564 0.0728
+vn 0.1873 0.9776 -0.0961
+vn 0.2421 0.9703 0.0000
+vn 0.0921 0.9772 -0.1913
+vn -0.0277 0.9947 -0.0993
+vn 0.2308 0.9274 -0.2944
+vn 0.2771 0.9572 -0.0837
+vn 0.3724 0.9074 0.1947
+vn 0.0777 0.9770 -0.1985
+vn -0.1094 0.9539 0.2794
+vn 0.0364 0.9844 0.1721
+vn 0.1683 0.9835 0.0659
+vn 0.0674 0.9901 0.1230
+vn 0.4338 0.8823 0.1829
+vn 0.2845 0.9565 0.0649
+vn 0.0886 0.9961 0.0000
+vn 0.2000 0.9789 0.0424
+vn 0.1417 0.9830 0.1171
+vn 0.3021 0.9524 0.0412
+vn -0.0193 0.9986 -0.0493
+vn 0.0000 0.9777 0.2098
+vn 0.0005 0.9781 -0.2083
+vn 0.1879 0.9782 -0.0887
+vn 0.2249 0.0000 0.9744
+vn 0.9783 0.0000 -0.2071
+vn 0.9783 0.0000 0.2071
+vn 0.0000 0.0000 -1.0000
+vn -1.0000 0.0000 0.0000
+vn -0.3645 0.0000 -0.9312
+vn -0.9312 0.0000 -0.3645
+vn -0.9312 0.0000 0.3645
+vn 0.2615 0.7979 -0.5431
+vn 0.5877 0.7979 -0.1341
+vn 0.4713 0.7979 0.3758
+vn -0.0000 0.7979 0.6028
+vn -0.4713 0.7979 0.3758
+vn -0.5877 0.7979 -0.1341
+vn -0.2615 0.7979 -0.5431
+vn -0.1285 0.9864 -0.1025
+vn 0.0929 0.8937 0.4389
+vn -0.4335 0.0407 -0.9002
+vn -0.2867 0.7507 -0.5952
+vn -0.4339 0.0095 -0.9009
+vn -0.4338 0.0209 -0.9008
+vn -0.0408 -0.9956 -0.0848
+vn -0.9741 0.0407 -0.2223
+vn -0.6441 0.7507 -0.1470
+vn -0.9749 0.0095 -0.2225
+vn -0.9747 0.0209 -0.2225
+vn -0.0918 -0.9956 -0.0209
+vn -0.7812 0.0407 0.6230
+vn -0.5165 0.7507 0.4119
+vn -0.7818 0.0095 0.6235
+vn -0.7817 0.0209 0.6234
+vn -0.0736 -0.9956 0.0587
+vn -0.0000 0.0407 0.9992
+vn 0.0000 0.7507 0.6607
+vn 0.0000 0.0095 1.0000
+vn -0.0000 0.0209 0.9998
+vn -0.0000 -0.9956 0.0941
+vn 0.7812 0.0407 0.6230
+vn 0.5165 0.7507 0.4119
+vn 0.7818 0.0095 0.6235
+vn 0.7817 0.0209 0.6234
+vn 0.0736 -0.9956 0.0587
+vn 0.9741 0.0407 -0.2223
+vn 0.6441 0.7507 -0.1470
+vn 0.9749 0.0095 -0.2225
+vn 0.9747 0.0209 -0.2225
+vn 0.0918 -0.9956 -0.0209
+vn 0.4335 0.0407 -0.9002
+vn 0.2867 0.7507 -0.5952
+vn 0.4339 0.0095 -0.9009
+vn 0.4338 0.0209 -0.9008
+vn 0.0408 -0.9956 -0.0848
+vn 0.3918 -0.4298 -0.8135
+vn 0.8803 -0.4298 -0.2009
+vn 0.7059 -0.4298 0.5630
+vn -0.0000 -0.4298 0.9029
+vn -0.7059 -0.4298 0.5630
+vn -0.8803 -0.4298 -0.2009
+vn -0.3918 -0.4298 -0.8135
+vn 0.0210 0.9998 -0.0048
+vn 0.0482 0.9981 -0.0385
+vn -0.0166 0.9914 -0.1301
+vn -0.0090 0.9904 -0.1379
+vn 0.2820 0.9576 0.0597
+vn -0.0000 0.9846 0.1749
+vn -0.0921 0.9772 -0.1913
+vn -0.1734 0.9794 0.1036
+s off
+f 1/1/1 7/2/1 6/3/1
+f 2/4/2 8/5/2 7/2/2
+f 4/6/3 8/5/3 3/7/3
+f 5/8/4 9/9/4 4/6/4
+f 6/3/5 12/10/5 11/11/5
+f 35/12/6 25/13/6 26/14/6
+f 7/2/7 37/15/7 12/10/7
+f 10/16/8 13/17/8 9/9/8
+f 12/10/9 15/18/9 11/11/9
+f 35/12/10 17/19/10 33/20/10
+f 13/17/11 19/21/11 18/22/11
+f 16/23/12 20/24/12 15/18/12
+f 17/19/13 21/25/13 16/23/13
+f 17/19/14 23/26/14 22/27/14
+f 26/14/15 24/28/15 23/26/15
+f 1/1/16 2/4/16 7/2/16
+f 2/4/3 3/7/3 8/5/3
+f 4/6/17 9/9/17 8/5/17
+f 5/8/18 10/16/18 9/9/18
+f 6/3/19 7/2/19 12/10/19
+f 25/13/20 39/29/20 9/9/20
+f 38/30/21 12/10/21 37/15/21
+f 10/16/22 14/31/22 13/17/22
+f 12/10/23 16/23/23 15/18/23
+f 8/5/24 36/32/24 7/2/24
+f 38/30/25 17/19/25 16/23/25
+f 13/17/22 14/31/22 19/21/22
+f 16/23/26 21/25/26 20/24/26
+f 17/19/27 22/27/27 21/25/27
+f 17/19/28 26/14/28 23/26/28
+f 26/14/29 19/33/29 24/28/29
+f 26/34/30 18/35/30 19/36/30
+f 26/34/31 13/37/31 18/35/31
+f 25/38/32 9/39/32 13/37/32
+f 22/40/33 31/41/33 21/42/33
+f 6/43/34 28/44/34 27/45/34
+f 15/46/34 28/44/34 11/47/34
+f 21/42/35 30/48/35 20/49/35
+f 20/49/36 29/50/36 15/46/36
+f 22/40/33 23/51/33 32/52/33
+f 6/43/37 27/45/37 1/53/37
+f 46/54/38 34/55/38 47/56/38
+f 47/56/39 34/55/39 67/57/39
+f 67/57/40 34/55/40 72/58/40
+f 72/58/41 34/55/41 52/59/41
+f 52/59/42 34/55/42 57/60/42
+f 57/60/43 34/55/43 62/61/43
+f 62/61/44 34/55/44 46/54/44
+f 40/62/45 41/63/45 39/29/45
+f 39/29/46 8/5/46 9/9/46
+f 38/64/47 42/65/47 33/66/47
+f 65/67/48 42/65/48 66/68/48
+f 65/67/49 44/69/49 43/70/49
+f 81/71/50 45/72/50 77/73/50
+f 62/74/51 45/75/51 63/76/51
+f 37/77/52 66/78/52 38/79/52
+f 60/80/53 66/78/53 61/81/53
+f 60/80/54 64/82/54 65/83/54
+f 58/84/55 81/85/55 80/86/55
+f 57/87/56 63/76/56 58/88/56
+f 56/89/57 37/77/57 36/90/57
+f 55/91/58 61/81/58 56/89/58
+f 54/92/59 60/80/59 55/91/59
+f 79/93/60 58/84/60 80/86/60
+f 52/94/61 58/88/61 53/95/61
+f 76/96/62 36/90/62 41/97/62
+f 75/98/63 56/89/63 76/96/63
+f 75/98/64 54/92/64 55/91/64
+f 73/99/65 79/93/65 83/100/65
+f 73/101/66 52/94/66 53/95/66
+f 71/102/67 41/97/67 40/103/67
+f 70/104/68 76/96/68 71/102/68
+f 70/104/69 74/105/69 75/98/69
+f 68/106/70 83/100/70 82/107/70
+f 67/108/71 73/101/71 68/109/71
+f 51/110/72 40/103/72 35/111/72
+f 50/112/73 71/102/73 51/110/73
+f 49/113/74 70/104/74 50/112/74
+f 78/114/75 68/106/75 82/107/75
+f 47/115/76 68/109/76 48/116/76
+f 42/65/77 35/111/77 33/66/77
+f 43/70/78 51/110/78 42/65/78
+f 44/69/79 50/112/79 43/70/79
+f 45/72/80 78/114/80 77/73/80
+f 46/117/81 48/116/81 45/75/81
+f 44/69/82 78/114/82 49/113/82
+f 49/113/83 82/107/83 69/118/83
+f 82/107/84 74/105/84 69/118/84
+f 83/100/85 54/92/85 74/105/85
+f 79/93/86 59/119/86 54/92/86
+f 80/86/87 64/82/87 59/119/87
+f 64/120/88 77/73/88 44/69/88
+f 35/12/89 40/62/89 25/13/89
+f 7/2/90 36/32/90 37/15/90
+f 35/12/91 26/14/91 17/19/91
+f 25/13/92 40/62/92 39/29/92
+f 38/30/93 16/23/93 12/10/93
+f 8/5/94 41/63/94 36/32/94
+f 38/30/95 33/20/95 17/19/95
+f 26/34/31 25/38/31 13/37/31
+f 22/40/33 32/52/33 31/41/33
+f 6/43/34 11/47/34 28/44/34
+f 15/46/34 29/50/34 28/44/34
+f 21/42/35 31/41/35 30/48/35
+f 20/49/36 30/48/36 29/50/36
+f 39/29/96 41/63/96 8/5/96
+f 38/64/47 66/68/47 42/65/47
+f 65/67/48 43/70/48 42/65/48
+f 65/67/49 64/120/49 44/69/49
+f 81/71/50 63/121/50 45/72/50
+f 62/74/51 46/117/51 45/75/51
+f 37/77/52 61/81/52 66/78/52
+f 60/80/53 65/83/53 66/78/53
+f 60/80/54 59/119/54 64/82/54
+f 58/84/55 63/122/55 81/85/55
+f 57/87/56 62/74/56 63/76/56
+f 56/89/57 61/81/57 37/77/57
+f 55/91/58 60/80/58 61/81/58
+f 54/92/59 59/119/59 60/80/59
+f 79/93/60 53/123/60 58/84/60
+f 52/94/61 57/87/61 58/88/61
+f 76/96/62 56/89/62 36/90/62
+f 75/98/63 55/91/63 56/89/63
+f 75/98/64 74/105/64 54/92/64
+f 73/99/65 53/123/65 79/93/65
+f 73/101/66 72/124/66 52/94/66
+f 71/102/67 76/96/67 41/97/67
+f 70/104/68 75/98/68 76/96/68
+f 70/104/69 69/118/69 74/105/69
+f 68/106/70 73/99/70 83/100/70
+f 67/108/71 72/124/71 73/101/71
+f 51/110/72 71/102/72 40/103/72
+f 50/112/73 70/104/73 71/102/73
+f 49/113/74 69/118/74 70/104/74
+f 78/114/75 48/125/75 68/106/75
+f 47/115/76 67/108/76 68/109/76
+f 42/65/77 51/110/77 35/111/77
+f 43/70/78 50/112/78 51/110/78
+f 44/69/79 49/113/79 50/112/79
+f 45/72/80 48/125/80 78/114/80
+f 46/117/81 47/115/81 48/116/81
+f 44/69/82 77/73/82 78/114/82
+f 49/113/83 78/114/83 82/107/83
+f 82/107/84 83/100/84 74/105/84
+f 83/100/85 79/93/85 54/92/85
+f 79/93/86 80/86/86 59/119/86
+f 80/86/87 81/85/87 64/82/87
+f 64/120/88 81/71/88 77/73/88

BIN
examples/resources/model/lowpoly-tower.png


+ 38 - 0
src/models.c

@@ -1918,3 +1918,41 @@ static Material LoadMTL(const char *fileName)
 
     return material;
 }
+
+RayHitInfo RaycastMesh( Ray ray, Mesh *mesh )
+{
+    RayHitInfo result = {0};
+
+    // If mesh doesn't have vertex data on CPU, can't test it.
+    if (!mesh->vertices) {
+        return result;
+    }
+
+    // mesh->triangleCount may not be set, vertexCount is more reliable
+    int triangleCount = mesh->vertexCount / 3;
+
+    // Test against all triangles in mesh
+    for (int i=0; i < triangleCount; i++) {
+        Vector3 a, b, c;
+        Vector3 *vertdata = (Vector3*)mesh->vertices;
+        if (mesh->indices) {
+            a = vertdata[ mesh->indices[i*3+0] ];
+            b = vertdata[ mesh->indices[i*3+1] ];
+            c = vertdata[ mesh->indices[i*3+2] ];            
+        } else {            
+            a = vertdata[i*3+0];
+            b = vertdata[i*3+1];
+            c = vertdata[i*3+2];
+        }
+
+        RayHitInfo triHitInfo = RaycastTriangle( ray, a, b, c );
+        if (triHitInfo.hit) {
+            // Save the closest hit triangle
+            if ((!result.hit)||(result.distance > triHitInfo.distance)) {
+                result = triHitInfo;
+            }
+        }
+    }
+
+    return result; 
+}

+ 18 - 0
src/raylib.h

@@ -97,6 +97,9 @@
 #define DEG2RAD (PI/180.0f)
 #define RAD2DEG (180.0f/PI)
 
+// A small number
+#define EPSILON 0.000001
+
 // raylib Config Flags
 #define FLAG_FULLSCREEN_MODE    1
 #define FLAG_RESIZABLE_WINDOW   2
@@ -491,6 +494,14 @@ typedef struct Ray {
     Vector3 direction;      // Ray direction
 } Ray;
 
+// Information returned from a raycast
+typedef struct RayHitInfo {
+    bool hit;             // Did the ray hit something?
+    float distance;       // Distance to nearest hit
+    Vector3 hitPosition;  // Position of nearest hit
+    Vector3 hitNormal;    // Surface normal of hit
+} RayHitInfo;
+
 // Wave type, defines audio wave data
 typedef struct Wave {
     unsigned int sampleCount;   // Number of samples
@@ -910,6 +921,13 @@ RLAPI bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphe
                                      Vector3 *collisionPoint);                                          // Detect collision between ray and sphere, returns collision point
 RLAPI bool CheckCollisionRayBox(Ray ray, BoundingBox box);                                              // Detect collision between ray and box
 
+//------------------------------------------------------------------------------------
+// Ray Casts
+//------------------------------------------------------------------------------------
+RLAPI RayHitInfo RaycastGroundPlane( Ray ray, float groundHeight );
+RLAPI RayHitInfo RaycastTriangle( Ray ray, Vector3 a, Vector3 b, Vector3 c );
+RLAPI RayHitInfo RaycastMesh( Ray ray, Mesh *mesh );
+
 //------------------------------------------------------------------------------------
 // Shaders System Functions (Module: rlgl)
 // NOTE: This functions are useless when using OpenGL 1.1

+ 26 - 0
src/raymath.h

@@ -130,6 +130,7 @@ RMDEF void VectorTransform(Vector3 *v, Matrix mat);           // Transforms a Ve
 RMDEF Vector3 VectorZero(void);                               // Return a Vector3 init to zero
 RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2);          // Return min value for each pair of components
 RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2);          // Return max value for each pair of components
+RMDEF Vector3 Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycentric coords for p in triangle abc
 
 //------------------------------------------------------------------------------------
 // Functions Declaration to work with Matrix
@@ -382,6 +383,31 @@ RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2)
     return result;
 }
 
+// Compute barycentric coordinates (u, v, w) for
+// point p with respect to triangle (a, b, c)
+// Assumes P is on the plane of the triangle
+RMDEF Vector3 Barycentric(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
+{
+
+    //Vector v0 = b - a, v1 = c - a, v2 = p - a;
+    Vector3 v0 = VectorSubtract( b, a );
+    Vector3 v1 = VectorSubtract( c, a );
+    Vector3 v2 = VectorSubtract( p, a );
+    float d00 = VectorDotProduct(v0, v0);
+    float d01 = VectorDotProduct(v0, v1);
+    float d11 = VectorDotProduct(v1, v1);
+    float d20 = VectorDotProduct(v2, v0);
+    float d21 = VectorDotProduct(v2, v1);
+    float denom = d00 * d11 - d01 * d01;
+    
+    Vector3 result;
+    result.y = (d11 * d20 - d01 * d21) / denom;
+    result.z = (d00 * d21 - d01 * d20) / denom;
+    result.x = 1.0f - (result.z + result.y);
+    
+    return result;
+}
+
 //----------------------------------------------------------------------------------
 // Module Functions Definition - Matrix math
 //----------------------------------------------------------------------------------

+ 82 - 1
src/shapes.c

@@ -533,4 +533,85 @@ Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
     }
 
     return retRec;
-}
+}
+
+
+RayHitInfo RaycastGroundPlane( Ray ray, float groundHeight )
+{
+    RayHitInfo result = {0};
+
+    if (fabs(ray.direction.y) > EPSILON)
+    {
+        float t = (ray.position.y - groundHeight) / -ray.direction.y;
+        if (t >= 0.0) {
+            Vector3 rayDir = ray.direction;
+            VectorScale( &rayDir, t );
+            result.hit = true;
+            result.distance = t;
+            result.hitNormal = (Vector3){ 0.0, 1.0, 0.0};
+            result.hitPosition = VectorAdd( ray.position, rayDir );
+        }
+    }
+    return result;
+}
+// Adapted from: 
+// https://en.wikipedia.org/wiki/M%C3%B6ller%E2%80%93Trumbore_intersection_algorithm
+RayHitInfo RaycastTriangle( Ray ray, Vector3 a, Vector3 b, Vector3 c )
+{
+    Vector3 e1, e2;  //Edge1, Edge2
+    Vector3 p, q, tv;
+    float det, inv_det, u, v;
+    float t;
+    RayHitInfo result = {0};
+    
+    //Find vectors for two edges sharing V1
+    e1 = VectorSubtract( b, a);
+    e2 = VectorSubtract( c, a);
+    
+    //Begin calculating determinant - also used to calculate u parameter
+    p = VectorCrossProduct( ray.direction, e2);
+    
+    //if determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle
+    det = VectorDotProduct(e1, p);
+    
+    //NOT CULLING
+    if(det > -EPSILON && det < EPSILON) return result;
+    inv_det = 1.f / det;
+    
+    //calculate distance from V1 to ray origin
+    tv = VectorSubtract( ray.position, a );
+    
+    //Calculate u parameter and test bound
+    u = VectorDotProduct(tv, p) * inv_det;
+    
+    //The intersection lies outside of the triangle
+    if(u < 0.f || u > 1.f) return result;
+    
+    //Prepare to test v parameter
+    q = VectorCrossProduct( tv, e1 );
+    
+    //Calculate V parameter and test bound
+    v = VectorDotProduct( ray.direction, q) * inv_det;
+    
+    //The intersection lies outside of the triangle
+    if(v < 0.f || (u + v)  > 1.f) return result;
+    
+    t = VectorDotProduct(e2, q) * inv_det;
+    
+    
+    if(t > EPSILON) { 
+        // ray hit, get hit point and normal
+        result.hit = true;
+        result.distance = t;
+
+        result.hit = true;
+        result.hitNormal = VectorCrossProduct( e1, e2 );
+        VectorNormalize( &result.hitNormal );
+        Vector3 rayDir = ray.direction;
+        VectorScale( &rayDir, t );        
+        result.hitPosition = VectorAdd( ray.position, rayDir );
+    }
+    
+    return result;
+}
+