Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

255 lines
6.7 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "NaniteDefinitions.h"
#include "Math/Bounds.h"
namespace Nanite
{
class FCluster;
struct FPageSections
{
uint32 Cluster = 0;
uint32 ClusterBoneInfluence = 0;
uint32 VoxelBoneInfluence = 0;
uint32 MaterialTable = 0;
uint32 VertReuseBatchInfo = 0;
uint32 BoneInfluence = 0;
uint32 BrickData = 0;
uint32 ExtendedData = 0;
uint32 DecodeInfo = 0;
uint32 Index = 0;
uint32 Position = 0;
uint32 Attribute = 0;
uint32 GetClusterBoneInfluenceSize() const { return Align(ClusterBoneInfluence, 16); }
uint32 GetVoxelBoneInfluenceSize() const { return Align(VoxelBoneInfluence, 16); }
uint32 GetMaterialTableSize() const { return Align(MaterialTable, 16); }
uint32 GetVertReuseBatchInfoSize() const { return Align(VertReuseBatchInfo, 16); }
uint32 GetBoneInfluenceSize() const { return Align(BoneInfluence, 16); }
uint32 GetBrickDataSize() const { return Align(BrickData, 16); }
uint32 GetExtendedDataSize() const { return Align(ExtendedData, 16); }
uint32 GetDecodeInfoSize() const { return Align(DecodeInfo, 16); }
uint32 GetClusterOffset() const { return NANITE_GPU_PAGE_HEADER_SIZE; }
uint32 GetClusterBoneInfluenceOffset() const{ return GetClusterOffset() + Cluster; }
uint32 GetVoxelBoneInfluenceOffset() const { return GetClusterBoneInfluenceOffset() + GetClusterBoneInfluenceSize(); }
uint32 GetMaterialTableOffset() const { return GetVoxelBoneInfluenceOffset() + GetVoxelBoneInfluenceSize(); }
uint32 GetVertReuseBatchInfoOffset() const { return GetMaterialTableOffset() + GetMaterialTableSize(); }
uint32 GetBoneInfluenceOffset() const { return GetVertReuseBatchInfoOffset() + GetVertReuseBatchInfoSize(); }
uint32 GetBrickDataOffset() const { return GetBoneInfluenceOffset() + GetBoneInfluenceSize(); }
uint32 GetExtendedDataOffset() const { return GetBrickDataOffset() + GetBrickDataSize(); }
uint32 GetDecodeInfoOffset() const { return GetExtendedDataOffset() + GetExtendedDataSize(); }
uint32 GetIndexOffset() const { return GetDecodeInfoOffset() + GetDecodeInfoSize(); }
uint32 GetPositionOffset() const { return GetIndexOffset() + Index; }
uint32 GetAttributeOffset() const { return GetPositionOffset() + Position; }
uint32 GetTotal() const { return GetAttributeOffset() + Attribute; }
FPageSections GetOffsets() const
{
return FPageSections
{
GetClusterOffset(),
GetClusterBoneInfluenceOffset(),
GetVoxelBoneInfluenceOffset(),
GetMaterialTableOffset(),
GetVertReuseBatchInfoOffset(),
GetBoneInfluenceOffset(),
GetBrickDataOffset(),
GetExtendedDataOffset(),
GetDecodeInfoOffset(),
GetIndexOffset(),
GetPositionOffset(),
GetAttributeOffset()
};
}
void operator+=(const FPageSections& Other)
{
Cluster += Other.Cluster;
ClusterBoneInfluence+= Other.ClusterBoneInfluence;
VoxelBoneInfluence += Other.VoxelBoneInfluence;
MaterialTable += Other.MaterialTable;
VertReuseBatchInfo += Other.VertReuseBatchInfo;
BoneInfluence += Other.BoneInfluence;
BrickData += Other.BrickData;
ExtendedData += Other.ExtendedData;
DecodeInfo += Other.DecodeInfo;
Index += Other.Index;
Position += Other.Position;
Attribute += Other.Attribute;
}
};
struct FPageStreams
{
TArray<uint32> StripBitmask;
TArray<uint32> PageClusterPair;
TArray<uint32> VertexRefBitmask;
TArray<uint16> VertexRef;
TArray<uint8> Index;
TArray<uint8> Attribute;
TArray<uint8> BoneInfluence;
TArray<uint8> Brick;
TArray<uint32> Extended;
TArray<uint32> MaterialRange;
TArray<uint32> VertReuseBatchInfo;
TArray<uint8> LowByte;
TArray<uint8> MidByte;
TArray<uint8> HighByte;
};
struct FPage
{
uint32 PartsStartIndex = 0;
uint32 PartsNum = 0;
uint32 NumClusters = 0;
uint32 MaxHierarchyPartDepth = 0; // Max depth of referenced parts
uint32 MaxHierarchyDepth = 0; // Depth to guarantee next level can also be reached
uint32 MaxClusterBoneInfluences = 0;
uint32 MaxVoxelBoneInfluences = 0;
bool bRelativeEncoding = false;
FPageSections GpuSizes;
};
struct FHierarchyNodeRef
{
uint32 NodeIndex = MAX_uint32;
uint32 ChildIndex = MAX_uint32;
};
struct FClusterGroupPart
{
TArray<uint32> Clusters;
FBounds3f Bounds;
float MinLODError = MAX_flt;
uint32 PageIndex = MAX_uint32;
uint32 GroupIndex = MAX_uint32;
uint32 PageClusterOffset = MAX_uint32;
TArray<FHierarchyNodeRef> HierarchyNodeRefs;
};
struct FUVInfo
{
FUintVector2 Min = FUintVector2::ZeroValue;
FUintVector2 NumBits = FUintVector2::ZeroValue;
};
struct FPackedUVHeader
{
FUintVector2 Data;
};
struct FClusterBoneInfluence
{
uint32 BoneIndex;
};
struct FPackedVoxelBoneInfluence
{
uint32 Weight_BoneIndex; // Weight: 8, BoneIndex: 24
};
struct FBoneInfluenceInfo
{
uint32 DataOffset = 0;
uint32 NumVertexBoneInfluences = 0;
uint32 NumVertexBoneIndexBits = 0;
uint32 NumVertexBoneWeightBits = 0;
TArray<uint32> BrickBoneIndices;
TArray<FClusterBoneInfluence> ClusterBoneInfluences;
TArray<FPackedVoxelBoneInfluence> VoxelBoneInfluences;
};
struct FPackedBrick
{
uint32 VoxelMask[2];
uint32 PositionAndBrickMax[2]; // MaxX: 2, MaxY: 2, MaxZ: 2, PosX: 19, PosY: 19, PosZ: 19
uint32 VertOffset_BoneIndex;
};
struct FEncodingInfo
{
uint32 BitsPerIndex = 0;
uint32 BitsPerAttribute = 0;
uint32 NormalPrecision = 0;
uint32 TangentPrecision = 0;
uint32 ColorMode = 0;
FIntVector4 ColorMin = FIntVector4(0, 0, 0, 0);
FIntVector4 ColorBits = FIntVector4(0, 0, 0, 0);
FUVInfo UVs[NANITE_MAX_UVS];
FBoneInfluenceInfo BoneInfluence;
FPageSections GpuSizes;
};
class FBitWriter
{
public:
FBitWriter(TArray<uint8>& Buffer) :
Buffer(Buffer),
PendingBits(0ull),
NumPendingBits(0)
{
}
void PutBits(uint32 Bits, uint32 NumBits)
{
check((uint64)Bits < (1ull << NumBits));
PendingBits |= (uint64)Bits << NumPendingBits;
NumPendingBits += NumBits;
while (NumPendingBits >= 8)
{
Buffer.Add((uint8)PendingBits);
PendingBits >>= 8;
NumPendingBits -= 8;
}
}
void Flush(uint32 Alignment=1)
{
if (NumPendingBits > 0)
Buffer.Add((uint8)PendingBits);
while (Buffer.Num() % Alignment != 0)
Buffer.Add(0);
PendingBits = 0;
NumPendingBits = 0;
}
private:
TArray<uint8>& Buffer;
uint64 PendingBits;
int32 NumPendingBits;
};
template<typename TLambda>
void ProcessPageClusters(const FPage& Page, const TArray<FClusterGroupPart>& Parts, TLambda&& Lambda)
{
uint32 LocalClusterIndex = 0;
for (uint32 PartIndex = 0; PartIndex < Page.PartsNum; PartIndex++)
{
const FClusterGroupPart& Part = Parts[Page.PartsStartIndex + PartIndex];
for (uint32 i = 0; i < (uint32)Part.Clusters.Num(); i++)
{
Lambda(LocalClusterIndex, Part.Clusters[i]);
LocalClusterIndex++;
}
}
check(LocalClusterIndex == Page.NumClusters);
}
}