Exemple #1
0
void BulletWrapper::utilSetupScene(const EigenTypes::Vector3f& refPosition)
{
   // setup walls 

  float halfSize = 0.05f;
  EigenTypes::Vector3f boxHalfExtents(halfSize, halfSize, halfSize);

  float spacing = 2.f * halfSize;

  float zDist = 0.5f;
  // for Dragonfly
  zDist = 0.6f * zDist;

  int halfCountX = std::min(4, int((zDist-halfSize)/spacing));
  int halfCountY = 3;


  for (int y = -halfCountY; y <= halfCountY; y++)
    for (int x = -halfCountX; x <= halfCountX; x++)
    {
      utilAddCube(refPosition + EigenTypes::Vector3f(spacing * x, spacing * y, -zDist), boxHalfExtents);

      utilAddCube(refPosition + EigenTypes::Vector3f(spacing * x, spacing * y, zDist), boxHalfExtents);

      utilAddCube(refPosition + EigenTypes::Vector3f(zDist, spacing * y, spacing * x), boxHalfExtents);

      utilAddCube(refPosition + EigenTypes::Vector3f(-zDist, spacing * y, spacing * x), boxHalfExtents);
    }

  // Add head representation
  const bool notVisible = false;
  m_HeadRepresentation = utilAddFingerSphere(refPosition, 0.2f, notVisible);

}
// The scabbard is a single constraint which should have multiple degrees of freedom, but will suffer from the following 
// artifacts if implemented using a single ball-and-socket constraint:
// 1. Undesired motion (excessive, potentially implausible, or just not artisitically desired) due to the simplification 
//    to a single point of attachment.
// 2. Excessive energy, or undersired enrgy preservation when the character comes to rest.
// 3. A potential performance impact if collisions are used to prevent interpenetration with the character.
// To address these we use a ragdoll constraint instead which allows full control to restict angular degrees of freedom of the
// underlying ball-and-socket, and we use angular damping to make sure the scabbard comes to rest quickly.
// We can then disable all collision between the scabbard and the hip, leaving all other collisions valid.
void HK_CALL CharacterAttachmentsHelpers::addScabbard(hkpWorld* world, 
												const hkaRagdollInstance* ragdollInstance,
												const hkQsTransform& currentTransform,
												const char* startBoneName, 
												hkpGroupFilter* filter,
												const ConstraintStabilityTricks& tricks )
{
	// We will use a tricks to increase stability:
	const hkReal angularDamping = 4.0f;


	// Get the relevant RBs to which we attach this belt.
	hkpRigidBody* torso = HK_NULL;
	{
		int torsoIndex = hkaSkeletonUtils::findBoneWithName( *ragdollInstance->m_skeleton, startBoneName);
		HK_ASSERT2( 0, torsoIndex >= 0, "Couldn't find " << startBoneName << " in ragdoll" );
		torso = ragdollInstance->getRigidBodyOfBone( torsoIndex );
	}

	hkpRigidBody* scabbard;
	{
		hkVector4 boxHalfExtents( 0.02f, 0.05f, 0.3f);

		// Create body 
		hkpRigidBodyCinfo info;
		info.m_shape = new hkpBoxShape( boxHalfExtents, 0.01f );

		// We are going to add a single body which does not collide with the bone to which it is attached in the ragdoll so we 
		// will put in the same group and disable collision using subgroups. 
		hkUint32 torsoFilterInfo = torso->getCollidable()->getCollisionFilterInfo();
		info.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(
			1, 
			2,
			31, // New subgroup - larger than any subgroup in the ragdoll
			hkpGroupFilter::getSubSystemIdFromFilterInfo(torsoFilterInfo) // Don't collide with torso subgroup
			);

		// Note that we use a scaled mass here to artificially damp the movement
		const hkReal mass = 1.0f;
		hkpInertiaTensorComputer::setShapeVolumeMassProperties( info.m_shape, mass, info );
		info.m_mass = mass;

		// Note that we use an increased angular damping to further artificially damp the movement
		if( tricks.m_useDamping ) 
		{
			info.m_angularDamping = angularDamping;
		}

		// Place roughly beside the character model space - we'll let a short simulation run settle the constraint properly.
		info.m_position.set( 0.2f, 0.0f, -0.2f );	

		// Move into world space behind character
		info.m_position.setTransformedPos(currentTransform, info.m_position);

		scabbard = new hkpRigidBody( info );
		info.m_shape->removeReference();

		world->addEntity( scabbard );
		scabbard->removeReference();
	}

	//
	// Create constraint (to attach and also restrict motion)
	// 
	hkVector4 pivotA, pivotB;
	{
		// Scabbard
		pivotA.set(-0.02f, 0.0f, 0.3f);

		// Torso
		pivotB.set(0.0f, 0.0f, 0.2f);
	}

	hkpConstraintData* cd = HK_NULL;

	if( tricks.m_useLimits ) 
	{
		hkReal planeMin =  -HK_REAL_PI * 0.5f;
		hkReal planeMax =  HK_REAL_PI * 0.05f;
		hkReal twistMin =  HK_REAL_PI * -0.04f;
		hkReal twistMax =  HK_REAL_PI *  0.04f;
		hkReal coneMin  =  HK_REAL_PI * 0.3f;

		hkpRagdollConstraintData* rdcd = new hkpRagdollConstraintData();

		rdcd->setConeAngularLimit(coneMin);
		rdcd->setPlaneMinAngularLimit(planeMin);
		rdcd->setPlaneMaxAngularLimit(planeMax);
		rdcd->setTwistMinAngularLimit(twistMin);
		rdcd->setTwistMaxAngularLimit(twistMax);

		// Scabbard
		hkVector4 twistAxisA(0.0f, 0.0f, 1.0f);
		hkVector4 planeAxisA(1.0f, 0.0f, 0.0f);

		// Torso
		hkVector4 twistAxisB(1.0f, 0.0f, 0.0f);
		hkVector4 planeAxisB(0.0f, 0.0f, 1.0f);

		rdcd->setInBodySpace(pivotA, pivotB, planeAxisA, planeAxisB, twistAxisA, twistAxisB);

		cd = rdcd;
	}
	else
	{
		// Just use a ball-and-socket (no angular limits)
		hkpBallAndSocketConstraintData* bscd = new hkpBallAndSocketConstraintData();

		bscd->setInBodySpace(pivotA, pivotB);

		cd = bscd;
	}

	//
	//	Create and add the constraint
	//
	{
		hkpConstraintInstance* constraint = new hkpConstraintInstance(scabbard, torso, cd );
		world->addConstraint(constraint);
		constraint->removeReference();
	}	
	cd->removeReference();
}
// The backpack is a single constraint which should have only one degree of freedom, but will suffer from the following 
// artifacts if implemented using a single hinge constraint:
// 1. Undesired motion (excessive, potentially implausible, or just not artisitically desired) due to the large
//    accelerations of the character.
// 2. A potential performance impact if collisions are used to prevent interpenetration with the character.
// To address this we use a limited hinge constraint which keeps the backpack from penetrating the spline and
// from moving to far upwards.
// The alternative approach of ensuring collisions between the character and the backpack keep it in place has the following flaws:
// (a) Constant collision (such as when the character is standing idle) is expensive, especially if colliding with several bodies
// such as are in the spine - a single constraint with fixed limits avoids this completely with minimal expense.
// (b) Again, without limits, even if the backpack rests against the base of the spine when moving down, there is nothing to prevent
// the large accelerations of the character forcing the backpack to swing up and forward over the shoulders until it collides with
// the back of the head, which is probably not desirable from an artistic standpoint.
void HK_CALL CharacterAttachmentsHelpers::addBackpack(hkpWorld* world, 
												const hkaRagdollInstance* ragdollInstance,
												const hkQsTransform& currentTransform,
												const char* startBoneName, 
												hkpGroupFilter* filter,
												const ConstraintStabilityTricks& tricks  )
{

	// Get the relevant RBs to which we attach this backpack.
	hkpRigidBody* torso = HK_NULL;
	{
		int torsoIndex = hkaSkeletonUtils::findBoneWithName( *ragdollInstance->m_skeleton, startBoneName);
		HK_ASSERT2( 0, torsoIndex >= 0, "Couldn't find " << startBoneName << " in ragdoll" );
		torso = ragdollInstance->getRigidBodyOfBone( torsoIndex );
	}

	hkpRigidBody* backpack;
	{
		hkVector4 boxHalfExtents( 0.1f, 0.05f, 0.2f);

		// Create a body
		hkpRigidBodyCinfo info;
		info.m_shape = new hkpBoxShape( boxHalfExtents, 0.01f );

		// We are going to add a single body which does not collide with the ragdoll *at all* so we 
		// will put in a different group and different layer and disable collision using layers. 
		info.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo( 2, 3 );
		filter->disableCollisionsBetween(1, 2);
	
		const hkReal mass = 1.0f;
		hkpInertiaTensorComputer::setShapeVolumeMassProperties( info.m_shape, mass, info );
		info.m_mass = mass;

		// Place roughly behind the character model space - we'll let a short simulation run settle the constraint properly.
		info.m_position.set( 0.2f, 0.0f, -0.2f );	

		// Move into world space behind character
		info.m_position.setTransformedPos(currentTransform, info.m_position);

		backpack = new hkpRigidBody( info );
		info.m_shape->removeReference();

		world->addEntity( backpack );
		backpack->removeReference();
	}

	//
	// Create constraint (to attach and also restrict motion)
	// 
	{
		hkpLimitedHingeConstraintData* lhc = new hkpLimitedHingeConstraintData();

		hkVector4 pivotA, pivotB;

		// Backpack
		pivotA.set(0.0f, -0.05f, 0.2f);
		hkVector4 axisA(1.0f, 0.0f, 0.0f);
		hkVector4 axisAPerp(0.0f, 0.0f, 1.0f);

		// Torso
		pivotB.set(0.1f, -0.07f, 0.0f);
		hkVector4 axisB(0.0f, 0.0f, 1.0f);
		hkVector4 axisBPerp(1.0f, 0.0f, 0.0f);

		lhc->setInBodySpace(pivotA, pivotB, axisA, axisB, axisAPerp, axisBPerp);
		lhc->setMinAngularLimit(HK_REAL_PI/40.0f);
		lhc->setMaxAngularLimit(HK_REAL_PI/4.0f);

		//
		//	Create and add the constraint
		//
		{
			hkpConstraintInstance* constraint = new hkpConstraintInstance(backpack, torso, lhc );
			world->addConstraint(constraint);
			constraint->removeReference();
		}	

		if( !tricks.m_useLimits ) 
		{
			lhc->disableLimits();
		}


		lhc->removeReference();
	}

}
void DemoKeeper::BinaryActionDemo( void )
{


	springNode=mSceneMgr->getRootSceneNode()->createChildSceneNode();

	mWorld->markForWrite();

	//
	// Create Rigid Body.
	//
	{
		/// Here we construct a simple cube with sides 2 units and mass 1.
		hkVector4 boxHalfExtents( 1.0f, 1.0f, 1.0f );  
		hkpBoxShape* geom = new hkpBoxShape( boxHalfExtents , 0 );

		const hkReal mass = 1.0f;
		hkVector4 pos( -2.0f, 5.0f, 0.0f );

		hkpRigidBodyCinfo boxInfo;
		hkMassProperties massProperties;
		hkpInertiaTensorComputer::computeBoxVolumeMassProperties(boxHalfExtents, mass, massProperties);
		boxInfo.m_mass = massProperties.m_mass;
		boxInfo.m_centerOfMass = massProperties.m_centerOfMass;
		boxInfo.m_inertiaTensor = massProperties.m_inertiaTensor;
		boxInfo.m_shape = geom;
		boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
		boxInfo.m_position = pos;
		boxInfo.m_gravityFactor = 0;

		m_boxRigidBody1 = new hkpRigidBody(boxInfo);

		// As the rigid bodies now references our shape, we no longer need to.
		geom->removeReference();

		// and add it to the world.
		mWorld->addEntity( m_boxRigidBody1 );

		//render it with Ogre
		Ogre::SceneNode* boxNode1 = mSceneMgr->getRootSceneNode()->createChildSceneNode();

		//scale
		boxNode1->scale(2, 2, 2);

		//display and sync
		Ogre::Entity *ent = mSceneMgr->createEntity(Ogre::StringConverter::toString(mLabMgr->getEntityCount()),"defCube.mesh");
		mLabMgr->setColor(ent, Ogre::Vector3(0.5538,0.3187,0.1275));
		HkOgre::Renderable* rend = new HkOgre::Renderable(boxNode1, m_boxRigidBody1,mWorld);
		boxNode1->attachObject(ent);

		//register to lab manager
		mLabMgr->registerEnity( boxNode1, m_boxRigidBody1);
	}

	//
	// Create Rigid Body.
	//
	{
		// Here we construct a simple cube with sides 2 units and mass 1.
		hkVector4 boxHalfExtents( 1.0f, 1.0f, 1.0f );  
		hkpBoxShape* geom = new hkpBoxShape( boxHalfExtents , 0 );

		const hkReal mass = 1.0f;
		hkVector4 pos( 2.0f, 5.0f, 0.0f );

		hkpRigidBodyCinfo boxInfo;
		hkMassProperties massProperties;
		hkpInertiaTensorComputer::computeBoxVolumeMassProperties(boxHalfExtents, mass, massProperties);
		boxInfo.m_mass = massProperties.m_mass;
		boxInfo.m_centerOfMass = massProperties.m_centerOfMass;
		boxInfo.m_inertiaTensor = massProperties.m_inertiaTensor;
		boxInfo.m_shape = geom;
		boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
		boxInfo.m_position = pos;
		boxInfo.m_gravityFactor = 0;

		m_boxRigidBody2 = new hkpRigidBody(boxInfo);

		// As the rigid bodies now references our shape, we no longer need to.
		geom->removeReference();

		// and add it to the world.
		mWorld->addEntity( m_boxRigidBody2 );


		//render it with Ogre
		Ogre::SceneNode* boxNode2 = mSceneMgr->getRootSceneNode()->createChildSceneNode();

		//scale
		boxNode2->scale(2, 2, 2);

		//display and sync
		Ogre::Entity *ent = mSceneMgr->createEntity(Ogre::StringConverter::toString(mLabMgr->getEntityCount()),"defCube.mesh");
		mLabMgr->setColor(ent, Ogre::Vector3(0.5538,0.3187,0.1275));
		HkOgre::Renderable* rend = new HkOgre::Renderable(boxNode2, m_boxRigidBody2,mWorld);
		boxNode2->attachObject(ent);

		//register to lab manager
		mLabMgr->registerEnity( boxNode2, m_boxRigidBody2);
	}

	//
	// Create the action and add it to the world.
	//
	{
		// hkpSpringAction applies forces to keep the two hkRigidBodies restLength apart
		// hkpSpringAction is defined in 'hkutilities/actions/spring/hkpSpringAction.h'.
		m_springAction = new hkpSpringAction(m_boxRigidBody1, m_boxRigidBody2);
		m_springAction->setPositionsInBodySpace( m_boxRigidBody1->getCenterOfMassLocal(), m_boxRigidBody2->getCenterOfMassLocal());
		m_springAction->setRestLength(6.0f);
		m_springAction->setDamping(0.3f);
		m_springAction->setStrength(10.0f);

		// Add springAction to the world. From now on springAction will automatically
		// be applied to its bodies during integration so long as the bodies are active.
		// If the bodies become inactive, antiGravityAction is not applied. If they
		// reactivate, springAction again starts applying to them.
		// springAction can also be removed using hkpWorld::removeAction(springAction)
		// after which it is no longer included in simulation.

		mWorld->addAction( m_springAction );
	}

	mWorld->unmarkForWrite();

	binaryaction_demoRunning = true;
}