diff options
Diffstat (limited to '')
-rw-r--r-- | dev/MinGfx/src/ray.h | 332 |
1 files changed, 166 insertions, 166 deletions
diff --git a/dev/MinGfx/src/ray.h b/dev/MinGfx/src/ray.h index d1b41b6..4bc3a8c 100644 --- a/dev/MinGfx/src/ray.h +++ b/dev/MinGfx/src/ray.h @@ -1,166 +1,166 @@ -/* - This file is part of the MinGfx Project. - - Copyright (c) 2017,2018 Regents of the University of Minnesota. - All Rights Reserved. - - Original Author(s) of this File: - Dan Keefe, 2018, University of Minnesota - - Author(s) of Significant Updates/Modifications to the File: - ... - */ - -#ifndef SRC_RAY_H_ -#define SRC_RAY_H_ - -#include <iostream> - -#include "aabb.h" -#include "point3.h" -#include "vector3.h" -#include "mesh.h" - - -namespace mingfx { - - -/** Stores the mathematical object of a ray that begins at an origin (a 3D - point) and points in a direction (a unit 3D vector). Rays can intersect - a variety of other computer graphics objects, such as planes, triangles, - spheres, 3D meshes, etc. These intersections can be tested with the - Intersect...() methods. The Ray can also be transformed by a Matrix4. - Example: - ~~~ - // Create a pick ray from the mouse position - void MyGraphicsApp::OnLeftMouseDown(const Point2 &mouse_in_2d_pixels) { - Point2 mouse_in_2d_ndc = PixelsToNormalizedDeviceCoords(mouse_in_2d_pixels); - Point3 mouse_in_3d = GfxMath::ScreenToNearPlane(view_matrix, proj_matrix, mouse_in_2d_ndc); - Matrix4 camera_matrix = view_matrix.Inverse(); - Point3 eye = camera_matrix.ColumnToPoint3(3); - - Ray pick_ray(eye, mouse_in_3d - eye); - - // check to see if the ray intersects a sphere - float t; - Point3 p; - if (pick_ray.IntersectSphere(Point3(0,0,0), 2.0, &t, &p)) { - std::cout << "Mouse pointing at sphere! Intersection point = " << p << std::endl; - } - } - ~~~ - */ -class Ray { -public: - - /// Defaults to a ray at the origin and pointing in the -Z direction - Ray(); - - /// Creates a ray from a 3D origin and direction - Ray(const Point3 &origin, const Vector3 &direction); - - /// Ray destructor - virtual ~Ray(); - - /// Check for "equality", taking floating point imprecision into account - bool operator==(const Ray& other) const; - - /// Check for "inequality", taking floating point imprecision into account - bool operator!=(const Ray& other) const; - - /// Returns the length of the direction vector - float Length() const; - - /** Checks to see if the ray intersects a plane defined by a point and a normal. - If there was an intersection, true is returned, iTime is set to the intersection - time, and iPoint is set to the intersection point. The plane is considered - to be 1-sided. That is the intersection will only occur if the ray hits the - plane from its front side as determined by the plane's normal. - */ - bool IntersectPlane(const Point3 &planePt, const Vector3 &planeNormal, - float *iTime, Point3 *iPoint) const; - - /** Checks to see if the ray intersects a triangle defined by the vertices v1, v2, and v3. - The vertices must be provided in counter-clockwise order so that the normal of the - triangle can be determined via the right-hand rule. The intersection will only happen - if the ray hits the front side of the triangle. If there was an intersection, - true is returned, iTime is set to the intersection time, and iPoint is set to the intersection point. - */ - bool IntersectTriangle(const Point3 &v1, const Point3 &v2, const Point3 &v3, - float *iTime, Point3 *iPoint) const; - - /** Checks to see if the ray intersects a quad defined by the vertices v1, v2, v3, and v4. - The vertices must be provided in counter-clockwise order so that the normal of the - triangle can be determined via the right-hand rule. The intersection will only happen - if the ray hits the front side of the triangle. If there was an intersection, - true is returned, iTime is set to the intersection time, and iPoint is set to the intersection point. - */ - bool IntersectQuad(const Point3 &v1, const Point3 &v2, const Point3 &v3, const Point3 &v4, - float *iTime, Point3 *iPoint) const; - - /** Checks to see if the ray intersects a sphere defined by a center point and a radius. - If there was an intersection, true is returned, iTime is set to the intersection time, - and iPoint is set to the intersection point. - */ - bool IntersectSphere(const Point3 ¢er, float radius, - float *iTime, Point3 *iPoint) const; - - /** Checks to see if the ray intersects a triangle mesh. This is a brute-force - check over each triangle in the mesh. If there was an intersection, true is returned, - iTime is set to the intersection time, iPoint is set to the intersection point, - and iTriangleID is set to the ID of the closest intersected triangle along the ray. - */ - bool IntersectMesh(const Mesh &mesh, float *iTime, - Point3 *iPoint, int *iTriangleID) const; - - /** Checks to see if the ray intersects a triangle mesh. This uses a BVH - (Bounding Volume Hierarchy) to accelerate the ray-triangle intersection tests. - Each mesh can optionally store a BVH. If a BVH has already been calculated - for the mesh (done with Mesh::CalculateBVH()), then this function will be - much faster than the brute-force IntersectMesh() function. If a BVH has - not already been calculated for the mesh, the first call to FastIntersectMesh() - will trigger the mesh to create a BVH (not a fast operation) but then - subsequent calls to FastIntersectMesh() will be fast. - */ - bool FastIntersectMesh(Mesh *mesh, float *iTime, - Point3 *iPoint, int *iTriangleID) const; - - /** Checks to see if the ray intersects an AABB (Axis-Aligned Bounding Box). - Typically, this is the first step of a more detailed intersection test and - we don't care about the actual point of intersection, just whether it - intersects or not. So, we don't bother calculating the iPoint. We get the - iTime for free though, so we do return that. You can calc the iPoint if - you want using: - ~~~ - float t; - if (ray.IntersectAABB(box, &t)) { - Point3 iPoint = ray.origin() + t*ray.direction(); - } - ~~~ - */ - bool IntersectAABB(const AABB &box, float *iTime) const; - - /// Returns the origin - Point3 origin() const; - - /// Returns the direction - Vector3 direction() const; - - /// Sets a new origin and direction - void set(Point3 newOrigin, Vector3 newDir); - -private: - Point3 p_; - Vector3 d_; -}; - - -// --- Stream operators --- - -std::ostream & operator<< ( std::ostream &os, const Ray &r); -std::istream & operator>> ( std::istream &is, Ray &r); - - -} // end namespace - -#endif +/*
+ This file is part of the MinGfx Project.
+
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+
+ Original Author(s) of this File:
+ Dan Keefe, 2018, University of Minnesota
+
+ Author(s) of Significant Updates/Modifications to the File:
+ ...
+ */
+
+#ifndef SRC_RAY_H_
+#define SRC_RAY_H_
+
+#include <iostream>
+
+#include "aabb.h"
+#include "point3.h"
+#include "vector3.h"
+#include "mesh.h"
+
+
+namespace mingfx {
+
+
+/** Stores the mathematical object of a ray that begins at an origin (a 3D
+ point) and points in a direction (a unit 3D vector). Rays can intersect
+ a variety of other computer graphics objects, such as planes, triangles,
+ spheres, 3D meshes, etc. These intersections can be tested with the
+ Intersect...() methods. The Ray can also be transformed by a Matrix4.
+ Example:
+ ~~~
+ // Create a pick ray from the mouse position
+ void MyGraphicsApp::OnLeftMouseDown(const Point2 &mouse_in_2d_pixels) {
+ Point2 mouse_in_2d_ndc = PixelsToNormalizedDeviceCoords(mouse_in_2d_pixels);
+ Point3 mouse_in_3d = GfxMath::ScreenToNearPlane(view_matrix, proj_matrix, mouse_in_2d_ndc);
+ Matrix4 camera_matrix = view_matrix.Inverse();
+ Point3 eye = camera_matrix.ColumnToPoint3(3);
+
+ Ray pick_ray(eye, mouse_in_3d - eye);
+
+ // check to see if the ray intersects a sphere
+ float t;
+ Point3 p;
+ if (pick_ray.IntersectSphere(Point3(0,0,0), 2.0, &t, &p)) {
+ std::cout << "Mouse pointing at sphere! Intersection point = " << p << std::endl;
+ }
+ }
+ ~~~
+ */
+class Ray {
+public:
+
+ /// Defaults to a ray at the origin and pointing in the -Z direction
+ Ray();
+
+ /// Creates a ray from a 3D origin and direction
+ Ray(const Point3 &origin, const Vector3 &direction);
+
+ /// Ray destructor
+ virtual ~Ray();
+
+ /// Check for "equality", taking floating point imprecision into account
+ bool operator==(const Ray& other) const;
+
+ /// Check for "inequality", taking floating point imprecision into account
+ bool operator!=(const Ray& other) const;
+
+ /// Returns the length of the direction vector
+ float Length() const;
+
+ /** Checks to see if the ray intersects a plane defined by a point and a normal.
+ If there was an intersection, true is returned, iTime is set to the intersection
+ time, and iPoint is set to the intersection point. The plane is considered
+ to be 1-sided. That is the intersection will only occur if the ray hits the
+ plane from its front side as determined by the plane's normal.
+ */
+ bool IntersectPlane(const Point3 &planePt, const Vector3 &planeNormal,
+ float *iTime, Point3 *iPoint) const;
+
+ /** Checks to see if the ray intersects a triangle defined by the vertices v1, v2, and v3.
+ The vertices must be provided in counter-clockwise order so that the normal of the
+ triangle can be determined via the right-hand rule. The intersection will only happen
+ if the ray hits the front side of the triangle. If there was an intersection,
+ true is returned, iTime is set to the intersection time, and iPoint is set to the intersection point.
+ */
+ bool IntersectTriangle(const Point3 &v1, const Point3 &v2, const Point3 &v3,
+ float *iTime, Point3 *iPoint) const;
+
+ /** Checks to see if the ray intersects a quad defined by the vertices v1, v2, v3, and v4.
+ The vertices must be provided in counter-clockwise order so that the normal of the
+ triangle can be determined via the right-hand rule. The intersection will only happen
+ if the ray hits the front side of the triangle. If there was an intersection,
+ true is returned, iTime is set to the intersection time, and iPoint is set to the intersection point.
+ */
+ bool IntersectQuad(const Point3 &v1, const Point3 &v2, const Point3 &v3, const Point3 &v4,
+ float *iTime, Point3 *iPoint) const;
+
+ /** Checks to see if the ray intersects a sphere defined by a center point and a radius.
+ If there was an intersection, true is returned, iTime is set to the intersection time,
+ and iPoint is set to the intersection point.
+ */
+ bool IntersectSphere(const Point3 ¢er, float radius,
+ float *iTime, Point3 *iPoint) const;
+
+ /** Checks to see if the ray intersects a triangle mesh. This is a brute-force
+ check over each triangle in the mesh. If there was an intersection, true is returned,
+ iTime is set to the intersection time, iPoint is set to the intersection point,
+ and iTriangleID is set to the ID of the closest intersected triangle along the ray.
+ */
+ bool IntersectMesh(const Mesh &mesh, float *iTime,
+ Point3 *iPoint, int *iTriangleID) const;
+
+ /** Checks to see if the ray intersects a triangle mesh. This uses a BVH
+ (Bounding Volume Hierarchy) to accelerate the ray-triangle intersection tests.
+ Each mesh can optionally store a BVH. If a BVH has already been calculated
+ for the mesh (done with Mesh::CalculateBVH()), then this function will be
+ much faster than the brute-force IntersectMesh() function. If a BVH has
+ not already been calculated for the mesh, the first call to FastIntersectMesh()
+ will trigger the mesh to create a BVH (not a fast operation) but then
+ subsequent calls to FastIntersectMesh() will be fast.
+ */
+ bool FastIntersectMesh(Mesh *mesh, float *iTime,
+ Point3 *iPoint, int *iTriangleID) const;
+
+ /** Checks to see if the ray intersects an AABB (Axis-Aligned Bounding Box).
+ Typically, this is the first step of a more detailed intersection test and
+ we don't care about the actual point of intersection, just whether it
+ intersects or not. So, we don't bother calculating the iPoint. We get the
+ iTime for free though, so we do return that. You can calc the iPoint if
+ you want using:
+ ~~~
+ float t;
+ if (ray.IntersectAABB(box, &t)) {
+ Point3 iPoint = ray.origin() + t*ray.direction();
+ }
+ ~~~
+ */
+ bool IntersectAABB(const AABB &box, float *iTime) const;
+
+ /// Returns the origin
+ Point3 origin() const;
+
+ /// Returns the direction
+ Vector3 direction() const;
+
+ /// Sets a new origin and direction
+ void set(Point3 newOrigin, Vector3 newDir);
+
+private:
+ Point3 p_;
+ Vector3 d_;
+};
+
+
+// --- Stream operators ---
+
+std::ostream & operator<< ( std::ostream &os, const Ray &r);
+std::istream & operator>> ( std::istream &is, Ray &r);
+
+
+} // end namespace
+
+#endif
|