Geogram Version 1.9.2
A programming library of geometric algorithms
Loading...
Searching...
No Matches
geometry.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef GEOGRAM_BASIC_GEOMETRY
41#define GEOGRAM_BASIC_GEOMETRY
42
45
51namespace GEO {
52
53 /************************************************************************/
54
60
66
72
79
86
93
94
101
108
115
116
122
128
134
135 /************************************************************************/
136
142 inline double det(const mat2& M) {
143 return det2x2(
144 M(0,0), M(0,1),
145 M(1,0), M(1,1)
146 );
147 }
148
154 inline double det(const mat3& M) {
155 return det3x3(
156 M(0,0), M(0,1), M(0,2),
157 M(1,0), M(1,1), M(1,2),
158 M(2,0), M(2,1), M(2,2)
159 );
160 }
161
167 inline double det(const mat4& M) {
168 return det4x4(
169 M(0,0), M(0,1), M(0,2), M(0,3),
170 M(1,0), M(1,1), M(1,2), M(1,3),
171 M(2,0), M(2,1), M(2,2), M(2,3),
172 M(3,0), M(3,1), M(3,2), M(3,3)
173 );
174 }
175
176 /************************************************************************/
177
181 namespace Geom {
182
189 inline vec3 barycenter(const vec3& p1, const vec3& p2) {
190 return vec3(
191 0.5 * (p1.x + p2.x),
192 0.5 * (p1.y + p2.y),
193 0.5 * (p1.z + p2.z)
194 );
195 }
196
203 inline vec2 barycenter(const vec2& p1, const vec2& p2) {
204 return vec2(
205 0.5 * (p1.x + p2.x),
206 0.5 * (p1.y + p2.y)
207 );
208 }
209
218 const vec3& p1, const vec3& p2, const vec3& p3
219 ) {
220 return vec3(
221 (p1.x + p2.x + p3.x) / 3.0,
222 (p1.y + p2.y + p3.y) / 3.0,
223 (p1.z + p2.z + p3.z) / 3.0
224 );
225 }
226
234 inline vec2 barycenter(
235 const vec2& p1, const vec2& p2, const vec2& p3
236 ) {
237 return vec2(
238 (p1.x + p2.x + p3.x) / 3.0,
239 (p1.y + p2.y + p3.y) / 3.0
240 );
241 }
242
249 inline double cos_angle(const vec3& a, const vec3& b) {
250 double lab = ::sqrt(length2(a)*length2(b));
251 double result = (lab > 1e-50) ? (dot(a, b) / lab) : 1.0;
252 // Numerical precision problem may occur, and generate
253 // normalized dot products that are outside the valid
254 // range of acos.
255 geo_clamp(result, -1.0, 1.0);
256 return result;
257 }
258
266 inline double angle(const vec3& a, const vec3& b) {
267 return ::acos(cos_angle(a, b));
268 }
269
276 inline double cos_angle(const vec2& a, const vec2& b) {
277 double lab = ::sqrt(length2(a)*length2(b));
278 double result = (lab > 1e-20) ? (dot(a, b) / lab) : 1.0;
279 // Numerical precision problem may occur, and generate
280 // normalized dot products that are outside the valid
281 // range of acos.
282 geo_clamp(result, -1.0, 1.0);
283 return result;
284 }
285
292 inline double det(const vec2& a, const vec2& b) {
293 return a.x * b.y - a.y * b.x;
294 }
295
303 inline double angle(const vec2& a, const vec2& b) {
304 return det(a, b) > 0 ?
305 ::acos(cos_angle(a, b)) :
306 -::acos(cos_angle(a, b));
307 }
308
316 const vec3& p1, const vec3& p2, const vec3& p3
317 ) {
318 return cross(p2 - p1, p3 - p1);
319 }
320
326 inline double triangle_area_3d(
327 const double* p1, const double* p2, const double* p3
328 ) {
329 double Ux = p2[0] - p1[0];
330 double Uy = p2[1] - p1[1];
331 double Uz = p2[2] - p1[2];
332
333 double Vx = p3[0] - p1[0];
334 double Vy = p3[1] - p1[1];
335 double Vz = p3[2] - p1[2];
336
337 double Nx = Uy*Vz - Uz*Vy;
338 double Ny = Uz*Vx - Ux*Vz;
339 double Nz = Ux*Vy - Uy*Vx;
340 return 0.5 * ::sqrt(Nx*Nx+Ny*Ny+Nz*Nz);
341 }
342
348 inline double triangle_area(
349 const vec3& p1, const vec3& p2, const vec3& p3
350 ) {
351 return triangle_area_3d(p1.data(), p2.data(), p3.data());
352 }
353
363 const double* p1, const double* p2, const double* p3
364 ) {
365 double a = p2[0]-p1[0];
366 double b = p3[0]-p1[0];
367 double c = p2[1]-p1[1];
368 double d = p3[1]-p1[1];
369 return 0.5*(a*d-b*c);
370 }
371
380 inline double triangle_signed_area(
381 const vec2& p1, const vec2& p2, const vec2& p3
382 ) {
383 return 0.5 * det(p2 - p1, p3 - p1);
384 }
385
393 inline double triangle_area(
394 const vec2& p1, const vec2& p2, const vec2& p3
395 ) {
396 return ::fabs(triangle_signed_area(p1, p2, p3));
397 }
398
406 inline double triangle_area_2d(
407 const double* p1, const double* p2, const double* p3
408 ) {
409 return ::fabs(triangle_signed_area_2d(p1,p2,p3));
410 }
411
421 const vec2& p1, const vec2& p2, const vec2& p3
422 );
423
429 inline bool has_nan(const vec3& v) {
430 return
431 Numeric::is_nan(v.x) ||
432 Numeric::is_nan(v.y) ||
433 Numeric::is_nan(v.z);
434 }
435
441 inline bool has_nan(const vec2& v) {
442 return
443 Numeric::is_nan(v.x) ||
444 Numeric::is_nan(v.y);
445 }
446
452 vec3 GEOGRAM_API perpendicular(const vec3& V);
453
463 inline double tetra_signed_volume(
464 const vec3& p1, const vec3& p2,
465 const vec3& p3, const vec3& p4
466 ) {
467 return dot(p2 - p1, cross(p3 - p1, p4 - p1)) / 6.0;
468 }
469
479 inline double tetra_signed_volume(
480 const double* p1, const double* p2,
481 const double* p3, const double* p4
482 ) {
483 return tetra_signed_volume(
484 *reinterpret_cast<const vec3*>(p1),
485 *reinterpret_cast<const vec3*>(p2),
486 *reinterpret_cast<const vec3*>(p3),
487 *reinterpret_cast<const vec3*>(p4)
488 );
489 }
490
500 inline double tetra_volume(
501 const vec3& p1, const vec3& p2,
502 const vec3& p3, const vec3& p4
503 ) {
504 return ::fabs(tetra_signed_volume(p1, p2, p3, p4));
505 }
506
518 const vec3& p1, const vec3& p2,
519 const vec3& p3, const vec3& p4
520 );
521
534 inline void triangle_centroid(
535 const vec3& p, const vec3& q, const vec3& r,
536 double a, double b, double c,
537 vec3& Vg, double& V
538 ) {
539 double abc = a + b + c;
540 double area = Geom::triangle_area(p, q, r);
541 V = area / 3.0 * abc;
542 double wp = a + abc;
543 double wq = b + abc;
544 double wr = c + abc;
545 double s = area / 12.0;
546 Vg.x = s * (wp * p.x + wq * q.x + wr * r.x);
547 Vg.y = s * (wp * p.y + wq * q.y + wr * r.y);
548 Vg.z = s * (wp * p.z + wq * q.z + wr * r.z);
549 }
550
563 inline double triangle_mass(
564 const vec3& p, const vec3& q, const vec3& r,
565 double a, double b, double c
566 ) {
567 return Geom::triangle_area(p, q, r) / 3.0 * (
568 sqrt(::fabs(a)) + sqrt(::fabs(b)) + sqrt(::fabs(c))
569 );
570 }
571
583 const vec3& p1,
584 const vec3& p2,
585 const vec3& p3
586 ) {
587 double s = Numeric::random_float64();
588 double t = Numeric::random_float64();
589 if(s + t > 1) {
590 s = 1.0 - s;
591 t = 1.0 - t;
592 }
593 double u = 1.0 - s - t;
594 return vec3(
595 u * p1.x + s * p2.x + t * p3.x,
596 u * p1.y + s * p2.y + t * p3.y,
597 u * p1.z + s * p2.z + t * p3.z
598 );
599 }
600 }
601
607 struct Plane {
608
615 Plane(const vec3& p1, const vec3& p2, const vec3& p3) {
616 vec3 n = cross(p2 - p1, p3 - p1);
617 a = n.x;
618 b = n.y;
619 c = n.z;
620 d = -(a * p1.x + b * p1.y + c * p1.z);
621 }
622
629 Plane(const vec3& p, const vec3& n) {
630 a = n.x;
631 b = n.y;
632 c = n.z;
633 d = -(a * p.x + b * p.y + c * p.z);
634 }
635
640 double a_in, double b_in, double c_in, double d_in
641 ) :
642 a(a_in),
643 b(b_in),
644 c(c_in),
645 d(d_in) {
646 }
647
652 }
653
657 vec3 normal() const {
658 return vec3(a, b, c);
659 }
660
661 double a, b, c, d;
662 };
663
664 /*******************************************************************/
665
669 class Box {
670 public:
671 double xyz_min[3];
672 double xyz_max[3];
673
679 bool contains(const vec3& b) const {
680 for(coord_index_t c = 0; c < 3; ++c) {
681 if(b[c] < xyz_min[c]) {
682 return false;
683 }
684 if(b[c] > xyz_max[c]) {
685 return false;
686 }
687 }
688 return true;
689 }
690 };
691
692 typedef Box Box3d;
693
701 inline bool bboxes_overlap(const Box& B1, const Box& B2) {
702 for(coord_index_t c = 0; c < 3; ++c) {
703 if(B1.xyz_max[c] < B2.xyz_min[c]) {
704 return false;
705 }
706 if(B1.xyz_min[c] > B2.xyz_max[c]) {
707 return false;
708 }
709 }
710 return true;
711 }
712
720 inline void bbox_union(Box& target, const Box& B1, const Box& B2) {
721 for(coord_index_t c = 0; c < 3; ++c) {
722 target.xyz_min[c] = std::min(B1.xyz_min[c], B2.xyz_min[c]);
723 target.xyz_max[c] = std::max(B1.xyz_max[c], B2.xyz_max[c]);
724 }
725 }
726
727 /*******************************************************************/
728
732 class Box2d {
733 public:
734 double xy_min[2];
735 double xy_max[2];
736
742 bool contains(const vec2& b) const {
743 for(coord_index_t c = 0; c < 2; ++c) {
744 if(b[c] < xy_min[c]) {
745 return false;
746 }
747 if(b[c] > xy_max[c]) {
748 return false;
749 }
750 }
751 return true;
752 }
753 };
754
755
763 inline bool bboxes_overlap(const Box2d& B1, const Box2d& B2) {
764 for(coord_index_t c = 0; c < 2; ++c) {
765 if(B1.xy_max[c] < B2.xy_min[c]) {
766 return false;
767 }
768 if(B1.xy_min[c] > B2.xy_max[c]) {
769 return false;
770 }
771 }
772 return true;
773 }
774
782 inline void bbox_union(Box2d& target, const Box2d& B1, const Box2d& B2) {
783 for(coord_index_t c = 0; c < 2; ++c) {
784 target.xy_min[c] = std::min(B1.xy_min[c], B2.xy_min[c]);
785 target.xy_max[c] = std::max(B1.xy_max[c], B2.xy_max[c]);
786 }
787 }
788
789 /*******************************************************************/
790
804 template <class FT> vecng<3,FT> transform_vector(
805 const vecng<3,FT>& v,
806 const Matrix<4,FT>& m
807 ){
808 index_t i,j ;
809 FT result[4] ;
810
811 for(i=0; i<4; i++) {
812 result[i] = 0 ;
813 }
814 for(i=0; i<4; i++) {
815 for(j=0; j<3; j++) {
816 result[i] += v[j] * m(j,i) ;
817 }
818 }
819
820 return vecng<3,FT>(
821 result[0], result[1], result[2]
822 ) ;
823 }
824
840 template <class FT> vecng<3,FT> transform_point(
841 const vecng<3,FT>& v,
842 const Matrix<4,FT>& m
843 ){
844 index_t i,j ;
845 FT result[4] ;
846
847 for(i=0; i<4; i++) {
848 result[i] = 0 ;
849 }
850 for(i=0; i<4; i++) {
851 for(j=0; j<3; j++) {
852 result[i] += v[j] * m(j,i) ;
853 }
854 result[i] += m(3,i);
855 }
856
857 return vecng<3,FT>(
858 result[0] / result[3],
859 result[1] / result[3],
860 result[2] / result[3]
861 ) ;
862 }
863
864
880 template <class FT> vecng<3,FT> transform_point(
881 const Matrix<4,FT>& m,
882 const vecng<3,FT>& v
883 ){
884 index_t i,j ;
885 FT result[4] ;
886
887 for(i=0; i<4; i++) {
888 result[i] = 0 ;
889 }
890 for(i=0; i<4; i++) {
891 for(j=0; j<3; j++) {
892 result[i] += v[j] * m(i,j) ;
893 }
894 result[i] += m(i,3);
895 }
896
897 return vecng<3,FT>(
898 result[0] / result[3],
899 result[1] / result[3],
900 result[2] / result[3]
901 ) ;
902 }
903
914 template <class FT> vecng<4,FT> transform_vector(
915 const vecng<4,FT>& v,
916 const Matrix<4,FT>& m
917 ) {
918 index_t i,j ;
919 FT res[4] = {FT(0), FT(0), FT(0), FT(0)};
920
921 for(i=0; i<4; i++) {
922 for(j=0; j<4; j++) {
923 res[i] += v[j] * m(j,i) ;
924 }
925 }
926
927 return vecng<4,FT>(res[0], res[1], res[2], res[3]) ;
928 }
929
930 /******************************************************************/
931
941 mat4 result;
942 result.load_identity();
943 result(3,0) = T.x;
944 result(3,1) = T.y;
945 result(3,2) = T.z;
946 return result;
947 }
948
957 inline mat4 create_scaling_matrix(double s) {
958 mat4 result;
959 result.load_identity();
960 result(0,0) = s;
961 result(1,1) = s;
962 result(2,2) = s;
963 return result;
964 }
965
966 /******************************************************************/
967
971 struct Ray {
977 Ray(vec3 O, vec3 D) : origin(O), direction(D) {
978 }
982 Ray() {
983 }
984 vec3 origin;
985 vec3 direction;
986 };
987
988 /******************************************************************/
989
990}
991
992#endif
Common include file, providing basic definitions. Should be included before anything else by all head...
Axis-aligned bounding box.
Definition geometry.h:732
bool contains(const vec2 &b) const
Tests whether a box contains a point.
Definition geometry.h:742
Axis-aligned bounding box.
Definition geometry.h:669
bool contains(const vec3 &b) const
Tests whether a box contains a point.
Definition geometry.h:679
A matrix type.
Definition matrix.h:66
void load_identity()
Sets the matrix to identity.
Definition matrix.h:145
Generic maths vector.
Definition vecg.h:70
T * data()
Gets modifiable vector data.
Definition vecg.h:161
Generic matrix type.
double det(const vec2 &a, const vec2 &b)
Computes the determinant of two vectors.
Definition geometry.h:292
double triangle_signed_area(const vec2 &p1, const vec2 &p2, const vec2 &p3)
Computes the area of a 2d triangle.
Definition geometry.h:380
vec3 tetra_circum_center(const vec3 &p1, const vec3 &p2, const vec3 &p3, const vec3 &p4)
Computes the center of the circumscribed sphere of 3d tetrahedron.
vec3 random_point_in_triangle(const vec3 &p1, const vec3 &p2, const vec3 &p3)
Generates a random point in a 3d triangle.
Definition geometry.h:582
double tetra_volume(const vec3 &p1, const vec3 &p2, const vec3 &p3, const vec3 &p4)
Computes the volume of a 3d tetrahedron.
Definition geometry.h:500
vec3 perpendicular(const vec3 &V)
Computes a 3d vector orthogonal to another one.
vec3 triangle_normal(const vec3 &p1, const vec3 &p2, const vec3 &p3)
Computes the normal of a 3d triangle.
Definition geometry.h:315
double triangle_mass(const vec3 &p, const vec3 &q, const vec3 &r, double a, double b, double c)
Computes the mass of a 3d triangle with weighted points.
Definition geometry.h:563
double cos_angle(const vec3 &a, const vec3 &b)
Computes the cosine of the angle between two 3d vectors.
Definition geometry.h:249
double triangle_area(const vec3 &p1, const vec3 &p2, const vec3 &p3)
Computes the area of a 3d triangle.
Definition geometry.h:348
double triangle_signed_area_2d(const double *p1, const double *p2, const double *p3)
Computes the area of a 2d triangle.
Definition geometry.h:362
void triangle_centroid(const vec3 &p, const vec3 &q, const vec3 &r, double a, double b, double c, vec3 &Vg, double &V)
Computes the centroid of a 3d triangle with weighted points.
Definition geometry.h:534
bool has_nan(const vec3 &v)
Tests whether a 3d vector has a NaN (not a number) coordinate.
Definition geometry.h:429
double triangle_area_2d(const double *p1, const double *p2, const double *p3)
Computes the area of a 2d triangle.
Definition geometry.h:406
double angle(const vec3 &a, const vec3 &b)
Computes the angle between two 3d vectors.
Definition geometry.h:266
double triangle_area_3d(const double *p1, const double *p2, const double *p3)
Computes the area of a 3d triangle.
Definition geometry.h:326
double tetra_signed_volume(const vec3 &p1, const vec3 &p2, const vec3 &p3, const vec3 &p4)
Computes the signed volume of a 3d tetrahedron.
Definition geometry.h:463
vec3 barycenter(const vec3 &p1, const vec3 &p2)
Computes the barycenter of two points in 3d.
Definition geometry.h:189
vec2 triangle_circumcenter(const vec2 &p1, const vec2 &p2, const vec2 &p3)
Computes the center of the circumscribed circle of a 2d triangle.
float64 random_float64()
Returns a 64 bits float between 0 and 1.
bool is_nan(float32 x)
Checks whether a 32 bits float is "not a number".
Global Vorpaline namespace.
Definition algorithm.h:65
Matrix< 4, Numeric::float64 > mat4
Represents a 4x4 matrix.
Definition geometry.h:133
bool bboxes_overlap(const Box &B1, const Box &B2)
Tests whether two Boxes have a non-empty intersection.
Definition geometry.h:701
vecng< 3, Numeric::float32 > vec3f
Represents points and vectors in 3d with single-precision coordinates.
Definition geometry.h:85
T dot(const vecng< 3, T > &v1, const vecng< 3, T > &v2)
Computes the dot product of 2 vectors. vecng
Definition vecg.h:916
vecng< 4, Numeric::float32 > vec4f
Represents points and vectors in 4d with single-precision coordinates.
Definition geometry.h:92
void bbox_union(Box &target, const Box &B1, const Box &B2)
Computes the smallest Box that encloses two Boxes.
Definition geometry.h:720
vecng< 3, FT > transform_vector(const vecng< 3, FT > &v, const Matrix< 4, FT > &m)
Applies a 3d transform to a 3d vector.
Definition geometry.h:804
vecng< 3, Numeric::float64 > vec3
Represents points and vectors in 3d.
Definition geometry.h:65
vecng< 3, Numeric::int32 > vec3i
Represents points and vectors in 3d with integer coordinates.
Definition geometry.h:107
T det3x3(const T &a11, const T &a12, const T &a13, const T &a21, const T &a22, const T &a23, const T &a31, const T &a32, const T &a33)
Computes a three-by-three determinant.
Definition determinant.h:69
T det4x4(const T &a11, const T &a12, const T &a13, const T &a14, const T &a21, const T &a22, const T &a23, const T &a24, const T &a31, const T &a32, const T &a33, const T &a34, const T &a41, const T &a42, const T &a43, const T &a44)
Computes a four-by-four determinant.
Definition determinant.h:85
void geo_clamp(T &x, T min, T max)
Clamps a value to a range.
Definition numeric.h:314
mat4 create_scaling_matrix(double s)
Creates a scaling matrix.
Definition geometry.h:957
vecng< 3, FT > transform_point(const vecng< 3, FT > &v, const Matrix< 4, FT > &m)
Applies a 3d transform to a 3d point.
Definition geometry.h:840
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:329
double det(const mat2 &M)
Computes the determinant of a 2x2 matrix.
Definition geometry.h:142
vecng< 4, Numeric::float64 > vec4
Represents points and vectors in 4d.
Definition geometry.h:71
mat4 create_translation_matrix(const vec3 &T)
Creates a translation matrix from a vector.
Definition geometry.h:940
vecng< 2, Numeric::int32 > vec2i
Represents points and vectors in 2d with integer coordinates.
Definition geometry.h:100
T det2x2(const T &a11, const T &a12, const T &a21, const T &a22)
Computes a two-by-two determinant.
Definition determinant.h:58
Matrix< 3, Numeric::float64 > mat3
Represents a 3x3 matrix.
Definition geometry.h:127
vecng< 2, Numeric::float32 > vec2f
Represents points and vectors in 2d with single-precision coordinates.
Definition geometry.h:78
vecng< 2, Numeric::float64 > vec2
Represents points and vectors in 2d.
Definition geometry.h:59
geo_coord_index_t coord_index_t
The type for storing coordinate indices, and iterating on the coordinates of a point.
Definition numeric.h:363
vecng< 4, Numeric::int32 > vec4i
Represents points and vectors in 4d with integer coordinates.
Definition geometry.h:114
Matrix< 2, Numeric::float64 > mat2
Represents a 2x2 matrix.
Definition geometry.h:121
A 3D Plane.
Definition geometry.h:607
Plane(const vec3 &p1, const vec3 &p2, const vec3 &p3)
Constructs the plane passing through three points.
Definition geometry.h:615
Plane(const vec3 &p, const vec3 &n)
Constructs a plane passign through a point and orthogonal to a vector.
Definition geometry.h:629
Plane(double a_in, double b_in, double c_in, double d_in)
Constructs a plane from the coefficients of its equation.
Definition geometry.h:639
Plane()
Constructs an uninitialized plane.
Definition geometry.h:651
vec3 normal() const
Gets the normal vector of the plane.
Definition geometry.h:657
A Ray, in parametric form.
Definition geometry.h:971
Ray()
Ray constructor.
Definition geometry.h:982
Ray(vec3 O, vec3 D)
Ray constructor.
Definition geometry.h:977