hkDefaultAnimationDemo::hkDefaultAnimationDemo(hkDemoEnvironment* env)
: hkDefaultDemo	(env)
	//m_animationViewersContext(HK_NULL)
{
// eg:
//	m_animationViewersContext= new hkAnimationContext;
//	hkAnimationContext::registerAllAnimationProcesses(); // all physics only ones

	// Most of the default animations hover above the ground, so we don't want shadows
	// until they are reauthored
	forceShadowState(false);

	setupLights(m_env); // after we decide if we want shadows

	// Disable compression & mapping reports
	if(m_env->m_reportingLevel < hkDemoEnvironment::REPORT_INFO )
	{
		hkError::getInstance().setEnabled(0x432434a4, false); // Track analysis report
		hkError::getInstance().setEnabled(0x432434a5, false); // Delta/wavelet constructor report
		hkError::getInstance().setEnabled(0x54e4323e, false); // hkaSkeletonMapperUtils::createMapping report
		hkError::getInstance().setEnabled(0xf0d1e423, false); // 'Could not realize an inplace texture of type PNG.'
		hkError::getInstance().setEnabled(0x36118e94, false); // Spline constructor report
	}
}
MultipleCharacterRbsDemo::MultipleCharacterRbsDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{

	// Setup the graphics
	{
		forceShadowState(false);
	}

	// Create the world
	{
		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize( 350.0f );  
		info.m_gravity.set(0, -9.8f, 0);
		info.m_contactPointGeneration = hkpWorldCinfo::CONTACT_POINT_ACCEPT_ALWAYS;
		info.m_collisionTolerance = 0.1f; // faster, but better 0.01f for accuracy
		m_world = new hkpWorld( info );
		m_world->lock();

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

		setupGraphics();
	}

	// Create the ground using the landscape repository
	{
		int landscapeIndex = LandscapeRepository::getInstance().getLandscapeIndexByName("simpleFlatLandOneMetreTris");
		m_landscapeContainer = LandscapeRepository::getInstance().getLandscape(landscapeIndex);

		hkpRigidBodyCinfo groundInfo;
		groundInfo.m_motionType = hkpMotion::MOTION_FIXED;
		groundInfo.m_shape = m_landscapeContainer->m_shape;

		hkpRigidBody* groundbody = new hkpRigidBody(groundInfo);

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

		setupDefaultCameras( env, m_landscapeContainer->m_cameraFrom, m_landscapeContainer->m_cameraTo, hkVector4(0,1,0) );
		
	}

	AabbSpawnUtil spawnUtil( m_landscapeContainer->m_spawnVolumes );
	

	//	Create character rigid bodies 

	const int numCharacters = 100;

	{
		m_characterRigidBodies.setSize( numCharacters );

		// Create a capsule to represent the character standing
		hkVector4 top(0, .4f, 0);
		hkVector4 bottom(0,-.4f, 0);		

		hkpShape* characterShape = new hkpCapsuleShape(top, bottom, .6f);

		// Construct characters
		for (int i=0; i < numCharacters; i++)
		{

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

			info.m_maxForce = 2000.0f;
			info.m_up = UP;
			spawnUtil.getNewSpawnPosition( hkVector4(1, 2, 1), info.m_position );

			info.m_maxSlope = 90.0f * HK_REAL_DEG_TO_RAD;

			m_characterRigidBodies[i] = new hkpCharacterRigidBody( info );
			m_world->addEntity( m_characterRigidBodies[i]->getRigidBody() );

		}
		characterShape->removeReference();
	}
	
	// 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
	{
		m_characterContexts.setSize(numCharacters);

		for (int i=0; i < numCharacters; i++)
		{
			m_characterContexts[i] = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND);
			m_characterContexts[i]->setCharacterType(hkpCharacterContext::HK_CHARACTER_RIGIDBODY);
		}
		manager->removeReference();
	}
	
	//Initialized the round robin counter
	m_tick = 0;

	m_world->unlock();
}
Esempio n. 3
0
UnevenTerrainVsDemo::UnevenTerrainVsDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{

	// Setup the graphics
	{
		forceShadowState(false);
	}

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

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

		setupGraphics();
	}

	// Setup layer collision
	{
		// Replace filter
		hkpGroupFilter* groupFilter = new hkpGroupFilter();

		// We disable collisions between characters
		groupFilter->disableCollisionsBetween(LAYER_CHARACTER_PROXY, LAYER_CHARACTER_RIGIDBODY);
		m_world->setCollisionFilter( groupFilter, true);
		groupFilter->removeReference();
	}

	// Create the ground using the landscape repository
	{
		int landscapeIndex = LandscapeRepository::getInstance().getLandscapeIndexByName("simpleFlatLandOneMetreTris");
		m_landscapeContainer = LandscapeRepository::getInstance().getLandscape(landscapeIndex);

		hkpRigidBodyCinfo groundInfo;
		groundInfo.m_motionType = hkpMotion::MOTION_FIXED;
		groundInfo.m_shape = m_landscapeContainer->m_shape;

		hkpRigidBody* groundbody = new hkpRigidBody(groundInfo);

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

		setupDefaultCameras( env, m_landscapeContainer->m_cameraFrom, m_landscapeContainer->m_cameraTo, hkVector4(0,1,0) );

	}

	AabbSpawnUtil spawnUtil( m_landscapeContainer->m_spawnVolumes );

	const hkReal characterMass = 100.0f;
	
	hkpShape* characterShape;
	{
		// Create a capsule to represent the character standing
		hkVector4 top( 0, m_options.m_characterCylinderHeight * 0.5f, 0 );
		hkVector4 bottom( 0, -m_options.m_characterCylinderHeight * 0.5f, 0 );		

		characterShape = new hkpCapsuleShape( top, bottom, m_options.m_characterRadius );
	}

	{
		// Construct a character rigid body
		hkpCharacterRigidBodyCinfo info;
		info.m_mass = characterMass;
		info.m_shape = characterShape;

		info.m_up = UP;
		info.m_position = characterStart;
		info.m_collisionFilterInfo = hkpGroupFilter::calcFilterInfo( LAYER_CHARACTER_RIGIDBODY, 0 );
		info.m_supportDistance = m_options.m_rbSupportDistance;
		info.m_hardSupportDistance = m_options.m_rbHardSupportDistance;
		info.m_allowedPenetrationDepth = m_options.m_rbAllowedPenetrationDepth;

		m_characterRigidBody = new hkpCharacterRigidBody( info );

		hkpCharacterRigidBodyListener* listener = new hkpCharacterRigidBodyListener();
		m_characterRigidBody->setListener( listener );
		listener->removeReference();

		m_world->addEntity( m_characterRigidBody->getRigidBody() );

		characterShape->removeReference();
	}

	// Create the Character state machine and context
	{
		hkpCharacterStateManager* manager;
		hkpCharacterState* state;
		manager = new hkpCharacterStateManager();

		static_cast<hkpCharacterStateOnGround*>( state = new hkpCharacterStateOnGround() )->setSpeed( m_options.m_characterWalkSpeed );
		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();
	}

	//	Create a character proxy object
	{
		// Construct a shape phantom
		m_phantom = new hkpSimpleShapePhantom( characterShape, hkTransform::getIdentity(), hkpGroupFilter::calcFilterInfo( LAYER_CHARACTER_PROXY, 0 ) );

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

		// Construct a character proxy
		hkpCharacterProxyCinfo cpci;
		cpci.m_position = characterStart;
		cpci.m_staticFriction = 0.0f;
		cpci.m_dynamicFriction = 1.0f;
		cpci.m_up = UP;
		cpci.m_userPlanes = 4;
		
		cpci.m_shapePhantom = m_phantom;
		m_characterProxy = new hkpCharacterProxy( cpci );
	}

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

		static_cast<hkpCharacterStateOnGround*>( state = new hkpCharacterStateOnGround() )->setSpeed( m_options.m_characterWalkSpeed );
		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_characterProxyContext = new hkpCharacterContext(manager, HK_CHARACTER_ON_GROUND);
		manager->removeReference();
	}

	//Initialized the round robin counter
	m_tick = 0;
	m_unsupportedFramesCountRb = 0;
	m_unsupportedFramesCountProxy = 0;

	m_filterRigidBody.m_framesInAir = m_options.m_clientStateFiltering;
	m_filterProxy.m_framesInAir = m_options.m_clientStateFiltering;

	m_world->unlock();
}
OptimizedWorldRaycastDemo::OptimizedWorldRaycastDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{
	{
		m_numRigidBodies = int(m_env->m_cpuMhz);
		m_numBroadphaseMarkers = 64;
		m_rayLength = 5;
		m_worldSizeX = 2.0f * hkMath::sqrt(hkReal(m_env->m_cpuMhz));
		m_worldSizeY = 3;
		m_worldSizeZ = m_worldSizeX;
	}
	//
	// Setup the camera.
	//
	{
		hkVector4 from(30.0f, 8.0f, 25.0f);
		hkVector4 to  ( 4.0f, 0.0f, -3.0f);
		hkVector4 up  ( 0.0f, 1.0f,  0.0f);
		setupDefaultCameras(env, from, to, up);

		// Demo is slow graphicaly as it without shadows
		forceShadowState(false);

	}

	//
	// Create the world.
	//
	{
		hkpWorldCinfo info;
		
		// Set gravity to zero so body floats.
		info.m_gravity.setZero4();

		// make the world big enough to hold all our objects
		// make y larger so that our raycasts stay within the world aabb
		info.m_broadPhaseWorldAabb.m_max.set( m_worldSizeX + 10, 10*m_worldSizeY + 10, m_worldSizeZ + 10 );
		info.m_broadPhaseWorldAabb.m_min.setNeg4( info.m_broadPhaseWorldAabb.m_max );

		// Subdivide the broadphase space into equal sections along the x-axis
		// NOTE: Disabling this until the marker crash issue is fixed.
		//info.m_broadPhaseNumMarkers = m_numBroadphaseMarkers;

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

		setupGraphics();
	}

	// register all agents(however, we put all objects into the some group,
	// so no collision will be detected
	hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() );

	// Add a collision filter to the world to allow the bodies interpenetrate
	{
		hkpGroupFilter* filter = new hkpGroupFilter();
		filter->disableCollisionsBetween( hkpGroupFilterSetup::LAYER_DEBRIS, hkpGroupFilterSetup::LAYER_DEBRIS );
		m_world->setCollisionFilter( filter );
		filter->removeReference();
	}

	//
	// Set the simulation time to 0
	//
	m_time = 0;


	//
	//	Create our phantom at our origin.
	//  This is a bad hack, we should really create our phantom at it's final position,
	//  but let's keep the demo simple.
	//  If you actually create many phantoms all at the origin, you get a massive CPU spike
	//  as every phantom will collide with every other phantom.
	//
	{
		hkAabb aabb;
		aabb.m_min.setZero4();
		aabb.m_max.setZero4();
		m_phantom = new hkpAabbPhantom( aabb );
		m_world->addPhantom( m_phantom );

		m_phantomUseCache = new hkpAabbPhantom( aabb );
		m_world->addPhantom( m_phantomUseCache );
	}


	//
	// Create some bodies (reuse the ShapeRaycastApi demo)
	//
	createBodies();

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