AsymetricCharacterRbDemo::AsymetricCharacterRbDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{
		
	// Create the world
	{
		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize( 350.0f );  
		info.m_gravity.set(0, -9.8f, 0);
		info.m_collisionTolerance = 0.01f;		
		info.m_contactPointGeneration = hkpWorldCinfo::CONTACT_POINT_ACCEPT_ALWAYS;
		m_world = new hkpWorld( info );
		m_world->lock();

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

		setupGraphics();
	}
	
	//	Create a terrain (more bumpy as in the classical character proxy demo)
	TerrainHeightFieldShape* heightFieldShape;
	{
		hkpSampledHeightFieldBaseCinfo ci;
		ci.m_xRes = 64;
		ci.m_zRes = 64;
		ci.m_scale.set(1.6f, 0.2f, 1.6f);

		// 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_zRes; z++)
			{
				hkReal dx,dz,height = 0;
				int octave = 1;
				
				// Add together 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 +=  4 * i * hkMath::cos(dx * HK_REAL_PI) * hkMath::sin(dz * HK_REAL_PI);
					height -= 2.5f;
					octave *= 2;				
				}

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

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

			m_world->addEntity(terrain);

			terrain->removeReference();
		}

		heightFieldShape->removeReference();
	}
	
	// Create some random static pilars (green) and smaller dynamic boxes (blue)
	{
		hkPseudoRandomGenerator randgen(12345);

		for (int i=0; i < 80; i++)
		{
			
			if (i%2)
			{
				// Dynamic boxes of random size
				hkVector4 size;
				randgen.getRandomVector11(size);
				size.setAbs4( size );
				size.mul4(0.5f);
				hkVector4 minSize; minSize.setAll3(0.25f);
				size.add4(minSize);
				
				// Random position
				hkVector4 position;
				randgen.getRandomVector11( position );
				position(0) *= 25; position(2) *= 25; position(1) = 4;

				{ 
					// To illustrate using the shape, create a rigid body by first defining a template.
					hkpRigidBodyCinfo rci;
					rci.m_shape = new hkpBoxShape( size );
					rci.m_position = position;
					rci.m_friction = 0.5f;
					rci.m_restitution = 0.0f;
					// Density of concrete
					const hkReal density = 2000.0f;
					rci.m_mass = size(0)*size(1)*size(2)*density;
					
					hkVector4 halfExtents(size(0) * 0.5f, size(1) * 0.5f, size(2) * 0.5f);
					hkpMassProperties massProperties;
					hkpInertiaTensorComputer::computeBoxVolumeMassProperties(halfExtents, rci.m_mass, massProperties);
					rci.m_inertiaTensor = massProperties.m_inertiaTensor;
					rci.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
										
					// Create a rigid body (using the template above).
					hkpRigidBody* box = new hkpRigidBody(rci);

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

					box->addProperty(HK_PROPERTY_DEBUG_DISPLAY_COLOR, int(hkColor::DARKBLUE)); 

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

			}
			else
			{
				// Fixed pilars of random size
				hkVector4 size;
				randgen.getRandomVector11(size);
				size.setAbs4( size );
				hkVector4 minSize; minSize.setAll3(0.5f);
				size.add4(minSize);
				size(1) = 2.5f;

				// Random position
				hkVector4 position;
				randgen.getRandomVector11( position );
				position(0) *= 25; position(2) *= 25; position(1) = 0;

				{ 
					// To illustrate using the shape, create a rigid body by first defining a template.
					hkpRigidBodyCinfo rci;
					
					rci.m_shape = new hkpBoxShape( size );
					rci.m_position = position;
					rci.m_friction = 0.1f;
					rci.m_motionType = hkpMotion::MOTION_FIXED;
					

					// Create a rigid body (using the template above).
					hkpRigidBody* pilar = new hkpRigidBody(rci);

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

					pilar->addProperty(HK_PROPERTY_DEBUG_DISPLAY_COLOR, int(hkColor::DARKGREEN)); 

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

					pilar->removeReference();
				} 
			}
		}
	}

	//	Create a character rigid body
	{
	
		// Construct a shape
		hkVector4 vertexA(0.4f,0,0);
		hkVector4 vertexB(-0.4f,0,0);		

		// Create a capsule to represent the character standing
		hkpShape* capsule = new hkpCapsuleShape(vertexA, vertexB, 0.6f);
		

		// Construct a character rigid body
		hkpCharacterRigidBodyCinfo info;
		info.m_mass = 100.0f;
		info.m_shape = capsule;
		info.m_maxForce = 1000.0f;
		info.m_up = UP;
		info.m_position.set(32.0f, 3.0f, 10.0f);
		info.m_maxSlope = HK_REAL_PI/2.0f;	// Only vertical plane is too steep


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

		capsule->removeReference();

	}
	
	// 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_IN_AIR);	
		manager->removeReference();			

		// Set new filter parameters for final output velocity filtering
		// Smoother interactions with small dynamic boxes
		m_characterContext->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY);
		m_characterContext->setFilterParameters(0.9f,12.0f,200.0f);
	}

	// Initialize hkpSurfaceInfo of ground from previous frame
	// Specific case (character is in the air, UP is Y)
	m_previousGround = new hkpSurfaceInfo(UP,hkVector4::getZero(),hkpSurfaceInfo::UNSUPPORTED);
	m_framesInAir = 0;
	
	// Current camera angle about up
	m_currentAngle = 0.0f;

	// Init actual time
	m_time = 0.0f;

	// Init rigid body normal
	m_rigidBodyNormal = UP;

	m_world->unlock();
}
Example #2
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();
}