geometry.h
1 /*************************************************************************/
2 /* geometry.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef GEOMETRY_H
30 #define GEOMETRY_H
31 
32 #include "vector3.h"
33 #include "face3.h"
34 #include "dvector.h"
35 #include "math_2d.h"
36 #include "vector.h"
37 #include "print_string.h"
38 #include "object.h"
39 #include "triangulate.h"
44 class Geometry {
45  Geometry();
46 public:
47 
48 
49 
50 
51  static float get_closest_points_between_segments( const Vector2& p1,const Vector2& q1, const Vector2& p2,const Vector2& q2, Vector2& c1, Vector2& c2) {
52 
53  Vector2 d1 = q1 - p1; // Direction vector of segment S1
54  Vector2 d2 = q2 - p2; // Direction vector of segment S2
55  Vector2 r = p1 - p2;
56  float a = d1.dot(d1); // Squared length of segment S1, always nonnegative
57  float e = d2.dot(d2); // Squared length of segment S2, always nonnegative
58  float f = d2.dot(r);
59  float s,t;
60  // Check if either or both segments degenerate into points
61  if (a <= CMP_EPSILON && e <= CMP_EPSILON) {
62  // Both segments degenerate into points
63  c1 = p1;
64  c2 = p2;
65  return Math::sqrt((c1 - c2).dot(c1 - c2));
66  }
67  if (a <= CMP_EPSILON) {
68  // First segment degenerates into a point
69  s = 0.0f;
70  t = f / e; // s = 0 => t = (b*s + f) / e = f / e
71  t = CLAMP(t, 0.0f, 1.0f);
72  } else {
73  float c = d1.dot(r);
74  if (e <= CMP_EPSILON) {
75  // Second segment degenerates into a point
76  t = 0.0f;
77  s = CLAMP(-c / a, 0.0f, 1.0f); // t = 0 => s = (b*t - c) / a = -c / a
78  } else {
79  // The general nondegenerate case starts here
80  float b = d1.dot(d2);
81  float denom = a*e-b*b; // Always nonnegative
82  // If segments not parallel, compute closest point on L1 to L2 and
83  // clamp to segment S1. Else pick arbitrary s (here 0)
84  if (denom != 0.0f) {
85  s = CLAMP((b*f - c*e) / denom, 0.0f, 1.0f);
86  } else
87  s = 0.0f;
88  // Compute point on L2 closest to S1(s) using
89  // t = Dot((P1 + D1*s) - P2,D2) / Dot(D2,D2) = (b*s + f) / e
90  t = (b*s + f) / e;
91 
92  //If t in [0,1] done. Else clamp t, recompute s for the new value
93  // of t using s = Dot((P2 + D2*t) - P1,D1) / Dot(D1,D1)= (t*b - c) / a
94  // and clamp s to [0, 1]
95  if (t < 0.0f) {
96  t = 0.0f;
97  s = CLAMP(-c / a, 0.0f, 1.0f);
98  } else if (t > 1.0f) {
99  t = 1.0f;
100  s = CLAMP((b - c) / a, 0.0f, 1.0f);
101  }
102  }
103  }
104  c1 = p1 + d1 * s;
105  c2 = p2 + d2 * t;
106  return Math::sqrt((c1 - c2).dot(c1 - c2));
107  }
108 
109 
110  static void get_closest_points_between_segments(const Vector3& p1,const Vector3& p2,const Vector3& q1,const Vector3& q2,Vector3& c1, Vector3& c2)
111  {
112  //do the function 'd' as defined by pb. I think is is dot product of some sort
113 #define d_of(m,n,o,p) ( (m.x - n.x) * (o.x - p.x) + (m.y - n.y) * (o.y - p.y) + (m.z - n.z) * (o.z - p.z) )
114 
115  //caluclate the parpametric position on the 2 curves, mua and mub
116  float mua = ( d_of(p1,q1,q2,q1) * d_of(q2,q1,p2,p1) - d_of(p1,q1,p2,p1) * d_of(q2,q1,q2,q1) ) / ( d_of(p2,p1,p2,p1) * d_of(q2,q1,q2,q1) - d_of(q2,q1,p2,p1) * d_of(q2,q1,p2,p1) );
117  float mub = ( d_of(p1,q1,q2,q1) + mua * d_of(q2,q1,p2,p1) ) / d_of(q2,q1,q2,q1);
118 
119  //clip the value between [0..1] constraining the solution to lie on the original curves
120  if (mua < 0) mua = 0;
121  if (mub < 0) mub = 0;
122  if (mua > 1) mua = 1;
123  if (mub > 1) mub = 1;
124  c1 = p1.linear_interpolate(p2,mua);
125  c2 = q1.linear_interpolate(q2,mub);
126  }
127 
128  static float get_closest_distance_between_segments( const Vector3& p_from_a,const Vector3& p_to_a, const Vector3& p_from_b,const Vector3& p_to_b) {
129  Vector3 u = p_to_a - p_from_a;
130  Vector3 v = p_to_b - p_from_b;
131  Vector3 w = p_from_a - p_to_a;
132  real_t a = u.dot(u); // always >= 0
133  real_t b = u.dot(v);
134  real_t c = v.dot(v); // always >= 0
135  real_t d = u.dot(w);
136  real_t e = v.dot(w);
137  real_t D = a*c - b*b; // always >= 0
138  real_t sc, sN, sD = D; // sc = sN / sD, default sD = D >= 0
139  real_t tc, tN, tD = D; // tc = tN / tD, default tD = D >= 0
140 
141  // compute the line parameters of the two closest points
142  if (D < CMP_EPSILON) { // the lines are almost parallel
143  sN = 0.0; // force using point P0 on segment S1
144  sD = 1.0; // to prevent possible division by 0.0 later
145  tN = e;
146  tD = c;
147  }
148  else { // get the closest points on the infinite lines
149  sN = (b*e - c*d);
150  tN = (a*e - b*d);
151  if (sN < 0.0) { // sc < 0 => the s=0 edge is visible
152  sN = 0.0;
153  tN = e;
154  tD = c;
155  }
156  else if (sN > sD) { // sc > 1 => the s=1 edge is visible
157  sN = sD;
158  tN = e + b;
159  tD = c;
160  }
161  }
162 
163  if (tN < 0.0) { // tc < 0 => the t=0 edge is visible
164  tN = 0.0;
165  // recompute sc for this edge
166  if (-d < 0.0)
167  sN = 0.0;
168  else if (-d > a)
169  sN = sD;
170  else {
171  sN = -d;
172  sD = a;
173  }
174  }
175  else if (tN > tD) { // tc > 1 => the t=1 edge is visible
176  tN = tD;
177  // recompute sc for this edge
178  if ((-d + b) < 0.0)
179  sN = 0;
180  else if ((-d + b) > a)
181  sN = sD;
182  else {
183  sN = (-d + b);
184  sD = a;
185  }
186  }
187  // finally do the division to get sc and tc
188  sc = (Math::abs(sN) < CMP_EPSILON ? 0.0 : sN / sD);
189  tc = (Math::abs(tN) < CMP_EPSILON ? 0.0 : tN / tD);
190 
191  // get the difference of the two closest points
192  Vector3 dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc)
193 
194  return dP.length(); // return the closest distance
195  }
196 
197  static inline bool ray_intersects_triangle( const Vector3& p_from, const Vector3& p_dir, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2,Vector3* r_res=0) {
198  Vector3 e1=p_v1-p_v0;
199  Vector3 e2=p_v2-p_v0;
200  Vector3 h = p_dir.cross(e2);
201  real_t a =e1.dot(h);
202  if (a>-CMP_EPSILON && a < CMP_EPSILON) // parallel test
203  return false;
204 
205  real_t f=1.0/a;
206 
207  Vector3 s=p_from-p_v0;
208  real_t u = f * s.dot(h);
209 
210  if ( u< 0.0 || u > 1.0)
211  return false;
212 
213  Vector3 q=s.cross(e1);
214 
215  real_t v = f * p_dir.dot(q);
216 
217  if (v < 0.0 || u + v > 1.0)
218  return false;
219 
220  // at this stage we can compute t to find out where
221  // the intersection point is on the line
222  real_t t = f * e2.dot(q);
223 
224  if (t > 0.00001) {// ray intersection
225  if (r_res)
226  *r_res=p_from+p_dir*t;
227  return true;
228  } else // this means that there is a line intersection
229  // but not a ray intersection
230  return false;
231  }
232 
233  static inline bool segment_intersects_triangle( const Vector3& p_from, const Vector3& p_to, const Vector3& p_v0,const Vector3& p_v1,const Vector3& p_v2,Vector3* r_res=0) {
234 
235  Vector3 rel=p_to-p_from;
236  Vector3 e1=p_v1-p_v0;
237  Vector3 e2=p_v2-p_v0;
238  Vector3 h = rel.cross(e2);
239  real_t a =e1.dot(h);
240  if (a>-CMP_EPSILON && a < CMP_EPSILON) // parallel test
241  return false;
242 
243  real_t f=1.0/a;
244 
245  Vector3 s=p_from-p_v0;
246  real_t u = f * s.dot(h);
247 
248  if ( u< 0.0 || u > 1.0)
249  return false;
250 
251  Vector3 q=s.cross(e1);
252 
253  real_t v = f * rel.dot(q);
254 
255  if (v < 0.0 || u + v > 1.0)
256  return false;
257 
258  // at this stage we can compute t to find out where
259  // the intersection point is on the line
260  real_t t = f * e2.dot(q);
261 
262  if (t > CMP_EPSILON && t<=1.0) {// ray intersection
263  if (r_res)
264  *r_res=p_from+rel*t;
265  return true;
266  } else // this means that there is a line intersection
267  // but not a ray intersection
268  return false;
269  }
270 
271  static inline bool segment_intersects_sphere( const Vector3& p_from, const Vector3& p_to, const Vector3& p_sphere_pos,real_t p_sphere_radius,Vector3* r_res=0,Vector3 *r_norm=0) {
272 
273 
274  Vector3 sphere_pos=p_sphere_pos-p_from;
275  Vector3 rel=(p_to-p_from);
276  float rel_l=rel.length();
277  if (rel_l<CMP_EPSILON)
278  return false; // both points are the same
279  Vector3 normal=rel/rel_l;
280 
281  float sphere_d=normal.dot(sphere_pos);
282 
283  //Vector3 ray_closest=normal*sphere_d;
284 
285  float ray_distance=sphere_pos.distance_to(normal*sphere_d);
286 
287  if (ray_distance>=p_sphere_radius)
288  return false;
289 
290  float inters_d2=p_sphere_radius*p_sphere_radius - ray_distance*ray_distance;
291  float inters_d=sphere_d;
292 
293  if (inters_d2>=CMP_EPSILON)
294  inters_d-=Math::sqrt(inters_d2);
295 
296  // check in segment
297  if (inters_d<0 || inters_d>rel_l)
298  return false;
299 
300  Vector3 result=p_from+normal*inters_d;;
301 
302  if (r_res)
303  *r_res=result;
304  if (r_norm)
305  *r_norm=(result-p_sphere_pos).normalized();
306 
307  return true;
308  }
309 
310  static inline bool segment_intersects_cylinder( const Vector3& p_from, const Vector3& p_to, float p_height,float p_radius,Vector3* r_res=0,Vector3 *r_norm=0) {
311 
312  Vector3 rel=(p_to-p_from);
313  float rel_l=rel.length();
314  if (rel_l<CMP_EPSILON)
315  return false; // both points are the same
316 
317  // first check if they are parallel
318  Vector3 normal=(rel/rel_l);
319  Vector3 crs = normal.cross(Vector3(0,0,1));
320  float crs_l=crs.length();
321 
322  Vector3 z_dir;
323 
324  if(crs_l<CMP_EPSILON) {
325  //blahblah parallel
326  z_dir=Vector3(1,0,0); //any x/y vector ok
327  } else {
328  z_dir=crs/crs_l;
329  }
330 
331  float dist=z_dir.dot(p_from);
332 
333  if (dist>=p_radius)
334  return false; // too far away
335 
336  // convert to 2D
337  float w2=p_radius*p_radius-dist*dist;
338  if (w2<CMP_EPSILON)
339  return false; //avoid numerical error
340  Size2 size(Math::sqrt(w2),p_height*0.5);
341 
342  Vector3 x_dir=z_dir.cross(Vector3(0,0,1)).normalized();
343 
344  Vector2 from2D(x_dir.dot(p_from),p_from.z);
345  Vector2 to2D(x_dir.dot(p_to),p_to.z);
346 
347  float min=0,max=1;
348 
349  int axis=-1;
350 
351  for(int i=0;i<2;i++) {
352 
353  real_t seg_from=from2D[i];
354  real_t seg_to=to2D[i];
355  real_t box_begin=-size[i];
356  real_t box_end=size[i];
357  real_t cmin,cmax;
358 
359 
360  if (seg_from < seg_to) {
361 
362  if (seg_from > box_end || seg_to < box_begin)
363  return false;
364  real_t length=seg_to-seg_from;
365  cmin = (seg_from < box_begin)?((box_begin - seg_from)/length):0;
366  cmax = (seg_to > box_end)?((box_end - seg_from)/length):1;
367 
368  } else {
369 
370  if (seg_to > box_end || seg_from < box_begin)
371  return false;
372  real_t length=seg_to-seg_from;
373  cmin = (seg_from > box_end)?(box_end - seg_from)/length:0;
374  cmax = (seg_to < box_begin)?(box_begin - seg_from)/length:1;
375  }
376 
377  if (cmin > min) {
378  min = cmin;
379  axis=i;
380  }
381  if (cmax < max)
382  max = cmax;
383  if (max < min)
384  return false;
385  }
386 
387 
388  // convert to 3D again
389  Vector3 result = p_from + (rel*min);
390  Vector3 res_normal = result;
391 
392  if (axis==0) {
393  res_normal.z=0;
394  } else {
395  res_normal.x=0;
396  res_normal.y=0;
397  }
398 
399 
400  res_normal.normalize();
401 
402  if (r_res)
403  *r_res=result;
404  if (r_norm)
405  *r_norm=res_normal;
406 
407  return true;
408  }
409 
410 
411  static bool segment_intersects_convex(const Vector3& p_from, const Vector3& p_to,const Plane* p_planes, int p_plane_count,Vector3 *p_res, Vector3 *p_norm) {
412 
413  real_t min=-1e20,max=1e20;
414 
415  Vector3 rel=p_to-p_from;
416  real_t rel_l=rel.length();
417 
418  if (rel_l<CMP_EPSILON)
419  return false;
420 
421  Vector3 dir=rel/rel_l;
422 
423  int min_index=-1;
424 
425  for (int i=0;i<p_plane_count;i++) {
426 
427  const Plane&p=p_planes[i];
428 
429  real_t den=p.normal.dot( dir );
430 
431  //printf("den is %i\n",den);
432  if (Math::abs(den)<=CMP_EPSILON)
433  continue; // ignore parallel plane
434 
435 
436  real_t dist=-p.distance_to(p_from ) / den;
437 
438  if (den>0) {
439  //backwards facing plane
440  if (dist<max)
441  max=dist;
442  } else {
443 
444  //front facing plane
445  if (dist>min) {
446  min=dist;
447  min_index=i;
448  }
449  }
450  }
451 
452  if (max<=min || min<0 || min>rel_l || min_index==-1) // exit conditions
453  return false; // no intersection
454 
455  if (p_res)
456  *p_res=p_from+dir*min;
457  if (p_norm)
458  *p_norm=p_planes[min_index].normal;
459 
460  return true;
461  }
462 
463  static Vector3 get_closest_point_to_segment(const Vector3& p_point, const Vector3 *p_segment) {
464 
465  Vector3 p=p_point-p_segment[0];
466  Vector3 n=p_segment[1]-p_segment[0];
467  float l =n.length();
468  if (l<1e-10)
469  return p_segment[0]; // both points are the same, just give any
470  n/=l;
471 
472  float d=n.dot(p);
473 
474  if (d<=0.0)
475  return p_segment[0]; // before first point
476  else if (d>=l)
477  return p_segment[1]; // after first point
478  else
479  return p_segment[0]+n*d; // inside
480  }
481 
482  static Vector3 get_closest_point_to_segment_uncapped(const Vector3& p_point, const Vector3 *p_segment) {
483 
484  Vector3 p=p_point-p_segment[0];
485  Vector3 n=p_segment[1]-p_segment[0];
486  float l =n.length();
487  if (l<1e-10)
488  return p_segment[0]; // both points are the same, just give any
489  n/=l;
490 
491  float d=n.dot(p);
492 
493  return p_segment[0]+n*d; // inside
494  }
495 
496  static Vector2 get_closest_point_to_segment_2d(const Vector2& p_point, const Vector2 *p_segment) {
497 
498  Vector2 p=p_point-p_segment[0];
499  Vector2 n=p_segment[1]-p_segment[0];
500  float l =n.length();
501  if (l<1e-10)
502  return p_segment[0]; // both points are the same, just give any
503  n/=l;
504 
505  float d=n.dot(p);
506 
507  if (d<=0.0)
508  return p_segment[0]; // before first point
509  else if (d>=l)
510  return p_segment[1]; // after first point
511  else
512  return p_segment[0]+n*d; // inside
513  }
514 
515  static bool is_point_in_triangle(const Vector2& s, const Vector2& a, const Vector2& b, const Vector2& c)
516  {
517  int as_x = s.x-a.x;
518  int as_y = s.y-a.y;
519 
520  bool s_ab = (b.x-a.x)*as_y-(b.y-a.y)*as_x > 0;
521 
522  if(((c.x-a.x)*as_y-(c.y-a.y)*as_x > 0) == s_ab) return false;
523 
524  if(((c.x-b.x)*(s.y-b.y)-(c.y-b.y)*(s.x-b.x) > 0) != s_ab) return false;
525 
526  return true;
527  }
528  static Vector2 get_closest_point_to_segment_uncapped_2d(const Vector2& p_point, const Vector2 *p_segment) {
529 
530  Vector2 p=p_point-p_segment[0];
531  Vector2 n=p_segment[1]-p_segment[0];
532  float l =n.length();
533  if (l<1e-10)
534  return p_segment[0]; // both points are the same, just give any
535  n/=l;
536 
537  float d=n.dot(p);
538 
539  return p_segment[0]+n*d; // inside
540  }
541 
542  static bool segment_intersects_segment_2d(const Vector2& p_from_a,const Vector2& p_to_a,const Vector2& p_from_b,const Vector2& p_to_b,Vector2* r_result) {
543 
544  Vector2 B = p_to_a-p_from_a;
545  Vector2 C = p_from_b-p_from_a;
546  Vector2 D = p_to_b-p_from_a;
547 
548  real_t ABlen = B.dot(B);
549  if (ABlen<=0)
550  return false;
551  Vector2 Bn = B/ABlen;
552  C = Vector2( C.x*Bn.x + C.y*Bn.y, C.y*Bn.x - C.x*Bn.y );
553  D = Vector2( D.x*Bn.x + D.y*Bn.y, D.y*Bn.x - D.x*Bn.y );
554 
555  if ((C.y<0 && D.y<0) || (C.y>=0 && D.y>=0))
556  return false;
557 
558  float ABpos=D.x+(C.x-D.x)*D.y/(D.y-C.y);
559 
560  // Fail if segment C-D crosses line A-B outside of segment A-B.
561  if (ABpos<0 || ABpos>1.0)
562  return false;
563 
564  // (4) Apply the discovered position to line A-B in the original coordinate system.
565  if (r_result)
566  *r_result=p_from_a+B*ABpos;
567 
568  return true;
569  }
570 
571 
572  static inline bool point_in_projected_triangle(const Vector3& p_point,const Vector3& p_v1,const Vector3& p_v2,const Vector3& p_v3) {
573 
574 
575  Vector3 face_n = (p_v1-p_v3).cross(p_v1-p_v2);
576 
577  Vector3 n1 = (p_point-p_v3).cross(p_point-p_v2);
578 
579  if (face_n.dot(n1)<0)
580  return false;
581 
582  Vector3 n2 = (p_v1-p_v3).cross(p_v1-p_point);
583 
584  if (face_n.dot(n2)<0)
585  return false;
586 
587  Vector3 n3 = (p_v1-p_point).cross(p_v1-p_v2);
588 
589  if (face_n.dot(n3)<0)
590  return false;
591 
592  return true;
593 
594  }
595 
596  static inline bool triangle_sphere_intersection_test(const Vector3 *p_triangle,const Vector3& p_normal,const Vector3& p_sphere_pos, real_t p_sphere_radius,Vector3& r_triangle_contact,Vector3& r_sphere_contact) {
597 
598  float d=p_normal.dot(p_sphere_pos)-p_normal.dot(p_triangle[0]);
599 
600  if (d > p_sphere_radius || d < -p_sphere_radius) // not touching the plane of the face, return
601  return false;
602 
603  Vector3 contact=p_sphere_pos - (p_normal*d);
604 
608  if (Geometry::point_in_projected_triangle(contact,p_triangle[0],p_triangle[1],p_triangle[2])) {
609  r_triangle_contact=contact;
610  r_sphere_contact=p_sphere_pos-p_normal*p_sphere_radius;
611  //printf("solved inside triangle\n");
612  return true;
613  }
614 
617  const Vector3 verts[4]={p_triangle[0],p_triangle[1],p_triangle[2],p_triangle[0]}; // for() friendly
618 
619  for (int i=0;i<3;i++) {
620 
621  // check edge cylinder
622 
623  Vector3 n1=verts[i]-verts[i+1];
624  Vector3 n2=p_sphere_pos-verts[i+1];
625 
627 
628  // check point within cylinder radius
629  Vector3 axis =n1.cross(n2).cross(n1);
630  axis.normalize(); // ugh
631 
632  float ad=axis.dot(n2);
633 
634  if (ABS(ad)>p_sphere_radius) {
635  // no chance with this edge, too far away
636  continue;
637  }
638 
639  // check point within edge capsule cylinder
642  float sphere_at = n1.dot(n2);
643 
644  if (sphere_at>=0 && sphere_at<n1.dot(n1)) {
645 
646  r_triangle_contact=p_sphere_pos-axis*(axis.dot(n2));
647  r_sphere_contact=p_sphere_pos-axis*p_sphere_radius;
648  // point inside here
649  //printf("solved inside edge\n");
650  return true;
651  }
652 
653  float r2=p_sphere_radius*p_sphere_radius;
654 
655  if (n2.length_squared()<r2) {
656 
657  Vector3 n=(p_sphere_pos-verts[i+1]).normalized();
658 
659  //r_triangle_contact=verts[i+1]+n*p_sphere_radius;p_sphere_pos+axis*(p_sphere_radius-axis.dot(n2));
660  r_triangle_contact=verts[i+1];
661  r_sphere_contact=p_sphere_pos-n*p_sphere_radius;
662  //printf("solved inside point segment 1\n");
663  return true;
664  }
665 
666  if (n2.distance_squared_to(n1)<r2) {
667  Vector3 n=(p_sphere_pos-verts[i]).normalized();
668 
669  //r_triangle_contact=verts[i]+n*p_sphere_radius;p_sphere_pos+axis*(p_sphere_radius-axis.dot(n2));
670  r_triangle_contact=verts[i];
671  r_sphere_contact=p_sphere_pos-n*p_sphere_radius;
672  //printf("solved inside point segment 1\n");
673  return true;
674  }
675 
676  break; // It's pointless to continue at this point, so save some cpu cycles
677  }
678 
679  return false;
680  }
681 
682 
683 
684  static real_t segment_intersects_circle(const Vector2& p_from, const Vector2& p_to, const Vector2& p_circle_pos, real_t p_circle_radius) {
685 
686  Vector2 line_vec = p_to - p_from;
687  Vector2 vec_to_line = p_from - p_circle_pos;
688 
689  /* create a quadratic formula of the form ax^2 + bx + c = 0 */
690  real_t a, b, c;
691 
692  a = line_vec.dot(line_vec);
693  b = 2 * vec_to_line.dot(line_vec);
694  c = vec_to_line.dot(vec_to_line) - p_circle_radius * p_circle_radius;
695 
696  /* solve for t */
697  real_t sqrtterm = b*b - 4*a*c;
698 
699  /* if the term we intend to square root is less than 0 then the answer won't be real, so it definitely won't be t in the range 0 to 1 */
700  if(sqrtterm < 0) return -1;
701 
702  /* if we can assume that the line segment starts outside the circle (e.g. for continuous time collision detection) then the following can be skipped and we can just return the equivalent of res1 */
703  sqrtterm = Math::sqrt(sqrtterm);
704  real_t res1 = ( -b - sqrtterm ) / (2 * a);
705  //real_t res2 = ( -b + sqrtterm ) / (2 * a);
706 
707  return (res1 >= 0 && res1 <= 1) ? res1 : -1;
708 
709  }
710 
711 
712 
713  static inline Vector<Vector3> clip_polygon(const Vector<Vector3>& polygon,const Plane& p_plane) {
714 
715  enum LocationCache {
716  LOC_INSIDE=1,
717  LOC_BOUNDARY=0,
718  LOC_OUTSIDE=-1
719  };
720 
721  if (polygon.size()==0)
722  return polygon;
723 
724  int *location_cache = (int*)alloca(sizeof(int)*polygon.size());
725  int inside_count = 0;
726  int outside_count = 0;
727 
728  for (int a = 0; a < polygon.size(); a++) {
729  //float p_plane.d = (*this) * polygon[a];
730  float dist = p_plane.distance_to(polygon[a]);
731  if (dist <-CMP_POINT_IN_PLANE_EPSILON) {
732  location_cache[a] = LOC_INSIDE;
733  inside_count++;
734  } else {
735  if (dist > CMP_POINT_IN_PLANE_EPSILON) {
736  location_cache[a] = LOC_OUTSIDE;
737  outside_count++;
738  } else {
739  location_cache[a] = LOC_BOUNDARY;
740  }
741  }
742  }
743 
744  if (outside_count == 0) {
745 
746  return polygon; // no changes
747 
748  } else if (inside_count == 0) {
749 
750  return Vector<Vector3>(); //empty
751  }
752 
753 // long count = 0;
754  long previous = polygon.size() - 1;
755 
756  Vector<Vector3> clipped;
757 
758  for (int index = 0; index < polygon.size(); index++) {
759  int loc = location_cache[index];
760  if (loc == LOC_OUTSIDE) {
761  if (location_cache[previous] == LOC_INSIDE) {
762  const Vector3& v1 = polygon[previous];
763  const Vector3& v2 = polygon[index];
764 
765  Vector3 segment= v1 - v2;
766  double den=p_plane.normal.dot( segment );
767  double dist=p_plane.distance_to( v1 ) / den;
768  dist=-dist;
769  clipped.push_back( v1 + segment * dist );
770  }
771  } else {
772  const Vector3& v1 = polygon[index];
773  if ((loc == LOC_INSIDE) && (location_cache[previous] == LOC_OUTSIDE)) {
774  const Vector3& v2 = polygon[previous];
775  Vector3 segment= v1 - v2;
776  double den=p_plane.normal.dot( segment );
777  double dist=p_plane.distance_to( v1 ) / den;
778  dist=-dist;
779  clipped.push_back( v1 + segment * dist );
780  }
781 
782  clipped.push_back(v1);
783  }
784 
785  previous = index;
786  }
787 
788  return clipped;
789  }
790 
791 
792  static Vector<int> triangulate_polygon(const Vector<Vector2>& p_polygon) {
793 
794  Vector<int> triangles;
795  if (!Triangulate::triangulate(p_polygon,triangles))
796  return Vector<int>(); //fail
797  return triangles;
798  }
799 
800  static Vector< Vector<Vector2> > (*_decompose_func)(const Vector<Vector2>& p_polygon);
801  static Vector< Vector<Vector2> > decompose_polygon(const Vector<Vector2>& p_polygon) {
802 
803  if (_decompose_func)
804  return _decompose_func(p_polygon);
805 
806  return Vector< Vector<Vector2> >();
807 
808  }
809 
810 
811  static DVector< DVector< Face3 > > separate_objects( DVector< Face3 > p_array );
812 
813  static DVector< Face3 > wrap_geometry( DVector< Face3 > p_array, float *p_error=NULL );
814 
815 
816  struct MeshData {
817 
818  struct Face {
819  Plane plane;
820  Vector<int> indices;
821  };
822 
823  Vector<Face> faces;
824 
825  struct Edge {
826 
827  int a,b;
828  };
829 
830  Vector<Edge> edges;
831 
832  Vector< Vector3 > vertices;
833 
834  void optimize_vertices();
835  };
836 
837 
838 
839  _FORCE_INLINE_ static int get_uv84_normal_bit(const Vector3& p_vector) {
840 
841  int lat = Math::fast_ftoi(Math::floor(Math::acos(p_vector.dot(Vector3(0,1,0)))*4.0/Math_PI+0.5));
842 
843  if (lat==0) {
844  return 24;
845  } else if (lat==4) {
846  return 25;
847  }
848 
849  int lon = Math::fast_ftoi(Math::floor( (Math_PI+Math::atan2(p_vector.x,p_vector.z))*8.0/(Math_PI*2.0) + 0.5))%8;
850 
851  return lon+(lat-1)*8;
852  }
853 
854  _FORCE_INLINE_ static int get_uv84_normal_bit_neighbors(int p_idx) {
855 
856  if (p_idx==24) {
857  return 1|2|4|8;
858  } else if (p_idx==25) {
859  return (1<<23)|(1<<22)|(1<<21)|(1<<20);
860  } else {
861 
862  int ret = 0;
863  if ((p_idx%8) == 0)
864  ret|=(1<<(p_idx+7));
865  else
866  ret|=(1<<(p_idx-1));
867  if ((p_idx%8) == 7)
868  ret|=(1<<(p_idx-7));
869  else
870  ret|=(1<<(p_idx+1));
871 
872  int mask = ret|(1<<p_idx);
873  if (p_idx<8)
874  ret|=24;
875  else
876  ret|=mask>>8;
877 
878  if (p_idx>=16)
879  ret|=25;
880  else
881  ret|=mask<<8;
882 
883  return ret;
884  }
885 
886  }
887 
888 
889  static double vec2_cross(const Point2 &O, const Point2 &A, const Point2 &B)
890  {
891  return (double)(A.x - O.x) * (B.y - O.y) - (double)(A.y - O.y) * (B.x - O.x);
892  }
893 
894  // Returns a list of points on the convex hull in counter-clockwise order.
895  // Note: the last point in the returned list is the same as the first one.
896  static Vector<Point2> convex_hull_2d(Vector<Point2> P)
897  {
898  int n = P.size(), k = 0;
899  Vector<Point2> H;
900  H.resize(2*n);
901 
902  // Sort points lexicographically
903  P.sort();
904 
905 
906  // Build lower hull
907  for (int i = 0; i < n; ++i) {
908  while (k >= 2 && vec2_cross(H[k-2], H[k-1], P[i]) <= 0) k--;
909  H[k++] = P[i];
910  }
911 
912  // Build upper hull
913  for (int i = n-2, t = k+1; i >= 0; i--) {
914  while (k >= t && vec2_cross(H[k-2], H[k-1], P[i]) <= 0) k--;
915  H[k++] = P[i];
916  }
917 
918  H.resize(k);
919  return H;
920  }
921 
922  static MeshData build_convex_mesh(const DVector<Plane> &p_planes);
923  static DVector<Plane> build_sphere_planes(float p_radius, int p_lats, int p_lons, Vector3::Axis p_axis=Vector3::AXIS_Z);
924  static DVector<Plane> build_box_planes(const Vector3& p_extents);
925  static DVector<Plane> build_cylinder_planes(float p_radius, float p_height, int p_sides, Vector3::Axis p_axis=Vector3::AXIS_Z);
926  static DVector<Plane> build_capsule_planes(float p_radius, float p_height, int p_sides, int p_lats, Vector3::Axis p_axis=Vector3::AXIS_Z);
927 
928  static void make_atlas(const Vector<Size2i>& p_rects,Vector<Point2i>& r_result, Size2i& r_size);
929 
930 
931 };
932 
933 
934 
935 #endif
static DVector< Face3 > wrap_geometry(DVector< Face3 > p_array, float *p_error=NULL)
create a "wrap" that encloses the given geometry
Definition: geometry.cpp:583
Definition: math_2d.h:369
Definition: geometry.h:818
Definition: geometry.h:825
Definition: geometry.h:816
Definition: vector3.h:38
Definition: geometry.h:44
Definition: math_2d.h:65
Definition: plane.h:35
Definition: dvector.h:43
static bool triangle_sphere_intersection_test(const Vector3 *p_triangle, const Vector3 &p_normal, const Vector3 &p_sphere_pos, real_t p_sphere_radius, Vector3 &r_triangle_contact, Vector3 &r_sphere_contact)
Definition: geometry.h:596