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);
}
void CollisionFilterViewerUtil::activate(const hkpRigidBody* rb, const hkpWorld* world)
{
	if( rb != HK_NULL )
	{
		m_isActive = true;

		if(m_bodiesColored.getSize() == 0)
		{
			// Print out filter info 
			{
				hkUint32 filterInfo = rb->getCollidable()->getCollisionFilterInfo();
				hkcout << "Body has filter info " << filterInfo << 
					" which means layer " << hkpGroupFilter::getLayerFromFilterInfo(filterInfo) <<
					" system group " << hkpGroupFilter::getSystemGroupFromFilterInfo(filterInfo) <<
					" subsystem group " << hkpGroupFilter::getSubSystemIdFromFilterInfo(filterInfo) <<
					" subsystem group nocollide " << hkpGroupFilter::getSubSystemDontCollideWithFromFilterInfo(filterInfo) <<
					"\n";
			}
			// Color the delected body red
			HK_SET_OBJECT_COLOR((hkUlong)rb->getCollidable(), hkColor::rgbFromChars(255, 0, 0));

			// Store original color
			m_bodiesColored.pushBack(rb);
			m_colors.pushBack( rb->isFixed() ? DEFAULT_FIXED_OBJECT_COLOR : DEFAULT_OBJECT_COLOR );

			// Now find all bodies colliding with this and colour orange, otherwise green
			hkpPhysicsSystem* system;
			system = world->getWorldAsOneSystem();

			for(int i = 0; i < system->getRigidBodies().getSize(); i++)
			{
				hkpRigidBody* rb2 = system->getRigidBodies()[i];

				if( rb == rb2) continue;

				if( world->getCollisionFilter()->isCollisionEnabled( *rb->getCollidable(), *rb2->getCollidable()) )
				{
					// Color orange
					HK_SET_OBJECT_COLOR((hkUlong)rb2->getCollidable(), hkColor::rgbFromChars(255, 128, 0));
				}
				else
				{
					// Color Green
					HK_SET_OBJECT_COLOR((hkUlong)rb2->getCollidable(), hkColor::rgbFromChars(0, 255, 0));
				}
				m_bodiesColored.pushBack(rb2);
				m_colors.pushBack(  rb2->isFixed() ? DEFAULT_FIXED_OBJECT_COLOR : DEFAULT_OBJECT_COLOR );
			}
			system->removeReference();

		}
	}
}
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();

}
void WorldLinearCastMultithreadedDemo::buildQueryObects( hkArray<hkpShape*>& shapes, hkArray<QueryObject>& objects )
{
	hkpShapeDisplayBuilder::hkpShapeDisplayBuilderEnvironment env;
	hkpShapeDisplayBuilder builder(env);

	for (int i = 0; i < shapes.getSize(); i++)
	{
		QueryObject qo;
		qo.m_transform = new hkTransform();
		qo.m_transform->setIdentity();

		qo.m_collidable = new hkpCollidable( shapes[i], qo.m_transform );
		objects.pushBack( qo );

		hkArray<hkDisplayGeometry*> displayGeometries;

		builder.buildDisplayGeometries( shapes[i], displayGeometries );
		hkDebugDisplay::getInstance().addGeometry( displayGeometries, hkTransform::getIdentity(), (hkUlong)qo.m_collidable, 0, 0 );

		while( displayGeometries.getSize() )
		{
			delete displayGeometries[0];
			displayGeometries.removeAt(0);
		}

		// Set green color
		HK_SET_OBJECT_COLOR((hkUlong)qo.m_collidable, hkColor::rgbFromChars(0,255,0,120));
	}
}
Exemple #5
0
		// hkpPhantom interface implementation
		virtual void phantomEnterEvent( const hkpCollidable* collidableA, const hkpCollidable* collidableB, const hkpCollisionInput& env )
		{
			// the color can only be changed once the entity has been added to the world
			hkpRigidBody* owner = hkGetRigidBody(collidableB);

			// the "Collidables" here are "faked" so it's necessary to get the owner first in order
			// to get the "real" collidable!
			HK_SET_OBJECT_COLOR((hkUlong)owner->getCollidable(), hkColor::rgbFromChars(255, 0, 0));
			//HK_SET_OBJECT_COLOR((int)&collidableB, hkColor::rgbFromChars(255, 0, 0));
		}
void CollisionFilterViewerUtil::deactivate()
{
	// Recolor all boides to their original color.
	for(int i = 0; i < m_bodiesColored.getSize(); i++)
	{
		HK_SET_OBJECT_COLOR((hkUlong)m_bodiesColored[i]->getCollidable(), m_colors[i]);
	}

	// Clear and mark as inactive.
	m_bodiesColored.clear();
	m_colors.clear();
	m_isActive = false;
}
Exemple #7
0
//
// Create a grid of ragdolls
//
void VehicleManagerDemo::createRagdollGrid( hkpWorld* world, int x_size, int y_size, hkReal xStep, hkReal yStep, hkArray<hkRagdoll*>&	ragdollsOut)
{
	int systemGroup = 2;
	hkReal ragdollHeight = 2.50f;

	for( int x = 0; x < x_size; x++ )
	{
		for( int y = 0; y < y_size; y++ )
		{
			hkVector4 position; 
			// do a raycast to place the ragdoll
			{
				hkpWorldRayCastInput ray;
				ray.m_from.set( x * xStep,  10, y * yStep );
				ray.m_to.  set( x * xStep, -10, y * yStep );
				hkpWorldRayCastOutput result;
				world->castRay( ray, result );
				position.setInterpolate4( ray.m_from, ray.m_to, result.m_hitFraction );
				position(1) += ragdollHeight* 0.5f;
			}

			hkQuaternion	rotation; rotation.setIdentity();

			rotation.setAxisAngle( hkTransform::getIdentity().getColumn(0), HK_REAL_PI  * -0.5f );

			hkpPhysicsSystem* ragdoll = GameUtils::createRagdoll( ragdollHeight, position, rotation, systemGroup, GameUtils::RPT_CAPSULE );
			{
				for ( int i = 0; i < ragdoll->getRigidBodies().getSize(); i++)
				{
					hkpRigidBody* rb = ragdoll->getRigidBodies()[i];
					rb->setCollisionFilterInfo( hkpGroupFilter::calcFilterInfo( RAGDOLL_LAYER, systemGroup ) );
				}
			}
			systemGroup++;

			world->addPhysicsSystem(ragdoll);
			{
				// Give the ragdolls some personality
				int color = hkColor::getRandomColor();
				for (hkInt32 i = 0; i < ragdoll->getRigidBodies().getSize(); i++)
				{
					hkpRigidBody* rb = ragdoll->getRigidBodies()[i];
					HK_SET_OBJECT_COLOR((hkUlong)rb->getCollidable(), color);	
				}
			}
			ragdoll->getRigidBodies()[0]->deactivate();
			ragdoll->removeReference();
		}
	}
}
Exemple #8
0
		// hkpPhantom interface implementation
		virtual void phantomLeaveEvent( const hkpCollidable* collidableA, const hkpCollidable* collidableB )
		{
			// the color can only be changed once the entity has been added to the world
			hkpRigidBody* owner = hkGetRigidBody(collidableB);

			// the "Collidables" here are "faked" so it's necessary to get the owner first in order
			// to get the "real" collidable!
			HK_SET_OBJECT_COLOR((hkUlong)owner->getCollidable(), hkColor::rgbFromChars(0, 255, 0));

			// If moving out AND falling down, apply impulse to fire it towards "wall"
			if(owner->getLinearVelocity()(1) < 0.0f)
			{
				hkVector4 impulse(-50.0f, 220.0f, 0.0f);
				owner->applyLinearImpulseAsCriticalOperation(impulse);
			}
		}
