void BulletDynamicsBody::SetMass( float mass )
{
  DEBUG_PRINTF("%s(%.2f)\n", __func__, mass);

  if( Dali::DynamicsBodyConfig::RIGID == mSettings->type )
  {
    btRigidBody* rigidBody( btRigidBody::upcast(mBody) );
    DALI_ASSERT_DEBUG( rigidBody );

    btVector3 inertia(0,0,0);
    if( ! EqualsZero( mass ) )
    {
      btCollisionShape* shape = mBody->getCollisionShape();
      shape->calculateLocalInertia(mass, inertia);
    }
    rigidBody->setMassProps(btScalar(mass), inertia);
  }
  else if( Dali::DynamicsBodyConfig::SOFT == mSettings->type )
  {
    btSoftBody* softBody( btSoftBody::upcast(mBody) );
    DALI_ASSERT_DEBUG( softBody );

    softBody->setTotalMass(mass);
  }
}
void BulletDynamicsBody::SetTransform( const Vector3& position, const Quaternion& rotation )
{
  Vector3 axis;
  float angle( 0.0f );
  rotation.ToAxisAngle( axis, angle );

  if( Dali::DynamicsBodyConfig::RIGID == mSettings->type )
  {
    btTransform& transform( mBody->getWorldTransform() );
    // modify parameters
    transform.setIdentity();
    transform.setOrigin( btVector3(position.x, position.y, position.z) );
    if( axis != Vector3::ZERO )
    {
      transform.setRotation( btQuaternion(btVector3(axis.x, axis.y, axis.z), btScalar(angle)) );
    }
  }
  else if( Dali::DynamicsBodyConfig::SOFT == mSettings->type )
  {
    btSoftBody* softBody( static_cast< btSoftBody* >( mBody ) );
    btTransform transform;
    transform.setIdentity();
    transform.setOrigin( btVector3(position.x, position.y, position.z) );
    if( axis != Vector3::ZERO )
    {
      transform.setRotation( btQuaternion(btVector3(axis.x, axis.y, axis.z), btScalar(angle)) );
    }
    softBody->transform( transform );
  }
}
void BulletDynamicsBody::AddAnchor( unsigned int index, const Integration::DynamicsBody* anchorBody, bool collisions )
{
  DEBUG_PRINTF("%s\n", __func__);
  const BulletDynamicsBody* anchorDynamicsBody( static_cast< const BulletDynamicsBody* >( anchorBody ) );

  btSoftBody* softBody( static_cast< btSoftBody* >( mBody ) );
  btRigidBody* rigidBody( static_cast< btRigidBody* >( anchorDynamicsBody->GetBody() ) );
  softBody->appendAnchor( index, rigidBody, !collisions );
}
void BulletDynamicsBody::ConserveShape( bool flag )
{
  if( mConserveShape != flag )
  {
    mConserveShape = flag;

    btSoftBody* softBody( static_cast<btSoftBody*>(mBody) );
    softBody->setPose( mConserveVolume, mConserveShape );
  }
}
void BulletDynamicsBody::GetSoftVertices( MeshData::VertexContainer& vertices ) const
{
  const float worldScale( 1.0f / mWorld->GetWorldScale() );

  // copy positions and normals
  const size_t vertexCount = vertices.size();
  MeshData::Vertex* vertex( &vertices[0] );

  btSoftBody* softBody( static_cast<btSoftBody*>( mBody ) );
  btSoftBody::Node* node( &softBody->m_nodes[0] );
  for( size_t i = 0; i < vertexCount; ++i )
  {
    vertex->x = node->m_x.x() * worldScale;
    vertex->y = node->m_x.y() * worldScale;
    vertex->z = node->m_x.z() * worldScale;

    vertex->nX = node->m_n.x();
    vertex->nY = node->m_n.y();
    vertex->nZ = node->m_n.z();

    ++vertex;
    ++node;
  }
}
void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
{
	//just for debugging purposes
	//printf("triangle %d",m_triangleCount++);
	
	btCollisionAlgorithmConstructionInfo ci;
	ci.m_dispatcher1 = m_dispatcher;

	///debug drawing of the overlapping triangles
	if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe))
	{
		btVector3 color(1,1,0);
		const btTransform& tr = m_triBody->getWorldTransform();
		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
	}

	btTriIndex	triIndex(partId,triangleIndex,0);
	btHashKey<btTriIndex> triKey(triIndex.getUid());


	btTriIndex* shapeIndex = m_shapeCache[triKey];
	if (shapeIndex)
	{
		btCollisionShape* tm = shapeIndex->m_childShape;
		btAssert(tm);

		//copy over user pointers to temporary shape
		tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());

		btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform());
		//btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
		btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform());

		btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr);

		colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
		colAlgo->~btCollisionAlgorithm();
		ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
		
		return;
	}

	//aabb filter is already applied!	

	//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);

	//	if (m_softBody->getCollisionShape()->getShapeType()==
	{
		//		btVector3 other;
		btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]);
		normal.normalize();
		normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION;
		//		other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
		//		other+=normal*22.f;
		btVector3	pts[6] = {triangle[0]+normal,
			triangle[1]+normal,
			triangle[2]+normal,
			triangle[0]-normal,
			triangle[1]-normal,
			triangle[2]-normal};

		btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6);


		//		btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);

		//btTriangleShape tm(triangle[0],triangle[1],triangle[2]);	
		//	tm.setMargin(m_collisionMarginTriangle);

		//copy over user pointers to temporary shape
		tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());

		
		btCollisionObjectWrapper softBody(0,m_softBody->getCollisionShape(),m_softBody,m_softBody->getWorldTransform());
		btCollisionObjectWrapper triBody(0,tm, m_triBody, m_triBody->getWorldTransform());//btTransform::getIdentity());//??

		btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody,&triBody,0);//m_manifoldPtr);

		colAlgo->processCollision(&softBody,&triBody,*m_dispatchInfoPtr,m_resultOut);
		colAlgo->~btCollisionAlgorithm();
		ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);

		triIndex.m_childShape = tm;
		m_shapeCache.insert(triKey,triIndex);

	}



}
void BulletDynamicsBody::CreateSoftBody( const Integration::DynamicsBodySettings& bodySettings, Dali::Integration::DynamicsShape* shape,
                                         const Vector3& startPosition, const Quaternion& startRotation )
{
  DEBUG_PRINTF("BulletDynamicsBody::CreateSoftBody()\n" );

  BulletDynamicsShape* dynamicsShape( static_cast< BulletDynamicsShape* >( shape ) );

  // copy positions
  MeshData::VertexContainer* vertices( dynamicsShape->mVertices );
  const size_t vertexCount = vertices->size();
  MeshData::Vertex* vertex( &(*vertices)[0] );

  MeshData::FaceIndices* faces( dynamicsShape->mFaces );
  const size_t faceCount = faces->size() / 3;
  unsigned short* faceIndex = ( &(*faces)[0] );

  const float worldScale( mWorld->GetWorldScale() );

  DEBUG_PRINTF("%s verts:%d faces:%d worldScale:%.2f\n", __func__, (int)vertexCount, (int)faceCount, worldScale );

  // copy vertex positions
  std::vector<btVector3> positions( vertexCount );
  btVector3* position = &positions[0];
  for( size_t i = 0; i < vertexCount; ++i )
  {
    *position++ = btVector3( vertex->x, vertex->y, vertex->z ) * worldScale;
    vertex++;
  }

  btSoftBody* softBody( new btSoftBody(mWorld->GetSoftBodyWorldInfo(), vertexCount, positions.data(), NULL) );

  // Add faces
  for( size_t i = 0; i < faceCount; ++i)
  {
    softBody->appendFace(faceIndex[0], faceIndex[1], faceIndex[2]);
    softBody->appendLink(faceIndex[0], faceIndex[1], NULL, true);
    softBody->appendLink(faceIndex[0], faceIndex[2], NULL, true);
    softBody->appendLink(faceIndex[1], faceIndex[2], NULL, true);
    faceIndex += 3;
  }

  softBody->m_cfg.kAHR = std::max(0.0f, std::min(1.0f, bodySettings.anchorHardness));
  softBody->m_cfg.kVC  = std::max(0.0f, bodySettings.volumeConservation);
  softBody->m_cfg.kMT  = std::max(0.0f, std::min(1.0f, bodySettings.shapeConservation));
  softBody->m_cfg.kDP  = Clamp( bodySettings.linearDamping, 0.0f, 1.0f );

  btSoftBody::Material* material( softBody->m_materials[0] );
  material->m_kLST = bodySettings.linearStiffness;

//  material->m_flags &= ~btSoftBody::fMaterial::DebugDraw;           // By default, inhibit debug draw for softbodies
  softBody->m_cfg.collisions = btSoftBody::fCollision::SDF_RS |
                               btSoftBody::fCollision::CL_SS |
                               0;

  softBody->getCollisionShape()->setMargin(0.5f);

  mBody = softBody;
  mBody->setUserPointer(this);

  SetTransform( startPosition, startRotation );
}