Exemple #1
0
FByteBulkData* USoundWave::GetCompressedData(FName Format)
{
	if (IsTemplate() || IsRunningDedicatedServer())
	{
		return NULL;
	}
	bool bContainedData = CompressedFormatData.Contains(Format);
	FByteBulkData* Result = &CompressedFormatData.GetFormat(Format);
	if (!bContainedData)
	{
		if (!FPlatformProperties::RequiresCookedData() && GetDerivedDataCache())
		{
			TArray<uint8> OutData;
			FDerivedAudioDataCompressor* DeriveAudioData = new FDerivedAudioDataCompressor(this, Format);
			GetDerivedDataCacheRef().GetSynchronous(DeriveAudioData, OutData);
			if (OutData.Num())
			{
				Result->Lock(LOCK_READ_WRITE);
				FMemory::Memcpy(Result->Realloc(OutData.Num()), OutData.GetData(), OutData.Num());
				Result->Unlock();
			}
		}
		else
		{
			UE_LOG(LogAudio, Error, TEXT("Attempt to access the DDC when there is none available on sound '%s', format = %s. Should have been cooked."), *GetFullName(), *Format.ToString());
		}
	}
	check(Result);
	return Result->GetBulkDataSize() > 0 ? Result : NULL; // we don't return empty bulk data...but we save it to avoid thrashing the DDC
}
FByteBulkData* UNavCollision::GetCookedData(FName Format)
{
	if (IsTemplate())
	{
		return NULL;
	}
	
	bool bContainedData = CookedFormatData.Contains(Format);
	FByteBulkData* Result = &CookedFormatData.GetFormat(Format);

	if (!bContainedData)
	{
		if (FPlatformProperties::RequiresCookedData())
		{
			UE_LOG(LogNavigation, Fatal, TEXT("Attempt to build nav collision data for %s when we are unable to. This platform requires cooked packages."), *GetPathName());
		}
		
		TArray<uint8> OutData;
		FDerivedDataNavCollisionCooker* DerivedNavCollisionData = new FDerivedDataNavCollisionCooker(Format, this);
		if (DerivedNavCollisionData->CanBuild() 
			&& GetDerivedDataCacheRef().GetSynchronous(DerivedNavCollisionData, OutData))
		{
			if (OutData.Num())
			{
				Result->Lock(LOCK_READ_WRITE);
				FMemory::Memcpy(Result->Realloc(OutData.Num()), OutData.GetData(), OutData.Num());
				Result->Unlock();
			}
		}
	}

	check(Result);
	return Result->GetBulkDataSize() > 0 ? Result : NULL; // we don't return empty bulk data...but we save it to avoid thrashing the DDC
}
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();
		}
	}
}
Exemple #4
0
FByteBulkData* UBodySetup::GetCookedData(FName Format)
{
	if (IsTemplate())
	{
		return NULL;
	}

	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(GetOuter());

	// If there is nothing to cook or if we are reading data from a cooked package for an asset with no collision, 
	// we want to return here
	if ((AggGeom.ConvexElems.Num() == 0 && CDP == NULL) || !bHasCookedCollisionData)
	{
		return NULL;
	}

	FFormatContainer* UseCookedData = CookedFormatDataOverride ? CookedFormatDataOverride : &CookedFormatData;

	bool bContainedData = UseCookedData->Contains(Format);
	FByteBulkData* Result = &UseCookedData->GetFormat(Format);
#if WITH_PHYSX
	if (!bContainedData)
	{
		if (FPlatformProperties::RequiresCookedData())
		{
			UE_LOG(LogPhysics, Error, TEXT("Attempt to build physics data for %s when we are unable to. This platform requires cooked packages."), *GetPathName());
		}

		if (AggGeom.ConvexElems.Num() == 0 && (CDP == NULL || CDP->ContainsPhysicsTriMeshData(bMeshCollideAll) == false))
		{
			return NULL;
		}

#if WITH_RUNTIME_PHYSICS_COOKING || WITH_EDITOR
		TArray<uint8> OutData;
		FDerivedDataPhysXCooker* DerivedPhysXData = new FDerivedDataPhysXCooker(Format, this);
		if (DerivedPhysXData->CanBuild())
		{
		#if WITH_EDITOR
			GetDerivedDataCacheRef().GetSynchronous(DerivedPhysXData, OutData);
		#elif WITH_RUNTIME_PHYSICS_COOKING
			DerivedPhysXData->Build(OutData);
		#endif
			if (OutData.Num())
			{
				Result->Lock(LOCK_READ_WRITE);
				FMemory::Memcpy(Result->Realloc(OutData.Num()), OutData.GetData(), OutData.Num());
				Result->Unlock();
			}
		}
		else
#endif
		{
			UE_LOG(LogPhysics, Warning, TEXT("Attempt to build physics data for %s when we are unable to."), *GetPathName());
		}
	}
#endif // WITH_PHYSX
	check(Result);
	return Result->GetBulkDataSize() > 0 ? Result : NULL; // we don't return empty bulk data...but we save it to avoid thrashing the DDC
}
Exemple #5
0
void USoundWave::InitAudioResource( FByteBulkData& CompressedData )
{
	if( !ResourceSize )
	{
		// Grab the compressed vorbis data from the bulk data
		ResourceSize = CompressedData.GetBulkDataSize();
		if( ResourceSize > 0 )
		{
			check(!ResourceData);
			CompressedData.GetCopy( ( void** )&ResourceData, true );
		}
	}
}
Exemple #6
0
bool USoundWave::InitAudioResource(FName Format)
{
	if( !ResourceSize && (!FPlatformProperties::SupportsAudioStreaming() || !IsStreaming()) )
	{
		FByteBulkData* Bulk = GetCompressedData(Format);
		if (Bulk)
		{
			ResourceSize = Bulk->GetBulkDataSize();
			check(ResourceSize > 0);
			check(!ResourceData);
			Bulk->GetCopy((void**)&ResourceData, true);
		}
	}

	return ResourceSize > 0;
}
Exemple #7
0
void FFormatContainer::Serialize(FArchive& Ar, UObject* Owner, const TArray<FName>* FormatsToSave)
{
	if (Ar.IsLoading())
	{
		int32 NumFormats = 0;
		Ar << NumFormats;
		for (int32 Index = 0; Index < NumFormats; Index++)
		{
			FName Name;
			Ar << Name;
			FByteBulkData& Bulk = GetFormat(Name);
			Bulk.Serialize(Ar, Owner);
		}
	}
	else
	{
		check(Ar.IsCooking() && FormatsToSave); // this thing is for cooking only, and you need to provide a list of formats

		int32 NumFormats = 0;
		for (TMap<FName, FByteBulkData*>:: TIterator It(Formats); It; ++It)
		{
			if (FormatsToSave->Contains(It.Key()) && It.Value()->GetBulkDataSize() > 0)
			{
				NumFormats++;
			}
		}
		Ar << NumFormats;
		for (TMap<FName, FByteBulkData*>:: TIterator It(Formats); It; ++It)
		{
			if (FormatsToSave->Contains(It.Key()) && It.Value()->GetBulkDataSize() > 0)
			{
				NumFormats--;
				FName Name = It.Key();
				Ar << Name;
				FByteBulkData* Bulk = It.Value();
				check(Bulk);
				Bulk->Serialize(Ar, Owner);
			}
		}
		check(NumFormats == 0);
	}
}
	FNavCollisionDataReader(FByteBulkData& InBulkData, FNavCollisionConvex& InTriMeshCollision, FNavCollisionConvex& InConvexCollision, TNavStatArray<int32>& InShapeIndices)
		: TriMeshCollision(InTriMeshCollision)
		, ConvexCollision(InConvexCollision)
		, ConvexShapeIndices(InShapeIndices)
	{
		// Read cooked data
		uint8* DataPtr = (uint8*)InBulkData.Lock( LOCK_READ_ONLY );
		FBufferReader Ar( DataPtr, InBulkData.GetBulkDataSize(), false );

		uint8 bLittleEndian = true;

		Ar << bLittleEndian;
		Ar.SetByteSwapping( PLATFORM_LITTLE_ENDIAN ? !bLittleEndian : !!bLittleEndian );
		Ar << TriMeshCollision.VertexBuffer;
		Ar << TriMeshCollision.IndexBuffer;
		Ar << ConvexCollision.VertexBuffer;
		Ar << ConvexCollision.IndexBuffer;
		Ar << ConvexShapeIndices;

		InBulkData.Unlock();
	}
