예제 #1
0
void UBodySetup::AddConvexElemsToRigidActor(PxRigidActor* PDestActor, const FTransform& RelativeTM, const FVector& Scale3D, const FVector& Scale3DAbs, TArray<PxShape*>* NewShapes) const
{
	float ContactOffsetFactor, MaxContactOffset;
	GetContactOffsetParams(ContactOffsetFactor, MaxContactOffset);
	PxMaterial* PDefaultMat = GetDefaultPhysMaterial();

	for (int32 i = 0; i < AggGeom.ConvexElems.Num(); i++)
	{
		const FKConvexElem& ConvexElem = AggGeom.ConvexElems[i];

		if (ConvexElem.ConvexMesh)
		{
			PxTransform PLocalPose;
			bool bUseNegX = CalcMeshNegScaleCompensation(Scale3D, PLocalPose);

			PxConvexMeshGeometry PConvexGeom;
			PConvexGeom.convexMesh = bUseNegX ? ConvexElem.ConvexMeshNegX : ConvexElem.ConvexMesh;
			PConvexGeom.scale.scale = U2PVector(Scale3DAbs * ConvexElem.GetTransform().GetScale3D().GetAbs());
			FTransform ConvexTransform = ConvexElem.GetTransform();
			if (ConvexTransform.GetScale3D().X < 0 || ConvexTransform.GetScale3D().Y < 0 || ConvexTransform.GetScale3D().Z < 0)
			{
				UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has negative scale. Not currently supported"), *GetPathNameSafe(GetOuter()), i);
			}
			if (ConvexTransform.IsValid())
			{
				PxTransform PElementTransform = U2PTransform(ConvexTransform * RelativeTM);
				PLocalPose.q *= PElementTransform.q;
				PLocalPose.p = PElementTransform.p;
				PLocalPose.p.x *= Scale3D.X;
				PLocalPose.p.y *= Scale3D.Y;
				PLocalPose.p.z *= Scale3D.Z;

				if (PConvexGeom.isValid())
				{
					PxVec3 PBoundsExtents = PConvexGeom.convexMesh->getLocalBounds().getExtents();

					ensure(PLocalPose.isValid());
					PxShape* NewShape = PDestActor->createShape(PConvexGeom, *PDefaultMat, PLocalPose);

					if (NewShapes)
					{
						NewShapes->Add(NewShape);
					}

					const float ContactOffset = FMath::Min(MaxContactOffset, ContactOffsetFactor * PBoundsExtents.minElement());
					NewShape->setContactOffset(ContactOffset);
				}
				else
				{
					UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] invalid"), *GetPathNameSafe(GetOuter()), i);
				}
			}
			else
			{
				UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: [%s] ConvexElem[%d] has invalid transform"), *GetPathNameSafe(GetOuter()), i);
			}
		}
		else
		{
			UE_LOG(LogPhysics, Warning, TEXT("AddConvexElemsToRigidActor: ConvexElem is missing ConvexMesh (%d: %s)"), i, *GetPathName());
		}
	}
}
PxController* ControlledActor::init(const ControlledActorDesc& desc, PxControllerManager* manager)
{
	const float radius	= desc.mRadius;
	float height		= desc.mHeight;
	float crouchHeight	= desc.mCrouchHeight;

	PxControllerDesc* cDesc;
	PxBoxControllerDesc boxDesc;
	PxCapsuleControllerDesc capsuleDesc;

	if(desc.mType==PxControllerShapeType::eBOX)
	{
		height *= 0.5f;
		height += radius;
		crouchHeight *= 0.5f;
		crouchHeight += radius;
		boxDesc.halfHeight			= height;
		boxDesc.halfSideExtent		= radius;
		boxDesc.halfForwardExtent	= radius;
		cDesc = &boxDesc;
	}
	else 
	{
		PX_ASSERT(desc.mType==PxControllerShapeType::eCAPSULE);
		capsuleDesc.height = height;
		capsuleDesc.radius = radius;
		capsuleDesc.climbingMode = PxCapsuleClimbingMode::eCONSTRAINED;
		cDesc = &capsuleDesc;
	}

	cDesc->density				= desc.mProxyDensity;
	cDesc->scaleCoeff			= desc.mProxyScale;
	cDesc->material				= &mOwner.getDefaultMaterial();
	cDesc->position				= desc.mPosition;
	cDesc->slopeLimit			= desc.mSlopeLimit;
	cDesc->contactOffset		= desc.mContactOffset;
	cDesc->stepOffset			= desc.mStepOffset;
	cDesc->invisibleWallHeight	= desc.mInvisibleWallHeight;
	cDesc->maxJumpHeight		= desc.mMaxJumpHeight;
//	cDesc->nonWalkableMode		= PxControllerNonWalkableMode::ePREVENT_CLIMBING_AND_FORCE_SLIDING;
	cDesc->reportCallback		= desc.mReportCallback;
	cDesc->behaviorCallback		= desc.mBehaviorCallback;
	cDesc->volumeGrowth			= desc.mVolumeGrowth;

	mType						= desc.mType;
	mInitialPosition			= desc.mPosition;
	mStandingSize				= height;
	mCrouchingSize				= crouchHeight;
	mControllerRadius			= radius;

	PxController* ctrl = static_cast<PxBoxController*>(manager->createController(*cDesc));
	PX_ASSERT(ctrl);

	// remove controller shape from scene query for standup overlap test
	PxRigidDynamic* actor = ctrl->getActor();
	if(actor)
	{
		if(actor->getNbShapes())
		{
			PxShape* ctrlShape;
			actor->getShapes(&ctrlShape,1);
			ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);

			Renderer* renderer = mOwner.getRenderer();

			if(desc.mType==PxControllerShapeType::eBOX)
			{
				const PxVec3 standingExtents(radius, height, radius);
				const PxVec3 crouchingExtents(radius, crouchHeight, radius);

				mRenderActorStanding = SAMPLE_NEW(RenderBoxActor)(*renderer, standingExtents);
				mRenderActorCrouching = SAMPLE_NEW(RenderBoxActor)(*renderer, crouchingExtents);
			}
			else if(desc.mType==PxControllerShapeType::eCAPSULE)
			{
				mRenderActorStanding = SAMPLE_NEW(RenderCapsuleActor)(*renderer, radius, height*0.5f);
				mRenderActorCrouching = SAMPLE_NEW(RenderCapsuleActor)(*renderer, radius, crouchHeight*0.5f);
			}
		}
	}

	mController = ctrl;
	return ctrl;
}
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);
	}

}
예제 #4
0
void SampleParticles::Raygun::update(float dtime)
{
	if(!isEnabled())
		return;
	
	PX_ASSERT(mSample && mForceSmokeCapsule && mForceWaterCapsule && mRenderActor);

	// access properties from sample
	PxScene& scene = mSample->getActiveScene();
	PxVec3 position = mSample->getCamera().getPos();
	PxTransform cameraPose = mSample->getCamera().getViewMatrix();
	PxMat33 cameraBase(cameraPose.q);
	PxVec3 cameraForward = -cameraBase[2];
	PxVec3 cameraUp = -cameraBase[1];
	
	// perform raycast here and update impact point
	PxRaycastHit hit;
	mIsImpacting = scene.raycastSingle(cameraPose.p, cameraForward, 500.0f, PxSceneQueryFlags(0xffffffff), hit);
	float impactParam = mIsImpacting ? (hit.impact - position).magnitude() : FLT_MAX;	

	PxTransform rayPose(position + cameraUp * 0.5f, cameraPose.q*PxQuat(PxHalfPi, PxVec3(0,1,0)));

	updateRayCapsule(mForceSmokeCapsule, rayPose, 1.0f);
	updateRayCapsule(mForceWaterCapsule, rayPose, 0.3f);
	mRenderActor->setTransform(rayPose);

	// if we had an impact
	if (impactParam < FLT_MAX)
	{
		PxVec3 impactPos = position + cameraForward*impactParam;
		// update emitter with new impact point and direction
		if(mSmokeEmitter.emitter)
			mSmokeEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));
		if(mDebrisEmitter.emitter)
			mDebrisEmitter.emitter->setLocalPose(PxTransform(impactPos, directionToQuaternion(-cameraForward)));

		// spawn new RB debris
		if(mRbDebrisTimer < 0.0f && impactParam < FLT_MAX) 
		{
			mRbDebrisTimer = RAYGUN_RB_DEBRIS_RATE;

			PxVec3 randDir(getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f),
				getSampleRandom().rand(-1.0f, 1.0f));
			PxVec3 vel = -7.0f * (cameraForward + RAYGUN_RB_DEBRIS_ANGLE_RANDOMNESS * randDir.getNormalized());
			PxVec3 dim(getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE),
				getSampleRandom().rand(0.0f, RAYGUN_RB_DEBRIS_SCALE));
			// give spawn position, initial velocity and dimensions, spawn convex
			// which will not act in scene queries
			PxConvexMesh* convexMesh = generateConvex(mSample->getPhysics(), mSample->getCooking(), RAYGUN_RB_DEBRIS_SCALE);
			mSample->runtimeAssert(convexMesh, "Error generating convex for debris.\n");
			PxRigidDynamic* debrisActor = PxCreateDynamic(
				mSample->getPhysics(), 
				PxTransform(impactPos - cameraForward * 0.5f), 
				PxConvexMeshGeometry(convexMesh), 
				mSample->getDefaultMaterial(), 1.f);  
			mSample->getActiveScene().addActor(*debrisActor);

			PX_ASSERT(debrisActor->getNbShapes() == 1);
			PxShape* debrisShape;
			debrisActor->getShapes(&debrisShape, 1);
			debrisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
			debrisActor->setLinearVelocity(vel);
			debrisActor->setActorFlag(PxActorFlag::eVISUALIZATION, true);
			debrisActor->setAngularDamping(0.5f);
			
			// default material is green for debris
			RenderMaterial* debriMaterial = mSample->getMaterial(MATERIAL_HEIGHTFIELD);
			if(!debriMaterial) 
			{
				debriMaterial = mSample->mRenderMaterials[MATERIAL_GREEN];				
			}
			mSample->createRenderObjectsFromActor(debrisActor, debriMaterial);
			mDebrisLifetime[debrisShape] = RAYGUN_RB_DEBRIS_LIFETIME;
		}
	}

	// update debris lifetime, remove if life ends
	DebrisLifetimeMap::iterator it = mDebrisLifetime.begin();
	while(it != mDebrisLifetime.end()) 
	{
		(*it).second -= dtime;
		if((*it).second < 0.0f) 
		{
			PxShape* debrisShape = (*it).first;
			PX_ASSERT(debrisShape);

			// remove convex mesh
			PxConvexMeshGeometry geometry;
			bool isConvex = debrisShape->getConvexMeshGeometry(geometry);
			PX_ASSERT(isConvex);
			PX_UNUSED(isConvex);
			geometry.convexMesh->release();
			
			// remove render and physics actor
			PxRigidActor& actorToRemove = debrisShape->getActor();
			mSample->removeActor(&actorToRemove);			
			actorToRemove.release();
			
			// remove actor from lifetime map
			mDebrisLifetime.erase(it);
			it = mDebrisLifetime.begin();
			continue;
		}
		++it;
	}
}
예제 #5
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);
	}
}
예제 #6
0
bool UWorld::ComponentOverlapTest(class UPrimitiveComponent* PrimComp, const FVector& Pos, const FRotator& Rot, const struct FComponentQueryParams& Params) const
{
	if(GetPhysicsScene() == NULL)
	{
		return false;
	}

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

	// if target is skeletalmeshcomponent and do not support singlebody physics, we don't support this yet
	// talk to @JG, SP, LH
	if ( !PrimComp->ShouldTrackOverlaps() )
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentOverlapMulti : (%s) Does not support skeletalmesh with Physics Asset and destructibles."), *PrimComp->GetPathName());
		return false;
	}
