ClothFactory ClothingScene::getClothFactory(bool& useCuda)
{
#ifdef PX_WINDOWS
	if (useCuda)
	{
		if (mGpuFactory.factory == NULL)
		{
			PxCudaContextManager* contextManager = NULL;
			PxGpuDispatcher* gpuDispatcher = mApexScene->getTaskManager()->getGpuDispatcher();
			if (gpuDispatcher != NULL)
			{
				contextManager = gpuDispatcher->getCudaContextManager();
			}

			if (contextManager != NULL)
			{
				mGpuFactory = mModule->createClothFactory(contextManager);
				if (mGpuFactory.factory != NULL)
				{
					NiApexSDK* apexSdk = NiGetApexSDK();
					mPhysXGpuIndicator = apexSdk->registerPhysXIndicatorGpuClient();
				}
			}
		}

		//APEX_DEBUG_INFO("Gpu Factory %p", mGpuFactory);
		if (mGpuFactory.factory != NULL)
		{
			return mGpuFactory;
		}
		else
		{
			APEX_DEBUG_INFO("Gpu Factory could not be created");
			useCuda = false;
		}
	}
	
	if (!useCuda)
#else
	PX_UNUSED(useCuda);
#endif
	{
		if (mCpuFactory.factory == NULL)
		{
			mCpuFactory = mModule->createClothFactory(NULL);
		}

		//APEX_DEBUG_INFO("Cpu Factory %p", mCpuFactory.factory);
		return mCpuFactory;
	}

#ifdef PX_WINDOWS
	PX_ALWAYS_ASSERT_MESSAGE("this code path is unreachable, at least it used to be.");
	return ClothFactory(NULL, NULL);
#endif
}
ResID ApexResourceProvider::getNSID(const char* nsName)
{
	physx::Hash<const char*> h;
	ResID id = h(nsName);
	const HashMapNSID::Entry* nsid = mNSID.find(id);
	if (nsid)
	{
		PX_ASSERT(nsid->second < mNameSpaces.size() && mNameSpaces[nsid->second] != NULL);
		if (nsid->second < mNameSpaces.size() && mNameSpaces[nsid->second] != NULL && !h.equal(nsName, mNameSpaces[nsid->second]->getNameSpace()))
		{
			PX_ALWAYS_ASSERT_MESSAGE("Hash collision detected for namespaces in ApexResourceProvider. Try to adjust hash function.");
			return INVALID_RESOURCE_ID;
		}
	}
	return id;
}
void Gu::GeometryUnion::set(const PxGeometry& g)
{
	switch(g.getType())
	{
	case PxGeometryType::eBOX :
		reinterpret_cast<PxBoxGeometry&>(geometry) = static_cast<const PxBoxGeometry&>(g);
		break;
	case PxGeometryType::eCAPSULE :
		reinterpret_cast<PxCapsuleGeometry&>(geometry) = static_cast<const PxCapsuleGeometry&>(g);
		break;
	case PxGeometryType::eSPHERE :
		reinterpret_cast<PxSphereGeometry&>(geometry) = static_cast<const PxSphereGeometry&>(g);
		reinterpret_cast<PxCapsuleGeometry&>(geometry).halfHeight = 0.0f;		//AM: make sphere geometry also castable as a zero height capsule.
		break;
	case PxGeometryType::ePLANE :
		reinterpret_cast<PxPlaneGeometry&>(geometry) = static_cast<const PxPlaneGeometry&>(g);
		break;
	case PxGeometryType::eCONVEXMESH :
		{
			reinterpret_cast<PxConvexMeshGeometry&>(geometry) = static_cast<const PxConvexMeshGeometry&>(g);
			reinterpret_cast<PxConvexMeshGeometryLL&>(geometry).hullData = &(Gu::getConvexMesh(get<PxConvexMeshGeometryLL>().convexMesh).getHull());
		}
		break;
	case PxGeometryType::eTRIANGLEMESH :
		{
			reinterpret_cast<PxTriangleMeshGeometry&>(geometry) = static_cast<const PxTriangleMeshGeometry&>(g);
			reinterpret_cast<PxTriangleMeshGeometryLL&>(geometry).meshData = &(Gu::getTriangleMesh(get<PxTriangleMeshGeometryLL>().triangleMesh).mMesh.mData);
			reinterpret_cast<PxTriangleMeshGeometryLL&>(geometry).materialIndices = (Gu::getTriangleMesh(get<PxTriangleMeshGeometryLL>().triangleMesh).mMesh.getMaterials());
			reinterpret_cast<PxTriangleMeshGeometryLL&>(geometry).materials = MaterialIndicesStruct();
		}
		break;
	case PxGeometryType::eHEIGHTFIELD :
		{
			reinterpret_cast<PxHeightFieldGeometry&>(geometry) = static_cast<const PxHeightFieldGeometry&>(g);
			reinterpret_cast<PxHeightFieldGeometryLL&>(geometry).heightFieldData = &Gu::getHeightField(get<PxHeightFieldGeometryLL>().heightField).getData();
			reinterpret_cast<PxHeightFieldGeometryLL&>(geometry).materials = MaterialIndicesStruct();
		}
		break;
	case PxGeometryType::eGEOMETRY_COUNT:
	case PxGeometryType::eINVALID:
	default :
		PX_ALWAYS_ASSERT_MESSAGE("geometry type not handled");
		break;
	}
}