FPhysXFormatDataReader::FPhysXFormatDataReader( FByteBulkData& InBulkData )
	: TriMesh( NULL )
	, TriMeshNegX( NULL )
{
	// Read cooked physics data
	uint8* DataPtr = (uint8*)InBulkData.Lock( LOCK_READ_ONLY );
	FBufferReader Ar( DataPtr, InBulkData.GetBulkDataSize(), false );
	
	uint8 bLittleEndian = true;
	int32 NumConvexElementsCooked = 0;
	int32 NumMirroredElementsCooked = 0;
	uint8 bTriMeshCooked = false;
	uint8 bMirroredTriMeshCooked = false;

	Ar << bLittleEndian;
	Ar.SetByteSwapping( PLATFORM_LITTLE_ENDIAN ? !bLittleEndian : !!bLittleEndian );
	Ar << NumConvexElementsCooked;	
	Ar << NumMirroredElementsCooked;
	Ar << bTriMeshCooked;
	Ar << bMirroredTriMeshCooked;
	
	ConvexMeshes.Empty( NumConvexElementsCooked );
	ConvexMeshesNegX.Empty( NumMirroredElementsCooked );

	for( int32 ElementIndex = 0; ElementIndex < NumConvexElementsCooked; ElementIndex++ )
	{
		PxConvexMesh* ConvexMesh = ReadConvexMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		ConvexMeshes.Add( ConvexMesh );
	}

	for( int32 ElementIndex = 0; ElementIndex < NumMirroredElementsCooked; ElementIndex++ )
	{
		PxConvexMesh* ConvexMeshNegX = ReadConvexMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		ConvexMeshesNegX.Add( ConvexMeshNegX );
	}

	if( bTriMeshCooked )
	{
		TriMesh = ReadTriMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		check(TriMesh);	
	}

	if( bMirroredTriMeshCooked )
	{
		TriMeshNegX = ReadTriMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		check(TriMeshNegX);	
	}

	InBulkData.Unlock();
}
FByteBulkData* UPhysicsSerializer::GetBinaryData(FName Format, const TArray<FBodyInstance*>& Bodies, const TArray<class UBodySetup*>& BodySetups, const TArray<class UPhysicalMaterial*>& PhysicalMaterials)
{
	if (!FParse::Param(FCommandLine::Get(), TEXT("PhysxSerialization")))
	{
		return nullptr;
	}

#if PLATFORM_MAC
	return nullptr;	//This is not supported right now
#endif

	QUICK_SCOPE_CYCLE_COUNTER(STAT_GetBinaryData);
	const bool bContainedData = BinaryFormatData.Contains(Format);
	FByteBulkData* Result = &BinaryFormatData.GetFormat(Format);
	if (!FParse::Param(FCommandLine::Get(), TEXT("NoPhysxAlignment")))
	{
		Result->SetBulkDataAlignment(PHYSX_SERIALIZATION_ALIGNMENT);
	}
	
	if (!bContainedData)
	{
#if WITH_EDITOR
#if WITH_PHYSX
		TArray<uint8> OutData;
		FDerivedDataPhysXBinarySerializer* DerivedPhysXSerializer = new FDerivedDataPhysXBinarySerializer(Format, Bodies, BodySetups, PhysicalMaterials, FGuid::NewGuid()); //TODO: Maybe it's worth adding this to the DDC. For now there's a lot of complexity with the guid invalidation so I've left it out.
		if (DerivedPhysXSerializer->CanBuild())
		{

			DerivedPhysXSerializer->Build(OutData);
#endif
			if (OutData.Num())
			{
				Result->Lock(LOCK_READ_WRITE);
				FMemory::Memcpy(Result->Realloc(OutData.Num()), OutData.GetData(), OutData.Num());
				Result->Unlock();
			}
		}
		else
#endif
		{
			UE_LOG(LogPhysics, Warning, TEXT("Attempt to use binary physics data but we are unable to."));
		}
	}

	return Result->GetBulkDataSize() > 0 ? Result : nullptr;
}
FPhysXFormatDataReader::FPhysXFormatDataReader( FByteBulkData& InBulkData, FBodySetupUVInfo* UVInfo )
{
	// Read cooked physics data
	uint8* DataPtr = (uint8*)InBulkData.Lock( LOCK_READ_ONLY );
	FBufferReader Ar( DataPtr, InBulkData.GetBulkDataSize(), false );
	
	uint8 bLittleEndian = true;
	int32 NumConvexElementsCooked = 0;
	int32 NumMirroredElementsCooked = 0;
	int32 NumTriMeshesCooked = 0;

	Ar << bLittleEndian;
	Ar.SetByteSwapping( PLATFORM_LITTLE_ENDIAN ? !bLittleEndian : !!bLittleEndian );
	Ar << NumConvexElementsCooked;	
	Ar << NumMirroredElementsCooked;
	Ar << NumTriMeshesCooked;
	
	ConvexMeshes.Empty(NumConvexElementsCooked);
	for( int32 ElementIndex = 0; ElementIndex < NumConvexElementsCooked; ElementIndex++ )
	{
		PxConvexMesh* ConvexMesh = ReadConvexMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		ConvexMeshes.Add( ConvexMesh );
	}

	ConvexMeshesNegX.Empty(NumMirroredElementsCooked);
	for( int32 ElementIndex = 0; ElementIndex < NumMirroredElementsCooked; ElementIndex++ )
	{
		PxConvexMesh* ConvexMeshNegX = ReadConvexMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		ConvexMeshesNegX.Add( ConvexMeshNegX );
	}

	TriMeshes.Empty(NumTriMeshesCooked);
	for(int32 ElementIndex = 0; ElementIndex < NumTriMeshesCooked; ++ElementIndex)
	{
		PxTriangleMesh* TriMesh = ReadTriMesh( Ar, DataPtr, InBulkData.GetBulkDataSize() );
		TriMeshes.Add(TriMesh);
	}

	// Init UVInfo pointer
	check(UVInfo);
	Ar << *UVInfo;

	InBulkData.Unlock();
}
Exemple #12
0
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
}
	/** Build the streamed audio. This function is safe to call from any thread. */
	void BuildStreamedAudio()
	{
		GetStreamedAudioDerivedDataKeySuffix(SoundWave, AudioFormatName, KeySuffix);

		DerivedData->Chunks.Empty();
		
		ITargetPlatformManagerModule* TPM = GetTargetPlatformManager();
		const IAudioFormat* AudioFormat = NULL;
		if (TPM)
		{
			AudioFormat = TPM->FindAudioFormat(AudioFormatName);
		}

		if (AudioFormat)
		{
			DerivedData->AudioFormat = AudioFormatName;

			FByteBulkData* CompressedData = SoundWave.GetCompressedData(AudioFormatName);
			TArray<uint8> CompressedBuffer;
			CompressedBuffer.Empty(CompressedData->GetBulkDataSize());
			CompressedBuffer.AddUninitialized(CompressedData->GetBulkDataSize());
			void* BufferData = CompressedBuffer.GetData();
			CompressedData->GetCopy(&BufferData, false);
			TArray<TArray<uint8>> ChunkBuffers;

			if (AudioFormat->SplitDataForStreaming(CompressedBuffer, ChunkBuffers))
			{
				for (int32 ChunkIndex = 0; ChunkIndex < ChunkBuffers.Num(); ++ChunkIndex)
				{
					FStreamedAudioChunk* NewChunk = new(DerivedData->Chunks) FStreamedAudioChunk();
					NewChunk->DataSize = ChunkBuffers[ChunkIndex].Num();
					NewChunk->BulkData.Lock(LOCK_READ_WRITE);
					void* NewChunkData = NewChunk->BulkData.Realloc(ChunkBuffers[ChunkIndex].Num());
					FMemory::Memcpy(NewChunkData, ChunkBuffers[ChunkIndex].GetData(), ChunkBuffers[ChunkIndex].Num());
					NewChunk->BulkData.Unlock();
				}
			}
			else
			{
				// Could not split so copy compressed data into a single chunk
				FStreamedAudioChunk* NewChunk = new(DerivedData->Chunks) FStreamedAudioChunk();
				NewChunk->DataSize = CompressedBuffer.Num();
				NewChunk->BulkData.Lock(LOCK_READ_WRITE);
				void* NewChunkData = NewChunk->BulkData.Realloc(CompressedBuffer.Num());
				FMemory::Memcpy(NewChunkData, CompressedBuffer.GetData(), CompressedBuffer.Num());
				NewChunk->BulkData.Unlock();
			}

			DerivedData->NumChunks = DerivedData->Chunks.Num();

			// Store it in the cache.
			PutDerivedDataInCache(DerivedData, KeySuffix);
		}
		
		if (DerivedData->Chunks.Num())
		{
			bool bInlineChunks = (CacheFlags & EStreamedAudioCacheFlags::InlineChunks) != 0;
			bSucceeded = !bInlineChunks || DerivedData->TryInlineChunkData();
		}
		else
		{
			UE_LOG(LogAudio, Warning, TEXT("Failed to build %s derived data for %s"),
				*AudioFormatName.GetPlainNameString(),
				*SoundWave.GetPathName()
				);
		}
	}