Beispiel #1
0
void Apex::LoadDynamicTriangleMesh(int numVerts, PxVec3* verts, ObjectInfo info)
{
	PxRigidDynamic* meshActor = mPhysics->createRigidDynamic(PxTransform::createIdentity());
	PxShape* meshShape, *convexShape;
	if(meshActor)
	{
		//meshActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);

		PxTriangleMeshDesc meshDesc;
		meshDesc.points.count           = numVerts;
		meshDesc.points.stride          = sizeof(PxVec3);
		meshDesc.points.data            = verts;

		//meshDesc.triangles.count        = numInds/3.;
		//meshDesc.triangles.stride       = 3*sizeof(int);
		//meshDesc.triangles.data         = inds;

		PxToolkit::MemoryOutputStream writeBuffer;
		bool status = mCooking->cookTriangleMesh(meshDesc, writeBuffer);
		if(!status)
			return;

		PxToolkit::MemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize());

		PxTriangleMeshGeometry triGeom;
		triGeom.triangleMesh = mPhysics->createTriangleMesh(readBuffer);
		//triGeom.scale = PxMeshScale(PxVec3(info.sx,info.sy,info.sz),physx::PxQuat::createIdentity());
		
		meshShape = meshActor->createShape(triGeom, *defaultMaterial);
		//meshShape->setLocalPose(PxTransform(PxVec3(info.x,info.y,info.z)));
		meshShape->setFlag(PxShapeFlag::eUSE_SWEPT_BOUNDS, true);

		PxConvexMeshDesc convexDesc;
		convexDesc.points.count     = numVerts;
		convexDesc.points.stride    = sizeof(PxVec3);
		convexDesc.points.data      = verts;
		convexDesc.flags            = PxConvexFlag::eCOMPUTE_CONVEX;

		if(!convexDesc.isValid())
			return;
		PxToolkit::MemoryOutputStream buf;
		if(!mCooking->cookConvexMesh(convexDesc, buf))
			return;
		PxToolkit::MemoryInputData input(buf.getData(), buf.getSize());
		PxConvexMesh* convexMesh = mPhysics->createConvexMesh(input);
		PxConvexMeshGeometry convexGeom = PxConvexMeshGeometry(convexMesh);
		convexShape = meshActor->createShape(convexGeom, *defaultMaterial);
		//convexShape->setLocalPose(PxTransform(PxVec3(info.x,info.y,info.z)));
		//convexShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);

		
		convexShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);
		meshShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
		meshActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, false);

		meshActor->setGlobalPose(PxTransform(PxVec3(info.x,info.y,info.z), PxQuat(info.ry, PxVec3(0.0f,1.0f,0.0f))));
		mScene[mCurrentScene]->addActor(*meshActor);
		dynamicActors.push_back(meshActor);
	}
}
void 
Spacetime::restoreState(void) {
	for (int i = 0; i < dynamic_actors.size(); i++) {
		PxRigidDynamic *current = dynamic_actors[i];
		current->setLinearVelocity(linearVelocityVector[i]);
		current->setAngularVelocity(angularVelocityVector[i]);
		current->setGlobalPose(globalPoseVector[i]);
	}
}
void UDestructibleComponent::OnUpdateTransform(bool bSkipPhysicsMove)
{
	// We are handling the physics move below, so don't handle it at higher levels
	Super::OnUpdateTransform(true);

	if (SkeletalMesh == NULL)
	{
		return;
	}

	if (!bPhysicsStateCreated || bSkipPhysicsMove)
	{
		return;
	}

	const FTransform& CurrentLocalToWorld = ComponentToWorld;

	if(CurrentLocalToWorld.ContainsNaN())
	{
		return;
	}

	// 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("UDestructibleComponent::SendPhysicsTransform : Non-uniform scale factor (%s) can cause physics to mismatch for %s  SkelMesh: %s"), *MeshScale3D.ToString(), *GetFullName(), SkeletalMesh ? *SkeletalMesh->GetFullName() : TEXT("NULL"));
	}
#endif

