Hi ! I am currently working on a volume rendering project.
By using the data from a custom format, I must dynamically generate a Volume Texture and then a material using a custom shader.
Here is the code I use to generate my texture:
void VolumeRenderingManager::createVolumeTexture(std::string name, int sx, int sy, int sz, unsigned char* data)
{
_width = sx;
_height = sy;
_depth = sz;
const unsigned long TotalSize = _width * _height * _depth * 4;
// Creating package and resource
std::string ManualName = "T_" + name + std::to_string(_id);
FString PackageName = TEXT("/Game/GeneratedTextures/");
FString TextureName = ManualName.c_str();
PackageName += TextureName;
UPackage* Package = CreatePackage(NULL, *PackageName);
Package->FullyLoad();
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
FString RelativePath = FPaths::ProjectContentDir();
_volumeTexture = NewObject<UVolumeTexture>((UObject*)Package, FName(*TextureName), RF_Public | RF_Standalone | RF_MarkAsRootSet);
_volumeTexture->AddToRoot(); // No garbage collection
_volumeTexture->PlatformData = new FTexturePlatformData();
_volumeTexture->PlatformData->SizeX = _width;
_volumeTexture->PlatformData->SizeY = _height;
_volumeTexture->PlatformData->NumSlices = _depth;
_volumeTexture->PlatformData->PixelFormat = EPixelFormat::PF_B8G8R8A8;
#if WITH_EDITORONLY_DATA
_volumeTexture->MipGenSettings = TMGS_NoMipmaps;
#endif
_volumeTexture->SRGB = false;
_volumeTexture->CompressionSettings = TextureCompressionSettings::TC_VectorDisplacementmap;
_volumeTexture->UpdateResource();
// Creating mip
FTexture2DMipMap* Mip = new(_volumeTexture->PlatformData->Mips) FTexture2DMipMap();
Mip->SizeX = _width;
Mip->SizeY = _height;
Mip->SizeZ = _depth;
// Copying data
Mip->BulkData.Lock(LOCK_READ_WRITE);
void* MipData = Mip->BulkData.Realloc(TotalSize);
FMemory::Memcpy(MipData, &data, TotalSize);
Mip->BulkData.Unlock();
#if WITH_EDITORONLY_DATA
_volumeTexture->MipGenSettings = TMGS_LeaveExistingMips;
_volumeTexture->Source.Init(_width, _height, _depth, 1, ETextureSourceFormat::TSF_RGBA8, data);
#endif
_volumeTexture->UpdateResource();
Package->MarkPackageDirty();
FAssetRegistryModule::AssetCreated(_volumeTexture);
FString PackageFileName = FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension());
bool bSaved = UPackage::SavePackage(Package, _volumeTexture, EObjectFlags::RF_Public | EObjectFlags::RF_Standalone, *PackageFileName, GError, nullptr, true, true, SAVE_NoError);
// Then generating the material
this->createMaterial(name);
}
The problem is that when I execute the code, I get the following error:
[2019.07.03-08.31.35:961][519]LogWindows: Error: === Critical error: ===
[2019.07.03-08.31.35:961][519]LogWindows: Error:
[2019.07.03-08.31.35:961][519]LogWindows: Error: Fatal error!
[2019.07.03-08.31.35:961][519]LogWindows: Error:
[2019.07.03-08.31.35:961][519]LogWindows: Error: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0xdf0d0000
And then the logs indicate that the crash happens at this line:
Mip->BulkData.Unlock();
However, if I try to print a UE_LOG just before this line, it doesn’t appear. Which strongly makes me think that the actual error comes from the Memcpy:
FMemory::Memcpy(MipData, &data, TotalSize);
By testing, I found out that there is a problem with the dimensions of my texture. The file I work with most is 100x100x60, but I managed to execute the code without errors by passing 18x18x18 (or less, like 16x16x16) as parameters to my function and I have no idea why this works.
Any ideas ?