void WorldLinearCastMultithreadedDemo::displayRootCdBody( hkpWorld* world, const hkpCollidable* collidable, hkpShapeKey key)
{
	hkpShapeCollection::ShapeBuffer shapeBuffer;

	//	Check, whether we have a triangle from the landscape or a single object
	if ( key == HK_INVALID_SHAPE_KEY )
	{
		// now we have a single object as we are not part of a hkpShapeCollection
		HK_SET_OBJECT_COLOR((hkUlong)collidable, hkColor::rgbFromChars(160,160,160));
	}
	else
	{
		// now we need to get our triangle.
		// Attention: The next lines make certain assumptions about how the landscape is constructed:
		//   1. The landscape is a single hkMoppShape with wraps a hkpShapeCollection, which
		//      produces only triangles.
		//   2. All hkShapeCollections are wrapped with a hkpBvTreeShape

		HK_ASSERT(0x3e93321f,  world->getCollisionDispatcher()->hasAlternateType( collidable->getShape()->getType(), HK_SHAPE_BV_TREE ) );

		const hkpBvTreeShape* bvTreeShape = static_cast<const hkpBvTreeShape*>(collidable->getShape());

		hkpShapeKey triangleId = key;

		const hkpShape* childShape = bvTreeShape->getContainer()->getChildShape( triangleId, shapeBuffer );

		HK_ASSERT(0x23f67112,  childShape->getType() == HK_SHAPE_TRIANGLE );
		const hkpTriangleShape* triangle = static_cast<const hkpTriangleShape*>( childShape );

		hkVector4 vertex[3];
		vertex[0].setTransformedPos(collidable->getTransform(), triangle->getVertex(0));
		vertex[1].setTransformedPos(collidable->getTransform(), triangle->getVertex(1));
		vertex[2].setTransformedPos(collidable->getTransform(), triangle->getVertex(2));

		//	Draw the border of the triangle
		HK_DISPLAY_LINE(vertex[0], vertex[1], hkColor::WHITE);
		HK_DISPLAY_LINE(vertex[2], vertex[1], hkColor::WHITE);
		HK_DISPLAY_LINE(vertex[0], vertex[2], hkColor::WHITE);

		if ( (const void*)childShape != (const void*)shapeBuffer && shapeBuffer[10] == 0 )
		{
			HK_ASSERT(0x20b8765d, 0);
		}
	}
}
Exemple #10
0
void ShapeQueryDemo::buildCachingPhantoms( hkpWorld* world, hkArray<hkpShape*>& shapes, hkArray<hkpCachingShapePhantom*>& phantoms, hkPseudoRandomGenerator& generator )
{
	for (int i = 0; i < shapes.getSize(); i++)
	{
		// create a random position. This is important, otherwise all the phantoms will start in the
		// center of the level and will overlap, causing an N squared worst case problem
		hkTransform t;
		t.getRotation().setIdentity();
		t.getTranslation().set( i * 10.f, 10.f, generator.getRandRange( -20.f, 20.f ));

		hkpCachingShapePhantom* phantom = new hkpCachingShapePhantom( shapes[i], t );

		phantoms.pushBack( phantom );
		world->addPhantom( phantom );
	
		// Set red color
		HK_SET_OBJECT_COLOR((hkUlong)phantom->getCollidable( ), hkColor::rgbFromChars(255,0,0,120));
	}
}
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();
}
Exemple #12
0
PhantomEventsDemo::PhantomEventsDemo( hkDemoEnvironment* env )
	:	hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE)
{
	//
	// Setup the camera
	//
	{
		hkVector4 from(13.0f, 10.0f, 13.0f);
		hkVector4 to   (0.0f, 0.0f, 0.0f);
		hkVector4 up   (0.0f, 1.0f, 0.0f);
		setupDefaultCameras( env, from, to, up );
	}


	//
	// Create the world
	//
	{
		hkpWorldCinfo info;
		info.setupSolverInfo(hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM); 
		info.setBroadPhaseWorldSize( 100.0f );
		info.m_enableDeactivation = false;
		m_world = new hkpWorld( info );
		m_world->lock();

		setupGraphics();
	}

	//
	// Register the collision agents
	//
	{
		hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() );
	}


	// In this demo we have three different objects; the wall, the sphere and a phantom volume. Both the wall, which is simply a box,
	// and the sphere are created in the usual manner using a hkpRigidBodyCinfo 'blueprint' and are added to the world.

	//
	// Create the wall box
	//
	{
		hkpRigidBodyCinfo info;
		hkVector4 fixedBoxSize( 0.5f, 5.0f , 5.0f );
		hkpBoxShape* fixedBoxShape = new hkpBoxShape( fixedBoxSize , 0 );
		info.m_shape = fixedBoxShape;
		info.m_motionType = hkpMotion::MOTION_FIXED;
		info.m_position.set(-2.0f, 0.0f ,0.0f);

		// Add some bounce.
		info.m_restitution = 0.9f;

		// Create fixed box
		hkpRigidBody* floor = new hkpRigidBody(info);
		m_world->addEntity(floor);
		floor->removeReference();

		fixedBoxShape->removeReference();
	}

	//
	// Create a moving sphere
	//
	{
		hkReal radius = 0.5f;
		hkpConvexShape* sphereShape = new hkpSphereShape(radius);


		// To illustrate using the shape, create a rigid body.
		hkpRigidBodyCinfo sphereInfo;

		sphereInfo.m_shape = sphereShape;
		sphereInfo.m_position.set(2.0f, 0.0f, 0.0f);
		sphereInfo.m_restitution = 0.9f;
		sphereInfo.m_motionType = hkpMotion::MOTION_SPHERE_INERTIA;

		// If we need to compute mass properties, we'll do this using the hkpInertiaTensorComputer.
		if (sphereInfo.m_motionType != hkpMotion::MOTION_FIXED)
		{
			sphereInfo.m_mass = 10.0f;
			hkpMassProperties massProperties;
			hkpInertiaTensorComputer::computeSphereVolumeMassProperties(radius, sphereInfo.m_mass, massProperties);

			sphereInfo.m_inertiaTensor = massProperties.m_inertiaTensor;
			sphereInfo.m_centerOfMass = massProperties.m_centerOfMass;
			sphereInfo.m_mass = massProperties.m_mass;	
		}
		
			
		// Create a rigid body (using the template above)
		hkpRigidBody* sphereRigidBody = new hkpRigidBody(sphereInfo);

		// Remove reference since the body now "owns" the Shape
		sphereShape->removeReference();

		// Finally add body so we can see it, and remove reference since the world now "owns" it.
		m_world->addEntity(sphereRigidBody);
		sphereRigidBody->removeReference();
	}


	// Given below is the construction code for the phantom volume:

	//
	// Create a PHANTOM floor
	//
	{
		hkpRigidBodyCinfo boxInfo;
		hkVector4 boxSize( 4.0f, 1.5f , 2.0f );
		hkpShape* boxShape = new hkpBoxShape( boxSize , 0 );
		boxInfo.m_motionType = hkpMotion::MOTION_FIXED;

		boxInfo.m_position.set(2.0f, -4.0f, 0.0f);
		
		MyPhantomShape* myPhantomShape = new MyPhantomShape();
		hkpBvShape* bvShape = new hkpBvShape( boxShape, myPhantomShape );
		boxShape->removeReference();
		myPhantomShape->removeReference();

		boxInfo.m_shape = bvShape;
	

		hkpRigidBody* boxRigidBody = new hkpRigidBody( boxInfo );
		bvShape->removeReference();

		m_world->addEntity( boxRigidBody );
		
		// the color can only be changed after the entity has been added to the world
		HK_SET_OBJECT_COLOR((hkUlong)boxRigidBody->getCollidable(), hkColor::rgbFromChars(255, 255, 255, 50));

		boxRigidBody->removeReference();
		
	}

	// The phantom volume is created using a hkpBvShape using a hkpBoxShape as the bounding volume and a 
	// hkpPhantomCallbackShape as the child shape. The volume is set to be fixed in space and coloured with a slight alpha blend.
	//
	// Once the simulation starts the ball drops into the phantom volume, upon notification of this event we colour the ball
	// RED and wait for an exit event. As soon as this event is raised we colour the ball GREEN and apply an impulse upwards
	// back towards the wall and the simulation repeats.

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

	//
	// Setup the camera
	//
	{
		hkVector4 from(  0.0f, 20.0f, -80.0f);
		hkVector4 to  (  0.0f,  0.0f,   0.0f);
		hkVector4 up  (  0.0f,  1.0f,   0.0f);
		setupDefaultCameras( env, from, to, up );

		// 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
		// float lightDir[] = { 0, -0.5f, -1 };
		// setSoleDirectionLight(m_env, lightDir, 0xffffffff );
	}

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

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

		setupGraphics();
	}

	// Load the level
	{
		hkVector4 tkScaleFactor(.32f,.32f,.32f);
		hkString fullname("Resources/Physics/Tk/CharacterController/");

		// We load our test case level.
		//fullname += "testcases.tk";
		fullname += "level.tk";

		hkpShape* moppShape = GameUtils::loadTK2MOPP(fullname.cString(),tkScaleFactor, -1.0f);
		HK_ASSERT2(0x64232cc0, moppShape,"TK file failed to load to MOPP in GameUtils::loadTK2MOPP.");

		hkpRigidBodyCinfo ci;
		ci.m_shape = moppShape;
		ci.m_motionType = hkpMotion::MOTION_FIXED;
		ci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo( 0, 1 );

		hkpRigidBody* entity = new hkpRigidBody(ci);
		moppShape->removeReference();
		m_world->addEntity(entity);
		entity->removeReference();
	}
	
	// Add a ladder
	hkVector4 baseSize( 1.0f, 0.5f, 3.6f);
	{ 
		hkpRigidBodyCinfo rci;
		rci.m_shape = new hkpBoxShape( baseSize );
		rci.m_position.set(3.4f, 8.f, 2);
		rci.m_motionType = hkpMotion::MOTION_FIXED;
		hkpRigidBody* ladder = new hkpRigidBody(rci);
		rci.m_shape->removeReference();
		m_world->addEntity(ladder)->removeReference();

		// Add a property so we can identify this as a ladder
		hkpPropertyValue val(1);
		ladder->addProperty(HK_OBJECT_IS_LADDER, val);

		// Color the ladder so we can see it clearly
		HK_SET_OBJECT_COLOR((hkUlong)ladder->getCollidable(), 0x7f1f3f1f);
	} 	
	//
	//	Create a character proxy object
	//
	{
		// Construct a shape

		hkVector4 vertexA(0,0, 0.4f);
		hkVector4 vertexB(0,0,-0.4f);		

		// Create a capsule to represent the character standing
		m_standShape = new hkpCapsuleShape(vertexA, vertexB, .6f);

		// Create a capsule to represent the character crouching
		// Note that we create the smaller capsule with the base at the same position as the larger capsule.
		// This means we can simply swap the shapes without having to reposition the character proxy,
		// and if the character is standing on the ground, it will still be on the ground.
		vertexA.setZero4();
		m_crouchShape = new hkpCapsuleShape(vertexA, vertexB, .6f);


		// Construct a Shape Phantom
		m_phantom = new hkpSimpleShapePhantom( m_standShape, hkTransform::getIdentity(), hkpGroupFilter::calcFilterInfo(0,2) );
		
		// Add the phantom to the world
		m_world->addPhantom(m_phantom);
		m_phantom->removeReference();

		// Construct a character proxy
		hkpCharacterProxyCinfo cpci;
		cpci.m_position.set(-9.1f, 35, .4f);
		cpci.m_staticFriction = 0.0f;
		cpci.m_dynamicFriction = 1.0f;
		cpci.m_up.setNeg4( m_world->getGravity() );
		cpci.m_up.normalize3();	
		cpci.m_userPlanes = 4;
		cpci.m_maxSlope = HK_REAL_PI / 3.f;

		cpci.m_shapePhantom = m_phantom;
		m_characterProxy = new hkpCharacterProxy( cpci );
	}
	
	//
	// Add in a custom friction model
	//
	{
		hkVector4 up( 0.f, 0.f, 1.f );
		m_listener = new MyCharacterListener();
		m_characterProxy->addCharacterProxyListener(m_listener);
	}

	//
	// Create the Character state machine and context
	//
	{
		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);
		manager->removeReference();
	}
	
	// Current camera angle about up
	m_currentAngle = HK_REAL_PI * 0.5f;
	
	m_world->unlock();
}
void AabbQueryDemo::queryAabbST()
{
	HK_TIME_CODE_BLOCK("queryAabbST", HK_NULL);
	hkAabb aabb;
	// Grab a body from the world, and compute it's AABB + some padding
	const hkpCollidable* queryCollidable;
	{
		queryCollidable = m_collidables[m_collIdx];
		hkpRigidBody* rb = hkGetRigidBody(queryCollidable);
		queryCollidable->getShape()->getAabb(rb->getTransform(), 20.0f, aabb);
	}

	//
	// For performance timings, we query the same AABB multiple times and overwrite the results.
	// When using this, make sure to use different output arrays!
	//
	hkArray<hkPrimitiveId> kdhitsRecurs, kdhitsIter;		
	hkArray<hkpBroadPhaseHandlePair> sapHits;

	{
		HK_TIME_CODE_BLOCK("KdQueryRecursiveST", HK_NULL);
		for (int i=0; i<numQueries; i++)
		{
			kdhitsRecurs.clear();
			hkKdTreeAabbQueryUtils::queryAabbRecursive(m_world->m_kdTreeManager->getTree(), aabb, kdhitsRecurs);
		}
	}

	{
		HK_TIME_CODE_BLOCK("KdQueryIterativeST", HK_NULL);
		for (int i=0; i<numQueries; i++)
		{
			kdhitsIter.clear();
			hkKdTreeAabbQueryUtils::queryAabbIterative(m_world->m_kdTreeManager->getTree(), aabb, kdhitsIter);
		}
	}

	// Visualize the results
	HK_DISPLAY_BOUNDING_BOX(aabb, hkColor::YELLOW);

	for (int i=0; i<kdhitsIter.getSize(); i++)
	{
		HK_SET_OBJECT_COLOR(kdhitsIter[i], hkColor::YELLOW);		
	}

	HK_SET_OBJECT_COLOR((hkUlong)queryCollidable, hkColor::RED);


	// Call the corresponding hkp3AxisSweep method for comparison
	{
		HK_TIME_CODE_BLOCK("BroadphaseQueryAabb", HK_NULL);
		for (int i=0; i<numQueries; i++)
		{
			sapHits.clear();
			m_world->getBroadPhase()->querySingleAabb( aabb, sapHits );
		}

	}

	{
		hkBool iterOk = compareHitArrays(aabb, kdhitsIter.begin(), kdhitsIter.getSize(), sapHits); 
		hkBool recursOk = compareHitArrays(aabb, kdhitsRecurs.begin(), kdhitsRecurs.getSize(), sapHits);

		if( !(iterOk && recursOk) )
		{
			m_env->m_textDisplay->outputText("ST Hit lits differed!", 20, 150, (hkUint32) hkColor::RED);
		}
	}
}
void AabbQueryDemo::queryAabbMT()
{
	HK_TIMER_BEGIN_LIST("queryAabbMT", "setup");

	hkAabb aabb;
	// Grab a body from the world, and compute it's AABB + some padding
	const hkpCollidable* queryCollidable;
	{
		queryCollidable = m_collidables[m_collIdx];
		hkpRigidBody* rb = hkGetRigidBody(queryCollidable);
		queryCollidable->getShape()->getAabb(rb->getTransform(), 20.0f, aabb);
	}

	hkArray<hkpKdTreeAabbCommand> commands;
	commands.setSize(numQueries);
	
	//
	// For performance timings, we query the same AABB multiple times and overwrite the results.
	// When using this, make sure to use different output arrays!
	//
	hkArray<hkPrimitiveId> output;
	output.setSize(50);

	//
	// Set up the commands for the job
	//
	for (int i=0; i<commands.getSize(); i++)
	{
		hkpKdTreeAabbCommand& command = commands[i];
		command.m_aabb = aabb;
		command.m_results = output.begin();
		command.m_resultsCapacity = output.getSize();
		command.m_numResultsOut = 0;
	}


	// 
	// Setup the job
	//
	hkArray<hkpRayCastQueryJobHeader> header(1);
	hkpKdTreeAabbJob aabbJob(header.begin(), commands.begin(), commands.getSize(), &m_semaphore);
	aabbJob.m_numTrees = 1;
	aabbJob.m_trees[0] = m_world->m_kdTreeManager->getTree();

	m_jobQueue->addJob( *reinterpret_cast<hkJobQueue::JobQueueEntry*>(&aabbJob), hkJobQueue::JOB_HIGH_PRIORITY );

	HK_TIMER_SPLIT_LIST("process");
	m_jobThreadPool->processAllJobs( m_jobQueue );
	m_jobThreadPool->waitForCompletion();
	m_semaphore.acquire();

	HK_TIMER_END_LIST();

	//
	// Run the same query on the broadphase for comparison purposes
	//
	hkArray<hkpBroadPhaseHandlePair> sapHits;
	{
		HK_TIME_CODE_BLOCK("BroadphaseQueryAabb", HK_NULL);
		for (int i=0; i<numQueries; i++)
		{
			sapHits.clear();
			m_world->getBroadPhase()->querySingleAabb( aabb, sapHits );
		}

	}

	//
	// Check results and draw 
	//
	for (int i=0; i<commands.getSize(); i++)
	{
		hkpKdTreeAabbCommand& command = commands[i];
		hkBool jobOk = compareHitArrays(command.m_aabb, command.m_results, command.m_numResultsOut, sapHits); 

		for (int j=0; j<command.m_numResultsOut; j++)
		{
			HK_SET_OBJECT_COLOR(command.m_results[j], hkColor::YELLOW);
		}
		HK_SET_OBJECT_COLOR((hkUlong)queryCollidable, hkColor::LIME);

		if( !jobOk )
		{
			m_env->m_textDisplay->outputText("MT Hit lits differed!", 20, 250, (hkUint32) hkColor::RED);
		}
	}


}
Exemple #16
0
LowFrequencyCharactersDemo::LowFrequencyCharactersDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{

	//
	// Setup the camera
	//
	{
		hkVector4 from(  0.0f, 20.0f, -80.0f);
		hkVector4 to  (  0.0f,  0.0f,   0.0f);
		hkVector4 up  (  0.0f,  1.0f,   0.0f);
		setupDefaultCameras( env, from, to, up );

		forceShadowState(false);

	}

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

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

		setupGraphics();
	}


	//
	//	Create a terrain 
	//
	TerrainHeightFieldShape* heightFieldShape;
	{
		hkpSampledHeightFieldBaseCinfo ci;
		ci.m_xRes = 64;
		ci.m_zRes = 64;
		ci.m_scale.set(4,1,4);

		//
		// Fill in a data array
		//
		m_data = hkAllocate<hkReal>(ci.m_xRes * ci.m_zRes, HK_MEMORY_CLASS_DEMO);
		for (int x = 0; x < ci.m_xRes; x++)
		{
			for (int z = 0; z < ci.m_xRes; z++)
			{
				hkReal dx,dz,height = 0;
				int octave = 1;
				// Add togther a few sine and cose waves
				for (int i=0; i< 3; i++)
				{
					dx = hkReal(x * octave) / ci.m_xRes;
					dz = hkReal(z * octave) / ci.m_zRes;
					height +=  (5 - (i * 2)) * hkMath::cos(dx * HK_REAL_PI) * hkMath::sin(dz * HK_REAL_PI);
					octave *= 4;
				}

				m_data[x*ci.m_zRes + z] = height;
			}
		}

		heightFieldShape = new TerrainHeightFieldShape( ci , m_data );
		//
		//	Create a fixed rigid body
		//
		{
			hkpRigidBodyCinfo rci;
			rci.m_motionType = hkpMotion::MOTION_FIXED;
			rci.m_position.setMul4( -0.5f, heightFieldShape->m_extents ); // center the heightfield
			rci.m_shape = heightFieldShape;
			rci.m_friction = 0.05f;

			hkpRigidBody* body = new hkpRigidBody( rci );

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

		heightFieldShape->removeReference();
	}

	//
	//	Create a character proxy object
	//
	{
		m_numBoxes = 0;
		m_numCapsules = 0;
		m_numSpheres = 0;
		
		// We'll store the simulation frequency in this 
		hkpPropertyValue val;

		// Construct shape phantoms for the characters
		hkPseudoRandomGenerator random(123);
		for (int i=0; i < NUM_CHARACTERS; i++)
		{

			// Create a random shape to represent the character
			hkpConvexShape* shape = HK_NULL;
			{
				hkReal scale = random.getRandReal01() * 0.25f + 0.75f;

				//Set the simulation frequency
				val.setInt( random.getRand32() % 3 );

				switch (val.getInt())
				{
					case 0:
						{
							hkVector4 top(0, scale * 0.4f, 0);
							hkVector4 bottom(0, -scale * 0.4f, 0);					
							shape = new hkpCapsuleShape(top, bottom, scale * 0.6f);
							m_numCapsules++;
						}
						break;
					case 1:
						{
							hkVector4 size(scale * 0.5f, scale , scale * 0.5f);
							shape = new hkpBoxShape(size);
							m_numBoxes++;
						}
						break;
					default:
						{
							shape = new hkpSphereShape(scale);
							m_numSpheres++;
						}
						break;
				}
			}

			hkpShapePhantom* phantom = new hkpSimpleShapePhantom( shape, hkTransform::getIdentity() );
			shape->removeReference();

			// Add the phantom to the world
			m_world->addPhantom(phantom);
			phantom->removeReference();

			HK_SET_OBJECT_COLOR( (hkUlong)phantom->getCollidable(), 0x7fffffff & hkColor::getRandomColor() );

			// Construct a character proxy
			hkpCharacterProxyCinfo cpci;
			random.getRandomVector11( cpci.m_position );
			cpci.m_position.mul4(32);
			cpci.m_position(1) = 10;
			cpci.m_up.setNeg4( m_world->getGravity() );
			cpci.m_up.normalize3();

			cpci.m_shapePhantom = phantom;
			m_characterProxy[i] = new hkpCharacterProxy( cpci );

			// Player is simulated at full frequency
			if (i==0)
			{
				val.setInt(0);
			}

			// Add the schedule property
			phantom->addProperty(HK_SCHEDULE_FREQUENCY, val);
		}
	}
	
	//
	// Create the Character state machine and context
	//
	hkpCharacterStateManager* manager;
	{
		hkpCharacterState* state;
		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();

	}

	// Create a context for each character
	{
		for (int i=0; i < NUM_CHARACTERS; i++)
		{
			m_characterContext[i] = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND);
		}
		manager->removeReference();
	}
	
	// Current camera angle about up
	m_currentAngle = 0.0f;

	//Initialised the round robin counter
	m_tick = 0;

	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();
}
Exemple #18
0
TruckDemo::TruckDemo(hkDemoEnvironment* env)
:	CarDemo(env, false, 4, 1)
{
	m_world->lock();
	{
		//
		// Create vehicle's chassis shape.
		//
		hkpConvexVerticesShape* chassisShape = HK_NULL;
		{
			hkReal xSize = 1.9f;
			hkReal xSizeFrontTop = 0.7f;
			hkReal xSizeFrontMid = 1.6f;
			hkReal ySize = 0.9f;
			hkReal ySizeMid = ySize - 0.7f;
			hkReal zSize = 1.0f;

			//hkReal xBumper = 1.9f;
			//hkReal yBumper = 0.35f;
			//hkReal zBumper = 1.0f;

			// 16 = 4 (size of "each float group", 3 for x,y,z, 1 for padding) * 4 (size of float).
			int stride = sizeof(float) * 4;
			
			{
				int numVertices = 10;

				float vertices[] = { 
					xSizeFrontTop, ySize, zSize, 0.0f,	// v0
					xSizeFrontTop, ySize, -zSize, 0.0f,	// v1
					xSize, -ySize, zSize, 0.0f,			// v2
					xSize, -ySize, -zSize, 0.0f,		// v3
					-xSize, ySize, zSize, 0.0f,			// v4
					-xSize, ySize, -zSize, 0.0f,		// v5
					-xSize, -ySize, zSize, 0.0f,		// v6
					-xSize, -ySize, -zSize, 0.0f,		// v7
					xSizeFrontMid, ySizeMid, zSize, 0.0f,	// v8
					xSizeFrontMid, ySizeMid, -zSize, 0.0f,	// v9
				};
				
				//
				// SHAPE CONSTRUCTION.
				//
				{
					hkStridedVertices stridedVerts;
					{
						stridedVerts.m_numVertices = numVertices;
						stridedVerts.m_striding = stride;
						stridedVerts.m_vertices = vertices;
					}
					chassisShape = new hkpConvexVerticesShape(stridedVerts);
				}
			}
		}

		createDisplayWheels(0.5f, 0.3f);

		for (int vehicleId = 0; vehicleId < m_numVehicles; vehicleId++)
		{
			//
			// Create the vehicle.
			//
			{
				//
				// Create the chassis body.
				//
				hkpRigidBody* chassisRigidBody;
				{
					hkpRigidBodyCinfo chassisInfo;

					chassisInfo.m_mass = 5000.0f;	
					chassisInfo.m_shape = chassisShape;
					chassisInfo.m_friction = 0.8f;
					chassisInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
					// Position chassis on the ground.
					chassisInfo.m_position.set(-10.0f, -4.5f, vehicleId * 5.0f);
					hkpInertiaTensorComputer::setShapeVolumeMassProperties(chassisInfo.m_shape,
																			chassisInfo.m_mass,
																			chassisInfo);

					chassisRigidBody = new hkpRigidBody(chassisInfo);
				}

				TruckSetup tsetup;
				m_vehicles[vehicleId].m_vehicle = createVehicle( tsetup, chassisRigidBody);
				m_vehicles[vehicleId].m_lastRPM = 0.0f;

				HK_SET_OBJECT_COLOR((hkUlong)chassisRigidBody->getCollidable(), 0x80ff8080);

				// This hkpAction flips the car upright if it turns over. 	 
				if (vehicleId == 0) 	 
				{ 	 
					hkVector4 rotationAxis(1.0f, 0.0f, 0.0f); 	 
					hkVector4 upAxis(0.0f, 1.0f, 0.0f); 	 
					hkReal strength = 8.0f; 	 
					m_reorientAction = new hkpReorientAction(chassisRigidBody, rotationAxis, upAxis, strength); 	 
				}

				chassisRigidBody->removeReference();
			}
		}
		chassisShape->removeReference();
	}

	//
	// Create the camera.
	//
	{
		VehicleApiUtils::createCamera( m_camera );
	}
	m_world->unlock();
}
Exemple #19
0
ThreeWaySqueezeDemo::ThreeWaySqueezeDemo(hkDemoEnvironment* env):	hkDefaultPhysicsDemo(env)
{
	// Disable warning
	hkError::getInstance().setEnabled(0xf0de4356, false);	// 'Your m_contactRestingVelocity seems to be too small'

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

	//
	// Create the world
	//
	{
		hkpWorldCinfo info;
		info.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM );
		info.setBroadPhaseWorldSize( 350.0f );  
		info.m_gravity.set(0,-40,0);
		info.m_collisionTolerance = 0.1f;
		info.m_numToisTillAllowedPenetrationToi = 1.1f;

		m_world = new hkpWorld( info );
		m_world->lock();

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

	{
		hkpCollisionFilter* cf = new My3WCollisionFilter();
		m_world->setCollisionFilter(cf);
		cf->removeReference();
	}

	// Build a Base
	hkVector4 baseSize( 50.0f, 1.0f, 50.0f);
	{ 
		hkpRigidBodyCinfo rci;
		rci.m_shape = new hkpBoxShape( baseSize );
		rci.m_position.set(0.0f, -0.5f, 0.0f);
		rci.m_motionType = hkpMotion::MOTION_FIXED;
			
		// Create a rigid body (using the template above).
		hkpRigidBody* base = new hkpRigidBody(rci);

		// Remove reference since the body now "owns" the Shape.
		rci.m_shape->removeReference();

		// Finally add body so we can see it, and remove reference since the world now "owns" it.
		m_world->addEntity( base )->removeReference();
	} 
	
	
	// Create a circle of keyframed objects 
	// Each of the objects is given a different increasing priority
	// We set the priority as a property on the object and extract this i nthe callback.
	hkVector4 blockerSize(1,3,5);
	hkpShape* blocker = new hkpBoxShape( blockerSize );
	{
		//hkPseudoRandomGenerator ran(100);
		for (int b = 0; b < NUM_OBJECTS; b++ )
		{
			hkVector4 up(0,1,0);
			hkReal angle = hkReal(b) / NUM_OBJECTS * HK_REAL_PI * 2;

			hkpRigidBodyCinfo rci;
			rci.m_position.set(5,0,0);
			rci.m_rotation.setAxisAngle( up, angle );
			rci.m_position.setRotatedDir( rci.m_rotation, rci.m_position );
			rci.m_shape = blocker;
			
			// If we set this to true, the body is fixed, and no mass properties need to be computed.
			rci.m_motionType = hkpMotion::MOTION_KEYFRAMED;
			if (b < 1)
			{
				rci.m_qualityType = HK_COLLIDABLE_QUALITY_KEYFRAMED;
			}
			else
			{
				rci.m_qualityType = HK_COLLIDABLE_QUALITY_FIXED;
			}

			m_objects[b] = new hkpRigidBody( rci );
			m_world->addEntity( m_objects[b] );
			m_objects[b]->removeReference();

			int color = rci.m_qualityType == HK_COLLIDABLE_QUALITY_FIXED ?
						hkColor::rgbFromFloats(1.0f, 0.0f, 0.0f, 1.0f) :
						hkColor::rgbFromFloats(0.0f, 1.0f, 0.0f, 1.0f) ;

			HK_SET_OBJECT_COLOR((hkUlong)m_objects[b]->getCollidable(), color );
		}
	}
	blocker->removeReference();

	//
	// Crate middle sphere
	//

	{
		hkpShape* shape = new hkpSphereShape(1.5f);
		hkpRigidBodyCinfo rbInfo;
		rbInfo.m_shape = shape;
		rbInfo.m_qualityType = HK_COLLIDABLE_QUALITY_CRITICAL;
		hkpRigidBody* body = new hkpRigidBody(rbInfo);
		m_world->addEntity(body);
		body->removeReference();
		shape->removeReference();
	}
	
	m_prevObj = 0;

	// Zero current time at start
	m_currentTime = 0.0f;

	m_world->unlock();
}
Exemple #20
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();
}
Exemple #21
0
hkDemo::Result ShapeQueryDemo::stepDemo()
{
	m_world->lock();

	//	Reset all object colors
	{
		for (int i = 0; i < m_fixedSmallBodies.getSize(); i++)
		{
			HK_SET_OBJECT_COLOR((hkUlong)m_fixedSmallBodies[i]->getCollidable(), hkColor::rgbFromChars(70,70,70));
		}
	}

	//
	//	Perform queries for the selected variant
	//
	switch (m_variantId)
	{

	// Raycast
	case 0:
		{
			HK_MONITOR_PUSH_DIR("hkpWorld::rayCastWithCollector");
			worldRayCast( m_world, m_time, true );
			HK_MONITOR_POP_DIR();

			HK_MONITOR_PUSH_DIR("hkpWorld::rayCast");
			worldRayCast( m_world, m_time, false );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("hkpPhantom::rayCastWithCollector");
			phantomRayCast( m_world, m_time, m_rayCastPhantoms, true );
			HK_MONITOR_POP_DIR();

			HK_MONITOR_PUSH_DIR("hkpPhantom::rayCast");
			phantomRayCast( m_world, m_time, m_rayCastPhantoms, false );
			HK_MONITOR_POP_DIR();
		}
		break;

	// Linear cast
	case 1:	
		{
			HK_MONITOR_PUSH_DIR("linearCast (world)");
			worldLinearCast( m_world, m_time, m_queryObjects );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("linearCast (simplePhantom)");
			phantomLinearCast<hkpSimpleShapePhantom>( this, m_simplePhantoms, HK_REAL_PI*0.16f );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("linearCast (cachingPhantom)");
			phantomLinearCast<hkpCachingShapePhantom>( this, m_cachingPhantoms, HK_REAL_PI*0.33f );
			HK_MONITOR_POP_DIR();
		}
		break;

	// Closest point
	case 2:
		{
			HK_MONITOR_PUSH_DIR("getClosestPoints (world)");
			worldGetClosestPoints( m_world, m_time, m_queryObjects );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("getClosestPoints (simplePhantom)");
			phantomGetClosestPoints<hkpSimpleShapePhantom>( this, m_simplePhantoms, HK_REAL_PI*0.16f );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("getClosestPoints (cachingPhantom)");
			phantomGetClosestPoints<hkpCachingShapePhantom>( this, m_cachingPhantoms, HK_REAL_PI*0.33f );
			HK_MONITOR_POP_DIR();
		}
		break;

	// Penetrations
	case 3:
		{
			HK_MONITOR_PUSH_DIR("getPenetrations (world)");
			worldGetPenetrations( m_world, m_time, m_queryObjects );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("getPenetrations (simplePhantom)");
			phantomGetPenetrations<hkpSimpleShapePhantom>(this, m_simplePhantoms, HK_REAL_PI*0.16f );
			HK_MONITOR_POP_DIR();
		}
		{
			HK_MONITOR_PUSH_DIR("getPenetrations (cachingPhantom)");
			phantomGetPenetrations<hkpCachingShapePhantom>(this, m_cachingPhantoms, HK_REAL_PI*0.33f );
			HK_MONITOR_POP_DIR();
		}
		break;

	// Unknown variant
	default:
		HK_ASSERT2(0xf7420c20, false, "Unknown shape query variant");
		break;
	}
	

	// Legend
	if (m_variantId != 0)
	{
		const int h = m_env->m_window->getHeight();
		m_env->m_textDisplay->outputText("Green: World queries", 20, h-70, (hkUint32)hkColor::GREEN, 1);
		m_env->m_textDisplay->outputText("Blue: Simple phantom queries", 20, h-50, (hkUint32)hkColor::BLUE, 1);
		m_env->m_textDisplay->outputText("Red: Caching phantom queries", 20, h-30, (hkUint32)hkColor::RED, 1);
	}

	m_time += 0.005f;

	m_world->unlock();

	return hkDefaultPhysicsDemo::stepDemo();
}
hkDemo::Result WorldLinearCastMultithreadedDemo::stepDemo()
{
	if (m_jobThreadPool->getNumThreads() == 0)
	{
		 HK_WARN(0x34561f23, "This demo does not run with only one thread");
		 return DEMO_STOP;
	}

//	const WorldLinearCastMultithreadedDemoVariant& variant = g_WorldLinearCastMultithreadedDemoVariants[m_variantId];

	m_world->lock();

	//	Reset all object colors
	{
		for (int i = 0; i < m_rocksOnTheFloor.getSize(); i++)
		{
			HK_SET_OBJECT_COLOR((hkUlong)m_rocksOnTheFloor[i]->getCollidable(), hkColor::rgbFromChars(70,70,70));
		}
	}


	// For this cast we use a hkpClosestCdPointCollector to gather the results:
	hkpClosestCdPointCollector collectors[10];

	// Since we're not too concerned with perfect accuracy, we can set the early out
	// distance to give the algorithm a chance to exit more quickly:
	m_world->getCollisionInput()->m_config->m_iterativeLinearCastEarlyOutDistance = 0.1f;
	
	m_world->unlock();

	// Cast direction & length.
	hkVector4 castVector( 0.0f, -30.0f, 0.0f );

	int numQueryObjects = m_queryObjects.getSize();

	//
	// Setup the output array where the resulting collision points will be returned.
	//
	hkpRootCdPoint* collisionPoints = hkAllocateChunk<hkpRootCdPoint>(numQueryObjects, HK_MEMORY_CLASS_DEMO);

	//
	// Setup commands: one command for each query object.
	//
	hkArray<hkpWorldLinearCastCommand> commands;
	{
		for ( int i = 0; i < numQueryObjects; i++ )
		{
			QueryObject& queryObject = m_queryObjects[i];

			//
			// Let QueryObjects move in circles.
			//
			hkVector4 position;
			{
				hkReal t = m_time + HK_REAL_PI * 2 * i / m_queryObjects.getSize();
				position.set( hkMath::sin( t ) * 10.0f, 10.0f, hkMath::cos( t ) * 10.0f );
			}

			queryObject.m_transform->setTranslation(position);

			hkpWorldLinearCastCommand& command = commands.expandOne();
			{
				// Init input data.
				{
					command.m_input.m_to				  . setAdd4( position, castVector );
					command.m_input.m_maxExtraPenetration = HK_REAL_EPSILON;
					command.m_input.m_startPointTolerance = HK_REAL_EPSILON;

					command.m_collidable				  = queryObject.m_collidable;
				}

				// Init output data.
				{
					command.m_results			= &collisionPoints[i];
					command.m_resultsCapacity	= 1;
					command.m_numResultsOut		= 0;
				}
			}
		}
	}

	//
	// Create the job header.
	//
	hkpCollisionQueryJobHeader* jobHeader;
	{
		jobHeader = hkAllocateChunk<hkpCollisionQueryJobHeader>(1, HK_MEMORY_CLASS_DEMO);
	}

	//
	// Setup hkpWorldLinearCastJob.
	//
	m_world->markForRead();
	hkpWorldLinearCastJob worldLinearCastJob(m_world->getCollisionInput(), jobHeader, commands.begin(), commands.getSize(), m_world->m_broadPhase, &m_semaphore);
	m_world->unmarkForRead();

	//
	// Put the job on the queue, kick-off the PPU/SPU threads and wait for everything to finish.
	//
	{
		m_world->lockReadOnly();

		//
		// Put the raycast job on the job queue.
		//

		worldLinearCastJob.setRunsOnSpuOrPpu();
		m_jobQueue->addJob( worldLinearCastJob, hkJobQueue::JOB_LOW_PRIORITY );

		m_jobThreadPool->processAllJobs( m_jobQueue );

		m_jobThreadPool->waitForCompletion();

		//
		// Wait for the one single job we started to finish.
		//
		m_semaphore.acquire();

		m_world->unlockReadOnly();
	}

	//
	// Display results.
	//
	{
		m_world->lock();
		{
			for (int i = 0; i < commands.getSize(); i++)
			{
				QueryObject& queryObject = m_queryObjects[i];

				hkpWorldLinearCastCommand& command = commands[i];
				if ( command.m_numResultsOut > 0 )
				{
					// move our position to the hit and draw a line along the cast direction
					hkVector4& pos = queryObject.m_transform->getTranslation();
					hkVector4 to; to.setAdd4( pos, castVector );
					hkVector4 newPos; newPos.setInterpolate4( pos, to, command.m_results->m_contact.getDistance() );
					HK_DISPLAY_LINE(pos, newPos, hkColor::GREEN);

					// Update our QO
					queryObject.m_transform->setTranslation( newPos );
					hkDebugDisplay::getInstance().updateGeometry( queryObject.m_collidable->getTransform(), (hkUlong)queryObject.m_collidable, 0);

					// call a function to display the details
					displayRootCdPoint( m_world, *command.m_results );
				}
				else
				{
					// only draw a line along the cast direction
					hkVector4& pos = queryObject.m_transform->getTranslation();
					hkVector4 to; to.setAdd4( pos, castVector );
					HK_DISPLAY_LINE(pos, to, hkColor::GREEN);

					// Update our QO
					hkVector4 nirvana(10000.0f, 10000.0f, 10000.0f);
					queryObject.m_transform->setTranslation( nirvana );
					hkDebugDisplay::getInstance().updateGeometry( queryObject.m_collidable->getTransform(), (hkUlong)queryObject.m_collidable, 0);
				}
			}
		}
		m_world->unlock();
	}

	//
	// Free temporarily allocated memory.
	//
	hkDeallocateChunk( jobHeader, 1, HK_MEMORY_CLASS_DEMO );
	hkDeallocateChunk(collisionPoints, numQueryObjects, HK_MEMORY_CLASS_DEMO);

	m_time += 0.005f;

	return hkDefaultPhysicsDemo::stepDemo();
}
	virtual void entityActivatedCallback(hkpEntity* entity)
	{
		HK_SET_OBJECT_COLOR( hkUlong(entity->getCollidable()), 0xff55ff55 );
	}
