void
btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
{
		//BTREVIEW 0.6%
	
	btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
    triangleShape.setMargin(m_triangleCollisionMargin);

	btVoronoiSimplexSolver	simplexSolver;
	btGjkEpaPenetrationDepthSolver	gjkEpaPenetrationSolver;

//#define  USE_SUBSIMPLEX_CONVEX_CAST 1
//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
	btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
#else
	//btGjkConvexCast	convexCaster(m_convexShape,&triangleShape,&simplexSolver);
	btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
#endif //#USE_SUBSIMPLEX_CONVEX_CAST
	
	btConvexCast::CastResult castResult;
	castResult.m_fraction = btScalar(1.);
	castResult.m_allowedPenetration = m_allowedPenetration;
	if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
	{
		//add hit
		if (castResult.m_normal.length2() > btScalar(0.0001))
		{					
			if (castResult.m_fraction < m_hitFraction)
			{
/* btContinuousConvexCast's normal is already in world space */
/*
#ifdef USE_SUBSIMPLEX_CONVEX_CAST
				//rotate normal into worldspace
				castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
#endif //USE_SUBSIMPLEX_CONVEX_CAST
*/
				castResult.m_normal.normalize();

				reportHit (castResult.m_normal,
							castResult.m_hitPoint,
							castResult.m_fraction,
							partId,
							triangleIndex);
			}
		}
	}
}
void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
	const btVector3 &vert0=triangle[0];
	const btVector3 &vert1=triangle[1];
	const btVector3 &vert2=triangle[2];

	btVector3 v10; v10 = vert1 - vert0 ;
	btVector3 v20; v20 = vert2 - vert0 ;

	btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
	
	const btScalar dist = vert0.dot(triangleNormal);
	btScalar dist_a = triangleNormal.dot(m_from) ;
	dist_a-= dist;
	btScalar dist_b = triangleNormal.dot(m_to);
	dist_b -= dist;

	if ( dist_a * dist_b >= btScalar(0.0) )
	{
		return ; // same sign
	}

	if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
	{
		// Backface, skip check
		return;
	}

	
	const btScalar proj_length=dist_a-dist_b;
	const btScalar distance = (dist_a)/(proj_length);
	// Now we have the intersection point on the plane, we'll see if it's inside the triangle
	// Add an epsilon as a tolerance for the raycast,
	// in case the ray hits exacly on the edge of the triangle.
	// It must be scaled for the triangle size.
	
	if(distance < m_hitFraction)
	{
		

		btScalar edge_tolerance =triangleNormal.length2();		
		edge_tolerance *= btScalar(-0.0001);
		btVector3 point; point.setInterpolate3( m_from, m_to, distance);
		{
			btVector3 v0p; v0p = vert0 - point;
			btVector3 v1p; v1p = vert1 - point;
			btVector3 cp0; cp0 = v0p.cross( v1p );

			if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) 
			{
						

				btVector3 v2p; v2p = vert2 -  point;
				btVector3 cp1;
				cp1 = v1p.cross( v2p);
				if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) 
				{
					btVector3 cp2;
					cp2 = v2p.cross(v0p);
					
					if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) 
					{
					  //@BP Mod
					  // Triangle normal isn't normalized
				      triangleNormal.normalize();

					 //@BP Mod - Allow for unflipped normal when raycasting against backfaces
						if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
						{
							m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
						}
						else
						{
							m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
						}
					}
				}
			}
		}
	}
}
int main(int argc, char *argv[])
{
  int sockfd, portno, n;
  struct sockaddr_in serv_addr;
  struct hostent *server;
  char buffer[256];
  if (argc < 3) {
    fprintf(stderr,"usage %s hostname port\n", argv[0]);
    exit(0);
  }
  portno = atoi(argv[2]);
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0)
    error("ERROR opening socket");
  server = gethostbyname(argv[1]);
  if (server == NULL) {
    fprintf(stderr,"ERROR, no such host\n");
    exit(0);
  }
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  bcopy((char *)server->h_addr,
        (char *)&serv_addr.sin_addr.s_addr,
        server->h_length);
  serv_addr.sin_port = htons(portno);
  if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
    error("ERROR connecting");
  printf("Please enter gun number: ");
  bzero(buffer,256);
  fgets(buffer,255,stdin);
  n = write(sockfd,buffer,strlen(buffer));
  if (n < 0)
    error("ERROR writing to socket");
  int choice;
  while(choice != 0)
    {

      printf("\n1. quit\n");
      printf("2. report shot\n");
      printf("3. report hit\n");
      /* printf("4. report error\n"); */
      printf("selection: ");

      scanf("%d",&choice);

      switch(choice)
        {
        case 1:
          return 0;
          break;
        case 2:
          reportShot(buffer, sockfd, n);
          break;
        case 3:
          reportHit(buffer, sockfd, n);
          break;
        case 4:
          reportError(buffer, sockfd, n);
          break;
        default:
          printf("\nBAD OPTION! Please choose again!");
        }


      /* bzero(buffer,256); */
      /* n = read(sockfd,buffer,255); */
      /* if (n < 0) */
      /*   error("ERROR reading from socket"); */
      /* printf("%s\n",buffer); */
      /* printf("\nPlease enter a command: "); */
      /* bzero(buffer,256); */
      /* fgets(buffer,255,stdin); */
      /* n = write(sockfd,buffer,strlen(buffer)); */
      /* if (n < 0) */
      /*   error("ERROR writing to socket"); */
    }
  close(sockfd);
  return 0;
}