bool UPrimitiveComponent::WeldToImplementation(USceneComponent * InParent, FName ParentSocketName /* = Name_None */, bool bWeldSimulatedChild /* = false */) { //WeldToInternal assumes attachment is already done if (AttachParent != InParent || AttachSocketName != ParentSocketName) { return false; } //Check that we can actually our own socket name FBodyInstance* BI = GetBodyInstance(NAME_None, false); if (BI == NULL) { return false; } if (BI->ShouldInstanceSimulatingPhysics() && bWeldSimulatedChild == false) { return false; } UnWeldFromParent(); //make sure to unweld from wherever we currently are FName SocketName; UPrimitiveComponent * RootComponent = GetRootWelded(this, ParentSocketName, &SocketName, true); if (RootComponent) { if (FBodyInstance* RootBI = RootComponent->GetBodyInstance(SocketName, false)) { if (BI->WeldParent == RootBI) //already welded so stop { return true; } BI->bWelded = true; //There are multiple cases to handle: //Root is kinematic, simulated //Child is kinematic, simulated //Child always inherits from root //if root is kinematic simply set child to be kinematic and we're done if (RootComponent->IsSimulatingPhysics(SocketName) == false) { BI->WeldParent = NULL; SetSimulatePhysics(false); return false; //return false because we need to continue with regular body initialization } //root is simulated so we actually weld the body FTransform RelativeTM = RootComponent == AttachParent ? GetRelativeTransform() : GetComponentToWorld().GetRelativeTransform(RootComponent->GetComponentToWorld()); //if direct parent we already have relative. Otherwise compute it RootBI->Weld(BI, GetComponentToWorld()); BI->WeldParent = RootBI; return true; } } return false; }
FBodyInstance* UPhysicsConstraintComponent::GetBodyInstance(EConstraintFrame::Type Frame) const { FBodyInstance* Instance = NULL; UPrimitiveComponent* PrimComp = GetComponentInternal(Frame); if(PrimComp != NULL) { if(Frame == EConstraintFrame::Frame1) { Instance = PrimComp->GetBodyInstance(ConstraintInstance.ConstraintBone1); } else { Instance = PrimComp->GetBodyInstance(ConstraintInstance.ConstraintBone2); } } return Instance; }
bool UGripMotionControllerComponent::TeleportMoveGrippedActor(AActor * GrippedActorToMove) { if (!GrippedActorToMove || !GrippedActors.Num()) return false; FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); for (int i = GrippedActors.Num() - 1; i >= 0; --i) { if (GrippedActors[i].Actor == GrippedActorToMove) { // GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up // Not sure whats wrong with the function but I might want to push a patch out eventually WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform); // Need to use WITH teleport for this function so that the velocity isn't updated and without sweep so that they don't collide GrippedActors[i].Actor->SetActorTransform(WorldTransform, false, NULL, ETeleportType::TeleportPhysics); FBPActorPhysicsHandleInformation * Handle = GetPhysicsGrip(GrippedActors[i]); if (Handle && Handle->KinActorData) { { PxScene* PScene = GetPhysXSceneFromIndex(Handle->SceneIndex); if (PScene) { SCOPED_SCENE_WRITE_LOCK(PScene); Handle->KinActorData->setKinematicTarget(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); } } //Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); UPrimitiveComponent *root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent()); if (root) { FBodyInstance * body = root->GetBodyInstance(); if (body) { body->SetBodyTransform(WorldTransform, ETeleportType::TeleportPhysics); } } } return true; } } return false; }
UPrimitiveComponent * GetRootWelded(const UPrimitiveComponent* PrimComponent, FName ParentSocketName = NAME_None, FName* OutSocketName = NULL, bool bAboutToWeld = false) { UPrimitiveComponent * Result = NULL; UPrimitiveComponent * RootComponent = Cast<UPrimitiveComponent>(PrimComponent->AttachParent); //we must find the root component along hierarchy that has bWelded set to true //check that body itself is welded if (FBodyInstance* BI = PrimComponent->GetBodyInstance(ParentSocketName, false)) { if (bAboutToWeld == false && BI->bWelded == false && BI->bAutoWeld == false) //we're not welded and we aren't trying to become welded { return NULL; } } FName PrevSocketName = ParentSocketName; FName SocketName = NAME_None; //because of skeletal mesh it's important that we check along the bones that we attached FBodyInstance* RootBI = NULL; for (; RootComponent; RootComponent = Cast<UPrimitiveComponent>(RootComponent->AttachParent)) { Result = RootComponent; SocketName = PrevSocketName; PrevSocketName = RootComponent->AttachSocketName; RootBI = RootComponent->GetBodyInstance(SocketName, false); if (RootBI && RootBI->bWelded) { continue; } break; } if (OutSocketName) { *OutSocketName = SocketName; } return Result; }
void UPrimitiveComponent::UnWeldFromParent() { FBodyInstance* NewRootBI = GetBodyInstance(NAME_None, false); UWorld* CurrentWorld = GetWorld(); if (NewRootBI == NULL || NewRootBI->bWelded == false || CurrentWorld == nullptr || IsPendingKill()) { return; } FName SocketName; UPrimitiveComponent * RootComponent = GetRootWelded(this, AttachSocketName, &SocketName); if (RootComponent) { if (FBodyInstance* RootBI = RootComponent->GetBodyInstance(SocketName, false)) { bool bRootIsBeingDeleted = RootComponent->HasAnyFlags(RF_PendingKill) || RootComponent->HasAnyFlags(RF_Unreachable); if (!bRootIsBeingDeleted) { //create new root RootBI->UnWeld(NewRootBI); //don't bother fixing up shapes if RootComponent is about to be deleted } NewRootBI->bWelded = false; const FBodyInstance* PrevWeldParent = NewRootBI->WeldParent; NewRootBI->WeldParent = nullptr; bool bHasBodySetup = GetBodySetup() != nullptr; //if BodyInstance hasn't already been created we need to initialize it if (bHasBodySetup && NewRootBI->IsValidBodyInstance() == false) { bool bPrevAutoWeld = NewRootBI->bAutoWeld; NewRootBI->bAutoWeld = false; NewRootBI->InitBody(GetBodySetup(), GetComponentToWorld(), this, CurrentWorld->GetPhysicsScene()); NewRootBI->bAutoWeld = bPrevAutoWeld; } if(PrevWeldParent == nullptr) //our parent is kinematic so no need to do any unwelding/rewelding of children { return; } //now weld its children to it TArray<FBodyInstance*> ChildrenBodies; TArray<FName> ChildrenLabels; GetWeldedBodies(ChildrenBodies, ChildrenLabels); for (int32 ChildIdx = 0; ChildIdx < ChildrenBodies.Num(); ++ChildIdx) { FBodyInstance* ChildBI = ChildrenBodies[ChildIdx]; if (ChildBI != NewRootBI) { if (!bRootIsBeingDeleted) { RootBI->UnWeld(ChildBI); } //At this point, NewRootBI must be kinematic because it's being unwelded. It's up to the code that simulates to call Weld on the children as needed ChildBI->WeldParent = nullptr; //null because we are currently kinematic } } } } }
void UGripMotionControllerComponent::PostTeleportMoveGrippedActors() { if (!GrippedActors.Num()) return; FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); for (int i = GrippedActors.Num() - 1; i >= 0; --i) { // GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up // Not sure whats wrong with the function but I might want to push a patch out eventually WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform); if (GrippedActors[i].Actor) { // Need to use WITH teleport for this function so that the velocity isn't updated and without sweep so that they don't collide GrippedActors[i].Actor->SetActorTransform(WorldTransform, false, NULL, ETeleportType::TeleportPhysics); } else if (GrippedActors[i].Component) { // Need to use WITH teleport for this function so that the velocity isn't updated and without sweep so that they don't collide GrippedActors[i].Component->SetWorldTransform(WorldTransform, false, NULL, ETeleportType::TeleportPhysics); } FBPActorPhysicsHandleInformation * Handle = GetPhysicsGrip(GrippedActors[i]); if (Handle && Handle->KinActorData) { { PxScene* PScene = GetPhysXSceneFromIndex(Handle->SceneIndex); if (PScene) { SCOPED_SCENE_WRITE_LOCK(PScene); Handle->KinActorData->setKinematicTarget(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); } } //Handle->KinActorData->setGlobalPose(PxTransform(U2PVector(WorldTransform.GetLocation()), Handle->KinActorData->getGlobalPose().q)); if (GrippedActors[i].Actor) { UPrimitiveComponent *root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent()); if (root) { FBodyInstance * body = root->GetBodyInstance(); if (body) { body->SetBodyTransform(WorldTransform, ETeleportType::TeleportPhysics); } } } else if (GrippedActors[i].Component) { FBodyInstance * body = GrippedActors[i].Component->GetBodyInstance(); if (body) { body->SetBodyTransform(WorldTransform, ETeleportType::TeleportPhysics); } } } /*else { if (bIsServer) { DestroyPhysicsHandle(GrippedActors[i]); GrippedActors.RemoveAt(i); // If it got garbage collected then just remove the pointer, won't happen with new uproperty use, but keeping it here anyway } }*/ } }
bool UGripMotionControllerComponent::SetUpPhysicsHandle(const FBPActorGripInformation &NewGrip) { UPrimitiveComponent *root = NewGrip.Component; if(!root) root = Cast<UPrimitiveComponent>(NewGrip.Actor->GetRootComponent()); if (!root) return false; // Needs to be simulating in order to run physics root->SetSimulatePhysics(true); root->SetEnableGravity(false); FBPActorPhysicsHandleInformation * HandleInfo = CreatePhysicsGrip(NewGrip); #if WITH_PHYSX // Get the PxRigidDynamic that we want to grab. FBodyInstance* BodyInstance = root->GetBodyInstance(NAME_None/*InBoneName*/); if (!BodyInstance) { return false; } ExecuteOnPxRigidDynamicReadWrite(BodyInstance, [&](PxRigidDynamic* Actor) { PxScene* Scene = Actor->getScene(); // Get transform of actor we are grabbing FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); WorldTransform = NewGrip.RelativeTransform.GetRelativeTransform(InverseTransform); PxVec3 KinLocation = U2PVector(WorldTransform.GetLocation() - (WorldTransform.GetLocation() - root->GetComponentLocation())); PxTransform GrabbedActorPose = Actor->getGlobalPose(); PxTransform KinPose(KinLocation, GrabbedActorPose.q); // set target and current, so we don't need another "Tick" call to have it right //TargetTransform = CurrentTransform = P2UTransform(KinPose); // If we don't already have a handle - make one now. if (!HandleInfo->HandleData) { // Create kinematic actor we are going to create joint with. This will be moved around with calls to SetLocation/SetRotation. PxRigidDynamic* KinActor = Scene->getPhysics().createRigidDynamic(KinPose); KinActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true); KinActor->setMass(0.0f); // 1.0f; KinActor->setMassSpaceInertiaTensor(PxVec3(0.0f, 0.0f, 0.0f));// PxVec3(1.0f, 1.0f, 1.0f)); KinActor->setMaxDepenetrationVelocity(PX_MAX_F32); // No bodyinstance KinActor->userData = NULL; // Add to Scene Scene->addActor(*KinActor); // Save reference to the kinematic actor. HandleInfo->KinActorData = KinActor; // Create the joint PxVec3 LocalHandlePos = GrabbedActorPose.transformInv(KinLocation); PxD6Joint* NewJoint = PxD6JointCreate(Scene->getPhysics(), KinActor, PxTransform::createIdentity(), Actor, PxTransform(LocalHandlePos)); if (!NewJoint) { HandleInfo->HandleData = 0; } else { // No constraint instance NewJoint->userData = NULL; HandleInfo->HandleData = NewJoint; // Remember the scene index that the handle joint/actor are in. FPhysScene* RBScene = FPhysxUserData::Get<FPhysScene>(Scene->userData); const uint32 SceneType = root->BodyInstance.UseAsyncScene(RBScene) ? PST_Async : PST_Sync; HandleInfo->SceneIndex = RBScene->PhysXSceneIndex[SceneType]; // Setting up the joint NewJoint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE); NewJoint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE); NewJoint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE); NewJoint->setDrivePosition(PxTransform(PxVec3(0, 0, 0))); NewJoint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE); NewJoint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE); NewJoint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE); //UpdateDriveSettings(); if (HandleInfo->HandleData != nullptr) { HandleInfo->HandleData->setDrive(PxD6Drive::eX, PxD6JointDrive(NewGrip.Stiffness, NewGrip.Damping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION)); HandleInfo->HandleData->setDrive(PxD6Drive::eY, PxD6JointDrive(NewGrip.Stiffness, NewGrip.Damping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION)); HandleInfo->HandleData->setDrive(PxD6Drive::eZ, PxD6JointDrive(NewGrip.Stiffness, NewGrip.Damping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION)); HandleInfo->HandleData->setDrive(PxD6Drive::eSLERP, PxD6JointDrive(NewGrip.Stiffness, NewGrip.Damping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION)); //HandleData->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(Stiffness, Damping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION)); //HandleData->setDrive(PxD6Drive::eSWING, PxD6JointDrive(Stiffness, Damping, PX_MAX_F32, PxD6JointDriveFlag::eACCELERATION)); } } } }); #else return false; #endif // WITH_PHYSX return true; }