void hctConvertToPhantomActionFilter::process( hkRootLevelContainer& data  )
{
	// Find and hkxScene and a hkPhysics Data objects in the root level container
	hkxScene* scenePtr = reinterpret_cast<hkxScene*>( data.findObjectByType( hkxSceneClass.getName() ) );
	if (scenePtr == HK_NULL || (scenePtr->m_rootNode == HK_NULL) )
	{
		HK_WARN_ALWAYS(0xabbaa5f0, "No scene data (or scene data root hkxNode) found. Can't continue.");
		return;
	}
	hkpPhysicsData* physicsPtr = reinterpret_cast<hkpPhysicsData*>( data.findObjectByType( hkpPhysicsDataClass.getName() ) );
	if (physicsPtr == HK_NULL)
	{
		HK_WARN_ALWAYS(0xabbaa3d0, "No physics data found, you need to use Create Rigid Bodies before this filter or have bodies already in the input data.");
		return;
	}

	// Keep track of how many phantoms we created so we can reported
	int numConverted = 0;

	// Search for rigid bodies in the scene
	for (int psi=0; psi<physicsPtr->getPhysicsSystems().getSize(); psi++)
	{
		const hkpPhysicsSystem* psystem = physicsPtr->getPhysicsSystems()[psi];

		for (int rbi=0; rbi<psystem->getRigidBodies().getSize(); rbi++)
		{
			hkpRigidBody* rbody = psystem->getRigidBodies()[rbi];
			const char* rbName = rbody->getName();
			
			// Require an associated node in the scene
			hkxNode* rbNode = (rbName)? scenePtr->findNodeByName(rbName): HK_NULL;
			if( !rbNode )
			{
				continue;
			}
			
			// Require an 'hkPhantomAction' attribute group
			const hkxAttributeGroup* attrGroup = rbNode->findAttributeGroupByName("hkPhantomAction");
			if (!attrGroup)
			{
				continue;
			}
			
			// Create our phantom shape
			MyPhantomShape* myPhantomShape = new MyPhantomShape();
			{
				// Set action type (required)
				const char* actionTypeStr = HK_NULL;
				attrGroup->getStringValue( "action", true, actionTypeStr );
				if( actionTypeStr )
				{
					if( hkString::strCasecmp( actionTypeStr, "wind" ) == 0 )
					{
						myPhantomShape->m_actionType = MyPhantomShape::ACTION_WIND;
					}
					else if( hkString::strCasecmp( actionTypeStr, "attract" ) == 0 )
					{
						myPhantomShape->m_actionType = MyPhantomShape::ACTION_ATTRACT;
					}
					else if( hkString::strCasecmp( actionTypeStr, "deflect" ) == 0 )
					{
						myPhantomShape->m_actionType = MyPhantomShape::ACTION_DEFLECT;
					}
					else
					{
						HK_WARN_ALWAYS(0xabbad3b4, "Unknow action type ("<<actionTypeStr<<").");
					}
				}
				else
				{
					HK_WARN_ALWAYS(0xabba9834, "Can't fine \"action\" attribute");
				}
				
				// Set other attributes (optional)
				attrGroup->getVectorValue( "direction", false, myPhantomShape->m_direction );
				attrGroup->getFloatValue( "strength", false, myPhantomShape->m_strength );

				// Useful warnings
				if ((myPhantomShape->m_actionType == MyPhantomShape::ACTION_WIND) && (myPhantomShape->m_direction.lengthSquared3()==0.0f))
				{
					HK_WARN_ALWAYS(0xabbadf82, "Wind direction is invalid - action will have no effect");
				}
				if (myPhantomShape->m_strength==0.0f)
				{
					HK_WARN_ALWAYS(0xabbacc83, "Strength is 0 - action will have no effect");
				}

			}
			
			// Set the phantom as a new bounding shape for the body
			{
				const hkpShape* oldShape = rbody->getCollidable()->getShape();
				
				hkpBvShape* bvShape = new hkpBvShape( oldShape, myPhantomShape );
				myPhantomShape->removeReference();
				
				rbody->setShape( bvShape );
				bvShape->removeReference();
			}
			
			// Remove meshes if the user chose to do so
			if (m_options.m_removeMeshes && (hkString::strCmp(rbNode->m_object.getClass()->getName(), "hkxMesh")==0) )
			{
				rbNode->m_object = HK_NULL;
			}
			
			HK_REPORT("Converted rigid body \""<<rbName<<"\" to phantom action");
			numConverted++;
		}
	}

	// Give a warning if the filter didn't do anything useful
	if (numConverted==0)
	{
		HK_WARN_ALWAYS(0xabba7632, "No rigid bodies converted to phantom action.");
	}
	else
	{
		HK_REPORT("Converted "<<numConverted<<" rigid bodies.");
	}
}
示例#2
0
PhantomEventsDemo::PhantomEventsDemo( hkDemoEnvironment* env )
	:	hkDefaultPhysicsDemo(env, DEMO_FLAGS_NO_SERIALIZE)
{
	//
	// Setup the camera
	//
	{
		hkVector4 from(13.0f, 10.0f, 13.0f);
		hkVector4 to   (0.0f, 0.0f, 0.0f);
		hkVector4 up   (0.0f, 1.0f, 0.0f);
		setupDefaultCameras( env, from, to, up );
	}


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

		setupGraphics();
	}

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


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

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

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

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

		fixedBoxShape->removeReference();
	}

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


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

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

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

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

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

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


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

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

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

		boxInfo.m_shape = bvShape;
	

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

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

		boxRigidBody->removeReference();
		
	}

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

	m_world->unlock();
}