Пример #1
0
void PhysX3::ApplyActionAtPoint(PintObjectHandle handle, PintActionType action_type, const Point& action, const Point& pos)
{
	PxRigidActor* RigidActor = GetActorFromHandle(handle);
	if(!RigidActor)
	{
		PxShape* Shape = GetShapeFromHandle(handle);
		ASSERT(Shape);
#ifdef SUPPORT_SHARED_SHAPES
		RigidActor = Shape->getActor();
#else
		RigidActor = &Shape->getActor();
#endif
	}

	if(RigidActor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC)
	{
		PxRigidDynamic* RigidDynamic = static_cast<PxRigidDynamic*>(RigidActor);
		if(!(RigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC))
		{
			PxForceMode::Enum mode;
			if(action_type==PINT_ACTION_FORCE)
				mode = PxForceMode::eFORCE;
			else if(action_type==PINT_ACTION_IMPULSE)
				mode = PxForceMode::eIMPULSE;
			else ASSERT(0);

			PxRigidBodyExt::addForceAtPos(*RigidDynamic, ToPxVec3(action), ToPxVec3(pos), mode);
		}
	}
}
void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps)
{
	PX_CHECK_AND_RETURN(scale > 0,
		"PxScaleRigidActor requires that the scale parameter is greater than zero");

	Ps::InlineArray<PxShape*, 64> shapes;
	shapes.resize(actor.getNbShapes());
	actor.getShapes(shapes.begin(), shapes.size());

	for(PxU32 i=0;i<shapes.size();i++)
	{
		shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale));		
		PxGeometryHolder h = shapes[i]->getGeometry();

		switch(h.getType())
		{
		case PxGeometryType::eSPHERE:	
			h.sphere().radius *= scale;			
			break;
		case PxGeometryType::ePLANE:
			break;
		case PxGeometryType::eCAPSULE:
			h.capsule().halfHeight *= scale;
			h.capsule().radius *= scale;
			break;
		case PxGeometryType::eBOX:
			h.box().halfExtents *= scale;
			break;
		case PxGeometryType::eCONVEXMESH:
			h.convexMesh().scale.scale *= scale;
			break;
		case PxGeometryType::eTRIANGLEMESH:
			h.triangleMesh().scale.scale *= scale;
			break;
		case PxGeometryType::eHEIGHTFIELD:
			h.heightField().heightScale *= scale;
			h.heightField().rowScale *= scale;
			h.heightField().columnScale *= scale;
			break;
		case PxGeometryType::eINVALID:
		case PxGeometryType::eGEOMETRY_COUNT:
		default:
			PX_ASSERT(0);
		}
		shapes[i]->setGeometry(h.any());
	}

	if(!scaleMassProps)
		return;

	PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>();
	if(!dynamic)
		return;

	PxReal scale3 = scale*scale*scale;
	dynamic->setMass(dynamic->getMass()*scale3);
	dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale);
	dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale));
}
Пример #3
0
void PhysXInterface::setMatrix( int id, const osg::Matrix& matrix )
{
    PxReal d[16];
    for ( int i=0; i<16; ++i ) d[i] = *(matrix.ptr() + i);
    
    PxRigidActor* actor = _actors[id];
    if ( actor ) actor->setGlobalPose( PxTransform(PxMat44(d)) );
}
Пример #4
0
        int RayCastManagerImpl::CastSweep(const XMFLOAT3& p_origin, XMFLOAT3& p_direction, float p_width, const float& p_range, int& o_flag)
        {
            if(p_range <= 0.0f)
            {
                cout << "Physcs. Raytracer. Sweep. Range of sweep was zero or below" << endl;
                return -1;
            }
            // Cast directx things to physx
            PxVec3 origin = PxVec3(p_origin.x, p_origin.y, p_origin.z);
            PxVec3 direction = PxVec3(p_direction.x, p_direction.y, p_direction.z);
            direction.normalize();
            PxSweepBuffer hit; // Used to save the hit
            /// Paramters for the sweep
            // PxGeometry* geometry
            bool status = m_utils.m_worldScene->sweep(PxSphereGeometry(p_width), PxTransform(origin), direction, p_range, hit, PxHitFlag::eMESH_BOTH_SIDES);
            // hit.block.position;
            if(!status && !hit.hasBlock)
            {
                // No hit detected, return -1 TODOKO Maybee i should return something better?
                return -1;
            }

            // Start with checking static and dynamic rigid bodies
            unordered_map<PxRigidActor*, int> idsByRigidBody = m_utils.m_rigidBodyManager->GetIDsByBodies();
            if(idsByRigidBody.find(hit.block.actor) != idsByRigidBody.end())
            {
                PxRigidActor* actorAsRigic = (PxRigidActor*)hit.block.actor;
                if(actorAsRigic->isRigidDynamic())
                {
                    PxRigidDynamic* actorsAsDynamic = (PxRigidDynamic*)hit.block.actor;
                    if(actorsAsDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
                    {
                        o_flag = 0;
                    }
                }
                else if(actorAsRigic->isRigidStatic())
                {
                    o_flag = 3;
                }
                return idsByRigidBody.find(hit.block.actor)->second;
            }
            else
            {
                // Nothing
            }
            // Now comes the difficult task of checking vs character controllers
            unordered_map<PxController*, int> idsByCharacterController = m_utils.m_characterControlManager->GetIdsByControllers();
            for(auto pairs : idsByCharacterController) // Loop through every pair in the list
            {
                if(pairs.first->getActor() == hit.block.actor) // The first part contains the actor pointer
                {
                    o_flag = 1;
                    return pairs.second; // If this is true we found a hit vs character controller, second contains ID
                }
            }

            return -1;
        }
void physx::PxSetGroupsMask(const PxRigidActor& actor, const PxGroupsMask& mask)
{
	PxFilterData tmp;
	PxFilterData fd = convert(mask);

	if (actor.getNbShapes() == 1)
	{
		PxShape* shape = NULL;
		actor.getShapes(&shape, 1);

		// retrieve current group
		tmp = shape->getSimulationFilterData();
		fd.word0 = tmp.word0;

		// set new filter data
		shape->setSimulationFilterData(fd);
	}
	else
	{
		PxShape* shape;
		PxU32 numShapes = actor.getNbShapes();
		shdfnd::InlineArray<PxShape*, 64> shapes;
		if(numShapes > 64)
		{
			shapes.resize(64);
		}
		else
		{
			shapes.resize(numShapes);
		}

		PxU32 iter = 1 + numShapes/64;

		for(PxU32 i=0; i < iter; i++)
		{
			PxU32 offset = i * 64;
			PxU32 size = numShapes - offset;
			if(size > 64)
				size = 64;

			actor.getShapes(shapes.begin(), size, offset);

			for(PxU32 j = size; j--;)
			{
				// retrieve current group mask
				shape = shapes[j];
				// retrieve current group
				tmp = shape->getSimulationFilterData();
				fd.word0 = tmp.word0;

				// set new filter data
				shape->setSimulationFilterData(fd);

			}
		}
	}
}
void physx::PxSetGroup(const PxRigidActor& actor, const PxU16 collisionGroup)
{	
	PX_CHECK_AND_RETURN(collisionGroup < 32,"Collision group must be less than 32");

	PxFilterData fd;
	
	if (actor.getNbShapes() == 1)
	{
		PxShape* shape = NULL;
		actor.getShapes(&shape, 1);

		// retrieve current group mask
		fd = shape->getSimulationFilterData();
		fd.word0 = collisionGroup;
		
		// set new filter data
		shape->setSimulationFilterData(fd);
	}
	else
	{
		PxShape* shape;
		PxU32 numShapes = actor.getNbShapes();
		shdfnd::InlineArray<PxShape*, 64> shapes;
		if(numShapes > 64)
		{
			shapes.resize(64);
		}
		else
		{
			shapes.resize(numShapes);
		}

		PxU32 iter = 1 + numShapes/64;

		for(PxU32 i=0; i < iter; i++)
		{
			PxU32 offset = i * 64;
			PxU32 size = numShapes - offset;
			if(size > 64)
				size = 64;

			actor.getShapes(shapes.begin(), size, offset);

			for(PxU32 j = size; j--;)
			{
				// retrieve current group mask
				shape = shapes[j];
				fd = shape->getSimulationFilterData();
				fd.word0 = collisionGroup;

				// set new filter data
				shape->setSimulationFilterData(fd);
			}
		}
	}
}
Пример #7
0
void 
PhysXRigidManager::move(std::string scene, float * transform) {
	if (rigidBodies.find(scene) != rigidBodies.end()) {
		PxRigidActor * actor = rigidBodies[scene].info.actor->is<PxRigidActor>();
		if (actor) {
			rigidBodies[scene].info.extInfo.transform = transform;
			actor->setGlobalPose(PxTransform(PxMat44(transform)));
		}
	}
}
PxGroupsMask physx::PxGetGroupsMask(const PxRigidActor& actor)
{
	PX_CHECK_AND_RETURN_VAL(actor.getNbShapes() >= 1,"At least one shape must be in actor",PxGroupsMask());

	PxShape* shape = NULL;
	actor.getShapes(&shape, 1);

	PxFilterData fd = shape->getSimulationFilterData();
	
	return convert(fd);
}
PxU16 physx::PxGetGroup(const PxRigidActor& actor)
{
	PX_CHECK_AND_RETURN_NULL(actor.getNbShapes() >= 1,"There must be a shape in actor");

	PxShape* shape = NULL;
	actor.getShapes(&shape, 1);

	PxFilterData fd = shape->getSimulationFilterData();

	return (PxU16)fd.word0;
}
PxExtendedVec3 SampleNorthPoleCameraController::computeCameraTarget()
{
	PxRigidActor* characterActor = mCCT.getActor();
	PxShape* shape;
	characterActor->getShapes(&shape,1);
	PxCapsuleGeometry geom;
	shape->getCapsuleGeometry(geom);

	const PxExtendedVec3 headPos = PxExtendedVec3(0,geom.halfHeight+geom.radius,0);
	return mCCT.getPosition() + headPos;
}
Пример #11
0
osg::Matrix PhysXInterface::getMatrix( int id )
{
    PxRigidActor* actor = _actors[id];
    if ( actor )
    {
        float m[16];
        PxMat44 pxMat( actor->getGlobalPose() );
        for ( int i=0; i<16; ++i ) m[i] = *(pxMat.front() + i);
        return osg::Matrix(&m[0]);
    }
    return osg::Matrix();
}
Пример #12
0
void PhysXHeightfield::InitHeightfield(PxPhysics* physics, PxScene* scene, const char* filename)
{
	float xScale = 0.0025f;
	float yScale = 0.0025f;
	float zScale = 10.00f;

	
	// NOTE: Assuming that heightfield texture has B8G8R8A8 format.
	if(LoadHeightfield(filename)) 
	{
		PxU16 nbColumns = PxU16(mHeightfield.width);
		PxU16 nbRows = PxU16(mHeightfield.height);

		PxHeightFieldDesc heightFieldDesc;
        heightFieldDesc.format             = PxHeightFieldFormat::eS16_TM;
		heightFieldDesc.nbColumns = nbColumns;
		heightFieldDesc.nbRows = nbRows;
		heightFieldDesc.samples.data = mHeightfield.data;
		heightFieldDesc.samples.stride = sizeof(PxHeightFieldSample);
		//heightFieldDesc.convexEdgeThreshold = 0;

		PxHeightField* heightField = physics->createHeightField(heightFieldDesc);
		// create shape for heightfield		
		PxTransform pose(PxVec3(-((PxReal)nbRows*yScale) / 2.0f, 
								0.0f, 
								-((PxReal)nbColumns*xScale) / 2.0f),  
						PxQuat::createIdentity());
       // PxTransform pose = PxTransform::createIdentity();
	    pose.p = PxVec3(-((nbColumns/2)*xScale),0.0,-((nbColumns/2)*xScale));

		PxRigidActor* hf = physics->createRigidStatic(pose);
        if(!hf) 
		    return;

		const PxMaterial* mMat = physics->createMaterial(0.9f, 0.9f, 0.001f);
		//PxShape* shape = hf->createShape((PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), yScale, xScale, xScale)), *mMat);

		//PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, rowScale, colScale);
		//PxShape* aHeightFieldShape = aHeightFieldActor->createShape(hfGeom, aMaterialArray, nbMaterials);

        PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), yScale, xScale, xScale);
	    PxShape* hfShape = hf->createShape(hfGeom, *mMat);
	    if(!hfShape) 
		    return;

		//shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, false);
		//shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
		//shape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, true);
		// add actor to the scene
		scene->addActor(*hf);
	}
}
Пример #13
0
bool Picking::pick(int x, int y)
{
	PxScene& scene = mFrame.getActiveScene();

	PxVec3 rayOrig, rayDir, pickOrig;
	computeCameraRay(rayOrig, rayDir, pickOrig, x, y);

	// raycast rigid bodies in scene
	PxRaycastHit hit; hit.shape = NULL;
	PxRaycastBuffer hit1;
	scene.raycast(rayOrig, rayDir, PX_MAX_F32, hit1, PxHitFlag::ePOSITION);
	hit = hit1.block;

	if(hit.shape)
	{ 
		const char* shapeName = hit.shape->getName();
		if(shapeName)
			printf("Picked shape name: %s\n", shapeName);

		PxRigidActor* actor = hit.actor;
		PX_ASSERT(actor);
		mSelectedActor = static_cast<PxRigidActor*>(actor->is<PxRigidDynamic>());
		if(!mSelectedActor)
			mSelectedActor = static_cast<PxRigidActor*>(actor->is<PxArticulationLink>());

		//ML::this is very useful to debug some collision problem
		PxTransform t = actor->getGlobalPose();

	//	printf("id = %i\n PxTransform transform(PxVec3(%f, %f, %f), PxQuat(%f, %f, %f, %f))\n", (int)actor->userData, t.p.x, t.p.y, t.p.z, t.q.x, t.q.y, t.q.z, t.q.w);
	}
	else
	{
		mSelectedActor = 0;
	}

	if(mSelectedActor)
	{
		printf("Actor '%s' picked! (userData: %p)\n", mSelectedActor->getName(), mSelectedActor->userData);

		//if its a dynamic rigid body, joint it for dragging purposes:
		grabActor(hit.position, rayOrig);
	}

#ifdef VISUALIZE_PICKING_RAYS
	Ray ray;
	ray.origin = rayOrig;
	ray.dir = rayDir;
	mRays.push_back(ray);
#endif
	return true;
}
Пример #14
0
void Picking::grabActor(const PxVec3& worldImpact, const PxVec3& rayOrigin)
{
	if(!mSelectedActor 
		|| (mSelectedActor->getType() != PxActorType::eRIGID_DYNAMIC 
		&& mSelectedActor->getType() != PxActorType::eARTICULATION_LINK))
		return;

	PxScene& scene = mFrame.getActiveScene();
	PxPhysics& physics = scene.getPhysics();

	//create a shape less actor for the mouse
	{
		mMouseActor = physics.createRigidDynamic(PxTransform(worldImpact, PxQuat::createIdentity()));
		mMouseActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true); 
		mMouseActor->setMass(1.0f);
		mMouseActor->setMassSpaceInertiaTensor(PxVec3(1.0f, 1.0f, 1.0f));

		scene.addActor(*mMouseActor);

		mFrame.addPhysicsActors(mMouseActor);
	}
	PxRigidActor* pickedActor = static_cast<PxRigidActor*>(mSelectedActor);

