Created
November 27, 2015 15:20
-
-
Save blackslate/46cf06ecdbf719e5c311 to your computer and use it in GitHub Desktop.
THREE.Ray.prototype.closestPointToRay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
THREE.Ray.prototype.closestPointToRay = function (that, details) { | |
// that: THREE.Ray() | |
// details: (optional) object | |
// { pointOnThisRay: <THREE.Vector3> | |
// , pointOnThatRay: <THREE.Vector3> | |
// , midPoint: <THREE.Vector3> | |
// , distanceBetweenClosestPoints: <float> | |
// } | |
// For an explanation of the vector mathematics, see: | |
// http://morroworks.com/Content/Docs/Rays%20closest%20point.pdf | |
// @return undefined if rays are invalid or parallel | |
// or THREE.Vector3() point on this ray which is closest | |
// to that ray. | |
if (!(that instanceof THREE.Ray)) { | |
return | |
} | |
var thisDirection = this.direction | |
var thatDirection = that.direction | |
if (!thisDirection.clone().cross(thatDirection).length()) { | |
// Rays are parallel | |
return | |
} | |
if ( !thisDirection.dot(thisDirection) | |
|| !thatDirection.dot(thatDirection)) { | |
// At least one of the rays is just a point with no direction | |
return | |
} | |
var closestPoint = new THREE.Vector3() | |
var thisOrigin = this.origin | |
var thatOrigin = that.origin | |
var sameOrigin = thisOrigin.equals(thatOrigin) | |
if (sameOrigin) { | |
// Simple case | |
closestPoint.copy(thisOrigin) | |
} else { | |
var a = thisDirection.clone().normalize() | |
var b = thatDirection.clone().normalize() | |
var c = thatOrigin.clone().sub(thisOrigin) | |
var p = a.dot(b) | |
var q = a.dot(c) | |
var r = b.dot(c) | |
var s = a.dot(a) // already known to be non-zero | |
var t = b.dot(b) // already known to be non-zero | |
var divisor = (s * t - p * p) | |
if (!divisor) { | |
// The two rays are colinear. They are "closest" at all points | |
// This case should already have been excluded by the .cross() | |
// check made at the start. | |
return | |
} | |
var d = (q * t - p * r) / divisor | |
closestPoint.copy(thisOrigin).add(a.multiplyScalar(d)) | |
} | |
if ( typeof details === "object" ) { | |
details.pointOnThisRay = closestPoint | |
if (sameOrigin) { | |
// Should all points be the same object or clones? | |
details.pointOnThatRay = closestPoint | |
details.midPoint = closestPoint | |
details.distanceBetweenClosestPoints = 0 | |
} else { | |
// TODO: Add other details | |
d = (p * q - r * s) / divisor | |
var thatPoint = new THREE.Vector3().copy(thatOrigin).add(b.multiplyScalar(d)) | |
details.pointOnThatRay = thatPoint | |
details.midPoint = closestPoint.clone() | |
.add(thatPoint) | |
.divideScalar(2) | |
details.distanceBetweenClosestPoints = closestPoint.distanceTo(thatPoint) | |
} | |
} | |
return closestPoint | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would write it something like this - I haven't checked this for simple mistakes, but it should be relatively close: