BOOL sTrimeshCapsuleColliderData::_cldTestSeparatingAxesOfCapsule(
											const dVector3 &v0,
											const dVector3 &v1,
											const dVector3 &v2,
											uint8 flags) 
{
	// calculate caps centers in absolute space
	dVector3 vCp0;
	vCp0[0] = m_vCapsulePosition[0] + m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
	vCp0[1] = m_vCapsulePosition[1] + m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
	vCp0[2] = m_vCapsulePosition[2] + m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);

	dVector3 vCp1;
	vCp1[0] = m_vCapsulePosition[0] - m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
	vCp1[1] = m_vCapsulePosition[1] - m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
	vCp1[2] = m_vCapsulePosition[2] - m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);

	// reset best axis
	m_iBestAxis = 0;
	// reset best depth
	m_fBestDepth  = -MAX_REAL;
	// reset separating axis vector
	dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)};

	// Epsilon value for checking axis vector length 
	const dReal fEpsilon = 1e-6f;

	// Translate triangle to Cc cord.
	SUBTRACT(v0, m_vCapsulePosition, m_vV0);
	SUBTRACT(v1, m_vCapsulePosition, m_vV1);
	SUBTRACT(v2, m_vCapsulePosition, m_vV2);

	// We begin to test for 19 separating axis now
	// I wonder does it help if we employ the method like ISA-GJK???
	// Or at least we should do experiment and find what axis will
	// be most likely to be separating axis to check it first.

	// Original
	// axis m_vN
	//vAxis = -m_vN;
	vAxis[0] = - m_vN[0];
	vAxis[1] = - m_vN[1];
	vAxis[2] = - m_vN[2];
	if (!_cldTestAxis(v0, v1, v2, vAxis, 1, TRUE)) 
	{ 
		return FALSE; 
	}

	if (flags & dxTriMeshData::kEdge0)
	{
		// axis CxE0 - Edge 0
		dCROSS(vAxis,=,m_vCapsuleAxis,m_vE0);
		//vAxis = dCROSS( m_vCapsuleAxis cross vE0 );
		if (_length2OfVector3( vAxis ) > fEpsilon) {
			if (!_cldTestAxis(v0, v1, v2, vAxis, 2)) { 
				return FALSE;
			}
		}
	}
Пример #2
0
void calculate( void )
{
    int j;

    N4 = N + 4;

    for (j = 0; j < 10*5; ++j) {
        memdiv5[j][0] = j/5;
        memdiv5[j][1] = 10*(j - memdiv5[j][0]*5);
    }

    for (j = 0; j < 10*25; ++j) {
        memdiv25[j][0] = j/25;
        memdiv25[j][1] = 10*(j - memdiv25[j][0]*25);
    }

    for (j = 0; j < 10*239; ++j) {
        memdiv239[j][0] = j/239;
        memdiv239[j][1] = 10*(j - memdiv239[j][0]*239);
    }

    SET( a, 0 );
    SET( b, 0 );

    for( j = 2 * N4 + 1; j >= 3; j -= 2 )
    {
        SET( c, 1 );
        DIVIDE( c, j );

        SUBTRACT( a, c, a );
        DIVIDE25( a );

        SUBTRACT( b, c, b );
        DIVIDE239( b );
        DIVIDE239( b );

        progress();
    }

    SET( c, 1 );

    SUBTRACT( a, c, a );
    DIVIDE5( a );

    SUBTRACT( b, c, b );
    DIVIDE239( b );

    MULTIPLY( a, 4 );
    SUBTRACT( a, a, b );
    MULTIPLY( a, 4 );

    progress();
}
Пример #3
0
inline void MACD(int short_window, int long_window, int smooth_window, dvector &input, dvector &macd, dvector &macd_signal, dvector &macd_hist)
{
	std::vector<double> short_emas;
	std::vector<double> long_emas;
	short_emas.reserve(input.size());
	long_emas.reserve(input.size());
	macd.reserve(input.size());
	macd_signal.reserve(input.size());
	macd_hist.reserve(input.size());
	EMA(short_window,input,short_emas);
	EMA(long_window,input,long_emas);
	SUBTRACT(short_emas,long_emas,macd);
	EMA(smooth_window,macd,macd_signal);
	SUBTRACT(macd,macd_signal,macd_hist);
}
// find two closest points on two lines
static BOOL _cldClosestPointOnTwoLines( dVector3 vPoint1, dVector3 vLenVec1, 
                                        dVector3 vPoint2, dVector3 vLenVec2, 
                                        dReal &fvalue1, dReal &fvalue2) 
{
  // calulate denominator
  dVector3 vp;
  SUBTRACT(vPoint2,vPoint1,vp);
  dReal fuaub  = dDOT(vLenVec1,vLenVec2);
  dReal fq1    = dDOT(vLenVec1,vp);
  dReal fq2    = -dDOT(vLenVec2,vp);
  dReal fd     = 1.0f - fuaub * fuaub;
  
  // if denominator is positive
  if (fd > 0.0f) {
    // calculate points of closest approach
    fd = 1.0f/fd;
    fvalue1 = (fq1 + fuaub*fq2)*fd;
    fvalue2 = (fuaub*fq1 + fq2)*fd;
    return TRUE;
  // otherwise  
  } else {
    // lines are parallel
    fvalue1 = 0.0f;
    fvalue2 = 0.0f;
    return FALSE;
  }

}
// helper for less key strokes
inline void _CalculateAxis(const dVector3& v1,
						   const dVector3& v2,
						   const dVector3& v3,
						   const dVector3& v4,
						   dVector3& r)
{
	dVector3 t1;
	dVector3 t2;

	SUBTRACT(v1,v2,t1);
	dCROSS(t2,=,t1,v3);
	dCROSS(r,=,t2,v4);
}
Пример #6
0
void calculate( void )
{
    int j;

    N4 = N + 4;

    SET( a, 0 );
    SET( b, 0 );

    for( j = 2 * N4 + 1; j >= 3; j -= 2 )
    {
        SET( c, 1 );
        DIVIDE( c, j );
	

        SUBTRACT( a, c, a );
        DIVIDE25(a);//DIVIDE( a, 25 );

        SUBTRACT( b, c, b );
        DIVIDE239(b);//DIVIDE( b, 239 );
        DIVIDE239(b);//DIVIDE( b, 239 );

        progress();
    }

    SET( c, 1 );

    SUBTRACT( a, c, a );
	DIVIDE5(a);	//DIVIDE( a, 5 );

    SUBTRACT( b, c, b );
    DIVIDE239(b);//DIVIDE( b, 239 );

    MULTIPLY( a, 4 );
    SUBTRACT( a, a, b );
    MULTIPLY( a, 4 );

    progress();
}
// clip and generate contacts
static void _cldClipping(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {

  // if we have edge/edge intersection
  if ( iBestAxis > 4 ) {

    dVector3 vub,vPb,vPa;

    SET(vPa,vHullBoxPos);

    // calculate point on box edge
    for( int i=0; i<3; i++) {
      dVector3 vRotCol;
      GETCOL(mHullBoxRot,i,vRotCol);
      dReal fSign = dDOT(vBestNormal,vRotCol) > 0 ? 1.0f : -1.0f;

      vPa[0] += fSign * vBoxHalfSize[i] * vRotCol[0];
      vPa[1] += fSign * vBoxHalfSize[i] * vRotCol[1];
      vPa[2] += fSign * vBoxHalfSize[i] * vRotCol[2];
    }

    int iEdge = (iBestAxis-5)%3;

    // decide which edge is on triangle
    if ( iEdge == 0 ) {
      SET(vPb,v0);
      SET(vub,vE0);
    } else if ( iEdge == 1) {
      SET(vPb,v2);
      SET(vub,vE1);
    } else {
      SET(vPb,v1);
      SET(vub,vE2);
    }
    

    // setup direction parameter for face edge
    dNormalize3(vub);

    dReal fParam1, fParam2;

    // setup direction parameter for box edge
    dVector3 vua;
    int col=(iBestAxis-5)/3;
    GETCOL(mHullBoxRot,col,vua);

    // find two closest points on both edges
    _cldClosestPointOnTwoLines( vPa, vua, vPb, vub, fParam1, fParam2 );
    vPa[0] += vua[0]*fParam1;
    vPa[1] += vua[1]*fParam1;
    vPa[2] += vua[2]*fParam1;

    vPb[0] += vub[0]*fParam2; 
    vPb[1] += vub[1]*fParam2; 
    vPb[2] += vub[2]*fParam2; 

    // calculate collision point
    dVector3 vPntTmp;
    ADD(vPa,vPb,vPntTmp);

    vPntTmp[0]*=0.5f;
    vPntTmp[1]*=0.5f;
    vPntTmp[2]*=0.5f;

    // generate contact point between two closest points
#ifdef ORIG
    if (ctContacts < (iFlags & 0x0ffff)) {
    dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);
    Contact->depth = fBestDepth;
    SET(Contact->normal,vBestNormal);
    SET(Contact->pos,vPntTmp);
    Contact->g1 = Geom1;
    Contact->g2 = Geom2;
    ctContacts++;
    }
#endif
    GenerateContact(iFlags, ContactGeoms, iStride,  Geom1, Geom2,
                    vPntTmp, vBestNormal, fBestDepth, ctContacts);



  // if triangle is the referent face then clip box to triangle face
  } else if ( iBestAxis == 1 ) {
    
    
    dVector3 vNormal2;
    vNormal2[0]=-vBestNormal[0];
    vNormal2[1]=-vBestNormal[1];
    vNormal2[2]=-vBestNormal[2];

    
    // vNr is normal in box frame, pointing from triangle to box
    dMatrix3 mTransposed;
    mTransposed[0*4+0]=mHullBoxRot[0*4+0];
    mTransposed[0*4+1]=mHullBoxRot[1*4+0];
    mTransposed[0*4+2]=mHullBoxRot[2*4+0];

    mTransposed[1*4+0]=mHullBoxRot[0*4+1];
    mTransposed[1*4+1]=mHullBoxRot[1*4+1];
    mTransposed[1*4+2]=mHullBoxRot[2*4+1];

    mTransposed[2*4+0]=mHullBoxRot[0*4+2];
    mTransposed[2*4+1]=mHullBoxRot[1*4+2];
    mTransposed[2*4+2]=mHullBoxRot[2*4+2];

    dVector3 vNr;
    vNr[0]=mTransposed[0*4+0]*vNormal2[0]+  mTransposed[0*4+1]*vNormal2[1]+  mTransposed[0*4+2]*vNormal2[2];
    vNr[1]=mTransposed[1*4+0]*vNormal2[0]+  mTransposed[1*4+1]*vNormal2[1]+  mTransposed[1*4+2]*vNormal2[2];
    vNr[2]=mTransposed[2*4+0]*vNormal2[0]+  mTransposed[2*4+1]*vNormal2[1]+  mTransposed[2*4+2]*vNormal2[2];
  

    dVector3 vAbsNormal;
    vAbsNormal[0] = dFabs( vNr[0] );
    vAbsNormal[1] = dFabs( vNr[1] );
    vAbsNormal[2] = dFabs( vNr[2] );

    // get closest face from box
    int iB0, iB1, iB2;
    if (vAbsNormal[1] > vAbsNormal[0]) {
      if (vAbsNormal[1] > vAbsNormal[2]) {
        iB1 = 0;  iB0 = 1;  iB2 = 2;
      } else {
        iB1 = 0;  iB2 = 1;  iB0 = 2;
      }
    } else {

      if (vAbsNormal[0] > vAbsNormal[2]) {
        iB0 = 0;  iB1 = 1;  iB2 = 2;
      } else {
        iB1 = 0;  iB2 = 1;  iB0 = 2;
      }
    }

    // Here find center of box face we are going to project
    dVector3 vCenter;
    dVector3 vRotCol;
    GETCOL(mHullBoxRot,iB0,vRotCol);
    
    if (vNr[iB0] > 0) {
        vCenter[0] = vHullBoxPos[0] - v0[0] - vBoxHalfSize[iB0] * vRotCol[0];
      vCenter[1] = vHullBoxPos[1] - v0[1] - vBoxHalfSize[iB0] * vRotCol[1];
      vCenter[2] = vHullBoxPos[2] - v0[2] - vBoxHalfSize[iB0] * vRotCol[2];
    } else {
      vCenter[0] = vHullBoxPos[0] - v0[0] + vBoxHalfSize[iB0] * vRotCol[0];
      vCenter[1] = vHullBoxPos[1] - v0[1] + vBoxHalfSize[iB0] * vRotCol[1];
      vCenter[2] = vHullBoxPos[2] - v0[2] + vBoxHalfSize[iB0] * vRotCol[2];
    }  

    // Here find 4 corner points of box
    dVector3 avPoints[4];

    dVector3 vRotCol2;
    GETCOL(mHullBoxRot,iB1,vRotCol);
    GETCOL(mHullBoxRot,iB2,vRotCol2);

    for(int x=0;x<3;x++) {
        avPoints[0][x] = vCenter[x] + (vBoxHalfSize[iB1] * vRotCol[x]) - (vBoxHalfSize[iB2] * vRotCol2[x]);
        avPoints[1][x] = vCenter[x] - (vBoxHalfSize[iB1] * vRotCol[x]) - (vBoxHalfSize[iB2] * vRotCol2[x]);
        avPoints[2][x] = vCenter[x] - (vBoxHalfSize[iB1] * vRotCol[x]) + (vBoxHalfSize[iB2] * vRotCol2[x]);
        avPoints[3][x] = vCenter[x] + (vBoxHalfSize[iB1] * vRotCol[x]) + (vBoxHalfSize[iB2] * vRotCol2[x]);
    }


    // clip Box face with 4 planes of triangle (1 face plane, 3 egde planes)
    dVector3 avTempArray1[9];
    dVector3 avTempArray2[9];
    dVector4 plPlane;

    int iTempCnt1=0;
    int iTempCnt2=0;

    // zeroify vectors - necessary?
    for(int i=0; i<9; i++) {
      avTempArray1[i][0]=0;
      avTempArray1[i][1]=0;
      avTempArray1[i][2]=0;

      avTempArray2[i][0]=0;
      avTempArray2[i][1]=0;
      avTempArray2[i][2]=0;
    }


    // Normal plane
    dVector3 vTemp;
    vTemp[0]=-vN[0];
    vTemp[1]=-vN[1];
    vTemp[2]=-vN[2];
    dNormalize3(vTemp);
    CONSTRUCTPLANE(plPlane,vTemp,0);

    _cldClipPolyToPlane( avPoints, 4, avTempArray1, iTempCnt1, plPlane  );
    

    // Plane p0
    dVector3 vTemp2;
    SUBTRACT(v1,v0,vTemp2);
    dCROSS(vTemp,=,vN,vTemp2);
    dNormalize3(vTemp);
    CONSTRUCTPLANE(plPlane,vTemp,0);

    _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane  );


    // Plane p1
    SUBTRACT(v2,v1,vTemp2);
    dCROSS(vTemp,=,vN,vTemp2);
    dNormalize3(vTemp);
    SUBTRACT(v0,v2,vTemp2);
    CONSTRUCTPLANE(plPlane,vTemp,dDOT(vTemp2,vTemp));

    _cldClipPolyToPlane( avTempArray2, iTempCnt2, avTempArray1, iTempCnt1, plPlane  );


    // Plane p2
    SUBTRACT(v0,v2,vTemp2);
    dCROSS(vTemp,=,vN,vTemp2);
    dNormalize3(vTemp);
    CONSTRUCTPLANE(plPlane,vTemp,0);

    _cldClipPolyToPlane( avTempArray1, iTempCnt1, avTempArray2, iTempCnt2, plPlane  );


    // END of clipping polygons



    // for each generated contact point
    for ( int i=0; i<iTempCnt2; i++ ) {
      // calculate depth
      dReal fTempDepth = dDOT(vNormal2,avTempArray2[i]);

      // clamp depth to zero
      if (fTempDepth > 0) {
        fTempDepth = 0;
      }

      dVector3 vPntTmp;
      ADD(avTempArray2[i],v0,vPntTmp);

#ifdef ORIG
    if (ctContacts < (iFlags & 0x0ffff)) {
          dContactGeom* Contact = SAFECONTACT(iFlags, ContactGeoms, ctContacts, iStride);

          Contact->depth = -fTempDepth;
          SET(Contact->normal,vBestNormal);
          SET(Contact->pos,vPntTmp);
          Contact->g1 = Geom1;
          Contact->g2 = Geom2;
          ctContacts++;
    }
#endif
    GenerateContact(iFlags, ContactGeoms, iStride,  Geom1, Geom2,
                    vPntTmp, vBestNormal, -fTempDepth, ctContacts);
    }

    //dAASSERT(ctContacts>0);

  // if box face is the referent face, then clip triangle on box face
  } else { // 2 <= if iBestAxis <= 4
static BOOL _cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {
  // reset best axis
  iBestAxis = 0;
  iExitAxis = -1;
  fBestDepth = MAXVALUE;

  // calculate edges
  SUBTRACT(v1,v0,vE0);
  SUBTRACT(v2,v0,vE1);
  SUBTRACT(vE1,vE0,vE2);

  // calculate poly normal
  dCROSS(vN,=,vE0,vE1);

  // extract box axes as vectors
  dVector3 vA0,vA1,vA2;
  GETCOL(mHullBoxRot,0,vA0);
  GETCOL(mHullBoxRot,1,vA1);
  GETCOL(mHullBoxRot,2,vA2);

  // box halfsizes
  dReal fa0 = vBoxHalfSize[0];
  dReal fa1 = vBoxHalfSize[1];
  dReal fa2 = vBoxHalfSize[2];

  // calculate relative position between box and triangle
  dVector3 vD;
  SUBTRACT(v0,vHullBoxPos,vD);

  // calculate length of face normal
  dReal fNLen = LENGTHOF( vN );

  dVector3 vL;
  dReal fp0, fp1, fp2, fR, fD;

  // Test separating axes for intersection
  // ************************************************
  // Axis 1 - Triangle Normal 
  SET(vL,vN);
  fp0  = dDOT(vL,vD);
  fp1  = fp0;
  fp2  = fp0;
  fR=fa0*dFabs( dDOT(vN,vA0) ) + fa1 * dFabs( dDOT(vN,vA1) ) + fa2 * dFabs( dDOT(vN,vA2) );


  if( !_cldTestNormal( fp0, fR, vL, 1) ) { 
    iExitAxis=1;
    return FALSE; 
  } 
 
  // ************************************************

  // Test Faces
  // ************************************************
  // Axis 2 - Box X-Axis
  SET(vL,vA0);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 + dDOT(vA0,vE0);
  fp2 = fp0 + dDOT(vA0,vE1);
  fR  = fa0;


  if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 2) ) { 
    iExitAxis=2;
    return FALSE; 
  }
  // ************************************************

  // ************************************************
  // Axis 3 - Box Y-Axis
  SET(vL,vA1);
  fD = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 + dDOT(vA1,vE0);
  fp2 = fp0 + dDOT(vA1,vE1);
  fR  = fa1;


  if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 3) ) { 
    iExitAxis=3;
    return FALSE; 
  }

  // ************************************************

  // ************************************************
  // Axis 4 - Box Z-Axis
  SET(vL,vA2);
  fD = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 + dDOT(vA2,vE0);
  fp2 = fp0 + dDOT(vA2,vE1);
  fR  = fa2;


  if( !_cldTestFace( fp0, fp1, fp2, fR, fD, vL, 4) ) { 
    iExitAxis=4;
    return FALSE; 
  }

  // ************************************************

  // Test Edges
  // ************************************************
  // Axis 5 - Box X-Axis cross Edge0
  dCROSS(vL,=,vA0,vE0);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0;
  fp2 = fp0 + dDOT(vA0,vN);
  fR  = fa1 * dFabs(dDOT(vA2,vE0)) + fa2 * dFabs(dDOT(vA1,vE0));


  if( !_cldTestEdge( fp1, fp2, fR, fD, vL, 5) ) { 
    iExitAxis=5;
    return FALSE; 
  }
  // ************************************************

  // ************************************************
  // Axis 6 - Box X-Axis cross Edge1
  dCROSS(vL,=,vA0,vE1);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA0,vN);
  fp2 = fp0;
  fR  = fa1 * dFabs(dDOT(vA2,vE1)) + fa2 * dFabs(dDOT(vA1,vE1));


  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 6) ) { 
    iExitAxis=6;
    return FALSE; 
  }
  // ************************************************

  // ************************************************
  // Axis 7 - Box X-Axis cross Edge2
  dCROSS(vL,=,vA0,vE2);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA0,vN);
  fp2 = fp0 - dDOT(vA0,vN);
  fR  = fa1 * dFabs(dDOT(vA2,vE2)) + fa2 * dFabs(dDOT(vA1,vE2));


  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 7) ) { 
    iExitAxis=7;
    return FALSE; 
  }

  // ************************************************

  // ************************************************
  // Axis 8 - Box Y-Axis cross Edge0
  dCROSS(vL,=,vA1,vE0);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0;
  fp2 = fp0 + dDOT(vA1,vN);
  fR  = fa0 * dFabs(dDOT(vA2,vE0)) + fa2 * dFabs(dDOT(vA0,vE0));


  if( !_cldTestEdge( fp0, fp2, fR, fD, vL, 8) ) { 
    iExitAxis=8;
    return FALSE; 
  }

  // ************************************************

  // ************************************************
  // Axis 9 - Box Y-Axis cross Edge1
  dCROSS(vL,=,vA1,vE1);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA1,vN);
  fp2 = fp0;
  fR  = fa0 * dFabs(dDOT(vA2,vE1)) + fa2 * dFabs(dDOT(vA0,vE1));


  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 9) ) { 
    iExitAxis=9;
    return FALSE; 
  }

  // ************************************************

  // ************************************************
  // Axis 10 - Box Y-Axis cross Edge2
  dCROSS(vL,=,vA1,vE2);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA1,vN);
  fp2 = fp0 - dDOT(vA1,vN);
  fR  = fa0 * dFabs(dDOT(vA2,vE2)) + fa2 * dFabs(dDOT(vA0,vE2));


  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 10) ) { 
    iExitAxis=10;
    return FALSE; 
  }

  // ************************************************

  // ************************************************
  // Axis 11 - Box Z-Axis cross Edge0
  dCROSS(vL,=,vA2,vE0);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0;
  fp2 = fp0 + dDOT(vA2,vN);
  fR  = fa0 * dFabs(dDOT(vA1,vE0)) + fa1 * dFabs(dDOT(vA0,vE0));


  if( !_cldTestEdge( fp0, fp2, fR, fD, vL, 11) ) { 
    iExitAxis=11;
    return FALSE; 
  }
  // ************************************************

  // ************************************************
  // Axis 12 - Box Z-Axis cross Edge1
  dCROSS(vL,=,vA2,vE1);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA2,vN);
  fp2 = fp0;
  fR  = fa0 * dFabs(dDOT(vA1,vE1)) + fa1 * dFabs(dDOT(vA0,vE1));


  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 12) ) { 
    iExitAxis=12;
    return FALSE; 
  }
  // ************************************************

  // ************************************************
  // Axis 13 - Box Z-Axis cross Edge2
  dCROSS(vL,=,vA2,vE2);
  fD  = dDOT(vL,vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA2,vN);
  fp2 = fp0 - dDOT(vA2,vN);
  fR  = fa0 * dFabs(dDOT(vA1,vE2)) + fa1 * dFabs(dDOT(vA0,vE2));


  if( !_cldTestEdge( fp0, fp1, fR, fD, vL, 13) ) { 
    iExitAxis=13;
    return FALSE; 
  }
 
  // ************************************************
  return TRUE; 
}
// test one mesh triangle on intersection with capsule
void sTrimeshCapsuleColliderData::_cldTestOneTriangleVSCapsule(
    const dVector3 &v0, const dVector3 &v1, const dVector3 &v2,
    uint8 flags)
{
    // calculate edges
    SUBTRACT(v1,v0,m_vE0);
    SUBTRACT(v2,v1,m_vE1);
    SUBTRACT(v0,v2,m_vE2);

    dVector3	_minus_vE0;
    SUBTRACT(v0,v1,_minus_vE0);

    // calculate poly normal
    dCalcVectorCross3(m_vN,m_vE1,_minus_vE0);

    // Even though all triangles might be initially valid, 
    // a triangle may degenerate into a segment after applying 
    // space transformation.
    if (!dSafeNormalize3(m_vN))
    {
        return;
    }

    // create plane from triangle
    dReal plDistance = -dCalcVectorDot3(v0,m_vN);
    dVector4 plTrianglePlane;
    CONSTRUCTPLANE(plTrianglePlane,m_vN,plDistance);

    // calculate capsule distance to plane
    dReal fDistanceCapsuleCenterToPlane = POINTDISTANCE(plTrianglePlane,m_vCapsulePosition);

    // Capsule must be over positive side of triangle
    if (fDistanceCapsuleCenterToPlane < 0 /* && !bDoubleSided*/) 
    {
        // if not don't generate contacts
        return;
    }

    dVector3 vPnt0;
    SET	(vPnt0,v0);
    dVector3 vPnt1;
    SET	(vPnt1,v1);
    dVector3 vPnt2;
    SET	(vPnt2,v2);

    if (fDistanceCapsuleCenterToPlane < 0 )
    {
        SET	(vPnt0,v0);
        SET	(vPnt1,v2);
        SET	(vPnt2,v1);
    }

    // do intersection test and find best separating axis
    if (!_cldTestSeparatingAxesOfCapsule(vPnt0, vPnt1, vPnt2, flags))
    {
        // if not found do nothing
        return;
    }

    // if best separation axis is not found
    if (m_iBestAxis == 0 ) 
    {
        // this should not happen (we should already exit in that case)
        dIASSERT(FALSE);
        // do nothing
        return;
    }

    // calculate caps centers in absolute space
    dVector3 vCposTrans;
    vCposTrans[0] = m_vCapsulePosition[0] + m_vNormal[0]*m_vCapsuleRadius;
    vCposTrans[1] = m_vCapsulePosition[1] + m_vNormal[1]*m_vCapsuleRadius;
    vCposTrans[2] = m_vCapsulePosition[2] + m_vNormal[2]*m_vCapsuleRadius;

    dVector3 vCEdgePoint0;
    vCEdgePoint0[0]  = vCposTrans[0] + m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCEdgePoint0[1]  = vCposTrans[1] + m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCEdgePoint0[2]  = vCposTrans[2] + m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);

    dVector3 vCEdgePoint1;
    vCEdgePoint1[0] = vCposTrans[0] - m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCEdgePoint1[1] = vCposTrans[1] - m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCEdgePoint1[2] = vCposTrans[2] - m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);

    // transform capsule edge points into triangle space
    vCEdgePoint0[0] -= vPnt0[0];
    vCEdgePoint0[1] -= vPnt0[1];
    vCEdgePoint0[2] -= vPnt0[2];

    vCEdgePoint1[0] -= vPnt0[0];
    vCEdgePoint1[1] -= vPnt0[1];
    vCEdgePoint1[2] -= vPnt0[2];

    dVector4 plPlane;
    dVector3 _minus_vN;
    _minus_vN[0] = -m_vN[0];
    _minus_vN[1] = -m_vN[1];
    _minus_vN[2] = -m_vN[2];
    // triangle plane
    CONSTRUCTPLANE(plPlane,_minus_vN,0);
    //plPlane = Plane4f( -m_vN, 0);

    if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
    { 
        return; 
    }

    // plane with edge 0
    dVector3 vTemp;
    dCalcVectorCross3(vTemp,m_vN,m_vE0);
    CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5));
    if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane ))
    { 
        return; 
    }

    dCalcVectorCross3(vTemp,m_vN,m_vE1);
    CONSTRUCTPLANE(plPlane, vTemp, -(dCalcVectorDot3(m_vE0,vTemp)-REAL(1e-5)));
    if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) 
    { 
        return; 
    }

    dCalcVectorCross3(vTemp,m_vN,m_vE2);
    CONSTRUCTPLANE(plPlane, vTemp, REAL(1e-5));
    if (!_cldClipEdgeToPlane( vCEdgePoint0, vCEdgePoint1, plPlane )) { 
        return; 
    }

    // return capsule edge points into absolute space
    vCEdgePoint0[0] += vPnt0[0];
    vCEdgePoint0[1] += vPnt0[1];
    vCEdgePoint0[2] += vPnt0[2];

    vCEdgePoint1[0] += vPnt0[0];
    vCEdgePoint1[1] += vPnt0[1];
    vCEdgePoint1[2] += vPnt0[2];

    // calculate depths for both contact points
    SUBTRACT(vCEdgePoint0,m_vCapsulePosition,vTemp);
    dReal fDepth0 = dCalcVectorDot3(vTemp,m_vNormal) - (m_fBestCenter-m_fBestrt);
    SUBTRACT(vCEdgePoint1,m_vCapsulePosition,vTemp);
    dReal fDepth1 = dCalcVectorDot3(vTemp,m_vNormal) - (m_fBestCenter-m_fBestrt);

    // clamp depths to zero
    if (fDepth0 < 0) 
    {
        fDepth0 = 0.0f;
    }

    if (fDepth1 < 0 ) 
    {
        fDepth1 = 0.0f;
    }

    // Cached contacts's data
    // contact 0
    dIASSERT(m_ctContacts < (m_iFlags & NUMC_MASK)); // Do not call function if there is no room to store result
    m_gLocalContacts[m_ctContacts].fDepth = fDepth0;
    SET(m_gLocalContacts[m_ctContacts].vNormal,m_vNormal);
    SET(m_gLocalContacts[m_ctContacts].vPos,vCEdgePoint0);
    m_gLocalContacts[m_ctContacts].nFlags = 1;
    m_ctContacts++;

    if (m_ctContacts < (m_iFlags & NUMC_MASK)) {
        // contact 1
        m_gLocalContacts[m_ctContacts].fDepth = fDepth1;
        SET(m_gLocalContacts[m_ctContacts].vNormal,m_vNormal);
        SET(m_gLocalContacts[m_ctContacts].vPos,vCEdgePoint1);
        m_gLocalContacts[m_ctContacts].nFlags = 1;
        m_ctContacts++;
    }
}
BOOL sTrimeshCapsuleColliderData::_cldTestSeparatingAxesOfCapsule(
    const dVector3 &v0,
    const dVector3 &v1,
    const dVector3 &v2,
    uint8 flags) 
{
    // calculate caps centers in absolute space
    dVector3 vCp0;
    vCp0[0] = m_vCapsulePosition[0] + m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCp0[1] = m_vCapsulePosition[1] + m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCp0[2] = m_vCapsulePosition[2] + m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);

    dVector3 vCp1;
    vCp1[0] = m_vCapsulePosition[0] - m_vCapsuleAxis[0]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCp1[1] = m_vCapsulePosition[1] - m_vCapsuleAxis[1]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);
    vCp1[2] = m_vCapsulePosition[2] - m_vCapsuleAxis[2]*(m_fCapsuleSize*REAL(0.5)-m_vCapsuleRadius);

    // reset best axis
    m_iBestAxis = 0;
    // reset best depth
    m_fBestDepth  = -MAX_REAL;
    // reset separating axis vector
    dVector3 vAxis = {REAL(0.0),REAL(0.0),REAL(0.0),REAL(0.0)};

    // Epsilon value for checking axis vector length 
    const dReal fEpsilon = 1e-6f;

    // Translate triangle to Cc cord.
    SUBTRACT(v0, m_vCapsulePosition, m_vV0);
    SUBTRACT(v1, m_vCapsulePosition, m_vV1);
    SUBTRACT(v2, m_vCapsulePosition, m_vV2);

    // We begin to test for 19 separating axis now
    // I wonder does it help if we employ the method like ISA-GJK???
    // Or at least we should do experiment and find what axis will
    // be most likely to be separating axis to check it first.

    // Original
    // axis m_vN
    //vAxis = -m_vN;
    vAxis[0] = - m_vN[0];
    vAxis[1] = - m_vN[1];
    vAxis[2] = - m_vN[2];
    if (!_cldTestAxis(v0, v1, v2, vAxis, 1, TRUE)) 
    { 
        return FALSE; 
    }

    if (flags & dxTriMeshData::kEdge0)
    {
        // axis CxE0 - Edge 0
        dCalcVectorCross3(vAxis,m_vCapsuleAxis,m_vE0);
        //vAxis = dCalcVectorCross3( m_vCapsuleAxis cross vE0 );
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 2)) { 
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge1)
    {
        // axis CxE1 - Edge 1
        dCalcVectorCross3(vAxis,m_vCapsuleAxis,m_vE1);
        //vAxis = ( m_vCapsuleAxis cross m_vE1 );
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 3)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge2)
    {
        // axis CxE2 - Edge 2
        //vAxis = ( m_vCapsuleAxis cross m_vE2 );
        dCalcVectorCross3(vAxis,m_vCapsuleAxis,m_vE2);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 4)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge0)
    {
        // first capsule point
        // axis ((Cp0-V0) x E0) x E0
        _CalculateAxis(vCp0,v0,m_vE0,m_vE0,vAxis);
        //	vAxis = ( ( vCp0-v0) cross vE0 ) cross vE0;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 5)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge1)
    {
        // axis ((Cp0-V1) x E1) x E1
        _CalculateAxis(vCp0,v1,m_vE1,m_vE1,vAxis);
        //vAxis = ( ( vCp0-v1) cross vE1 ) cross vE1;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 6)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge2)
    {
        // axis ((Cp0-V2) x E2) x E2
        _CalculateAxis(vCp0,v2,m_vE2,m_vE2,vAxis);
        //vAxis = ( ( vCp0-v2) cross vE2 ) cross vE2;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 7)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge0)
    {
        // second capsule point
        // axis ((Cp1-V0) x E0) x E0
        _CalculateAxis(vCp1,v0,m_vE0,m_vE0,vAxis);
        //vAxis = ( ( vCp1-v0 ) cross vE0 ) cross vE0;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 8)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge1)
    {
        // axis ((Cp1-V1) x E1) x E1
        _CalculateAxis(vCp1,v1,m_vE1,m_vE1,vAxis);
        //vAxis = ( ( vCp1-v1 ) cross vE1 ) cross vE1;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 9)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kEdge2)
    {
        // axis ((Cp1-V2) x E2) x E2
        _CalculateAxis(vCp1,v2,m_vE2,m_vE2,vAxis);
        //vAxis = ( ( vCp1-v2 ) cross vE2 ) cross vE2;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 10)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert0)
    {
        // first vertex on triangle
        // axis ((V0-Cp0) x C) x C
        _CalculateAxis(v0,vCp0,m_vCapsuleAxis,m_vCapsuleAxis,vAxis);
        //vAxis = ( ( v0-vCp0 ) cross m_vCapsuleAxis ) cross m_vCapsuleAxis;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 11)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert1)
    {
        // second vertex on triangle
        // axis ((V1-Cp0) x C) x C
        _CalculateAxis(v1,vCp0,m_vCapsuleAxis,m_vCapsuleAxis,vAxis);	
        //vAxis = ( ( v1-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 12)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert2)
    {
        // third vertex on triangle
        // axis ((V2-Cp0) x C) x C
        _CalculateAxis(v2,vCp0,m_vCapsuleAxis,m_vCapsuleAxis,vAxis);
        //vAxis = ( ( v2-vCp0 ) cross vCapsuleAxis ) cross vCapsuleAxis;
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 13)) {
                return FALSE;
            }
        }
    }

    // Test as separating axes direction vectors between each triangle
    // edge and each capsule's cap center

    if (flags & dxTriMeshData::kVert0)
    {
        // first triangle vertex and first capsule point
        //vAxis = v0 - vCp0;
        SUBTRACT(v0,vCp0,vAxis);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 14)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert1)
    {
        // second triangle vertex and first capsule point
        //vAxis = v1 - vCp0;
        SUBTRACT(v1,vCp0,vAxis);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 15)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert2)
    {
        // third triangle vertex and first capsule point
        //vAxis = v2 - vCp0;
        SUBTRACT(v2,vCp0,vAxis);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 16)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert0)
    {
        // first triangle vertex and second capsule point
        //vAxis = v0 - vCp1;
        SUBTRACT(v0,vCp1,vAxis);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 17)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert1)
    {
        // second triangle vertex and second capsule point
        //vAxis = v1 - vCp1;
        SUBTRACT(v1,vCp1,vAxis);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 18)) {
                return FALSE;
            }
        }
    }

    if (flags & dxTriMeshData::kVert2)
    {
        // third triangle vertex and second capsule point
        //vAxis = v2 - vCp1;
        SUBTRACT(v2,vCp1,vAxis);
        if (_length2OfVector3( vAxis ) > fEpsilon) {
            if (!_cldTestAxis(v0, v1, v2, vAxis, 19)) {
                return FALSE;
            }
        }
    }

    return TRUE;
}
bool sTrimeshBoxColliderData::_cldTestSeparatingAxes(const dVector3 &v0, const dVector3 &v1, const dVector3 &v2) {
  // reset best axis
  m_iBestAxis = 0;
  m_iExitAxis = -1;
  m_fBestDepth = MAXVALUE;

  // calculate edges
  SUBTRACT(v1,v0,m_vE0);
  SUBTRACT(v2,v0,m_vE1);
  SUBTRACT(m_vE1,m_vE0,m_vE2);

  // calculate poly normal
  dCROSS(m_vN,=,m_vE0,m_vE1);

  // calculate length of face normal
  dReal fNLen = LENGTHOF(m_vN);

  // Even though all triangles might be initially valid, 
  // a triangle may degenerate into a segment after applying 
  // space transformation.
  if (!fNLen) {
	  return false;
  }

  // extract box axes as vectors
  dVector3 vA0,vA1,vA2;
  GETCOL(m_mHullBoxRot,0,vA0);
  GETCOL(m_mHullBoxRot,1,vA1);
  GETCOL(m_mHullBoxRot,2,vA2);

  // box halfsizes
  dReal fa0 = m_vBoxHalfSize[0];
  dReal fa1 = m_vBoxHalfSize[1];
  dReal fa2 = m_vBoxHalfSize[2];

  // calculate relative position between box and triangle
  dVector3 vD;
  SUBTRACT(v0,m_vHullBoxPos,vD);

  dVector3 vL;
  dReal fp0, fp1, fp2, fR, fD;

  // Test separating axes for intersection
  // ************************************************
  // Axis 1 - Triangle Normal
  SET(vL,m_vN);
  fp0  = dDOT(vL,vD);
  fp1  = fp0;
  fp2  = fp0;
  fR=fa0*dFabs( dDOT(m_vN,vA0) ) + fa1 * dFabs( dDOT(m_vN,vA1) ) + fa2 * dFabs( dDOT(m_vN,vA2) );

  if (!_cldTestNormal(fp0, fR, vL, 1)) {
    m_iExitAxis=1;
    return false;
  }

  // ************************************************

  // Test Faces
  // ************************************************
  // Axis 2 - Box X-Axis
  SET(vL,vA0);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 + dDOT(vA0,m_vE0);
  fp2 = fp0 + dDOT(vA0,m_vE1);
  fR  = fa0;

  if (!_cldTestFace(fp0, fp1, fp2, fR, fD, vL, 2)) {
    m_iExitAxis=2;
    return false;
  }
  // ************************************************

  // ************************************************
  // Axis 3 - Box Y-Axis
  SET(vL,vA1);
  fD = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 + dDOT(vA1,m_vE0);
  fp2 = fp0 + dDOT(vA1,m_vE1);
  fR  = fa1;

  if (!_cldTestFace(fp0, fp1, fp2, fR, fD, vL, 3)) {
    m_iExitAxis=3;
    return false;
  }

  // ************************************************

  // ************************************************
  // Axis 4 - Box Z-Axis
  SET(vL,vA2);
  fD = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 + dDOT(vA2,m_vE0);
  fp2 = fp0 + dDOT(vA2,m_vE1);
  fR  = fa2;

  if (!_cldTestFace(fp0, fp1, fp2, fR, fD, vL, 4)) {
    m_iExitAxis=4;
    return false;
  }

  // ************************************************

  // Test Edges
  // ************************************************
  // Axis 5 - Box X-Axis cross Edge0
  dCROSS(vL,=,vA0,m_vE0);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0;
  fp2 = fp0 + dDOT(vA0,m_vN);
  fR  = fa1 * dFabs(dDOT(vA2,m_vE0)) + fa2 * dFabs(dDOT(vA1,m_vE0));

  if (!_cldTestEdge(fp1, fp2, fR, fD, vL, 5)) {
    m_iExitAxis=5;
    return false;
  }
  // ************************************************

  // ************************************************
  // Axis 6 - Box X-Axis cross Edge1
  dCROSS(vL,=,vA0,m_vE1);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA0,m_vN);
  fp2 = fp0;
  fR  = fa1 * dFabs(dDOT(vA2,m_vE1)) + fa2 * dFabs(dDOT(vA1,m_vE1));

  if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 6)) {
    m_iExitAxis=6;
    return false;
  }
  // ************************************************

  // ************************************************
  // Axis 7 - Box X-Axis cross Edge2
  dCROSS(vL,=,vA0,m_vE2);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA0,m_vN);
  fp2 = fp0 - dDOT(vA0,m_vN);
  fR  = fa1 * dFabs(dDOT(vA2,m_vE2)) + fa2 * dFabs(dDOT(vA1,m_vE2));

  if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 7)) {
    m_iExitAxis=7;
    return false;
  }

  // ************************************************

  // ************************************************
  // Axis 8 - Box Y-Axis cross Edge0
  dCROSS(vL,=,vA1,m_vE0);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0;
  fp2 = fp0 + dDOT(vA1,m_vN);
  fR  = fa0 * dFabs(dDOT(vA2,m_vE0)) + fa2 * dFabs(dDOT(vA0,m_vE0));

  if (!_cldTestEdge(fp0, fp2, fR, fD, vL, 8)) {
    m_iExitAxis=8;
    return false;
  }

  // ************************************************

  // ************************************************
  // Axis 9 - Box Y-Axis cross Edge1
  dCROSS(vL,=,vA1,m_vE1);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA1,m_vN);
  fp2 = fp0;
  fR  = fa0 * dFabs(dDOT(vA2,m_vE1)) + fa2 * dFabs(dDOT(vA0,m_vE1));

  if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 9)) {
    m_iExitAxis=9;
    return false;
  }

  // ************************************************

  // ************************************************
  // Axis 10 - Box Y-Axis cross Edge2
  dCROSS(vL,=,vA1,m_vE2);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA1,m_vN);
  fp2 = fp0 - dDOT(vA1,m_vN);
  fR  = fa0 * dFabs(dDOT(vA2,m_vE2)) + fa2 * dFabs(dDOT(vA0,m_vE2));

  if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 10)) {
    m_iExitAxis=10;
    return false;
  }

  // ************************************************

  // ************************************************
  // Axis 11 - Box Z-Axis cross Edge0
  dCROSS(vL,=,vA2,m_vE0);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0;
  fp2 = fp0 + dDOT(vA2,m_vN);
  fR  = fa0 * dFabs(dDOT(vA1,m_vE0)) + fa1 * dFabs(dDOT(vA0,m_vE0));

  if (!_cldTestEdge(fp0, fp2, fR, fD, vL, 11)) {
    m_iExitAxis=11;
    return false;
  }
  // ************************************************

  // ************************************************
  // Axis 12 - Box Z-Axis cross Edge1
  dCROSS(vL,=,vA2,m_vE1);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA2,m_vN);
  fp2 = fp0;
  fR  = fa0 * dFabs(dDOT(vA1,m_vE1)) + fa1 * dFabs(dDOT(vA0,m_vE1));

  if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 12)) {
    m_iExitAxis=12;
    return false;
  }
  // ************************************************

  // ************************************************
  // Axis 13 - Box Z-Axis cross Edge2
  dCROSS(vL,=,vA2,m_vE2);
  fD  = dDOT(vL,m_vN)/fNLen;
  fp0 = dDOT(vL,vD);
  fp1 = fp0 - dDOT(vA2,m_vN);
  fp2 = fp0 - dDOT(vA2,m_vN);
  fR  = fa0 * dFabs(dDOT(vA1,m_vE2)) + fa1 * dFabs(dDOT(vA0,m_vE2));

  if (!_cldTestEdge(fp0, fp1, fR, fD, vL, 13)) {
    m_iExitAxis=13;
    return false;
  }

  // ************************************************
  return true;
}
Пример #12
0
int pointblankrange_calculate(lpPointBlankRange pointblankrange)
{
  Vector dr, r, tv, v, w;
  double mv, vm, elev, mh, vz, bw;
  double dt, eq, t, mach, drg;
  int    i, itcnt, mhr;

/* Set values that don't change for the pointblankrange... */
  if (pointblankrange->alc) 
    atmos_standardalt(pointblankrange->atmos);
  else 
    atmos_atmos(pointblankrange->atmos);
  mach = pointblankrange->atmos->mach;
  eq = pointblankrange->atmos->density/ATMOS_DENSSTD;
  vz = INTOFT(pointblankrange->vital_zone);
  bw = pointblankrange->bullet_weight;


  itcnt = 0;
  pointblankrange->found = 0;
  elev = vz/(250.0*PBR_DX);
  while ((!pointblankrange->found) && (itcnt < PBR_MAXIMUM_ITCNT))
  {
    vm = pointblankrange->muzzle_velocity;
    pointblankrange->muzzle_energy = PBR_ENERGY(bw, vm);
    t = 0.0;
    mh = INTOFT(-pointblankrange->sight_height);
    r = vector(0.0, mh, 0.0);
    dr = vector(0.0, 0.0, 0.0);
    v.x = vm*cos(elev);
    v.y = vm*sin(elev);
    v.z = 0.0;

    for (i = 0; (r.y > -vz); i++)
    {

      if (vm < PBR_ABSMINVX) break;

      vm  = LENGTH(v);
      dt  = 0.5*PBR_DX/v.x;
      drg = eq*vm*bc_getdrag(pointblankrange->bc, vm/mach);
      tv  = SUBTRACT(v, MULTIPLY(dt, SUBTRACT(MULTIPLY(drg, v), PBR_GRAVITY)));
      vm  = LENGTH(tv);
      dt  = PBR_DX/tv.x;
      drg = eq*vm*bc_getdrag(pointblankrange->bc, vm/mach);
      v   = SUBTRACT(v, MULTIPLY(dt, SUBTRACT(MULTIPLY(drg, tv), PBR_GRAVITY)));
      dr  = vector(PBR_DX, v.y*dt, v.z*dt);
      r   = ADD(r, dr);
      t   = t + LENGTH(dr)/vm;
      vm  = LENGTH(v);

      if (r.y > 0.0) pointblankrange->pbzero = i;
      pointblankrange->pbrange = i;

      if (r.y > mh)
      {
	mh = r.y;
	mhr = i;
      }
    }
    pointblankrange->found = (fabs(mh - vz) < PBR_MAXIMUM_ERROR);
    if (!pointblankrange->found)
    {
      elev = elev - (mh - vz)/(mhr*PBR_DX);
    }
    itcnt++;
    pointblankrange->terminal_energy = PBR_ENERGY(bw, vm);
  }

  return 0;
}