#if USE_D6_JOINT_FOR_MOUSE
	mMouseJoint = PxD6JointCreate(		physics,
										mMouseActor,
										PxTransform::createIdentity(),
										pickedActor,
										PxTransform(pickedActor->getGlobalPose().transformInv(worldImpact)));
#elif USE_SPHERICAL_JOINT_FOR_MOUSE
	mMouseJoint = PxSphericalJointCreate(physics,
										mMouseActor,
										PxTransform::createIdentity(),
										pickedActor,
										PxTransform(pickedActor->getGlobalPose().transformInv(worldImpact)));
#else
	mMouseJoint = PxDistanceJointCreate(physics, 
										mMouseActor, 
										PxTransform::createIdentity(),
										pickedActor,
										PxTransform(pickedActor->getGlobalPose().transformInv(worldImpact)));
	mMouseJoint->setMaxDistance(0.0f);
	mMouseJoint->setMinDistance(0.0f);
	mMouseJoint->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED);
#endif

	mDistanceToPicked = (worldImpact - rayOrigin).magnitude();
}
Пример #15
0
void PhysX::AddWorldImpulseAtWorldPos(PintObjectHandle handle, const Point& world_impulse, const Point& world_pos)
{
	PxRigidActor* RigidActor = GetActorFromHandle(handle);
	if(!RigidActor)
	{
		PxShape* Shape = GetShapeFromHandle(handle);
		ASSERT(Shape);
		RigidActor = &Shape->getActor();
	}

	if(RigidActor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC)
	{
		PxRigidDynamic* RigidDynamic = static_cast<PxRigidDynamic*>(RigidActor);
		PxRigidBodyExt::addForceAtPos(*RigidDynamic, ToPxVec3(world_impulse), ToPxVec3(world_pos), PxForceMode::eIMPULSE);
	}
}
Пример #16
0
void PhysX::AddLocalTorque(PintObjectHandle handle, const Point& local_torque)
{
	PxRigidActor* RigidActor = GetActorFromHandle(handle);
	if(!RigidActor)
	{
		PxShape* Shape = GetShapeFromHandle(handle);
		ASSERT(Shape);
		RigidActor = &Shape->getActor();
	}

	if(RigidActor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC)
	{
		PxRigidDynamic* RigidDynamic = static_cast<PxRigidDynamic*>(RigidActor);
		const PxVec3 GlobalTorque = RigidDynamic->getGlobalPose().rotate(ToPxVec3(local_torque));
		RigidDynamic->addTorque(GlobalTorque, PxForceMode::eACCELERATION, true);
	}
}
void TCompCharacterController::SetFilterData(PxFilterData& filter)
{
	PxRigidActor *ra = m_pActor->getActor()->isRigidActor();
	m_filter = filter;
	if (ra) {
		const PxU32 numShapes = ra->getNbShapes();
		PxShape **ptr;
		ptr = new PxShape*[numShapes];
		ra->getShapes(ptr, numShapes);
		for (PxU32 i = 0; i < numShapes; i++)
		{
			PxShape* shape = ptr[i];
			shape->setSimulationFilterData(m_filter);
			shape->setQueryFilterData(m_filter);
		}
	}
}
PxBounds3 NpShapeManager::getWorldBounds(const PxRigidActor& actor) const
{
	PxBounds3 bounds(PxBounds3::empty());

	const PxU32 nbShapes = getNbShapes();
	PxTransform actorPose = actor.getGlobalPose();
	NpShape*const* PX_RESTRICT shapes = getShapes();

	for(PxU32 i=0;i<nbShapes;i++)
		bounds.include(Gu::computeBounds(shapes[i]->getScbShape().getGeometry(), actorPose * shapes[i]->getLocalPoseFast(), !physx::gUnifiedHeightfieldCollision));
		
	return bounds;
}
Пример #19
0
	bool CreateGeometryFromPhysxActor(PxActor *a, LevelGeometry::Mesh &mesh)
	{
		bool rv = false;

		if (!a)
			return rv;

		PxRigidActor *ra = a->isRigidActor();
		if (!ra)
			return rv;

		GameObject* gameObj = NULL;
		PhysicsCallbackObject* userData = static_cast<PhysicsCallbackObject*>(ra->userData);
		if(userData) gameObj = userData->isGameObject();

		r3dCSHolder block(g_pPhysicsWorld->GetConcurrencyGuard());

		PxU32 nbShapes = ra->getNbShapes();
		for (PxU32 i = 0; i < nbShapes; ++i)
		{
			PxShape *s = 0;
			ra->getShapes(&s, 1, i);
			PxGeometryType::Enum gt = s->getGeometryType();
			switch(gt)
			{
			case PxGeometryType::eTRIANGLEMESH:
				{
					PxTriangleMeshGeometry g;
					s->getTriangleMeshGeometry(g);
					PxTransform t = s->getLocalPose().transform(ra->getGlobalPose());
					rv = CreateGeometryFromPhysxGeometry(g, t, mesh);
					break;
				}
			default:
				r3dArtBug("buildNavigation: Unsupported physx mesh type %d, obj: %s\n", gt, gameObj ? gameObj->Name.c_str() : "<unknown>");
			}
		}
		return rv;
	}