#if WITH_APEX
	if (ApexDestructibleActor)
	{
		PxRigidDynamic* PRootActor = ApexDestructibleActor->getChunkPhysXActor(0);
		PxMat44 GlobalPose(PxMat33(U2PQuat(CurrentLocalToWorld.GetRotation())), U2PVector(CurrentLocalToWorld.GetTranslation()));
		if(!PRootActor || PRootActor->getScene())	//either root chunk is null meaning fractured (so there's a scene), or the root has a scene
		{
			ApexDestructibleActor->setGlobalPose(GlobalPose);
		}else
		{
			PRootActor->setGlobalPose(PxTransform(GlobalPose));	//we're not in a scene yet, so place the root actor in this new position
		}
	}
#endif // #if WITH_APEX
}
void PhysicsEngine::createVehicle(Vehicle* vehicle, PxTransform transform)
{
	VehicleTuning* tuning = &vehicle->tuning;
	tuningFromUserTuning(vehicle);
	
	PxVehicleDrive4W* physVehicle = vehCreator->createVehicle4W(vehicle);
	//PxTransform startTransform(PxVec3(0, (tuning->chassisDims.y*0.5f + tuning->wheelRadius + 1.0f), 0), PxQuat(PxIdentity));
	PxRigidDynamic* actor = physVehicle->getRigidDynamicActor();

	actor->setGlobalPose(transform);
	scene->addActor(*actor);

	physVehicle->setToRestState();
	physVehicle->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
	physVehicle->mDriveDynData.setUseAutoGears(true);
	
	vehicle->setActor(actor);
	vehicle->setPhysicsVehicle(physVehicle);
	actor->userData = vehicle;

	vehicles.push_back(physVehicle);
}
void
Spacetime::setState(matrix<double> stateVector) {
	std::vector<PxQuat> theta;
	for (int i = 0; i < joints.size(); i++) {
		PxQuat q = PxQuat::createIdentity();
		if (i == 0) {
			if (DOF > X) { q *= PxQuat(stateVector((i)*DOF+X,0), PxVec3(1,0,0)); }
			if (DOF > Y) { q *= PxQuat(stateVector((i)*DOF+Y,0), PxVec3(0,1,0)); }
			if (DOF > Z) { q *= PxQuat(stateVector((i)*DOF+Z,0), PxVec3(0,0,1)); }
		} else {
			if (DOF > X) { q *= PxQuat(stateVector((i)*DOF+X,0), PxVec3(1,0,0)) * theta[(i-1)*DOF+X]; }
			if (DOF > Y) { q *= PxQuat(stateVector((i)*DOF+Y,0), PxVec3(0,1,0)) * theta[(i-1)*DOF+Y]; }
			if (DOF > Z) { q *= PxQuat(stateVector((i)*DOF+Z,0), PxVec3(0,0,1)) * theta[(i-1)*DOF+Z]; }
		}
		theta.push_back(q);
	}
	dynamic_actors[0]->setGlobalPose(PxTransform(root, PxQuat::createIdentity()));
	PxVec3 lastJointPos = dynamic_actors[0]->getGlobalPose().p + PxVec3(0,0.5,0);
	PxQuat lastJointRot = dynamic_actors[0]->getGlobalPose().q;
	for (int i = 0; i < joints.size(); i++) {
		PxRigidDynamic *current = dynamic_actors[i+1];
		PxVec3 t = theta[i].rotate(-joint_local_positions[i]);
		PxVec3 gPos = lastJointPos + t;
		current->setGlobalPose(PxTransform(gPos, theta[i]));
		lastJointPos = lastJointPos + 2*t;
	}
	for (int i = 0; i < joints.size(); i++) {
		PxRigidDynamic *current = dynamic_actors[i+1];
		PxVec3 angularVelocity;
		if (DOF > X) { angularVelocity[X] = stateVector(joints.size()*DOF + i*DOF+X,0); }
		else		 { angularVelocity[X] = 0.0; }
		if (DOF > Y) { angularVelocity[Y] = stateVector(joints.size()*DOF + i*DOF+Y,0); }
		else		 { angularVelocity[Y] = 0.0; }
		if (DOF > Z) { angularVelocity[Z] = stateVector(joints.size()*DOF + i*DOF+Z,0); }
		else		 { angularVelocity[Z] = 0.0; }
		current->setAngularVelocity(angularVelocity);
		current->setLinearVelocity(PxVec3(0,0,0));
	}
}
Beispiel #6
0
bool CTank::CreateTankActor( CPhysX * pPhysX )
{
	if( !LoadData( "InitShader.lua" ) )
		return false;

// 	CParamTank* pParamTank = new CParamTank;
// 
// 	if( !CLua::LoadParamTank( "", &pParamTank ) )
// 	{
// 
// 	}

	if( GameObject * pBody = GetDetail( BODY ) )
	{
		if ( pBody->CreateTriangleMesh( pPhysX ) )
		{			
			pBody->Update( 0.f );
			
			PxTriangleMesh* triangleMesh = pBody->GetTriangleMesh();
			D3DXVECTOR3     Position     = pBody->GetPosition();
			//D3DXComputeBoundingBox(Vertices,  g_pMesh->GetNumVertices(),  FVFVertexSize, &pMin, &pMax);
			//PxRigidDynamic* pRigDynAct   = pPhysX->GetPhysics()->createRigidDynamic( PxTransform( physx::PxVec3( Position.x, Position.y, Position.z ) ) );
// 			PxRigidDynamic* pRigDynAct   = PxCreateDynamic( *pPhysX->GetPhysics(), PxTransform( physx::PxVec3( Position.x, Position.y, Position.z ) ), PxBoxGeometry( 14.f, 4.6f, 6.f ), *pMaterial, 1.f );
// 
// 			if( pRigDynAct && pMaterial && triangleMesh )
// 			{
// 				//pRigDynAct->createShape( PxTriangleMeshGeometry( triangleMesh ), *pMaterial );
// 				
// 				pRigDynAct->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, false);
// 				pRigDynAct->setActorFlag( PxActorFlag::eVISUALIZATION, true );
// 				pRigDynAct->setAngularDamping( 0.5f );
// 				//pRigDynAct->setMass( 10000.f );
// 				PxRigidBodyExt::updateMassAndInertia( *pRigDynAct, 10.f );
// 				
// 				if( pMaterial )
// 					pPhysX->PushMaterial( pMaterial );
// 				
// 				pPhysX->AddActorScene( pRigDynAct );
// 				m_pActor = pRigDynAct;
// 
// 				return true;
// 			}

			const int    nWheels     = 12;
			PxF32        chassisMass = 1500.f;
			const PxF32  wheelMass   = 50.f;			
			PxF32		 fShift      = -0.85f;
			PxVec3 wheelCentreOffsets[ nWheels ];

			for( int i = 0; i < nWheels/2; ++i )
			{
				wheelCentreOffsets[ i*2   ] = PxVec3( -1.2f, -0.5f,  2.1f + i * fShift );
				wheelCentreOffsets[ i*2+1 ] = PxVec3(  1.2f, -0.5f,  2.1f + i * fShift );				
			}

			// размеры корпуса
			const PxVec3 chassisDims( 2.4f, 1.f, 6.f );// = computeChassisAABBDimensions(chassisConvexMesh);

			// Начало координат находится в центре шасси сетки
			// Установить центр масс будет ниже этой точки
			const PxVec3 chassisCMOffset = PxVec3( 0.f, -chassisDims.y * 0.5f - 0.65f, 0.f );

			PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate( nWheels );
			PxVehicleWheelsSimData& wheelsData = *wheelsSimData;
			PxVehicleDriveSimData4W driveData;
			
			PxVec3 chassisMOI( (chassisDims.y*chassisDims.y + chassisDims.z * chassisDims.z) * chassisMass / 12.f,
							   (chassisDims.x*chassisDims.x + chassisDims.z * chassisDims.z) * chassisMass / 12.f,
							   (chassisDims.x*chassisDims.x + chassisDims.y * chassisDims.y) * chassisMass / 12.f);

			// структура шасси
			PxVehicleChassisData chassisData;
			
			chassisData.mMass	  = chassisMass;		// Масса транспортного средства жесткой актер тела
			chassisData.mMOI	  = chassisMOI;			// Момент инерции автомобиля жесткая актер тела.
			chassisData.mCMOffset = chassisCMOffset;	// Центр масс смещение автомобиля жесткая актер тела.

			// Немного настройки здесь.Автомобиль будет иметь более отзывчивым поворот, если мы сведем
			// у-компоненты шасси момента инерции.
			chassisMOI.y *= 0.8f;

			const PxF32 massRear  = 0.5f * chassisMass * ( chassisDims.z - 3 * chassisCMOffset.z ) / chassisDims.z;
			const PxF32 massFront = massRear;

			//Extract the wheel radius and width from the wheel convex meshes
			PxF32 wheelWidths[ nWheels ] = {0.f};
			PxF32 wheelRadii[ nWheels ]  = {0.f};
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				 wheelWidths[ i ] = 0.5f;
				 wheelRadii [ i ] = 0.32f;
			}

			// Теперь вычислим колеса массы и инерции компонентов вокруг оси оси			
			PxF32 wheelMOIs[ nWheels ];
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				wheelMOIs[ i ] = 0.5f * wheelMass * wheelRadii[ i ] * wheelRadii[ i ];
			}

			// Давайте создадим структуру данных колеса теперь с радиусом, массы и МВД
			PxVehicleWheelData wheels[ nWheels ];
			for(PxU32 i = 0; i < nWheels; ++i )
			{
				wheels[ i ].mRadius				= wheelRadii[ i ];		// Радиус блок, который включает в себя колеса металл плюс резиновые шины
				wheels[ i ].mMass				= wheelMass;			// Масса колеса плюс шины
				wheels[ i ].mMOI				= wheelMOIs[ i ];		// Момент инерции колеса
				wheels[ i ].mWidth				= wheelWidths[ i ];		// Максимальная ширина блок, который включает в себя колеса плюс шин
				//wheels[ i ].mMaxHandBrakeTorque = 0.f;					// Отключение стояночного тормоза от передних колес и позволяют для задних колес
				//wheels[ i ].mMaxSteer			= 0.f;					// Включить рулевого управления для передних колес и отключить для передних колес
				//wheels[ i ].mDampingRate		= 1.f;				// Скорость затухания описывает скорость, с которой свободно вращающееся колесо теряет скорость вращения
			}

			//Let's set up the tire data structures now.
			//Put slicks on the front tires and wets on the rear tires.
			PxVehicleTireData tires[ nWheels ];

			for(PxU32 i = 0; i < nWheels; ++i )
			{				
				tires[ i ].mType = 1;			// тип сцепления шин с поверхностью
			}

			// Структура данных подвески
			PxVehicleSuspensionData susps[ nWheels ];

			for( PxU32 i = 0; i < nWheels; i++ )
			{
				susps[ i ].mMaxCompression	 = 0.03f;				// Максимальное сжатие пружинной подвески
				susps[ i ].mMaxDroop		 = 0.03f;				// Максимальное удлинение пружинной подвески
				susps[ i ].mSpringStrength	 = 20000.f;	// пружинная сила подвески блока
				susps[ i ].mSpringDamperRate = 500.f;
				susps[ i ].mSprungMass		 = chassisMass / nWheels;	// Масса транспортного средства, которая поддерживается пружинная подвеска, указанных в кг.
			}
			
			PxVec3 suspTravelDirections[ nWheels ];
			PxVec3 wheelCentreCMOffsets[ nWheels ];
			PxVec3 suspForceAppCMOffsets[ nWheels ];
			PxVec3 tireForceAppCMOffsets[ nWheels ];

			for( PxU32 i = 0 ; i < nWheels; ++i )
			{
				wheelCentreCMOffsets [ i ] = wheelCentreOffsets[ i ] - chassisCMOffset;
				suspForceAppCMOffsets[ i ] = PxVec3( wheelCentreCMOffsets[ i ].x, -0.3f, wheelCentreCMOffsets[ i ].z );
				tireForceAppCMOffsets[ i ] = PxVec3( wheelCentreCMOffsets[ i ].x, -0.3f, wheelCentreCMOffsets[ i ].z );
				suspTravelDirections [ i ] = PxVec3( 0, -1, 0 );	// направление подвески
			}

			// Теперь добавьте колеса, шины и подвеска данных
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				wheelsData.setWheelData( i, wheels[ i ] );								// установить данные колеса
				wheelsData.setTireData( i, tires[ i ] );								// Установите шину данных колеса
				wheelsData.setSuspensionData( i, susps[ i ] );							// Установите подвеску данные колеса
				wheelsData.setSuspTravelDirection( i, suspTravelDirections[ i ] );		// Установить направление движения подвески колес
				wheelsData.setWheelCentreOffset( i, wheelCentreCMOffsets[ i ] );		// Установить смещение от центра жесткой тело массой в центре колеса
				wheelsData.setSuspForceAppPointOffset( i, suspForceAppCMOffsets[ i ] );	// Установить приложение точкой подвески силу подвески колес
				wheelsData.setTireForceAppPointOffset( i, tireForceAppCMOffsets[ i ] );	// Установить приложение точку шин силу шинах колес
			}

			//Diff
			PxVehicleDifferential4WData diff;
			diff.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
			driveData.setDiffData( diff );

			//Engine
			PxVehicleEngineData engine;
			engine.mPeakTorque								= 300.f;	// максимальная скорость вращения двигателя
			engine.mMaxOmega								= 400.f;	// Максимальный крутящий момент доступен обратиться к двигателю
			engine.mDampingRateFullThrottle					= 0.15f;	// скорость затухания двигатель при полностью открытой дроссельной заслонке	
			engine.mDampingRateZeroThrottleClutchEngaged	= 8.f;		// скорость затухания двигатель при нулевой газ при включении сцепления
			engine.mDampingRateZeroThrottleClutchDisengaged	= 0.35f;	// Краткие скорость затухания двигатель при нулевой газ при выключенном сцеплении (на нейтральной передаче)

			driveData.setEngineData( engine );

			//Gears
			PxVehicleGearsData gears;
			gears.mSwitchTime = 0.5f;
			driveData.setGearsData( gears );

			// Прочность сцепления
			PxVehicleClutchData clutch;
			clutch.mStrength = PxVehicleGearsData::eMAX_NUM_GEAR_RATIOS;
			driveData.setClutchData( clutch );

			//Ackermann steer accuracy
			PxVehicleAckermannGeometryData ackermann;
			ackermann.mAccuracy		  = 0.1f;
			ackermann.mAxleSeparation = wheelCentreOffsets[ 0 ].z - wheelCentreOffsets[ nWheels - 1 ].z;	// Расстояние между центром передней оси и центром задней оси
			ackermann.mFrontWidth	  = wheelCentreOffsets[ 0 ].x - wheelCentreOffsets[ 1		    ].x;	// Расстояние между центральной точке два передних колеса
			ackermann.mRearWidth	  = wheelCentreOffsets[ nWheels - 2 ].x - wheelCentreOffsets[ nWheels - 1 ].x;	// Расстояние между центральной точке два задних колеса
			driveData.setAckermannGeometryData(ackermann);			
			
			PxTriangleMesh * pTriangleMesh = 0;
			D3DXVECTOR3      vPosition;

			if( GameObject * pRoller = GetDetail( WHEEL_LEFT_1ST ) )
			{
				if( pRoller->CreateTriangleMesh( pPhysX ) )
				{
					pRoller->Update( 0.f );					
					pTriangleMesh = pRoller->GetTriangleMesh();
					Position      = pRoller->GetPosition();
				}
			}

			// Нам нужно добавить колеса столкновения форм, их местный позы, материал для колес, и моделирование фильтра для колес
			PxTriangleMeshGeometry WheelGeom( pTriangleMesh );
			
			PxGeometry* wheelGeometries[ nWheels ] = {0};
			PxTransform wheelLocalPoses[ nWheels ];

			for( PxU32 i = 0; i < nWheels; ++i )
			{
				wheelGeometries[ i ] = &WheelGeom;
				wheelLocalPoses[ i ] = PxTransform::createIdentity();
			}
			
			PxMaterial* pMaterial = pPhysX->GetPhysics()->createMaterial( 0.5f, 0.5f, 0.1f );    //коэффициенты трения скольжения и покоя(Dynamic friction,Static friction), коэффициент упругости
			const PxMaterial& wheelMaterial	= *pMaterial;
			PxFilterData wheelCollFilterData;

			wheelCollFilterData.word0 = COLLISION_FLAG_WHEEL;
			wheelCollFilterData.word1 = COLLISION_FLAG_WHEEL_AGAINST;

			// Нам нужно добавить шасси столкновения форм, их местный позы, материала для шасси и моделирования фильтр для шасси.
			//PxBoxGeometry chassisConvexGeom( 1.5f, 0.3f, 4.f );
			PxBoxGeometry chassisConvexGeom( chassisDims.x/2, chassisDims.y/2, chassisDims.z/2 );

			const PxGeometry* chassisGeoms	    = &chassisConvexGeom;
			const PxTransform chassisLocalPoses = PxTransform::createIdentity();
			const PxMaterial& chassisMaterial	= *pMaterial;

			PxFilterData chassisCollFilterData;
			chassisCollFilterData.word0 = COLLISION_FLAG_CHASSIS;
			chassisCollFilterData.word1 = COLLISION_FLAG_CHASSIS_AGAINST;

			// Создание фильтра запроса данных для автомобилей, чтобы машины не пытайтесь ездить на себя.
			PxFilterData vehQryFilterData;			
			SampleVehicleSetupVehicleShapeQueryFilterData( &vehQryFilterData );

			PxRigidDynamic* vehActor = pPhysX->GetPhysics()->createRigidDynamic( PxTransform::createIdentity() );

			//Add all the wheel shapes to the actor.
			for( PxU32 i = 0; i < nWheels; ++i )
			{
				PxShape* wheelShape=vehActor->createShape( *wheelGeometries[ i ], wheelMaterial );
				wheelShape->setQueryFilterData( vehQryFilterData );
				wheelShape->setSimulationFilterData( wheelCollFilterData );
				wheelShape->setLocalPose( wheelLocalPoses[ i ] );
				wheelShape->setFlag( PxShapeFlag::eSIMULATION_SHAPE, true );
			}

			//Add the chassis shapes to the actor			
			PxShape* chassisShape = vehActor->createShape( *chassisGeoms, chassisMaterial );
			chassisShape->setQueryFilterData( vehQryFilterData );
			chassisShape->setSimulationFilterData( chassisCollFilterData );
			chassisShape->setLocalPose( PxTransform( physx::PxVec3( 0, 0, 0 ) ) );
			

			vehActor->setMass( chassisData.mMass );
			vehActor->setMassSpaceInertiaTensor( chassisData.mMOI );
			vehActor->setCMassLocalPose( PxTransform( chassisData.mCMOffset, PxQuat::createIdentity() ) );
			vehActor->setGlobalPose( PxTransform( physx::PxVec3( 0, 8, 0 ), PxQuat::createIdentity() ) );

			PxVehicleDriveTank* pTank = PxVehicleDriveTank::allocate( nWheels );
 			
 			pTank->setup( pPhysX->GetPhysics(), vehActor, *wheelsSimData, driveData, nWheels );			
			pPhysX->AddActorScene( vehActor );
			m_pActor = vehActor;
			pPhysX->AddTank( pTank );

			//Free the sim data because we don't need that any more.
			wheelsSimData->free();
			//pTank->setDriveModel( PxVehicleDriveTank::eDRIVE_MODEL_SPECIAL );
			pTank->setToRestState();			
			pTank->mDriveDynData.setUseAutoGears( true );

			return true;
		}
	}

	return false;
}
void USkeletalMeshComponent::UpdateKinematicBonesToAnim(const TArray<FTransform>& InSpaceBases, ETeleportType Teleport, bool bNeedsSkinning)
{
	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 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);
		}
	}

	// 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 (bTeleport || (BodyInst->IsValidBodyInstance() && !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.ContainsNaN())
						{
							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());
							continue;
						}					

						// If kinematic and not teleporting, set kinematic target
						PxRigidDynamic* PRigidDynamic = BodyInst->GetPxRigidDynamic_AssumesLocked();
						if (!IsRigidBodyNonKinematic_AssumesLocked(PRigidDynamic) && !bTeleport)
						{
							PhysScene->SetKinematicTarget_AssumesLocked(BodyInst, BoneTransform, true);
						}
						// Otherwise, set global pose
						else
						{
							const PxTransform PNewPose = U2PTransform(BoneTransform);
							ensure(PNewPose.isValid());
							PRigidDynamic->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())
					{
						UE_LOG(LogPhysics, Warning, 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)
Beispiel #8
0
bool doRaycastCCD(PxShape* shape, PxTransform& newPose, PxVec3& newShapeCenter, const PxVec3& ccdWitness, const PxVec3& ccdWitnessOffset)
{
	PxRigidDynamic* dyna = canDoCCD(shape);
	if(!dyna)
		return true;

	bool updateCCDWitness = true;

	const PxVec3 offset = newPose.p - newShapeCenter;
//printf("CCD0: %f | %f | %f\n", newShapeCenter.x, newShapeCenter.y, newShapeCenter.z);
	const PxVec3& origin = ccdWitness;
//			const PxVec3& dest = newPose.p;
	const PxVec3& dest = newShapeCenter;

	PxVec3 dir = dest - origin;
	const PxReal length = dir.magnitude();
	if(length!=0.0f)
	{
		dir /= length;

		// Compute internal radius
//		PxVec3 localCenter;
		const PxReal internalRadius = computeInternalRadius(shape, dir, /*localCenter,*/ ccdWitnessOffset);

		// Compute distance to impact
		PxRaycastHit hit;
//		if(internalRadius!=0.0f && CCDRaycast(shape->getActor().getActiveScene(), origin + localCenter, dir, length, hit))
		if(internalRadius!=0.0f && CCDRaycast(shape->getActor().getScene(), origin, dir, length, hit))
		{
#ifdef RAYCAST_CCD_PRINT_DEBUG
			static int count=0;
			printf("CCD hit %d\n", count++);
#endif
			updateCCDWitness = false;
			const PxReal radiusLimit = internalRadius * 0.75f;
			if(hit.distance>radiusLimit)
			{
//				newPose.p = origin + dir * (hit.distance - radiusLimit);
				newShapeCenter = origin + dir * (hit.distance - radiusLimit);
#ifdef RAYCAST_CCD_PRINT_DEBUG
				printf("  Path0: %f | %f\n", hit.distance, radiusLimit);
#endif
			}
			else
			{
//				newPose.p = origin;
				newShapeCenter = origin;
//				newShapeCenter = origin + hit.normal * (radiusLimit - hit.distance);
#ifdef RAYCAST_CCD_PRINT_DEBUG
				printf("  Path1: %f\n", hit.distance);
#endif
			}

			{
				newPose.p = offset + newShapeCenter;
//newPose.p.y += 10.0f;
//printf("%f | %f | %f\n", newPose.p.x, newPose.p.y, newPose.p.z);

//				dyna->setGlobalPose(newPose);

				// newPose = actorGlobalPose * shapeLocalPose
				// newPose * inverse(shapeLocalPose) = actorGlobalPose

				const PxTransform shapeLocalPose = shape->getLocalPose();
				const PxTransform inverseShapeLocalPose = shapeLocalPose.getInverse();
				PxTransform newGlobalPose = newPose * inverseShapeLocalPose;
				dyna->setGlobalPose(newGlobalPose);
//dyna->setGlobalPose(newPose);
//printf("%f | %f | %f\n", newGlobalPose.p.x, newGlobalPose.p.y, newGlobalPose.p.z);
//printf("%f | %f | %f\n", shapeLocalPose.p.x, shapeLocalPose.p.y, shapeLocalPose.p.z);

/*PX_INLINE PxTransform PxShapeExt::getGlobalPose(const PxShape& shape)
{
PxRigidActor& ra = shape.getActor();

return ra.getGlobalPose() * shape.getLocalPose();
}*/
const PxVec3 testShapeCenter = getShapeCenter(shape, ccdWitnessOffset);
float d = (testShapeCenter - newShapeCenter).magnitude();
//printf("%f\n", d);
//printf("CCD1: %f | %f | %f\n", testShapeCenter.x, testShapeCenter.y, testShapeCenter.z);

//dyna->clearForce(PxForceMode::eFORCE);
//dyna->clearForce(PxForceMode::eIMPULSE);
//dyna->setLinearVelocity(PxVec3(0));	// PT: this helps the CCT but stops small objects dead, which doesn't look great

			}
		}
	}
	return updateCCDWitness;
}