Collisions.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /**
  2. * @author bartek drozdz / http://everyday3d.com/
  3. */
  4. THREE.PlaneCollider = function( point, normal ) {
  5. this.point = point;
  6. this.normal = normal;
  7. };
  8. THREE.SphereCollider = function( center, radius ) {
  9. this.center = center;
  10. this.radius = radius;
  11. this.radiusSq = radius * radius;
  12. };
  13. THREE.BoxCollider = function( min, max ) {
  14. this.min = min;
  15. this.max = max;
  16. this.dynamic = true;
  17. this.normal = new THREE.Vector3();
  18. };
  19. THREE.MeshCollider = function( vertices, faces, normals, box ) {
  20. this.vertices = vertices;
  21. this.faces = faces;
  22. this.normals = normals;
  23. this.box = box;
  24. this.numFaces = this.faces.length;
  25. this.normal = new THREE.Vector3();
  26. };
  27. THREE.CollisionSystem = function() {
  28. this.collisionNormal = new THREE.Vector3();
  29. this.colliders = [];
  30. this.hits = [];
  31. // console.log("Collision system init / 004");
  32. };
  33. THREE.Collisions = new THREE.CollisionSystem();
  34. THREE.CollisionSystem.prototype.merge = function( collisionSystem ) {
  35. this.colliders = this.colliders.concat( collisionSystem.colliders );
  36. this.hits = this.hits.concat( collisionSystem.hits );
  37. };
  38. THREE.CollisionSystem.prototype.rayCastAll = function( ray ) {
  39. ray.direction.normalize();
  40. this.hits.length = 0;
  41. var i, l, d, collider,
  42. ld = 0;
  43. for ( i = 0, l = this.colliders.length; i < l; i++ ) {
  44. collider = this.colliders[ i ];
  45. d = this.rayCast( ray, collider );
  46. if ( d < Number.MAX_VALUE ) {
  47. collider.distance = d;
  48. if ( d > ld )
  49. this.hits.push( collider );
  50. else
  51. this.hits.unshift( collider );
  52. ld = d;
  53. }
  54. }
  55. return this.hits;
  56. };
  57. THREE.CollisionSystem.prototype.rayCastNearest = function( ray ) {
  58. var cs = this.rayCastAll( ray );
  59. if( cs.length == 0 ) return null;
  60. var i = 0;
  61. while( cs[ i ] instanceof THREE.MeshCollider ) {
  62. var d = this.rayMesh( ray, cs[ i ] );
  63. if( d < Number.MAX_VALUE ) {
  64. cs[ i ].distance = d;
  65. break;
  66. }
  67. i++;
  68. }
  69. if ( i > cs.length ) return null;
  70. return cs[ i ];
  71. };
  72. THREE.CollisionSystem.prototype.rayCast = function( ray, collider ) {
  73. if ( collider instanceof THREE.PlaneCollider )
  74. return this.rayPlane( ray, collider );
  75. else if ( collider instanceof THREE.SphereCollider )
  76. return this.raySphere( ray, collider );
  77. else if ( collider instanceof THREE.BoxCollider )
  78. return this.rayBox( ray, collider );
  79. else if ( collider instanceof THREE.MeshCollider && collider.box )
  80. return this.rayBox( ray, collider.box );
  81. };
  82. THREE.CollisionSystem.prototype.rayMesh = function( r, me ) {
  83. var rt = this.makeRayLocal( r, me.mesh );
  84. var d = Number.MAX_VALUE;
  85. for( var i = 0; i < me.numFaces/3; i++ ) {
  86. var t = i * 3;
  87. var p0 = me.vertices[ me.faces[ t + 0 ] ];
  88. var p1 = me.vertices[ me.faces[ t + 1 ] ];
  89. var p2 = me.vertices[ me.faces[ t + 2 ] ];
  90. var nd = this.rayTriangle( rt, p0, p1, p2, d, this.collisionNormal );
  91. if( nd < d ) {
  92. d = nd;
  93. me.normal.copy( this.collisionNormal );
  94. me.normal.normalize();
  95. }
  96. }
  97. return d;
  98. };
  99. THREE.CollisionSystem.prototype.rayTriangle = function( ray, p0, p1, p2, mind, n ) {
  100. var e1 = THREE.CollisionSystem.__v1,
  101. e2 = THREE.CollisionSystem.__v2;
  102. n.set( 0, 0, 0 );
  103. // do not crash on quads, fail instead
  104. e1.sub( p1, p0 );
  105. e2.sub( p2, p1 );
  106. n.cross( e1, e2 )
  107. var dot = n.dot( ray.direction );
  108. if ( !( dot < 0 ) ) return Number.MAX_VALUE;
  109. var d = n.dot( p0 );
  110. var t = d - n.dot( ray.origin );
  111. if ( !( t <= 0 ) ) return Number.MAX_VALUE;
  112. if ( !( t >= dot * mind ) ) return Number.MAX_VALUE;
  113. t = t / dot;
  114. var p = THREE.CollisionSystem.__v3;
  115. p.copy( ray.direction );
  116. p.multiplyScalar( t );
  117. p.addSelf( ray.origin );
  118. var u0, u1, u2, v0, v1, v2;
  119. if ( Math.abs( n.x ) > Math.abs( n.y ) ) {
  120. if ( Math.abs( n.x ) > Math.abs( n.z ) ) {
  121. u0 = p.y - p0.y;
  122. u1 = p1.y - p0.y;
  123. u2 = p2.y - p0.y;
  124. v0 = p.z - p0.z;
  125. v1 = p1.z - p0.z;
  126. v2 = p2.z - p0.z;
  127. } else {
  128. u0 = p.x - p0.x;
  129. u1 = p1.x - p0.x;
  130. u2 = p2.x - p0.x;
  131. v0 = p.y - p0.y;
  132. v1 = p1.y - p0.y;
  133. v2 = p2.y - p0.y;
  134. }
  135. } else {
  136. if( Math.abs( n.y ) > Math.abs( n.z ) ) {
  137. u0 = p.x - p0.x;
  138. u1 = p1.x - p0.x;
  139. u2 = p2.x - p0.x;
  140. v0 = p.z - p0.z;
  141. v1 = p1.z - p0.z;
  142. v2 = p2.z - p0.z;
  143. } else {
  144. u0 = p.x - p0.x;
  145. u1 = p1.x - p0.x;
  146. u2 = p2.x - p0.x;
  147. v0 = p.y - p0.y;
  148. v1 = p1.y - p0.y;
  149. v2 = p2.y - p0.y;
  150. }
  151. }
  152. var temp = u1 * v2 - v1 * u2;
  153. if( !(temp != 0) ) return Number.MAX_VALUE;
  154. //console.log("temp: " + temp);
  155. temp = 1 / temp;
  156. var alpha = ( u0 * v2 - v0 * u2 ) * temp;
  157. if( !(alpha >= 0) ) return Number.MAX_VALUE;
  158. //console.log("alpha: " + alpha);
  159. var beta = ( u1 * v0 - v1 * u0 ) * temp;
  160. if( !(beta >= 0) ) return Number.MAX_VALUE;
  161. //console.log("beta: " + beta);
  162. var gamma = 1 - alpha - beta;
  163. if( !(gamma >= 0) ) return Number.MAX_VALUE;
  164. //console.log("gamma: " + gamma);
  165. return t;
  166. };
  167. THREE.CollisionSystem.prototype.makeRayLocal = function( ray, m ) {
  168. var mt = THREE.CollisionSystem.__m;
  169. THREE.Matrix4.makeInvert( m.matrixWorld, mt );
  170. var rt = THREE.CollisionSystem.__r;
  171. rt.origin.copy( ray.origin );
  172. rt.direction.copy( ray.direction );
  173. mt.multiplyVector3( rt.origin );
  174. mt.rotateAxis( rt.direction );
  175. rt.direction.normalize();
  176. //m.localRay = rt;
  177. return rt;
  178. };
  179. THREE.CollisionSystem.prototype.rayBox = function( ray, ab ) {
  180. var rt;
  181. if ( ab.dynamic && ab.mesh && ab.mesh.matrixWorld ) {
  182. rt = this.makeRayLocal( ray, ab.mesh );
  183. } else {
  184. rt = THREE.CollisionSystem.__r;
  185. rt.origin.copy( ray.origin );
  186. rt.direction.copy( ray.direction );
  187. }
  188. var xt = 0, yt = 0, zt = 0;
  189. var xn = 0, yn = 0, zn = 0;
  190. var ins = true;
  191. if( rt.origin.x < ab.min.x ) {
  192. xt = ab.min.x - rt.origin.x;
  193. //if(xt > ray.direction.x) return return Number.MAX_VALUE;
  194. xt /= rt.direction.x;
  195. ins = false;
  196. xn = -1;
  197. } else if( rt.origin.x > ab.max.x ) {
  198. xt = ab.max.x - rt.origin.x;
  199. //if(xt < ray.direction.x) return return Number.MAX_VALUE;
  200. xt /= rt.direction.x;
  201. ins = false;
  202. xn = 1;
  203. }
  204. if( rt.origin.y < ab.min.y ) {
  205. yt = ab.min.y - rt.origin.y;
  206. //if(yt > ray.direction.y) return return Number.MAX_VALUE;
  207. yt /= rt.direction.y;
  208. ins = false;
  209. yn = -1;
  210. } else if( rt.origin.y > ab.max.y ) {
  211. yt = ab.max.y - rt.origin.y;
  212. //if(yt < ray.direction.y) return return Number.MAX_VALUE;
  213. yt /= rt.direction.y;
  214. ins = false;
  215. yn = 1;
  216. }
  217. if( rt.origin.z < ab.min.z ) {
  218. zt = ab.min.z - rt.origin.z;
  219. //if(zt > ray.direction.z) return return Number.MAX_VALUE;
  220. zt /= rt.direction.z;
  221. ins = false;
  222. zn = -1;
  223. } else if( rt.origin.z > ab.max.z ) {
  224. zt = ab.max.z - rt.origin.z;
  225. //if(zt < ray.direction.z) return return Number.MAX_VALUE;
  226. zt /= rt.direction.z;
  227. ins = false;
  228. zn = 1;
  229. }
  230. if( ins ) return -1;
  231. var which = 0;
  232. var t = xt;
  233. if( yt > t ) {
  234. which = 1;
  235. t = yt;
  236. }
  237. if ( zt > t ) {
  238. which = 2;
  239. t = zt;
  240. }
  241. switch( which ) {
  242. case 0:
  243. var y = rt.origin.y + rt.direction.y * t;
  244. if ( y < ab.min.y || y > ab.max.y ) return Number.MAX_VALUE;
  245. var z = rt.origin.z + rt.direction.z * t;
  246. if ( z < ab.min.z || z > ab.max.z ) return Number.MAX_VALUE;
  247. ab.normal.set( xn, 0, 0 );
  248. break;
  249. case 1:
  250. var x = rt.origin.x + rt.direction.x * t;
  251. if ( x < ab.min.x || x > ab.max.x ) return Number.MAX_VALUE;
  252. var z = rt.origin.z + rt.direction.z * t;
  253. if ( z < ab.min.z || z > ab.max.z ) return Number.MAX_VALUE;
  254. ab.normal.set( 0, yn, 0) ;
  255. break;
  256. case 2:
  257. var x = rt.origin.x + rt.direction.x * t;
  258. if ( x < ab.min.x || x > ab.max.x ) return Number.MAX_VALUE;
  259. var y = rt.origin.y + rt.direction.y * t;
  260. if ( y < ab.min.y || y > ab.max.y ) return Number.MAX_VALUE;
  261. ab.normal.set( 0, 0, zn );
  262. break;
  263. }
  264. return t;
  265. };
  266. THREE.CollisionSystem.prototype.rayPlane = function( r, p ) {
  267. var t = r.direction.dot( p.normal );
  268. var d = p.point.dot( p.normal );
  269. var ds;
  270. if( t < 0 ) ds = ( d - r.origin.dot( p.normal ) ) / t;
  271. else return Number.MAX_VALUE;
  272. if( ds > 0 ) return ds;
  273. else return Number.MAX_VALUE;
  274. };
  275. THREE.CollisionSystem.prototype.raySphere = function( r, s ) {
  276. var e = s.center.clone().subSelf( r.origin );
  277. if ( e.lengthSq < s.radiusSq ) return -1;
  278. var a = e.dot( r.direction.clone() );
  279. if ( a <= 0 ) return Number.MAX_VALUE;
  280. var t = s.radiusSq - ( e.lengthSq() - a * a );
  281. if ( t >= 0 ) return Math.abs( a ) - Math.sqrt( t );
  282. return Number.MAX_VALUE;
  283. };
  284. THREE.CollisionSystem.__v1 = new THREE.Vector3();
  285. THREE.CollisionSystem.__v2 = new THREE.Vector3();
  286. THREE.CollisionSystem.__v3 = new THREE.Vector3();
  287. THREE.CollisionSystem.__nr = new THREE.Vector3();
  288. THREE.CollisionSystem.__m = new THREE.Matrix4();
  289. THREE.CollisionSystem.__r = new THREE.Ray();
粤ICP备19079148号