CollisionModel_contents.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition 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. #pragma hdrstop
  26. #include "../idlib/precompiled.h"
  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. const int mask = 1 << bitNum; \
  97. if ( ( edge->sideSet & mask ) == 0 ) { \
  98. const float fl = (bpl).PermutedInnerProduct( epl ); \
  99. edge->side = ( edge->side & ~mask ) | ( ( fl < 0.0f ) ? mask : 0 ); \
  100. edge->sideSet |= mask; \
  101. } \
  102. }
  103. /*
  104. ================
  105. CM_SetTrmPolygonSidedness
  106. ================
  107. */
  108. #define CM_SetTrmPolygonSidedness( v, plane, bitNum ) { \
  109. const int mask = 1 << bitNum; \
  110. if ( ( (v)->sideSet & mask ) == 0 ) { \
  111. const float fl = plane.Distance( (v)->p ); \
  112. (v)->side = ( (v)->side & ~mask ) | ( ( fl < 0.0f ) ? mask : 0 ); \
  113. (v)->sideSet |= mask; \
  114. } \
  115. }
  116. /*
  117. ================
  118. idCollisionModelManagerLocal::TestTrmInPolygon
  119. returns true if the trm intersects the polygon
  120. ================
  121. */
  122. bool idCollisionModelManagerLocal::TestTrmInPolygon( cm_traceWork_t *tw, cm_polygon_t *p ) {
  123. int i, j, k, edgeNum, flip, trmEdgeNum, bitNum, bestPlane;
  124. int sides[MAX_TRACEMODEL_VERTS];
  125. float d, bestd;
  126. cm_trmEdge_t *trmEdge;
  127. cm_edge_t *edge;
  128. cm_vertex_t *v, *v1, *v2;
  129. // if already checked this polygon
  130. if ( p->checkcount == idCollisionModelManagerLocal::checkCount ) {
  131. return false;
  132. }
  133. p->checkcount = idCollisionModelManagerLocal::checkCount;
  134. // if this polygon does not have the right contents behind it
  135. if ( !(p->contents & tw->contents) ) {
  136. return false;
  137. }
  138. // if the polygon bounds don't intersect the trace bounds
  139. if ( !p->bounds.IntersectsBounds( tw->bounds ) ) {
  140. return false;
  141. }
  142. // bounds should cross polygon plane
  143. switch( tw->bounds.PlaneSide( p->plane ) ) {
  144. case PLANESIDE_CROSS:
  145. break;
  146. case PLANESIDE_FRONT:
  147. if ( tw->model->isConvex ) {
  148. tw->quickExit = true;
  149. return true;
  150. }
  151. default:
  152. return false;
  153. }
  154. // if the trace model is convex
  155. if ( tw->isConvex ) {
  156. // test if any polygon vertices are inside the trm
  157. for ( i = 0; i < p->numEdges; i++ ) {
  158. edgeNum = p->edges[i];
  159. edge = tw->model->edges + abs(edgeNum);
  160. // if this edge is already tested
  161. if ( edge->checkcount == idCollisionModelManagerLocal::checkCount ) {
  162. continue;
  163. }
  164. for ( j = 0; j < 2; j++ ) {
  165. v = &tw->model->vertices[edge->vertexNum[j]];
  166. // if this vertex is already tested
  167. if ( v->checkcount == idCollisionModelManagerLocal::checkCount ) {
  168. continue;
  169. }
  170. bestPlane = 0;
  171. bestd = -idMath::INFINITY;
  172. for ( k = 0; k < tw->numPolys; k++ ) {
  173. d = tw->polys[k].plane.Distance( v->p );
  174. if ( d >= 0.0f ) {
  175. break;
  176. }
  177. if ( d > bestd ) {
  178. bestd = d;
  179. bestPlane = k;
  180. }
  181. }
  182. if ( k >= tw->numPolys ) {
  183. tw->trace.fraction = 0.0f;
  184. tw->trace.c.type = CONTACT_MODELVERTEX;
  185. tw->trace.c.normal = -tw->polys[bestPlane].plane.Normal();
  186. tw->trace.c.dist = -tw->polys[bestPlane].plane.Dist();
  187. tw->trace.c.contents = p->contents;
  188. tw->trace.c.material = p->material;
  189. tw->trace.c.point = v->p;
  190. tw->trace.c.modelFeature = edge->vertexNum[j];
  191. tw->trace.c.trmFeature = 0;
  192. return true;
  193. }
  194. }
  195. }
  196. }
  197. for ( i = 0; i < p->numEdges; i++ ) {
  198. edgeNum = p->edges[i];
  199. edge = tw->model->edges + abs(edgeNum);
  200. // reset sidedness cache if this is the first time we encounter this edge
  201. if ( edge->checkcount != idCollisionModelManagerLocal::checkCount ) {
  202. edge->sideSet = 0;
  203. }
  204. // pluecker coordinate for edge
  205. tw->polygonEdgePlueckerCache[i].FromLine( tw->model->vertices[edge->vertexNum[0]].p,
  206. tw->model->vertices[edge->vertexNum[1]].p );
  207. v = &tw->model->vertices[edge->vertexNum[INT32_SIGNBITSET( edgeNum )]];
  208. // reset sidedness cache if this is the first time we encounter this vertex
  209. if ( v->checkcount != idCollisionModelManagerLocal::checkCount ) {
  210. v->sideSet = 0;
  211. }
  212. v->checkcount = idCollisionModelManagerLocal::checkCount;
  213. }
  214. // get side of polygon for each trm vertex
  215. for ( i = 0; i < tw->numVerts; i++ ) {
  216. d = p->plane.Distance( tw->vertices[i].p );
  217. sides[i] = d < 0.0f ? -1 : 1;
  218. }
  219. // test if any trm edges go through the polygon
  220. for ( i = 1; i <= tw->numEdges; i++ ) {
  221. // if the trm edge does not cross the polygon plane
  222. if ( sides[tw->edges[i].vertexNum[0]] == sides[tw->edges[i].vertexNum[1]] ) {
  223. continue;
  224. }
  225. // check from which side to which side the trm edge goes
  226. flip = INT32_SIGNBITSET( sides[tw->edges[i].vertexNum[0]] );
  227. // test if trm edge goes through the polygon between the polygon edges
  228. for ( j = 0; j < p->numEdges; j++ ) {
  229. edgeNum = p->edges[j];
  230. edge = tw->model->edges + abs(edgeNum);
  231. #if 1
  232. CM_SetTrmEdgeSidedness( edge, tw->edges[i].pl, tw->polygonEdgePlueckerCache[j], i );
  233. if ( INT32_SIGNBITSET( edgeNum ) ^ ( ( edge->side >> i ) & 1 ) ^ flip ) {
  234. break;
  235. }
  236. #else
  237. d = tw->edges[i].pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[j] );
  238. if ( flip ) {
  239. d = -d;
  240. }
  241. if ( edgeNum > 0 ) {
  242. if ( d <= 0.0f ) {
  243. break;
  244. }
  245. }
  246. else {
  247. if ( d >= 0.0f ) {
  248. break;
  249. }
  250. }
  251. #endif
  252. }
  253. if ( j >= p->numEdges ) {
  254. tw->trace.fraction = 0.0f;
  255. tw->trace.c.type = CONTACT_EDGE;
  256. tw->trace.c.normal = p->plane.Normal();
  257. tw->trace.c.dist = p->plane.Dist();
  258. tw->trace.c.contents = p->contents;
  259. tw->trace.c.material = p->material;
  260. tw->trace.c.point = tw->vertices[tw->edges[i].vertexNum[ !flip ]].p;
  261. tw->trace.c.modelFeature = *reinterpret_cast<int *>(&p);
  262. tw->trace.c.trmFeature = i;
  263. return true;
  264. }
  265. }
  266. // test if any polygon edges go through the trm polygons
  267. for ( i = 0; i < p->numEdges; i++ ) {
  268. edgeNum = p->edges[i];
  269. edge = tw->model->edges + abs(edgeNum);
  270. if ( edge->checkcount == idCollisionModelManagerLocal::checkCount ) {
  271. continue;
  272. }
  273. edge->checkcount = idCollisionModelManagerLocal::checkCount;
  274. for ( j = 0; j < tw->numPolys; j++ ) {
  275. #if 1
  276. v1 = tw->model->vertices + edge->vertexNum[0];
  277. CM_SetTrmPolygonSidedness( v1, tw->polys[j].plane, j );
  278. v2 = tw->model->vertices + edge->vertexNum[1];
  279. CM_SetTrmPolygonSidedness( v2, tw->polys[j].plane, j );
  280. // if the polygon edge does not cross the trm polygon plane
  281. if ( !(((v1->side ^ v2->side) >> j) & 1) ) {
  282. continue;
  283. }
  284. flip = (v1->side >> j) & 1;
  285. #else
  286. float d1, d2;
  287. v1 = tw->model->vertices + edge->vertexNum[0];
  288. d1 = tw->polys[j].plane.Distance( v1->p );
  289. v2 = tw->model->vertices + edge->vertexNum[1];
  290. d2 = tw->polys[j].plane.Distance( v2->p );
  291. // if the polygon edge does not cross the trm polygon plane
  292. if ( (d1 >= 0.0f && d2 >= 0.0f) || (d1 <= 0.0f && d2 <= 0.0f) ) {
  293. continue;
  294. }
  295. flip = false;
  296. if ( d1 < 0.0f ) {
  297. flip = true;
  298. }
  299. #endif
  300. // test if polygon edge goes through the trm polygon between the trm polygon edges
  301. for ( k = 0; k < tw->polys[j].numEdges; k++ ) {
  302. trmEdgeNum = tw->polys[j].edges[k];
  303. trmEdge = tw->edges + abs(trmEdgeNum);
  304. #if 1
  305. bitNum = abs(trmEdgeNum);
  306. CM_SetTrmEdgeSidedness( edge, trmEdge->pl, tw->polygonEdgePlueckerCache[i], bitNum );
  307. if ( INT32_SIGNBITSET( trmEdgeNum ) ^ ( ( edge->side >> bitNum ) & 1 ) ^ flip ) {
  308. break;
  309. }
  310. #else
  311. d = trmEdge->pl.PermutedInnerProduct( tw->polygonEdgePlueckerCache[i] );
  312. if ( flip ) {
  313. d = -d;
  314. }
  315. if ( trmEdgeNum > 0 ) {
  316. if ( d <= 0.0f ) {
  317. break;
  318. }
  319. }
  320. else {
  321. if ( d >= 0.0f ) {
  322. break;
  323. }
  324. }
  325. #endif
  326. }
  327. if ( k >= tw->polys[j].numEdges ) {
  328. tw->trace.fraction = 0.0f;
  329. tw->trace.c.type = CONTACT_EDGE;
  330. tw->trace.c.normal = -tw->polys[j].plane.Normal();
  331. tw->trace.c.dist = -tw->polys[j].plane.Dist();
  332. tw->trace.c.contents = p->contents;
  333. tw->trace.c.material = p->material;
  334. tw->trace.c.point = tw->model->vertices[edge->vertexNum[ !flip ]].p;
  335. tw->trace.c.modelFeature = edgeNum;
  336. tw->trace.c.trmFeature = j;
  337. return true;
  338. }
  339. }
  340. }
  341. return false;
  342. }
  343. /*
  344. ================
  345. idCollisionModelManagerLocal::PointNode
  346. ================
  347. */
  348. cm_node_t *idCollisionModelManagerLocal::PointNode( const idVec3 &p, cm_model_t *model ) {
  349. cm_node_t *node;
  350. node = model->node;
  351. while ( node->planeType != -1 ) {
  352. if (p[node->planeType] > node->planeDist) {
  353. node = node->children[0];
  354. }
  355. else {
  356. node = node->children[1];
  357. }
  358. assert( node != NULL );
  359. }
  360. return node;
  361. }
  362. /*
  363. ================
  364. idCollisionModelManagerLocal::PointContents
  365. ================
  366. */
  367. int idCollisionModelManagerLocal::PointContents( const idVec3 p, cmHandle_t model ) {
  368. int i;
  369. float d;
  370. cm_node_t *node;
  371. cm_brushRef_t *bref;
  372. cm_brush_t *b;
  373. idPlane *plane;
  374. node = idCollisionModelManagerLocal::PointNode( p, idCollisionModelManagerLocal::models[model] );
  375. for ( bref = node->brushes; bref; bref = bref->next ) {
  376. b = bref->b;
  377. // test if the point is within the brush bounds
  378. for ( i = 0; i < 3; i++ ) {
  379. if ( p[i] < b->bounds[0][i] ) {
  380. break;
  381. }
  382. if ( p[i] > b->bounds[1][i] ) {
  383. break;
  384. }
  385. }
  386. if ( i < 3 ) {
  387. continue;
  388. }
  389. // test if the point is inside the brush
  390. plane = b->planes;
  391. for ( i = 0; i < b->numPlanes; i++, plane++ ) {
  392. d = plane->Distance( p );
  393. if ( d >= 0.0f ) {
  394. break;
  395. }
  396. }
  397. if ( i >= b->numPlanes ) {
  398. return b->contents;
  399. }
  400. }
  401. return 0;
  402. }
  403. /*
  404. ==================
  405. idCollisionModelManagerLocal::TransformedPointContents
  406. ==================
  407. */
  408. int idCollisionModelManagerLocal::TransformedPointContents( const idVec3 &p, cmHandle_t model, const idVec3 &origin, const idMat3 &modelAxis ) {
  409. idVec3 p_l;
  410. // subtract origin offset
  411. p_l = p - origin;
  412. if ( modelAxis.IsRotated() ) {
  413. p_l *= modelAxis;
  414. }
  415. return idCollisionModelManagerLocal::PointContents( p_l, model );
  416. }
  417. /*
  418. ==================
  419. idCollisionModelManagerLocal::ContentsTrm
  420. ==================
  421. */
  422. int idCollisionModelManagerLocal::ContentsTrm( trace_t *results, const idVec3 &start,
  423. const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
  424. cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
  425. int i;
  426. bool model_rotated, trm_rotated;
  427. idMat3 invModelAxis, tmpAxis;
  428. idVec3 dir;
  429. ALIGN16( cm_traceWork_t tw );
  430. // fast point case
  431. if ( !trm || ( trm->bounds[1][0] - trm->bounds[0][0] <= 0.0f &&
  432. trm->bounds[1][1] - trm->bounds[0][1] <= 0.0f &&
  433. trm->bounds[1][2] - trm->bounds[0][2] <= 0.0f ) ) {
  434. results->c.contents = idCollisionModelManagerLocal::TransformedPointContents( start, model, modelOrigin, modelAxis );
  435. results->fraction = ( results->c.contents == 0 );
  436. results->endpos = start;
  437. results->endAxis = trmAxis;
  438. return results->c.contents;
  439. }
  440. idCollisionModelManagerLocal::checkCount++;
  441. tw.trace.fraction = 1.0f;
  442. tw.trace.c.contents = 0;
  443. tw.trace.c.type = CONTACT_NONE;
  444. tw.contents = contentMask;
  445. tw.isConvex = true;
  446. tw.rotation = false;
  447. tw.positionTest = true;
  448. tw.pointTrace = false;
  449. tw.quickExit = false;
  450. tw.numContacts = 0;
  451. tw.model = idCollisionModelManagerLocal::models[model];
  452. tw.start = start - modelOrigin;
  453. tw.end = tw.start;
  454. model_rotated = modelAxis.IsRotated();
  455. if ( model_rotated ) {
  456. invModelAxis = modelAxis.Transpose();
  457. }
  458. // setup trm structure
  459. idCollisionModelManagerLocal::SetupTrm( &tw, trm );
  460. trm_rotated = trmAxis.IsRotated();
  461. // calculate vertex positions
  462. if ( trm_rotated ) {
  463. for ( i = 0; i < tw.numVerts; i++ ) {
  464. // rotate trm around the start position
  465. tw.vertices[i].p *= trmAxis;
  466. }
  467. }
  468. for ( i = 0; i < tw.numVerts; i++ ) {
  469. // set trm at start position
  470. tw.vertices[i].p += tw.start;
  471. }
  472. if ( model_rotated ) {
  473. for ( i = 0; i < tw.numVerts; i++ ) {
  474. // rotate trm around model instead of rotating the model
  475. tw.vertices[i].p *= invModelAxis;
  476. }
  477. }
  478. // add offset to start point
  479. if ( trm_rotated ) {
  480. dir = trm->offset * trmAxis;
  481. tw.start += dir;
  482. tw.end += dir;
  483. } else {
  484. tw.start += trm->offset;
  485. tw.end += trm->offset;
  486. }
  487. if ( model_rotated ) {
  488. // rotate trace instead of model
  489. tw.start *= invModelAxis;
  490. tw.end *= invModelAxis;
  491. }
  492. // setup trm vertices
  493. tw.size.Clear();
  494. for ( i = 0; i < tw.numVerts; i++ ) {
  495. // get axial trm size after rotations
  496. tw.size.AddPoint( tw.vertices[i].p - tw.start );
  497. }
  498. // setup trm edges
  499. for ( i = 1; i <= tw.numEdges; i++ ) {
  500. // edge start, end and pluecker coordinate
  501. tw.edges[i].start = tw.vertices[tw.edges[i].vertexNum[0]].p;
  502. tw.edges[i].end = tw.vertices[tw.edges[i].vertexNum[1]].p;
  503. tw.edges[i].pl.FromLine( tw.edges[i].start, tw.edges[i].end );
  504. }
  505. // setup trm polygons
  506. if ( trm_rotated & model_rotated ) {
  507. tmpAxis = trmAxis * invModelAxis;
  508. for ( i = 0; i < tw.numPolys; i++ ) {
  509. tw.polys[i].plane *= tmpAxis;
  510. }
  511. } else if ( trm_rotated ) {
  512. for ( i = 0; i < tw.numPolys; i++ ) {
  513. tw.polys[i].plane *= trmAxis;
  514. }
  515. } else if ( model_rotated ) {
  516. for ( i = 0; i < tw.numPolys; i++ ) {
  517. tw.polys[i].plane *= invModelAxis;
  518. }
  519. }
  520. for ( i = 0; i < tw.numPolys; i++ ) {
  521. tw.polys[i].plane.FitThroughPoint( tw.edges[abs(tw.polys[i].edges[0])].start );
  522. }
  523. // bounds for full trace, a little bit larger for epsilons
  524. for ( i = 0; i < 3; i++ ) {
  525. if ( tw.start[i] < tw.end[i] ) {
  526. tw.bounds[0][i] = tw.start[i] + tw.size[0][i] - CM_BOX_EPSILON;
  527. tw.bounds[1][i] = tw.end[i] + tw.size[1][i] + CM_BOX_EPSILON;
  528. } else {
  529. tw.bounds[0][i] = tw.end[i] + tw.size[0][i] - CM_BOX_EPSILON;
  530. tw.bounds[1][i] = tw.start[i] + tw.size[1][i] + CM_BOX_EPSILON;
  531. }
  532. if ( idMath::Fabs(tw.size[0][i]) > idMath::Fabs(tw.size[1][i]) ) {
  533. tw.extents[i] = idMath::Fabs( tw.size[0][i] ) + CM_BOX_EPSILON;
  534. } else {
  535. tw.extents[i] = idMath::Fabs( tw.size[1][i] ) + CM_BOX_EPSILON;
  536. }
  537. }
  538. // trace through the model
  539. idCollisionModelManagerLocal::TraceThroughModel( &tw );
  540. *results = tw.trace;
  541. results->fraction = ( results->c.contents == 0 );
  542. results->endpos = start;
  543. results->endAxis = trmAxis;
  544. return results->c.contents;
  545. }
  546. /*
  547. ==================
  548. idCollisionModelManagerLocal::Contents
  549. ==================
  550. */
  551. int idCollisionModelManagerLocal::Contents( const idVec3 &start,
  552. const idTraceModel *trm, const idMat3 &trmAxis, int contentMask,
  553. cmHandle_t model, const idVec3 &modelOrigin, const idMat3 &modelAxis ) {
  554. trace_t results;
  555. if ( model < 0 || model > idCollisionModelManagerLocal::maxModels || model > MAX_SUBMODELS ) {
  556. common->Printf("idCollisionModelManagerLocal::Contents: invalid model handle\n");
  557. return 0;
  558. }
  559. if ( !idCollisionModelManagerLocal::models || !idCollisionModelManagerLocal::models[model] ) {
  560. common->Printf("idCollisionModelManagerLocal::Contents: invalid model\n");
  561. return 0;
  562. }
  563. return ContentsTrm( &results, start, trm, trmAxis, contentMask, model, modelOrigin, modelAxis );
  564. }