Пример #20
0
PR PhysX3::GetWorldTransform(PintObjectHandle handle)
{
	PxTransform Pose;

	PxRigidActor* RigidActor = GetActorFromHandle(handle);
	if(RigidActor)
	{
		Pose = RigidActor->getGlobalPose();
	}
	else
	{
		PxShape* Shape = GetShapeFromHandle(handle);
		ASSERT(Shape);
#ifdef SUPPORT_SHARED_SHAPES
		ASSERT(Shape->getActor());
		Pose = PxShapeExt::getGlobalPose(*Shape, *Shape->getActor());
#else
		Pose = PxShapeExt::getGlobalPose(*Shape);
#endif
	}

	return PR(ToPoint(Pose.p), ToQuat(Pose.q));
}
void TCompCharacterController::SetCollisions(bool new_collisions)
{
	PxRigidActor *ra = m_pActor->getActor()->isRigidActor();
	if (ra) {
		const PxU32 numShapes = ra->getNbShapes();
		PxShape **ptr;
		ptr = new PxShape*[numShapes];
		ra->getShapes(ptr, numShapes);
		for (PxU32 i = 0; i < numShapes; i++)
		{
			PxShape* shape = ptr[i];
			if (!new_collisions) {
				m_filter.word1 &= ~ItLightensFilter::eCOLLISION;
				m_filter.word1 &= ~ItLightensFilter::eCAN_TRIGGER;	//for test only
			}
			else {
				m_filter.word1 |= ItLightensFilter::eCOLLISION;
				m_filter.word1 |= ItLightensFilter::eCAN_TRIGGER;		//for test only
			}
			shape->setSimulationFilterData(m_filter);
			shape->setQueryFilterData(m_filter);
		}
	}
}
void NpShapeManager::setupAllSceneQuery(NpScene* scene, const PxRigidActor& actor, bool hasPrunerStructure, const PxBounds3* bounds)
{ 
	PX_ASSERT(scene);		// shouldn't get here unless we're in a scene
	SceneQueryManager& sqManager = scene->getSceneQueryManagerFast();

	const PxU32 nbShapes = getNbShapes();
	NpShape*const *shapes = getShapes();

	const PxType actorType = actor.getConcreteType();
	const bool isDynamic = actorType == PxConcreteType::eRIGID_DYNAMIC || actorType == PxConcreteType::eARTICULATION_LINK;

	for(PxU32 i=0;i<nbShapes;i++)
	{
		if(isSceneQuery(*shapes[i]))
			setPrunerData(i, sqManager.addPrunerShape(*shapes[i], actor, isDynamic, bounds ? bounds + i : NULL, hasPrunerStructure));
	}
}
void NpShapeManager::visualize(Cm::RenderOutput& out, NpScene* scene, const PxRigidActor& actor)
{
	const PxU32 nbShapes = getNbShapes();
	NpShape*const* PX_RESTRICT shapes = getShapes();
	PxTransform actorPose = actor.getGlobalPose();

	const bool visualizeCompounds = (nbShapes>1) && scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_COMPOUNDS)!=0.0f;

	PxBounds3 compoundBounds(PxBounds3::empty());
	for(PxU32 i=0;i<nbShapes;i++)
	{
		Scb::Shape& shape = shapes[i]->getScbShape();
		if(shape.getFlags() & PxShapeFlag::eVISUALIZATION)
		{
			shapes[i]->visualize(out, actor);
			if(visualizeCompounds)
				compoundBounds.include(Gu::computeBounds(shape.getGeometry(), actorPose*shapes[i]->getLocalPose(), !physx::gUnifiedHeightfieldCollision));
		}
	}
	if(visualizeCompounds && !compoundBounds.isEmpty())
		out << PxU32(PxDebugColor::eARGB_MAGENTA) << PxMat44(PxIdentity) << Cm::DebugBox(compoundBounds);
}
Пример #24
0
void USkeletalMeshComponent::UpdateKinematicBonesToAnim(const TArray<FTransform>& InSpaceBases, ETeleportType Teleport, bool bNeedsSkinning, EAllowKinematicDeferral DeferralAllowed)
{
	SCOPE_CYCLE_COUNTER(STAT_UpdateRBBones);

	// This below code produces some interesting result here
	// - below codes update physics data, so if you don't update pose, the physics won't have the right result
	// - but if we just update physics bone without update current pose, it will have stale data
	// If desired, pass the animation data to the physics joints so they can be used by motors.
	// See if we are going to need to update kinematics
	const bool bUpdateKinematics = (KinematicBonesUpdateType != EKinematicBonesUpdateToPhysics::SkipAllBones);
	const bool bTeleport = Teleport == ETeleportType::TeleportPhysics;
	// If desired, update physics bodies associated with skeletal mesh component to match.
	if(!bUpdateKinematics && !(bTeleport && IsAnySimulatingPhysics()))
	{
		// nothing to do 
		return;
	}

	// Get the scene, and do nothing if we can't get one.
	FPhysScene* PhysScene = nullptr;
	if (GetWorld() != nullptr)
	{
		PhysScene = GetWorld()->GetPhysicsScene();
	}

	if(PhysScene == nullptr)
	{
		return;
	}

	const FTransform& CurrentLocalToWorld = ComponentToWorld;

	// Gracefully handle NaN
	if(CurrentLocalToWorld.ContainsNaN())
	{
		return;
	}

	// If we are only using bodies for physics, don't need to move them right away, can defer until simulation (unless told not to)
	if(BodyInstance.GetCollisionEnabled() == ECollisionEnabled::PhysicsOnly && DeferralAllowed == EAllowKinematicDeferral::AllowDeferral)
	{
		PhysScene->MarkForPreSimKinematicUpdate(this, Teleport, bNeedsSkinning);
		return;
	}

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	// If desired, draw the skeleton at the point where we pass it to the physics.
	if (bShowPrePhysBones && SkeletalMesh && InSpaceBases.Num() == SkeletalMesh->RefSkeleton.GetNum())
	{
		for (int32 i = 1; i<InSpaceBases.Num(); i++)
		{
			FVector ThisPos = CurrentLocalToWorld.TransformPosition(InSpaceBases[i].GetLocation());

			int32 ParentIndex = SkeletalMesh->RefSkeleton.GetParentIndex(i);
			FVector ParentPos = CurrentLocalToWorld.TransformPosition(InSpaceBases[ParentIndex].GetLocation());

			GetWorld()->LineBatcher->DrawLine(ThisPos, ParentPos, AnimSkelDrawColor, SDPG_Foreground);
		}
	}
#endif

	// warn if it has non-uniform scale
	const FVector& MeshScale3D = CurrentLocalToWorld.GetScale3D();
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if( !MeshScale3D.IsUniform() )
	{
		UE_LOG(LogPhysics, Log, TEXT("USkeletalMeshComponent::UpdateKinematicBonesToAnim : Non-uniform scale factor (%s) can cause physics to mismatch for %s  SkelMesh: %s"), *MeshScale3D.ToString(), *GetFullName(), SkeletalMesh ? *SkeletalMesh->GetFullName() : TEXT("NULL"));
	}
#endif


	if (bEnablePerPolyCollision == false)
	{
		const UPhysicsAsset* const PhysicsAsset = GetPhysicsAsset();
		if (PhysicsAsset && SkeletalMesh && Bodies.Num() > 0)
		{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
			if (!ensure(PhysicsAsset->BodySetup.Num() == Bodies.Num()))
			{
				// related to TTP 280315
				UE_LOG(LogPhysics, Warning, TEXT("Mesh (%s) has PhysicsAsset(%s), and BodySetup(%d) and Bodies(%d) don't match"),
					*SkeletalMesh->GetName(), *PhysicsAsset->GetName(), PhysicsAsset->BodySetup.Num(), Bodies.Num());
				return;
			}
#endif

#if WITH_PHYSX
			// Lock the scenes we need (flags set in InitArticulated)
			if(bHasBodiesInSyncScene)
			{
				SCENE_LOCK_WRITE(PhysScene->GetPhysXScene(PST_Sync))
			}

			if (bHasBodiesInAsyncScene)
			{
				SCENE_LOCK_WRITE(PhysScene->GetPhysXScene(PST_Async))
			}
#endif

			// Iterate over each body
			for (int32 i = 0; i < Bodies.Num(); i++)
			{
				// If we have a physics body, and its kinematic...
				FBodyInstance* BodyInst = Bodies[i];
				check(BodyInst);

				if (BodyInst->IsValidBodyInstance() && (bTeleport || !BodyInst->IsInstanceSimulatingPhysics()))
				{
					const int32 BoneIndex = BodyInst->InstanceBoneIndex;

					// If we could not find it - warn.
					if (BoneIndex == INDEX_NONE || BoneIndex >= GetNumSpaceBases())
					{
						const FName BodyName = PhysicsAsset->BodySetup[i]->BoneName;
						UE_LOG(LogPhysics, Log, TEXT("UpdateRBBones: WARNING: Failed to find bone '%s' need by PhysicsAsset '%s' in SkeletalMesh '%s'."), *BodyName.ToString(), *PhysicsAsset->GetName(), *SkeletalMesh->GetName());
					}
					else
					{
#if WITH_PHYSX
						// update bone transform to world
						const FTransform BoneTransform = InSpaceBases[BoneIndex] * CurrentLocalToWorld;
						if(!BoneTransform.IsValid())
						{
							const FName BodyName = PhysicsAsset->BodySetup[i]->BoneName;
							UE_LOG(LogPhysics, Warning, TEXT("UpdateKinematicBonesToAnim: Trying to set transform with bad data %s on PhysicsAsset '%s' in SkeletalMesh '%s' for bone '%s'"), *BoneTransform.ToHumanReadableString(), *PhysicsAsset->GetName(), *SkeletalMesh->GetName(), *BodyName.ToString());
							BoneTransform.DiagnosticCheck_IsValid();	//In special nan mode we want to actually ensure

							continue;
						}

						// If kinematic and not teleporting, set kinematic target
						if (!BodyInst->IsInstanceSimulatingPhysics() && !bTeleport)
						{
							PhysScene->SetKinematicTarget_AssumesLocked(BodyInst, BoneTransform, true);
						}
						// Otherwise, set global pose
						else
						{
							const PxTransform PNewPose = U2PTransform(BoneTransform);
							ensure(PNewPose.isValid());
							PxRigidActor* RigidActor = BodyInst->GetPxRigidActor_AssumesLocked(); // This should never fail because IsValidBodyInstance() passed above
							RigidActor->setGlobalPose(PNewPose);
						}
#endif


						// now update scale
						// if uniform, we'll use BoneTranform
						if (MeshScale3D.IsUniform())
						{
							// @todo UE4 should we update scale when it's simulated?
							BodyInst->UpdateBodyScale(BoneTransform.GetScale3D());
						}
						else
						{
							// @note When you have non-uniform scale on mesh base,
							// hierarchical bone transform can update scale too often causing performance issue
							// So we just use mesh scale for all bodies when non-uniform
							// This means physics representation won't be accurate, but
							// it is performance friendly by preventing too frequent physics update
							BodyInst->UpdateBodyScale(MeshScale3D);
						}
					}
				}
				else
				{
					//make sure you have physics weight or blendphysics on, otherwise, you'll have inconsistent representation of bodies
					// @todo make this to be kismet log? But can be too intrusive
					if (!bBlendPhysics && BodyInst->PhysicsBlendWeight <= 0.f && BodyInst->BodySetup.IsValid())
					{
						//It's not clear whether this should be a warning. There are certainly cases where you interpolate the blend weight towards 0. The blend feature needs some work which will probably change this in the future.
						//Making it Verbose for now
						UE_LOG(LogPhysics, Verbose, TEXT("%s(Mesh %s, PhysicsAsset %s, Bone %s) is simulating, but no blending. "),
							*GetName(), *GetNameSafe(SkeletalMesh), *GetNameSafe(PhysicsAsset), *BodyInst->BodySetup.Get()->BoneName.ToString());
					}
				}
			}

#if WITH_PHYSX
			// Unlock the scenes 
			if (bHasBodiesInSyncScene)
			{
				SCENE_UNLOCK_WRITE(PhysScene->GetPhysXScene(PST_Sync))
			}

			if (bHasBodiesInAsyncScene)
			{
				SCENE_UNLOCK_WRITE(PhysScene->GetPhysXScene(PST_Async))
			}
#endif
		}
	}
	else
	{
		//per poly update requires us to update all vertex positions
		if (MeshObject)
Пример #25
0
bool copyStaticProperties(PxRigidActor& to, const PxRigidActor& from,NxMirrorScene::MirrorFilter &mirrorFilter)
{
	physx::shdfnd::InlineArray<PxShape*, 64> shapes;
	shapes.resize(from.getNbShapes());

	PxU32 shapeCount = from.getNbShapes();
	from.getShapes(shapes.begin(), shapeCount);

	physx::shdfnd::InlineArray<PxMaterial*, 64> materials;
	for(PxU32 i = 0; i < shapeCount; i++)
	{
		PxShape* s = shapes[i];

		if ( mirrorFilter.shouldMirror(*s) )
		{
			PxU32 materialCount = s->getNbMaterials();
			materials.resize(materialCount);
			s->getMaterials(materials.begin(), materialCount);
			PxShape* shape = to.createShape(s->getGeometry().any(), materials.begin(), static_cast<physx::PxU16>(materialCount));
			shape->setLocalPose( s->getLocalPose());
			shape->setContactOffset(s->getContactOffset());
			shape->setRestOffset(s->getRestOffset());
			shape->setFlags(s->getFlags());
			shape->setSimulationFilterData(s->getSimulationFilterData());
			shape->setQueryFilterData(s->getQueryFilterData());
			mirrorFilter.reviseMirrorShape(*shape);
		}
	}

	to.setActorFlags(from.getActorFlags());
	to.setOwnerClient(from.getOwnerClient());
	to.setDominanceGroup(from.getDominanceGroup());

	if ( to.getNbShapes() )
	{
		mirrorFilter.reviseMirrorActor(to);
	}

	return to.getNbShapes() != 0;
}
Пример #26
0
bool UWorld::ComponentSweepMulti(TArray<struct FHitResult>& OutHits, class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const
{
	if(GetPhysicsScene() == NULL)
	{
		return false;
	}

	if(PrimComp == NULL)
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : No PrimComp"));
		return false;
	}

	// if target is skeletalmeshcomponent and do not support singlebody physics
	if ( !PrimComp->ShouldTrackOverlaps() )
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName());
		return false;
	}

	ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType();

#if WITH_PHYSX
	// if extent is 0, do line trace
	if (PrimComp->IsZeroExtent())
	{
		return RaycastMulti(this, OutHits, Start, End, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels()));
	}

	PxRigidActor* PRigidActor = PrimComp->BodyInstance.GetPxRigidActor();
	if(PRigidActor == NULL)
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetPathName());
		return false;
	}
	PxScene * const PScene = PRigidActor->getScene();

	OutHits.Empty();

	// Get all the shapes from the actor
	TArray<PxShape*, TInlineAllocator<8>> PShapes;
	{
		SCOPED_SCENE_READ_LOCK(PScene);
		PShapes.AddZeroed(PRigidActor->getNbShapes());
		PRigidActor->getShapes(PShapes.GetData(), PShapes.Num());
	}

	// calculate the test global pose of the actor
	PxTransform PGlobalStartPose = U2PTransform(FTransform(Start));
	PxTransform PGlobalEndPose = U2PTransform(FTransform(End));

	bool bHaveBlockingHit = false;
	PxQuat PGeomRot = U2PQuat(Rot.Quaternion());

	// Iterate over each shape
	SCENE_LOCK_READ(PScene);
	for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++)
	{
		PxShape* PShape = PShapes[ShapeIdx];
		check(PShape);

		TArray<struct FHitResult> Hits;

		// Calc shape global pose
		PxTransform PLocalShape = PShape->getLocalPose();
		PxTransform PShapeGlobalStartPose = PGlobalStartPose.transform(PLocalShape);
		PxTransform PShapeGlobalEndPose = PGlobalEndPose.transform(PLocalShape);
		// consider localshape rotation for shape rotation
		PxQuat PShapeRot = PGeomRot * PLocalShape.q;

		GET_GEOMETRY_FROM_SHAPE(PGeom, PShape);

		if(PGeom != NULL)
		{
			SCENE_UNLOCK_READ(PScene);
			if (GeomSweepMulti(this, *PGeom, PShapeRot, Hits, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())))
			{
				bHaveBlockingHit = true;
			}

			OutHits.Append(Hits);
			SCENE_LOCK_READ(PScene);
		}
	}
	SCENE_UNLOCK_READ(PScene);

	return bHaveBlockingHit;
