Ejemplo n.º 1
0
static void verifyIsTerminalOrTransform(const hkpShape* shape)
{
	if (hkOneFixedMoppUtil::isTerminalConvexShape(shape))
	{
		return;
	}

	hkpShapeType type = shape->getType();

	if (type == HK_SHAPE_TRANSFORM || type == HK_SHAPE_CONVEX_TRANSFORM || type == HK_SHAPE_CONVEX_TRANSLATE )
	{
		const hkpShape* childShape = HK_NULL;
		switch(type)
		{
			case HK_SHAPE_TRANSFORM: childShape = static_cast<const hkpTransformShape*>(shape)->getChildShape(); break;
			case HK_SHAPE_CONVEX_TRANSFORM: childShape = static_cast<const hkpConvexTransformShape*>(shape)->getChildShape(); break;
			case HK_SHAPE_CONVEX_TRANSLATE: childShape = static_cast<const hkpConvexTranslateShape*>(shape)->getChildShape(); break;
			default: break;
		}
		HK_ASSERT2(0xad7788dd, hkOneFixedMoppUtil::isTerminalConvexShape(childShape), "bad" );

		return;
	}

	HK_ASSERT2(0xad6888dd, false, "bad");
}
Ejemplo n.º 2
0
SkeletonDemo::SkeletonDemo( hkDemoEnvironment* env )
:	hkDefaultAnimationDemo(env)
{
	// Load the data
	m_loader = new hkLoader();

	// Convert the scene
	{
		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];
	}

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

	setupGraphics();
}
Ejemplo n.º 3
0
DumpClassListDemo::DumpClassListDemo( hkDemoEnvironment* env) 
	: hkDefaultDemo(env) 
{
	hkString filePath("Common/Api/Serialize/Versioning/DumpClassList/");
	hkString fileName = hkString(hkVersionUtil::getCurrentVersion()).replace("-","").replace(".","")+"Classes";
	const char registryVariableName[] = "CustomStaticRegistry";

	// Dump all currently reflected runtime classes
	// Open a stream to write the cpp header file
	{
		hkOstream outfile( hkString(filePath + fileName + ".h").cString() );
		HK_ASSERT2( 0x215d080f, outfile.isOk(), "Could not open '" << fileName.cString() << "h' for writing." );
		// extern the runtime classes into the header file
		hkVersionUtil::generateCppExternClassList(outfile, fileName.replace(".","_").asUpperCase().cString(), classes, registryVariableName);
	}
	// Open a stream to write the cpp source file
	{
		hkOstream outfile( hkString(filePath + fileName + ".cpp").cString() );
		HK_ASSERT2( 0x215d0810, outfile.isOk(), "Could not open '" << fileName.cString() << "cpp' for writing." );
		// set demos pch file
		const char* pchfilename = "demos/Demos.h";
		// dump the runtime classes into the cpp file
		hkVersionUtil::generateCppClassList(outfile, classes, pchfilename, registryVariableName);
	}
}
hkResult DestructibleHierarchy::updateRigidBodyOfDestructibleHierarchy(DestructibleHierarchy* hierarchy, unsigned int nodeIdx, hkpRigidBody* newOwningBody)
{
	Node* node = &hierarchy->m_nodes[nodeIdx];

	while(node->m_body == HK_NULL)
	{
		HK_ASSERT2(0xad789aae, node->m_parentIdx != INVALID_NODE_INDEX, "could not find the parent hkpRigidBody.");
		node = &hierarchy->m_nodes[node->m_parentIdx];
	}

//!! update for Evos
	if (node->m_body)
	{
		HK_ASSERT2(0xad789aee, node->m_initialTransformOfHierarchy == HK_NULL, "this body was alredy reassigned to a different hkpRigidBody once..");
		node->m_initialTransformOfHierarchy = new hkTransform(node->m_body->getTransform());

		node->m_body->removeReference();
		node->m_body = newOwningBody;
		node->m_body->addReference();
		return HK_SUCCESS;
	}

	HK_ASSERT2(0xad768dda, false, "Could not find the rigid body a hierarchy");
	return HK_FAILURE;
}
void hkDefaultPhysicsDemo::loadAndAddRigidBodies( hkLoader* loader, const char* filename )
{
	//hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Physics/levels/test_level.hkx");
	hkString assetFile = hkAssetManagementUtil::getFilePath(filename);
	//hkString assetFile = hkAssetManagementUtil::getFilePath("Resources/Physics/levels/onemesh_test_level.hkx");
	hkRootLevelContainer* container = 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");
	m_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];

			// Associate the display and physics (by name)
			if (scene)
			{
				hkDefaultPhysicsDemo::addPrecreatedDisplayObjectsByName( psys[i]->getRigidBodies(), scene );
			}
			// add the lot to the world
			m_world->addPhysicsSystem(system);
		}
	}
}
Ejemplo n.º 6
0
WindChimesDemo::WindChimesDemo(hkDemoEnvironment* env)
:	hkDefaultPhysicsDemo(env),
	m_loader(HK_NULL)
{
	const WindChimesVariant& variant =  g_variants[m_variantId];

	//
	// Create the sound manager.
	//

	//
	// Set up the camera
	//
	{
		hkVector4 from(6.0f, 0.0f, 3.0f);
		hkVector4 to  (0.0f, 0.0f, 0.0f);
		hkVector4 up  (0.0f, 0.0f, 1.0f);
		setupDefaultCameras( env, from, to, up );
	}

	hkString assetFile = hkAssetManagementUtil::getFilePath(variant.m_assetName);
	m_loader = new hkLoader();
	hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
	HK_ASSERT2(0xaefe9356, container != HK_NULL , "Could not load asset");

	hkpPhysicsData* physics = static_cast<hkpPhysicsData*>( container->findObjectByType( hkpPhysicsDataClass.getName() ) );
	HK_ASSERT2(0x245982ae, physics != HK_NULL, "Could not find physics data in root level object" );
	{
		m_world = new hkpWorld( *physics->getWorldCinfo() );

		m_world->lock();

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

		setupGraphics();
	}

	m_world->addPhysicsSystem( physics->getPhysicsSystems()[0] );

	// There are 5 pipes in the circular chimes asset, called Chime0, Chime1...etc.
	for( int i = 0; i < variant.m_numChimes; i++ )
	{
		hkString chimeName;
		chimeName.printf( "Chime%d", i );
		hkpRigidBody* chime = physics->findRigidBodyByName( chimeName.cString() );
		HK_ASSERT(0x99862353, chime);

		new WindChimesCollisionListener( chime, i % variant.m_numDifferentChimeSizes );
	}
	m_world->unlock();
}
Ejemplo n.º 7
0
// the original shapes should be intact..
hkpShape* hkFlattenShapeHierarchyUtil::flattenHierarchy(const hkpShape* shape)
{
	hkArray<hkpExtendedMeshShape::TrianglesSubpart> triangleParts;
	hkArray<hkpConvexShape*> convexShapes;
	hkArray<hkpShape*> otherShapes;

	// Get all leaf shapes with their 'wrapping' transform shapes onto the list
	getLeafShapesFromShape(shape, hkTransform::getIdentity(), false, triangleParts, convexShapes, otherShapes);

	hkpShape* list = HK_NULL;

	hkArray<hkpShape*> allShapes;
	for (int s = 0; s < convexShapes.getSize(); s++)
	{
		allShapes.pushBack(static_cast<hkpShape*>(convexShapes[s]));
	}
	for (int s = 0; s < otherShapes.getSize(); s++)
	{
		allShapes.pushBack(otherShapes[s]);
	}

	HK_ASSERT2(0xad6788c6, allShapes.getSize(), "No shapes to process!.");

	if (allShapes.getSize() > 1)
	{
		list = new hkpListShape(allShapes.begin(), allShapes.getSize());
		for (int s = 0; s < allShapes.getSize(); s++)
		{
			allShapes[s]->removeReference();
		}
	}
	else
	{
		return allShapes[0];
	}


	HK_ASSERT2(0xad789aaa, 0 == list->getUserData(), "Overwriting user data ?");

	// WE'RE MARKING THIS BODY FOR INCLUSION IN THE FIXED UBER SHAPE LATER ..
	//  -- only if the number of child shapes is greater than 20
//	if (list->getNumChildShapes() > 20)
	{
		list->setUserData(0x0000beef);
	}

	return list;
}
/// Initialize multi-threading sharedThreadData and create threads.
vHavokCpuJobThreadPool::vHavokCpuJobThreadPool(const vHavokCpuJobThreadPoolCinfo& ci)
{
    m_isRunning = false;
    m_threadName = ci.m_threadName;
    m_stackSize = ci.m_stackSize;

    m_sharedThreadData.m_localHavokStackSize = ci.m_havokStackSize;
    m_sharedThreadData.m_timerBufferAllocation = ci.m_timerBufferPerThreadAllocation;

    int numThreads = ci.m_numThreads;
    if (numThreads >= MAX_NUM_THREADS)
    {
        HK_WARN( 0xf0defd23, "You requested 6 or more threads, this is not supported by vHavokCpuJobThreadPool" );
        numThreads = MAX_NUM_THREADS - 1;
    }

    m_sharedThreadData.m_numThreads = numThreads;

    m_sharedThreadData.m_OnWorkerThreadCreatedPtr = ci.m_OnWorkerThreadCreatedPtr;
    m_sharedThreadData.m_OnWorkerThreadFinishedPtr = ci.m_OnWorkerThreadFinishedPtr;

#if defined(HK_PLATFORM_XBOX360)
    int numCores = 3;
    int numThreadsPerCore = 2;
#elif defined(HK_PLATFORM_WIN32)
    hkHardwareInfo info;
    hkGetHardwareInfo( info );
    int numCores = info.m_numThreads; //This reports actual cores - ignoring hyperthreading
    int numThreadsPerCore = 1;
    numCores /= numThreadsPerCore;
#endif

    for (int i = 0; i < numThreads; i++ )
    {
        WorkerThreadData& data = m_workerThreads[i];
        data.m_sharedThreadData = &m_sharedThreadData;
        data.m_threadId = i + 1; // don't start with thread 0 (assume that is the calling thread)
        data.m_monitorStreamBegin = HK_NULL;
        data.m_monitorStreamEnd = HK_NULL;
        data.m_killThread = false;
        data.m_clearTimers = false;

#if defined(HK_PLATFORM_XBOX360) || defined(HK_PLATFORM_WIN32)
        if (ci.m_hardwareThreadIds.getSize() > 0)
        {
            HK_ASSERT2( 0x975fe134, ci.m_hardwareThreadIds.getSize() >= numThreads, "If you initialize hardware thread ids, you must give an ID to all threads");
            data.m_hardwareThreadId = ci.m_hardwareThreadIds[i];
        }
        else
        {
            //X360: { 2,4,1,3,5, 0, 2,4,.. }
            int procGroup = (data.m_threadId % numCores) * numThreadsPerCore;
            data.m_hardwareThreadId = procGroup + (numThreadsPerCore > 1? ((data.m_threadId / numCores) % numThreadsPerCore) : 0 );
        }
#endif

        data.m_thread.startThread( &hkWorkerThreadFunc, &data, m_threadName, m_stackSize );
    }
    hkReferencedObject::setLockMode( hkReferencedObject::LOCK_MODE_AUTO);
}
Ejemplo n.º 9
0
void HK_CALL popDoubleConversionCheck()
{
	g_checkDoubleStackIndex--;
	HK_ASSERT2(0x7511c51f, g_checkDoubleStackIndex >= 0, "Double check underflow");
	
	g_checkDoubles = g_checkDoubleStack[g_checkDoubleStackIndex];
}
void DestructibleHierarchy::insertShapeKeysIntoDestructibleHierarchy(hkpRigidBody* fixedBody)
{
	const hkpShape* shape = fixedBody->getCollidable()->getShape();
	HK_ASSERT2(0xad6738dd, shape->getType() == HK_SHAPE_MOPP, "The fixed body must have a mopp.");
	const hkpMoppBvTreeShape* mopp = static_cast<const hkpMoppBvTreeShape*>(shape);

	hkArray<hkpShapeKey> shapeKeys;
	hkMoppFindAllVirtualMachine_getAllKeys(mopp->getMoppCode(), &shapeKeys );

	// ultimately we want to skip looking through triangles here..

	hkpShapeCollection::ShapeBuffer shapeBuffer;
	//hkpShape* childShape = reinterpret_cast<hkpShape*>(&shapeBuffer);
	for (int k = 0; k < shapeKeys.getSize(); k++)
	{
		hkpShapeKey shapeKey = shapeKeys[k];
		const hkpShape* childShape = mopp->getShapeCollection()->getChildShape(shapeKey, shapeBuffer);
		hkUint16 lookupIdx = hkUint16((hkUlong(childShape->getUserData())>>16) & 0xffff);

		if (childShape->getUserData())
		{
			int oyo  = 0;
			oyo++;
		}

		if (lookupIdx)
		{
			DestructibleHierarchy* hierarchy = DestructibleHierarchy::getDestructibleHierarchy(lookupIdx);
			unsigned int nodeIdx = DestructibleHierarchy::getNodeIndex(lookupIdx);

			DestructibleHierarchy::Node* node = &hierarchy->m_nodes[nodeIdx];
			node->m_shapeKey = shapeKey;
		}
	}
}
hkpRigidBody* DestructibleHierarchy::buildRigidBody(const hkpShape* shape, DestructibleHierarchy* hierarchy, int nodeIdx)
{
	hkpRigidBodyCinfo info;
	info.m_shape = shape;
	
	hkpMassProperties massProperties;
	hkpInertiaTensorComputer::computeShapeVolumeMassProperties(shape, 1000.0f, massProperties);
	
	info.m_centerOfMass = massProperties.m_centerOfMass;
	info.m_inertiaTensor.setMul(massProperties.m_volume, massProperties.m_inertiaTensor);
	info.m_mass = massProperties.m_volume * massProperties.m_mass;

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

		// Many broken off elements will have thin box inertia, so we limit their angular vel.
	//info.m_maxAngularVelocity = 5.0f;

	hkpRigidBody* body = new hkpRigidBody(info);

	if (nodeIdx == INVALID_NODE_INDEX)
	{
		nodeIdx = hierarchy->m_rootNodeIdx;
	}
	hkpRigidBody*& bodyPtr = hierarchy->m_nodes[nodeIdx].m_body;

	HK_ASSERT2(0xad7899dd, bodyPtr == HK_NULL, "Overwriting body pointer");
	bodyPtr = body;
	body->addReference();

	return body;
}
void vHavokBehaviorComponent::InitVisionCharacter( VisBaseEntity_cl* entityOwner )
{
	m_entityOwner = entityOwner;
	m_isListeningToEvents = false;

	vHavokBehaviorModule* behaviorModule = vHavokBehaviorModule::GetInstance();
	if( behaviorModule != HK_NULL )
	{
		HK_ASSERT2(0x2f1c46e9, m_character == HK_NULL, "Character should be freed first." );

		// Try to create a character.  May fail if path/file settings are not specified
		m_character = behaviorModule->addCharacter( this );
		if( m_character != HK_NULL )
		{
			// Set up the animation config and create bone mapping
			UpdateAnimationAndBoneIndexList();

			// Set character transform
			UpdateHavokTransformFromVision();

			// Update the Physics
			UpdateBehaviorPhysics();
		}
	}
}
Ejemplo n.º 13
0
//
//	Creates a scaled version of the given hkpMoppBvTreeShape
//	Both the triangle data and hkpMoppCode are shared between the instances, resulting in very little memory overhead.
//  Also, since we use existing Havok classes, the resulting shapes can be simulated on the SPU without any additional work.
//	There are a few important things to note:
//	1) If the world is serialized out after the scaled instance is created (e.g. with hkpHavokSnapshot), multiple copies of
//		the code will be stored.
//	2) The scaled instance must not be used after the original is removed from memory. This is because the hkpMoppCode
//		isn't reference counted.
//  3) Scaling is currently only supported for hkpExtendedMeshShape. If the hkpExtendedMeshShape has ShapesSubpart, these
//		will NOT be scaled correctly.
//
hkpMoppBvTreeShape* MoppInstancingDemo::createScaledMopp(const hkpMoppBvTreeShape* originalMopp, hkReal relativeScale)
{
	const hkpShape* oldContainer = originalMopp->getShapeCollection();
	HK_ASSERT2(0x530b238a, oldContainer->getType() == HK_SHAPE_EXTENDED_MESH, "This function only scales hkpExtendedMeshShapes");

	const hkpExtendedMeshShape* oldMesh = static_cast<const hkpExtendedMeshShape*>(oldContainer);

	// Create an new mesh, and copy the mesh data
	// Note that the underlying vertex data isn't duplicated, only the pointer information, etc.
	hkpExtendedMeshShape* newMesh;
	{
		newMesh= new hkpExtendedMeshShape(oldMesh->getRadius(), oldMesh->getNumBitsForSubpartIndex());
		
		// Adjust the mesh scaling for the copy.
		// We have to do this BEFORE we add the triangle subparts, or else the AABB won't be computed correctly
		hkVector4 scaleMult; scaleMult.setAll3(relativeScale);
		hkVector4 newMeshScale; newMeshScale.setMul4( scaleMult, oldMesh->getScaling() );
		newMesh->setScaling(newMeshScale);

		for (int i=0; i<oldMesh->getNumTrianglesSubparts(); i++)
		{
			newMesh->addTrianglesSubpart(oldMesh->getTrianglesSubpartAt(i));
		}
		HK_ASSERT2(0x401d4c68, oldMesh->getNumShapesSubparts() == 0, "Can't scale shape subparts!");
	
	}

	// Create a new hkpMoppCode. The internal data points to the original data, so the memory overhead is negligible.
	const hkpMoppCode* oldCode = originalMopp->getMoppCode();
	hkpMoppCode* newcode;
	{
		hkpMoppCode::CodeInfo newCodeInfo = oldCode->m_info;

		// This is the tricky part. Adjusting the offset in this way will ensure that the collisions are handled properly.
		hkVector4 codeMult; codeMult.set( relativeScale, relativeScale, relativeScale, 1.0f / relativeScale );
		newCodeInfo.m_offset.mul4(codeMult);

		// Use the newly scaled hkpMoppCode::CodeInfo, and point to the old data
		newcode = new hkpMoppCode(newCodeInfo, oldCode->m_data.begin(), oldCode->m_data.getSize());
	}

	hkpMoppBvTreeShape* newMopp = new hkpMoppBvTreeShape(newMesh, newcode);
	newMesh->removeReference();
	newcode->removeReference();
	
	return newMopp;
}
Ejemplo n.º 14
0
void HK_CALL pushDoubleConversionCheck(hkBool enable)
{
	g_checkDoubleStack[g_checkDoubleStackIndex] = g_checkDoubles;
	g_checkDoubleStackIndex++;
	HK_ASSERT2(0x6c9871d4, g_checkDoubleStackIndex < 255, "Double check overflow");
	
	g_checkDoubles = enable;
}
BridgeLand::BridgeLand(hkReal maxHeight, int numTiles, hkReal canyonWidthRatio, hkBool smoothBreak) : FlatLand(numTiles)
{
	HK_ASSERT2(0xaf25fe34, canyonWidthRatio > 0.0f && canyonWidthRatio < 1.0f, "The canyon's width ratio must be between (and excluding) 0 and 1.");

	m_maxHeight				= maxHeight;
	m_halfCanyonWidthRatio	= canyonWidthRatio * 0.5f;
	m_smoothBreak			= smoothBreak;
}
hkUint16 DestructibleHierarchy::getLookupIndexOfNewDestructibleNode(DestructibleHierarchy* hierarchy, int nodeIdxInDestructibleHierarchy)
{
	HK_ASSERT2(0xad678bad, s_nodeInfos, "Array not created.");
	if (s_nodeInfos->isEmpty())
	{
		// dummy node, so that index of valid nodes in non-zero
		s_nodeInfos->expandOne();
	}

	unsigned int lookupIdx = s_nodeInfos->getSize();

	NodeInformation& info = s_nodeInfos->expandOne();
	info.m_destructibleHierarchy = hierarchy;
	info.m_nodeIdx = nodeIdxInDestructibleHierarchy;
	HK_ASSERT2(0xad6288dd, s_nodeInfos->getSize() <= (1<<16), "Too many destructible nodes in the lookup table -- we only have 16 bits for the index into the table" );

	return hkUint16(lookupIdx);
}
void vHavokCpuJobThreadPool::removeThread()
{
    HK_ASSERT2(0xad67bd89, !m_isRunning, "You can only add or remove working threads via calls from the master thread and not between processJobs() and waitForCompletion() calls. ");

    HK_ASSERT2(0xcede9735, m_sharedThreadData.m_numThreads > 0, "You cannot set a negative number of threads" );

    --m_sharedThreadData.m_numThreads;

    WorkerThreadData& data = m_workerThreads[m_sharedThreadData.m_numThreads];

    // Signal the thread to be killed, and release the thread
    data.m_killThread = true;
    data.m_semaphore.release();

    // Wait until the thread actually finishes
    m_sharedThreadData.m_workerThreadFinished.acquire();
    data.m_thread.joinThread();
}
void vHavokCpuJobThreadPool::addThread()
{
    HK_ASSERT2(0xad67bd88, ! m_isRunning, "You can only add or remove working threads via calls from the master thread and not between processAllJobs() and waitForCompletion() calls. ");

#if defined(HK_PLATFORM_HAS_SPU)
    HK_ASSERT2(0xcede9735, m_sharedThreadData.m_numThreads < 2, "Only 2 PPU threads are supported on the PS3" );
#endif

    HK_ASSERT2(0xcede9734, m_sharedThreadData.m_numThreads < MAX_NUM_THREADS, "A maximum of 6 threads are supported." );
    WorkerThreadData& data = m_workerThreads[m_sharedThreadData.m_numThreads];
    data.m_sharedThreadData = &m_sharedThreadData;
    data.m_threadId = m_sharedThreadData.m_numThreads+1;
    data.m_monitorStreamBegin = HK_NULL;
    data.m_monitorStreamEnd = HK_NULL;
    data.m_killThread = false;
    data.m_clearTimers = false;

#if defined(HK_PLATFORM_WIN32) || defined(HK_PLATFORM_XBOX360)
#if defined HK_PLATFORM_XBOX360
    int numCores = 3;
    int numThreadsPerCore = 2;
#elif defined(HK_PLATFORM_WINRT)
    //XX	   GetSystemInfoEx(&sysInfo);
    int numCores = 4;
    int numThreadsPerCore = 1;
#else
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);

    int numCores = sysInfo.dwNumberOfProcessors;
    int numThreadsPerCore = 1; //XX Work out hyper threading (not just logical versus physical processors)
    numCores /= numThreadsPerCore;
