CollisionModel_contents.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. /*
  21. ===============================================================================
  22. Trace model vs. polygonal model collision detection.
  23. ===============================================================================
  24. */
  25. #include "../idlib/precompiled.h"
  26. #pragma hdrstop
  27. #include "CollisionModel_local.h"
  28. /*
  29. ===============================================================================
  30. Contents test
  31. ===============================================================================
  32. */
  33. /*
  34. ================
  35. idCollisionModelManagerLocal::TestTrmVertsInBrush
  36. returns true if any of the trm vertices is inside the brush
  37. ================
  38. */
  39. bool idCollisionModelManagerLocal::TestTrmVertsInBrush( cm_traceWork_t *tw, cm_brush_t *b ) {
  40. int i, j, numVerts, bestPlane;
  41. float d, bestd;
  42. idVec3 *p;
  43. if ( b->checkcount == idCollisionModelManagerLocal::checkCount ) {
  44. return false;
  45. }
  46. b->checkcount = idCollisionModelManagerLocal::checkCount;
  47. if ( !(b->contents & tw->contents) ) {
  48. return false;
  49. }
  50. // if the brush bounds don't intersect the trace bounds
  51. if ( !b->bounds.IntersectsBounds( tw->bounds ) ) {
  52. return false;
  53. }
  54. if ( tw->pointTrace ) {
  55. numVerts = 1;
  56. }
  57. else {
  58. numVerts = tw->numVerts;
  59. }
  60. for ( j = 0; j < numVerts; j++ ) {
  61. p = &tw->vertices[j].p;
  62. // see if the point is inside the brush
  63. bestPlane = 0;
  64. bestd = -idMath::INFINITY;
  65. for ( i = 0; i < b->numPlanes; i++ ) {
  66. d = b->planes[i].Distance( *p );
  67. if ( d >= 0.0f ) {
  68. break;
  69. }
  70. if ( d > bestd ) {
  71. bestd = d;
  72. bestPlane = i;
  73. }
  74. }
  75. if ( i >= b->numPlanes ) {
  76. tw->trace.fraction = 0.0f;
  77. tw->trace.c.type = CONTACT_TRMVERTEX;
  78. tw->trace.c.normal = b->planes[bestPlane].Normal();
  79. tw->trace.c.dist = b->planes[bestPlane].Dist();
  80. tw->trace.c.contents = b->contents;
  81. tw->trace.c.material = b->material;
  82. tw->trace.c.point = *p;
  83. tw->trace.c.modelFeature = 0;
  84. tw->trace.c.trmFeature = j;
  85. return true;
  86. }
  87. }
  88. return false;
  89. }
  90. /*
  91. ================
  92. CM_SetTrmEdgeSidedness
  93. ================
  94. */
  95. #define CM_SetTrmEdgeSidedness( edge, bpl, epl, bitNum ) { \
  96. if ( !(edge->sideSet & (1<<bitNum)) ) { \
  97. float fl; \
  98. fl = (bpl).PermutedInnerProduct( epl ); \
  99. edge->side = (edge->side & ~(1<<bitNum)) | (FLOATSIGNBITSET(fl) << bitNum); \
  100. edge->sideSet |= (1 << bitNum); \
  101. } \
  102. }
  103. /*
  104. ================
  105. CM_SetTrmPolygonSidedness
  106. ================
  107. */
  108. #define CM_SetTrmPolygonSidedness( v, plane, bitNum ) { \
  109. if ( !((v)->sideSet & (1<<bitNum)) ) { \
  110. float fl; \
  111. fl = plane.Distance( (v)->p ); \
  112. /* cannot use float sign bit because it is undetermined when fl == 0.0f */ \
  113. if ( fl < 0.0f ) { \
  114. (v)->side |= (1 << bitNum); \
  115. } \
  116. else { \
  117. (v)->side &= ~(1 << bitNum); \
  118. } \
  119. (v)->sideSet |= (1 << bitNum); \
  120. } \
  121. }
  122. /*
  123. ================
  124. idCollisionModelManagerLocal::TestTrmInPolygon
  125. returns true if the trm intersects the polygon
  126. ================
  127. */
  128. bool idCollisionModelManagerLocal::TestTrmInPolygon( cm_traceWork_t *tw, cm_polygon_t *p ) {
  129. int i, j, k, edgeNum, flip, trmEdgeNum, bitNum, bestPlane;
  130. int sides[MAX_TRACEMODEL_VERTS];
  131. float d, bestd;
  132. cm_trmEdge_t *trmEdge;
  133. cm_edge_t *edge;
  134. cm_vertex_t *v, *v1, *v2;
  135. // if already checked this polygon
  136. if ( p->checkcount == idCollisionModelManagerLocal::checkCount ) {
  137. return false;
  138. }
  139. p->checkcount = idCollisionModelManagerLocal::checkCount;
  140. // if this polygon does not have the right contents behind it
  141. if ( !(p->contents & tw->contents) ) {
  142. return false;
  143. }
  144. // if the polygon bounds don't intersect the trace bounds
  145. if ( !p->bounds.IntersectsBounds( tw->bounds ) ) {
  146. return false;
  147. }
  148. // bounds should cross polygon plane
  149. switch( tw->bounds.PlaneSide( p->plane ) ) {
  150. case PLANESIDE_CROSS:
  151. break;
  152. case PLANESIDE_FRONT:
  153. if ( tw->model->isConvex ) {
  154. tw->quickExit = true;
  155. return true;
  156. }
  157. default:
  158. return false;
  159. }
  160. // if the trace model is convex
  161. if ( tw->isConvex ) {
  162. // test if any polygon vertices are inside the trm
  163. for ( i = 0; i < p->numEdges; i++ ) {
  164. edgeNum = p->edges[i];
  165. edge = tw->model->edges + abs(edgeNum);
  166. // if this edge is already tested
  167. if ( edge->checkcount == idCollisionModelManagerLocal::checkCount ) {
  168. continue;
  169. }
  170. for ( j = 0; j < 2; j++ ) {
  171. v = &tw->model->vertices[edge->vertexNum[j]];
  172. // if this vertex is already tested
  173. if ( v->checkcount == idCollisionModelManagerLocal::checkCount ) {
  174. continue;
  175. }
  176. bestPlane = 0;
  177. bestd = -idMath::INFINITY;
  178. for ( k = 0; k < tw->numPolys; k++ ) {
  179. d = tw->polys[k].plane.Distance( v->p );
  180. if ( d >= 0.0f ) {
  181. break;
  182. }
  183. if ( d > bestd ) {
  184. bestd = d;
  185. bestPlane = k;
  186. }
  187. }
  188. if ( k >= tw->numPolys ) {
  189. tw->trace.fraction = 0.0f;
  190. tw->trace.c.type = CONTACT_MODELVERTEX;
  191. tw->trace.c.normal = -tw->polys[bestPlane].plane.Normal();
  192. tw->trace.c.dist = -tw->polys[bestPlane].plane.Dist();
  193. tw->trace.c.contents = p->contents;
  194. tw->trace.c.material = p->material;
  195. tw->trace.c.point = v->p;
  196. tw->trace.c.modelFeature = edge->vertexNum[j];
  197. tw->trace.c.trmFeature = 0;
  198. return true;
  199. }
  200. }
  201. }
  202. }
  203. for ( i = 0; i < p->numEdges; i++ ) {
  204. edgeNum = p->edges[i];
  205. edge = tw->model->edges + abs(edgeNum);
  206. // reset sidedness cache if this is the first time we encounter this edge
  207. if ( edge->checkcount != idCollisionModelManagerLocal::checkCount ) {
  208. edge->sideSet = 0;
  209. }
  210. // pluecker coordinate for edge
  211. tw->polygonEdgePlueckerCache[i].FromLine( tw->model->vertices[edge->vertexNum[0]].p,
  212. tw->model->vertices[edge->vertexNum[1]].p );
  213. v = &tw->model->vertices[edge->vertexNum[INTSIGNBITSET(edgeNum)]];
  214. // reset sidedness cache if this is the first time we encounter this vertex
  215. if ( v->checkcount != idCollisionModelManagerLocal::checkCount ) {
  216. v->sideSet = 0;
  217. }
  218. v->checkcount = idCollisionModelManagerLocal::checkCount;
  219. }
  220. // get side of polygon for each trm vertex
  221. for ( i = 0; i < tw->numVerts; i++ ) {
  222. d = p->plane.Distance( tw->vertices[i].p );
  223. sides[i] = d < 0.0f ? -1 : 1;
  224. }
  225. // test if any trm edges go through the polygon
  226. for ( i = 1; i <= tw->numEdges; i++ ) {
  227. // if the trm edge does not cross the polygon plane
  228. if ( sides[tw->edges[i].vertexNum[0]] == sides[tw->edges[i].vertexNum[1]] ) {
  229. continue;
  230. }
  231. // check from which side to which side the trm edge goes
  232. flip = INTSIGNBITSET( sides[tw->edges[i].vertexNum[0]] );
  233. // test if trm edge goes through the polygon between the polygon edges
  234. for ( j = 0; j < p->numEdges; j++ ) {
  235. edgeNum = p->edges[j];
  236. edge = tw->model->edges + abs(edgeNum);
  237. #if 1
  238. CM_SetTrmEdgeSidedness( edge, tw->edges[i].pl, tw->polygonEdgePlueckerCache[j], i );
  239. if ( INTSIGNBITSET(edgeNum) ^ ((edge->side >> i) & 1) ^ flip ) {
  240. break;
  241. }
  242. #else
  243. d = tw->edges[i].pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[j] );
  244. if ( flip ) {
  245. d = -d;
  246. }
  247. if ( edgeNum > 0 ) {
  248. if ( d <= 0.0f ) {
  249. break;
  250. }
  251. }
  252. else {
  253. if ( d >= 0.0f ) {
  254. break;
  255. }
  256. }
  257. #endif
  258. }
  259. if ( j >= p->numEdges ) {
  260. tw->trace.fraction = 0.0f;
  261. tw->trace.c.type = CONTACT_EDGE;
  262. tw->trace.c.normal = p->plane.Normal();
  263. tw->trace.c.dist = p->plane.Dist();
  264. tw->trace.c.contents = p->contents;
  265. tw->trace.c.material = p->material;
  266. tw->trace.c.point = tw->vertices[tw->edges[i].vertexNum[ !flip ]].p;
  267. tw->trace.c.modelFeature = *reinterpret_cast<int *>(&p);
  268. tw->trace.c.trmFeature = i;
  269. return true;
  270. }
  271. }
  272. // test if any polygon edges go through the trm polygons
  273. for ( i = 0; i < p->numEdges; i++ ) {
  274. edgeNum = p->edges[i];
  275. edge = tw->model->edges + abs(edgeNum);
  276. if ( edge->checkcount == idCollisionModelManagerLocal::checkCount ) {
  277. continue;
  278. }
  279. edge->checkcount = idCollisionModelManagerLocal::checkCount;
  280. for ( j = 0; j < tw->numPolys; j++ ) {
  281. #if 1
  282. v1 = tw->model->vertices + edge->vertexNum[0];
  283. CM_SetTrmPolygonSidedness( v1, tw->polys[j].plane, j );
  284. v2 = tw->model->vertices + edge->vertexNum[1];
  285. CM_SetTrmPolygonSidedness( v2, tw->polys[j].plane, j );
  286. // if the polygon edge does not cross the trm polygon plane
  287. if ( !(((v1->side ^ v2->side) >> j) & 1) ) {
  288. continue;
  289. }
  290. flip = (v1->side >> j) & 1;
  291. #else
  292. float d1, d2;
  293. v1 = tw->model->vertices + edge->vertexNum[0];
  294. d1 = tw->polys[j].plane.Distance( v1->p );
  295. v2 = tw->model->vertices + edge->vertexNum[1];
  296. d2 = tw->polys[j].plane.Distance( v2->p );
  297. // if the polygon edge does not cross the trm polygon plane
  298. if ( (d1 >= 0.0f && d2 >= 0.0f) || (d1 <= 0.0f && d2 <= 0.0f) ) {
  299. continue;
  300. }
  301. flip = false;
  302. if ( d1 < 0.0f ) {
  303. flip = true;
  304. }
  305. #endif
  306. // test if polygon edge goes through the trm polygon between the trm polygon edges
  307. for ( k = 0; k < tw->polys[j].numEdges; k++ ) {
  308. trmEdgeNum = tw->polys[j].edges[k];
  309. trmEdge = tw->edges + abs(trmEdgeNum);
  310. #if 1
  311. bitNum = abs(trmEdgeNum);
  312. CM_SetTrmEdgeSidedness( edge, trmEdge->pl, tw->polygonEdgePlueckerCache[i], bitNum );
  313. if ( INTSIGNBITSET(trmEdgeNum) ^ ((edge->side >> bitNum) & 1) ^ flip ) {
  314. break;
  315. }
  316. #else
  317. d = trmEdge->pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[i] );
  318. if ( flip ) {
  319. d = -d;
  320. }
  321. if ( trmEdgeNum > 0 ) {
  322. if ( d <= 0.0f ) {
  323. break;
  324. }
  325. }
  326. else {
  327. if ( d >= 0.0f ) {
  328. break;
  329. }
  330. }
  331. #endif
  332. }
  333. if ( k >= tw->polys[j].numEdges ) {
  334. tw->trace.fraction = 0.0f;
  335. tw->trace.c.type = CONTACT_EDGE;
  336. tw->trace.c.normal = -tw->polys[j].plane.Normal();
  337. tw->trace.c.dist = -tw->polys[j].plane.Dist();
  338. tw->trace.c.contents = p->contents;
  339. tw->trace.c.material = p->material;
  340. tw->trace.c.point = tw->model->vertices[edge->vertexNum[ !flip ]].p;
  341. tw->trace.c.modelFeature = edgeNum;
  342. tw->trace.c.trmFeature = j;
  343. return true;
  344. }
  345. }
  346. }
  347. return false;
  348. }
  349. /*
  350. ================
  351. idCollisionModelManagerLocal::PointNode
  352. ================
  353. */
  354. cm_node_t *idCollisionModelManagerLocal::PointNode( const idVec3 &p, cm_model_t *model ) {
  355. cm_node_t *node;
  356. node = model->node;
  357. while ( node->planeType != -1 ) {
  358. if (p[node->planeType] > node->planeDist) {
  359. node = node->children[0];
  360. }
  361. else {
  362. node = node->children[1];
  363. }
  364. assert( node != NULL );
  365. }
  366. return node;
  367. }
  368. /*
  369. ================
  370. idCollisionModelManagerLocal::PointContents
  371. ================
  372. */
  373. int idCollisionModelManagerLocal::PointContents( const idVec3 p, cmHandle_t model ) {
  374. int i;
  375. float d;
  376. cm_node_t *node;
  377. cm_brushRef_t *bref;
  378. cm_brush_t *b;
  379. idPlane *plane;
  380. node = idCollisionModelManagerLocal::PointNode( p, idCollisionModelManagerLocal::models[model] );
  381. for ( bref = node->brushes; bref; bref = bref->next ) {
  382. b = bref->b;
  383. // test if the point is within the brush bounds
  384. for ( i = 0; i < 3; i++ ) {
  385. if ( p[i] < b->bounds[0][i] ) {
  386. break;
  387. }
  388. if ( p[i] > b->bounds[1][i] ) {
  389. break;
  390. }
  391. }
  392. if ( i < 3 ) {
  393. continue;
  394. }
  395. // test if the point is inside the brush
  396. plane = b->planes;
  397. for ( i = 0; i < b->numPlanes; i++, plane++ ) {
  398. d = plane->Distance( p );
  399. if ( d >= 0 ) {
  400. break;
  401. }
  402. }
  403. if ( i >= b->numPlanes ) {
  404. return b->contents;
  405. }
  406. }
  407. return 0;
  408. }
  409. /*
  410. ==================
  411. idCollisionModelManagerLocal::TransformedPointContents
  412. ==================
  413. */
  414. int idCollisionModelManagerLocal::TransformedPointContents( const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis ) {
  415. idVec3 p_l;
  416. // subtract origin offset
  417. p_l = p - origin;
  418. if ( modelAxis.IsRotated() ) {
  419. p_l *= modelAxis;
  420. }
  421. return idCollisionModelManagerLocal::PointContents( p_l, model );
  422. }
  423. /*
  424. ==================
  425. idCollisionModelManagerLocal::ContentsTrm
  426. ==================
  427. */
  428. int idCollisionModelManagerLocal::ContentsTrm( trace_t *results, const idVec3 &start,
  429. const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
  430. cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
  431. int i;
  432. bool model_rotated, trm_rotated;
  433. idMat3 invModelAxis, tmpAxis;
  434. idVec3 dir;
  435. ALIGN16( cm_traceWork_t tw );
  436. // fast point case
  437. if ( !trm || ( trm->bounds[1][0] - trm->bounds[0][0] <= 0.0f &&
  438. trm->bounds[1][1] - trm->bounds[0][1] <= 0.0f &&
  439. trm->bounds[1][2] - trm->bounds[0][2] <= 0.0f ) ) {
  440. results->c.contents = idCollisionModelManagerLocal::TransformedPointContents( start, model, modelOrigin, modelAxis );
  441. results->fraction = ( results->c.contents == 0 );
  442. results->endpos = start;
  443. results->endAxis = trmAxis;
  444. return results->c.contents;
  445. }
  446. idCollisionModelManagerLocal::checkCount++;
  447. tw.trace.fraction = 1.0f;
  448. tw.trace.c.contents = 0;
  449. tw.trace.c.type = CONTACT_NONE;
  450. tw.contents = contentMask;
  451. tw.isConvex = true;
  452. tw.rotation = false;
  453. tw.positionTest = true;
  454. tw.pointTrace = false;
  455. tw.quickExit = false;
  456. tw.numContacts = 0;
  457. tw.model = idCollisionModelManagerLocal::models[model];
  458. tw.start = start - modelOrigin;
  459. tw.end = tw.start;
  460. model_rotated = modelAxis.IsRotated();
  461. if ( model_rotated ) {
  462. invModelAxis = modelAxis.Transpose();
  463. }
  464. // setup trm structure
  465. idCollisionModelManagerLocal::SetupTrm( &tw, trm );
  466. trm_rotated = trmAxis.IsRotated();
  467. // calculate vertex positions
  468. if ( trm_rotated ) {
  469. for ( i = 0; i < tw.numVerts; i++ ) {
  470. // rotate trm around the start position
  471. tw.vertices[i].p *= trmAxis;
  472. }
  473. }
  474. for ( i = 0; i < tw.numVerts; i++ ) {
  475. // set trm at start position
  476. tw.vertices[i].p += tw.start;
  477. }
  478. if ( model_rotated ) {
  479. for ( i = 0; i < tw.numVerts; i++ ) {
  480. // rotate trm around model instead of rotating the model
  481. tw.vertices[i].p *= invModelAxis;
  482. }
  483. }
  484. // add offset to start point
  485. if ( trm_rotated ) {
  486. dir = trm->offset * trmAxis;
  487. tw.start += dir;
  488. tw.end += dir;
  489. } else {
  490. tw.start += trm->offset;
  491. tw.end += trm->offset;
  492. }
  493. if ( model_rotated ) {
  494. // rotate trace instead of model
  495. tw.start *= invModelAxis;
  496. tw.end *= invModelAxis;
  497. }
  498. // setup trm vertices
  499. tw.size.Clear();
  500. for ( i = 0; i < tw.numVerts; i++ ) {
  501. // get axial trm size after rotations
  502. tw.size.AddPoint( tw.vertices[i].p - tw.start );
  503. }
  504. // setup trm edges
  505. for ( i = 1; i <= tw.numEdges; i++ ) {
  506. // edge start, end and pluecker coordinate
  507. tw.edges[i].start = tw.vertices[tw.edges[i].vertexNum[0]].p;
  508. tw.edges[i].end = tw.vertices[tw.edges[i].vertexNum[1]].p;
  509. tw.edges[i].pl.FromLine( tw.edges[i].start, tw.edges[i].end );
  510. }
  511. // setup trm polygons
  512. if ( trm_rotated & model_rotated ) {
  513. tmpAxis = trmAxis * invModelAxis;
  514. for ( i = 0; i < tw.numPolys; i++ ) {
  515. tw.polys[i].plane *= tmpAxis;
  516. }
  517. } else if ( trm_rotated ) {
  518. for ( i = 0; i < tw.numPolys; i++ ) {
  519. tw.polys[i].plane *= trmAxis;
  520. }
  521. } else if ( model_rotated ) {
  522. for ( i = 0; i < tw.numPolys; i++ ) {
  523. tw.polys[i].plane *= invModelAxis;
  524. }
  525. }
  526. for ( i = 0; i < tw.numPolys; i++ ) {
  527. tw.polys[i].plane.FitThroughPoint( tw.edges[abs(tw.polys[i].edges[0])].start );
  528. }
  529. // bounds for full trace, a little bit larger for epsilons
  530. for ( i = 0; i < 3; i++ ) {
  531. if ( tw.start[i] < tw.end[i] ) {
  532. tw.bounds[0][i] = tw.start[i] + tw.size[0][i] - CM_BOX_EPSILON;
  533. tw.bounds[1][i] = tw.end[i] + tw.size[1][i] + CM_BOX_EPSILON;
  534. } else {
  535. tw.bounds[0][i] = tw.end[i] + tw.size[0][i] - CM_BOX_EPSILON;
  536. tw.bounds[1][i] = tw.start[i] + tw.size[1][i] + CM_BOX_EPSILON;
  537. }
  538. if ( idMath::Fabs(tw.size[0][i]) > idMath::Fabs(tw.size[1][i]) ) {
  539. tw.extents[i] = idMath::Fabs( tw.size[0][i] ) + CM_BOX_EPSILON;
  540. } else {
  541. tw.extents[i] = idMath::Fabs( tw.size[1][i] ) + CM_BOX_EPSILON;
  542. }
  543. }
  544. // trace through the model
  545. idCollisionModelManagerLocal::TraceThroughModel( &tw );
  546. *results = tw.trace;
  547. results->fraction = ( results->c.contents == 0 );
  548. results->endpos = start;
  549. results->endAxis = trmAxis;
  550. return results->c.contents;
  551. }
  552. /*
  553. ==================
  554. idCollisionModelManagerLocal::Contents
  555. ==================
  556. */
  557. int idCollisionModelManagerLocal::Contents( const idVec3 &start,
  558. const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
  559. cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
  560. trace_t results;
  561. if ( model < 0 || model > idCollisionModelManagerLocal::maxModels || model > MAX_SUBMODELS ) {
  562. common->Printf("idCollisionModelManagerLocal::Contents: invalid model handle\n");
  563. return 0;
  564. }
  565. if ( !idCollisionModelManagerLocal::models || !idCollisionModelManagerLocal::models[model] ) {
  566. common->Printf("idCollisionModelManagerLocal::Contents: invalid model\n");
  567. return 0;
  568. }
  569. return ContentsTrm( &results, start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis );
  570. }