#if WITH_PHYSX
	ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType();

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

	// calculate the test global pose of the actor
	PxTransform PTestGlobalPose = U2PTransform(FTransform(Rot, Pos));

	// Get all the shapes from the actor
	TArray<PxShape*, TInlineAllocator<8>> PShapes;
	PShapes.AddZeroed(PRigidActor->getNbShapes());
	int32 NumShapes = PRigidActor->getShapes(PShapes.GetData(), PShapes.Num());

	// Iterate over each shape
	for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++)
	{
		PxShape* PShape = PShapes[ShapeIdx];
		check(PShape);
		// Calc shape global pose
		PxTransform PLocalPose = PShape->getLocalPose();
		PxTransform PShapeGlobalPose = PTestGlobalPose.transform(PLocalPose);

		GET_GEOMETRY_FROM_SHAPE(PGeom, PShape);

		if(PGeom != NULL)
		{
			if( GeomOverlapTest(this, *PGeom, PShapeGlobalPose, TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())))
			{
				// in this test, it only matters true or false. 
				// if we found first true, we don't care next test anymore. 
				return true;
			}
		}
	}

#endif //WITH_PHYSX
	return false;
}
예제 #7
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;
}
//=================================================================================
// Multiple hits compound sweep
// AP: we might be able to improve the return results API but no time for it in 3.3
PxU32 PxRigidBodyExt::linearSweepMultiple(
	PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, PxHitFlags outputFlags,
	PxSweepHit* hitBuffer, PxU32* hitShapeIndices, PxU32 hitBufferSize, PxSweepHit& block, PxI32& blockingHitShapeIndex,
	bool& overflow, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
	const PxQueryCache* cache, const PxReal inflation)
{
	overflow = false;
	blockingHitShapeIndex = -1;

	for (PxU32 i = 0; i < hitBufferSize; i++)
		hitShapeIndices[i] = 0xFFFFffff;

	PxI32 sumNbResults = 0;

	PxU32 nbShapes = body.getNbShapes();
	PxF32 shrunkMaxDistance = distance;
	for(PxU32 i=0; i < nbShapes; i++)
	{
		PxShape* shape = NULL;
		body.getShapes(&shape, 1, i);
		PX_ASSERT(shape != NULL);
		PxTransform pose = PxShapeExt::getGlobalPose(*shape, body);
		PxQueryFilterData fd;
		fd.flags = filterData.flags;
		PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3);
		fd.data = or4 ? filterData.data : shape->getSimulationFilterData();
		PxGeometryHolder anyGeom = shape->getGeometry();

		PxU32 bufSizeLeft = hitBufferSize-sumNbResults;
		PxSweepHit extraHit;
		PxSweepBuffer buffer(bufSizeLeft == 0 ? &extraHit : hitBuffer+sumNbResults, bufSizeLeft == 0 ? 1 : hitBufferSize-sumNbResults);
		scene.sweep(anyGeom.any(), pose, unitDir, shrunkMaxDistance, buffer, outputFlags, fd, filterCall, cache, inflation);

		// Check and abort on overflow. Assume overflow if result count is bufSize.
		PxU32 nbNewResults = buffer.getNbTouches();
		overflow |= (nbNewResults >= bufSizeLeft);
		if (bufSizeLeft == 0) // this is for when we used the extraHit buffer
			nbNewResults = 0;

		// set hitShapeIndices for each new non-blocking hit
		for (PxU32 j = 0; j < nbNewResults; j++)
			if (sumNbResults + PxU32(j) < hitBufferSize)
				hitShapeIndices[sumNbResults+j] = i;

		if (buffer.hasBlock) // there's a blocking hit in the most recent sweepMultiple results
		{
			// overwrite the return result blocking hit with the new blocking hit if under
			if (blockingHitShapeIndex == -1 || buffer.block.distance < block.distance)
			{
				blockingHitShapeIndex = (PxI32)i;
				block = buffer.block;
			}

			// Remove all the old touching hits below the new maxDist
			// sumNbResults is not updated yet at this point
			//   and represents the count accumulated so far excluding the very last query
			PxI32 nbNewResultsSigned = PxI32(nbNewResults); // need a signed version, see nbNewResultsSigned-- below
			for (PxI32 j = sumNbResults-1; j >= 0; j--) // iterate over "old" hits (up to shapeIndex-1)
				if (buffer.block.distance < hitBuffer[j].distance)
				{
					// overwrite with last "new" hit
					PxI32 sourceIndex = PxI32(sumNbResults)+nbNewResultsSigned-1; PX_ASSERT(sourceIndex >= j);
					hitBuffer[j] = hitBuffer[sourceIndex];
					hitShapeIndices[j] = hitShapeIndices[sourceIndex];
					nbNewResultsSigned--; // can get negative, that means we are shifting the last results array
				}

			sumNbResults += nbNewResultsSigned;
		} else // if there was no new blocking hit we don't need to do anything special, simply append all results to touch array
			sumNbResults += nbNewResults;

		PX_ASSERT(sumNbResults >= 0 && sumNbResults <= PxI32(hitBufferSize));
	}

	return (PxU32)sumNbResults;
}
예제 #9
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;
}
예제 #10
0
PxCapsuleController* SampleCustomGravity::createCharacter(const PxExtendedVec3& position)
#endif
{
	const float height = 2.0f;		
//	const float height = 1e-6f;	// PT: TODO: make it work with 0?

#ifdef USE_BOX_CONTROLLER
	PxBoxControllerDesc cDesc;
	cDesc.halfHeight			= height;
	cDesc.halfSideExtent		= mControllerRadius;
	cDesc.halfForwardExtent		= mControllerRadius;
#else
	PxCapsuleControllerDesc cDesc;
	cDesc.height				= height;
	cDesc.radius				= mControllerRadius;
#endif
	cDesc.material				= &getDefaultMaterial();
	cDesc.position				= position;
	cDesc.slopeLimit			= SLOPE_LIMIT;
	cDesc.contactOffset			= CONTACT_OFFSET;
	cDesc.stepOffset			= STEP_OFFSET;
	cDesc.invisibleWallHeight	= INVISIBLE_WALLS_HEIGHT;
	cDesc.maxJumpHeight			= MAX_JUMP_HEIGHT;
	cDesc.callback				= this;

	mControllerInitialPosition = cDesc.position;

#ifdef USE_BOX_CONTROLLER
	PxBoxController* ctrl = static_cast<PxBoxController*>(mControllerManager->createController(getPhysics(), &getActiveScene(), cDesc));
#else
	PxCapsuleController* ctrl = static_cast<PxCapsuleController*>(mControllerManager->createController(getPhysics(), &getActiveScene(), cDesc));
#endif
	// remove controller shape from scene query for standup overlap test
	PxRigidDynamic* actor = ctrl->getActor();
	if(actor)
	{
		if(actor->getNbShapes())
		{
			PxShape* ctrlShape;
			actor->getShapes(&ctrlShape,1);
			ctrlShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);

#ifdef USE_BOX_CONTROLLER
			const PxVec3 standingExtents(mControllerRadius, height, mControllerRadius);
 			mRenderActor = SAMPLE_NEW(RenderBoxActor)(*getRenderer(), standingExtents);
#else
 			mRenderActor = SAMPLE_NEW(RenderCapsuleActor)(*getRenderer(), mControllerRadius, height*0.5f);
#endif
			if(mRenderActor)
				mRenderActors.push_back(mRenderActor);
		}
		else
			fatalError("character actor has no shape");
	}
	else
		fatalError("character could not create actor");

	// uncomment the next line to render the character
	//createRenderObjectsFromActor(ctrl->getActor());

	return ctrl;
}
예제 #11
0
osg::Node* createNodeForActor( PxRigidActor* actor )
{
    if ( !actor ) return NULL;
    std::vector<PxShape*> shapes( actor->getNbShapes() );
    
    osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
    transform->setMatrix( toMatrix(PxMat44(actor->getGlobalPose())) );
    
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    transform->addChild( geode.get() );
    
    PxU32 num = actor->getShapes( &(shapes[0]), actor->getNbShapes() );
    for ( PxU32 i=0; i<num; ++i )
    {
        PxShape* shape = shapes[i];
        osg::Matrix localMatrix = toMatrix( PxMat44(actor->getGlobalPose()) );
        osg::Vec3 localPos = toVec3( shape->getLocalPose().p );
        osg::Quat localQuat(shape->getLocalPose().q.x, shape->getLocalPose().q.y,
                            shape->getLocalPose().q.z, shape->getLocalPose().q.w);
        
        switch ( shape->getGeometryType() )
        {
        case PxGeometryType::eSPHERE:
            {
                PxSphereGeometry sphere;
                shape->getSphereGeometry( sphere );
                
                osg::Sphere* sphereShape = new osg::Sphere(localPos, sphere.radius);
                geode->addDrawable( new osg::ShapeDrawable(sphereShape) );
            }
            break;
        case PxGeometryType::ePLANE:
            // TODO
            break;
        case PxGeometryType::eCAPSULE:
            {
                PxCapsuleGeometry capsule;
                shape->getCapsuleGeometry( capsule );
                
                osg::Capsule* capsuleShape = new osg::Capsule(
                    localPos, capsule.radius, capsule.halfHeight * 2.0f);
                capsuleShape->setRotation( localQuat );
                geode->addDrawable( new osg::ShapeDrawable(capsuleShape) );
            }
            break;
        case PxGeometryType::eBOX:
            {
                PxBoxGeometry box;
                shape->getBoxGeometry( box );
                
                osg::Box* boxShape = new osg::Box(localPos,
                    box.halfExtents[0] * 2.0f, box.halfExtents[1] * 2.0f, box.halfExtents[2] * 2.0f);
                boxShape->setRotation( localQuat );
                geode->addDrawable( new osg::ShapeDrawable(boxShape) );
            }
            break;
        case PxGeometryType::eCONVEXMESH:
            {
                PxConvexMeshGeometry convexMeshGeom;
                shape->getConvexMeshGeometry( convexMeshGeom );
                // TODO: consider convexMeshGeom.scale
                
                PxConvexMesh* convexMesh = convexMeshGeom.convexMesh;
                if ( convexMesh )
                {
                    /*for ( unsigned int i=0; i<convexMesh->getNbPolygons(); ++i )
                    {
                        
                    }*/
                    // TODO
                }
            }
            break;
        case PxGeometryType::eTRIANGLEMESH:
            {
                PxTriangleMeshGeometry triangleMeshGeom;
                shape->getTriangleMeshGeometry( triangleMeshGeom );
                // TODO: consider triangleMeshGeom.scale
                
                PxTriangleMesh* triangleMesh = triangleMeshGeom.triangleMesh;
                if ( triangleMesh )
                {
                    osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array( triangleMesh->getNbVertices() );
                    for ( unsigned int i=0; i<va->size(); ++i )
                        (*va)[i] = toVec3( *(triangleMesh->getVertices() + i) ) * localMatrix;
                    
                    osg::ref_ptr<osg::DrawElements> de;
                    if ( triangleMesh->getTriangleMeshFlags()&PxTriangleMeshFlag::eHAS_16BIT_TRIANGLE_INDICES )
                    {
                        osg::DrawElementsUShort* de16 = new osg::DrawElementsUShort(GL_TRIANGLES);
                        de = de16;
                        
                        const PxU16* indices = (const PxU16*)triangleMesh->getTriangles();
                        for ( unsigned int i=0; i<triangleMesh->getNbTriangles(); ++i )
                        {
                            de16->push_back( indices[3 * i + 0] );
                            de16->push_back( indices[3 * i + 1] );
                            de16->push_back( indices[3 * i + 2] );
                        }
                    }
                    else
                    {
                        osg::DrawElementsUInt* de32 = new osg::DrawElementsUInt(GL_TRIANGLES);
                        de = de32;
                        
                        const PxU32* indices = (const PxU32*)triangleMesh->getTriangles();
                        for ( unsigned int i=0; i<triangleMesh->getNbTriangles(); ++i )
                        {
                            de32->push_back( indices[3 * i + 0] );
                            de32->push_back( indices[3 * i + 1] );
                            de32->push_back( indices[3 * i + 2] );
                        }
                    }
                    geode->addDrawable( createGeometry(va.get(), NULL, NULL, de.get()) );
                }
            }
            break;
        case PxGeometryType::eHEIGHTFIELD:
            {
                PxHeightFieldGeometry hfGeom;
                shape->getHeightFieldGeometry( hfGeom );
                // TODO: consider hfGeom.*scale
                
                PxHeightField* heightField = hfGeom.heightField;
                if ( heightField )
                {
                    // TODO
                }
            }
            break;
        }
    }
    return transform.release();
}
FDbool BuildingSystem::searchForHit(PhysicsSystem& physicsSystem,
		Ray r, PxGeometry& pixelFrustum, SearchContext& searchContext) {

	// Cast the ray into the scene. Quit if no intersection at all.
	PxQueryFilterData qFilterData;
	qFilterData.flags |= PxQueryFlag::ePREFILTER | PxQueryFlag::ePOSTFILTER;
	FDbool rayStatus = physicsSystem.scene->raycast(
			r.position, r.direction, 100, searchContext.hitBuffer, 
			PxHitFlag::ePOSITION | PxHitFlag::eDISTANCE | PxHitFlag::eNORMAL,
			qFilterData, &CustomPhysicsQueryFilter());

	/* Demo-ing to a friend showed that it can be confusing to try to connect
	* up an existing point that lies on the guide plane, since part of it will
	* be behind the guide plane, which the ray-cast will see as being closer.
	* To remedy this, I treat the GuidePlane as a "touching" rather than 
	* "blocking hit" and give some priority to points. */
	if (rayStatus && searchContext.hitBuffer.hasBlock) {
		
		// In this case, we know we hit something other than the guide plane.
		searchContext.hitActor = searchContext.hitBuffer.block.actor;
		searchContext.rayHit = &searchContext.hitBuffer.block;
		FDreal blockDistance = searchContext.rayHit->distance;
		searchContext.setHit(&searchContext.hitBuffer.block);

		// If the guide plane was also hit, see if it is closer. 
		if (searchContext.hitBuffer.nbTouches > 0) {
			float guidePlaneDistance = searchContext.hitBuffer.getTouch(0).
					distance;

			// If the point intersects the plane, prefer it.
			if (searchContext.hitActor == pointActor) {

				FDUint i = (FDUint)searchContext.rayHit->shape->userData;
				Vector3 pointPos = *pointAuthor->getAttribute<Vector3>(i, 0);
				float pointRadius = 0.2;

				Vector3 guidePlaneNormal = searchContext.hitBuffer.
						getTouch(0).normal;
				Plane p = Plane(searchContext.hitBuffer.getTouch(0).position,
						guidePlaneNormal);

				// We know the point (modeled as a sphere) intersects the
				// plane if the point is within 1 sphere radius.
				float pointPlaneDistance = p.distance(pointPos);
				if (abs(pointPlaneDistance) <= pointRadius) {
					blockDistance = 0;
				}
			} 
			
			if (guidePlaneDistance < blockDistance) {
				searchContext.hitActor = searchContext.hitBuffer.getTouch(0).
						actor;
				searchContext.setHit(&searchContext.hitBuffer.getTouch(0));
			}

		}

	} else if (rayStatus) {
		
		// Only the guide plane was hit.
		searchContext.hitActor = searchContext.hitBuffer.getTouch(0).actor;
		searchContext.setHit(&searchContext.hitBuffer.getTouch(0));
	}

	// Try overlap test for other geometry.
	Quaternion q = fdmath::getRotationBetween(Vector3(0, 0, 1), r.direction);
	Vector3 obo = q.rotate(Vector3(0, 0, 1));

	PxTransform pose(r.position, q);

	PxQueryFilterData qPixelFilterData;
	qPixelFilterData.flags |= PxQueryFlag::ePREFILTER;
	physicsSystem.scene->overlap(pixelFrustum, pose, 
			searchContext.overlapBuffer, qPixelFilterData, 
			&PixelQueryFilter());

	for (FDUint i = 0; i < searchContext.overlapBuffer.nbTouches; i++) {
		PxRigidStatic* thisActor = (PxRigidStatic*)searchContext.overlapBuffer.
				touches[i].actor;
		PxShape* thisShape = searchContext.overlapBuffer.touches[i].shape;

		// Get the closet point on the line to the ray.

		Transform lineTransform = thisActor->getGlobalPose() *
				thisShape->getLocalPose();
		Vector3 lineAxisPoint = lineTransform.transform(Vector3(1, 0, 0));
		Vector3 centerPos = lineTransform.p;
		Vector3 lineAxis = (lineAxisPoint - centerPos).getNormalized();

		Vector3 uAxis = lineAxis.cross(r.direction);
		uAxis.normalize();

		Plane p(centerPos, lineAxisPoint, centerPos + uAxis);
		Vector3 intersectionPoint;
		FDbool intersects = r.intersect(p, intersectionPoint);
		FD_ASSERT(intersects, "Ray did not intersect line's plane.");

		FDreal y = lineAxis.dot(intersectionPoint) - lineAxis.dot(centerPos);
		Vector3 closestPoint = centerPos + lineAxis * y;

		FDreal dist = (closestPoint - r.position).magnitude(); 
		if (dist < searchContext.hitDist) {
			searchContext.setHit(&searchContext.overlapBuffer.touches[i],
					closestPoint, -r.direction, dist);
			searchContext.hitActor = thisActor;
		}
	} 

	return searchContext.hitHappened;
}
예제 #13
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;
}
예제 #14
0
bool UWorld::ComponentSweepSingle(struct FHitResult& OutHit,class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FRotator& Rot, const struct FComponentQueryParams& Params) const
{
	OutHit.TraceStart = Start;
	OutHit.TraceEnd = End;

	if(GetPhysicsScene() == NULL)
	{
		return false;
	}

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

	// if target is skeletalmeshcomponent and do not support singlebody physics
	if ( !PrimComp->ShouldTrackOverlaps() )
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepSingle : (%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 RaycastSingle(this, OutHit, 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;
	}

	// Get all the shapes from the actor
	TArray<PxShape*, TInlineAllocator<8>> PShapes;
	PShapes.AddZeroed(PRigidActor->getNbShapes());
	int32 NumShapes = 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
	for(int32 ShapeIdx=0; ShapeIdx<PShapes.Num(); ShapeIdx++)
	{
		PxShape* PShape = PShapes[ShapeIdx];
		check(PShape);

		// 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)
		{
			// @todo UE4, this might not be the best behavior. If we're looking for the most closest, this have to change to save the result, and find the closest one or 
			// any other options, right now if anything hits first, it will return
			if (GeomSweepSingle(this, *PGeom, PShapeRot, OutHit, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())))
			{
				bHaveBlockingHit = true;
				break;
			}
		}
	}

	return bHaveBlockingHit;
#endif //WITH_PHYSX
	return false;
}
bool UWorld::ComponentSweepMulti(TArray<struct FHitResult>& OutHits, class UPrimitiveComponent* PrimComp, const FVector& Start, const FVector& End, const FQuat& Quat, const struct FComponentQueryParams& Params) const
{
	if (GetPhysicsScene() == NULL)
	{
		return false;
	}

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

	ECollisionChannel TraceChannel = PrimComp->GetCollisionObjectType();

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

	OutHits.Reset();

#if UE_WITH_PHYSICS
	const FBodyInstance* BodyInstance = PrimComp->GetBodyInstance();

	if (!BodyInstance || !BodyInstance->IsValidBodyInstance())
	{
		UE_LOG(LogCollision, Log, TEXT("ComponentSweepMulti : (%s) No physics data"), *PrimComp->GetReadableName());
		return false;
	}

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	if(PrimComp->IsA(USkeletalMeshComponent::StaticClass()))
	{
		UE_LOG(LogCollision, Warning, TEXT("ComponentSweepMulti : SkeletalMeshComponent support only root body (%s) "), *PrimComp->GetReadableName());
	}
#endif

#endif

	SCOPE_CYCLE_COUNTER(STAT_Collision_GeomSweepMultiple);
	bool bHaveBlockingHit = false;

#if WITH_PHYSX
	ExecuteOnPxRigidActorReadOnly(BodyInstance, [&] (const PxRigidActor* PRigidActor)
	{
		// Get all the shapes from the actor
		FInlinePxShapeArray PShapes;
		const int32 NumShapes = FillInlinePxShapeArray(PShapes, *PRigidActor);

		// calculate the test global pose of the actor
		const PxQuat PGeomRot = U2PQuat(Quat);
		const PxTransform PGlobalStartPose = PxTransform(U2PVector(Start), PGeomRot);
		const PxTransform PGlobalEndPose = PxTransform(U2PVector(End), PGeomRot);

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

			GET_GEOMETRY_FROM_SHAPE(PGeom, PShape);

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

				if (GeomSweepMulti_PhysX(this, *PGeom, PShapeRot, OutHits, P2UVector(PShapeGlobalStartPose.p), P2UVector(PShapeGlobalEndPose.p), TraceChannel, Params, FCollisionResponseParams(PrimComp->GetCollisionResponseToChannels())))
				{
					bHaveBlockingHit = true;
				}
			}
		}
	});