#endif

    //X360: { 2,4,1,3,5, 0, 2,4,.. }
    int procGroup = (data.m_threadId % numCores) * numThreadsPerCore;
    data.m_hardwareThreadId = procGroup + (numThreadsPerCore > 1? ((data.m_threadId / numCores) % numThreadsPerCore) : 0 );
#endif

    data.m_thread.startThread( &hkWorkerThreadFunc, &data, m_threadName, m_stackSize);
    m_sharedThreadData.m_numThreads++;
}
Ejemplo n.º 19
0
DoorSpring::DoorSpring(const hkpConstraintInstance* hinge, const hkReal strength, const hkReal damping)
: hkpUnaryAction(hinge->getEntityA())
, m_hinge(hinge)
, m_strength(strength)
, m_damping(damping)
, m_angVel(0.0f)
, m_torque(0.0f)
{
	// Assume the door is hung vertically
	m_axis = m_entity->getWorld()->getGravity();
	m_axis.normalize3();
	HK_ASSERT2(0x0, !m_entity->isFixed(), "Entity A must be dynamic, only because that is the entity that I pass to the hkpUnaryAction constructor.");
}
Ejemplo n.º 20
0
void HK_CALL VehicleApiUtils::reorient(hkBool buttonPressed, hkpAction* action, hkpWorld* world) 	 
{ 	
	HK_ASSERT2(0x0, action != HK_NULL, "Action is NULL in VehicleApiUtils::reorient()!");
	HK_ASSERT2(0x0, world != HK_NULL, "World is NULL in VehicleApiUtils::reorient()!");

	if ( buttonPressed ) 	 
	{ 	 
		// If not already added, add it
		if ( action->getWorld() == HK_NULL ) 	 
		{ 	 
			world->addAction(action); 	
		} 	 
	} 	 
	else 	 
	{ 	 
		// If not already removed, remove it
		if ( action->getWorld() != HK_NULL ) 	 
		{ 	 
			world->removeAction(action); 	 
		} 	 
	} 	 

}
void vHavokCpuJobThreadPool::processAllJobs( hkJobQueue* queue, hkJobType firstJobType_unused )
{
    m_sharedThreadData.m_jobQueue = queue;

    HK_ASSERT2(0xad56dd77, m_isRunning == false, "Calling vHavokCpuJobThreadPool::processJobs() for the second time, without having called vHavokCpuJobThreadPool::waitForCompletion().");

    m_isRunning = true;

    for (int i = m_sharedThreadData.m_numThreads - 1; i >=0; i--)
    {
        WorkerThreadData& data = m_workerThreads[i];
        data.m_semaphore.release();
    }
}
Ejemplo n.º 22
0
hkaSkeleton* gkRigManager::loadRig( const TCHAR* name )
{

	// check if we had one
	RigMap::iterator it = m_mapRigs.find(name);

	if (it != m_mapRigs.end())
	{
		return it->second;
	}

	CHAR szPath[MAX_PATH] = "";
#ifdef UNICODE
	WideCharToMultiByte(CP_ACP, 0,  name, -1, szPath, MAX_PATH, NULL, NULL);
#else
	_tcscpy_s( szPath, MAX_PATH, name );
#endif

	hkStringBuf assetFile(szPath); hkAssetManagementUtil::getFilePath(assetFile);
	hkRootLevelContainer* container = getAnimationPtr()->getGlobalLoader()->load( szPath );
	HK_ASSERT2(0x27343437, container != HK_NULL , "Could not load asset");

	if (!container)
	{
		return false;
	}

	hkaAnimationContainer* ac = reinterpret_cast<hkaAnimationContainer*>( container->findObjectByType( hkaAnimationContainerClass.getName() ));

	HK_ASSERT2(0x27343435, ac && (ac->m_skeletons.getSize() > 0), "No skeleton loaded");
	hkaSkeleton* skeleton = ac->m_skeletons[0];

	m_mapRigs.insert(RigMap::value_type(name, skeleton));

	return skeleton;
}
Ejemplo n.º 23
0
void MyExtendedUserDataListener::contactPointConfirmedCallback( hkpContactPointConfirmedEvent& event)
{
	// Get num extra user datas for that body
	const int numDatas = event.getNumExtendedUserDatas(event.m_callbackFiredFrom);

	// Create a temp array to store the data
	hkInplaceArray<hkpContactPointProperties::UserData, 8> data; data.setSize(numDatas);

	// Get the data
	event.getExtendedUserDatas(event.m_callbackFiredFrom, data.begin(), numDatas);

	int id = data[numDatas-1];
	HK_ASSERT2(0xad755512, m_contactInfos[id].m_confirmed == false 
		                && m_contactInfos[id].m_processed >=1, "Callbacks don't match."); // We might have multiple process callbacks already if the point was involved in a toi
	m_contactInfos[id].m_confirmed = true;
}
void vHavokBehaviorComponent::InitVisionCharacter( VisBaseEntity_cl* entityOwner )
{
	m_entityOwner = entityOwner;
	m_isListeningToEvents = false;

	vHavokBehaviorModule* behaviorModule = vHavokBehaviorModule::GetInstance();
	if( behaviorModule != HK_NULL )
	{
		HK_ASSERT2(0x2f1c46e9, m_character == HK_NULL, "Character should be freed first." );

		// Try to create a character.  May fail if path/file settings are not specified
		m_character = behaviorModule->addCharacter( this );
		if( m_character != HK_NULL )
		{
			// Set up the animation config and create bone mapping
			UpdateAnimationAndBoneIndexList();

			// Set character transform
			UpdateHavokTransformFromVision();

			// Update the Physics
			UpdateBehaviorPhysics();

			// Tag ragdoll rigid bodies to be ignored by nav mesh cutting
			hkbRagdollDriver* ragdollDriver = m_character->getRagdollDriver();
			if (ragdollDriver)
			{
				hkbRagdollInterface* ragdollInterface = ragdollDriver->getRagdollInterface();
				if (ragdollInterface)
				{
					for (int i = 0; i < ragdollInterface->getNumBones(); i++)
					{
						hkpRigidBody* rigidBody = static_cast<hkpRigidBody*>(ragdollInterface->getRigidBodyOfBone(i));
						if (rigidBody)
						{
							rigidBody->addProperty(VHAVOK_PROPERTY_DO_NO_CUT_NAV_MESH, 1);
						}
					}
				}
			}
		}
	}
}
Ejemplo n.º 25
0
hkResult BrowseDemo::readAndSetupPackfile(const char* filename)
{
	hkRefPtr<hkResource> res = hkSerializeUtil::load(filename);
	if( res )
	{
		// Keep a handle to the loaded data
		m_packfileData = res;

		// Get the top level object in the file
		m_contents = res->getContents<hkRootLevelContainer>();
		HK_ASSERT2(0xa6451543, m_contents != HK_NULL, "Could not load root level obejct" );

		if( hkpPhysicsData* physicsData = static_cast<hkpPhysicsData*>( m_contents->findObjectByType( hkpPhysicsDataClass.getName() ) ) )
		{
			//HK_ASSERT2(0xa6451544, physicsData != HK_NULL, "Could not find physics data in root level object" );
			//HK_ASSERT2(0xa6451535, physicsData->getWorldCinfo() != HK_NULL, "No physics cinfo in loaded file - cannot create a hkWorld" );
			if( physicsData->getWorldCinfo() )
			{
				// Create a world and add the physics systems to it
				m_world = new hkpWorld( *physicsData->getWorldCinfo() );
				m_world->lock();

				// Register all collision agents
				hkpAgentRegisterUtil::registerAllAgents( m_world->getCollisionDispatcher() );

				// Add all the physics systems to the world
				for ( int i = 0; i < physicsData->getPhysicsSystems().getSize(); ++i )
				{
					m_world->addPhysicsSystem( physicsData->getPhysicsSystems()[i] );
				}

				// Setup graphics - this creates graphics objects for all rigid bodies and phantoms in the world
				setupGraphics();
				m_world->unlock();
			}
		}
	}

	return res ? HK_SUCCESS : HK_FAILURE;
}
	void updatePackfileDataVersion(hkArray<char>& ioBuf)
	{
		hkArray<char> origBuf;
		origBuf.swap(ioBuf);

		// Load the entire file inplace
		hkBinaryPackfileReader reader;
		reader.loadEntireFileInplace(origBuf.begin(), origBuf.getSize());

		// check versioning
		if( hkVersionUtil::updateToCurrentVersion( reader, hkVersionRegistry::getInstance() ) != HK_SUCCESS )
		{
			HK_WARN_ALWAYS(0, "Couldn't update version, skipping.\n");
		}
		// Get the top level object in the file
		hkRootLevelContainer* container = static_cast<hkRootLevelContainer*>( reader.getContents( hkRootLevelContainerClass.getName() ) );
		HK_ASSERT2(0xa6451543, container != HK_NULL, "Could not load root level obejct" );

		hkOstream nativeFile(ioBuf);
		hkBool success = hkpHavokSnapshot::save(container, hkRootLevelContainerClass, nativeFile.getStreamWriter(), true);
		HK_ASSERT(0xa6451545, success == true);
	}
