Add ray intersection tests for primitive shapes#87
Add ray intersection tests for primitive shapes#87WhyPenguins merged 23 commits intothoth-tech:t3-2024from
Conversation
…angle and improve documentation
…rove documentation
…mprove documentation
| vector_2d origin_to_edge = vector_point_to_point(origin, start_point); | ||
|
|
||
| // Cross product to determine parallelism | ||
| double cross_ray_and_edge = (heading.x * edge_vector.y) - (heading.y * edge_vector.x); |
There was a problem hiding this comment.
The code doesn't check for zero vectors in the heading parameter. This could lead to division by zero in this calculation. could add something like this:
const double ZERO_MAGNITUDE_THRESHOLD = 1e-10;
if (vector_magnitude(heading) < ZERO_MAGNITUDE_THRESHOLD)
There was a problem hiding this comment.
I added checks for a zero vector heading in the rectangle, circle, triangle and quad functions. I opted to use the DBL_EPSILON constant as it is already defined and has more meaning than an arbitrary value.
NoahJCross
left a comment
There was a problem hiding this comment.
There are some structural and safety improvements that could be made, but the core functionality is good, with the ray intersection calculations working correctly.
coresdk/src/test/test_geometry.cpp
Outdated
| close_window(w1); | ||
| } | ||
|
|
||
| void ray_shape_intersection(const line& l, const point_2d& circ_center, color& clr) |
There was a problem hiding this comment.
function name is slightly misleading as it's actually drawing visualization.
There was a problem hiding this comment.
Changed name to draw_ray_shape_intersection.
| auto q1_hit_point = point_at(0.0, 0.0); | ||
| double q1_distance = 0.0; | ||
| bool q1_intersection = false; | ||
| auto player = point_at(300.0, 300.0); |
There was a problem hiding this comment.
Something like this would be a little cleaner and more clear:
struct TestShape {
color clr;
point_2d hit_point;
double distance;
bool intersection;
};
TestShape rect_data{COLOR_BLUE, point_at(0,0), 0.0, false};
|
|
||
| // Cross product to determine parallelism | ||
| double cross_ray_and_edge = (heading.x * edge_vector.y) - (heading.y * edge_vector.x); | ||
| if (std::fabs(cross_ray_and_edge) < 1e-8) continue; // Skip edges nearly parallel to the ray |
There was a problem hiding this comment.
1e-8 could be a const, PARALLEL_THRESHOLD seems like an apropriate name.
|
I found another issue where if the heading is a not a unit vector, the functions are buggy. I altered the functions to convert the heading to a unit vector at the beginning of each function. The zero vector check is performed on the unit heading. |
That's a good catch. A non normalized vector would definitely cause issues with the hit_distance. |
There was a problem hiding this comment.
I've reviewed this PR and approve of these changes.
The ray intersection tests add important features to SplashKit while keeping high standards:
Code Quality
- Good use of doubles for accurate geometric calculations
- Proper vector normalization for accurate distance measurements
- Good handling of edge cases (zero vectors, interior points)
- Clean code that fits well with existing geometry systems
Testing
- Good test coverage in test_geometry.cpp
Documentation
- Clear methods for both detailed and simple intersection checks
- Consistent design across different shapes
- Well-documented code that explains how it works
The changes add useful geometry features while keeping types consistent and calculations stable.
Approved.
WhyPenguins
left a comment
There was a problem hiding this comment.
Looks good! 😃 Have tested and it works well, code is clean and easy to read too.
I think this can be merged as-is, but just wanted to mention that it might have been simpler/better to write a polygon_ray_intersection(const point_2d &origin, const vector_2d &heading, const vector<line> lines, point_2d &hit_point, double &hit_distance) function based on the logic in the triangle_ray_intersection, which the quad, rectangle, and triangle functions all use internally.
I think if we add further shapes then this would be a good way to reduce the duplication 😃
Description
There has been growing interest in using SplashKit to perform ray-tracing in both 2D and 3D environments. However, there is a lack of ray-based intersection functions with primitive shapes. I have added ray intersection functions for rectangles, circles, triangles, and quads.
Each shape has been given a function which can output the the intersection position and distance. I have also included an overload of each function that only returns a Boolean. By including the overload, the user is not required to pass arguments by reference which may be confusing to SIT102 students.
I collaborated with Shaun Ratcliff to complete the logic for the intersection functions.
Type of change
How Has This Been Tested?
I added a new real-time graphical test to
sktestintest_geometry.cppto demonstrate the functions. It allows the user to move a ray's origin with the arrow keys, while the heading is determined by the mouse cursor's position. All four shapes are present for testing. If an intersection occurs, the corresponding shape is highlighted and the intersection point is shown.Testing Checklist
Checklist