예제 #1
0
hkpConvexVerticesShape* FindConvexShape(bool share_shapes, std::vector<hkpConvexVerticesShape*>& shapes, const PINT_CONVEX_CREATE& convex_create, const hkStridedVertices& strided_verts)
{
	if(share_shapes && convex_create.mRenderer)
	{
		const int size = shapes.size();
		for(int i=0;i<size;i++)
		{
			hkpConvexVerticesShape* CurrentShape = shapes[i];
			if(CurrentShape->getUserData()==hkUlong(convex_create.mRenderer))
			{
				CurrentShape->addReference();
				return CurrentShape;
			}
		}
	}

	hkpConvexVerticesShape* shape = new hkpConvexVerticesShape(strided_verts);
	ASSERT(shape);
	shapes.push_back(shape);

	if(convex_create.mRenderer)
		shape->setUserData(hkUlong(convex_create.mRenderer));

	return shape;
}
예제 #2
0
hkpBoxShape* FindBoxShape(bool share_shapes, std::vector<hkpBoxShape*>& shapes, const PINT_BOX_CREATE& box_create)
{
	const hkVector4 halfExtents = ToHkVector4(box_create.mExtents);
	if(share_shapes)
	{
		const int size = shapes.size();
		for(int i=0;i<size;i++)
		{
			hkpBoxShape* CurrentShape = shapes[i];
			const hkVector4& CurrentExtents = CurrentShape->getHalfExtents();
			if(		CurrentExtents(0)==halfExtents(0)
				&&	CurrentExtents(1)==halfExtents(1)
				&&	CurrentExtents(2)==halfExtents(2))
			{
				CurrentShape->addReference();
				return CurrentShape;
			}
		}
	}
	hkpBoxShape* shape = new hkpBoxShape(halfExtents, 0);
	ASSERT(shape);
	shapes.push_back(shape);

	if(box_create.mRenderer)
		shape->setUserData(hkUlong(box_create.mRenderer));

	return shape;
}
예제 #3
0
hkpCapsuleShape* FindCapsuleShape(bool share_shapes, std::vector<InternalCapsuleShape>& shapes, const PINT_CAPSULE_CREATE& capsule_create)
{
	const float Radius = capsule_create.mRadius;
	const float HalfHeight = capsule_create.mHalfHeight;
	if(share_shapes)
	{
		const int size = shapes.size();
		for(int i=0;i<size;i++)
		{
			const InternalCapsuleShape& CurrentShape = shapes[i];
			if(CurrentShape.mRadius==Radius && CurrentShape.mHalfHeight==HalfHeight)
			{
				CurrentShape.mShape->addReference();
				return CurrentShape.mShape;
			}
		}
	}

	const hkVector4 vertexA(0.0f, HalfHeight, 0.0f);
	const hkVector4 vertexB(0.0f, -HalfHeight, 0.0f);

	hkpCapsuleShape* shape = new hkpCapsuleShape(vertexA, vertexB, capsule_create.mRadius);
	ASSERT(shape);

	InternalCapsuleShape ICS;
	ICS.mShape		= shape;
	ICS.mRadius		= Radius;
	ICS.mHalfHeight	= HalfHeight;
	shapes.push_back(ICS);

	if(capsule_create.mRenderer)
		shape->setUserData(hkUlong(capsule_create.mRenderer));

	return shape;
}
예제 #4
0
hkpSphereShape* FindSphereShape(bool share_shapes, std::vector<hkpSphereShape*>& shapes, const PINT_SPHERE_CREATE& sphere_create)
{
	const float Radius = sphere_create.mRadius;
	if(share_shapes)
	{
		const int size = shapes.size();
		for(int i=0;i<size;i++)
		{
			hkpSphereShape* CurrentShape = shapes[i];
			if(CurrentShape->getRadius()==Radius)
			{
				CurrentShape->addReference();
				return CurrentShape;
			}
		}
	}

	hkpSphereShape* shape = new hkpSphereShape(Radius);
	ASSERT(shape);
	shapes.push_back(shape);

	if(sphere_create.mRenderer)
		shape->setUserData(hkUlong(sphere_create.mRenderer));

	return shape;
}
예제 #5
0
udword Havok::CreateConvexObject(const PINT_CONVEX_DATA_CREATE& desc)
{
	hkStridedVertices StridedVerts;
	StridedVerts.m_numVertices	= desc.mNbVerts;
	StridedVerts.m_striding		= sizeof(Point);
	StridedVerts.m_vertices		= &desc.mVerts->x;

//	hkpConvexVerticesShape* shape = FindConvexShape(gShareShapes, mConvexShapes, *ConvexCreate, StridedVerts);

	hkpConvexVerticesShape* shape = new hkpConvexVerticesShape(StridedVerts);
	ASSERT(shape);

	if(desc.mRenderer)
		shape->setUserData(hkUlong(desc.mRenderer));

	const udword CurrentSize = mConvexObjects.size();
	mConvexObjects.push_back(shape);
	return CurrentSize;

/*	btConvexHullShape* shape = new btConvexHullShape(&desc.mVerts->x, desc.mNbVerts, sizeof(Point));
	ASSERT(shape);

	if(desc.mRenderer)
		shape->setUserPointer(desc.mRenderer);

	const udword CurrentSize = mConvexObjects.size();
	mConvexObjects.push_back(shape);
	return CurrentSize;*/
}
예제 #6
0
void SlidingWorldDemo::addBodiesNewlyInsideSimulationAreaToSimulation()
{
	m_world->lock();
	hkpBroadPhase* bp = m_world->getBroadPhase();

	hkAabb broadphaseAabb;
	bp->getExtents( broadphaseAabb.m_min, broadphaseAabb.m_max);

	for (int i = 0; i < m_boxes.getSize(); i++)
	{
		hkpRigidBody* rb = m_boxes[i];

		// If we're not in simulation, check if we're now inside the simulation area/broadphase
		if( rb->getWorld() == HK_NULL )
		{		
			// In general you'd have some world object management code here. In our case, we'll just check if the current
			// aabb  of the body would be fully contained inside the new broadphase location.
			hkAabb rbAabb;
			rb->getCollidable()->getShape()->getAabb(rb->getTransform(), 0, rbAabb);

			if (broadphaseAabb.contains(rbAabb)) 
			{
				m_world->addEntity( rb );
					// Color them slightly green so they are clearly marked as newly added
				HK_SET_OBJECT_COLOR(hkUlong(rb->getCollidable()), hkColor::rgbFromChars(200, 255, 200));
			}
		}
	}

	m_world->unlock();

}
예제 #7
0
void BreakOffPartsDemo::removeSubShapeFromDisplay(hkpRigidBody* body, hkpListShape* listShape, int shapeKey)
{
		// get the vertex set
	hkgVertexSet* vertexSet;
	{
		int geometryIndex = shapeKey;
		const hkpCollidable* collidable = body->getCollidable();
		hkgDisplayObject* displayObject = m_env->m_displayHandler->findDisplayObject(hkUlong(collidable));
		hkgGeometry* geometry = displayObject->getGeometry(geometryIndex);
		hkgFaceSet* faceSet = geometry->getMaterialFaceSet(0)->getFaceSet(0);
		vertexSet = faceSet->getVertexSet();
	}

		// Simply zero-out all vertices. This will degenerate the triangles but that should be ok.
	{
		m_env->m_window->getContext()->lock();
		vertexSet->lock(HKG_LOCK_WRITEDISCARD);
		hkVector4 newPos(0,0,0);
		for (int i = 0; i < vertexSet->getNumVerts(); i++)
		{
			vertexSet->setVertexComponentData(HKG_VERTEX_COMPONENT_POS, i, &newPos(0));
		}
		vertexSet->unlock();
		m_env->m_window->getContext()->unlock();
	}
}
예제 #8
0
InteractiveFloor::InteractiveFloor(Ogre::Vector3 Pos, Ogre::Vector3 size, Physics * physics, Ogre::SceneManager * manager)
	:Floor(Pos,
		size,
		physics,
		manager)
{
	Body->setUserData(hkUlong(this));
}
void PlatformsCharacterRbDemo::cameraHandling()
{
	const hkReal height = .7f;
	hkVector4 forward;
	forward.set(1,0,0);
	forward.setRotatedDir( m_currentOrient, forward );

	hkVector4 from, to;
	to = m_characterRigidBody->getPosition();
	to.addMul4(height, UP );

	hkVector4 dir;
	dir.setMul4( height, UP );
	dir.addMul4( -8.f, forward);

	from.setAdd4(to, dir);

	// Make object in line of sight transparent
	{
		// Cast down to landscape to get an accurate position
		hkpWorldRayCastInput raycastIn;

		// Reverse direction for collision detection
		raycastIn.m_from = to;
		raycastIn.m_to = from;
		raycastIn.m_filterInfo = hkpGroupFilter::calcFilterInfo(0);

		hkpAllRayHitCollector collector;

		m_world->castRay( raycastIn, collector);

		hkLocalArray<hkUlong>	transp(5);

		// Loop over all collected objects
		for(int i=0; i < collector.getHits().getSize();i++)
		{
			hkpWorldRayCastOutput raycastOut = collector.getHits()[i];

			transp.pushBack(hkUlong(raycastOut.m_rootCollidable));
		}

		// loop over display ids
		for(int i=0; i < m_objectIds.getSize();i++)
		{
			if(transp.indexOf(m_objectIds[i]) != -1)
			{
				HK_SET_OBJECT_COLOR(m_objectIds[i], TRANSPARENT_GREY);
			}
			else
			{
				HK_SET_OBJECT_COLOR(m_objectIds[i],NORMAL_GRAY);
			}
		}

	}

	setupDefaultCameras(m_env, from , to, UP, 1.0f);
}
예제 #10
0
InteractiveWall::InteractiveWall(Ogre::Vector3 Pos, Ogre::Vector3 size,Physics * physics, Ogre::SceneManager * manager, float rotation)
	: Wall(Pos,
			size,
			physics,
			manager,
			rotation)
{
	Body->setUserData(hkUlong(this));
}
예제 #11
0
Wall::Wall(Ogre::Vector3 Pos, Ogre::Vector3 size,Physics * physics, Ogre::SceneManager * manager, float rotation)
	: StaticObject(Pos,
					Ogre::Vector3(size.x, size.y, 20.0f),
					"cube.mesh",
					physics,
					manager)
{
	mOrintation = Ogre::Quaternion(Ogre::Radian(Ogre::Degree(rotation)), Ogre::Vector3(0,1,0));
	hkVector4 HalfSize( mSize.x / 2.0, mSize.y / 2.0, mSize.z / 2.0);
	hkpBoxShape* Hbox =						new hkpBoxShape(HalfSize,0);
	Hbox->setRadius(0.0f);
	
	hkpRigidBodyCinfo						WallInfo;
	WallInfo.m_mass =						100.0f;
	hkMassProperties massProperties;
	hkpInertiaTensorComputer::computeBoxVolumeMassProperties(
		HalfSize, WallInfo.m_mass, massProperties);
	WallInfo.m_mass =						massProperties.m_mass;
	WallInfo.m_centerOfMass =				massProperties.m_centerOfMass;
	WallInfo.m_inertiaTensor =				massProperties.m_inertiaTensor;
	WallInfo.m_solverDeactivation =			WallInfo.SOLVER_DEACTIVATION_MEDIUM;
	WallInfo.m_shape =						Hbox;
	WallInfo.m_restitution =				0.0f;
	WallInfo.m_qualityType =				HK_COLLIDABLE_QUALITY_FIXED;
	WallInfo.m_motionType =					hkpMotion::MOTION_FIXED;
	WallInfo.m_rotation =					hkQuaternion(mOrintation.x, mOrintation.y, mOrintation.z, mOrintation.w);
	WallInfo.m_position = 					hkVector4(mPosition.x,mPosition.y,mPosition.z);
	Body =									new hkpRigidBody(WallInfo);
	Body->setUserData(hkUlong(this));
	mPhysicsManager->GetPhysicsWorld()->addEntity(Body);
	ObjectNode->setScale(mSize.x / ObjectEnt->getBoundingBox().getSize().x,
		mSize.y / ObjectEnt->getBoundingBox().getSize().y, mSize.z / ObjectEnt->getBoundingBox().getSize().z);
	ObjectNode->setPosition(Ogre::Vector3(Body->getPosition()(0), Body->getPosition()(1),Body->getPosition()(2)));
	ObjectEnt->setMaterialName("Examples/RustySteel");
	hkQuaternion GetBodyAngle = Body->getRotation();
	hkVector4 GetrotationAxis(0,0,0);
	if(GetBodyAngle.hasValidAxis())
	{
		GetBodyAngle.getAxis(GetrotationAxis);
	}
	Ogre::Quaternion UpdateOrintation(Ogre::Radian(GetBodyAngle.getAngle()), Ogre::Vector3(GetrotationAxis(0),GetrotationAxis(1),GetrotationAxis(2)));
	ObjectNode->setOrientation(UpdateOrintation);
}
예제 #12
0
Turret::Turret(Ogre::Vector3 Pos, Ogre::SceneManager* manager, Physics* physicsManager)
		:	DynamicObject( Pos,
						"cube.mesh",
						Ogre::Vector3(20.0,50.0,20.0),
						Ogre::Quaternion( Ogre::Radian(0), Ogre::Vector3(0,1,0)),
						manager,
						physicsManager )
				,mRotateValue(0)
				,mChangeInRotation(0.001)
				,mKillTimer(0)
				,mShutdown(false)
{
	hkVector4 HalfSize( mSize.x / 2.0, mSize.y / 2.0, mSize.z / 2.0);
	hkpBoxShape* Hbox =						new hkpBoxShape(HalfSize,0);
	Hbox->setRadius(0.0f);
	
	hkpRigidBodyCinfo						TurretInfo;
	TurretInfo.m_mass =						5000.0f;
	hkMassProperties massProperties;
	hkpInertiaTensorComputer::computeBoxVolumeMassProperties(
		HalfSize, TurretInfo.m_mass, massProperties);
	TurretInfo.m_mass =						massProperties.m_mass;
	TurretInfo.m_centerOfMass =				hkVector4(massProperties.m_centerOfMass(0),massProperties.m_centerOfMass(1) - 20,massProperties.m_centerOfMass(2));
	TurretInfo.m_inertiaTensor =			massProperties.m_inertiaTensor;
	TurretInfo.m_solverDeactivation =		TurretInfo.SOLVER_DEACTIVATION_MEDIUM;
	TurretInfo.m_shape =					Hbox;
	TurretInfo.m_restitution =				0.0f;
	TurretInfo.m_qualityType =				HK_COLLIDABLE_QUALITY_MOVING;
	TurretInfo.m_motionType =				hkpMotion::MOTION_BOX_INERTIA;
	TurretInfo.m_rotation =					hkQuaternion(mOrintation.x, mOrintation.y, mOrintation.z, mOrintation.w);
	TurretInfo.m_position = 				hkVector4(mPosition.x,mPosition.y,mPosition.z);
	Body =									new hkpRigidBody(TurretInfo);
	Body->setUserData(hkUlong(this));
	mPhysicsManager->GetPhysicsWorld()->addEntity(Body);
	ObjectNode->setScale(mSize.x / ObjectEnt->getBoundingBox().getSize().x,
		mSize.y / ObjectEnt->getBoundingBox().getSize().y, mSize.z / ObjectEnt->getBoundingBox().getSize().z);
	ObjectNode->setPosition(Ogre::Vector3(Body->getPosition()(0), Body->getPosition()(1),Body->getPosition()(2)));
}
예제 #13
0
hkpShape* CreateMeshShape(const PINT_MESH_CREATE& create, HavokMeshFormat format, std::vector<HavokMeshRender>& meshes, PintShapeRenderer* renderer)
{
	if(/*gShareMeshData &&*/renderer)
	{
		const udword Size = meshes.size();
		for(udword i=0;i<Size;i++)
		{
			const HavokMeshRender& CurrentMesh = meshes[i];
			if(CurrentMesh.mRenderer==renderer)
			{
				return CurrentMesh.mTriangleMesh;
			}
		}
	}

	hkpShape* S = CreateMeshShape(create, format);
	meshes.push_back(HavokMeshRender(S, renderer));

	if(create.mRenderer)
		S->setUserData(hkUlong(create.mRenderer));

	return S;
}
예제 #14
0
Create::Create(Ogre::Vector3 Pos, Ogre::SceneManager* manager, Physics* physicsManager)
	:	DynamicObject( Pos,
						"cube.mesh",
						Ogre::Vector3(34.0,34.0,34.0),
						Ogre::Quaternion( Ogre::Radian(0), Ogre::Vector3(0,1,0)),
						manager,
						physicsManager )
						,Hit(false)
{
	hkVector4 HalfSize( mSize.x / 2.0, mSize.y / 2.0, mSize.z / 2.0);
	hkpBoxShape* Hbox =						new hkpBoxShape(HalfSize,0);
	Hbox->setRadius(0.0f);
	
	hkpRigidBodyCinfo						CreateInfo;
	CreateInfo.m_mass =						100.0f;
	hkMassProperties massProperties;
	hkpInertiaTensorComputer::computeBoxVolumeMassProperties(
		HalfSize, CreateInfo.m_mass, massProperties);
	CreateInfo.m_mass =						massProperties.m_mass;
	CreateInfo.m_centerOfMass =				massProperties.m_centerOfMass;
	CreateInfo.m_inertiaTensor =			massProperties.m_inertiaTensor;
	CreateInfo.m_solverDeactivation =		CreateInfo.SOLVER_DEACTIVATION_MEDIUM;
	CreateInfo.m_shape =					Hbox;
	CreateInfo.m_restitution =				0.0f;
	CreateInfo.m_qualityType =				HK_COLLIDABLE_QUALITY_MOVING;
	CreateInfo.m_motionType =				hkpMotion::MOTION_BOX_INERTIA;
	CreateInfo.m_rotation =					hkQuaternion(mOrintation.x, mOrintation.y, mOrintation.z, mOrintation.w);
	CreateInfo.m_position = 				hkVector4(mPosition.x,mPosition.y,mPosition.z);
	Body =									new hkpRigidBody(CreateInfo);
	Body->setUserData(hkUlong(this));
	RecptorFront = mOrintation * Ogre::Vector3::UNIT_X;
	RecptorSide = mOrintation * Ogre::Vector3::UNIT_Z;
	mPhysicsManager->GetPhysicsWorld()->addEntity(Body);
	ObjectNode->setScale(mSize.x / ObjectEnt->getBoundingBox().getSize().x,
		mSize.y / ObjectEnt->getBoundingBox().getSize().y, mSize.z / ObjectEnt->getBoundingBox().getSize().z);
	ObjectNode->setPosition(Ogre::Vector3(Body->getPosition()(0), Body->getPosition()(1),Body->getPosition()(2)));
}
예제 #15
0
BallAndSocketRopeDemo::BallAndSocketRopeDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE)
{
	const BallAndSocketRopeVariant& variant = g_variants[env->m_variantId];

	//
	// Setup the camera
	//
	{
		hkVector4 from(0.0f, -10.0f, 6.0f);
		hkVector4 to  (0.0f, 0.0f, 1.0f);
		hkVector4 up  (0.0f, 0.0f, 1.0f);
		setupDefaultCameras( env, from, to, up, 0.1f, 500.0f );
	}

	//
	// Create the world
	//
	{
		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize( 1000.0f );
		info.m_gravity.set(0.0f, 0.0f, -9.81f);
		m_world = new hkpWorld( info );
		m_world->lock();
		m_world->m_wantDeactivation = false;

		setupGraphics();

		//
		// Create a group filter to avoid intra-collision for the rope
		//
		{
			hkpGroupFilter* filter = new hkpGroupFilter();
			m_world->setCollisionFilter( filter );
			filter->removeReference();
		}

	}

	hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() );


	//
	// Create debris
	//
	
	{
		int numDebris = 40;

		hkPseudoRandomGenerator generator(0xF14);

		hkpRigidBodyCinfo info;
		hkVector4 top; top.set(0.0f, 0.0f, 0.50f);
		hkVector4 bottom; bottom.set(0.f, 0.f, -0.50f);
		info.m_shape = new hkpCapsuleShape( top, bottom, 0.3f );
		hkpInertiaTensorComputer::setShapeVolumeMassProperties( info.m_shape, 5.0f, info );

		for (int d = 0; d < numDebris; d++)
		{
			hkReal xPos = generator.getRandRange(-10.0f, 10.0f);
			hkReal yPos = generator.getRandRange(-10.0f, 10.0f);

			hkBool isDynamic = (generator.getRand32() % 4) != 0;
			info.m_position.set( xPos, yPos, isDynamic ? 0.8f : 0.5f );

			info.m_motionType = isDynamic ? hkpMotion::MOTION_DYNAMIC : hkpMotion::MOTION_FIXED;

			hkpRigidBody* debris = new hkpRigidBody(info);
			m_world->addEntity(debris);
			debris->removeReference();
		}
		info.m_shape->removeReference();
	}

	//
	// Create ground box
	//
	{
		hkpRigidBodyCinfo info;
		info.m_motionType = hkpMotion::MOTION_FIXED;
		info.m_shape = new hkpBoxShape( hkVector4(100.0f, 100.0f, 0.1f) );
		info.m_position(2) = - 0.1f;

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

		m_world->addEntity(ground);
		ground->removeReference();

		HK_SET_OBJECT_COLOR( hkUlong(ground->getCollidable()), 0xff339933);
	}

	//
	// Create fixed peg over the ground
	//
	{
		hkpRigidBodyCinfo info;
		info.m_motionType = hkpMotion::MOTION_FIXED;
		info.m_shape = new hkpCapsuleShape( hkVector4(0.0f, 1.0f, 0.0f), hkVector4( 0,-1.0f, 0), 0.3f );
		info.m_position.set(0.0f, 0.0f, 3.0f);

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

		m_world->addEntity(peg);
		peg->removeReference();
	}



	//
	// Create chain
	//
	{
		hkReal elemHalfSize = 0.075f;
		hkpShape* sphereShape = new hkpSphereShape(0.3f); 
		hkpShape* capsuleShape = new hkpCapsuleShape( hkVector4(elemHalfSize, 0.0f, 0.0f), hkVector4(-elemHalfSize, 0.0f, 0.0f), 0.03f );

		hkpRigidBodyCinfo info;

		info.m_linearDamping = 0.0f;
		info.m_angularDamping = 0.3f;
		info.m_friction = 0.0f;
		//info.m_qualityType = HK_COLLIDABLE_QUALITY_MOVING;
		info.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA;
		info.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(1, 1);


		{
			hkArray<hkpRigidBody*> entities;
		
			for (int b = 0; b < variant.m_numBodies; b++)
			{
				info.m_position.set(elemHalfSize * 2.0f * (b - hkReal(variant.m_numBodies-1) / 2.0f), 0.0f, 4.0f);

				hkReal mass;
				hkReal inertiaMultiplier;
				if (0 == b || variant.m_numBodies-1 == b)
				{
					info.m_shape = sphereShape;
					mass  = 10.0f;
					inertiaMultiplier = 1.0f;
				}
				else
				{
					info.m_shape = capsuleShape;
					mass  = 1.0f;
					inertiaMultiplier = 50.0f;
				}
				hkpInertiaTensorComputer::setShapeVolumeMassProperties(info.m_shape, inertiaMultiplier * mass, info);
				info.m_mass = mass;


				{
					hkpRigidBody* body = new hkpRigidBody(info);
					m_world->addEntity(body);
					entities.pushBack(body);
				}
			}
	
			{
				// connect all the bodies
				hkpConstraintChainInstance* chainInstance;
				{
					hkpBallSocketChainData* chainData = new hkpBallSocketChainData();
					chainInstance = new hkpConstraintChainInstance( chainData );

					chainInstance->addEntity( entities[0] );
					for (int e = 1; e < entities.getSize(); e++)
					{
						chainData->addConstraintInfoInBodySpace( hkVector4(elemHalfSize, 0.0f, 0.0f), hkVector4( -elemHalfSize, 0.0f, 0.0f) );
						chainInstance->addEntity( entities[e] );
					}
					chainData->removeReference();
				}

				m_world->addConstraint(chainInstance);
				chainInstance->removeReference();
			}

			for (int i = 0; i < entities.getSize(); i++)
			{
				entities[i]->removeReference();
			}
		}
		sphereShape->removeReference();
		capsuleShape->removeReference();
	}

	m_world->unlock();
}
void ConcreteFractureCollisionListener::contactPointConfirmedCallback( hkpContactPointConfirmedEvent& event)
{
	m_randomSeed++;

		// Check whether our velocity is strong enough to fracture the body.
		// You might also want to check the type of object, the mass, volume and the material
		// (soft ball hardly fractures a piece of glass)
	if (event.m_projectedVelocity < -m_fractureVelocity )
	{
			//
			// get and fix the direction of the normal;
			//
		hkContactPoint cp = *event.m_contactPoint;
		if (event.m_callbackFiredFrom->getCollidable() == event.m_collidableA)
		{
			hkVector4 tmp; tmp.setNeg4(cp.getSeparatingNormal());
			cp.setSeparatingNormal(tmp);
		}

			// get the hitting body, e.g. the bullet
		hkpRigidBody* otherBody = reinterpret_cast<hkpRigidBody*>(hkUlong(event.m_callbackFiredFrom) ^ hkUlong(event.m_collidableA->getOwner()) ^ hkUlong(event.m_collidableB->getOwner()));

			// Remember the bullets velocity so we can revert the bullet body back to its original velocity.
			//
			// The reasons is:
			//  - that this callback is called just before the bullet's velocities are updated
			//    (either in the PSI-integrate step or in a TOI-event-handling function), 
			//  - and at the world is locked at the time of this callback, so the bullet still interacts with the old/original
			//    unfractured body (instead of with the intended fractured pieces),
			// 
			// So, to have a 'more' proper fracturing interaction we do:
			//  - reset the velocity of the fracturing bullet once the fractured body is replaced by 
			//    its resulting pieces and the world is unlocked,
			//  - reintegrate and re-collide the bullet body, so that it collides with the fractured pieces
			//
		hkVector4 linearVel = otherBody->getLinearVelocity();
		hkVector4 angularVel = otherBody->getAngularVelocity();
		SetBodyVelocityAsCriticalOperation* callback = new SetBodyVelocityAsCriticalOperation(otherBody, linearVel, angularVel, true);

			//
			// Fracture the piece
			// 
		hkpRigidBody* originalBody = static_cast<hkpRigidBody*>(event.m_callbackFiredFrom);
		HK_ASSERT2(0xad23eb33, originalBody, "This listener must be attached as a hkpEntity-CollisonListener.");
		originalBody->removeCollisionListener(this);
		hkpWorld* world = otherBody->getWorld();
		hkInplaceArray<hkpRigidBody*, 32> newBodies;
		createFracturedRigidBodyPieces(world, originalBody, cp, newBodies);

			//
			// Replace the body with fractured pieces.
			//
		world->removeEntity(originalBody);
		world->addEntityBatch(reinterpret_cast<hkpEntity**>(newBodies.begin()), newBodies.getSize());

			//
			//	Add our undo velocities to the delayed operation queue. It will be executed as
			//  soon as all our fractured pieces are all added to the world.
			//
		if (!otherBody->isFixedOrKeyframed() )
		{
			if (!event.m_callbackFiredFrom->isFixedOrKeyframed())
			{
				// Warning: this can cause multiple TOI events. It is not safe with fixedOrKeyframed bodies. 
				world->queueCallback(callback);
			}
		}
		callback->removeReferenceLockUnchecked();

		//
		// If an external hkArray<hkpRigidBody*> is supplied then export the references to new bodies.
		//
		if (m_fracturedBodies)
		{
			m_fracturedBodies->insertAt(m_fracturedBodies->getSize(), newBodies.begin(), newBodies.getSize() );
		}
		else
		{
			for (int i = 0; i < newBodies.getSize(); i++)
			{
				newBodies[i]->removeReference();
			}
		}

	}
}
예제 #17
0
void hkFlattenShapeHierarchyUtil::getLeafShapesFromShape(const hkpShape* shape, const hkTransform& transform, const hkBool isFixedBody, hkArray<hkpExtendedMeshShape::TrianglesSubpart>& trianglePartsOut, hkArray<hkpConvexShape*>& convexShapesOut, hkArray<hkpShape*>& otherShapesOut)
{
	const hkpShapeType type = shape->getType();

	hkTransform newTransform;

	const hkpShape* childShape = HK_NULL;
	hkUlong userData = HK_NULL;

	switch(type)
	{
	case HK_SHAPE_LIST:
	case HK_SHAPE_CONVEX_LIST:
		{
			const hkpShapeContainer* container = shape->getContainer();
			hkpShapeContainer::ShapeBuffer buffer;

			HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(shape->getUserData())), "We're dropping a non-zero lookupIndex from user data.");
			hkUint16 materialId = hkUint16(0xffff & hkUlong(shape->getUserData()));

			for (hkpShapeKey key = container->getFirstKey(); key != HK_INVALID_SHAPE_KEY; key = container->getNextKey(key))
			{
				const hkpShape* child = container->getChildShape(key, buffer);

				if (materialId && 0 == (0xffff & hkUlong(child->getUserData())) )
				{
					// no material id for the child -- copy it
					hkUlong childData = hkUlong(child->getUserData()) | materialId;
					// Warning: modifying the const input hkpShape*
					const_cast<hkpShape*>(child)->setUserData(childData);
				}
				//HK_ASSERT2(0xad6777dd, isFixedBody || !isLeafShape(child), "A child of a list shape cannot be a terminal node. You must use a transform shape in between." );
				getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut);
			}
		}
		break;
	case HK_SHAPE_TRANSFORM:
		{
			const hkpTransformShape* transformShape = static_cast<const hkpTransformShape*>(shape);
			newTransform.setMul(transform, transformShape->getTransform());
			childShape = transformShape->getChildShape();
			userData = hkUlong(transformShape->getUserData());
		}
		break;
	case HK_SHAPE_CONVEX_TRANSFORM:
		{
			const hkpConvexTransformShape* convexTransformShape = static_cast<const hkpConvexTransformShape*>(shape);
			newTransform.setMul(transform, convexTransformShape->getTransform());
			childShape = convexTransformShape->getChildShape();
			userData = hkUlong(convexTransformShape->getUserData());
		}
		break;
	case HK_SHAPE_CONVEX_TRANSLATE:
		{
			const hkpConvexTranslateShape* convexTranslateShape = static_cast<const hkpConvexTranslateShape*>(shape);
			hkTransform localTransform( static_cast<const hkRotation&>(hkRotation::getIdentity()), convexTranslateShape->getTranslation() );
			newTransform.setMul(transform, localTransform);
			childShape = convexTranslateShape->getChildShape();
			userData = hkUlong(convexTranslateShape->getUserData());
		}
		break;

	case HK_SHAPE_BV_TREE:
		{
			const hkpBvTreeShape* bvTreeshape = static_cast<const hkpBvTreeShape*>(shape);	
			HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data.");

			const hkpShapeContainer* container = bvTreeshape->getContainer();
			for (hkpShapeKey key = container->getFirstKey(); key!= HK_INVALID_SHAPE_KEY; key = container->getNextKey(key))
			{
				hkpShapeContainer::ShapeBuffer buffer;
				const hkpShape* child = container->getChildShape(key, buffer);
				const hkpShapeType childType = child->getType();
				if ((childType == HK_SHAPE_LIST) || (childType == HK_SHAPE_CONVEX_LIST))
				{
					getLeafShapesFromShape(child, transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut);
				}
			}

			break;
		}
	case HK_SHAPE_MOPP:
		{
			const hkpMoppBvTreeShape* bvTreeshape = static_cast<const hkpMoppBvTreeShape*>(shape);	
		//	HK_ASSERT2(0xad67da22, 0 == (0xffff0000 & hkUlong(bvTreeshape->getUserData())), "We're dropping a non-zero lookupIndex from user data.");
			getLeafShapesFromShape(bvTreeshape->getShapeCollection(), transform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut);

			break;
		}

	default:
		{
			//HK_ASSERT2(0xad67ddaa, isFixedBody, "A child of a list was attached without an intermediate transform shape. This is not handled.");
			
			// We can get simple shapes without transforms when processing fixed bodies. We do add a hkpConvexTransformShape as usual then ...
			childShape = shape;
			newTransform = transform;
			userData = hkUlong(shape->getUserData());
			//HK_ASSERT2(0XAD678D8D, 0 == (userData & 0xffff0000), "Userdata of a fixed body (other than the one fixed uber body) has a non-zero destructible info index.");
		}
		break;
	}

	if (HK_NULL != childShape)
	{
		hkBool leafDone = false;
		if (hkOneFixedMoppUtil::isTerminalConvexShape(childShape))
		{
			// Create new transform shape to wrap the child terminal shape
			hkpConvexTransformShape* newConvexTransformShape = new hkpConvexTransformShape(static_cast<const hkpConvexShape*>(childShape), newTransform);
			newConvexTransformShape->setUserData( userData );

			HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data.");
			HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape.");

			// put this transform on the shapesOut list
			convexShapesOut.pushBack(newConvexTransformShape);
			leafDone = true;
		}
		else if (isLeafShape(childShape))
		{
				// It's not a terminal(leaf?) convex shape, but it might be a mesh, or indeed a simplemesh.
				// It's most likely to be a storagemesh, but we can't assume that, so check vtable:
			const hkClass* childShapeClass = hkBuiltinTypeRegistry::getInstance().getVtableClassRegistry()->getClassFromVirtualInstance(childShape);
			if( hkpMeshShapeClass.isSuperClass(*childShapeClass) )
			{
				const hkpMeshShape* mesh = static_cast<const hkpMeshShape*>(childShape);

				// Confirm vertex data not shared, see below
#if defined(HK_DEBUG)
				{
					for(int i = 0; i < mesh->getNumSubparts(); i++)
					{
						const hkpMeshShape::Subpart& meshSubPartI = mesh->getSubpartAt(i);
						for(int j = i+1; j < mesh->getNumSubparts(); j++)
						{
							const hkpMeshShape::Subpart& meshSubPartJ = mesh->getSubpartAt(j);
							HK_ASSERT2(0x0, meshSubPartI.m_vertexBase != meshSubPartJ.m_vertexBase, "This method can't (currently) collapse chared meshs data as it collpases the transform into the verts\n");
						}
						
					}
				}
#endif

				for(int i = 0; i < mesh->getNumSubparts(); i++)
				{
					const hkpMeshShape::Subpart& meshSubPart = mesh->getSubpartAt(i);
					// Now we have the subpart. We can't know if the data pointed to is 'owned' by the mesh (eg. subclass hkpStorageMeshShape)
					// or 'pointed to' (base class hkpMeshShape)
					//
					// We'll just assume here we can 'share' the data by grabbing the pointers...

					hkpExtendedMeshShape::TrianglesSubpart extendedMeshSubPart;
					
					extendedMeshSubPart.m_vertexBase = meshSubPart.m_vertexBase;
					extendedMeshSubPart.m_vertexStriding = meshSubPart.m_vertexStriding;
					extendedMeshSubPart.m_numVertices = meshSubPart.m_numVertices;
					extendedMeshSubPart.m_triangleOffset = meshSubPart.m_triangleOffset;

					// .. but we'll have to multiply in the transform! This assumes the vertex data is not shared!
					{
						for(int j = 0; j < extendedMeshSubPart.m_numVertices ; j++)
						{
							hkVector4 v;
							v(0) = extendedMeshSubPart.m_vertexBase[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j];
							v(1) = extendedMeshSubPart.m_vertexBase[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j];
							v(2) = extendedMeshSubPart.m_vertexBase[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j];
							v.setTransformedPos(transform, v);
							const_cast<float*>(extendedMeshSubPart.m_vertexBase)[0 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(0);
							const_cast<float*>(extendedMeshSubPart.m_vertexBase)[1 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(1);
							const_cast<float*>(extendedMeshSubPart.m_vertexBase)[2 + extendedMeshSubPart.m_vertexStriding/sizeof(float) * j] = v(2);
						}
					}

					extendedMeshSubPart.m_indexBase = meshSubPart.m_indexBase;
					extendedMeshSubPart.m_indexStriding = meshSubPart.m_indexStriding;
					extendedMeshSubPart.m_numTriangleShapes = meshSubPart.m_numTriangles;
					extendedMeshSubPart.m_stridingType = (meshSubPart.m_stridingType == hkpMeshShape::INDICES_INT16) ? hkpExtendedMeshShape::INDICES_INT16 : hkpExtendedMeshShape::INDICES_INT32;

					trianglePartsOut.pushBack(extendedMeshSubPart);

					leafDone = true;
				}
			}
		}

		if(!leafDone)
		{
			HK_WARN(0xad678dda, "An extra hkTransform shape has been inserted into the hierarchy. This might be suboptimal.");
			// Create new transform shape to wrap the child terminal shape
			hkpTransformShape* newTransformShape = new hkpTransformShape(childShape, newTransform);
			newTransformShape->setUserData( userData );

			HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data.");
			HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & userData) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape.");

			// put this transform on the shapesOut list
			otherShapesOut.pushBack(newTransformShape);
			leafDone = true;
		}

		if(!leafDone)
		{
			//HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & shape->getUserData()), "We're dropping a non-zero user data.");
			if ( 0xffff0000 & hkUlong(shape->getUserData()) )
			{
				// copy the destruction info index downwards..
				HK_ASSERT2(0xad67da23, 0 == (0xffff0000 & hkUlong(childShape->getUserData())) || (0xffff0000 & userData) == (0xffff0000 & hkUlong(childShape->getUserData())), "We're dropping a non-zero user data.");
				HK_ASSERT2(0xad67da24, 0 == (0xffff & hkUlong(childShape->getUserData())) || (0xffff & hkUlong(shape->getUserData())) == (0xffff & hkUlong(childShape->getUserData())), "Materials differ in the terminal shape and its wrapping hkpTransformShape.");

				//HK_WORLD_ACCESS_CHECK(parentBody->getWorld(), HK_ACCESS_RW );
				// Warning: we're actually modifying the const hkpShape* passed as an input parameter
				const_cast<hkpShape*>(childShape)->setUserData( shape->getUserData() );
			}
			getLeafShapesFromShape(childShape, newTransform, isFixedBody, trianglePartsOut, convexShapesOut, otherShapesOut);
		}
	}
}
CrashTestDummiesDemo::CrashTestDummiesDemo(hkDemoEnvironment* env): hkDefaultPhysicsDemo( env )
{
    // Disable warnings:
    hkError::getInstance().setEnabled(0xafe97523, false); //'This utility is intended primarily for Havok demo use. If you wish to step the world asynchronously,...'

    // XXX remove once async stepping fixed
    hkpWorld::IgnoreForceMultithreadedSimulation ignoreForceMultithreaded;

    enableDisplayingToiInformation(true);

    m_ragdoll = HK_NULL;

    //
    //	Create the world
    //
    {
        hkpWorldCinfo info;
        info.m_gravity.set( 0.0f, 0.0f, -10.0f );
        //info.m_enableDeactivation = false;
        info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_CONTINUOUS;
        //info.m_simulationType = hkpWorldCinfo::SIMULATION_TYPE_BACKSTEP_SIMPLE;
        m_world = new hkpWorld( info );
        m_world->lock();

        // Register ALL agents (though some may not be necessary)
        hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher());
    }

    //
    // Collision Filter
    //
    {
        m_filter = new hkpGroupFilter();
        hkpGroupFilterSetup::setupGroupFilter( m_filter );
        m_world->setCollisionFilter(m_filter);
    }

    //
    // Setup the camera
    //
    {
        hkVector4 from(0.0f, 8.0f, 3.0f);
        hkVector4 to(0.0f, 0.0f, 1.0f);
        hkVector4 up(0.0f, 0.0f, 1.0f);
        setupDefaultCameras( env, from, to, up, 1.f, 1000.0f );

        setupGraphics();
    }

    m_car =	createSimpleCarHull();
    m_world->addEntity( m_car )->removeReference();
    HK_SET_OBJECT_COLOR(hkUlong(m_car->getCollidable()), hkColor::rgbFromChars(255, 255, 255, 50));

    fitRagdollsIn(hkVector4::getZero());
    //hkVector4 pos(3.0f, 1.0f, 0.8f);
    //putBoxesIn( pos );
    //putBoxesIn(hkVector4(4.1f, 1.0f, 0.8f));

    createGroundBox();
    createFastObject();

    m_world->unlock();
}
PlatformsCharacterRbDemo::PlatformsCharacterRbDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{

	// Setup the graphics
	{
		// Disable back face culling
		setGraphicsState(HKG_ENABLED_CULLFACE, false);

		// don't really want shadows as makes it too dark
		forceShadowState(false);

		setupLights(m_env); // so that the extra lights are added

		// allow color change on precreated objects
		m_env->m_displayHandler->setAllowColorChangeOnPrecreated(true);
	}

	// Create the world
	{
		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize( 350.0f );
		info.m_gravity.set(0,0,-9.8f);
		info.m_collisionTolerance = 0.01f;
		m_world = new hkpWorld( info );
		m_world->lock();

		hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher());

		setupGraphics();
	}

	// Load the level
	{
		m_loader = new hkLoader();

		hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Physics/levels/test_platform.hkx");
		hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
		HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset");
		hkxScene* scene = reinterpret_cast<hkxScene*>( container->findObjectByType( hkxSceneClass.getName() ));

		HK_ASSERT2(0x27343635, scene, "No scene loaded");
		env->m_sceneConverter->convert( scene, hkgAssetConverter::CONVERT_ALL );

		hkpPhysicsData* physics = reinterpret_cast<hkpPhysicsData*>( container->findObjectByType( hkpPhysicsDataClass.getName() ));
		HK_ASSERT2(0x27343635, physics, "No physics loaded");

		// Physics
		if (physics)
		{
			const hkArray<hkpPhysicsSystem*>& psys = physics->getPhysicsSystems();

			// Tie the two together
			for (int i=0; i<psys.getSize(); i++)
			{
				hkpPhysicsSystem* system = psys[i];

				// Change the layer of the rigid bodies
				for (int rb=0; rb < system->getRigidBodies().getSize(); rb++)
				{
					const hkUlong id = hkUlong(system->getRigidBodies()[rb]->getCollidable());
					HK_SET_OBJECT_COLOR(id,NORMAL_GRAY);
					m_objectIds.pushBack(id);
				}

				// Associate the display and physics (by name)
				if (scene)
				{
					addPrecreatedDisplayObjectsByName( psys[i]->getRigidBodies(), scene );
				}

				// add the lot to the world
				m_world->addPhysicsSystem(system);
			}
		}
	}

	// Add horizontal keyframed platform
	{

		hkpShape* platform = new hkpBoxShape(hkVector4(1.5,2.5,0.25));

		hkpRigidBodyCinfo rbci;
		rbci.m_shape = platform;
		rbci.m_motionType = hkpMotion::MOTION_KEYFRAMED;
		rbci.m_position.set(2.5f, 0.0f, 0.25f);
		rbci.m_friction = 1.0f;
		rbci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1));

		m_horPlatform = new hkpRigidBody(rbci);

		platform->removeReference();
		m_world->addEntity(m_horPlatform);
		m_horPlatform->removeReference();

	}

	// Add vertical keyframed platform
	{
		hkpShape* platform = new hkpBoxShape(hkVector4(1.5,2.5,0.25));

		hkpRigidBodyCinfo rbci;
		rbci.m_shape = platform;
		rbci.m_motionType = hkpMotion::MOTION_KEYFRAMED;
		rbci.m_position.set(-3.5f, 0.0f, 3.25f);
		rbci.m_friction = 1.0f;
		rbci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(hkpGroupFilter::calcFilterInfo(1));

		m_verPlatform = new hkpRigidBody(rbci);

		platform->removeReference();
		m_world->addEntity(m_verPlatform);
		m_verPlatform->removeReference();
	}

	//	Create a character rigid body
	{
		// Create a capsule to represent the character standing
		hkVector4 vertexA(0,0, 0.4f);
		hkVector4 vertexB(0,0,-0.4f);
	
		m_standShape = new hkpCapsuleShape(vertexA, vertexB, .6f);

		// Construct a character rigid body
		hkpCharacterRigidBodyCinfo info;
		info.m_mass = 100.0f;
		info.m_shape = m_standShape;

		info.m_maxForce = 1000.0f;
		info.m_up = UP;
		info.m_position.set(0.0f, 5.0f, 1.5f);
		info.m_maxSlope = HK_REAL_PI/2.0f;

		m_characterRigidBody = new hkpCharacterRigidBody( info );
		m_world->addEntity( m_characterRigidBody->getRigidBody() );

	}
	
	// Create the character state machine
	{
		hkpCharacterState* state;
		hkpCharacterStateManager* manager = new hkpCharacterStateManager();

		state = new hkpCharacterStateOnGround();
		manager->registerState( state,	HK_CHARACTER_ON_GROUND);
		state->removeReference();

		state = new hkpCharacterStateInAir();
		manager->registerState( state,	HK_CHARACTER_IN_AIR);
		state->removeReference();

		state = new hkpCharacterStateJumping();
		manager->registerState( state,	HK_CHARACTER_JUMPING);
		state->removeReference();

		state = new hkpCharacterStateClimbing();
		manager->registerState( state,	HK_CHARACTER_CLIMBING);
		state->removeReference();

		m_characterContext = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND);
		m_characterContext->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY);
		manager->removeReference();
	}

	// Set colors of platforms
	HK_SET_OBJECT_COLOR(hkUlong(m_verPlatform->getCollidable()),hkColor::BLUE);
	HK_SET_OBJECT_COLOR(hkUlong(m_horPlatform->getCollidable()),hkColor::GREEN);

	// Set global time
	m_time = 0.0f;

	// Initialize hkpSurfaceInfo for previous ground 
	m_previousGround = new hkpSurfaceInfo();
	m_framesInAir = 0;

	// Current camera angle about up
	m_currentAngle = HK_REAL_PI * 0.5f;

	m_world->unlock();
}
예제 #20
0
hkDemo::Result SlidingWorldDemo::stepDemo()
{
	makeFakeInput();

	hkBool doShift = false;
	hkVector4 newCenter;
	handleKeys(doShift, newCenter);



	m_world->lock();

 	if(doShift)
	{
		   // reset the box colors to a light grey
		for (int i = 0; i < m_boxes.getSize(); i++)
		{
			HK_SET_OBJECT_COLOR(hkUlong(m_boxes[i]->getCollidable()), hkColor::LIGHTGREY);
		}

		{
			//hkVector4 currentCenter = m_centers[((m_ticks / delay) + (numCenters-1)) % numCenters];
			//HK_DISPLAY_STAR(currentCenter, 2.5f, 0xFF00FF00);
			//HK_DISPLAY_LINE(nextCenter, m_currentCenter, 0xFF00FF00);
		}

		hkVector4 diff; 
		diff.setSub4(newCenter, m_currentCenter);
		
		hkArray<hkpBroadPhaseHandle*> objectsEnteringBroadphaseBorder;
		
		hkVector4 effectiveShift;
		if( g_variants[m_variantId].m_mode == SlidingWorldDemoVariant::RECENTER_BROAD_PHASE_ONLY )
		{
			recenterBroadPhaseVariant(diff, objectsEnteringBroadphaseBorder, effectiveShift);
			
		}
		else // SlidingWorldDemoVariant::SHIFT_COORDINATE_SPACE)
		{
			shiftCoordinateSystemVariant(diff, objectsEnteringBroadphaseBorder, effectiveShift);
			
		} 

		removeDuplicatesFromArray(objectsEnteringBroadphaseBorder);

		// Some bodies may have to be removed from simulation, some may need to be added.
		{		
			removeBodiesLeavingBroadphaseFromSimulation(objectsEnteringBroadphaseBorder);
			addBodiesNewlyInsideSimulationAreaToSimulation();
		}

		m_currentCenter = newCenter;
	
	}

	
	// draw the grid in cyan
	{
		hkVector4 minOffset; minOffset.set(-5, 1, -5);
		hkVector4 maxOffset; maxOffset.set(5,1,5);
		hkVector4 min, max;

		for (int i = -2; i <= 2; i++)
		for (int j = -2; j <= 2; j++)
		{
			min.set((hkReal)10*i, 0, (hkReal)10*j);
			max = min;
			min.add4(minOffset);
			max.add4(maxOffset);
			drawAabb(min, max, hkColor::CYAN );
		}
	}

	 // draw the broadphase extents in red
	displayCurrentBroadPhaseAabb(m_world, hkColor::RED );

	// draw locations of all 'unsimulated' bodies
	drawUnsimulatedBodies();

	if( m_currentMode == AUTOMATIC_SHIFT)
	{
		m_ticks++;
	}

	m_world->unlock();

	return hkDefaultPhysicsDemo::stepDemo();
}
void DestructibleHierarchy::removeSubShapeFromDisplay(hkpRigidBody* moppRigidBody, hkpMoppBvTreeShape* moppShape, int subShapeKey)
{
	if (!m_env)
	{
		return;
	}

	//
	// calculate the shape's index in the hkgDisplayObject's geometry array
	//
	int geometryIndex;
	{
		hkpShapeCollection::ShapeBuffer buffer;
		const hkpExtendedMeshShape* meshShape = static_cast<const hkpExtendedMeshShape*>( moppShape->getContainer()->getChildShape(0, buffer) );

		hkpExtendedMeshShape::SubpartType type = meshShape->getSubpartType(subShapeKey);
		int subpartIndex = meshShape->getSubPartIndex(subShapeKey);

		geometryIndex = 0;

		if ( type == hkpExtendedMeshShape::SUBPART_TRIANGLES )
		{
			geometryIndex = subpartIndex;
		}
		else // type == hkpExtendedMeshShape::SUBPART_SHAPE
		{
			// skip all triangle subparts
			geometryIndex += meshShape->getNumTrianglesSubparts();

			// loop over all previous shape subparts
			{
				for (int i=0; i<subpartIndex; i++)
				{
					geometryIndex += meshShape->getShapesSubpartAt(i).m_numChildShapes;
				}
			}
			geometryIndex += meshShape->getTerminalIndexInSubPart(subShapeKey);
		}
	}

	//
	// get the terrain's vertex set
	//
	hkgVertexSet* vertexSet;
	{
		const hkpCollidable* collidable = moppRigidBody->getCollidable();
		hkgDisplayObject* displayObject = m_env->m_displayHandler->findDisplayObject(hkUlong(collidable));
		hkgGeometry* geometry = displayObject->getGeometry(geometryIndex);
		hkgFaceSet* faceSet = geometry->getMaterialFaceSet(0)->getFaceSet(0);
		vertexSet = faceSet->getVertexSet();
	}

	m_env->m_window->getContext()->lock();

	// vertex set has to be locked before any vertices can be manipulated
	vertexSet->lock(HKG_LOCK_WRITEDISCARD);

	{
		//
		// Simply zero-out all vertices. This will degenerate the triangles but that should be ok.
		//
		hkVector4 newPos(0,0,0);
		for (int i = 0; i < vertexSet->getNumVerts(); i++)
		{
			vertexSet->setVertexComponentData(HKG_VERTEX_COMPONENT_POS, i, &newPos(0));
		}
	}

	// unlock the vertex set again
	vertexSet->unlock();

	m_env->m_window->getContext()->unlock();

	return;
}
	virtual void entityActivatedCallback(hkpEntity* entity)
	{
		HK_SET_OBJECT_COLOR( hkUlong(entity->getCollidable()), 0xff55ff55 );
	}