Tanoda
pb_HandleUtility.cs
Go to the documentation of this file.
1using UnityEngine;
2using System.Collections;
3using System.Collections.Generic;
4
5namespace GILES
6{
7
11 public class pb_HandleUtility
12 {
13
22 public static bool ClosestPointsOnTwoLines(Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2, out Vector3 closestPointLine1, out Vector3 closestPointLine2)
23 {
24 closestPointLine1 = Vector3.zero;
25 closestPointLine2 = Vector3.zero;
26
27 float a = Vector3.Dot(lineVec1, lineVec1);
28 float b = Vector3.Dot(lineVec1, lineVec2);
29 float e = Vector3.Dot(lineVec2, lineVec2);
30
31 float d = a*e - b*b;
32
33 //lines are not parallel
34 if(d != 0.0f){
35
36 Vector3 r = linePoint1 - linePoint2;
37 float c = Vector3.Dot(lineVec1, r);
38 float f = Vector3.Dot(lineVec2, r);
39
40 float s = (b*f - c*e) / d;
41 float t = (a*f - c*b) / d;
42
43 closestPointLine1 = linePoint1 + lineVec1 * s;
44 closestPointLine2 = linePoint2 + lineVec2 * t;
45
46 return true;
47 }
48 else
49 {
50 return false;
51 }
52 }
53
58 public static bool PointOnLine(Ray InLineA, Ray InLineB, out Vector3 OutPointA, out Vector3 OutPointB)
59 {
60 return ClosestPointsOnTwoLines(InLineA.origin, InLineA.direction, InLineB.origin, InLineB.direction, out OutPointA, out OutPointB);
61 }
62
66 public static bool PointOnPlane(Ray ray, Vector3 planePosition, Vector3 planeNormal, out Vector3 hit)
67 {
68 return PointOnPlane(ray, new Plane(planeNormal, planePosition), out hit);
69 }
70
74 public static bool PointOnPlane(Ray ray, Plane plane, out Vector3 hit)
75 {
76 float distance;
77
78 if(plane.Raycast(ray, out distance))
79 {
80 hit = ray.GetPoint(distance);
81 return true;
82 }
83 else
84 {
85 hit = Vector3.zero;
86 return false;
87 }
88 }
89
90 private static Vector3 Mask(Vector3 vec)
91 {
92 return new Vector3( vec.x > 0f ? 1f : -1f,
93 vec.y > 0f ? 1f : -1f,
94 vec.z > 0f ? 1f : -1f);
95 }
96
97 private static float Mask(float val)
98 {
99 return val > 0f ? 1f : -1f;
100 }
101
102 public static Vector3 DirectionMask(Transform target, Vector3 rayDirection)
103 {
104 Vector3 viewDir = -Mask(new Vector3(Vector3.Dot(rayDirection, target.right),
105 Vector3.Dot(rayDirection, target.up),
106 Vector3.Dot(rayDirection, target.forward)));
107 return viewDir;
108 }
109
113 public static float CalcMouseDeltaSignWithAxes(Camera cam, Vector3 origin, Vector3 upDir, Vector3 rightDir, Vector2 mouseDelta)
114 {
115 if( Mathf.Abs(mouseDelta.magnitude) < .0001f)
116 return 1f;
117
118 Vector2 or = cam.WorldToScreenPoint(origin);
119 Vector2 ud = cam.WorldToScreenPoint(origin + upDir);
120 Vector2 rd = cam.WorldToScreenPoint(origin + rightDir);
121
122 float mouseDotUp = Vector2.Dot(mouseDelta, ud - or);
123 float mouseDotRight = Vector2.Dot(mouseDelta, rd - or);
124
125 if( Mathf.Abs(mouseDotUp) > Mathf.Abs(mouseDotRight))
126 return Mathf.Sign(mouseDotUp);
127 else
128 return Mathf.Sign(mouseDotRight);
129 }
130
136 public static float CalcSignedMouseDelta(Vector2 lhs, Vector2 rhs)
137 {
138 float delta = Vector2.Distance(lhs, rhs);
139 float scale = 1f / Mathf.Min(Screen.width, Screen.height);
140
141 // If horizontal movement is greater than vertical movement, use the X axis for sign.
142 if( Mathf.Abs(lhs.x - rhs.x) > Mathf.Abs(lhs.y - rhs.y) )
143 return delta * scale * ( (lhs.x-rhs.x) > 0f ? 1f : -1f );
144 else
145 return delta * scale * ( (lhs.y-rhs.y) > 0f ? 1f : -1f );
146 }
147
151 public static float GetHandleSize(Vector3 position)
152 {
153 Camera cam = Camera.main;
154 if(!cam) return 1f;
155 Transform t = cam.transform;
156 float z = Vector3.Dot(position-t.position, cam.transform.forward);
157 Vector3 lhs = cam.WorldToScreenPoint(t.position + (t.forward * z));
158 Vector3 rhs = cam.WorldToScreenPoint(t.position + (t.right + t.forward * z));
159 return 1f/(lhs-rhs).magnitude;
160 }
161
165 public static Ray TransformRay(Ray ray, Transform transform)
166 {
167 Matrix4x4 m = transform.worldToLocalMatrix;
168 Ray local = new Ray(m.MultiplyPoint(ray.origin), m.MultiplyVector(ray.direction));
169
170 return local;
171 }
172
176 public static GameObject ObjectRaycast(Ray ray, IEnumerable<GameObject> objects, bool ignoreSelection = false)
177 {
178 Renderer renderer;
179 float distance = Mathf.Infinity;
180 float best = Mathf.Infinity;
181 GameObject obj = null;
182 Bounds bounds = new Bounds(Vector3.zero, Vector3.one * 0.02f);
183
184 pb_RaycastHit hit;
185
186 foreach(GameObject go in objects)
187 {
188 if(ignoreSelection && go == pb_Selection.activeGameObject) continue;
189
190 Ray localRay = TransformRay(ray, go.transform);
191
192 renderer = go.GetComponent<Renderer>();
193
194 if( renderer != null )
195 {
196 Debug.DrawRay(ray.origin, ray.direction, Color.magenta, 5);
197 if( renderer.bounds.IntersectRay(ray, out distance) )
198 {
199 MeshFilter mf = go.GetComponent<MeshFilter>();
200
201 if( mf != null && mf.sharedMesh != null && MeshRaycast(mf.sharedMesh, localRay, out hit))
202 {
203 if(hit.distance < best)
204 {
205 best = hit.distance;
206 obj = go;
207 }
208 }
209 }
210 }
211 else
212 {
213 bounds.center = go.transform.position;
214
215 if(bounds.IntersectRay(ray, out distance))
216 {
217 if( distance < best )
218 {
219 best = distance;
220 obj = go;
221 }
222 }
223 }
224 }
225
226 return obj;
227 }
228
232 public static GameObject ObjectRaycast(Ray ray, IEnumerable<GameObject> objects, float maxdist, bool ignoreMeshFilter = false)
233 {
234 Renderer renderer;
235 float distance = Mathf.Infinity;
236 float best = maxdist;
237 GameObject obj = null;
238 Bounds bounds = new Bounds(Vector3.zero, Vector3.one * 0.02f);
239
240 pb_RaycastHit hit;
241
242 foreach (GameObject go in objects)
243 {
244 Ray localRay = TransformRay(ray, go.transform);
245
246 renderer = go.GetComponent<Renderer>();
247
248 if (renderer != null)
249 {
250 //Debug.DrawRay(ray.origin, ray.direction, Color.magenta, 5);
251 Debug.DrawLine(ray.origin, ray.GetPoint(maxdist), Color.magenta, 5);
252 if (renderer.bounds.IntersectRay(ray, out distance))
253 {
254 if (ignoreMeshFilter)
255 {
256 if (distance < best)
257 {
258 best = distance;
259 obj = go;
260 }
261 }
262 else
263 {
264 MeshFilter mf = go.GetComponent<MeshFilter>();
265
266 if (mf != null && mf.sharedMesh != null && MeshRaycast(mf.sharedMesh, localRay, out hit))
267 {
268 if (hit.distance < best)
269 {
270 best = hit.distance;
271 obj = go;
272 }
273 }
274 }
275 }
276 }
277 else
278 {
279 bounds.center = go.transform.position;
280
281 if (bounds.IntersectRay(ray, out distance))
282 {
283 if (distance < best)
284 {
285 best = distance;
286 obj = go;
287 }
288 }
289 }
290 }
291
292 return obj;
293 }
294 public static GameObject ObjectRaycast(Ray ray, IEnumerable<GameObject> objects, float maxdist, bool ignoreMeshFilter = false, List<GameObject> ignoreList = null)
295 {
296 Renderer renderer;
297 float distance = Mathf.Infinity;
298 float best = maxdist;
299 GameObject obj = null;
300 Bounds bounds = new Bounds(Vector3.zero, Vector3.one * 0.02f);
301
302 pb_RaycastHit hit;
303
304 foreach (GameObject go in objects)
305 {
306 if (ignoreList != null)
307 if (ignoreList.Contains(go)) continue;
308
309 Ray localRay = TransformRay(ray, go.transform);
310
311 renderer = go.GetComponent<Renderer>();
312
313 if (renderer != null)
314 {
315 //Debug.DrawRay(ray.origin, ray.direction, Color.magenta, 5);
316 Debug.DrawLine(ray.origin, ray.GetPoint(maxdist), Color.magenta, 5);
317 if (renderer.bounds.IntersectRay(ray, out distance))
318 {
319 if (ignoreMeshFilter)
320 {
321 if (distance < best)
322 {
323 best = distance;
324 obj = go;
325 }
326 }
327 else
328 {
329 MeshFilter mf = go.GetComponent<MeshFilter>();
330
331 if (mf != null && mf.sharedMesh != null && MeshRaycast(mf.sharedMesh, localRay, out hit))
332 {
333 if (hit.distance < best)
334 {
335 best = hit.distance;
336 obj = go;
337 }
338 }
339 }
340 }
341 }
342 else
343 {
344 bounds.center = go.transform.position;
345
346 if (bounds.IntersectRay(ray, out distance))
347 {
348 if (distance < best)
349 {
350 best = distance;
351 obj = go;
352 }
353 }
354 }
355 }
356
357 return obj;
358 }
359
363 public static GameObject ObjectRaycast(Ray ray, IEnumerable<GameObject> objects, out pb_RaycastHit besthit)
364 {
365 Renderer renderer;
366 float distance = Mathf.Infinity;
367 float best = Mathf.Infinity;
368 GameObject obj = null;
369 Bounds bounds = new Bounds(Vector3.zero, Vector3.one * 0.02f);
370 pb_RaycastHit hit;
371
372 besthit = null;
373
374 foreach(GameObject go in objects)
375 {
376 Ray localRay = TransformRay(ray, go.transform);
377
378 renderer = go.GetComponent<Renderer>();
379
380 if( renderer != null )
381 {
382 Debug.DrawRay(ray.origin, ray.direction, Color.magenta, 5);
383 if( renderer.bounds.IntersectRay(ray, out distance) )
384 {
385 MeshFilter mf = go.GetComponent<MeshFilter>();
386
387 if( mf != null && mf.sharedMesh != null && MeshRaycast(mf.sharedMesh, localRay, out hit))
388 {
389 if (hit.distance < best)
390 {
391 besthit = hit;
392 best = hit.distance;
393 obj = go;
394 }
395 }
396 }
397 }
398 else
399 {
400 bounds.center = go.transform.position;
401
402 if(bounds.IntersectRay(ray, out distance))
403 {
404 if( distance < best )
405 {
406 best = distance;
407 obj = go;
408 }
409 }
410 }
411 }
412
413 return obj;
414 }
415
416 public static bool MeshRaycast(Mesh mesh, Ray ray, out pb_RaycastHit hit)
417 {
418 Vector3[] vertices = mesh.vertices;
419 int[] triangles = mesh.triangles;
420
421 float dist = Mathf.Infinity;
422 Vector3 point = Vector3.zero;
423 Vector3 a, b, c;
424
425 for(int i = 0; i < triangles.Length; i += 3)
426 {
427 a = vertices[triangles[i+0]];
428 b = vertices[triangles[i+1]];
429 c = vertices[triangles[i+2]];
430
431 if(pb_Geometry.RayIntersectsTriangle(ray, a, b, c, Culling.Front, out dist, out point))
432 {
433 hit = new pb_RaycastHit();
434 hit.point = point;
435 hit.distance = Vector3.Distance(hit.point, ray.origin);
436 hit.normal = Vector3.Cross(b-a, c-a);
437 hit.triangle = new int[] { triangles[i], triangles[i+1], triangles[i+2] };
438 return true;
439 }
440 }
441
442 hit = null;
443 return false;
444 }
445
449 public static float DistancePoint2DToLine(Camera cam, Vector2 mousePosition, Vector3 worldPosition1, Vector3 worldPosition2)
450 {
451 Vector2 v0 = cam.WorldToScreenPoint(worldPosition1);
452 Vector2 v1 = cam.WorldToScreenPoint(worldPosition2);
453
454 return DistancePointLineSegment(mousePosition, v0, v1);
455 }
456
461 public static float DistancePointLineSegment(Vector2 p, Vector2 v, Vector2 w)
462 {
463 // lineStart = v
464 // lineEnd = w
465 // point = p
466
467 // Return minimum distance between line segment vw and point p
468 float l2 = ((v.x - w.x)*(v.x - w.x)) + ((v.y - w.y)*(v.y - w.y)); // i.e. |w-v|^2 - avoid a sqrt
469
470 if (l2 == 0.0f) return Vector2.Distance(p, v); // v == w case
471
472 // Consider the line extending the segment, parameterized as v + t (w - v).
473 // We find projection of point p onto the line.
474 // It falls where t = [(p-v) . (w-v)] / |w-v|^2
475 float t = Vector2.Dot(p - v, w - v) / l2;
476
477 if (t < 0.0)
478 return Vector2.Distance(p, v); // Beyond the 'v' end of the segment
479 else if (t > 1.0)
480 return Vector2.Distance(p, w); // Beyond the 'w' end of the segment
481
482 Vector2 projection = v + t * (w - v); // Projection falls on the segment
483
484 return Vector2.Distance(p, projection);
485 }
486
493 public static bool PointInPolygon(Vector2[] polygon, Vector2 point)
494 {
495 float xmin = Mathf.Infinity, xmax = -Mathf.Infinity, ymin = Mathf.Infinity, ymax = -Mathf.Infinity;
496
497 for(int i = 0; i < polygon.Length; i++)
498 {
499 if(polygon[i].x < xmin)
500 xmin = polygon[i].x;
501 else if(polygon[i].x > xmax)
502 xmax = polygon[i].x;
503
504 if(polygon[i].y < ymin)
505 ymin = polygon[i].y;
506 else if(polygon[i].y > ymax)
507 ymax = polygon[i].y;
508 }
509
510 if(point.x < xmin || point.x > xmax || point.y < ymin || point.y > ymax)
511 return false;
512
513 Vector2 rayStart = new Vector2(xmin - 1f, ymax + 1f);
514
515 int collisions = 0;
516
517 for(int i = 0; i < polygon.Length; i += 2)
518 {
519 if( GetLineSegmentIntersect(rayStart, point, polygon[i], polygon[i+1]) )
520 collisions++;
521 }
522
523 return collisions % 2 != 0;
524 }
525
529 public static bool GetLineSegmentIntersect(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
530 {
531 Vector2 s1, s2;
532 s1.x = p1.x - p0.x; s1.y = p1.y - p0.y;
533 s2.x = p3.x - p2.x; s2.y = p3.y - p2.y;
534
535 float s, t;
536 s = (-s1.y * (p0.x - p2.x) + s1.x * (p0.y - p2.y)) / (-s2.x * s1.y + s1.x * s2.y);
537 t = ( s2.x * (p0.y - p2.y) - s2.y * (p0.x - p2.x)) / (-s2.x * s1.y + s1.x * s2.y);
538
539 return (s >= 0 && s <= 1 && t >= 0 && t <= 1);
540 }
541 }
542}
UnityEngine.Debug Debug
Definition: TanodaServer.cs:19
UnityEngine.Color Color
Definition: TestScript.cs:32
static float CalcMouseDeltaSignWithAxes(Camera cam, Vector3 origin, Vector3 upDir, Vector3 rightDir, Vector2 mouseDelta)
static GameObject ObjectRaycast(Ray ray, IEnumerable< GameObject > objects, float maxdist, bool ignoreMeshFilter=false)
static float GetHandleSize(Vector3 position)
static float CalcSignedMouseDelta(Vector2 lhs, Vector2 rhs)
static bool PointOnPlane(Ray ray, Plane plane, out Vector3 hit)
static float DistancePointLineSegment(Vector2 p, Vector2 v, Vector2 w)
static bool GetLineSegmentIntersect(Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3)
static GameObject ObjectRaycast(Ray ray, IEnumerable< GameObject > objects, float maxdist, bool ignoreMeshFilter=false, List< GameObject > ignoreList=null)
static bool PointOnLine(Ray InLineA, Ray InLineB, out Vector3 OutPointA, out Vector3 OutPointB)
static Ray TransformRay(Ray ray, Transform transform)
static GameObject ObjectRaycast(Ray ray, IEnumerable< GameObject > objects, out pb_RaycastHit besthit)
static bool PointInPolygon(Vector2[] polygon, Vector2 point)
static bool ClosestPointsOnTwoLines(Vector3 linePoint1, Vector3 lineVec1, Vector3 linePoint2, Vector3 lineVec2, out Vector3 closestPointLine1, out Vector3 closestPointLine2)
static Vector3 DirectionMask(Transform target, Vector3 rayDirection)
static bool MeshRaycast(Mesh mesh, Ray ray, out pb_RaycastHit hit)
static float DistancePoint2DToLine(Camera cam, Vector2 mousePosition, Vector3 worldPosition1, Vector3 worldPosition2)
static bool PointOnPlane(Ray ray, Vector3 planePosition, Vector3 planeNormal, out Vector3 hit)
static GameObject ObjectRaycast(Ray ray, IEnumerable< GameObject > objects, bool ignoreSelection=false)
static GameObject activeGameObject
Definition: pb_Selection.cs:82
Culling
Definition: pb_Enum.cs:62