AabbQueryDemo::AabbQueryDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env), 
	m_semaphore(0, 1000 ), 
	m_rand(1337)
{

	{
		m_worldSizeX = 2.0f * hkMath::sqrt(hkReal(m_env->m_cpuMhz));
		m_worldSizeY = 3;
		m_worldSizeZ = m_worldSizeX;
	}

	// Setup the camera and graphics
	{
		// setup the camera
		hkVector4 from(0.0f, m_worldSizeZ*2.f, -m_worldSizeZ);
		hkVector4 to  (0.0f, 0.0f,  0.0f);
		hkVector4 up  (0.0f, 1.0f,  0.0f);
		setupDefaultCameras( env, from, to, up, 1.0f, 5000.0f );
	}


	{
		hkpWorldCinfo cinfo;
		cinfo.m_gravity.setAll(0);
		cinfo.m_broadPhaseWorldAabb.m_max.set( m_worldSizeX,  10.0f*m_worldSizeY,  m_worldSizeZ);
		cinfo.m_broadPhaseWorldAabb.m_min.setNeg4(	cinfo.m_broadPhaseWorldAabb.m_max );	
		cinfo.m_useKdTree = true;
		m_world = new hkpWorld(cinfo);
		m_world->lock();
	}

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

	//
	// Create a random batch of boxes in the world
	//
	{
		hkAabb worldAabb; 
		worldAabb.m_max.set( m_worldSizeX,  m_worldSizeY, m_worldSizeZ );
		worldAabb.m_min.setNeg4( worldAabb.m_max );	

		hkpMotion::MotionType motionType = hkpMotion::MOTION_SPHERE_INERTIA;
		hkPseudoRandomGenerator rand(100);

		KdTreeDemoUtils::createRandomBodies(m_world, worldAabb, 500, motionType, &rand, m_collidables);
	}

	setupGraphics();

	m_world->unlock();

	hkpRayCastQueryJobQueueUtils::registerWithJobQueue(m_jobQueue);
	m_collIdx = 0;

	// timer tracking
	m_monitorHelper = new MultithreadedMonitorHelper(this);
	m_monitorHelper->trackTimer("KdAabbQueryJob", MultithreadedMonitorHelper::TRACK_FRAME_MAX);
	m_monitorHelper->trackTimer("KdQueryRecursiveST", MultithreadedMonitorHelper::TRACK_FRAME_MAX);
	m_monitorHelper->trackTimer("KdQueryIterativeST", MultithreadedMonitorHelper::TRACK_FRAME_MAX);
	m_monitorHelper->trackTimer("BroadphaseQueryAabb", MultithreadedMonitorHelper::TRACK_FRAME_MAX);
}
ConstraintKit2Demo::ConstraintKit2Demo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE)
{
	//
	// Setup the camera
	//
	{
		hkVector4 from(0.0f, 5.0f, 15.0f);
		hkVector4 to  (0.0f, 2.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 );
		m_world = new hkpWorld( info );
		m_world->lock();
		m_world->m_wantDeactivation = false;

		setupGraphics();
	}

	//
	// Set up a collision filter so we can disable collision between the objects we constrain together
	//
	{
		hkpGroupFilter* groupFilter = new hkpGroupFilter;
		hkpGroupFilterSetup::setupGroupFilter( groupFilter );

		m_world->setCollisionFilter( groupFilter );
		groupFilter->removeReference();
	}

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

	//
	// Create a fixed 'floor' box
	//
	const hkVector4 floorSize(10.0f, 0.5f, 10.0f);
	{
		m_world->addEntity( GameUtils::createBox( floorSize, 0.0f, hkVector4(0,-1,0) ) )->removeReference();
	}

	// We create a 'diagonal line' of boxes; each new box after the first will have
	// its transform fixed in its initial position (actually expressed as a relative 
	// offset to the previous box).

	const int numBoxes = 5;
	{
		hkpRigidBody* lastBox = 0;

		for(int boxCount = 0; boxCount < numBoxes; boxCount++)
		{
			hkVector4 pos( (hkReal)boxCount - ((hkReal)numBoxes-1) / 2.0f, (hkReal)boxCount, 0.0f);
			hkpRigidBody* box = GameUtils::createBox(hkVector4(1,1,1),10.0f,	pos );

			// Set filter info to be in group 1, so all boxes are in same group and don't collide
			box->setCollisionFilterInfo( hkpGroupFilter::calcFilterInfo(0,1) );
			m_world->addEntity(box);
			box->removeReference();

			if( lastBox )
			{
				// If there is a previous box, then we create a constraint between that box, and
				// the box just added. Here is the code that initially constructs the hkFixedConstraint:
				hkFixedConstraintData* fixedConstraint = new hkFixedConstraintData(box, lastBox);

				// Now we set the transform of the attached box in reference box space (the product
				// of inv(refToWorld) * attToWorld)
				hkTransform attToRef;
				{
					hkTransform refToWorld = lastBox->getTransform();
					hkTransform attToWorld = box->getTransform();
					attToRef.setMulInverseMul(refToWorld, attToWorld);
				}

				// This modifies the internal parameters of the constraint as follows:
				fixedConstraint->setTransformInRef(attToRef);

				m_world->createAndAddConstraintInstance(box, lastBox, fixedConstraint)->removeReference();
				fixedConstraint->removeReference();
			}

			lastBox = box;
		}
	}

	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();
}
Example #4
0
ChunkMoppDemo::ChunkMoppDemo(hkDemoEnvironment* env)
	:	hkDefaultPhysicsDemo(env)
{
	//setGraphicsState(HKG_ENABLED_WIREFRAME, true);	
	//
	// Setup the camera
	//
	{
		hkVector4 from(55.0f, 50.0f, 55.0f);
		hkVector4 to  ( 0.0f,  0.0f,   0.0f);
		hkVector4 up  ( 0.0f,  1.0f,   0.0f);
		setupDefaultCameras(env, from, to, up, 0.1f, 20000.0f);
	}

	//
	// Create the world
	//
	{
		hkpWorldCinfo worldInfo;
		{
			worldInfo.m_gravity.set(0.0f, -9.81f, 0.0f);
			worldInfo.setBroadPhaseWorldSize(10000.0f);
			worldInfo.setupSolverInfo( hkpWorldCinfo::SOLVER_TYPE_4ITERS_MEDIUM );
			worldInfo.m_enableDeactivation = false;
		}
		m_world = new hkpWorld(worldInfo);
		m_world->lock();

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

		setupGraphics();
	}

	hkpShapeCollection* meshShape = createMeshShape( VERTS_PER_SIDE, m_delayedCleanup );
	m_shape = createMoppShape( meshShape, true );
	m_shape->getAabb( hkTransform::getIdentity(), 0.1f, m_bounds );

	//
	//  create the ground mopp
	//
	{

		hkpRigidBodyCinfo terrainInfo;
		{
			hkVector4 size(100.0f, 1.0f, 100.0f);

			terrainInfo.m_shape = m_shape;
			terrainInfo.m_motionType = hkpMotion::MOTION_FIXED;
			terrainInfo.m_friction = 0.5f;

			hkpRigidBody* terrainBody = new hkpRigidBody(terrainInfo);
			m_world->addEntity(terrainBody);
			terrainBody->removeReference();	
		}
		terrainInfo.m_shape->removeReference();
	}

	hkVector4 halfExtents;
	hkVector4 centre;
	{
		m_bounds.getHalfExtents( halfExtents );
		m_bounds.getCenter( centre );

		m_minIndex = (halfExtents(0) < halfExtents(1)) ? 
			((halfExtents(0) < halfExtents(2)) ? 0 : 2) :
			((halfExtents(1) < halfExtents(2)) ? 1 : 2) ;
	}

	// Setup the camera
	{
		hkVector4 up; up.setZero4();
		up(m_minIndex) = 1.0f;

		hkVector4 from; from.setAddMul4( m_bounds.m_max, up, 5.0f);
		setupDefaultCameras(env, from, centre, up, 0.1f, 10000.0f);
	}

	//
	// Create objects at random coordinates
	//
	{
		hkVector4 size(0.5f, 0.5f, 0.5f);
		hkpBoxShape* boxShape =  new hkpBoxShape(size);

		hkpRigidBodyCinfo boxInfo;
		{
			boxInfo.m_mass = 1.0f;
			boxInfo.m_shape = boxShape;
			boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
		}

		hkPseudoRandomGenerator random(15);

		//
		// create the boxes
		//
		{
			hkVector4 range; range.setSub4( m_bounds.m_max, m_bounds.m_min );
			range.mul4( 1.0f );
			
			const int numObjects = 500;
			for (int i = 0; i < numObjects; i++)
			{
				hkVector4 pos; random.getRandomVector11(pos);
				pos.mul4(0.1f);
				pos.mul4(range);
				pos( m_minIndex ) += m_bounds.m_max( m_minIndex ) + i * (range(m_minIndex)) / numObjects + 4.0f;

				boxInfo.m_position = pos;
				hkpRigidBody* shape;
				shape = new hkpRigidBody(boxInfo);
				
				shape->setMaxLinearVelocity( 30 );
				m_world->addEntity(shape);
				shape->removeReference();
			}
		}

		boxShape->removeReference();
	}

	m_world->unlock();

	m_time = 0.0f;
}
Example #5
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();
}
hkDemo::Result CharacterDemo::stepDemo()
{

	hkVector4 up;
	hkQuaternion orient;

	{
		m_world->lock();

		//	Get user input data
		int m_upAxisIndex = 2;
		up.setZero4();
		up(m_upAxisIndex) = 1;

		hkReal posX = 0.f;
		hkReal posY = 0.f;
		{
			float deltaAngle = 0.f;
			CharacterUtils::getUserInputForCharacter(m_env, deltaAngle, posX, posY);
			m_currentAngle += deltaAngle;
			orient.setAxisAngle(up, m_currentAngle);
		}

		hkpCharacterInput input;
		hkpCharacterOutput output;
		{
			input.m_inputLR = posX;
			input.m_inputUD = posY;

			input.m_wantJump =  m_env->m_window->getMouse().wasButtonPressed(HKG_MOUSE_LEFT_BUTTON)
				|| m_env->m_gamePad->wasButtonPressed(HKG_PAD_BUTTON_1);
			input.m_atLadder = m_listener->m_atLadder;

			input.m_up = up;
			input.m_forward.set(1,0,0);
			input.m_forward.setRotatedDir( orient, input.m_forward );

			input.m_stepInfo.m_deltaTime = m_timestep;
			input.m_stepInfo.m_invDeltaTime = 1.0f / m_timestep;
			input.m_characterGravity.set(0,0,-16);
			input.m_velocity = m_characterProxy->getLinearVelocity();
			input.m_position = m_characterProxy->getPosition();

			if (m_listener->m_atLadder)
			{
				hkVector4 right, ladderUp;
				right.setCross( up, m_listener->m_ladderNorm );
				ladderUp.setCross( m_listener->m_ladderNorm, right );
				// Calculate the up vector for the ladder
				if (ladderUp.lengthSquared3() > HK_REAL_EPSILON)
				{
					ladderUp.normalize3();
				}

				// Reorient the forward vector so it points up along the ladder
				input.m_forward.addMul4( -m_listener->m_ladderNorm.dot3(input.m_forward), m_listener->m_ladderNorm);
				input.m_forward.add4( ladderUp );
				input.m_forward.normalize3();

				input.m_surfaceNormal = m_listener->m_ladderNorm;
				input.m_surfaceVelocity = m_listener->m_ladderVelocity;
			}
			else 
			{
				hkVector4 down;	down.setNeg4(up);
				hkpSurfaceInfo ground;
				m_characterProxy->checkSupport(down, ground);
				input.m_isSupported = ground.m_supportedState == hkpSurfaceInfo::SUPPORTED;

				input.m_surfaceNormal = ground.m_surfaceNormal;
				input.m_surfaceVelocity = ground.m_surfaceVelocity;
			}
		}

		// Apply the character state machine
		{
			HK_TIMER_BEGIN( "update character state", HK_NULL );

			m_characterContext->update(input, output);

			HK_TIMER_END();
		}

		//Apply the player character controller
		{
			HK_TIMER_BEGIN( "simulate character", HK_NULL );

			// Feed output from state machine into character proxy
			m_characterProxy->setLinearVelocity(output.m_velocity);

			hkStepInfo si;
			si.m_deltaTime = m_timestep;
			si.m_invDeltaTime = 1.0f/m_timestep;
			m_characterProxy->integrate( si, m_world->getGravity() );

			HK_TIMER_END();
		}

		// Display state
		{
			hkpCharacterStateType state = m_characterContext->getState();
			char * stateStr;

			switch (state)
			{
			case HK_CHARACTER_ON_GROUND:
				stateStr = "On Ground";	break;
			case HK_CHARACTER_JUMPING:
				stateStr = "Jumping"; break;
			case HK_CHARACTER_IN_AIR:
				stateStr = "In Air"; break;
			case HK_CHARACTER_CLIMBING:
				stateStr = "Climbing"; break;
			default:
				stateStr = "Other";	break;
			}
			char buffer[255];
			hkString::snprintf(buffer, 255, "State : %s", stateStr);
			m_env->m_textDisplay->outputText(buffer, 20, 270, 0xffffffff);
		}

		//
		// Handle crouching
		//
		{
			hkBool wantCrouch = ( m_env->m_window->getMouse().getButtonState() & HKG_MOUSE_RIGHT_BUTTON )
				|| (m_env->m_gamePad->getButtonState() & HKG_PAD_BUTTON_2);

			hkBool isCrouching = m_phantom->getCollidable()->getShape() == m_crouchShape;


			// We want to stand
			if (isCrouching && !wantCrouch)
			{
				swapPhantomShape(m_standShape);
			}

			// We want to crouch
			if (!isCrouching && wantCrouch)
			{
				swapPhantomShape(m_crouchShape);
			}
		}
		m_world->unlock();
	}

	// Step the world
	hkDefaultPhysicsDemo::stepDemo();

	// Camera Handling
	{
		m_world->lock();
		{
			const hkReal height = .7f;
			hkVector4 forward;
			forward.set(1,0,0);
			forward.setRotatedDir( orient, forward );

			hkVector4 from, to;
			to = m_characterProxy->getPosition();
			to.addMul4(height, up);

			hkVector4 dir;
			dir.setMul4( height, up );
			dir.addMul4( -4.f, forward);

			from.setAdd4(to, dir);
			setupDefaultCameras(m_env, from, to, up, 1.0f);
		}

		m_world->unlock();
	}

	return hkDemo::DEMO_OK;
}
Example #7
0
BrickWallDemo::BrickWallDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{

	// Disable warnings:									
	hkError::getInstance().setEnabled(0xaf55adde, false); //'No runtime block of size 637136 currently available. Allocating new block from unmanaged memory.'


	hkDefaultPhysicsDemo::enableDisplayingToiInformation( true );
	m_frameToSimulationFrequencyRatio = 1.0f;
	m_timestep = 1.0f / 60.0f;

	const BrickWallVariant& variant =  g_variants[m_variantId];

	int wallHeight = variant.m_height;
	int wallWidth  = variant.m_width;
	int numWalls = variant.m_numWalls;
	hkpWorldCinfo::SimulationType simulationType;
	simulationType = hkpWorldCinfo::SIMULATION_TYPE_CONTINUOUS;
	
	//
	// Setup the camera so that we can see the ball hit the (first) wall.
	//
	{
		hkVector4 from(40.0f, 20.0f, 40.0f);
		hkVector4 to  ( 0.0f, 10.0f, 0.0f);
		hkVector4 up  ( 0.0f,  1.0f, 0.0f);
		setupDefaultCameras( env, from, to, up );
	}


	{

		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize( 5000.0f );
		info.setupSolverInfo(hkpWorldCinfo::SOLVER_TYPE_4ITERS_HARD);
		info.m_collisionTolerance = 0.01f;
		info.m_gravity = hkVector4( 0.0f,-9.8f,0.0f);
		info.m_simulationType = simulationType;
		info.m_broadPhaseBorderBehaviour = info.BROADPHASE_BORDER_FIX_ENTITY;
		//info.m_enableDeactivation = false;
		//info.m_enableSimulationIslands = false;
		info.m_enableDeactivation = false;
		m_world = new hkpWorld( info );
		m_world->lock();
	}
	{
		// Register ALL agents (though some may not be necessary)
		hkpAgentRegisterUtil::registerAllAgents(m_world->getCollisionDispatcher());

		setupGraphics();

		// enable instancing (if present on platform)
		hkpShapeDisplayViewer* shapeViewer = (hkpShapeDisplayViewer*)getLocalViewerByName( hkpShapeDisplayViewer::getName() );
		if (shapeViewer)
		{
			shapeViewer->setInstancingEnabled( true );
		}
	}




	//
	//  Create the ground box
	//
	{
		hkVector4 groundRadii( 70.0f, 2.0f, 70.0f );
		hkpConvexShape* shape = new hkpBoxShape( groundRadii , 0 );
		
		hkpRigidBodyCinfo ci;
		
		ci.m_shape = shape;
		ci.m_motionType = hkpMotion::MOTION_FIXED;
		ci.m_position = hkVector4( 0.0f, -2.0f, 0.0f );
		ci.m_qualityType = HK_COLLIDABLE_QUALITY_FIXED;
		
		m_world->addEntity( new hkpRigidBody( ci ) )->removeReference();
		shape->removeReference();
	}

	hkVector4 groundPos( 0.0f, 0.0f, 0.0f );
	hkVector4 posy = groundPos;
	
	//
	// Create the walls
	//
	if(1)
	{
		hkVector4 boxSize( 1.0f, 0.5f, 0.5f);
		hkpBoxShape* box = new hkpBoxShape( boxSize , 0 );
		box->setRadius( 0.0f );
		hkReal deltaZ = 25.0f;
		posy(2) = -deltaZ * numWalls * 0.5f; 

		for ( int y = 0; y < numWalls; y ++ )			// first wall
		{
			createBrickWall( m_world, wallHeight, wallWidth, posy, 0.2f, box, boxSize );
			posy(2) += deltaZ;
		}
		box->removeReference();
	}


	//
	// Create the ball
	//
	if (1)
	{
		const hkReal radius = 1.5f;
		const hkReal sphereMass = 150.0f;

		hkVector4 relPos( 0.0f,radius + 0.0f, 20.0f );

		hkpRigidBodyCinfo info;
		hkpMassProperties massProperties;
		hkpInertiaTensorComputer::computeSphereVolumeMassProperties(radius, sphereMass, massProperties);

		info.m_mass = massProperties.m_mass;
		info.m_centerOfMass  = massProperties.m_centerOfMass;
		info.m_inertiaTensor = massProperties.m_inertiaTensor;
		info.m_shape = new hkpSphereShape( radius );
		info.m_position.setAdd4(posy, relPos );
		info.m_motionType  = hkpMotion::MOTION_BOX_INERTIA;

		if ( variant.m_usePredictive)
		{
			info.m_qualityType = HK_COLLIDABLE_QUALITY_BULLET;
		}
		else
		{
			info.m_qualityType = HK_COLLIDABLE_QUALITY_DEBRIS;
		}

		hkpRigidBody* sphereRigidBody = new hkpRigidBody( info );

		m_world->addEntity( sphereRigidBody );
		sphereRigidBody->removeReference();
		info.m_shape->removeReference();

		hkVector4 vel(  0.0f,4.9f, -200.0f );
		sphereRigidBody->setLinearVelocity( vel );
	}

	m_world->unlock();
}
Example #8
0
HingeHittingTableDemo::HingeHittingTableDemo(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,...'

	enableDisplayingToiInformation(true);

	//
	// Setup the camera
	//
	{
		hkVector4 from( 0, 0, 10);
		hkVector4 to  ( 0, 0, 0);
		hkVector4 up  ( 0, 1, 0);
		setupDefaultCameras(env, from, to, up);
	}


	//
	// Setup and create the hkpWorld
	//
	{
		hkpWorldCinfo info;
		info.setBroadPhaseWorldSize(150.0f);
		info.m_collisionTolerance = .03f; 
		info.m_gravity.setZero4();
		info.m_simulationType = info.SIMULATION_TYPE_CONTINUOUS;
		
		m_world = new hkpWorld( info );
		m_world->lock();

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

		setupGraphics();		
	}

	const HingeHittingTableDemoVariant& variant =  g_variants[this->m_variantId];

	//
	// Collision Filter
	//
	{ 
		hkpGroupFilter* filter = new hkpGroupFilter();
		hkpGroupFilterSetup::setupGroupFilter( filter );
		m_world->setCollisionFilter(filter);
		filter->disableCollisionsBetween(30,30);
		filter->removeReference();
	}

	// Create a box
	{
		hkReal mass = 0.0f;
		hkVector4 size( 2.0f, 0.2f, 2.0f );
		hkVector4 position( 1.0f, 0.0f, 0.0f );

		hkpRigidBody* body = HK_NULL;

		if( 1 ) 
		{
			// use a hkpBoxShape
			body = GameUtils::createBox( size, mass, position );
		}
		else
		{
			// use a hkpConvexVerticesShape
			body = GameUtils::createConvexVerticesBox( size, mass, position );
		}

		body->setName("table0");
		m_world->addEntity( body )->removeReference();
	}

	hkVector4 pos(-2.0f, 0.0f, 0.0f);
	hkVector4 vel(45.0f, 0.0f, 0.0f);

	switch(variant.m_sceneType)
	{
		case VARIANT_HINGE:
			createHinge(m_world, variant.m_objectQualityType, variant.m_constraintPriorityLevel, pos, vel);
			break;
		case VARIANT_RAGDOLL:
		case VARIANT_RAGDOLL_INCREASED_INERTIA:
			createRagdoll(m_world, variant.m_objectQualityType, variant.m_constraintPriorityLevel, pos, vel, variant.m_sceneType);
			break;

	}

	m_world->unlock();
}
Example #9
0
BindingDemo::BindingDemo( hkDemoEnvironment* env )
:	hkDefaultAnimationDemo(env)
{
	//
	// Setup the camera
	//
	{
		hkVector4 from( 0, -2.5f, 0.0f );
		hkVector4 to  ( 0,0,0 );
		hkVector4 up  ( 0,0,1 );
		setupDefaultCameras( env, from, to, up );
	}

	m_loader = new hkLoader();

	// Get the rig
	{
		hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkRig.hkx");
		hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
		HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset");
		hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

		HK_ASSERT2(0x27343435, ac && (ac->m_numSkeletons > 0), "No skeleton loaded");
		m_skeleton = ac->m_skeletons[0];
	}

	// Get the animations and the binding
	{
		hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkIdle.hkx");
		hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
		HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset");
		hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

		HK_ASSERT2(0x27343435, ac && (ac->m_numAnimations > 0 ), "No animation loaded");
		m_animation[0] =  ac->m_animations[0];

		HK_ASSERT2(0x27343435, ac && (ac->m_numBindings > 0), "No binding loaded");
		m_binding[0] = ac->m_bindings[0];

		assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkWaveLoop.hkx");
		container = m_loader->load( assetFile.cString() );
		ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

		HK_ASSERT2(0x27343435, ac && (ac->m_numAnimations > 0 ), "No animation loaded");
		m_animation[1] =  ac->m_animations[0];

		HK_ASSERT2(0x27343435, ac && (ac->m_numBindings > 0), "No binding loaded");
		m_binding[1] = ac->m_bindings[0];
	}

	// Create the skeleton
	m_skeletonInstance = new hkaAnimatedSkeleton( m_skeleton );

	// If the weight on any bone drops below this then it is filled with the T-Pose
	m_skeletonInstance->setReferencePoseWeightThreshold(0.1f);

	// Grab the animations
	for (int i=0; i < NUM_ANIMS; i++)
	{
		m_control[i] = new hkaDefaultAnimationControl( m_binding[i] );
		m_control[i]->setMasterWeight( 0.0f );
		m_control[i]->setPlaybackSpeed( 1.0f );

		m_skeletonInstance->addAnimationControl( m_control[i] );
		m_control[i]->removeReference();
	}

	// make a world so that we can auto create a display world to hold the skin
	setupGraphics( );
}
CollisionEventsDemo::CollisionEventsDemo( hkDemoEnvironment* env) 
	: hkDefaultPhysicsDemo(env) 
{
	//
	// Setup the camera
	//
	{
		hkVector4 from(3.0f, 4.0f, 8.0f);
		hkVector4 to(0.0f, 1.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_simulationType = info.SIMULATION_TYPE_CONTINUOUS;

		// Turn off deactivation so we can see continuous contact point processing
		info.m_enableDeactivation = false;
		m_world = new hkpWorld( info );
		m_world->lock();

		setupGraphics();
	}

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




	//
	// Create the floor
	//
	{
		hkpRigidBodyCinfo info;
		hkVector4 fixedBoxSize(5.0f, 0.5f , 5.0f );
		hkpBoxShape* fixedBoxShape = new hkpBoxShape( fixedBoxSize , 0 );

		info.m_shape = fixedBoxShape;
		info.m_motionType = hkpMotion::MOTION_FIXED;
		info.m_position.setZero4();

		// Add some bounce.
		info.m_restitution = 0.8f;
		info.m_friction = 1.0f;

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

		floor->removeReference();
		fixedBoxShape->removeReference();
	}

	// For this demo we simply have two box shapes which are constructed in the usual manner using a hkpRigidBodyCinfo 'blueprint'.
	// The dynamic box creation code in presented below. There are two key things to note in this example;
	// the 'm_restitution' member variable, which we have explicitly set to value of 0.9.
	// The restitution is over twice the default value of
	// 0.4 and is set to give the box (the floor has been set likewise) a more 'bouncy' nature. 

	//
	// Create a moving box
	//
	{
		hkpRigidBodyCinfo boxInfo;
		hkVector4 boxSize( .5f, .5f ,.5f );
		boxInfo.m_shape = new hkpBoxShape( boxSize , 0 );


		// Compute the box inertia tensor
		hkpInertiaTensorComputer::setShapeVolumeMassProperties( boxInfo.m_shape, 1.0f, boxInfo );

		boxInfo.m_qualityType = HK_COLLIDABLE_QUALITY_DEBRIS;
		boxInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;

		// Place the box so it bounces interestingly
		boxInfo.m_position.set(0.0f, 5.0f, 0.0f);
		hkVector4 axis(1.0f, 2.0f, 3.0f);
		axis.normalize3();
		boxInfo.m_rotation.setAxisAngle(axis, -0.7f);

		// Add some bounce.
		boxInfo.m_restitution = 0.5f;
		boxInfo.m_friction = 0.1f;

		hkpRigidBody* boxRigidBody = new hkpRigidBody( boxInfo );

		// remove reference from boxShape since rigid body "owns" it
		boxInfo.m_shape->removeReference();

		m_world->addEntity( boxRigidBody );
		boxRigidBody->removeReference();
		
		// Add the collision event listener to the rigid body
		MyCollisionListener* listener = new MyCollisionListener( boxRigidBody );
		listener->m_reportLevel = m_env->m_reportingLevel;
	}

	m_world->unlock();

}
Example #11
0
AdditiveBlendingDemo::AdditiveBlendingDemo( hkDemoEnvironment* env )
:	hkDefaultAnimationDemo(env)
{
	// Disable warnings: if no renderer									
	if( hkString::strCmp( m_env->m_options->m_renderer, "n" ) == 0 )
	{
		hkError::getInstance().setEnabled(0xf0d1e423, false); //'Could not realize an inplace texture of type PNG.'
	}

	//
	// Setup the camera
	//
	{
		hkVector4 from( 0.3f, -1, 1 );
		hkVector4 to  ( 0, 0, 0.5f );
		hkVector4 up  ( 0.0f, 0.0f, 1.0f );
		setupDefaultCameras( env, from, to, up, 0.1f, 100 );
	}

	m_loader = new hkLoader();

	// Convert the scene
	{
		hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/Scene/hkScene.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");
		removeLights(m_env);
		env->m_sceneConverter->convert( scene );
	}

	// Get the rig
	{
		hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkRig.hkx");
		hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
		HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset");
		hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

		HK_ASSERT2(0x27343435, ac && (ac->m_numSkeletons > 0), "No skeleton loaded");
		m_skeleton = ac->m_skeletons[0];
	}

	// Get the animations and the binding
	{
		hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkWalkLoop.hkx");
		hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
		HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset");
		hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

		HK_ASSERT2(0x27343435, ac && (ac->m_numAnimations > 0 ), "No animation loaded");
		m_animation[HK_WALK_ANIM] =  ac->m_animations[0];

		HK_ASSERT2(0x27343435, ac && (ac->m_numBindings > 0), "No binding loaded");
		m_binding[HK_WALK_ANIM] = ac->m_bindings[0];

		assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkHeadMovement.hkx");
		container = m_loader->load( assetFile.cString() );
		ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

		HK_ASSERT2(0x27343435, ac && (ac->m_numAnimations > 0 ), "No animation loaded");
		m_animation[HK_ADDITIVE_ANIM] =  ac->m_animations[0];

		HK_ASSERT2(0x27343435, ac && (ac->m_numBindings > 0), "No binding loaded");
		m_binding[HK_ADDITIVE_ANIM] = ac->m_bindings[0];
	}

	// Create an additive animation
	// This can also be done offline in the toolchain using the CreateAdditiveAnimation filter
	// See the Additive configuration of hkHeadMovement.max
	{
		hkaInterleavedUncompressedAnimation* interleavedAnim = static_cast< hkaInterleavedUncompressedAnimation* >(m_animation[ HK_ADDITIVE_ANIM ]);

		hkaAdditiveAnimationUtility::Input input;
		input.m_originalData = interleavedAnim->m_transforms;
		input.m_numberOfPoses = interleavedAnim->m_numTransforms / interleavedAnim->m_numberOfTransformTracks;
		input.m_numberOfTransformTracks = interleavedAnim->m_numberOfTransformTracks;
		input.m_baseData = interleavedAnim->m_transforms;


		// We create an additive animation by subtracting off the iniital pose for the first frame of the animation
		// This is done by passing the same animation for both the originalData and the baseData
		// Note that only the first frame of the basedata is used so this initial frame is subtracted
		// from each of the frames in the animation
		hkaAdditiveAnimationUtility::createAdditiveFromPose( input, interleavedAnim->m_transforms );

		// Switch the binding to additive so this animation will be blended differently in sample and combine.
		m_binding[HK_ADDITIVE_ANIM]->m_blendHint = hkaAnimationBinding::ADDITIVE;
	}

	// Convert the skin
	{
		const char* skinFile = "Resources/Animation/HavokGirl/hkLowResSkinWithEyes.hkx";
		hkString assetFile = hkAssetManagementUtil::getFilePath( skinFile );
		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(0x27343435, scene , "No scene loaded");

		hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));
		HK_ASSERT2(0x27343435, ac && (ac->m_numSkins > 0), "No animation loaded");

		m_numSkinBindings = ac->m_numSkins;
		m_skinBindings = ac->m_skins;

		m_numAttachments = ac->m_numAttachments;
		m_attachments = ac->m_attachments;

		// Make graphics output buffers for the skins
		env->m_sceneConverter->convert( scene );

		for (int a=0; a < m_numAttachments; ++a)
		{
			hkaBoneAttachment* ba = m_attachments[a];
			hkgDisplayObject* hkgObject = HK_NULL;

			//Check the attachment is a mesh
			if ( hkString::strCmp(ba->m_attachment.m_class->getName(), hkxMeshClass.getName()) == 0)
			{
				hkgObject = env->m_sceneConverter->findFirstDisplayObjectUsingMesh((hkxMesh*)ba->m_attachment.m_object);
				if (hkgObject)
				{
					hkgObject->setStatusFlags( hkgObject->getStatusFlags() | HKG_DISPLAY_OBJECT_DYNAMIC);
				}
			}

			m_attachmentObjects.pushBack(hkgObject);
		}

	}

	// Create the animated skeleton
	m_skeletonInstance = new hkaAnimatedSkeleton( m_skeleton );

	// Set the fill threshold
	m_skeletonInstance->setReferencePoseWeightThreshold( 0.05f );

	// Grab the animations and build controls
	for (int i=0; i < NUM_ANIMS; i++)
	{
		m_control[i] = new hkaDefaultAnimationControl( m_binding[i] );
		m_control[i]->setMasterWeight( 1.0f );
		m_control[i]->setPlaybackSpeed( 1.0f );

		m_skeletonInstance->addAnimationControl( m_control[i] );
		m_control[i]->removeReference();
	}

	// We initially turn the additive animation off and allow the user to ramp it in
	m_control[HK_ADDITIVE_ANIM]->setMasterWeight( 0.0f );
	m_control[HK_ADDITIVE_ANIM]->setPlaybackSpeed( 1.0f );
	setupGraphics( );

}
Example #12
0
SimpleShapesDemo::SimpleShapesDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{
	const ShapeVariant& variant =  g_variants[m_variantId];

	// Setup the camera.
	{
		hkVector4 from(0.0f, 5.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, setting gravity to zero so body floats.
	hkpWorldCinfo info;
	info.m_gravity.set(0.0f, 0.0f, 0.0f);	
	info.setBroadPhaseWorldSize( 100.0f );
	m_world = new hkpWorld(info);
	m_world->lock();

	setupGraphics();

	// Create the shape variant
	hkpShape* shape = 0;
	switch (variant.m_shapeType)
	{
		// Box
	case HK_SHAPE_BOX:
		{
			// Data specific to this shape.
			hkVector4 halfExtents(1.0f, 1.0f, 1.0f);

			/////////////////// SHAPE CONSTRUCTION ////////////////
			shape = new hkpBoxShape(halfExtents, 0 );

			break;
		}


		// Sphere
	case HK_SHAPE_SPHERE:
		{
			// The box is of side 2, so we must bound it by a sphere of radius >= sqrt(3)
			hkReal radius = 1.75f;

			/////////////////// SHAPE CONSTRUCTION ////////////////
			shape = new hkpSphereShape(radius);

			break;
		}


		// Triangle
	case HK_SHAPE_TRIANGLE:
		{
			// Disable face culling
			setGraphicsState(HKG_ENABLED_CULLFACE, false);

			float vertices[] = {
				-0.5f, -0.5f,  0.0f, 0.0f, // v0
				0.5f, -0.5f,  0.0f, 0.0f, // v1
				0.0f,  0.5f,  0.0f, 0.0f, // v2
			};

			/////////////////// SHAPE CONSTRUCTION ////////////////
			shape = new hkpTriangleShape();

			int index = 0;
			for (int i = 0; i < 3; i++)
			{
				static_cast<hkpTriangleShape*>(shape)->setVertex(i, hkVector4(vertices[index], vertices[index + 1], vertices[index + 2]));
				index = index + 4;
			}

			break;
		}


		// Capsule
	case HK_SHAPE_CAPSULE:
		{
			hkReal radius = 1.5f;
			hkVector4 top(0.0f, 1.5f, 0.0f);
			hkVector4 bottom(0.0f, -1.0f, 0.0f);

			/////////////////// SHAPE CONSTRUCTION ////////////////
			shape = new hkpCapsuleShape(top, bottom, radius);

			break;
		}


		// Cylinder
	case HK_SHAPE_CYLINDER:
		{
			hkReal radius = 1.5f;
			hkVector4 top(0.0f, 1.5f, 0.0f);
			hkVector4 bottom(0.0f, -1.0f, 0.0f);

			/////////////////// SHAPE CONSTRUCTION ////////////////
			shape = new hkpCylinderShape(top, bottom, radius);

			break;
		}


		// Convex vertices
	case HK_SHAPE_CONVEX_VERTICES:
		{
			// Data specific to this shape.
			int numVertices = 4;

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

			float vertices[] = { // 4 vertices plus padding
				-2.0f, 2.0f, 1.0f, 0.0f, // v0
				1.0f, 3.0f, 0.0f, 0.0f, // v1
				0.0f, 1.0f, 3.0f, 0.0f, // v2
				1.0f, 0.0f, 0.0f, 0.0f  // v3
			};

			/////////////////// SHAPE CONSTRUCTION ////////////////
			hkStridedVertices stridedVerts;
			{
				stridedVerts.m_numVertices = numVertices;
				stridedVerts.m_striding = stride;
				stridedVerts.m_vertices = vertices;
			}
			
			shape = new hkpConvexVerticesShape(stridedVerts);

			break;
		}

	default:
		break;
	}

	// Make sure that a shape was created
	HK_ASSERT(0, shape);

	// To illustrate using the shape, first define a rigid body template.
	hkpRigidBodyCinfo rigidBodyInfo;
	rigidBodyInfo.m_position.set(0.0f, 0.0f, 0.0f);
	rigidBodyInfo.m_angularDamping = 0.0f;
	rigidBodyInfo.m_linearDamping = 0.0f;

	rigidBodyInfo.m_shape = shape;

	// Compute the rigid body inertia.
	rigidBodyInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
	hkpInertiaTensorComputer::setShapeVolumeMassProperties( rigidBodyInfo.m_shape, 100.0f, rigidBodyInfo );

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

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

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

	m_world->unlock();
}
Example #13
0
BreakOffPartsAndSpuDemo::BreakOffPartsAndSpuDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env)
{
	m_list0 = m_list1 = HK_NULL;

	m_debugViewerNames.pushBack( hkpMidphaseViewer::getName() );

	m_bootstrapIterations = 150;

	const BreakOffPartsAndSpuVariant& variant = g_variants[m_variantId];

	//
	// Setup the camera
	//
	{
		hkVector4 from(0.0f, 35.0f, -50.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.m_gravity.set(0.0f, -9.8f, 0.0f);

		if ( variant.m_type == BREAK_OFF_PARTS_DEMO_COLLISION_RESPONSE)
		{
			info.m_contactRestingVelocity = 0.5f;
		}

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

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

	//
	//	Create the break off utility
	//
	{
		m_breakUtil = new hkpBreakOffPartsUtil( m_world, this );
	}


	// Create ground
	//
	{
		hkVector4 size (100.0f, 1.0f, 100.0f);
		hkReal mass = 0.0f;
		hkVector4 position (0.0f, -0.5f, 0.0f);
		hkpRigidBody* ground = GameUtils::createBox(size, mass, position);
		m_world->addEntity(ground);
		ground->removeReference();
	}

	// Create two big shapes
	//
	{
		hkVector4 size(0.5f, 0.5f, 0.5f);
		hkReal radius = 0.02f;
		hkReal dist = size(0)*2.0f + radius + 0.1f;
		
		hkArray<hkpConvexShape*> shapes; shapes.reserve(400);
		{
			hkpBoxShape* terminal = new hkpBoxShape(size, radius);
			int dim = 20;
			for (int i = 0; i < dim; i++)
			{
				for (int j = (i+1)%2; j < dim; j+=2)
				{
					hkTransform transform = hkTransform::getIdentity();
					hkReal offset = (hkReal(dim)-1.0f)*-0.5f;
					transform.setTranslation(hkVector4( (offset+hkReal(i))*dist, (offset+hkReal(j))*dist, 0.0f));
					hkpConvexTransformShape* cts = new hkpConvexTransformShape(terminal, transform);
					shapes.pushBack(cts);
				}
			}
			terminal->removeReference();
		}

		// Create new list/mesh shape
		//
		hkpShapeCollection* collectionShape0;
		hkpShapeCollection* collectionShape1;
		if (!variant.m_useMeshCollection)
		{
			collectionShape0 = m_list0 = new hkpListShape(reinterpret_cast<hkpShape**>(static_cast<hkpConvexShape**>(shapes.begin())), shapes.getSize());
			collectionShape1 = m_list1 = new hkpListShape(reinterpret_cast<hkpShape**>(static_cast<hkpConvexShape**>(shapes.begin())), shapes.getSize());
			if (variant.m_extraListInHierarchy)
			{
				collectionShape0 = new hkpListShape((hkpShape**)&collectionShape0, 1);
				collectionShape1 = new hkpListShape((hkpShape**)&collectionShape1, 1);
				m_list0->removeReference();
				m_list1->removeReference();
			}
		}
		else
		{
			// This is a share shape because it's not destructible
			hkpExtendedMeshShape* meshShape = new hkpExtendedMeshShape(radius);
			collectionShape0 = meshShape;
			collectionShape1 = meshShape;
			hkpExtendedMeshShape::ShapesSubpart part(shapes.begin(), shapes.getSize());
			meshShape->addShapesSubpart(part);
			// Add a reference to meshShape.
			// collectionShape0 and collectionShape1 both reference it, which means there has to be a second reference to remove later.
			meshShape->addReference();
		}
		hkReferencedObject::removeReferences(shapes.begin(), shapes.getSize());

		// Wrap it with a mopp
		//
		hkpShape* finalShape0 = collectionShape0;
		hkpShape* finalShape1 = collectionShape1;
		if (variant.m_useMopp)
		{
			hkpMoppCompilerInput mci;
			mci.m_enableChunkSubdivision = true;
			hkpMoppCode* code0 = hkpMoppUtility::buildCode( collectionShape0->getContainer(),mci);
			hkpMoppCode* code1 = hkpMoppUtility::buildCode( collectionShape1->getContainer(),mci);

			finalShape0 = new hkpMoppBvTreeShape( collectionShape0, code0 );
			finalShape1 = new hkpMoppBvTreeShape( collectionShape1, code1 );

			code0->removeReference();
			code1->removeReference();
			collectionShape0->removeReference();
			collectionShape1->removeReference();
		}

		// finally add create two bodies with the shape
		//
		{
			hkpRigidBodyCinfo info;
			info.m_shape = finalShape0;
			hkpInertiaTensorComputer::setShapeVolumeMassProperties(finalShape0, 10.0f, info);
			info.m_motionType = hkpMotion::MOTION_DYNAMIC;
			info.m_numUserDatasInContactPointProperties = 1;
			info.m_position.set(0.0f, 15.0f, 0.0f);

			m_body0 = new hkpRigidBody(info);

			info.m_rotation.setAxisAngle(hkVector4(0.0f,1.0f, 0.0f), 90.0f * HK_REAL_DEG_TO_RAD);
			info.m_position(0) += dist;
			info.m_shape = finalShape1;

			if (variant.m_fixOneBody)
			{
				info.m_motionType = hkpMotion::MOTION_FIXED;
			}

			m_body1 = new hkpRigidBody(info);

			finalShape0->removeReference();
			finalShape1->removeReference();

			m_world->addEntity(m_body0);
			m_world->addEntity(m_body1); 

			
		}

	}

	// Mark bodies breakable
	//
	if (variant.m_useMeshCollection != 1 && variant.m_extraListInHierarchy != 1)
	{
		m_breakUtil->markEntityBreakable(m_body0, 1.0f);
		m_breakUtil->markEntityBreakable(m_body1, 1.0f);
	}


	m_world->unlock();
}