2022-11-25 09:18:31 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# if WITH_EDITOR
# include "SparseVolumeTextureOpenVDBUtility.h"
# include "SparseVolumeTextureOpenVDB.h"
# include "SparseVolumeTexture/SparseVolumeTexture.h"
2023-03-01 16:56:41 -05:00
# include "SparseVolumeTexture/SparseVolumeTextureData.h"
2023-01-10 15:51:23 -05:00
# include "OpenVDBGridAdapter.h"
2023-01-31 01:11:48 -05:00
# include "OpenVDBImportOptions.h"
2022-11-25 09:18:31 -05:00
DEFINE_LOG_CATEGORY_STATIC ( LogSparseVolumeTextureOpenVDBUtility , Log , All ) ;
# if OPENVDB_AVAILABLE
namespace
{
2023-02-23 14:53:04 -05:00
// Utility class acting as adapter between TArray64<uint8> and std::istream.
// In order to work around a problem where a std::streambuf implementation is limited to
// 2GB buffers, we need to manually update the pointers whenever we are done processing a 2GB chunk.
2022-11-25 09:18:31 -05:00
class FArrayUint8StreamBuf : public std : : streambuf
{
public :
2023-02-23 14:53:04 -05:00
explicit FArrayUint8StreamBuf ( TArray64 < uint8 > & Array )
2022-11-25 09:18:31 -05:00
{
char * Data = ( char * ) Array . GetData ( ) ;
2023-02-23 14:53:04 -05:00
size_t Num = Array . Num ( ) ;
FileBegin = Data ;
FileEnd = Data + Num ;
FileRead = Data ;
2022-11-25 09:18:31 -05:00
}
2023-02-23 14:53:04 -05:00
// Calls setg() to with a set of pointers exposing a window into the input file.
// Returns true if there are any more bytes to be read.
bool UpdatePointers ( )
{
StreamBegin = FileRead ;
StreamEnd = FMath : : Min ( FileEnd , StreamBegin + ChunkSize ) ;
StreamRead = StreamBegin ;
FileRead = StreamRead ;
setg ( StreamBegin , StreamRead , StreamEnd ) ;
const bool bHasBytesToRead = StreamBegin < StreamEnd ;
return bHasBytesToRead ;
}
// This function is called by the parent class and is expected to be implemented by subclasses.
// It requests n bytes to be copied into s.
std : : streamsize xsgetn ( char * s , std : : streamsize n ) override
{
for ( std : : streamsize ReadBytes = 0 ; ReadBytes < n ; )
{
// We read all bytes of the input file. gptr() is the current read ptr and egptr() is the end ptr.
if ( gptr ( ) = = egptr ( ) & & ! UpdatePointers ( ) )
{
check ( gptr ( ) = = FileEnd ) ;
return ReadBytes ;
}
// Try to read n bytes but make a smaller read if we would read past the current ptr window exposed to streambuf.
const std : : streamsize Available = FMath : : Min ( n - ReadBytes , static_cast < std : : streamsize > ( egptr ( ) - gptr ( ) ) ) ;
memcpy ( s , gptr ( ) , Available ) ;
// Advance pointers and the ReadBytes counter
s + = Available ;
ReadBytes + = Available ;
StreamRead = gptr ( ) + Available ;
FileRead = StreamRead ;
// Update the Next ptr in streambuf
setg ( StreamBegin , StreamRead , StreamEnd ) ;
}
return n ;
}
// Get the current character but don't advance the position. This is called by uflow() in the parent class when it runs out of bytes.
// We use it to move the exposed window into the file data.
int_type underflow ( ) override
{
return ( gptr ( ) = = egptr ( ) & & ! UpdatePointers ( ) ) ? traits_type : : eof ( ) : * gptr ( ) ;
}
private :
static constexpr size_t ChunkSize = INT32_MAX ; // The size of the range to expose to std::streambuf with setg()
char * FileBegin = nullptr ; // Begin ptr of the file data
char * FileEnd = nullptr ; // One byte past the end of the file data
char * FileRead = nullptr ; // The position up to which the file data has been exposed to/processed by the streambuf.
char * StreamBegin = nullptr ; // The begin ptr of the currently exposed file chunk.
char * StreamEnd = nullptr ; // The end ptr of the currently exposed file chunk.
char * StreamRead = nullptr ; // The last value of the read/next ptr set with setg().
2022-11-25 09:18:31 -05:00
} ;
}
2023-01-24 21:44:51 -05:00
static FOpenVDBGridInfo GetOpenVDBGridInfo ( openvdb : : GridBase : : Ptr Grid , uint32 GridIndex , bool bCreateStrings )
2022-11-25 09:18:31 -05:00
{
2023-01-24 21:44:51 -05:00
openvdb : : CoordBBox VolumeActiveAABB = Grid - > evalActiveVoxelBoundingBox ( ) ;
openvdb : : Coord VolumeActiveDim = Grid - > evalActiveVoxelDim ( ) ;
openvdb : : math : : MapBase : : ConstPtr MapBase = Grid - > constTransform ( ) . baseMap ( ) ;
openvdb : : Vec3d VoxelSize = MapBase - > voxelSize ( ) ;
openvdb : : Mat4d GridTransformVDB = MapBase - > getAffineMap ( ) - > getConstMat4 ( ) ;
2022-11-25 09:18:31 -05:00
2023-01-24 21:44:51 -05:00
FOpenVDBGridInfo GridInfo ;
GridInfo . Index = GridIndex ;
GridInfo . NumComponents = 0 ;
GridInfo . Type = EOpenVDBGridType : : Unknown ;
2023-02-22 09:39:24 -05:00
GridInfo . VolumeActiveAABBMin = FIntVector3 ( VolumeActiveAABB . min ( ) . x ( ) , VolumeActiveAABB . min ( ) . y ( ) , VolumeActiveAABB . min ( ) . z ( ) ) ;
GridInfo . VolumeActiveAABBMax = FIntVector3 ( VolumeActiveAABB . max ( ) . x ( ) + 1 , VolumeActiveAABB . max ( ) . y ( ) + 1 , VolumeActiveAABB . max ( ) . z ( ) + 1 ) ; // +1 because CoordBBox::Max is inclusive, but we want exclusive
GridInfo . VolumeActiveDim = FIntVector3 ( VolumeActiveDim . x ( ) , VolumeActiveDim . y ( ) , VolumeActiveDim . z ( ) ) ;
2023-01-24 21:44:51 -05:00
GridInfo . bIsInWorldSpace = Grid - > isInWorldSpace ( ) ;
2022-11-25 09:18:31 -05:00
2024-02-08 16:08:23 -05:00
FMatrix TransformMatrix ;
2023-01-24 21:44:51 -05:00
for ( int i = 0 ; i < 4 ; + + i )
{
for ( int j = 0 ; j < 4 ; + + j )
{
2024-02-08 16:08:23 -05:00
TransformMatrix . M [ i ] [ j ] = GridTransformVDB [ i ] [ j ] ;
2023-01-24 21:44:51 -05:00
}
}
2024-02-08 16:08:23 -05:00
GridInfo . Transform = FTransform ( TransformMatrix ) ;
2023-01-24 21:44:51 -05:00
// Figure out the type/format of the grid
2023-04-13 10:50:12 -04:00
if ( Grid - > isType < FOpenVDBHalf1Grid > ( ) )
{
GridInfo . NumComponents = 1 ;
GridInfo . Type = EOpenVDBGridType : : Half ;
}
else if ( Grid - > isType < FOpenVDBHalf2Grid > ( ) )
{
GridInfo . NumComponents = 2 ;
GridInfo . Type = EOpenVDBGridType : : Half2 ;
}
else if ( Grid - > isType < FOpenVDBHalf3Grid > ( ) )
{
GridInfo . NumComponents = 3 ;
GridInfo . Type = EOpenVDBGridType : : Half3 ;
}
else if ( Grid - > isType < FOpenVDBHalf4Grid > ( ) )
{
GridInfo . NumComponents = 4 ;
GridInfo . Type = EOpenVDBGridType : : Half4 ;
}
else if ( Grid - > isType < FOpenVDBFloat1Grid > ( ) )
2023-01-24 21:44:51 -05:00
{
GridInfo . NumComponents = 1 ;
GridInfo . Type = EOpenVDBGridType : : Float ;
}
else if ( Grid - > isType < FOpenVDBFloat2Grid > ( ) )
{
GridInfo . NumComponents = 2 ;
GridInfo . Type = EOpenVDBGridType : : Float2 ;
}
else if ( Grid - > isType < FOpenVDBFloat3Grid > ( ) )
{
GridInfo . NumComponents = 3 ;
GridInfo . Type = EOpenVDBGridType : : Float3 ;
}
else if ( Grid - > isType < FOpenVDBFloat4Grid > ( ) )
{
GridInfo . NumComponents = 4 ;
GridInfo . Type = EOpenVDBGridType : : Float4 ;
}
else if ( Grid - > isType < FOpenVDBDouble1Grid > ( ) )
{
GridInfo . NumComponents = 1 ;
GridInfo . Type = EOpenVDBGridType : : Double ;
}
else if ( Grid - > isType < FOpenVDBDouble2Grid > ( ) )
{
GridInfo . NumComponents = 2 ;
GridInfo . Type = EOpenVDBGridType : : Double2 ;
}
else if ( Grid - > isType < FOpenVDBDouble3Grid > ( ) )
{
GridInfo . NumComponents = 3 ;
GridInfo . Type = EOpenVDBGridType : : Double3 ;
}
else if ( Grid - > isType < FOpenVDBDouble4Grid > ( ) )
{
GridInfo . NumComponents = 4 ;
GridInfo . Type = EOpenVDBGridType : : Double4 ;
}
if ( bCreateStrings )
{
GridInfo . Name = Grid - > getName ( ) . c_str ( ) ;
FStringFormatOrderedArguments FormatArgs ;
FormatArgs . Add ( GridInfo . Index ) ;
FormatArgs . Add ( OpenVDBGridTypeToString ( GridInfo . Type ) ) ;
FormatArgs . Add ( GridInfo . Name ) ;
GridInfo . DisplayString = FString : : Format ( TEXT ( " {0}. Type: {1}, Name: \" {2} \" " ) , FormatArgs ) ;
}
return GridInfo ;
2022-11-25 09:18:31 -05:00
}
# endif
2023-01-24 21:44:51 -05:00
bool IsOpenVDBGridValid ( const FOpenVDBGridInfo & GridInfo , const FString & Filename )
2022-11-25 09:18:31 -05:00
{
return true ;
}
2023-02-23 14:53:04 -05:00
bool GetOpenVDBGridInfo ( TArray64 < uint8 > & SourceFile , bool bCreateStrings , TArray < FOpenVDBGridInfo > * OutGridInfo )
2022-11-30 15:06:09 -05:00
{
# if OPENVDB_AVAILABLE
FArrayUint8StreamBuf StreamBuf ( SourceFile ) ;
std : : istream IStream ( & StreamBuf ) ;
2023-04-12 09:45:05 -04:00
openvdb : : io : : Stream Stream ;
try
{
Stream = openvdb : : io : : Stream ( IStream , false /*delayLoad*/ ) ;
}
catch ( const openvdb : : Exception & Exception )
{
UE_LOG ( LogSparseVolumeTextureOpenVDBUtility , Error , TEXT ( " Failed to read file due to exception: %s " ) , * FString ( Exception . what ( ) ) ) ;
return false ;
}
2022-11-30 15:06:09 -05:00
openvdb : : GridPtrVecPtr Grids = Stream . getGrids ( ) ;
2023-01-10 15:51:23 -05:00
OutGridInfo - > Empty ( Grids - > size ( ) ) ;
2022-11-30 15:06:09 -05:00
uint32 GridIndex = 0 ;
for ( openvdb : : GridBase : : Ptr & Grid : * Grids )
{
2023-01-24 21:44:51 -05:00
OutGridInfo - > Add ( GetOpenVDBGridInfo ( Grid , GridIndex , bCreateStrings ) ) ;
+ + GridIndex ;
2022-11-30 15:06:09 -05:00
}
return true ;
# endif // OPENVDB_AVAILABLE
return false ;
}
2023-01-31 01:11:48 -05:00
static EPixelFormat GetMultiComponentFormat ( ESparseVolumeAttributesFormat Format , uint32 NumComponents )
2022-12-01 19:25:56 -05:00
{
switch ( Format )
{
2023-01-31 01:11:48 -05:00
case ESparseVolumeAttributesFormat : : Unorm8 :
2022-12-01 19:25:56 -05:00
{
switch ( NumComponents )
{
case 1 : return PF_R8 ;
case 2 : return PF_R8G8 ;
case 3 :
case 4 : return PF_R8G8B8A8 ;
}
break ;
}
2023-01-31 01:11:48 -05:00
case ESparseVolumeAttributesFormat : : Float16 :
2022-12-01 19:25:56 -05:00
{
switch ( NumComponents )
{
case 1 : return PF_R16F ;
case 2 : return PF_G16R16F ;
case 3 :
case 4 : return PF_FloatRGBA ;
}
break ;
}
2023-01-31 01:11:48 -05:00
case ESparseVolumeAttributesFormat : : Float32 :
2022-12-01 19:25:56 -05:00
{
switch ( NumComponents )
{
case 1 : return PF_R32_FLOAT ;
case 2 : return PF_G32R32F ;
case 3 :
case 4 : return PF_A32B32G32R32F ;
}
break ;
}
}
return PF_Unknown ;
}
2023-01-12 13:06:52 -05:00
2022-11-25 09:18:31 -05:00
# if OPENVDB_AVAILABLE
2022-12-01 19:25:56 -05:00
2023-05-31 08:14:22 -04:00
class FSparseVolumeTextureDataProviderOpenVDB : public UE : : SVT : : ITextureDataProvider
2023-02-22 09:39:24 -05:00
{
public :
2023-01-11 20:56:20 -05:00
2024-02-08 16:08:23 -05:00
bool Initialize ( TArray64 < uint8 > & SourceFile , const FOpenVDBImportOptions & ImportOptions , const FIntVector3 & InVolumeBoundsMin )
2022-12-01 19:25:56 -05:00
{
2023-02-22 09:39:24 -05:00
Attributes = ImportOptions . Attributes ;
VolumeBoundsMin = InVolumeBoundsMin ;
// Compute some basic info about the number of components and which format to use
EPixelFormat MultiCompFormat [ NumAttributesDescs ] = { } ;
bool bNormalizedFormat [ NumAttributesDescs ] = { } ;
bool bHasValidSourceGrids [ NumAttributesDescs ] = { } ;
bool bAnySourceGridIndicesValid = false ;
for ( int32 AttributesIdx = 0 ; AttributesIdx < NumAttributesDescs ; + + AttributesIdx )
2022-12-01 19:25:56 -05:00
{
2023-02-22 09:39:24 -05:00
int32 NumRequiredComponents = 0 ;
for ( int32 ComponentIdx = 0 ; ComponentIdx < 4 ; + + ComponentIdx )
2023-01-11 20:56:20 -05:00
{
2023-02-22 09:39:24 -05:00
if ( Attributes [ AttributesIdx ] . Mappings [ ComponentIdx ] . SourceGridIndex ! = INDEX_NONE )
{
check ( Attributes [ AttributesIdx ] . Mappings [ ComponentIdx ] . SourceComponentIndex ! = INDEX_NONE ) ;
NumRequiredComponents = FMath : : Max ( ComponentIdx + 1 , NumRequiredComponents ) ;
bHasValidSourceGrids [ AttributesIdx ] = true ;
bAnySourceGridIndicesValid = true ;
}
}
if ( bHasValidSourceGrids [ AttributesIdx ] )
{
NumComponents [ AttributesIdx ] = NumRequiredComponents = = 3 ? 4 : NumRequiredComponents ; // We don't support formats with only 3 components
bNormalizedFormat [ AttributesIdx ] = Attributes [ AttributesIdx ] . Format = = ESparseVolumeAttributesFormat : : Unorm8 ;
MultiCompFormat [ AttributesIdx ] = GetMultiComponentFormat ( Attributes [ AttributesIdx ] . Format , NumComponents [ AttributesIdx ] ) ;
if ( MultiCompFormat [ AttributesIdx ] = = PF_Unknown )
{
UE_LOG ( LogSparseVolumeTextureOpenVDBUtility , Warning , TEXT ( " SparseVolumeTexture is set to use an unsupported format: %i " ) , ( int32 ) Attributes [ AttributesIdx ] . Format ) ;
return false ;
}
2023-01-11 20:56:20 -05:00
}
}
2023-02-22 09:39:24 -05:00
// All source grid indices are INDEX_NONE, so nothing was selected for import
if ( ! bAnySourceGridIndicesValid )
2023-01-11 20:56:20 -05:00
{
2023-02-22 09:39:24 -05:00
UE_LOG ( LogSparseVolumeTextureOpenVDBUtility , Warning , TEXT ( " SparseVolumeTexture has all components set to <None>, so there is nothing to import. " ) ) ;
return false ;
2022-12-01 19:25:56 -05:00
}
2023-02-22 09:39:24 -05:00
// Load file
FArrayUint8StreamBuf StreamBuf ( SourceFile ) ;
std : : istream IStream ( & StreamBuf ) ;
2023-04-12 09:45:05 -04:00
openvdb : : io : : Stream Stream ;
try
{
Stream = openvdb : : io : : Stream ( IStream , false /*delayLoad*/ ) ;
}
catch ( const openvdb : : Exception & Exception )
{
UE_LOG ( LogSparseVolumeTextureOpenVDBUtility , Error , TEXT ( " Failed to read file due to exception: %s " ) , * FString ( Exception . what ( ) ) ) ;
return false ;
}
2022-12-01 19:25:56 -05:00
2023-02-22 09:39:24 -05:00
// Check that the source grid indices are valid
openvdb : : GridPtrVecPtr Grids = Stream . getGrids ( ) ;
const size_t NumSourceGrids = Grids ? Grids - > size ( ) : 0 ;
for ( const FOpenVDBSparseVolumeAttributesDesc & AttributesDesc : Attributes )
2023-01-11 20:56:20 -05:00
{
2023-02-22 09:39:24 -05:00
for ( const FOpenVDBSparseVolumeComponentMapping & Mapping : AttributesDesc . Mappings )
2023-01-11 20:56:20 -05:00
{
2023-02-22 09:39:24 -05:00
const int32 SourceGridIndex = Mapping . SourceGridIndex ;
if ( SourceGridIndex ! = INDEX_NONE & & SourceGridIndex > = ( int32 ) NumSourceGrids )
{
UE_LOG ( LogSparseVolumeTextureOpenVDBUtility , Warning , TEXT ( " SparseVolumeTexture has invalid index into the array of grids in the source file: %i " ) , SourceGridIndex ) ;
return false ;
}
2023-01-11 20:56:20 -05:00
}
}
2023-02-22 09:39:24 -05:00
2023-04-25 07:50:06 -04:00
SVTCreateInfo . AttributesFormats [ 0 ] = MultiCompFormat [ 0 ] ;
SVTCreateInfo . AttributesFormats [ 1 ] = MultiCompFormat [ 1 ] ;
2023-02-22 09:39:24 -05:00
FIntVector3 SmallestAABBMin = FIntVector3 ( INT32_MAX ) ;
FIntVector3 LargestAABBMax = FIntVector3 ( INT32_MIN ) ;
2024-02-08 16:08:23 -05:00
const FTransform * LastGridTransformPtr = nullptr ;
2023-02-22 09:39:24 -05:00
// Compute per source grid data of up to 4 different grids (one per component)
UniqueGridAdapters . SetNum ( ( int32 ) NumSourceGrids ) ;
GridToComponentMappings . SetNum ( ( int32 ) NumSourceGrids ) ;
for ( int32 AttributesIdx = 0 ; AttributesIdx < NumAttributesDescs ; + + AttributesIdx )
{
for ( int32 CompIdx = 0 ; CompIdx < 4 ; + + CompIdx )
{
const uint32 SourceGridIndex = Attributes [ AttributesIdx ] . Mappings [ CompIdx ] . SourceGridIndex ;
const uint32 SourceComponentIndex = Attributes [ AttributesIdx ] . Mappings [ CompIdx ] . SourceComponentIndex ;
if ( SourceGridIndex = = INDEX_NONE )
{
continue ;
}
openvdb : : GridBase : : Ptr GridBase = ( * Grids ) [ SourceGridIndex ] ;
// Try to reuse adapters. Internally they use caching to accelerate read accesses,
// so using three different adapters to access the three components of a single grid would be wasteful.
if ( UniqueGridAdapters [ SourceGridIndex ] = = nullptr )
{
UniqueGridAdapters [ SourceGridIndex ] = CreateOpenVDBGridAdapter ( GridBase ) ;
if ( ! UniqueGridAdapters [ SourceGridIndex ] )
{
return false ;
}
}
FOpenVDBGridInfo GridInfo = GetOpenVDBGridInfo ( GridBase , 0 , false ) ;
if ( ! IsOpenVDBGridValid ( GridInfo , TEXT ( " " ) ) )
{
return false ;
}
SmallestAABBMin . X = FMath : : Min ( SmallestAABBMin . X , GridInfo . VolumeActiveAABBMin . X ) ;
SmallestAABBMin . Y = FMath : : Min ( SmallestAABBMin . Y , GridInfo . VolumeActiveAABBMin . Y ) ;
SmallestAABBMin . Z = FMath : : Min ( SmallestAABBMin . Z , GridInfo . VolumeActiveAABBMin . Z ) ;
LargestAABBMax . X = FMath : : Max ( LargestAABBMax . X , GridInfo . VolumeActiveAABBMax . X ) ;
LargestAABBMax . Y = FMath : : Max ( LargestAABBMax . Y , GridInfo . VolumeActiveAABBMax . Y ) ;
LargestAABBMax . Z = FMath : : Max ( LargestAABBMax . Z , GridInfo . VolumeActiveAABBMax . Z ) ;
2024-02-08 16:08:23 -05:00
if ( LastGridTransformPtr & & ! LastGridTransformPtr - > Equals ( GridInfo . Transform ) )
{
UE_LOG ( LogSparseVolumeTextureOpenVDBUtility , Warning , TEXT ( " Frame has multiple grids with different transforms in the same frame! Data will likely not be imported/displayed correctly! " ) ) ;
}
LastGridTransformPtr = & GridInfo . Transform ;
2023-09-14 12:42:33 -04:00
2023-04-25 07:50:06 -04:00
SVTCreateInfo . FallbackValues [ AttributesIdx ] [ CompIdx ] = UniqueGridAdapters [ SourceGridIndex ] - > GetBackgroundValue ( SourceComponentIndex ) ;
2023-02-22 09:39:24 -05:00
FSingleGridToComponentMapping Mapping { } ;
Mapping . AttributesIdx = ( int32 ) AttributesIdx ;
Mapping . ComponentIdx = ( int32 ) CompIdx ;
Mapping . GridComponentIdx = ( int32 ) SourceComponentIndex ;
GridToComponentMappings [ SourceGridIndex ] . Add ( Mapping ) ;
}
}
2023-09-14 12:42:33 -04:00
2023-06-23 10:22:59 -04:00
const bool bEmptyBounds = SmallestAABBMin . X > = LargestAABBMax . X | | SmallestAABBMin . Y > = LargestAABBMax . Y | | SmallestAABBMin . Z > = LargestAABBMax . Z ;
SVTCreateInfo . VirtualVolumeAABBMin = bEmptyBounds ? FIntVector3 ( INT32_MAX ) : ( SmallestAABBMin - VolumeBoundsMin ) ;
SVTCreateInfo . VirtualVolumeAABBMax = bEmptyBounds ? FIntVector3 ( INT32_MIN ) : ( LargestAABBMax - VolumeBoundsMin ) ;
2024-02-08 16:08:23 -05:00
FrameTransform = LastGridTransformPtr ? * LastGridTransformPtr : FTransform : : Identity ;
FrameTransform . AddToTranslation ( FVector ( VolumeBoundsMin ) * FrameTransform . GetScale3D ( ) ) ; // We made the volume relative to VolumeBoundsMin, so we need to undo this translation when using the frame transform
2023-02-22 09:39:24 -05:00
return true ;
2022-11-25 09:18:31 -05:00
}
2023-05-31 08:14:22 -04:00
virtual UE : : SVT : : FTextureDataCreateInfo GetCreateInfo ( ) const override
2022-12-01 19:25:56 -05:00
{
2023-04-25 07:50:06 -04:00
return SVTCreateInfo ;
2023-02-22 09:39:24 -05:00
}
void IteratePhysicalSource ( TFunctionRef < void ( const FIntVector3 & Coord , int32 AttributesIdx , int32 ComponentIdx , float VoxelValue ) > OnVisit ) const override
{
for ( int32 GridIdx = 0 ; GridIdx < UniqueGridAdapters . Num ( ) ; + + GridIdx )
2022-12-01 19:25:56 -05:00
{
2023-02-22 09:39:24 -05:00
if ( ! UniqueGridAdapters [ GridIdx ] )
2023-01-11 20:56:20 -05:00
{
continue ;
}
2022-12-01 19:25:56 -05:00
2023-02-22 09:39:24 -05:00
UniqueGridAdapters [ GridIdx ] - > IteratePhysical (
[ & ] ( const FIntVector3 & Coord , uint32 NumVoxelComponents , float * VoxelValues )
2023-01-11 20:56:20 -05:00
{
2024-02-08 16:08:23 -05:00
FIntVector3 RemappedCoord = Coord - VolumeBoundsMin ;
2023-02-22 09:39:24 -05:00
for ( const FSingleGridToComponentMapping & Mapping : GridToComponentMappings [ GridIdx ] )
2023-01-12 13:06:52 -05:00
{
2023-09-14 12:42:33 -04:00
OnVisit ( RemappedCoord , Mapping . AttributesIdx , Mapping . ComponentIdx , VoxelValues [ Mapping . GridComponentIdx ] ) ;
2023-01-12 13:06:52 -05:00
}
2023-02-22 09:39:24 -05:00
} ) ;
2022-11-25 09:18:31 -05:00
}
}
2024-02-08 16:08:23 -05:00
FTransform GetFrameTransform ( ) const { return FrameTransform ; }
2023-02-22 09:39:24 -05:00
private :
struct FSingleGridToComponentMapping
2022-11-25 09:18:31 -05:00
{
2023-02-22 09:39:24 -05:00
int32 AttributesIdx ;
int32 ComponentIdx ;
int32 GridComponentIdx ;
2023-02-16 10:42:36 -05:00
} ;
2023-02-22 09:39:24 -05:00
static constexpr int32 NumAttributesDescs = 2 ;
TArray < TSharedPtr < IOpenVDBGridAdapterBase > > UniqueGridAdapters ;
TArray < TArray < FSingleGridToComponentMapping , TInlineAllocator < 4 > > > GridToComponentMappings ;
TStaticArray < FOpenVDBSparseVolumeAttributesDesc , NumAttributesDescs > Attributes ;
TStaticArray < uint32 , NumAttributesDescs > NumComponents ;
2023-05-31 08:14:22 -04:00
UE : : SVT : : FTextureDataCreateInfo SVTCreateInfo ;
2023-02-22 09:39:24 -05:00
FIntVector3 VolumeBoundsMin ;
2024-02-08 16:08:23 -05:00
FTransform FrameTransform ;
2023-02-22 09:39:24 -05:00
} ;
# endif // OPENVDB_AVAILABLE
2024-02-08 16:08:23 -05:00
bool ConvertOpenVDBToSparseVolumeTexture ( TArray64 < uint8 > & SourceFile , const FOpenVDBImportOptions & ImportOptions , const FIntVector3 & VolumeBoundsMin , UE : : SVT : : FTextureData & OutResult , FTransform & OutFrameTransform )
2023-02-22 09:39:24 -05:00
{
# if OPENVDB_AVAILABLE
2023-04-25 07:50:06 -04:00
FSparseVolumeTextureDataProviderOpenVDB DataProvider ;
2024-02-08 16:08:23 -05:00
if ( ! DataProvider . Initialize ( SourceFile , ImportOptions , VolumeBoundsMin ) )
2023-02-16 10:42:36 -05:00
{
2023-02-22 09:39:24 -05:00
return false ;
2023-02-16 10:42:36 -05:00
}
2023-04-25 07:50:06 -04:00
if ( ! OutResult . Create ( DataProvider ) )
2022-11-25 09:18:31 -05:00
{
2023-02-22 09:39:24 -05:00
return false ;
2022-11-25 09:18:31 -05:00
}
2024-02-08 16:08:23 -05:00
OutFrameTransform = DataProvider . GetFrameTransform ( ) ;
2022-11-25 09:18:31 -05:00
return true ;
# else
return false ;
# endif // OPENVDB_AVAILABLE
}
2023-01-10 15:51:23 -05:00
const TCHAR * OpenVDBGridTypeToString ( EOpenVDBGridType Type )
2022-11-30 15:06:09 -05:00
{
2023-01-10 15:51:23 -05:00
switch ( Type )
2022-11-30 15:06:09 -05:00
{
2023-04-13 10:50:12 -04:00
case EOpenVDBGridType : : Half :
return TEXT ( " Half " ) ;
case EOpenVDBGridType : : Half2 :
return TEXT ( " Half2 " ) ;
case EOpenVDBGridType : : Half3 :
return TEXT ( " Half3 " ) ;
case EOpenVDBGridType : : Half4 :
return TEXT ( " Half4 " ) ;
2023-01-10 15:51:23 -05:00
case EOpenVDBGridType : : Float :
2022-11-30 15:06:09 -05:00
return TEXT ( " Float " ) ;
2023-01-10 15:51:23 -05:00
case EOpenVDBGridType : : Float2 :
return TEXT ( " Float2 " ) ;
case EOpenVDBGridType : : Float3 :
return TEXT ( " Float3 " ) ;
case EOpenVDBGridType : : Float4 :
return TEXT ( " Float4 " ) ;
case EOpenVDBGridType : : Double :
2022-12-01 19:25:56 -05:00
return TEXT ( " Double " ) ;
2023-01-10 15:51:23 -05:00
case EOpenVDBGridType : : Double2 :
return TEXT ( " Double2 " ) ;
case EOpenVDBGridType : : Double3 :
return TEXT ( " Double3 " ) ;
case EOpenVDBGridType : : Double4 :
return TEXT ( " Double4 " ) ;
2022-11-30 15:06:09 -05:00
default :
return TEXT ( " Unknown " ) ;
}
}
2022-11-25 09:18:31 -05:00
# endif // WITH_EDITOR