UserRayHitCollectorDemo::UserRayHitCollectorDemo(hkDemoEnvironment* env)
	:	hkDefaultPhysicsDemo(env), 
		m_time(0.0f)
{

	//	
	// Setup the camera.
	//
	{
		hkVector4 from(-8.0f, 25.0f, 20.0f);
		hkVector4 to  (0.0f, 0.0f, 0.0f);
		hkVector4 up  (0.0f, 1.0f, 0.0f);
		setupDefaultCameras(env, from, to, up);
	}



	//
	// Create the world.
	//
	{
		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize( 100.0f );

		m_world = new hkpWorld(info);
		m_world->lock();

		setupGraphics();
	}

	//
	//	Create a row of colored rigid bodies
	//
	{
		hkVector4 halfExtents(.5f, .5f, .5f );
		hkpShape* shape = new hkpBoxShape( halfExtents , 0 );

		int colors[4] = { hkColor::RED, hkColor::GREEN, hkColor::BLUE, hkColor::YELLOW };
		for (int i = 0; i < 4; i++ )
		{
			hkpRigidBodyCinfo ci;
			ci.m_motionType = hkpMotion::MOTION_FIXED;
			ci.m_shape = shape;
			ci.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(i+1);
			ci.m_position.set( i * 3.0f, 0.f, 0.0f);

			hkpRigidBody* body = new hkpRigidBody( ci );

			body->addProperty( COLOR_PROPERTY_ID, colors[i] );
			m_world->addEntity(body);
			body->removeReference();

			// show the objects in nice transparent colors
			colors[i] &= ~hkColor::rgbFromChars( 0, 0, 0 );
			colors[i] |= hkColor::rgbFromChars( 0, 0, 0, 120 );
			HK_SET_OBJECT_COLOR((hkUlong)body->getCollidable(), colors[i]);
		}
		shape->removeReference();
	}

	m_world->unlock();
}
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();
}
Exemple #26
0
BigRigDemo::BigRigDemo(hkDemoEnvironment* env) : CarDemo(env, false)
{
    // Create the vehicles

        //
        // Create tractor shape.
        //
        hkpListShape* tractorShape = HK_NULL;
        {
            hkReal xSize = 1.9f;
            hkReal xSizeFrontTop = 0.7f;
            hkReal xSizeFrontMid = 1.6f;
            hkReal ySize = 0.9f;
            hkReal ySizeMid = ySize - 0.7f;
            hkReal zSize = 1.0f;
            
            //hkReal xBumper = 1.9f;
            //hkReal yBumper = 0.35f;
            //hkReal zBumper = 1.0f;
            
            hkVector4 halfExtents(1.0f, 0.35f, 1.0f);
            
            // 16 = 4 (size of "each float group", 3 for x,y,z, 1 for padding) * 4 (size of float).
            int stride = sizeof(float) * 4;
            
            {
                int numVertices = 10;
                
                float vertices[] = { 
                    xSizeFrontTop, ySize, zSize, 0.0f,	// v0
                        xSizeFrontTop, ySize, -zSize, 0.0f,	// v1
                        xSize, -ySize, zSize, 0.0f,			// v2
                        xSize, -ySize, -zSize, 0.0f,		// v3
                        -xSize, ySize, zSize, 0.0f,			// v4
                        -xSize, ySize, -zSize, 0.0f,		// v5
                        -xSize, -ySize, zSize, 0.0f,		// v6
                        -xSize, -ySize, -zSize, 0.0f,		// v7
                        xSizeFrontMid, ySizeMid, zSize, 0.0f,	// v8
                        xSizeFrontMid, ySizeMid, -zSize, 0.0f,	// v9
                };
                
                hkpBoxShape* boxShape = new hkpBoxShape(halfExtents, 0.05f );

				hkTransform transform;
                transform.setIdentity();
                transform.setTranslation(hkVector4(-2.5f, -0.55f, 0.0f));
                
                hkpConvexTransformShape* transformShape = new hkpConvexTransformShape(boxShape, transform);
				boxShape->removeReference();
                
				hkpConvexVerticesShape* convexShape;
				{
					hkStridedVertices stridedVerts;
					{
						stridedVerts.m_numVertices = numVertices;
						stridedVerts.m_striding = stride;
						stridedVerts.m_vertices = vertices;
					}

					convexShape = new hkpConvexVerticesShape(stridedVerts);
				}
                
                hkArray<hkpShape*> shapeArray;
                shapeArray.pushBack(transformShape);
                shapeArray.pushBack(convexShape);
                
                tractorShape = new hkpListShape(shapeArray.begin(), shapeArray.getSize());
				transformShape->removeReference();
				convexShape->removeReference();
            }
        }
        
        //
        // Create trailer shape.
        //
        hkpListShape* trailerShape = HK_NULL;
        {
            hkVector4 halfExtents1(5.0f, 1.5f, 1.0f); // Box
            hkVector4 halfExtents2(1.0f, 1.0f, 1.0f); // Tongue
            
            hkTransform transform;
            transform.setIdentity();
            
            {						
                hkpBoxShape* boxShape1 = new hkpBoxShape(halfExtents1, 0.05f );
                hkpBoxShape* boxShape2 = new hkpBoxShape(halfExtents2, 0.05f );
                
                transform.setTranslation(hkVector4(6.0f, 0.5f, 0.0f));
				hkpConvexTransformShape* transformShape = new hkpConvexTransformShape(boxShape2, transform);
				boxShape2->removeReference();
                
                hkArray<hkpShape*> shapeArray;
                shapeArray.pushBack(boxShape1);
                shapeArray.pushBack(transformShape);
                
                trailerShape = new hkpListShape(shapeArray.begin(), shapeArray.getSize());
				boxShape1->removeReference();
				transformShape->removeReference();
            }
        }
        
        // Create the tractor vehicles
        {
		m_world->lock();
		{
			HK_ASSERT(0x526edf5d, m_world->getCollisionFilter() && m_world->getCollisionFilter()->m_type == hkpCollisionFilter::HK_FILTER_GROUP);
			hkpGroupFilter* groupFilter = static_cast<hkpGroupFilter*>(const_cast<hkpCollisionFilter*>(m_world->getCollisionFilter()));
			m_vehicles.clear();
            for (int vehicleId = 0; vehicleId < m_numVehicles; vehicleId++)
            {
				int vehicleGroup = groupFilter->getNewSystemGroup();
                //
                // Create the tractor.
                //
                {
                    //
                    // Create the tractor body.
                    //
                    hkpRigidBody* tractorRigidBody;
                    {
                        hkpRigidBodyCinfo tractorInfo;
                        tractorInfo.m_shape = tractorShape;
                        tractorInfo.m_friction = 0.8f;
                        tractorInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
						tractorInfo.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(0, vehicleGroup );

						// Position chassis on the ground.
                        tractorInfo.m_position.set(0.0f, -3.0f, (vehicleId + 1) * 9.0f);
                        //tractorInfo.m_angularDamping = 0.5f;

						// No need to set the inertia tensor, as this will be set automatically by the vehicle setup
						tractorInfo.m_mass = 15000.0f;
						tractorInfo.m_inertiaTensor.setDiagonal( 1.f, 1.f, 1.f );
						tractorInfo.m_centerOfMass.set( -1.0f, -0.8f, 0.0f);
                                              
                        tractorRigidBody = new hkpRigidBody(tractorInfo);
                    }

					m_vehicles.expandOne();
					TractorSetup tsetup;
                    createTractorVehicle( tsetup, tractorRigidBody, m_vehicles.getSize()-1);
                    tractorRigidBody->removeReference();
                }

				//
                // Create the trailer body.
                //
				{
                    hkpRigidBody* trailerRigidBody;
                    {
                        hkpRigidBodyCinfo trailerInfo;
                        trailerInfo.m_shape = trailerShape;
                        trailerInfo.m_friction = 0.8f;
                        trailerInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
                        trailerInfo.m_position.set(-9.0f, -3.0f, (1 + vehicleId) * 9.0f);
						trailerInfo.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo(0, vehicleGroup );

						// No need to set the inertia tensor, as this will be set automatically by the vehicle setup
                        trailerInfo.m_mass = 10000.0f;
						trailerInfo.m_inertiaTensor.setDiagonal( 1.f, 1.f, 1.f );

						// Trailers are generally bottom-heavy to improve stability.
						// Move the centre of mass lower but keep it within the chassis limits.
						trailerInfo.m_centerOfMass.set(-1.0f, -1.0f, 0.0f);
                                              
                        trailerRigidBody = new hkpRigidBody(trailerInfo);
                    }
                    
					m_vehicles.expandOne();
					TrailerSetup tsetup;
					createTrailerVehicle( tsetup, trailerRigidBody, m_vehicles.getSize()-1);

					HK_SET_OBJECT_COLOR((hkUlong)trailerRigidBody->getCollidable(), 0x80ff8080);
                    
                    trailerRigidBody->removeReference();
                }
            }
            
            tractorShape->removeReference();
            trailerShape->removeReference();
        }
		
	//
	//	Create the wheels
	//
		createDisplayWheels(0.5f, 0.2f);


    // Attach Tractors and Trailers
        for (int vehicleId = 0; vehicleId < m_vehicles.getSize(); vehicleId+=2)
        {
            hkpRigidBody* tractor = m_vehicles[vehicleId].m_vehicle->getChassis();
            hkpRigidBody* trailer = m_vehicles[vehicleId + 1 ].m_vehicle->getChassis();


			//
			// Use a hinge constraint to connect the tractor to the trailer
			//
			if (0)
	        {
				//
			    // Set the pivot
				//
		        hkVector4 axis(0.0f, 1.0f, 0.0f);
				hkVector4 point1(-3.5f, 0.4f, 0.0f);
				hkVector4 point2(6.0f, -0.4f, 0.0f);

			        // Create constraint
				hkpHingeConstraintData* hc = new hkpHingeConstraintData(); 
		        hc->setInBodySpace(point1, point2, axis, axis); 
		        m_world->createAndAddConstraintInstance( tractor, trailer, hc )->removeReference();
		        hc->removeReference();  
	        }
			
			//
			// Use a ball-and-socket constraint to connect the tractor to the trailer
			//
			else if (0)
			{
				hkVector4 point1(-3.5f, 0.4f, 0.0f);
				hkVector4 point2(6.0f, -0.4f, 0.0f);

				// Create the constraint
				hkpBallAndSocketConstraintData* bs = new hkpBallAndSocketConstraintData(); 
				bs->setInBodySpace(point1, point2);
				m_world->createAndAddConstraintInstance( tractor, trailer, bs )->removeReference();
				bs->removeReference();  
			}

			//
			// Use a ragdoll constraint to connect the tractor to the trailer
			//
			else if(1)
			{
				hkReal planeMin =  HK_REAL_PI * -0.45f;
				hkReal planeMax =  HK_REAL_PI * 0.45f;
				hkReal twistMin =  HK_REAL_PI * -0.005f;
				hkReal twistMax =  HK_REAL_PI *  0.005f;
				hkReal coneMin  =  HK_REAL_PI * -0.55f;
				hkReal coneMax = HK_REAL_PI * 0.55f;

				hkpRagdollConstraintData* rdc = new hkpRagdollConstraintData();
				rdc->setPlaneMinAngularLimit(planeMin);
				rdc->setPlaneMaxAngularLimit(planeMax);
				rdc->setTwistMinAngularLimit(twistMin);
				rdc->setTwistMaxAngularLimit(twistMax);

				hkVector4 twistAxisA(1.0f, 0.0f, 0.0f);
				hkVector4 planeAxisA(0.0f, 0.0f, 1.0f);
				hkVector4 twistAxisB(1.0f, 0.0f, 0.0f);
				hkVector4 planeAxisB(0.0f, 0.0f, 1.0f);
				hkVector4 point1(-2.3f, -0.7f, 0.0f);
				hkVector4 point2( 7.2f, -1.3f, 0.0f);

				rdc->setInBodySpace(point1, point2, planeAxisA, planeAxisB, twistAxisA, twistAxisB);
				rdc->setAsymmetricConeAngle(coneMin, coneMax);
				m_world->createAndAddConstraintInstance(tractor, trailer, rdc)->removeReference();
				rdc->removeReference();
			}
        }
		m_world->unlock();
    }
    
    //
    // Create the camera.
    //
    {
		hkp1dAngularFollowCamCinfo cinfo;

		cinfo.m_yawSignCorrection = 1.0f; 
		cinfo.m_upDirWS.set(0.0f, 1.0f, 0.0f); 
		cinfo.m_rigidBodyForwardDir.set(1.0f, 0.0f, 0.0f); 

		cinfo.m_set[0].m_velocity = 10.0f;
		cinfo.m_set[1].m_velocity = 50.0f;
		cinfo.m_set[0].m_speedInfluenceOnCameraDirection = 1.0f;
		cinfo.m_set[1].m_speedInfluenceOnCameraDirection = 1.0f;
		cinfo.m_set[0].m_angularRelaxation = 3.5f;
		cinfo.m_set[1].m_angularRelaxation = 4.5f;

		// The two camera positions ("slow" and "fast" rest positions) are both the same here,
		// -6 units behind the chassis, and 2 units above it. Again, this is dependent on 
		// m_chassisCoordinateSystem.
		cinfo.m_set[0].m_positionUS.set( -27.0f, 8.0f, 0.0f); 
		cinfo.m_set[1].m_positionUS.set( -27.0f, 8.0f, 0.0f); 

		cinfo.m_set[0].m_lookAtUS.set ( 2.0f, 0.0f, 0.0f );
		cinfo.m_set[1].m_lookAtUS.set ( 2.0f, 0.0f, 0.0f );

		cinfo.m_set[0].m_fov = 70.0f;
		cinfo.m_set[1].m_fov = 70.0f;

		m_camera.reinitialize( cinfo );
    }
}
PlanetGravityDemo::PlanetGravityDemo( hkDemoEnvironment* env )
: hkDefaultPhysicsDemo(env)
{
	hkString filename; // We have a different binary file depending on the compiler and platform
	filename.printf( "Resources/Physics/Levels/planetgravity_L%d%d%d%d.hkx",
					 hkStructureLayout::HostLayoutRules.m_bytesInPointer,
					 hkStructureLayout::HostLayoutRules.m_littleEndian ? 1 : 0,
					 hkStructureLayout::HostLayoutRules.m_reusePaddingOptimization? 1 : 0,
					 hkStructureLayout::HostLayoutRules.m_emptyBaseClassOptimization? 1 : 0 );
	hkIstream infile( filename.cString() );
	HK_ASSERT( 0x215d080c, infile.isOk() );

	hkpWorld::IgnoreForceMultithreadedSimulation ignoreForceMultithreaded;

	// Disable warning: 'm_contactRestingVelocity not set, setting it to REAL_MAX, so that the new collision restitution code will be disabled'
	hkError::getInstance().setEnabled( 0xf03243ed, false );

	// Load the startup scene
	{
		m_worldUp.set( 0.0f, 0.0f, 1.0f );
		m_characterForward.set( 1.0f, 0.0f, 0.0f );

		// Initialize hkpSurfaceInfo for storing the old ground info
		m_previousGround = new hkpSurfaceInfo();
		m_framesInAir = 0;

		m_cameraForward.set( 1.0f, 0.0f, 0.0f );
		m_cameraUp = m_cameraForward;
		m_cameraPosition.set( 20.0f, 1.0f, 35.0f );

		m_detachedCamera = false;

		// Load the world.
		m_world = loadWorld( filename.cString(), &m_physicsData, &m_loadedData );
		m_world->markForWrite();

		setupDefaultCameras( env, m_cameraPosition, m_characterRigidBody->getPosition(), m_worldUp );

		// Setup graphics
		setupGraphics();
		forceShadowState(false); // Disable shadows
		setupSkyBox(env);

		{
			removeLights( m_env );
			float v[] = { 0.941f, 0.941f, 0.784f };
			m_flashLight = hkgLight::create();
			m_flashLight->setType( HKG_LIGHT_DIRECTIONAL );
			m_flashLight->setDiffuse( v );
			v[0] = 0;
			v[1] = 1;
			v[2] = -0.5;
			m_flashLight->setDirection( v );
			v[0] = 0;
			v[1] = -1000;
			v[2] = 0;
			m_flashLight->setPosition( v );
			m_flashLight->setDesiredEnabledState( true );
			env->m_displayWorld->getLightManager()->addLight( m_flashLight );
			env->m_displayWorld->getLightManager()->computeActiveSet( HKG_VEC3_ZERO );
		}

		// Set up the collision filter
		{
			hkpGroupFilter* filter = new hkpGroupFilter();
			filter->disableCollisionsBetween(1, 1);
			m_world->setCollisionFilter(filter);
			filter->removeReference();
		}

		// Go through all loaded rigid bodies
		for( int i = 0; i < m_physicsData->getPhysicsSystems().getSize(); i++ )
		{
			const hkArray<hkpRigidBody*>& bodies = m_physicsData->getPhysicsSystems()[i]->getRigidBodies();
			for( int j = 0; j < bodies.getSize(); j++ )
			{
				hkString rbName( bodies[j]->getName() );

				// If the rb is a planet (name is "planet*")
				if( rbName.beginsWith( "planet" ) )
				{
					// If the body is a representation of a gravitational field (name: "*GravField"),
					//  remove it from the simulation.
					if( rbName.endsWith( "GravField" ) )
					{
						m_world->removeEntity( bodies[j] );
					}
					// Otherwise, it's actually a planet.
					else
					{
						hkAabb currentAabb;
						const hkpCollidable* hullCollidable = HK_NULL;

						// Find the planet's gravity field
						hkpRigidBody* planetRigidBody = bodies[j];
						hkString gravFieldRbName;
						gravFieldRbName.printf( "%sGravField", rbName.cString() );
						hkpRigidBody* gravFieldRigidBody = m_physicsData->findRigidBodyByName( gravFieldRbName.cString() );

						// If there's a GravField rigid body, then grab its collidable to be used for gravity calculation.
						if( gravFieldRigidBody )
						{
							hullCollidable = gravFieldRigidBody->getCollidable();
							gravFieldRigidBody->getCollidable()->getShape()->getAabb( gravFieldRigidBody->getTransform(), 0.0f, currentAabb );
						}
						else
						{
							planetRigidBody->getCollidable()->getShape()->getAabb( planetRigidBody->getTransform(), 0.0f, currentAabb );
						}

						// Scale up the planet's gravity field's AABB so it goes beyond the planet
						hkVector4 extents;
						extents.setSub4( currentAabb.m_max, currentAabb.m_min );
						hkInt32 majorAxis = extents.getMajorAxis();
						hkReal maxExtent = extents( majorAxis );
						maxExtent *= 0.4f;

						// Scale the AABB's extents
						hkVector4 extension;
						extension.setAll( maxExtent );
						currentAabb.m_max.add4( extension );
						currentAabb.m_min.sub4( extension );

						// Attach a gravity phantom to the planet so it can catch objects which come close
						SimpleGravityPhantom* gravityAabbPhantom = new SimpleGravityPhantom( planetRigidBody, currentAabb, hullCollidable );
						m_world->addPhantom( gravityAabbPhantom );
						gravityAabbPhantom->removeReference();

						// Add a tracking action to the phantom so it follows the planet. This allows support for non-fixed motion type planets
						if (planetRigidBody->getMotion()->getType() != hkpMotion::MOTION_FIXED)
						{
							PhantomTrackAction* trackAction = new PhantomTrackAction( planetRigidBody, gravityAabbPhantom );
							m_world->addAction( trackAction );
							trackAction->removeReference();
						}
					}
				}
				// if the rigid body is a launchpad (name: "launchPadSource*")
				else if( rbName.beginsWith("launchPadSource" ) )
				{
					hkString targetName;

					// Find launchpad "target" (used to calculate trajectory when launching)
					targetName.printf( "launchPadTarget%s", rbName.substr( hkString::strLen("launchPadSource") ).cString() );
					hkpRigidBody* target = m_physicsData->findRigidBodyByName( targetName.cString() );
					HK_ASSERT2( 0x0, target, "All launchPadSource rigid bodies must have associated launchPadTargets." );

					// Add a collision listener to the launchpad so it can apply forces to colliding rbs
					LaunchPadListener* launchPadListener = new LaunchPadListener( target->getPosition() );
					bodies[j]->addCollisionListener( launchPadListener );
					bodies[j]->setMotionType( hkpMotion::MOTION_FIXED );

					HK_SET_OBJECT_COLOR( reinterpret_cast<hkUlong>( bodies[j]->getCollidable() ), hkColor::RED );

					m_world->removeEntity( target );
				}
				// A "basic" launchpad just applies a force in the direction of the collision normal
				else if( rbName.beginsWith( "launchPadBasic" ) )
				{
					LaunchPadListener* launchPadListener = new LaunchPadListener( bodies[j]->getMass() );
					bodies[j]->addCollisionListener( launchPadListener );
					bodies[j]->setMotionType( hkpMotion::MOTION_FIXED );

					HK_SET_OBJECT_COLOR( reinterpret_cast<hkUlong>( bodies[j]->getCollidable() ), hkColor::RED );
				}
				else if( rbName.beginsWith( "teleporterSource" ) )
				{
					hkString targetName;

					// Find the teleportation destination of the teleporter
					targetName.printf( "teleporterTarget%s", rbName.substr( hkString::strLen("teleporterSource") ).cString() );
					hkpRigidBody* target = m_physicsData->findRigidBodyByName( targetName.cString() );
					HK_ASSERT2( 0, target, "All teleporterSource rigid bodies must have associated teleporterTargets." );

					// Replace the rb with a callback shape phantom. Colliding rbs will be teleported to the destination.
					TeleporterPhantomCallbackShape* phantomCallbackShape = new TeleporterPhantomCallbackShape( target->getTransform() );
					hkpBvShape* phantom = new hkpBvShape( bodies[j]->getCollidable()->getShape(), phantomCallbackShape );
					phantomCallbackShape->removeReference();
					bodies[j]->getCollidable()->getShape()->removeReference();
					bodies[j]->setShape( phantom );
					phantom->removeReference();

					m_world->removeEntity( target );
				}
				else if( rbName.beginsWith( "TurretTop" ) )
				{
					// Create a place to store state information for this turret.
					Turret& turret = m_turrets.expandOne();
					turret.constraint = bodies[j]->getConstraint(0);
					turret.hinge = static_cast<hkpLimitedHingeConstraintData*>( const_cast<hkpConstraintData*>( turret.constraint->getData() ) );
					turret.turretRigidBody = bodies[j];
					turret.cooldown = 0.0f;

					// Allow the hinge to spin infinitely and start the motor up
					turret.hinge->disableLimits();
					turret.hinge->setMotorActive( turret.constraint, true );

					// Do not allow the turret's simulation island deactivate.
					//  If it does, it will stop spinning.
					turret.turretRigidBody->setDeactivator( hkpRigidBodyDeactivator::DEACTIVATOR_NEVER );
				}

				// Update collision filter so that needless CollColl3 agents are not created.
				// For example, turrets  and geometry marked as "static" (such as the swing)
				//  should never collide with a planet, nor each other.
				if(  ( rbName.beginsWith( "planet" ) && !rbName.endsWith( "GravField" ) )
					|| rbName.beginsWith( "Turret" )
					|| rbName.endsWith( "_static" ) )
				{
					bodies[j]->setCollisionFilterInfo( hkpGroupFilter::calcFilterInfo( 1 ) );

					// Destroy or create agents (according to new quality type). This also removes Toi events.
					m_world->updateCollisionFilterOnEntity(bodies[j], HK_UPDATE_FILTER_ON_ENTITY_FULL_CHECK, HK_UPDATE_COLLECTION_FILTER_PROCESS_SHAPE_COLLECTIONS);
				}
			}
		}

		m_world->unmarkForWrite();
	}
}