hkDemo::Result DestructibleWallsDemo::stepDemo()
{
	m_world->lock();

	{
		const hkgPad* pad = m_env->m_gamePad;

		// Cannon control + drawing
		// check to see if the user has pressed one of the control keys:
		int x = ((pad->getButtonState() & HKG_PAD_DPAD_LEFT) != 0)? -1:0;
		x = ((pad->getButtonState() & HKG_PAD_DPAD_RIGHT) != 0)? 1:x;
		int y = ((pad->getButtonState() & HKG_PAD_DPAD_DOWN) != 0)? -1:0;
		y = ((pad->getButtonState() & HKG_PAD_DPAD_UP) != 0)?    1:y;

		m_shootingDirX += x * 0.015f;
		m_shootingDirY += y * 0.015f;

		hkVector4 canonStart( m_centerOfScene );
		canonStart(2) += m_options.m_WallsWidth*2.0f;

		hkVector4 canonDir( m_shootingDirX, m_shootingDirY, -1.0f );
		canonDir.normalize3();

		// display the canon direction 
		{
			hkpWorldRayCastInput in;
			in.m_from = canonStart;
			in.m_to.setAddMul4( in.m_from, canonDir, 100.0f );
			in.m_filterInfo = 0;
			hkpWorldRayCastOutput out;
			m_world->castRay( in , out );
			hkVector4 hit; hit.setInterpolate4( in.m_from, in.m_to, out.m_hitFraction );
			HK_DISPLAY_LINE( in.m_from, hit, 0x600000ff );
			if ( out.hasHit() )
			{
				HK_DISPLAY_ARROW( hit, out.m_normal, 0x60ff00ff );
			}
			HK_DISPLAY_ARROW( canonStart, canonDir, hkColor::CYAN );
		}

		// Shooting bullets
		{
			hkBool shooting = false;

			if ( pad->wasButtonPressed(HKG_PAD_BUTTON_1)!= 0 )
			{
				shooting = true;
			}

			if (  pad->isButtonPressed(HKG_PAD_BUTTON_2)!= 0)
			{
				if ( m_gunCounter-- < 0 )
				{
					shooting = true;
					m_gunCounter = 5;
				}
			}  

			if ( shooting )
			{
				hkpMassProperties result;
				hkpInertiaTensorComputer::computeSphereVolumeMassProperties(m_options.m_cannonBallRadius, m_options.m_cannonBallMass, result);

				hkpSphereShape* sphereShape = new hkpSphereShape(m_options.m_cannonBallRadius); 
				hkVector4 spherePos(-20.0f, 0.0f + m_options.m_cannonBallRadius, 200.0f);

				hkpRigidBodyCinfo sphereInfo;
				sphereInfo.m_mass = result.m_mass;
				sphereInfo.m_centerOfMass = result.m_centerOfMass;
				sphereInfo.m_inertiaTensor = result.m_inertiaTensor;
				sphereInfo.m_shape = sphereShape;
				sphereInfo.m_motionType = hkpMotion::MOTION_BOX_INERTIA;
				sphereInfo.m_position = canonStart;
				sphereInfo.m_qualityType = HK_COLLIDABLE_QUALITY_BULLET;
				sphereInfo.m_linearVelocity.setMul4( 100.0f, canonDir );

				hkpRigidBody* bullet = new hkpRigidBody( sphereInfo );
				sphereInfo.m_shape->removeReference();

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

	// release the world
	m_world->unlock();

	// step demo
	hkDemo::Result res = hkDefaultPhysicsDemo::stepDemo();


	//HK_TIMER_BEGIN_LIST( "Update Walls", "Update Walls"/*HK_NULL*/);
	HK_TIMER_BEGIN( "Update Walls", "update walls"/*HK_NULL*/);
	if(m_collisionDetectionType == PARALLEL)
	{
		HK_ASSERT2(0x7274e9ec, m_fractureUtility!=HK_NULL ,"The parallel simulation wasn't set!!");
		// and update walls
		m_fractureUtility->Update();
	}
	HK_TIMER_END();

	HK_TIMER_BEGIN("DebugDisplay", HK_NULL);
	// DEBUG DISPLAY
	if(m_fractureUtility->getSimulation() && m_options.m_showDebugDisplay)
	{
		// applied impulses
		for(int i=0; i<m_fractureUtility->getSimulation()->debugImpulses.getSize(); i+=2)
		{
			hkVector4 start( m_fractureUtility->getSimulation()->debugImpulses[i] );
			hkVector4 end( m_fractureUtility->getSimulation()->debugImpulses[i+1] );
			end.mul4( 0.01f );
			HK_DISPLAY_ARROW(start, end , 0x00000000);			
		}
		
		if(m_fractureUtility->getSimulation()->debugImpulses.getSize() > 100 )
			m_fractureUtility->getSimulation()->debugImpulses.clear();

		// bricks positions in parallel simulation
		hkArray<hkVector4> positions;
		m_fractureUtility->getSimulation()->getAllBricksPositions( positions );
		for(int i=0; i<positions.getSize(); ++i)
		{
			drawBrick(positions[i] , m_brickHalfExtents);
		}
		positions.clear();

		// edges of union find
		for(int i=0; i<m_fractureUtility->getSimulation()->debugEdges.getSize(); i+=2)
		{
			HK_DISPLAY_LINE(m_fractureUtility->getSimulation()->debugEdges[i], m_fractureUtility->getSimulation()->debugEdges[i+1] , 0x00000000);
		}
	}
	HK_TIMER_END();

	if(m_collisionDetectionType == PARALLEL)
	{
		hkArray< hkVector4 > planes;
		m_fractureUtility->getSimulation()->getAllDebugfracturePlanes(planes);
		for(int i=0; i< planes.getSize()-2; ++i)
		{
			if(planes[i].length3()!=0)
			{
				hkVector4 offset(.0f, .5f, .0f/*.5f, .5f, .5f*/);
				HK_DISPLAY_PLANE(planes[i], offset, 0.5f, 0xffffffff);
			}
		}
		if(!planes.isEmpty() && planes[planes.getSize()-1].length3()!=0)
		{
			hkVector4 offset(.0f, .5f, .0f/*.5f, .5f, .5f*/);
			HK_DISPLAY_PLANE(planes[planes.getSize()-2], offset, 0.5f, 0x00000000);
			HK_DISPLAY_PLANE(planes[planes.getSize()-1], offset, 0.5f, 0xffff0000);
		}
		hkArray<hkVector4> cpts;
		hkArray<hkVector4> impulses;
		m_fractureUtility->getSimulation()->getAllDebugImpulsesAndContactPoints(impulses, cpts);
		for(int i=0; i< cpts.getSize(); ++i)
		{
			HK_DISPLAY_ARROW(cpts[i], impulses[i] , 0x00000000);	
		}
	}
	return res;
}
void DestructibleHierarchy::breakOffNode(int nodeIdx, hkArray<DestructibleHierarchyCollisionEvent>& collisionEvents)
{
	Node* node = &m_nodes[nodeIdx];

	int immediateParent = node->m_parentIdx;
	HK_ASSERT2(0xad78d9dd, immediateParent != INVALID_NODE_INDEX, "where's the parent?");

	// detach from parent
	Node* immediateParentNode = &m_nodes[immediateParent];
	HK_ON_DEBUG( int initChildCount = immediateParentNode->m_childrenIdx.getSize() );
	for (int c = 0; c < immediateParentNode->m_childrenIdx.getSize(); c++)
	{
		if (immediateParentNode->m_childrenIdx[c] == nodeIdx)
		{
			immediateParentNode->m_childrenIdx.removeAtAndCopy(c);
			break;
		}
	}
	HK_ASSERT2(0xad78ddaa, initChildCount-1 == immediateParentNode->m_childrenIdx.getSize(), "child not detached!" );

	hkTransform accumulatedTransform = immediateParentNode->m_transform;

	// Find parent rigid body..
	int parentIdx = immediateParent;
	Node* parentNode = immediateParentNode;
	while(parentNode->m_body == HK_NULL)
	{
		parentIdx = parentNode->m_parentIdx;
		parentNode = &m_nodes[parentIdx];
		hkTransform tmp; tmp.setMul(parentNode->m_transform, accumulatedTransform);
		accumulatedTransform = tmp;
		HK_ASSERT2(0xad678daa, parentNode, "No parent rigid body found!");
	}

	// Create new body
	hkpRigidBody* newBody;
	{
		hkpShape* shape = buildShape(nodeIdx);
		hkpShape* flatShape = hkFlattenShapeHierarchyUtil::flattenHierarchy(shape);
		shape->removeReference();
		newBody = DestructibleHierarchy::buildRigidBody(flatShape, this, nodeIdx);
		flatShape->removeReference();

		const hkSmallArray< hkpCollisionListener* >& listeners = parentNode->m_body->getCollisionListeners();
		for (int i = 0; i < listeners.getSize(); i++)
		{
			newBody->addCollisionListener(listeners[i]);
		}

	}
	// init velocites for new body
	{
		// reposition the body
		hkTransform parentTransform;
		if (parentNode->m_initialTransformOfHierarchy)
		{
			parentTransform = *parentNode->m_initialTransformOfHierarchy;
		}
		else
		{
			parentTransform = parentNode->m_body->getTransform();
		}
		hkTransform newBodyTransform; newBodyTransform.setMul( parentTransform, accumulatedTransform );
		newBody->setTransform(newBodyTransform);

		// compute velocities
		hkVector4 linVel = parentNode->m_body->getLinearVelocity();
		hkVector4 angVel = parentNode->m_body->getAngularVelocity();
		hkVector4 relCm; relCm.setSub4(newBody->getCenterOfMassInWorld(), parentNode->m_body->getCenterOfMassInWorld());
		hkVector4 extraLin; extraLin.setCross(angVel, relCm);
		linVel.add4(extraLin);
		newBody->setLinearVelocity( linVel );
		newBody->setAngularVelocity( angVel );

	}

	// set newBody  position
	parentNode->m_body->getWorld()->addEntity(newBody);
	newBody->removeReference();
	newBody = HK_NULL;

	// Update shape of parent body
	if (!parentNode->m_body->isFixed())
	{
		hkpShape* shape = buildShape(parentIdx);
		if (shape)
		{
			hkVector4 oldCm = parentNode->m_body->getCenterOfMassInWorld();
			hkpShape* flatShape = hkFlattenShapeHierarchyUtil::flattenHierarchy(shape);
			updateShapeOfRigidBody(flatShape, parentNode->m_body);
			shape->removeReference();
			flatShape->removeReference();

			hkVector4 relCm; relCm.setSub4(parentNode->m_body->getCenterOfMassInWorld(), oldCm);
			hkVector4 extraLin; extraLin.setCross(parentNode->m_body->getAngularVelocity(), relCm);

			hkVector4 linVel; linVel.setAdd4(parentNode->m_body->getLinearVelocity(), extraLin);
			parentNode->m_body->setLinearVelocity(linVel);
		}
		else 
		{
			parentNode->m_body->getWorld()->removeEntity(parentNode->m_body);
			parentNode->m_body->removeReference();
			parentNode->m_body = HK_NULL;
		}
	}
	else // if (!parentNode->m_body->isFixed())
	{

		// if we're breaking off of a fixed shape -- this must be the one fixed mopp shape

		const hkpShape* shape = parentNode->m_body->getCollidable()->getShape();
		HK_ASSERT2(0xad1788dd, shape->getType() == HK_SHAPE_MOPP, "The fixed body must have a mopp.");
		const hkpMoppBvTreeShape* mopp = static_cast<const hkpMoppBvTreeShape*>(shape);

		// Remove shapeKeys from mopp

		HK_ACCESS_CHECK_OBJECT(parentNode->m_body->getWorld(), HK_ACCESS_RW );

		hkArray<hkpShapeKey> brokenOffShapeKeys;
		collectShapeKeys(nodeIdx, brokenOffShapeKeys);

		for (int i = brokenOffShapeKeys.getSize()-1; i >=0; i--)
		{
			if(brokenOffShapeKeys[i] == HK_INVALID_SHAPE_KEY)
			{
				brokenOffShapeKeys.removeAt(i);
			}
			else
			{
				const hkpMoppBvTreeShape* moppShape = static_cast<const hkpMoppBvTreeShape*>( parentNode->m_body->getCollidable()->getShape() );
				removeSubShapeFromDisplay(parentNode->m_body, const_cast<hkpMoppBvTreeShape*>(moppShape), brokenOffShapeKeys[i]);
			}
		}
		hkpRemoveTerminalsMoppModifier modifier(mopp->getMoppCode(), mopp->getShapeCollection(), brokenOffShapeKeys);
		modifier.applyRemoveTerminals( const_cast<hkpMoppCode*>(mopp->getMoppCode()) );

		// disable contact points for the removed shapes..
		hkPointerMap<hkpShapeKey, int> shapeKeyMap;
		shapeKeyMap.reserve(brokenOffShapeKeys.getSize());
		for (int k = 0; k < brokenOffShapeKeys.getSize(); k++)
		{
			shapeKeyMap.insert(brokenOffShapeKeys[k], 0);
		}

		for (int e = 0; e < collisionEvents.getSize(); e++)
		{
			if (collisionEvents[e].m_contactMgr)
			{
				hkpShapeKey key = collisionEvents[e].m_shapeKey;

				hkPointerMap<hkpShapeKey, int>::Iterator it = shapeKeyMap.findKey(key);
				if (shapeKeyMap.isValid(it) && collisionEvents[e].m_body == parentNode->m_body)
				{
					static_cast<hkpDynamicsContactMgr*>(collisionEvents[e].m_contactMgr)->getContactPoint(collisionEvents[e].m_contactPointId)->setDistance(100000.0f);
					collisionEvents.removeAt(e);
					e--;
				}
			}
			else
			{
				collisionEvents.removeAt(e);
				e--;
			}
		}

	}



}
MotionExtractionDemo::MotionExtractionDemo( 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.'
	}

	// want to do software skinning always in this demo
	// see HardwareSkinningDemo for how to setup hardware palettes etc
	m_env->m_sceneConverter->setAllowHardwareSkinning(false);

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

		// so we can use the sticks on consoles
		if (m_env->m_options->m_trackballMode == 0)
		{
			m_forcedOnTrackball = true;
			m_env->m_window->getViewport(0)->setNavigationMode(HKG_CAMERA_NAV_TRACKBALL);
		}
	}

	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 animation 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[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/hkWalkTurnLLoop.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];

		assetFile = hkAssetManagementUtil::getFilePath("Resources/Animation/HavokGirl/hkWalkTurnRLoop.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[2] =  ac->m_animations[0];

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

	// Convert the skin
	{
		const char* skinFile = "Resources/Animation/HavokGirl/hkLowResSkin.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 skins loaded");

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

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

	// Create the skeleton
	m_skeletonInstance = new hkaAnimatedSkeleton( m_skeleton );
	m_skeletonInstance->setReferencePoseWeightThreshold( 0.01f );

	float weights[NUM_ANIMS];
	weights[0] = 0.1f;
	weights[1] = 0.0f;
	weights[2] = 0.0f;

	// Grab the animations
	for (int i=0; i < NUM_ANIMS; i++)
	{
		m_control[i] = new hkaDefaultAnimationControl( m_binding[i] );
		m_control[i]->setMasterWeight( weights[i] );
		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( );

	m_currentMotion.setIdentity();
}
Ejemplo n.º 30
0
void MyExtendedUserDataListener::contactPointAddedCallback(	hkpContactPointAddedEvent& event )
{
	//
	// Read the shape key hierarchy -- this is done identically for both Psi and Toi contact points.
	//
	hkpShapeKey shapeKey;
	{
		// This is the body to which the listener is attached.
		hkpEntity* body = event.m_callbackFiredFrom;

		// Extended user data only works when you use the default hkpSimpleConstraintContactMgr.
		// The function below will assert otherwise.

		// The atom caches information on how many extended user datas we store for each body.
		// Each body stores its data independently.
		const int numDatas = event.getNumExtendedUserDatas(event.m_callbackFiredFrom);

		// Now we can read the data.
		// The first user data stores the hkpShapeKey of the bottom most hkpCdBody in the shape hierarchy, 
		// the next one stores hkpShapeKey of its parent, and so on, till we store '-1' as the hkpShapeKey
		// of the root collidable, or we run out of extended user data slots, in which case only a part
		// of the hierarchy is stored.
		//
		// In this demo we expect to have:
		// extendedUserDatas[0] in the [0,7] range -- this is the hkpShapeKey of one of the 8 transformed sphere shapes grouped under a hkpListShape
		// extendedUserDatas[1] equal -1 -- this is the root hkpListShape, with no parent, and therefore no hkpShapeKey
		//
		// Note that we only have two levels of hierarchy, while our shape is composed of hkpListShape->hkpConvexTransformShape->hkpSphereShape.
		// That's because hkpConvexTransform/TranslateShapes don't create a corresponding hkpCdBody during collision detection.
		// Note that the above is not the case for the deprecated hkpTransformShape.
		hkInplaceArray<hkpContactPointProperties::UserData,8> data; data.setSize(numDatas);
		event.getExtendedUserDatas(body, data.begin(), numDatas);

		// Let us store our custom contact point id. Let's store it in the last data slot to avoid overwriting the hkpShapeKey hierarchy.
		// We know we have enough room, as we set entity->m_numUserDatasInContactPointProperties = 3 which is more that the max hierarchy depth for our shape.
		data[numDatas-1] = m_uniqueIdCounter++;

		// And write back all datas
		event.setExtendedUserDatas(body, data.begin(), numDatas);

		// Get the hkpShapeKey
		shapeKey = data[0];
	}

	// Sample demo structure holding history about callbacks triggered for this contact point.
	{
		ContactPointInfo& info = m_contactInfos.expandOne();
		new (&info) ContactPointInfo();
		HK_ASSERT2(0xad7853aa, m_contactInfos.getSize() == m_uniqueIdCounter, "Unique ID is not in synch with m_contactInfos array.");
		info.m_type = event.isToi() ? ContactPointInfo::TOI : ContactPointInfo::PSI;
		info.m_added = true;
		info.m_key = int(shapeKey);
	}

	// By setting the  ProcessContactCallbackDelay to 0 we will receive callbacks for 
	// any collisions processed for this body every frame (simulation step), i.e. the delay between
	// any such callbacks is 0 frames.

	// If you wish to only be notified every N frames simply set the delay to be N-1.
	// The default is 65536, i.e. (for practical purpose) once for the first collision only, until
	// the bodies separate to outside the collision tolerance. 
	event.m_callbackFiredFrom->setProcessContactCallbackDelay(0);
}