#endif //WITH_PHYSX

	//@TODO: BOX2D: Implement UWorld::ComponentSweepMulti
#if WITH_BOX2D
// 	if (b2Body* BodyInstance = PrimComp->BodyInstance.BodyInstancePtr)
// 	{
// 		
// 	}
#endif

	return bHaveBlockingHit;
}
예제 #16
0
void SampleSubmarine::createDynamicActors()
{
	// create mines
	static const PxU32 numMines = 20;
	static const PxVec3 mineFieldCenter = PxVec3(0, 64, 0);
	static const PxReal minMineDistance = 3.0f;
	static const PxI32 mineFieldRadius = 30;
	for(PxU32 i = 0; i < numMines; i++)
	{
		// raycast against floor (height field) to find the height to attach the mine
		PxRaycastHit rayHit;
		bool hit = false;
		do
		{
			PxVec3 offset = PxVec3(PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)), 0, PxReal(getSampleRandom().rand(-mineFieldRadius, mineFieldRadius)));
			PxVec3 raycastStart = mineFieldCenter + offset*minMineDistance;
			hit = getActiveScene().raycastSingle(raycastStart, PxVec3(0,-1,0), 100.0f, PxSceneQueryFlag::eIMPACT, rayHit);
		} 
		while(!hit || (rayHit.impact.y > 25.0f) || rayHit.shape->getActor().is<PxRigidDynamic>());
		createSeamine(rayHit.impact, getSampleRandom().rand(10.0f, 25.0f));
	}

	// create treasure
	{
		static const PxVec3 treasureDim = PxVec3(5, 3, 4)*0.5f;

		PxRaycastHit rayHit;
		PxVec3 raycastStart = PxVec3(-19, 64, -24);
		getActiveScene().raycastSingle(raycastStart, PxVec3(0,-1,0), 100.0f, PxSceneQueryFlag::eIMPACT, rayHit);

#ifdef RENDERER_PSP2
		gTreasureActor = createBox(rayHit.impact+treasureDim, treasureDim, NULL, mTreasureMaterial, 1)->is<PxRigidDynamic>();
#else
		gTreasureActor = createBox(rayHit.impact+treasureDim, treasureDim, NULL, mManagedMaterials[MATERIAL_BLUE], 1)->is<PxRigidDynamic>();
#endif
		if(!gTreasureActor) fatalError("createBox failed!");
		gTreasureActor->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
		PxShape* treasureShape;
		gTreasureActor->getShapes(&treasureShape, 1);
		treasureShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
		treasureShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);
	}

	// create submarine
	createSubmarine(PxVec3(-110, 50, 110), 2.1f);
	
	char theCrabName[256];
	sprintf(theCrabName, "crab_%s.bin", getPlatformName());
	
	// If we have already had crab copy, just load it, or will create crab and export it
	char thePathBuffer[1024];
	const char* theCrabPath = getSampleOutputDirManager().getFilePath( theCrabName, thePathBuffer, false );
	FILE *fp = fopen( theCrabPath, "r" );
	if( fp )
	{
		printf("loading the crab from file status: ");
		gCrab = SAMPLE_NEW(Crab)(*this, theCrabPath, mManagedMaterials[MATERIAL_RED]);
		if (gCrab && !gCrab->getCrabBody())
		{
			delete gCrab;
			gCrab = NULL;
		}
		printf(gCrab ? "successful\n":"failed\n");						
		fclose (fp); 
	}

	if( !gCrab )
	{
		gCrab = SAMPLE_NEW(Crab)(*this, PxVec3(0, 50, 0), mManagedMaterials[MATERIAL_RED]);
		printf("crab file not found ... exporting crab file\n");
		gCrab->save(theCrabPath);
	}
	
	PX_ASSERT( gCrab );
	mCrabs.push_back(gCrab);

	static const PxU32 numCrabs = 3;
	for(PxU32 i = 0; i < numCrabs; i++)
	{
		Crab* crab = SAMPLE_NEW(Crab)(*this, PxVec3(getSampleRandom().rand(-20.0f,20.0f), 50, getSampleRandom().rand(-20.0f,20.0f)), mManagedMaterials[MATERIAL_RED]);
		mCrabs.push_back(crab);
	}
}
void Cct::findTouchedGeometry(
	const InternalCBData_FindTouchedGeom* userData,
	const PxExtendedBounds3& worldBounds,		// ### we should also accept other volumes

	TriArray& worldTriangles,
	IntArray& triIndicesArray,
	IntArray& geomStream,

	const CCTFilter& filter,
	const CCTParams& params)
{
	PX_ASSERT(userData);
	
	const PxInternalCBData_FindTouchedGeom* internalData = static_cast<const PxInternalCBData_FindTouchedGeom*>(userData);
	PxScene* scene = internalData->scene;
	Cm::RenderBuffer* renderBuffer = internalData->renderBuffer;

	PxExtendedVec3 Origin;	// Will be TouchedGeom::mOffset
	getCenter(worldBounds, Origin);

	// Find touched *boxes* i.e. touched objects' AABBs in the world
	// We collide against dynamic shapes too, to get back dynamic boxes/etc
	// TODO: add active groups in interface!
	PxSceneQueryFilterFlags sqFilterFlags;
	if(filter.mStaticShapes)	sqFilterFlags |= PxSceneQueryFilterFlag::eSTATIC;
	if(filter.mDynamicShapes)	sqFilterFlags |= PxSceneQueryFilterFlag::eDYNAMIC;
	if(filter.mFilterCallback)
	{
		if(filter.mPreFilter)
			sqFilterFlags |= PxSceneQueryFilterFlag::ePREFILTER;
		if(filter.mPostFilter)
			sqFilterFlags |= PxSceneQueryFilterFlag::ePOSTFILTER;
	}

	// ### this one is dangerous
	const PxBounds3 tmpBounds(toVec3(worldBounds.minimum), toVec3(worldBounds.maximum));	// LOSS OF ACCURACY

	// PT: unfortunate conversion forced by the PxGeometry API
	PxVec3 center = tmpBounds.getCenter(), extents = tmpBounds.getExtents();

	PxShape* hits[100];
	PxU32 size = 100;

	const PxSceneQueryFilterData sceneQueryFilterData = filter.mFilterData ? PxSceneQueryFilterData(*filter.mFilterData, sqFilterFlags) : PxSceneQueryFilterData(sqFilterFlags);

	PxI32 numberHits = scene->overlapMultiple(PxBoxGeometry(extents), PxTransform(center), hits, size, sceneQueryFilterData, filter.mFilterCallback);
	
	for(PxI32 i = 0; i < numberHits; i++)
	{
		PxShape* shape = hits[i];
		if(shape == NULL)
			continue;

		// Filtering

		// Discard all CCT shapes, i.e. kinematic actors we created ourselves. We don't need to collide with them since they're surrounded
		// by the real CCT volume - and collisions with those are handled elsewhere. We use the userData field for filtering because that's
		// really our only valid option (filtering groups are already used by clients and we don't have control over them, clients might
		// create other kinematic actors that we may want to keep here, etc, etc)
		if(internalData->cctShapeHashSet->contains(shape))
			continue;

		// Ubi (EA) : Discarding Triggers :
		if(shape->getFlags() & PxShapeFlag::eTRIGGER_SHAPE)
			continue;

		// PT: here you might want to disable kinematic objects.

		// Output shape to stream
		const PxTransform globalPose = getShapeGlobalPose(*shape);

		const PxGeometryType::Enum type = shape->getGeometryType();	// ### VIRTUAL!
		if(type==PxGeometryType::eSPHERE)				outputSphereToStream(shape, globalPose, geomStream, Origin);
		else	if(type==PxGeometryType::eCAPSULE)		outputCapsuleToStream(shape, globalPose, geomStream, Origin);
		else	if(type==PxGeometryType::eBOX)			outputBoxToStream(shape, globalPose, geomStream, worldTriangles, triIndicesArray, Origin, tmpBounds, params, renderBuffer);
		else	if(type==PxGeometryType::eTRIANGLEMESH)	outputMeshToStream(shape, globalPose, geomStream, worldTriangles, triIndicesArray, Origin, tmpBounds, params, renderBuffer);
		else	if(type==PxGeometryType::eHEIGHTFIELD)	outputHeightFieldToStream(shape, globalPose, geomStream, worldTriangles, triIndicesArray, Origin, tmpBounds, params, renderBuffer);
		else	if(type==PxGeometryType::eCONVEXMESH)	outputConvexToStream(shape, globalPose, geomStream, worldTriangles, triIndicesArray, Origin, tmpBounds);
		else	if(type==PxGeometryType::ePLANE)		outputPlaneToStream(shape, globalPose, geomStream, worldTriangles, triIndicesArray, Origin, tmpBounds, params, renderBuffer);
	}
}
void SimulationEventCallback::destroyWallBlock(const PxRigidBody& _krRigidBody, const PxShape& _krShape)
{
	Entity* wallBlock = static_cast<Entity*>(_krRigidBody.userData);
	if (find(m_destroyedWallBlocks.begin(), m_destroyedWallBlocks.end(), wallBlock) != m_destroyedWallBlocks.end())
	{
		return;
	}

	PxBoxGeometry geometry;
	_krShape.getBoxGeometry(geometry);

	PxTransform transform = _krRigidBody.getGlobalPose();
	Matrix44 transformation = PhysXMatrix::toMatrix44(transform);

	PxVec3 angularVelocity = _krRigidBody.getAngularVelocity();
	PxVec3 linearVelocity = _krRigidBody.getLinearVelocity();

	m_destroyedWallBlocks.push_back(wallBlock);
	GazEngine::removeEntity(*wallBlock);

	float halfSize = geometry.halfExtents.x / 2.0f;

	Matrix44 fragment0Transformation = transformation;
	getTranslation3(fragment0Transformation) += Vector3(-halfSize, halfSize, 0.0f);
	Entity* pFragment0 = CreateWallBlock(fragment0Transformation, halfSize, *m_pParentNode);
	PxRigidBody* pFragment0RigidBody = pFragment0->getSingleComponent<PhysXBody>()->getActor()->isRigidBody();
	pFragment0RigidBody->setAngularVelocity(angularVelocity);
	pFragment0RigidBody->setLinearVelocity(linearVelocity);
	// The body only got a position in the constructor... lets give it a rotation too.
	PxTransform fragment0Transform = transform;
	fragment0Transform.p += PxVec3(-halfSize, halfSize, 0.0f);
	pFragment0RigidBody->setGlobalPose(fragment0Transform);

	Matrix44 fragment1Transformation = transformation;
	getTranslation3(fragment1Transformation) += Vector3(halfSize, halfSize, 0.0f);
	Entity* pFragment1 = CreateWallBlock(fragment1Transformation, halfSize, *m_pParentNode);
	PxRigidBody* pFragment1RigidBody = pFragment1->getSingleComponent<PhysXBody>()->getActor()->isRigidBody();
	pFragment1RigidBody->setAngularVelocity(angularVelocity);
	pFragment1RigidBody->setLinearVelocity(linearVelocity);
	// The body only got a position in the constructor... lets give it a rotation too.
	PxTransform fragment1Transform = transform;
	fragment1Transform.p += PxVec3(halfSize, halfSize, 0.0f);
	pFragment1RigidBody->setGlobalPose(fragment1Transform);

	Matrix44 fragment2Transformation = transformation;
	getTranslation3(fragment2Transformation) += Vector3(halfSize, -halfSize, 0.0f);
	Entity* pFragment2 = CreateWallBlock(fragment2Transformation, halfSize, *m_pParentNode);
	PxRigidBody* pFragment2RigidBody = pFragment2->getSingleComponent<PhysXBody>()->getActor()->isRigidBody();
	pFragment2RigidBody->setAngularVelocity(angularVelocity);
	pFragment2RigidBody->setLinearVelocity(linearVelocity);
	// The body only got a position in the constructor... lets give it a rotation too.
	PxTransform fragment2Transform = transform;
	fragment2Transform.p += PxVec3(halfSize, -halfSize, 0.0f);
	pFragment2RigidBody->setGlobalPose(fragment2Transform);

	Matrix44 fragment3Transformation = transformation;
	getTranslation3(fragment3Transformation) += Vector3(-halfSize, -halfSize, 0.0f);
	Entity* pFragment3 = CreateWallBlock(fragment3Transformation, halfSize, *m_pParentNode);
	PxRigidBody* pFragment3RigidBody = pFragment3->getSingleComponent<PhysXBody>()->getActor()->isRigidBody();
	pFragment3RigidBody->setAngularVelocity(angularVelocity);
	pFragment3RigidBody->setLinearVelocity(linearVelocity);
	// The body only got a position in the constructor... lets give it a rotation too.
	PxTransform fragment3Transform = transform;
	fragment3Transform.p += PxVec3(-halfSize, -halfSize, 0.0f);
	pFragment3RigidBody->setGlobalPose(fragment3Transform);
}