void UBodySetup::AddShapesToRigidActor_AssumesLocked(FBodyInstance* OwningInstance, physx::PxRigidActor* PDestActor, EPhysicsSceneType SceneType, FVector& Scale3D, physx::PxMaterial* SimpleMaterial, TArray<UPhysicalMaterial*>& ComplexMaterials, FShapeData& ShapeData, const FTransform& RelativeTM, TArray<physx::PxShape*>* NewShapes, bool bShapeSharing) { #if WITH_RUNTIME_PHYSICS_COOKING || WITH_EDITOR // in editor, there are a lot of things relying on body setup to create physics meshes CreatePhysicsMeshes(); #endif FAddShapesHelper AddShapesHelper(this, OwningInstance, PDestActor, SceneType, Scale3D, SimpleMaterial, ComplexMaterials, ShapeData, RelativeTM, NewShapes, bShapeSharing); // Create shapes for simple collision if we do not want to use the complex collision mesh // for simple queries as well if (GetCollisionTraceFlag() != ECollisionTraceFlag::CTF_UseComplexAsSimple) { AddShapesHelper.AddSpheresToRigidActor_AssumesLocked(); AddShapesHelper.AddBoxesToRigidActor_AssumesLocked(); AddShapesHelper.AddSphylsToRigidActor_AssumesLocked(); AddShapesHelper.AddConvexElemsToRigidActor_AssumesLocked(); } // Create tri-mesh shape, when we are not using simple collision shapes for // complex queries as well if (GetCollisionTraceFlag() != ECollisionTraceFlag::CTF_UseSimpleAsComplex) { AddShapesHelper.AddTriMeshToRigidActor_AssumesLocked(); } if (OwningInstance) { if (PxRigidBody* RigidBody = OwningInstance->GetPxRigidBody_AssumesLocked()) { RigidBody->setRigidBodyFlags(ShapeData.SyncBodyFlags); } } }
void UBodySetup::PostEditUndo() { Super::PostEditUndo(); // If we have any convex elems, ensure they are recreated whenever anything is modified! if(AggGeom.ConvexElems.Num() > 0) { InvalidatePhysicsData(); CreatePhysicsMeshes(); } }
void UBodySetup::AddShapesToRigidActor(PxRigidActor* PDestActor, FVector& Scale3D, const FTransform& RelativeTM /* = FTransform::Identity */, TArray<physx::PxShape*>* NewShapes /* = NULL */ ) { #if WITH_RUNTIME_PHYSICS_COOKING || WITH_EDITOR // in editor, there are a lot of things relying on body setup to create physics meshes CreatePhysicsMeshes(); #endif float MinScale; float MinScaleAbs; FVector Scale3DAbs; SetupNonUniformHelper(Scale3D, MinScale, MinScaleAbs, Scale3DAbs); { float MinScaleRelative; float MinScaleAbsRelative; FVector Scale3DAbsRelative; FVector Scale3DRelative = RelativeTM.GetScale3D(); SetupNonUniformHelper(Scale3DRelative, MinScaleRelative, MinScaleAbsRelative, Scale3DAbsRelative); MinScaleAbs *= MinScaleAbsRelative; Scale3DAbs.X *= Scale3DAbsRelative.X; Scale3DAbs.Y *= Scale3DAbsRelative.Y; Scale3DAbs.Z *= Scale3DAbsRelative.Z; } // Create shapes for simple collision if we do not want to use the complex collision mesh // for simple queries as well if (CollisionTraceFlag != ECollisionTraceFlag::CTF_UseComplexAsSimple) { AddSpheresToRigidActor(PDestActor, RelativeTM, MinScale, MinScaleAbs, NewShapes); AddBoxesToRigidActor(PDestActor, RelativeTM, Scale3D, Scale3DAbs, NewShapes); AddSphylsToRigidActor(PDestActor, RelativeTM, Scale3D, Scale3DAbs, NewShapes); AddConvexElemsToRigidActor(PDestActor, RelativeTM, Scale3D, Scale3DAbs, NewShapes); } // Create tri-mesh shape, when we are not using simple collision shapes for // complex queries as well if( CollisionTraceFlag != ECollisionTraceFlag::CTF_UseSimpleAsComplex ) { AddTriMeshToRigidActor(PDestActor, Scale3D, Scale3DAbs); } }
void UBodySetup::CreatePhysicsMeshes() { #if WITH_PHYSX // Create meshes from cooked data if not already done if(bCreatedPhysicsMeshes) { return; } // Find or create cooked physics data static FName PhysicsFormatName(FPlatformProperties::GetPhysicsFormat()); FByteBulkData* FormatData = GetCookedData(PhysicsFormatName); if( FormatData ) { if (FormatData->IsLocked()) { // seems it's being already processed return; } FPhysXFormatDataReader CookedDataReader(*FormatData); if (CollisionTraceFlag != CTF_UseComplexAsSimple) { bool bNeedsCooking = bGenerateNonMirroredCollision && CookedDataReader.ConvexMeshes.Num() != AggGeom.ConvexElems.Num(); bNeedsCooking = bNeedsCooking || (bGenerateMirroredCollision && CookedDataReader.ConvexMeshesNegX.Num() != AggGeom.ConvexElems.Num()); if (bNeedsCooking) //Because of bugs it's possible to save with out of sync cooked data. In editor we want to fixup this data { #if WITH_EDITOR InvalidatePhysicsData(); CreatePhysicsMeshes(); return; #endif } } ClearPhysicsMeshes(); if (CollisionTraceFlag != CTF_UseComplexAsSimple) { ensure(!bGenerateNonMirroredCollision || CookedDataReader.ConvexMeshes.Num() == 0 || CookedDataReader.ConvexMeshes.Num() == AggGeom.ConvexElems.Num()); ensure(!bGenerateMirroredCollision || CookedDataReader.ConvexMeshesNegX.Num() == 0 || CookedDataReader.ConvexMeshesNegX.Num() == AggGeom.ConvexElems.Num()); //If the cooked data no longer has convex meshes, make sure to empty AggGeom.ConvexElems - otherwise we leave NULLS which cause issues, and we also read past the end of CookedDataReader.ConvexMeshes if ((bGenerateNonMirroredCollision && CookedDataReader.ConvexMeshes.Num() == 0) || (bGenerateMirroredCollision && CookedDataReader.ConvexMeshesNegX.Num() == 0)) { AggGeom.ConvexElems.Empty(); } for (int32 ElementIndex = 0; ElementIndex < AggGeom.ConvexElems.Num(); ElementIndex++) { FKConvexElem& ConvexElem = AggGeom.ConvexElems[ElementIndex]; if (bGenerateNonMirroredCollision) { ConvexElem.ConvexMesh = CookedDataReader.ConvexMeshes[ElementIndex]; FPhysxSharedData::Get().Add(ConvexElem.ConvexMesh); } if (bGenerateMirroredCollision) { ConvexElem.ConvexMeshNegX = CookedDataReader.ConvexMeshesNegX[ElementIndex]; FPhysxSharedData::Get().Add(ConvexElem.ConvexMeshNegX); } } } if(bGenerateNonMirroredCollision) { TriMesh = CookedDataReader.TriMesh; FPhysxSharedData::Get().Add(TriMesh); } if(bGenerateMirroredCollision) { TriMeshNegX = CookedDataReader.TriMeshNegX; FPhysxSharedData::Get().Add(TriMeshNegX); } } else { ClearPhysicsMeshes(); // Make sure all are cleared then } // Clear the cooked data if (!GIsEditor && !bSharedCookedData) { CookedFormatData.FlushData(); } bCreatedPhysicsMeshes = true; #endif }
void UBodySetup::PostLoad() { Super::PostLoad(); // Our owner needs to be post-loaded before us else they may not have loaded // their data yet. UObject* Outer = GetOuter(); if (Outer) { Outer->ConditionalPostLoad(); } if ( GetLinkerUE4Version() < VER_UE4_BUILD_SCALE_VECTOR ) { BuildScale3D = FVector( BuildScale_DEPRECATED ); } DefaultInstance.FixupData(this); if ( GetLinkerUE4Version() < VER_UE4_REFACTOR_PHYSICS_BLENDING ) { if ( bAlwaysFullAnimWeight_DEPRECATED ) { PhysicsType = PhysType_Simulated; } else if ( DefaultInstance.bSimulatePhysics == false ) { PhysicsType = PhysType_Kinematic; } else { PhysicsType = PhysType_Default; } } if ( GetLinkerUE4Version() < VER_UE4_BODYSETUP_COLLISION_CONVERSION ) { if ( DefaultInstance.GetCollisionEnabled() == ECollisionEnabled::NoCollision ) { CollisionReponse = EBodyCollisionResponse::BodyCollision_Disabled; } } // Compress to whatever formats the active target platforms want ITargetPlatformManagerModule* TPM = GetTargetPlatformManager(); if (TPM) { const TArray<ITargetPlatform*>& Platforms = TPM->GetActiveTargetPlatforms(); for (int32 Index = 0; Index < Platforms.Num(); Index++) { GetCookedData(Platforms[Index]->GetPhysicsFormat(this)); } } // make sure that we load the physX data while the linker's loader is still open CreatePhysicsMeshes(); // fix up invalid transform to use identity // this can be here because BodySetup isn't blueprintable if ( GetLinkerUE4Version() < VER_UE4_FIXUP_BODYSETUP_INVALID_CONVEX_TRANSFORM ) { for (int32 i=0; i<AggGeom.ConvexElems.Num(); ++i) { if ( AggGeom.ConvexElems[i].GetTransform().IsValid() == false ) { AggGeom.ConvexElems[i].SetTransform(FTransform::Identity); } } } }