void UNavCollision::Setup(UBodySetup* BodySetup) { // Create meshes from cooked data if not already done if (bHasConvexGeometry || BodySetup == NULL) { return; } BodySetupGuid = BodySetup->BodySetupGuid; // Make sure all are cleared before we start ClearCollision(); if (ShouldUseConvexCollision()) { // Find or create cooked navcollision data FByteBulkData* FormatData = GetCookedData(NAVCOLLISION_FORMAT); if (!bForceGeometryRebuild && FormatData) { // if it's not being already processed if (FormatData->IsLocked() == false) { // Create physics objects FNavCollisionDataReader CookedDataReader(*FormatData, TriMeshCollision, ConvexCollision, ConvexShapeIndices); bHasConvexGeometry = true; } } else { GatherCollision(); } } }
void UBodySetup::Serialize(FArchive& Ar) { Super::Serialize(Ar); // Load GUID (or create one for older versions) Ar << BodySetupGuid; // If we loaded a ZERO Guid, fix that if(Ar.IsLoading() && !BodySetupGuid.IsValid()) { MarkPackageDirty(); UE_LOG(LogPhysics, Log, TEXT("FIX GUID FOR: %s"), *GetPathName()); BodySetupGuid = FGuid::NewGuid(); } bool bCooked = Ar.IsCooking(); Ar << bCooked; if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading()) { UE_LOG(LogPhysics, Fatal, TEXT("This platform requires cooked packages, and physX data was not cooked into %s."), *GetFullName()); } if (bCooked) { if (Ar.IsCooking()) { // Make sure to reset bHasCookedCollision data to true before calling GetCookedData for cooking bHasCookedCollisionData = true; FName Format = Ar.CookingTarget()->GetPhysicsFormat(this); bHasCookedCollisionData = GetCookedData(Format) != NULL; // Get the data from the DDC or build it TArray<FName> ActualFormatsToSave; ActualFormatsToSave.Add(Format); Ar << bHasCookedCollisionData; CookedFormatData.Serialize(Ar, this, &ActualFormatsToSave); } else { if (Ar.UE4Ver() >= VER_UE4_STORE_HASCOOKEDDATA_FOR_BODYSETUP) { Ar << bHasCookedCollisionData; } CookedFormatData.Serialize(Ar, this); } } if ( Ar.IsLoading() ) { AggGeom.Serialize( Ar ); } }
void UNavCollision::Serialize(FArchive& Ar) { Super::Serialize(Ar); const int32 VerInitial = 1; const int32 VerAreaClass = 2; const int32 VerConvexTransforms = 3; const int32 VerLatest = VerConvexTransforms; // use magic number to determine if serialized stream has version :/ const int32 MagicNum = 0xA237F237; int64 StreamStartPos = Ar.Tell(); int32 Version = VerLatest; int32 MyMagicNum = MagicNum; Ar << MyMagicNum; if (MyMagicNum != MagicNum) { Version = VerInitial; Ar.Seek(StreamStartPos); } else { Ar << Version; } // loading a dummy GUID to have serialization not break on // packages serialized before switching over UNavCollision to // use BodySetup's guid rather than its own one // motivation: not creating a new engine version // @NOTE could be addressed during next engine version bump FGuid Guid; Ar << Guid; bool bCooked = Ar.IsCooking(); Ar << bCooked; if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading()) { UE_LOG(LogNavigation, Fatal, TEXT("This platform requires cooked packages, and NavCollision data was not cooked into %s."), *GetFullName()); } if (bCooked && ShouldUseConvexCollision()) { if (Ar.IsCooking()) { FName Format = NAVCOLLISION_FORMAT; GetCookedData(Format); // Get the data from the DDC or build it TArray<FName> ActualFormatsToSave; ActualFormatsToSave.Add(Format); CookedFormatData.Serialize(Ar, this, &ActualFormatsToSave); } else { CookedFormatData.Serialize(Ar, this); } } if (Version >= VerAreaClass) { Ar << AreaClass; } if (Version < VerConvexTransforms && Ar.IsLoading() && GIsEditor) { bForceGeometryRebuild = true; } }
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); } } } }