home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / idlib / geometry / TraceModel.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  43KB  |  1,634 lines

  1.  
  2. #include "../../idlib/precompiled.h"
  3. #pragma hdrstop
  4.  
  5. #include "TraceModel.h"
  6.  
  7.  
  8. /*
  9. ============
  10. idTraceModel::SetupBox
  11. ============
  12. */
  13. void idTraceModel::SetupBox( const idBounds &boxBounds ) {
  14.     int i;
  15.  
  16.     if ( type != TRM_BOX ) {
  17.         InitBox();
  18.     }
  19.     // offset to center
  20.     offset = ( boxBounds[0] + boxBounds[1] ) * 0.5f;
  21.     // set box vertices
  22.     for ( i = 0; i < 8; i++ ) {
  23.         verts[i][0] = boxBounds[(i^(i>>1))&1][0];
  24.         verts[i][1] = boxBounds[(i>>1)&1][1];
  25.         verts[i][2] = boxBounds[(i>>2)&1][2];
  26.     }
  27.     // set polygon plane distances
  28.     polys[0].dist = -boxBounds[0][2];
  29.     polys[1].dist = boxBounds[1][2];
  30.     polys[2].dist = -boxBounds[0][1];
  31.     polys[3].dist = boxBounds[1][0];
  32.     polys[4].dist = boxBounds[1][1];
  33.     polys[5].dist = -boxBounds[0][0];
  34.     // set polygon bounds
  35.     for ( i = 0; i < 6; i++ ) {
  36.         polys[i].bounds = boxBounds;
  37.     }
  38.     polys[0].bounds[1][2] = boxBounds[0][2];
  39.     polys[1].bounds[0][2] = boxBounds[1][2];
  40.     polys[2].bounds[1][1] = boxBounds[0][1];
  41.     polys[3].bounds[0][0] = boxBounds[1][0];
  42.     polys[4].bounds[0][1] = boxBounds[1][1];
  43.     polys[5].bounds[1][0] = boxBounds[0][0];
  44.  
  45.     bounds = boxBounds;
  46. }
  47.  
  48. /*
  49. ============
  50. idTraceModel::SetupBox
  51.  
  52.   The origin is placed at the center of the cube.
  53. ============
  54. */
  55. void idTraceModel::SetupBox( const float size ) {
  56.     idBounds boxBounds;
  57.     float halfSize;
  58.  
  59.     halfSize = size * 0.5f;
  60.     boxBounds[0].Set( -halfSize, -halfSize, -halfSize );
  61.     boxBounds[1].Set( halfSize, halfSize, halfSize );
  62.     SetupBox( boxBounds );
  63. }
  64.  
  65. /*
  66. ============
  67. idTraceModel::InitBox
  68.  
  69.   Initialize size independent box.
  70. ============
  71. */
  72. void idTraceModel::InitBox( void ) {
  73.     int i;
  74.  
  75.     type = TRM_BOX;
  76.     numVerts = 8;
  77.     numEdges = 12;
  78.     numPolys = 6;
  79.  
  80.     // set box edges
  81.     for ( i = 0; i < 4; i++ ) {
  82.         edges[ i + 1 ].v[0] = i;
  83.         edges[ i + 1 ].v[1] = (i + 1) & 3;
  84.         edges[ i + 5 ].v[0] = 4 + i;
  85.         edges[ i + 5 ].v[1] = 4 + ((i + 1) & 3);
  86.         edges[ i + 9 ].v[0] = i;
  87.         edges[ i + 9 ].v[1] = 4 + i;
  88.     }
  89.  
  90.     // all edges of a polygon go counter clockwise
  91.     polys[0].numEdges = 4;
  92.     polys[0].edges[0] = -4;
  93.     polys[0].edges[1] = -3;
  94.     polys[0].edges[2] = -2;
  95.     polys[0].edges[3] = -1;
  96.     polys[0].normal.Set( 0.0f, 0.0f, -1.0f );
  97.  
  98.     polys[1].numEdges = 4;
  99.     polys[1].edges[0] = 5;
  100.     polys[1].edges[1] = 6;
  101.     polys[1].edges[2] = 7;
  102.     polys[1].edges[3] = 8;
  103.     polys[1].normal.Set( 0.0f, 0.0f, 1.0f );
  104.  
  105.     polys[2].numEdges = 4;
  106.     polys[2].edges[0] = 1;
  107.     polys[2].edges[1] = 10;
  108.     polys[2].edges[2] = -5;
  109.     polys[2].edges[3] = -9;
  110.     polys[2].normal.Set( 0.0f, -1.0f,  0.0f );
  111.  
  112.     polys[3].numEdges = 4;
  113.     polys[3].edges[0] = 2;
  114.     polys[3].edges[1] = 11;
  115.     polys[3].edges[2] = -6;
  116.     polys[3].edges[3] = -10;
  117.     polys[3].normal.Set( 1.0f,  0.0f,  0.0f );
  118.  
  119.     polys[4].numEdges = 4;
  120.     polys[4].edges[0] = 3;
  121.     polys[4].edges[1] = 12;
  122.     polys[4].edges[2] = -7;
  123.     polys[4].edges[3] = -11;
  124.     polys[4].normal.Set( 0.0f,  1.0f,  0.0f );
  125.  
  126.     polys[5].numEdges = 4;
  127.     polys[5].edges[0] = 4;
  128.     polys[5].edges[1] = 9;
  129.     polys[5].edges[2] = -8;
  130.     polys[5].edges[3] = -12;
  131.     polys[5].normal.Set( -1.0f,  0.0f,  0.0f );
  132.  
  133.     // convex model
  134.     isConvex = true;
  135.  
  136.     GenerateEdgeNormals();
  137. }
  138.  
  139. /*
  140. ============
  141. idTraceModel::SetupOctahedron
  142. ============
  143. */
  144. void idTraceModel::SetupOctahedron( const idBounds &octBounds ) {
  145.     int i, e0, e1, v0, v1, v2;
  146.     idVec3 v;
  147.  
  148.     if ( type != TRM_OCTAHEDRON ) {
  149.         InitOctahedron();
  150.     }
  151.  
  152.     offset = ( octBounds[0] + octBounds[1] ) * 0.5f;
  153.     v[0] = octBounds[1][0] - offset[0];
  154.     v[1] = octBounds[1][1] - offset[1];
  155.     v[2] = octBounds[1][2] - offset[2];
  156.  
  157.     // set vertices
  158.     verts[0].Set( offset.x + v[0], offset.y, offset.z );
  159.     verts[1].Set( offset.x - v[0], offset.y, offset.z );
  160.     verts[2].Set( offset.x, offset.y + v[1], offset.z );
  161.     verts[3].Set( offset.x, offset.y - v[1], offset.z );
  162.     verts[4].Set( offset.x, offset.y, offset.z + v[2] );
  163.     verts[5].Set( offset.x, offset.y, offset.z - v[2] );
  164.  
  165.     // set polygons
  166.     for ( i = 0; i < numPolys; i++ ) {
  167.         e0 = polys[i].edges[0];
  168.         e1 = polys[i].edges[1];
  169.         v0 = edges[abs(e0)].v[INTSIGNBITSET(e0)];
  170.         v1 = edges[abs(e0)].v[INTSIGNBITNOTSET(e0)];
  171.         v2 = edges[abs(e1)].v[INTSIGNBITNOTSET(e1)];
  172.         // polygon plane
  173.         polys[i].normal = ( verts[v1] - verts[v0] ).Cross( verts[v2] - verts[v0] );
  174.         polys[i].normal.Normalize();
  175.         polys[i].dist = polys[i].normal * verts[v0];
  176.         // polygon bounds
  177.         polys[i].bounds[0] = polys[i].bounds[1] = verts[v0];
  178.         polys[i].bounds.AddPoint( verts[v1] );
  179.         polys[i].bounds.AddPoint( verts[v2] );
  180.     }
  181.  
  182.     // trm bounds
  183.     bounds = octBounds;
  184.  
  185.     GenerateEdgeNormals();
  186. }
  187.  
  188. /*
  189. ============
  190. idTraceModel::SetupOctahedron
  191.  
  192.   The origin is placed at the center of the octahedron.
  193. ============
  194. */
  195. void idTraceModel::SetupOctahedron( const float size ) {
  196.     idBounds octBounds;
  197.     float halfSize;
  198.  
  199.     halfSize = size * 0.5f;
  200.     octBounds[0].Set( -halfSize, -halfSize, -halfSize );
  201.     octBounds[1].Set( halfSize, halfSize, halfSize );
  202.     SetupOctahedron( octBounds );
  203. }
  204.  
  205. /*
  206. ============
  207. idTraceModel::InitOctahedron
  208.  
  209.   Initialize size independent octahedron.
  210. ============
  211. */
  212. void idTraceModel::InitOctahedron( void ) {
  213.  
  214.     type = TRM_OCTAHEDRON;
  215.     numVerts = 6;
  216.     numEdges = 12;
  217.     numPolys = 8;
  218.  
  219.     // set edges
  220.     edges[ 1].v[0] =  4; edges[ 1].v[1] =  0;
  221.     edges[ 2].v[0] =  0; edges[ 2].v[1] =  2;
  222.     edges[ 3].v[0] =  2; edges[ 3].v[1] =  4;
  223.     edges[ 4].v[0] =  2; edges[ 4].v[1] =  1;
  224.     edges[ 5].v[0] =  1; edges[ 5].v[1] =  4;
  225.     edges[ 6].v[0] =  1; edges[ 6].v[1] =  3;
  226.     edges[ 7].v[0] =  3; edges[ 7].v[1] =  4;
  227.     edges[ 8].v[0] =  3; edges[ 8].v[1] =  0;
  228.     edges[ 9].v[0] =  5; edges[ 9].v[1] =  2;
  229.     edges[10].v[0] =  0; edges[10].v[1] =  5;
  230.     edges[11].v[0] =  5; edges[11].v[1] =  1;
  231.     edges[12].v[0] =  5; edges[12].v[1] =  3;
  232.  
  233.     // all edges of a polygon go counter clockwise
  234.     polys[0].numEdges = 3;
  235.     polys[0].edges[0] = 1;
  236.     polys[0].edges[1] = 2;
  237.     polys[0].edges[2] = 3;
  238.  
  239.     polys[1].numEdges = 3;
  240.     polys[1].edges[0] = -3;
  241.     polys[1].edges[1] = 4;
  242.     polys[1].edges[2] = 5;
  243.  
  244.     polys[2].numEdges = 3;
  245.     polys[2].edges[0] = -5;
  246.     polys[2].edges[1] = 6;
  247.     polys[2].edges[2] = 7;
  248.  
  249.     polys[3].numEdges = 3;
  250.     polys[3].edges[0] = -7;
  251.     polys[3].edges[1] = 8;
  252.     polys[3].edges[2] = -1;
  253.  
  254.     polys[4].numEdges = 3;
  255.     polys[4].edges[0] = 9;
  256.     polys[4].edges[1] = -2;
  257.     polys[4].edges[2] = 10;
  258.  
  259.     polys[5].numEdges = 3;
  260.     polys[5].edges[0] = 11;
  261.     polys[5].edges[1] = -4;
  262.     polys[5].edges[2] = -9;
  263.  
  264.     polys[6].numEdges = 3;
  265.     polys[6].edges[0] = 12;
  266.     polys[6].edges[1] = -6;
  267.     polys[6].edges[2] = -11;
  268.  
  269.     polys[7].numEdges = 3;
  270.     polys[7].edges[0] = -10;
  271.     polys[7].edges[1] = -8;
  272.     polys[7].edges[2] = -12;
  273.  
  274.     // convex model
  275.     isConvex = true;
  276. }
  277.  
  278. /*
  279. ============
  280. idTraceModel::SetupDodecahedron
  281. ============
  282. */
  283. void idTraceModel::SetupDodecahedron( const idBounds &dodBounds ) {
  284.     int i, e0, e1, e2, e3, v0, v1, v2, v3, v4;
  285.     float s, d;
  286.     idVec3 a, b, c;
  287.  
  288.     if ( type != TRM_DODECAHEDRON ) {
  289.         InitDodecahedron();
  290.     }
  291.  
  292.     a[0] = a[1] = a[2] = 0.5773502691896257f; // 1.0f / ( 3.0f ) ^ 0.5f;
  293.     b[0] = b[1] = b[2] = 0.3568220897730899f; // ( ( 3.0f - ( 5.0f ) ^ 0.5f ) / 6.0f ) ^ 0.5f;
  294.     c[0] = c[1] = c[2] = 0.9341723589627156f; // ( ( 3.0f + ( 5.0f ) ^ 0.5f ) / 6.0f ) ^ 0.5f;
  295.     d = 0.5f / c[0];
  296.     s = ( dodBounds[1][0] - dodBounds[0][0] ) * d;
  297.     a[0] *= s;
  298.     b[0] *= s;
  299.     c[0] *= s;
  300.     s = ( dodBounds[1][1] - dodBounds[0][1] ) * d;
  301.     a[1] *= s;
  302.     b[1] *= s;
  303.     c[1] *= s;
  304.     s = ( dodBounds[1][2] - dodBounds[0][2] ) * d;
  305.     a[2] *= s;
  306.     b[2] *= s;
  307.     c[2] *= s;
  308.  
  309.     offset = ( dodBounds[0] + dodBounds[1] ) * 0.5f;
  310.  
  311.     // set vertices
  312.     verts[ 0].Set( offset.x + a[0], offset.y + a[1], offset.z + a[2] );
  313.     verts[ 1].Set( offset.x + a[0], offset.y + a[1], offset.z - a[2] );
  314.     verts[ 2].Set( offset.x + a[0], offset.y - a[1], offset.z + a[2] );
  315.     verts[ 3].Set( offset.x + a[0], offset.y - a[1], offset.z - a[2] );
  316.     verts[ 4].Set( offset.x - a[0], offset.y + a[1], offset.z + a[2] );
  317.     verts[ 5].Set( offset.x - a[0], offset.y + a[1], offset.z - a[2] );
  318.     verts[ 6].Set( offset.x - a[0], offset.y - a[1], offset.z + a[2] );
  319.     verts[ 7].Set( offset.x - a[0], offset.y - a[1], offset.z - a[2] );
  320.     verts[ 8].Set( offset.x + b[0], offset.y + c[1], offset.z        );
  321.     verts[ 9].Set( offset.x - b[0], offset.y + c[1], offset.z        );
  322.     verts[10].Set( offset.x + b[0], offset.y - c[1], offset.z        );
  323.     verts[11].Set( offset.x - b[0], offset.y - c[1], offset.z        );
  324.     verts[12].Set( offset.x + c[0], offset.y       , offset.z + b[2] );
  325.     verts[13].Set( offset.x + c[0], offset.y       , offset.z - b[2] );
  326.     verts[14].Set( offset.x - c[0], offset.y       , offset.z + b[2] );
  327.     verts[15].Set( offset.x - c[0], offset.y       , offset.z - b[2] );
  328.     verts[16].Set( offset.x       , offset.y + b[1], offset.z + c[2] );
  329.     verts[17].Set( offset.x       , offset.y - b[1], offset.z + c[2] );
  330.     verts[18].Set( offset.x       , offset.y + b[1], offset.z - c[2] );
  331.     verts[19].Set( offset.x       , offset.y - b[1], offset.z - c[2] );
  332.  
  333.     // set polygons
  334.     for ( i = 0; i < numPolys; i++ ) {
  335.         e0 = polys[i].edges[0];
  336.         e1 = polys[i].edges[1];
  337.         e2 = polys[i].edges[2];
  338.         e3 = polys[i].edges[3];
  339.         v0 = edges[abs(e0)].v[INTSIGNBITSET(e0)];
  340.         v1 = edges[abs(e0)].v[INTSIGNBITNOTSET(e0)];
  341.         v2 = edges[abs(e1)].v[INTSIGNBITNOTSET(e1)];
  342.         v3 = edges[abs(e2)].v[INTSIGNBITNOTSET(e2)];
  343.         v4 = edges[abs(e3)].v[INTSIGNBITNOTSET(e3)];
  344.         // polygon plane
  345.         polys[i].normal = ( verts[v1] - verts[v0] ).Cross( verts[v2] - verts[v0] );
  346.         polys[i].normal.Normalize();
  347.         polys[i].dist = polys[i].normal * verts[v0];
  348.         // polygon bounds
  349.         polys[i].bounds[0] = polys[i].bounds[1] = verts[v0];
  350.         polys[i].bounds.AddPoint( verts[v1] );
  351.         polys[i].bounds.AddPoint( verts[v2] );
  352.         polys[i].bounds.AddPoint( verts[v3] );
  353.         polys[i].bounds.AddPoint( verts[v4] );
  354.     }
  355.  
  356.     // trm bounds
  357.     bounds = dodBounds;
  358.  
  359.     GenerateEdgeNormals();
  360. }
  361.  
  362. /*
  363. ============
  364. idTraceModel::SetupDodecahedron
  365.  
  366.   The origin is placed at the center of the octahedron.
  367. ============
  368. */
  369. void idTraceModel::SetupDodecahedron( const float size ) {
  370.     idBounds dodBounds;
  371.     float halfSize;
  372.  
  373.     halfSize = size * 0.5f;
  374.     dodBounds[0].Set( -halfSize, -halfSize, -halfSize );
  375.     dodBounds[1].Set( halfSize, halfSize, halfSize );
  376.     SetupDodecahedron( dodBounds );
  377. }
  378.  
  379. /*
  380. ============
  381. idTraceModel::InitDodecahedron
  382.  
  383.   Initialize size independent dodecahedron.
  384. ============
  385. */
  386. void idTraceModel::InitDodecahedron( void ) {
  387.  
  388.     type = TRM_DODECAHEDRON;
  389.     numVerts = 20;
  390.     numEdges = 30;
  391.     numPolys = 12;
  392.  
  393.     // set edges
  394.     edges[ 1].v[0] =  0; edges[ 1].v[1] =  8;
  395.     edges[ 2].v[0] =  8; edges[ 2].v[1] =  9;
  396.     edges[ 3].v[0] =  9; edges[ 3].v[1] =  4;
  397.     edges[ 4].v[0] =  4; edges[ 4].v[1] = 16;
  398.     edges[ 5].v[0] = 16; edges[ 5].v[1] =  0;
  399.     edges[ 6].v[0] = 16; edges[ 6].v[1] = 17;
  400.     edges[ 7].v[0] = 17; edges[ 7].v[1] =  2;
  401.     edges[ 8].v[0] =  2; edges[ 8].v[1] = 12;
  402.     edges[ 9].v[0] = 12; edges[ 9].v[1] =  0;
  403.     edges[10].v[0] =  2; edges[10].v[1] = 10;
  404.     edges[11].v[0] = 10; edges[11].v[1] =  3;
  405.     edges[12].v[0] =  3; edges[12].v[1] = 13;
  406.     edges[13].v[0] = 13; edges[13].v[1] = 12;
  407.     edges[14].v[0] =  9; edges[14].v[1] =  5;
  408.     edges[15].v[0] =  5; edges[15].v[1] = 15;
  409.     edges[16].v[0] = 15; edges[16].v[1] = 14;
  410.     edges[17].v[0] = 14; edges[17].v[1] =  4;
  411.     edges[18].v[0] =  3; edges[18].v[1] = 19;
  412.     edges[19].v[0] = 19; edges[19].v[1] = 18;
  413.     edges[20].v[0] = 18; edges[20].v[1] =  1;
  414.     edges[21].v[0] =  1; edges[21].v[1] = 13;
  415.     edges[22].v[0] =  7; edges[22].v[1] = 11;
  416.     edges[23].v[0] = 11; edges[23].v[1] =  6;
  417.     edges[24].v[0] =  6; edges[24].v[1] = 14;
  418.     edges[25].v[0] = 15; edges[25].v[1] =  7;
  419.     edges[26].v[0] =  1; edges[26].v[1] =  8;
  420.     edges[27].v[0] = 18; edges[27].v[1] =  5;
  421.     edges[28].v[0] =  6; edges[28].v[1] = 17;
  422.     edges[29].v[0] = 11; edges[29].v[1] = 10;
  423.     edges[30].v[0] = 19; edges[30].v[1] =  7;
  424.  
  425.     // all edges of a polygon go counter clockwise
  426.     polys[0].numEdges = 5;
  427.     polys[0].edges[0] = 1;
  428.     polys[0].edges[1] = 2;
  429.     polys[0].edges[2] = 3;
  430.     polys[0].edges[3] = 4;
  431.     polys[0].edges[4] = 5;
  432.  
  433.     polys[1].numEdges = 5;
  434.     polys[1].edges[0] = -5;
  435.     polys[1].edges[1] = 6;
  436.     polys[1].edges[2] = 7;
  437.     polys[1].edges[3] = 8;
  438.     polys[1].edges[4] = 9;
  439.  
  440.     polys[2].numEdges = 5;
  441.     polys[2].edges[0] = -8;
  442.     polys[2].edges[1] = 10;
  443.     polys[2].edges[2] = 11;
  444.     polys[2].edges[3] = 12;
  445.     polys[2].edges[4] = 13;
  446.  
  447.     polys[3].numEdges = 5;
  448.     polys[3].edges[0] = 14;
  449.     polys[3].edges[1] = 15;
  450.     polys[3].edges[2] = 16;
  451.     polys[3].edges[3] = 17;
  452.     polys[3].edges[4] = -3;
  453.  
  454.     polys[4].numEdges = 5;
  455.     polys[4].edges[0] = 18;
  456.     polys[4].edges[1] = 19;
  457.     polys[4].edges[2] = 20;
  458.     polys[4].edges[3] = 21;
  459.     polys[4].edges[4] = -12;
  460.  
  461.     polys[5].numEdges = 5;
  462.     polys[5].edges[0] = 22;
  463.     polys[5].edges[1] = 23;
  464.     polys[5].edges[2] = 24;
  465.     polys[5].edges[3] = -16;
  466.     polys[5].edges[4] = 25;
  467.  
  468.     polys[6].numEdges = 5;
  469.     polys[6].edges[0] = -9;
  470.     polys[6].edges[1] = -13;
  471.     polys[6].edges[2] = -21;
  472.     polys[6].edges[3] = 26;
  473.     polys[6].edges[4] = -1;
  474.  
  475.     polys[7].numEdges = 5;
  476.     polys[7].edges[0] = -26;
  477.     polys[7].edges[1] = -20;
  478.     polys[7].edges[2] = 27;
  479.     polys[7].edges[3] = -14;
  480.     polys[7].edges[4] = -2;
  481.  
  482.     polys[8].numEdges = 5;
  483.     polys[8].edges[0] = -4;
  484.     polys[8].edges[1] = -17;
  485.     polys[8].edges[2] = -24;
  486.     polys[8].edges[3] = 28;
  487.     polys[8].edges[4] = -6;
  488.  
  489.     polys[9].numEdges = 5;
  490.     polys[9].edges[0] = -23;
  491.     polys[9].edges[1] = 29;
  492.     polys[9].edges[2] = -10;
  493.     polys[9].edges[3] = -7;
  494.     polys[9].edges[4] = -28;
  495.  
  496.     polys[10].numEdges = 5;
  497.     polys[10].edges[0] = -25;
  498.     polys[10].edges[1] = -15;
  499.     polys[10].edges[2] = -27;
  500.     polys[10].edges[3] = -19;
  501.     polys[10].edges[4] = 30;
  502.  
  503.     polys[11].numEdges = 5;
  504.     polys[11].edges[0] = -30;
  505.     polys[11].edges[1] = -18;
  506.     polys[11].edges[2] = -11;
  507.     polys[11].edges[3] = -29;
  508.     polys[11].edges[4] = -22;
  509.  
  510.     // convex model
  511.     isConvex = true;
  512. }
  513.  
  514. /*
  515. ============
  516. idTraceModel::SetupCylinder
  517. ============
  518. */
  519. void idTraceModel::SetupCylinder( const idBounds &cylBounds, const int numSides ) {
  520.     int i, n, ii, n2;
  521.     float angle;
  522.     idVec3 halfSize;
  523.  
  524.     n = numSides;
  525.     if ( n < 3 ) {
  526.         n = 3;
  527.     }
  528.     if ( n * 2 > MAX_TRACEMODEL_VERTS ) {
  529.         idLib::common->Printf( "WARNING: idTraceModel::SetupCylinder: too many vertices\n" );
  530.         n = MAX_TRACEMODEL_VERTS / 2;
  531.     }
  532.     if ( n * 3 > MAX_TRACEMODEL_EDGES ) {
  533.         idLib::common->Printf( "WARNING: idTraceModel::SetupCylinder: too many sides\n" );
  534.         n = MAX_TRACEMODEL_EDGES / 3;
  535.     }
  536.     if ( n + 2 > MAX_TRACEMODEL_POLYS ) {
  537.         idLib::common->Printf( "WARNING: idTraceModel::SetupCylinder: too many polygons\n" );
  538.         n = MAX_TRACEMODEL_POLYS - 2;
  539.     }
  540.  
  541.     type = TRM_CYLINDER;
  542.     numVerts = n * 2;
  543.     numEdges = n * 3;
  544.     numPolys = n + 2;
  545.     offset = ( cylBounds[0] + cylBounds[1] ) * 0.5f;
  546.     halfSize = cylBounds[1] - offset;
  547.     for ( i = 0; i < n; i++ ) {
  548.         // verts
  549.         angle = idMath::TWO_PI * i / n;
  550. // RAVEN BEGIN
  551.         verts[i].x = idMath::Cos( angle ) * halfSize.x + offset.x;
  552.         verts[i].y = idMath::Sin( angle ) * halfSize.y + offset.y;
  553. // RAVEN END
  554.         verts[i].z = -halfSize.z + offset.z;
  555.         verts[n+i].x = verts[i].x;
  556.         verts[n+i].y = verts[i].y;
  557.         verts[n+i].z = halfSize.z + offset.z;
  558.         // edges
  559.         ii = i + 1;
  560.         n2 = n << 1;
  561.         edges[ii].v[0] = i;
  562.         edges[ii].v[1] = ii % n;
  563.         edges[n+ii].v[0] = edges[ii].v[0] + n;
  564.         edges[n+ii].v[1] = edges[ii].v[1] + n;
  565.         edges[n2+ii].v[0] = i;
  566.         edges[n2+ii].v[1] = n + i;
  567.         // vertical polygon edges
  568.         polys[i].numEdges = 4;
  569.         polys[i].edges[0] = ii;
  570.         polys[i].edges[1] = n2 + (ii % n) + 1;
  571.         polys[i].edges[2] = -(n + ii);
  572.         polys[i].edges[3] = -(n2 + ii);
  573.         // bottom and top polygon edges
  574.         polys[n].edges[i] = -(n - i);
  575.         polys[n+1].edges[i] = n + ii;
  576.     }
  577.     // bottom and top polygon numEdges
  578.     polys[n].numEdges = n;
  579.     polys[n+1].numEdges = n;
  580.     // polygons
  581.     for ( i = 0; i < n; i++ ) {
  582.         // vertical polygon plane
  583.         polys[i].normal = (verts[(i+1)%n] - verts[i]).Cross( verts[n+i] - verts[i] );
  584.         polys[i].normal.Normalize();
  585.         polys[i].dist = polys[i].normal * verts[i];
  586.         // vertical polygon bounds
  587.         polys[i].bounds.Clear();
  588.         polys[i].bounds.AddPoint( verts[i] );
  589.         polys[i].bounds.AddPoint( verts[(i+1)%n] );
  590.         polys[i].bounds[0][2] = -halfSize.z + offset.z;
  591.         polys[i].bounds[1][2] = halfSize.z + offset.z;
  592.     }
  593.     // bottom and top polygon plane
  594.     polys[n].normal.Set( 0.0f, 0.0f, -1.0f );
  595.     polys[n].dist = -cylBounds[0][2];
  596.     polys[n+1].normal.Set( 0.0f, 0.0f, 1.0f );
  597.     polys[n+1].dist = cylBounds[1][2];
  598.     // trm bounds
  599.     bounds = cylBounds;
  600.     // bottom and top polygon bounds
  601.     polys[n].bounds = bounds;
  602.     polys[n].bounds[1][2] = bounds[0][2];
  603.     polys[n+1].bounds = bounds;
  604.     polys[n+1].bounds[0][2] = bounds[1][2];
  605.     // convex model
  606.     isConvex = true;
  607.  
  608.     GenerateEdgeNormals();
  609. }
  610.  
  611. /*
  612. ============
  613. idTraceModel::SetupCylinder
  614.  
  615.   The origin is placed at the center of the cylinder.
  616. ============
  617. */
  618. void idTraceModel::SetupCylinder( const float height, const float width, const int numSides ) {
  619.     idBounds cylBounds;
  620.     float halfHeight, halfWidth;
  621.  
  622.     halfHeight = height * 0.5f;
  623.     halfWidth = width * 0.5f;
  624.     cylBounds[0].Set( -halfWidth, -halfWidth, -halfHeight );
  625.     cylBounds[1].Set( halfWidth, halfWidth, halfHeight );
  626.     SetupCylinder( cylBounds, numSides );
  627. }
  628.  
  629. /*
  630. ============
  631. idTraceModel::SetupCone
  632. ============
  633. */
  634. void idTraceModel::SetupCone( const idBounds &coneBounds, const int numSides ) {
  635.     int i, n, ii;
  636.     float angle;
  637.     idVec3 halfSize;
  638.  
  639.     n = numSides;
  640.     if ( n < 2 ) {
  641.         n = 3;
  642.     }
  643.     if ( n + 1 > MAX_TRACEMODEL_VERTS ) {
  644.         idLib::common->Printf( "WARNING: idTraceModel::SetupCone: too many vertices\n" );
  645.         n = MAX_TRACEMODEL_VERTS - 1;
  646.     }
  647.     if ( n * 2 > MAX_TRACEMODEL_EDGES ) {
  648.         idLib::common->Printf( "WARNING: idTraceModel::SetupCone: too many edges\n" );
  649.         n = MAX_TRACEMODEL_EDGES / 2;
  650.     }
  651.     if ( n + 1 > MAX_TRACEMODEL_POLYS ) {
  652.         idLib::common->Printf( "WARNING: idTraceModel::SetupCone: too many polygons\n" );
  653.         n = MAX_TRACEMODEL_POLYS - 1;
  654.     }
  655.  
  656.     type = TRM_CONE;
  657.     numVerts = n + 1;
  658.     numEdges = n * 2;
  659.     numPolys = n + 1;
  660.     offset = ( coneBounds[0] + coneBounds[1] ) * 0.5f;
  661.     halfSize = coneBounds[1] - offset;
  662.     verts[n].Set( 0.0f, 0.0f, halfSize.z + offset.z );
  663.     for ( i = 0; i < n; i++ ) {
  664.         // verts
  665.         angle = idMath::TWO_PI * i / n;
  666. // RAVEN BEGIN
  667.         verts[i].x = idMath::Cos( angle ) * halfSize.x + offset.x;
  668.         verts[i].y = idMath::Sin( angle ) * halfSize.y + offset.y;
  669. // RAVEN END
  670.         verts[i].z = -halfSize.z + offset.z;
  671.         // edges
  672.         ii = i + 1;
  673.         edges[ii].v[0] = i;
  674.         edges[ii].v[1] = ii % n;
  675.         edges[n+ii].v[0] = i;
  676.         edges[n+ii].v[1] = n;
  677.         // vertical polygon edges
  678.         polys[i].numEdges = 3;
  679.         polys[i].edges[0] = ii;
  680.         polys[i].edges[1] = n + (ii % n) + 1;
  681.         polys[i].edges[2] = -(n + ii);
  682.         // bottom polygon edges
  683.         polys[n].edges[i] = -(n - i);
  684.     }
  685.     // bottom polygon numEdges
  686.     polys[n].numEdges = n;
  687.  
  688.     // polygons
  689.     for ( i = 0; i < n; i++ ) {
  690.         // polygon plane
  691.         polys[i].normal = (verts[(i+1)%n] - verts[i]).Cross( verts[n] - verts[i] );
  692.         polys[i].normal.Normalize();
  693.         polys[i].dist = polys[i].normal * verts[i];
  694.         // polygon bounds
  695.         polys[i].bounds.Clear();
  696.         polys[i].bounds.AddPoint( verts[i] );
  697.         polys[i].bounds.AddPoint( verts[(i+1)%n] );
  698.         polys[i].bounds.AddPoint( verts[n] );
  699.     }
  700.     // bottom polygon plane
  701.     polys[n].normal.Set( 0.0f, 0.0f, -1.0f );
  702.     polys[n].dist = -coneBounds[0][2];
  703.     // trm bounds
  704.     bounds = coneBounds;
  705.     // bottom polygon bounds
  706.     polys[n].bounds = bounds;
  707.     polys[n].bounds[1][2] = bounds[0][2];
  708.     // convex model
  709.     isConvex = true;
  710.  
  711.     GenerateEdgeNormals();
  712. }
  713.  
  714. /*
  715. ============
  716. idTraceModel::SetupCone
  717.  
  718.   The origin is placed at the apex of the cone.
  719. ============
  720. */
  721. void idTraceModel::SetupCone( const float height, const float width, const int numSides ) {
  722.     idBounds coneBounds;
  723.     float halfWidth;
  724.  
  725.     halfWidth = width * 0.5f;
  726.     coneBounds[0].Set( -halfWidth, -halfWidth, -height );
  727.     coneBounds[1].Set( halfWidth, halfWidth, 0.0f );
  728.     SetupCone( coneBounds, numSides );
  729. }
  730.  
  731. /*
  732. ============
  733. idTraceModel::SetupBone
  734.  
  735.   The origin is placed at the center of the bone.
  736. ============
  737. */
  738. void idTraceModel::SetupBone( const float length, const float width ) {
  739.     int i, j, edgeNum;
  740.     float halfLength = length * 0.5f;
  741.  
  742.     if ( type != TRM_BONE ) {
  743.         InitBone();
  744.     }
  745.     // offset to center
  746.     offset.Set( 0.0f, 0.0f, 0.0f );
  747.     // set vertices
  748.     verts[0].Set( 0.0f, 0.0f, -halfLength );
  749.     verts[1].Set( 0.0f, width * -0.5f, 0.0f );
  750.     verts[2].Set( width * 0.5f, width * 0.25f, 0.0f );
  751.     verts[3].Set( width * -0.5f, width * 0.25f, 0.0f );
  752.     verts[4].Set( 0.0f, 0.0f, halfLength );
  753.     // set bounds
  754.     bounds[0].Set( width * -0.5f, width * -0.5f, -halfLength );
  755.     bounds[1].Set( width * 0.5f, width * 0.25f, halfLength );
  756.     // poly plane normals
  757.     polys[0].normal = ( verts[2] - verts[0] ).Cross( verts[1] - verts[0] );
  758.     polys[0].normal.Normalize();
  759.     polys[2].normal.Set( -polys[0].normal[0], polys[0].normal[1], polys[0].normal[2] );
  760.     polys[3].normal.Set( polys[0].normal[0], polys[0].normal[1], -polys[0].normal[2] );
  761.     polys[5].normal.Set( -polys[0].normal[0], polys[0].normal[1], -polys[0].normal[2] );
  762.     polys[1].normal = (verts[3] - verts[0]).Cross(verts[2] - verts[0]);
  763.     polys[1].normal.Normalize();
  764.     polys[4].normal.Set( polys[1].normal[0], polys[1].normal[1], -polys[1].normal[2] );
  765.     // poly plane distances
  766.     for ( i = 0; i < 6; i++ ) {
  767.         polys[i].dist = polys[i].normal * verts[ edges[ abs(polys[i].edges[0]) ].v[0] ];
  768.         polys[i].bounds.Clear();
  769.         for ( j = 0; j < 3; j++ ) {
  770.             edgeNum = polys[i].edges[ j ];
  771.             polys[i].bounds.AddPoint( verts[ edges[abs(edgeNum)].v[edgeNum < 0] ] );
  772.         }
  773.     }
  774.  
  775.     GenerateEdgeNormals();
  776. }
  777.  
  778. /*
  779. ============
  780. idTraceModel::InitBone
  781.  
  782.   Initialize size independent bone.
  783. ============
  784. */
  785. void idTraceModel::InitBone( void ) {
  786.     int i;
  787.  
  788.     type = TRM_BONE;
  789.     numVerts = 5;
  790.     numEdges = 9;
  791.     numPolys = 6;
  792.  
  793.     // set bone edges
  794.     for ( i = 0; i < 3; i++ ) {
  795.         edges[ i + 1 ].v[0] = 0;
  796.         edges[ i + 1 ].v[1] = i + 1;
  797.         edges[ i + 4 ].v[0] = 1 + i;
  798.         edges[ i + 4 ].v[1] = 1 + ((i + 1) % 3);
  799.         edges[ i + 7 ].v[0] = i + 1;
  800.         edges[ i + 7 ].v[1] = 4;
  801.     }
  802.  
  803.     // all edges of a polygon go counter clockwise
  804.     polys[0].numEdges = 3;
  805.     polys[0].edges[0] = 2;
  806.     polys[0].edges[1] = -4;
  807.     polys[0].edges[2] = -1;
  808.  
  809.     polys[1].numEdges = 3;
  810.     polys[1].edges[0] = 3;
  811.     polys[1].edges[1] = -5;
  812.     polys[1].edges[2] = -2;
  813.  
  814.     polys[2].numEdges = 3;
  815.     polys[2].edges[0] = 1;
  816.     polys[2].edges[1] = -6;
  817.     polys[2].edges[2] = -3;
  818.  
  819.     polys[3].numEdges = 3;
  820.     polys[3].edges[0] = 4;
  821.     polys[3].edges[1] = 8;
  822.     polys[3].edges[2] = -7;
  823.  
  824.     polys[4].numEdges = 3;
  825.     polys[4].edges[0] = 5;
  826.     polys[4].edges[1] = 9;
  827.     polys[4].edges[2] = -8;
  828.  
  829.     polys[5].numEdges = 3;
  830.     polys[5].edges[0] = 6;
  831.     polys[5].edges[1] = 7;
  832.     polys[5].edges[2] = -9;
  833.  
  834.     // convex model
  835.     isConvex = true;
  836. }
  837.  
  838. /*
  839. ============
  840. idTraceModel::SetupPolygon
  841. ============
  842. */
  843. void idTraceModel::SetupPolygon( const idVec3 *v, const int count ) {
  844.     int i, j;
  845.     idVec3 mid;
  846.  
  847.     type = TRM_POLYGON;
  848.     numVerts = count;
  849.     // times three because we need to be able to turn the polygon into a volume
  850.     if ( numVerts * 3 > MAX_TRACEMODEL_EDGES ) {
  851.         idLib::common->Printf( "WARNING: idTraceModel::SetupPolygon: too many vertices\n" );
  852.         numVerts = MAX_TRACEMODEL_EDGES / 3;
  853.     }
  854.  
  855.     numEdges = numVerts;
  856.     numPolys = 2;
  857.     // set polygon planes
  858.     polys[0].numEdges = numEdges;
  859.     polys[0].normal = ( v[1] - v[0] ).Cross( v[2] - v[0] );
  860.     polys[0].normal.Normalize();
  861.     polys[0].dist = polys[0].normal * v[0];
  862.     polys[1].numEdges = numEdges;
  863.     polys[1].normal = -polys[0].normal;
  864.     polys[1].dist = -polys[0].dist;
  865.     // setup verts, edges and polygons
  866.     polys[0].bounds.Clear();
  867.     mid = vec3_origin;
  868.     for ( i = 0, j = 1; i < numVerts; i++, j++ ) {
  869.         if ( j >= numVerts ) {
  870.             j = 0;
  871.         }
  872.         verts[i] = v[i];
  873.         edges[i+1].v[0] = i;
  874.         edges[i+1].v[1] = j;
  875.         edges[i+1].normal = polys[0].normal.Cross( v[i] - v[j] );
  876.         edges[i+1].normal.Normalize();
  877.         polys[0].edges[i] = i + 1;
  878.         polys[1].edges[i] = -(numVerts - i);
  879.         polys[0].bounds.AddPoint( verts[i] );
  880.         mid += v[i];
  881.     }
  882.     polys[1].bounds = polys[0].bounds;
  883.     // offset to center
  884.     offset = mid * (1.0f / numVerts);
  885.     // total bounds
  886.     bounds = polys[0].bounds;
  887.     // considered non convex because the model has no volume
  888.     isConvex = false;
  889. }
  890.  
  891. /*
  892. ============
  893. idTraceModel::SetupPolygon
  894. ============
  895. */
  896. void idTraceModel::SetupPolygon( const idWinding &w ) {
  897.     int i;
  898.     idVec3 *verts;
  899.  
  900.     verts = (idVec3 *) _alloca16( w.GetNumPoints() * sizeof( idVec3 ) );
  901.     for ( i = 0; i < w.GetNumPoints(); i++ ) {
  902.         verts[i] = w[i].ToVec3();
  903.     }
  904.     SetupPolygon( verts, w.GetNumPoints() );
  905. }
  906.  
  907. /*
  908. ============
  909. idTraceModel::VolumeFromPolygon
  910. ============
  911. */
  912. void idTraceModel::VolumeFromPolygon( idTraceModel &trm, float thickness ) const {
  913.     int i;
  914.  
  915.     trm = *this;
  916.     trm.type = TRM_POLYGONVOLUME;
  917.     trm.numVerts = numVerts * 2;
  918.     trm.numEdges = numEdges * 3;
  919.     trm.numPolys = numEdges + 2;
  920.     for ( i = 0; i < numEdges; i++ ) {
  921.         trm.verts[ numVerts + i ] = verts[i] - thickness * polys[0].normal;
  922.         trm.edges[ numEdges + i + 1 ].v[0] = numVerts + i;
  923.         trm.edges[ numEdges + i + 1 ].v[1] = numVerts + (i+1) % numVerts;
  924.         trm.edges[ numEdges * 2 + i + 1 ].v[0] = i;
  925.         trm.edges[ numEdges * 2 + i + 1 ].v[1] = numVerts + i;
  926.         trm.polys[1].edges[i] = -(numEdges + i + 1);
  927.         trm.polys[2+i].numEdges = 4;
  928.         trm.polys[2+i].edges[0] = -(i + 1);
  929.         trm.polys[2+i].edges[1] = numEdges*2 + i + 1;
  930.         trm.polys[2+i].edges[2] = numEdges + i + 1;
  931.         trm.polys[2+i].edges[3] = -(numEdges*2 + (i+1) % numEdges + 1);
  932.         trm.polys[2+i].normal = (verts[(i + 1) % numVerts] - verts[i]).Cross( polys[0].normal );
  933.         trm.polys[2+i].normal.Normalize();
  934.         trm.polys[2+i].dist = trm.polys[2+i].normal * verts[i];
  935.     }
  936.     trm.polys[1].dist = trm.polys[1].normal * trm.verts[ numEdges ];
  937.  
  938.     trm.GenerateEdgeNormals();
  939. }
  940.  
  941. /*
  942. ============
  943. idTraceModel::GenerateEdgeNormals
  944. ============
  945. */
  946. #define SHARP_EDGE_DOT    -0.7f
  947.  
  948. int idTraceModel::GenerateEdgeNormals( void ) {
  949.     int i, j, edgeNum, numSharpEdges;
  950.     float dot;
  951.     idVec3 dir;
  952.     traceModelPoly_t *poly;
  953.     traceModelEdge_t *edge;
  954.  
  955.     for ( i = 0; i <= numEdges; i++ ) {
  956.         edges[i].normal.Zero();
  957.     }
  958.  
  959.     numSharpEdges = 0;
  960.  
  961.     for ( i = 0; i < numPolys; i++ ) {
  962.         poly = polys + i;
  963.         for ( j = 0; j < poly->numEdges; j++ ) {
  964.             edgeNum = poly->edges[j];
  965.             edge = edges + abs( edgeNum );
  966.             if ( edge->normal[0] == 0.0f && edge->normal[1] == 0.0f && edge->normal[2] == 0.0f ) {
  967.                 edge->normal = poly->normal;
  968.             } else {
  969.                 dot = edge->normal * poly->normal;
  970.                 // if the two planes make a very sharp edge
  971.                 if ( dot < SHARP_EDGE_DOT ) {
  972.                     // max length normal pointing outside both polygons
  973.                     dir = verts[ edge->v[edgeNum > 0]] - verts[ edge->v[edgeNum < 0]];
  974.                     edge->normal = edge->normal.Cross( dir ) + poly->normal.Cross( -dir );
  975.                     edge->normal *= ( 1.0f / ( 1.0f + SHARP_EDGE_DOT ) ) / edge->normal.Length();
  976.                     numSharpEdges++;
  977.                 } else {
  978.                     edge->normal = ( 1.0f / ( 1.0f + dot ) ) * ( edge->normal + poly->normal );
  979.                 }
  980.             }
  981.         }
  982.     }
  983.  
  984.     return numSharpEdges;
  985. }
  986.  
  987. /*
  988. ============
  989. idTraceModel::TestConvexity
  990. ============
  991. */
  992. void idTraceModel::TestConvexity( void ) {
  993.     int i, j;
  994.  
  995.     // assume convex
  996.     isConvex = true;
  997.     // check if really convex
  998.     for ( i = 0; i < numPolys; i++ ) {
  999.         // to be convex no vertices should be in front of any polygon plane
  1000.         for ( j = 0; j < numVerts; j++ ) {
  1001.             if ( polys[ i ].normal * verts[ j ] - polys[ i ].dist > 0.01f ) {
  1002.                 isConvex = false;
  1003.                 break;
  1004.             }
  1005.         }
  1006.         if ( j < numVerts ) {
  1007.             break;
  1008.         }
  1009.     }
  1010. }
  1011.  
  1012. /*
  1013. ============
  1014. idTraceModel::Translate
  1015. ============
  1016. */
  1017. void idTraceModel::Translate( const idVec3 &translation ) {
  1018.     int i;
  1019.  
  1020.     for ( i = 0; i < numVerts; i++ ) {
  1021.         verts[i] += translation;
  1022.     }
  1023.     for ( i = 0; i < numPolys; i++ ) {
  1024.         polys[i].dist += polys[i].normal * translation;
  1025.         polys[i].bounds[0] += translation;
  1026.         polys[i].bounds[1] += translation;
  1027.     }
  1028.     offset += translation;
  1029.     bounds[0] += translation;
  1030.     bounds[1] += translation;
  1031. }
  1032.  
  1033. /*
  1034. ============
  1035. idTraceModel::Rotate
  1036. ============
  1037. */
  1038. void idTraceModel::Rotate( const idMat3 &rotation ) {
  1039.     int i, j, edgeNum;
  1040.  
  1041.     for ( i = 0; i < numVerts; i++ ) {
  1042.         verts[i] *= rotation;
  1043.     }
  1044.  
  1045.     bounds.Clear();
  1046.     for ( i = 0; i < numPolys; i++ ) {
  1047.         polys[i].normal *= rotation;
  1048.         polys[i].bounds.Clear();
  1049.         edgeNum = 0;
  1050.         for ( j = 0; j < polys[i].numEdges; j++ ) {
  1051.             edgeNum = polys[i].edges[j];
  1052.             polys[i].bounds.AddPoint( verts[edges[abs(edgeNum)].v[INTSIGNBITSET(edgeNum)]] );
  1053.         }
  1054.         polys[i].dist = polys[i].normal * verts[edges[abs(edgeNum)].v[INTSIGNBITSET(edgeNum)]];
  1055.         bounds += polys[i].bounds;
  1056.     }
  1057.  
  1058.     GenerateEdgeNormals();
  1059. }
  1060.  
  1061. /*
  1062. ============
  1063. idTraceModel::Shrink
  1064. ============
  1065. */
  1066. void idTraceModel::Shrink( const float m ) {
  1067.     int i, j, edgeNum, vertexNum;
  1068.     float d, bestd, n, invDet, f0, f1;
  1069.     traceModelPoly_t *poly, *poly1, *poly2;
  1070.     traceModelEdge_t *edge;
  1071.     idVec3 start, dir;
  1072.     int vertexPolys[MAX_TRACEMODEL_VERTS][MAX_TRACEMODEL_POLYS];
  1073.     int vertexNumPolys[MAX_TRACEMODEL_VERTS];
  1074.  
  1075.     // special case for single polygon
  1076.     if ( type == TRM_POLYGON ) {
  1077.         for ( i = 0; i < numEdges; i++ ) {
  1078.             edgeNum = polys[0].edges[i];
  1079.             edge = &edges[abs(edgeNum)];
  1080.             dir = verts[ edge->v[ INTSIGNBITSET(edgeNum) ] ] - verts[ edge->v[ INTSIGNBITNOTSET(edgeNum) ] ];
  1081.             if ( dir.Normalize() < 2.0f * m ) {
  1082.                 continue;
  1083.             }
  1084.             dir *= m;
  1085.             verts[ edge->v[ 0 ] ] -= dir;
  1086.             verts[ edge->v[ 1 ] ] += dir;
  1087.         }
  1088.         return;
  1089.     }
  1090.  
  1091.     // the trace model should be a closed surface
  1092.     assert( IsClosedSurface() );
  1093.  
  1094.     memset( vertexPolys, 0, sizeof( vertexPolys ) );
  1095.     memset( vertexNumPolys, 0, sizeof( vertexNumPolys ) );
  1096.  
  1097.     // move polygon planes and find the vertex polygons
  1098.     for ( i = 0; i < numPolys; i++ ) {
  1099.         poly = &polys[i];
  1100.  
  1101.         poly->dist -= m;
  1102.  
  1103.         for ( j = 0; j < poly->numEdges; j++ ) {
  1104.             edgeNum = poly->edges[j];
  1105.             edge = &edges[abs(edgeNum)];
  1106.             vertexNum = edge->v[ INTSIGNBITSET( edgeNum ) ];
  1107.  
  1108.             vertexPolys[vertexNum][vertexNumPolys[vertexNum]] = i;
  1109.             vertexNumPolys[vertexNum]++;
  1110.         }
  1111.     }
  1112.  
  1113.     // move vertices
  1114.     for ( i = 0; i < numVerts; i++ ) {
  1115.  
  1116.         assert( vertexNumPolys[i] >= 3 );
  1117.  
  1118.         poly1 = &polys[vertexPolys[i][0]];
  1119.         poly2 = NULL;
  1120.  
  1121.         // find the polygon that is most orthogonal to the first polygon
  1122.         bestd = 1.0f;
  1123.         for ( j = 1; j < vertexNumPolys[i]; j++ ) {
  1124.             d = fabs( poly1->normal * polys[vertexPolys[i][j]].normal );
  1125.             if ( d < bestd ) {
  1126.                 bestd = d;
  1127.                 poly2 = &polys[vertexPolys[i][j]];
  1128.             }
  1129.         }
  1130.  
  1131.         // calculate intersection line between planes
  1132.         n = poly1->normal * poly2->normal;
  1133.         invDet = 1.0f / ( 1.0f - n * n );
  1134.         f0 = ( poly1->dist - n * poly2->dist ) * invDet;
  1135.         f1 = ( poly2->dist - n * poly1->dist ) * invDet;
  1136.         start = f0 * poly1->normal + f1 * poly2->normal;
  1137.         dir = poly1->normal.Cross( poly2->normal );
  1138.  
  1139.         // find the polygon that is most orthogonal to the plane intersection ray
  1140.         bestd = 0.0f;
  1141.         for ( j = 1; j < vertexNumPolys[i]; j++ ) {
  1142.             d = fabs( dir * polys[vertexPolys[i][j]].normal );
  1143.             if ( d > bestd ) {
  1144.                 bestd = d;
  1145.                 poly2 = &polys[vertexPolys[i][j]];
  1146.             }
  1147.         }
  1148.  
  1149.         // calculate intersection with plane intersection ray
  1150.         f0 = poly2->normal * start - poly2->dist;
  1151.         f1 = poly2->normal * dir;
  1152.         verts[i] = start - dir * ( f0 / f1 );
  1153.     }
  1154.  
  1155.     Verify();
  1156. }
  1157.  
  1158. /*
  1159. ============
  1160. idTraceModel::ClearUnused
  1161. ============
  1162. */
  1163. void idTraceModel::ClearUnused( void ) {
  1164.     int i, j;
  1165.  
  1166.     for ( i = numVerts; i < MAX_TRACEMODEL_VERTS; i++ ) {
  1167.         verts[i].Zero();
  1168.     }
  1169.     memset( &edges[0], 0, sizeof( edges[0] ) );
  1170.     for ( i = numEdges+1; i < MAX_TRACEMODEL_EDGES+1; i++ ) {
  1171.         memset( &edges[i], 0, sizeof( edges[i] ) );
  1172.     }
  1173.     for ( i = 0; i < numPolys; i++ ) {
  1174.         for ( j = polys[i].numEdges; j < MAX_TRACEMODEL_POLYEDGES; j++ ) {
  1175.             polys[i].edges[j] = 0;
  1176.         }
  1177.     }
  1178.     for ( i = numPolys; i < MAX_TRACEMODEL_POLYS; i++ ) {
  1179.         memset( &polys[i], 0, sizeof( polys[i] ) );
  1180.     }
  1181. }
  1182.  
  1183. /*
  1184. ============
  1185. idTraceModel::Verify
  1186. ============
  1187. */
  1188. bool idTraceModel::Verify( void ) {
  1189.     int i, j, edgeNum, vertexNum;
  1190.     traceModelPoly_t *poly;
  1191.     traceModelEdge_t *edge;
  1192.  
  1193.     // test whether or not the vertices are on the polygon planes
  1194.     for ( i = 0; i < numPolys; i++ ) {
  1195.         poly = &polys[i];
  1196.  
  1197.         for ( j = 0; j < polys[i].numEdges; j++ ) {
  1198.             edgeNum = poly->edges[j];
  1199.             edge = &edges[abs(edgeNum)];
  1200.             vertexNum = edge->v[ INTSIGNBITSET( edgeNum ) ];
  1201.             float d = poly->normal * verts[vertexNum] - poly->dist;
  1202.             if ( fabs( d ) > 1e-4f ) {
  1203.                 return false;
  1204.             }
  1205.         }
  1206.     }
  1207.  
  1208.     return true;
  1209. }
  1210.  
  1211. /*
  1212. ============
  1213. idTraceModel::Compare
  1214. ============
  1215. */
  1216. bool idTraceModel::Compare( const idTraceModel &trm ) const {
  1217.     int i;
  1218.  
  1219.     if ( type != trm.type || numVerts != trm.numVerts || 
  1220.             numEdges != trm.numEdges || numPolys != trm.numPolys ) {
  1221.         return false;
  1222.     }
  1223.     if ( bounds != trm.bounds || offset != trm.offset ) {
  1224.         return false;
  1225.     }
  1226.  
  1227.     switch( type ) {
  1228.         case TRM_INVALID:
  1229.         case TRM_BOX:
  1230.         case TRM_OCTAHEDRON:
  1231.         case TRM_DODECAHEDRON:
  1232.         case TRM_CYLINDER:
  1233.         case TRM_CONE:
  1234.             break;
  1235.         case TRM_BONE:
  1236.         case TRM_POLYGON:
  1237.         case TRM_POLYGONVOLUME:
  1238.         case TRM_CUSTOM:
  1239.             for ( i = 0; i < trm.numVerts; i++ ) {
  1240.                 if ( verts[i] != trm.verts[i] ) {
  1241.                     return false;
  1242.                 }
  1243.             }
  1244.             break;
  1245.     }
  1246.     return true;
  1247. }
  1248.  
  1249. /*
  1250. ============
  1251. idTraceModel::IsClosedSurface
  1252. ============
  1253. */
  1254. bool idTraceModel::IsClosedSurface( void ) const {
  1255.     int i, j, numEdgeUsers[MAX_TRACEMODEL_EDGES+1];
  1256.  
  1257.     // each edge should be used exactly twice
  1258.     memset( numEdgeUsers, 0, sizeof(numEdgeUsers) );
  1259.     for ( i = 0; i < numPolys; i++ ) {
  1260.         for ( j = 0; j < polys[i].numEdges; j++ ) {
  1261.             numEdgeUsers[ abs( polys[i].edges[j] ) ]++;
  1262.         }
  1263.     }
  1264.     for ( i = 1; i <= numEdges; i++ ) {
  1265.         if ( numEdgeUsers[i] != 2 ) {
  1266.             return false;
  1267.         }
  1268.     }
  1269.     return true;
  1270. }
  1271.  
  1272. /*
  1273. ============
  1274. idTraceModel::GetPolygonArea
  1275. ============
  1276. */
  1277. float idTraceModel::GetPolygonArea( int polyNum ) const {
  1278.     int i;
  1279.     idVec3 base, v1, v2, cross;
  1280.     float total;
  1281.     const traceModelPoly_t *poly;
  1282.  
  1283.     if ( polyNum < 0 || polyNum >= numPolys ) {
  1284.         return 0.0f;
  1285.     }
  1286.     poly = &polys[polyNum];
  1287.     total = 0.0f;
  1288.     base = verts[ edges[ abs(poly->edges[0]) ].v[ INTSIGNBITSET( poly->edges[0] ) ] ];
  1289.     for ( i = 0; i < poly->numEdges; i++ ) {
  1290.         v1 = verts[ edges[ abs(poly->edges[i]) ].v[ INTSIGNBITSET( poly->edges[i] ) ] ] - base;
  1291.         v2 = verts[ edges[ abs(poly->edges[i]) ].v[ INTSIGNBITNOTSET( poly->edges[i] ) ] ] - base;
  1292.         cross = v1.Cross( v2 );
  1293.         total += cross.Length();
  1294.     }
  1295.     return total * 0.5f;
  1296. }
  1297.  
  1298. /*
  1299. ============
  1300. idTraceModel::GetOrderedSilhouetteEdges
  1301. ============
  1302. */
  1303. int idTraceModel::GetOrderedSilhouetteEdges( const int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1], int silEdges[MAX_TRACEMODEL_EDGES] ) const {
  1304.     int i, j, edgeNum, numSilEdges, nextSilVert;
  1305.     int unsortedSilEdges[MAX_TRACEMODEL_EDGES+1];
  1306.  
  1307.     numSilEdges = 0;
  1308.     for ( i = 1; i <= numEdges; i++ ) {
  1309.         if ( edgeIsSilEdge[i] ) {
  1310.             unsortedSilEdges[numSilEdges++] = i;
  1311.         }
  1312.     }
  1313.  
  1314.     silEdges[0] = unsortedSilEdges[0];
  1315.     unsortedSilEdges[0] = -1;
  1316.     nextSilVert = edges[silEdges[0]].v[0];
  1317.     for ( i = 1; i < numSilEdges; i++ ) {
  1318.         for ( j = 1; j < numSilEdges; j++ ) {
  1319.             edgeNum = unsortedSilEdges[j];
  1320.             if ( edgeNum >= 0 ) {
  1321.                 if ( edges[edgeNum].v[0] == nextSilVert ) {
  1322.                     nextSilVert = edges[edgeNum].v[1];
  1323.                     silEdges[i] = edgeNum;
  1324.                     break;
  1325.                 }
  1326.                 if ( edges[edgeNum].v[1] == nextSilVert ) {
  1327.                     nextSilVert = edges[edgeNum].v[0];
  1328.                     silEdges[i] = -edgeNum;
  1329.                     break;
  1330.                 }
  1331.             }
  1332.         }
  1333.         if ( j >= numSilEdges ) {
  1334.             silEdges[i] = 1;    // shouldn't happen
  1335.         }
  1336.         unsortedSilEdges[j] = -1;
  1337.     }
  1338.     return numSilEdges;
  1339. }
  1340.  
  1341. /*
  1342. ============
  1343. idTraceModel::GetProjectionSilhouetteEdges
  1344. ============
  1345. */
  1346. int idTraceModel::GetProjectionSilhouetteEdges( const idVec3 &projectionOrigin, int silEdges[MAX_TRACEMODEL_EDGES] ) const {
  1347.     int i, j, edgeNum;
  1348.     int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1];
  1349.     const traceModelPoly_t *poly;
  1350.     idVec3 dir;
  1351.  
  1352.     memset( edgeIsSilEdge, 0, sizeof( edgeIsSilEdge ) );
  1353.  
  1354.     for ( i = 0; i < numPolys; i++ ) {
  1355.         poly = &polys[i];
  1356.         edgeNum = poly->edges[0];
  1357.         dir = verts[ edges[abs(edgeNum)].v[ INTSIGNBITSET(edgeNum) ] ] - projectionOrigin;
  1358.         if ( dir * poly->normal < 0.0f ) {
  1359.             for ( j = 0; j < poly->numEdges; j++ ) {
  1360.                 edgeNum = poly->edges[j];
  1361.                 edgeIsSilEdge[abs(edgeNum)] ^= 1;
  1362.             }
  1363.         }
  1364.     }
  1365.  
  1366.     return GetOrderedSilhouetteEdges( edgeIsSilEdge, silEdges );
  1367. }
  1368.  
  1369. /*
  1370. ============
  1371. idTraceModel::GetParallelProjectionSilhouetteEdges
  1372. ============
  1373. */
  1374. int idTraceModel::GetParallelProjectionSilhouetteEdges( const idVec3 &projectionDir, int silEdges[MAX_TRACEMODEL_EDGES] ) const {
  1375.     int i, j, edgeNum;
  1376.     int edgeIsSilEdge[MAX_TRACEMODEL_EDGES+1];
  1377.     const traceModelPoly_t *poly;
  1378.  
  1379.     memset( edgeIsSilEdge, 0, sizeof( edgeIsSilEdge ) );
  1380.  
  1381.     for ( i = 0; i < numPolys; i++ ) {
  1382.         poly = &polys[i];
  1383.         if ( projectionDir * poly->normal < 0.0f ) {
  1384.             for ( j = 0; j < poly->numEdges; j++ ) {
  1385.                 edgeNum = poly->edges[j];
  1386.                 edgeIsSilEdge[abs(edgeNum)] ^= 1;
  1387.             }
  1388.         }
  1389.     }
  1390.  
  1391.     return GetOrderedSilhouetteEdges( edgeIsSilEdge, silEdges );
  1392. }
  1393.  
  1394.  
  1395. /*
  1396.  
  1397.   credits to Brian Mirtich for his paper "Fast and Accurate Computation of Polyhedral Mass Properties"
  1398.  
  1399. */
  1400.  
  1401. struct projectionIntegrals_t {
  1402.     float P1;
  1403.     float Pa, Pb;
  1404.     float Paa, Pab, Pbb;
  1405.     float Paaa, Paab, Pabb, Pbbb;
  1406. };
  1407.  
  1408. /*
  1409. ============
  1410. idTraceModel::ProjectionIntegrals
  1411. ============
  1412. */
  1413. void idTraceModel::ProjectionIntegrals( int polyNum, int a, int b, projectionIntegrals_t &integrals ) const {
  1414.     const traceModelPoly_t *poly;
  1415.     int i, edgeNum;
  1416.     idVec3 v1, v2;
  1417.     float a0, a1, da;
  1418.     float b0, b1, db;
  1419.     float a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
  1420.     float a1_2, a1_3, b1_2, b1_3;
  1421.     float C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
  1422.     float Cab, Kab, Caab, Kaab, Cabb, Kabb;
  1423.  
  1424.     memset(&integrals, 0, sizeof(projectionIntegrals_t));
  1425.     poly = &polys[polyNum];
  1426.     for ( i = 0; i < poly->numEdges; i++ ) {
  1427.         edgeNum = poly->edges[i];
  1428.         v1 = verts[ edges[ abs(edgeNum) ].v[ edgeNum < 0 ] ];
  1429.         v2 = verts[ edges[ abs(edgeNum) ].v[ edgeNum > 0 ] ];
  1430.         a0 = v1[a];
  1431.         b0 = v1[b];
  1432.         a1 = v2[a];
  1433.         b1 = v2[b];
  1434.         da = a1 - a0;
  1435.         db = b1 - b0;
  1436.         a0_2 = a0 * a0;
  1437.         a0_3 = a0_2 * a0;
  1438.         a0_4 = a0_3 * a0;
  1439.         b0_2 = b0 * b0;
  1440.         b0_3 = b0_2 * b0;
  1441.         b0_4 = b0_3 * b0;
  1442.         a1_2 = a1 * a1;
  1443.         a1_3 = a1_2 * a1; 
  1444.         b1_2 = b1 * b1;
  1445.         b1_3 = b1_2 * b1;
  1446.  
  1447.         C1 = a1 + a0;
  1448.         Ca = a1 * C1 + a0_2;
  1449.         Caa = a1 * Ca + a0_3;
  1450.         Caaa = a1 * Caa + a0_4;
  1451.         Cb = b1 * (b1 + b0) + b0_2;
  1452.         Cbb = b1 * Cb + b0_3;
  1453.         Cbbb = b1 * Cbb + b0_4;
  1454.         Cab = 3 * a1_2 + 2 * a1 * a0 + a0_2;
  1455.         Kab = a1_2 + 2 * a1 * a0 + 3 * a0_2;
  1456.         Caab = a0 * Cab + 4 * a1_3;
  1457.         Kaab = a1 * Kab + 4 * a0_3;
  1458.         Cabb = 4 * b1_3 + 3 * b1_2 * b0 + 2 * b1 * b0_2 + b0_3;
  1459.         Kabb = b1_3 + 2 * b1_2 * b0 + 3 * b1 * b0_2 + 4 * b0_3;
  1460.  
  1461.         integrals.P1 += db * C1;
  1462.         integrals.Pa += db * Ca;
  1463.         integrals.Paa += db * Caa;
  1464.         integrals.Paaa += db * Caaa;
  1465.         integrals.Pb += da * Cb;
  1466.         integrals.Pbb += da * Cbb;
  1467.         integrals.Pbbb += da * Cbbb;
  1468.         integrals.Pab += db * (b1 * Cab + b0 * Kab);
  1469.         integrals.Paab += db * (b1 * Caab + b0 * Kaab);
  1470.         integrals.Pabb += da * (a1 * Cabb + a0 * Kabb);
  1471.     }
  1472.  
  1473.     integrals.P1 *= (1.0f / 2.0f);
  1474.     integrals.Pa *= (1.0f / 6.0f);
  1475.     integrals.Paa *= (1.0f / 12.0f);
  1476.     integrals.Paaa *= (1.0f / 20.0f);
  1477.     integrals.Pb *= (1.0f / -6.0f);
  1478.     integrals.Pbb *= (1.0f / -12.0f);
  1479.     integrals.Pbbb *= (1.0f / -20.0f);
  1480.     integrals.Pab *= (1.0f / 24.0f);
  1481.     integrals.Paab *= (1.0f / 60.0f);
  1482.     integrals.Pabb *= (1.0f / -60.0f);
  1483. }
  1484.  
  1485. struct polygonIntegrals_t {
  1486.     float Fa, Fb, Fc;
  1487.     float Faa, Fbb, Fcc;
  1488.     float Faaa, Fbbb, Fccc;
  1489.     float Faab, Fbbc, Fcca;
  1490. };
  1491.  
  1492. /*
  1493. ============
  1494. idTraceModel::PolygonIntegrals
  1495. ============
  1496. */
  1497. void idTraceModel::PolygonIntegrals( int polyNum, int a, int b, int c, polygonIntegrals_t &integrals ) const {
  1498.     projectionIntegrals_t pi;
  1499.     idVec3 n;
  1500.     float w;
  1501.     float k1, k2, k3, k4;
  1502.  
  1503.     ProjectionIntegrals( polyNum, a, b, pi );
  1504.  
  1505.     n = polys[polyNum].normal;
  1506.     w = -polys[polyNum].dist;
  1507.     k1 = 1 / n[c];
  1508.     k2 = k1 * k1;
  1509.     k3 = k2 * k1;
  1510.     k4 = k3 * k1;
  1511.  
  1512.     integrals.Fa = k1 * pi.Pa;
  1513.     integrals.Fb = k1 * pi.Pb;
  1514.     integrals.Fc = -k2 * (n[a] * pi.Pa + n[b] * pi.Pb + w * pi.P1);
  1515.  
  1516.     integrals.Faa = k1 * pi.Paa;
  1517.     integrals.Fbb = k1 * pi.Pbb;
  1518.     integrals.Fcc = k3 * (Square(n[a]) * pi.Paa + 2 * n[a] * n[b] * pi.Pab + Square(n[b]) * pi.Pbb
  1519.             + w * (2 * (n[a] * pi.Pa + n[b] * pi.Pb) + w * pi.P1));
  1520.  
  1521.     integrals.Faaa = k1 * pi.Paaa;
  1522.     integrals.Fbbb = k1 * pi.Pbbb;
  1523.     integrals.Fccc = -k4 * (Cube(n[a]) * pi.Paaa + 3 * Square(n[a]) * n[b] * pi.Paab 
  1524.             + 3 * n[a] * Square(n[b]) * pi.Pabb + Cube(n[b]) * pi.Pbbb
  1525.             + 3 * w * (Square(n[a]) * pi.Paa + 2 * n[a] * n[b] * pi.Pab + Square(n[b]) * pi.Pbb)
  1526.             + w * w * (3 * (n[a] * pi.Pa + n[b] * pi.Pb) + w * pi.P1));
  1527.  
  1528.     integrals.Faab = k1 * pi.Paab;
  1529.     integrals.Fbbc = -k2 * (n[a] * pi.Pabb + n[b] * pi.Pbbb + w * pi.Pbb);
  1530.     integrals.Fcca = k3 * (Square(n[a]) * pi.Paaa + 2 * n[a] * n[b] * pi.Paab + Square(n[b]) * pi.Pabb
  1531.             + w * (2 * (n[a] * pi.Paa + n[b] * pi.Pab) + w * pi.Pa));
  1532. }
  1533.  
  1534. struct volumeIntegrals_t {
  1535.     float T0;
  1536.     idVec3 T1;
  1537.     idVec3 T2;
  1538.     idVec3 TP;
  1539. };
  1540.  
  1541. /*
  1542. ============
  1543. idTraceModel::VolumeIntegrals
  1544. ============
  1545. */
  1546. void idTraceModel::VolumeIntegrals( volumeIntegrals_t &integrals ) const {
  1547.     const traceModelPoly_t *poly;
  1548.     polygonIntegrals_t pi;
  1549.     int i, a, b, c;
  1550.     float nx, ny, nz;
  1551.  
  1552.     memset( &integrals, 0, sizeof(volumeIntegrals_t) );
  1553.     for ( i = 0; i < numPolys; i++ ) {
  1554.         poly = &polys[i];
  1555.  
  1556.         nx = idMath::Fabs( poly->normal[0] );
  1557.         ny = idMath::Fabs( poly->normal[1] );
  1558.         nz = idMath::Fabs( poly->normal[2] );
  1559.         if ( nx > ny && nx > nz ) {
  1560.             c = 0;
  1561.         }
  1562.         else {
  1563.             c = (ny > nz) ? 1 : 2;
  1564.         }
  1565.         a = (c + 1) % 3;
  1566.         b = (a + 1) % 3;
  1567.  
  1568.         PolygonIntegrals( i, a, b, c, pi );
  1569.  
  1570.         integrals.T0 += poly->normal[0] * ((a == 0) ? pi.Fa : ((b == 0) ? pi.Fb : pi.Fc));
  1571.  
  1572.         integrals.T1[a] += poly->normal[a] * pi.Faa;
  1573.         integrals.T1[b] += poly->normal[b] * pi.Fbb;
  1574.         integrals.T1[c] += poly->normal[c] * pi.Fcc;
  1575.         integrals.T2[a] += poly->normal[a] * pi.Faaa;
  1576.         integrals.T2[b] += poly->normal[b] * pi.Fbbb;
  1577.         integrals.T2[c] += poly->normal[c] * pi.Fccc;
  1578.         integrals.TP[a] += poly->normal[a] * pi.Faab;
  1579.         integrals.TP[b] += poly->normal[b] * pi.Fbbc;
  1580.         integrals.TP[c] += poly->normal[c] * pi.Fcca;
  1581.     }
  1582.  
  1583.     integrals.T1 *= 0.5f;
  1584.     integrals.T2 *= (1.0f / 3.0f);
  1585.     integrals.TP *= 0.5f;
  1586. }
  1587.  
  1588. /*
  1589. ============
  1590. idTraceModel::GetMassProperties
  1591. ============
  1592. */
  1593. void idTraceModel::GetMassProperties( const float density, float &mass, idVec3 ¢erOfMass, idMat3 &inertiaTensor ) const {
  1594.     volumeIntegrals_t integrals;
  1595.  
  1596.     // if polygon trace model
  1597.     if ( type == TRM_POLYGON ) {
  1598.         idTraceModel trm;
  1599.  
  1600.         VolumeFromPolygon( trm, 1.0f );
  1601.         trm.GetMassProperties( density, mass, centerOfMass, inertiaTensor );
  1602.         return;
  1603.     }
  1604.  
  1605.     VolumeIntegrals( integrals );
  1606.  
  1607.     // if no volume
  1608.     if ( integrals.T0 == 0.0f ) {
  1609.         mass = 1.0f;
  1610.         centerOfMass.Zero();
  1611.         inertiaTensor.Identity();
  1612.         return;
  1613.     }
  1614.  
  1615.     // mass of model
  1616.     mass = density * integrals.T0;
  1617.     // center of mass
  1618.     centerOfMass = integrals.T1 / integrals.T0;
  1619.     // compute inertia tensor
  1620.     inertiaTensor[0][0] = density * (integrals.T2[1] + integrals.T2[2]);
  1621.     inertiaTensor[1][1] = density * (integrals.T2[2] + integrals.T2[0]);
  1622.     inertiaTensor[2][2] = density * (integrals.T2[0] + integrals.T2[1]);
  1623.     inertiaTensor[0][1] = inertiaTensor[1][0] = - density * integrals.TP[0];
  1624.     inertiaTensor[1][2] = inertiaTensor[2][1] = - density * integrals.TP[1];
  1625.     inertiaTensor[2][0] = inertiaTensor[0][2] = - density * integrals.TP[2];
  1626.     // translate inertia tensor to center of mass
  1627.     inertiaTensor[0][0] -= mass * (centerOfMass[1]*centerOfMass[1] + centerOfMass[2]*centerOfMass[2]);
  1628.     inertiaTensor[1][1] -= mass * (centerOfMass[2]*centerOfMass[2] + centerOfMass[0]*centerOfMass[0]);
  1629.     inertiaTensor[2][2] -= mass * (centerOfMass[0]*centerOfMass[0] + centerOfMass[1]*centerOfMass[1]);
  1630.     inertiaTensor[0][1] = inertiaTensor[1][0] += mass * centerOfMass[0] * centerOfMass[1];
  1631.     inertiaTensor[1][2] = inertiaTensor[2][1] += mass * centerOfMass[1] * centerOfMass[2];
  1632.     inertiaTensor[2][0] = inertiaTensor[0][2] += mass * centerOfMass[2] * centerOfMass[0];
  1633. }
  1634.