#endif //WITH_PHYSX
	return false;
}
Пример #27
0
PxRigidActor* SampleSubmarine::loadTerrain(const char* name, const PxReal heightScale, const PxReal rowScale, const PxReal columnScale) 
{
	PxRigidActor* heightFieldActor = NULL;
	BmpLoader loader;
	if(loader.loadBmp(getSampleMediaFilename(name))) 
	{
		PxU16 nbColumns = PxU16(loader.mWidth), nbRows = PxU16(loader.mHeight);
		PxHeightFieldDesc heightFieldDesc;
		heightFieldDesc.nbColumns = nbColumns;
		heightFieldDesc.nbRows = nbRows;
		PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*nbColumns * nbRows);
		heightFieldDesc.samples.data = samplesData;
		heightFieldDesc.samples.stride = sizeof(PxU32);
		PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data;
		PxU8* loader_ptr = loader.mRGB;
		PxVec3Alloc* vertexesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns];
		PxF32* uvs = (PxF32*)SAMPLE_ALLOC(sizeof(PxF32) * nbRows * nbColumns * 2);
		PxVec3* vertexes = vertexesA;
		for (PxU32 row = 0; row < nbRows; row++) 
		{
			for (PxU32 column = 0; column < nbColumns; column++) 
			{
				PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
				currentSample->height = *loader_ptr;
				vertexes[row * nbColumns + column] = PxVec3(PxReal(row)*rowScale, 
					PxReal(currentSample->height * heightScale), 
					PxReal(column)*columnScale);

				uvs[(row * nbColumns + column)*2 + 0] = (float)column/7.0f;
				uvs[(row * nbColumns + column)*2 + 1] = (float)row/7.0f;

				currentSample->materialIndex0 = 0;
				currentSample->materialIndex1 = 0;
				currentSample->clearTessFlag();
				currentByte += heightFieldDesc.samples.stride;
				loader_ptr += 3 * sizeof(PxU8);
			}
		}
		PxHeightField* heightField = getPhysics().createHeightField(heightFieldDesc);
		if(!heightField) fatalError("createHeightField failed!");
		// create shape for heightfield		
		PxTransform pose(PxVec3(-((PxReal)nbRows*rowScale) / 2.0f, 
			0.0f, 
			-((PxReal)nbColumns*columnScale) / 2.0f), 
			PxQuat::createIdentity());
		heightFieldActor = getPhysics().createRigidStatic(pose);
		if(!heightFieldActor) fatalError("createRigidStatic failed!");
		PxShape* shape = heightFieldActor->createShape(PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), heightScale, rowScale, columnScale), getDefaultMaterial());
		if(!shape) fatalError("createShape failed!");
		// add actor to the scene
		getActiveScene().addActor(*heightFieldActor);
		// create indices
		PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32)*((nbColumns - 1) * (nbRows - 1) * 3 * 2));
		for(int i = 0; i < (nbColumns - 1); ++i) 
		{
			for(int j = 0; j < (nbRows - 1); ++j) 
			{
				// first triangle
				indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j; 
				indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1;
				// second triangle
				indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1;
				indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1;
			}
		}
		// add mesh to renderer
		RAWMesh data;
		data.mName = name;
		data.mTransform = PxTransform::createIdentity();
		data.mNbVerts = nbColumns * nbRows;
		data.mVerts = vertexes;
		data.mVertexNormals = NULL;
		data.mUVs = uvs;
		data.mMaterialID = MATERIAL_TERRAIN_MUD;
		data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2;
		data.mIndices = indices;

		RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data);
		if(!hf_mesh) fatalError("createRenderMeshFromRawMesh failed!");
		hf_mesh->setPhysicsShape(shape);
		shape->setFlag(PxShapeFlag::eVISUALIZATION, false);
		SAMPLE_FREE(indices);
		SAMPLE_FREE(uvs);
		DELETEARRAY(vertexesA);
		SAMPLE_FREE(samplesData);
	}

	return heightFieldActor;
}
Пример #28
0
// Creates an physics entity from an entity info structure and a starting transform
void PhysicsEngine::createEntity(PhysicsEntity* entity, PhysicsEntityInfo* info, PxTransform transform)
{
	transform.p.y += info->yPosOffset;
	// Set static/dynamic info for actor depending on its type
	PxRigidActor* actor;
	if (info->type == PhysicsType::DYNAMIC) 
	{
		DynamicInfo* dInfo = info->dynamicInfo;
		PxRigidDynamic* dynamicActor = physics->createRigidDynamic(transform);
		dynamicActor->setLinearDamping(dInfo->linearDamping);
		dynamicActor->setAngularDamping(dInfo->angularDamping);
		dynamicActor->setMaxAngularVelocity(dInfo->maxAngularVelocity);

		actor = dynamicActor;
	}
	else if (info->type == PhysicsType::STATIC)
	{
		PxRigidStatic* staticActor = physics->createRigidStatic(transform);
		actor = staticActor;
	}

	// All shapes in actor
	for (auto sInfo : info->shapeInfo)
	{
		// Create material and geometry for shape and add it to actor
		PxGeometry* geometry;
		PxMaterial* material;
		if (sInfo->geometry == Geometry::SPHERE)
		{
			SphereInfo* sphInfo = (SphereInfo*)sInfo;
			geometry = new PxSphereGeometry(sphInfo->radius);
		}
		else if (sInfo->geometry == Geometry::BOX)
		{
			BoxInfo* boxInfo = (BoxInfo*)sInfo;		
			geometry = new PxBoxGeometry(boxInfo->halfX, boxInfo->halfY, boxInfo->halfZ);
		}
		else if (sInfo->geometry == Geometry::CAPSULE)
		{
			CapsuleInfo* capInfo = (CapsuleInfo*)sInfo;
			geometry = new PxCapsuleGeometry(capInfo->radius, capInfo->halfHeight);
		}
		else if (sInfo->geometry == Geometry::CONVEX_MESH)
		{
			ConvexMeshInfo* cmInfo = (ConvexMeshInfo*)sInfo;

			PxConvexMesh* mesh = helper->createConvexMesh(cmInfo->verts.data(), cmInfo->verts.size());
			geometry = new PxConvexMeshGeometry(mesh);
		}
		// Not working until index drawing is set up
		else if (sInfo->geometry == Geometry::TRIANGLE_MESH)
		{
			TriangleMeshInfo* tmInfo = (TriangleMeshInfo*)sInfo;

			PxTriangleMesh* mesh = helper->createTriangleMesh(tmInfo->verts.data(), tmInfo->verts.size(), tmInfo->faces.data(), tmInfo->faces.size()/3);
			geometry = new PxTriangleMeshGeometry(mesh);
		}
		material = (sInfo->isDrivable) ? drivingSurfaces[0] : physics->createMaterial(sInfo->dynamicFriction, sInfo->staticFriction, sInfo->restitution);
		PxShape* shape = actor->createShape(*geometry, *material); // TODO support shape flags
		shape->setLocalPose(sInfo->transform);

		material->release();
		delete geometry;

		// Set up querry filter data for shape
		PxFilterData qryFilterData;
		qryFilterData.word3 = (sInfo->isDrivable) ? (PxU32)Surface::DRIVABLE : (PxU32)Surface::UNDRIVABLE;
		shape->setQueryFilterData(qryFilterData);

		// Set up simulation filter data for shape
		PxFilterData simFilterData;
		simFilterData.word0 = (PxU32)sInfo->filterFlag0;
		simFilterData.word1 = (PxU32)sInfo->filterFlag1;
		simFilterData.word2 = (PxU32)sInfo->filterFlag2;
		simFilterData.word3 = (PxU32)sInfo->filterFlag3;
		shape->setSimulationFilterData(simFilterData);

		if (info->type == PhysicsType::DYNAMIC) 
		{
			DynamicInfo* dInfo = info->dynamicInfo;
			PxRigidBodyExt::updateMassAndInertia(*(PxRigidBody*)actor, dInfo->density, &dInfo->cmOffset);

			PxRigidBody* body = (PxRigidBody*)actor;
		}
	}

	// Add actor to scene, set actor for entity, and set user data for actor. Creates one to one between entities and phyX
	scene->addActor(*actor);
	entity->setActor(actor);
	actor->userData = entity;
}
Пример #29
0
void SampleParticles::loadTerrain(const char* path, PxReal xScale, PxReal yScale, PxReal zScale) 
{
	SampleFramework::SampleAsset* asset = getAsset(terrain_hf, SampleFramework::SampleAsset::ASSET_TEXTURE);
	mManagedAssets.push_back(asset);
	PX_ASSERT(asset->getType() == SampleFramework::SampleAsset::ASSET_TEXTURE);	
	SampleFramework::SampleTextureAsset* texAsset = static_cast<SampleFramework::SampleTextureAsset*>(asset);
	SampleRenderer::RendererTexture2D* heightfieldTexture = texAsset->getTexture();
	// NOTE: Assuming that heightfield texture has B8G8R8A8 format.
	if(heightfieldTexture) 
	{
		PxU16 nbColumns = PxU16(heightfieldTexture->getWidth());
		PxU16 nbRows = PxU16(heightfieldTexture->getHeight());
		PxHeightFieldDesc heightFieldDesc;
		heightFieldDesc.nbColumns = nbColumns;
		heightFieldDesc.nbRows = nbRows;
		PxU32* samplesData = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32) * nbColumns * nbRows);
		heightFieldDesc.samples.data = samplesData;
		heightFieldDesc.samples.stride = sizeof(PxU32);
		heightFieldDesc.convexEdgeThreshold = 0;
		PxU8* currentByte = (PxU8*)heightFieldDesc.samples.data;
		PxU32 texturePitch = 0;
		PxU8* loaderPtr = static_cast<PxU8*>(heightfieldTexture->lockLevel(0, texturePitch));
		PxVec3Alloc* verticesA = SAMPLE_NEW(PxVec3Alloc)[nbRows * nbColumns];
		PxVec3* vertices = verticesA;
		PxReal* UVs = (PxReal*)SAMPLE_ALLOC(sizeof(PxReal) * nbRows * nbColumns * 2);
		for (PxU32 row = 0; row < nbRows; row++) 
		{
			for (PxU32 column = 0; column < nbColumns; column++) 
			{
				PxHeightFieldSample* currentSample = (PxHeightFieldSample*)currentByte;
				currentSample->height = *loaderPtr;
				vertices[row * nbColumns + column] = 
					PxVec3(PxReal(row) * xScale, 
					PxReal(currentSample->height * zScale), 
					PxReal(column) * yScale);
				
				UVs[2 * (row * nbColumns + column)] = (PxReal(row) / PxReal(nbRows)) * 7.0f;
				UVs[2 * (row * nbColumns + column) + 1] = (PxReal(column) / PxReal(nbColumns)) * 7.0f;
				currentSample->materialIndex0 = 0;
				currentSample->materialIndex1 = 0;
				currentSample->clearTessFlag();
				currentByte += heightFieldDesc.samples.stride;
				loaderPtr += 4 * sizeof(PxU8);
			}
		}
		PxHeightField* heightField = getPhysics().createHeightField(heightFieldDesc);
		// free allocated memory for heightfield samples description
		SAMPLE_FREE(samplesData);
		// create shape for heightfield		
		PxTransform pose(PxVec3(-((PxReal)nbRows*yScale) / 2.0f, 
								0.0f, 
								-((PxReal)nbColumns*xScale) / 2.0f), 
						PxQuat::createIdentity());
		PxRigidActor* hf = getPhysics().createRigidStatic(pose);
		runtimeAssert(hf, "PxPhysics::createRigidStatic returned NULL\n");
		PxShape* shape = hf->createShape(PxHeightFieldGeometry(heightField, PxMeshGeometryFlags(), zScale, xScale, yScale), getDefaultMaterial());
		runtimeAssert(shape, "PxRigidActor::createShape returned NULL\n");
		shape->setFlag(PxShapeFlag::ePARTICLE_DRAIN, false);
		shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
		// add actor to the scene
		getActiveScene().addActor(*hf);
		mPhysicsActors.push_back(hf);
		// create indices and UVs
		PxU32* indices = (PxU32*)SAMPLE_ALLOC(sizeof(PxU32) * (nbColumns - 1) * (nbRows - 1) * 3 * 2);
		for(int i = 0; i < (nbColumns - 1); ++i) 
		{
			for(int j = 0; j < (nbRows - 1); ++j) 
			{
				// first triangle
				indices[6 * (i * (nbRows - 1) + j) + 0] = (i + 1) * nbRows + j; 
				indices[6 * (i * (nbRows - 1) + j) + 1] = i * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 2] = i * nbRows + j + 1;
				// second triangle
				indices[6 * (i * (nbRows - 1) + j) + 3] = (i + 1) * nbRows + j + 1;
				indices[6 * (i * (nbRows - 1) + j) + 4] = (i + 1) * nbRows + j;
				indices[6 * (i * (nbRows - 1) + j) + 5] = i * nbRows + j + 1;
			}
		}
		// add mesh to renderer
		RAWMesh data;
		data.mName = "terrain";
		data.mTransform = PxTransform::createIdentity();
		data.mNbVerts = nbColumns * nbRows;
		data.mVerts = (PxVec3*)vertices;
		data.mVertexNormals = NULL;
		data.mUVs = UVs;
		data.mMaterialID = MATERIAL_HEIGHTFIELD;
		data.mNbFaces = (nbColumns - 1) * (nbRows - 1) * 2;
		data.mIndices = indices;
		RenderMeshActor* hf_mesh = createRenderMeshFromRawMesh(data);
		hf_mesh->setPhysicsShape(shape);
		SAMPLE_FREE(indices);
		SAMPLE_FREE(UVs);
		DELETEARRAY(verticesA);
	} 
	else 
	{ 
		char errMsg[256];
		physx::string::sprintf_s(errMsg, 256, "Couldn't load %s\n", path);
		fatalError(errMsg);
	}
}
void SampleCustomGravityCameraController::update(Camera& camera, PxReal dtime)
{
	const PxExtendedVec3& currentPos = mCCT.getPosition();
	const PxVec3 curPos = toVec3(currentPos);

	// Compute up vector for current CCT position
	PxVec3 upVector;
	mBase.mPlanet.getUpVector(upVector, curPos);
	PX_ASSERT(upVector.isFinite());

	// Update CCT
	if(!mBase.isPaused())
	{
		if(1)
		{
			bool recordPos = true;
			const PxU32 currentSize = mNbRecords;
			if(currentSize)
			{
				const PxVec3 lastPos = mHistory[currentSize-1];
//				const float limit = 0.1f;
				const float limit = 0.5f;
				if((curPos - lastPos).magnitude()<limit)
					recordPos = false;
			}
			if(recordPos)
			{
				if(mNbRecords==POS_HISTORY_LIMIT)
				{
					for(PxU32 i=1;i<mNbRecords;i++)
						mHistory[i-1] = mHistory[i];
					mNbRecords--;
				}
				mHistory[mNbRecords++] = curPos;
			}
		}

		// Subtract off the 'up' component of the view direction to get our forward motion vector.
		PxVec3 viewDir = camera.getViewDir();
		PxVec3 forward = (viewDir - upVector * upVector.dot(viewDir)).getNormalized();
	
//		PxVec3 forward = mForward;

		// Compute "right" vector
		PxVec3 right = forward.cross(upVector);
		right.normalize();
//		PxVec3 right = mRightV;

		PxVec3 targetKeyDisplacement(0);
		if(mFwd)	targetKeyDisplacement += forward;
		if(mBwd)	targetKeyDisplacement -= forward;

		if(mRight)	targetKeyDisplacement += right;
		if(mLeft)	targetKeyDisplacement -= right;

		targetKeyDisplacement *= mKeyShiftDown ? mRunningSpeed : mWalkingSpeed;
//		targetKeyDisplacement += PxVec3(0,-9.81,0);
		targetKeyDisplacement *= dtime;

		PxVec3 targetPadDisplacement(0);
		targetPadDisplacement += forward * mGamepadForwardInc * mRunningSpeed;
		targetPadDisplacement += right * mGamepadLateralInc * mRunningSpeed;
//		targetPadDisplacement += PxVec3(0,-9.81,0);
		targetPadDisplacement *= dtime;


		const PxF32 heightDelta = gJump.getHeight(dtime);
//		printf("%f\n", heightDelta);
		PxVec3 upDisp = upVector;
		if(heightDelta!=0.0f)
			upDisp *= heightDelta;
		else
			upDisp *= -9.81f * dtime;
		const PxVec3 disp = targetKeyDisplacement + targetPadDisplacement + upDisp;

//upDisp.normalize();
//printf("%f | %f | %f\n", upDisp.x, upDisp.y, upDisp.z);
//		printf("%f | %f | %f\n", targetKeyDisplacement.x, targetKeyDisplacement.y, targetKeyDisplacement.z);
//		printf("%f | %f | %f\n\n", targetPadDisplacement.x, targetPadDisplacement.y, targetPadDisplacement.z);

		mCCT.setUpDirection(upVector);
		const PxU32 flags = mCCT.move(disp, 0.001f, dtime, PxControllerFilters());
		if(flags & PxControllerFlag::eCOLLISION_DOWN)
		{
			gJump.stopJump();
//			printf("Stop jump\n");
		}
	}

	// Update camera
	if(1)
	{
		mTargetYaw		+= mGamepadYawInc * dtime;
		mTargetPitch	+= mGamepadPitchInc * dtime;

		// Clamp pitch
//		if(mTargetPitch<mPitchMin)	mTargetPitch = mPitchMin;
//		if(mTargetPitch>mPitchMax)	mTargetPitch = mPitchMax;
	}

	if(1)
	{
		PxVec3 up = upVector;

		PxQuat localPitchQ(mTargetPitch, PxVec3(1.0f, 0.0f, 0.0f));
		PX_ASSERT(localPitchQ.isSane());
		PxMat33 localPitchM(localPitchQ);

		const PxVec3 upRef(0.0f, 1.0f, 0.0f);

		PxQuat localYawQ(mTargetYaw, upRef);
		PX_ASSERT(localYawQ.isSane());
		PxMat33 localYawM(localYawQ);

			bool res;
			PxQuat localToWorldQ = rotationArc(upRef, up, res);
			static PxQuat memory(0,0,0,1);
			if(!res)
			{
				localToWorldQ = memory;
			}
			else
			{
				memory = localToWorldQ;
			}
			PX_ASSERT(localToWorldQ.isSane());
			PxMat33 localToWorld(localToWorldQ);
		

			static PxVec3 previousUp(0.0f, 1.0f, 0.0f);
			static PxQuat incLocalToWorldQ(0.0f, 0.0f, 0.0f, 1.0f);
			PxQuat incQ = rotationArc(previousUp, up, res);
			PX_ASSERT(incQ.isSane());
//			incLocalToWorldQ = incLocalToWorldQ * incQ;
			incLocalToWorldQ = incQ * incLocalToWorldQ;
			PX_ASSERT(incLocalToWorldQ.isSane());
			incLocalToWorldQ.normalize();
			PxMat33 incLocalToWorldM(incLocalToWorldQ);
			localToWorld = incLocalToWorldM;
			previousUp = up;

mTest = localToWorld;
//mTest = localToWorld * localYawM;

//		PxMat33 rot = localYawM * localToWorld;
		PxMat33 rot = localToWorld * localYawM * localPitchM;
//		PxMat33 rot = localToWorld * localYawM;
		PX_ASSERT(rot.column0.isFinite());
		PX_ASSERT(rot.column1.isFinite());
		PX_ASSERT(rot.column2.isFinite());

		////

		PxMat44 view(rot.column0, rot.column1, rot.column2, PxVec3(0));

		mForward = -rot.column2;
		mRightV = rot.column0;

		camera.setView(PxTransform(view));
		PxVec3 viewDir = camera.getViewDir();
		PX_ASSERT(viewDir.isFinite());

		////

		PxRigidActor* characterActor = mCCT.getActor();
		
		PxShape* shape;
		characterActor->getShapes(&shape,1);

		PxCapsuleGeometry geom;
		shape->getCapsuleGeometry(geom);

		up *= geom.halfHeight+geom.radius;

		const PxVec3 headPos = curPos + up;
		const float distanceToTarget = 10.0f;
//		const float distanceToTarget = 20.0f;
//		const float distanceToTarget = 5.0f;
//		const PxVec3 camPos = headPos - viewDir*distanceToTarget;
		const PxVec3 camPos = headPos - mForward*distanceToTarget;// + up * 20.0f;
//		view.t = camPos;
		view.column3 = PxVec4(camPos,0);
//		camera.setView(view);
		camera.setView(PxTransform(view));
		mTarget = headPos;
	}

	if(0)
	{
		PxControllerState cctState;
		mCCT.getState(cctState);
		printf("\nCCT state:\n");
		printf("delta:             %.02f | %.02f | %.02f\n", cctState.deltaXP.x, cctState.deltaXP.y, cctState.deltaXP.z);
		printf("touchedShape:      %p\n", cctState.touchedShape);
		printf("touchedObstacle:   %p\n", cctState.touchedObstacle);
		printf("standOnAnotherCCT: %d\n", cctState.standOnAnotherCCT);
		printf("standOnObstacle:   %d\n", cctState.standOnObstacle);
		printf("isMovingUp:        %d\n", cctState.isMovingUp);
		printf("collisionFlags:    %d\n", cctState.collisionFlags);
	}

}